diff options
Diffstat (limited to 'drivers/pinctrl/bcm')
-rw-r--r-- | drivers/pinctrl/bcm/pinctrl-bcm2835.c | 19 | ||||
-rw-r--r-- | drivers/pinctrl/bcm/pinctrl-iproc-gpio.c | 38 | ||||
-rw-r--r-- | drivers/pinctrl/bcm/pinctrl-ns.c | 1 | ||||
-rw-r--r-- | drivers/pinctrl/bcm/pinctrl-nsp-gpio.c | 23 |
4 files changed, 53 insertions, 28 deletions
diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index 8e2551a08c37..7435173e10f4 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -90,6 +90,8 @@ struct bcm2835_pinctrl { struct pinctrl_gpio_range gpio_range; raw_spinlock_t irq_lock[BCM2835_NUM_BANKS]; + /* Protect FSEL registers */ + spinlock_t fsel_lock; }; /* pins are just named GPIO0..GPIO53 */ @@ -284,14 +286,19 @@ static inline void bcm2835_pinctrl_fsel_set( struct bcm2835_pinctrl *pc, unsigned pin, enum bcm2835_fsel fsel) { - u32 val = bcm2835_gpio_rd(pc, FSEL_REG(pin)); - enum bcm2835_fsel cur = (val >> FSEL_SHIFT(pin)) & BCM2835_FSEL_MASK; + u32 val; + enum bcm2835_fsel cur; + unsigned long flags; + + spin_lock_irqsave(&pc->fsel_lock, flags); + val = bcm2835_gpio_rd(pc, FSEL_REG(pin)); + cur = (val >> FSEL_SHIFT(pin)) & BCM2835_FSEL_MASK; dev_dbg(pc->dev, "read %08x (%u => %s)\n", val, pin, - bcm2835_functions[cur]); + bcm2835_functions[cur]); if (cur == fsel) - return; + goto unlock; if (cur != BCM2835_FSEL_GPIO_IN && fsel != BCM2835_FSEL_GPIO_IN) { /* always transition through GPIO_IN */ @@ -309,6 +316,9 @@ static inline void bcm2835_pinctrl_fsel_set( dev_dbg(pc->dev, "write %08x (%u <= %s)\n", val, pin, bcm2835_functions[fsel]); bcm2835_gpio_wr(pc, FSEL_REG(pin), val); + +unlock: + spin_unlock_irqrestore(&pc->fsel_lock, flags); } static int bcm2835_gpio_direction_input(struct gpio_chip *chip, unsigned offset) @@ -1248,6 +1258,7 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) pc->gpio_chip = *pdata->gpio_chip; pc->gpio_chip.parent = dev; + spin_lock_init(&pc->fsel_lock); for (i = 0; i < BCM2835_NUM_BANKS; i++) { unsigned long events; unsigned offset; diff --git a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c index 3df56a4ea510..cc3eb7409ab3 100644 --- a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c +++ b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c @@ -23,6 +23,7 @@ #include <linux/kernel.h> #include <linux/of_device.h> #include <linux/of_irq.h> +#include <linux/seq_file.h> #include <linux/slab.h> #include <linux/pinctrl/consumer.h> @@ -108,7 +109,6 @@ struct iproc_gpio { raw_spinlock_t lock; - struct irq_chip irqchip; struct gpio_chip gc; unsigned num_banks; @@ -217,7 +217,7 @@ static void iproc_gpio_irq_set_mask(struct irq_data *d, bool unmask) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct iproc_gpio *chip = gpiochip_get_data(gc); - unsigned gpio = d->hwirq; + unsigned gpio = irqd_to_hwirq(d); iproc_set_bit(chip, IPROC_GPIO_INT_MSK_OFFSET, gpio, unmask); } @@ -231,6 +231,7 @@ static void iproc_gpio_irq_mask(struct irq_data *d) raw_spin_lock_irqsave(&chip->lock, flags); iproc_gpio_irq_set_mask(d, false); raw_spin_unlock_irqrestore(&chip->lock, flags); + gpiochip_disable_irq(gc, irqd_to_hwirq(d)); } static void iproc_gpio_irq_unmask(struct irq_data *d) @@ -239,6 +240,7 @@ static void iproc_gpio_irq_unmask(struct irq_data *d) struct iproc_gpio *chip = gpiochip_get_data(gc); unsigned long flags; + gpiochip_enable_irq(gc, irqd_to_hwirq(d)); raw_spin_lock_irqsave(&chip->lock, flags); iproc_gpio_irq_set_mask(d, true); raw_spin_unlock_irqrestore(&chip->lock, flags); @@ -302,6 +304,26 @@ static int iproc_gpio_irq_set_type(struct irq_data *d, unsigned int type) return 0; } +static void iproc_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct iproc_gpio *chip = gpiochip_get_data(gc); + + seq_printf(p, dev_name(chip->dev)); +} + +static const struct irq_chip iproc_gpio_irq_chip = { + .irq_ack = iproc_gpio_irq_ack, + .irq_mask = iproc_gpio_irq_mask, + .irq_unmask = iproc_gpio_irq_unmask, + .irq_set_type = iproc_gpio_irq_set_type, + .irq_enable = iproc_gpio_irq_unmask, + .irq_disable = iproc_gpio_irq_mask, + .irq_print_chip = iproc_gpio_irq_print_chip, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + /* * Request the Iproc IOMUX pinmux controller to mux individual pins to GPIO */ @@ -852,20 +874,10 @@ static int iproc_gpio_probe(struct platform_device *pdev) /* optional GPIO interrupt support */ irq = platform_get_irq_optional(pdev, 0); if (irq > 0) { - struct irq_chip *irqc; struct gpio_irq_chip *girq; - irqc = &chip->irqchip; - irqc->name = dev_name(dev); - irqc->irq_ack = iproc_gpio_irq_ack; - irqc->irq_mask = iproc_gpio_irq_mask; - irqc->irq_unmask = iproc_gpio_irq_unmask; - irqc->irq_set_type = iproc_gpio_irq_set_type; - irqc->irq_enable = iproc_gpio_irq_unmask; - irqc->irq_disable = iproc_gpio_irq_mask; - girq = &gc->irq; - girq->chip = irqc; + gpio_irq_chip_set_chip(girq, &iproc_gpio_irq_chip); girq->parent_handler = iproc_gpio_irq_handler; girq->num_parents = 1; girq->parents = devm_kcalloc(dev, 1, diff --git a/drivers/pinctrl/bcm/pinctrl-ns.c b/drivers/pinctrl/bcm/pinctrl-ns.c index 465cc96814a1..f80630a74d34 100644 --- a/drivers/pinctrl/bcm/pinctrl-ns.c +++ b/drivers/pinctrl/bcm/pinctrl-ns.c @@ -299,5 +299,4 @@ static struct platform_driver ns_pinctrl_driver = { module_platform_driver(ns_pinctrl_driver); MODULE_AUTHOR("Rafał Miłecki"); -MODULE_LICENSE("GPL v2"); MODULE_DEVICE_TABLE(of, ns_pinctrl_of_match_table); diff --git a/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c b/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c index 3c792bf03bda..5045a7e57f1d 100644 --- a/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c +++ b/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c @@ -60,7 +60,6 @@ struct nsp_gpio { struct device *dev; void __iomem *base; void __iomem *io_ctrl; - struct irq_chip irqchip; struct gpio_chip gc; struct pinctrl_dev *pctl; struct pinctrl_desc pctldesc; @@ -193,6 +192,7 @@ static void nsp_gpio_irq_mask(struct irq_data *d) raw_spin_lock_irqsave(&chip->lock, flags); nsp_gpio_irq_set_mask(d, false); raw_spin_unlock_irqrestore(&chip->lock, flags); + gpiochip_disable_irq(gc, irqd_to_hwirq(d)); } static void nsp_gpio_irq_unmask(struct irq_data *d) @@ -201,6 +201,7 @@ static void nsp_gpio_irq_unmask(struct irq_data *d) struct nsp_gpio *chip = gpiochip_get_data(gc); unsigned long flags; + gpiochip_enable_irq(gc, irqd_to_hwirq(d)); raw_spin_lock_irqsave(&chip->lock, flags); nsp_gpio_irq_set_mask(d, true); raw_spin_unlock_irqrestore(&chip->lock, flags); @@ -258,6 +259,16 @@ static int nsp_gpio_irq_set_type(struct irq_data *d, unsigned int type) return 0; } +static const struct irq_chip nsp_gpio_irq_chip = { + .name = "gpio-a", + .irq_ack = nsp_gpio_irq_ack, + .irq_mask = nsp_gpio_irq_mask, + .irq_unmask = nsp_gpio_irq_unmask, + .irq_set_type = nsp_gpio_irq_set_type, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + static int nsp_gpio_direction_input(struct gpio_chip *gc, unsigned gpio) { struct nsp_gpio *chip = gpiochip_get_data(gc); @@ -650,14 +661,6 @@ static int nsp_gpio_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq > 0) { struct gpio_irq_chip *girq; - struct irq_chip *irqc; - - irqc = &chip->irqchip; - irqc->name = "gpio-a"; - irqc->irq_ack = nsp_gpio_irq_ack; - irqc->irq_mask = nsp_gpio_irq_mask; - irqc->irq_unmask = nsp_gpio_irq_unmask; - irqc->irq_set_type = nsp_gpio_irq_set_type; val = readl(chip->base + NSP_CHIP_A_INT_MASK); val = val | NSP_CHIP_A_GPIO_INT_BIT; @@ -673,7 +676,7 @@ static int nsp_gpio_probe(struct platform_device *pdev) } girq = &chip->gc.irq; - girq->chip = irqc; + gpio_irq_chip_set_chip(girq, &nsp_gpio_irq_chip); /* This will let us handle the parent IRQ in the driver */ girq->parent_handler = NULL; girq->num_parents = 0; |