]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blobdiff - drivers/pinctrl/pinctrl-amd.c
net: hns: Bugfix for Tx timeout handling in hns driver
[mirror_ubuntu-zesty-kernel.git] / drivers / pinctrl / pinctrl-amd.c
index c9a146948192dba19ca5da1587791c25b315d628..07a88b83e02bb9e14deef37a39648a2cb865ac38 100644 (file)
@@ -41,11 +41,11 @@ static int amd_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
        u32 pin_reg;
        struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
 
-       spin_lock_irqsave(&gpio_dev->lock, flags);
+       raw_spin_lock_irqsave(&gpio_dev->lock, flags);
        pin_reg = readl(gpio_dev->base + offset * 4);
        pin_reg &= ~BIT(OUTPUT_ENABLE_OFF);
        writel(pin_reg, gpio_dev->base + offset * 4);
-       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+       raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
 
        return 0;
 }
@@ -57,7 +57,7 @@ static int amd_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
        unsigned long flags;
        struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
 
-       spin_lock_irqsave(&gpio_dev->lock, flags);
+       raw_spin_lock_irqsave(&gpio_dev->lock, flags);
        pin_reg = readl(gpio_dev->base + offset * 4);
        pin_reg |= BIT(OUTPUT_ENABLE_OFF);
        if (value)
@@ -65,7 +65,7 @@ static int amd_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
        else
                pin_reg &= ~BIT(OUTPUT_VALUE_OFF);
        writel(pin_reg, gpio_dev->base + offset * 4);
-       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+       raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
 
        return 0;
 }
@@ -76,9 +76,9 @@ static int amd_gpio_get_value(struct gpio_chip *gc, unsigned offset)
        unsigned long flags;
        struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
 
-       spin_lock_irqsave(&gpio_dev->lock, flags);
+       raw_spin_lock_irqsave(&gpio_dev->lock, flags);
        pin_reg = readl(gpio_dev->base + offset * 4);
-       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+       raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
 
        return !!(pin_reg & BIT(PIN_STS_OFF));
 }
@@ -89,14 +89,14 @@ static void amd_gpio_set_value(struct gpio_chip *gc, unsigned offset, int value)
        unsigned long flags;
        struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
 
-       spin_lock_irqsave(&gpio_dev->lock, flags);
+       raw_spin_lock_irqsave(&gpio_dev->lock, flags);
        pin_reg = readl(gpio_dev->base + offset * 4);
        if (value)
                pin_reg |= BIT(OUTPUT_VALUE_OFF);
        else
                pin_reg &= ~BIT(OUTPUT_VALUE_OFF);
        writel(pin_reg, gpio_dev->base + offset * 4);
-       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+       raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
 }
 
 static int amd_gpio_set_debounce(struct gpio_chip *gc, unsigned offset,
@@ -108,7 +108,7 @@ static int amd_gpio_set_debounce(struct gpio_chip *gc, unsigned offset,
        unsigned long flags;
        struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
 
-       spin_lock_irqsave(&gpio_dev->lock, flags);
+       raw_spin_lock_irqsave(&gpio_dev->lock, flags);
        pin_reg = readl(gpio_dev->base + offset * 4);
 
        if (debounce) {
@@ -159,7 +159,7 @@ static int amd_gpio_set_debounce(struct gpio_chip *gc, unsigned offset,
                pin_reg &= ~DB_CNTRl_MASK;
        }
        writel(pin_reg, gpio_dev->base + offset * 4);
-       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+       raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
 
        return ret;
 }
@@ -202,13 +202,15 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc)
                        i = 128;
                        pin_num = AMD_GPIO_PINS_BANK2 + i;
                        break;
+               default:
+                       return;
                }
 
                for (; i < pin_num; i++) {
                        seq_printf(s, "pin%d\t", i);
-                       spin_lock_irqsave(&gpio_dev->lock, flags);
+                       raw_spin_lock_irqsave(&gpio_dev->lock, flags);
                        pin_reg = readl(gpio_dev->base + i * 4);
-                       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+                       raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
 
                        if (pin_reg & BIT(INTERRUPT_ENABLE_OFF)) {
                                interrupt_enable = "interrupt is enabled|";
@@ -313,12 +315,12 @@ static void amd_gpio_irq_enable(struct irq_data *d)
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
        struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
 
-       spin_lock_irqsave(&gpio_dev->lock, flags);
+       raw_spin_lock_irqsave(&gpio_dev->lock, flags);
        pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
        pin_reg |= BIT(INTERRUPT_ENABLE_OFF);
        pin_reg |= BIT(INTERRUPT_MASK_OFF);
        writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
-       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+       raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
 }
 
 static void amd_gpio_irq_disable(struct irq_data *d)
@@ -328,12 +330,12 @@ static void amd_gpio_irq_disable(struct irq_data *d)
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
        struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
 
-       spin_lock_irqsave(&gpio_dev->lock, flags);
+       raw_spin_lock_irqsave(&gpio_dev->lock, flags);
        pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
        pin_reg &= ~BIT(INTERRUPT_ENABLE_OFF);
        pin_reg &= ~BIT(INTERRUPT_MASK_OFF);
        writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
-       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+       raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
 }
 
 static void amd_gpio_irq_mask(struct irq_data *d)
