summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-at91
diff options
context:
space:
mode:
authorAhmad Fatoum <a.fatoum@pengutronix.de>2019-09-26 11:35:25 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2019-10-14 15:26:28 +0200
commit3042dd2d4237dc3fc82fa160be2dd0df5d7a7a1a (patch)
tree85deb7b37f7b780b9c3f44e87d9429c8fac0b0d2 /arch/arm/mach-at91
parent621032149f2b668b4303a907f931af80c644ffd2 (diff)
downloadbarebox-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/Kconfig13
-rw-r--r--arch/arm/mach-at91/include/mach/at91_pio.h33
-rw-r--r--arch/arm/mach-at91/include/mach/gpio.h134
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__ */