From f49312ef0e30f3f9cf346a477f4d4f0da55fa99d Mon Sep 17 00:00:00 2001 From: "Huan.Feng" Date: Fri, 3 Dec 2021 10:54:10 +0800 Subject: [PATCH] modify jh7110 gpio driver --- drivers/gpio/gpio-starfive-jh7110.c | 144 ++++++++++++------------------------ 1 file changed, 48 insertions(+), 96 deletions(-) diff --git a/drivers/gpio/gpio-starfive-jh7110.c b/drivers/gpio/gpio-starfive-jh7110.c index 2ca62b0e..82bb840 100644 --- a/drivers/gpio/gpio-starfive-jh7110.c +++ b/drivers/gpio/gpio-starfive-jh7110.c @@ -37,29 +37,30 @@ #include #include -#define GPIO_EN 0xe0 -#define GPIO_IS_LOW 0xe4 -#define GPIO_IS_HIGH 0xe8 -#define GPIO_IBE_LOW 0xf4 -#define GPIO_IBE_HIGH 0xf8 -#define GPIO_IEV_LOW 0xfc -#define GPIO_IEV_HIGH 0x100 -#define GPIO_IE_LOW 0x104 -#define GPIO_IE_HIGH 0x108 -#define GPIO_IC_LOW 0xec -#define GPIO_IC_HIGH 0xf0 +#define GPIO_EN 0xdc +#define GPIO_IS_LOW 0xe0 +#define GPIO_IS_HIGH 0xe4 +#define GPIO_IC_LOW 0xe8 +#define GPIO_IC_HIGH 0xec +#define GPIO_IBE_LOW 0xf0 +#define GPIO_IBE_HIGH 0xf4 +#define GPIO_IEV_LOW 0xf8 +#define GPIO_IEV_HIGH 0xfc +#define GPIO_IE_LOW 0x100 +#define GPIO_IE_HIGH 0x104 + //read only -#define GPIO_RIS_LOW 0x10c -#define GPIO_RIS_HIGH 0x110 -#define GPIO_MIS_LOW 0x114 -#define GPIO_MIS_HIGH 0x118 -#define GPIO_DIN_LOW 0x11C -#define GPIO_DIN_HIGH 0x120 +#define GPIO_RIS_LOW 0x108 +#define GPIO_RIS_HIGH 0x10c +#define GPIO_MIS_LOW 0x110 +#define GPIO_MIS_HIGH 0x114 +#define GPIO_DIN_LOW 0x118 +#define GPIO_DIN_HIGH 0x11c -#define GPIO_DOUT_X_REG 0x0 -#define GPIO_DOEN_X_REG 0x40 +#define GPIO_DOEN_X_REG 0x0 +#define GPIO_DOUT_X_REG 0x40 -#define GPIO_INPUT_ENABLE_X_REG 0x124 +#define GPIO_INPUT_ENABLE_X_REG 0x120 #define MAX_GPIO 64 @@ -93,7 +94,7 @@ static int sfvic7110_direction_input(struct gpio_chip *gc, unsigned offset) if (offset >= gc->ngpio) return -EINVAL; - + raw_spin_lock_irqsave(&chip->lock, flags); v = readl_relaxed(chip->base + GPIO_DOEN_X_REG + (offset & ~0x3)); v &= ~(0x3f << ((offset & 0x3) * 8)); @@ -112,13 +113,14 @@ static int sfvic7110_direction_output(struct gpio_chip *gc, unsigned offset, int if (offset >= gc->ngpio) return -EINVAL; + raw_spin_lock_irqsave(&chip->lock, flags); v = readl_relaxed(chip->base + GPIO_DOEN_X_REG + (offset & ~0x3)); v &= ~(0x3f << ((offset & 0x3) * 8)); writel_relaxed(v, chip->base + GPIO_DOEN_X_REG + (offset & ~0x3)); v = readl_relaxed(chip->base + GPIO_DOUT_X_REG + (offset & ~0x3)); - v &= ~(0x3f << ((offset & 0x3) * 8)); + v &= ~(0x7f << ((offset & 0x3) * 8)); v |= value << ((offset & 0x3) * 8); writel_relaxed(v, chip->base + GPIO_DOUT_X_REG + (offset & ~0x3)); raw_spin_unlock_irqrestore(&chip->lock, flags); @@ -166,7 +168,7 @@ static void sfvic7110_set_value(struct gpio_chip *gc, unsigned offset, int value raw_spin_lock_irqsave(&chip->lock, flags); v = readl_relaxed(chip->base + GPIO_DOUT_X_REG + (offset & ~0x3)); - v &= ~(0x3f << ((offset & 0x3) * 8)); + v &= ~(0x7f << ((offset & 0x3) * 8)); v |= value << ((offset & 0x3) * 8); writel_relaxed(v, chip->base + GPIO_DOUT_X_REG + (offset & ~0x3)); raw_spin_unlock_irqrestore(&chip->lock, flags); @@ -217,10 +219,10 @@ static int sfvic7110_irq_set_type(struct irq_data *d, unsigned trigger) reg_iev = readl_relaxed(chip->base + GPIO_IEV_LOW + reg_offset); reg_is &= (~(0x1<< index)); reg_ibe &= (~(0x1<< index)); - reg_iev |= (0x1<< index); - writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset); - writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset); + reg_iev |= (~(0x1<< index)); writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset); + writel_relaxed(reg_ibe, chip->base + GPIO_IBE_LOW + reg_offset); + writel_relaxed(reg_iev, chip->base + GPIO_IEV_LOW + reg_offset); break; case IRQ_TYPE_LEVEL_LOW: reg_is = readl_relaxed(chip->base + GPIO_IS_LOW + reg_offset); @@ -230,41 +232,41 @@ static int sfvic7110_irq_set_type(struct irq_data *d, unsigned trigger) reg_ibe &= (~(0x1<< index)); reg_iev &= (0x1<< index); writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset); - writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset); - writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset); + writel_relaxed(reg_ibe, chip->base + GPIO_IBE_LOW + reg_offset); + writel_relaxed(reg_iev, chip->base + GPIO_IEV_LOW + reg_offset); break; case IRQ_TYPE_EDGE_BOTH: reg_is = readl_relaxed(chip->base + GPIO_IS_LOW + reg_offset); reg_ibe = readl_relaxed(chip->base + GPIO_IBE_LOW + reg_offset); - //reg_iev = readl_relaxed(chip->base + GPIO_IEV_LOW + reg_offset); - reg_is |= (~(0x1<< index)); - reg_ibe |= (~(0x1<< index)); - //reg_iev |= (0x1<< index); - writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset); + reg_iev = readl_relaxed(chip->base + GPIO_IEV_LOW + reg_offset); + reg_is |= (0x1<< index); + reg_ibe |= (0x1<< index); + reg_iev |= (~(0x1<< index)); writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset); - //writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset); + writel_relaxed(reg_ibe, chip->base + GPIO_IBE_LOW + reg_offset); + writel_relaxed(reg_iev, chip->base + GPIO_IEV_LOW + reg_offset); break; case IRQ_TYPE_EDGE_RISING: reg_is = readl_relaxed(chip->base + GPIO_IS_LOW + reg_offset); reg_ibe = readl_relaxed(chip->base + GPIO_IBE_LOW + reg_offset); reg_iev = readl_relaxed(chip->base + GPIO_IEV_LOW + reg_offset); - reg_is |= (~(0x1<< index)); + reg_is |= (0x1<< index); reg_ibe &= (~(0x1<< index)); reg_iev |= (0x1<< index); writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset); - writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset); - writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset); + writel_relaxed(reg_ibe, chip->base + GPIO_IBE_LOW + reg_offset); + writel_relaxed(reg_iev, chip->base + GPIO_IEV_LOW + reg_offset); break; case IRQ_TYPE_EDGE_FALLING: reg_is = readl_relaxed(chip->base + GPIO_IS_LOW + reg_offset); reg_ibe = readl_relaxed(chip->base + GPIO_IBE_LOW + reg_offset); reg_iev = readl_relaxed(chip->base + GPIO_IEV_LOW + reg_offset); - reg_is |= (~(0x1<< index)); + reg_is |= (0x1<< index); reg_ibe &= (~(0x1<< index)); - reg_iev &= (0x1<< index); - writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset); - writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset); + reg_iev &= (~(0x1<< index)); writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset); + writel_relaxed(reg_ibe, chip->base + GPIO_IBE_LOW + reg_offset); + writel_relaxed(reg_iev, chip->base + GPIO_IEV_LOW + reg_offset); break; } @@ -351,22 +353,6 @@ static struct irq_chip sfvic7110_irqchip = { .irq_disable = sfvic7110_irq_disable, }; - -static int starfive_gpio_child_to_parent_hwirq(struct gpio_chip *gc, - unsigned int child, - unsigned int child_type, - unsigned int *parent, - unsigned int *parent_type) -{ - struct sfvic7110_gpio *chip = gpiochip_get_data(gc); - struct irq_data *d = irq_get_irq_data(chip->irq_parent[child]); - - *parent_type = IRQ_TYPE_NONE; - *parent = irqd_to_hwirq(d); - - return 0; -} - static irqreturn_t sfvic7110_irq_handler(int irq, void *gc) { int offset; @@ -411,7 +397,7 @@ void sf_vic_gpio_dout_reverse(int gpio,int en) spin_lock(&sfg_lock); value = ioread32(gpio_base + offset); - value &= ~(0x3f << ((offset & 0x3) * 8)); + value &= ~(0x7f << ((offset & 0x3) * 8)); value |= (en & 0x1) << ((offset & 0x3) * 8); iowrite32(value, gpio_base + offset); spin_unlock(&sfg_lock); @@ -430,8 +416,8 @@ void sf_vic_gpio_dout_value(int gpio,int v) spin_lock(&sfg_lock); value = ioread32(gpio_base + offset); - value &= ~(0x3f << ((offset & 0x3) * 8)); - value |= (v & 0x3f) << ((offset & 0x3) * 8); + value &= ~(0x7f << ((offset & 0x3) * 8)); + value |= (v & 0x7f) << ((offset & 0x3) * 8); iowrite32(value,gpio_base + offset); spin_unlock(&sfg_lock); } @@ -651,10 +637,6 @@ static int sfvic7110_gpio_probe(struct platform_device *pdev) struct resource *res; int irq, ret, ngpio; int loop; - struct gpio_irq_chip *girq; - struct device_node *node = pdev->dev.of_node; - struct device_node *irq_parent; - struct irq_domain *parent; chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); if (!chip) { @@ -684,60 +666,30 @@ static int sfvic7110_gpio_probe(struct platform_device *pdev) chip->gc.parent = dev; chip->gc.owner = THIS_MODULE; - irq_parent = of_irq_find_parent(node); - if (!irq_parent) { - dev_err(dev, "no IRQ parent node\n"); - return -ENODEV; - } - parent = irq_find_host(irq_parent); - if (!parent) { - dev_err(dev, "no IRQ parent domain\n"); - return -ENODEV; - } - - girq = &chip->gc.irq; - girq->chip = &sfvic7110_irqchip; - girq->fwnode = of_node_to_fwnode(node); - girq->parent_domain = parent; - girq->child_to_parent_hwirq = starfive_gpio_child_to_parent_hwirq; - girq->handler = handle_simple_irq; - girq->default_type = IRQ_TYPE_NONE; - - /* Disable all GPIO interrupts before enabling parent interrupts */ - iowrite32(0, chip->base + GPIO_IE_HIGH); - iowrite32(0, chip->base + GPIO_IE_LOW); - chip->enabled = 0; - - platform_set_drvdata(pdev, chip); ret = gpiochip_add_data(&chip->gc, chip); if (ret){ dev_err(dev, "gpiochip_add_data ret=%d!\n", ret); return ret; } - -#if 0 + /* Disable all GPIO interrupts before enabling parent interrupts */ iowrite32(0, chip->base + GPIO_IE_HIGH); iowrite32(0, chip->base + GPIO_IE_LOW); chip->enabled = 0; - ret = gpiochip_gpiochip_add(&chip->gc, &sfvic7110_irqchip, 0, + ret = gpiochip_irqchip_add(&chip->gc, &sfvic7110_irqchip, 0, handle_simple_irq, IRQ_TYPE_NONE); if (ret) { dev_err(dev, "could not add irqchip\n"); gpiochip_remove(&chip->gc); return ret; } -#endif - irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(dev, "Cannot get IRQ resource\n"); return irq; } - chip->irq_parent[0] = irq; - ret = devm_request_irq(dev, irq, sfvic7110_irq_handler, IRQF_SHARED, dev_name(dev), chip); if (ret) { -- 2.7.4