summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>2014-07-28 17:15:41 +0200
committerUwe Kleine-König <u.kleine-koenig@pengutronix.de>2015-09-09 22:52:49 +0200
commiteb408eb0d6ab0471a7be0a6dbc7119eb3f48ef41 (patch)
tree230fd0138b0fd4603072e31a1a0f63b999a4f545
parent12b3e3a9538ccd18a5fb6ba719061d19ffb28b83 (diff)
downloadlinux-efm/work.tar.gz
linux-efm/work.tar.xz
-rw-r--r--drivers/pinctrl/pinctrl-efm32.c78
-rw-r--r--kernel/irq/irqdomain.c1
2 files changed, 37 insertions, 42 deletions
diff --git a/drivers/pinctrl/pinctrl-efm32.c b/drivers/pinctrl/pinctrl-efm32.c
index 27c0f7c24a5d..b197d61ca4fd 100644
--- a/drivers/pinctrl/pinctrl-efm32.c
+++ b/drivers/pinctrl/pinctrl-efm32.c
@@ -66,11 +66,11 @@ struct efm32_pinctrl_ddata {
unsigned int irq_even, irq_odd;
struct irq_domain *irq_domain;
- struct gpio_chip chip;
+ struct gpio_chip gpiochip;
unsigned assigned_irqpins;
};
-#define to_ddata(_chip) container_of(_chip, struct efm32_pinctrl_ddata, chip)
+#define to_ddata(_chip) container_of(_chip, struct efm32_pinctrl_ddata, gpiochip)
static unsigned efm32_pinctrl_get_mode(struct efm32_pinctrl_ddata *ddata,
unsigned pin, unsigned port)
@@ -78,7 +78,7 @@ static unsigned efm32_pinctrl_get_mode(struct efm32_pinctrl_ddata *ddata,
return (readl(ddata->base + (pin < 8 ? REG_PORT_MODEL(port) : REG_PORT_MODEH(port))) >> (4 * (pin & 7))) & 0xf;
}
-static int efm32_pinctrl_direction_input(struct gpio_chip *chip,
+static int efm32_pinctrl_gpio_direction_input(struct gpio_chip *chip,
unsigned offset)
{
struct efm32_pinctrl_ddata *ddata = to_ddata(chip);
@@ -99,10 +99,9 @@ static int efm32_pinctrl_direction_input(struct gpio_chip *chip,
ret = -EIO;
return ret;
-
}
-static int efm32_pinctrl_get(struct gpio_chip *chip, unsigned offset)
+static int efm32_pinctrl_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct efm32_pinctrl_ddata *ddata = to_ddata(chip);
unsigned pin = offset % 16;
@@ -112,7 +111,7 @@ static int efm32_pinctrl_get(struct gpio_chip *chip, unsigned offset)
return din & (1 << pin);
}
-static int efm32_pinctrl_direction_output(struct gpio_chip *chip,
+static int efm32_pinctrl_gpio_direction_output(struct gpio_chip *chip,
unsigned offset, int value)
{
struct efm32_pinctrl_ddata *ddata = to_ddata(chip);
@@ -137,7 +136,7 @@ static int efm32_pinctrl_direction_output(struct gpio_chip *chip,
return ret;
}
-static void efm32_pinctrl_set(struct gpio_chip *chip,
+static void efm32_pinctrl_gpio_set(struct gpio_chip *chip,
unsigned offset, int value)
{
struct efm32_pinctrl_ddata *ddata = to_ddata(chip);
@@ -148,28 +147,12 @@ static void efm32_pinctrl_set(struct gpio_chip *chip,
(value ? REG_PORT_DOUTSET(port) : REG_PORT_DOUTCLR(port)));
}
-static int efm32_pinctrl_to_irq(struct gpio_chip *chip, unsigned offset)
+static int efm32_pinctrl_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct efm32_pinctrl_ddata *ddata = to_ddata(chip);
- unsigned pin = offset % 16;
- unsigned port = offset / 16;
- unsigned extipsel_offset = pin < 8 ? REG_EXTIPSELL : REG_EXTIPSELL;
- unsigned extipsel;
- unsigned extipsel_shift = (pin % 8) * 4;
-
- extipsel = readl(ddata->base + extipsel_offset);
-
- if (ddata->assigned_irqpins & (1 << pin)) {
- if (((extipsel >> extipsel_shift) & 0x7) != port)
- return -EBUSY;
- }
- extipsel &= ~(0x7 << extipsel_shift);
- extipsel |= port << extipsel_shift;
- ddata->assigned_irqpins |= 1 << pin;
- writel(extipsel, ddata->base + extipsel_offset);
-
- return irq_create_mapping(ddata->irq_domain, offset % 16);
+ pr_info("%s: %d\n", __func__, offset);
+ return irq_create_mapping(ddata->irq_domain, offset);
}
static void efm32_pinctrl_handler(unsigned int irq, struct irq_desc *desc,
@@ -185,8 +168,19 @@ static void efm32_pinctrl_handler(unsigned int irq, struct irq_desc *desc,
while (flag) {
int line = __fls(flag);
+ u32 extipsel;
+ unsigned port;
+
+ if (line <= 7)
+ extipsel = readl(ddata->base + REG_EXTIPSELL);
+ else
+ extipsel = readl(ddata->base + REG_EXTIPSELH);
+
+ port = (extipsel >> 4 * (line & 7)) & 0x7;
+ pr_info("%s: port = %u, line = %d\n", __func__, port, line);
- generic_handle_irq(irq_create_mapping(ddata->irq_domain, line));
+ generic_handle_irq(irq_create_mapping(ddata->irq_domain,
+ 16 * port + line));
flag &= ~(1 << line);
}
@@ -247,7 +241,6 @@ static void efm32_pinctrl_irq_level_unmask(struct irq_data *data)
ien = readl(ddata->base + REG_IEN);
ien |= 1 << data->hwirq;
writel(ien, ddata->base + REG_IEN);
-
}
static struct irq_chip efm32_pinctrl_level_irqchip = {
@@ -262,12 +255,13 @@ static int efm32_pinctrl_irq_map(struct irq_domain *d, unsigned int virq,
{
struct efm32_pinctrl_ddata *ddata = d->host_data;
+ pr_info("%s: virq=%u, hwirq=%lu\n", __func__, virq, hw);
irq_set_chip_data(virq, ddata);
irq_set_chip_and_handler(virq, &efm32_pinctrl_level_irqchip, handle_level_irq);
set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
- return 0;
+ return -EBUSY;
}
static const struct irq_domain_ops efm32_pinctrl_irq_domain_ops = {
@@ -466,25 +460,25 @@ int efm32_pinctrl_probe(struct platform_device *pdev)
irq_set_chained_handler(ddata->irq_odd, efm32_pinctrl_handler_odd);
ddata->irq_domain = irq_domain_add_linear(pdev->dev.of_node,
- 16, &efm32_pinctrl_irq_domain_ops, ddata);
+ 16 * 6, &efm32_pinctrl_irq_domain_ops, ddata);
if (!ddata->irq_domain) {
dev_err(&pdev->dev, "failed to add irq_domain\n");
goto err_add_irq_domain;
}
- ddata->chip.label = DRIVER_NAME;
- ddata->chip.dev = &pdev->dev;
- ddata->chip.owner = THIS_MODULE;
+ ddata->gpiochip.label = DRIVER_NAME;
+ ddata->gpiochip.dev = &pdev->dev;
+ ddata->gpiochip.owner = THIS_MODULE;
//ddata->chip.get_direction
- ddata->chip.direction_input = efm32_pinctrl_direction_input;
- ddata->chip.get = efm32_pinctrl_get;
- ddata->chip.direction_output = efm32_pinctrl_direction_output;
- ddata->chip.set = efm32_pinctrl_set;
- ddata->chip.to_irq = efm32_pinctrl_to_irq;
- ddata->chip.base = -1;
- ddata->chip.ngpio = 96;
- ddata->chip.can_sleep = 0;
+ ddata->gpiochip.direction_input = efm32_pinctrl_gpio_direction_input;
+ ddata->gpiochip.get = efm32_pinctrl_gpio_get;
+ ddata->gpiochip.direction_output = efm32_pinctrl_gpio_direction_output;
+ ddata->gpiochip.set = efm32_pinctrl_gpio_set;
+ ddata->gpiochip.to_irq = efm32_pinctrl_gpio_to_irq;
+ ddata->gpiochip.base = -1;
+ ddata->gpiochip.ngpio = 96;
+ ddata->gpiochip.can_sleep = 0;
ddata->pinctrl = pinctrl_register(&efm32_pinctldesc, &pdev->dev, ddata);
if (!ddata->pinctrl) {
@@ -493,7 +487,7 @@ int efm32_pinctrl_probe(struct platform_device *pdev)
goto err_pinctrl_register;
}
- ret = gpiochip_add(&ddata->chip);
+ ret = gpiochip_add(&ddata->gpiochip);
if (ret) {
dev_err(&pdev->dev, "Failed to register gpiochip\n");
pinctrl_unregister(ddata->pinctrl);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 8c3577fef78c..8d3ece33d074 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -307,6 +307,7 @@ int irq_domain_associate(struct irq_domain *domain, unsigned int virq,
/* If not already assigned, give the domain the chip's name */
if (!domain->name && irq_data->chip)
+ /* XXX: domain name is already used above ... */
domain->name = irq_data->chip->name;
}