]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
Revert "pinctrl: bcm2835: switch to GPIOLIB_IRQCHIP"
authorpopcornmix <popcornmix@gmail.com>
Tue, 3 Jan 2017 18:25:01 +0000 (18:25 +0000)
committerKleber Sacilotto de Souza <kleber.souza@canonical.com>
Tue, 19 Sep 2017 10:07:40 +0000 (12:07 +0200)
This reverts commit 85ae9e512f437cd09bf61564bdba29ab88bab3e3.

drivers/pinctrl/bcm/Kconfig
drivers/pinctrl/bcm/pinctrl-bcm2835.c

index 8968dd7aebed2133b0103b39d7b752916dbfaab0..63246770bd74b9dcd3804cee66a960f2404b7092 100644 (file)
@@ -20,7 +20,6 @@ config PINCTRL_BCM2835
        bool
        select PINMUX
        select PINCONF
-       select GPIOLIB_IRQCHIP
 
 config PINCTRL_IPROC_GPIO
        bool "Broadcom iProc GPIO (with PINCONF) driver"
index 85d0091128644c446aed878e87769e82c77c3ebf..4f2621272bfd5cbc0d691d2fabe89e2ee428d6db 100644 (file)
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/gpio/driver.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/irqdesc.h>
+#include <linux/irqdomain.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/of.h>
@@ -79,6 +81,11 @@ enum bcm2835_pinconf_param {
 #define BCM2835_PINCONF_UNPACK_PARAM(_conf_) ((_conf_) >> 16)
 #define BCM2835_PINCONF_UNPACK_ARG(_conf_) ((_conf_) & 0xffff)
 
+struct bcm2835_gpio_irqdata {
+       struct bcm2835_pinctrl *pc;
+       int irqgroup;
+};
+
 struct bcm2835_pinctrl {
        struct device *dev;
        void __iomem *base;
@@ -89,13 +96,16 @@ struct bcm2835_pinctrl {
        unsigned int irq_type[BCM2835_NUM_GPIOS];
 
        struct pinctrl_dev *pctl_dev;
+       struct irq_domain *irq_domain;
        struct gpio_chip gpio_chip;
        struct pinctrl_gpio_range gpio_range;
 
-       int irq_group[BCM2835_NUM_IRQS];
+       struct bcm2835_gpio_irqdata irq_data[BCM2835_NUM_IRQS];
        spinlock_t irq_lock[BCM2835_NUM_BANKS];
 };
 
+static struct lock_class_key gpio_lock_class;
+
 /* pins are just named GPIO0..GPIO53 */
 #define BCM2835_GPIO_PIN(a) PINCTRL_PIN(a, "gpio" #a)
 static struct pinctrl_pin_desc bcm2835_gpio_pins[] = {
@@ -353,6 +363,13 @@ static int bcm2835_gpio_direction_output(struct gpio_chip *chip,
        return pinctrl_gpio_direction_output(chip->base + offset);
 }
 
+static int bcm2835_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
+
+       return irq_linear_revmap(pc->irq_domain, offset);
+}
+
 static struct gpio_chip bcm2835_gpio_chip = {
        .label = MODULE_NAME,
        .owner = THIS_MODULE,
@@ -363,13 +380,14 @@ static struct gpio_chip bcm2835_gpio_chip = {
        .get_direction = bcm2835_gpio_get_direction,
        .get = bcm2835_gpio_get,
        .set = bcm2835_gpio_set,
+       .to_irq = bcm2835_gpio_to_irq,
        .base = -1,
        .ngpio = BCM2835_NUM_GPIOS,
        .can_sleep = false,
 };
 
-static void bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc,
-                                        unsigned int bank, u32 mask)
+static int bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc,
+                                       unsigned int bank, u32 mask)
 {
        unsigned long events;
        unsigned offset;
@@ -381,49 +399,34 @@ static void bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc,
        events &= pc->enabled_irq_map[bank];
        for_each_set_bit(offset, &events, 32) {
                gpio = (32 * bank) + offset;
-               /* FIXME: no clue why the code looks up the type here */
                type = pc->irq_type[gpio];
 
-               generic_handle_irq(irq_linear_revmap(pc->gpio_chip.irqdomain,
-                                                    gpio));
+               generic_handle_irq(irq_linear_revmap(pc->irq_domain, gpio));
        }
+
+       return (events != 0);
 }
 
-static void bcm2835_gpio_irq_handler(struct irq_desc *desc)
+static irqreturn_t bcm2835_gpio_irq_handler(int irq, void *dev_id)
 {
-       struct gpio_chip *chip = irq_desc_get_handler_data(desc);
-       struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
-       struct irq_chip *host_chip = irq_desc_get_chip(desc);
-       int irq = irq_desc_get_irq(desc);
-       int group;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(pc->irq); i++) {
-               if (pc->irq[i] == irq) {
-                       group = pc->irq_group[i];
-                       break;
-               }
-       }
-       /* This should not happen, every IRQ has a bank */
-       if (i == ARRAY_SIZE(pc->irq))
-               BUG();
+       struct bcm2835_gpio_irqdata *irqdata = dev_id;
+       struct bcm2835_pinctrl *pc = irqdata->pc;
+       int handled = 0;
 
-       chained_irq_enter(host_chip, desc);
-
-       switch (group) {
+       switch (irqdata->irqgroup) {
        case 0: /* IRQ0 covers GPIOs 0-27 */
-               bcm2835_gpio_irq_handle_bank(pc, 0, 0x0fffffff);
+               handled = bcm2835_gpio_irq_handle_bank(pc, 0, 0x0fffffff);
                break;
        case 1: /* IRQ1 covers GPIOs 28-45 */
-               bcm2835_gpio_irq_handle_bank(pc, 0, 0xf0000000);
-               bcm2835_gpio_irq_handle_bank(pc, 1, 0x00003fff);
+               handled = bcm2835_gpio_irq_handle_bank(pc, 0, 0xf0000000) |
+                         bcm2835_gpio_irq_handle_bank(pc, 1, 0x00003fff);
                break;
        case 2: /* IRQ2 covers GPIOs 46-53 */
-               bcm2835_gpio_irq_handle_bank(pc, 1, 0x003fc000);
+               handled = bcm2835_gpio_irq_handle_bank(pc, 1, 0x003fc000);
                break;
        }
 
-       chained_irq_exit(host_chip, desc);
+       return handled ? IRQ_HANDLED : IRQ_NONE;
 }
 
 static inline void __bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc,
@@ -469,8 +472,7 @@ static void bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc,
 
 static void bcm2835_gpio_irq_enable(struct irq_data *data)
 {
-       struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
-       struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
+       struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data);
        unsigned gpio = irqd_to_hwirq(data);
        unsigned offset = GPIO_REG_SHIFT(gpio);
        unsigned bank = GPIO_REG_OFFSET(gpio);
@@ -484,8 +486,7 @@ static void bcm2835_gpio_irq_enable(struct irq_data *data)
 
 static void bcm2835_gpio_irq_disable(struct irq_data *data)
 {
-       struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
-       struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
+       struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data);
        unsigned gpio = irqd_to_hwirq(data);
        unsigned offset = GPIO_REG_SHIFT(gpio);
        unsigned bank = GPIO_REG_OFFSET(gpio);
@@ -591,8 +592,7 @@ static int __bcm2835_gpio_irq_set_type_enabled(struct bcm2835_pinctrl *pc,
 
 static int bcm2835_gpio_irq_set_type(struct irq_data *data, unsigned int type)
 {
-       struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
-       struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
+       struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data);
        unsigned gpio = irqd_to_hwirq(data);
        unsigned offset = GPIO_REG_SHIFT(gpio);
        unsigned bank = GPIO_REG_OFFSET(gpio);
@@ -618,8 +618,7 @@ static int bcm2835_gpio_irq_set_type(struct irq_data *data, unsigned int type)
 
 static void bcm2835_gpio_irq_ack(struct irq_data *data)
 {
-       struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
-       struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
+       struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data);
        unsigned gpio = irqd_to_hwirq(data);
 
        bcm2835_gpio_set_bit(pc, GPEDS0, gpio);
@@ -662,11 +661,10 @@ static void bcm2835_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
                unsigned offset)
 {
        struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
-       struct gpio_chip *chip = &pc->gpio_chip;
        enum bcm2835_fsel fsel = bcm2835_pinctrl_fsel_get(pc, offset);
        const char *fname = bcm2835_functions[fsel];
        int value = bcm2835_gpio_get_bit(pc, GPLEV0, offset);
-       int irq = irq_find_mapping(chip->irqdomain, offset);
+       int irq = irq_find_mapping(pc->irq_domain, offset);
 
        seq_printf(s, "function %s in %s; irq %d (%s)",
                fname, value ? "hi" : "lo",
@@ -1012,6 +1010,21 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
        pc->gpio_chip.parent = dev;
        pc->gpio_chip.of_node = np;
 
+       pc->irq_domain = irq_domain_add_linear(np, BCM2835_NUM_GPIOS,
+                       &irq_domain_simple_ops, NULL);
+       if (!pc->irq_domain) {
+               dev_err(dev, "could not create IRQ domain\n");
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < BCM2835_NUM_GPIOS; i++) {
+               int irq = irq_create_mapping(pc->irq_domain, i);
+               irq_set_lockdep_class(irq, &gpio_lock_class);
+               irq_set_chip_and_handler(irq, &bcm2835_gpio_irq_chip,
+                               handle_level_irq);
+               irq_set_chip_data(irq, pc);
+       }
+
        for (i = 0; i < BCM2835_NUM_BANKS; i++) {
                unsigned long events;
                unsigned offset;
@@ -1032,35 +1045,34 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
                spin_lock_init(&pc->irq_lock[i]);
        }
 
-       err = gpiochip_add_data(&pc->gpio_chip, pc);
-       if (err) {
-               dev_err(dev, "could not add GPIO chip\n");
-               return err;
+       for (i = 0; i < BCM2835_NUM_IRQS; i++) {
+               int len;
+               char *name;
+               pc->irq[i] = irq_of_parse_and_map(np, i);
+               pc->irq_data[i].pc = pc;
+               pc->irq_data[i].irqgroup = i;
+
+               len = strlen(dev_name(pc->dev)) + 16;
+               name = devm_kzalloc(pc->dev, len, GFP_KERNEL);
+               if (!name)
+                       return -ENOMEM;
+               snprintf(name, len, "%s:bank%d", dev_name(pc->dev), i);
+
+               err = devm_request_irq(dev, pc->irq[i],
+                       bcm2835_gpio_irq_handler, IRQF_SHARED,
+                       name, &pc->irq_data[i]);
+               if (err) {
+                       dev_err(dev, "unable to request IRQ %d\n", pc->irq[i]);
+                       return err;
+               }
        }
 
-       err = gpiochip_irqchip_add(&pc->gpio_chip, &bcm2835_gpio_irq_chip,
-                                  0, handle_level_irq, IRQ_TYPE_NONE);
+       err = gpiochip_add_data(&pc->gpio_chip, pc);
        if (err) {
-               dev_info(dev, "could not add irqchip\n");
+               dev_err(dev, "could not add GPIO chip\n");
                return err;
        }
 
-       for (i = 0; i < BCM2835_NUM_IRQS; i++) {
-               pc->irq[i] = irq_of_parse_and_map(np, i);
-               pc->irq_group[i] = i;
-               /*
-                * Use the same handler for all groups: this is necessary
-                * since we use one gpiochip to cover all lines - the
-                * irq handler then needs to figure out which group and
-                * bank that was firing the IRQ and look up the per-group
-                * and bank data.
-                */
-               gpiochip_set_chained_irqchip(&pc->gpio_chip,
-                                            &bcm2835_gpio_irq_chip,
-                                            pc->irq[i],
-                                            bcm2835_gpio_irq_handler);
-       }
-
        pc->pctl_dev = devm_pinctrl_register(dev, &bcm2835_pinctrl_desc, pc);
        if (IS_ERR(pc->pctl_dev)) {
                gpiochip_remove(&pc->gpio_chip);