diff options
Diffstat (limited to 'drivers/pinctrl/pxa')
-rw-r--r-- | drivers/pinctrl/pxa/Kconfig | 17 | ||||
-rw-r--r-- | drivers/pinctrl/pxa/Makefile | 2 | ||||
-rw-r--r-- | drivers/pinctrl/pxa/pinctrl-pxa27x.c | 566 | ||||
-rw-r--r-- | drivers/pinctrl/pxa/pinctrl-pxa2xx.c | 437 | ||||
-rw-r--r-- | drivers/pinctrl/pxa/pinctrl-pxa2xx.h | 92 |
5 files changed, 1114 insertions, 0 deletions
diff --git a/drivers/pinctrl/pxa/Kconfig b/drivers/pinctrl/pxa/Kconfig new file mode 100644 index 000000000000..990667ff772c --- /dev/null +++ b/drivers/pinctrl/pxa/Kconfig @@ -0,0 +1,17 @@ +if (ARCH_PXA || COMPILE_TEST) + +config PINCTRL_PXA + bool + select PINMUX + select PINCONF + select GENERIC_PINCONF + +config PINCTRL_PXA27X + tristate "Marvell PXA27x pin controller driver" + select PINCTRL_PXA + default y if PXA27x + help + This is the pinctrl, pinmux, pinconf driver for the Marvell + PXA2xx block found in the pxa25x and pxa27x platforms. + +endif diff --git a/drivers/pinctrl/pxa/Makefile b/drivers/pinctrl/pxa/Makefile new file mode 100644 index 000000000000..f1d56af2bfc0 --- /dev/null +++ b/drivers/pinctrl/pxa/Makefile @@ -0,0 +1,2 @@ +# Marvell PXA pin control drivers +obj-$(CONFIG_PINCTRL_PXA27X) += pinctrl-pxa2xx.o pinctrl-pxa27x.o diff --git a/drivers/pinctrl/pxa/pinctrl-pxa27x.c b/drivers/pinctrl/pxa/pinctrl-pxa27x.c new file mode 100644 index 000000000000..2e2c3709ef05 --- /dev/null +++ b/drivers/pinctrl/pxa/pinctrl-pxa27x.c @@ -0,0 +1,566 @@ +/* + * Marvell PXA27x family pin control + * + * Copyright (C) 2015 Robert Jarzmik + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + */ +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/pinctrl/pinctrl.h> + +#include "pinctrl-pxa2xx.h" + +static const struct pxa_desc_pin pxa27x_pins[] = { + PXA_GPIO_ONLY_PIN(PXA_PINCTRL_PIN(0)), + PXA_GPIO_ONLY_PIN(PXA_PINCTRL_PIN(1)), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(9), + PXA_FUNCTION(0, 3, "FFCTS"), + PXA_FUNCTION(1, 1, "HZ_CLK"), + PXA_FUNCTION(1, 3, "CHOUT<0>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(10), + PXA_FUNCTION(0, 1, "FFDCD"), + PXA_FUNCTION(0, 3, "USB_P3_5"), + PXA_FUNCTION(1, 1, "HZ_CLK"), + PXA_FUNCTION(1, 3, "CHOUT<1>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(11), + PXA_FUNCTION(0, 1, "EXT_SYNC<0>"), + PXA_FUNCTION(0, 2, "SSPRXD2"), + PXA_FUNCTION(0, 3, "USB_P3_1"), + PXA_FUNCTION(1, 1, "CHOUT<0>"), + PXA_FUNCTION(1, 1, "PWM_OUT<2>"), + PXA_FUNCTION(1, 3, "48_MHz")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(12), + PXA_FUNCTION(0, 1, "EXT_SYNC<1>"), + PXA_FUNCTION(0, 2, "CIF_DD<7>"), + PXA_FUNCTION(1, 1, "CHOUT<1>"), + PXA_FUNCTION(1, 1, "PWM_OUT<3>"), + PXA_FUNCTION(1, 3, "48_MHz")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(13), + PXA_FUNCTION(0, 1, "CLK_EXT"), + PXA_FUNCTION(0, 2, "KP_DKIN<7>"), + PXA_FUNCTION(0, 3, "KP_MKIN<7>"), + PXA_FUNCTION(1, 1, "SSPTXD2")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(14), + PXA_FUNCTION(0, 1, "L_VSYNC"), + PXA_FUNCTION(0, 2, "SSPSFRM2"), + PXA_FUNCTION(1, 1, "SSPSFRM2"), + PXA_FUNCTION(1, 3, "UCLK")), + PXA_GPIO_ONLY_PIN(PXA_PINCTRL_PIN(15)), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(16), + PXA_FUNCTION(0, 1, "KP_MKIN<5>"), + PXA_FUNCTION(1, 2, "PWM_OUT<0>"), + PXA_FUNCTION(1, 3, "FFTXD")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(17), + PXA_FUNCTION(0, 1, "KP_MKIN<6>"), + PXA_FUNCTION(0, 2, "CIF_DD<6>"), + PXA_FUNCTION(1, 2, "PWM_OUT<1>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(18), + PXA_FUNCTION(0, 1, "RDY")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(19), + PXA_FUNCTION(0, 1, "SSPSCLK2"), + PXA_FUNCTION(0, 3, "FFRXD"), + PXA_FUNCTION(1, 1, "SSPSCLK2"), + PXA_FUNCTION(1, 2, "L_CS"), + PXA_FUNCTION(1, 3, "nURST")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(20), + PXA_FUNCTION(0, 1, "DREQ<0>"), + PXA_FUNCTION(0, 2, "MBREQ"), + PXA_FUNCTION(1, 1, "nSDCS<2>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(21), + PXA_FUNCTION(1, 1, "nSDCS<3>"), + PXA_FUNCTION(1, 2, "DVAL<0>"), + PXA_FUNCTION(1, 3, "MBGNT")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(22), + PXA_FUNCTION(0, 1, "SSPEXTCLK2"), + PXA_FUNCTION(0, 2, "SSPSCLKEN2"), + PXA_FUNCTION(0, 3, "SSPSCLK2"), + PXA_FUNCTION(1, 1, "KP_MKOUT<7>"), + PXA_FUNCTION(1, 2, "SSPSYSCLK2"), + PXA_FUNCTION(1, 3, "SSPSCLK2")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(23), + PXA_FUNCTION(0, 2, "SSPSCLK"), + PXA_FUNCTION(1, 1, "CIF_MCLK"), + PXA_FUNCTION(1, 1, "SSPSCLK")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(24), + PXA_FUNCTION(0, 1, "CIF_FV"), + PXA_FUNCTION(0, 2, "SSPSFRM"), + PXA_FUNCTION(1, 1, "CIF_FV"), + PXA_FUNCTION(1, 2, "SSPSFRM")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(25), + PXA_FUNCTION(0, 1, "CIF_LV"), + PXA_FUNCTION(1, 1, "CIF_LV"), + PXA_FUNCTION(1, 2, "SSPTXD")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(26), + PXA_FUNCTION(0, 1, "SSPRXD"), + PXA_FUNCTION(0, 2, "CIF_PCLK"), + PXA_FUNCTION(0, 3, "FFCTS")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(27), + PXA_FUNCTION(0, 1, "SSPEXTCLK"), + PXA_FUNCTION(0, 2, "SSPSCLKEN"), + PXA_FUNCTION(0, 3, "CIF_DD<0>"), + PXA_FUNCTION(1, 1, "SSPSYSCLK"), + PXA_FUNCTION(1, 3, "FFRTS")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(28), + PXA_FUNCTION(0, 1, "AC97_BITCLK"), + PXA_FUNCTION(0, 2, "I2S_BITCLK"), + PXA_FUNCTION(0, 3, "SSPSFRM"), + PXA_FUNCTION(1, 1, "I2S_BITCLK"), + PXA_FUNCTION(1, 3, "SSPSFRM")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(29), + PXA_FUNCTION(0, 1, "AC97_SDATA_IN_0"), + PXA_FUNCTION(0, 2, "I2S_SDATA_IN"), + PXA_FUNCTION(0, 3, "SSPSCLK"), + PXA_FUNCTION(1, 1, "SSPRXD2"), + PXA_FUNCTION(1, 3, "SSPSCLK")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(30), + PXA_FUNCTION(1, 1, "I2S_SDATA_OUT"), + PXA_FUNCTION(1, 2, "AC97_SDATA_OUT"), + PXA_FUNCTION(1, 3, "USB_P3_2")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(31), + PXA_FUNCTION(1, 1, "I2S_SYNC"), + PXA_FUNCTION(1, 2, "AC97_SYNC"), + PXA_FUNCTION(1, 3, "USB_P3_6")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(32), + PXA_FUNCTION(1, 1, "MSSCLK"), + PXA_FUNCTION(1, 2, "MMCLK")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(33), + PXA_FUNCTION(0, 1, "FFRXD"), + PXA_FUNCTION(0, 2, "FFDSR"), + PXA_FUNCTION(1, 1, "DVAL<1>"), + PXA_FUNCTION(1, 2, "nCS<5>"), + PXA_FUNCTION(1, 3, "MBGNT")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(34), + PXA_FUNCTION(0, 1, "FFRXD"), + PXA_FUNCTION(0, 2, "KP_MKIN<3>"), + PXA_FUNCTION(0, 3, "SSPSCLK3"), + PXA_FUNCTION(1, 1, "USB_P2_2"), + PXA_FUNCTION(1, 3, "SSPSCLK3")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(35), + PXA_FUNCTION(0, 1, "FFCTS"), + PXA_FUNCTION(0, 2, "USB_P2_1"), + PXA_FUNCTION(0, 3, "SSPSFRM3"), + PXA_FUNCTION(1, 2, "KP_MKOUT<6>"), + PXA_FUNCTION(1, 3, "SSPTXD3")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(36), + PXA_FUNCTION(0, 1, "FFDCD"), + PXA_FUNCTION(0, 2, "SSPSCLK2"), + PXA_FUNCTION(0, 3, "KP_MKIN<7>"), + PXA_FUNCTION(1, 1, "USB_P2_4"), + PXA_FUNCTION(1, 2, "SSPSCLK2")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(37), + PXA_FUNCTION(0, 1, "FFDSR"), + PXA_FUNCTION(0, 2, "SSPSFRM2"), + PXA_FUNCTION(0, 3, "KP_MKIN<3>"), + PXA_FUNCTION(1, 1, "USB_P2_8"), + PXA_FUNCTION(1, 2, "SSPSFRM2"), + PXA_FUNCTION(1, 3, "FFTXD")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(38), + PXA_FUNCTION(0, 1, "FFRI"), + PXA_FUNCTION(0, 2, "KP_MKIN<4>"), + PXA_FUNCTION(0, 3, "USB_P2_3"), + PXA_FUNCTION(1, 1, "SSPTXD3"), + PXA_FUNCTION(1, 2, "SSPTXD2"), + PXA_FUNCTION(1, 3, "PWM_OUT<0>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(39), + PXA_FUNCTION(0, 1, "KP_MKIN<4>"), + PXA_FUNCTION(0, 3, "SSPSFRM3"), + PXA_FUNCTION(1, 1, "USB_P2_6"), + PXA_FUNCTION(1, 2, "FFTXD"), + PXA_FUNCTION(1, 3, "SSPSFRM3")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(40), + PXA_FUNCTION(0, 1, "SSPRXD2"), + PXA_FUNCTION(0, 3, "USB_P2_5"), + PXA_FUNCTION(1, 1, "KP_MKOUT<6>"), + PXA_FUNCTION(1, 2, "FFDTR"), + PXA_FUNCTION(1, 3, "SSPSCLK3")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(41), + PXA_FUNCTION(0, 1, "FFRXD"), + PXA_FUNCTION(0, 2, "USB_P2_7"), + PXA_FUNCTION(0, 3, "SSPRXD3"), + PXA_FUNCTION(1, 1, "KP_MKOUT<7>"), + PXA_FUNCTION(1, 2, "FFRTS")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(42), + PXA_FUNCTION(0, 1, "BTRXD"), + PXA_FUNCTION(0, 2, "ICP_RXD"), + PXA_FUNCTION(1, 3, "CIF_MCLK")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(43), + PXA_FUNCTION(0, 3, "CIF_FV"), + PXA_FUNCTION(1, 1, "ICP_TXD"), + PXA_FUNCTION(1, 2, "BTTXD"), + PXA_FUNCTION(1, 3, "CIF_FV")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(44), + PXA_FUNCTION(0, 1, "BTCTS"), + PXA_FUNCTION(0, 3, "CIF_LV"), + PXA_FUNCTION(1, 3, "CIF_LV")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(45), + PXA_FUNCTION(0, 3, "CIF_PCLK"), + PXA_FUNCTION(1, 1, "AC97_SYSCLK"), + PXA_FUNCTION(1, 2, "BTRTS"), + PXA_FUNCTION(1, 3, "SSPSYSCLK3")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(46), + PXA_FUNCTION(0, 1, "ICP_RXD"), + PXA_FUNCTION(0, 2, "STD_RXD"), + PXA_FUNCTION(1, 2, "PWM_OUT<2>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(47), + PXA_FUNCTION(0, 1, "CIF_DD<0>"), + PXA_FUNCTION(1, 1, "STD_TXD"), + PXA_FUNCTION(1, 2, "ICP_TXD"), + PXA_FUNCTION(1, 3, "PWM_OUT<3>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(48), + PXA_FUNCTION(0, 1, "CIF_DD<5>"), + PXA_FUNCTION(1, 1, "BB_OB_DAT<1>"), + PXA_FUNCTION(1, 2, "nPOE")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(49), + PXA_FUNCTION(1, 2, "nPWE")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(50), + PXA_FUNCTION(0, 1, "CIF_DD<3>"), + PXA_FUNCTION(0, 3, "SSPSCLK2"), + PXA_FUNCTION(1, 1, "BB_OB_DAT<2>"), + PXA_FUNCTION(1, 2, "nPIOR"), + PXA_FUNCTION(1, 3, "SSPSCLK2")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(51), + PXA_FUNCTION(0, 1, "CIF_DD<2>"), + PXA_FUNCTION(1, 1, "BB_OB_DAT<3>"), + PXA_FUNCTION(1, 2, "nPIOW")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(52), + PXA_FUNCTION(0, 1, "CIF_DD<4>"), + PXA_FUNCTION(0, 2, "SSPSCLK3"), + PXA_FUNCTION(1, 1, "BB_OB_CLK"), + PXA_FUNCTION(1, 2, "SSPSCLK3")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(53), + PXA_FUNCTION(0, 1, "FFRXD"), + PXA_FUNCTION(0, 2, "USB_P2_3"), + PXA_FUNCTION(1, 1, "BB_OB_STB"), + PXA_FUNCTION(1, 2, "CIF_MCLK"), + PXA_FUNCTION(1, 3, "SSPSYSCLK")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(54), + PXA_FUNCTION(0, 2, "BB_OB_WAIT"), + PXA_FUNCTION(0, 3, "CIF_PCLK"), + PXA_FUNCTION(1, 2, "nPCE<2>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(55), + PXA_FUNCTION(0, 1, "CIF_DD<1>"), + PXA_FUNCTION(0, 2, "BB_IB_DAT<1>"), + PXA_FUNCTION(1, 2, "nPREG")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(56), + PXA_FUNCTION(0, 1, "nPWAIT"), + PXA_FUNCTION(0, 2, "BB_IB_DAT<2>"), + PXA_FUNCTION(1, 1, "USB_P3_4")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(57), + PXA_FUNCTION(0, 1, "nIOS16"), + PXA_FUNCTION(0, 2, "BB_IB_DAT<3>"), + PXA_FUNCTION(1, 3, "SSPTXD")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(58), + PXA_FUNCTION(0, 2, "LDD<0>"), + PXA_FUNCTION(1, 2, "LDD<0>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(59), + PXA_FUNCTION(0, 2, "LDD<1>"), + PXA_FUNCTION(1, 2, "LDD<1>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(60), + PXA_FUNCTION(0, 2, "LDD<2>"), + PXA_FUNCTION(1, 2, "LDD<2>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(61), + PXA_FUNCTION(0, 2, "LDD<3>"), + PXA_FUNCTION(1, 2, "LDD<3>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(62), + PXA_FUNCTION(0, 2, "LDD<4>"), + PXA_FUNCTION(1, 2, "LDD<4>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(63), + PXA_FUNCTION(0, 2, "LDD<5>"), + PXA_FUNCTION(1, 2, "LDD<5>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(64), + PXA_FUNCTION(0, 2, "LDD<6>"), + PXA_FUNCTION(1, 2, "LDD<6>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(65), + PXA_FUNCTION(0, 2, "LDD<7>"), + PXA_FUNCTION(1, 2, "LDD<7>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(66), + PXA_FUNCTION(0, 2, "LDD<8>"), + PXA_FUNCTION(1, 2, "LDD<8>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(67), + PXA_FUNCTION(0, 2, "LDD<9>"), + PXA_FUNCTION(1, 2, "LDD<9>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(68), + PXA_FUNCTION(0, 2, "LDD<10>"), + PXA_FUNCTION(1, 2, "LDD<10>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(69), + PXA_FUNCTION(0, 2, "LDD<11>"), + PXA_FUNCTION(1, 2, "LDD<11>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(70), + PXA_FUNCTION(0, 2, "LDD<12>"), + PXA_FUNCTION(1, 2, "LDD<12>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(71), + PXA_FUNCTION(0, 2, "LDD<13>"), + PXA_FUNCTION(1, 2, "LDD<13>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(72), + PXA_FUNCTION(0, 2, "LDD<14>"), + PXA_FUNCTION(1, 2, "LDD<14>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(73), + PXA_FUNCTION(0, 2, "LDD<15>"), + PXA_FUNCTION(1, 2, "LDD<15>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(74), + PXA_FUNCTION(1, 2, "L_FCLK_RD")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(75), + PXA_FUNCTION(1, 2, "L_LCLK_A0")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(76), + PXA_FUNCTION(1, 2, "L_PCLK_WR")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(77), + PXA_FUNCTION(1, 2, "L_BIAS")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(78), + PXA_FUNCTION(1, 1, "nPCE<2>"), + PXA_FUNCTION(1, 2, "nCS<2>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(79), + PXA_FUNCTION(1, 1, "PSKTSEL"), + PXA_FUNCTION(1, 2, "nCS<3>"), + PXA_FUNCTION(1, 3, "PWM_OUT<2>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(80), + PXA_FUNCTION(0, 1, "DREQ<1>"), + PXA_FUNCTION(0, 2, "MBREQ"), + PXA_FUNCTION(1, 2, "nCS<4>"), + PXA_FUNCTION(1, 3, "PWM_OUT<3>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(81), + PXA_FUNCTION(0, 2, "CIF_DD<0>"), + PXA_FUNCTION(1, 1, "SSPTXD3"), + PXA_FUNCTION(1, 2, "BB_OB_DAT<0>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(82), + PXA_FUNCTION(0, 1, "SSPRXD3"), + PXA_FUNCTION(0, 2, "BB_IB_DAT<0>"), + PXA_FUNCTION(0, 3, "CIF_DD<5>"), + PXA_FUNCTION(1, 3, "FFDTR")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(83), + PXA_FUNCTION(0, 1, "SSPSFRM3"), + PXA_FUNCTION(0, 2, "BB_IB_CLK"), + PXA_FUNCTION(0, 3, "CIF_DD<5>"), + PXA_FUNCTION(1, 1, "SSPSFRM3"), + PXA_FUNCTION(1, 2, "FFTXD"), + PXA_FUNCTION(1, 3, "FFRTS")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(84), + PXA_FUNCTION(0, 1, "SSPCLK3"), + PXA_FUNCTION(0, 2, "BB_IB_STB"), + PXA_FUNCTION(0, 3, "CIF_FV"), + PXA_FUNCTION(1, 1, "SSPCLK3"), + PXA_FUNCTION(1, 3, "CIF_FV")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(85), + PXA_FUNCTION(0, 1, "FFRXD"), + PXA_FUNCTION(0, 2, "DREQ<2>"), + PXA_FUNCTION(0, 3, "CIF_LV"), + PXA_FUNCTION(1, 1, "nPCE<1>"), + PXA_FUNCTION(1, 2, "BB_IB_WAIT"), + PXA_FUNCTION(1, 3, "CIF_LV")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(86), + PXA_FUNCTION(0, 1, "SSPRXD2"), + PXA_FUNCTION(0, 2, "LDD<16>"), + PXA_FUNCTION(0, 3, "USB_P3_5"), + PXA_FUNCTION(1, 1, "nPCE<1>"), + PXA_FUNCTION(1, 2, "LDD<16>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(87), + PXA_FUNCTION(0, 1, "nPCE<2>"), + PXA_FUNCTION(0, 2, "LDD<17>"), + PXA_FUNCTION(0, 3, "USB_P3_1"), + PXA_FUNCTION(1, 1, "SSPTXD2"), + PXA_FUNCTION(1, 2, "LDD<17>"), + PXA_FUNCTION(1, 3, "SSPSFRM2")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(88), + PXA_FUNCTION(0, 1, "USBHPWR<1>"), + PXA_FUNCTION(0, 2, "SSPRXD2"), + PXA_FUNCTION(0, 3, "SSPSFRM2"), + PXA_FUNCTION(1, 2, "SSPTXD2"), + PXA_FUNCTION(1, 3, "SSPSFRM2")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(89), + PXA_FUNCTION(0, 1, "SSPRXD3"), + PXA_FUNCTION(0, 3, "FFRI"), + PXA_FUNCTION(1, 1, "AC97_SYSCLK"), + PXA_FUNCTION(1, 2, "USBHPEN<1>"), + PXA_FUNCTION(1, 3, "SSPTXD2")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(90), + PXA_FUNCTION(0, 1, "KP_MKIN<5>"), + PXA_FUNCTION(0, 3, "USB_P3_5"), + PXA_FUNCTION(1, 1, "CIF_DD<4>"), + PXA_FUNCTION(1, 2, "nURST")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(91), + PXA_FUNCTION(0, 1, "KP_MKIN<6>"), + PXA_FUNCTION(0, 3, "USB_P3_1"), + PXA_FUNCTION(1, 1, "CIF_DD<5>"), + PXA_FUNCTION(1, 2, "UCLK")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(92), + PXA_FUNCTION(0, 1, "MMDAT<0>"), + PXA_FUNCTION(1, 1, "MMDAT<0>"), + PXA_FUNCTION(1, 2, "MSBS")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(93), + PXA_FUNCTION(0, 1, "KP_DKIN<0>"), + PXA_FUNCTION(0, 2, "CIF_DD<6>"), + PXA_FUNCTION(1, 1, "AC97_SDATA_OUT")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(94), + PXA_FUNCTION(0, 1, "KP_DKIN<1>"), + PXA_FUNCTION(0, 2, "CIF_DD<5>"), + PXA_FUNCTION(1, 1, "AC97_SYNC")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(95), + PXA_FUNCTION(0, 1, "KP_DKIN<2>"), + PXA_FUNCTION(0, 2, "CIF_DD<4>"), + PXA_FUNCTION(0, 3, "KP_MKIN<6>"), + PXA_FUNCTION(1, 1, "AC97_RESET_n")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(96), + PXA_FUNCTION(0, 1, "KP_DKIN<3>"), + PXA_FUNCTION(0, 2, "MBREQ"), + PXA_FUNCTION(0, 3, "FFRXD"), + PXA_FUNCTION(1, 2, "DVAL<1>"), + PXA_FUNCTION(1, 3, "KP_MKOUT<6>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(97), + PXA_FUNCTION(0, 1, "KP_DKIN<4>"), + PXA_FUNCTION(0, 2, "DREQ<1>"), + PXA_FUNCTION(0, 3, "KP_MKIN<3>"), + PXA_FUNCTION(1, 2, "MBGNT")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(98), + PXA_FUNCTION(0, 1, "KP_DKIN<5>"), + PXA_FUNCTION(0, 2, "CIF_DD<0>"), + PXA_FUNCTION(0, 3, "KP_MKIN<4>"), + PXA_FUNCTION(1, 1, "AC97_SYSCLK"), + PXA_FUNCTION(1, 3, "FFRTS")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(99), + PXA_FUNCTION(0, 1, "KP_DKIN<6>"), + PXA_FUNCTION(0, 2, "AC97_SDATA_IN_1"), + PXA_FUNCTION(0, 3, "KP_MKIN<5>"), + PXA_FUNCTION(1, 3, "FFTXD")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(100), + PXA_FUNCTION(0, 1, "KP_MKIN<0>"), + PXA_FUNCTION(0, 2, "DREQ<2>"), + PXA_FUNCTION(0, 3, "FFCTS")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(101), + PXA_FUNCTION(0, 1, "KP_MKIN<1>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(102), + PXA_FUNCTION(0, 1, "KP_MKIN<2>"), + PXA_FUNCTION(0, 3, "FFRXD"), + PXA_FUNCTION(1, 1, "nPCE<1>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(103), + PXA_FUNCTION(0, 1, "CIF_DD<3>"), + PXA_FUNCTION(1, 2, "KP_MKOUT<0>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(104), + PXA_FUNCTION(0, 1, "CIF_DD<2>"), + PXA_FUNCTION(1, 1, "PSKTSEL"), + PXA_FUNCTION(1, 2, "KP_MKOUT<1>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(105), + PXA_FUNCTION(0, 1, "CIF_DD<1>"), + PXA_FUNCTION(1, 1, "nPCE<2>"), + PXA_FUNCTION(1, 2, "KP_MKOUT<2>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(106), + PXA_FUNCTION(0, 1, "CIF_DD<9>"), + PXA_FUNCTION(1, 2, "KP_MKOUT<3>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(107), + PXA_FUNCTION(0, 1, "CIF_DD<8>"), + PXA_FUNCTION(1, 2, "KP_MKOUT<4>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(108), + PXA_FUNCTION(0, 1, "CIF_DD<7>"), + PXA_FUNCTION(1, 1, "CHOUT<0>"), + PXA_FUNCTION(1, 2, "KP_MKOUT<5>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(109), + PXA_FUNCTION(0, 1, "MMDAT<1>"), + PXA_FUNCTION(0, 2, "MSSDIO"), + PXA_FUNCTION(1, 1, "MMDAT<1>"), + PXA_FUNCTION(1, 2, "MSSDIO")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(110), + PXA_FUNCTION(0, 1, "MMDAT<2>"), + PXA_FUNCTION(1, 1, "MMDAT<2>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(111), + PXA_FUNCTION(0, 1, "MMDAT<3>"), + PXA_FUNCTION(1, 1, "MMDAT<3>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(112), + PXA_FUNCTION(0, 1, "MMCMD"), + PXA_FUNCTION(0, 2, "nMSINS"), + PXA_FUNCTION(1, 1, "MMCMD")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(113), + PXA_FUNCTION(0, 3, "USB_P3_3"), + PXA_FUNCTION(1, 1, "I2S_SYSCLK"), + PXA_FUNCTION(1, 2, "AC97_RESET_n")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(114), + PXA_FUNCTION(0, 1, "CIF_DD<1>"), + PXA_FUNCTION(1, 1, "UEN"), + PXA_FUNCTION(1, 2, "UVS0")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(115), + PXA_FUNCTION(0, 1, "DREQ<0>"), + PXA_FUNCTION(0, 2, "CIF_DD<3>"), + PXA_FUNCTION(0, 3, "MBREQ"), + PXA_FUNCTION(1, 1, "UEN"), + PXA_FUNCTION(1, 2, "nUVS1"), + PXA_FUNCTION(1, 3, "PWM_OUT<1>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(116), + PXA_FUNCTION(0, 1, "CIF_DD<2>"), + PXA_FUNCTION(0, 2, "AC97_SDATA_IN_0"), + PXA_FUNCTION(0, 3, "UDET"), + PXA_FUNCTION(1, 1, "DVAL<0>"), + PXA_FUNCTION(1, 2, "nUVS2"), + PXA_FUNCTION(1, 3, "MBGNT")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(117), + PXA_FUNCTION(0, 1, "SCL"), + PXA_FUNCTION(1, 1, "SCL")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(118), + PXA_FUNCTION(0, 1, "SDA"), + PXA_FUNCTION(1, 1, "SDA")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(119), + PXA_FUNCTION(0, 1, "USBHPWR<2>")), + PXA_GPIO_PIN(PXA_PINCTRL_PIN(120), + PXA_FUNCTION(1, 2, "USBHPEN<2>")), +}; + +static int pxa27x_pinctrl_probe(struct platform_device *pdev) +{ + int ret, i; + void __iomem *base_af[8]; + void __iomem *base_dir[4]; + void __iomem *base_sleep[4]; + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base_af[0] = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base_af[0])) + return PTR_ERR(base_af[0]); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + base_dir[0] = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base_dir[0])) + return PTR_ERR(base_dir[0]); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 2); + base_dir[3] = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base_dir[3])) + return PTR_ERR(base_dir[3]); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 3); + base_sleep[0] = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base_sleep[0])) + return PTR_ERR(base_sleep[0]); + + for (i = 0; i < ARRAY_SIZE(base_af); i++) + base_af[i] = base_af[0] + sizeof(base_af[0]) * i; + for (i = 0; i < 3; i++) + base_dir[i] = base_dir[0] + sizeof(base_dir[0]) * i; + for (i = 0; i < ARRAY_SIZE(base_sleep); i++) + base_sleep[i] = base_sleep[0] + sizeof(base_af[0]) * i; + + ret = pxa2xx_pinctrl_init(pdev, pxa27x_pins, ARRAY_SIZE(pxa27x_pins), + base_af, base_dir, base_sleep); + return ret; +} + +static const struct of_device_id pxa27x_pinctrl_match[] = { + { .compatible = "marvell,pxa27x-pinctrl", }, + {} +}; +MODULE_DEVICE_TABLE(of, pxa27x_pinctrl_match); + +static struct platform_driver pxa27x_pinctrl_driver = { + .probe = pxa27x_pinctrl_probe, + .driver = { + .name = "pxa27x-pinctrl", + .of_match_table = pxa27x_pinctrl_match, + }, +}; +module_platform_driver(pxa27x_pinctrl_driver); + +MODULE_AUTHOR("Robert Jarzmik <robert.jarzmik@free.fr>"); +MODULE_DESCRIPTION("Marvell PXA27x pinctrl driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/pxa/pinctrl-pxa2xx.c b/drivers/pinctrl/pxa/pinctrl-pxa2xx.c new file mode 100644 index 000000000000..216f227c6009 --- /dev/null +++ b/drivers/pinctrl/pxa/pinctrl-pxa2xx.c @@ -0,0 +1,437 @@ +/* + * Marvell PXA2xx family pin control + * + * Copyright (C) 2015 Robert Jarzmik + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + */ + +#include <linux/bitops.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/module.h> +#include <linux/pinctrl/pinconf.h> +#include <linux/pinctrl/pinconf-generic.h> +#include <linux/pinctrl/pinmux.h> +#include <linux/pinctrl/pinctrl.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#include "../pinctrl-utils.h" +#include "pinctrl-pxa2xx.h" + +static int pxa2xx_pctrl_get_groups_count(struct pinctrl_dev *pctldev) +{ + struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + return pctl->ngroups; +} + +static const char *pxa2xx_pctrl_get_group_name(struct pinctrl_dev *pctldev, + unsigned tgroup) +{ + struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + struct pxa_pinctrl_group *group = pctl->groups + tgroup; + + return group->name; +} + +static int pxa2xx_pctrl_get_group_pins(struct pinctrl_dev *pctldev, + unsigned tgroup, + const unsigned **pins, + unsigned *num_pins) +{ + struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + struct pxa_pinctrl_group *group = pctl->groups + tgroup; + + *pins = (unsigned *)&group->pin; + *num_pins = 1; + + return 0; +} + +static const struct pinctrl_ops pxa2xx_pctl_ops = { +#ifdef CONFIG_OF + .dt_node_to_map = pinconf_generic_dt_node_to_map_all, + .dt_free_map = pinctrl_utils_dt_free_map, +#endif + .get_groups_count = pxa2xx_pctrl_get_groups_count, + .get_group_name = pxa2xx_pctrl_get_group_name, + .get_group_pins = pxa2xx_pctrl_get_group_pins, +}; + +static struct pxa_desc_function * +pxa_desc_by_func_group(struct pxa_pinctrl *pctl, const char *pin_name, + const char *func_name) +{ + int i; + struct pxa_desc_function *df; + + for (i = 0; i < pctl->npins; i++) { + const struct pxa_desc_pin *pin = pctl->ppins + i; + + if (!strcmp(pin->pin.name, pin_name)) + for (df = pin->functions; df->name; df++) + if (!strcmp(df->name, func_name)) + return df; + } + + return NULL; +} + +static int pxa2xx_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned pin, + bool input) +{ + struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + unsigned long flags; + uint32_t val; + void __iomem *gpdr; + + gpdr = pctl->base_gpdr[pin / 32]; + dev_dbg(pctl->dev, "set_direction(pin=%d): dir=%d\n", + pin, !input); + + spin_lock_irqsave(&pctl->lock, flags); + + val = readl_relaxed(gpdr); + val = (val & ~BIT(pin % 32)) | (input ? 0 : BIT(pin % 32)); + writel_relaxed(val, gpdr); + + spin_unlock_irqrestore(&pctl->lock, flags); + + return 0; +} + +static const char *pxa2xx_pmx_get_func_name(struct pinctrl_dev *pctldev, + unsigned function) +{ + struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + struct pxa_pinctrl_function *pf = pctl->functions + function; + + return pf->name; +} + +static int pxa2xx_get_functions_count(struct pinctrl_dev *pctldev) +{ + struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + return pctl->nfuncs; +} + +static int pxa2xx_pmx_get_func_groups(struct pinctrl_dev *pctldev, + unsigned function, + const char * const **groups, + unsigned * const num_groups) +{ + struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + struct pxa_pinctrl_function *pf = pctl->functions + function; + + *groups = pf->groups; + *num_groups = pf->ngroups; + + return 0; +} + +static int pxa2xx_pmx_set_mux(struct pinctrl_dev *pctldev, unsigned function, + unsigned tgroup) +{ + struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + struct pxa_pinctrl_group *group = pctl->groups + tgroup; + struct pxa_desc_function *df; + int pin, shift; + unsigned long flags; + void __iomem *gafr, *gpdr; + u32 val; + + + df = pxa_desc_by_func_group(pctl, group->name, + (pctl->functions + function)->name); + if (!df) + return -EINVAL; + + pin = group->pin; + gafr = pctl->base_gafr[pin / 16]; + gpdr = pctl->base_gpdr[pin / 32]; + shift = (pin % 16) << 1; + dev_dbg(pctl->dev, "set_mux(pin=%d): af=%d dir=%d\n", + pin, df->muxval >> 1, df->muxval & 0x1); + + spin_lock_irqsave(&pctl->lock, flags); + + val = readl_relaxed(gafr); + val = (val & ~(0x3 << shift)) | ((df->muxval >> 1) << shift); + writel_relaxed(val, gafr); + + val = readl_relaxed(gpdr); + val = (val & ~BIT(pin % 32)) | ((df->muxval & 1) ? BIT(pin % 32) : 0); + writel_relaxed(val, gpdr); + + spin_unlock_irqrestore(&pctl->lock, flags); + + return 0; +} +static const struct pinmux_ops pxa2xx_pinmux_ops = { + .get_functions_count = pxa2xx_get_functions_count, + .get_function_name = pxa2xx_pmx_get_func_name, + .get_function_groups = pxa2xx_pmx_get_func_groups, + .set_mux = pxa2xx_pmx_set_mux, + .gpio_set_direction = pxa2xx_pmx_gpio_set_direction, +}; + +static int pxa2xx_pconf_group_get(struct pinctrl_dev *pctldev, + unsigned group, + unsigned long *config) +{ + struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + struct pxa_pinctrl_group *g = pctl->groups + group; + unsigned long flags; + unsigned pin = g->pin; + void __iomem *pgsr = pctl->base_pgsr[pin / 32]; + u32 val; + + spin_lock_irqsave(&pctl->lock, flags); + val = readl_relaxed(pgsr) & BIT(pin % 32); + *config = val ? PIN_CONFIG_LOW_POWER_MODE : 0; + spin_unlock_irqrestore(&pctl->lock, flags); + + dev_dbg(pctl->dev, "get sleep gpio state(pin=%d) %d\n", + pin, !!val); + return 0; +} + +static int pxa2xx_pconf_group_set(struct pinctrl_dev *pctldev, + unsigned group, + unsigned long *configs, + unsigned num_configs) +{ + struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + struct pxa_pinctrl_group *g = pctl->groups + group; + unsigned long flags; + unsigned pin = g->pin; + void __iomem *pgsr = pctl->base_pgsr[pin / 32]; + int i, is_set = 0; + u32 val; + + for (i = 0; i < num_configs; i++) { + switch (pinconf_to_config_param(configs[i])) { + case PIN_CONFIG_LOW_POWER_MODE: + is_set = pinconf_to_config_argument(configs[i]); + break; + default: + return -EINVAL; + } + } + + dev_dbg(pctl->dev, "set sleep gpio state(pin=%d) %d\n", + pin, is_set); + + spin_lock_irqsave(&pctl->lock, flags); + val = readl_relaxed(pgsr); + val = (val & ~BIT(pin % 32)) | (is_set ? BIT(pin % 32) : 0); + writel_relaxed(val, pgsr); + spin_unlock_irqrestore(&pctl->lock, flags); + + return 0; +} + +static const struct pinconf_ops pxa2xx_pconf_ops = { + .pin_config_group_get = pxa2xx_pconf_group_get, + .pin_config_group_set = pxa2xx_pconf_group_set, + .is_generic = true, +}; + +static struct pinctrl_desc pxa2xx_pinctrl_desc = { + .confops = &pxa2xx_pconf_ops, + .pctlops = &pxa2xx_pctl_ops, + .pmxops = &pxa2xx_pinmux_ops, +}; + +static const struct pxa_pinctrl_function * +pxa2xx_find_function(struct pxa_pinctrl *pctl, const char *fname, + const struct pxa_pinctrl_function *functions) +{ + const struct pxa_pinctrl_function *func; + + for (func = functions; func->name; func++) + if (!strcmp(fname, func->name)) + return func; + + return NULL; +} + +static int pxa2xx_build_functions(struct pxa_pinctrl *pctl) +{ + int i; + struct pxa_pinctrl_function *functions; + struct pxa_desc_function *df; + + /* + * Each pin can have at most 6 alternate functions, and 2 gpio functions + * which are common to each pin. As there are more than 2 pins without + * alternate function, 6 * npins is an absolute high limit of the number + * of functions. + */ + functions = devm_kcalloc(pctl->dev, pctl->npins * 6, + sizeof(*functions), GFP_KERNEL); + if (!functions) + return -ENOMEM; + + for (i = 0; i < pctl->npins; i++) + for (df = pctl->ppins[i].functions; df->name; df++) + if (!pxa2xx_find_function(pctl, df->name, functions)) + (functions + pctl->nfuncs++)->name = df->name; + pctl->functions = devm_kmemdup(pctl->dev, functions, + pctl->nfuncs * sizeof(*functions), + GFP_KERNEL); + if (!pctl->functions) + return -ENOMEM; + + devm_kfree(pctl->dev, functions); + return 0; +} + +static int pxa2xx_build_groups(struct pxa_pinctrl *pctl) +{ + int i, j, ngroups; + struct pxa_pinctrl_function *func; + struct pxa_desc_function *df; + char **gtmp; + + gtmp = devm_kmalloc_array(pctl->dev, pctl->npins, sizeof(*gtmp), + GFP_KERNEL); + if (!gtmp) + return -ENOMEM; + + for (i = 0; i < pctl->nfuncs; i++) { + ngroups = 0; + for (j = 0; j < pctl->npins; j++) + for (df = pctl->ppins[j].functions; df->name; + df++) + if (!strcmp(pctl->functions[i].name, + df->name)) + gtmp[ngroups++] = (char *) + pctl->ppins[j].pin.name; + func = pctl->functions + i; + func->ngroups = ngroups; + func->groups = + devm_kmalloc_array(pctl->dev, ngroups, + sizeof(char *), GFP_KERNEL); + if (!func->groups) + return -ENOMEM; + + memcpy(func->groups, gtmp, ngroups * sizeof(*gtmp)); + } + + devm_kfree(pctl->dev, gtmp); + return 0; +} + +static int pxa2xx_build_state(struct pxa_pinctrl *pctl, + const struct pxa_desc_pin *ppins, int npins) +{ + struct pxa_pinctrl_group *group; + struct pinctrl_pin_desc *pins; + int ret, i; + + pctl->npins = npins; + pctl->ppins = ppins; + pctl->ngroups = npins; + + pctl->desc.npins = npins; + pins = devm_kcalloc(pctl->dev, npins, sizeof(*pins), GFP_KERNEL); + if (!pins) + return -ENOMEM; + + pctl->desc.pins = pins; + for (i = 0; i < npins; i++) + pins[i] = ppins[i].pin; + + pctl->groups = devm_kmalloc_array(pctl->dev, pctl->ngroups, + sizeof(*pctl->groups), GFP_KERNEL); + if (!pctl->groups) + return -ENOMEM; + + for (i = 0; i < npins; i++) { + group = pctl->groups + i; + group->name = ppins[i].pin.name; + group->pin = ppins[i].pin.number; + } + + ret = pxa2xx_build_functions(pctl); + if (ret) + return ret; + + ret = pxa2xx_build_groups(pctl); + if (ret) + return ret; + + return 0; +} + +int pxa2xx_pinctrl_init(struct platform_device *pdev, + const struct pxa_desc_pin *ppins, int npins, + void __iomem *base_gafr[], void __iomem *base_gpdr[], + void __iomem *base_pgsr[]) +{ + struct pxa_pinctrl *pctl; + int ret, i, maxpin = 0; + + for (i = 0; i < npins; i++) + maxpin = max_t(int, ppins[i].pin.number, maxpin); + + pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL); + if (!pctl) + return -ENOMEM; + pctl->base_gafr = devm_kcalloc(&pdev->dev, roundup(maxpin, 16), + sizeof(*pctl->base_gafr), GFP_KERNEL); + pctl->base_gpdr = devm_kcalloc(&pdev->dev, roundup(maxpin, 32), + sizeof(*pctl->base_gpdr), GFP_KERNEL); + pctl->base_pgsr = devm_kcalloc(&pdev->dev, roundup(maxpin, 32), + sizeof(*pctl->base_pgsr), GFP_KERNEL); + if (!pctl->base_gafr || !pctl->base_gpdr || !pctl->base_pgsr) + return -ENOMEM; + + platform_set_drvdata(pdev, pctl); + spin_lock_init(&pctl->lock); + + pctl->dev = &pdev->dev; + pctl->desc = pxa2xx_pinctrl_desc; + pctl->desc.name = dev_name(&pdev->dev); + pctl->desc.owner = THIS_MODULE; + + for (i = 0; i < roundup(maxpin, 16); i += 16) + pctl->base_gafr[i / 16] = base_gafr[i / 16]; + for (i = 0; i < roundup(maxpin, 32); i += 32) { + pctl->base_gpdr[i / 32] = base_gpdr[i / 32]; + pctl->base_pgsr[i / 32] = base_pgsr[i / 32]; + } + + ret = pxa2xx_build_state(pctl, ppins, npins); + if (ret) + return ret; + + pctl->pctl_dev = pinctrl_register(&pctl->desc, &pdev->dev, pctl); + if (IS_ERR(pctl->pctl_dev)) { + dev_err(&pdev->dev, "couldn't register pinctrl driver\n"); + return PTR_ERR(pctl->pctl_dev); + } + + dev_info(&pdev->dev, "initialized pxa2xx pinctrl driver\n"); + + return 0; +} +EXPORT_SYMBOL(pxa2xx_pinctrl_init); + +int pxa2xx_pinctrl_exit(struct platform_device *pdev) +{ + struct pxa_pinctrl *pctl = platform_get_drvdata(pdev); + + pinctrl_unregister(pctl->pctl_dev); + return 0; +} diff --git a/drivers/pinctrl/pxa/pinctrl-pxa2xx.h b/drivers/pinctrl/pxa/pinctrl-pxa2xx.h new file mode 100644 index 000000000000..8be1e0b79751 --- /dev/null +++ b/drivers/pinctrl/pxa/pinctrl-pxa2xx.h @@ -0,0 +1,92 @@ +/* + * Marvell PXA2xx family pin control + * + * Copyright (C) 2015 Robert Jarzmik + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + */ + +#ifndef __PINCTRL_PXA_H +#define __PINCTRL_PXA_H + +#define PXA_FUNCTION(_dir, _af, _name) \ + { \ + .name = _name, \ + .muxval = (_dir | (_af << 1)), \ + } + +#define PXA_PIN(_pin, funcs...) \ + { \ + .pin = _pin, \ + .functions = (struct pxa_desc_function[]){ \ + funcs, { } }, \ + } + +#define PXA_GPIO_PIN(_pin, funcs...) \ + { \ + .pin = _pin, \ + .functions = (struct pxa_desc_function[]){ \ + PXA_FUNCTION(0, 0, "gpio_in"), \ + PXA_FUNCTION(1, 0, "gpio_out"), \ + funcs, { } }, \ + } + +#define PXA_GPIO_ONLY_PIN(_pin) \ + { \ + .pin = _pin, \ + .functions = (struct pxa_desc_function[]){ \ + PXA_FUNCTION(0, 0, "gpio_in"), \ + PXA_FUNCTION(1, 0, "gpio_out"), \ + { } }, \ + } + +#define PXA_PINCTRL_PIN(pin) \ + PINCTRL_PIN(pin, "P" #pin) + +struct pxa_desc_function { + const char *name; + u8 muxval; +}; + +struct pxa_desc_pin { + struct pinctrl_pin_desc pin; + struct pxa_desc_function *functions; +}; + +struct pxa_pinctrl_group { + const char *name; + unsigned pin; +}; + +struct pxa_pinctrl_function { + const char *name; + const char **groups; + unsigned ngroups; +}; + +struct pxa_pinctrl { + spinlock_t lock; + void __iomem **base_gafr; + void __iomem **base_gpdr; + void __iomem **base_pgsr; + struct device *dev; + struct pinctrl_desc desc; + struct pinctrl_dev *pctl_dev; + unsigned npins; + const struct pxa_desc_pin *ppins; + unsigned ngroups; + struct pxa_pinctrl_group *groups; + unsigned nfuncs; + struct pxa_pinctrl_function *functions; + char *name; +}; + +int pxa2xx_pinctrl_init(struct platform_device *pdev, + const struct pxa_desc_pin *ppins, int npins, + void __iomem *base_gafr[], void __iomem *base_gpdr[], + void __iomem *base_gpsr[]); + +#endif /* __PINCTRL_PXA_H */ |