diff options
author | Uwe Kleine-König <u.kleine-koenig@pengutronix.de> | 2014-07-28 17:15:41 +0200 |
---|---|---|
committer | Uwe Kleine-König <u.kleine-koenig@pengutronix.de> | 2015-09-09 22:52:49 +0200 |
commit | eb408eb0d6ab0471a7be0a6dbc7119eb3f48ef41 (patch) | |
tree | 230fd0138b0fd4603072e31a1a0f63b999a4f545 | |
parent | 12b3e3a9538ccd18a5fb6ba719061d19ffb28b83 (diff) | |
download | linux-efm/work.tar.gz linux-efm/work.tar.xz |
wipefm/work
-rw-r--r-- | drivers/pinctrl/pinctrl-efm32.c | 78 | ||||
-rw-r--r-- | kernel/irq/irqdomain.c | 1 |
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; } |