diff options
Diffstat (limited to 'drivers/pinctrl/bcm/pinctrl-nsp-gpio.c')
-rw-r--r-- | drivers/pinctrl/bcm/pinctrl-nsp-gpio.c | 119 |
1 files changed, 56 insertions, 63 deletions
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 = { |