@@ -343,11 +345,11 @@ static void amd_gpio_irq_mask(struct irq_data *d)
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
        struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
 
-       spin_lock_irqsave(&gpio_dev->lock, flags);
+       raw_spin_lock_irqsave(&gpio_dev->lock, flags);
        pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
        pin_reg &= ~BIT(INTERRUPT_MASK_OFF);
        writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
-       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+       raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
 }
 
 static void amd_gpio_irq_unmask(struct irq_data *d)
@@ -357,11 +359,11 @@ static void amd_gpio_irq_unmask(struct irq_data *d)
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
        struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
 
-       spin_lock_irqsave(&gpio_dev->lock, flags);
+       raw_spin_lock_irqsave(&gpio_dev->lock, flags);
        pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
        pin_reg |= BIT(INTERRUPT_MASK_OFF);
        writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
-       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+       raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
 }
 
 static void amd_gpio_irq_eoi(struct irq_data *d)
@@ -371,11 +373,11 @@ static void amd_gpio_irq_eoi(struct irq_data *d)
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
        struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
 
-       spin_lock_irqsave(&gpio_dev->lock, flags);
+       raw_spin_lock_irqsave(&gpio_dev->lock, flags);
        reg = readl(gpio_dev->base + WAKE_INT_MASTER_REG);
        reg |= EOI_MASK;
        writel(reg, gpio_dev->base + WAKE_INT_MASTER_REG);
-       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+       raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
 }
 
 static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type)
@@ -386,7 +388,7 @@ static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type)
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
        struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
 
