diff options
author | Ahmad Fatoum <a.fatoum@pengutronix.de> | 2019-09-26 11:35:25 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2019-10-14 15:26:28 +0200 |
commit | 3042dd2d4237dc3fc82fa160be2dd0df5d7a7a1a (patch) | |
tree | 85deb7b37f7b780b9c3f44e87d9429c8fac0b0d2 /arch/arm/mach-at91 | |
parent | 621032149f2b668b4303a907f931af80c644ffd2 (diff) | |
download | barebox-3042dd2d4237dc3fc82fa160be2dd0df5d7a7a1a.tar.gz barebox-3042dd2d4237dc3fc82fa160be2dd0df5d7a7a1a.tar.xz |
pinctrl: add gpio and pinctrl driver for sama5d2 PIO4
The sama5d2 features a GPIO and pin controller different than the one
we support in barebox. The device tree bindings are different as well,
so it makes sense to have a separate driver for it.
Add the pin control and GPIO driver as well as some helpers usable
from PBL, should we want to do pinmuxing that early.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch/arm/mach-at91')
-rw-r--r-- | arch/arm/mach-at91/Kconfig | 13 | ||||
-rw-r--r-- | arch/arm/mach-at91/include/mach/at91_pio.h | 33 | ||||
-rw-r--r-- | arch/arm/mach-at91/include/mach/gpio.h | 134 |
3 files changed, 177 insertions, 3 deletions
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 8e1bf0629a..3f24892be7 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -6,6 +6,9 @@ config HAVE_AT91_UTMI config HAVE_AT91_USB_CLK bool +config HAVE_AT91_PIO4 + bool + config COMMON_CLK_AT91 bool select COMMON_CLK @@ -47,6 +50,7 @@ config SOC_AT91SAM9 select HAVE_AT91_SMD select HAVE_AT91_USB_CLK select HAVE_AT91_UTMI + select PINCTRL_AT91 config SOC_SAMA5 bool @@ -66,6 +70,7 @@ config SOC_SAMA5D3 select HAVE_AT91_SMD select HAVE_AT91_USB_CLK select HAVE_AT91_UTMI + select PINCTRL_AT91 config SOC_SAMA5D4 bool @@ -76,6 +81,7 @@ config SOC_SAMA5D4 select HAVE_AT91_SMD select HAVE_AT91_USB_CLK select HAVE_AT91_UTMI + select PINCTRL_AT91 config ARCH_TEXT_BASE hex @@ -102,11 +108,13 @@ config SOC_AT91RM9200 select HAS_AT91_ETHER select HAVE_AT91_DBGU0 select HAVE_AT91_USB_CLK + select PINCTRL_AT91 config SOC_AT91SAM9260 bool select SOC_AT91SAM9 select HAS_MACB + select PINCTRL_AT91 help Select this if you are using one of Atmel's AT91SAM9260, AT91SAM9XE or AT91SAM9G20 SoC. @@ -114,6 +122,7 @@ config SOC_AT91SAM9260 config SOC_AT91SAM9261 bool select SOC_AT91SAM9 + select PINCTRL_AT91 help Select this if you are using one of Atmel's AT91SAM9261 or AT91SAM9G10 SoC. @@ -122,11 +131,13 @@ config SOC_AT91SAM9263 select SOC_AT91SAM9 select HAS_MACB select HAVE_AT91_LOAD_BAREBOX_SRAM + select PINCTRL_AT91 config SOC_AT91SAM9G45 bool select SOC_AT91SAM9 select HAS_MACB + select PINCTRL_AT91 help Select this if you are using one of Atmel's AT91SAM9G45 family SoC. This support covers AT91SAM9G45, AT91SAM9G46, AT91SAM9M10 and AT91SAM9M11. @@ -136,6 +147,7 @@ config SOC_AT91SAM9X5 select SOC_AT91SAM9 select HAS_MACB select COMMON_CLK_OF_PROVIDER + select PINCTRL_AT91 help Select this if you are using one of Atmel's AT91SAM9x5 family SoC. This means that your SAM9 name finishes with a '5' (except if it is @@ -146,6 +158,7 @@ config SOC_AT91SAM9X5 config SOC_AT91SAM9N12 bool select SOC_AT91SAM9 + select PINCTRL_AT91 help Select this if you are using Atmel's AT91SAM9N12 SoC. diff --git a/arch/arm/mach-at91/include/mach/at91_pio.h b/arch/arm/mach-at91/include/mach/at91_pio.h index 2d80dfc3c9..0f129c9975 100644 --- a/arch/arm/mach-at91/include/mach/at91_pio.h +++ b/arch/arm/mach-at91/include/mach/at91_pio.h @@ -3,6 +3,8 @@ * * Copyright (C) 2005 Ivan Kokshaysky * Copyright (C) SAN People + * Copyright (C) 2015 Atmel, + * 2015 Ludovic Desroches <ludovic.desroches@atmel.com> * * Parallel I/O Controller (PIO) - System peripherals registers. * Based on AT91RM9200 datasheet revision E. @@ -16,6 +18,8 @@ #ifndef AT91_PIO_H #define AT91_PIO_H +#include <linux/bitops.h> + #define PIO_PER 0x00 /* Enable Register */ #define PIO_PDR 0x04 /* Disable Register */ #define PIO_PSR 0x08 /* Status Register */ @@ -71,4 +75,33 @@ #define ABCDSR_PERIPH_C 0x2 #define ABCDSR_PERIPH_D 0x3 +#define PIO4_MSKR 0x0000 /* Mask Register */ +#define PIO4_CFGR 0x0004 /* Configuration Register */ +#define PIO4_CFGR_FUNC_MASK GENMASK(2, 0) +#define PIO4_DIR_MASK BIT(8) +#define PIO4_PUEN_MASK BIT(9) +#define PIO4_PDEN_MASK BIT(10) +#define PIO4_IFEN_MASK BIT(12) +#define PIO4_IFSCEN_MASK BIT(13) +#define PIO4_OPD_MASK BIT(14) +#define PIO4_SCHMITT_MASK BIT(15) +#define PIO4_DRVSTR_MASK GENMASK(17, 16) +#define PIO4_DRVSTR_OFFSET 16 +#define PIO4_CFGR_EVTSEL_MASK GENMASK(26, 24) +#define PIO4_CFGR_EVTSEL_FALLING (0 << 24) +#define PIO4_CFGR_EVTSEL_RISING (1 << 24) +#define PIO4_CFGR_EVTSEL_BOTH (2 << 24) +#define PIO4_CFGR_EVTSEL_LOW (3 << 24) +#define PIO4_CFGR_EVTSEL_HIGH (4 << 24) +#define PIO4_PDSR 0x0008 /* Data Status Register */ +#define PIO4_LOCKSR 0x000C /* Lock Status Register */ +#define PIO4_SODR 0x0010 /* Set Output Data Register */ +#define PIO4_CODR 0x0014 /* Clear Output Data Register */ +#define PIO4_ODSR 0x0018 /* Output Data Status Register */ +#define PIO4_IER 0x0020 /* Interrupt Enable Register */ +#define PIO4_IDR 0x0024 /* Interrupt Disable Register */ +#define PIO4_IMR 0x0028 /* Interrupt Mask Register */ +#define PIO4_ISR 0x002C /* Interrupt Status Register */ +#define PIO4_IOFR 0x003C /* I/O Freeze Configuration Register */ + #endif diff --git a/arch/arm/mach-at91/include/mach/gpio.h b/arch/arm/mach-at91/include/mach/gpio.h index b893dc220c..ddd6971e37 100644 --- a/arch/arm/mach-at91/include/mach/gpio.h +++ b/arch/arm/mach-at91/include/mach/gpio.h @@ -8,6 +8,8 @@ #define __AT91_GPIO_H__ #include <dt-bindings/gpio/gpio.h> +#include <asm/io.h> +#include <mach/at91_pio.h> #define MAX_NB_GPIO_PER_BANK 32 @@ -17,6 +19,9 @@ enum at91_mux { AT91_MUX_PERIPH_B = 2, AT91_MUX_PERIPH_C = 3, AT91_MUX_PERIPH_D = 4, + AT91_MUX_PERIPH_E = 5, + AT91_MUX_PERIPH_F = 6, + AT91_MUX_PERIPH_G = 7, }; static inline unsigned pin_to_bank(unsigned pin) @@ -140,10 +145,10 @@ int value) static inline int at91_mux_gpio_get(void __iomem *pio, unsigned mask) { - u32 pdsr; + u32 pdsr; - pdsr = readl(pio + PIO_PDSR); - return (pdsr & mask) != 0; + pdsr = readl(pio + PIO_PDSR); + return (pdsr & mask) != 0; } static inline void at91_mux_pio3_pin(void __iomem *pio, unsigned mask, @@ -167,6 +172,9 @@ static inline void at91_mux_pio3_pin(void __iomem *pio, unsigned mask, case AT91_MUX_PERIPH_D: at91_mux_pio3_set_D_periph(pio, mask); break; + default: + /* ignore everything else */ + break; } if (mux != AT91_MUX_GPIO) at91_mux_gpio_disable(pio, mask); @@ -175,4 +183,124 @@ static inline void at91_mux_pio3_pin(void __iomem *pio, unsigned mask, at91_mux_pio3_set_pulldown(pio, mask, gpio_state & GPIO_PULL_DOWN); } +/* helpers for PIO4 pinctrl (>= sama5d2) */ + +static inline void at91_mux_pio4_set_periph(void __iomem *pio, unsigned mask, u32 func) +{ + writel(mask, pio + PIO4_MSKR); + writel(func, pio + PIO4_CFGR); +} + +static inline void at91_mux_pio4_set_A_periph(void __iomem *pio, unsigned mask) +{ + at91_mux_pio4_set_periph(pio, mask, AT91_MUX_PERIPH_A); +} + +static inline void at91_mux_pio4_set_B_periph(void __iomem *pio, unsigned mask) +{ + at91_mux_pio4_set_periph(pio, mask, AT91_MUX_PERIPH_B); +} + +static inline void at91_mux_pio4_set_C_periph(void __iomem *pio, unsigned mask) +{ + at91_mux_pio4_set_periph(pio, mask, AT91_MUX_PERIPH_C); +} + +static inline void at91_mux_pio4_set_D_periph(void __iomem *pio, unsigned mask) +{ + at91_mux_pio4_set_periph(pio, mask, AT91_MUX_PERIPH_D); +} + +static inline void at91_mux_pio4_set_E_periph(void __iomem *pio, unsigned mask) +{ + at91_mux_pio4_set_periph(pio, mask, AT91_MUX_PERIPH_E); +} + +static inline void at91_mux_pio4_set_F_periph(void __iomem *pio, unsigned mask) +{ + at91_mux_pio4_set_periph(pio, mask, AT91_MUX_PERIPH_F); +} + +static inline void at91_mux_pio4_set_G_periph(void __iomem *pio, unsigned mask) +{ + at91_mux_pio4_set_periph(pio, mask, AT91_MUX_PERIPH_G); +} + +static inline void at91_mux_pio4_set_func(void __iomem *pio, + unsigned pin_mask, + unsigned cfgr_and_mask, + unsigned cfgr_or_mask) +{ + u32 reg; + writel(pin_mask, pio + PIO4_MSKR); + reg = readl(pio + PIO4_CFGR); + reg &= cfgr_and_mask; + reg |= cfgr_or_mask; + writel(reg, pio + PIO4_CFGR); +} + +static inline void at91_mux_pio4_set_bistate(void __iomem *pio, + unsigned pin_mask, + unsigned func_mask, + bool is_on) +{ + at91_mux_pio4_set_func(pio, pin_mask, ~func_mask, + is_on ? func_mask : 0); +} + +static inline void at91_mux_pio4_set_deglitch(void __iomem *pio, unsigned mask, bool is_on) +{ + at91_mux_pio4_set_bistate(pio, mask, PIO4_IFEN_MASK, is_on); +} + +static inline void at91_mux_pio4_set_debounce(void __iomem *pio, unsigned mask, + bool is_on, u32 div) +{ + at91_mux_pio4_set_bistate(pio, mask, PIO4_IFEN_MASK, is_on); + at91_mux_pio4_set_bistate(pio, mask, PIO4_IFSCEN_MASK, is_on); +} + +static inline void at91_mux_pio4_set_pulldown(void __iomem *pio, unsigned mask, bool is_on) +{ + at91_mux_pio4_set_bistate(pio, mask, PIO4_PDEN_MASK, is_on); +} + +static inline void at91_mux_pio4_disable_schmitt_trig(void __iomem *pio, unsigned mask) +{ + at91_mux_pio4_set_bistate(pio, mask, PIO4_SCHMITT_MASK, false); +} + +static inline void at91_mux_gpio4_enable(void __iomem *pio, unsigned mask) +{ + at91_mux_pio4_set_func(pio, mask, ~PIO4_CFGR_FUNC_MASK, AT91_MUX_GPIO); +} + +static inline void at91_mux_gpio4_input(void __iomem *pio, unsigned mask, bool input) +{ + u32 cfgr; + + writel(mask, pio + PIO4_MSKR); + + cfgr = readl(pio + PIO4_CFGR); + if (input) + cfgr &= ~PIO4_DIR_MASK; + else + cfgr |= PIO4_DIR_MASK; + writel(cfgr, pio + PIO4_CFGR); +} + +static inline void at91_mux_gpio4_set(void __iomem *pio, unsigned mask, + int value) +{ + writel(mask, pio + (value ? PIO4_SODR : PIO4_CODR)); +} + +static inline int at91_mux_gpio4_get(void __iomem *pio, unsigned mask) +{ + u32 pdsr; + + pdsr = readl(pio + PIO4_PDSR); + return (pdsr & mask) != 0; +} + #endif /* __AT91_GPIO_H__ */ |