summaryrefslogtreecommitdiff
path: root/drivers/pinctrl/pinctrl-pistachio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pinctrl/pinctrl-pistachio.c')
-rw-r--r--drivers/pinctrl/pinctrl-pistachio.c112
1 files changed, 67 insertions, 45 deletions
diff --git a/drivers/pinctrl/pinctrl-pistachio.c b/drivers/pinctrl/pinctrl-pistachio.c
index aa5f949ef219..0b33b01dbaad 100644
--- a/drivers/pinctrl/pinctrl-pistachio.c
+++ b/drivers/pinctrl/pinctrl-pistachio.c
@@ -1,25 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Pistachio SoC pinctrl driver
*
* Copyright (C) 2014 Imagination Technologies Ltd.
* Copyright (C) 2014 Google, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
*/
#include <linux/gpio/driver.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
-#include <linux/of.h>
-#include <linux/of_irq.h>
+#include <linux/mod_devicetable.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
@@ -96,10 +94,10 @@ struct pistachio_pin_group {
struct pistachio_gpio_bank {
struct pistachio_pinctrl *pctl;
void __iomem *base;
+ int instance;
unsigned int pin_base;
unsigned int npins;
struct gpio_chip gpio_chip;
- struct irq_chip irq_chip;
};
struct pistachio_pinctrl {
@@ -1158,18 +1156,24 @@ static const struct pinconf_ops pistachio_pinconf_ops = {
.is_generic = true,
};
-static struct pinctrl_desc pistachio_pinctrl_desc = {
+static const struct pinctrl_desc pistachio_pinctrl_desc = {
.name = "pistachio-pinctrl",
.pctlops = &pistachio_pinctrl_ops,
.pmxops = &pistachio_pinmux_ops,
.confops = &pistachio_pinconf_ops,
+ .pins = pistachio_pins,
+ .npins = ARRAY_SIZE(pistachio_pins),
+
};
static int pistachio_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
{
struct pistachio_gpio_bank *bank = gpiochip_get_data(chip);
- return !(gpio_readl(bank, GPIO_OUTPUT_EN) & BIT(offset));
+ if (gpio_readl(bank, GPIO_OUTPUT_EN) & BIT(offset))
+ return GPIO_LINE_DIRECTION_OUT;
+
+ return GPIO_LINE_DIRECTION_IN;
}
static int pistachio_gpio_get(struct gpio_chip *chip, unsigned offset)
@@ -1185,12 +1189,14 @@ static int pistachio_gpio_get(struct gpio_chip *chip, unsigned offset)
return !!(gpio_readl(bank, reg) & BIT(offset));
}
-static void pistachio_gpio_set(struct gpio_chip *chip, unsigned offset,
- int value)
+static int pistachio_gpio_set(struct gpio_chip *chip, unsigned int offset,
+ int value)
{
struct pistachio_gpio_bank *bank = gpiochip_get_data(chip);
gpio_mask_writel(bank, GPIO_OUTPUT, offset, !!value);
+
+ return 0;
}
static int pistachio_gpio_direction_input(struct gpio_chip *chip,
@@ -1228,12 +1234,14 @@ static void pistachio_gpio_irq_mask(struct irq_data *data)
struct pistachio_gpio_bank *bank = irqd_to_bank(data);
gpio_mask_writel(bank, GPIO_INTERRUPT_EN, data->hwirq, 0);
+ gpiochip_disable_irq(&bank->gpio_chip, irqd_to_hwirq(data));
}
static void pistachio_gpio_irq_unmask(struct irq_data *data)
{
struct pistachio_gpio_bank *bank = irqd_to_bank(data);
+ gpiochip_enable_irq(&bank->gpio_chip, irqd_to_hwirq(data));
gpio_mask_writel(bank, GPIO_INTERRUPT_EN, data->hwirq, 1);
}
@@ -1306,12 +1314,13 @@ static void pistachio_gpio_irq_handler(struct irq_desc *desc)
pending = gpio_readl(bank, GPIO_INTERRUPT_STATUS) &
gpio_readl(bank, GPIO_INTERRUPT_EN);
for_each_set_bit(pin, &pending, 16)
- generic_handle_irq(irq_linear_revmap(gc->irq.domain, pin));
+ generic_handle_domain_irq(gc->irq.domain, pin);
chained_irq_exit(chip, desc);
}
#define GPIO_BANK(_bank, _pin_base, _npins) \
{ \
+ .instance = (_bank), \
.pin_base = _pin_base, \
.npins = _npins, \
.gpio_chip = { \
@@ -1326,14 +1335,6 @@ static void pistachio_gpio_irq_handler(struct irq_desc *desc)
.base = _pin_base, \
.ngpio = _npins, \
}, \
- .irq_chip = { \
- .name = "GPIO" #_bank, \
- .irq_startup = pistachio_gpio_irq_startup, \
- .irq_ack = pistachio_gpio_irq_ack, \
- .irq_mask = pistachio_gpio_irq_mask, \
- .irq_unmask = pistachio_gpio_irq_unmask, \
- .irq_set_type = pistachio_gpio_irq_set_type, \
- }, \
}
static struct pistachio_gpio_bank pistachio_gpio_banks[] = {
@@ -1345,62 +1346,88 @@ static struct pistachio_gpio_bank pistachio_gpio_banks[] = {
GPIO_BANK(5, PISTACHIO_PIN_MFIO(80), 10),
};
+static void pistachio_gpio_irq_print_chip(struct irq_data *data,
+ struct seq_file *p)
+{
+ struct pistachio_gpio_bank *bank = irqd_to_bank(data);
+
+ seq_printf(p, "GPIO%d", bank->instance);
+}
+
+static const struct irq_chip pistachio_gpio_irq_chip = {
+ .irq_startup = pistachio_gpio_irq_startup,
+ .irq_ack = pistachio_gpio_irq_ack,
+ .irq_mask = pistachio_gpio_irq_mask,
+ .irq_unmask = pistachio_gpio_irq_unmask,
+ .irq_set_type = pistachio_gpio_irq_set_type,
+ .irq_print_chip = pistachio_gpio_irq_print_chip,
+ .flags = IRQCHIP_IMMUTABLE,
+ GPIOCHIP_IRQ_RESOURCE_HELPERS,
+};
+
static int pistachio_gpio_register(struct pistachio_pinctrl *pctl)
{
- struct device_node *node = pctl->dev->of_node;
struct pistachio_gpio_bank *bank;
unsigned int i;
int irq, ret = 0;
for (i = 0; i < pctl->nbanks; i++) {
char child_name[sizeof("gpioXX")];
- struct device_node *child;
+ struct fwnode_handle *child;
+ struct gpio_irq_chip *girq;
snprintf(child_name, sizeof(child_name), "gpio%d", i);
- child = of_get_child_by_name(node, child_name);
+ child = device_get_named_child_node(pctl->dev, child_name);
if (!child) {
dev_err(pctl->dev, "No node for bank %u\n", i);
ret = -ENODEV;
goto err;
}
- if (!of_find_property(child, "gpio-controller", NULL)) {
+ if (!fwnode_property_present(child, "gpio-controller")) {
+ fwnode_handle_put(child);
dev_err(pctl->dev,
"No gpio-controller property for bank %u\n", i);
ret = -ENODEV;
goto err;
}
- irq = irq_of_parse_and_map(child, 0);
- if (irq < 0) {
- dev_err(pctl->dev, "No IRQ for bank %u: %d\n", i, irq);
- ret = irq;
+ ret = fwnode_irq_get(child, 0);
+ if (ret < 0) {
+ fwnode_handle_put(child);
+ dev_err(pctl->dev, "Failed to retrieve IRQ for bank %u\n", i);
goto err;
}
+ irq = ret;
bank = &pctl->gpio_banks[i];
bank->pctl = pctl;
bank->base = pctl->base + GPIO_BANK_BASE(i);
bank->gpio_chip.parent = pctl->dev;
- bank->gpio_chip.of_node = child;
- ret = gpiochip_add_data(&bank->gpio_chip, bank);
- if (ret < 0) {
- dev_err(pctl->dev, "Failed to add GPIO chip %u: %d\n",
- i, ret);
+ bank->gpio_chip.fwnode = child;
+
+ girq = &bank->gpio_chip.irq;
+ gpio_irq_chip_set_chip(girq, &pistachio_gpio_irq_chip);
+ girq->parent_handler = pistachio_gpio_irq_handler;
+ girq->num_parents = 1;
+ girq->parents = devm_kcalloc(pctl->dev, 1,
+ sizeof(*girq->parents),
+ GFP_KERNEL);
+ if (!girq->parents) {
+ ret = -ENOMEM;
goto err;
}
+ girq->parents[0] = irq;
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_level_irq;
- ret = gpiochip_irqchip_add(&bank->gpio_chip, &bank->irq_chip,
- 0, handle_level_irq, IRQ_TYPE_NONE);
+ ret = gpiochip_add_data(&bank->gpio_chip, bank);
if (ret < 0) {
- dev_err(pctl->dev, "Failed to add IRQ chip %u: %d\n",
+ dev_err(pctl->dev, "Failed to add GPIO chip %u: %d\n",
i, ret);
- gpiochip_remove(&bank->gpio_chip);
goto err;
}
- gpiochip_set_chained_irqchip(&bank->gpio_chip, &bank->irq_chip,
- irq, pistachio_gpio_irq_handler);
ret = gpiochip_add_pin_range(&bank->gpio_chip,
dev_name(pctl->dev), 0,
@@ -1430,7 +1457,6 @@ static const struct of_device_id pistachio_pinctrl_of_match[] = {
static int pistachio_pinctrl_probe(struct platform_device *pdev)
{
struct pistachio_pinctrl *pctl;
- struct resource *res;
pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
if (!pctl)
@@ -1438,8 +1464,7 @@ static int pistachio_pinctrl_probe(struct platform_device *pdev)
pctl->dev = &pdev->dev;
dev_set_drvdata(&pdev->dev, pctl);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- pctl->base = devm_ioremap_resource(&pdev->dev, res);
+ pctl->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(pctl->base))
return PTR_ERR(pctl->base);
@@ -1452,9 +1477,6 @@ static int pistachio_pinctrl_probe(struct platform_device *pdev)
pctl->gpio_banks = pistachio_gpio_banks;
pctl->nbanks = ARRAY_SIZE(pistachio_gpio_banks);
- pistachio_pinctrl_desc.pins = pctl->pins;
- pistachio_pinctrl_desc.npins = pctl->npins;
-
pctl->pctldev = devm_pinctrl_register(&pdev->dev, &pistachio_pinctrl_desc,
pctl);
if (IS_ERR(pctl->pctldev)) {