-       spin_lock_irqsave(&gpio_dev->lock, flags);
+       raw_spin_lock_irqsave(&gpio_dev->lock, flags);
        pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
 
        /* Ignore the settings coming from the client and
@@ -451,7 +453,7 @@ static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 
        pin_reg |= CLR_INTR_STAT << INTERRUPT_STS_OFF;
        writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
-       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+       raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
 
        return ret;
 }
@@ -476,64 +478,54 @@ static struct irq_chip amd_gpio_irqchip = {
        .irq_set_type = amd_gpio_irq_set_type,
 };
 
-static void amd_gpio_irq_handler(struct irq_desc *desc)
+#define PIN_IRQ_PENDING        (BIT(INTERRUPT_STS_OFF) | BIT(WAKE_STS_OFF))
+
+static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id)
 {
-       u32 i;
-       u32 off;
-       u32 reg;
-       u32 pin_reg;
-       u64 reg64;
-       int handled = 0;
-       unsigned int irq;
+       struct amd_gpio *gpio_dev = dev_id;
+       struct gpio_chip *gc = &gpio_dev->gc;
+       irqreturn_t ret = IRQ_NONE;
+       unsigned int i, irqnr;
        unsigned long flags;
-       struct irq_chip *chip = irq_desc_get_chip(desc);
-       struct gpio_chip *gc = irq_desc_get_handler_data(desc);
-       struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
-
-       chained_irq_enter(chip, desc);
-       /*enable GPIO interrupt again*/
-       spin_lock_irqsave(&gpio_dev->lock, flags);
-       reg = readl(gpio_dev->base + WAKE_INT_STATUS_REG1);
-       reg64 = reg;
-       reg64 = reg64 << 32;
-
-       reg = readl(gpio_dev->base + WAKE_INT_STATUS_REG0);
-       reg64 |= reg;
-       spin_unlock_irqrestore(&gpio_dev->lock, flags);
-
-       /*
-        * first 46 bits indicates interrupt status.
-        * one bit represents four interrupt sources.
-       */
-       for (off = 0; off < 46 ; off++) {
-               if (reg64 & BIT(off)) {
-                       for (i = 0; i < 4; i++) {
-                               pin_reg = readl(gpio_dev->base +
-                                               (off * 4 + i) * 4);
-                               if ((pin_reg & BIT(INTERRUPT_STS_OFF)) ||
-                                       (pin_reg & BIT(WAKE_STS_OFF))) {
-                                       irq = irq_find_mapping(gc->irqdomain,
-                                                               off * 4 + i);
-                                       generic_handle_irq(irq);
-                                       writel(pin_reg,
-                                               gpio_dev->base
-                                               + (off * 4 + i) * 4);
-                                       handled++;
-                               }
-                       }
+       u32 *regs, regval;
+       u64 status, mask;
+
+       /* Read the wake status */
+       raw_spin_lock_irqsave(&gpio_dev->lock, flags);
+       status = readl(gpio_dev->base + WAKE_INT_STATUS_REG1);
+       status <<= 32;
+       status |= readl(gpio_dev->base + WAKE_INT_STATUS_REG0);
+       raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
+
+       /* Bit 0-45 contain the relevant status bits */
+       status &= (1ULL << 46) - 1;
+       regs = gpio_dev->base;
+       for (mask = 1, irqnr = 0; status; mask <<= 1, regs += 4, irqnr += 4) {
+               if (!(status & mask))
+                       continue;
+               status &= ~mask;
+
+               /* Each status bit covers four pins */
+               for (i = 0; i < 4; i++) {
+                       regval = readl(regs + i);
+                       if (!(regval & PIN_IRQ_PENDING))
+                               continue;
+                       irq = irq_find_mapping(gc->irqdomain, irqnr + i);
+                       generic_handle_irq(irq);
+                       /* Clear interrupt */
+                       writel(regval, regs + i);
+                       ret = IRQ_HANDLED;
                }
        }
 
-       if (handled == 0)
-               handle_bad_irq(desc);
+       /* Signal EOI to the GPIO unit */
+       raw_spin_lock_irqsave(&gpio_dev->lock, flags);
+       regval = readl(gpio_dev->base + WAKE_INT_MASTER_REG);
+       regval |= EOI_MASK;
+       writel(regval, gpio_dev->base + WAKE_INT_MASTER_REG);
+       raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
 
-       spin_lock_irqsave(&gpio_dev->lock, flags);
-       reg = readl(gpio_dev->base + WAKE_INT_MASTER_REG);
-       reg |= EOI_MASK;
-       writel(reg, gpio_dev->base + WAKE_INT_MASTER_REG);
-       spin_unlock_irqrestore(&gpio_dev->lock, flags);
-
-       chained_irq_exit(chip, desc);
+       return ret;
 }
 
 static int amd_get_groups_count(struct pinctrl_dev *pctldev)
@@ -583,9 +575,9 @@ static int amd_pinconf_get(struct pinctrl_dev *pctldev,
        struct amd_gpio *gpio_dev = pinctrl_dev_get_drvdata(pctldev);
        enum pin_config_param param = pinconf_to_config_param(*config);
 
-       spin_lock_irqsave(&gpio_dev->lock, flags);
+       raw_spin_lock_irqsave(&gpio_dev->lock, flags);
        pin_reg = readl(gpio_dev->base + pin*4);
-       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+       raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
        switch (param) {
        case PIN_CONFIG_INPUT_DEBOUNCE:
                arg = pin_reg & DB_TMR_OUT_MASK;
@@ -625,7 +617,7 @@ static int amd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
        enum pin_config_param param;
        struct amd_gpio *gpio_dev = pinctrl_dev_get_drvdata(pctldev);
 
-       spin_lock_irqsave(&gpio_dev->lock, flags);
+       raw_spin_lock_irqsave(&gpio_dev->lock, flags);
        for (i = 0; i < num_configs; i++) {
                param = pinconf_to_config_param(configs[i]);
                arg = pinconf_to_config_argument(configs[i]);
@@ -664,7 +656,7 @@ static int amd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
 
                writel(pin_reg, gpio_dev->base + pin*4);
        }
-       spin_unlock_irqrestore(&gpio_dev->lock, flags);
+       raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
 
        return ret;
 }
@@ -732,7 +724,7 @@ static int amd_gpio_probe(struct platform_device *pdev)
        if (!gpio_dev)
                return -ENOMEM;
 
-       spin_lock_init(&gpio_dev->lock);
+       raw_spin_lock_init(&gpio_dev->lock);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
@@ -801,10 +793,10 @@ static int amd_gpio_probe(struct platform_device *pdev)
                goto out2;
        }
 
-       gpiochip_set_chained_irqchip(&gpio_dev->gc,
-                                &amd_gpio_irqchip,
-                                irq_base,
-                                amd_gpio_irq_handler);
+       ret = devm_request_irq(&pdev->dev, irq_base, amd_gpio_irq_handler, 0,
+                              KBUILD_MODNAME, gpio_dev);
+       if (ret)
+               goto out2;
 
        platform_set_drvdata(pdev, gpio_dev);