diff options
Diffstat (limited to 'drivers/pinctrl/bcm')
-rw-r--r-- | drivers/pinctrl/bcm/pinctrl-bcm281xx.c | 4 | ||||
-rw-r--r-- | drivers/pinctrl/bcm/pinctrl-bcm2835.c | 156 | ||||
-rw-r--r-- | drivers/pinctrl/bcm/pinctrl-cygnus-mux.c | 8 | ||||
-rw-r--r-- | drivers/pinctrl/bcm/pinctrl-iproc-gpio.c | 177 | ||||
-rw-r--r-- | drivers/pinctrl/bcm/pinctrl-ns2-mux.c | 12 | ||||
-rw-r--r-- | drivers/pinctrl/bcm/pinctrl-nsp-gpio.c | 119 | ||||
-rw-r--r-- | drivers/pinctrl/bcm/pinctrl-nsp-mux.c | 8 |
7 files changed, 315 insertions, 169 deletions
diff --git a/drivers/pinctrl/bcm/pinctrl-bcm281xx.c b/drivers/pinctrl/bcm/pinctrl-bcm281xx.c index bc3b232a727a..f690fc5cd688 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm281xx.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm281xx.c @@ -1400,12 +1400,10 @@ static struct pinctrl_desc bcm281xx_pinctrl_desc = { static int __init bcm281xx_pinctrl_probe(struct platform_device *pdev) { struct bcm281xx_pinctrl_data *pdata = &bcm281xx_pinctrl; - struct resource *res; struct pinctrl_dev *pctl; /* So far We can assume there is only 1 bank of registers */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - pdata->reg_base = devm_ioremap_resource(&pdev->dev, res); + pdata->reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(pdata->reg_base)) { dev_err(&pdev->dev, "Failed to ioremap MEM resource\n"); return -ENODEV; diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index 183d1ffe6a75..0de1a3a96984 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -57,19 +57,27 @@ #define GPAFEN0 0x88 /* Pin Async Falling Edge Detect */ #define GPPUD 0x94 /* Pin Pull-up/down Enable */ #define GPPUDCLK0 0x98 /* Pin Pull-up/down Enable Clock */ +#define GP_GPIO_PUP_PDN_CNTRL_REG0 0xe4 /* 2711 Pin Pull-up/down select */ #define FSEL_REG(p) (GPFSEL0 + (((p) / 10) * 4)) #define FSEL_SHIFT(p) (((p) % 10) * 3) #define GPIO_REG_OFFSET(p) ((p) / 32) #define GPIO_REG_SHIFT(p) ((p) % 32) +#define PUD_2711_MASK 0x3 +#define PUD_2711_REG_OFFSET(p) ((p) / 16) +#define PUD_2711_REG_SHIFT(p) (((p) % 16) * 2) + /* argument: bcm2835_pinconf_pull */ #define BCM2835_PINCONF_PARAM_PULL (PIN_CONFIG_END + 1) +#define BCM2711_PULL_NONE 0x0 +#define BCM2711_PULL_UP 0x1 +#define BCM2711_PULL_DOWN 0x2 + struct bcm2835_pinctrl { struct device *dev; void __iomem *base; - int irq[BCM2835_NUM_IRQS]; /* note: locking assumes each bank will have its own unsigned long */ unsigned long enabled_irq_map[BCM2835_NUM_BANKS]; @@ -373,14 +381,14 @@ static void bcm2835_gpio_irq_handler(struct irq_desc *desc) int group; int i; - for (i = 0; i < ARRAY_SIZE(pc->irq); i++) { - if (pc->irq[i] == irq) { + for (i = 0; i < BCM2835_NUM_IRQS; i++) { + if (chip->irq.parents[i] == irq) { group = i; break; } } /* This should not happen, every IRQ has a bank */ - if (i == ARRAY_SIZE(pc->irq)) + if (i == BCM2835_NUM_IRQS) BUG(); chained_irq_enter(host_chip, desc); @@ -975,6 +983,77 @@ static const struct pinconf_ops bcm2835_pinconf_ops = { .pin_config_set = bcm2835_pinconf_set, }; +static void bcm2711_pull_config_set(struct bcm2835_pinctrl *pc, + unsigned int pin, unsigned int arg) +{ + u32 shifter; + u32 value; + u32 off; + + off = PUD_2711_REG_OFFSET(pin); + shifter = PUD_2711_REG_SHIFT(pin); + + value = bcm2835_gpio_rd(pc, GP_GPIO_PUP_PDN_CNTRL_REG0 + (off * 4)); + value &= ~(PUD_2711_MASK << shifter); + value |= (arg << shifter); + bcm2835_gpio_wr(pc, GP_GPIO_PUP_PDN_CNTRL_REG0 + (off * 4), value); +} + +static int bcm2711_pinconf_set(struct pinctrl_dev *pctldev, + unsigned int pin, unsigned long *configs, + unsigned int num_configs) +{ + struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); + u32 param, arg; + int i; + + for (i = 0; i < num_configs; i++) { + param = pinconf_to_config_param(configs[i]); + arg = pinconf_to_config_argument(configs[i]); + + switch (param) { + /* convert legacy brcm,pull */ + case BCM2835_PINCONF_PARAM_PULL: + if (arg == BCM2835_PUD_UP) + arg = BCM2711_PULL_UP; + else if (arg == BCM2835_PUD_DOWN) + arg = BCM2711_PULL_DOWN; + else + arg = BCM2711_PULL_NONE; + + bcm2711_pull_config_set(pc, pin, arg); + break; + + /* Set pull generic bindings */ + case PIN_CONFIG_BIAS_DISABLE: + bcm2711_pull_config_set(pc, pin, BCM2711_PULL_NONE); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + bcm2711_pull_config_set(pc, pin, BCM2711_PULL_DOWN); + break; + case PIN_CONFIG_BIAS_PULL_UP: + bcm2711_pull_config_set(pc, pin, BCM2711_PULL_UP); + break; + + /* Set output-high or output-low */ + case PIN_CONFIG_OUTPUT: + bcm2835_gpio_set_bit(pc, arg ? GPSET0 : GPCLR0, pin); + break; + + default: + return -ENOTSUPP; + } + } /* for each config */ + + return 0; +} + +static const struct pinconf_ops bcm2711_pinconf_ops = { + .is_generic = true, + .pin_config_get = bcm2835_pinconf_get, + .pin_config_set = bcm2711_pinconf_set, +}; + static struct pinctrl_desc bcm2835_pinctrl_desc = { .name = MODULE_NAME, .pins = bcm2835_gpio_pins, @@ -990,13 +1069,28 @@ static struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range = { .npins = BCM2835_NUM_GPIOS, }; +static const struct of_device_id bcm2835_pinctrl_match[] = { + { + .compatible = "brcm,bcm2835-gpio", + .data = &bcm2835_pinconf_ops, + }, + { + .compatible = "brcm,bcm2711-gpio", + .data = &bcm2711_pinconf_ops, + }, + {} +}; + static int bcm2835_pinctrl_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct bcm2835_pinctrl *pc; + struct gpio_irq_chip *girq; struct resource iomem; int err, i; + const struct of_device_id *match; + BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_pins) != BCM2835_NUM_GPIOS); BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_groups) != BCM2835_NUM_GPIOS); @@ -1041,36 +1135,37 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) raw_spin_lock_init(&pc->irq_lock[i]); } + girq = &pc->gpio_chip.irq; + girq->chip = &bcm2835_gpio_irq_chip; + girq->parent_handler = bcm2835_gpio_irq_handler; + girq->num_parents = BCM2835_NUM_IRQS; + girq->parents = devm_kcalloc(dev, BCM2835_NUM_IRQS, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + /* + * 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. + */ + for (i = 0; i < BCM2835_NUM_IRQS; i++) + girq->parents[i] = irq_of_parse_and_map(np, i); + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_level_irq; + err = gpiochip_add_data(&pc->gpio_chip, pc); if (err) { dev_err(dev, "could not add GPIO chip\n"); return err; } - err = gpiochip_irqchip_add(&pc->gpio_chip, &bcm2835_gpio_irq_chip, - 0, handle_level_irq, IRQ_TYPE_NONE); - if (err) { - dev_info(dev, "could not add irqchip\n"); - return err; - } - - for (i = 0; i < BCM2835_NUM_IRQS; i++) { - pc->irq[i] = irq_of_parse_and_map(np, i); - - if (pc->irq[i] == 0) - continue; - - /* - * 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); + match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node); + if (match) { + bcm2835_pinctrl_desc.confops = + (const struct pinconf_ops *)match->data; } pc->pctl_dev = devm_pinctrl_register(dev, &bcm2835_pinctrl_desc, pc); @@ -1087,11 +1182,6 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) return 0; } -static const struct of_device_id bcm2835_pinctrl_match[] = { - { .compatible = "brcm,bcm2835-gpio" }, - {} -}; - static struct platform_driver bcm2835_pinctrl_driver = { .probe = bcm2835_pinctrl_probe, .driver = { diff --git a/drivers/pinctrl/bcm/pinctrl-cygnus-mux.c b/drivers/pinctrl/bcm/pinctrl-cygnus-mux.c index 44df35942a43..4344c5732400 100644 --- a/drivers/pinctrl/bcm/pinctrl-cygnus-mux.c +++ b/drivers/pinctrl/bcm/pinctrl-cygnus-mux.c @@ -923,7 +923,6 @@ static int cygnus_mux_log_init(struct cygnus_pinctrl *pinctrl) if (!pinctrl->mux_log) return -ENOMEM; - log = pinctrl->mux_log; for (i = 0; i < CYGNUS_NUM_IOMUX_REGS; i++) { for (j = 0; j < CYGNUS_NUM_MUX_PER_REG; j++) { log = &pinctrl->mux_log[i * CYGNUS_NUM_MUX_PER_REG @@ -941,7 +940,6 @@ static int cygnus_mux_log_init(struct cygnus_pinctrl *pinctrl) static int cygnus_pinmux_probe(struct platform_device *pdev) { struct cygnus_pinctrl *pinctrl; - struct resource *res; int i, ret; struct pinctrl_pin_desc *pins; unsigned num_pins = ARRAY_SIZE(cygnus_pins); @@ -954,15 +952,13 @@ static int cygnus_pinmux_probe(struct platform_device *pdev) platform_set_drvdata(pdev, pinctrl); spin_lock_init(&pinctrl->lock); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - pinctrl->base0 = devm_ioremap_resource(&pdev->dev, res); + pinctrl->base0 = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(pinctrl->base0)) { dev_err(&pdev->dev, "unable to map I/O space\n"); return PTR_ERR(pinctrl->base0); } - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - pinctrl->base1 = devm_ioremap_resource(&pdev->dev, res); + pinctrl->base1 = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(pinctrl->base1)) { dev_err(&pdev->dev, "unable to map I/O space\n"); return PTR_ERR(pinctrl->base1); diff --git a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c index b70058caee50..25166217c3e0 100644 --- a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c +++ b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c @@ -1,14 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2014-2017 Broadcom - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ /* @@ -54,8 +46,12 @@ /* drive strength control for ASIU GPIO */ #define IPROC_GPIO_ASIU_DRV0_CTRL_OFFSET 0x58 -/* drive strength control for CCM/CRMU (AON) GPIO */ -#define IPROC_GPIO_DRV0_CTRL_OFFSET 0x00 +/* pinconf for CCM GPIO */ +#define IPROC_GPIO_PULL_DN_OFFSET 0x10 +#define IPROC_GPIO_PULL_UP_OFFSET 0x14 + +/* pinconf for CRMU(aon) GPIO and CCM GPIO*/ +#define IPROC_GPIO_DRV_CTRL_OFFSET 0x00 #define GPIO_BANK_SIZE 0x200 #define NGPIOS_PER_BANK 32 @@ -76,6 +72,12 @@ enum iproc_pinconf_param { IPROC_PINCON_MAX, }; +enum iproc_pinconf_ctrl_type { + IOCTRL_TYPE_AON = 1, + IOCTRL_TYPE_CDRU, + IOCTRL_TYPE_INVALID, +}; + /* * Iproc GPIO core * @@ -100,9 +102,11 @@ struct iproc_gpio { void __iomem *base; void __iomem *io_ctrl; + enum iproc_pinconf_ctrl_type io_ctrl_type; raw_spinlock_t lock; + struct irq_chip irqchip; struct gpio_chip gc; unsigned num_banks; @@ -282,6 +286,12 @@ static int iproc_gpio_irq_set_type(struct irq_data *d, unsigned int type) iproc_set_bit(chip, IPROC_GPIO_INT_DE_OFFSET, gpio, dual_edge); iproc_set_bit(chip, IPROC_GPIO_INT_EDGE_OFFSET, gpio, rising_or_high); + + if (type & IRQ_TYPE_EDGE_BOTH) + irq_set_handler_locked(d, handle_edge_irq); + else + irq_set_handler_locked(d, handle_level_irq); + raw_spin_unlock_irqrestore(&chip->lock, flags); dev_dbg(chip->dev, @@ -291,14 +301,6 @@ static int iproc_gpio_irq_set_type(struct irq_data *d, unsigned int type) return 0; } -static struct irq_chip iproc_gpio_irq_chip = { - .name = "bcm-iproc-gpio", - .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, -}; - /* * Request the Iproc IOMUX pinmux controller to mux individual pins to GPIO */ @@ -355,6 +357,15 @@ static int iproc_gpio_direction_output(struct gpio_chip *gc, unsigned gpio, return 0; } +static int iproc_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio) +{ + struct iproc_gpio *chip = gpiochip_get_data(gc); + unsigned int offset = IPROC_GPIO_REG(gpio, IPROC_GPIO_OUT_EN_OFFSET); + unsigned int shift = IPROC_GPIO_SHIFT(gpio); + + return !(readl(chip->base + offset) & BIT(shift)); +} + static void iproc_gpio_set(struct gpio_chip *gc, unsigned gpio, int val) { struct iproc_gpio *chip = gpiochip_get_data(gc); @@ -461,20 +472,44 @@ static const struct pinctrl_ops iproc_pctrl_ops = { static int iproc_gpio_set_pull(struct iproc_gpio *chip, unsigned gpio, bool disable, bool pull_up) { + void __iomem *base; unsigned long flags; + unsigned int shift; + u32 val_1, val_2; raw_spin_lock_irqsave(&chip->lock, flags); - - if (disable) { - iproc_set_bit(chip, IPROC_GPIO_RES_EN_OFFSET, gpio, false); + if (chip->io_ctrl_type == IOCTRL_TYPE_CDRU) { + base = chip->io_ctrl; + shift = IPROC_GPIO_SHIFT(gpio); + + val_1 = readl(base + IPROC_GPIO_PULL_UP_OFFSET); + val_2 = readl(base + IPROC_GPIO_PULL_DN_OFFSET); + if (disable) { + /* no pull-up or pull-down */ + val_1 &= ~BIT(shift); + val_2 &= ~BIT(shift); + } else if (pull_up) { + val_1 |= BIT(shift); + val_2 &= ~BIT(shift); + } else { + val_1 &= ~BIT(shift); + val_2 |= BIT(shift); + } + writel(val_1, base + IPROC_GPIO_PULL_UP_OFFSET); + writel(val_2, base + IPROC_GPIO_PULL_DN_OFFSET); } else { - iproc_set_bit(chip, IPROC_GPIO_PAD_RES_OFFSET, gpio, - pull_up); - iproc_set_bit(chip, IPROC_GPIO_RES_EN_OFFSET, gpio, true); + if (disable) { + iproc_set_bit(chip, IPROC_GPIO_RES_EN_OFFSET, gpio, + false); + } else { + iproc_set_bit(chip, IPROC_GPIO_PAD_RES_OFFSET, gpio, + pull_up); + iproc_set_bit(chip, IPROC_GPIO_RES_EN_OFFSET, gpio, + true); + } } raw_spin_unlock_irqrestore(&chip->lock, flags); - dev_dbg(chip->dev, "gpio:%u set pullup:%d\n", gpio, pull_up); return 0; @@ -483,14 +518,35 @@ static int iproc_gpio_set_pull(struct iproc_gpio *chip, unsigned gpio, static void iproc_gpio_get_pull(struct iproc_gpio *chip, unsigned gpio, bool *disable, bool *pull_up) { + void __iomem *base; unsigned long flags; + unsigned int shift; + u32 val_1, val_2; raw_spin_lock_irqsave(&chip->lock, flags); - *disable = !iproc_get_bit(chip, IPROC_GPIO_RES_EN_OFFSET, gpio); - *pull_up = iproc_get_bit(chip, IPROC_GPIO_PAD_RES_OFFSET, gpio); + if (chip->io_ctrl_type == IOCTRL_TYPE_CDRU) { + base = chip->io_ctrl; + shift = IPROC_GPIO_SHIFT(gpio); + + val_1 = readl(base + IPROC_GPIO_PULL_UP_OFFSET) & BIT(shift); + val_2 = readl(base + IPROC_GPIO_PULL_DN_OFFSET) & BIT(shift); + + *pull_up = val_1 ? true : false; + *disable = (val_1 | val_2) ? false : true; + + } else { + *disable = !iproc_get_bit(chip, IPROC_GPIO_RES_EN_OFFSET, gpio); + *pull_up = iproc_get_bit(chip, IPROC_GPIO_PAD_RES_OFFSET, gpio); + } raw_spin_unlock_irqrestore(&chip->lock, flags); } +#define DRV_STRENGTH_OFFSET(gpio, bit, type) ((type) == IOCTRL_TYPE_AON ? \ + ((2 - (bit)) * 4 + IPROC_GPIO_DRV_CTRL_OFFSET) : \ + ((type) == IOCTRL_TYPE_CDRU) ? \ + ((bit) * 4 + IPROC_GPIO_DRV_CTRL_OFFSET) : \ + ((bit) * 4 + IPROC_GPIO_REG(gpio, IPROC_GPIO_ASIU_DRV0_CTRL_OFFSET))) + static int iproc_gpio_set_strength(struct iproc_gpio *chip, unsigned gpio, unsigned strength) { @@ -505,11 +561,8 @@ static int iproc_gpio_set_strength(struct iproc_gpio *chip, unsigned gpio, if (chip->io_ctrl) { base = chip->io_ctrl; - offset = IPROC_GPIO_DRV0_CTRL_OFFSET; } else { base = chip->base; - offset = IPROC_GPIO_REG(gpio, - IPROC_GPIO_ASIU_DRV0_CTRL_OFFSET); } shift = IPROC_GPIO_SHIFT(gpio); @@ -520,11 +573,11 @@ static int iproc_gpio_set_strength(struct iproc_gpio *chip, unsigned gpio, raw_spin_lock_irqsave(&chip->lock, flags); strength = (strength / 2) - 1; for (i = 0; i < GPIO_DRV_STRENGTH_BITS; i++) { + offset = DRV_STRENGTH_OFFSET(gpio, i, chip->io_ctrl_type); val = readl(base + offset); val &= ~BIT(shift); val |= ((strength >> i) & 0x1) << shift; writel(val, base + offset); - offset += 4; } raw_spin_unlock_irqrestore(&chip->lock, flags); @@ -541,11 +594,8 @@ static int iproc_gpio_get_strength(struct iproc_gpio *chip, unsigned gpio, if (chip->io_ctrl) { base = chip->io_ctrl; - offset = IPROC_GPIO_DRV0_CTRL_OFFSET; } else { base = chip->base; - offset = IPROC_GPIO_REG(gpio, - IPROC_GPIO_ASIU_DRV0_CTRL_OFFSET); } shift = IPROC_GPIO_SHIFT(gpio); @@ -553,10 +603,10 @@ static int iproc_gpio_get_strength(struct iproc_gpio *chip, unsigned gpio, raw_spin_lock_irqsave(&chip->lock, flags); *strength = 0; for (i = 0; i < GPIO_DRV_STRENGTH_BITS; i++) { + offset = DRV_STRENGTH_OFFSET(gpio, i, chip->io_ctrl_type); val = readl(base + offset) & BIT(shift); val >>= shift; *strength += (val << i); - offset += 4; } /* convert to mA */ @@ -734,6 +784,7 @@ static int iproc_gpio_probe(struct platform_device *pdev) u32 ngpios, pinconf_disable_mask = 0; int irq, ret; bool no_pinconf = false; + enum iproc_pinconf_ctrl_type io_ctrl_type = IOCTRL_TYPE_INVALID; /* NSP does not support drive strength config */ if (of_device_is_compatible(dev->of_node, "brcm,iproc-nsp-gpio")) @@ -750,8 +801,7 @@ static int iproc_gpio_probe(struct platform_device *pdev) chip->dev = dev; platform_set_drvdata(pdev, chip); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - chip->base = devm_ioremap_resource(dev, res); + chip->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(chip->base)) { dev_err(dev, "unable to map I/O memory\n"); return PTR_ERR(chip->base); @@ -764,8 +814,15 @@ static int iproc_gpio_probe(struct platform_device *pdev) dev_err(dev, "unable to map I/O memory\n"); return PTR_ERR(chip->io_ctrl); } + if (of_device_is_compatible(dev->of_node, + "brcm,cygnus-ccm-gpio")) + io_ctrl_type = IOCTRL_TYPE_CDRU; + else + io_ctrl_type = IOCTRL_TYPE_AON; } + chip->io_ctrl_type = io_ctrl_type; + if (of_property_read_u32(dev->of_node, "ngpios", &ngpios)) { dev_err(&pdev->dev, "missing ngpios DT property\n"); return -ENODEV; @@ -784,12 +841,42 @@ static int iproc_gpio_probe(struct platform_device *pdev) gc->free = iproc_gpio_free; gc->direction_input = iproc_gpio_direction_input; gc->direction_output = iproc_gpio_direction_output; + gc->get_direction = iproc_gpio_get_direction; gc->set = iproc_gpio_set; gc->get = iproc_gpio_get; chip->pinmux_is_supported = of_property_read_bool(dev->of_node, "gpio-ranges"); + /* 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; + girq->parent_handler = iproc_gpio_irq_handler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(dev, 1, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + girq->parents[0] = irq; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_bad_irq; + } + ret = gpiochip_add_data(gc, chip); if (ret < 0) { dev_err(dev, "unable to add GPIO chip\n"); @@ -814,20 +901,6 @@ static int iproc_gpio_probe(struct platform_device *pdev) } } - /* optional GPIO interrupt support */ - irq = platform_get_irq(pdev, 0); - if (irq) { - ret = gpiochip_irqchip_add(gc, &iproc_gpio_irq_chip, 0, - handle_simple_irq, IRQ_TYPE_NONE); - if (ret) { - dev_err(dev, "no GPIO irqchip\n"); - goto err_rm_gpiochip; - } - - gpiochip_set_chained_irqchip(gc, &iproc_gpio_irq_chip, irq, - iproc_gpio_irq_handler); - } - return 0; err_rm_gpiochip: diff --git a/drivers/pinctrl/bcm/pinctrl-ns2-mux.c b/drivers/pinctrl/bcm/pinctrl-ns2-mux.c index 2bf6af7df7d9..57044ab376d3 100644 --- a/drivers/pinctrl/bcm/pinctrl-ns2-mux.c +++ b/drivers/pinctrl/bcm/pinctrl-ns2-mux.c @@ -640,8 +640,8 @@ static int ns2_pinmux_enable(struct pinctrl_dev *pctrl_dev, const struct ns2_pin_function *func; const struct ns2_pin_group *grp; - if (grp_select > pinctrl->num_groups || - func_select > pinctrl->num_functions) + if (grp_select >= pinctrl->num_groups || + func_select >= pinctrl->num_functions) return -EINVAL; func = &pinctrl->functions[func_select]; @@ -1042,23 +1042,21 @@ static int ns2_pinmux_probe(struct platform_device *pdev) platform_set_drvdata(pdev, pinctrl); spin_lock_init(&pinctrl->lock); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - pinctrl->base0 = devm_ioremap_resource(&pdev->dev, res); + pinctrl->base0 = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(pinctrl->base0)) return PTR_ERR(pinctrl->base0); res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (!res) return -EINVAL; - pinctrl->base1 = devm_ioremap_nocache(&pdev->dev, res->start, + pinctrl->base1 = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!pinctrl->base1) { dev_err(&pdev->dev, "unable to map I/O space\n"); return -ENOMEM; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 2); - pinctrl->pinconf_base = devm_ioremap_resource(&pdev->dev, res); + pinctrl->pinconf_base = devm_platform_ioremap_resource(pdev, 2); if (IS_ERR(pinctrl->pinconf_base)) return PTR_ERR(pinctrl->pinconf_base); diff --git a/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c b/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c index e67ae52023ad..bed0124388c0 100644 --- a/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c +++ b/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c @@ -64,17 +64,16 @@ * @gc: GPIO chip * @pctl: pointer to pinctrl_dev * @pctldesc: pinctrl descriptor - * @irq_domain: pointer to irq domain * @lock: lock to protect access to I/O registers */ 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; - struct irq_domain *irq_domain; raw_spinlock_t lock; }; @@ -136,8 +135,8 @@ static inline bool nsp_get_bit(struct nsp_gpio *chip, enum base_type address, static irqreturn_t nsp_gpio_irq_handler(int irq, void *data) { - struct nsp_gpio *chip = (struct nsp_gpio *)data; - struct gpio_chip gc = chip->gc; + struct gpio_chip *gc = (struct gpio_chip *)data; + struct nsp_gpio *chip = gpiochip_get_data(gc); int bit; unsigned long int_bits = 0; u32 int_status; @@ -155,14 +154,14 @@ static irqreturn_t nsp_gpio_irq_handler(int irq, void *data) level &= readl(chip->base + NSP_GPIO_INT_MASK); int_bits = level | event; - for_each_set_bit(bit, &int_bits, gc.ngpio) { + for_each_set_bit(bit, &int_bits, gc->ngpio) { /* * Clear the interrupt before invoking the * handler, so we do not leave any window */ writel(BIT(bit), chip->base + NSP_GPIO_EVENT); generic_handle_irq( - irq_linear_revmap(chip->irq_domain, bit)); + irq_linear_revmap(gc->irq.domain, bit)); } } @@ -171,7 +170,8 @@ static irqreturn_t nsp_gpio_irq_handler(int irq, void *data) static void nsp_gpio_irq_ack(struct irq_data *d) { - struct nsp_gpio *chip = irq_data_get_irq_chip_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct nsp_gpio *chip = gpiochip_get_data(gc); unsigned gpio = d->hwirq; u32 val = BIT(gpio); u32 trigger_type; @@ -189,7 +189,8 @@ static void nsp_gpio_irq_ack(struct irq_data *d) */ static void nsp_gpio_irq_set_mask(struct irq_data *d, bool unmask) { - struct nsp_gpio *chip = irq_data_get_irq_chip_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct nsp_gpio *chip = gpiochip_get_data(gc); unsigned gpio = d->hwirq; u32 trigger_type; @@ -202,7 +203,8 @@ static void nsp_gpio_irq_set_mask(struct irq_data *d, bool unmask) static void nsp_gpio_irq_mask(struct irq_data *d) { - struct nsp_gpio *chip = irq_data_get_irq_chip_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct nsp_gpio *chip = gpiochip_get_data(gc); unsigned long flags; raw_spin_lock_irqsave(&chip->lock, flags); @@ -212,7 +214,8 @@ static void nsp_gpio_irq_mask(struct irq_data *d) static void nsp_gpio_irq_unmask(struct irq_data *d) { - struct nsp_gpio *chip = irq_data_get_irq_chip_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct nsp_gpio *chip = gpiochip_get_data(gc); unsigned long flags; raw_spin_lock_irqsave(&chip->lock, flags); @@ -222,7 +225,8 @@ static void nsp_gpio_irq_unmask(struct irq_data *d) static int nsp_gpio_irq_set_type(struct irq_data *d, unsigned int type) { - struct nsp_gpio *chip = irq_data_get_irq_chip_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct nsp_gpio *chip = gpiochip_get_data(gc); unsigned gpio = d->hwirq; bool level_low; bool falling; @@ -265,16 +269,6 @@ static int nsp_gpio_irq_set_type(struct irq_data *d, unsigned int type) return 0; } -static struct irq_chip nsp_gpio_irq_chip = { - .name = "gpio-a", - .irq_enable = nsp_gpio_irq_unmask, - .irq_disable = nsp_gpio_irq_mask, - .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, -}; - static int nsp_gpio_direction_input(struct gpio_chip *gc, unsigned gpio) { struct nsp_gpio *chip = gpiochip_get_data(gc); @@ -303,30 +297,36 @@ static int nsp_gpio_direction_output(struct gpio_chip *gc, unsigned gpio, return 0; } -static void nsp_gpio_set(struct gpio_chip *gc, unsigned gpio, int val) +static int nsp_gpio_get_direction(struct gpio_chip *gc, unsigned gpio) { struct nsp_gpio *chip = gpiochip_get_data(gc); unsigned long flags; + int val; raw_spin_lock_irqsave(&chip->lock, flags); - nsp_set_bit(chip, REG, NSP_GPIO_DATA_OUT, gpio, !!(val)); + val = nsp_get_bit(chip, REG, NSP_GPIO_OUT_EN, gpio); raw_spin_unlock_irqrestore(&chip->lock, flags); - dev_dbg(chip->dev, "gpio:%u set, value:%d\n", gpio, val); + return !val; } -static int nsp_gpio_get(struct gpio_chip *gc, unsigned gpio) +static void nsp_gpio_set(struct gpio_chip *gc, unsigned gpio, int val) { struct nsp_gpio *chip = gpiochip_get_data(gc); + unsigned long flags; - return !!(readl(chip->base + NSP_GPIO_DATA_IN) & BIT(gpio)); + raw_spin_lock_irqsave(&chip->lock, flags); + nsp_set_bit(chip, REG, NSP_GPIO_DATA_OUT, gpio, !!(val)); + raw_spin_unlock_irqrestore(&chip->lock, flags); + + dev_dbg(chip->dev, "gpio:%u set, value:%d\n", gpio, val); } -static int nsp_gpio_to_irq(struct gpio_chip *gc, unsigned offset) +static int nsp_gpio_get(struct gpio_chip *gc, unsigned gpio) { struct nsp_gpio *chip = gpiochip_get_data(gc); - return irq_linear_revmap(chip->irq_domain, offset); + return !!(readl(chip->base + NSP_GPIO_DATA_IN) & BIT(gpio)); } static int nsp_get_groups_count(struct pinctrl_dev *pctldev) @@ -613,10 +613,9 @@ static const struct of_device_id nsp_gpio_of_match[] = { static int nsp_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct resource *res; struct nsp_gpio *chip; struct gpio_chip *gc; - u32 val, count; + u32 val; int irq, ret; if (of_property_read_u32(pdev->dev.of_node, "ngpios", &val)) { @@ -631,15 +630,13 @@ static int nsp_gpio_probe(struct platform_device *pdev) chip->dev = dev; platform_set_drvdata(pdev, chip); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - chip->base = devm_ioremap_resource(dev, res); + chip->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(chip->base)) { dev_err(dev, "unable to map I/O memory\n"); return PTR_ERR(chip->base); } - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - chip->io_ctrl = devm_ioremap_resource(dev, res); + chip->io_ctrl = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(chip->io_ctrl)) { dev_err(dev, "unable to map I/O memory\n"); return PTR_ERR(chip->io_ctrl); @@ -657,46 +654,47 @@ static int nsp_gpio_probe(struct platform_device *pdev) gc->free = gpiochip_generic_free; gc->direction_input = nsp_gpio_direction_input; gc->direction_output = nsp_gpio_direction_output; + gc->get_direction = nsp_gpio_get_direction; gc->set = nsp_gpio_set; gc->get = nsp_gpio_get; - gc->to_irq = nsp_gpio_to_irq; /* optional GPIO interrupt support */ irq = platform_get_irq(pdev, 0); if (irq > 0) { - /* Create irq domain so that each pin can be assigned an IRQ.*/ - chip->irq_domain = irq_domain_add_linear(gc->of_node, gc->ngpio, - &irq_domain_simple_ops, - chip); - if (!chip->irq_domain) { - dev_err(&pdev->dev, "Couldn't allocate IRQ domain\n"); - return -ENXIO; - } + struct gpio_irq_chip *girq; + struct irq_chip *irqc; - /* Map each gpio to an IRQ and set the handler for gpiolib. */ - for (count = 0; count < gc->ngpio; count++) { - int irq = irq_create_mapping(chip->irq_domain, count); + 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; - irq_set_chip_and_handler(irq, &nsp_gpio_irq_chip, - handle_simple_irq); - irq_set_chip_data(irq, chip); - } + val = readl(chip->base + NSP_CHIP_A_INT_MASK); + val = val | NSP_CHIP_A_GPIO_INT_BIT; + writel(val, (chip->base + NSP_CHIP_A_INT_MASK)); /* Install ISR for this GPIO controller. */ - ret = devm_request_irq(&pdev->dev, irq, nsp_gpio_irq_handler, - IRQF_SHARED, "gpio-a", chip); + ret = devm_request_irq(dev, irq, nsp_gpio_irq_handler, + IRQF_SHARED, "gpio-a", &chip->gc); if (ret) { dev_err(&pdev->dev, "Unable to request IRQ%d: %d\n", irq, ret); - goto err_rm_gpiochip; + return ret; } - val = readl(chip->base + NSP_CHIP_A_INT_MASK); - val = val | NSP_CHIP_A_GPIO_INT_BIT; - writel(val, (chip->base + NSP_CHIP_A_INT_MASK)); + girq = &chip->gc.irq; + girq->chip = irqc; + /* This will let us handle the parent IRQ in the driver */ + girq->parent_handler = NULL; + girq->num_parents = 0; + girq->parents = NULL; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_simple_irq; } - ret = gpiochip_add_data(gc, chip); + ret = devm_gpiochip_add_data(dev, gc, chip); if (ret < 0) { dev_err(dev, "unable to add GPIO chip\n"); return ret; @@ -705,15 +703,10 @@ static int nsp_gpio_probe(struct platform_device *pdev) ret = nsp_gpio_register_pinconf(chip); if (ret) { dev_err(dev, "unable to register pinconf\n"); - goto err_rm_gpiochip; + return ret; } return 0; - -err_rm_gpiochip: - gpiochip_remove(gc); - - return ret; } static struct platform_driver nsp_gpio_driver = { diff --git a/drivers/pinctrl/bcm/pinctrl-nsp-mux.c b/drivers/pinctrl/bcm/pinctrl-nsp-mux.c index 87618a4e90e4..f1d60a708815 100644 --- a/drivers/pinctrl/bcm/pinctrl-nsp-mux.c +++ b/drivers/pinctrl/bcm/pinctrl-nsp-mux.c @@ -571,23 +571,21 @@ static int nsp_pinmux_probe(struct platform_device *pdev) platform_set_drvdata(pdev, pinctrl); spin_lock_init(&pinctrl->lock); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - pinctrl->base0 = devm_ioremap_resource(&pdev->dev, res); + pinctrl->base0 = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(pinctrl->base0)) return PTR_ERR(pinctrl->base0); res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (!res) return -EINVAL; - pinctrl->base1 = devm_ioremap_nocache(&pdev->dev, res->start, + pinctrl->base1 = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!pinctrl->base1) { dev_err(&pdev->dev, "unable to map I/O space\n"); return -ENOMEM; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 2); - pinctrl->base2 = devm_ioremap_resource(&pdev->dev, res); + pinctrl->base2 = devm_platform_ioremap_resource(pdev, 2); if (IS_ERR(pinctrl->base2)) return PTR_ERR(pinctrl->base2); |