ARM: at91: add pinctrl support
This is also include the gpio controller as the IP share both.
Each soc will have to describe the SoC limitation and pin configuration via
DT.
This will allow to do not need to touch the C code when adding new SoC if the
IP version is supported.
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 431c375..3d7f11f 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -329,6 +329,8 @@
select IRQ_DOMAIN
select NEED_MACH_GPIO_H
select NEED_MACH_IO_H if PCCARD
+ select PINCTRL
+ select PINCTRL_AT91 if USE_OF
help
This enables support for systems based on Atmel
AT91RM9200 and AT91SAM9* processors.
diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c
index e8f45c4..3b6a948 100644
--- a/arch/arm/mach-at91/board-dt.c
+++ b/arch/arm/mach-at91/board-dt.c
@@ -30,8 +30,6 @@
static const struct of_device_id irq_of_match[] __initconst = {
{ .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init },
- { .compatible = "atmel,at91rm9200-gpio", .data = at91_gpio_of_irq_setup },
- { .compatible = "atmel,at91sam9x5-gpio", .data = at91_gpio_of_irq_setup },
{ /*sentinel*/ }
};
diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c
index a34f0ed..c5d7e1e 100644
--- a/arch/arm/mach-at91/gpio.c
+++ b/arch/arm/mach-at91/gpio.c
@@ -23,8 +23,6 @@
#include <linux/io.h>
#include <linux/irqdomain.h>
#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/of_gpio.h>
#include <asm/mach/irq.h>
@@ -717,80 +715,6 @@
*/
static struct lock_class_key gpio_lock_class;
-#if defined(CONFIG_OF)
-static int at91_gpio_irq_map(struct irq_domain *h, unsigned int virq,
- irq_hw_number_t hw)
-{
- struct at91_gpio_chip *at91_gpio = h->host_data;
-
- irq_set_lockdep_class(virq, &gpio_lock_class);
-
- /*
- * Can use the "simple" and not "edge" handler since it's
- * shorter, and the AIC handles interrupts sanely.
- */
- irq_set_chip_and_handler(virq, &gpio_irqchip,
- handle_simple_irq);
- set_irq_flags(virq, IRQF_VALID);
- irq_set_chip_data(virq, at91_gpio);
-
- return 0;
-}
-
-static struct irq_domain_ops at91_gpio_ops = {
- .map = at91_gpio_irq_map,
- .xlate = irq_domain_xlate_twocell,
-};
-
-int __init at91_gpio_of_irq_setup(struct device_node *node,
- struct device_node *parent)
-{
- struct at91_gpio_chip *prev = NULL;
- int alias_idx = of_alias_get_id(node, "gpio");
- struct at91_gpio_chip *at91_gpio = &gpio_chip[alias_idx];
-
- /* Setup proper .irq_set_type function */
- if (has_pio3())
- gpio_irqchip.irq_set_type = alt_gpio_irq_type;
- else
- gpio_irqchip.irq_set_type = gpio_irq_type;
-
- /* Disable irqs of this PIO controller */
- __raw_writel(~0, at91_gpio->regbase + PIO_IDR);
-
- /* Setup irq domain */
- at91_gpio->domain = irq_domain_add_linear(node, at91_gpio->chip.ngpio,
- &at91_gpio_ops, at91_gpio);
- if (!at91_gpio->domain)
- panic("at91_gpio.%d: couldn't allocate irq domain (DT).\n",
- at91_gpio->pioc_idx);
-
- /* Setup chained handler */
- if (at91_gpio->pioc_idx)
- prev = &gpio_chip[at91_gpio->pioc_idx - 1];
-
- /* The toplevel handler handles one bank of GPIOs, except
- * on some SoC it can handles up to three...
- * We only set up the handler for the first of the list.
- */
- if (prev && prev->next == at91_gpio)
- return 0;
-
- at91_gpio->pioc_virq = irq_create_mapping(irq_find_host(parent),
- at91_gpio->pioc_hwirq);
- irq_set_chip_data(at91_gpio->pioc_virq, at91_gpio);
- irq_set_chained_handler(at91_gpio->pioc_virq, gpio_irq_handler);
-
- return 0;
-}
-#else
-int __init at91_gpio_of_irq_setup(struct device_node *node,
- struct device_node *parent)
-{
- return -EINVAL;
-}
-#endif
-
/*
* irqdomain initialization: pile up irqdomains on top of AIC range
*/
@@ -989,85 +913,6 @@
return -EINVAL;
}
-#ifdef CONFIG_OF_GPIO
-static void __init of_at91_gpio_init_one(struct device_node *np)
-{
- int alias_idx;
- struct at91_gpio_chip *at91_gpio;
- uint32_t ngpio;
-
- if (!np)
- return;
-
- alias_idx = of_alias_get_id(np, "gpio");
- if (alias_idx >= MAX_GPIO_BANKS) {
- pr_err("at91_gpio, failed alias idx(%d) > MAX_GPIO_BANKS(%d), ignoring.\n",
- alias_idx, MAX_GPIO_BANKS);
- return;
- }
-
- at91_gpio = &gpio_chip[alias_idx];
- at91_gpio->chip.base = alias_idx * MAX_NB_GPIO_PER_BANK;
-
- at91_gpio->regbase = of_iomap(np, 0);
- if (!at91_gpio->regbase) {
- pr_err("at91_gpio.%d, failed to map registers, ignoring.\n",
- alias_idx);
- return;
- }
-
- /* Get the interrupts property */
- if (of_property_read_u32(np, "interrupts", &at91_gpio->pioc_hwirq)) {
- pr_err("at91_gpio.%d, failed to get interrupts property, ignoring.\n",
- alias_idx);
- goto ioremap_err;
- }
-
- /* Get capabilities from compatibility property */
- if (of_device_is_compatible(np, "atmel,at91sam9x5-gpio"))
- at91_gpio_caps |= AT91_GPIO_CAP_PIO3;
-
- if (!of_property_read_u32(np, "#gpio-lines", &ngpio)) {
- if (ngpio >= MAX_NB_GPIO_PER_BANK)
- pr_err("at91_gpio.%d, gpio-nb >= %d failback to %d\n",
- alias_idx, MAX_NB_GPIO_PER_BANK, MAX_NB_GPIO_PER_BANK);
- else
- at91_gpio->chip.ngpio = ngpio;
- }
-
- /* Setup clock */
- if (at91_gpio_setup_clk(alias_idx))
- goto ioremap_err;
-
- at91_gpio->chip.of_node = np;
- gpio_banks = max(gpio_banks, alias_idx + 1);
- at91_gpio->pioc_idx = alias_idx;
- return;
-
-ioremap_err:
- iounmap(at91_gpio->regbase);
-}
-
-static int __init of_at91_gpio_init(void)
-{
- struct device_node *np = NULL;
-
- /*
- * This isn't ideal, but it gets things hooked up until this
- * driver is converted into a platform_device
- */
- for_each_compatible_node(np, NULL, "atmel,at91rm9200-gpio")
- of_at91_gpio_init_one(np);
-
- return gpio_banks > 0 ? 0 : -EINVAL;
-}
-#else
-static int __init of_at91_gpio_init(void)
-{
- return -EINVAL;
-}
-#endif
-
static void __init at91_gpio_init_one(int idx, u32 regbase, int pioc_hwirq)
{
struct at91_gpio_chip *at91_gpio = &gpio_chip[idx];
@@ -1102,11 +947,11 @@
BUG_ON(nr_banks > MAX_GPIO_BANKS);
- if (of_at91_gpio_init() < 0) {
- /* No GPIO controller found in device tree */
- for (i = 0; i < nr_banks; i++)
- at91_gpio_init_one(i, data[i].regbase, data[i].id);
- }
+ if (of_have_populated_dt())
+ return;
+
+ for (i = 0; i < nr_banks; i++)
+ at91_gpio_init_one(i, data[i].regbase, data[i].id);
for (i = 0; i < gpio_banks; i++) {
at91_gpio = &gpio_chip[i];