diff options
Diffstat (limited to 'drivers/pinctrl/nomadik')
-rw-r--r-- | drivers/pinctrl/nomadik/Kconfig | 51 | ||||
-rw-r--r-- | drivers/pinctrl/nomadik/Makefile | 10 | ||||
-rw-r--r-- | drivers/pinctrl/nomadik/pinctrl-ab8500.c | 485 | ||||
-rw-r--r-- | drivers/pinctrl/nomadik/pinctrl-ab8505.c | 381 | ||||
-rw-r--r-- | drivers/pinctrl/nomadik/pinctrl-ab8540.c | 408 | ||||
-rw-r--r-- | drivers/pinctrl/nomadik/pinctrl-ab9540.c | 486 | ||||
-rw-r--r-- | drivers/pinctrl/nomadik/pinctrl-abx500.c | 1346 | ||||
-rw-r--r-- | drivers/pinctrl/nomadik/pinctrl-abx500.h | 246 | ||||
-rw-r--r-- | drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c | 1257 | ||||
-rw-r--r-- | drivers/pinctrl/nomadik/pinctrl-nomadik-db8540.c | 1266 | ||||
-rw-r--r-- | drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c | 356 | ||||
-rw-r--r-- | drivers/pinctrl/nomadik/pinctrl-nomadik.c | 2099 | ||||
-rw-r--r-- | drivers/pinctrl/nomadik/pinctrl-nomadik.h | 192 |
13 files changed, 8583 insertions, 0 deletions
diff --git a/drivers/pinctrl/nomadik/Kconfig b/drivers/pinctrl/nomadik/Kconfig new file mode 100644 index 000000000000..d48a5aa24a29 --- /dev/null +++ b/drivers/pinctrl/nomadik/Kconfig @@ -0,0 +1,51 @@ +if ARCH_U8500 + +config PINCTRL_ABX500 + bool "ST-Ericsson ABx500 family Mixed Signal Circuit gpio functions" + depends on AB8500_CORE + select GENERIC_PINCONF + help + Select this to enable the ABx500 family IC GPIO driver + +config PINCTRL_AB8500 + bool "AB8500 pin controller driver" + depends on PINCTRL_ABX500 && ARCH_U8500 + +config PINCTRL_AB8540 + bool "AB8540 pin controller driver" + depends on PINCTRL_ABX500 && ARCH_U8500 + +config PINCTRL_AB9540 + bool "AB9540 pin controller driver" + depends on PINCTRL_ABX500 && ARCH_U8500 + +config PINCTRL_AB8505 + bool "AB8505 pin controller driver" + depends on PINCTRL_ABX500 && ARCH_U8500 + +endif + +if (ARCH_U8500 || ARCH_NOMADIK) + +config PINCTRL_NOMADIK + bool "Nomadik pin controller driver" + depends on ARCH_U8500 || ARCH_NOMADIK + select PINMUX + select PINCONF + select GPIOLIB + select OF_GPIO + select GPIOLIB_IRQCHIP + +config PINCTRL_STN8815 + bool "STN8815 pin controller driver" + depends on PINCTRL_NOMADIK && ARCH_NOMADIK + +config PINCTRL_DB8500 + bool "DB8500 pin controller driver" + depends on PINCTRL_NOMADIK && ARCH_U8500 + +config PINCTRL_DB8540 + bool "DB8540 pin controller driver" + depends on PINCTRL_NOMADIK && ARCH_U8500 + +endif diff --git a/drivers/pinctrl/nomadik/Makefile b/drivers/pinctrl/nomadik/Makefile new file mode 100644 index 000000000000..30b27f18cd52 --- /dev/null +++ b/drivers/pinctrl/nomadik/Makefile @@ -0,0 +1,10 @@ +# Nomadik family pin control drivers +obj-$(CONFIG_PINCTRL_ABX500) += pinctrl-abx500.o +obj-$(CONFIG_PINCTRL_AB8500) += pinctrl-ab8500.o +obj-$(CONFIG_PINCTRL_AB8540) += pinctrl-ab8540.o +obj-$(CONFIG_PINCTRL_AB9540) += pinctrl-ab9540.o +obj-$(CONFIG_PINCTRL_AB8505) += pinctrl-ab8505.o +obj-$(CONFIG_PINCTRL_NOMADIK) += pinctrl-nomadik.o +obj-$(CONFIG_PINCTRL_STN8815) += pinctrl-nomadik-stn8815.o +obj-$(CONFIG_PINCTRL_DB8500) += pinctrl-nomadik-db8500.o +obj-$(CONFIG_PINCTRL_DB8540) += pinctrl-nomadik-db8540.o diff --git a/drivers/pinctrl/nomadik/pinctrl-ab8500.c b/drivers/pinctrl/nomadik/pinctrl-ab8500.c new file mode 100644 index 000000000000..2ac2d0ad3025 --- /dev/null +++ b/drivers/pinctrl/nomadik/pinctrl-ab8500.c @@ -0,0 +1,485 @@ +/* + * Copyright (C) ST-Ericsson SA 2012 + * + * Author: Patrice Chotard <patrice.chotard@stericsson.com> for ST-Ericsson. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/gpio.h> +#include <linux/pinctrl/pinctrl.h> +#include <linux/mfd/abx500/ab8500.h> +#include "pinctrl-abx500.h" + +/* All the pins that can be used for GPIO and some other functions */ +#define ABX500_GPIO(offset) (offset) + +#define AB8500_PIN_T10 ABX500_GPIO(1) +#define AB8500_PIN_T9 ABX500_GPIO(2) +#define AB8500_PIN_U9 ABX500_GPIO(3) +#define AB8500_PIN_W2 ABX500_GPIO(4) +/* hole */ +#define AB8500_PIN_Y18 ABX500_GPIO(6) +#define AB8500_PIN_AA20 ABX500_GPIO(7) +#define AB8500_PIN_W18 ABX500_GPIO(8) +#define AB8500_PIN_AA19 ABX500_GPIO(9) +#define AB8500_PIN_U17 ABX500_GPIO(10) +#define AB8500_PIN_AA18 ABX500_GPIO(11) +#define AB8500_PIN_U16 ABX500_GPIO(12) +#define AB8500_PIN_W17 ABX500_GPIO(13) +#define AB8500_PIN_F14 ABX500_GPIO(14) +#define AB8500_PIN_B17 ABX500_GPIO(15) +#define AB8500_PIN_F15 ABX500_GPIO(16) +#define AB8500_PIN_P5 ABX500_GPIO(17) +#define AB8500_PIN_R5 ABX500_GPIO(18) +#define AB8500_PIN_U5 ABX500_GPIO(19) +#define AB8500_PIN_T5 ABX500_GPIO(20) +#define AB8500_PIN_H19 ABX500_GPIO(21) +#define AB8500_PIN_G20 ABX500_GPIO(22) +#define AB8500_PIN_G19 ABX500_GPIO(23) +#define AB8500_PIN_T14 ABX500_GPIO(24) +#define AB8500_PIN_R16 ABX500_GPIO(25) +#define AB8500_PIN_M16 ABX500_GPIO(26) +#define AB8500_PIN_J6 ABX500_GPIO(27) +#define AB8500_PIN_K6 ABX500_GPIO(28) +#define AB8500_PIN_G6 ABX500_GPIO(29) +#define AB8500_PIN_H6 ABX500_GPIO(30) +#define AB8500_PIN_F5 ABX500_GPIO(31) +#define AB8500_PIN_G5 ABX500_GPIO(32) +/* hole */ +#define AB8500_PIN_R17 ABX500_GPIO(34) +#define AB8500_PIN_W15 ABX500_GPIO(35) +#define AB8500_PIN_A17 ABX500_GPIO(36) +#define AB8500_PIN_E15 ABX500_GPIO(37) +#define AB8500_PIN_C17 ABX500_GPIO(38) +#define AB8500_PIN_E16 ABX500_GPIO(39) +#define AB8500_PIN_T19 ABX500_GPIO(40) +#define AB8500_PIN_U19 ABX500_GPIO(41) +#define AB8500_PIN_U2 ABX500_GPIO(42) + +/* indicates the highest GPIO number */ +#define AB8500_GPIO_MAX_NUMBER 42 + +/* + * The names of the pins are denoted by GPIO number and ball name, even + * though they can be used for other things than GPIO, this is the first + * column in the table of the data sheet and often used on schematics and + * such. + */ +static const struct pinctrl_pin_desc ab8500_pins[] = { + PINCTRL_PIN(AB8500_PIN_T10, "GPIO1_T10"), + PINCTRL_PIN(AB8500_PIN_T9, "GPIO2_T9"), + PINCTRL_PIN(AB8500_PIN_U9, "GPIO3_U9"), + PINCTRL_PIN(AB8500_PIN_W2, "GPIO4_W2"), + /* hole */ + PINCTRL_PIN(AB8500_PIN_Y18, "GPIO6_Y18"), + PINCTRL_PIN(AB8500_PIN_AA20, "GPIO7_AA20"), + PINCTRL_PIN(AB8500_PIN_W18, "GPIO8_W18"), + PINCTRL_PIN(AB8500_PIN_AA19, "GPIO9_AA19"), + PINCTRL_PIN(AB8500_PIN_U17, "GPIO10_U17"), + PINCTRL_PIN(AB8500_PIN_AA18, "GPIO11_AA18"), + PINCTRL_PIN(AB8500_PIN_U16, "GPIO12_U16"), + PINCTRL_PIN(AB8500_PIN_W17, "GPIO13_W17"), + PINCTRL_PIN(AB8500_PIN_F14, "GPIO14_F14"), + PINCTRL_PIN(AB8500_PIN_B17, "GPIO15_B17"), + PINCTRL_PIN(AB8500_PIN_F15, "GPIO16_F15"), + PINCTRL_PIN(AB8500_PIN_P5, "GPIO17_P5"), + PINCTRL_PIN(AB8500_PIN_R5, "GPIO18_R5"), + PINCTRL_PIN(AB8500_PIN_U5, "GPIO19_U5"), + PINCTRL_PIN(AB8500_PIN_T5, "GPIO20_T5"), + PINCTRL_PIN(AB8500_PIN_H19, "GPIO21_H19"), + PINCTRL_PIN(AB8500_PIN_G20, "GPIO22_G20"), + PINCTRL_PIN(AB8500_PIN_G19, "GPIO23_G19"), + PINCTRL_PIN(AB8500_PIN_T14, "GPIO24_T14"), + PINCTRL_PIN(AB8500_PIN_R16, "GPIO25_R16"), + PINCTRL_PIN(AB8500_PIN_M16, "GPIO26_M16"), + PINCTRL_PIN(AB8500_PIN_J6, "GPIO27_J6"), + PINCTRL_PIN(AB8500_PIN_K6, "GPIO28_K6"), + PINCTRL_PIN(AB8500_PIN_G6, "GPIO29_G6"), + PINCTRL_PIN(AB8500_PIN_H6, "GPIO30_H6"), + PINCTRL_PIN(AB8500_PIN_F5, "GPIO31_F5"), + PINCTRL_PIN(AB8500_PIN_G5, "GPIO32_G5"), + /* hole */ + PINCTRL_PIN(AB8500_PIN_R17, "GPIO34_R17"), + PINCTRL_PIN(AB8500_PIN_W15, "GPIO35_W15"), + PINCTRL_PIN(AB8500_PIN_A17, "GPIO36_A17"), + PINCTRL_PIN(AB8500_PIN_E15, "GPIO37_E15"), + PINCTRL_PIN(AB8500_PIN_C17, "GPIO38_C17"), + PINCTRL_PIN(AB8500_PIN_E16, "GPIO39_E16"), + PINCTRL_PIN(AB8500_PIN_T19, "GPIO40_T19"), + PINCTRL_PIN(AB8500_PIN_U19, "GPIO41_U19"), + PINCTRL_PIN(AB8500_PIN_U2, "GPIO42_U2"), +}; + +/* + * Maps local GPIO offsets to local pin numbers + */ +static const struct abx500_pinrange ab8500_pinranges[] = { + ABX500_PINRANGE(1, 4, ABX500_ALT_A), + ABX500_PINRANGE(6, 4, ABX500_ALT_A), + ABX500_PINRANGE(10, 4, ABX500_DEFAULT), + ABX500_PINRANGE(14, 12, ABX500_ALT_A), + ABX500_PINRANGE(26, 1, ABX500_DEFAULT), + ABX500_PINRANGE(27, 6, ABX500_ALT_A), + ABX500_PINRANGE(34, 1, ABX500_ALT_A), + ABX500_PINRANGE(35, 1, ABX500_DEFAULT), + ABX500_PINRANGE(36, 7, ABX500_ALT_A), +}; + +/* + * Read the pin group names like this: + * sysclkreq2_d_1 = first groups of pins for sysclkreq2 on default function + * + * The groups are arranged as sets per altfunction column, so we can + * mux in one group at a time by selecting the same altfunction for them + * all. When functions require pins on different altfunctions, you need + * to combine several groups. + */ + +/* default column */ +static const unsigned sysclkreq2_d_1_pins[] = { AB8500_PIN_T10 }; +static const unsigned sysclkreq3_d_1_pins[] = { AB8500_PIN_T9 }; +static const unsigned sysclkreq4_d_1_pins[] = { AB8500_PIN_U9 }; +static const unsigned sysclkreq6_d_1_pins[] = { AB8500_PIN_W2 }; +static const unsigned ycbcr0123_d_1_pins[] = { AB8500_PIN_Y18, AB8500_PIN_AA20, + AB8500_PIN_W18, AB8500_PIN_AA19}; +static const unsigned gpio10_d_1_pins[] = { AB8500_PIN_U17 }; +static const unsigned gpio11_d_1_pins[] = { AB8500_PIN_AA18 }; +static const unsigned gpio12_d_1_pins[] = { AB8500_PIN_U16 }; +static const unsigned gpio13_d_1_pins[] = { AB8500_PIN_W17 }; +static const unsigned pwmout1_d_1_pins[] = { AB8500_PIN_F14 }; +static const unsigned pwmout2_d_1_pins[] = { AB8500_PIN_B17 }; +static const unsigned pwmout3_d_1_pins[] = { AB8500_PIN_F15 }; + +/* audio data interface 1*/ +static const unsigned adi1_d_1_pins[] = { AB8500_PIN_P5, AB8500_PIN_R5, + AB8500_PIN_U5, AB8500_PIN_T5 }; +/* USBUICC */ +static const unsigned usbuicc_d_1_pins[] = { AB8500_PIN_H19, AB8500_PIN_G20, + AB8500_PIN_G19 }; +static const unsigned sysclkreq7_d_1_pins[] = { AB8500_PIN_T14 }; +static const unsigned sysclkreq8_d_1_pins[] = { AB8500_PIN_R16 }; +static const unsigned gpio26_d_1_pins[] = { AB8500_PIN_M16 }; +/* Digital microphone 1 and 2 */ +static const unsigned dmic12_d_1_pins[] = { AB8500_PIN_J6, AB8500_PIN_K6 }; +/* Digital microphone 3 and 4 */ +static const unsigned dmic34_d_1_pins[] = { AB8500_PIN_G6, AB8500_PIN_H6 }; +/* Digital microphone 5 and 6 */ +static const unsigned dmic56_d_1_pins[] = { AB8500_PIN_F5, AB8500_PIN_G5 }; +static const unsigned extcpena_d_1_pins[] = { AB8500_PIN_R17 }; +static const unsigned gpio35_d_1_pins[] = { AB8500_PIN_W15 }; +/* APE SPI */ +static const unsigned apespi_d_1_pins[] = { AB8500_PIN_A17, AB8500_PIN_E15, + AB8500_PIN_C17, AB8500_PIN_E16}; +/* modem SDA/SCL */ +static const unsigned modsclsda_d_1_pins[] = { AB8500_PIN_T19, AB8500_PIN_U19 }; +static const unsigned sysclkreq5_d_1_pins[] = { AB8500_PIN_U2 }; + +/* Altfunction A column */ +static const unsigned gpio1_a_1_pins[] = { AB8500_PIN_T10 }; +static const unsigned gpio2_a_1_pins[] = { AB8500_PIN_T9 }; +static const unsigned gpio3_a_1_pins[] = { AB8500_PIN_U9 }; +static const unsigned gpio4_a_1_pins[] = { AB8500_PIN_W2 }; +static const unsigned gpio6_a_1_pins[] = { AB8500_PIN_Y18 }; +static const unsigned gpio7_a_1_pins[] = { AB8500_PIN_AA20 }; +static const unsigned gpio8_a_1_pins[] = { AB8500_PIN_W18 }; +static const unsigned gpio9_a_1_pins[] = { AB8500_PIN_AA19 }; +/* YCbCr4 YCbCr5 YCbCr6 YCbCr7*/ +static const unsigned ycbcr4567_a_1_pins[] = { AB8500_PIN_U17, AB8500_PIN_AA18, + AB8500_PIN_U16, AB8500_PIN_W17}; +static const unsigned gpio14_a_1_pins[] = { AB8500_PIN_F14 }; +static const unsigned gpio15_a_1_pins[] = { AB8500_PIN_B17 }; +static const unsigned gpio16_a_1_pins[] = { AB8500_PIN_F15 }; +static const unsigned gpio17_a_1_pins[] = { AB8500_PIN_P5 }; +static const unsigned gpio18_a_1_pins[] = { AB8500_PIN_R5 }; +static const unsigned gpio19_a_1_pins[] = { AB8500_PIN_U5 }; +static const unsigned gpio20_a_1_pins[] = { AB8500_PIN_T5 }; +static const unsigned gpio21_a_1_pins[] = { AB8500_PIN_H19 }; +static const unsigned gpio22_a_1_pins[] = { AB8500_PIN_G20 }; +static const unsigned gpio23_a_1_pins[] = { AB8500_PIN_G19 }; +static const unsigned gpio24_a_1_pins[] = { AB8500_PIN_T14 }; +static const unsigned gpio25_a_1_pins[] = { AB8500_PIN_R16 }; +static const unsigned gpio27_a_1_pins[] = { AB8500_PIN_J6 }; +static const unsigned gpio28_a_1_pins[] = { AB8500_PIN_K6 }; +static const unsigned gpio29_a_1_pins[] = { AB8500_PIN_G6 }; +static const unsigned gpio30_a_1_pins[] = { AB8500_PIN_H6 }; +static const unsigned gpio31_a_1_pins[] = { AB8500_PIN_F5 }; +static const unsigned gpio32_a_1_pins[] = { AB8500_PIN_G5 }; +static const unsigned gpio34_a_1_pins[] = { AB8500_PIN_R17 }; +static const unsigned gpio36_a_1_pins[] = { AB8500_PIN_A17 }; +static const unsigned gpio37_a_1_pins[] = { AB8500_PIN_E15 }; +static const unsigned gpio38_a_1_pins[] = { AB8500_PIN_C17 }; +static const unsigned gpio39_a_1_pins[] = { AB8500_PIN_E16 }; +static const unsigned gpio40_a_1_pins[] = { AB8500_PIN_T19 }; +static const unsigned gpio41_a_1_pins[] = { AB8500_PIN_U19 }; +static const unsigned gpio42_a_1_pins[] = { AB8500_PIN_U2 }; + +/* Altfunction B colum */ +static const unsigned hiqclkena_b_1_pins[] = { AB8500_PIN_U17 }; +static const unsigned usbuiccpd_b_1_pins[] = { AB8500_PIN_AA18 }; +static const unsigned i2ctrig1_b_1_pins[] = { AB8500_PIN_U16 }; +static const unsigned i2ctrig2_b_1_pins[] = { AB8500_PIN_W17 }; + +/* Altfunction C column */ +static const unsigned usbvdat_c_1_pins[] = { AB8500_PIN_W17 }; + + +#define AB8500_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins, \ + .npins = ARRAY_SIZE(a##_pins), .altsetting = b } + +static const struct abx500_pingroup ab8500_groups[] = { + /* default column */ + AB8500_PIN_GROUP(sysclkreq2_d_1, ABX500_DEFAULT), + AB8500_PIN_GROUP(sysclkreq3_d_1, ABX500_DEFAULT), + AB8500_PIN_GROUP(sysclkreq4_d_1, ABX500_DEFAULT), + AB8500_PIN_GROUP(sysclkreq6_d_1, ABX500_DEFAULT), + AB8500_PIN_GROUP(ycbcr0123_d_1, ABX500_DEFAULT), + AB8500_PIN_GROUP(gpio10_d_1, ABX500_DEFAULT), + AB8500_PIN_GROUP(gpio11_d_1, ABX500_DEFAULT), + AB8500_PIN_GROUP(gpio12_d_1, ABX500_DEFAULT), + AB8500_PIN_GROUP(gpio13_d_1, ABX500_DEFAULT), + AB8500_PIN_GROUP(pwmout1_d_1, ABX500_DEFAULT), + AB8500_PIN_GROUP(pwmout2_d_1, ABX500_DEFAULT), + AB8500_PIN_GROUP(pwmout3_d_1, ABX500_DEFAULT), + AB8500_PIN_GROUP(adi1_d_1, ABX500_DEFAULT), + AB8500_PIN_GROUP(usbuicc_d_1, ABX500_DEFAULT), + AB8500_PIN_GROUP(sysclkreq7_d_1, ABX500_DEFAULT), + AB8500_PIN_GROUP(sysclkreq8_d_1, ABX500_DEFAULT), + AB8500_PIN_GROUP(gpio26_d_1, ABX500_DEFAULT), + AB8500_PIN_GROUP(dmic12_d_1, ABX500_DEFAULT), + AB8500_PIN_GROUP(dmic34_d_1, ABX500_DEFAULT), + AB8500_PIN_GROUP(dmic56_d_1, ABX500_DEFAULT), + AB8500_PIN_GROUP(extcpena_d_1, ABX500_DEFAULT), + AB8500_PIN_GROUP(gpio35_d_1, ABX500_DEFAULT), + AB8500_PIN_GROUP(apespi_d_1, ABX500_DEFAULT), + AB8500_PIN_GROUP(modsclsda_d_1, ABX500_DEFAULT), + AB8500_PIN_GROUP(sysclkreq5_d_1, ABX500_DEFAULT), + /* Altfunction A column */ + AB8500_PIN_GROUP(gpio1_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio2_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio3_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio4_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio6_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio7_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio8_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio9_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(ycbcr4567_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio14_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio15_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio16_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio17_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio18_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio19_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio20_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio21_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio22_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio23_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio24_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio25_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio27_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio28_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio29_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio30_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio31_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio32_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio34_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio36_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio37_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio38_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio39_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio40_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio41_a_1, ABX500_ALT_A), + AB8500_PIN_GROUP(gpio42_a_1, ABX500_ALT_A), + /* Altfunction B column */ + AB8500_PIN_GROUP(hiqclkena_b_1, ABX500_ALT_B), + AB8500_PIN_GROUP(usbuiccpd_b_1, ABX500_ALT_B), + AB8500_PIN_GROUP(i2ctrig1_b_1, ABX500_ALT_B), + AB8500_PIN_GROUP(i2ctrig2_b_1, ABX500_ALT_B), + /* Altfunction C column */ + AB8500_PIN_GROUP(usbvdat_c_1, ABX500_ALT_C), +}; + +/* We use this macro to define the groups applicable to a function */ +#define AB8500_FUNC_GROUPS(a, b...) \ +static const char * const a##_groups[] = { b }; + +AB8500_FUNC_GROUPS(sysclkreq, "sysclkreq2_d_1", "sysclkreq3_d_1", + "sysclkreq4_d_1", "sysclkreq5_d_1", "sysclkreq6_d_1", + "sysclkreq7_d_1", "sysclkreq8_d_1"); +AB8500_FUNC_GROUPS(ycbcr, "ycbcr0123_d_1", "ycbcr4567_a_1"); +AB8500_FUNC_GROUPS(gpio, "gpio1_a_1", "gpio2_a_1", "gpio3_a_1", "gpio4_a_1", + "gpio6_a_1", "gpio7_a_1", "gpio8_a_1", "gpio9_a_1", + "gpio10_d_1", "gpio11_d_1", "gpio12_d_1", "gpio13_d_1", + "gpio14_a_1", "gpio15_a_1", "gpio16_a_1", "gpio17_a_1", + "gpio18_a_1", "gpio19_a_1", "gpio20_a_1", "gpio21_a_1", + "gpio22_a_1", "gpio23_a_1", "gpio24_a_1", "gpio25_a_1", + "gpio26_d_1", "gpio27_a_1", "gpio28_a_1", "gpio29_a_1", + "gpio30_a_1", "gpio31_a_1", "gpio32_a_1", "gpio34_a_1", + "gpio35_d_1", "gpio36_a_1", "gpio37_a_1", "gpio38_a_1", + "gpio39_a_1", "gpio40_a_1", "gpio41_a_1", "gpio42_a_1"); +AB8500_FUNC_GROUPS(pwmout, "pwmout1_d_1", "pwmout2_d_1", "pwmout3_d_1"); +AB8500_FUNC_GROUPS(adi1, "adi1_d_1"); +AB8500_FUNC_GROUPS(usbuicc, "usbuicc_d_1", "usbuiccpd_b_1"); +AB8500_FUNC_GROUPS(dmic, "dmic12_d_1", "dmic34_d_1", "dmic56_d_1"); +AB8500_FUNC_GROUPS(extcpena, "extcpena_d_1"); +AB8500_FUNC_GROUPS(apespi, "apespi_d_1"); +AB8500_FUNC_GROUPS(modsclsda, "modsclsda_d_1"); +AB8500_FUNC_GROUPS(hiqclkena, "hiqclkena_b_1"); +AB8500_FUNC_GROUPS(i2ctrig, "i2ctrig1_b_1", "i2ctrig2_b_1"); +AB8500_FUNC_GROUPS(usbvdat, "usbvdat_c_1"); + +#define FUNCTION(fname) \ + { \ + .name = #fname, \ + .groups = fname##_groups, \ + .ngroups = ARRAY_SIZE(fname##_groups), \ + } + +static const struct abx500_function ab8500_functions[] = { + FUNCTION(sysclkreq), + FUNCTION(ycbcr), + FUNCTION(gpio), + FUNCTION(pwmout), + FUNCTION(adi1), + FUNCTION(usbuicc), + FUNCTION(dmic), + FUNCTION(extcpena), + FUNCTION(apespi), + FUNCTION(modsclsda), + FUNCTION(hiqclkena), + FUNCTION(i2ctrig), + FUNCTION(usbvdat), +}; + +/* + * this table translates what's is in the AB8500 specification regarding the + * balls alternate functions (as for DB, default, ALT_A, ALT_B and ALT_C). + * ALTERNATE_FUNCTIONS(GPIO_NUMBER, GPIOSEL bit, ALTERNATFUNC bit1, + * ALTERNATEFUNC bit2, ALTA val, ALTB val, ALTC val), + * + * example : + * + * ALTERNATE_FUNCTIONS(13, 4, 3, 4, 0, 1 ,2), + * means that pin AB8500_PIN_W17 (pin 13) supports 4 mux (default/ALT_A, + * ALT_B and ALT_C), so GPIOSEL and ALTERNATFUNC registers are used to + * select the mux. ALTA, ALTB and ALTC val indicates values to write in + * ALTERNATFUNC register. We need to specifies these values as SOC + * designers didn't apply the same logic on how to select mux in the + * ABx500 family. + * + * As this pins supports at least ALT_B mux, default mux is + * selected by writing 1 in GPIOSEL bit : + * + * | GPIOSEL bit=4 | alternatfunc bit2=4 | alternatfunc bit1=3 + * default | 1 | 0 | 0 + * alt_A | 0 | 0 | 0 + * alt_B | 0 | 0 | 1 + * alt_C | 0 | 1 | 0 + * + * ALTERNATE_FUNCTIONS(8, 7, UNUSED, UNUSED), + * means that pin AB8500_PIN_W18 (pin 8) supports 2 mux, so only GPIOSEL + * register is used to select the mux. As this pins doesn't support at + * least ALT_B mux, default mux is by writing 0 in GPIOSEL bit : + * + * | GPIOSEL bit=7 | alternatfunc bit2= | alternatfunc bit1= + * default | 0 | 0 | 0 + * alt_A | 1 | 0 | 0 + */ + +static struct +alternate_functions ab8500_alternate_functions[AB8500_GPIO_MAX_NUMBER + 1] = { + ALTERNATE_FUNCTIONS(0, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO0 */ + ALTERNATE_FUNCTIONS(1, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO1, altA controlled by bit 0 */ + ALTERNATE_FUNCTIONS(2, 1, UNUSED, UNUSED, 0, 0, 0), /* GPIO2, altA controlled by bit 1 */ + ALTERNATE_FUNCTIONS(3, 2, UNUSED, UNUSED, 0, 0, 0), /* GPIO3, altA controlled by bit 2*/ + ALTERNATE_FUNCTIONS(4, 3, UNUSED, UNUSED, 0, 0, 0), /* GPIO4, altA controlled by bit 3*/ + /* bit 4 reserved */ + ALTERNATE_FUNCTIONS(5, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO5 */ + ALTERNATE_FUNCTIONS(6, 5, UNUSED, UNUSED, 0, 0, 0), /* GPIO6, altA controlled by bit 5*/ + ALTERNATE_FUNCTIONS(7, 6, UNUSED, UNUSED, 0, 0, 0), /* GPIO7, altA controlled by bit 6*/ + ALTERNATE_FUNCTIONS(8, 7, UNUSED, UNUSED, 0, 0, 0), /* GPIO8, altA controlled by bit 7*/ + + ALTERNATE_FUNCTIONS(9, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO9, altA controlled by bit 0*/ + ALTERNATE_FUNCTIONS(10, 1, 0, UNUSED, 0, 1, 0), /* GPIO10, altA and altB controlled by bit 0 */ + ALTERNATE_FUNCTIONS(11, 2, 1, UNUSED, 0, 1, 0), /* GPIO11, altA and altB controlled by bit 1 */ + ALTERNATE_FUNCTIONS(12, 3, 2, UNUSED, 0, 1, 0), /* GPIO12, altA and altB controlled by bit 2 */ + ALTERNATE_FUNCTIONS(13, 4, 3, 4, 0, 1, 2), /* GPIO13, altA altB and altC controlled by bit 3 and 4 */ + ALTERNATE_FUNCTIONS(14, 5, UNUSED, UNUSED, 0, 0, 0), /* GPIO14, altA controlled by bit 5 */ + ALTERNATE_FUNCTIONS(15, 6, UNUSED, UNUSED, 0, 0, 0), /* GPIO15, altA controlled by bit 6 */ + ALTERNATE_FUNCTIONS(16, 7, UNUSED, UNUSED, 0, 0, 0), /* GPIO16, altA controlled by bit 7 */ + /* + * pins 17 to 20 are special case, only bit 0 is used to select + * alternate function for these 4 pins. + * bits 1 to 3 are reserved + */ + ALTERNATE_FUNCTIONS(17, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO17, altA controlled by bit 0 */ + ALTERNATE_FUNCTIONS(18, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO18, altA controlled by bit 0 */ + ALTERNATE_FUNCTIONS(19, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO19, altA controlled by bit 0 */ + ALTERNATE_FUNCTIONS(20, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO20, altA controlled by bit 0 */ + ALTERNATE_FUNCTIONS(21, 4, UNUSED, UNUSED, 0, 0, 0), /* GPIO21, altA controlled by bit 4 */ + ALTERNATE_FUNCTIONS(22, 5, UNUSED, UNUSED, 0, 0, 0), /* GPIO22, altA controlled by bit 5 */ + ALTERNATE_FUNCTIONS(23, 6, UNUSED, UNUSED, 0, 0, 0), /* GPIO23, altA controlled by bit 6 */ + ALTERNATE_FUNCTIONS(24, 7, UNUSED, UNUSED, 0, 0, 0), /* GPIO24, altA controlled by bit 7 */ + + ALTERNATE_FUNCTIONS(25, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO25, altA controlled by bit 0 */ + /* pin 26 special case, no alternate function, bit 1 reserved */ + ALTERNATE_FUNCTIONS(26, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* GPIO26 */ + ALTERNATE_FUNCTIONS(27, 2, UNUSED, UNUSED, 0, 0, 0), /* GPIO27, altA controlled by bit 2 */ + ALTERNATE_FUNCTIONS(28, 3, UNUSED, UNUSED, 0, 0, 0), /* GPIO28, altA controlled by bit 3 */ + ALTERNATE_FUNCTIONS(29, 4, UNUSED, UNUSED, 0, 0, 0), /* GPIO29, altA controlled by bit 4 */ + ALTERNATE_FUNCTIONS(30, 5, UNUSED, UNUSED, 0, 0, 0), /* GPIO30, altA controlled by bit 5 */ + ALTERNATE_FUNCTIONS(31, 6, UNUSED, UNUSED, 0, 0, 0), /* GPIO31, altA controlled by bit 6 */ + ALTERNATE_FUNCTIONS(32, 7, UNUSED, UNUSED, 0, 0, 0), /* GPIO32, altA controlled by bit 7 */ + + ALTERNATE_FUNCTIONS(33, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO33 */ + ALTERNATE_FUNCTIONS(34, 1, UNUSED, UNUSED, 0, 0, 0), /* GPIO34, altA controlled by bit 1 */ + /* pin 35 special case, no alternate function, bit 2 reserved */ + ALTERNATE_FUNCTIONS(35, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* GPIO35 */ + ALTERNATE_FUNCTIONS(36, 3, UNUSED, UNUSED, 0, 0, 0), /* GPIO36, altA controlled by bit 3 */ + ALTERNATE_FUNCTIONS(37, 4, UNUSED, UNUSED, 0, 0, 0), /* GPIO37, altA controlled by bit 4 */ + ALTERNATE_FUNCTIONS(38, 5, UNUSED, UNUSED, 0, 0, 0), /* GPIO38, altA controlled by bit 5 */ + ALTERNATE_FUNCTIONS(39, 6, UNUSED, UNUSED, 0, 0, 0), /* GPIO39, altA controlled by bit 6 */ + ALTERNATE_FUNCTIONS(40, 7, UNUSED, UNUSED, 0, 0, 0), /* GPIO40, altA controlled by bit 7 */ + + ALTERNATE_FUNCTIONS(41, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO41, altA controlled by bit 0 */ + ALTERNATE_FUNCTIONS(42, 1, UNUSED, UNUSED, 0, 0, 0), /* GPIO42, altA controlled by bit 1 */ +}; + +/* + * Only some GPIOs are interrupt capable, and they are + * organized in discontiguous clusters: + * + * GPIO6 to GPIO13 + * GPIO24 and GPIO25 + * GPIO36 to GPIO41 + */ +static struct abx500_gpio_irq_cluster ab8500_gpio_irq_cluster[] = { + GPIO_IRQ_CLUSTER(6, 13, AB8500_INT_GPIO6R), + GPIO_IRQ_CLUSTER(24, 25, AB8500_INT_GPIO24R), + GPIO_IRQ_CLUSTER(36, 41, AB8500_INT_GPIO36R), +}; + +static struct abx500_pinctrl_soc_data ab8500_soc = { + .gpio_ranges = ab8500_pinranges, + .gpio_num_ranges = ARRAY_SIZE(ab8500_pinranges), + .pins = ab8500_pins, + .npins = ARRAY_SIZE(ab8500_pins), + .functions = ab8500_functions, + .nfunctions = ARRAY_SIZE(ab8500_functions), + .groups = ab8500_groups, + .ngroups = ARRAY_SIZE(ab8500_groups), + .alternate_functions = ab8500_alternate_functions, + .gpio_irq_cluster = ab8500_gpio_irq_cluster, + .ngpio_irq_cluster = ARRAY_SIZE(ab8500_gpio_irq_cluster), + .irq_gpio_rising_offset = AB8500_INT_GPIO6R, + .irq_gpio_falling_offset = AB8500_INT_GPIO6F, + .irq_gpio_factor = 1, +}; + +void abx500_pinctrl_ab8500_init(struct abx500_pinctrl_soc_data **soc) +{ + *soc = &ab8500_soc; +} diff --git a/drivers/pinctrl/nomadik/pinctrl-ab8505.c b/drivers/pinctrl/nomadik/pinctrl-ab8505.c new file mode 100644 index 000000000000..bf0ef4ac376f --- /dev/null +++ b/drivers/pinctrl/nomadik/pinctrl-ab8505.c @@ -0,0 +1,381 @@ +/* + * Copyright (C) ST-Ericsson SA 2012 + * + * Author: Patrice Chotard <patrice.chotard@stericsson.com> for ST-Ericsson. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/gpio.h> +#include <linux/pinctrl/pinctrl.h> +#include <linux/mfd/abx500/ab8500.h> +#include "pinctrl-abx500.h" + +/* All the pins that can be used for GPIO and some other functions */ +#define ABX500_GPIO(offset) (offset) + +#define AB8505_PIN_N4 ABX500_GPIO(1) +#define AB8505_PIN_R5 ABX500_GPIO(2) +#define AB8505_PIN_P5 ABX500_GPIO(3) +/* hole */ +#define AB8505_PIN_B16 ABX500_GPIO(10) +#define AB8505_PIN_B17 ABX500_GPIO(11) +/* hole */ +#define AB8505_PIN_D17 ABX500_GPIO(13) +#define AB8505_PIN_C16 ABX500_GPIO(14) +/* hole */ +#define AB8505_PIN_P2 ABX500_GPIO(17) +#define AB8505_PIN_N3 ABX500_GPIO(18) +#define AB8505_PIN_T1 ABX500_GPIO(19) +#define AB8505_PIN_P3 ABX500_GPIO(20) +/* hole */ +#define AB8505_PIN_H14 ABX500_GPIO(34) +/* hole */ +#define AB8505_PIN_J15 ABX500_GPIO(40) +#define AB8505_PIN_J14 ABX500_GPIO(41) +/* hole */ +#define AB8505_PIN_L4 ABX500_GPIO(50) +/* hole */ +#define AB8505_PIN_D16 ABX500_GPIO(52) +#define AB8505_PIN_D15 ABX500_GPIO(53) + +/* indicates the higher GPIO number */ +#define AB8505_GPIO_MAX_NUMBER 53 + +/* + * The names of the pins are denoted by GPIO number and ball name, even + * though they can be used for other things than GPIO, this is the first + * column in the table of the data sheet and often used on schematics and + * such. + */ +static const struct pinctrl_pin_desc ab8505_pins[] = { + PINCTRL_PIN(AB8505_PIN_N4, "GPIO1_N4"), + PINCTRL_PIN(AB8505_PIN_R5, "GPIO2_R5"), + PINCTRL_PIN(AB8505_PIN_P5, "GPIO3_P5"), +/* hole */ + PINCTRL_PIN(AB8505_PIN_B16, "GPIO10_B16"), + PINCTRL_PIN(AB8505_PIN_B17, "GPIO11_B17"), +/* hole */ + PINCTRL_PIN(AB8505_PIN_D17, "GPIO13_D17"), + PINCTRL_PIN(AB8505_PIN_C16, "GPIO14_C16"), +/* hole */ + PINCTRL_PIN(AB8505_PIN_P2, "GPIO17_P2"), + PINCTRL_PIN(AB8505_PIN_N3, "GPIO18_N3"), + PINCTRL_PIN(AB8505_PIN_T1, "GPIO19_T1"), + PINCTRL_PIN(AB8505_PIN_P3, "GPIO20_P3"), +/* hole */ + PINCTRL_PIN(AB8505_PIN_H14, "GPIO34_H14"), +/* hole */ + PINCTRL_PIN(AB8505_PIN_J15, "GPIO40_J15"), + PINCTRL_PIN(AB8505_PIN_J14, "GPIO41_J14"), +/* hole */ + PINCTRL_PIN(AB8505_PIN_L4, "GPIO50_L4"), +/* hole */ + PINCTRL_PIN(AB8505_PIN_D16, "GPIO52_D16"), + PINCTRL_PIN(AB8505_PIN_D15, "GPIO53_D15"), +}; + +/* + * Maps local GPIO offsets to local pin numbers + */ +static const struct abx500_pinrange ab8505_pinranges[] = { + ABX500_PINRANGE(1, 3, ABX500_ALT_A), + ABX500_PINRANGE(10, 2, ABX500_DEFAULT), + ABX500_PINRANGE(13, 1, ABX500_DEFAULT), + ABX500_PINRANGE(14, 1, ABX500_ALT_A), + ABX500_PINRANGE(17, 4, ABX500_ALT_A), + ABX500_PINRANGE(34, 1, ABX500_ALT_A), + ABX500_PINRANGE(40, 2, ABX500_ALT_A), + ABX500_PINRANGE(50, 1, ABX500_DEFAULT), + ABX500_PINRANGE(52, 2, ABX500_ALT_A), +}; + +/* + * Read the pin group names like this: + * sysclkreq2_d_1 = first groups of pins for sysclkreq2 on default function + * + * The groups are arranged as sets per altfunction column, so we can + * mux in one group at a time by selecting the same altfunction for them + * all. When functions require pins on different altfunctions, you need + * to combine several groups. + */ + +/* default column */ +static const unsigned sysclkreq2_d_1_pins[] = { AB8505_PIN_N4 }; +static const unsigned sysclkreq3_d_1_pins[] = { AB8505_PIN_R5 }; +static const unsigned sysclkreq4_d_1_pins[] = { AB8505_PIN_P5 }; +static const unsigned gpio10_d_1_pins[] = { AB8505_PIN_B16 }; +static const unsigned gpio11_d_1_pins[] = { AB8505_PIN_B17 }; +static const unsigned gpio13_d_1_pins[] = { AB8505_PIN_D17 }; +static const unsigned pwmout1_d_1_pins[] = { AB8505_PIN_C16 }; +/* audio data interface 2*/ +static const unsigned adi2_d_1_pins[] = { AB8505_PIN_P2, AB8505_PIN_N3, + AB8505_PIN_T1, AB8505_PIN_P3 }; +static const unsigned extcpena_d_1_pins[] = { AB8505_PIN_H14 }; +/* modem SDA/SCL */ +static const unsigned modsclsda_d_1_pins[] = { AB8505_PIN_J15, AB8505_PIN_J14 }; +static const unsigned gpio50_d_1_pins[] = { AB8505_PIN_L4 }; +static const unsigned resethw_d_1_pins[] = { AB8505_PIN_D16 }; +static const unsigned service_d_1_pins[] = { AB8505_PIN_D15 }; + +/* Altfunction A column */ +static const unsigned gpio1_a_1_pins[] = { AB8505_PIN_N4 }; +static const unsigned gpio2_a_1_pins[] = { AB8505_PIN_R5 }; +static const unsigned gpio3_a_1_pins[] = { AB8505_PIN_P5 }; +static const unsigned hiqclkena_a_1_pins[] = { AB8505_PIN_B16 }; +static const unsigned pdmclk_a_1_pins[] = { AB8505_PIN_B17 }; +static const unsigned uarttxdata_a_1_pins[] = { AB8505_PIN_D17 }; +static const unsigned gpio14_a_1_pins[] = { AB8505_PIN_C16 }; +static const unsigned gpio17_a_1_pins[] = { AB8505_PIN_P2 }; +static const unsigned gpio18_a_1_pins[] = { AB8505_PIN_N3 }; +static const unsigned gpio19_a_1_pins[] = { AB8505_PIN_T1 }; +static const unsigned gpio20_a_1_pins[] = { AB8505_PIN_P3 }; +static const unsigned gpio34_a_1_pins[] = { AB8505_PIN_H14 }; +static const unsigned gpio40_a_1_pins[] = { AB8505_PIN_J15 }; +static const unsigned gpio41_a_1_pins[] = { AB8505_PIN_J14 }; +static const unsigned uartrxdata_a_1_pins[] = { AB8505_PIN_J14 }; +static const unsigned gpio50_a_1_pins[] = { AB8505_PIN_L4 }; +static const unsigned gpio52_a_1_pins[] = { AB8505_PIN_D16 }; +static const unsigned gpio53_a_1_pins[] = { AB8505_PIN_D15 }; + +/* Altfunction B colum */ +static const unsigned pdmdata_b_1_pins[] = { AB8505_PIN_B16 }; +static const unsigned extvibrapwm1_b_1_pins[] = { AB8505_PIN_D17 }; +static const unsigned extvibrapwm2_b_1_pins[] = { AB8505_PIN_L4 }; + +/* Altfunction C column */ +static const unsigned usbvdat_c_1_pins[] = { AB8505_PIN_D17 }; + +#define AB8505_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins, \ + .npins = ARRAY_SIZE(a##_pins), .altsetting = b } + +static const struct abx500_pingroup ab8505_groups[] = { + AB8505_PIN_GROUP(sysclkreq2_d_1, ABX500_DEFAULT), + AB8505_PIN_GROUP(sysclkreq3_d_1, ABX500_DEFAULT), + AB8505_PIN_GROUP(sysclkreq4_d_1, ABX500_DEFAULT), + AB8505_PIN_GROUP(gpio10_d_1, ABX500_DEFAULT), + AB8505_PIN_GROUP(gpio11_d_1, ABX500_DEFAULT), + AB8505_PIN_GROUP(gpio13_d_1, ABX500_DEFAULT), + AB8505_PIN_GROUP(pwmout1_d_1, ABX500_DEFAULT), + AB8505_PIN_GROUP(adi2_d_1, ABX500_DEFAULT), + AB8505_PIN_GROUP(extcpena_d_1, ABX500_DEFAULT), + AB8505_PIN_GROUP(modsclsda_d_1, ABX500_DEFAULT), + AB8505_PIN_GROUP(gpio50_d_1, ABX500_DEFAULT), + AB8505_PIN_GROUP(resethw_d_1, ABX500_DEFAULT), + AB8505_PIN_GROUP(service_d_1, ABX500_DEFAULT), + AB8505_PIN_GROUP(gpio1_a_1, ABX500_ALT_A), + AB8505_PIN_GROUP(gpio2_a_1, ABX500_ALT_A), + AB8505_PIN_GROUP(gpio3_a_1, ABX500_ALT_A), + AB8505_PIN_GROUP(hiqclkena_a_1, ABX500_ALT_A), + AB8505_PIN_GROUP(pdmclk_a_1, ABX500_ALT_A), + AB8505_PIN_GROUP(uarttxdata_a_1, ABX500_ALT_A), + AB8505_PIN_GROUP(gpio14_a_1, ABX500_ALT_A), + AB8505_PIN_GROUP(gpio17_a_1, ABX500_ALT_A), + AB8505_PIN_GROUP(gpio18_a_1, ABX500_ALT_A), + AB8505_PIN_GROUP(gpio19_a_1, ABX500_ALT_A), + AB8505_PIN_GROUP(gpio20_a_1, ABX500_ALT_A), + AB8505_PIN_GROUP(gpio34_a_1, ABX500_ALT_A), + AB8505_PIN_GROUP(gpio40_a_1, ABX500_ALT_A), + AB8505_PIN_GROUP(gpio41_a_1, ABX500_ALT_A), + AB8505_PIN_GROUP(uartrxdata_a_1, ABX500_ALT_A), + AB8505_PIN_GROUP(gpio52_a_1, ABX500_ALT_A), + AB8505_PIN_GROUP(gpio53_a_1, ABX500_ALT_A), + AB8505_PIN_GROUP(pdmdata_b_1, ABX500_ALT_B), + AB8505_PIN_GROUP(extvibrapwm1_b_1, ABX500_ALT_B), + AB8505_PIN_GROUP(extvibrapwm2_b_1, ABX500_ALT_B), + AB8505_PIN_GROUP(usbvdat_c_1, ABX500_ALT_C), +}; + +/* We use this macro to define the groups applicable to a function */ +#define AB8505_FUNC_GROUPS(a, b...) \ +static const char * const a##_groups[] = { b }; + +AB8505_FUNC_GROUPS(sysclkreq, "sysclkreq2_d_1", "sysclkreq3_d_1", + "sysclkreq4_d_1"); +AB8505_FUNC_GROUPS(gpio, "gpio1_a_1", "gpio2_a_1", "gpio3_a_1", + "gpio10_d_1", "gpio11_d_1", "gpio13_d_1", "gpio14_a_1", + "gpio17_a_1", "gpio18_a_1", "gpio19_a_1", "gpio20_a_1", + "gpio34_a_1", "gpio40_a_1", "gpio41_a_1", "gpio50_d_1", + "gpio52_a_1", "gpio53_a_1"); +AB8505_FUNC_GROUPS(pwmout, "pwmout1_d_1"); +AB8505_FUNC_GROUPS(adi2, "adi2_d_1"); +AB8505_FUNC_GROUPS(extcpena, "extcpena_d_1"); +AB8505_FUNC_GROUPS(modsclsda, "modsclsda_d_1"); +AB8505_FUNC_GROUPS(resethw, "resethw_d_1"); +AB8505_FUNC_GROUPS(service, "service_d_1"); +AB8505_FUNC_GROUPS(hiqclkena, "hiqclkena_a_1"); +AB8505_FUNC_GROUPS(pdm, "pdmclk_a_1", "pdmdata_b_1"); +AB8505_FUNC_GROUPS(uartdata, "uarttxdata_a_1", "uartrxdata_a_1"); +AB8505_FUNC_GROUPS(extvibra, "extvibrapwm1_b_1", "extvibrapwm2_b_1"); +AB8505_FUNC_GROUPS(usbvdat, "usbvdat_c_1"); + +#define FUNCTION(fname) \ + { \ + .name = #fname, \ + .groups = fname##_groups, \ + .ngroups = ARRAY_SIZE(fname##_groups), \ + } + +static const struct abx500_function ab8505_functions[] = { + FUNCTION(sysclkreq), + FUNCTION(gpio), + FUNCTION(pwmout), + FUNCTION(adi2), + FUNCTION(extcpena), + FUNCTION(modsclsda), + FUNCTION(resethw), + FUNCTION(service), + FUNCTION(hiqclkena), + FUNCTION(pdm), + FUNCTION(uartdata), + FUNCTION(extvibra), + FUNCTION(extvibra), + FUNCTION(usbvdat), +}; + +/* + * this table translates what's is in the AB8505 specification regarding the + * balls alternate functions (as for DB, default, ALT_A, ALT_B and ALT_C). + * ALTERNATE_FUNCTIONS(GPIO_NUMBER, GPIOSEL bit, ALTERNATFUNC bit1, + * ALTERNATEFUNC bit2, ALTA val, ALTB val, ALTC val), + * + * example : + * + * ALTERNATE_FUNCTIONS(13, 4, 3, 4, 1, 0, 2), + * means that pin AB8505_PIN_D18 (pin 13) supports 4 mux (default/ALT_A, + * ALT_B and ALT_C), so GPIOSEL and ALTERNATFUNC registers are used to + * select the mux. ALTA, ALTB and ALTC val indicates values to write in + * ALTERNATFUNC register. We need to specifies these values as SOC + * designers didn't apply the same logic on how to select mux in the + * ABx500 family. + * + * As this pins supports at least ALT_B mux, default mux is + * selected by writing 1 in GPIOSEL bit : + * + * | GPIOSEL bit=4 | alternatfunc bit2=4 | alternatfunc bit1=3 + * default | 1 | 0 | 0 + * alt_A | 0 | 0 | 1 + * alt_B | 0 | 0 | 0 + * alt_C | 0 | 1 | 0 + * + * ALTERNATE_FUNCTIONS(1, 0, UNUSED, UNUSED), + * means that pin AB9540_PIN_R4 (pin 1) supports 2 mux, so only GPIOSEL + * register is used to select the mux. As this pins doesn't support at + * least ALT_B mux, default mux is by writing 0 in GPIOSEL bit : + * + * | GPIOSEL bit=0 | alternatfunc bit2= | alternatfunc bit1= + * default | 0 | 0 | 0 + * alt_A | 1 | 0 | 0 + */ + +static struct +alternate_functions ab8505_alternate_functions[AB8505_GPIO_MAX_NUMBER + 1] = { + ALTERNATE_FUNCTIONS(0, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO0 */ + ALTERNATE_FUNCTIONS(1, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO1, altA controlled by bit 0 */ + ALTERNATE_FUNCTIONS(2, 1, UNUSED, UNUSED, 0, 0, 0), /* GPIO2, altA controlled by bit 1 */ + ALTERNATE_FUNCTIONS(3, 2, UNUSED, UNUSED, 0, 0, 0), /* GPIO3, altA controlled by bit 2*/ + ALTERNATE_FUNCTIONS(4, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO4, bit 3 reserved */ + ALTERNATE_FUNCTIONS(5, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO5, bit 4 reserved */ + ALTERNATE_FUNCTIONS(6, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO6, bit 5 reserved */ + ALTERNATE_FUNCTIONS(7, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO7, bit 6 reserved */ + ALTERNATE_FUNCTIONS(8, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO8, bit 7 reserved */ + + ALTERNATE_FUNCTIONS(9, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO9, bit 0 reserved */ + ALTERNATE_FUNCTIONS(10, 1, 0, UNUSED, 1, 0, 0), /* GPIO10, altA and altB controlled by bit 0 */ + ALTERNATE_FUNCTIONS(11, 2, 1, UNUSED, 0, 0, 0), /* GPIO11, altA controlled by bit 2 */ + ALTERNATE_FUNCTIONS(12, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO12, bit3 reseved */ + ALTERNATE_FUNCTIONS(13, 4, 3, 4, 1, 0, 2), /* GPIO13, altA altB and altC controlled by bit 3 and 4 */ + ALTERNATE_FUNCTIONS(14, 5, UNUSED, UNUSED, 0, 0, 0), /* GPIO14, altA controlled by bit 5 */ + ALTERNATE_FUNCTIONS(15, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO15, bit 6 reserved */ + ALTERNATE_FUNCTIONS(16, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO15, bit 7 reserved */ + /* + * pins 17 to 20 are special case, only bit 0 is used to select + * alternate function for these 4 pins. + * bits 1 to 3 are reserved + */ + ALTERNATE_FUNCTIONS(17, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO17, altA controlled by bit 0 */ + ALTERNATE_FUNCTIONS(18, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO18, altA controlled by bit 0 */ + ALTERNATE_FUNCTIONS(19, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO19, altA controlled by bit 0 */ + ALTERNATE_FUNCTIONS(20, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO20, altA controlled by bit 0 */ + ALTERNATE_FUNCTIONS(21, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO21, bit 4 reserved */ + ALTERNATE_FUNCTIONS(22, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO22, bit 5 reserved */ + ALTERNATE_FUNCTIONS(23, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO23, bit 6 reserved */ + ALTERNATE_FUNCTIONS(24, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO24, bit 7 reserved */ + + ALTERNATE_FUNCTIONS(25, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO25, bit 0 reserved */ + ALTERNATE_FUNCTIONS(26, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO26, bit 1 reserved */ + ALTERNATE_FUNCTIONS(27, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO27, bit 2 reserved */ + ALTERNATE_FUNCTIONS(28, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO28, bit 3 reserved */ + ALTERNATE_FUNCTIONS(29, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO29, bit 4 reserved */ + ALTERNATE_FUNCTIONS(30, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO30, bit 5 reserved */ + ALTERNATE_FUNCTIONS(31, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO31, bit 6 reserved */ + ALTERNATE_FUNCTIONS(32, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO32, bit 7 reserved */ + + ALTERNATE_FUNCTIONS(33, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO33, bit 0 reserved */ + ALTERNATE_FUNCTIONS(34, 1, UNUSED, UNUSED, 0, 0, 0), /* GPIO34, altA controlled by bit 1 */ + ALTERNATE_FUNCTIONS(35, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO35, bit 2 reserved */ + ALTERNATE_FUNCTIONS(36, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO36, bit 2 reserved */ + ALTERNATE_FUNCTIONS(37, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO37, bit 2 reserved */ + ALTERNATE_FUNCTIONS(38, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO38, bit 2 reserved */ + ALTERNATE_FUNCTIONS(39, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO39, bit 2 reserved */ + ALTERNATE_FUNCTIONS(40, 7, UNUSED, UNUSED, 0, 0, 0), /* GPIO40, altA controlled by bit 7*/ + + ALTERNATE_FUNCTIONS(41, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO41, altA controlled by bit 0 */ + ALTERNATE_FUNCTIONS(42, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO42, bit 1 reserved */ + ALTERNATE_FUNCTIONS(43, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO43, bit 2 reserved */ + ALTERNATE_FUNCTIONS(44, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO44, bit 3 reserved */ + ALTERNATE_FUNCTIONS(45, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO45, bit 4 reserved */ + ALTERNATE_FUNCTIONS(46, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO46, bit 5 reserved */ + ALTERNATE_FUNCTIONS(47, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO47, bit 6 reserved */ + ALTERNATE_FUNCTIONS(48, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO48, bit 7 reserved */ + + ALTERNATE_FUNCTIONS(49, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO49, bit 0 reserved */ + ALTERNATE_FUNCTIONS(50, 1, 2, UNUSED, 1, 0, 0), /* GPIO50, altA controlled by bit 1 */ + ALTERNATE_FUNCTIONS(51, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO49, bit 0 reserved */ + ALTERNATE_FUNCTIONS(52, 3, UNUSED, UNUSED, 0, 0, 0), /* GPIO52, altA controlled by bit 3 */ + ALTERNATE_FUNCTIONS(53, 4, UNUSED, UNUSED, 0, 0, 0), /* GPIO53, altA controlled by bit 4 */ +}; + +/* + * For AB8505 Only some GPIOs are interrupt capable, and they are + * organized in discontiguous clusters: + * + * GPIO10 to GPIO11 + * GPIO13 + * GPIO40 and GPIO41 + * GPIO50 + * GPIO52 to GPIO53 + */ +static struct abx500_gpio_irq_cluster ab8505_gpio_irq_cluster[] = { + GPIO_IRQ_CLUSTER(10, 11, AB8500_INT_GPIO10R), + GPIO_IRQ_CLUSTER(13, 13, AB8500_INT_GPIO13R), + GPIO_IRQ_CLUSTER(40, 41, AB8500_INT_GPIO40R), + GPIO_IRQ_CLUSTER(50, 50, AB9540_INT_GPIO50R), + GPIO_IRQ_CLUSTER(52, 53, AB9540_INT_GPIO52R), +}; + +static struct abx500_pinctrl_soc_data ab8505_soc = { + .gpio_ranges = ab8505_pinranges, + .gpio_num_ranges = ARRAY_SIZE(ab8505_pinranges), + .pins = ab8505_pins, + .npins = ARRAY_SIZE(ab8505_pins), + .functions = ab8505_functions, + .nfunctions = ARRAY_SIZE(ab8505_functions), + .groups = ab8505_groups, + .ngroups = ARRAY_SIZE(ab8505_groups), + .alternate_functions = ab8505_alternate_functions, + .gpio_irq_cluster = ab8505_gpio_irq_cluster, + .ngpio_irq_cluster = ARRAY_SIZE(ab8505_gpio_irq_cluster), + .irq_gpio_rising_offset = AB8500_INT_GPIO6R, + .irq_gpio_falling_offset = AB8500_INT_GPIO6F, + .irq_gpio_factor = 1, +}; + +void +abx500_pinctrl_ab8505_init(struct abx500_pinctrl_soc_data **soc) +{ + *soc = &ab8505_soc; +} diff --git a/drivers/pinctrl/nomadik/pinctrl-ab8540.c b/drivers/pinctrl/nomadik/pinctrl-ab8540.c new file mode 100644 index 000000000000..9867535d49c1 --- /dev/null +++ b/drivers/pinctrl/nomadik/pinctrl-ab8540.c @@ -0,0 +1,408 @@ +/* + * Copyright (C) ST-Ericsson SA 2012 + * + * Author: Patrice Chotard <patrice.chotard@stericsson.com> for ST-Ericsson. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/gpio.h> +#include <linux/pinctrl/pinctrl.h> +#include <linux/mfd/abx500/ab8500.h> +#include "pinctrl-abx500.h" + +/* All the pins that can be used for GPIO and some other functions */ +#define ABX500_GPIO(offset) (offset) + +#define AB8540_PIN_J16 ABX500_GPIO(1) +#define AB8540_PIN_D17 ABX500_GPIO(2) +#define AB8540_PIN_C12 ABX500_GPIO(3) +#define AB8540_PIN_G12 ABX500_GPIO(4) +/* hole */ +#define AB8540_PIN_D16 ABX500_GPIO(14) +#define AB8540_PIN_F15 ABX500_GPIO(15) +#define AB8540_PIN_J8 ABX500_GPIO(16) +#define AB8540_PIN_K16 ABX500_GPIO(17) +#define AB8540_PIN_G15 ABX500_GPIO(18) +#define AB8540_PIN_F17 ABX500_GPIO(19) +#define AB8540_PIN_E17 ABX500_GPIO(20) +/* hole */ +#define AB8540_PIN_AA16 ABX500_GPIO(27) +#define AB8540_PIN_W18 ABX500_GPIO(28) +#define AB8540_PIN_Y15 ABX500_GPIO(29) +#define AB8540_PIN_W16 ABX500_GPIO(30) +#define AB8540_PIN_V15 ABX500_GPIO(31) +#define AB8540_PIN_W17 ABX500_GPIO(32) +/* hole */ +#define AB8540_PIN_D12 ABX500_GPIO(42) +#define AB8540_PIN_P4 ABX500_GPIO(43) +#define AB8540_PIN_AB1 ABX500_GPIO(44) +#define AB8540_PIN_K7 ABX500_GPIO(45) +#define AB8540_PIN_L7 ABX500_GPIO(46) +#define AB8540_PIN_G10 ABX500_GPIO(47) +#define AB8540_PIN_K12 ABX500_GPIO(48) +/* hole */ +#define AB8540_PIN_N8 ABX500_GPIO(51) +#define AB8540_PIN_P12 ABX500_GPIO(52) +#define AB8540_PIN_K8 ABX500_GPIO(53) +#define AB8540_PIN_J11 ABX500_GPIO(54) +#define AB8540_PIN_AC2 ABX500_GPIO(55) +#define AB8540_PIN_AB2 ABX500_GPIO(56) + +/* indicates the highest GPIO number */ +#define AB8540_GPIO_MAX_NUMBER 56 + +/* + * The names of the pins are denoted by GPIO number and ball name, even + * though they can be used for other things than GPIO, this is the first + * column in the table of the data sheet and often used on schematics and + * such. + */ +static const struct pinctrl_pin_desc ab8540_pins[] = { + PINCTRL_PIN(AB8540_PIN_J16, "GPIO1_J16"), + PINCTRL_PIN(AB8540_PIN_D17, "GPIO2_D17"), + PINCTRL_PIN(AB8540_PIN_C12, "GPIO3_C12"), + PINCTRL_PIN(AB8540_PIN_G12, "GPIO4_G12"), + /* hole */ + PINCTRL_PIN(AB8540_PIN_D16, "GPIO14_D16"), + PINCTRL_PIN(AB8540_PIN_F15, "GPIO15_F15"), + PINCTRL_PIN(AB8540_PIN_J8, "GPIO16_J8"), + PINCTRL_PIN(AB8540_PIN_K16, "GPIO17_K16"), + PINCTRL_PIN(AB8540_PIN_G15, "GPIO18_G15"), + PINCTRL_PIN(AB8540_PIN_F17, "GPIO19_F17"), + PINCTRL_PIN(AB8540_PIN_E17, "GPIO20_E17"), + /* hole */ + PINCTRL_PIN(AB8540_PIN_AA16, "GPIO27_AA16"), + PINCTRL_PIN(AB8540_PIN_W18, "GPIO28_W18"), + PINCTRL_PIN(AB8540_PIN_Y15, "GPIO29_Y15"), + PINCTRL_PIN(AB8540_PIN_W16, "GPIO30_W16"), + PINCTRL_PIN(AB8540_PIN_V15, "GPIO31_V15"), + PINCTRL_PIN(AB8540_PIN_W17, "GPIO32_W17"), + /* hole */ + PINCTRL_PIN(AB8540_PIN_D12, "GPIO42_D12"), + PINCTRL_PIN(AB8540_PIN_P4, "GPIO43_P4"), + PINCTRL_PIN(AB8540_PIN_AB1, "GPIO44_AB1"), + PINCTRL_PIN(AB8540_PIN_K7, "GPIO45_K7"), + PINCTRL_PIN(AB8540_PIN_L7, "GPIO46_L7"), + PINCTRL_PIN(AB8540_PIN_G10, "GPIO47_G10"), + PINCTRL_PIN(AB8540_PIN_K12, "GPIO48_K12"), + /* hole */ + PINCTRL_PIN(AB8540_PIN_N8, "GPIO51_N8"), + PINCTRL_PIN(AB8540_PIN_P12, "GPIO52_P12"), + PINCTRL_PIN(AB8540_PIN_K8, "GPIO53_K8"), + PINCTRL_PIN(AB8540_PIN_J11, "GPIO54_J11"), + PINCTRL_PIN(AB8540_PIN_AC2, "GPIO55_AC2"), + PINCTRL_PIN(AB8540_PIN_AB2, "GPIO56_AB2"), +}; + +/* + * Maps local GPIO offsets to local pin numbers + */ +static const struct abx500_pinrange ab8540_pinranges[] = { + ABX500_PINRANGE(1, 4, ABX500_ALT_A), + ABX500_PINRANGE(14, 7, ABX500_ALT_A), + ABX500_PINRANGE(27, 6, ABX500_ALT_A), + ABX500_PINRANGE(42, 7, ABX500_ALT_A), + ABX500_PINRANGE(51, 6, ABX500_ALT_A), +}; + +/* + * Read the pin group names like this: + * sysclkreq2_d_1 = first groups of pins for sysclkreq2 on default function + * + * The groups are arranged as sets per altfunction column, so we can + * mux in one group at a time by selecting the same altfunction for them + * all. When functions require pins on different altfunctions, you need + * to combine several groups. + */ + +/* default column */ +static const unsigned sysclkreq2_d_1_pins[] = { AB8540_PIN_J16 }; +static const unsigned sysclkreq3_d_1_pins[] = { AB8540_PIN_D17 }; +static const unsigned sysclkreq4_d_1_pins[] = { AB8540_PIN_C12 }; +static const unsigned sysclkreq6_d_1_pins[] = { AB8540_PIN_G12 }; +static const unsigned pwmout1_d_1_pins[] = { AB8540_PIN_D16 }; +static const unsigned pwmout2_d_1_pins[] = { AB8540_PIN_F15 }; +static const unsigned pwmout3_d_1_pins[] = { AB8540_PIN_J8 }; + +/* audio data interface 1*/ +static const unsigned adi1_d_1_pins[] = { AB8540_PIN_K16, AB8540_PIN_G15, + AB8540_PIN_F17, AB8540_PIN_E17 }; +/* Digital microphone 1 and 2 */ +static const unsigned dmic12_d_1_pins[] = { AB8540_PIN_AA16, AB8540_PIN_W18 }; +/* Digital microphone 3 and 4 */ +static const unsigned dmic34_d_1_pins[] = { AB8540_PIN_Y15, AB8540_PIN_W16 }; +/* Digital microphone 5 and 6 */ +static const unsigned dmic56_d_1_pins[] = { AB8540_PIN_V15, AB8540_PIN_W17 }; +static const unsigned sysclkreq5_d_1_pins[] = { AB8540_PIN_D12 }; +static const unsigned batremn_d_1_pins[] = { AB8540_PIN_P4 }; +static const unsigned service_d_1_pins[] = { AB8540_PIN_AB1 }; +static const unsigned pwrctrl0_d_1_pins[] = { AB8540_PIN_K7 }; +static const unsigned pwrctrl1_d_1_pins[] = { AB8540_PIN_L7 }; +static const unsigned pwmextvibra1_d_1_pins[] = { AB8540_PIN_G10 }; +static const unsigned pwmextvibra2_d_1_pins[] = { AB8540_PIN_K12 }; +static const unsigned gpio1_vbat_d_1_pins[] = { AB8540_PIN_N8 }; +static const unsigned gpio2_vbat_d_1_pins[] = { AB8540_PIN_P12 }; +static const unsigned gpio3_vbat_d_1_pins[] = { AB8540_PIN_K8 }; +static const unsigned gpio4_vbat_d_1_pins[] = { AB8540_PIN_J11 }; +static const unsigned pdmclkdat_d_1_pins[] = { AB8540_PIN_AC2, AB8540_PIN_AB2 }; + +/* Altfunction A column */ +static const unsigned gpio1_a_1_pins[] = { AB8540_PIN_J16 }; +static const unsigned gpio2_a_1_pins[] = { AB8540_PIN_D17 }; +static const unsigned gpio3_a_1_pins[] = { AB8540_PIN_C12 }; +static const unsigned gpio4_a_1_pins[] = { AB8540_PIN_G12 }; +static const unsigned gpio14_a_1_pins[] = { AB8540_PIN_D16 }; +static const unsigned gpio15_a_1_pins[] = { AB8540_PIN_F15 }; +static const unsigned gpio16_a_1_pins[] = { AB8540_PIN_J8 }; +static const unsigned gpio17_a_1_pins[] = { AB8540_PIN_K16 }; +static const unsigned gpio18_a_1_pins[] = { AB8540_PIN_G15 }; +static const unsigned gpio19_a_1_pins[] = { AB8540_PIN_F17 }; +static const unsigned gpio20_a_1_pins[] = { AB8540_PIN_E17 }; +static const unsigned gpio27_a_1_pins[] = { AB8540_PIN_AA16 }; +static const unsigned gpio28_a_1_pins[] = { AB8540_PIN_W18 }; +static const unsigned gpio29_a_1_pins[] = { AB8540_PIN_Y15 }; +static const unsigned gpio30_a_1_pins[] = { AB8540_PIN_W16 }; +static const unsigned gpio31_a_1_pins[] = { AB8540_PIN_V15 }; +static const unsigned gpio32_a_1_pins[] = { AB8540_PIN_W17 }; +static const unsigned gpio42_a_1_pins[] = { AB8540_PIN_D12 }; +static const unsigned gpio43_a_1_pins[] = { AB8540_PIN_P4 }; +static const unsigned gpio44_a_1_pins[] = { AB8540_PIN_AB1 }; +static const unsigned gpio45_a_1_pins[] = { AB8540_PIN_K7 }; +static const unsigned gpio46_a_1_pins[] = { AB8540_PIN_L7 }; +static const unsigned gpio47_a_1_pins[] = { AB8540_PIN_G10 }; +static const unsigned gpio48_a_1_pins[] = { AB8540_PIN_K12 }; +static const unsigned gpio51_a_1_pins[] = { AB8540_PIN_N8 }; +static const unsigned gpio52_a_1_pins[] = { AB8540_PIN_P12 }; +static const unsigned gpio53_a_1_pins[] = { AB8540_PIN_K8 }; +static const unsigned gpio54_a_1_pins[] = { AB8540_PIN_J11 }; +static const unsigned gpio55_a_1_pins[] = { AB8540_PIN_AC2 }; +static const unsigned gpio56_a_1_pins[] = { AB8540_PIN_AB2 }; + +#define AB8540_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins, \ + .npins = ARRAY_SIZE(a##_pins), .altsetting = b } + +static const struct abx500_pingroup ab8540_groups[] = { + /* default column */ + AB8540_PIN_GROUP(sysclkreq2_d_1, ABX500_DEFAULT), + AB8540_PIN_GROUP(sysclkreq3_d_1, ABX500_DEFAULT), + AB8540_PIN_GROUP(sysclkreq4_d_1, ABX500_DEFAULT), + AB8540_PIN_GROUP(sysclkreq6_d_1, ABX500_DEFAULT), + AB8540_PIN_GROUP(pwmout1_d_1, ABX500_DEFAULT), + AB8540_PIN_GROUP(pwmout2_d_1, ABX500_DEFAULT), + AB8540_PIN_GROUP(pwmout3_d_1, ABX500_DEFAULT), + AB8540_PIN_GROUP(adi1_d_1, ABX500_DEFAULT), + AB8540_PIN_GROUP(dmic12_d_1, ABX500_DEFAULT), + AB8540_PIN_GROUP(dmic34_d_1, ABX500_DEFAULT), + AB8540_PIN_GROUP(dmic56_d_1, ABX500_DEFAULT), + AB8540_PIN_GROUP(sysclkreq5_d_1, ABX500_DEFAULT), + AB8540_PIN_GROUP(batremn_d_1, ABX500_DEFAULT), + AB8540_PIN_GROUP(service_d_1, ABX500_DEFAULT), + AB8540_PIN_GROUP(pwrctrl0_d_1, ABX500_DEFAULT), + AB8540_PIN_GROUP(pwrctrl1_d_1, ABX500_DEFAULT), + AB8540_PIN_GROUP(pwmextvibra1_d_1, ABX500_DEFAULT), + AB8540_PIN_GROUP(pwmextvibra2_d_1, ABX500_DEFAULT), + AB8540_PIN_GROUP(gpio1_vbat_d_1, ABX500_DEFAULT), + AB8540_PIN_GROUP(gpio2_vbat_d_1, ABX500_DEFAULT), + AB8540_PIN_GROUP(gpio3_vbat_d_1, ABX500_DEFAULT), + AB8540_PIN_GROUP(gpio4_vbat_d_1, ABX500_DEFAULT), + AB8540_PIN_GROUP(pdmclkdat_d_1, ABX500_DEFAULT), + /* Altfunction A column */ + AB8540_PIN_GROUP(gpio1_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio2_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio3_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio4_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio14_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio15_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio16_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio17_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio18_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio19_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio20_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio27_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio28_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio29_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio30_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio31_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio32_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio42_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio43_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio44_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio45_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio46_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio47_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio48_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio51_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio52_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio53_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio54_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio55_a_1, ABX500_ALT_A), + AB8540_PIN_GROUP(gpio56_a_1, ABX500_ALT_A), +}; + +/* We use this macro to define the groups applicable to a function */ +#define AB8540_FUNC_GROUPS(a, b...) \ +static const char * const a##_groups[] = { b }; + +AB8540_FUNC_GROUPS(sysclkreq, "sysclkreq2_d_1", "sysclkreq3_d_1", + "sysclkreq4_d_1", "sysclkreq5_d_1", "sysclkreq6_d_1"); +AB8540_FUNC_GROUPS(gpio, "gpio1_a_1", "gpio2_a_1", "gpio3_a_1", "gpio4_a_1", + "gpio14_a_1", "gpio15_a_1", "gpio16_a_1", "gpio17_a_1", + "gpio18_a_1", "gpio19_a_1", "gpio20_a_1", "gpio27_a_1", + "gpio28_a_1", "gpio29_a_1", "gpio30_a_1", "gpio31_a_1", + "gpio32_a_1", "gpio42_a_1", "gpio43_a_1", "gpio44_a_1", + "gpio45_a_1", "gpio46_a_1", "gpio47_a_1", "gpio48_a_1", + "gpio51_a_1", "gpio52_a_1", "gpio53_a_1", "gpio54_a_1", + "gpio55_a_1", "gpio56_a_1"); +AB8540_FUNC_GROUPS(pwmout, "pwmout1_d_1", "pwmout2_d_1", "pwmout3_d_1"); +AB8540_FUNC_GROUPS(adi1, "adi1_d_1"); +AB8540_FUNC_GROUPS(dmic, "dmic12_d_1", "dmic34_d_1", "dmic56_d_1"); +AB8540_FUNC_GROUPS(batremn, "batremn_d_1"); +AB8540_FUNC_GROUPS(service, "service_d_1"); +AB8540_FUNC_GROUPS(pwrctrl, "pwrctrl0_d_1", "pwrctrl1_d_1"); +AB8540_FUNC_GROUPS(pwmextvibra, "pwmextvibra1_d_1", "pwmextvibra2_d_1"); +AB8540_FUNC_GROUPS(gpio_vbat, "gpio1_vbat_d_1", "gpio2_vbat_d_1", + "gpio3_vbat_d_1", "gpio4_vbat_d_1"); +AB8540_FUNC_GROUPS(pdm, "pdmclkdat_d_1"); + +#define FUNCTION(fname) \ + { \ + .name = #fname, \ + .groups = fname##_groups, \ + .ngroups = ARRAY_SIZE(fname##_groups), \ + } + +static const struct abx500_function ab8540_functions[] = { + FUNCTION(sysclkreq), + FUNCTION(gpio), + FUNCTION(pwmout), + FUNCTION(adi1), + FUNCTION(dmic), + FUNCTION(batremn), + FUNCTION(service), + FUNCTION(pwrctrl), + FUNCTION(pwmextvibra), + FUNCTION(gpio_vbat), + FUNCTION(pdm), +}; + +/* + * this table translates what's is in the AB8540 specification regarding the + * balls alternate functions (as for DB, default, ALT_A, ALT_B and ALT_C). + * ALTERNATE_FUNCTIONS(GPIO_NUMBER, GPIOSEL bit, ALTERNATFUNC bit1, + * ALTERNATEFUNC bit2, ALTA val, ALTB val, ALTC val), + * AB8540 only supports DEFAULT and ALTA functions, so ALTERNATFUNC + * registers is not used + * + */ + +static struct +alternate_functions ab8540_alternate_functions[AB8540_GPIO_MAX_NUMBER + 1] = { + /* GPIOSEL1 - bit 4-7 reserved */ + ALTERNATE_FUNCTIONS(0, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO0 */ + ALTERNATE_FUNCTIONS(1, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO1, altA controlled by bit 0 */ + ALTERNATE_FUNCTIONS(2, 1, UNUSED, UNUSED, 0, 0, 0), /* GPIO2, altA controlled by bit 1 */ + ALTERNATE_FUNCTIONS(3, 2, UNUSED, UNUSED, 0, 0, 0), /* GPIO3, altA controlled by bit 2*/ + ALTERNATE_FUNCTIONS(4, 3, UNUSED, UNUSED, 0, 0, 0), /* GPIO4, altA controlled by bit 3*/ + ALTERNATE_FUNCTIONS(5, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO5 */ + ALTERNATE_FUNCTIONS(6, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO6 */ + ALTERNATE_FUNCTIONS(7, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO7 */ + ALTERNATE_FUNCTIONS(8, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO8 */ + /* GPIOSEL2 - bit 0-4 reserved */ + ALTERNATE_FUNCTIONS(9, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO9 */ + ALTERNATE_FUNCTIONS(10, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO10 */ + ALTERNATE_FUNCTIONS(11, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO11 */ + ALTERNATE_FUNCTIONS(12, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO12 */ + ALTERNATE_FUNCTIONS(13, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO13 */ + ALTERNATE_FUNCTIONS(14, 5, UNUSED, UNUSED, 0, 0, 0), /* GPIO14, altA controlled by bit 5 */ + ALTERNATE_FUNCTIONS(15, 6, UNUSED, UNUSED, 0, 0, 0), /* GPIO15, altA controlled by bit 6 */ + ALTERNATE_FUNCTIONS(16, 7, UNUSED, UNUSED, 0, 0, 0), /* GPIO16, altA controlled by bit 7 */ + /* GPIOSEL3 - bit 4-7 reserved */ + ALTERNATE_FUNCTIONS(17, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO17, altA controlled by bit 0 */ + ALTERNATE_FUNCTIONS(18, 1, UNUSED, UNUSED, 0, 0, 0), /* GPIO18, altA controlled by bit 1 */ + ALTERNATE_FUNCTIONS(19, 2, UNUSED, UNUSED, 0, 0, 0), /* GPIO19, altA controlled by bit 2 */ + ALTERNATE_FUNCTIONS(20, 3, UNUSED, UNUSED, 0, 0, 0), /* GPIO20, altA controlled by bit 3 */ + ALTERNATE_FUNCTIONS(21, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO21 */ + ALTERNATE_FUNCTIONS(22, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO22 */ + ALTERNATE_FUNCTIONS(23, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO23 */ + ALTERNATE_FUNCTIONS(24, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO24 */ + /* GPIOSEL4 - bit 0-1 reserved */ + ALTERNATE_FUNCTIONS(25, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO25 */ + ALTERNATE_FUNCTIONS(26, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO26 */ + ALTERNATE_FUNCTIONS(27, 2, UNUSED, UNUSED, 0, 0, 0), /* GPIO27, altA controlled by bit 2 */ + ALTERNATE_FUNCTIONS(28, 3, UNUSED, UNUSED, 0, 0, 0), /* GPIO28, altA controlled by bit 3 */ + ALTERNATE_FUNCTIONS(29, 4, UNUSED, UNUSED, 0, 0, 0), /* GPIO29, altA controlled by bit 4 */ + ALTERNATE_FUNCTIONS(30, 5, UNUSED, UNUSED, 0, 0, 0), /* GPIO30, altA controlled by bit 5 */ + ALTERNATE_FUNCTIONS(31, 6, UNUSED, UNUSED, 0, 0, 0), /* GPIO31, altA controlled by bit 6 */ + ALTERNATE_FUNCTIONS(32, 7, UNUSED, UNUSED, 0, 0, 0), /* GPIO32, altA controlled by bit 7 */ + /* GPIOSEL5 - bit 0-7 reserved */ + ALTERNATE_FUNCTIONS(33, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO33 */ + ALTERNATE_FUNCTIONS(34, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO34 */ + ALTERNATE_FUNCTIONS(35, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO35 */ + ALTERNATE_FUNCTIONS(36, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO36 */ + ALTERNATE_FUNCTIONS(37, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO37 */ + ALTERNATE_FUNCTIONS(38, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO38 */ + ALTERNATE_FUNCTIONS(39, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO39 */ + ALTERNATE_FUNCTIONS(40, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO40 */ + /* GPIOSEL6 - bit 0 reserved */ + ALTERNATE_FUNCTIONS(41, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO41 */ + ALTERNATE_FUNCTIONS(42, 1, UNUSED, UNUSED, 0, 0, 0), /* GPIO42, altA controlled by bit 1 */ + ALTERNATE_FUNCTIONS(43, 2, UNUSED, UNUSED, 0, 0, 0), /* GPIO43, altA controlled by bit 2 */ + ALTERNATE_FUNCTIONS(44, 3, UNUSED, UNUSED, 0, 0, 0), /* GPIO44, altA controlled by bit 3 */ + ALTERNATE_FUNCTIONS(45, 4, UNUSED, UNUSED, 0, 0, 0), /* GPIO45, altA controlled by bit 4 */ + ALTERNATE_FUNCTIONS(46, 5, UNUSED, UNUSED, 0, 0, 0), /* GPIO46, altA controlled by bit 5 */ + ALTERNATE_FUNCTIONS(47, 6, UNUSED, UNUSED, 0, 0, 0), /* GPIO47, altA controlled by bit 6 */ + ALTERNATE_FUNCTIONS(48, 7, UNUSED, UNUSED, 0, 0, 0), /* GPIO48, altA controlled by bit 7 */ + /* GPIOSEL7 - bit 0-1 reserved */ + ALTERNATE_FUNCTIONS(49, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO49 */ + ALTERNATE_FUNCTIONS(50, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO50 */ + ALTERNATE_FUNCTIONS(51, 2, UNUSED, UNUSED, 0, 0, 0), /* GPIO51, altA controlled by bit 2 */ + ALTERNATE_FUNCTIONS(52, 3, UNUSED, UNUSED, 0, 0, 0), /* GPIO52, altA controlled by bit 3 */ + ALTERNATE_FUNCTIONS(53, 4, UNUSED, UNUSED, 0, 0, 0), /* GPIO53, altA controlled by bit 4 */ + ALTERNATE_FUNCTIONS(54, 5, UNUSED, UNUSED, 0, 0, 0), /* GPIO54, altA controlled by bit 5 */ + ALTERNATE_FUNCTIONS(55, 6, UNUSED, UNUSED, 0, 0, 0), /* GPIO55, altA controlled by bit 6 */ + ALTERNATE_FUNCTIONS(56, 7, UNUSED, UNUSED, 0, 0, 0), /* GPIO56, altA controlled by bit 7 */ +}; + +static struct pullud ab8540_pullud = { + .first_pin = 51, /* GPIO1_VBAT */ + .last_pin = 54, /* GPIO4_VBAT */ +}; + +/* + * For AB8540 Only some GPIOs are interrupt capable: + * GPIO43 to GPIO44 + * GPIO51 to GPIO54 + */ +static struct abx500_gpio_irq_cluster ab8540_gpio_irq_cluster[] = { + GPIO_IRQ_CLUSTER(43, 43, AB8540_INT_GPIO43F), + GPIO_IRQ_CLUSTER(44, 44, AB8540_INT_GPIO44F), + GPIO_IRQ_CLUSTER(51, 54, AB9540_INT_GPIO51R), +}; + +static struct abx500_pinctrl_soc_data ab8540_soc = { + .gpio_ranges = ab8540_pinranges, + .gpio_num_ranges = ARRAY_SIZE(ab8540_pinranges), + .pins = ab8540_pins, + .npins = ARRAY_SIZE(ab8540_pins), + .functions = ab8540_functions, + .nfunctions = ARRAY_SIZE(ab8540_functions), + .groups = ab8540_groups, + .ngroups = ARRAY_SIZE(ab8540_groups), + .alternate_functions = ab8540_alternate_functions, + .pullud = &ab8540_pullud, + .gpio_irq_cluster = ab8540_gpio_irq_cluster, + .ngpio_irq_cluster = ARRAY_SIZE(ab8540_gpio_irq_cluster), + .irq_gpio_rising_offset = AB8540_INT_GPIO43R, + .irq_gpio_falling_offset = AB8540_INT_GPIO43F, + .irq_gpio_factor = 2, +}; + +void +abx500_pinctrl_ab8540_init(struct abx500_pinctrl_soc_data **soc) +{ + *soc = &ab8540_soc; +} diff --git a/drivers/pinctrl/nomadik/pinctrl-ab9540.c b/drivers/pinctrl/nomadik/pinctrl-ab9540.c new file mode 100644 index 000000000000..1a281ca95dac --- /dev/null +++ b/drivers/pinctrl/nomadik/pinctrl-ab9540.c @@ -0,0 +1,486 @@ +/* + * Copyright (C) ST-Ericsson SA 2012 + * + * Author: Patrice Chotard <patrice.chotard@stericsson.com> for ST-Ericsson. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/gpio.h> +#include <linux/pinctrl/pinctrl.h> +#include <linux/mfd/abx500/ab8500.h> +#include "pinctrl-abx500.h" + +/* All the pins that can be used for GPIO and some other functions */ +#define ABX500_GPIO(offset) (offset) + +#define AB9540_PIN_R4 ABX500_GPIO(1) +#define AB9540_PIN_V3 ABX500_GPIO(2) +#define AB9540_PIN_T4 ABX500_GPIO(3) +#define AB9540_PIN_T5 ABX500_GPIO(4) +/* hole */ +#define AB9540_PIN_B18 ABX500_GPIO(10) +#define AB9540_PIN_C18 ABX500_GPIO(11) +/* hole */ +#define AB9540_PIN_D18 ABX500_GPIO(13) +#define AB9540_PIN_B19 ABX500_GPIO(14) +#define AB9540_PIN_C19 ABX500_GPIO(15) +#define AB9540_PIN_D19 ABX500_GPIO(16) +#define AB9540_PIN_R3 ABX500_GPIO(17) +#define AB9540_PIN_T2 ABX500_GPIO(18) +#define AB9540_PIN_U2 ABX500_GPIO(19) +#define AB9540_PIN_V2 ABX500_GPIO(20) +#define AB9540_PIN_N17 ABX500_GPIO(21) +#define AB9540_PIN_N16 ABX500_GPIO(22) +#define AB9540_PIN_M19 ABX500_GPIO(23) +#define AB9540_PIN_T3 ABX500_GPIO(24) +#define AB9540_PIN_W2 ABX500_GPIO(25) +/* hole */ +#define AB9540_PIN_H4 ABX500_GPIO(27) +#define AB9540_PIN_F1 ABX500_GPIO(28) +#define AB9540_PIN_F4 ABX500_GPIO(29) +#define AB9540_PIN_F2 ABX500_GPIO(30) +#define AB9540_PIN_E4 ABX500_GPIO(31) +#define AB9540_PIN_F3 ABX500_GPIO(32) +/* hole */ +#define AB9540_PIN_J13 ABX500_GPIO(34) +/* hole */ +#define AB9540_PIN_L17 ABX500_GPIO(40) +#define AB9540_PIN_L16 ABX500_GPIO(41) +#define AB9540_PIN_W3 ABX500_GPIO(42) +#define AB9540_PIN_N4 ABX500_GPIO(50) +#define AB9540_PIN_G12 ABX500_GPIO(51) +#define AB9540_PIN_E17 ABX500_GPIO(52) +#define AB9540_PIN_D11 ABX500_GPIO(53) +#define AB9540_PIN_M18 ABX500_GPIO(54) + +/* indicates the highest GPIO number */ +#define AB9540_GPIO_MAX_NUMBER 54 + +/* + * The names of the pins are denoted by GPIO number and ball name, even + * though they can be used for other things than GPIO, this is the first + * column in the table of the data sheet and often used on schematics and + * such. + */ +static const struct pinctrl_pin_desc ab9540_pins[] = { + PINCTRL_PIN(AB9540_PIN_R4, "GPIO1_R4"), + PINCTRL_PIN(AB9540_PIN_V3, "GPIO2_V3"), + PINCTRL_PIN(AB9540_PIN_T4, "GPIO3_T4"), + PINCTRL_PIN(AB9540_PIN_T5, "GPIO4_T5"), + /* hole */ + PINCTRL_PIN(AB9540_PIN_B18, "GPIO10_B18"), + PINCTRL_PIN(AB9540_PIN_C18, "GPIO11_C18"), + /* hole */ + PINCTRL_PIN(AB9540_PIN_D18, "GPIO13_D18"), + PINCTRL_PIN(AB9540_PIN_B19, "GPIO14_B19"), + PINCTRL_PIN(AB9540_PIN_C19, "GPIO15_C19"), + PINCTRL_PIN(AB9540_PIN_D19, "GPIO16_D19"), + PINCTRL_PIN(AB9540_PIN_R3, "GPIO17_R3"), + PINCTRL_PIN(AB9540_PIN_T2, "GPIO18_T2"), + PINCTRL_PIN(AB9540_PIN_U2, "GPIO19_U2"), + PINCTRL_PIN(AB9540_PIN_V2, "GPIO20_V2"), + PINCTRL_PIN(AB9540_PIN_N17, "GPIO21_N17"), + PINCTRL_PIN(AB9540_PIN_N16, "GPIO22_N16"), + PINCTRL_PIN(AB9540_PIN_M19, "GPIO23_M19"), + PINCTRL_PIN(AB9540_PIN_T3, "GPIO24_T3"), + PINCTRL_PIN(AB9540_PIN_W2, "GPIO25_W2"), + /* hole */ + PINCTRL_PIN(AB9540_PIN_H4, "GPIO27_H4"), + PINCTRL_PIN(AB9540_PIN_F1, "GPIO28_F1"), + PINCTRL_PIN(AB9540_PIN_F4, "GPIO29_F4"), + PINCTRL_PIN(AB9540_PIN_F2, "GPIO30_F2"), + PINCTRL_PIN(AB9540_PIN_E4, "GPIO31_E4"), + PINCTRL_PIN(AB9540_PIN_F3, "GPIO32_F3"), + /* hole */ + PINCTRL_PIN(AB9540_PIN_J13, "GPIO34_J13"), + /* hole */ + PINCTRL_PIN(AB9540_PIN_L17, "GPIO40_L17"), + PINCTRL_PIN(AB9540_PIN_L16, "GPIO41_L16"), + PINCTRL_PIN(AB9540_PIN_W3, "GPIO42_W3"), + PINCTRL_PIN(AB9540_PIN_N4, "GPIO50_N4"), + PINCTRL_PIN(AB9540_PIN_G12, "GPIO51_G12"), + PINCTRL_PIN(AB9540_PIN_E17, "GPIO52_E17"), + PINCTRL_PIN(AB9540_PIN_D11, "GPIO53_D11"), + PINCTRL_PIN(AB9540_PIN_M18, "GPIO60_M18"), +}; + +/* + * Maps local GPIO offsets to local pin numbers + */ +static const struct abx500_pinrange ab9540_pinranges[] = { + ABX500_PINRANGE(1, 4, ABX500_ALT_A), + ABX500_PINRANGE(10, 2, ABX500_DEFAULT), + ABX500_PINRANGE(13, 1, ABX500_DEFAULT), + ABX500_PINRANGE(14, 12, ABX500_ALT_A), + ABX500_PINRANGE(27, 6, ABX500_ALT_A), + ABX500_PINRANGE(34, 1, ABX500_ALT_A), + ABX500_PINRANGE(40, 3, ABX500_ALT_A), + ABX500_PINRANGE(50, 1, ABX500_DEFAULT), + ABX500_PINRANGE(51, 3, ABX500_ALT_A), + ABX500_PINRANGE(54, 1, ABX500_DEFAULT), +}; + +/* + * Read the pin group names like this: + * sysclkreq2_d_1 = first groups of pins for sysclkreq2 on default function + * + * The groups are arranged as sets per altfunction column, so we can + * mux in one group at a time by selecting the same altfunction for them + * all. When functions require pins on different altfunctions, you need + * to combine several groups. + */ + +/* default column */ +static const unsigned sysclkreq2_d_1_pins[] = { AB9540_PIN_R4 }; +static const unsigned sysclkreq3_d_1_pins[] = { AB9540_PIN_V3 }; +static const unsigned sysclkreq4_d_1_pins[] = { AB9540_PIN_T4 }; +static const unsigned sysclkreq6_d_1_pins[] = { AB9540_PIN_T5 }; +static const unsigned gpio10_d_1_pins[] = { AB9540_PIN_B18 }; +static const unsigned gpio11_d_1_pins[] = { AB9540_PIN_C18 }; +static const unsigned gpio13_d_1_pins[] = { AB9540_PIN_D18 }; +static const unsigned pwmout1_d_1_pins[] = { AB9540_PIN_B19 }; +static const unsigned pwmout2_d_1_pins[] = { AB9540_PIN_C19 }; +static const unsigned pwmout3_d_1_pins[] = { AB9540_PIN_D19 }; +/* audio data interface 1*/ +static const unsigned adi1_d_1_pins[] = { AB9540_PIN_R3, AB9540_PIN_T2, + AB9540_PIN_U2, AB9540_PIN_V2 }; +/* USBUICC */ +static const unsigned usbuicc_d_1_pins[] = { AB9540_PIN_N17, AB9540_PIN_N16, + AB9540_PIN_M19 }; +static const unsigned sysclkreq7_d_1_pins[] = { AB9540_PIN_T3 }; +static const unsigned sysclkreq8_d_1_pins[] = { AB9540_PIN_W2 }; +/* Digital microphone 1 and 2 */ +static const unsigned dmic12_d_1_pins[] = { AB9540_PIN_H4, AB9540_PIN_F1 }; +/* Digital microphone 3 and 4 */ +static const unsigned dmic34_d_1_pins[] = { AB9540_PIN_F4, AB9540_PIN_F2 }; +/* Digital microphone 5 and 6 */ +static const unsigned dmic56_d_1_pins[] = { AB9540_PIN_E4, AB9540_PIN_F3 }; +static const unsigned extcpena_d_1_pins[] = { AB9540_PIN_J13 }; +/* modem SDA/SCL */ +static const unsigned modsclsda_d_1_pins[] = { AB9540_PIN_L17, AB9540_PIN_L16 }; +static const unsigned sysclkreq5_d_1_pins[] = { AB9540_PIN_W3 }; +static const unsigned gpio50_d_1_pins[] = { AB9540_PIN_N4 }; +static const unsigned batremn_d_1_pins[] = { AB9540_PIN_G12 }; +static const unsigned resethw_d_1_pins[] = { AB9540_PIN_E17 }; +static const unsigned service_d_1_pins[] = { AB9540_PIN_D11 }; +static const unsigned gpio60_d_1_pins[] = { AB9540_PIN_M18 }; + +/* Altfunction A column */ +static const unsigned gpio1_a_1_pins[] = { AB9540_PIN_R4 }; +static const unsigned gpio2_a_1_pins[] = { AB9540_PIN_V3 }; +static const unsigned gpio3_a_1_pins[] = { AB9540_PIN_T4 }; +static const unsigned gpio4_a_1_pins[] = { AB9540_PIN_T5 }; +static const unsigned hiqclkena_a_1_pins[] = { AB9540_PIN_B18 }; +static const unsigned pdmclk_a_1_pins[] = { AB9540_PIN_C18 }; +static const unsigned uartdata_a_1_pins[] = { AB9540_PIN_D18, AB9540_PIN_N4 }; +static const unsigned gpio14_a_1_pins[] = { AB9540_PIN_B19 }; +static const unsigned gpio15_a_1_pins[] = { AB9540_PIN_C19 }; +static const unsigned gpio16_a_1_pins[] = { AB9540_PIN_D19 }; +static const unsigned gpio17_a_1_pins[] = { AB9540_PIN_R3 }; +static const unsigned gpio18_a_1_pins[] = { AB9540_PIN_T2 }; +static const unsigned gpio19_a_1_pins[] = { AB9540_PIN_U2 }; +static const unsigned gpio20_a_1_pins[] = { AB9540_PIN_V2 }; +static const unsigned gpio21_a_1_pins[] = { AB9540_PIN_N17 }; +static const unsigned gpio22_a_1_pins[] = { AB9540_PIN_N16 }; +static const unsigned gpio23_a_1_pins[] = { AB9540_PIN_M19 }; +static const unsigned gpio24_a_1_pins[] = { AB9540_PIN_T3 }; +static const unsigned gpio25_a_1_pins[] = { AB9540_PIN_W2 }; +static const unsigned gpio27_a_1_pins[] = { AB9540_PIN_H4 }; +static const unsigned gpio28_a_1_pins[] = { AB9540_PIN_F1 }; +static const unsigned gpio29_a_1_pins[] = { AB9540_PIN_F4 }; +static const unsigned gpio30_a_1_pins[] = { AB9540_PIN_F2 }; +static const unsigned gpio31_a_1_pins[] = { AB9540_PIN_E4 }; +static const unsigned gpio32_a_1_pins[] = { AB9540_PIN_F3 }; +static const unsigned gpio34_a_1_pins[] = { AB9540_PIN_J13 }; +static const unsigned gpio40_a_1_pins[] = { AB9540_PIN_L17 }; +static const unsigned gpio41_a_1_pins[] = { AB9540_PIN_L16 }; +static const unsigned gpio42_a_1_pins[] = { AB9540_PIN_W3 }; +static const unsigned gpio51_a_1_pins[] = { AB9540_PIN_G12 }; +static const unsigned gpio52_a_1_pins[] = { AB9540_PIN_E17 }; +static const unsigned gpio53_a_1_pins[] = { AB9540_PIN_D11 }; +static const unsigned usbuiccpd_a_1_pins[] = { AB9540_PIN_M18 }; + +/* Altfunction B colum */ +static const unsigned pdmdata_b_1_pins[] = { AB9540_PIN_B18 }; +static const unsigned pwmextvibra1_b_1_pins[] = { AB9540_PIN_D18 }; +static const unsigned pwmextvibra2_b_1_pins[] = { AB9540_PIN_N4 }; + +/* Altfunction C column */ +static const unsigned usbvdat_c_1_pins[] = { AB9540_PIN_D18 }; + +#define AB9540_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins, \ + .npins = ARRAY_SIZE(a##_pins), .altsetting = b } + +static const struct abx500_pingroup ab9540_groups[] = { + /* default column */ + AB9540_PIN_GROUP(sysclkreq2_d_1, ABX500_DEFAULT), + AB9540_PIN_GROUP(sysclkreq3_d_1, ABX500_DEFAULT), + AB9540_PIN_GROUP(sysclkreq4_d_1, ABX500_DEFAULT), + AB9540_PIN_GROUP(sysclkreq6_d_1, ABX500_DEFAULT), + AB9540_PIN_GROUP(gpio10_d_1, ABX500_DEFAULT), + AB9540_PIN_GROUP(gpio11_d_1, ABX500_DEFAULT), + AB9540_PIN_GROUP(gpio13_d_1, ABX500_DEFAULT), + AB9540_PIN_GROUP(pwmout1_d_1, ABX500_DEFAULT), + AB9540_PIN_GROUP(pwmout2_d_1, ABX500_DEFAULT), + AB9540_PIN_GROUP(pwmout3_d_1, ABX500_DEFAULT), + AB9540_PIN_GROUP(adi1_d_1, ABX500_DEFAULT), + AB9540_PIN_GROUP(usbuicc_d_1, ABX500_DEFAULT), + AB9540_PIN_GROUP(sysclkreq7_d_1, ABX500_DEFAULT), + AB9540_PIN_GROUP(sysclkreq8_d_1, ABX500_DEFAULT), + AB9540_PIN_GROUP(dmic12_d_1, ABX500_DEFAULT), + AB9540_PIN_GROUP(dmic34_d_1, ABX500_DEFAULT), + AB9540_PIN_GROUP(dmic56_d_1, ABX500_DEFAULT), + AB9540_PIN_GROUP(extcpena_d_1, ABX500_DEFAULT), + AB9540_PIN_GROUP(modsclsda_d_1, ABX500_DEFAULT), + AB9540_PIN_GROUP(sysclkreq5_d_1, ABX500_DEFAULT), + AB9540_PIN_GROUP(gpio50_d_1, ABX500_DEFAULT), + AB9540_PIN_GROUP(batremn_d_1, ABX500_DEFAULT), + AB9540_PIN_GROUP(resethw_d_1, ABX500_DEFAULT), + AB9540_PIN_GROUP(service_d_1, ABX500_DEFAULT), + AB9540_PIN_GROUP(gpio60_d_1, ABX500_DEFAULT), + + /* Altfunction A column */ + AB9540_PIN_GROUP(gpio1_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio2_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio3_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio4_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(hiqclkena_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(pdmclk_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(uartdata_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio14_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio15_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio16_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio17_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio18_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio19_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio20_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio21_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio22_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio23_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio24_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio25_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio27_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio28_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio29_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio30_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio31_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio32_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio34_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio40_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio41_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio42_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio51_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio52_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(gpio53_a_1, ABX500_ALT_A), + AB9540_PIN_GROUP(usbuiccpd_a_1, ABX500_ALT_A), + + /* Altfunction B column */ + AB9540_PIN_GROUP(pdmdata_b_1, ABX500_ALT_B), + AB9540_PIN_GROUP(pwmextvibra1_b_1, ABX500_ALT_B), + AB9540_PIN_GROUP(pwmextvibra2_b_1, ABX500_ALT_B), + + /* Altfunction C column */ + AB9540_PIN_GROUP(usbvdat_c_1, ABX500_ALT_C), +}; + +/* We use this macro to define the groups applicable to a function */ +#define AB9540_FUNC_GROUPS(a, b...) \ +static const char * const a##_groups[] = { b }; + +AB9540_FUNC_GROUPS(sysclkreq, "sysclkreq2_d_1", "sysclkreq3_d_1", + "sysclkreq4_d_1", "sysclkreq5_d_1", "sysclkreq6_d_1", + "sysclkreq7_d_1", "sysclkreq8_d_1"); +AB9540_FUNC_GROUPS(gpio, "gpio1_a_1", "gpio2_a_1", "gpio3_a_1", "gpio4_a_1", + "gpio10_d_1", "gpio11_d_1", "gpio13_d_1", "gpio14_a_1", + "gpio15_a_1", "gpio16_a_1", "gpio17_a_1", "gpio18_a_1", + "gpio19_a_1", "gpio20_a_1", "gpio21_a_1", "gpio22_a_1", + "gpio23_a_1", "gpio24_a_1", "gpio25_a_1", "gpio27_a_1", + "gpio28_a_1", "gpio29_a_1", "gpio30_a_1", "gpio31_a_1", + "gpio32_a_1", "gpio34_a_1", "gpio40_a_1", "gpio41_a_1", + "gpio42_a_1", "gpio50_d_1", "gpio51_a_1", "gpio52_a_1", + "gpio53_a_1", "gpio60_d_1"); +AB9540_FUNC_GROUPS(pwmout, "pwmout1_d_1", "pwmout2_d_1", "pwmout3_d_1"); +AB9540_FUNC_GROUPS(adi1, "adi1_d_1"); +AB9540_FUNC_GROUPS(usbuicc, "usbuicc_d_1", "usbuiccpd_a_1"); +AB9540_FUNC_GROUPS(dmic, "dmic12_d_1", "dmic34_d_1", "dmic56_d_1"); +AB9540_FUNC_GROUPS(extcpena, "extcpena_d_1"); +AB9540_FUNC_GROUPS(modsclsda, "modsclsda_d_1"); +AB9540_FUNC_GROUPS(batremn, "batremn_d_1"); +AB9540_FUNC_GROUPS(resethw, "resethw_d_1"); +AB9540_FUNC_GROUPS(service, "service_d_1"); +AB9540_FUNC_GROUPS(hiqclkena, "hiqclkena_a_1"); +AB9540_FUNC_GROUPS(pdm, "pdmdata_b_1", "pdmclk_a_1"); +AB9540_FUNC_GROUPS(uartdata, "uartdata_a_1"); +AB9540_FUNC_GROUPS(pwmextvibra, "pwmextvibra1_b_1", "pwmextvibra2_b_1"); +AB9540_FUNC_GROUPS(usbvdat, "usbvdat_c_1"); + +#define FUNCTION(fname) \ + { \ + .name = #fname, \ + .groups = fname##_groups, \ + .ngroups = ARRAY_SIZE(fname##_groups), \ + } + +static const struct abx500_function ab9540_functions[] = { + FUNCTION(sysclkreq), + FUNCTION(gpio), + FUNCTION(pwmout), + FUNCTION(adi1), + FUNCTION(usbuicc), + FUNCTION(dmic), + FUNCTION(extcpena), + FUNCTION(modsclsda), + FUNCTION(batremn), + FUNCTION(resethw), + FUNCTION(service), + FUNCTION(hiqclkena), + FUNCTION(pdm), + FUNCTION(uartdata), + FUNCTION(pwmextvibra), + FUNCTION(usbvdat), +}; + +/* + * this table translates what's is in the AB9540 specification regarding the + * balls alternate functions (as for DB, default, ALT_A, ALT_B and ALT_C). + * ALTERNATE_FUNCTIONS(GPIO_NUMBER, GPIOSEL bit, ALTERNATFUNC bit1, + * ALTERNATEFUNC bit2, ALTA val, ALTB val, ALTC val), + * + * example : + * + * ALTERNATE_FUNCTIONS(13, 4, 3, 4, 1, 0, 2), + * means that pin AB9540_PIN_D18 (pin 13) supports 4 mux (default/ALT_A, + * ALT_B and ALT_C), so GPIOSEL and ALTERNATFUNC registers are used to + * select the mux. ALTA, ALTB and ALTC val indicates values to write in + * ALTERNATFUNC register. We need to specifies these values as SOC + * designers didn't apply the same logic on how to select mux in the + * ABx500 family. + * + * As this pins supports at least ALT_B mux, default mux is + * selected by writing 1 in GPIOSEL bit : + * + * | GPIOSEL bit=4 | alternatfunc bit2=4 | alternatfunc bit1=3 + * default | 1 | 0 | 0 + * alt_A | 0 | 0 | 1 + * alt_B | 0 | 0 | 0 + * alt_C | 0 | 1 | 0 + * + * ALTERNATE_FUNCTIONS(1, 0, UNUSED, UNUSED), + * means that pin AB9540_PIN_R4 (pin 1) supports 2 mux, so only GPIOSEL + * register is used to select the mux. As this pins doesn't support at + * least ALT_B mux, default mux is by writing 0 in GPIOSEL bit : + * + * | GPIOSEL bit=0 | alternatfunc bit2= | alternatfunc bit1= + * default | 0 | 0 | 0 + * alt_A | 1 | 0 | 0 + */ + +static struct +alternate_functions ab9540alternate_functions[AB9540_GPIO_MAX_NUMBER + 1] = { + /* GPIOSEL1 - bits 4-7 are reserved */ + ALTERNATE_FUNCTIONS(0, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO0 */ + ALTERNATE_FUNCTIONS(1, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO1, altA controlled by bit 0 */ + ALTERNATE_FUNCTIONS(2, 1, UNUSED, UNUSED, 0, 0, 0), /* GPIO2, altA controlled by bit 1 */ + ALTERNATE_FUNCTIONS(3, 2, UNUSED, UNUSED, 0, 0, 0), /* GPIO3, altA controlled by bit 2*/ + ALTERNATE_FUNCTIONS(4, 3, UNUSED, UNUSED, 0, 0, 0), /* GPIO4, altA controlled by bit 3*/ + ALTERNATE_FUNCTIONS(5, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO5 */ + ALTERNATE_FUNCTIONS(6, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO6 */ + ALTERNATE_FUNCTIONS(7, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO7 */ + ALTERNATE_FUNCTIONS(8, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO8 */ + /* GPIOSEL2 - bits 0 and 3 are reserved */ + ALTERNATE_FUNCTIONS(9, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO9 */ + ALTERNATE_FUNCTIONS(10, 1, 0, UNUSED, 1, 0, 0), /* GPIO10, altA and altB controlled by bit 0 */ + ALTERNATE_FUNCTIONS(11, 2, 1, UNUSED, 0, 0, 0), /* GPIO11, altA controlled by bit 1 */ + ALTERNATE_FUNCTIONS(12, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO12 */ + ALTERNATE_FUNCTIONS(13, 4, 3, 4, 1, 0, 2), /* GPIO13, altA altB and altC controlled by bit 3 and 4 */ + ALTERNATE_FUNCTIONS(14, 5, UNUSED, UNUSED, 0, 0, 0), /* GPIO14, altA controlled by bit 5 */ + ALTERNATE_FUNCTIONS(15, 6, UNUSED, UNUSED, 0, 0, 0), /* GPIO15, altA controlled by bit 6 */ + ALTERNATE_FUNCTIONS(16, 7, UNUSED, UNUSED, 0, 0, 0), /* GPIO16, altA controlled by bit 7 */ + /* GPIOSEL3 - bit 1-3 reserved + * pins 17 to 20 are special case, only bit 0 is used to select + * alternate function for these 4 pins. + * bits 1 to 3 are reserved + */ + ALTERNATE_FUNCTIONS(17, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO17, altA controlled by bit 0 */ + ALTERNATE_FUNCTIONS(18, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO18, altA controlled by bit 0 */ + ALTERNATE_FUNCTIONS(19, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO19, altA controlled by bit 0 */ + ALTERNATE_FUNCTIONS(20, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO20, altA controlled by bit 0 */ + ALTERNATE_FUNCTIONS(21, 4, UNUSED, UNUSED, 0, 0, 0), /* GPIO21, altA controlled by bit 4 */ + ALTERNATE_FUNCTIONS(22, 5, UNUSED, UNUSED, 0, 0, 0), /* GPIO22, altA controlled by bit 5 */ + ALTERNATE_FUNCTIONS(23, 6, UNUSED, UNUSED, 0, 0, 0), /* GPIO23, altA controlled by bit 6 */ + ALTERNATE_FUNCTIONS(24, 7, UNUSED, UNUSED, 0, 0, 0), /* GPIO24, altA controlled by bit 7 */ + /* GPIOSEL4 - bit 1 reserved */ + ALTERNATE_FUNCTIONS(25, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO25, altA controlled by bit 0 */ + ALTERNATE_FUNCTIONS(26, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO26 */ + ALTERNATE_FUNCTIONS(27, 2, UNUSED, UNUSED, 0, 0, 0), /* GPIO27, altA controlled by bit 2 */ + ALTERNATE_FUNCTIONS(28, 3, UNUSED, UNUSED, 0, 0, 0), /* GPIO28, altA controlled by bit 3 */ + ALTERNATE_FUNCTIONS(29, 4, UNUSED, UNUSED, 0, 0, 0), /* GPIO29, altA controlled by bit 4 */ + ALTERNATE_FUNCTIONS(30, 5, UNUSED, UNUSED, 0, 0, 0), /* GPIO30, altA controlled by bit 5 */ + ALTERNATE_FUNCTIONS(31, 6, UNUSED, UNUSED, 0, 0, 0), /* GPIO31, altA controlled by bit 6 */ + ALTERNATE_FUNCTIONS(32, 7, UNUSED, UNUSED, 0, 0, 0), /* GPIO32, altA controlled by bit 7 */ + /* GPIOSEL5 - bit 0, 2-6 are reserved */ + ALTERNATE_FUNCTIONS(33, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO33 */ + ALTERNATE_FUNCTIONS(34, 1, UNUSED, UNUSED, 0, 0, 0), /* GPIO34, altA controlled by bit 1 */ + ALTERNATE_FUNCTIONS(35, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO35 */ + ALTERNATE_FUNCTIONS(36, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO36 */ + ALTERNATE_FUNCTIONS(37, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO37 */ + ALTERNATE_FUNCTIONS(38, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO38 */ + ALTERNATE_FUNCTIONS(39, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO39 */ + ALTERNATE_FUNCTIONS(40, 7, UNUSED, UNUSED, 0, 0, 0), /* GPIO40, altA controlled by bit 7 */ + /* GPIOSEL6 - bit 2-7 are reserved */ + ALTERNATE_FUNCTIONS(41, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO41, altA controlled by bit 0 */ + ALTERNATE_FUNCTIONS(42, 1, UNUSED, UNUSED, 0, 0, 0), /* GPIO42, altA controlled by bit 1 */ + ALTERNATE_FUNCTIONS(43, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO43 */ + ALTERNATE_FUNCTIONS(44, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO44 */ + ALTERNATE_FUNCTIONS(45, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO45 */ + ALTERNATE_FUNCTIONS(46, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO46 */ + ALTERNATE_FUNCTIONS(47, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO47 */ + ALTERNATE_FUNCTIONS(48, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO48 */ + /* + * GPIOSEL7 - bit 0 and 6-7 are reserved + * special case with GPIO60, wich is located at offset 5 of gpiosel7 + * don't know why it has been called GPIO60 in AB9540 datasheet, + * GPIO54 would be logical..., so at SOC point of view we consider + * GPIO60 = GPIO54 + */ + ALTERNATE_FUNCTIONS(49, 0, UNUSED, UNUSED, 0, 0, 0), /* no GPIO49 */ + ALTERNATE_FUNCTIONS(50, 1, 2, UNUSED, 1, 0, 0), /* GPIO50, altA and altB controlled by bit 1 */ + ALTERNATE_FUNCTIONS(51, 2, UNUSED, UNUSED, 0, 0, 0), /* GPIO51, altA controlled by bit 2 */ + ALTERNATE_FUNCTIONS(52, 3, UNUSED, UNUSED, 0, 0, 0), /* GPIO52, altA controlled by bit 3 */ + ALTERNATE_FUNCTIONS(53, 4, UNUSED, UNUSED, 0, 0, 0), /* GPIO53, altA controlled by bit 4 */ + ALTERNATE_FUNCTIONS(54, 5, UNUSED, UNUSED, 0, 0, 0), /* GPIO54 = GPIO60, altA controlled by bit 5 */ +}; + +static struct abx500_gpio_irq_cluster ab9540_gpio_irq_cluster[] = { + GPIO_IRQ_CLUSTER(10, 13, AB8500_INT_GPIO10R), + GPIO_IRQ_CLUSTER(24, 25, AB8500_INT_GPIO24R), + GPIO_IRQ_CLUSTER(40, 41, AB8500_INT_GPIO40R), + GPIO_IRQ_CLUSTER(50, 54, AB9540_INT_GPIO50R), +}; + +static struct abx500_pinctrl_soc_data ab9540_soc = { + .gpio_ranges = ab9540_pinranges, + .gpio_num_ranges = ARRAY_SIZE(ab9540_pinranges), + .pins = ab9540_pins, + .npins = ARRAY_SIZE(ab9540_pins), + .functions = ab9540_functions, + .nfunctions = ARRAY_SIZE(ab9540_functions), + .groups = ab9540_groups, + .ngroups = ARRAY_SIZE(ab9540_groups), + .alternate_functions = ab9540alternate_functions, + .gpio_irq_cluster = ab9540_gpio_irq_cluster, + .ngpio_irq_cluster = ARRAY_SIZE(ab9540_gpio_irq_cluster), + .irq_gpio_rising_offset = AB8500_INT_GPIO6R, + .irq_gpio_falling_offset = AB8500_INT_GPIO6F, + .irq_gpio_factor = 1, +}; + +void +abx500_pinctrl_ab9540_init(struct abx500_pinctrl_soc_data **soc) +{ + *soc = &ab9540_soc; +} diff --git a/drivers/pinctrl/nomadik/pinctrl-abx500.c b/drivers/pinctrl/nomadik/pinctrl-abx500.c new file mode 100644 index 000000000000..a53a689a2bfa --- /dev/null +++ b/drivers/pinctrl/nomadik/pinctrl-abx500.c @@ -0,0 +1,1346 @@ +/* + * Copyright (C) ST-Ericsson SA 2013 + * + * Author: Patrice Chotard <patrice.chotard@st.com> + * License terms: GNU General Public License (GPL) version 2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/slab.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/err.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/gpio.h> +#include <linux/irq.h> +#include <linux/irqdomain.h> +#include <linux/interrupt.h> +#include <linux/bitops.h> +#include <linux/mfd/abx500.h> +#include <linux/mfd/abx500/ab8500.h> +#include <linux/pinctrl/pinctrl.h> +#include <linux/pinctrl/consumer.h> +#include <linux/pinctrl/pinmux.h> +#include <linux/pinctrl/pinconf.h> +#include <linux/pinctrl/pinconf-generic.h> +#include <linux/pinctrl/machine.h> + +#include "pinctrl-abx500.h" +#include "../core.h" +#include "../pinconf.h" + +/* + * The AB9540 and AB8540 GPIO support are extended versions + * of the AB8500 GPIO support. + * The AB9540 supports an additional (7th) register so that + * more GPIO may be configured and used. + * The AB8540 supports 4 new gpios (GPIOx_VBAT) that have + * internal pull-up and pull-down capabilities. + */ + +/* + * GPIO registers offset + * Bank: 0x10 + */ +#define AB8500_GPIO_SEL1_REG 0x00 +#define AB8500_GPIO_SEL2_REG 0x01 +#define AB8500_GPIO_SEL3_REG 0x02 +#define AB8500_GPIO_SEL4_REG 0x03 +#define AB8500_GPIO_SEL5_REG 0x04 +#define AB8500_GPIO_SEL6_REG 0x05 +#define AB9540_GPIO_SEL7_REG 0x06 + +#define AB8500_GPIO_DIR1_REG 0x10 +#define AB8500_GPIO_DIR2_REG 0x11 +#define AB8500_GPIO_DIR3_REG 0x12 +#define AB8500_GPIO_DIR4_REG 0x13 +#define AB8500_GPIO_DIR5_REG 0x14 +#define AB8500_GPIO_DIR6_REG 0x15 +#define AB9540_GPIO_DIR7_REG 0x16 + +#define AB8500_GPIO_OUT1_REG 0x20 +#define AB8500_GPIO_OUT2_REG 0x21 +#define AB8500_GPIO_OUT3_REG 0x22 +#define AB8500_GPIO_OUT4_REG 0x23 +#define AB8500_GPIO_OUT5_REG 0x24 +#define AB8500_GPIO_OUT6_REG 0x25 +#define AB9540_GPIO_OUT7_REG 0x26 + +#define AB8500_GPIO_PUD1_REG 0x30 +#define AB8500_GPIO_PUD2_REG 0x31 +#define AB8500_GPIO_PUD3_REG 0x32 +#define AB8500_GPIO_PUD4_REG 0x33 +#define AB8500_GPIO_PUD5_REG 0x34 +#define AB8500_GPIO_PUD6_REG 0x35 +#define AB9540_GPIO_PUD7_REG 0x36 + +#define AB8500_GPIO_IN1_REG 0x40 +#define AB8500_GPIO_IN2_REG 0x41 +#define AB8500_GPIO_IN3_REG 0x42 +#define AB8500_GPIO_IN4_REG 0x43 +#define AB8500_GPIO_IN5_REG 0x44 +#define AB8500_GPIO_IN6_REG 0x45 +#define AB9540_GPIO_IN7_REG 0x46 +#define AB8540_GPIO_VINSEL_REG 0x47 +#define AB8540_GPIO_PULL_UPDOWN_REG 0x48 +#define AB8500_GPIO_ALTFUN_REG 0x50 +#define AB8540_GPIO_PULL_UPDOWN_MASK 0x03 +#define AB8540_GPIO_VINSEL_MASK 0x03 +#define AB8540_GPIOX_VBAT_START 51 +#define AB8540_GPIOX_VBAT_END 54 + +#define ABX500_GPIO_INPUT 0 +#define ABX500_GPIO_OUTPUT 1 + +struct abx500_pinctrl { + struct device *dev; + struct pinctrl_dev *pctldev; + struct abx500_pinctrl_soc_data *soc; + struct gpio_chip chip; + struct ab8500 *parent; + struct abx500_gpio_irq_cluster *irq_cluster; + int irq_cluster_size; +}; + +/** + * to_abx500_pinctrl() - get the pointer to abx500_pinctrl + * @chip: Member of the structure abx500_pinctrl + */ +static inline struct abx500_pinctrl *to_abx500_pinctrl(struct gpio_chip *chip) +{ + return container_of(chip, struct abx500_pinctrl, chip); +} + +static int abx500_gpio_get_bit(struct gpio_chip *chip, u8 reg, + unsigned offset, bool *bit) +{ + struct abx500_pinctrl *pct = to_abx500_pinctrl(chip); + u8 pos = offset % 8; + u8 val; + int ret; + + reg += offset / 8; + ret = abx500_get_register_interruptible(pct->dev, + AB8500_MISC, reg, &val); + + *bit = !!(val & BIT(pos)); + + if (ret < 0) + dev_err(pct->dev, + "%s read reg =%x, offset=%x failed (%d)\n", + __func__, reg, offset, ret); + + return ret; +} + +static int abx500_gpio_set_bits(struct gpio_chip *chip, u8 reg, + unsigned offset, int val) +{ + struct abx500_pinctrl *pct = to_abx500_pinctrl(chip); + u8 pos = offset % 8; + int ret; + + reg += offset / 8; + ret = abx500_mask_and_set_register_interruptible(pct->dev, + AB8500_MISC, reg, BIT(pos), val << pos); + if (ret < 0) + dev_err(pct->dev, "%s write reg, %x offset %x failed (%d)\n", + __func__, reg, offset, ret); + + return ret; +} + +/** + * abx500_gpio_get() - Get the particular GPIO value + * @chip: Gpio device + * @offset: GPIO number to read + */ +static int abx500_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct abx500_pinctrl *pct = to_abx500_pinctrl(chip); + bool bit; + bool is_out; + u8 gpio_offset = offset - 1; + int ret; + + ret = abx500_gpio_get_bit(chip, AB8500_GPIO_DIR1_REG, + gpio_offset, &is_out); + if (ret < 0) + goto out; + + if (is_out) + ret = abx500_gpio_get_bit(chip, AB8500_GPIO_OUT1_REG, + gpio_offset, &bit); + else + ret = abx500_gpio_get_bit(chip, AB8500_GPIO_IN1_REG, + gpio_offset, &bit); +out: + if (ret < 0) { + dev_err(pct->dev, "%s failed (%d)\n", __func__, ret); + return ret; + } + + return bit; +} + +static void abx500_gpio_set(struct gpio_chip *chip, unsigned offset, int val) +{ + struct abx500_pinctrl *pct = to_abx500_pinctrl(chip); + int ret; + + ret = abx500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, val); + if (ret < 0) + dev_err(pct->dev, "%s write failed (%d)\n", __func__, ret); +} + +static int abx500_get_pull_updown(struct abx500_pinctrl *pct, int offset, + enum abx500_gpio_pull_updown *pull_updown) +{ + u8 pos; + u8 val; + int ret; + struct pullud *pullud; + + if (!pct->soc->pullud) { + dev_err(pct->dev, "%s AB chip doesn't support pull up/down feature", + __func__); + ret = -EPERM; + goto out; + } + + pullud = pct->soc->pullud; + + if ((offset < pullud->first_pin) + || (offset > pullud->last_pin)) { + ret = -EINVAL; + goto out; + } + + ret = abx500_get_register_interruptible(pct->dev, + AB8500_MISC, AB8540_GPIO_PULL_UPDOWN_REG, &val); + + pos = (offset - pullud->first_pin) << 1; + *pull_updown = (val >> pos) & AB8540_GPIO_PULL_UPDOWN_MASK; + +out: + if (ret < 0) + dev_err(pct->dev, "%s failed (%d)\n", __func__, ret); + + return ret; +} + +static int abx500_set_pull_updown(struct abx500_pinctrl *pct, + int offset, enum abx500_gpio_pull_updown val) +{ + u8 pos; + int ret; + struct pullud *pullud; + + if (!pct->soc->pullud) { + dev_err(pct->dev, "%s AB chip doesn't support pull up/down feature", + __func__); + ret = -EPERM; + goto out; + } + + pullud = pct->soc->pullud; + + if ((offset < pullud->first_pin) + || (offset > pullud->last_pin)) { + ret = -EINVAL; + goto out; + } + pos = (offset - pullud->first_pin) << 1; + + ret = abx500_mask_and_set_register_interruptible(pct->dev, + AB8500_MISC, AB8540_GPIO_PULL_UPDOWN_REG, + AB8540_GPIO_PULL_UPDOWN_MASK << pos, val << pos); + +out: + if (ret < 0) + dev_err(pct->dev, "%s failed (%d)\n", __func__, ret); + + return ret; +} + +static bool abx500_pullud_supported(struct gpio_chip *chip, unsigned gpio) +{ + struct abx500_pinctrl *pct = to_abx500_pinctrl(chip); + struct pullud *pullud = pct->soc->pullud; + + return (pullud && + gpio >= pullud->first_pin && + gpio <= pullud->last_pin); +} + +static int abx500_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, + int val) +{ + struct abx500_pinctrl *pct = to_abx500_pinctrl(chip); + unsigned gpio; + int ret; + + /* set direction as output */ + ret = abx500_gpio_set_bits(chip, + AB8500_GPIO_DIR1_REG, + offset, + ABX500_GPIO_OUTPUT); + if (ret < 0) + goto out; + + /* disable pull down */ + ret = abx500_gpio_set_bits(chip, + AB8500_GPIO_PUD1_REG, + offset, + ABX500_GPIO_PULL_NONE); + if (ret < 0) + goto out; + + /* if supported, disable both pull down and pull up */ + gpio = offset + 1; + if (abx500_pullud_supported(chip, gpio)) { + ret = abx500_set_pull_updown(pct, + gpio, + ABX500_GPIO_PULL_NONE); + } +out: + if (ret < 0) { + dev_err(pct->dev, "%s failed (%d)\n", __func__, ret); + return ret; + } + + /* set the output as 1 or 0 */ + return abx500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, val); +} + +static int abx500_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + /* set the register as input */ + return abx500_gpio_set_bits(chip, + AB8500_GPIO_DIR1_REG, + offset, + ABX500_GPIO_INPUT); +} + +static int abx500_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + struct abx500_pinctrl *pct = to_abx500_pinctrl(chip); + /* The AB8500 GPIO numbers are off by one */ + int gpio = offset + 1; + int hwirq; + int i; + + for (i = 0; i < pct->irq_cluster_size; i++) { + struct abx500_gpio_irq_cluster *cluster = + &pct->irq_cluster[i]; + + if (gpio >= cluster->start && gpio <= cluster->end) { + /* + * The ABx500 GPIO's associated IRQs are clustered together + * throughout the interrupt numbers at irregular intervals. + * To solve this quandry, we have placed the read-in values + * into the cluster information table. + */ + hwirq = gpio - cluster->start + cluster->to_irq; + return irq_create_mapping(pct->parent->domain, hwirq); + } + } + + return -EINVAL; +} + +static int abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip, + unsigned gpio, int alt_setting) +{ + struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); + struct alternate_functions af = pct->soc->alternate_functions[gpio]; + int ret; + int val; + unsigned offset; + + const char *modes[] = { + [ABX500_DEFAULT] = "default", + [ABX500_ALT_A] = "altA", + [ABX500_ALT_B] = "altB", + [ABX500_ALT_C] = "altC", + }; + + /* sanity check */ + if (((alt_setting == ABX500_ALT_A) && (af.gpiosel_bit == UNUSED)) || + ((alt_setting == ABX500_ALT_B) && (af.alt_bit1 == UNUSED)) || + ((alt_setting == ABX500_ALT_C) && (af.alt_bit2 == UNUSED))) { + dev_dbg(pct->dev, "pin %d doesn't support %s mode\n", gpio, + modes[alt_setting]); + return -EINVAL; + } + + /* on ABx5xx, there is no GPIO0, so adjust the offset */ + offset = gpio - 1; + + switch (alt_setting) { + case ABX500_DEFAULT: + /* + * for ABx5xx family, default mode is always selected by + * writing 0 to GPIOSELx register, except for pins which + * support at least ALT_B mode, default mode is selected + * by writing 1 to GPIOSELx register + */ + val = 0; + if (af.alt_bit1 != UNUSED) + val++; + + ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG, + offset, val); + break; + + case ABX500_ALT_A: + /* + * for ABx5xx family, alt_a mode is always selected by + * writing 1 to GPIOSELx register, except for pins which + * support at least ALT_B mode, alt_a mode is selected + * by writing 0 to GPIOSELx register and 0 in ALTFUNC + * register + */ + if (af.alt_bit1 != UNUSED) { + ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG, + offset, 0); + if (ret < 0) + goto out; + + ret = abx500_gpio_set_bits(chip, + AB8500_GPIO_ALTFUN_REG, + af.alt_bit1, + !!(af.alta_val & BIT(0))); + if (ret < 0) + goto out; + + if (af.alt_bit2 != UNUSED) + ret = abx500_gpio_set_bits(chip, + AB8500_GPIO_ALTFUN_REG, + af.alt_bit2, + !!(af.alta_val & BIT(1))); + } else + ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG, + offset, 1); + break; + + case ABX500_ALT_B: + ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG, + offset, 0); + if (ret < 0) + goto out; + + ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG, + af.alt_bit1, !!(af.altb_val & BIT(0))); + if (ret < 0) + goto out; + + if (af.alt_bit2 != UNUSED) + ret = abx500_gpio_set_bits(chip, + AB8500_GPIO_ALTFUN_REG, + af.alt_bit2, + !!(af.altb_val & BIT(1))); + break; + + case ABX500_ALT_C: + ret = abx500_gpio_set_bits(chip, AB8500_GPIO_SEL1_REG, + offset, 0); + if (ret < 0) + goto out; + + ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG, + af.alt_bit2, !!(af.altc_val & BIT(0))); + if (ret < 0) + goto out; + + ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG, + af.alt_bit2, !!(af.altc_val & BIT(1))); + break; + + default: + dev_dbg(pct->dev, "unknow alt_setting %d\n", alt_setting); + + return -EINVAL; + } +out: + if (ret < 0) + dev_err(pct->dev, "%s failed (%d)\n", __func__, ret); + + return ret; +} + +static int abx500_get_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip, + unsigned gpio) +{ + u8 mode; + bool bit_mode; + bool alt_bit1; + bool alt_bit2; + struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); + struct alternate_functions af = pct->soc->alternate_functions[gpio]; + /* on ABx5xx, there is no GPIO0, so adjust the offset */ + unsigned offset = gpio - 1; + int ret; + + /* + * if gpiosel_bit is set to unused, + * it means no GPIO or special case + */ + if (af.gpiosel_bit == UNUSED) + return ABX500_DEFAULT; + + /* read GpioSelx register */ + ret = abx500_gpio_get_bit(chip, AB8500_GPIO_SEL1_REG + (offset / 8), + af.gpiosel_bit, &bit_mode); + if (ret < 0) + goto out; + + mode = bit_mode; + + /* sanity check */ + if ((af.alt_bit1 < UNUSED) || (af.alt_bit1 > 7) || + (af.alt_bit2 < UNUSED) || (af.alt_bit2 > 7)) { + dev_err(pct->dev, + "alt_bitX value not in correct range (-1 to 7)\n"); + return -EINVAL; + } + + /* if alt_bit2 is used, alt_bit1 must be used too */ + if ((af.alt_bit2 != UNUSED) && (af.alt_bit1 == UNUSED)) { + dev_err(pct->dev, + "if alt_bit2 is used, alt_bit1 can't be unused\n"); + return -EINVAL; + } + + /* check if pin use AlternateFunction register */ + if ((af.alt_bit1 == UNUSED) && (af.alt_bit2 == UNUSED)) + return mode; + /* + * if pin GPIOSEL bit is set and pin supports alternate function, + * it means DEFAULT mode + */ + if (mode) + return ABX500_DEFAULT; + + /* + * pin use the AlternatFunction register + * read alt_bit1 value + */ + ret = abx500_gpio_get_bit(chip, AB8500_GPIO_ALTFUN_REG, + af.alt_bit1, &alt_bit1); + if (ret < 0) + goto out; + + if (af.alt_bit2 != UNUSED) { + /* read alt_bit2 value */ + ret = abx500_gpio_get_bit(chip, AB8500_GPIO_ALTFUN_REG, + af.alt_bit2, + &alt_bit2); + if (ret < 0) + goto out; + } else + alt_bit2 = 0; + + mode = (alt_bit2 << 1) + alt_bit1; + if (mode == af.alta_val) + return ABX500_ALT_A; + else if (mode == af.altb_val) + return ABX500_ALT_B; + else + return ABX500_ALT_C; + +out: + dev_err(pct->dev, "%s failed (%d)\n", __func__, ret); + return ret; +} + +#ifdef CONFIG_DEBUG_FS + +#include <linux/seq_file.h> + +static void abx500_gpio_dbg_show_one(struct seq_file *s, + struct pinctrl_dev *pctldev, + struct gpio_chip *chip, + unsigned offset, unsigned gpio) +{ + struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); + const char *label = gpiochip_is_requested(chip, offset - 1); + u8 gpio_offset = offset - 1; + int mode = -1; + bool is_out; + bool pd; + enum abx500_gpio_pull_updown pud = 0; + int ret; + + const char *modes[] = { + [ABX500_DEFAULT] = "default", + [ABX500_ALT_A] = "altA", + [ABX500_ALT_B] = "altB", + [ABX500_ALT_C] = "altC", + }; + + const char *pull_up_down[] = { + [ABX500_GPIO_PULL_DOWN] = "pull down", + [ABX500_GPIO_PULL_NONE] = "pull none", + [ABX500_GPIO_PULL_NONE + 1] = "pull none", + [ABX500_GPIO_PULL_UP] = "pull up", + }; + + ret = abx500_gpio_get_bit(chip, AB8500_GPIO_DIR1_REG, + gpio_offset, &is_out); + if (ret < 0) + goto out; + + seq_printf(s, " gpio-%-3d (%-20.20s) %-3s", + gpio, label ?: "(none)", + is_out ? "out" : "in "); + + if (!is_out) { + if (abx500_pullud_supported(chip, offset)) { + ret = abx500_get_pull_updown(pct, offset, &pud); + if (ret < 0) + goto out; + + seq_printf(s, " %-9s", pull_up_down[pud]); + } else { + ret = abx500_gpio_get_bit(chip, AB8500_GPIO_PUD1_REG, + gpio_offset, &pd); + if (ret < 0) + goto out; + + seq_printf(s, " %-9s", pull_up_down[pd]); + } + } else + seq_printf(s, " %-9s", chip->get(chip, offset) ? "hi" : "lo"); + + if (pctldev) + mode = abx500_get_mode(pctldev, chip, offset); + + seq_printf(s, " %s", (mode < 0) ? "unknown" : modes[mode]); + +out: + if (ret < 0) + dev_err(pct->dev, "%s failed (%d)\n", __func__, ret); +} + +static void abx500_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) +{ + unsigned i; + unsigned gpio = chip->base; + struct abx500_pinctrl *pct = to_abx500_pinctrl(chip); + struct pinctrl_dev *pctldev = pct->pctldev; + + for (i = 0; i < chip->ngpio; i++, gpio++) { + /* On AB8500, there is no GPIO0, the first is the GPIO 1 */ + abx500_gpio_dbg_show_one(s, pctldev, chip, i + 1, gpio); + seq_printf(s, "\n"); + } +} + +#else +static inline void abx500_gpio_dbg_show_one(struct seq_file *s, + struct pinctrl_dev *pctldev, + struct gpio_chip *chip, + unsigned offset, unsigned gpio) +{ +} +#define abx500_gpio_dbg_show NULL +#endif + +static int abx500_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + int gpio = chip->base + offset; + + return pinctrl_request_gpio(gpio); +} + +static void abx500_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + int gpio = chip->base + offset; + + pinctrl_free_gpio(gpio); +} + +static struct gpio_chip abx500gpio_chip = { + .label = "abx500-gpio", + .owner = THIS_MODULE, + .request = abx500_gpio_request, + .free = abx500_gpio_free, + .direction_input = abx500_gpio_direction_input, + .get = abx500_gpio_get, + .direction_output = abx500_gpio_direction_output, + .set = abx500_gpio_set, + .to_irq = abx500_gpio_to_irq, + .dbg_show = abx500_gpio_dbg_show, +}; + +static int abx500_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev) +{ + struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); + + return pct->soc->nfunctions; +} + +static const char *abx500_pmx_get_func_name(struct pinctrl_dev *pctldev, + unsigned function) +{ + struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); + + return pct->soc->functions[function].name; +} + +static int abx500_pmx_get_func_groups(struct pinctrl_dev *pctldev, + unsigned function, + const char * const **groups, + unsigned * const num_groups) +{ + struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); + + *groups = pct->soc->functions[function].groups; + *num_groups = pct->soc->functions[function].ngroups; + + return 0; +} + +static int abx500_pmx_enable(struct pinctrl_dev *pctldev, unsigned function, + unsigned group) +{ + struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); + struct gpio_chip *chip = &pct->chip; + const struct abx500_pingroup *g; + int i; + int ret = 0; + + g = &pct->soc->groups[group]; + if (g->altsetting < 0) + return -EINVAL; + + dev_dbg(pct->dev, "enable group %s, %u pins\n", g->name, g->npins); + + for (i = 0; i < g->npins; i++) { + dev_dbg(pct->dev, "setting pin %d to altsetting %d\n", + g->pins[i], g->altsetting); + + ret = abx500_set_mode(pctldev, chip, g->pins[i], g->altsetting); + } + + if (ret < 0) + dev_err(pct->dev, "%s failed (%d)\n", __func__, ret); + + return ret; +} + +static int abx500_gpio_request_enable(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned offset) +{ + struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); + const struct abx500_pinrange *p; + int ret; + int i; + + /* + * Different ranges have different ways to enable GPIO function on a + * pin, so refer back to our local range type, where we handily define + * what altfunc enables GPIO for a certain pin. + */ + for (i = 0; i < pct->soc->gpio_num_ranges; i++) { + p = &pct->soc->gpio_ranges[i]; + if ((offset >= p->offset) && + (offset < (p->offset + p->npins))) + break; + } + + if (i == pct->soc->gpio_num_ranges) { + dev_err(pct->dev, "%s failed to locate range\n", __func__); + return -ENODEV; + } + + dev_dbg(pct->dev, "enable GPIO by altfunc %d at gpio %d\n", + p->altfunc, offset); + + ret = abx500_set_mode(pct->pctldev, &pct->chip, + offset, p->altfunc); + if (ret < 0) + dev_err(pct->dev, "%s setting altfunc failed\n", __func__); + + return ret; +} + +static void abx500_gpio_disable_free(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned offset) +{ +} + +static const struct pinmux_ops abx500_pinmux_ops = { + .get_functions_count = abx500_pmx_get_funcs_cnt, + .get_function_name = abx500_pmx_get_func_name, + .get_function_groups = abx500_pmx_get_func_groups, + .enable = abx500_pmx_enable, + .gpio_request_enable = abx500_gpio_request_enable, + .gpio_disable_free = abx500_gpio_disable_free, +}; + +static int abx500_get_groups_cnt(struct pinctrl_dev *pctldev) +{ + struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); + + return pct->soc->ngroups; +} + +static const char *abx500_get_group_name(struct pinctrl_dev *pctldev, + unsigned selector) +{ + struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); + + return pct->soc->groups[selector].name; +} + +static int abx500_get_group_pins(struct pinctrl_dev *pctldev, + unsigned selector, + const unsigned **pins, + unsigned *num_pins) +{ + struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); + + *pins = pct->soc->groups[selector].pins; + *num_pins = pct->soc->groups[selector].npins; + + return 0; +} + +static void abx500_pin_dbg_show(struct pinctrl_dev *pctldev, + struct seq_file *s, unsigned offset) +{ + struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); + struct gpio_chip *chip = &pct->chip; + + abx500_gpio_dbg_show_one(s, pctldev, chip, offset, + chip->base + offset - 1); +} + +static void abx500_dt_free_map(struct pinctrl_dev *pctldev, + struct pinctrl_map *map, unsigned num_maps) +{ + int i; + + for (i = 0; i < num_maps; i++) + if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN) + kfree(map[i].data.configs.configs); + kfree(map); +} + +static int abx500_dt_reserve_map(struct pinctrl_map **map, + unsigned *reserved_maps, + unsigned *num_maps, + unsigned reserve) +{ + unsigned old_num = *reserved_maps; + unsigned new_num = *num_maps + reserve; + struct pinctrl_map *new_map; + + if (old_num >= new_num) + return 0; + + new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL); + if (!new_map) + return -ENOMEM; + + memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map)); + + *map = new_map; + *reserved_maps = new_num; + + return 0; +} + +static int abx500_dt_add_map_mux(struct pinctrl_map **map, + unsigned *reserved_maps, + unsigned *num_maps, const char *group, + const char *function) +{ + if (*num_maps == *reserved_maps) + return -ENOSPC; + + (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP; + (*map)[*num_maps].data.mux.group = group; + (*map)[*num_maps].data.mux.function = function; + (*num_maps)++; + + return 0; +} + +static int abx500_dt_add_map_configs(struct pinctrl_map **map, + unsigned *reserved_maps, + unsigned *num_maps, const char *group, + unsigned long *configs, unsigned num_configs) +{ + unsigned long *dup_configs; + + if (*num_maps == *reserved_maps) + return -ENOSPC; + + dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs), + GFP_KERNEL); + if (!dup_configs) + return -ENOMEM; + + (*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_PIN; + + (*map)[*num_maps].data.configs.group_or_pin = group; + (*map)[*num_maps].data.configs.configs = dup_configs; + (*map)[*num_maps].data.configs.num_configs = num_configs; + (*num_maps)++; + + return 0; +} + +static const char *abx500_find_pin_name(struct pinctrl_dev *pctldev, + const char *pin_name) +{ + int i, pin_number; + struct abx500_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); + + if (sscanf((char *)pin_name, "GPIO%d", &pin_number) == 1) + for (i = 0; i < npct->soc->npins; i++) + if (npct->soc->pins[i].number == pin_number) + return npct->soc->pins[i].name; + return NULL; +} + +static int abx500_dt_subnode_to_map(struct pinctrl_dev *pctldev, + struct device_node *np, + struct pinctrl_map **map, + unsigned *reserved_maps, + unsigned *num_maps) +{ + int ret; + const char *function = NULL; + unsigned long *configs; + unsigned int nconfigs = 0; + bool has_config = 0; + unsigned reserve = 0; + struct property *prop; + const char *group, *gpio_name; + struct device_node *np_config; + + ret = of_property_read_string(np, "ste,function", &function); + if (ret >= 0) + reserve = 1; + + ret = pinconf_generic_parse_dt_config(np, &configs, &nconfigs); + if (nconfigs) + has_config = 1; + + np_config = of_parse_phandle(np, "ste,config", 0); + if (np_config) { + ret = pinconf_generic_parse_dt_config(np_config, &configs, + &nconfigs); + if (ret) + goto exit; + has_config |= nconfigs; + } + + ret = of_property_count_strings(np, "ste,pins"); + if (ret < 0) + goto exit; + + if (has_config) + reserve++; + + reserve *= ret; + + ret = abx500_dt_reserve_map(map, reserved_maps, num_maps, reserve); + if (ret < 0) + goto exit; + + of_property_for_each_string(np, "ste,pins", prop, group) { + if (function) { + ret = abx500_dt_add_map_mux(map, reserved_maps, + num_maps, group, function); + if (ret < 0) + goto exit; + } + if (has_config) { + gpio_name = abx500_find_pin_name(pctldev, group); + + ret = abx500_dt_add_map_configs(map, reserved_maps, + num_maps, gpio_name, configs, 1); + if (ret < 0) + goto exit; + } + + } +exit: + return ret; +} + +static int abx500_dt_node_to_map(struct pinctrl_dev *pctldev, + struct device_node *np_config, + struct pinctrl_map **map, unsigned *num_maps) +{ + unsigned reserved_maps; + struct device_node *np; + int ret; + + reserved_maps = 0; + *map = NULL; + *num_maps = 0; + + for_each_child_of_node(np_config, np) { + ret = abx500_dt_subnode_to_map(pctldev, np, map, + &reserved_maps, num_maps); + if (ret < 0) { + abx500_dt_free_map(pctldev, *map, *num_maps); + return ret; + } + } + + return 0; +} + +static const struct pinctrl_ops abx500_pinctrl_ops = { + .get_groups_count = abx500_get_groups_cnt, + .get_group_name = abx500_get_group_name, + .get_group_pins = abx500_get_group_pins, + .pin_dbg_show = abx500_pin_dbg_show, + .dt_node_to_map = abx500_dt_node_to_map, + .dt_free_map = abx500_dt_free_map, +}; + +static int abx500_pin_config_get(struct pinctrl_dev *pctldev, + unsigned pin, + unsigned long *config) +{ + return -ENOSYS; +} + +static int abx500_pin_config_set(struct pinctrl_dev *pctldev, + unsigned pin, + unsigned long *configs, + unsigned num_configs) +{ + struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); + struct gpio_chip *chip = &pct->chip; + unsigned offset; + int ret = -EINVAL; + int i; + enum pin_config_param param; + enum pin_config_param argument; + + for (i = 0; i < num_configs; i++) { + param = pinconf_to_config_param(configs[i]); + argument = pinconf_to_config_argument(configs[i]); + + dev_dbg(chip->dev, "pin %d [%#lx]: %s %s\n", + pin, configs[i], + (param == PIN_CONFIG_OUTPUT) ? "output " : "input", + (param == PIN_CONFIG_OUTPUT) ? + (argument ? "high" : "low") : + (argument ? "pull up" : "pull down")); + + /* on ABx500, there is no GPIO0, so adjust the offset */ + offset = pin - 1; + + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + ret = abx500_gpio_direction_input(chip, offset); + if (ret < 0) + goto out; + /* + * Some chips only support pull down, while some + * actually support both pull up and pull down. Such + * chips have a "pullud" range specified for the pins + * that support both features. If the pin is not + * within that range, we fall back to the old bit set + * that only support pull down. + */ + if (abx500_pullud_supported(chip, pin)) + ret = abx500_set_pull_updown(pct, + pin, + ABX500_GPIO_PULL_NONE); + else + /* Chip only supports pull down */ + ret = abx500_gpio_set_bits(chip, + AB8500_GPIO_PUD1_REG, offset, + ABX500_GPIO_PULL_NONE); + break; + + case PIN_CONFIG_BIAS_PULL_DOWN: + ret = abx500_gpio_direction_input(chip, offset); + if (ret < 0) + goto out; + /* + * if argument = 1 set the pull down + * else clear the pull down + * Some chips only support pull down, while some + * actually support both pull up and pull down. Such + * chips have a "pullud" range specified for the pins + * that support both features. If the pin is not + * within that range, we fall back to the old bit set + * that only support pull down. + */ + if (abx500_pullud_supported(chip, pin)) + ret = abx500_set_pull_updown(pct, + pin, + argument ? ABX500_GPIO_PULL_DOWN : + ABX500_GPIO_PULL_NONE); + else + /* Chip only supports pull down */ + ret = abx500_gpio_set_bits(chip, + AB8500_GPIO_PUD1_REG, + offset, + argument ? ABX500_GPIO_PULL_DOWN : + ABX500_GPIO_PULL_NONE); + break; + + case PIN_CONFIG_BIAS_PULL_UP: + ret = abx500_gpio_direction_input(chip, offset); + if (ret < 0) + goto out; + /* + * if argument = 1 set the pull up + * else clear the pull up + */ + ret = abx500_gpio_direction_input(chip, offset); + /* + * Some chips only support pull down, while some + * actually support both pull up and pull down. Such + * chips have a "pullud" range specified for the pins + * that support both features. If the pin is not + * within that range, do nothing + */ + if (abx500_pullud_supported(chip, pin)) + ret = abx500_set_pull_updown(pct, + pin, + argument ? ABX500_GPIO_PULL_UP : + ABX500_GPIO_PULL_NONE); + break; + + case PIN_CONFIG_OUTPUT: + ret = abx500_gpio_direction_output(chip, offset, + argument); + break; + + default: + dev_err(chip->dev, "illegal configuration requested\n"); + } + } /* for each config */ +out: + if (ret < 0) + dev_err(pct->dev, "%s failed (%d)\n", __func__, ret); + + return ret; +} + +static const struct pinconf_ops abx500_pinconf_ops = { + .pin_config_get = abx500_pin_config_get, + .pin_config_set = abx500_pin_config_set, +}; + +static struct pinctrl_desc abx500_pinctrl_desc = { + .name = "pinctrl-abx500", + .pctlops = &abx500_pinctrl_ops, + .pmxops = &abx500_pinmux_ops, + .confops = &abx500_pinconf_ops, + .owner = THIS_MODULE, +}; + +static int abx500_get_gpio_num(struct abx500_pinctrl_soc_data *soc) +{ + unsigned int lowest = 0; + unsigned int highest = 0; + unsigned int npins = 0; + int i; + + /* + * Compute number of GPIOs from the last SoC gpio range descriptors + * These ranges may include "holes" but the GPIO number space shall + * still be homogeneous, so we need to detect and account for any + * such holes so that these are included in the number of GPIO pins. + */ + for (i = 0; i < soc->gpio_num_ranges; i++) { + unsigned gstart; + unsigned gend; + const struct abx500_pinrange *p; + + p = &soc->gpio_ranges[i]; + gstart = p->offset; + gend = p->offset + p->npins - 1; + + if (i == 0) { + /* First iteration, set start values */ + lowest = gstart; + highest = gend; + } else { + if (gstart < lowest) + lowest = gstart; + if (gend > highest) + highest = gend; + } + } + /* this gives the absolute number of pins */ + npins = highest - lowest + 1; + return npins; +} + +static const struct of_device_id abx500_gpio_match[] = { + { .compatible = "stericsson,ab8500-gpio", .data = (void *)PINCTRL_AB8500, }, + { .compatible = "stericsson,ab8505-gpio", .data = (void *)PINCTRL_AB8505, }, + { .compatible = "stericsson,ab8540-gpio", .data = (void *)PINCTRL_AB8540, }, + { .compatible = "stericsson,ab9540-gpio", .data = (void *)PINCTRL_AB9540, }, + { } +}; + +static int abx500_gpio_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + const struct of_device_id *match; + struct abx500_pinctrl *pct; + unsigned int id = -1; + int ret, err; + int i; + + if (!np) { + dev_err(&pdev->dev, "gpio dt node missing\n"); + return -ENODEV; + } + + pct = devm_kzalloc(&pdev->dev, sizeof(struct abx500_pinctrl), + GFP_KERNEL); + if (pct == NULL) { + dev_err(&pdev->dev, + "failed to allocate memory for pct\n"); + return -ENOMEM; + } + + pct->dev = &pdev->dev; + pct->parent = dev_get_drvdata(pdev->dev.parent); + pct->chip = abx500gpio_chip; + pct->chip.dev = &pdev->dev; + pct->chip.base = -1; /* Dynamic allocation */ + + match = of_match_device(abx500_gpio_match, &pdev->dev); + if (!match) { + dev_err(&pdev->dev, "gpio dt not matching\n"); + return -ENODEV; + } + id = (unsigned long)match->data; + + /* Poke in other ASIC variants here */ + switch (id) { + case PINCTRL_AB8500: + abx500_pinctrl_ab8500_init(&pct->soc); + break; + case PINCTRL_AB8540: + abx500_pinctrl_ab8540_init(&pct->soc); + break; + case PINCTRL_AB9540: + abx500_pinctrl_ab9540_init(&pct->soc); + break; + case PINCTRL_AB8505: + abx500_pinctrl_ab8505_init(&pct->soc); + break; + default: + dev_err(&pdev->dev, "Unsupported pinctrl sub driver (%d)\n", id); + return -EINVAL; + } + + if (!pct->soc) { + dev_err(&pdev->dev, "Invalid SOC data\n"); + return -EINVAL; + } + + pct->chip.ngpio = abx500_get_gpio_num(pct->soc); + pct->irq_cluster = pct->soc->gpio_irq_cluster; + pct->irq_cluster_size = pct->soc->ngpio_irq_cluster; + + ret = gpiochip_add(&pct->chip); + if (ret) { + dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); + return ret; + } + dev_info(&pdev->dev, "added gpiochip\n"); + + abx500_pinctrl_desc.pins = pct->soc->pins; + abx500_pinctrl_desc.npins = pct->soc->npins; + pct->pctldev = pinctrl_register(&abx500_pinctrl_desc, &pdev->dev, pct); + if (!pct->pctldev) { + dev_err(&pdev->dev, + "could not register abx500 pinctrl driver\n"); + ret = -EINVAL; + goto out_rem_chip; + } + dev_info(&pdev->dev, "registered pin controller\n"); + + /* We will handle a range of GPIO pins */ + for (i = 0; i < pct->soc->gpio_num_ranges; i++) { + const struct abx500_pinrange *p = &pct->soc->gpio_ranges[i]; + + ret = gpiochip_add_pin_range(&pct->chip, + dev_name(&pdev->dev), + p->offset - 1, p->offset, p->npins); + if (ret < 0) + goto out_rem_chip; + } + + platform_set_drvdata(pdev, pct); + dev_info(&pdev->dev, "initialized abx500 pinctrl driver\n"); + + return 0; + +out_rem_chip: + err = gpiochip_remove(&pct->chip); + if (err) + dev_info(&pdev->dev, "failed to remove gpiochip\n"); + + return ret; +} + +/** + * abx500_gpio_remove() - remove Ab8500-gpio driver + * @pdev: Platform device registered + */ +static int abx500_gpio_remove(struct platform_device *pdev) +{ + struct abx500_pinctrl *pct = platform_get_drvdata(pdev); + int ret; + + ret = gpiochip_remove(&pct->chip); + if (ret < 0) { + dev_err(pct->dev, "unable to remove gpiochip: %d\n", + ret); + return ret; + } + + return 0; +} + +static struct platform_driver abx500_gpio_driver = { + .driver = { + .name = "abx500-gpio", + .owner = THIS_MODULE, + .of_match_table = abx500_gpio_match, + }, + .probe = abx500_gpio_probe, + .remove = abx500_gpio_remove, +}; + +static int __init abx500_gpio_init(void) +{ + return platform_driver_register(&abx500_gpio_driver); +} +core_initcall(abx500_gpio_init); + +MODULE_AUTHOR("Patrice Chotard <patrice.chotard@st.com>"); +MODULE_DESCRIPTION("Driver allows to use AxB5xx unused pins to be used as GPIO"); +MODULE_ALIAS("platform:abx500-gpio"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/nomadik/pinctrl-abx500.h b/drivers/pinctrl/nomadik/pinctrl-abx500.h new file mode 100644 index 000000000000..2beef3bfe9ca --- /dev/null +++ b/drivers/pinctrl/nomadik/pinctrl-abx500.h @@ -0,0 +1,246 @@ +#ifndef PINCTRL_PINCTRL_ABx500_H +#define PINCTRL_PINCTRL_ABx500_H + +/* Package definitions */ +#define PINCTRL_AB8500 0 +#define PINCTRL_AB8540 1 +#define PINCTRL_AB9540 2 +#define PINCTRL_AB8505 3 + +/* pins alternate function */ +enum abx500_pin_func { + ABX500_DEFAULT, + ABX500_ALT_A, + ABX500_ALT_B, + ABX500_ALT_C, +}; + +enum abx500_gpio_pull_updown { + ABX500_GPIO_PULL_DOWN = 0x0, + ABX500_GPIO_PULL_NONE = 0x1, + ABX500_GPIO_PULL_UP = 0x3, +}; + +enum abx500_gpio_vinsel { + ABX500_GPIO_VINSEL_VBAT = 0x0, + ABX500_GPIO_VINSEL_VIN_1V8 = 0x1, + ABX500_GPIO_VINSEL_VDD_BIF = 0x2, +}; + +/** + * struct abx500_function - ABx500 pinctrl mux function + * @name: The name of the function, exported to pinctrl core. + * @groups: An array of pin groups that may select this function. + * @ngroups: The number of entries in @groups. + */ +struct abx500_function { + const char *name; + const char * const *groups; + unsigned ngroups; +}; + +/** + * struct abx500_pingroup - describes a ABx500 pin group + * @name: the name of this specific pin group + * @pins: an array of discrete physical pins used in this group, taken + * from the driver-local pin enumeration space + * @num_pins: the number of pins in this group array, i.e. the number of + * elements in .pins so we can iterate over that array + * @altsetting: the altsetting to apply to all pins in this group to + * configure them to be used by a function + */ +struct abx500_pingroup { + const char *name; + const unsigned int *pins; + const unsigned npins; + int altsetting; +}; + +#define ALTERNATE_FUNCTIONS(pin, sel_bit, alt1, alt2, alta, altb, altc) \ +{ \ + .pin_number = pin, \ + .gpiosel_bit = sel_bit, \ + .alt_bit1 = alt1, \ + .alt_bit2 = alt2, \ + .alta_val = alta, \ + .altb_val = altb, \ + .altc_val = altc, \ +} + +#define UNUSED -1 +/** + * struct alternate_functions + * @pin_number: The pin number + * @gpiosel_bit: Control bit in GPIOSEL register, + * @alt_bit1: First AlternateFunction bit used to select the + * alternate function + * @alt_bit2: Second AlternateFunction bit used to select the + * alternate function + * + * these 3 following fields are necessary due to none + * coherency on how to select the altA, altB and altC + * function between the ABx500 SOC family when using + * alternatfunc register. + * @alta_val: value to write in alternatfunc to select altA function + * @altb_val: value to write in alternatfunc to select altB function + * @altc_val: value to write in alternatfunc to select altC function + */ +struct alternate_functions { + unsigned pin_number; + s8 gpiosel_bit; + s8 alt_bit1; + s8 alt_bit2; + u8 alta_val; + u8 altb_val; + u8 altc_val; +}; + +/** + * struct pullud - specific pull up/down feature + * @first_pin: The pin number of the first pins which support + * specific pull up/down + * @last_pin: The pin number of the last pins + */ +struct pullud { + unsigned first_pin; + unsigned last_pin; +}; + +#define GPIO_IRQ_CLUSTER(a, b, c) \ +{ \ + .start = a, \ + .end = b, \ + .to_irq = c, \ +} + +/** + * struct abx500_gpio_irq_cluster - indicates GPIOs which are interrupt + * capable + * @start: The pin number of the first pin interrupt capable + * @end: The pin number of the last pin interrupt capable + * @to_irq: The ABx500 GPIO's associated IRQs are clustered + * together throughout the interrupt numbers at irregular + * intervals. To solve this quandary, we will place the + * read-in values into the cluster information table + */ + +struct abx500_gpio_irq_cluster { + int start; + int end; + int to_irq; +}; + +/** + * struct abx500_pinrange - map pin numbers to GPIO offsets + * @offset: offset into the GPIO local numberspace, incidentally + * identical to the offset into the local pin numberspace + * @npins: number of pins to map from both offsets + * @altfunc: altfunc setting to be used to enable GPIO on a pin in + * this range (may vary) + */ +struct abx500_pinrange { + unsigned int offset; + unsigned int npins; + int altfunc; +}; + +#define ABX500_PINRANGE(a, b, c) { .offset = a, .npins = b, .altfunc = c } + +/** + * struct abx500_pinctrl_soc_data - ABx500 pin controller per-SoC configuration + * @gpio_ranges: An array of GPIO ranges for this SoC + * @gpio_num_ranges: The number of GPIO ranges for this SoC + * @pins: An array describing all pins the pin controller affects. + * All pins which are also GPIOs must be listed first within the + * array, and be numbered identically to the GPIO controller's + * numbering. + * @npins: The number of entries in @pins. + * @functions: The functions supported on this SoC. + * @nfunction: The number of entries in @functions. + * @groups: An array describing all pin groups the pin SoC supports. + * @ngroups: The number of entries in @groups. + * @alternate_functions: array describing pins which supports alternate and + * how to set it. + * @pullud: array describing pins which supports pull up/down + * specific registers. + * @gpio_irq_cluster: An array of GPIO interrupt capable for this SoC + * @ngpio_irq_cluster: The number of GPIO inetrrupt capable for this SoC + * @irq_gpio_rising_offset: Interrupt offset used as base to compute specific + * setting strategy of the rising interrupt line + * @irq_gpio_falling_offset: Interrupt offset used as base to compute specific + * setting strategy of the falling interrupt line + * @irq_gpio_factor: Factor used to compute specific setting strategy of + * the interrupt line + */ + +struct abx500_pinctrl_soc_data { + const struct abx500_pinrange *gpio_ranges; + unsigned gpio_num_ranges; + const struct pinctrl_pin_desc *pins; + unsigned npins; + const struct abx500_function *functions; + unsigned nfunctions; + const struct abx500_pingroup *groups; + unsigned ngroups; + struct alternate_functions *alternate_functions; + struct pullud *pullud; + struct abx500_gpio_irq_cluster *gpio_irq_cluster; + unsigned ngpio_irq_cluster; + int irq_gpio_rising_offset; + int irq_gpio_falling_offset; + int irq_gpio_factor; +}; + +#ifdef CONFIG_PINCTRL_AB8500 + +void abx500_pinctrl_ab8500_init(struct abx500_pinctrl_soc_data **soc); + +#else + +static inline void +abx500_pinctrl_ab8500_init(struct abx500_pinctrl_soc_data **soc) +{ +} + +#endif + +#ifdef CONFIG_PINCTRL_AB8540 + +void abx500_pinctrl_ab8540_init(struct abx500_pinctrl_soc_data **soc); + +#else + +static inline void +abx500_pinctrl_ab8540_init(struct abx500_pinctrl_soc_data **soc) +{ +} + +#endif + +#ifdef CONFIG_PINCTRL_AB9540 + +void abx500_pinctrl_ab9540_init(struct abx500_pinctrl_soc_data **soc); + +#else + +static inline void +abx500_pinctrl_ab9540_init(struct abx500_pinctrl_soc_data **soc) +{ +} + +#endif + +#ifdef CONFIG_PINCTRL_AB8505 + +void abx500_pinctrl_ab8505_init(struct abx500_pinctrl_soc_data **soc); + +#else + +static inline void +abx500_pinctrl_ab8505_init(struct abx500_pinctrl_soc_data **soc) +{ +} + +#endif + +#endif /* PINCTRL_PINCTRL_ABx500_H */ diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c b/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c new file mode 100644 index 000000000000..c74840729648 --- /dev/null +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c @@ -0,0 +1,1257 @@ +#include <linux/kernel.h> +#include <linux/pinctrl/pinctrl.h> +#include "pinctrl-nomadik.h" + +/* All the pins that can be used for GPIO and some other functions */ +#define _GPIO(offset) (offset) + +#define DB8500_PIN_AJ5 _GPIO(0) +#define DB8500_PIN_AJ3 _GPIO(1) +#define DB8500_PIN_AH4 _GPIO(2) +#define DB8500_PIN_AH3 _GPIO(3) +#define DB8500_PIN_AH6 _GPIO(4) +#define DB8500_PIN_AG6 _GPIO(5) +#define DB8500_PIN_AF6 _GPIO(6) +#define DB8500_PIN_AG5 _GPIO(7) +#define DB8500_PIN_AD5 _GPIO(8) +#define DB8500_PIN_AE4 _GPIO(9) +#define DB8500_PIN_AF5 _GPIO(10) +#define DB8500_PIN_AG4 _GPIO(11) +#define DB8500_PIN_AC4 _GPIO(12) +#define DB8500_PIN_AF3 _GPIO(13) +#define DB8500_PIN_AE3 _GPIO(14) +#define DB8500_PIN_AC3 _GPIO(15) +#define DB8500_PIN_AD3 _GPIO(16) +#define DB8500_PIN_AD4 _GPIO(17) +#define DB8500_PIN_AC2 _GPIO(18) +#define DB8500_PIN_AC1 _GPIO(19) +#define DB8500_PIN_AB4 _GPIO(20) +#define DB8500_PIN_AB3 _GPIO(21) +#define DB8500_PIN_AA3 _GPIO(22) +#define DB8500_PIN_AA4 _GPIO(23) +#define DB8500_PIN_AB2 _GPIO(24) +#define DB8500_PIN_Y4 _GPIO(25) +#define DB8500_PIN_Y2 _GPIO(26) +#define DB8500_PIN_AA2 _GPIO(27) +#define DB8500_PIN_AA1 _GPIO(28) +#define DB8500_PIN_W2 _GPIO(29) +#define DB8500_PIN_W3 _GPIO(30) +#define DB8500_PIN_V3 _GPIO(31) +#define DB8500_PIN_V2 _GPIO(32) +#define DB8500_PIN_AF2 _GPIO(33) +#define DB8500_PIN_AE1 _GPIO(34) +#define DB8500_PIN_AE2 _GPIO(35) +#define DB8500_PIN_AG2 _GPIO(36) +/* Hole */ +#define DB8500_PIN_F3 _GPIO(64) +#define DB8500_PIN_F1 _GPIO(65) +#define DB8500_PIN_G3 _GPIO(66) +#define DB8500_PIN_G2 _GPIO(67) +#define DB8500_PIN_E1 _GPIO(68) +#define DB8500_PIN_E2 _GPIO(69) +#define DB8500_PIN_G5 _GPIO(70) +#define DB8500_PIN_G4 _GPIO(71) +#define DB8500_PIN_H4 _GPIO(72) +#define DB8500_PIN_H3 _GPIO(73) +#define DB8500_PIN_J3 _GPIO(74) +#define DB8500_PIN_H2 _GPIO(75) +#define DB8500_PIN_J2 _GPIO(76) +#define DB8500_PIN_H1 _GPIO(77) +#define DB8500_PIN_F4 _GPIO(78) +#define DB8500_PIN_E3 _GPIO(79) +#define DB8500_PIN_E4 _GPIO(80) +#define DB8500_PIN_D2 _GPIO(81) +#define DB8500_PIN_C1 _GPIO(82) +#define DB8500_PIN_D3 _GPIO(83) +#define DB8500_PIN_C2 _GPIO(84) +#define DB8500_PIN_D5 _GPIO(85) +#define DB8500_PIN_C6 _GPIO(86) +#define DB8500_PIN_B3 _GPIO(87) +#define DB8500_PIN_C4 _GPIO(88) +#define DB8500_PIN_E6 _GPIO(89) +#define DB8500_PIN_A3 _GPIO(90) +#define DB8500_PIN_B6 _GPIO(91) +#define DB8500_PIN_D6 _GPIO(92) +#define DB8500_PIN_B7 _GPIO(93) +#define DB8500_PIN_D7 _GPIO(94) +#define DB8500_PIN_E8 _GPIO(95) +#define DB8500_PIN_D8 _GPIO(96) +#define DB8500_PIN_D9 _GPIO(97) +/* Hole */ +#define DB8500_PIN_A5 _GPIO(128) +#define DB8500_PIN_B4 _GPIO(129) +#define DB8500_PIN_C8 _GPIO(130) +#define DB8500_PIN_A12 _GPIO(131) +#define DB8500_PIN_C10 _GPIO(132) +#define DB8500_PIN_B10 _GPIO(133) +#define DB8500_PIN_B9 _GPIO(134) +#define DB8500_PIN_A9 _GPIO(135) +#define DB8500_PIN_C7 _GPIO(136) +#define DB8500_PIN_A7 _GPIO(137) +#define DB8500_PIN_C5 _GPIO(138) +#define DB8500_PIN_C9 _GPIO(139) +#define DB8500_PIN_B11 _GPIO(140) +#define DB8500_PIN_C12 _GPIO(141) +#define DB8500_PIN_C11 _GPIO(142) +#define DB8500_PIN_D12 _GPIO(143) +#define DB8500_PIN_B13 _GPIO(144) +#define DB8500_PIN_C13 _GPIO(145) +#define DB8500_PIN_D13 _GPIO(146) +#define DB8500_PIN_C15 _GPIO(147) +#define DB8500_PIN_B16 _GPIO(148) +#define DB8500_PIN_B14 _GPIO(149) +#define DB8500_PIN_C14 _GPIO(150) +#define DB8500_PIN_D17 _GPIO(151) +#define DB8500_PIN_D16 _GPIO(152) +#define DB8500_PIN_B17 _GPIO(153) +#define DB8500_PIN_C16 _GPIO(154) +#define DB8500_PIN_C19 _GPIO(155) +#define DB8500_PIN_C17 _GPIO(156) +#define DB8500_PIN_A18 _GPIO(157) +#define DB8500_PIN_C18 _GPIO(158) +#define DB8500_PIN_B19 _GPIO(159) +#define DB8500_PIN_B20 _GPIO(160) +#define DB8500_PIN_D21 _GPIO(161) +#define DB8500_PIN_D20 _GPIO(162) +#define DB8500_PIN_C20 _GPIO(163) +#define DB8500_PIN_B21 _GPIO(164) +#define DB8500_PIN_C21 _GPIO(165) +#define DB8500_PIN_A22 _GPIO(166) +#define DB8500_PIN_B24 _GPIO(167) +#define DB8500_PIN_C22 _GPIO(168) +#define DB8500_PIN_D22 _GPIO(169) +#define DB8500_PIN_C23 _GPIO(170) +#define DB8500_PIN_D23 _GPIO(171) +/* Hole */ +#define DB8500_PIN_AJ27 _GPIO(192) +#define DB8500_PIN_AH27 _GPIO(193) +#define DB8500_PIN_AF27 _GPIO(194) +#define DB8500_PIN_AG28 _GPIO(195) +#define DB8500_PIN_AG26 _GPIO(196) +#define DB8500_PIN_AH24 _GPIO(197) +#define DB8500_PIN_AG25 _GPIO(198) +#define DB8500_PIN_AH23 _GPIO(199) +#define DB8500_PIN_AH26 _GPIO(200) +#define DB8500_PIN_AF24 _GPIO(201) +#define DB8500_PIN_AF25 _GPIO(202) +#define DB8500_PIN_AE23 _GPIO(203) +#define DB8500_PIN_AF23 _GPIO(204) +#define DB8500_PIN_AG23 _GPIO(205) +#define DB8500_PIN_AG24 _GPIO(206) +#define DB8500_PIN_AJ23 _GPIO(207) +#define DB8500_PIN_AH16 _GPIO(208) +#define DB8500_PIN_AG15 _GPIO(209) +#define DB8500_PIN_AJ15 _GPIO(210) +#define DB8500_PIN_AG14 _GPIO(211) +#define DB8500_PIN_AF13 _GPIO(212) +#define DB8500_PIN_AG13 _GPIO(213) +#define DB8500_PIN_AH15 _GPIO(214) +#define DB8500_PIN_AH13 _GPIO(215) +#define DB8500_PIN_AG12 _GPIO(216) +#define DB8500_PIN_AH12 _GPIO(217) +#define DB8500_PIN_AH11 _GPIO(218) +#define DB8500_PIN_AG10 _GPIO(219) +#define DB8500_PIN_AH10 _GPIO(220) +#define DB8500_PIN_AJ11 _GPIO(221) +#define DB8500_PIN_AJ9 _GPIO(222) +#define DB8500_PIN_AH9 _GPIO(223) +#define DB8500_PIN_AG9 _GPIO(224) +#define DB8500_PIN_AG8 _GPIO(225) +#define DB8500_PIN_AF8 _GPIO(226) +#define DB8500_PIN_AH7 _GPIO(227) +#define DB8500_PIN_AJ6 _GPIO(228) +#define DB8500_PIN_AG7 _GPIO(229) +#define DB8500_PIN_AF7 _GPIO(230) +/* Hole */ +#define DB8500_PIN_AF28 _GPIO(256) +#define DB8500_PIN_AE29 _GPIO(257) +#define DB8500_PIN_AD29 _GPIO(258) +#define DB8500_PIN_AC29 _GPIO(259) +#define DB8500_PIN_AD28 _GPIO(260) +#define DB8500_PIN_AD26 _GPIO(261) +#define DB8500_PIN_AE26 _GPIO(262) +#define DB8500_PIN_AG29 _GPIO(263) +#define DB8500_PIN_AE27 _GPIO(264) +#define DB8500_PIN_AD27 _GPIO(265) +#define DB8500_PIN_AC28 _GPIO(266) +#define DB8500_PIN_AC27 _GPIO(267) + +/* + * The names of the pins are denoted by GPIO number and ball name, even + * though they can be used for other things than GPIO, this is the first + * column in the table of the data sheet and often used on schematics and + * such. + */ +static const struct pinctrl_pin_desc nmk_db8500_pins[] = { + PINCTRL_PIN(DB8500_PIN_AJ5, "GPIO0_AJ5"), + PINCTRL_PIN(DB8500_PIN_AJ3, "GPIO1_AJ3"), + PINCTRL_PIN(DB8500_PIN_AH4, "GPIO2_AH4"), + PINCTRL_PIN(DB8500_PIN_AH3, "GPIO3_AH3"), + PINCTRL_PIN(DB8500_PIN_AH6, "GPIO4_AH6"), + PINCTRL_PIN(DB8500_PIN_AG6, "GPIO5_AG6"), + PINCTRL_PIN(DB8500_PIN_AF6, "GPIO6_AF6"), + PINCTRL_PIN(DB8500_PIN_AG5, "GPIO7_AG5"), + PINCTRL_PIN(DB8500_PIN_AD5, "GPIO8_AD5"), + PINCTRL_PIN(DB8500_PIN_AE4, "GPIO9_AE4"), + PINCTRL_PIN(DB8500_PIN_AF5, "GPIO10_AF5"), + PINCTRL_PIN(DB8500_PIN_AG4, "GPIO11_AG4"), + PINCTRL_PIN(DB8500_PIN_AC4, "GPIO12_AC4"), + PINCTRL_PIN(DB8500_PIN_AF3, "GPIO13_AF3"), + PINCTRL_PIN(DB8500_PIN_AE3, "GPIO14_AE3"), + PINCTRL_PIN(DB8500_PIN_AC3, "GPIO15_AC3"), + PINCTRL_PIN(DB8500_PIN_AD3, "GPIO16_AD3"), + PINCTRL_PIN(DB8500_PIN_AD4, "GPIO17_AD4"), + PINCTRL_PIN(DB8500_PIN_AC2, "GPIO18_AC2"), + PINCTRL_PIN(DB8500_PIN_AC1, "GPIO19_AC1"), + PINCTRL_PIN(DB8500_PIN_AB4, "GPIO20_AB4"), + PINCTRL_PIN(DB8500_PIN_AB3, "GPIO21_AB3"), + PINCTRL_PIN(DB8500_PIN_AA3, "GPIO22_AA3"), + PINCTRL_PIN(DB8500_PIN_AA4, "GPIO23_AA4"), + PINCTRL_PIN(DB8500_PIN_AB2, "GPIO24_AB2"), + PINCTRL_PIN(DB8500_PIN_Y4, "GPIO25_Y4"), + PINCTRL_PIN(DB8500_PIN_Y2, "GPIO26_Y2"), + PINCTRL_PIN(DB8500_PIN_AA2, "GPIO27_AA2"), + PINCTRL_PIN(DB8500_PIN_AA1, "GPIO28_AA1"), + PINCTRL_PIN(DB8500_PIN_W2, "GPIO29_W2"), + PINCTRL_PIN(DB8500_PIN_W3, "GPIO30_W3"), + PINCTRL_PIN(DB8500_PIN_V3, "GPIO31_V3"), + PINCTRL_PIN(DB8500_PIN_V2, "GPIO32_V2"), + PINCTRL_PIN(DB8500_PIN_AF2, "GPIO33_AF2"), + PINCTRL_PIN(DB8500_PIN_AE1, "GPIO34_AE1"), + PINCTRL_PIN(DB8500_PIN_AE2, "GPIO35_AE2"), + PINCTRL_PIN(DB8500_PIN_AG2, "GPIO36_AG2"), + /* Hole */ + PINCTRL_PIN(DB8500_PIN_F3, "GPIO64_F3"), + PINCTRL_PIN(DB8500_PIN_F1, "GPIO65_F1"), + PINCTRL_PIN(DB8500_PIN_G3, "GPIO66_G3"), + PINCTRL_PIN(DB8500_PIN_G2, "GPIO67_G2"), + PINCTRL_PIN(DB8500_PIN_E1, "GPIO68_E1"), + PINCTRL_PIN(DB8500_PIN_E2, "GPIO69_E2"), + PINCTRL_PIN(DB8500_PIN_G5, "GPIO70_G5"), + PINCTRL_PIN(DB8500_PIN_G4, "GPIO71_G4"), + PINCTRL_PIN(DB8500_PIN_H4, "GPIO72_H4"), + PINCTRL_PIN(DB8500_PIN_H3, "GPIO73_H3"), + PINCTRL_PIN(DB8500_PIN_J3, "GPIO74_J3"), + PINCTRL_PIN(DB8500_PIN_H2, "GPIO75_H2"), + PINCTRL_PIN(DB8500_PIN_J2, "GPIO76_J2"), + PINCTRL_PIN(DB8500_PIN_H1, "GPIO77_H1"), + PINCTRL_PIN(DB8500_PIN_F4, "GPIO78_F4"), + PINCTRL_PIN(DB8500_PIN_E3, "GPIO79_E3"), + PINCTRL_PIN(DB8500_PIN_E4, "GPIO80_E4"), + PINCTRL_PIN(DB8500_PIN_D2, "GPIO81_D2"), + PINCTRL_PIN(DB8500_PIN_C1, "GPIO82_C1"), + PINCTRL_PIN(DB8500_PIN_D3, "GPIO83_D3"), + PINCTRL_PIN(DB8500_PIN_C2, "GPIO84_C2"), + PINCTRL_PIN(DB8500_PIN_D5, "GPIO85_D5"), + PINCTRL_PIN(DB8500_PIN_C6, "GPIO86_C6"), + PINCTRL_PIN(DB8500_PIN_B3, "GPIO87_B3"), + PINCTRL_PIN(DB8500_PIN_C4, "GPIO88_C4"), + PINCTRL_PIN(DB8500_PIN_E6, "GPIO89_E6"), + PINCTRL_PIN(DB8500_PIN_A3, "GPIO90_A3"), + PINCTRL_PIN(DB8500_PIN_B6, "GPIO91_B6"), + PINCTRL_PIN(DB8500_PIN_D6, "GPIO92_D6"), + PINCTRL_PIN(DB8500_PIN_B7, "GPIO93_B7"), + PINCTRL_PIN(DB8500_PIN_D7, "GPIO94_D7"), + PINCTRL_PIN(DB8500_PIN_E8, "GPIO95_E8"), + PINCTRL_PIN(DB8500_PIN_D8, "GPIO96_D8"), + PINCTRL_PIN(DB8500_PIN_D9, "GPIO97_D9"), + /* Hole */ + PINCTRL_PIN(DB8500_PIN_A5, "GPIO128_A5"), + PINCTRL_PIN(DB8500_PIN_B4, "GPIO129_B4"), + PINCTRL_PIN(DB8500_PIN_C8, "GPIO130_C8"), + PINCTRL_PIN(DB8500_PIN_A12, "GPIO131_A12"), + PINCTRL_PIN(DB8500_PIN_C10, "GPIO132_C10"), + PINCTRL_PIN(DB8500_PIN_B10, "GPIO133_B10"), + PINCTRL_PIN(DB8500_PIN_B9, "GPIO134_B9"), + PINCTRL_PIN(DB8500_PIN_A9, "GPIO135_A9"), + PINCTRL_PIN(DB8500_PIN_C7, "GPIO136_C7"), + PINCTRL_PIN(DB8500_PIN_A7, "GPIO137_A7"), + PINCTRL_PIN(DB8500_PIN_C5, "GPIO138_C5"), + PINCTRL_PIN(DB8500_PIN_C9, "GPIO139_C9"), + PINCTRL_PIN(DB8500_PIN_B11, "GPIO140_B11"), + PINCTRL_PIN(DB8500_PIN_C12, "GPIO141_C12"), + PINCTRL_PIN(DB8500_PIN_C11, "GPIO142_C11"), + PINCTRL_PIN(DB8500_PIN_D12, "GPIO143_D12"), + PINCTRL_PIN(DB8500_PIN_B13, "GPIO144_B13"), + PINCTRL_PIN(DB8500_PIN_C13, "GPIO145_C13"), + PINCTRL_PIN(DB8500_PIN_D13, "GPIO146_D13"), + PINCTRL_PIN(DB8500_PIN_C15, "GPIO147_C15"), + PINCTRL_PIN(DB8500_PIN_B16, "GPIO148_B16"), + PINCTRL_PIN(DB8500_PIN_B14, "GPIO149_B14"), + PINCTRL_PIN(DB8500_PIN_C14, "GPIO150_C14"), + PINCTRL_PIN(DB8500_PIN_D17, "GPIO151_D17"), + PINCTRL_PIN(DB8500_PIN_D16, "GPIO152_D16"), + PINCTRL_PIN(DB8500_PIN_B17, "GPIO153_B17"), + PINCTRL_PIN(DB8500_PIN_C16, "GPIO154_C16"), + PINCTRL_PIN(DB8500_PIN_C19, "GPIO155_C19"), + PINCTRL_PIN(DB8500_PIN_C17, "GPIO156_C17"), + PINCTRL_PIN(DB8500_PIN_A18, "GPIO157_A18"), + PINCTRL_PIN(DB8500_PIN_C18, "GPIO158_C18"), + PINCTRL_PIN(DB8500_PIN_B19, "GPIO159_B19"), + PINCTRL_PIN(DB8500_PIN_B20, "GPIO160_B20"), + PINCTRL_PIN(DB8500_PIN_D21, "GPIO161_D21"), + PINCTRL_PIN(DB8500_PIN_D20, "GPIO162_D20"), + PINCTRL_PIN(DB8500_PIN_C20, "GPIO163_C20"), + PINCTRL_PIN(DB8500_PIN_B21, "GPIO164_B21"), + PINCTRL_PIN(DB8500_PIN_C21, "GPIO165_C21"), + PINCTRL_PIN(DB8500_PIN_A22, "GPIO166_A22"), + PINCTRL_PIN(DB8500_PIN_B24, "GPIO167_B24"), + PINCTRL_PIN(DB8500_PIN_C22, "GPIO168_C22"), + PINCTRL_PIN(DB8500_PIN_D22, "GPIO169_D22"), + PINCTRL_PIN(DB8500_PIN_C23, "GPIO170_C23"), + PINCTRL_PIN(DB8500_PIN_D23, "GPIO171_D23"), + /* Hole */ + PINCTRL_PIN(DB8500_PIN_AJ27, "GPIO192_AJ27"), + PINCTRL_PIN(DB8500_PIN_AH27, "GPIO193_AH27"), + PINCTRL_PIN(DB8500_PIN_AF27, "GPIO194_AF27"), + PINCTRL_PIN(DB8500_PIN_AG28, "GPIO195_AG28"), + PINCTRL_PIN(DB8500_PIN_AG26, "GPIO196_AG26"), + PINCTRL_PIN(DB8500_PIN_AH24, "GPIO197_AH24"), + PINCTRL_PIN(DB8500_PIN_AG25, "GPIO198_AG25"), + PINCTRL_PIN(DB8500_PIN_AH23, "GPIO199_AH23"), + PINCTRL_PIN(DB8500_PIN_AH26, "GPIO200_AH26"), + PINCTRL_PIN(DB8500_PIN_AF24, "GPIO201_AF24"), + PINCTRL_PIN(DB8500_PIN_AF25, "GPIO202_AF25"), + PINCTRL_PIN(DB8500_PIN_AE23, "GPIO203_AE23"), + PINCTRL_PIN(DB8500_PIN_AF23, "GPIO204_AF23"), + PINCTRL_PIN(DB8500_PIN_AG23, "GPIO205_AG23"), + PINCTRL_PIN(DB8500_PIN_AG24, "GPIO206_AG24"), + PINCTRL_PIN(DB8500_PIN_AJ23, "GPIO207_AJ23"), + PINCTRL_PIN(DB8500_PIN_AH16, "GPIO208_AH16"), + PINCTRL_PIN(DB8500_PIN_AG15, "GPIO209_AG15"), + PINCTRL_PIN(DB8500_PIN_AJ15, "GPIO210_AJ15"), + PINCTRL_PIN(DB8500_PIN_AG14, "GPIO211_AG14"), + PINCTRL_PIN(DB8500_PIN_AF13, "GPIO212_AF13"), + PINCTRL_PIN(DB8500_PIN_AG13, "GPIO213_AG13"), + PINCTRL_PIN(DB8500_PIN_AH15, "GPIO214_AH15"), + PINCTRL_PIN(DB8500_PIN_AH13, "GPIO215_AH13"), + PINCTRL_PIN(DB8500_PIN_AG12, "GPIO216_AG12"), + PINCTRL_PIN(DB8500_PIN_AH12, "GPIO217_AH12"), + PINCTRL_PIN(DB8500_PIN_AH11, "GPIO218_AH11"), + PINCTRL_PIN(DB8500_PIN_AG10, "GPIO219_AG10"), + PINCTRL_PIN(DB8500_PIN_AH10, "GPIO220_AH10"), + PINCTRL_PIN(DB8500_PIN_AJ11, "GPIO221_AJ11"), + PINCTRL_PIN(DB8500_PIN_AJ9, "GPIO222_AJ9"), + PINCTRL_PIN(DB8500_PIN_AH9, "GPIO223_AH9"), + PINCTRL_PIN(DB8500_PIN_AG9, "GPIO224_AG9"), + PINCTRL_PIN(DB8500_PIN_AG8, "GPIO225_AG8"), + PINCTRL_PIN(DB8500_PIN_AF8, "GPIO226_AF8"), + PINCTRL_PIN(DB8500_PIN_AH7, "GPIO227_AH7"), + PINCTRL_PIN(DB8500_PIN_AJ6, "GPIO228_AJ6"), + PINCTRL_PIN(DB8500_PIN_AG7, "GPIO229_AG7"), + PINCTRL_PIN(DB8500_PIN_AF7, "GPIO230_AF7"), + /* Hole */ + PINCTRL_PIN(DB8500_PIN_AF28, "GPIO256_AF28"), + PINCTRL_PIN(DB8500_PIN_AE29, "GPIO257_AE29"), + PINCTRL_PIN(DB8500_PIN_AD29, "GPIO258_AD29"), + PINCTRL_PIN(DB8500_PIN_AC29, "GPIO259_AC29"), + PINCTRL_PIN(DB8500_PIN_AD28, "GPIO260_AD28"), + PINCTRL_PIN(DB8500_PIN_AD26, "GPIO261_AD26"), + PINCTRL_PIN(DB8500_PIN_AE26, "GPIO262_AE26"), + PINCTRL_PIN(DB8500_PIN_AG29, "GPIO263_AG29"), + PINCTRL_PIN(DB8500_PIN_AE27, "GPIO264_AE27"), + PINCTRL_PIN(DB8500_PIN_AD27, "GPIO265_AD27"), + PINCTRL_PIN(DB8500_PIN_AC28, "GPIO266_AC28"), + PINCTRL_PIN(DB8500_PIN_AC27, "GPIO267_AC27"), +}; + +#define DB8500_GPIO_RANGE(a, b, c) { .name = "DB8500", .id = a, .base = b, \ + .pin_base = b, .npins = c } + +/* + * This matches the 32-pin gpio chips registered by the GPIO portion. This + * cannot be const since we assign the struct gpio_chip * pointer at runtime. + */ +static struct pinctrl_gpio_range nmk_db8500_ranges[] = { + DB8500_GPIO_RANGE(0, 0, 32), + DB8500_GPIO_RANGE(1, 32, 5), + DB8500_GPIO_RANGE(2, 64, 32), + DB8500_GPIO_RANGE(3, 96, 2), + DB8500_GPIO_RANGE(4, 128, 32), + DB8500_GPIO_RANGE(5, 160, 12), + DB8500_GPIO_RANGE(6, 192, 32), + DB8500_GPIO_RANGE(7, 224, 7), + DB8500_GPIO_RANGE(8, 256, 12), +}; + +/* + * Read the pin group names like this: + * u0_a_1 = first groups of pins for uart0 on alt function a + * i2c2_b_2 = second group of pins for i2c2 on alt function b + * + * The groups are arranged as sets per altfunction column, so we can + * mux in one group at a time by selecting the same altfunction for them + * all. When functions require pins on different altfunctions, you need + * to combine several groups. + */ + +/* Altfunction A column */ +static const unsigned u0_a_1_pins[] = { DB8500_PIN_AJ5, DB8500_PIN_AJ3, + DB8500_PIN_AH4, DB8500_PIN_AH3 }; +static const unsigned u1rxtx_a_1_pins[] = { DB8500_PIN_AH6, DB8500_PIN_AG6 }; +static const unsigned u1ctsrts_a_1_pins[] = { DB8500_PIN_AF6, DB8500_PIN_AG5 }; +/* Image processor I2C line, this is driven by image processor firmware */ +static const unsigned ipi2c_a_1_pins[] = { DB8500_PIN_AD5, DB8500_PIN_AE4 }; +static const unsigned ipi2c_a_2_pins[] = { DB8500_PIN_AF5, DB8500_PIN_AG4 }; +/* MSP0 can only be on these pins, but TXD and RXD can be flipped */ +static const unsigned msp0txrx_a_1_pins[] = { DB8500_PIN_AC4, DB8500_PIN_AC3 }; +static const unsigned msp0tfstck_a_1_pins[] = { DB8500_PIN_AF3, DB8500_PIN_AE3 }; +static const unsigned msp0rfsrck_a_1_pins[] = { DB8500_PIN_AD3, DB8500_PIN_AD4 }; +/* Basic pins of the MMC/SD card 0 interface */ +static const unsigned mc0_a_1_pins[] = { DB8500_PIN_AC2, DB8500_PIN_AC1, + DB8500_PIN_AB4, DB8500_PIN_AA3, DB8500_PIN_AA4, DB8500_PIN_AB2, + DB8500_PIN_Y4, DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 }; +/* Often only 4 bits are used, then these are not needed (only used for MMC) */ +static const unsigned mc0_dat47_a_1_pins[] = { DB8500_PIN_W2, DB8500_PIN_W3, + DB8500_PIN_V3, DB8500_PIN_V2}; +static const unsigned mc0dat31dir_a_1_pins[] = { DB8500_PIN_AB3 }; +/* MSP1 can only be on these pins, but TXD and RXD can be flipped */ +static const unsigned msp1txrx_a_1_pins[] = { DB8500_PIN_AF2, DB8500_PIN_AG2 }; +static const unsigned msp1_a_1_pins[] = { DB8500_PIN_AE1, DB8500_PIN_AE2 }; +/* LCD interface */ +static const unsigned lcdb_a_1_pins[] = { DB8500_PIN_F3, DB8500_PIN_F1, + DB8500_PIN_G3, DB8500_PIN_G2 }; +static const unsigned lcdvsi0_a_1_pins[] = { DB8500_PIN_E1 }; +static const unsigned lcdvsi1_a_1_pins[] = { DB8500_PIN_E2 }; +static const unsigned lcd_d0_d7_a_1_pins[] = { + DB8500_PIN_G5, DB8500_PIN_G4, DB8500_PIN_H4, DB8500_PIN_H3, + DB8500_PIN_J3, DB8500_PIN_H2, DB8500_PIN_J2, DB8500_PIN_H1 }; +/* D8 thru D11 often used as TVOUT lines */ +static const unsigned lcd_d8_d11_a_1_pins[] = { DB8500_PIN_F4, + DB8500_PIN_E3, DB8500_PIN_E4, DB8500_PIN_D2 }; +static const unsigned lcd_d12_d23_a_1_pins[] = { + DB8500_PIN_C1, DB8500_PIN_D3, DB8500_PIN_C2, DB8500_PIN_D5, + DB8500_PIN_C6, DB8500_PIN_B3, DB8500_PIN_C4, DB8500_PIN_E6, + DB8500_PIN_A3, DB8500_PIN_B6, DB8500_PIN_D6, DB8500_PIN_B7 }; +static const unsigned kp_a_1_pins[] = { DB8500_PIN_D7, DB8500_PIN_E8, + DB8500_PIN_D8, DB8500_PIN_D9 }; +static const unsigned kpskaskb_a_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16 }; +static const unsigned kp_a_2_pins[] = { + DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17, + DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20, + DB8500_PIN_D21, DB8500_PIN_D20, DB8500_PIN_C20, DB8500_PIN_B21, + DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 }; +/* MC2 has 8 data lines and no direction control, so only for (e)MMC */ +static const unsigned mc2_a_1_pins[] = { DB8500_PIN_A5, DB8500_PIN_B4, + DB8500_PIN_C8, DB8500_PIN_A12, DB8500_PIN_C10, DB8500_PIN_B10, + DB8500_PIN_B9, DB8500_PIN_A9, DB8500_PIN_C7, DB8500_PIN_A7, + DB8500_PIN_C5 }; +static const unsigned ssp1_a_1_pins[] = { DB8500_PIN_C9, DB8500_PIN_B11, + DB8500_PIN_C12, DB8500_PIN_C11 }; +static const unsigned ssp0_a_1_pins[] = { DB8500_PIN_D12, DB8500_PIN_B13, + DB8500_PIN_C13, DB8500_PIN_D13 }; +static const unsigned i2c0_a_1_pins[] = { DB8500_PIN_C15, DB8500_PIN_B16 }; +/* + * Image processor GPIO pins are named "ipgpio" and have their own + * numberspace + */ +static const unsigned ipgpio0_a_1_pins[] = { DB8500_PIN_B14 }; +static const unsigned ipgpio1_a_1_pins[] = { DB8500_PIN_C14 }; +/* Three modem pins named RF_PURn, MODEM_STATE and MODEM_PWREN */ +static const unsigned modem_a_1_pins[] = { DB8500_PIN_D22, DB8500_PIN_C23, + DB8500_PIN_D23 }; +/* + * This MSP cannot switch RX and TX, SCK in a separate group since this + * seems to be optional. + */ +static const unsigned msp2sck_a_1_pins[] = { DB8500_PIN_AJ27 }; +static const unsigned msp2_a_1_pins[] = { DB8500_PIN_AH27, DB8500_PIN_AF27, + DB8500_PIN_AG28, DB8500_PIN_AG26 }; +static const unsigned mc4_a_1_pins[] = { DB8500_PIN_AH24, DB8500_PIN_AG25, + DB8500_PIN_AH23, DB8500_PIN_AH26, DB8500_PIN_AF24, DB8500_PIN_AF25, + DB8500_PIN_AE23, DB8500_PIN_AF23, DB8500_PIN_AG23, DB8500_PIN_AG24, + DB8500_PIN_AJ23 }; +/* MC1 has only 4 data pins, designed for SD or SDIO exclusively */ +static const unsigned mc1_a_1_pins[] = { DB8500_PIN_AH16, DB8500_PIN_AG15, + DB8500_PIN_AJ15, DB8500_PIN_AG14, DB8500_PIN_AF13, DB8500_PIN_AG13, + DB8500_PIN_AH15 }; +static const unsigned mc1_a_2_pins[] = { DB8500_PIN_AH16, DB8500_PIN_AJ15, + DB8500_PIN_AG14, DB8500_PIN_AF13, DB8500_PIN_AG13, DB8500_PIN_AH15 }; +static const unsigned mc1dir_a_1_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AG12, + DB8500_PIN_AH12, DB8500_PIN_AH11 }; +static const unsigned hsir_a_1_pins[] = { DB8500_PIN_AG10, DB8500_PIN_AH10, + DB8500_PIN_AJ11 }; +static const unsigned hsit_a_1_pins[] = { DB8500_PIN_AJ9, DB8500_PIN_AH9, + DB8500_PIN_AG9, DB8500_PIN_AG8, DB8500_PIN_AF8 }; +static const unsigned hsit_a_2_pins[] = { DB8500_PIN_AJ9, DB8500_PIN_AH9, + DB8500_PIN_AG9, DB8500_PIN_AG8 }; +static const unsigned clkout1_a_1_pins[] = { DB8500_PIN_AH7 }; +static const unsigned clkout1_a_2_pins[] = { DB8500_PIN_AG7 }; +static const unsigned clkout2_a_1_pins[] = { DB8500_PIN_AJ6 }; +static const unsigned clkout2_a_2_pins[] = { DB8500_PIN_AF7 }; +static const unsigned usb_a_1_pins[] = { DB8500_PIN_AF28, DB8500_PIN_AE29, + DB8500_PIN_AD29, DB8500_PIN_AC29, DB8500_PIN_AD28, DB8500_PIN_AD26, + DB8500_PIN_AE26, DB8500_PIN_AG29, DB8500_PIN_AE27, DB8500_PIN_AD27, + DB8500_PIN_AC28, DB8500_PIN_AC27 }; + +/* Altfunction B column */ +static const unsigned trig_b_1_pins[] = { DB8500_PIN_AJ5, DB8500_PIN_AJ3 }; +static const unsigned i2c4_b_1_pins[] = { DB8500_PIN_AH6, DB8500_PIN_AG6 }; +static const unsigned i2c1_b_1_pins[] = { DB8500_PIN_AF6, DB8500_PIN_AG5 }; +static const unsigned i2c2_b_1_pins[] = { DB8500_PIN_AD5, DB8500_PIN_AE4 }; +static const unsigned i2c2_b_2_pins[] = { DB8500_PIN_AF5, DB8500_PIN_AG4 }; +static const unsigned msp0txrx_b_1_pins[] = { DB8500_PIN_AC4, DB8500_PIN_AC3 }; +static const unsigned i2c1_b_2_pins[] = { DB8500_PIN_AD3, DB8500_PIN_AD4 }; +/* Just RX and TX for UART2 */ +static const unsigned u2rxtx_b_1_pins[] = { DB8500_PIN_AC2, DB8500_PIN_AC1 }; +static const unsigned uartmodtx_b_1_pins[] = { DB8500_PIN_AB4 }; +static const unsigned msp0sck_b_1_pins[] = { DB8500_PIN_AB3 }; +static const unsigned uartmodrx_b_1_pins[] = { DB8500_PIN_AA3 }; +static const unsigned stmmod_b_1_pins[] = { DB8500_PIN_AA4, DB8500_PIN_Y4, + DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 }; +static const unsigned uartmodrx_b_2_pins[] = { DB8500_PIN_AB2 }; +static const unsigned spi3_b_1_pins[] = { DB8500_PIN_W2, DB8500_PIN_W3, + DB8500_PIN_V3, DB8500_PIN_V2 }; +static const unsigned msp1txrx_b_1_pins[] = { DB8500_PIN_AF2, DB8500_PIN_AG2 }; +static const unsigned kp_b_1_pins[] = { DB8500_PIN_F3, DB8500_PIN_F1, + DB8500_PIN_G3, DB8500_PIN_G2, DB8500_PIN_E1, DB8500_PIN_E2, + DB8500_PIN_G5, DB8500_PIN_G4, DB8500_PIN_H4, DB8500_PIN_H3, + DB8500_PIN_J3, DB8500_PIN_H2, DB8500_PIN_J2, DB8500_PIN_H1, + DB8500_PIN_F4, DB8500_PIN_E3, DB8500_PIN_E4, DB8500_PIN_D2, + DB8500_PIN_C1, DB8500_PIN_D3, DB8500_PIN_C2, DB8500_PIN_D5 }; +static const unsigned kp_b_2_pins[] = { DB8500_PIN_F3, DB8500_PIN_F1, + DB8500_PIN_G3, DB8500_PIN_G2, DB8500_PIN_F4, DB8500_PIN_E3}; +static const unsigned sm_b_1_pins[] = { DB8500_PIN_C6, DB8500_PIN_B3, + DB8500_PIN_C4, DB8500_PIN_E6, DB8500_PIN_A3, DB8500_PIN_B6, + DB8500_PIN_D6, DB8500_PIN_B7, DB8500_PIN_D7, DB8500_PIN_D8, + DB8500_PIN_D9, DB8500_PIN_A5, DB8500_PIN_B4, DB8500_PIN_C8, + DB8500_PIN_A12, DB8500_PIN_C10, DB8500_PIN_B10, DB8500_PIN_B9, + DB8500_PIN_A9, DB8500_PIN_C7, DB8500_PIN_A7, DB8500_PIN_C5, + DB8500_PIN_C9 }; +/* This chip select pin can be "ps0" in alt C so have it separately */ +static const unsigned smcs0_b_1_pins[] = { DB8500_PIN_E8 }; +/* This chip select pin can be "ps1" in alt C so have it separately */ +static const unsigned smcs1_b_1_pins[] = { DB8500_PIN_B14 }; +static const unsigned ipgpio7_b_1_pins[] = { DB8500_PIN_B11 }; +static const unsigned ipgpio2_b_1_pins[] = { DB8500_PIN_C12 }; +static const unsigned ipgpio3_b_1_pins[] = { DB8500_PIN_C11 }; +static const unsigned lcdaclk_b_1_pins[] = { DB8500_PIN_C14 }; +static const unsigned lcda_b_1_pins[] = { DB8500_PIN_D22, + DB8500_PIN_C23, DB8500_PIN_D23 }; +static const unsigned lcd_b_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16, + DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17, + DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20, + DB8500_PIN_D21, DB8500_PIN_D20, DB8500_PIN_C20, DB8500_PIN_B21, + DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 }; +static const unsigned ddrtrig_b_1_pins[] = { DB8500_PIN_AJ27 }; +static const unsigned pwl_b_1_pins[] = { DB8500_PIN_AF25 }; +static const unsigned spi1_b_1_pins[] = { DB8500_PIN_AG15, DB8500_PIN_AF13, + DB8500_PIN_AG13, DB8500_PIN_AH15 }; +static const unsigned mc3_b_1_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AG12, + DB8500_PIN_AH12, DB8500_PIN_AH11, DB8500_PIN_AG10, DB8500_PIN_AH10, + DB8500_PIN_AJ11, DB8500_PIN_AJ9, DB8500_PIN_AH9, DB8500_PIN_AG9, + DB8500_PIN_AG8 }; +static const unsigned pwl_b_2_pins[] = { DB8500_PIN_AF8 }; +static const unsigned pwl_b_3_pins[] = { DB8500_PIN_AG7 }; +static const unsigned pwl_b_4_pins[] = { DB8500_PIN_AF7 }; + +/* Altfunction C column */ +static const unsigned ipjtag_c_1_pins[] = { DB8500_PIN_AJ5, DB8500_PIN_AJ3, + DB8500_PIN_AH4, DB8500_PIN_AH3, DB8500_PIN_AH6 }; +static const unsigned ipgpio6_c_1_pins[] = { DB8500_PIN_AG6 }; +static const unsigned ipgpio0_c_1_pins[] = { DB8500_PIN_AF6 }; +static const unsigned ipgpio1_c_1_pins[] = { DB8500_PIN_AG5 }; +static const unsigned ipgpio3_c_1_pins[] = { DB8500_PIN_AF5 }; +static const unsigned ipgpio2_c_1_pins[] = { DB8500_PIN_AG4 }; +static const unsigned slim0_c_1_pins[] = { DB8500_PIN_AD3, DB8500_PIN_AD4 }; +/* Optional 4-bit Memory Stick interface */ +static const unsigned ms_c_1_pins[] = { DB8500_PIN_AC2, DB8500_PIN_AC1, + DB8500_PIN_AB3, DB8500_PIN_AA3, DB8500_PIN_AA4, DB8500_PIN_AB2, + DB8500_PIN_Y4, DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 }; +static const unsigned iptrigout_c_1_pins[] = { DB8500_PIN_AB4 }; +static const unsigned u2rxtx_c_1_pins[] = { DB8500_PIN_W2, DB8500_PIN_W3 }; +static const unsigned u2ctsrts_c_1_pins[] = { DB8500_PIN_V3, DB8500_PIN_V2 }; +static const unsigned u0_c_1_pins[] = { DB8500_PIN_AF2, DB8500_PIN_AE1, + DB8500_PIN_AE2, DB8500_PIN_AG2 }; +static const unsigned ipgpio4_c_1_pins[] = { DB8500_PIN_F3 }; +static const unsigned ipgpio5_c_1_pins[] = { DB8500_PIN_F1 }; +static const unsigned ipgpio6_c_2_pins[] = { DB8500_PIN_G3 }; +static const unsigned ipgpio7_c_1_pins[] = { DB8500_PIN_G2 }; +static const unsigned smcleale_c_1_pins[] = { DB8500_PIN_E1, DB8500_PIN_E2 }; +static const unsigned stmape_c_1_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4, + DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3 }; +static const unsigned u2rxtx_c_2_pins[] = { DB8500_PIN_H2, DB8500_PIN_J2 }; +static const unsigned ipgpio2_c_2_pins[] = { DB8500_PIN_F4 }; +static const unsigned ipgpio3_c_2_pins[] = { DB8500_PIN_E3 }; +static const unsigned ipgpio4_c_2_pins[] = { DB8500_PIN_E4 }; +static const unsigned ipgpio5_c_2_pins[] = { DB8500_PIN_D2 }; +static const unsigned mc5_c_1_pins[] = { DB8500_PIN_C6, DB8500_PIN_B3, + DB8500_PIN_C4, DB8500_PIN_E6, DB8500_PIN_A3, DB8500_PIN_B6, + DB8500_PIN_D6, DB8500_PIN_B7, DB8500_PIN_D7, DB8500_PIN_D8, + DB8500_PIN_D9 }; +static const unsigned mc2rstn_c_1_pins[] = { DB8500_PIN_C8 }; +static const unsigned kp_c_1_pins[] = { DB8500_PIN_C9, DB8500_PIN_B11, + DB8500_PIN_C12, DB8500_PIN_C11, DB8500_PIN_D17, DB8500_PIN_D16, + DB8500_PIN_C23, DB8500_PIN_D23 }; +static const unsigned smps0_c_1_pins[] = { DB8500_PIN_E8 }; +static const unsigned smps1_c_1_pins[] = { DB8500_PIN_B14 }; +static const unsigned u2rxtx_c_3_pins[] = { DB8500_PIN_B17, DB8500_PIN_C16 }; +static const unsigned stmape_c_2_pins[] = { DB8500_PIN_C19, DB8500_PIN_C17, + DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19 }; +static const unsigned uartmodrx_c_1_pins[] = { DB8500_PIN_D21 }; +static const unsigned uartmodtx_c_1_pins[] = { DB8500_PIN_D20 }; +static const unsigned stmmod_c_1_pins[] = { DB8500_PIN_C20, DB8500_PIN_B21, + DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24 }; +static const unsigned usbsim_c_1_pins[] = { DB8500_PIN_D22 }; +static const unsigned mc4rstn_c_1_pins[] = { DB8500_PIN_AF25 }; +static const unsigned clkout1_c_1_pins[] = { DB8500_PIN_AH13 }; +static const unsigned clkout2_c_1_pins[] = { DB8500_PIN_AH12 }; +static const unsigned i2c3_c_1_pins[] = { DB8500_PIN_AG12, DB8500_PIN_AH11 }; +static const unsigned spi0_c_1_pins[] = { DB8500_PIN_AH10, DB8500_PIN_AH9, + DB8500_PIN_AG9, DB8500_PIN_AG8 }; +static const unsigned usbsim_c_2_pins[] = { DB8500_PIN_AF8 }; +static const unsigned i2c3_c_2_pins[] = { DB8500_PIN_AG7, DB8500_PIN_AF7 }; + +/* Other C1 column */ +static const unsigned u2rx_oc1_1_pins[] = { DB8500_PIN_AB2 }; +static const unsigned stmape_oc1_1_pins[] = { DB8500_PIN_AA4, DB8500_PIN_Y4, + DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 }; +static const unsigned remap0_oc1_1_pins[] = { DB8500_PIN_E1 }; +static const unsigned remap1_oc1_1_pins[] = { DB8500_PIN_E2 }; +static const unsigned ptma9_oc1_1_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4, + DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3, DB8500_PIN_H2, + DB8500_PIN_J2, DB8500_PIN_H1 }; +static const unsigned kp_oc1_1_pins[] = { DB8500_PIN_C6, DB8500_PIN_B3, + DB8500_PIN_C4, DB8500_PIN_E6, DB8500_PIN_A3, DB8500_PIN_B6, + DB8500_PIN_D6, DB8500_PIN_B7 }; +static const unsigned rf_oc1_1_pins[] = { DB8500_PIN_D8, DB8500_PIN_D9 }; +static const unsigned hxclk_oc1_1_pins[] = { DB8500_PIN_D16 }; +static const unsigned uartmodrx_oc1_1_pins[] = { DB8500_PIN_B17 }; +static const unsigned uartmodtx_oc1_1_pins[] = { DB8500_PIN_C16 }; +static const unsigned stmmod_oc1_1_pins[] = { DB8500_PIN_C19, DB8500_PIN_C17, + DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19 }; +static const unsigned hxgpio_oc1_1_pins[] = { DB8500_PIN_D21, DB8500_PIN_D20, + DB8500_PIN_C20, DB8500_PIN_B21, DB8500_PIN_C21, DB8500_PIN_A22, + DB8500_PIN_B24, DB8500_PIN_C22 }; +static const unsigned rf_oc1_2_pins[] = { DB8500_PIN_C23, DB8500_PIN_D23 }; +static const unsigned spi2_oc1_1_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AG12, + DB8500_PIN_AH12, DB8500_PIN_AH11 }; +static const unsigned spi2_oc1_2_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AH12, + DB8500_PIN_AH11 }; + +/* Other C2 column */ +static const unsigned sbag_oc2_1_pins[] = { DB8500_PIN_AA4, DB8500_PIN_AB2, + DB8500_PIN_Y4, DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 }; +static const unsigned etmr4_oc2_1_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4, + DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3, DB8500_PIN_H2, + DB8500_PIN_J2, DB8500_PIN_H1 }; +static const unsigned ptma9_oc2_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16, + DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17, + DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20, + DB8500_PIN_D21, DB8500_PIN_D20, DB8500_PIN_C20, DB8500_PIN_B21, + DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 }; + +/* Other C3 column */ +static const unsigned stmmod_oc3_1_pins[] = { DB8500_PIN_AB2, DB8500_PIN_W2, + DB8500_PIN_W3, DB8500_PIN_V3, DB8500_PIN_V2 }; +static const unsigned stmmod_oc3_2_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4, + DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3 }; +static const unsigned uartmodrx_oc3_1_pins[] = { DB8500_PIN_H2 }; +static const unsigned uartmodtx_oc3_1_pins[] = { DB8500_PIN_J2 }; +static const unsigned etmr4_oc3_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16, + DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17, + DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20, + DB8500_PIN_D21, DB8500_PIN_D20, DB8500_PIN_C20, DB8500_PIN_B21, + DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 }; + +/* Other C4 column */ +static const unsigned sbag_oc4_1_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4, + DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3, DB8500_PIN_H1 }; +static const unsigned hwobs_oc4_1_pins[] = { DB8500_PIN_D17, DB8500_PIN_D16, + DB8500_PIN_B17, DB8500_PIN_C16, DB8500_PIN_C19, DB8500_PIN_C17, + DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19, DB8500_PIN_B20, + DB8500_PIN_D21, DB8500_PIN_D20, DB8500_PIN_C20, DB8500_PIN_B21, + DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 }; + +#define DB8500_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins, \ + .npins = ARRAY_SIZE(a##_pins), .altsetting = b } + +static const struct nmk_pingroup nmk_db8500_groups[] = { + /* Altfunction A column */ + DB8500_PIN_GROUP(u0_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(u1rxtx_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(u1ctsrts_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(ipi2c_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(ipi2c_a_2, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(msp0txrx_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(msp0tfstck_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(msp0rfsrck_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(mc0_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(mc0_dat47_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(mc0dat31dir_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(msp1txrx_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(msp1_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(lcdb_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(lcdvsi0_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(lcdvsi1_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(lcd_d0_d7_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(lcd_d8_d11_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(lcd_d12_d23_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(kp_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(mc2_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(ssp1_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(ssp0_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(i2c0_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(ipgpio0_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(ipgpio1_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(kp_a_2, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(msp2sck_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(msp2_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(mc4_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(mc1_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(mc1_a_2, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(hsir_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(hsit_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(hsit_a_2, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(clkout1_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(clkout1_a_2, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(clkout2_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(clkout2_a_2, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(usb_a_1, NMK_GPIO_ALT_A), + /* Altfunction B column */ + DB8500_PIN_GROUP(trig_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(i2c4_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(i2c1_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(i2c2_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(i2c2_b_2, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(msp0txrx_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(i2c1_b_2, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(u2rxtx_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(uartmodtx_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(msp0sck_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(uartmodrx_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(stmmod_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(uartmodrx_b_2, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(spi3_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(msp1txrx_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(kp_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(kp_b_2, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(sm_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(smcs0_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(smcs1_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(ipgpio7_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(ipgpio2_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(ipgpio3_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(lcdaclk_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(lcda_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(lcd_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(ddrtrig_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(pwl_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(spi1_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(mc3_b_1, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(pwl_b_2, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(pwl_b_3, NMK_GPIO_ALT_B), + DB8500_PIN_GROUP(pwl_b_4, NMK_GPIO_ALT_B), + /* Altfunction C column */ + DB8500_PIN_GROUP(ipjtag_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(ipgpio6_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(ipgpio0_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(ipgpio1_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(ipgpio3_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(ipgpio2_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(slim0_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(ms_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(iptrigout_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(u2rxtx_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(u2ctsrts_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(u0_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(ipgpio4_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(ipgpio5_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(ipgpio6_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(ipgpio7_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(smcleale_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(stmape_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(u2rxtx_c_2, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(ipgpio2_c_2, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(ipgpio3_c_2, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(ipgpio4_c_2, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(ipgpio5_c_2, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(mc5_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(mc2rstn_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(kp_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(smps0_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(smps1_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(u2rxtx_c_3, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(stmape_c_2, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(uartmodrx_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(uartmodtx_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(stmmod_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(usbsim_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(mc4rstn_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(clkout1_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(clkout2_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(i2c3_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(spi0_c_1, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(usbsim_c_2, NMK_GPIO_ALT_C), + DB8500_PIN_GROUP(i2c3_c_2, NMK_GPIO_ALT_C), + /* Other alt C1 column */ + DB8500_PIN_GROUP(u2rx_oc1_1, NMK_GPIO_ALT_C1), + DB8500_PIN_GROUP(stmape_oc1_1, NMK_GPIO_ALT_C1), + DB8500_PIN_GROUP(remap0_oc1_1, NMK_GPIO_ALT_C1), + DB8500_PIN_GROUP(remap1_oc1_1, NMK_GPIO_ALT_C1), + DB8500_PIN_GROUP(ptma9_oc1_1, NMK_GPIO_ALT_C1), + DB8500_PIN_GROUP(kp_oc1_1, NMK_GPIO_ALT_C1), + DB8500_PIN_GROUP(rf_oc1_1, NMK_GPIO_ALT_C1), + DB8500_PIN_GROUP(hxclk_oc1_1, NMK_GPIO_ALT_C1), + DB8500_PIN_GROUP(uartmodrx_oc1_1, NMK_GPIO_ALT_C1), + DB8500_PIN_GROUP(uartmodtx_oc1_1, NMK_GPIO_ALT_C1), + DB8500_PIN_GROUP(stmmod_oc1_1, NMK_GPIO_ALT_C1), + DB8500_PIN_GROUP(hxgpio_oc1_1, NMK_GPIO_ALT_C1), + DB8500_PIN_GROUP(rf_oc1_2, NMK_GPIO_ALT_C1), + DB8500_PIN_GROUP(spi2_oc1_1, NMK_GPIO_ALT_C1), + DB8500_PIN_GROUP(spi2_oc1_2, NMK_GPIO_ALT_C1), + /* Other alt C2 column */ + DB8500_PIN_GROUP(sbag_oc2_1, NMK_GPIO_ALT_C2), + DB8500_PIN_GROUP(etmr4_oc2_1, NMK_GPIO_ALT_C2), + DB8500_PIN_GROUP(ptma9_oc2_1, NMK_GPIO_ALT_C2), + /* Other alt C3 column */ + DB8500_PIN_GROUP(stmmod_oc3_1, NMK_GPIO_ALT_C3), + DB8500_PIN_GROUP(stmmod_oc3_2, NMK_GPIO_ALT_C3), + DB8500_PIN_GROUP(uartmodrx_oc3_1, NMK_GPIO_ALT_C3), + DB8500_PIN_GROUP(uartmodtx_oc3_1, NMK_GPIO_ALT_C3), + DB8500_PIN_GROUP(etmr4_oc3_1, NMK_GPIO_ALT_C3), + /* Other alt C4 column */ + DB8500_PIN_GROUP(sbag_oc4_1, NMK_GPIO_ALT_C4), + DB8500_PIN_GROUP(hwobs_oc4_1, NMK_GPIO_ALT_C4), +}; + +/* We use this macro to define the groups applicable to a function */ +#define DB8500_FUNC_GROUPS(a, b...) \ +static const char * const a##_groups[] = { b }; + +DB8500_FUNC_GROUPS(u0, "u0_a_1", "u0_c_1"); +DB8500_FUNC_GROUPS(u1, "u1rxtx_a_1", "u1ctsrts_a_1"); +/* + * UART2 can be muxed out with just RX/TX in four places, CTS+RTS is however + * only available on two pins in alternative function C + */ +DB8500_FUNC_GROUPS(u2, "u2rxtx_b_1", "u2rxtx_c_1", "u2ctsrts_c_1", + "u2rxtx_c_2", "u2rxtx_c_3", "u2rx_oc1_1"); +DB8500_FUNC_GROUPS(ipi2c, "ipi2c_a_1", "ipi2c_a_2"); +/* + * MSP0 can only be on a certain set of pins, but the TX/RX pins can be + * switched around by selecting the altfunction A or B. The SCK pin is + * only available on the altfunction B. + */ +DB8500_FUNC_GROUPS(msp0, "msp0txrx_a_1", "msp0tfstck_a_1", "msp0rfstck_a_1", + "msp0txrx_b_1", "msp0sck_b_1"); +DB8500_FUNC_GROUPS(mc0, "mc0_a_1", "mc0_dat47_a_1", "mc0dat31dir_a_1"); +/* MSP0 can swap RX/TX like MSP0 but has no SCK pin available */ +DB8500_FUNC_GROUPS(msp1, "msp1txrx_a_1", "msp1_a_1", "msp1txrx_b_1"); +DB8500_FUNC_GROUPS(lcdb, "lcdb_a_1"); +DB8500_FUNC_GROUPS(lcd, "lcdvsi0_a_1", "lcdvsi1_a_1", "lcd_d0_d7_a_1", + "lcd_d8_d11_a_1", "lcd_d12_d23_a_1", "lcd_b_1"); +DB8500_FUNC_GROUPS(kp, "kp_a_1", "kp_a_2", "kp_b_1", "kp_b_2", "kp_c_1", "kp_oc1_1"); +DB8500_FUNC_GROUPS(mc2, "mc2_a_1", "mc2rstn_c_1"); +DB8500_FUNC_GROUPS(ssp1, "ssp1_a_1"); +DB8500_FUNC_GROUPS(ssp0, "ssp0_a_1"); +DB8500_FUNC_GROUPS(i2c0, "i2c0_a_1"); +/* The image processor has 8 GPIO pins that can be muxed out */ +DB8500_FUNC_GROUPS(ipgpio, "ipgpio0_a_1", "ipgpio1_a_1", "ipgpio7_b_1", + "ipgpio2_b_1", "ipgpio3_b_1", "ipgpio6_c_1", "ipgpio0_c_1", + "ipgpio1_c_1", "ipgpio3_c_1", "ipgpio2_c_1", "ipgpio4_c_1", + "ipgpio5_c_1", "ipgpio6_c_2", "ipgpio7_c_1", "ipgpio2_c_2", + "ipgpio3_c_2", "ipgpio4_c_2", "ipgpio5_c_2"); +/* MSP2 can not invert the RX/TX pins but has the optional SCK pin */ +DB8500_FUNC_GROUPS(msp2, "msp2sck_a_1", "msp2_a_1"); +DB8500_FUNC_GROUPS(mc4, "mc4_a_1", "mc4rstn_c_1"); +DB8500_FUNC_GROUPS(mc1, "mc1_a_1", "mc1_a_2", "mc1dir_a_1"); +DB8500_FUNC_GROUPS(hsi, "hsir_a_1", "hsit_a_1", "hsit_a_2"); +DB8500_FUNC_GROUPS(clkout, "clkout1_a_1", "clkout1_a_2", "clkout1_c_1", + "clkout2_a_1", "clkout2_a_2", "clkout2_c_1"); +DB8500_FUNC_GROUPS(usb, "usb_a_1"); +DB8500_FUNC_GROUPS(trig, "trig_b_1"); +DB8500_FUNC_GROUPS(i2c4, "i2c4_b_1"); +DB8500_FUNC_GROUPS(i2c1, "i2c1_b_1", "i2c1_b_2"); +DB8500_FUNC_GROUPS(i2c2, "i2c2_b_1", "i2c2_b_2"); +/* + * The modem UART can output its RX and TX pins in some different places, + * so select one of each. + */ +DB8500_FUNC_GROUPS(uartmod, "uartmodtx_b_1", "uartmodrx_b_1", "uartmodrx_b_2", + "uartmodrx_c_1", "uartmod_tx_c_1", "uartmodrx_oc1_1", + "uartmodtx_oc1_1", "uartmodrx_oc3_1", "uartmodtx_oc3_1"); +DB8500_FUNC_GROUPS(stmmod, "stmmod_b_1", "stmmod_c_1", "stmmod_oc1_1", + "stmmod_oc3_1", "stmmod_oc3_2"); +DB8500_FUNC_GROUPS(spi3, "spi3_b_1"); +/* Select between CS0 on alt B or PS1 on alt C */ +DB8500_FUNC_GROUPS(sm, "sm_b_1", "smcs0_b_1", "smcs1_b_1", "smcleale_c_1", + "smps0_c_1", "smps1_c_1"); +DB8500_FUNC_GROUPS(lcda, "lcdaclk_b_1", "lcda_b_1"); +DB8500_FUNC_GROUPS(ddrtrig, "ddrtrig_b_1"); +DB8500_FUNC_GROUPS(pwl, "pwl_b_1", "pwl_b_2", "pwl_b_3", "pwl_b_4"); +DB8500_FUNC_GROUPS(spi1, "spi1_b_1"); +DB8500_FUNC_GROUPS(mc3, "mc3_b_1"); +DB8500_FUNC_GROUPS(ipjtag, "ipjtag_c_1"); +DB8500_FUNC_GROUPS(slim0, "slim0_c_1"); +DB8500_FUNC_GROUPS(ms, "ms_c_1"); +DB8500_FUNC_GROUPS(iptrigout, "iptrigout_c_1"); +DB8500_FUNC_GROUPS(stmape, "stmape_c_1", "stmape_c_2", "stmape_oc1_1"); +DB8500_FUNC_GROUPS(mc5, "mc5_c_1"); +DB8500_FUNC_GROUPS(usbsim, "usbsim_c_1", "usbsim_c_2"); +DB8500_FUNC_GROUPS(i2c3, "i2c3_c_1", "i2c3_c_2"); +DB8500_FUNC_GROUPS(spi0, "spi0_c_1"); +DB8500_FUNC_GROUPS(spi2, "spi2_oc1_1", "spi2_oc1_2"); +DB8500_FUNC_GROUPS(remap, "remap0_oc1_1", "remap1_oc1_1"); +DB8500_FUNC_GROUPS(sbag, "sbag_oc2_1", "sbag_oc4_1"); +DB8500_FUNC_GROUPS(ptm, "ptma9_oc1_1", "ptma9_oc2_1"); +DB8500_FUNC_GROUPS(rf, "rf_oc1_1", "rf_oc1_2"); +DB8500_FUNC_GROUPS(hx, "hxclk_oc1_1", "hxgpio_oc1_1"); +DB8500_FUNC_GROUPS(etm, "etmr4_oc2_1", "etmr4_oc3_1"); +DB8500_FUNC_GROUPS(hwobs, "hwobs_oc4_1"); +#define FUNCTION(fname) \ + { \ + .name = #fname, \ + .groups = fname##_groups, \ + .ngroups = ARRAY_SIZE(fname##_groups), \ + } + +static const struct nmk_function nmk_db8500_functions[] = { + FUNCTION(u0), + FUNCTION(u1), + FUNCTION(u2), + FUNCTION(ipi2c), + FUNCTION(msp0), + FUNCTION(mc0), + FUNCTION(msp1), + FUNCTION(lcdb), + FUNCTION(lcd), + FUNCTION(kp), + FUNCTION(mc2), + FUNCTION(ssp1), + FUNCTION(ssp0), + FUNCTION(i2c0), + FUNCTION(ipgpio), + FUNCTION(msp2), + FUNCTION(mc4), + FUNCTION(mc1), + FUNCTION(hsi), + FUNCTION(clkout), + FUNCTION(usb), + FUNCTION(trig), + FUNCTION(i2c4), + FUNCTION(i2c1), + FUNCTION(i2c2), + FUNCTION(uartmod), + FUNCTION(stmmod), + FUNCTION(spi3), + FUNCTION(sm), + FUNCTION(lcda), + FUNCTION(ddrtrig), + FUNCTION(pwl), + FUNCTION(spi1), + FUNCTION(mc3), + FUNCTION(ipjtag), + FUNCTION(slim0), + FUNCTION(ms), + FUNCTION(iptrigout), + FUNCTION(stmape), + FUNCTION(mc5), + FUNCTION(usbsim), + FUNCTION(i2c3), + FUNCTION(spi0), + FUNCTION(spi2), + FUNCTION(remap), + FUNCTION(ptm), + FUNCTION(rf), + FUNCTION(hx), + FUNCTION(etm), + FUNCTION(hwobs), +}; + +static const struct prcm_gpiocr_altcx_pin_desc db8500_altcx_pins[] = { + PRCM_GPIOCR_ALTCX(23, true, PRCM_IDX_GPIOCR1, 9, /* STMAPE_CLK_a */ + true, PRCM_IDX_GPIOCR1, 7, /* SBAG_CLK_a */ + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(24, true, PRCM_IDX_GPIOCR1, 9, /* STMAPE or U2_RXD ??? */ + true, PRCM_IDX_GPIOCR1, 7, /* SBAG_VAL_a */ + true, PRCM_IDX_GPIOCR1, 10, /* STM_MOD_CMD0 */ + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(25, true, PRCM_IDX_GPIOCR1, 9, /* STMAPE_DAT_a[0] */ + true, PRCM_IDX_GPIOCR1, 7, /* SBAG_D_a[0] */ + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(26, true, PRCM_IDX_GPIOCR1, 9, /* STMAPE_DAT_a[1] */ + true, PRCM_IDX_GPIOCR1, 7, /* SBAG_D_a[1] */ + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(27, true, PRCM_IDX_GPIOCR1, 9, /* STMAPE_DAT_a[2] */ + true, PRCM_IDX_GPIOCR1, 7, /* SBAG_D_a[2] */ + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(28, true, PRCM_IDX_GPIOCR1, 9, /* STMAPE_DAT_a[3] */ + true, PRCM_IDX_GPIOCR1, 7, /* SBAG_D_a[3] */ + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(29, false, 0, 0, + false, 0, 0, + true, PRCM_IDX_GPIOCR1, 10, /* STM_MOD_CMD0 */ + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(30, false, 0, 0, + false, 0, 0, + true, PRCM_IDX_GPIOCR1, 10, /* STM_MOD_CMD0 */ + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(31, false, 0, 0, + false, 0, 0, + true, PRCM_IDX_GPIOCR1, 10, /* STM_MOD_CMD0 */ + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(32, false, 0, 0, + false, 0, 0, + true, PRCM_IDX_GPIOCR1, 10, /* STM_MOD_CMD0 */ + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(68, true, PRCM_IDX_GPIOCR1, 18, /* REMAP_SELECT_ON */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(69, true, PRCM_IDX_GPIOCR1, 18, /* REMAP_SELECT_ON */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(70, true, PRCM_IDX_GPIOCR1, 5, /* PTM_A9_D23 */ + true, PRCM_IDX_GPIOCR2, 2, /* DBG_ETM_R4_CMD0 */ + true, PRCM_IDX_GPIOCR1, 11, /* STM_MOD_CMD1 */ + true, PRCM_IDX_GPIOCR1, 8 /* SBAG_CLK */ + ), + PRCM_GPIOCR_ALTCX(71, true, PRCM_IDX_GPIOCR1, 5, /* PTM_A9_D22 */ + true, PRCM_IDX_GPIOCR2, 2, /* DBG_ETM_R4_CMD0 */ + true, PRCM_IDX_GPIOCR1, 11, /* STM_MOD_CMD1 */ + true, PRCM_IDX_GPIOCR1, 8 /* SBAG_D3 */ + ), + PRCM_GPIOCR_ALTCX(72, true, PRCM_IDX_GPIOCR1, 5, /* PTM_A9_D21 */ + true, PRCM_IDX_GPIOCR2, 2, /* DBG_ETM_R4_CMD0 */ + true, PRCM_IDX_GPIOCR1, 11, /* STM_MOD_CMD1 */ + true, PRCM_IDX_GPIOCR1, 8 /* SBAG_D2 */ + ), + PRCM_GPIOCR_ALTCX(73, true, PRCM_IDX_GPIOCR1, 5, /* PTM_A9_D20 */ + true, PRCM_IDX_GPIOCR2, 2, /* DBG_ETM_R4_CMD0 */ + true, PRCM_IDX_GPIOCR1, 11, /* STM_MOD_CMD1 */ + true, PRCM_IDX_GPIOCR1, 8 /* SBAG_D1 */ + ), + PRCM_GPIOCR_ALTCX(74, true, PRCM_IDX_GPIOCR1, 5, /* PTM_A9_D19 */ + true, PRCM_IDX_GPIOCR2, 2, /* DBG_ETM_R4_CMD0 */ + true, PRCM_IDX_GPIOCR1, 11, /* STM_MOD_CMD1 */ + true, PRCM_IDX_GPIOCR1, 8 /* SBAG_D0 */ + ), + PRCM_GPIOCR_ALTCX(75, true, PRCM_IDX_GPIOCR1, 5, /* PTM_A9_D18 */ + true, PRCM_IDX_GPIOCR2, 2, /* DBG_ETM_R4_CMD0 */ + true, PRCM_IDX_GPIOCR1, 0, /* DBG_UARTMOD_CMD0 */ + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(76, true, PRCM_IDX_GPIOCR1, 5, /* PTM_A9_D17 */ + true, PRCM_IDX_GPIOCR2, 2, /* DBG_ETM_R4_CMD0 */ + true, PRCM_IDX_GPIOCR1, 0, /* DBG_UARTMOD_CMD0 */ + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(77, true, PRCM_IDX_GPIOCR1, 5, /* PTM_A9_D16 */ + true, PRCM_IDX_GPIOCR2, 2, /* DBG_ETM_R4_CMD0 */ + false, 0, 0, + true, PRCM_IDX_GPIOCR1, 8 /* SBAG_VAL */ + ), + PRCM_GPIOCR_ALTCX(86, true, PRCM_IDX_GPIOCR1, 12, /* KP_O3 */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(87, true, PRCM_IDX_GPIOCR1, 12, /* KP_O2 */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(88, true, PRCM_IDX_GPIOCR1, 12, /* KP_I3 */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(89, true, PRCM_IDX_GPIOCR1, 12, /* KP_I2 */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(90, true, PRCM_IDX_GPIOCR1, 12, /* KP_O1 */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(91, true, PRCM_IDX_GPIOCR1, 12, /* KP_O0 */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(92, true, PRCM_IDX_GPIOCR1, 12, /* KP_I1 */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(93, true, PRCM_IDX_GPIOCR1, 12, /* KP_I0 */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(96, true, PRCM_IDX_GPIOCR2, 3, /* RF_INT */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(97, true, PRCM_IDX_GPIOCR2, 1, /* RF_CTRL */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(151, false, 0, 0, + true, PRCM_IDX_GPIOCR1, 6, /* PTM_A9_CTL */ + true, PRCM_IDX_GPIOCR1, 15, /* DBG_ETM_R4_CMD1*/ + true, PRCM_IDX_GPIOCR1, 25 /* HW_OBS17 */ + ), + PRCM_GPIOCR_ALTCX(152, true, PRCM_IDX_GPIOCR1, 4, /* Hx_CLK */ + true, PRCM_IDX_GPIOCR1, 6, /* PTM_A9_CLK */ + true, PRCM_IDX_GPIOCR1, 15, /* DBG_ETM_R4_CMD1*/ + true, PRCM_IDX_GPIOCR1, 25 /* HW_OBS16 */ + ), + PRCM_GPIOCR_ALTCX(153, true, PRCM_IDX_GPIOCR1, 1, /* UARTMOD_CMD1 */ + true, PRCM_IDX_GPIOCR1, 14, /* PTM_A9_D15 */ + true, PRCM_IDX_GPIOCR1, 19, /* DBG_ETM_R4_CMD2 */ + true, PRCM_IDX_GPIOCR1, 25 /* HW_OBS15 */ + ), + PRCM_GPIOCR_ALTCX(154, true, PRCM_IDX_GPIOCR1, 1, /* UARTMOD_CMD1 */ + true, PRCM_IDX_GPIOCR1, 14, /* PTM_A9_D14 */ + true, PRCM_IDX_GPIOCR1, 19, /* DBG_ETM_R4_CMD2 */ + true, PRCM_IDX_GPIOCR1, 25 /* HW_OBS14 */ + ), + PRCM_GPIOCR_ALTCX(155, true, PRCM_IDX_GPIOCR1, 13, /* STM_MOD_CMD2 */ + true, PRCM_IDX_GPIOCR1, 14, /* PTM_A9_D13 */ + true, PRCM_IDX_GPIOCR1, 19, /* DBG_ETM_R4_CMD2 */ + true, PRCM_IDX_GPIOCR1, 25 /* HW_OBS13 */ + ), + PRCM_GPIOCR_ALTCX(156, true, PRCM_IDX_GPIOCR1, 13, /* STM_MOD_CMD2 */ + true, PRCM_IDX_GPIOCR1, 14, /* PTM_A9_D12 */ + true, PRCM_IDX_GPIOCR1, 19, /* DBG_ETM_R4_CMD2 */ + true, PRCM_IDX_GPIOCR1, 25 /* HW_OBS12 */ + ), + PRCM_GPIOCR_ALTCX(157, true, PRCM_IDX_GPIOCR1, 13, /* STM_MOD_CMD2 */ + true, PRCM_IDX_GPIOCR1, 14, /* PTM_A9_D11 */ + true, PRCM_IDX_GPIOCR1, 19, /* DBG_ETM_R4_CMD2 */ + true, PRCM_IDX_GPIOCR1, 25 /* HW_OBS11 */ + ), + PRCM_GPIOCR_ALTCX(158, true, PRCM_IDX_GPIOCR1, 13, /* STM_MOD_CMD2 */ + true, PRCM_IDX_GPIOCR1, 14, /* PTM_A9_D10 */ + true, PRCM_IDX_GPIOCR1, 19, /* DBG_ETM_R4_CMD2 */ + true, PRCM_IDX_GPIOCR1, 25 /* HW_OBS10 */ + ), + PRCM_GPIOCR_ALTCX(159, true, PRCM_IDX_GPIOCR1, 13, /* STM_MOD_CMD2 */ + true, PRCM_IDX_GPIOCR1, 14, /* PTM_A9_D9 */ + true, PRCM_IDX_GPIOCR1, 19, /* DBG_ETM_R4_CMD2 */ + true, PRCM_IDX_GPIOCR1, 25 /* HW_OBS9 */ + ), + PRCM_GPIOCR_ALTCX(160, false, 0, 0, + true, PRCM_IDX_GPIOCR1, 14, /* PTM_A9_D8 */ + true, PRCM_IDX_GPIOCR1, 19, /* DBG_ETM_R4_CMD2 */ + true, PRCM_IDX_GPIOCR1, 25 /* HW_OBS8 */ + ), + PRCM_GPIOCR_ALTCX(161, true, PRCM_IDX_GPIOCR1, 4, /* Hx_GPIO7 */ + true, PRCM_IDX_GPIOCR1, 6, /* PTM_A9_D7 */ + true, PRCM_IDX_GPIOCR1, 15, /* DBG_ETM_R4_CMD1*/ + true, PRCM_IDX_GPIOCR1, 24 /* HW_OBS7 */ + ), + PRCM_GPIOCR_ALTCX(162, true, PRCM_IDX_GPIOCR1, 4, /* Hx_GPIO6 */ + true, PRCM_IDX_GPIOCR1, 6, /* PTM_A9_D6 */ + true, PRCM_IDX_GPIOCR1, 15, /* DBG_ETM_R4_CMD1*/ + true, PRCM_IDX_GPIOCR1, 24 /* HW_OBS6 */ + ), + PRCM_GPIOCR_ALTCX(163, true, PRCM_IDX_GPIOCR1, 4, /* Hx_GPIO5 */ + true, PRCM_IDX_GPIOCR1, 6, /* PTM_A9_D5 */ + true, PRCM_IDX_GPIOCR1, 15, /* DBG_ETM_R4_CMD1*/ + true, PRCM_IDX_GPIOCR1, 24 /* HW_OBS5 */ + ), + PRCM_GPIOCR_ALTCX(164, true, PRCM_IDX_GPIOCR1, 4, /* Hx_GPIO4 */ + true, PRCM_IDX_GPIOCR1, 6, /* PTM_A9_D4 */ + true, PRCM_IDX_GPIOCR1, 15, /* DBG_ETM_R4_CMD1*/ + true, PRCM_IDX_GPIOCR1, 24 /* HW_OBS4 */ + ), + PRCM_GPIOCR_ALTCX(165, true, PRCM_IDX_GPIOCR1, 4, /* Hx_GPIO3 */ + true, PRCM_IDX_GPIOCR1, 6, /* PTM_A9_D3 */ + true, PRCM_IDX_GPIOCR1, 15, /* DBG_ETM_R4_CMD1*/ + true, PRCM_IDX_GPIOCR1, 24 /* HW_OBS3 */ + ), + PRCM_GPIOCR_ALTCX(166, true, PRCM_IDX_GPIOCR1, 4, /* Hx_GPIO2 */ + true, PRCM_IDX_GPIOCR1, 6, /* PTM_A9_D2 */ + true, PRCM_IDX_GPIOCR1, 15, /* DBG_ETM_R4_CMD1*/ + true, PRCM_IDX_GPIOCR1, 24 /* HW_OBS2 */ + ), + PRCM_GPIOCR_ALTCX(167, true, PRCM_IDX_GPIOCR1, 4, /* Hx_GPIO1 */ + true, PRCM_IDX_GPIOCR1, 6, /* PTM_A9_D1 */ + true, PRCM_IDX_GPIOCR1, 15, /* DBG_ETM_R4_CMD1*/ + true, PRCM_IDX_GPIOCR1, 24 /* HW_OBS1 */ + ), + PRCM_GPIOCR_ALTCX(168, true, PRCM_IDX_GPIOCR1, 4, /* Hx_GPIO0 */ + true, PRCM_IDX_GPIOCR1, 6, /* PTM_A9_D0 */ + true, PRCM_IDX_GPIOCR1, 15, /* DBG_ETM_R4_CMD1*/ + true, PRCM_IDX_GPIOCR1, 24 /* HW_OBS0 */ + ), + PRCM_GPIOCR_ALTCX(170, true, PRCM_IDX_GPIOCR2, 2, /* RF_INT */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(171, true, PRCM_IDX_GPIOCR2, 0, /* RF_CTRL */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(215, true, PRCM_IDX_GPIOCR1, 23, /* SPI2_TXD */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(216, true, PRCM_IDX_GPIOCR1, 23, /* SPI2_FRM */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(217, true, PRCM_IDX_GPIOCR1, 23, /* SPI2_CLK */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(218, true, PRCM_IDX_GPIOCR1, 23, /* SPI2_RXD */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), +}; + +static const u16 db8500_prcm_gpiocr_regs[] = { + [PRCM_IDX_GPIOCR1] = 0x138, + [PRCM_IDX_GPIOCR2] = 0x574, +}; + +static const struct nmk_pinctrl_soc_data nmk_db8500_soc = { + .gpio_ranges = nmk_db8500_ranges, + .gpio_num_ranges = ARRAY_SIZE(nmk_db8500_ranges), + .pins = nmk_db8500_pins, + .npins = ARRAY_SIZE(nmk_db8500_pins), + .functions = nmk_db8500_functions, + .nfunctions = ARRAY_SIZE(nmk_db8500_functions), + .groups = nmk_db8500_groups, + .ngroups = ARRAY_SIZE(nmk_db8500_groups), + .altcx_pins = db8500_altcx_pins, + .npins_altcx = ARRAY_SIZE(db8500_altcx_pins), + .prcm_gpiocr_registers = db8500_prcm_gpiocr_regs, +}; + +void nmk_pinctrl_db8500_init(const struct nmk_pinctrl_soc_data **soc) +{ + *soc = &nmk_db8500_soc; +} diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik-db8540.c b/drivers/pinctrl/nomadik/pinctrl-nomadik-db8540.c new file mode 100644 index 000000000000..d7ba5443bae0 --- /dev/null +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik-db8540.c @@ -0,0 +1,1266 @@ +#include <linux/kernel.h> +#include <linux/pinctrl/pinctrl.h> +#include "pinctrl-nomadik.h" + +/* All the pins that can be used for GPIO and some other functions */ +#define _GPIO(offset) (offset) + +#define DB8540_PIN_AH6 _GPIO(0) +#define DB8540_PIN_AG7 _GPIO(1) +#define DB8540_PIN_AF2 _GPIO(2) +#define DB8540_PIN_AD3 _GPIO(3) +#define DB8540_PIN_AF6 _GPIO(4) +#define DB8540_PIN_AG6 _GPIO(5) +#define DB8540_PIN_AD5 _GPIO(6) +#define DB8540_PIN_AF7 _GPIO(7) +#define DB8540_PIN_AG5 _GPIO(8) +#define DB8540_PIN_AH5 _GPIO(9) +#define DB8540_PIN_AE4 _GPIO(10) +#define DB8540_PIN_AD1 _GPIO(11) +#define DB8540_PIN_AD2 _GPIO(12) +#define DB8540_PIN_AC2 _GPIO(13) +#define DB8540_PIN_AC4 _GPIO(14) +#define DB8540_PIN_AC3 _GPIO(15) +#define DB8540_PIN_AH7 _GPIO(16) +#define DB8540_PIN_AE7 _GPIO(17) +/* Hole */ +#define DB8540_PIN_AF8 _GPIO(22) +#define DB8540_PIN_AH11 _GPIO(23) +#define DB8540_PIN_AG11 _GPIO(24) +#define DB8540_PIN_AF11 _GPIO(25) +#define DB8540_PIN_AH10 _GPIO(26) +#define DB8540_PIN_AG10 _GPIO(27) +#define DB8540_PIN_AF10 _GPIO(28) +/* Hole */ +#define DB8540_PIN_AD4 _GPIO(33) +#define DB8540_PIN_AF3 _GPIO(34) +#define DB8540_PIN_AF5 _GPIO(35) +#define DB8540_PIN_AG4 _GPIO(36) +#define DB8540_PIN_AF9 _GPIO(37) +#define DB8540_PIN_AE8 _GPIO(38) +/* Hole */ +#define DB8540_PIN_M26 _GPIO(64) +#define DB8540_PIN_M25 _GPIO(65) +#define DB8540_PIN_M27 _GPIO(66) +#define DB8540_PIN_N25 _GPIO(67) +/* Hole */ +#define DB8540_PIN_M28 _GPIO(70) +#define DB8540_PIN_N26 _GPIO(71) +#define DB8540_PIN_M22 _GPIO(72) +#define DB8540_PIN_N22 _GPIO(73) +#define DB8540_PIN_N27 _GPIO(74) +#define DB8540_PIN_N28 _GPIO(75) +#define DB8540_PIN_P22 _GPIO(76) +#define DB8540_PIN_P28 _GPIO(77) +#define DB8540_PIN_P26 _GPIO(78) +#define DB8540_PIN_T22 _GPIO(79) +#define DB8540_PIN_R27 _GPIO(80) +#define DB8540_PIN_P27 _GPIO(81) +#define DB8540_PIN_R26 _GPIO(82) +#define DB8540_PIN_R25 _GPIO(83) +#define DB8540_PIN_U22 _GPIO(84) +#define DB8540_PIN_T27 _GPIO(85) +#define DB8540_PIN_T25 _GPIO(86) +#define DB8540_PIN_T26 _GPIO(87) +/* Hole */ +#define DB8540_PIN_AF20 _GPIO(116) +#define DB8540_PIN_AG21 _GPIO(117) +#define DB8540_PIN_AH19 _GPIO(118) +#define DB8540_PIN_AE19 _GPIO(119) +#define DB8540_PIN_AG18 _GPIO(120) +#define DB8540_PIN_AH17 _GPIO(121) +#define DB8540_PIN_AF19 _GPIO(122) +#define DB8540_PIN_AF18 _GPIO(123) +#define DB8540_PIN_AE18 _GPIO(124) +#define DB8540_PIN_AG17 _GPIO(125) +#define DB8540_PIN_AF17 _GPIO(126) +#define DB8540_PIN_AE17 _GPIO(127) +#define DB8540_PIN_AC27 _GPIO(128) +#define DB8540_PIN_AD27 _GPIO(129) +#define DB8540_PIN_AE28 _GPIO(130) +#define DB8540_PIN_AG26 _GPIO(131) +#define DB8540_PIN_AF25 _GPIO(132) +#define DB8540_PIN_AE27 _GPIO(133) +#define DB8540_PIN_AF27 _GPIO(134) +#define DB8540_PIN_AG28 _GPIO(135) +#define DB8540_PIN_AF28 _GPIO(136) +#define DB8540_PIN_AG25 _GPIO(137) +#define DB8540_PIN_AG24 _GPIO(138) +#define DB8540_PIN_AD25 _GPIO(139) +#define DB8540_PIN_AH25 _GPIO(140) +#define DB8540_PIN_AF26 _GPIO(141) +#define DB8540_PIN_AF23 _GPIO(142) +#define DB8540_PIN_AG23 _GPIO(143) +#define DB8540_PIN_AE25 _GPIO(144) +#define DB8540_PIN_AH24 _GPIO(145) +#define DB8540_PIN_AJ25 _GPIO(146) +#define DB8540_PIN_AG27 _GPIO(147) +#define DB8540_PIN_AH23 _GPIO(148) +#define DB8540_PIN_AE26 _GPIO(149) +#define DB8540_PIN_AE24 _GPIO(150) +#define DB8540_PIN_AJ24 _GPIO(151) +#define DB8540_PIN_AE21 _GPIO(152) +#define DB8540_PIN_AG22 _GPIO(153) +#define DB8540_PIN_AF21 _GPIO(154) +#define DB8540_PIN_AF24 _GPIO(155) +#define DB8540_PIN_AH22 _GPIO(156) +#define DB8540_PIN_AJ23 _GPIO(157) +#define DB8540_PIN_AH21 _GPIO(158) +#define DB8540_PIN_AG20 _GPIO(159) +#define DB8540_PIN_AE23 _GPIO(160) +#define DB8540_PIN_AH20 _GPIO(161) +#define DB8540_PIN_AG19 _GPIO(162) +#define DB8540_PIN_AF22 _GPIO(163) +#define DB8540_PIN_AJ21 _GPIO(164) +#define DB8540_PIN_AD26 _GPIO(165) +#define DB8540_PIN_AD28 _GPIO(166) +#define DB8540_PIN_AC28 _GPIO(167) +#define DB8540_PIN_AC26 _GPIO(168) +/* Hole */ +#define DB8540_PIN_J3 _GPIO(192) +#define DB8540_PIN_H1 _GPIO(193) +#define DB8540_PIN_J2 _GPIO(194) +#define DB8540_PIN_H2 _GPIO(195) +#define DB8540_PIN_H3 _GPIO(196) +#define DB8540_PIN_H4 _GPIO(197) +#define DB8540_PIN_G2 _GPIO(198) +#define DB8540_PIN_G3 _GPIO(199) +#define DB8540_PIN_G4 _GPIO(200) +#define DB8540_PIN_F2 _GPIO(201) +#define DB8540_PIN_C6 _GPIO(202) +#define DB8540_PIN_B6 _GPIO(203) +#define DB8540_PIN_B7 _GPIO(204) +#define DB8540_PIN_A7 _GPIO(205) +#define DB8540_PIN_D7 _GPIO(206) +#define DB8540_PIN_D8 _GPIO(207) +#define DB8540_PIN_F3 _GPIO(208) +#define DB8540_PIN_E2 _GPIO(209) +#define DB8540_PIN_C7 _GPIO(210) +#define DB8540_PIN_B8 _GPIO(211) +#define DB8540_PIN_C10 _GPIO(212) +#define DB8540_PIN_C8 _GPIO(213) +#define DB8540_PIN_C9 _GPIO(214) +/* Hole */ +#define DB8540_PIN_B9 _GPIO(219) +#define DB8540_PIN_A10 _GPIO(220) +#define DB8540_PIN_D9 _GPIO(221) +#define DB8540_PIN_B11 _GPIO(222) +#define DB8540_PIN_B10 _GPIO(223) +#define DB8540_PIN_E10 _GPIO(224) +#define DB8540_PIN_B12 _GPIO(225) +#define DB8540_PIN_D10 _GPIO(226) +#define DB8540_PIN_D11 _GPIO(227) +#define DB8540_PIN_AJ6 _GPIO(228) +#define DB8540_PIN_B13 _GPIO(229) +#define DB8540_PIN_C12 _GPIO(230) +#define DB8540_PIN_B14 _GPIO(231) +#define DB8540_PIN_E11 _GPIO(232) +/* Hole */ +#define DB8540_PIN_D12 _GPIO(256) +#define DB8540_PIN_D15 _GPIO(257) +#define DB8540_PIN_C13 _GPIO(258) +#define DB8540_PIN_C14 _GPIO(259) +#define DB8540_PIN_C18 _GPIO(260) +#define DB8540_PIN_C16 _GPIO(261) +#define DB8540_PIN_B16 _GPIO(262) +#define DB8540_PIN_D18 _GPIO(263) +#define DB8540_PIN_C15 _GPIO(264) +#define DB8540_PIN_C17 _GPIO(265) +#define DB8540_PIN_B17 _GPIO(266) +#define DB8540_PIN_D17 _GPIO(267) + +/* + * The names of the pins are denoted by GPIO number and ball name, even + * though they can be used for other things than GPIO, this is the first + * column in the table of the data sheet and often used on schematics and + * such. + */ +static const struct pinctrl_pin_desc nmk_db8540_pins[] = { + PINCTRL_PIN(DB8540_PIN_AH6, "GPIO0_AH6"), + PINCTRL_PIN(DB8540_PIN_AG7, "GPIO1_AG7"), + PINCTRL_PIN(DB8540_PIN_AF2, "GPIO2_AF2"), + PINCTRL_PIN(DB8540_PIN_AD3, "GPIO3_AD3"), + PINCTRL_PIN(DB8540_PIN_AF6, "GPIO4_AF6"), + PINCTRL_PIN(DB8540_PIN_AG6, "GPIO5_AG6"), + PINCTRL_PIN(DB8540_PIN_AD5, "GPIO6_AD5"), + PINCTRL_PIN(DB8540_PIN_AF7, "GPIO7_AF7"), + PINCTRL_PIN(DB8540_PIN_AG5, "GPIO8_AG5"), + PINCTRL_PIN(DB8540_PIN_AH5, "GPIO9_AH5"), + PINCTRL_PIN(DB8540_PIN_AE4, "GPIO10_AE4"), + PINCTRL_PIN(DB8540_PIN_AD1, "GPIO11_AD1"), + PINCTRL_PIN(DB8540_PIN_AD2, "GPIO12_AD2"), + PINCTRL_PIN(DB8540_PIN_AC2, "GPIO13_AC2"), + PINCTRL_PIN(DB8540_PIN_AC4, "GPIO14_AC4"), + PINCTRL_PIN(DB8540_PIN_AC3, "GPIO15_AC3"), + PINCTRL_PIN(DB8540_PIN_AH7, "GPIO16_AH7"), + PINCTRL_PIN(DB8540_PIN_AE7, "GPIO17_AE7"), + /* Hole */ + PINCTRL_PIN(DB8540_PIN_AF8, "GPIO22_AF8"), + PINCTRL_PIN(DB8540_PIN_AH11, "GPIO23_AH11"), + PINCTRL_PIN(DB8540_PIN_AG11, "GPIO24_AG11"), + PINCTRL_PIN(DB8540_PIN_AF11, "GPIO25_AF11"), + PINCTRL_PIN(DB8540_PIN_AH10, "GPIO26_AH10"), + PINCTRL_PIN(DB8540_PIN_AG10, "GPIO27_AG10"), + PINCTRL_PIN(DB8540_PIN_AF10, "GPIO28_AF10"), + /* Hole */ + PINCTRL_PIN(DB8540_PIN_AD4, "GPIO33_AD4"), + PINCTRL_PIN(DB8540_PIN_AF3, "GPIO34_AF3"), + PINCTRL_PIN(DB8540_PIN_AF5, "GPIO35_AF5"), + PINCTRL_PIN(DB8540_PIN_AG4, "GPIO36_AG4"), + PINCTRL_PIN(DB8540_PIN_AF9, "GPIO37_AF9"), + PINCTRL_PIN(DB8540_PIN_AE8, "GPIO38_AE8"), + /* Hole */ + PINCTRL_PIN(DB8540_PIN_M26, "GPIO64_M26"), + PINCTRL_PIN(DB8540_PIN_M25, "GPIO65_M25"), + PINCTRL_PIN(DB8540_PIN_M27, "GPIO66_M27"), + PINCTRL_PIN(DB8540_PIN_N25, "GPIO67_N25"), + /* Hole */ + PINCTRL_PIN(DB8540_PIN_M28, "GPIO70_M28"), + PINCTRL_PIN(DB8540_PIN_N26, "GPIO71_N26"), + PINCTRL_PIN(DB8540_PIN_M22, "GPIO72_M22"), + PINCTRL_PIN(DB8540_PIN_N22, "GPIO73_N22"), + PINCTRL_PIN(DB8540_PIN_N27, "GPIO74_N27"), + PINCTRL_PIN(DB8540_PIN_N28, "GPIO75_N28"), + PINCTRL_PIN(DB8540_PIN_P22, "GPIO76_P22"), + PINCTRL_PIN(DB8540_PIN_P28, "GPIO77_P28"), + PINCTRL_PIN(DB8540_PIN_P26, "GPIO78_P26"), + PINCTRL_PIN(DB8540_PIN_T22, "GPIO79_T22"), + PINCTRL_PIN(DB8540_PIN_R27, "GPIO80_R27"), + PINCTRL_PIN(DB8540_PIN_P27, "GPIO81_P27"), + PINCTRL_PIN(DB8540_PIN_R26, "GPIO82_R26"), + PINCTRL_PIN(DB8540_PIN_R25, "GPIO83_R25"), + PINCTRL_PIN(DB8540_PIN_U22, "GPIO84_U22"), + PINCTRL_PIN(DB8540_PIN_T27, "GPIO85_T27"), + PINCTRL_PIN(DB8540_PIN_T25, "GPIO86_T25"), + PINCTRL_PIN(DB8540_PIN_T26, "GPIO87_T26"), + /* Hole */ + PINCTRL_PIN(DB8540_PIN_AF20, "GPIO116_AF20"), + PINCTRL_PIN(DB8540_PIN_AG21, "GPIO117_AG21"), + PINCTRL_PIN(DB8540_PIN_AH19, "GPIO118_AH19"), + PINCTRL_PIN(DB8540_PIN_AE19, "GPIO119_AE19"), + PINCTRL_PIN(DB8540_PIN_AG18, "GPIO120_AG18"), + PINCTRL_PIN(DB8540_PIN_AH17, "GPIO121_AH17"), + PINCTRL_PIN(DB8540_PIN_AF19, "GPIO122_AF19"), + PINCTRL_PIN(DB8540_PIN_AF18, "GPIO123_AF18"), + PINCTRL_PIN(DB8540_PIN_AE18, "GPIO124_AE18"), + PINCTRL_PIN(DB8540_PIN_AG17, "GPIO125_AG17"), + PINCTRL_PIN(DB8540_PIN_AF17, "GPIO126_AF17"), + PINCTRL_PIN(DB8540_PIN_AE17, "GPIO127_AE17"), + PINCTRL_PIN(DB8540_PIN_AC27, "GPIO128_AC27"), + PINCTRL_PIN(DB8540_PIN_AD27, "GPIO129_AD27"), + PINCTRL_PIN(DB8540_PIN_AE28, "GPIO130_AE28"), + PINCTRL_PIN(DB8540_PIN_AG26, "GPIO131_AG26"), + PINCTRL_PIN(DB8540_PIN_AF25, "GPIO132_AF25"), + PINCTRL_PIN(DB8540_PIN_AE27, "GPIO133_AE27"), + PINCTRL_PIN(DB8540_PIN_AF27, "GPIO134_AF27"), + PINCTRL_PIN(DB8540_PIN_AG28, "GPIO135_AG28"), + PINCTRL_PIN(DB8540_PIN_AF28, "GPIO136_AF28"), + PINCTRL_PIN(DB8540_PIN_AG25, "GPIO137_AG25"), + PINCTRL_PIN(DB8540_PIN_AG24, "GPIO138_AG24"), + PINCTRL_PIN(DB8540_PIN_AD25, "GPIO139_AD25"), + PINCTRL_PIN(DB8540_PIN_AH25, "GPIO140_AH25"), + PINCTRL_PIN(DB8540_PIN_AF26, "GPIO141_AF26"), + PINCTRL_PIN(DB8540_PIN_AF23, "GPIO142_AF23"), + PINCTRL_PIN(DB8540_PIN_AG23, "GPIO143_AG23"), + PINCTRL_PIN(DB8540_PIN_AE25, "GPIO144_AE25"), + PINCTRL_PIN(DB8540_PIN_AH24, "GPIO145_AH24"), + PINCTRL_PIN(DB8540_PIN_AJ25, "GPIO146_AJ25"), + PINCTRL_PIN(DB8540_PIN_AG27, "GPIO147_AG27"), + PINCTRL_PIN(DB8540_PIN_AH23, "GPIO148_AH23"), + PINCTRL_PIN(DB8540_PIN_AE26, "GPIO149_AE26"), + PINCTRL_PIN(DB8540_PIN_AE24, "GPIO150_AE24"), + PINCTRL_PIN(DB8540_PIN_AJ24, "GPIO151_AJ24"), + PINCTRL_PIN(DB8540_PIN_AE21, "GPIO152_AE21"), + PINCTRL_PIN(DB8540_PIN_AG22, "GPIO153_AG22"), + PINCTRL_PIN(DB8540_PIN_AF21, "GPIO154_AF21"), + PINCTRL_PIN(DB8540_PIN_AF24, "GPIO155_AF24"), + PINCTRL_PIN(DB8540_PIN_AH22, "GPIO156_AH22"), + PINCTRL_PIN(DB8540_PIN_AJ23, "GPIO157_AJ23"), + PINCTRL_PIN(DB8540_PIN_AH21, "GPIO158_AH21"), + PINCTRL_PIN(DB8540_PIN_AG20, "GPIO159_AG20"), + PINCTRL_PIN(DB8540_PIN_AE23, "GPIO160_AE23"), + PINCTRL_PIN(DB8540_PIN_AH20, "GPIO161_AH20"), + PINCTRL_PIN(DB8540_PIN_AG19, "GPIO162_AG19"), + PINCTRL_PIN(DB8540_PIN_AF22, "GPIO163_AF22"), + PINCTRL_PIN(DB8540_PIN_AJ21, "GPIO164_AJ21"), + PINCTRL_PIN(DB8540_PIN_AD26, "GPIO165_AD26"), + PINCTRL_PIN(DB8540_PIN_AD28, "GPIO166_AD28"), + PINCTRL_PIN(DB8540_PIN_AC28, "GPIO167_AC28"), + PINCTRL_PIN(DB8540_PIN_AC26, "GPIO168_AC26"), + /* Hole */ + PINCTRL_PIN(DB8540_PIN_J3, "GPIO192_J3"), + PINCTRL_PIN(DB8540_PIN_H1, "GPIO193_H1"), + PINCTRL_PIN(DB8540_PIN_J2, "GPIO194_J2"), + PINCTRL_PIN(DB8540_PIN_H2, "GPIO195_H2"), + PINCTRL_PIN(DB8540_PIN_H3, "GPIO196_H3"), + PINCTRL_PIN(DB8540_PIN_H4, "GPIO197_H4"), + PINCTRL_PIN(DB8540_PIN_G2, "GPIO198_G2"), + PINCTRL_PIN(DB8540_PIN_G3, "GPIO199_G3"), + PINCTRL_PIN(DB8540_PIN_G4, "GPIO200_G4"), + PINCTRL_PIN(DB8540_PIN_F2, "GPIO201_F2"), + PINCTRL_PIN(DB8540_PIN_C6, "GPIO202_C6"), + PINCTRL_PIN(DB8540_PIN_B6, "GPIO203_B6"), + PINCTRL_PIN(DB8540_PIN_B7, "GPIO204_B7"), + PINCTRL_PIN(DB8540_PIN_A7, "GPIO205_A7"), + PINCTRL_PIN(DB8540_PIN_D7, "GPIO206_D7"), + PINCTRL_PIN(DB8540_PIN_D8, "GPIO207_D8"), + PINCTRL_PIN(DB8540_PIN_F3, "GPIO208_F3"), + PINCTRL_PIN(DB8540_PIN_E2, "GPIO209_E2"), + PINCTRL_PIN(DB8540_PIN_C7, "GPIO210_C7"), + PINCTRL_PIN(DB8540_PIN_B8, "GPIO211_B8"), + PINCTRL_PIN(DB8540_PIN_C10, "GPIO212_C10"), + PINCTRL_PIN(DB8540_PIN_C8, "GPIO213_C8"), + PINCTRL_PIN(DB8540_PIN_C9, "GPIO214_C9"), + /* Hole */ + PINCTRL_PIN(DB8540_PIN_B9, "GPIO219_B9"), + PINCTRL_PIN(DB8540_PIN_A10, "GPIO220_A10"), + PINCTRL_PIN(DB8540_PIN_D9, "GPIO221_D9"), + PINCTRL_PIN(DB8540_PIN_B11, "GPIO222_B11"), + PINCTRL_PIN(DB8540_PIN_B10, "GPIO223_B10"), + PINCTRL_PIN(DB8540_PIN_E10, "GPIO224_E10"), + PINCTRL_PIN(DB8540_PIN_B12, "GPIO225_B12"), + PINCTRL_PIN(DB8540_PIN_D10, "GPIO226_D10"), + PINCTRL_PIN(DB8540_PIN_D11, "GPIO227_D11"), + PINCTRL_PIN(DB8540_PIN_AJ6, "GPIO228_AJ6"), + PINCTRL_PIN(DB8540_PIN_B13, "GPIO229_B13"), + PINCTRL_PIN(DB8540_PIN_C12, "GPIO230_C12"), + PINCTRL_PIN(DB8540_PIN_B14, "GPIO231_B14"), + PINCTRL_PIN(DB8540_PIN_E11, "GPIO232_E11"), + /* Hole */ + PINCTRL_PIN(DB8540_PIN_D12, "GPIO256_D12"), + PINCTRL_PIN(DB8540_PIN_D15, "GPIO257_D15"), + PINCTRL_PIN(DB8540_PIN_C13, "GPIO258_C13"), + PINCTRL_PIN(DB8540_PIN_C14, "GPIO259_C14"), + PINCTRL_PIN(DB8540_PIN_C18, "GPIO260_C18"), + PINCTRL_PIN(DB8540_PIN_C16, "GPIO261_C16"), + PINCTRL_PIN(DB8540_PIN_B16, "GPIO262_B16"), + PINCTRL_PIN(DB8540_PIN_D18, "GPIO263_D18"), + PINCTRL_PIN(DB8540_PIN_C15, "GPIO264_C15"), + PINCTRL_PIN(DB8540_PIN_C17, "GPIO265_C17"), + PINCTRL_PIN(DB8540_PIN_B17, "GPIO266_B17"), + PINCTRL_PIN(DB8540_PIN_D17, "GPIO267_D17"), +}; + +#define DB8540_GPIO_RANGE(a, b, c) { .name = "db8540", .id = a, .base = b, \ + .pin_base = b, .npins = c } + +/* + * This matches the 32-pin gpio chips registered by the GPIO portion. This + * cannot be const since we assign the struct gpio_chip * pointer at runtime. + */ +static struct pinctrl_gpio_range nmk_db8540_ranges[] = { + DB8540_GPIO_RANGE(0, 0, 18), + DB8540_GPIO_RANGE(0, 22, 7), + DB8540_GPIO_RANGE(1, 33, 6), + DB8540_GPIO_RANGE(2, 64, 4), + DB8540_GPIO_RANGE(2, 70, 18), + DB8540_GPIO_RANGE(3, 116, 12), + DB8540_GPIO_RANGE(4, 128, 32), + DB8540_GPIO_RANGE(5, 160, 9), + DB8540_GPIO_RANGE(6, 192, 23), + DB8540_GPIO_RANGE(6, 219, 5), + DB8540_GPIO_RANGE(7, 224, 9), + DB8540_GPIO_RANGE(8, 256, 12), +}; + +/* + * Read the pin group names like this: + * u0_a_1 = first groups of pins for uart0 on alt function a + * i2c2_b_2 = second group of pins for i2c2 on alt function b + * + * The groups are arranged as sets per altfunction column, so we can + * mux in one group at a time by selecting the same altfunction for them + * all. When functions require pins on different altfunctions, you need + * to combine several groups. + */ + +/* Altfunction A column */ +static const unsigned u0_a_1_pins[] = { DB8540_PIN_AH6, DB8540_PIN_AG7, + DB8540_PIN_AF2, DB8540_PIN_AD3 }; +static const unsigned u1rxtx_a_1_pins[] = { DB8540_PIN_AF6, DB8540_PIN_AG6 }; +static const unsigned u1ctsrts_a_1_pins[] = { DB8540_PIN_AD5, DB8540_PIN_AF7 }; +/* Image processor I2C line, this is driven by image processor firmware */ +static const unsigned ipi2c_a_1_pins[] = { DB8540_PIN_AG5, DB8540_PIN_AH5 }; +static const unsigned ipi2c_a_2_pins[] = { DB8540_PIN_AE4, DB8540_PIN_AD1 }; +/* MSP0 can only be on these pins, but TXD and RXD can be flipped */ +static const unsigned msp0txrx_a_1_pins[] = { DB8540_PIN_AD2, DB8540_PIN_AC3 }; +static const unsigned msp0tfstck_a_1_pins[] = { DB8540_PIN_AC2, + DB8540_PIN_AC4 }; +static const unsigned msp0rfsrck_a_1_pins[] = { DB8540_PIN_AH7, + DB8540_PIN_AE7 }; +/* Basic pins of the MMC/SD card 0 interface */ +static const unsigned mc0_a_1_pins[] = { DB8540_PIN_AH11, DB8540_PIN_AG11, + DB8540_PIN_AF11, DB8540_PIN_AH10, DB8540_PIN_AG10, DB8540_PIN_AF10}; +/* MSP1 can only be on these pins, but TXD and RXD can be flipped */ +static const unsigned msp1txrx_a_1_pins[] = { DB8540_PIN_AD4, DB8540_PIN_AG4 }; +static const unsigned msp1_a_1_pins[] = { DB8540_PIN_AF3, DB8540_PIN_AF5 }; + +static const unsigned modobsclk_a_1_pins[] = { DB8540_PIN_AF9 }; +static const unsigned clkoutreq_a_1_pins[] = { DB8540_PIN_AE8 }; +/* LCD interface */ +static const unsigned lcdb_a_1_pins[] = { DB8540_PIN_M26, DB8540_PIN_M25, + DB8540_PIN_M27, DB8540_PIN_N25 }; +static const unsigned lcdvsi0_a_1_pins[] = { DB8540_PIN_AJ24 }; +static const unsigned lcdvsi1_a_1_pins[] = { DB8540_PIN_AE21 }; +static const unsigned lcd_d0_d7_a_1_pins[] = { DB8540_PIN_M28, DB8540_PIN_N26, + DB8540_PIN_M22, DB8540_PIN_N22, DB8540_PIN_N27, DB8540_PIN_N28, + DB8540_PIN_P22, DB8540_PIN_P28 }; +/* D8 thru D11 often used as TVOUT lines */ +static const unsigned lcd_d8_d11_a_1_pins[] = { DB8540_PIN_P26, DB8540_PIN_T22, + DB8540_PIN_R27, DB8540_PIN_P27 }; +static const unsigned lcd_d12_d23_a_1_pins[] = { DB8540_PIN_R26, DB8540_PIN_R25, + DB8540_PIN_U22, DB8540_PIN_T27, DB8540_PIN_AG22, DB8540_PIN_AF21, + DB8540_PIN_AF24, DB8540_PIN_AH22, DB8540_PIN_AJ23, DB8540_PIN_AH21, + DB8540_PIN_AG20, DB8540_PIN_AE23 }; +static const unsigned kp_a_1_pins[] = { DB8540_PIN_AH20, DB8540_PIN_AG19, + DB8540_PIN_AF22, DB8540_PIN_AJ21, DB8540_PIN_T25, DB8540_PIN_T26 }; +/* MC2 has 8 data lines and no direction control, so only for (e)MMC */ +static const unsigned mc2_a_1_pins[] = { DB8540_PIN_AC27, DB8540_PIN_AD27, + DB8540_PIN_AE28, DB8540_PIN_AG26, DB8540_PIN_AF25, DB8540_PIN_AE27, + DB8540_PIN_AF27, DB8540_PIN_AG28, DB8540_PIN_AF28, DB8540_PIN_AG25, + DB8540_PIN_AG24 }; +static const unsigned ssp1_a_1_pins[] = { DB8540_PIN_AD25, DB8540_PIN_AH25, + DB8540_PIN_AF26, DB8540_PIN_AF23 }; +static const unsigned ssp0_a_1_pins[] = { DB8540_PIN_AG23, DB8540_PIN_AE25, + DB8540_PIN_AH24, DB8540_PIN_AJ25 }; +static const unsigned i2c0_a_1_pins[] = { DB8540_PIN_AG27, DB8540_PIN_AH23 }; +/* + * Image processor GPIO pins are named "ipgpio" and have their own + * numberspace + */ +static const unsigned ipgpio0_a_1_pins[] = { DB8540_PIN_AE26 }; +static const unsigned ipgpio1_a_1_pins[] = { DB8540_PIN_AE24 }; +/* modem i2s interface */ +static const unsigned modi2s_a_1_pins[] = { DB8540_PIN_AD26, DB8540_PIN_AD28, + DB8540_PIN_AC28, DB8540_PIN_AC26 }; +static const unsigned spi2_a_1_pins[] = { DB8540_PIN_AF20, DB8540_PIN_AG21, + DB8540_PIN_AH19, DB8540_PIN_AE19 }; +static const unsigned u2txrx_a_1_pins[] = { DB8540_PIN_AG18, DB8540_PIN_AH17 }; +static const unsigned u2ctsrts_a_1_pins[] = { DB8540_PIN_AF19, + DB8540_PIN_AF18 }; +static const unsigned modsmb_a_1_pins[] = { DB8540_PIN_AF17, DB8540_PIN_AE17 }; +static const unsigned msp2sck_a_1_pins[] = { DB8540_PIN_J3 }; +static const unsigned msp2txdtcktfs_a_1_pins[] = { DB8540_PIN_H1, DB8540_PIN_J2, + DB8540_PIN_H2 }; +static const unsigned msp2rxd_a_1_pins[] = { DB8540_PIN_H3 }; +static const unsigned mc4_a_1_pins[] = { DB8540_PIN_H4, DB8540_PIN_G2, + DB8540_PIN_G3, DB8540_PIN_G4, DB8540_PIN_F2, DB8540_PIN_C6, + DB8540_PIN_B6, DB8540_PIN_B7, DB8540_PIN_A7, DB8540_PIN_D7, + DB8540_PIN_D8 }; +static const unsigned mc1_a_1_pins[] = { DB8540_PIN_F3, DB8540_PIN_E2, + DB8540_PIN_C7, DB8540_PIN_B8, DB8540_PIN_C10, DB8540_PIN_C8, + DB8540_PIN_C9 }; +/* mc1_a_2_pins exclude MC1_FBCLK */ +static const unsigned mc1_a_2_pins[] = { DB8540_PIN_F3, DB8540_PIN_C7, + DB8540_PIN_B8, DB8540_PIN_C10, DB8540_PIN_C8, + DB8540_PIN_C9 }; +static const unsigned hsir_a_1_pins[] = { DB8540_PIN_B9, DB8540_PIN_A10, + DB8540_PIN_D9 }; +static const unsigned hsit_a_1_pins[] = { DB8540_PIN_B11, DB8540_PIN_B10, + DB8540_PIN_E10, DB8540_PIN_B12, DB8540_PIN_D10 }; +static const unsigned hsit_a_2_pins[] = { DB8540_PIN_B11, DB8540_PIN_B10, + DB8540_PIN_E10, DB8540_PIN_B12 }; +static const unsigned clkout1_a_1_pins[] = { DB8540_PIN_D11 }; +static const unsigned clkout1_a_2_pins[] = { DB8540_PIN_B13 }; +static const unsigned clkout2_a_1_pins[] = { DB8540_PIN_AJ6 }; +static const unsigned clkout2_a_2_pins[] = { DB8540_PIN_C12 }; +static const unsigned msp4_a_1_pins[] = { DB8540_PIN_B14, DB8540_PIN_E11 }; +static const unsigned usb_a_1_pins[] = { DB8540_PIN_D12, DB8540_PIN_D15, + DB8540_PIN_C13, DB8540_PIN_C14, DB8540_PIN_C18, DB8540_PIN_C16, + DB8540_PIN_B16, DB8540_PIN_D18, DB8540_PIN_C15, DB8540_PIN_C17, + DB8540_PIN_B17, DB8540_PIN_D17 }; +/* Altfunction B colum */ +static const unsigned apetrig_b_1_pins[] = { DB8540_PIN_AH6, DB8540_PIN_AG7 }; +static const unsigned modtrig_b_1_pins[] = { DB8540_PIN_AF2, DB8540_PIN_AD3 }; +static const unsigned i2c4_b_1_pins[] = { DB8540_PIN_AF6, DB8540_PIN_AG6 }; +static const unsigned i2c1_b_1_pins[] = { DB8540_PIN_AD5, DB8540_PIN_AF7 }; +static const unsigned i2c2_b_1_pins[] = { DB8540_PIN_AG5, DB8540_PIN_AH5 }; +static const unsigned i2c2_b_2_pins[] = { DB8540_PIN_AE4, DB8540_PIN_AD1 }; +static const unsigned msp0txrx_b_1_pins[] = { DB8540_PIN_AD2, DB8540_PIN_AC3 }; +static const unsigned i2c1_b_2_pins[] = { DB8540_PIN_AH7, DB8540_PIN_AE7 }; +static const unsigned stmmod_b_1_pins[] = { DB8540_PIN_AH11, DB8540_PIN_AF11, + DB8540_PIN_AH10, DB8540_PIN_AG10, DB8540_PIN_AF10 }; +static const unsigned moduartstmmux_b_1_pins[] = { DB8540_PIN_AG11 }; +static const unsigned msp1txrx_b_1_pins[] = { DB8540_PIN_AD4, DB8540_PIN_AG4 }; +static const unsigned kp_b_1_pins[] = { DB8540_PIN_AJ24, DB8540_PIN_AE21, + DB8540_PIN_M26, DB8540_PIN_M25, DB8540_PIN_M27, DB8540_PIN_N25, + DB8540_PIN_M28, DB8540_PIN_N26, DB8540_PIN_M22, DB8540_PIN_N22, + DB8540_PIN_N27, DB8540_PIN_N28, DB8540_PIN_P22, DB8540_PIN_P28, + DB8540_PIN_P26, DB8540_PIN_T22, DB8540_PIN_R27, DB8540_PIN_P27, + DB8540_PIN_R26, DB8540_PIN_R25 }; +static const unsigned u2txrx_b_1_pins[] = { DB8540_PIN_U22, DB8540_PIN_T27 }; +static const unsigned sm_b_1_pins[] = { DB8540_PIN_AG22, DB8540_PIN_AF21, + DB8540_PIN_AF24, DB8540_PIN_AH22, DB8540_PIN_AJ23, DB8540_PIN_AH21, + DB8540_PIN_AG20, DB8540_PIN_AE23, DB8540_PIN_AH20, DB8540_PIN_AF22, + DB8540_PIN_AJ21, DB8540_PIN_AC27, DB8540_PIN_AD27, DB8540_PIN_AE28, + DB8540_PIN_AG26, DB8540_PIN_AF25, DB8540_PIN_AE27, DB8540_PIN_AF27, + DB8540_PIN_AG28, DB8540_PIN_AF28, DB8540_PIN_AG25, DB8540_PIN_AG24, + DB8540_PIN_AD25 }; +static const unsigned smcs0_b_1_pins[] = { DB8540_PIN_AG19 }; +static const unsigned smcs1_b_1_pins[] = { DB8540_PIN_AE26 }; +static const unsigned ipgpio7_b_1_pins[] = { DB8540_PIN_AH25 }; +static const unsigned ipgpio2_b_1_pins[] = { DB8540_PIN_AF26 }; +static const unsigned ipgpio3_b_1_pins[] = { DB8540_PIN_AF23 }; +static const unsigned i2c6_b_1_pins[] = { DB8540_PIN_AG23, DB8540_PIN_AE25 }; +static const unsigned i2c5_b_1_pins[] = { DB8540_PIN_AH24, DB8540_PIN_AJ25 }; +static const unsigned u3txrx_b_1_pins[] = { DB8540_PIN_AF20, DB8540_PIN_AG21 }; +static const unsigned u3ctsrts_b_1_pins[] = { DB8540_PIN_AH19, + DB8540_PIN_AE19 }; +static const unsigned i2c5_b_2_pins[] = { DB8540_PIN_AG18, DB8540_PIN_AH17 }; +static const unsigned i2c4_b_2_pins[] = { DB8540_PIN_AF19, DB8540_PIN_AF18 }; +static const unsigned u4txrx_b_1_pins[] = { DB8540_PIN_AE18, DB8540_PIN_AG17 }; +static const unsigned u4ctsrts_b_1_pins[] = { DB8540_PIN_AF17, + DB8540_PIN_AE17 }; +static const unsigned ddrtrig_b_1_pins[] = { DB8540_PIN_J3 }; +static const unsigned msp4_b_1_pins[] = { DB8540_PIN_H3 }; +static const unsigned pwl_b_1_pins[] = { DB8540_PIN_C6 }; +static const unsigned spi1_b_1_pins[] = { DB8540_PIN_E2, DB8540_PIN_C10, + DB8540_PIN_C8, DB8540_PIN_C9 }; +static const unsigned mc3_b_1_pins[] = { DB8540_PIN_B9, DB8540_PIN_A10, + DB8540_PIN_D9, DB8540_PIN_B11, DB8540_PIN_B10, DB8540_PIN_E10, + DB8540_PIN_B12 }; +static const unsigned pwl_b_2_pins[] = { DB8540_PIN_D10 }; +static const unsigned pwl_b_3_pins[] = { DB8540_PIN_B13 }; +static const unsigned pwl_b_4_pins[] = { DB8540_PIN_C12 }; +static const unsigned u2txrx_b_2_pins[] = { DB8540_PIN_B17, DB8540_PIN_D17 }; + +/* Altfunction C column */ +static const unsigned ipgpio6_c_1_pins[] = { DB8540_PIN_AG6 }; +static const unsigned ipgpio0_c_1_pins[] = { DB8540_PIN_AD5 }; +static const unsigned ipgpio1_c_1_pins[] = { DB8540_PIN_AF7 }; +static const unsigned ipgpio3_c_1_pins[] = { DB8540_PIN_AE4 }; +static const unsigned ipgpio2_c_1_pins[] = { DB8540_PIN_AD1 }; +static const unsigned u0_c_1_pins[] = { DB8540_PIN_AD4, DB8540_PIN_AF3, + DB8540_PIN_AF5, DB8540_PIN_AG4 }; +static const unsigned smcleale_c_1_pins[] = { DB8540_PIN_AJ24, + DB8540_PIN_AE21 }; +static const unsigned ipgpio4_c_1_pins[] = { DB8540_PIN_M26 }; +static const unsigned ipgpio5_c_1_pins[] = { DB8540_PIN_M25 }; +static const unsigned ipgpio6_c_2_pins[] = { DB8540_PIN_M27 }; +static const unsigned ipgpio7_c_1_pins[] = { DB8540_PIN_N25 }; +static const unsigned stmape_c_1_pins[] = { DB8540_PIN_M28, DB8540_PIN_N26, + DB8540_PIN_M22, DB8540_PIN_N22, DB8540_PIN_N27 }; +static const unsigned u2rxtx_c_1_pins[] = { DB8540_PIN_N28, DB8540_PIN_P22 }; +static const unsigned modobsresout_c_1_pins[] = { DB8540_PIN_P28 }; +static const unsigned ipgpio2_c_2_pins[] = { DB8540_PIN_P26 }; +static const unsigned ipgpio3_c_2_pins[] = { DB8540_PIN_T22 }; +static const unsigned ipgpio4_c_2_pins[] = { DB8540_PIN_R27 }; +static const unsigned ipgpio5_c_2_pins[] = { DB8540_PIN_P27 }; +static const unsigned modaccgpo_c_1_pins[] = { DB8540_PIN_R26, DB8540_PIN_R25, + DB8540_PIN_U22 }; +static const unsigned modobspwrrst_c_1_pins[] = { DB8540_PIN_T27 }; +static const unsigned mc5_c_1_pins[] = { DB8540_PIN_AG22, DB8540_PIN_AF21, + DB8540_PIN_AF24, DB8540_PIN_AH22, DB8540_PIN_AJ23, DB8540_PIN_AH21, + DB8540_PIN_AG20, DB8540_PIN_AE23, DB8540_PIN_AH20, DB8540_PIN_AF22, + DB8540_PIN_AJ21}; +static const unsigned smps0_c_1_pins[] = { DB8540_PIN_AG19 }; +static const unsigned moduart1_c_1_pins[] = { DB8540_PIN_T25, DB8540_PIN_T26 }; +static const unsigned mc2rstn_c_1_pins[] = { DB8540_PIN_AE28 }; +static const unsigned i2c5_c_1_pins[] = { DB8540_PIN_AG28, DB8540_PIN_AF28 }; +static const unsigned ipgpio0_c_2_pins[] = { DB8540_PIN_AG25 }; +static const unsigned ipgpio1_c_2_pins[] = { DB8540_PIN_AG24 }; +static const unsigned kp_c_1_pins[] = { DB8540_PIN_AD25, DB8540_PIN_AH25, + DB8540_PIN_AF26, DB8540_PIN_AF23 }; +static const unsigned modrf_c_1_pins[] = { DB8540_PIN_AG23, DB8540_PIN_AE25, + DB8540_PIN_AH24 }; +static const unsigned smps1_c_1_pins[] = { DB8540_PIN_AE26 }; +static const unsigned i2c5_c_2_pins[] = { DB8540_PIN_AH19, DB8540_PIN_AE19 }; +static const unsigned u4ctsrts_c_1_pins[] = { DB8540_PIN_AG18, + DB8540_PIN_AH17 }; +static const unsigned u3rxtx_c_1_pins[] = { DB8540_PIN_AF19, DB8540_PIN_AF18 }; +static const unsigned msp4_c_1_pins[] = { DB8540_PIN_J3 }; +static const unsigned mc4rstn_c_1_pins[] = { DB8540_PIN_C6 }; +static const unsigned spi0_c_1_pins[] = { DB8540_PIN_A10, DB8540_PIN_B10, + DB8540_PIN_E10, DB8540_PIN_B12 }; +static const unsigned i2c3_c_1_pins[] = { DB8540_PIN_B13, DB8540_PIN_C12 }; + +/* Other alt C1 column */ +static const unsigned spi3_oc1_1_pins[] = { DB8540_PIN_AG5, DB8540_PIN_AH5, + DB8540_PIN_AE4, DB8540_PIN_AD1 }; +static const unsigned stmape_oc1_1_pins[] = { DB8540_PIN_AH11, DB8540_PIN_AF11, + DB8540_PIN_AH10, DB8540_PIN_AG10, DB8540_PIN_AF10 }; +static const unsigned u2_oc1_1_pins[] = { DB8540_PIN_AG11 }; +static const unsigned remap0_oc1_1_pins[] = { DB8540_PIN_AJ24 }; +static const unsigned remap1_oc1_1_pins[] = { DB8540_PIN_AE21 }; +static const unsigned modobsrefclk_oc1_1_pins[] = { DB8540_PIN_M26 }; +static const unsigned modobspwrctrl_oc1_1_pins[] = { DB8540_PIN_M25 }; +static const unsigned modobsclkout_oc1_1_pins[] = { DB8540_PIN_M27 }; +static const unsigned moduart1_oc1_1_pins[] = { DB8540_PIN_N25 }; +static const unsigned modprcmudbg_oc1_1_pins[] = { DB8540_PIN_M28, + DB8540_PIN_N26, DB8540_PIN_M22, DB8540_PIN_N22, DB8540_PIN_N27, + DB8540_PIN_P22, DB8540_PIN_P28, DB8540_PIN_P26, DB8540_PIN_T22, + DB8540_PIN_R26, DB8540_PIN_R25, DB8540_PIN_U22, DB8540_PIN_T27, + DB8540_PIN_AH20, DB8540_PIN_AG19, DB8540_PIN_AF22, DB8540_PIN_AJ21, + DB8540_PIN_T25}; +static const unsigned modobsresout_oc1_1_pins[] = { DB8540_PIN_N28 }; +static const unsigned modaccgpo_oc1_1_pins[] = { DB8540_PIN_R27, DB8540_PIN_P27, + DB8540_PIN_T26 }; +static const unsigned kp_oc1_1_pins[] = { DB8540_PIN_AG22, DB8540_PIN_AF21, + DB8540_PIN_AF24, DB8540_PIN_AH22, DB8540_PIN_AJ23, DB8540_PIN_AH21, + DB8540_PIN_AG20, DB8540_PIN_AE23 }; +static const unsigned modxmip_oc1_1_pins[] = { DB8540_PIN_AD25, DB8540_PIN_AH25, + DB8540_PIN_AG23, DB8540_PIN_AE25 }; +static const unsigned i2c6_oc1_1_pins[] = { DB8540_PIN_AE26, DB8540_PIN_AE24 }; +static const unsigned u2txrx_oc1_1_pins[] = { DB8540_PIN_B7, DB8540_PIN_A7 }; +static const unsigned u2ctsrts_oc1_1_pins[] = { DB8540_PIN_D7, DB8540_PIN_D8 }; + +/* Other alt C2 column */ +static const unsigned sbag_oc2_1_pins[] = { DB8540_PIN_AH11, DB8540_PIN_AG11, + DB8540_PIN_AF11, DB8540_PIN_AH10, DB8540_PIN_AG10, DB8540_PIN_AF10 }; +static const unsigned hxclk_oc2_1_pins[] = { DB8540_PIN_M25 }; +static const unsigned modaccuart_oc2_1_pins[] = { DB8540_PIN_N25 }; +static const unsigned stmmod_oc2_1_pins[] = { DB8540_PIN_M28, DB8540_PIN_N26, + DB8540_PIN_M22, DB8540_PIN_N22, DB8540_PIN_N27 }; +static const unsigned moduartstmmux_oc2_1_pins[] = { DB8540_PIN_N28 }; +static const unsigned hxgpio_oc2_1_pins[] = { DB8540_PIN_P22, DB8540_PIN_P28, + DB8540_PIN_P26, DB8540_PIN_T22, DB8540_PIN_R27, DB8540_PIN_P27, + DB8540_PIN_R26, DB8540_PIN_R25 }; +static const unsigned sbag_oc2_2_pins[] = { DB8540_PIN_U22, DB8540_PIN_T27, + DB8540_PIN_AG22, DB8540_PIN_AF21, DB8540_PIN_AF24, DB8540_PIN_AH22 }; +static const unsigned modobsservice_oc2_1_pins[] = { DB8540_PIN_AJ23 }; +static const unsigned moduart0_oc2_1_pins[] = { DB8540_PIN_AG20, + DB8540_PIN_AE23 }; +static const unsigned stmape_oc2_1_pins[] = { DB8540_PIN_AH20, DB8540_PIN_AG19, + DB8540_PIN_AF22, DB8540_PIN_AJ21, DB8540_PIN_T25 }; +static const unsigned u2_oc2_1_pins[] = { DB8540_PIN_T26, DB8540_PIN_AH21 }; +static const unsigned modxmip_oc2_1_pins[] = { DB8540_PIN_AE26, + DB8540_PIN_AE24 }; + +/* Other alt C3 column */ +static const unsigned modaccgpo_oc3_1_pins[] = { DB8540_PIN_AG11 }; +static const unsigned tpui_oc3_1_pins[] = { DB8540_PIN_M26, DB8540_PIN_M25, + DB8540_PIN_M27, DB8540_PIN_N25, DB8540_PIN_M28, DB8540_PIN_N26, + DB8540_PIN_M22, DB8540_PIN_N22, DB8540_PIN_N27, DB8540_PIN_N28, + DB8540_PIN_P22, DB8540_PIN_P28, DB8540_PIN_P26, DB8540_PIN_T22, + DB8540_PIN_R27, DB8540_PIN_P27, DB8540_PIN_R26, DB8540_PIN_R25, + DB8540_PIN_U22, DB8540_PIN_T27, DB8540_PIN_AG22, DB8540_PIN_AF21, + DB8540_PIN_AF24, DB8540_PIN_AH22, DB8540_PIN_AJ23, DB8540_PIN_AH21, + DB8540_PIN_AG20, DB8540_PIN_AE23, DB8540_PIN_AH20, DB8540_PIN_AG19, + DB8540_PIN_AF22, DB8540_PIN_AJ21, DB8540_PIN_T25, DB8540_PIN_T26 }; + +/* Other alt C4 column */ +static const unsigned hwobs_oc4_1_pins[] = { DB8540_PIN_M26, DB8540_PIN_M25, + DB8540_PIN_M27, DB8540_PIN_N25, DB8540_PIN_M28, DB8540_PIN_N26, + DB8540_PIN_M22, DB8540_PIN_N22, DB8540_PIN_N27, DB8540_PIN_N28, + DB8540_PIN_P22, DB8540_PIN_P28, DB8540_PIN_P26, DB8540_PIN_T22, + DB8540_PIN_R27, DB8540_PIN_P27, DB8540_PIN_R26, DB8540_PIN_R25 }; +static const unsigned moduart1txrx_oc4_1_pins[] = { DB8540_PIN_U22, + DB8540_PIN_T27 }; +static const unsigned moduart1rtscts_oc4_1_pins[] = { DB8540_PIN_AG22, + DB8540_PIN_AF21 }; +static const unsigned modaccuarttxrx_oc4_1_pins[] = { DB8540_PIN_AF24, + DB8540_PIN_AH22 }; +static const unsigned modaccuartrtscts_oc4_1_pins[] = { DB8540_PIN_AJ23, + DB8540_PIN_AH21 }; +static const unsigned stmmod_oc4_1_pins[] = { DB8540_PIN_AH20, DB8540_PIN_AG19, + DB8540_PIN_AF22, DB8540_PIN_AJ21, DB8540_PIN_T25 }; +static const unsigned moduartstmmux_oc4_1_pins[] = { DB8540_PIN_T26 }; + +#define DB8540_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins, \ + .npins = ARRAY_SIZE(a##_pins), .altsetting = b } + +static const struct nmk_pingroup nmk_db8540_groups[] = { + /* Altfunction A column */ + DB8540_PIN_GROUP(u0_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(u1rxtx_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(u1ctsrts_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(ipi2c_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(ipi2c_a_2, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(msp0txrx_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(msp0tfstck_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(msp0rfsrck_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(mc0_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(msp1txrx_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(msp1_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(modobsclk_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(clkoutreq_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(lcdb_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(lcdvsi0_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(lcdvsi1_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(lcd_d0_d7_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(lcd_d8_d11_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(lcd_d12_d23_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(kp_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(mc2_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(ssp1_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(ssp0_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(i2c0_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(ipgpio0_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(ipgpio1_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(modi2s_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(spi2_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(u2txrx_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(u2ctsrts_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(modsmb_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(msp2sck_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(msp2txdtcktfs_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(msp2rxd_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(mc4_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(mc1_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(hsir_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(hsit_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(hsit_a_2, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(clkout1_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(clkout1_a_2, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(clkout2_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(clkout2_a_2, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(msp4_a_1, NMK_GPIO_ALT_A), + DB8540_PIN_GROUP(usb_a_1, NMK_GPIO_ALT_A), + /* Altfunction B column */ + DB8540_PIN_GROUP(apetrig_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(modtrig_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(i2c4_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(i2c1_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(i2c2_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(i2c2_b_2, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(msp0txrx_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(i2c1_b_2, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(stmmod_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(moduartstmmux_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(msp1txrx_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(kp_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(u2txrx_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(sm_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(smcs0_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(smcs1_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(ipgpio7_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(ipgpio2_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(ipgpio3_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(i2c6_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(i2c5_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(u3txrx_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(u3ctsrts_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(i2c5_b_2, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(i2c4_b_2, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(u4txrx_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(u4ctsrts_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(ddrtrig_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(msp4_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(pwl_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(spi1_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(mc3_b_1, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(pwl_b_2, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(pwl_b_3, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(pwl_b_4, NMK_GPIO_ALT_B), + DB8540_PIN_GROUP(u2txrx_b_2, NMK_GPIO_ALT_B), + /* Altfunction C column */ + DB8540_PIN_GROUP(ipgpio6_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(ipgpio0_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(ipgpio1_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(ipgpio3_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(ipgpio2_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(u0_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(smcleale_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(ipgpio4_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(ipgpio5_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(ipgpio6_c_2, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(ipgpio7_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(stmape_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(u2rxtx_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(modobsresout_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(ipgpio2_c_2, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(ipgpio3_c_2, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(ipgpio4_c_2, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(ipgpio5_c_2, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(modaccgpo_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(modobspwrrst_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(mc5_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(smps0_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(moduart1_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(mc2rstn_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(i2c5_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(ipgpio0_c_2, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(ipgpio1_c_2, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(kp_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(modrf_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(smps1_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(i2c5_c_2, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(u4ctsrts_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(u3rxtx_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(msp4_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(mc4rstn_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(spi0_c_1, NMK_GPIO_ALT_C), + DB8540_PIN_GROUP(i2c3_c_1, NMK_GPIO_ALT_C), + + /* Other alt C1 column */ + DB8540_PIN_GROUP(spi3_oc1_1, NMK_GPIO_ALT_C1), + DB8540_PIN_GROUP(stmape_oc1_1, NMK_GPIO_ALT_C1), + DB8540_PIN_GROUP(u2_oc1_1, NMK_GPIO_ALT_C1), + DB8540_PIN_GROUP(remap0_oc1_1, NMK_GPIO_ALT_C1), + DB8540_PIN_GROUP(remap1_oc1_1, NMK_GPIO_ALT_C1), + DB8540_PIN_GROUP(modobsrefclk_oc1_1, NMK_GPIO_ALT_C1), + DB8540_PIN_GROUP(modobspwrctrl_oc1_1, NMK_GPIO_ALT_C1), + DB8540_PIN_GROUP(modobsclkout_oc1_1, NMK_GPIO_ALT_C1), + DB8540_PIN_GROUP(moduart1_oc1_1, NMK_GPIO_ALT_C1), + DB8540_PIN_GROUP(modprcmudbg_oc1_1, NMK_GPIO_ALT_C1), + DB8540_PIN_GROUP(modobsresout_oc1_1, NMK_GPIO_ALT_C1), + DB8540_PIN_GROUP(modaccgpo_oc1_1, NMK_GPIO_ALT_C1), + DB8540_PIN_GROUP(kp_oc1_1, NMK_GPIO_ALT_C1), + DB8540_PIN_GROUP(modxmip_oc1_1, NMK_GPIO_ALT_C1), + DB8540_PIN_GROUP(i2c6_oc1_1, NMK_GPIO_ALT_C1), + DB8540_PIN_GROUP(u2txrx_oc1_1, NMK_GPIO_ALT_C1), + DB8540_PIN_GROUP(u2ctsrts_oc1_1, NMK_GPIO_ALT_C1), + + /* Other alt C2 column */ + DB8540_PIN_GROUP(sbag_oc2_1, NMK_GPIO_ALT_C2), + DB8540_PIN_GROUP(hxclk_oc2_1, NMK_GPIO_ALT_C2), + DB8540_PIN_GROUP(modaccuart_oc2_1, NMK_GPIO_ALT_C2), + DB8540_PIN_GROUP(stmmod_oc2_1, NMK_GPIO_ALT_C2), + DB8540_PIN_GROUP(moduartstmmux_oc2_1, NMK_GPIO_ALT_C2), + DB8540_PIN_GROUP(hxgpio_oc2_1, NMK_GPIO_ALT_C2), + DB8540_PIN_GROUP(sbag_oc2_2, NMK_GPIO_ALT_C2), + DB8540_PIN_GROUP(modobsservice_oc2_1, NMK_GPIO_ALT_C2), + DB8540_PIN_GROUP(moduart0_oc2_1, NMK_GPIO_ALT_C2), + DB8540_PIN_GROUP(stmape_oc2_1, NMK_GPIO_ALT_C2), + DB8540_PIN_GROUP(u2_oc2_1, NMK_GPIO_ALT_C2), + DB8540_PIN_GROUP(modxmip_oc2_1, NMK_GPIO_ALT_C2), + + /* Other alt C3 column */ + DB8540_PIN_GROUP(modaccgpo_oc3_1, NMK_GPIO_ALT_C3), + DB8540_PIN_GROUP(tpui_oc3_1, NMK_GPIO_ALT_C3), + + /* Other alt C4 column */ + DB8540_PIN_GROUP(hwobs_oc4_1, NMK_GPIO_ALT_C4), + DB8540_PIN_GROUP(moduart1txrx_oc4_1, NMK_GPIO_ALT_C4), + DB8540_PIN_GROUP(moduart1rtscts_oc4_1, NMK_GPIO_ALT_C4), + DB8540_PIN_GROUP(modaccuarttxrx_oc4_1, NMK_GPIO_ALT_C4), + DB8540_PIN_GROUP(modaccuartrtscts_oc4_1, NMK_GPIO_ALT_C4), + DB8540_PIN_GROUP(stmmod_oc4_1, NMK_GPIO_ALT_C4), + DB8540_PIN_GROUP(moduartstmmux_oc4_1, NMK_GPIO_ALT_C4), + +}; + +/* We use this macro to define the groups applicable to a function */ +#define DB8540_FUNC_GROUPS(a, b...) \ +static const char * const a##_groups[] = { b }; + +DB8540_FUNC_GROUPS(apetrig, "apetrig_b_1"); +DB8540_FUNC_GROUPS(clkout, "clkoutreq_a_1", "clkout1_a_1", "clkout1_a_2", + "clkout2_a_1", "clkout2_a_2"); +DB8540_FUNC_GROUPS(ddrtrig, "ddrtrig_b_1"); +DB8540_FUNC_GROUPS(hsi, "hsir_a_1", "hsit_a_1", "hsit_a_2"); +DB8540_FUNC_GROUPS(hwobs, "hwobs_oc4_1"); +DB8540_FUNC_GROUPS(hx, "hxclk_oc2_1", "hxgpio_oc2_1"); +DB8540_FUNC_GROUPS(i2c0, "i2c0_a_1"); +DB8540_FUNC_GROUPS(i2c1, "i2c1_b_1", "i2c1_b_2"); +DB8540_FUNC_GROUPS(i2c2, "i2c2_b_1", "i2c2_b_2"); +DB8540_FUNC_GROUPS(i2c3, "i2c3_c_1", "i2c4_b_1"); +DB8540_FUNC_GROUPS(i2c4, "i2c4_b_2"); +DB8540_FUNC_GROUPS(i2c5, "i2c5_b_1", "i2c5_b_2", "i2c5_c_1", "i2c5_c_2"); +DB8540_FUNC_GROUPS(i2c6, "i2c6_b_1", "i2c6_oc1_1"); +/* The image processor has 8 GPIO pins that can be muxed out */ +DB8540_FUNC_GROUPS(ipgpio, "ipgpio0_a_1", "ipgpio0_c_1", "ipgpio0_c_2", + "ipgpio1_a_1", "ipgpio1_c_1", "ipgpio1_c_2", + "ipgpio2_b_1", "ipgpio2_c_1", "ipgpio2_c_2", + "ipgpio3_b_1", "ipgpio3_c_1", "ipgpio3_c_2", + "ipgpio4_c_1", "ipgpio4_c_2", + "ipgpio5_c_1", "ipgpio5_c_2", + "ipgpio6_c_1", "ipgpio6_c_2", + "ipgpio7_b_1", "ipgpio7_c_1"); +DB8540_FUNC_GROUPS(ipi2c, "ipi2c_a_1", "ipi2c_a_2"); +DB8540_FUNC_GROUPS(kp, "kp_a_1", "kp_b_1", "kp_c_1", "kp_oc1_1"); +DB8540_FUNC_GROUPS(lcd, "lcd_d0_d7_a_1", "lcd_d12_d23_a_1", "lcd_d8_d11_a_1", + "lcdvsi0_a_1", "lcdvsi1_a_1"); +DB8540_FUNC_GROUPS(lcdb, "lcdb_a_1"); +DB8540_FUNC_GROUPS(mc0, "mc0_a_1"); +DB8540_FUNC_GROUPS(mc1, "mc1_a_1", "mc1_a_2"); +DB8540_FUNC_GROUPS(mc2, "mc2_a_1", "mc2rstn_c_1"); +DB8540_FUNC_GROUPS(mc3, "mc3_b_1"); +DB8540_FUNC_GROUPS(mc4, "mc4_a_1", "mc4rstn_c_1"); +DB8540_FUNC_GROUPS(mc5, "mc5_c_1"); +DB8540_FUNC_GROUPS(modaccgpo, "modaccgpo_c_1", "modaccgpo_oc1_1", + "modaccgpo_oc3_1"); +DB8540_FUNC_GROUPS(modaccuart, "modaccuart_oc2_1", "modaccuarttxrx_oc4_1", + "modaccuartrtccts_oc4_1"); +DB8540_FUNC_GROUPS(modi2s, "modi2s_a_1"); +DB8540_FUNC_GROUPS(modobs, "modobsclk_a_1", "modobsclkout_oc1_1", + "modobspwrctrl_oc1_1", "modobspwrrst_c_1", + "modobsrefclk_oc1_1", "modobsresout_c_1", + "modobsresout_oc1_1", "modobsservice_oc2_1"); +DB8540_FUNC_GROUPS(modprcmudbg, "modprcmudbg_oc1_1"); +DB8540_FUNC_GROUPS(modrf, "modrf_c_1"); +DB8540_FUNC_GROUPS(modsmb, "modsmb_a_1"); +DB8540_FUNC_GROUPS(modtrig, "modtrig_b_1"); +DB8540_FUNC_GROUPS(moduart, "moduart1_c_1", "moduart1_oc1_1", + "moduart1txrx_oc4_1", "moduart1rtscts_oc4_1", "moduart0_oc2_1"); +DB8540_FUNC_GROUPS(moduartstmmux, "moduartstmmux_b_1", "moduartstmmux_oc2_1", + "moduartstmmux_oc4_1"); +DB8540_FUNC_GROUPS(modxmip, "modxmip_oc1_1", "modxmip_oc2_1"); +/* + * MSP0 can only be on a certain set of pins, but the TX/RX pins can be + * switched around by selecting the altfunction A or B. + */ +DB8540_FUNC_GROUPS(msp0, "msp0rfsrck_a_1", "msp0tfstck_a_1", "msp0txrx_a_1", + "msp0txrx_b_1"); +DB8540_FUNC_GROUPS(msp1, "msp1_a_1", "msp1txrx_a_1", "msp1txrx_b_1"); +DB8540_FUNC_GROUPS(msp2, "msp2sck_a_1", "msp2txdtcktfs_a_1", "msp2rxd_a_1"); +DB8540_FUNC_GROUPS(msp4, "msp4_a_1", "msp4_b_1", "msp4_c_1"); +DB8540_FUNC_GROUPS(pwl, "pwl_b_1", "pwl_b_2", "pwl_b_3", "pwl_b_4"); +DB8540_FUNC_GROUPS(remap, "remap0_oc1_1", "remap1_oc1_1"); +DB8540_FUNC_GROUPS(sbag, "sbag_oc2_1", "sbag_oc2_2"); +/* Select between CS0 on alt B or PS1 on alt C */ +DB8540_FUNC_GROUPS(sm, "sm_b_1", "smcleale_c_1", "smcs0_b_1", "smcs1_b_1", + "smps0_c_1", "smps1_c_1"); +DB8540_FUNC_GROUPS(spi0, "spi0_c_1"); +DB8540_FUNC_GROUPS(spi1, "spi1_b_1"); +DB8540_FUNC_GROUPS(spi2, "spi2_a_1"); +DB8540_FUNC_GROUPS(spi3, "spi3_oc1_1"); +DB8540_FUNC_GROUPS(ssp0, "ssp0_a_1"); +DB8540_FUNC_GROUPS(ssp1, "ssp1_a_1"); +DB8540_FUNC_GROUPS(stmape, "stmape_c_1", "stmape_oc1_1", "stmape_oc2_1"); +DB8540_FUNC_GROUPS(stmmod, "stmmod_b_1", "stmmod_oc2_1", "stmmod_oc4_1"); +DB8540_FUNC_GROUPS(tpui, "tpui_oc3_1"); +DB8540_FUNC_GROUPS(u0, "u0_a_1", "u0_c_1"); +DB8540_FUNC_GROUPS(u1, "u1ctsrts_a_1", "u1rxtx_a_1"); +DB8540_FUNC_GROUPS(u2, "u2_oc1_1", "u2_oc2_1", "u2ctsrts_a_1", "u2ctsrts_oc1_1", + "u2rxtx_c_1", "u2txrx_a_1", "u2txrx_b_1", "u2txrx_b_2", + "u2txrx_oc1_1"); +DB8540_FUNC_GROUPS(u3, "u3ctsrts_b_1", "u3rxtx_c_1", "u3txrxa_b_1"); +DB8540_FUNC_GROUPS(u4, "u4ctsrts_b_1", "u4ctsrts_c_1", "u4txrx_b_1"); +DB8540_FUNC_GROUPS(usb, "usb_a_1"); + + +#define FUNCTION(fname) \ + { \ + .name = #fname, \ + .groups = fname##_groups, \ + .ngroups = ARRAY_SIZE(fname##_groups), \ + } + +static const struct nmk_function nmk_db8540_functions[] = { + FUNCTION(apetrig), + FUNCTION(clkout), + FUNCTION(ddrtrig), + FUNCTION(hsi), + FUNCTION(hwobs), + FUNCTION(hx), + FUNCTION(i2c0), + FUNCTION(i2c1), + FUNCTION(i2c2), + FUNCTION(i2c3), + FUNCTION(i2c4), + FUNCTION(i2c5), + FUNCTION(i2c6), + FUNCTION(ipgpio), + FUNCTION(ipi2c), + FUNCTION(kp), + FUNCTION(lcd), + FUNCTION(lcdb), + FUNCTION(mc0), + FUNCTION(mc1), + FUNCTION(mc2), + FUNCTION(mc3), + FUNCTION(mc4), + FUNCTION(mc5), + FUNCTION(modaccgpo), + FUNCTION(modaccuart), + FUNCTION(modi2s), + FUNCTION(modobs), + FUNCTION(modprcmudbg), + FUNCTION(modrf), + FUNCTION(modsmb), + FUNCTION(modtrig), + FUNCTION(moduart), + FUNCTION(modxmip), + FUNCTION(msp0), + FUNCTION(msp1), + FUNCTION(msp2), + FUNCTION(msp4), + FUNCTION(pwl), + FUNCTION(remap), + FUNCTION(sbag), + FUNCTION(sm), + FUNCTION(spi0), + FUNCTION(spi1), + FUNCTION(spi2), + FUNCTION(spi3), + FUNCTION(ssp0), + FUNCTION(ssp1), + FUNCTION(stmape), + FUNCTION(stmmod), + FUNCTION(tpui), + FUNCTION(u0), + FUNCTION(u1), + FUNCTION(u2), + FUNCTION(u3), + FUNCTION(u4), + FUNCTION(usb) +}; + +static const struct prcm_gpiocr_altcx_pin_desc db8540_altcx_pins[] = { + PRCM_GPIOCR_ALTCX(8, true, PRCM_IDX_GPIOCR1, 20, /* SPI3_CLK */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(9, true, PRCM_IDX_GPIOCR1, 20, /* SPI3_RXD */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(10, true, PRCM_IDX_GPIOCR1, 20, /* SPI3_FRM */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(11, true, PRCM_IDX_GPIOCR1, 20, /* SPI3_TXD */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(23, true, PRCM_IDX_GPIOCR1, 9, /* STMAPE_CLK_a */ + true, PRCM_IDX_GPIOCR2, 10, /* SBAG_CLK_a */ + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(24, true, PRCM_IDX_GPIOCR3, 30, /* U2_RXD_g */ + true, PRCM_IDX_GPIOCR2, 10, /* SBAG_VAL_a */ + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(25, true, PRCM_IDX_GPIOCR1, 9, /* STMAPE_DAT_a[0] */ + true, PRCM_IDX_GPIOCR2, 10, /* SBAG_D_a[0] */ + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(26, true, PRCM_IDX_GPIOCR1, 9, /* STMAPE_DAT_a[1] */ + true, PRCM_IDX_GPIOCR2, 10, /* SBAG_D_a[1] */ + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(27, true, PRCM_IDX_GPIOCR1, 9, /* STMAPE_DAT_a[2] */ + true, PRCM_IDX_GPIOCR2, 10, /* SBAG_D_a[2] */ + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(28, true, PRCM_IDX_GPIOCR1, 9, /* STMAPE_DAT_a[3] */ + true, PRCM_IDX_GPIOCR2, 10, /* SBAG_D_a[3] */ + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(64, true, PRCM_IDX_GPIOCR1, 15, /* MODOBS_REFCLK_REQ */ + false, 0, 0, + true, PRCM_IDX_GPIOCR1, 2, /* TPIU_CTL */ + true, PRCM_IDX_GPIOCR2, 23 /* HW_OBS_APE_PRCMU[17] */ + ), + PRCM_GPIOCR_ALTCX(65, true, PRCM_IDX_GPIOCR1, 19, /* MODOBS_PWRCTRL0 */ + true, PRCM_IDX_GPIOCR1, 24, /* Hx_CLK */ + true, PRCM_IDX_GPIOCR1, 2, /* TPIU_CLK */ + true, PRCM_IDX_GPIOCR2, 24 /* HW_OBS_APE_PRCMU[16] */ + ), + PRCM_GPIOCR_ALTCX(66, true, PRCM_IDX_GPIOCR1, 15, /* MODOBS_CLKOUT1 */ + false, 0, 0, + true, PRCM_IDX_GPIOCR1, 2, /* TPIU_D[15] */ + true, PRCM_IDX_GPIOCR2, 25 /* HW_OBS_APE_PRCMU[15] */ + ), + PRCM_GPIOCR_ALTCX(67, true, PRCM_IDX_GPIOCR1, 1, /* MODUART1_TXD_a */ + true, PRCM_IDX_GPIOCR1, 6, /* MODACCUART_TXD_a */ + true, PRCM_IDX_GPIOCR1, 2, /* TPIU_D[14] */ + true, PRCM_IDX_GPIOCR2, 26 /* HW_OBS_APE_PRCMU[14] */ + ), + PRCM_GPIOCR_ALTCX(70, true, PRCM_IDX_GPIOCR3, 6, /* MOD_PRCMU_DEBUG[17] */ + true, PRCM_IDX_GPIOCR1, 10, /* STMMOD_CLK_b */ + true, PRCM_IDX_GPIOCR1, 2, /* TPIU_D[13] */ + true, PRCM_IDX_GPIOCR2, 27 /* HW_OBS_APE_PRCMU[13] */ + ), + PRCM_GPIOCR_ALTCX(71, true, PRCM_IDX_GPIOCR3, 6, /* MOD_PRCMU_DEBUG[16] */ + true, PRCM_IDX_GPIOCR1, 10, /* STMMOD_DAT_b[3] */ + true, PRCM_IDX_GPIOCR1, 2, /* TPIU_D[12] */ + true, PRCM_IDX_GPIOCR2, 27 /* HW_OBS_APE_PRCMU[12] */ + ), + PRCM_GPIOCR_ALTCX(72, true, PRCM_IDX_GPIOCR3, 6, /* MOD_PRCMU_DEBUG[15] */ + true, PRCM_IDX_GPIOCR1, 10, /* STMMOD_DAT_b[2] */ + true, PRCM_IDX_GPIOCR1, 2, /* TPIU_D[11] */ + true, PRCM_IDX_GPIOCR2, 27 /* HW_OBS_APE_PRCMU[11] */ + ), + PRCM_GPIOCR_ALTCX(73, true, PRCM_IDX_GPIOCR3, 6, /* MOD_PRCMU_DEBUG[14] */ + true, PRCM_IDX_GPIOCR1, 10, /* STMMOD_DAT_b[1] */ + true, PRCM_IDX_GPIOCR1, 2, /* TPIU_D[10] */ + true, PRCM_IDX_GPIOCR2, 27 /* HW_OBS_APE_PRCMU[10] */ + ), + PRCM_GPIOCR_ALTCX(74, true, PRCM_IDX_GPIOCR3, 6, /* MOD_PRCMU_DEBUG[13] */ + true, PRCM_IDX_GPIOCR1, 10, /* STMMOD_DAT_b[0] */ + true, PRCM_IDX_GPIOCR1, 2, /* TPIU_D[9] */ + true, PRCM_IDX_GPIOCR2, 27 /* HW_OBS_APE_PRCMU[9] */ + ), + PRCM_GPIOCR_ALTCX(75, true, PRCM_IDX_GPIOCR1, 12, /* MODOBS_RESOUT0_N */ + true, PRCM_IDX_GPIOCR2, 1, /* MODUART_STMMUX_RXD_b */ + true, PRCM_IDX_GPIOCR1, 2, /* TPIU_D[8] */ + true, PRCM_IDX_GPIOCR2, 28 /* HW_OBS_APE_PRCMU[8] */ + ), + PRCM_GPIOCR_ALTCX(76, true, PRCM_IDX_GPIOCR3, 7, /* MOD_PRCMU_DEBUG[12] */ + true, PRCM_IDX_GPIOCR1, 25, /* Hx_GPIO[7] */ + true, PRCM_IDX_GPIOCR1, 2, /* TPIU_D[7] */ + true, PRCM_IDX_GPIOCR2, 29 /* HW_OBS_APE_PRCMU[7] */ + ), + PRCM_GPIOCR_ALTCX(77, true, PRCM_IDX_GPIOCR3, 7, /* MOD_PRCMU_DEBUG[11] */ + true, PRCM_IDX_GPIOCR1, 25, /* Hx_GPIO[6] */ + true, PRCM_IDX_GPIOCR1, 2, /* TPIU_D[6] */ + true, PRCM_IDX_GPIOCR2, 29 /* HW_OBS_APE_PRCMU[6] */ + ), + PRCM_GPIOCR_ALTCX(78, true, PRCM_IDX_GPIOCR3, 7, /* MOD_PRCMU_DEBUG[10] */ + true, PRCM_IDX_GPIOCR1, 25, /* Hx_GPIO[5] */ + true, PRCM_IDX_GPIOCR1, 2, /* TPIU_D[5] */ + true, PRCM_IDX_GPIOCR2, 29 /* HW_OBS_APE_PRCMU[5] */ + ), + PRCM_GPIOCR_ALTCX(79, true, PRCM_IDX_GPIOCR3, 7, /* MOD_PRCMU_DEBUG[9] */ + true, PRCM_IDX_GPIOCR1, 25, /* Hx_GPIO[4] */ + true, PRCM_IDX_GPIOCR1, 2, /* TPIU_D[4] */ + true, PRCM_IDX_GPIOCR2, 29 /* HW_OBS_APE_PRCMU[4] */ + ), + PRCM_GPIOCR_ALTCX(80, true, PRCM_IDX_GPIOCR1, 26, /* MODACC_GPO[0] */ + true, PRCM_IDX_GPIOCR1, 25, /* Hx_GPIO[3] */ + true, PRCM_IDX_GPIOCR1, 2, /* TPIU_D[3] */ + true, PRCM_IDX_GPIOCR2, 30 /* HW_OBS_APE_PRCMU[3] */ + ), + PRCM_GPIOCR_ALTCX(81, true, PRCM_IDX_GPIOCR2, 17, /* MODACC_GPO[1] */ + true, PRCM_IDX_GPIOCR1, 25, /* Hx_GPIO[2] */ + true, PRCM_IDX_GPIOCR1, 2, /* TPIU_D[2] */ + true, PRCM_IDX_GPIOCR2, 30 /* HW_OBS_APE_PRCMU[2] */ + ), + PRCM_GPIOCR_ALTCX(82, true, PRCM_IDX_GPIOCR3, 8, /* MOD_PRCMU_DEBUG[8] */ + true, PRCM_IDX_GPIOCR1, 25, /* Hx_GPIO[1] */ + true, PRCM_IDX_GPIOCR1, 2, /* TPIU_D[1] */ + true, PRCM_IDX_GPIOCR2, 31 /* HW_OBS_APE_PRCMU[1] */ + ), + PRCM_GPIOCR_ALTCX(83, true, PRCM_IDX_GPIOCR3, 8, /* MOD_PRCMU_DEBUG[7] */ + true, PRCM_IDX_GPIOCR1, 25, /* Hx_GPIO[0] */ + true, PRCM_IDX_GPIOCR1, 2, /* TPIU_D[0] */ + true, PRCM_IDX_GPIOCR2, 31 /* HW_OBS_APE_PRCMU[0] */ + ), + PRCM_GPIOCR_ALTCX(84, true, PRCM_IDX_GPIOCR3, 9, /* MOD_PRCMU_DEBUG[6] */ + true, PRCM_IDX_GPIOCR1, 8, /* SBAG_CLK_b */ + true, PRCM_IDX_GPIOCR1, 3, /* TPIU_D[23] */ + true, PRCM_IDX_GPIOCR1, 16 /* MODUART1_RXD_b */ + ), + PRCM_GPIOCR_ALTCX(85, true, PRCM_IDX_GPIOCR3, 9, /* MOD_PRCMU_DEBUG[5] */ + true, PRCM_IDX_GPIOCR1, 8, /* SBAG_D_b[3] */ + true, PRCM_IDX_GPIOCR1, 3, /* TPIU_D[22] */ + true, PRCM_IDX_GPIOCR1, 16 /* MODUART1_TXD_b */ + ), + PRCM_GPIOCR_ALTCX(86, true, PRCM_IDX_GPIOCR3, 9, /* MOD_PRCMU_DEBUG[0] */ + true, PRCM_IDX_GPIOCR2, 18, /* STMAPE_DAT_b[0] */ + true, PRCM_IDX_GPIOCR1, 14, /* TPIU_D[25] */ + true, PRCM_IDX_GPIOCR1, 11 /* STMMOD_DAT_c[0] */ + ), + PRCM_GPIOCR_ALTCX(87, true, PRCM_IDX_GPIOCR3, 0, /* MODACC_GPO_a[5] */ + true, PRCM_IDX_GPIOCR2, 3, /* U2_RXD_c */ + true, PRCM_IDX_GPIOCR1, 4, /* TPIU_D[24] */ + true, PRCM_IDX_GPIOCR1, 21 /* MODUART_STMMUX_RXD_c */ + ), + PRCM_GPIOCR_ALTCX(151, true, PRCM_IDX_GPIOCR1, 18, /* REMAP0 */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(152, true, PRCM_IDX_GPIOCR1, 18, /* REMAP1 */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(153, true, PRCM_IDX_GPIOCR3, 2, /* KP_O_b[6] */ + true, PRCM_IDX_GPIOCR1, 8, /* SBAG_D_b[2] */ + true, PRCM_IDX_GPIOCR1, 3, /* TPIU_D[21] */ + true, PRCM_IDX_GPIOCR1, 0 /* MODUART1_RTS */ + ), + PRCM_GPIOCR_ALTCX(154, true, PRCM_IDX_GPIOCR3, 2, /* KP_I_b[6] */ + true, PRCM_IDX_GPIOCR1, 8, /* SBAG_D_b[1] */ + true, PRCM_IDX_GPIOCR1, 3, /* TPIU_D[20] */ + true, PRCM_IDX_GPIOCR1, 0 /* MODUART1_CTS */ + ), + PRCM_GPIOCR_ALTCX(155, true, PRCM_IDX_GPIOCR3, 3, /* KP_O_b[5] */ + true, PRCM_IDX_GPIOCR1, 8, /* SBAG_D_b[0] */ + true, PRCM_IDX_GPIOCR1, 3, /* TPIU_D[19] */ + true, PRCM_IDX_GPIOCR1, 5 /* MODACCUART_RXD_c */ + ), + PRCM_GPIOCR_ALTCX(156, true, PRCM_IDX_GPIOCR3, 3, /* KP_O_b[4] */ + true, PRCM_IDX_GPIOCR1, 8, /* SBAG_VAL_b */ + true, PRCM_IDX_GPIOCR1, 3, /* TPIU_D[18] */ + true, PRCM_IDX_GPIOCR1, 5 /* MODACCUART_TXD_b */ + ), + PRCM_GPIOCR_ALTCX(157, true, PRCM_IDX_GPIOCR3, 4, /* KP_I_b[5] */ + true, PRCM_IDX_GPIOCR1, 23, /* MODOBS_SERVICE_N */ + true, PRCM_IDX_GPIOCR1, 3, /* TPIU_D[17] */ + true, PRCM_IDX_GPIOCR1, 14 /* MODACCUART_RTS */ + ), + PRCM_GPIOCR_ALTCX(158, true, PRCM_IDX_GPIOCR3, 4, /* KP_I_b[4] */ + true, PRCM_IDX_GPIOCR2, 0, /* U2_TXD_c */ + true, PRCM_IDX_GPIOCR1, 3, /* TPIU_D[16] */ + true, PRCM_IDX_GPIOCR1, 14 /* MODACCUART_CTS */ + ), + PRCM_GPIOCR_ALTCX(159, true, PRCM_IDX_GPIOCR3, 5, /* KP_O_b[3] */ + true, PRCM_IDX_GPIOCR3, 10, /* MODUART0_RXD */ + true, PRCM_IDX_GPIOCR1, 4, /* TPIU_D[31] */ + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(160, true, PRCM_IDX_GPIOCR3, 5, /* KP_I_b[3] */ + true, PRCM_IDX_GPIOCR3, 10, /* MODUART0_TXD */ + true, PRCM_IDX_GPIOCR1, 4, /* TPIU_D[30] */ + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(161, true, PRCM_IDX_GPIOCR3, 9, /* MOD_PRCMU_DEBUG[4] */ + true, PRCM_IDX_GPIOCR2, 18, /* STMAPE_CLK_b */ + true, PRCM_IDX_GPIOCR1, 4, /* TPIU_D[29] */ + true, PRCM_IDX_GPIOCR1, 11 /* STMMOD_CLK_c */ + ), + PRCM_GPIOCR_ALTCX(162, true, PRCM_IDX_GPIOCR3, 9, /* MOD_PRCMU_DEBUG[3] */ + true, PRCM_IDX_GPIOCR2, 18, /* STMAPE_DAT_b[3] */ + true, PRCM_IDX_GPIOCR1, 4, /* TPIU_D[28] */ + true, PRCM_IDX_GPIOCR1, 11 /* STMMOD_DAT_c[3] */ + ), + PRCM_GPIOCR_ALTCX(163, true, PRCM_IDX_GPIOCR3, 9, /* MOD_PRCMU_DEBUG[2] */ + true, PRCM_IDX_GPIOCR2, 18, /* STMAPE_DAT_b[2] */ + true, PRCM_IDX_GPIOCR1, 4, /* TPIU_D[27] */ + true, PRCM_IDX_GPIOCR1, 11 /* STMMOD_DAT_c[2] */ + ), + PRCM_GPIOCR_ALTCX(164, true, PRCM_IDX_GPIOCR3, 9, /* MOD_PRCMU_DEBUG[1] */ + true, PRCM_IDX_GPIOCR2, 18, /* STMAPE_DAT_b[1] */ + true, PRCM_IDX_GPIOCR1, 4, /* TPIU_D[26] */ + true, PRCM_IDX_GPIOCR1, 11 /* STMMOD_DAT_c[1] */ + ), + PRCM_GPIOCR_ALTCX(204, true, PRCM_IDX_GPIOCR2, 2, /* U2_RXD_f */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(205, true, PRCM_IDX_GPIOCR2, 2, /* U2_TXD_f */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(206, true, PRCM_IDX_GPIOCR2, 2, /* U2_CTSn_b */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), + PRCM_GPIOCR_ALTCX(207, true, PRCM_IDX_GPIOCR2, 2, /* U2_RTSn_b */ + false, 0, 0, + false, 0, 0, + false, 0, 0 + ), +}; + +static const u16 db8540_prcm_gpiocr_regs[] = { + [PRCM_IDX_GPIOCR1] = 0x138, + [PRCM_IDX_GPIOCR2] = 0x574, + [PRCM_IDX_GPIOCR3] = 0x2bc, +}; + +static const struct nmk_pinctrl_soc_data nmk_db8540_soc = { + .gpio_ranges = nmk_db8540_ranges, + .gpio_num_ranges = ARRAY_SIZE(nmk_db8540_ranges), + .pins = nmk_db8540_pins, + .npins = ARRAY_SIZE(nmk_db8540_pins), + .functions = nmk_db8540_functions, + .nfunctions = ARRAY_SIZE(nmk_db8540_functions), + .groups = nmk_db8540_groups, + .ngroups = ARRAY_SIZE(nmk_db8540_groups), + .altcx_pins = db8540_altcx_pins, + .npins_altcx = ARRAY_SIZE(db8540_altcx_pins), + .prcm_gpiocr_registers = db8540_prcm_gpiocr_regs, +}; + +void nmk_pinctrl_db8540_init(const struct nmk_pinctrl_soc_data **soc) +{ + *soc = &nmk_db8540_soc; +} diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c b/drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c new file mode 100644 index 000000000000..ed39dcafd4f8 --- /dev/null +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c @@ -0,0 +1,356 @@ +#include <linux/kernel.h> +#include <linux/pinctrl/pinctrl.h> +#include "pinctrl-nomadik.h" + +/* All the pins that can be used for GPIO and some other functions */ +#define _GPIO(offset) (offset) + +#define STN8815_PIN_B4 _GPIO(0) +#define STN8815_PIN_D5 _GPIO(1) +#define STN8815_PIN_C5 _GPIO(2) +#define STN8815_PIN_A4 _GPIO(3) +#define STN8815_PIN_B5 _GPIO(4) +#define STN8815_PIN_D6 _GPIO(5) +#define STN8815_PIN_C6 _GPIO(6) +#define STN8815_PIN_B6 _GPIO(7) +#define STN8815_PIN_B10 _GPIO(8) +#define STN8815_PIN_A10 _GPIO(9) +#define STN8815_PIN_C11 _GPIO(10) +#define STN8815_PIN_B11 _GPIO(11) +#define STN8815_PIN_A11 _GPIO(12) +#define STN8815_PIN_C12 _GPIO(13) +#define STN8815_PIN_B12 _GPIO(14) +#define STN8815_PIN_A12 _GPIO(15) +#define STN8815_PIN_C13 _GPIO(16) +#define STN8815_PIN_B13 _GPIO(17) +#define STN8815_PIN_A13 _GPIO(18) +#define STN8815_PIN_D13 _GPIO(19) +#define STN8815_PIN_C14 _GPIO(20) +#define STN8815_PIN_B14 _GPIO(21) +#define STN8815_PIN_A14 _GPIO(22) +#define STN8815_PIN_D15 _GPIO(23) +#define STN8815_PIN_C15 _GPIO(24) +#define STN8815_PIN_B15 _GPIO(25) +#define STN8815_PIN_A15 _GPIO(26) +#define STN8815_PIN_C16 _GPIO(27) +#define STN8815_PIN_B16 _GPIO(28) +#define STN8815_PIN_A16 _GPIO(29) +#define STN8815_PIN_D17 _GPIO(30) +#define STN8815_PIN_C17 _GPIO(31) +#define STN8815_PIN_AB6 _GPIO(32) +#define STN8815_PIN_AA6 _GPIO(33) +#define STN8815_PIN_Y6 _GPIO(34) +#define STN8815_PIN_Y5 _GPIO(35) +#define STN8815_PIN_AA5 _GPIO(36) +#define STN8815_PIN_AB5 _GPIO(37) +#define STN8815_PIN_AB4 _GPIO(38) +#define STN8815_PIN_Y4 _GPIO(39) +#define STN8815_PIN_R1 _GPIO(40) +#define STN8815_PIN_R2 _GPIO(41) +#define STN8815_PIN_R3 _GPIO(42) +#define STN8815_PIN_P1 _GPIO(43) +#define STN8815_PIN_P2 _GPIO(44) +#define STN8815_PIN_P3 _GPIO(45) +#define STN8815_PIN_N1 _GPIO(46) +#define STN8815_PIN_N2 _GPIO(47) +#define STN8815_PIN_N3 _GPIO(48) +#define STN8815_PIN_M1 _GPIO(49) +#define STN8815_PIN_M3 _GPIO(50) +#define STN8815_PIN_M2 _GPIO(51) +#define STN8815_PIN_L1 _GPIO(52) +#define STN8815_PIN_L4 _GPIO(53) +#define STN8815_PIN_L3 _GPIO(54) +#define STN8815_PIN_L2 _GPIO(55) +#define STN8815_PIN_F3 _GPIO(56) +#define STN8815_PIN_F2 _GPIO(57) +#define STN8815_PIN_E1 _GPIO(58) +#define STN8815_PIN_E3 _GPIO(59) +#define STN8815_PIN_E2 _GPIO(60) +#define STN8815_PIN_E4 _GPIO(61) +#define STN8815_PIN_D3 _GPIO(62) +#define STN8815_PIN_D2 _GPIO(63) +#define STN8815_PIN_F21 _GPIO(64) +#define STN8815_PIN_F20 _GPIO(65) +#define STN8815_PIN_E22 _GPIO(66) +#define STN8815_PIN_D22 _GPIO(67) +#define STN8815_PIN_E21 _GPIO(68) +#define STN8815_PIN_E20 _GPIO(69) +#define STN8815_PIN_C22 _GPIO(70) +#define STN8815_PIN_D21 _GPIO(71) +#define STN8815_PIN_D20 _GPIO(72) +#define STN8815_PIN_C21 _GPIO(73) +#define STN8815_PIN_C20 _GPIO(74) +#define STN8815_PIN_C19 _GPIO(75) +#define STN8815_PIN_B20 _GPIO(76) +#define STN8815_PIN_B8 _GPIO(77) +#define STN8815_PIN_A8 _GPIO(78) +#define STN8815_PIN_C9 _GPIO(79) +#define STN8815_PIN_B9 _GPIO(80) +#define STN8815_PIN_A9 _GPIO(81) +#define STN8815_PIN_C10 _GPIO(82) +#define STN8815_PIN_K1 _GPIO(83) +#define STN8815_PIN_K3 _GPIO(84) +#define STN8815_PIN_K2 _GPIO(85) +#define STN8815_PIN_J1 _GPIO(86) +#define STN8815_PIN_J3 _GPIO(87) +#define STN8815_PIN_J2 _GPIO(88) +#define STN8815_PIN_H1 _GPIO(89) +#define STN8815_PIN_H3 _GPIO(90) +#define STN8815_PIN_H2 _GPIO(91) +#define STN8815_PIN_G1 _GPIO(92) +#define STN8815_PIN_G3 _GPIO(93) +#define STN8815_PIN_G2 _GPIO(94) +#define STN8815_PIN_F1 _GPIO(95) +#define STN8815_PIN_T20 _GPIO(96) +#define STN8815_PIN_R21 _GPIO(97) +#define STN8815_PIN_R20 _GPIO(98) +#define STN8815_PIN_U22 _GPIO(99) +#define STN8815_PIN_N21 _GPIO(100) +#define STN8815_PIN_N20 _GPIO(101) +#define STN8815_PIN_P22 _GPIO(102) +#define STN8815_PIN_N22 _GPIO(103) +#define STN8815_PIN_V22 _GPIO(104) +#define STN8815_PIN_V21 _GPIO(105) +#define STN8815_PIN_K22 _GPIO(106) +#define STN8815_PIN_K21 _GPIO(107) +#define STN8815_PIN_H20 _GPIO(108) +#define STN8815_PIN_G20 _GPIO(109) +#define STN8815_PIN_L21 _GPIO(110) +#define STN8815_PIN_H21 _GPIO(111) +#define STN8815_PIN_J21 _GPIO(112) +#define STN8815_PIN_H22 _GPIO(113) +#define STN8815_PIN_K20 _GPIO(114) +#define STN8815_PIN_L22 _GPIO(115) +#define STN8815_PIN_G21 _GPIO(116) +#define STN8815_PIN_J20 _GPIO(117) +#define STN8815_PIN_G22 _GPIO(118) +#define STN8815_PIN_U19 _GPIO(119) +#define STN8815_PIN_G19 _GPIO(120) +#define STN8815_PIN_M22 _GPIO(121) +#define STN8815_PIN_M19 _GPIO(122) +#define STN8815_PIN_J22 _GPIO(123) +/* GPIOs 124-127 not routed to pins */ + +/* + * The names of the pins are denoted by GPIO number and ball name, even + * though they can be used for other things than GPIO, this is the first + * column in the table of the data sheet and often used on schematics and + * such. + */ +static const struct pinctrl_pin_desc nmk_stn8815_pins[] = { + PINCTRL_PIN(STN8815_PIN_B4, "GPIO0_B4"), + PINCTRL_PIN(STN8815_PIN_D5, "GPIO1_D5"), + PINCTRL_PIN(STN8815_PIN_C5, "GPIO2_C5"), + PINCTRL_PIN(STN8815_PIN_A4, "GPIO3_A4"), + PINCTRL_PIN(STN8815_PIN_B5, "GPIO4_B5"), + PINCTRL_PIN(STN8815_PIN_D6, "GPIO5_D6"), + PINCTRL_PIN(STN8815_PIN_C6, "GPIO6_C6"), + PINCTRL_PIN(STN8815_PIN_B6, "GPIO7_B6"), + PINCTRL_PIN(STN8815_PIN_B10, "GPIO8_B10"), + PINCTRL_PIN(STN8815_PIN_A10, "GPIO9_A10"), + PINCTRL_PIN(STN8815_PIN_C11, "GPIO10_C11"), + PINCTRL_PIN(STN8815_PIN_B11, "GPIO11_B11"), + PINCTRL_PIN(STN8815_PIN_A11, "GPIO12_A11"), + PINCTRL_PIN(STN8815_PIN_C12, "GPIO13_C12"), + PINCTRL_PIN(STN8815_PIN_B12, "GPIO14_B12"), + PINCTRL_PIN(STN8815_PIN_A12, "GPIO15_A12"), + PINCTRL_PIN(STN8815_PIN_C13, "GPIO16_C13"), + PINCTRL_PIN(STN8815_PIN_B13, "GPIO17_B13"), + PINCTRL_PIN(STN8815_PIN_A13, "GPIO18_A13"), + PINCTRL_PIN(STN8815_PIN_D13, "GPIO19_D13"), + PINCTRL_PIN(STN8815_PIN_C14, "GPIO20_C14"), + PINCTRL_PIN(STN8815_PIN_B14, "GPIO21_B14"), + PINCTRL_PIN(STN8815_PIN_A14, "GPIO22_A14"), + PINCTRL_PIN(STN8815_PIN_D15, "GPIO23_D15"), + PINCTRL_PIN(STN8815_PIN_C15, "GPIO24_C15"), + PINCTRL_PIN(STN8815_PIN_B15, "GPIO25_B15"), + PINCTRL_PIN(STN8815_PIN_A15, "GPIO26_A15"), + PINCTRL_PIN(STN8815_PIN_C16, "GPIO27_C16"), + PINCTRL_PIN(STN8815_PIN_B16, "GPIO28_B16"), + PINCTRL_PIN(STN8815_PIN_A16, "GPIO29_A16"), + PINCTRL_PIN(STN8815_PIN_D17, "GPIO30_D17"), + PINCTRL_PIN(STN8815_PIN_C17, "GPIO31_C17"), + PINCTRL_PIN(STN8815_PIN_AB6, "GPIO32_AB6"), + PINCTRL_PIN(STN8815_PIN_AA6, "GPIO33_AA6"), + PINCTRL_PIN(STN8815_PIN_Y6, "GPIO34_Y6"), + PINCTRL_PIN(STN8815_PIN_Y5, "GPIO35_Y5"), + PINCTRL_PIN(STN8815_PIN_AA5, "GPIO36_AA5"), + PINCTRL_PIN(STN8815_PIN_AB5, "GPIO37_AB5"), + PINCTRL_PIN(STN8815_PIN_AB4, "GPIO38_AB4"), + PINCTRL_PIN(STN8815_PIN_Y4, "GPIO39_Y4"), + PINCTRL_PIN(STN8815_PIN_R1, "GPIO40_R1"), + PINCTRL_PIN(STN8815_PIN_R2, "GPIO41_R2"), + PINCTRL_PIN(STN8815_PIN_R3, "GPIO42_R3"), + PINCTRL_PIN(STN8815_PIN_P1, "GPIO43_P1"), + PINCTRL_PIN(STN8815_PIN_P2, "GPIO44_P2"), + PINCTRL_PIN(STN8815_PIN_P3, "GPIO45_P3"), + PINCTRL_PIN(STN8815_PIN_N1, "GPIO46_N1"), + PINCTRL_PIN(STN8815_PIN_N2, "GPIO47_N2"), + PINCTRL_PIN(STN8815_PIN_N3, "GPIO48_N3"), + PINCTRL_PIN(STN8815_PIN_M1, "GPIO49_M1"), + PINCTRL_PIN(STN8815_PIN_M3, "GPIO50_M3"), + PINCTRL_PIN(STN8815_PIN_M2, "GPIO51_M2"), + PINCTRL_PIN(STN8815_PIN_L1, "GPIO52_L1"), + PINCTRL_PIN(STN8815_PIN_L4, "GPIO53_L4"), + PINCTRL_PIN(STN8815_PIN_L3, "GPIO54_L3"), + PINCTRL_PIN(STN8815_PIN_L2, "GPIO55_L2"), + PINCTRL_PIN(STN8815_PIN_F3, "GPIO56_F3"), + PINCTRL_PIN(STN8815_PIN_F2, "GPIO57_F2"), + PINCTRL_PIN(STN8815_PIN_E1, "GPIO58_E1"), + PINCTRL_PIN(STN8815_PIN_E3, "GPIO59_E3"), + PINCTRL_PIN(STN8815_PIN_E2, "GPIO60_E2"), + PINCTRL_PIN(STN8815_PIN_E4, "GPIO61_E4"), + PINCTRL_PIN(STN8815_PIN_D3, "GPIO62_D3"), + PINCTRL_PIN(STN8815_PIN_D2, "GPIO63_D2"), + PINCTRL_PIN(STN8815_PIN_F21, "GPIO64_F21"), + PINCTRL_PIN(STN8815_PIN_F20, "GPIO65_F20"), + PINCTRL_PIN(STN8815_PIN_E22, "GPIO66_E22"), + PINCTRL_PIN(STN8815_PIN_D22, "GPIO67_D22"), + PINCTRL_PIN(STN8815_PIN_E21, "GPIO68_E21"), + PINCTRL_PIN(STN8815_PIN_E20, "GPIO69_E20"), + PINCTRL_PIN(STN8815_PIN_C22, "GPIO70_C22"), + PINCTRL_PIN(STN8815_PIN_D21, "GPIO71_D21"), + PINCTRL_PIN(STN8815_PIN_D20, "GPIO72_D20"), + PINCTRL_PIN(STN8815_PIN_C21, "GPIO73_C21"), + PINCTRL_PIN(STN8815_PIN_C20, "GPIO74_C20"), + PINCTRL_PIN(STN8815_PIN_C19, "GPIO75_C19"), + PINCTRL_PIN(STN8815_PIN_B20, "GPIO76_B20"), + PINCTRL_PIN(STN8815_PIN_B8, "GPIO77_B8"), + PINCTRL_PIN(STN8815_PIN_A8, "GPIO78_A8"), + PINCTRL_PIN(STN8815_PIN_C9, "GPIO79_C9"), + PINCTRL_PIN(STN8815_PIN_B9, "GPIO80_B9"), + PINCTRL_PIN(STN8815_PIN_A9, "GPIO81_A9"), + PINCTRL_PIN(STN8815_PIN_C10, "GPIO82_C10"), + PINCTRL_PIN(STN8815_PIN_K1, "GPIO83_K1"), + PINCTRL_PIN(STN8815_PIN_K3, "GPIO84_K3"), + PINCTRL_PIN(STN8815_PIN_K2, "GPIO85_K2"), + PINCTRL_PIN(STN8815_PIN_J1, "GPIO86_J1"), + PINCTRL_PIN(STN8815_PIN_J3, "GPIO87_J3"), + PINCTRL_PIN(STN8815_PIN_J2, "GPIO88_J2"), + PINCTRL_PIN(STN8815_PIN_H1, "GPIO89_H1"), + PINCTRL_PIN(STN8815_PIN_H3, "GPIO90_H3"), + PINCTRL_PIN(STN8815_PIN_H2, "GPIO91_H2"), + PINCTRL_PIN(STN8815_PIN_G1, "GPIO92_G1"), + PINCTRL_PIN(STN8815_PIN_G3, "GPIO93_G3"), + PINCTRL_PIN(STN8815_PIN_G2, "GPIO94_G2"), + PINCTRL_PIN(STN8815_PIN_F1, "GPIO95_F1"), + PINCTRL_PIN(STN8815_PIN_T20, "GPIO96_T20"), + PINCTRL_PIN(STN8815_PIN_R21, "GPIO97_R21"), + PINCTRL_PIN(STN8815_PIN_R20, "GPIO98_R20"), + PINCTRL_PIN(STN8815_PIN_U22, "GPIO99_U22"), + PINCTRL_PIN(STN8815_PIN_N21, "GPIO100_N21"), + PINCTRL_PIN(STN8815_PIN_N20, "GPIO101_N20"), + PINCTRL_PIN(STN8815_PIN_P22, "GPIO102_P22"), + PINCTRL_PIN(STN8815_PIN_N22, "GPIO103_N22"), + PINCTRL_PIN(STN8815_PIN_V22, "GPIO104_V22"), + PINCTRL_PIN(STN8815_PIN_V21, "GPIO105_V21"), + PINCTRL_PIN(STN8815_PIN_K22, "GPIO106_K22"), + PINCTRL_PIN(STN8815_PIN_K21, "GPIO107_K21"), + PINCTRL_PIN(STN8815_PIN_H20, "GPIO108_H20"), + PINCTRL_PIN(STN8815_PIN_G20, "GPIO109_G20"), + PINCTRL_PIN(STN8815_PIN_L21, "GPIO110_L21"), + PINCTRL_PIN(STN8815_PIN_H21, "GPIO111_H21"), + PINCTRL_PIN(STN8815_PIN_J21, "GPIO112_J21"), + PINCTRL_PIN(STN8815_PIN_H22, "GPIO113_H22"), + PINCTRL_PIN(STN8815_PIN_K20, "GPIO114_K20"), + PINCTRL_PIN(STN8815_PIN_L22, "GPIO115_L22"), + PINCTRL_PIN(STN8815_PIN_G21, "GPIO116_G21"), + PINCTRL_PIN(STN8815_PIN_J20, "GPIO117_J20"), + PINCTRL_PIN(STN8815_PIN_G22, "GPIO118_G22"), + PINCTRL_PIN(STN8815_PIN_U19, "GPIO119_U19"), + PINCTRL_PIN(STN8815_PIN_G19, "GPIO120_G19"), + PINCTRL_PIN(STN8815_PIN_M22, "GPIO121_M22"), + PINCTRL_PIN(STN8815_PIN_M19, "GPIO122_M19"), + PINCTRL_PIN(STN8815_PIN_J22, "GPIO123_J22"), +}; + +#define STN8815_GPIO_RANGE(a, b, c) { .name = "STN8815", .id = a, .base = b, \ + .pin_base = b, .npins = c } + +/* + * This matches the 32-pin gpio chips registered by the GPIO portion. This + * cannot be const since we assign the struct gpio_chip * pointer at runtime. + */ +static struct pinctrl_gpio_range nmk_stn8815_ranges[] = { + STN8815_GPIO_RANGE(0, 0, 32), + STN8815_GPIO_RANGE(1, 32, 32), + STN8815_GPIO_RANGE(2, 64, 32), + STN8815_GPIO_RANGE(3, 96, 28), +}; + +/* + * Read the pin group names like this: + * u0_a_1 = first groups of pins for uart0 on alt function a + * i2c2_b_2 = second group of pins for i2c2 on alt function b + */ + +/* Altfunction A */ +static const unsigned u0_a_1_pins[] = { STN8815_PIN_B4, STN8815_PIN_D5, + STN8815_PIN_C5, STN8815_PIN_A4, STN8815_PIN_B5, STN8815_PIN_D6, + STN8815_PIN_C6, STN8815_PIN_B6 }; +static const unsigned mmcsd_a_1_pins[] = { STN8815_PIN_B10, STN8815_PIN_A10, + STN8815_PIN_C11, STN8815_PIN_B11, STN8815_PIN_A11, STN8815_PIN_C12, + STN8815_PIN_B12, STN8815_PIN_A12, STN8815_PIN_C13, STN8815_PIN_C15 }; +static const unsigned u1_a_1_pins[] = { STN8815_PIN_M2, STN8815_PIN_L1, + STN8815_PIN_F3, STN8815_PIN_F2 }; +static const unsigned i2c1_a_1_pins[] = { STN8815_PIN_L4, STN8815_PIN_L3 }; +static const unsigned i2c0_a_1_pins[] = { STN8815_PIN_D3, STN8815_PIN_D2 }; +/* Altfunction B */ +static const unsigned u1_b_1_pins[] = { STN8815_PIN_B16, STN8815_PIN_A16 }; +static const unsigned i2cusb_b_1_pins[] = { STN8815_PIN_C21, STN8815_PIN_C20 }; + +#define STN8815_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins, \ + .npins = ARRAY_SIZE(a##_pins), .altsetting = b } + +static const struct nmk_pingroup nmk_stn8815_groups[] = { + STN8815_PIN_GROUP(u0_a_1, NMK_GPIO_ALT_A), + STN8815_PIN_GROUP(mmcsd_a_1, NMK_GPIO_ALT_A), + STN8815_PIN_GROUP(u1_a_1, NMK_GPIO_ALT_A), + STN8815_PIN_GROUP(i2c1_a_1, NMK_GPIO_ALT_A), + STN8815_PIN_GROUP(i2c0_a_1, NMK_GPIO_ALT_A), + STN8815_PIN_GROUP(u1_b_1, NMK_GPIO_ALT_B), + STN8815_PIN_GROUP(i2cusb_b_1, NMK_GPIO_ALT_B), +}; + +/* We use this macro to define the groups applicable to a function */ +#define STN8815_FUNC_GROUPS(a, b...) \ +static const char * const a##_groups[] = { b }; + +STN8815_FUNC_GROUPS(u0, "u0_a_1"); +STN8815_FUNC_GROUPS(mmcsd, "mmcsd_a_1"); +STN8815_FUNC_GROUPS(u1, "u1_a_1", "u1_b_1"); +STN8815_FUNC_GROUPS(i2c1, "i2c1_a_1"); +STN8815_FUNC_GROUPS(i2c0, "i2c0_a_1"); +STN8815_FUNC_GROUPS(i2cusb, "i2cusb_b_1"); + +#define FUNCTION(fname) \ + { \ + .name = #fname, \ + .groups = fname##_groups, \ + .ngroups = ARRAY_SIZE(fname##_groups), \ + } + +static const struct nmk_function nmk_stn8815_functions[] = { + FUNCTION(u0), + FUNCTION(mmcsd), + FUNCTION(u1), + FUNCTION(i2c1), + FUNCTION(i2c0), + FUNCTION(i2cusb), +}; + +static const struct nmk_pinctrl_soc_data nmk_stn8815_soc = { + .gpio_ranges = nmk_stn8815_ranges, + .gpio_num_ranges = ARRAY_SIZE(nmk_stn8815_ranges), + .pins = nmk_stn8815_pins, + .npins = ARRAY_SIZE(nmk_stn8815_pins), + .functions = nmk_stn8815_functions, + .nfunctions = ARRAY_SIZE(nmk_stn8815_functions), + .groups = nmk_stn8815_groups, + .ngroups = ARRAY_SIZE(nmk_stn8815_groups), +}; + +void nmk_pinctrl_stn8815_init(const struct nmk_pinctrl_soc_data **soc) +{ + *soc = &nmk_stn8815_soc; +} diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik.c b/drivers/pinctrl/nomadik/pinctrl-nomadik.c new file mode 100644 index 000000000000..e7cab07eef47 --- /dev/null +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.c @@ -0,0 +1,2099 @@ +/* + * Generic GPIO driver for logic cells found in the Nomadik SoC + * + * Copyright (C) 2008,2009 STMicroelectronics + * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it> + * Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com> + * Copyright (C) 2011-2013 Linus Walleij <linus.walleij@linaro.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/gpio.h> +#include <linux/spinlock.h> +#include <linux/interrupt.h> +#include <linux/slab.h> +#include <linux/of_device.h> +#include <linux/of_address.h> +#include <linux/pinctrl/machine.h> +#include <linux/pinctrl/pinctrl.h> +#include <linux/pinctrl/pinmux.h> +#include <linux/pinctrl/pinconf.h> +/* Since we request GPIOs from ourself */ +#include <linux/pinctrl/consumer.h> +#include "pinctrl-nomadik.h" +#include "../core.h" + +/* + * The GPIO module in the Nomadik family of Systems-on-Chip is an + * AMBA device, managing 32 pins and alternate functions. The logic block + * is currently used in the Nomadik and ux500. + * + * Symbols in this file are called "nmk_gpio" for "nomadik gpio" + */ + +/* + * pin configurations are represented by 32-bit integers: + * + * bit 0.. 8 - Pin Number (512 Pins Maximum) + * bit 9..10 - Alternate Function Selection + * bit 11..12 - Pull up/down state + * bit 13 - Sleep mode behaviour + * bit 14 - Direction + * bit 15 - Value (if output) + * bit 16..18 - SLPM pull up/down state + * bit 19..20 - SLPM direction + * bit 21..22 - SLPM Value (if output) + * bit 23..25 - PDIS value (if input) + * bit 26 - Gpio mode + * bit 27 - Sleep mode + * + * to facilitate the definition, the following macros are provided + * + * PIN_CFG_DEFAULT - default config (0): + * pull up/down = disabled + * sleep mode = input/wakeup + * direction = input + * value = low + * SLPM direction = same as normal + * SLPM pull = same as normal + * SLPM value = same as normal + * + * PIN_CFG - default config with alternate function + */ + +typedef unsigned long pin_cfg_t; + +#define PIN_NUM_MASK 0x1ff +#define PIN_NUM(x) ((x) & PIN_NUM_MASK) + +#define PIN_ALT_SHIFT 9 +#define PIN_ALT_MASK (0x3 << PIN_ALT_SHIFT) +#define PIN_ALT(x) (((x) & PIN_ALT_MASK) >> PIN_ALT_SHIFT) +#define PIN_GPIO (NMK_GPIO_ALT_GPIO << PIN_ALT_SHIFT) +#define PIN_ALT_A (NMK_GPIO_ALT_A << PIN_ALT_SHIFT) +#define PIN_ALT_B (NMK_GPIO_ALT_B << PIN_ALT_SHIFT) +#define PIN_ALT_C (NMK_GPIO_ALT_C << PIN_ALT_SHIFT) + +#define PIN_PULL_SHIFT 11 +#define PIN_PULL_MASK (0x3 << PIN_PULL_SHIFT) +#define PIN_PULL(x) (((x) & PIN_PULL_MASK) >> PIN_PULL_SHIFT) +#define PIN_PULL_NONE (NMK_GPIO_PULL_NONE << PIN_PULL_SHIFT) +#define PIN_PULL_UP (NMK_GPIO_PULL_UP << PIN_PULL_SHIFT) +#define PIN_PULL_DOWN (NMK_GPIO_PULL_DOWN << PIN_PULL_SHIFT) + +#define PIN_SLPM_SHIFT 13 +#define PIN_SLPM_MASK (0x1 << PIN_SLPM_SHIFT) +#define PIN_SLPM(x) (((x) & PIN_SLPM_MASK) >> PIN_SLPM_SHIFT) +#define PIN_SLPM_MAKE_INPUT (NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT) +#define PIN_SLPM_NOCHANGE (NMK_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT) +/* These two replace the above in DB8500v2+ */ +#define PIN_SLPM_WAKEUP_ENABLE (NMK_GPIO_SLPM_WAKEUP_ENABLE << PIN_SLPM_SHIFT) +#define PIN_SLPM_WAKEUP_DISABLE (NMK_GPIO_SLPM_WAKEUP_DISABLE << PIN_SLPM_SHIFT) +#define PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP PIN_SLPM_WAKEUP_DISABLE + +#define PIN_SLPM_GPIO PIN_SLPM_WAKEUP_ENABLE /* In SLPM, pin is a gpio */ +#define PIN_SLPM_ALTFUNC PIN_SLPM_WAKEUP_DISABLE /* In SLPM, pin is altfunc */ + +#define PIN_DIR_SHIFT 14 +#define PIN_DIR_MASK (0x1 << PIN_DIR_SHIFT) +#define PIN_DIR(x) (((x) & PIN_DIR_MASK) >> PIN_DIR_SHIFT) +#define PIN_DIR_INPUT (0 << PIN_DIR_SHIFT) +#define PIN_DIR_OUTPUT (1 << PIN_DIR_SHIFT) + +#define PIN_VAL_SHIFT 15 +#define PIN_VAL_MASK (0x1 << PIN_VAL_SHIFT) +#define PIN_VAL(x) (((x) & PIN_VAL_MASK) >> PIN_VAL_SHIFT) +#define PIN_VAL_LOW (0 << PIN_VAL_SHIFT) +#define PIN_VAL_HIGH (1 << PIN_VAL_SHIFT) + +#define PIN_SLPM_PULL_SHIFT 16 +#define PIN_SLPM_PULL_MASK (0x7 << PIN_SLPM_PULL_SHIFT) +#define PIN_SLPM_PULL(x) \ + (((x) & PIN_SLPM_PULL_MASK) >> PIN_SLPM_PULL_SHIFT) +#define PIN_SLPM_PULL_NONE \ + ((1 + NMK_GPIO_PULL_NONE) << PIN_SLPM_PULL_SHIFT) +#define PIN_SLPM_PULL_UP \ + ((1 + NMK_GPIO_PULL_UP) << PIN_SLPM_PULL_SHIFT) +#define PIN_SLPM_PULL_DOWN \ + ((1 + NMK_GPIO_PULL_DOWN) << PIN_SLPM_PULL_SHIFT) + +#define PIN_SLPM_DIR_SHIFT 19 +#define PIN_SLPM_DIR_MASK (0x3 << PIN_SLPM_DIR_SHIFT) +#define PIN_SLPM_DIR(x) \ + (((x) & PIN_SLPM_DIR_MASK) >> PIN_SLPM_DIR_SHIFT) +#define PIN_SLPM_DIR_INPUT ((1 + 0) << PIN_SLPM_DIR_SHIFT) +#define PIN_SLPM_DIR_OUTPUT ((1 + 1) << PIN_SLPM_DIR_SHIFT) + +#define PIN_SLPM_VAL_SHIFT 21 +#define PIN_SLPM_VAL_MASK (0x3 << PIN_SLPM_VAL_SHIFT) +#define PIN_SLPM_VAL(x) \ + (((x) & PIN_SLPM_VAL_MASK) >> PIN_SLPM_VAL_SHIFT) +#define PIN_SLPM_VAL_LOW ((1 + 0) << PIN_SLPM_VAL_SHIFT) +#define PIN_SLPM_VAL_HIGH ((1 + 1) << PIN_SLPM_VAL_SHIFT) + +#define PIN_SLPM_PDIS_SHIFT 23 +#define PIN_SLPM_PDIS_MASK (0x3 << PIN_SLPM_PDIS_SHIFT) +#define PIN_SLPM_PDIS(x) \ + (((x) & PIN_SLPM_PDIS_MASK) >> PIN_SLPM_PDIS_SHIFT) +#define PIN_SLPM_PDIS_NO_CHANGE (0 << PIN_SLPM_PDIS_SHIFT) +#define PIN_SLPM_PDIS_DISABLED (1 << PIN_SLPM_PDIS_SHIFT) +#define PIN_SLPM_PDIS_ENABLED (2 << PIN_SLPM_PDIS_SHIFT) + +#define PIN_LOWEMI_SHIFT 25 +#define PIN_LOWEMI_MASK (0x1 << PIN_LOWEMI_SHIFT) +#define PIN_LOWEMI(x) (((x) & PIN_LOWEMI_MASK) >> PIN_LOWEMI_SHIFT) +#define PIN_LOWEMI_DISABLED (0 << PIN_LOWEMI_SHIFT) +#define PIN_LOWEMI_ENABLED (1 << PIN_LOWEMI_SHIFT) + +#define PIN_GPIOMODE_SHIFT 26 +#define PIN_GPIOMODE_MASK (0x1 << PIN_GPIOMODE_SHIFT) +#define PIN_GPIOMODE(x) (((x) & PIN_GPIOMODE_MASK) >> PIN_GPIOMODE_SHIFT) +#define PIN_GPIOMODE_DISABLED (0 << PIN_GPIOMODE_SHIFT) +#define PIN_GPIOMODE_ENABLED (1 << PIN_GPIOMODE_SHIFT) + +#define PIN_SLEEPMODE_SHIFT 27 +#define PIN_SLEEPMODE_MASK (0x1 << PIN_SLEEPMODE_SHIFT) +#define PIN_SLEEPMODE(x) (((x) & PIN_SLEEPMODE_MASK) >> PIN_SLEEPMODE_SHIFT) +#define PIN_SLEEPMODE_DISABLED (0 << PIN_SLEEPMODE_SHIFT) +#define PIN_SLEEPMODE_ENABLED (1 << PIN_SLEEPMODE_SHIFT) + + +/* Shortcuts. Use these instead of separate DIR, PULL, and VAL. */ +#define PIN_INPUT_PULLDOWN (PIN_DIR_INPUT | PIN_PULL_DOWN) +#define PIN_INPUT_PULLUP (PIN_DIR_INPUT | PIN_PULL_UP) +#define PIN_INPUT_NOPULL (PIN_DIR_INPUT | PIN_PULL_NONE) +#define PIN_OUTPUT_LOW (PIN_DIR_OUTPUT | PIN_VAL_LOW) +#define PIN_OUTPUT_HIGH (PIN_DIR_OUTPUT | PIN_VAL_HIGH) + +#define PIN_SLPM_INPUT_PULLDOWN (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_DOWN) +#define PIN_SLPM_INPUT_PULLUP (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_UP) +#define PIN_SLPM_INPUT_NOPULL (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_NONE) +#define PIN_SLPM_OUTPUT_LOW (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_LOW) +#define PIN_SLPM_OUTPUT_HIGH (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_HIGH) + +#define PIN_CFG_DEFAULT (0) + +#define PIN_CFG(num, alt) \ + (PIN_CFG_DEFAULT |\ + (PIN_NUM(num) | PIN_##alt)) + +#define PIN_CFG_INPUT(num, alt, pull) \ + (PIN_CFG_DEFAULT |\ + (PIN_NUM(num) | PIN_##alt | PIN_INPUT_##pull)) + +#define PIN_CFG_OUTPUT(num, alt, val) \ + (PIN_CFG_DEFAULT |\ + (PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val)) + +/* + * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving + * the "gpio" namespace for generic and cross-machine functions + */ + +#define GPIO_BLOCK_SHIFT 5 +#define NMK_GPIO_PER_CHIP (1 << GPIO_BLOCK_SHIFT) + +/* Register in the logic block */ +#define NMK_GPIO_DAT 0x00 +#define NMK_GPIO_DATS 0x04 +#define NMK_GPIO_DATC 0x08 +#define NMK_GPIO_PDIS 0x0c +#define NMK_GPIO_DIR 0x10 +#define NMK_GPIO_DIRS 0x14 +#define NMK_GPIO_DIRC 0x18 +#define NMK_GPIO_SLPC 0x1c +#define NMK_GPIO_AFSLA 0x20 +#define NMK_GPIO_AFSLB 0x24 +#define NMK_GPIO_LOWEMI 0x28 + +#define NMK_GPIO_RIMSC 0x40 +#define NMK_GPIO_FIMSC 0x44 +#define NMK_GPIO_IS 0x48 +#define NMK_GPIO_IC 0x4c +#define NMK_GPIO_RWIMSC 0x50 +#define NMK_GPIO_FWIMSC 0x54 +#define NMK_GPIO_WKS 0x58 +/* These appear in DB8540 and later ASICs */ +#define NMK_GPIO_EDGELEVEL 0x5C +#define NMK_GPIO_LEVEL 0x60 + + +/* Pull up/down values */ +enum nmk_gpio_pull { + NMK_GPIO_PULL_NONE, + NMK_GPIO_PULL_UP, + NMK_GPIO_PULL_DOWN, +}; + +/* Sleep mode */ +enum nmk_gpio_slpm { + NMK_GPIO_SLPM_INPUT, + NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT, + NMK_GPIO_SLPM_NOCHANGE, + NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE, +}; + +struct nmk_gpio_chip { + struct gpio_chip chip; + void __iomem *addr; + struct clk *clk; + unsigned int bank; + unsigned int parent_irq; + int latent_parent_irq; + u32 (*get_latent_status)(unsigned int bank); + void (*set_ioforce)(bool enable); + spinlock_t lock; + bool sleepmode; + /* Keep track of configured edges */ + u32 edge_rising; + u32 edge_falling; + u32 real_wake; + u32 rwimsc; + u32 fwimsc; + u32 rimsc; + u32 fimsc; + u32 pull_up; + u32 lowemi; +}; + +/** + * struct nmk_pinctrl - state container for the Nomadik pin controller + * @dev: containing device pointer + * @pctl: corresponding pin controller device + * @soc: SoC data for this specific chip + * @prcm_base: PRCM register range virtual base + */ +struct nmk_pinctrl { + struct device *dev; + struct pinctrl_dev *pctl; + const struct nmk_pinctrl_soc_data *soc; + void __iomem *prcm_base; +}; + +static struct nmk_gpio_chip * +nmk_gpio_chips[DIV_ROUND_UP(ARCH_NR_GPIOS, NMK_GPIO_PER_CHIP)]; + +static DEFINE_SPINLOCK(nmk_gpio_slpm_lock); + +#define NUM_BANKS ARRAY_SIZE(nmk_gpio_chips) + +static void __nmk_gpio_set_mode(struct nmk_gpio_chip *nmk_chip, + unsigned offset, int gpio_mode) +{ + u32 bit = 1 << offset; + u32 afunc, bfunc; + + afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & ~bit; + bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & ~bit; + if (gpio_mode & NMK_GPIO_ALT_A) + afunc |= bit; + if (gpio_mode & NMK_GPIO_ALT_B) + bfunc |= bit; + writel(afunc, nmk_chip->addr + NMK_GPIO_AFSLA); + writel(bfunc, nmk_chip->addr + NMK_GPIO_AFSLB); +} + +static void __nmk_gpio_set_slpm(struct nmk_gpio_chip *nmk_chip, + unsigned offset, enum nmk_gpio_slpm mode) +{ + u32 bit = 1 << offset; + u32 slpm; + + slpm = readl(nmk_chip->addr + NMK_GPIO_SLPC); + if (mode == NMK_GPIO_SLPM_NOCHANGE) + slpm |= bit; + else + slpm &= ~bit; + writel(slpm, nmk_chip->addr + NMK_GPIO_SLPC); +} + +static void __nmk_gpio_set_pull(struct nmk_gpio_chip *nmk_chip, + unsigned offset, enum nmk_gpio_pull pull) +{ + u32 bit = 1 << offset; + u32 pdis; + + pdis = readl(nmk_chip->addr + NMK_GPIO_PDIS); + if (pull == NMK_GPIO_PULL_NONE) { + pdis |= bit; + nmk_chip->pull_up &= ~bit; + } else { + pdis &= ~bit; + } + + writel(pdis, nmk_chip->addr + NMK_GPIO_PDIS); + + if (pull == NMK_GPIO_PULL_UP) { + nmk_chip->pull_up |= bit; + writel(bit, nmk_chip->addr + NMK_GPIO_DATS); + } else if (pull == NMK_GPIO_PULL_DOWN) { + nmk_chip->pull_up &= ~bit; + writel(bit, nmk_chip->addr + NMK_GPIO_DATC); + } +} + +static void __nmk_gpio_set_lowemi(struct nmk_gpio_chip *nmk_chip, + unsigned offset, bool lowemi) +{ + u32 bit = BIT(offset); + bool enabled = nmk_chip->lowemi & bit; + + if (lowemi == enabled) + return; + + if (lowemi) + nmk_chip->lowemi |= bit; + else + nmk_chip->lowemi &= ~bit; + + writel_relaxed(nmk_chip->lowemi, + nmk_chip->addr + NMK_GPIO_LOWEMI); +} + +static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip, + unsigned offset) +{ + writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC); +} + +static void __nmk_gpio_set_output(struct nmk_gpio_chip *nmk_chip, + unsigned offset, int val) +{ + if (val) + writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATS); + else + writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATC); +} + +static void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip, + unsigned offset, int val) +{ + writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS); + __nmk_gpio_set_output(nmk_chip, offset, val); +} + +static void __nmk_gpio_set_mode_safe(struct nmk_gpio_chip *nmk_chip, + unsigned offset, int gpio_mode, + bool glitch) +{ + u32 rwimsc = nmk_chip->rwimsc; + u32 fwimsc = nmk_chip->fwimsc; + + if (glitch && nmk_chip->set_ioforce) { + u32 bit = BIT(offset); + + /* Prevent spurious wakeups */ + writel(rwimsc & ~bit, nmk_chip->addr + NMK_GPIO_RWIMSC); + writel(fwimsc & ~bit, nmk_chip->addr + NMK_GPIO_FWIMSC); + + nmk_chip->set_ioforce(true); + } + + __nmk_gpio_set_mode(nmk_chip, offset, gpio_mode); + + if (glitch && nmk_chip->set_ioforce) { + nmk_chip->set_ioforce(false); + + writel(rwimsc, nmk_chip->addr + NMK_GPIO_RWIMSC); + writel(fwimsc, nmk_chip->addr + NMK_GPIO_FWIMSC); + } +} + +static void +nmk_gpio_disable_lazy_irq(struct nmk_gpio_chip *nmk_chip, unsigned offset) +{ + u32 falling = nmk_chip->fimsc & BIT(offset); + u32 rising = nmk_chip->rimsc & BIT(offset); + int gpio = nmk_chip->chip.base + offset; + int irq = irq_find_mapping(nmk_chip->chip.irqdomain, offset); + struct irq_data *d = irq_get_irq_data(irq); + + if (!rising && !falling) + return; + + if (!d || !irqd_irq_disabled(d)) + return; + + if (rising) { + nmk_chip->rimsc &= ~BIT(offset); + writel_relaxed(nmk_chip->rimsc, + nmk_chip->addr + NMK_GPIO_RIMSC); + } + + if (falling) { + nmk_chip->fimsc &= ~BIT(offset); + writel_relaxed(nmk_chip->fimsc, + nmk_chip->addr + NMK_GPIO_FIMSC); + } + + dev_dbg(nmk_chip->chip.dev, "%d: clearing interrupt mask\n", gpio); +} + +static void nmk_write_masked(void __iomem *reg, u32 mask, u32 value) +{ + u32 val; + + val = readl(reg); + val = ((val & ~mask) | (value & mask)); + writel(val, reg); +} + +static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct, + unsigned offset, unsigned alt_num) +{ + int i; + u16 reg; + u8 bit; + u8 alt_index; + const struct prcm_gpiocr_altcx_pin_desc *pin_desc; + const u16 *gpiocr_regs; + + if (!npct->prcm_base) + return; + + if (alt_num > PRCM_IDX_GPIOCR_ALTC_MAX) { + dev_err(npct->dev, "PRCM GPIOCR: alternate-C%i is invalid\n", + alt_num); + return; + } + + for (i = 0 ; i < npct->soc->npins_altcx ; i++) { + if (npct->soc->altcx_pins[i].pin == offset) + break; + } + if (i == npct->soc->npins_altcx) { + dev_dbg(npct->dev, "PRCM GPIOCR: pin %i is not found\n", + offset); + return; + } + + pin_desc = npct->soc->altcx_pins + i; + gpiocr_regs = npct->soc->prcm_gpiocr_registers; + + /* + * If alt_num is NULL, just clear current ALTCx selection + * to make sure we come back to a pure ALTC selection + */ + if (!alt_num) { + for (i = 0 ; i < PRCM_IDX_GPIOCR_ALTC_MAX ; i++) { + if (pin_desc->altcx[i].used == true) { + reg = gpiocr_regs[pin_desc->altcx[i].reg_index]; + bit = pin_desc->altcx[i].control_bit; + if (readl(npct->prcm_base + reg) & BIT(bit)) { + nmk_write_masked(npct->prcm_base + reg, BIT(bit), 0); + dev_dbg(npct->dev, + "PRCM GPIOCR: pin %i: alternate-C%i has been disabled\n", + offset, i+1); + } + } + } + return; + } + + alt_index = alt_num - 1; + if (pin_desc->altcx[alt_index].used == false) { + dev_warn(npct->dev, + "PRCM GPIOCR: pin %i: alternate-C%i does not exist\n", + offset, alt_num); + return; + } + + /* + * Check if any other ALTCx functions are activated on this pin + * and disable it first. + */ + for (i = 0 ; i < PRCM_IDX_GPIOCR_ALTC_MAX ; i++) { + if (i == alt_index) + continue; + if (pin_desc->altcx[i].used == true) { + reg = gpiocr_regs[pin_desc->altcx[i].reg_index]; + bit = pin_desc->altcx[i].control_bit; + if (readl(npct->prcm_base + reg) & BIT(bit)) { + nmk_write_masked(npct->prcm_base + reg, BIT(bit), 0); + dev_dbg(npct->dev, + "PRCM GPIOCR: pin %i: alternate-C%i has been disabled\n", + offset, i+1); + } + } + } + + reg = gpiocr_regs[pin_desc->altcx[alt_index].reg_index]; + bit = pin_desc->altcx[alt_index].control_bit; + dev_dbg(npct->dev, "PRCM GPIOCR: pin %i: alternate-C%i has been selected\n", + offset, alt_index+1); + nmk_write_masked(npct->prcm_base + reg, BIT(bit), BIT(bit)); +} + +/* + * Safe sequence used to switch IOs between GPIO and Alternate-C mode: + * - Save SLPM registers + * - Set SLPM=0 for the IOs you want to switch and others to 1 + * - Configure the GPIO registers for the IOs that are being switched + * - Set IOFORCE=1 + * - Modify the AFLSA/B registers for the IOs that are being switched + * - Set IOFORCE=0 + * - Restore SLPM registers + * - Any spurious wake up event during switch sequence to be ignored and + * cleared + */ +static void nmk_gpio_glitch_slpm_init(unsigned int *slpm) +{ + int i; + + for (i = 0; i < NUM_BANKS; i++) { + struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; + unsigned int temp = slpm[i]; + + if (!chip) + break; + + clk_enable(chip->clk); + + slpm[i] = readl(chip->addr + NMK_GPIO_SLPC); + writel(temp, chip->addr + NMK_GPIO_SLPC); + } +} + +static void nmk_gpio_glitch_slpm_restore(unsigned int *slpm) +{ + int i; + + for (i = 0; i < NUM_BANKS; i++) { + struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; + + if (!chip) + break; + + writel(slpm[i], chip->addr + NMK_GPIO_SLPC); + + clk_disable(chip->clk); + } +} + +static int __maybe_unused nmk_prcm_gpiocr_get_mode(struct pinctrl_dev *pctldev, int gpio) +{ + int i; + u16 reg; + u8 bit; + struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); + const struct prcm_gpiocr_altcx_pin_desc *pin_desc; + const u16 *gpiocr_regs; + + if (!npct->prcm_base) + return NMK_GPIO_ALT_C; + + for (i = 0; i < npct->soc->npins_altcx; i++) { + if (npct->soc->altcx_pins[i].pin == gpio) + break; + } + if (i == npct->soc->npins_altcx) + return NMK_GPIO_ALT_C; + + pin_desc = npct->soc->altcx_pins + i; + gpiocr_regs = npct->soc->prcm_gpiocr_registers; + for (i = 0; i < PRCM_IDX_GPIOCR_ALTC_MAX; i++) { + if (pin_desc->altcx[i].used == true) { + reg = gpiocr_regs[pin_desc->altcx[i].reg_index]; + bit = pin_desc->altcx[i].control_bit; + if (readl(npct->prcm_base + reg) & BIT(bit)) + return NMK_GPIO_ALT_C+i+1; + } + } + return NMK_GPIO_ALT_C; +} + +int nmk_gpio_get_mode(int gpio) +{ + struct nmk_gpio_chip *nmk_chip; + u32 afunc, bfunc, bit; + + nmk_chip = nmk_gpio_chips[gpio / NMK_GPIO_PER_CHIP]; + if (!nmk_chip) + return -EINVAL; + + bit = 1 << (gpio % NMK_GPIO_PER_CHIP); + + clk_enable(nmk_chip->clk); + + afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & bit; + bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & bit; + + clk_disable(nmk_chip->clk); + + return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0); +} +EXPORT_SYMBOL(nmk_gpio_get_mode); + + +/* IRQ functions */ +static inline int nmk_gpio_get_bitmask(int gpio) +{ + return 1 << (gpio % NMK_GPIO_PER_CHIP); +} + +static void nmk_gpio_irq_ack(struct irq_data *d) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(d); + struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); + + clk_enable(nmk_chip->clk); + writel(nmk_gpio_get_bitmask(d->hwirq), nmk_chip->addr + NMK_GPIO_IC); + clk_disable(nmk_chip->clk); +} + +enum nmk_gpio_irq_type { + NORMAL, + WAKE, +}; + +static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip, + int gpio, enum nmk_gpio_irq_type which, + bool enable) +{ + u32 bitmask = nmk_gpio_get_bitmask(gpio); + u32 *rimscval; + u32 *fimscval; + u32 rimscreg; + u32 fimscreg; + + if (which == NORMAL) { + rimscreg = NMK_GPIO_RIMSC; + fimscreg = NMK_GPIO_FIMSC; + rimscval = &nmk_chip->rimsc; + fimscval = &nmk_chip->fimsc; + } else { + rimscreg = NMK_GPIO_RWIMSC; + fimscreg = NMK_GPIO_FWIMSC; + rimscval = &nmk_chip->rwimsc; + fimscval = &nmk_chip->fwimsc; + } + + /* we must individually set/clear the two edges */ + if (nmk_chip->edge_rising & bitmask) { + if (enable) + *rimscval |= bitmask; + else + *rimscval &= ~bitmask; + writel(*rimscval, nmk_chip->addr + rimscreg); + } + if (nmk_chip->edge_falling & bitmask) { + if (enable) + *fimscval |= bitmask; + else + *fimscval &= ~bitmask; + writel(*fimscval, nmk_chip->addr + fimscreg); + } +} + +static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip, + int gpio, bool on) +{ + /* + * Ensure WAKEUP_ENABLE is on. No need to disable it if wakeup is + * disabled, since setting SLPM to 1 increases power consumption, and + * wakeup is anyhow controlled by the RIMSC and FIMSC registers. + */ + if (nmk_chip->sleepmode && on) { + __nmk_gpio_set_slpm(nmk_chip, gpio % NMK_GPIO_PER_CHIP, + NMK_GPIO_SLPM_WAKEUP_ENABLE); + } + + __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on); +} + +static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable) +{ + struct nmk_gpio_chip *nmk_chip; + unsigned long flags; + u32 bitmask; + + nmk_chip = irq_data_get_irq_chip_data(d); + bitmask = nmk_gpio_get_bitmask(d->hwirq); + if (!nmk_chip) + return -EINVAL; + + clk_enable(nmk_chip->clk); + spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); + spin_lock(&nmk_chip->lock); + + __nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, enable); + + if (!(nmk_chip->real_wake & bitmask)) + __nmk_gpio_set_wake(nmk_chip, d->hwirq, enable); + + spin_unlock(&nmk_chip->lock); + spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); + clk_disable(nmk_chip->clk); + + return 0; +} + +static void nmk_gpio_irq_mask(struct irq_data *d) +{ + nmk_gpio_irq_maskunmask(d, false); +} + +static void nmk_gpio_irq_unmask(struct irq_data *d) +{ + nmk_gpio_irq_maskunmask(d, true); +} + +static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on) +{ + struct nmk_gpio_chip *nmk_chip; + unsigned long flags; + u32 bitmask; + + nmk_chip = irq_data_get_irq_chip_data(d); + if (!nmk_chip) + return -EINVAL; + bitmask = nmk_gpio_get_bitmask(d->hwirq); + + clk_enable(nmk_chip->clk); + spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); + spin_lock(&nmk_chip->lock); + + if (irqd_irq_disabled(d)) + __nmk_gpio_set_wake(nmk_chip, d->hwirq, on); + + if (on) + nmk_chip->real_wake |= bitmask; + else + nmk_chip->real_wake &= ~bitmask; + + spin_unlock(&nmk_chip->lock); + spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); + clk_disable(nmk_chip->clk); + + return 0; +} + +static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type) +{ + bool enabled = !irqd_irq_disabled(d); + bool wake = irqd_is_wakeup_set(d); + struct nmk_gpio_chip *nmk_chip; + unsigned long flags; + u32 bitmask; + + nmk_chip = irq_data_get_irq_chip_data(d); + bitmask = nmk_gpio_get_bitmask(d->hwirq); + if (!nmk_chip) + return -EINVAL; + if (type & IRQ_TYPE_LEVEL_HIGH) + return -EINVAL; + if (type & IRQ_TYPE_LEVEL_LOW) + return -EINVAL; + + clk_enable(nmk_chip->clk); + spin_lock_irqsave(&nmk_chip->lock, flags); + + if (enabled) + __nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, false); + + if (enabled || wake) + __nmk_gpio_irq_modify(nmk_chip, d->hwirq, WAKE, false); + + nmk_chip->edge_rising &= ~bitmask; + if (type & IRQ_TYPE_EDGE_RISING) + nmk_chip->edge_rising |= bitmask; + + nmk_chip->edge_falling &= ~bitmask; + if (type & IRQ_TYPE_EDGE_FALLING) + nmk_chip->edge_falling |= bitmask; + + if (enabled) + __nmk_gpio_irq_modify(nmk_chip, d->hwirq, NORMAL, true); + + if (enabled || wake) + __nmk_gpio_irq_modify(nmk_chip, d->hwirq, WAKE, true); + + spin_unlock_irqrestore(&nmk_chip->lock, flags); + clk_disable(nmk_chip->clk); + + return 0; +} + +static unsigned int nmk_gpio_irq_startup(struct irq_data *d) +{ + struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d); + + clk_enable(nmk_chip->clk); + nmk_gpio_irq_unmask(d); + return 0; +} + +static void nmk_gpio_irq_shutdown(struct irq_data *d) +{ + struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d); + + nmk_gpio_irq_mask(d); + clk_disable(nmk_chip->clk); +} + +static struct irq_chip nmk_gpio_irq_chip = { + .name = "Nomadik-GPIO", + .irq_ack = nmk_gpio_irq_ack, + .irq_mask = nmk_gpio_irq_mask, + .irq_unmask = nmk_gpio_irq_unmask, + .irq_set_type = nmk_gpio_irq_set_type, + .irq_set_wake = nmk_gpio_irq_set_wake, + .irq_startup = nmk_gpio_irq_startup, + .irq_shutdown = nmk_gpio_irq_shutdown, + .flags = IRQCHIP_MASK_ON_SUSPEND, +}; + +static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc, + u32 status) +{ + struct irq_chip *host_chip = irq_get_chip(irq); + struct gpio_chip *chip = irq_desc_get_handler_data(desc); + + chained_irq_enter(host_chip, desc); + + while (status) { + int bit = __ffs(status); + + generic_handle_irq(irq_find_mapping(chip->irqdomain, bit)); + status &= ~BIT(bit); + } + + chained_irq_exit(host_chip, desc); +} + +static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + struct gpio_chip *chip = irq_desc_get_handler_data(desc); + struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); + u32 status; + + clk_enable(nmk_chip->clk); + status = readl(nmk_chip->addr + NMK_GPIO_IS); + clk_disable(nmk_chip->clk); + + __nmk_gpio_irq_handler(irq, desc, status); +} + +static void nmk_gpio_latent_irq_handler(unsigned int irq, + struct irq_desc *desc) +{ + struct gpio_chip *chip = irq_desc_get_handler_data(desc); + struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); + u32 status = nmk_chip->get_latent_status(nmk_chip->bank); + + __nmk_gpio_irq_handler(irq, desc, status); +} + +/* I/O Functions */ + +static int nmk_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + /* + * Map back to global GPIO space and request muxing, the direction + * parameter does not matter for this controller. + */ + int gpio = chip->base + offset; + + return pinctrl_request_gpio(gpio); +} + +static void nmk_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + int gpio = chip->base + offset; + + pinctrl_free_gpio(gpio); +} + +static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset) +{ + struct nmk_gpio_chip *nmk_chip = + container_of(chip, struct nmk_gpio_chip, chip); + + clk_enable(nmk_chip->clk); + + writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC); + + clk_disable(nmk_chip->clk); + + return 0; +} + +static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned offset) +{ + struct nmk_gpio_chip *nmk_chip = + container_of(chip, struct nmk_gpio_chip, chip); + u32 bit = 1 << offset; + int value; + + clk_enable(nmk_chip->clk); + + value = (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0; + + clk_disable(nmk_chip->clk); + + return value; +} + +static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset, + int val) +{ + struct nmk_gpio_chip *nmk_chip = + container_of(chip, struct nmk_gpio_chip, chip); + + clk_enable(nmk_chip->clk); + + __nmk_gpio_set_output(nmk_chip, offset, val); + + clk_disable(nmk_chip->clk); +} + +static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset, + int val) +{ + struct nmk_gpio_chip *nmk_chip = + container_of(chip, struct nmk_gpio_chip, chip); + + clk_enable(nmk_chip->clk); + + __nmk_gpio_make_output(nmk_chip, offset, val); + + clk_disable(nmk_chip->clk); + + return 0; +} + +#ifdef CONFIG_DEBUG_FS + +#include <linux/seq_file.h> + +static void nmk_gpio_dbg_show_one(struct seq_file *s, + struct pinctrl_dev *pctldev, struct gpio_chip *chip, + unsigned offset, unsigned gpio) +{ + const char *label = gpiochip_is_requested(chip, offset); + struct nmk_gpio_chip *nmk_chip = + container_of(chip, struct nmk_gpio_chip, chip); + int mode; + bool is_out; + bool pull; + u32 bit = 1 << offset; + const char *modes[] = { + [NMK_GPIO_ALT_GPIO] = "gpio", + [NMK_GPIO_ALT_A] = "altA", + [NMK_GPIO_ALT_B] = "altB", + [NMK_GPIO_ALT_C] = "altC", + [NMK_GPIO_ALT_C+1] = "altC1", + [NMK_GPIO_ALT_C+2] = "altC2", + [NMK_GPIO_ALT_C+3] = "altC3", + [NMK_GPIO_ALT_C+4] = "altC4", + }; + + clk_enable(nmk_chip->clk); + is_out = !!(readl(nmk_chip->addr + NMK_GPIO_DIR) & bit); + pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & bit); + mode = nmk_gpio_get_mode(gpio); + if ((mode == NMK_GPIO_ALT_C) && pctldev) + mode = nmk_prcm_gpiocr_get_mode(pctldev, gpio); + + seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s %s", + gpio, label ?: "(none)", + is_out ? "out" : "in ", + chip->get + ? (chip->get(chip, offset) ? "hi" : "lo") + : "? ", + (mode < 0) ? "unknown" : modes[mode], + pull ? "pull" : "none"); + + if (!is_out) { + int irq = gpio_to_irq(gpio); + struct irq_desc *desc = irq_to_desc(irq); + + /* This races with request_irq(), set_irq_type(), + * and set_irq_wake() ... but those are "rare". + */ + if (irq > 0 && desc && desc->action) { + char *trigger; + u32 bitmask = nmk_gpio_get_bitmask(gpio); + + if (nmk_chip->edge_rising & bitmask) + trigger = "edge-rising"; + else if (nmk_chip->edge_falling & bitmask) + trigger = "edge-falling"; + else + trigger = "edge-undefined"; + + seq_printf(s, " irq-%d %s%s", + irq, trigger, + irqd_is_wakeup_set(&desc->irq_data) + ? " wakeup" : ""); + } + } + clk_disable(nmk_chip->clk); +} + +static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) +{ + unsigned i; + unsigned gpio = chip->base; + + for (i = 0; i < chip->ngpio; i++, gpio++) { + nmk_gpio_dbg_show_one(s, NULL, chip, i, gpio); + seq_printf(s, "\n"); + } +} + +#else +static inline void nmk_gpio_dbg_show_one(struct seq_file *s, + struct pinctrl_dev *pctldev, + struct gpio_chip *chip, + unsigned offset, unsigned gpio) +{ +} +#define nmk_gpio_dbg_show NULL +#endif + +/* This structure is replicated for each GPIO block allocated at probe time */ +static struct gpio_chip nmk_gpio_template = { + .request = nmk_gpio_request, + .free = nmk_gpio_free, + .direction_input = nmk_gpio_make_input, + .get = nmk_gpio_get_input, + .direction_output = nmk_gpio_make_output, + .set = nmk_gpio_set_output, + .dbg_show = nmk_gpio_dbg_show, + .can_sleep = false, +}; + +void nmk_gpio_clocks_enable(void) +{ + int i; + + for (i = 0; i < NUM_BANKS; i++) { + struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; + + if (!chip) + continue; + + clk_enable(chip->clk); + } +} + +void nmk_gpio_clocks_disable(void) +{ + int i; + + for (i = 0; i < NUM_BANKS; i++) { + struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; + + if (!chip) + continue; + + clk_disable(chip->clk); + } +} + +/* + * Called from the suspend/resume path to only keep the real wakeup interrupts + * (those that have had set_irq_wake() called on them) as wakeup interrupts, + * and not the rest of the interrupts which we needed to have as wakeups for + * cpuidle. + * + * PM ops are not used since this needs to be done at the end, after all the + * other drivers are done with their suspend callbacks. + */ +void nmk_gpio_wakeups_suspend(void) +{ + int i; + + for (i = 0; i < NUM_BANKS; i++) { + struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; + + if (!chip) + break; + + clk_enable(chip->clk); + + writel(chip->rwimsc & chip->real_wake, + chip->addr + NMK_GPIO_RWIMSC); + writel(chip->fwimsc & chip->real_wake, + chip->addr + NMK_GPIO_FWIMSC); + + clk_disable(chip->clk); + } +} + +void nmk_gpio_wakeups_resume(void) +{ + int i; + + for (i = 0; i < NUM_BANKS; i++) { + struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; + + if (!chip) + break; + + clk_enable(chip->clk); + + writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC); + writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC); + + clk_disable(chip->clk); + } +} + +/* + * Read the pull up/pull down status. + * A bit set in 'pull_up' means that pull up + * is selected if pull is enabled in PDIS register. + * Note: only pull up/down set via this driver can + * be detected due to HW limitations. + */ +void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up) +{ + if (gpio_bank < NUM_BANKS) { + struct nmk_gpio_chip *chip = nmk_gpio_chips[gpio_bank]; + + if (!chip) + return; + + *pull_up = chip->pull_up; + } +} + +static int nmk_gpio_probe(struct platform_device *dev) +{ + struct device_node *np = dev->dev.of_node; + struct nmk_gpio_chip *nmk_chip; + struct gpio_chip *chip; + struct resource *res; + struct clk *clk; + int latent_irq; + bool supports_sleepmode; + void __iomem *base; + int irq; + int ret; + + if (of_get_property(np, "st,supports-sleepmode", NULL)) + supports_sleepmode = true; + else + supports_sleepmode = false; + + if (of_property_read_u32(np, "gpio-bank", &dev->id)) { + dev_err(&dev->dev, "gpio-bank property not found\n"); + return -EINVAL; + } + + irq = platform_get_irq(dev, 0); + if (irq < 0) + return irq; + + /* It's OK for this IRQ not to be present */ + latent_irq = platform_get_irq(dev, 1); + + res = platform_get_resource(dev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(&dev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + clk = devm_clk_get(&dev->dev, NULL); + if (IS_ERR(clk)) + return PTR_ERR(clk); + clk_prepare(clk); + + nmk_chip = devm_kzalloc(&dev->dev, sizeof(*nmk_chip), GFP_KERNEL); + if (!nmk_chip) + return -ENOMEM; + + /* + * The virt address in nmk_chip->addr is in the nomadik register space, + * so we can simply convert the resource address, without remapping + */ + nmk_chip->bank = dev->id; + nmk_chip->clk = clk; + nmk_chip->addr = base; + nmk_chip->chip = nmk_gpio_template; + nmk_chip->parent_irq = irq; + nmk_chip->latent_parent_irq = latent_irq; + nmk_chip->sleepmode = supports_sleepmode; + spin_lock_init(&nmk_chip->lock); + + chip = &nmk_chip->chip; + chip->base = dev->id * NMK_GPIO_PER_CHIP; + chip->ngpio = NMK_GPIO_PER_CHIP; + chip->label = dev_name(&dev->dev); + chip->dev = &dev->dev; + chip->owner = THIS_MODULE; + + clk_enable(nmk_chip->clk); + nmk_chip->lowemi = readl_relaxed(nmk_chip->addr + NMK_GPIO_LOWEMI); + clk_disable(nmk_chip->clk); + chip->of_node = np; + + ret = gpiochip_add(&nmk_chip->chip); + if (ret) + return ret; + + BUG_ON(nmk_chip->bank >= ARRAY_SIZE(nmk_gpio_chips)); + + nmk_gpio_chips[nmk_chip->bank] = nmk_chip; + + platform_set_drvdata(dev, nmk_chip); + + /* + * Let the generic code handle this edge IRQ, the the chained + * handler will perform the actual work of handling the parent + * interrupt. + */ + ret = gpiochip_irqchip_add(&nmk_chip->chip, + &nmk_gpio_irq_chip, + 0, + handle_edge_irq, + IRQ_TYPE_EDGE_FALLING); + if (ret) { + dev_err(&dev->dev, "could not add irqchip\n"); + ret = gpiochip_remove(&nmk_chip->chip); + return -ENODEV; + } + /* Then register the chain on the parent IRQ */ + gpiochip_set_chained_irqchip(&nmk_chip->chip, + &nmk_gpio_irq_chip, + nmk_chip->parent_irq, + nmk_gpio_irq_handler); + if (nmk_chip->latent_parent_irq > 0) + gpiochip_set_chained_irqchip(&nmk_chip->chip, + &nmk_gpio_irq_chip, + nmk_chip->latent_parent_irq, + nmk_gpio_latent_irq_handler); + + dev_info(&dev->dev, "at address %p\n", nmk_chip->addr); + + return 0; +} + +static int nmk_get_groups_cnt(struct pinctrl_dev *pctldev) +{ + struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); + + return npct->soc->ngroups; +} + +static const char *nmk_get_group_name(struct pinctrl_dev *pctldev, + unsigned selector) +{ + struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); + + return npct->soc->groups[selector].name; +} + +static int nmk_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, + const unsigned **pins, + unsigned *num_pins) +{ + struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); + + *pins = npct->soc->groups[selector].pins; + *num_pins = npct->soc->groups[selector].npins; + return 0; +} + +static struct pinctrl_gpio_range * +nmk_match_gpio_range(struct pinctrl_dev *pctldev, unsigned offset) +{ + struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); + int i; + + for (i = 0; i < npct->soc->gpio_num_ranges; i++) { + struct pinctrl_gpio_range *range; + + range = &npct->soc->gpio_ranges[i]; + if (offset >= range->pin_base && + offset <= (range->pin_base + range->npins - 1)) + return range; + } + return NULL; +} + +static void nmk_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, + unsigned offset) +{ + struct pinctrl_gpio_range *range; + struct gpio_chip *chip; + + range = nmk_match_gpio_range(pctldev, offset); + if (!range || !range->gc) { + seq_printf(s, "invalid pin offset"); + return; + } + chip = range->gc; + nmk_gpio_dbg_show_one(s, pctldev, chip, offset - chip->base, offset); +} + +static void nmk_pinctrl_dt_free_map(struct pinctrl_dev *pctldev, + struct pinctrl_map *map, unsigned num_maps) +{ + int i; + + for (i = 0; i < num_maps; i++) + if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN) + kfree(map[i].data.configs.configs); + kfree(map); +} + +static int nmk_dt_reserve_map(struct pinctrl_map **map, unsigned *reserved_maps, + unsigned *num_maps, unsigned reserve) +{ + unsigned old_num = *reserved_maps; + unsigned new_num = *num_maps + reserve; + struct pinctrl_map *new_map; + + if (old_num >= new_num) + return 0; + + new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL); + if (!new_map) + return -ENOMEM; + + memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map)); + + *map = new_map; + *reserved_maps = new_num; + + return 0; +} + +static int nmk_dt_add_map_mux(struct pinctrl_map **map, unsigned *reserved_maps, + unsigned *num_maps, const char *group, + const char *function) +{ + if (*num_maps == *reserved_maps) + return -ENOSPC; + + (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP; + (*map)[*num_maps].data.mux.group = group; + (*map)[*num_maps].data.mux.function = function; + (*num_maps)++; + + return 0; +} + +static int nmk_dt_add_map_configs(struct pinctrl_map **map, + unsigned *reserved_maps, + unsigned *num_maps, const char *group, + unsigned long *configs, unsigned num_configs) +{ + unsigned long *dup_configs; + + if (*num_maps == *reserved_maps) + return -ENOSPC; + + dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs), + GFP_KERNEL); + if (!dup_configs) + return -ENOMEM; + + (*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_PIN; + + (*map)[*num_maps].data.configs.group_or_pin = group; + (*map)[*num_maps].data.configs.configs = dup_configs; + (*map)[*num_maps].data.configs.num_configs = num_configs; + (*num_maps)++; + + return 0; +} + +#define NMK_CONFIG_PIN(x, y) { .property = x, .config = y, } +#define NMK_CONFIG_PIN_ARRAY(x, y) { .property = x, .choice = y, \ + .size = ARRAY_SIZE(y), } + +static const unsigned long nmk_pin_input_modes[] = { + PIN_INPUT_NOPULL, + PIN_INPUT_PULLUP, + PIN_INPUT_PULLDOWN, +}; + +static const unsigned long nmk_pin_output_modes[] = { + PIN_OUTPUT_LOW, + PIN_OUTPUT_HIGH, + PIN_DIR_OUTPUT, +}; + +static const unsigned long nmk_pin_sleep_modes[] = { + PIN_SLEEPMODE_DISABLED, + PIN_SLEEPMODE_ENABLED, +}; + +static const unsigned long nmk_pin_sleep_input_modes[] = { + PIN_SLPM_INPUT_NOPULL, + PIN_SLPM_INPUT_PULLUP, + PIN_SLPM_INPUT_PULLDOWN, + PIN_SLPM_DIR_INPUT, +}; + +static const unsigned long nmk_pin_sleep_output_modes[] = { + PIN_SLPM_OUTPUT_LOW, + PIN_SLPM_OUTPUT_HIGH, + PIN_SLPM_DIR_OUTPUT, +}; + +static const unsigned long nmk_pin_sleep_wakeup_modes[] = { + PIN_SLPM_WAKEUP_DISABLE, + PIN_SLPM_WAKEUP_ENABLE, +}; + +static const unsigned long nmk_pin_gpio_modes[] = { + PIN_GPIOMODE_DISABLED, + PIN_GPIOMODE_ENABLED, +}; + +static const unsigned long nmk_pin_sleep_pdis_modes[] = { + PIN_SLPM_PDIS_DISABLED, + PIN_SLPM_PDIS_ENABLED, +}; + +struct nmk_cfg_param { + const char *property; + unsigned long config; + const unsigned long *choice; + int size; +}; + +static const struct nmk_cfg_param nmk_cfg_params[] = { + NMK_CONFIG_PIN_ARRAY("ste,input", nmk_pin_input_modes), + NMK_CONFIG_PIN_ARRAY("ste,output", nmk_pin_output_modes), + NMK_CONFIG_PIN_ARRAY("ste,sleep", nmk_pin_sleep_modes), + NMK_CONFIG_PIN_ARRAY("ste,sleep-input", nmk_pin_sleep_input_modes), + NMK_CONFIG_PIN_ARRAY("ste,sleep-output", nmk_pin_sleep_output_modes), + NMK_CONFIG_PIN_ARRAY("ste,sleep-wakeup", nmk_pin_sleep_wakeup_modes), + NMK_CONFIG_PIN_ARRAY("ste,gpio", nmk_pin_gpio_modes), + NMK_CONFIG_PIN_ARRAY("ste,sleep-pull-disable", nmk_pin_sleep_pdis_modes), +}; + +static int nmk_dt_pin_config(int index, int val, unsigned long *config) +{ + int ret = 0; + + if (nmk_cfg_params[index].choice == NULL) + *config = nmk_cfg_params[index].config; + else { + /* test if out of range */ + if (val < nmk_cfg_params[index].size) { + *config = nmk_cfg_params[index].config | + nmk_cfg_params[index].choice[val]; + } + } + return ret; +} + +static const char *nmk_find_pin_name(struct pinctrl_dev *pctldev, const char *pin_name) +{ + int i, pin_number; + struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); + + if (sscanf((char *)pin_name, "GPIO%d", &pin_number) == 1) + for (i = 0; i < npct->soc->npins; i++) + if (npct->soc->pins[i].number == pin_number) + return npct->soc->pins[i].name; + return NULL; +} + +static bool nmk_pinctrl_dt_get_config(struct device_node *np, + unsigned long *configs) +{ + bool has_config = 0; + unsigned long cfg = 0; + int i, val, ret; + + for (i = 0; i < ARRAY_SIZE(nmk_cfg_params); i++) { + ret = of_property_read_u32(np, + nmk_cfg_params[i].property, &val); + if (ret != -EINVAL) { + if (nmk_dt_pin_config(i, val, &cfg) == 0) { + *configs |= cfg; + has_config = 1; + } + } + } + + return has_config; +} + +static int nmk_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev, + struct device_node *np, + struct pinctrl_map **map, + unsigned *reserved_maps, + unsigned *num_maps) +{ + int ret; + const char *function = NULL; + unsigned long configs = 0; + bool has_config = 0; + unsigned reserve = 0; + struct property *prop; + const char *group, *gpio_name; + struct device_node *np_config; + + ret = of_property_read_string(np, "ste,function", &function); + if (ret >= 0) + reserve = 1; + + has_config = nmk_pinctrl_dt_get_config(np, &configs); + + np_config = of_parse_phandle(np, "ste,config", 0); + if (np_config) + has_config |= nmk_pinctrl_dt_get_config(np_config, &configs); + + ret = of_property_count_strings(np, "ste,pins"); + if (ret < 0) + goto exit; + + if (has_config) + reserve++; + + reserve *= ret; + + ret = nmk_dt_reserve_map(map, reserved_maps, num_maps, reserve); + if (ret < 0) + goto exit; + + of_property_for_each_string(np, "ste,pins", prop, group) { + if (function) { + ret = nmk_dt_add_map_mux(map, reserved_maps, num_maps, + group, function); + if (ret < 0) + goto exit; + } + if (has_config) { + gpio_name = nmk_find_pin_name(pctldev, group); + + ret = nmk_dt_add_map_configs(map, reserved_maps, num_maps, + gpio_name, &configs, 1); + if (ret < 0) + goto exit; + } + + } +exit: + return ret; +} + +static int nmk_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, + struct device_node *np_config, + struct pinctrl_map **map, unsigned *num_maps) +{ + unsigned reserved_maps; + struct device_node *np; + int ret; + + reserved_maps = 0; + *map = NULL; + *num_maps = 0; + + for_each_child_of_node(np_config, np) { + ret = nmk_pinctrl_dt_subnode_to_map(pctldev, np, map, + &reserved_maps, num_maps); + if (ret < 0) { + nmk_pinctrl_dt_free_map(pctldev, *map, *num_maps); + return ret; + } + } + + return 0; +} + +static const struct pinctrl_ops nmk_pinctrl_ops = { + .get_groups_count = nmk_get_groups_cnt, + .get_group_name = nmk_get_group_name, + .get_group_pins = nmk_get_group_pins, + .pin_dbg_show = nmk_pin_dbg_show, + .dt_node_to_map = nmk_pinctrl_dt_node_to_map, + .dt_free_map = nmk_pinctrl_dt_free_map, +}; + +static int nmk_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev) +{ + struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); + + return npct->soc->nfunctions; +} + +static const char *nmk_pmx_get_func_name(struct pinctrl_dev *pctldev, + unsigned function) +{ + struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); + + return npct->soc->functions[function].name; +} + +static int nmk_pmx_get_func_groups(struct pinctrl_dev *pctldev, + unsigned function, + const char * const **groups, + unsigned * const num_groups) +{ + struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); + + *groups = npct->soc->functions[function].groups; + *num_groups = npct->soc->functions[function].ngroups; + + return 0; +} + +static int nmk_pmx_enable(struct pinctrl_dev *pctldev, unsigned function, + unsigned group) +{ + struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); + const struct nmk_pingroup *g; + static unsigned int slpm[NUM_BANKS]; + unsigned long flags = 0; + bool glitch; + int ret = -EINVAL; + int i; + + g = &npct->soc->groups[group]; + + if (g->altsetting < 0) + return -EINVAL; + + dev_dbg(npct->dev, "enable group %s, %u pins\n", g->name, g->npins); + + /* + * If we're setting altfunc C by setting both AFSLA and AFSLB to 1, + * we may pass through an undesired state. In this case we take + * some extra care. + * + * Safe sequence used to switch IOs between GPIO and Alternate-C mode: + * - Save SLPM registers (since we have a shadow register in the + * nmk_chip we're using that as backup) + * - Set SLPM=0 for the IOs you want to switch and others to 1 + * - Configure the GPIO registers for the IOs that are being switched + * - Set IOFORCE=1 + * - Modify the AFLSA/B registers for the IOs that are being switched + * - Set IOFORCE=0 + * - Restore SLPM registers + * - Any spurious wake up event during switch sequence to be ignored + * and cleared + * + * We REALLY need to save ALL slpm registers, because the external + * IOFORCE will switch *all* ports to their sleepmode setting to as + * to avoid glitches. (Not just one port!) + */ + glitch = ((g->altsetting & NMK_GPIO_ALT_C) == NMK_GPIO_ALT_C); + + if (glitch) { + spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); + + /* Initially don't put any pins to sleep when switching */ + memset(slpm, 0xff, sizeof(slpm)); + + /* + * Then mask the pins that need to be sleeping now when we're + * switching to the ALT C function. + */ + for (i = 0; i < g->npins; i++) + slpm[g->pins[i] / NMK_GPIO_PER_CHIP] &= ~BIT(g->pins[i]); + nmk_gpio_glitch_slpm_init(slpm); + } + + for (i = 0; i < g->npins; i++) { + struct pinctrl_gpio_range *range; + struct nmk_gpio_chip *nmk_chip; + struct gpio_chip *chip; + unsigned bit; + + range = nmk_match_gpio_range(pctldev, g->pins[i]); + if (!range) { + dev_err(npct->dev, + "invalid pin offset %d in group %s at index %d\n", + g->pins[i], g->name, i); + goto out_glitch; + } + if (!range->gc) { + dev_err(npct->dev, "GPIO chip missing in range for pin offset %d in group %s at index %d\n", + g->pins[i], g->name, i); + goto out_glitch; + } + chip = range->gc; + nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); + dev_dbg(npct->dev, "setting pin %d to altsetting %d\n", g->pins[i], g->altsetting); + + clk_enable(nmk_chip->clk); + bit = g->pins[i] % NMK_GPIO_PER_CHIP; + /* + * If the pin is switching to altfunc, and there was an + * interrupt installed on it which has been lazy disabled, + * actually mask the interrupt to prevent spurious interrupts + * that would occur while the pin is under control of the + * peripheral. Only SKE does this. + */ + nmk_gpio_disable_lazy_irq(nmk_chip, bit); + + __nmk_gpio_set_mode_safe(nmk_chip, bit, + (g->altsetting & NMK_GPIO_ALT_C), glitch); + clk_disable(nmk_chip->clk); + + /* + * Call PRCM GPIOCR config function in case ALTC + * has been selected: + * - If selection is a ALTCx, some bits in PRCM GPIOCR registers + * must be set. + * - If selection is pure ALTC and previous selection was ALTCx, + * then some bits in PRCM GPIOCR registers must be cleared. + */ + if ((g->altsetting & NMK_GPIO_ALT_C) == NMK_GPIO_ALT_C) + nmk_prcm_altcx_set_mode(npct, g->pins[i], + g->altsetting >> NMK_GPIO_ALT_CX_SHIFT); + } + + /* When all pins are successfully reconfigured we get here */ + ret = 0; + +out_glitch: + if (glitch) { + nmk_gpio_glitch_slpm_restore(slpm); + spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); + } + + return ret; +} + +static int nmk_gpio_request_enable(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned offset) +{ + struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); + struct nmk_gpio_chip *nmk_chip; + struct gpio_chip *chip; + unsigned bit; + + if (!range) { + dev_err(npct->dev, "invalid range\n"); + return -EINVAL; + } + if (!range->gc) { + dev_err(npct->dev, "missing GPIO chip in range\n"); + return -EINVAL; + } + chip = range->gc; + nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); + + dev_dbg(npct->dev, "enable pin %u as GPIO\n", offset); + + clk_enable(nmk_chip->clk); + bit = offset % NMK_GPIO_PER_CHIP; + /* There is no glitch when converting any pin to GPIO */ + __nmk_gpio_set_mode(nmk_chip, bit, NMK_GPIO_ALT_GPIO); + clk_disable(nmk_chip->clk); + + return 0; +} + +static void nmk_gpio_disable_free(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned offset) +{ + struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); + + dev_dbg(npct->dev, "disable pin %u as GPIO\n", offset); + /* Set the pin to some default state, GPIO is usually default */ +} + +static const struct pinmux_ops nmk_pinmux_ops = { + .get_functions_count = nmk_pmx_get_funcs_cnt, + .get_function_name = nmk_pmx_get_func_name, + .get_function_groups = nmk_pmx_get_func_groups, + .enable = nmk_pmx_enable, + .gpio_request_enable = nmk_gpio_request_enable, + .gpio_disable_free = nmk_gpio_disable_free, +}; + +static int nmk_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin, + unsigned long *config) +{ + /* Not implemented */ + return -EINVAL; +} + +static int nmk_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin, + unsigned long *configs, unsigned num_configs) +{ + static const char *pullnames[] = { + [NMK_GPIO_PULL_NONE] = "none", + [NMK_GPIO_PULL_UP] = "up", + [NMK_GPIO_PULL_DOWN] = "down", + [3] /* illegal */ = "??" + }; + static const char *slpmnames[] = { + [NMK_GPIO_SLPM_INPUT] = "input/wakeup", + [NMK_GPIO_SLPM_NOCHANGE] = "no-change/no-wakeup", + }; + struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); + struct nmk_gpio_chip *nmk_chip; + struct pinctrl_gpio_range *range; + struct gpio_chip *chip; + unsigned bit; + pin_cfg_t cfg; + int pull, slpm, output, val, i; + bool lowemi, gpiomode, sleep; + + range = nmk_match_gpio_range(pctldev, pin); + if (!range) { + dev_err(npct->dev, "invalid pin offset %d\n", pin); + return -EINVAL; + } + if (!range->gc) { + dev_err(npct->dev, "GPIO chip missing in range for pin %d\n", + pin); + return -EINVAL; + } + chip = range->gc; + nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); + + for (i = 0; i < num_configs; i++) { + /* + * The pin config contains pin number and altfunction fields, + * here we just ignore that part. It's being handled by the + * framework and pinmux callback respectively. + */ + cfg = (pin_cfg_t) configs[i]; + pull = PIN_PULL(cfg); + slpm = PIN_SLPM(cfg); + output = PIN_DIR(cfg); + val = PIN_VAL(cfg); + lowemi = PIN_LOWEMI(cfg); + gpiomode = PIN_GPIOMODE(cfg); + sleep = PIN_SLEEPMODE(cfg); + + if (sleep) { + int slpm_pull = PIN_SLPM_PULL(cfg); + int slpm_output = PIN_SLPM_DIR(cfg); + int slpm_val = PIN_SLPM_VAL(cfg); + + /* All pins go into GPIO mode at sleep */ + gpiomode = true; + + /* + * The SLPM_* values are normal values + 1 to allow zero + * to mean "same as normal". + */ + if (slpm_pull) + pull = slpm_pull - 1; + if (slpm_output) + output = slpm_output - 1; + if (slpm_val) + val = slpm_val - 1; + + dev_dbg(nmk_chip->chip.dev, + "pin %d: sleep pull %s, dir %s, val %s\n", + pin, + slpm_pull ? pullnames[pull] : "same", + slpm_output ? (output ? "output" : "input") + : "same", + slpm_val ? (val ? "high" : "low") : "same"); + } + + dev_dbg(nmk_chip->chip.dev, + "pin %d [%#lx]: pull %s, slpm %s (%s%s), lowemi %s\n", + pin, cfg, pullnames[pull], slpmnames[slpm], + output ? "output " : "input", + output ? (val ? "high" : "low") : "", + lowemi ? "on" : "off"); + + clk_enable(nmk_chip->clk); + bit = pin % NMK_GPIO_PER_CHIP; + if (gpiomode) + /* No glitch when going to GPIO mode */ + __nmk_gpio_set_mode(nmk_chip, bit, NMK_GPIO_ALT_GPIO); + if (output) + __nmk_gpio_make_output(nmk_chip, bit, val); + else { + __nmk_gpio_make_input(nmk_chip, bit); + __nmk_gpio_set_pull(nmk_chip, bit, pull); + } + /* TODO: isn't this only applicable on output pins? */ + __nmk_gpio_set_lowemi(nmk_chip, bit, lowemi); + + __nmk_gpio_set_slpm(nmk_chip, bit, slpm); + clk_disable(nmk_chip->clk); + } /* for each config */ + + return 0; +} + +static const struct pinconf_ops nmk_pinconf_ops = { + .pin_config_get = nmk_pin_config_get, + .pin_config_set = nmk_pin_config_set, +}; + +static struct pinctrl_desc nmk_pinctrl_desc = { + .name = "pinctrl-nomadik", + .pctlops = &nmk_pinctrl_ops, + .pmxops = &nmk_pinmux_ops, + .confops = &nmk_pinconf_ops, + .owner = THIS_MODULE, +}; + +static const struct of_device_id nmk_pinctrl_match[] = { + { + .compatible = "stericsson,stn8815-pinctrl", + .data = (void *)PINCTRL_NMK_STN8815, + }, + { + .compatible = "stericsson,db8500-pinctrl", + .data = (void *)PINCTRL_NMK_DB8500, + }, + { + .compatible = "stericsson,db8540-pinctrl", + .data = (void *)PINCTRL_NMK_DB8540, + }, + {}, +}; + +#ifdef CONFIG_PM_SLEEP +static int nmk_pinctrl_suspend(struct device *dev) +{ + struct nmk_pinctrl *npct; + + npct = dev_get_drvdata(dev); + if (!npct) + return -EINVAL; + + return pinctrl_force_sleep(npct->pctl); +} + +static int nmk_pinctrl_resume(struct device *dev) +{ + struct nmk_pinctrl *npct; + + npct = dev_get_drvdata(dev); + if (!npct) + return -EINVAL; + + return pinctrl_force_default(npct->pctl); +} +#endif + +static int nmk_pinctrl_probe(struct platform_device *pdev) +{ + const struct of_device_id *match; + struct device_node *np = pdev->dev.of_node; + struct device_node *prcm_np; + struct nmk_pinctrl *npct; + unsigned int version = 0; + int i; + + npct = devm_kzalloc(&pdev->dev, sizeof(*npct), GFP_KERNEL); + if (!npct) + return -ENOMEM; + + match = of_match_device(nmk_pinctrl_match, &pdev->dev); + if (!match) + return -ENODEV; + version = (unsigned int) match->data; + + /* Poke in other ASIC variants here */ + if (version == PINCTRL_NMK_STN8815) + nmk_pinctrl_stn8815_init(&npct->soc); + if (version == PINCTRL_NMK_DB8500) + nmk_pinctrl_db8500_init(&npct->soc); + if (version == PINCTRL_NMK_DB8540) + nmk_pinctrl_db8540_init(&npct->soc); + + prcm_np = of_parse_phandle(np, "prcm", 0); + if (prcm_np) + npct->prcm_base = of_iomap(prcm_np, 0); + if (!npct->prcm_base) { + if (version == PINCTRL_NMK_STN8815) { + dev_info(&pdev->dev, + "No PRCM base, " + "assuming no ALT-Cx control is available\n"); + } else { + dev_err(&pdev->dev, "missing PRCM base address\n"); + return -EINVAL; + } + } + + /* + * We need all the GPIO drivers to probe FIRST, or we will not be able + * to obtain references to the struct gpio_chip * for them, and we + * need this to proceed. + */ + for (i = 0; i < npct->soc->gpio_num_ranges; i++) { + if (!nmk_gpio_chips[npct->soc->gpio_ranges[i].id]) { + dev_warn(&pdev->dev, "GPIO chip %d not registered yet\n", i); + return -EPROBE_DEFER; + } + npct->soc->gpio_ranges[i].gc = &nmk_gpio_chips[npct->soc->gpio_ranges[i].id]->chip; + } + + nmk_pinctrl_desc.pins = npct->soc->pins; + nmk_pinctrl_desc.npins = npct->soc->npins; + npct->dev = &pdev->dev; + + npct->pctl = pinctrl_register(&nmk_pinctrl_desc, &pdev->dev, npct); + if (!npct->pctl) { + dev_err(&pdev->dev, "could not register Nomadik pinctrl driver\n"); + return -EINVAL; + } + + /* We will handle a range of GPIO pins */ + for (i = 0; i < npct->soc->gpio_num_ranges; i++) + pinctrl_add_gpio_range(npct->pctl, &npct->soc->gpio_ranges[i]); + + platform_set_drvdata(pdev, npct); + dev_info(&pdev->dev, "initialized Nomadik pin control driver\n"); + + return 0; +} + +static const struct of_device_id nmk_gpio_match[] = { + { .compatible = "st,nomadik-gpio", }, + {} +}; + +static struct platform_driver nmk_gpio_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "gpio", + .of_match_table = nmk_gpio_match, + }, + .probe = nmk_gpio_probe, +}; + +static SIMPLE_DEV_PM_OPS(nmk_pinctrl_pm_ops, + nmk_pinctrl_suspend, + nmk_pinctrl_resume); + +static struct platform_driver nmk_pinctrl_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "pinctrl-nomadik", + .of_match_table = nmk_pinctrl_match, + .pm = &nmk_pinctrl_pm_ops, + }, + .probe = nmk_pinctrl_probe, +}; + +static int __init nmk_gpio_init(void) +{ + int ret; + + ret = platform_driver_register(&nmk_gpio_driver); + if (ret) + return ret; + return platform_driver_register(&nmk_pinctrl_driver); +} + +core_initcall(nmk_gpio_init); + +MODULE_AUTHOR("Prafulla WADASKAR and Alessandro Rubini"); +MODULE_DESCRIPTION("Nomadik GPIO Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik.h b/drivers/pinctrl/nomadik/pinctrl-nomadik.h new file mode 100644 index 000000000000..d8215f1e70c7 --- /dev/null +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.h @@ -0,0 +1,192 @@ +#ifndef PINCTRL_PINCTRL_NOMADIK_H +#define PINCTRL_PINCTRL_NOMADIK_H + +/* Package definitions */ +#define PINCTRL_NMK_STN8815 0 +#define PINCTRL_NMK_DB8500 1 +#define PINCTRL_NMK_DB8540 2 + +/* Alternate functions: function C is set in hw by setting both A and B */ +#define NMK_GPIO_ALT_GPIO 0 +#define NMK_GPIO_ALT_A 1 +#define NMK_GPIO_ALT_B 2 +#define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B) + +#define NMK_GPIO_ALT_CX_SHIFT 2 +#define NMK_GPIO_ALT_C1 ((1<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C) +#define NMK_GPIO_ALT_C2 ((2<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C) +#define NMK_GPIO_ALT_C3 ((3<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C) +#define NMK_GPIO_ALT_C4 ((4<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C) + +#define PRCM_GPIOCR_ALTCX(pin_num,\ + altc1_used, altc1_ri, altc1_cb,\ + altc2_used, altc2_ri, altc2_cb,\ + altc3_used, altc3_ri, altc3_cb,\ + altc4_used, altc4_ri, altc4_cb)\ +{\ + .pin = pin_num,\ + .altcx[PRCM_IDX_GPIOCR_ALTC1] = {\ + .used = altc1_used,\ + .reg_index = altc1_ri,\ + .control_bit = altc1_cb\ + },\ + .altcx[PRCM_IDX_GPIOCR_ALTC2] = {\ + .used = altc2_used,\ + .reg_index = altc2_ri,\ + .control_bit = altc2_cb\ + },\ + .altcx[PRCM_IDX_GPIOCR_ALTC3] = {\ + .used = altc3_used,\ + .reg_index = altc3_ri,\ + .control_bit = altc3_cb\ + },\ + .altcx[PRCM_IDX_GPIOCR_ALTC4] = {\ + .used = altc4_used,\ + .reg_index = altc4_ri,\ + .control_bit = altc4_cb\ + },\ +} + +/** + * enum prcm_gpiocr_reg_index + * Used to reference an PRCM GPIOCR register address. + */ +enum prcm_gpiocr_reg_index { + PRCM_IDX_GPIOCR1, + PRCM_IDX_GPIOCR2, + PRCM_IDX_GPIOCR3 +}; +/** + * enum prcm_gpiocr_altcx_index + * Used to reference an Other alternate-C function. + */ +enum prcm_gpiocr_altcx_index { + PRCM_IDX_GPIOCR_ALTC1, + PRCM_IDX_GPIOCR_ALTC2, + PRCM_IDX_GPIOCR_ALTC3, + PRCM_IDX_GPIOCR_ALTC4, + PRCM_IDX_GPIOCR_ALTC_MAX, +}; + +/** + * struct prcm_gpio_altcx - Other alternate-C function + * @used: other alternate-C function availability + * @reg_index: PRCM GPIOCR register index used to control the function + * @control_bit: PRCM GPIOCR bit used to control the function + */ +struct prcm_gpiocr_altcx { + bool used:1; + u8 reg_index:2; + u8 control_bit:5; +} __packed; + +/** + * struct prcm_gpio_altcx_pin_desc - Other alternate-C pin + * @pin: The pin number + * @altcx: array of other alternate-C[1-4] functions + */ +struct prcm_gpiocr_altcx_pin_desc { + unsigned short pin; + struct prcm_gpiocr_altcx altcx[PRCM_IDX_GPIOCR_ALTC_MAX]; +}; + +/** + * struct nmk_function - Nomadik pinctrl mux function + * @name: The name of the function, exported to pinctrl core. + * @groups: An array of pin groups that may select this function. + * @ngroups: The number of entries in @groups. + */ +struct nmk_function { + const char *name; + const char * const *groups; + unsigned ngroups; +}; + +/** + * struct nmk_pingroup - describes a Nomadik pin group + * @name: the name of this specific pin group + * @pins: an array of discrete physical pins used in this group, taken + * from the driver-local pin enumeration space + * @num_pins: the number of pins in this group array, i.e. the number of + * elements in .pins so we can iterate over that array + * @altsetting: the altsetting to apply to all pins in this group to + * configure them to be used by a function + */ +struct nmk_pingroup { + const char *name; + const unsigned int *pins; + const unsigned npins; + int altsetting; +}; + +/** + * struct nmk_pinctrl_soc_data - Nomadik pin controller per-SoC configuration + * @gpio_ranges: An array of GPIO ranges for this SoC + * @gpio_num_ranges: The number of GPIO ranges for this SoC + * @pins: An array describing all pins the pin controller affects. + * All pins which are also GPIOs must be listed first within the + * array, and be numbered identically to the GPIO controller's + * numbering. + * @npins: The number of entries in @pins. + * @functions: The functions supported on this SoC. + * @nfunction: The number of entries in @functions. + * @groups: An array describing all pin groups the pin SoC supports. + * @ngroups: The number of entries in @groups. + * @altcx_pins: The pins that support Other alternate-C function on this SoC + * @npins_altcx: The number of Other alternate-C pins + * @prcm_gpiocr_registers: The array of PRCM GPIOCR registers on this SoC + */ +struct nmk_pinctrl_soc_data { + struct pinctrl_gpio_range *gpio_ranges; + unsigned gpio_num_ranges; + const struct pinctrl_pin_desc *pins; + unsigned npins; + const struct nmk_function *functions; + unsigned nfunctions; + const struct nmk_pingroup *groups; + unsigned ngroups; + const struct prcm_gpiocr_altcx_pin_desc *altcx_pins; + unsigned npins_altcx; + const u16 *prcm_gpiocr_registers; +}; + +#ifdef CONFIG_PINCTRL_STN8815 + +void nmk_pinctrl_stn8815_init(const struct nmk_pinctrl_soc_data **soc); + +#else + +static inline void +nmk_pinctrl_stn8815_init(const struct nmk_pinctrl_soc_data **soc) +{ +} + +#endif + +#ifdef CONFIG_PINCTRL_DB8500 + +void nmk_pinctrl_db8500_init(const struct nmk_pinctrl_soc_data **soc); + +#else + +static inline void +nmk_pinctrl_db8500_init(const struct nmk_pinctrl_soc_data **soc) +{ +} + +#endif + +#ifdef CONFIG_PINCTRL_DB8540 + +void nmk_pinctrl_db8540_init(const struct nmk_pinctrl_soc_data **soc); + +#else + +static inline void +nmk_pinctrl_db8540_init(const struct nmk_pinctrl_soc_data **soc) +{ +} + +#endif + +#endif /* PINCTRL_PINCTRL_NOMADIK_H */ |