From 2dc63f73678c18831efce3ec1a383375aa5423f1 Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Thu, 23 Mar 2017 12:44:36 +0800 Subject: gpio: at91_gpio: remove CPU_HAS_PIO3 macro The intention of the removal is the preparation to introduce the new AT91 PIO pinctrl driver. Use the union to make the PIO3 and PIO2's registers be together and make their offset aligned. Signed-off-by: Wenyou Yang Reviewed-by: Simon Glass --- drivers/gpio/at91_gpio.c | 142 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 97 insertions(+), 45 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/at91_gpio.c b/drivers/gpio/at91_gpio.c index 8e52e3dad0..2f9e44b620 100644 --- a/drivers/gpio/at91_gpio.c +++ b/drivers/gpio/at91_gpio.c @@ -59,11 +59,6 @@ int at91_set_pio_pullup(unsigned port, unsigned pin, int use_pullup) { struct at91_port *at91_port = at91_pio_get_port(port); -#if defined(CPU_HAS_PIO3) - if (use_pullup) - at91_set_pio_pulldown(port, pin, 0); -#endif - if (at91_port && (pin < GPIO_PER_BANK)) at91_set_port_pullup(at91_port, pin, use_pullup); @@ -100,14 +95,7 @@ int at91_set_a_periph(unsigned port, unsigned pin, int use_pullup) mask = 1 << pin; writel(mask, &at91_port->idr); at91_set_pio_pullup(port, pin, use_pullup); -#if defined(CPU_HAS_PIO3) - writel(readl(&at91_port->abcdsr1) & ~mask, - &at91_port->abcdsr1); - writel(readl(&at91_port->abcdsr2) & ~mask, - &at91_port->abcdsr2); -#else - writel(mask, &at91_port->asr); -#endif + writel(mask, &at91_port->mux.pio2.asr); writel(mask, &at91_port->pdr); } @@ -126,25 +114,62 @@ int at91_set_b_periph(unsigned port, unsigned pin, int use_pullup) mask = 1 << pin; writel(mask, &at91_port->idr); at91_set_pio_pullup(port, pin, use_pullup); -#if defined(CPU_HAS_PIO3) - writel(readl(&at91_port->abcdsr1) | mask, - &at91_port->abcdsr1); - writel(readl(&at91_port->abcdsr2) & ~mask, - &at91_port->abcdsr2); -#else - writel(mask, &at91_port->bsr); -#endif + writel(mask, &at91_port->mux.pio2.bsr); + writel(mask, &at91_port->pdr); + } + + return 0; +} + +/* + * mux the pin to the "A" internal peripheral role. + */ +int at91_pio3_set_a_periph(unsigned port, unsigned pin, int use_pullup) +{ + struct at91_port *at91_port = at91_pio_get_port(port); + u32 mask; + + if (at91_port && (pin < GPIO_PER_BANK)) { + mask = 1 << pin; + writel(mask, &at91_port->idr); + at91_set_pio_pullup(port, pin, use_pullup); + writel(readl(&at91_port->mux.pio3.abcdsr1) & ~mask, + &at91_port->mux.pio3.abcdsr1); + writel(readl(&at91_port->mux.pio3.abcdsr2) & ~mask, + &at91_port->mux.pio3.abcdsr2); + writel(mask, &at91_port->pdr); } return 0; } -#if defined(CPU_HAS_PIO3) +/* + * mux the pin to the "B" internal peripheral role. + */ +int at91_pio3_set_b_periph(unsigned port, unsigned pin, int use_pullup) +{ + struct at91_port *at91_port = at91_pio_get_port(port); + u32 mask; + + if (at91_port && (pin < GPIO_PER_BANK)) { + mask = 1 << pin; + writel(mask, &at91_port->idr); + at91_set_pio_pullup(port, pin, use_pullup); + writel(readl(&at91_port->mux.pio3.abcdsr1) | mask, + &at91_port->mux.pio3.abcdsr1); + writel(readl(&at91_port->mux.pio3.abcdsr2) & ~mask, + &at91_port->mux.pio3.abcdsr2); + + writel(mask, &at91_port->pdr); + } + + return 0; +} /* * mux the pin to the "C" internal peripheral role. */ -int at91_set_c_periph(unsigned port, unsigned pin, int use_pullup) +int at91_pio3_set_c_periph(unsigned port, unsigned pin, int use_pullup) { struct at91_port *at91_port = at91_pio_get_port(port); u32 mask; @@ -153,10 +178,10 @@ int at91_set_c_periph(unsigned port, unsigned pin, int use_pullup) mask = 1 << pin; writel(mask, &at91_port->idr); at91_set_pio_pullup(port, pin, use_pullup); - writel(readl(&at91_port->abcdsr1) & ~mask, - &at91_port->abcdsr1); - writel(readl(&at91_port->abcdsr2) | mask, - &at91_port->abcdsr2); + writel(readl(&at91_port->mux.pio3.abcdsr1) & ~mask, + &at91_port->mux.pio3.abcdsr1); + writel(readl(&at91_port->mux.pio3.abcdsr2) | mask, + &at91_port->mux.pio3.abcdsr2); writel(mask, &at91_port->pdr); } @@ -166,7 +191,7 @@ int at91_set_c_periph(unsigned port, unsigned pin, int use_pullup) /* * mux the pin to the "D" internal peripheral role. */ -int at91_set_d_periph(unsigned port, unsigned pin, int use_pullup) +int at91_pio3_set_d_periph(unsigned port, unsigned pin, int use_pullup) { struct at91_port *at91_port = at91_pio_get_port(port); u32 mask; @@ -175,16 +200,15 @@ int at91_set_d_periph(unsigned port, unsigned pin, int use_pullup) mask = 1 << pin; writel(mask, &at91_port->idr); at91_set_pio_pullup(port, pin, use_pullup); - writel(readl(&at91_port->abcdsr1) | mask, - &at91_port->abcdsr1); - writel(readl(&at91_port->abcdsr2) | mask, - &at91_port->abcdsr2); + writel(readl(&at91_port->mux.pio3.abcdsr1) | mask, + &at91_port->mux.pio3.abcdsr1); + writel(readl(&at91_port->mux.pio3.abcdsr2) | mask, + &at91_port->mux.pio3.abcdsr2); writel(mask, &at91_port->pdr); } return 0; } -#endif #ifdef CONFIG_DM_GPIO static bool at91_get_port_output(struct at91_port *at91_port, int offset) @@ -261,12 +285,29 @@ int at91_set_pio_deglitch(unsigned port, unsigned pin, int is_on) struct at91_port *at91_port = at91_pio_get_port(port); u32 mask; + if (at91_port && (pin < GPIO_PER_BANK)) { + mask = 1 << pin; + if (is_on) + writel(mask, &at91_port->ifer); + else + writel(mask, &at91_port->ifdr); + } + + return 0; +} + +/* + * enable/disable the glitch filter. mostly used with IRQ handling. + */ +int at91_pio3_set_pio_deglitch(unsigned port, unsigned pin, int is_on) +{ + struct at91_port *at91_port = at91_pio_get_port(port); + u32 mask; + if (at91_port && (pin < GPIO_PER_BANK)) { mask = 1 << pin; if (is_on) { -#if defined(CPU_HAS_PIO3) - writel(mask, &at91_port->ifscdr); -#endif + writel(mask, &at91_port->mux.pio3.ifscdr); writel(mask, &at91_port->ifer); } else { writel(mask, &at91_port->ifdr); @@ -276,11 +317,10 @@ int at91_set_pio_deglitch(unsigned port, unsigned pin, int is_on) return 0; } -#if defined(CPU_HAS_PIO3) /* * enable/disable the debounce filter. */ -int at91_set_pio_debounce(unsigned port, unsigned pin, int is_on, int div) +int at91_pio3_set_pio_debounce(unsigned port, unsigned pin, int is_on, int div) { struct at91_port *at91_port = at91_pio_get_port(port); u32 mask; @@ -288,8 +328,8 @@ int at91_set_pio_debounce(unsigned port, unsigned pin, int is_on, int div) if (at91_port && (pin < GPIO_PER_BANK)) { mask = 1 << pin; if (is_on) { - writel(mask, &at91_port->ifscer); - writel(div & PIO_SCDR_DIV, &at91_port->scdr); + writel(mask, &at91_port->mux.pio3.ifscer); + writel(div & PIO_SCDR_DIV, &at91_port->mux.pio3.scdr); writel(mask, &at91_port->ifer); } else { writel(mask, &at91_port->ifdr); @@ -303,7 +343,7 @@ int at91_set_pio_debounce(unsigned port, unsigned pin, int is_on, int div) * enable/disable the pull-down. * If pull-up already enabled while calling the function, we disable it. */ -int at91_set_pio_pulldown(unsigned port, unsigned pin, int is_on) +int at91_pio3_set_pio_pulldown(unsigned port, unsigned pin, int is_on) { struct at91_port *at91_port = at91_pio_get_port(port); u32 mask; @@ -312,18 +352,31 @@ int at91_set_pio_pulldown(unsigned port, unsigned pin, int is_on) mask = 1 << pin; if (is_on) { at91_set_pio_pullup(port, pin, 0); - writel(mask, &at91_port->ppder); + writel(mask, &at91_port->mux.pio3.ppder); } else - writel(mask, &at91_port->ppddr); + writel(mask, &at91_port->mux.pio3.ppddr); } return 0; } +int at91_pio3_set_pio_pullup(unsigned port, unsigned pin, int use_pullup) +{ + struct at91_port *at91_port = at91_pio_get_port(port); + + if (use_pullup) + at91_pio3_set_pio_pulldown(port, pin, 0); + + if (at91_port && (pin < GPIO_PER_BANK)) + at91_set_port_pullup(at91_port, pin, use_pullup); + + return 0; +} + /* * disable Schmitt trigger */ -int at91_set_pio_disable_schmitt_trig(unsigned port, unsigned pin) +int at91_pio3_set_pio_disable_schmitt_trig(unsigned port, unsigned pin) { struct at91_port *at91_port = at91_pio_get_port(port); u32 mask; @@ -336,7 +389,6 @@ int at91_set_pio_disable_schmitt_trig(unsigned port, unsigned pin) return 0; } -#endif /* * enable/disable the multi-driver. This is only valid for output and -- cgit From 5a07a5f9224d792a27ac9894f86239bc7b3298ba Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Thu, 23 Mar 2017 12:46:19 +0800 Subject: gpio: Kconfig: add CONFIG_AT91_GPIO option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CONFIG_AT91_GPIO option is used to select AT91 PIO GPIO driver. Signed-off-by: Wenyou Yang Reviewed-by: Simon Glass Reviewed-by: Andreas Bießmann --- drivers/gpio/Kconfig | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index dc4108f378..c95e9acd5f 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -28,6 +28,19 @@ config DWAPB_GPIO help Support for the Designware APB GPIO driver. +config AT91_GPIO + bool "AT91 PIO GPIO driver" + depends on DM_GPIO + default n + help + Say yes here to select AT91 PIO GPIO driver. AT91 PIO + controller manages up to 32 fully programmable input/output + lines. Each I/O line may be dedicated as a general-purpose + I/O or be assigned to a function of an embedded peripheral. + The assignment to a function of an embedded peripheral is + the responsibility of AT91 Pinctrl driver. This driver is + responsible for the general-purpose I/O. + config ATMEL_PIO4 bool "ATMEL PIO4 driver" depends on DM_GPIO -- cgit From cf468880c37be1a7fea0a842a14ba1e1e388147c Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Thu, 23 Mar 2017 12:46:20 +0800 Subject: gpio: at91_gpio: add the device tree support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the device tree support. Signed-off-by: Wenyou Yang Reviewed-by: Simon Glass Reviewed-by: Andreas Bießmann --- drivers/gpio/at91_gpio.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/at91_gpio.c b/drivers/gpio/at91_gpio.c index 2f9e44b620..37955cc99a 100644 --- a/drivers/gpio/at91_gpio.c +++ b/drivers/gpio/at91_gpio.c @@ -572,14 +572,29 @@ static int at91_gpio_probe(struct udevice *dev) uc_priv->bank_name = plat->bank_name; uc_priv->gpio_count = GPIO_PER_BANK; + +#if CONFIG_IS_ENABLED(OF_CONTROL) + plat->base_addr = (uint32_t)dev_get_addr_ptr(dev); +#endif port->regs = (struct at91_port *)plat->base_addr; return 0; } +#if CONFIG_IS_ENABLED(OF_CONTROL) +static const struct udevice_id at91_gpio_ids[] = { + { .compatible = "atmel,at91rm9200-gpio" }, + { } +}; +#endif + U_BOOT_DRIVER(gpio_at91) = { .name = "gpio_at91", .id = UCLASS_GPIO, +#if CONFIG_IS_ENABLED(OF_CONTROL) + .of_match = at91_gpio_ids, + .platdata_auto_alloc_size = sizeof(struct at91_port_platdata), +#endif .ops = &gpio_at91_ops, .probe = at91_gpio_probe, .priv_auto_alloc_size = sizeof(struct at91_port_priv), -- cgit From f2f3c1576a5d4b15788843ab3353e6307fe380ba Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Thu, 23 Mar 2017 12:46:21 +0800 Subject: gpio: at91_gpio: add the clock support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the clock support. Signed-off-by: Wenyou Yang Reviewed-by: Simon Glass Reviewed-by: Andreas Bießmann --- drivers/gpio/at91_gpio.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/at91_gpio.c b/drivers/gpio/at91_gpio.c index 37955cc99a..98dbd8210e 100644 --- a/drivers/gpio/at91_gpio.c +++ b/drivers/gpio/at91_gpio.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -569,6 +570,18 @@ static int at91_gpio_probe(struct udevice *dev) struct at91_port_priv *port = dev_get_priv(dev); struct at91_port_platdata *plat = dev_get_platdata(dev); struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct clk clk; + int ret; + + ret = clk_get_by_index(dev, 0, &clk); + if (ret) + return ret; + + ret = clk_enable(&clk); + if (ret) + return ret; + + clk_free(&clk); uc_priv->bank_name = plat->bank_name; uc_priv->gpio_count = GPIO_PER_BANK; -- cgit