1875a92b3SAndy Shevchenko // SPDX-License-Identifier: GPL-2.0
25fae8b86SMika Westerberg /*
35fae8b86SMika Westerberg  * Pinctrl GPIO driver for Intel Baytrail
45fae8b86SMika Westerberg  *
5875a92b3SAndy Shevchenko  * Copyright (c) 2012-2013, Intel Corporation
65fae8b86SMika Westerberg  * Author: Mathias Nyman <mathias.nyman@linux.intel.com>
75fae8b86SMika Westerberg  */
85fae8b86SMika Westerberg 
95fae8b86SMika Westerberg #include <linux/kernel.h>
105fae8b86SMika Westerberg #include <linux/init.h>
115fae8b86SMika Westerberg #include <linux/types.h>
125fae8b86SMika Westerberg #include <linux/bitops.h>
135fae8b86SMika Westerberg #include <linux/interrupt.h>
1486e3ef81SCristina Ciocan #include <linux/gpio.h>
15bf9a5c96SLinus Walleij #include <linux/gpio/driver.h>
165fae8b86SMika Westerberg #include <linux/acpi.h>
175fae8b86SMika Westerberg #include <linux/platform_device.h>
185fae8b86SMika Westerberg #include <linux/seq_file.h>
195fae8b86SMika Westerberg #include <linux/io.h>
205fae8b86SMika Westerberg #include <linux/pm_runtime.h>
215fae8b86SMika Westerberg #include <linux/pinctrl/pinctrl.h>
22c501d0b1SCristina Ciocan #include <linux/pinctrl/pinmux.h>
23c501d0b1SCristina Ciocan #include <linux/pinctrl/pinconf.h>
24c501d0b1SCristina Ciocan #include <linux/pinctrl/pinconf-generic.h>
255fae8b86SMika Westerberg 
265fae8b86SMika Westerberg /* memory mapped register offsets */
275fae8b86SMika Westerberg #define BYT_CONF0_REG		0x000
285fae8b86SMika Westerberg #define BYT_CONF1_REG		0x004
295fae8b86SMika Westerberg #define BYT_VAL_REG		0x008
305fae8b86SMika Westerberg #define BYT_DFT_REG		0x00c
315fae8b86SMika Westerberg #define BYT_INT_STAT_REG	0x800
32658b476cSCristina Ciocan #define BYT_DEBOUNCE_REG	0x9d0
335fae8b86SMika Westerberg 
345fae8b86SMika Westerberg /* BYT_CONF0_REG register bits */
355fae8b86SMika Westerberg #define BYT_IODEN		BIT(31)
365fae8b86SMika Westerberg #define BYT_DIRECT_IRQ_EN	BIT(27)
375fae8b86SMika Westerberg #define BYT_TRIG_NEG		BIT(26)
385fae8b86SMika Westerberg #define BYT_TRIG_POS		BIT(25)
395fae8b86SMika Westerberg #define BYT_TRIG_LVL		BIT(24)
40658b476cSCristina Ciocan #define BYT_DEBOUNCE_EN		BIT(20)
419291c65bSHans de Goede #define BYT_GLITCH_FILTER_EN	BIT(19)
429291c65bSHans de Goede #define BYT_GLITCH_F_SLOW_CLK	BIT(17)
439291c65bSHans de Goede #define BYT_GLITCH_F_FAST_CLK	BIT(16)
445fae8b86SMika Westerberg #define BYT_PULL_STR_SHIFT	9
455fae8b86SMika Westerberg #define BYT_PULL_STR_MASK	(3 << BYT_PULL_STR_SHIFT)
465fae8b86SMika Westerberg #define BYT_PULL_STR_2K		(0 << BYT_PULL_STR_SHIFT)
475fae8b86SMika Westerberg #define BYT_PULL_STR_10K	(1 << BYT_PULL_STR_SHIFT)
485fae8b86SMika Westerberg #define BYT_PULL_STR_20K	(2 << BYT_PULL_STR_SHIFT)
495fae8b86SMika Westerberg #define BYT_PULL_STR_40K	(3 << BYT_PULL_STR_SHIFT)
505fae8b86SMika Westerberg #define BYT_PULL_ASSIGN_SHIFT	7
515fae8b86SMika Westerberg #define BYT_PULL_ASSIGN_MASK	(3 << BYT_PULL_ASSIGN_SHIFT)
525fae8b86SMika Westerberg #define BYT_PULL_ASSIGN_UP	(1 << BYT_PULL_ASSIGN_SHIFT)
535fae8b86SMika Westerberg #define BYT_PULL_ASSIGN_DOWN	(2 << BYT_PULL_ASSIGN_SHIFT)
545fae8b86SMika Westerberg #define BYT_PIN_MUX		0x07
555fae8b86SMika Westerberg 
565fae8b86SMika Westerberg /* BYT_VAL_REG register bits */
575fae8b86SMika Westerberg #define BYT_INPUT_EN		BIT(2)  /* 0: input enabled (active low)*/
585fae8b86SMika Westerberg #define BYT_OUTPUT_EN		BIT(1)  /* 0: output enabled (active low)*/
595fae8b86SMika Westerberg #define BYT_LEVEL		BIT(0)
605fae8b86SMika Westerberg 
615fae8b86SMika Westerberg #define BYT_DIR_MASK		(BIT(1) | BIT(2))
625fae8b86SMika Westerberg #define BYT_TRIG_MASK		(BIT(26) | BIT(25) | BIT(24))
635fae8b86SMika Westerberg 
64fcc18debSMika Westerberg #define BYT_CONF0_RESTORE_MASK	(BYT_DIRECT_IRQ_EN | BYT_TRIG_MASK | \
65fcc18debSMika Westerberg 				 BYT_PIN_MUX)
66fcc18debSMika Westerberg #define BYT_VAL_RESTORE_MASK	(BYT_DIR_MASK | BYT_LEVEL)
67fcc18debSMika Westerberg 
68658b476cSCristina Ciocan /* BYT_DEBOUNCE_REG bits */
69658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_MASK		0x7
70658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_375US	1
71658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_750US	2
72658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_1500US	3
73658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_3MS		4
74658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_6MS		5
75658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_12MS		6
76658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_24MS		7
77658b476cSCristina Ciocan 
785fae8b86SMika Westerberg #define BYT_NGPIO_SCORE		102
795fae8b86SMika Westerberg #define BYT_NGPIO_NCORE		28
805fae8b86SMika Westerberg #define BYT_NGPIO_SUS		44
815fae8b86SMika Westerberg 
825fae8b86SMika Westerberg #define BYT_SCORE_ACPI_UID	"1"
835fae8b86SMika Westerberg #define BYT_NCORE_ACPI_UID	"2"
845fae8b86SMika Westerberg #define BYT_SUS_ACPI_UID	"3"
855fae8b86SMika Westerberg 
86c501d0b1SCristina Ciocan /*
87c501d0b1SCristina Ciocan  * This is the function value most pins have for GPIO muxing. If the value
88c501d0b1SCristina Ciocan  * differs from the default one, it must be explicitly mentioned. Otherwise, the
89c501d0b1SCristina Ciocan  * pin control implementation will set the muxing value to default GPIO if it
90c501d0b1SCristina Ciocan  * does not find a match for the requested function.
91c501d0b1SCristina Ciocan  */
92c501d0b1SCristina Ciocan #define BYT_DEFAULT_GPIO_MUX	0
93c501d0b1SCristina Ciocan 
94c8f5c4c7SCristina Ciocan struct byt_gpio_pin_context {
95c8f5c4c7SCristina Ciocan 	u32 conf0;
96c8f5c4c7SCristina Ciocan 	u32 val;
97c8f5c4c7SCristina Ciocan };
985fae8b86SMika Westerberg 
99c8f5c4c7SCristina Ciocan struct byt_simple_func_mux {
100c8f5c4c7SCristina Ciocan 	const char *name;
101c8f5c4c7SCristina Ciocan 	unsigned short func;
102c8f5c4c7SCristina Ciocan };
103c8f5c4c7SCristina Ciocan 
104c8f5c4c7SCristina Ciocan struct byt_mixed_func_mux {
105c8f5c4c7SCristina Ciocan 	const char *name;
106c8f5c4c7SCristina Ciocan 	const unsigned short *func_values;
107c8f5c4c7SCristina Ciocan };
108c8f5c4c7SCristina Ciocan 
109c8f5c4c7SCristina Ciocan struct byt_pingroup {
110c8f5c4c7SCristina Ciocan 	const char *name;
111c8f5c4c7SCristina Ciocan 	const unsigned int *pins;
112c8f5c4c7SCristina Ciocan 	size_t npins;
113c8f5c4c7SCristina Ciocan 	unsigned short has_simple_funcs;
114c8f5c4c7SCristina Ciocan 	union {
115c8f5c4c7SCristina Ciocan 		const struct byt_simple_func_mux *simple_funcs;
116c8f5c4c7SCristina Ciocan 		const struct byt_mixed_func_mux *mixed_funcs;
117c8f5c4c7SCristina Ciocan 	};
118c8f5c4c7SCristina Ciocan 	size_t nfuncs;
119c8f5c4c7SCristina Ciocan };
120c8f5c4c7SCristina Ciocan 
121c8f5c4c7SCristina Ciocan struct byt_function {
122c8f5c4c7SCristina Ciocan 	const char *name;
123c8f5c4c7SCristina Ciocan 	const char * const *groups;
124c8f5c4c7SCristina Ciocan 	size_t ngroups;
125c8f5c4c7SCristina Ciocan };
126c8f5c4c7SCristina Ciocan 
127c8f5c4c7SCristina Ciocan struct byt_community {
128c8f5c4c7SCristina Ciocan 	unsigned int pin_base;
129c8f5c4c7SCristina Ciocan 	size_t npins;
130c8f5c4c7SCristina Ciocan 	const unsigned int *pad_map;
131c8f5c4c7SCristina Ciocan 	void __iomem *reg_base;
132c8f5c4c7SCristina Ciocan };
133c8f5c4c7SCristina Ciocan 
134c8f5c4c7SCristina Ciocan #define SIMPLE_FUNC(n, f)	\
135c8f5c4c7SCristina Ciocan 	{			\
136c8f5c4c7SCristina Ciocan 		.name	= (n),	\
137c8f5c4c7SCristina Ciocan 		.func	= (f),	\
138c8f5c4c7SCristina Ciocan 	}
139c8f5c4c7SCristina Ciocan #define MIXED_FUNC(n, f)		\
140c8f5c4c7SCristina Ciocan 	{				\
141c8f5c4c7SCristina Ciocan 		.name		= (n),	\
142c8f5c4c7SCristina Ciocan 		.func_values	= (f),	\
143c8f5c4c7SCristina Ciocan 	}
144c8f5c4c7SCristina Ciocan 
145c8f5c4c7SCristina Ciocan #define PIN_GROUP_SIMPLE(n, p, f)				\
146c8f5c4c7SCristina Ciocan 	{							\
147c8f5c4c7SCristina Ciocan 		.name			= (n),			\
148c8f5c4c7SCristina Ciocan 		.pins			= (p),			\
149c8f5c4c7SCristina Ciocan 		.npins			= ARRAY_SIZE((p)),	\
150c8f5c4c7SCristina Ciocan 		.has_simple_funcs	= 1,			\
151bbccb9c7SAndrew Morton 		{						\
152c8f5c4c7SCristina Ciocan 			.simple_funcs		= (f),		\
153bbccb9c7SAndrew Morton 		},						\
154c8f5c4c7SCristina Ciocan 		.nfuncs			= ARRAY_SIZE((f)),	\
155c8f5c4c7SCristina Ciocan 	}
156c8f5c4c7SCristina Ciocan #define PIN_GROUP_MIXED(n, p, f)				\
157c8f5c4c7SCristina Ciocan 	{							\
158c8f5c4c7SCristina Ciocan 		.name			= (n),			\
159c8f5c4c7SCristina Ciocan 		.pins			= (p),			\
160c8f5c4c7SCristina Ciocan 		.npins			= ARRAY_SIZE((p)),	\
161c8f5c4c7SCristina Ciocan 		.has_simple_funcs	= 0,			\
162bbccb9c7SAndrew Morton 		{						\
163c8f5c4c7SCristina Ciocan 			.mixed_funcs		= (f),		\
164bbccb9c7SAndrew Morton 		},						\
165c8f5c4c7SCristina Ciocan 		.nfuncs			= ARRAY_SIZE((f)),	\
166c8f5c4c7SCristina Ciocan 	}
167c8f5c4c7SCristina Ciocan 
168c8f5c4c7SCristina Ciocan #define FUNCTION(n, g)					\
169c8f5c4c7SCristina Ciocan 	{						\
170c8f5c4c7SCristina Ciocan 		.name		= (n),			\
171c8f5c4c7SCristina Ciocan 		.groups		= (g),			\
172c8f5c4c7SCristina Ciocan 		.ngroups	= ARRAY_SIZE((g)),	\
173c8f5c4c7SCristina Ciocan 	}
174c8f5c4c7SCristina Ciocan 
175c8f5c4c7SCristina Ciocan #define COMMUNITY(p, n, map)		\
176c8f5c4c7SCristina Ciocan 	{				\
177c8f5c4c7SCristina Ciocan 		.pin_base	= (p),	\
178c8f5c4c7SCristina Ciocan 		.npins		= (n),	\
179c8f5c4c7SCristina Ciocan 		.pad_map	= (map),\
180c8f5c4c7SCristina Ciocan 	}
181c8f5c4c7SCristina Ciocan 
182c8f5c4c7SCristina Ciocan struct byt_pinctrl_soc_data {
183c8f5c4c7SCristina Ciocan 	const char *uid;
184c8f5c4c7SCristina Ciocan 	const struct pinctrl_pin_desc *pins;
185c8f5c4c7SCristina Ciocan 	size_t npins;
186c8f5c4c7SCristina Ciocan 	const struct byt_pingroup *groups;
187c8f5c4c7SCristina Ciocan 	size_t ngroups;
188c8f5c4c7SCristina Ciocan 	const struct byt_function *functions;
189c8f5c4c7SCristina Ciocan 	size_t nfunctions;
190c8f5c4c7SCristina Ciocan 	const struct byt_community *communities;
191c8f5c4c7SCristina Ciocan 	size_t ncommunities;
192c8f5c4c7SCristina Ciocan };
193c8f5c4c7SCristina Ciocan 
19471e6ca61SCristina Ciocan struct byt_gpio {
19571e6ca61SCristina Ciocan 	struct gpio_chip chip;
19671e6ca61SCristina Ciocan 	struct platform_device *pdev;
19771e6ca61SCristina Ciocan 	struct pinctrl_dev *pctl_dev;
19871e6ca61SCristina Ciocan 	struct pinctrl_desc pctl_desc;
19971e6ca61SCristina Ciocan 	raw_spinlock_t lock;
20071e6ca61SCristina Ciocan 	const struct byt_pinctrl_soc_data *soc_data;
20171e6ca61SCristina Ciocan 	struct byt_community *communities_copy;
20271e6ca61SCristina Ciocan 	struct byt_gpio_pin_context *saved_context;
20371e6ca61SCristina Ciocan };
20471e6ca61SCristina Ciocan 
205c8f5c4c7SCristina Ciocan /* SCORE pins, aka GPIOC_<pin_no> or GPIO_S0_SC[<pin_no>] */
206c8f5c4c7SCristina Ciocan static const struct pinctrl_pin_desc byt_score_pins[] = {
207c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(0, "SATA_GP0"),
208c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(1, "SATA_GP1"),
209c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(2, "SATA_LED#"),
210c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(3, "PCIE_CLKREQ0"),
211c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(4, "PCIE_CLKREQ1"),
212c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(5, "PCIE_CLKREQ2"),
213c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(6, "PCIE_CLKREQ3"),
214c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(7, "SD3_WP"),
215c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(8, "HDA_RST"),
216c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(9, "HDA_SYNC"),
217c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(10, "HDA_CLK"),
218c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(11, "HDA_SDO"),
219c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(12, "HDA_SDI0"),
220c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(13, "HDA_SDI1"),
221c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(14, "GPIO_S0_SC14"),
222c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(15, "GPIO_S0_SC15"),
223c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(16, "MMC1_CLK"),
224c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(17, "MMC1_D0"),
225c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(18, "MMC1_D1"),
226c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(19, "MMC1_D2"),
227c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(20, "MMC1_D3"),
228c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(21, "MMC1_D4"),
229c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(22, "MMC1_D5"),
230c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(23, "MMC1_D6"),
231c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(24, "MMC1_D7"),
232c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(25, "MMC1_CMD"),
233c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(26, "MMC1_RST"),
234c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(27, "SD2_CLK"),
235c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(28, "SD2_D0"),
236c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(29, "SD2_D1"),
237c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(30, "SD2_D2"),
238c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(31, "SD2_D3_CD"),
239c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(32, "SD2_CMD"),
240c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(33, "SD3_CLK"),
241c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(34, "SD3_D0"),
242c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(35, "SD3_D1"),
243c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(36, "SD3_D2"),
244c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(37, "SD3_D3"),
245c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(38, "SD3_CD"),
246c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(39, "SD3_CMD"),
247c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(40, "SD3_1P8EN"),
248c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(41, "SD3_PWREN#"),
249c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(42, "ILB_LPC_AD0"),
250c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(43, "ILB_LPC_AD1"),
251c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(44, "ILB_LPC_AD2"),
252c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(45, "ILB_LPC_AD3"),
253c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(46, "ILB_LPC_FRAME"),
254c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(47, "ILB_LPC_CLK0"),
255c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(48, "ILB_LPC_CLK1"),
256c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(49, "ILB_LPC_CLKRUN"),
257c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(50, "ILB_LPC_SERIRQ"),
258c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(51, "PCU_SMB_DATA"),
259c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(52, "PCU_SMB_CLK"),
260c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(53, "PCU_SMB_ALERT"),
261c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(54, "ILB_8254_SPKR"),
262c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(55, "GPIO_S0_SC55"),
263c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(56, "GPIO_S0_SC56"),
264c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(57, "GPIO_S0_SC57"),
265c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(58, "GPIO_S0_SC58"),
266c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(59, "GPIO_S0_SC59"),
267c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(60, "GPIO_S0_SC60"),
268c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(61, "GPIO_S0_SC61"),
269c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(62, "LPE_I2S2_CLK"),
270c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(63, "LPE_I2S2_FRM"),
271c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(64, "LPE_I2S2_DATAIN"),
272c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(65, "LPE_I2S2_DATAOUT"),
273c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(66, "SIO_SPI_CS"),
274c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(67, "SIO_SPI_MISO"),
275c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(68, "SIO_SPI_MOSI"),
276c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(69, "SIO_SPI_CLK"),
277c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(70, "SIO_UART1_RXD"),
278c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(71, "SIO_UART1_TXD"),
279c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(72, "SIO_UART1_RTS"),
280c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(73, "SIO_UART1_CTS"),
281c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(74, "SIO_UART2_RXD"),
282c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(75, "SIO_UART2_TXD"),
283c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(76, "SIO_UART2_RTS"),
284c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(77, "SIO_UART2_CTS"),
285c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(78, "SIO_I2C0_DATA"),
286c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(79, "SIO_I2C0_CLK"),
287c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(80, "SIO_I2C1_DATA"),
288c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(81, "SIO_I2C1_CLK"),
289c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(82, "SIO_I2C2_DATA"),
290c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(83, "SIO_I2C2_CLK"),
291c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(84, "SIO_I2C3_DATA"),
292c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(85, "SIO_I2C3_CLK"),
293c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(86, "SIO_I2C4_DATA"),
294c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(87, "SIO_I2C4_CLK"),
295c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(88, "SIO_I2C5_DATA"),
296c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(89, "SIO_I2C5_CLK"),
297c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(90, "SIO_I2C6_DATA"),
298c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(91, "SIO_I2C6_CLK"),
299c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(92, "GPIO_S0_SC92"),
300c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(93, "GPIO_S0_SC93"),
301c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(94, "SIO_PWM0"),
302c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(95, "SIO_PWM1"),
303c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(96, "PMC_PLT_CLK0"),
304c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(97, "PMC_PLT_CLK1"),
305c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(98, "PMC_PLT_CLK2"),
306c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(99, "PMC_PLT_CLK3"),
307c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(100, "PMC_PLT_CLK4"),
308c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(101, "PMC_PLT_CLK5"),
309c8f5c4c7SCristina Ciocan };
3105fae8b86SMika Westerberg 
311c8f5c4c7SCristina Ciocan static const unsigned int byt_score_pins_map[BYT_NGPIO_SCORE] = {
312c8f5c4c7SCristina Ciocan 	85, 89, 93, 96, 99, 102, 98, 101, 34, 37,
313c8f5c4c7SCristina Ciocan 	36, 38, 39, 35, 40, 84, 62, 61, 64, 59,
314c8f5c4c7SCristina Ciocan 	54, 56, 60, 55, 63, 57, 51, 50, 53, 47,
315c8f5c4c7SCristina Ciocan 	52, 49, 48, 43, 46, 41, 45, 42, 58, 44,
316c8f5c4c7SCristina Ciocan 	95, 105, 70, 68, 67, 66, 69, 71, 65, 72,
317c8f5c4c7SCristina Ciocan 	86, 90, 88, 92, 103, 77, 79, 83, 78, 81,
318c8f5c4c7SCristina Ciocan 	80, 82, 13, 12, 15, 14, 17, 18, 19, 16,
319c8f5c4c7SCristina Ciocan 	2, 1, 0, 4, 6, 7, 9, 8, 33, 32,
320c8f5c4c7SCristina Ciocan 	31, 30, 29, 27, 25, 28, 26, 23, 21, 20,
321c8f5c4c7SCristina Ciocan 	24, 22, 5, 3, 10, 11, 106, 87, 91, 104,
322c8f5c4c7SCristina Ciocan 	97, 100,
3235fae8b86SMika Westerberg };
3245fae8b86SMika Westerberg 
325c8f5c4c7SCristina Ciocan /* SCORE groups */
326c8f5c4c7SCristina Ciocan static const unsigned int byt_score_uart1_pins[] = { 70, 71, 72, 73 };
327c8f5c4c7SCristina Ciocan static const unsigned int byt_score_uart2_pins[] = { 74, 75, 76, 77 };
328c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_score_uart_mux[] = {
329c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("uart", 1),
330c8f5c4c7SCristina Ciocan };
331c8f5c4c7SCristina Ciocan 
332c8f5c4c7SCristina Ciocan static const unsigned int byt_score_pwm0_pins[] = { 94 };
333c8f5c4c7SCristina Ciocan static const unsigned int byt_score_pwm1_pins[] = { 95 };
334c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_score_pwm_mux[] = {
335c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("pwm", 1),
336c8f5c4c7SCristina Ciocan };
337c8f5c4c7SCristina Ciocan 
338c8f5c4c7SCristina Ciocan static const unsigned int byt_score_sio_spi_pins[] = { 66, 67, 68, 69 };
339c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_score_spi_mux[] = {
340c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("spi", 1),
341c8f5c4c7SCristina Ciocan };
342c8f5c4c7SCristina Ciocan 
343c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c5_pins[] = { 88, 89 };
344c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c6_pins[] = { 90, 91 };
345c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c4_pins[] = { 86, 87 };
346c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c3_pins[] = { 84, 85 };
347c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c2_pins[] = { 82, 83 };
348c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c1_pins[] = { 80, 81 };
349c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c0_pins[] = { 78, 79 };
350c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_score_i2c_mux[] = {
351c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("i2c", 1),
352c8f5c4c7SCristina Ciocan };
353c8f5c4c7SCristina Ciocan 
354c8f5c4c7SCristina Ciocan static const unsigned int byt_score_ssp0_pins[] = { 8, 9, 10, 11 };
355c8f5c4c7SCristina Ciocan static const unsigned int byt_score_ssp1_pins[] = { 12, 13, 14, 15 };
356c8f5c4c7SCristina Ciocan static const unsigned int byt_score_ssp2_pins[] = { 62, 63, 64, 65 };
357c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_score_ssp_mux[] = {
358c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("ssp", 1),
359c8f5c4c7SCristina Ciocan };
360c8f5c4c7SCristina Ciocan 
361c8f5c4c7SCristina Ciocan static const unsigned int byt_score_sdcard_pins[] = {
362c8f5c4c7SCristina Ciocan 	7, 33, 34, 35, 36, 37, 38, 39, 40, 41,
363c8f5c4c7SCristina Ciocan };
364c8f5c4c7SCristina Ciocan static const unsigned short byt_score_sdcard_mux_values[] = {
365c8f5c4c7SCristina Ciocan 	2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
366c8f5c4c7SCristina Ciocan };
367c8f5c4c7SCristina Ciocan static const struct byt_mixed_func_mux byt_score_sdcard_mux[] = {
368c8f5c4c7SCristina Ciocan 	MIXED_FUNC("sdcard", byt_score_sdcard_mux_values),
369c8f5c4c7SCristina Ciocan };
370c8f5c4c7SCristina Ciocan 
371c8f5c4c7SCristina Ciocan static const unsigned int byt_score_sdio_pins[] = { 27, 28, 29, 30, 31, 32 };
372c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_score_sdio_mux[] = {
373c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("sdio", 1),
374c8f5c4c7SCristina Ciocan };
375c8f5c4c7SCristina Ciocan 
376c8f5c4c7SCristina Ciocan static const unsigned int byt_score_emmc_pins[] = {
377c8f5c4c7SCristina Ciocan 	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
378c8f5c4c7SCristina Ciocan };
379c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_score_emmc_mux[] = {
380c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("emmc", 1),
381c8f5c4c7SCristina Ciocan };
382c8f5c4c7SCristina Ciocan 
383c8f5c4c7SCristina Ciocan static const unsigned int byt_score_ilb_lpc_pins[] = {
384c8f5c4c7SCristina Ciocan 	42, 43, 44, 45, 46, 47, 48, 49, 50,
385c8f5c4c7SCristina Ciocan };
386c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_score_lpc_mux[] = {
387c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("lpc", 1),
388c8f5c4c7SCristina Ciocan };
389c8f5c4c7SCristina Ciocan 
390c8f5c4c7SCristina Ciocan static const unsigned int byt_score_sata_pins[] = { 0, 1, 2 };
391c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_score_sata_mux[] = {
392c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("sata", 1),
393c8f5c4c7SCristina Ciocan };
394c8f5c4c7SCristina Ciocan 
395c8f5c4c7SCristina Ciocan static const unsigned int byt_score_plt_clk0_pins[] = { 96 };
396c8f5c4c7SCristina Ciocan static const unsigned int byt_score_plt_clk1_pins[] = { 97 };
397c8f5c4c7SCristina Ciocan static const unsigned int byt_score_plt_clk2_pins[] = { 98 };
398b41aa4f8SCristina Ciocan static const unsigned int byt_score_plt_clk3_pins[] = { 99 };
399b41aa4f8SCristina Ciocan static const unsigned int byt_score_plt_clk4_pins[] = { 100 };
400b41aa4f8SCristina Ciocan static const unsigned int byt_score_plt_clk5_pins[] = { 101 };
401c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_score_plt_clk_mux[] = {
402c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("plt_clk", 1),
403c8f5c4c7SCristina Ciocan };
404c8f5c4c7SCristina Ciocan 
405c8f5c4c7SCristina Ciocan static const unsigned int byt_score_smbus_pins[] = { 51, 52, 53 };
406c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_score_smbus_mux[] = {
407c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("smbus", 1),
408c8f5c4c7SCristina Ciocan };
409c8f5c4c7SCristina Ciocan 
410c8f5c4c7SCristina Ciocan static const struct byt_pingroup byt_score_groups[] = {
411c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("uart1_grp",
412c8f5c4c7SCristina Ciocan 			 byt_score_uart1_pins, byt_score_uart_mux),
413c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("uart2_grp",
414c8f5c4c7SCristina Ciocan 			 byt_score_uart2_pins, byt_score_uart_mux),
415c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("pwm0_grp",
416c8f5c4c7SCristina Ciocan 			 byt_score_pwm0_pins, byt_score_pwm_mux),
417c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("pwm1_grp",
418c8f5c4c7SCristina Ciocan 			 byt_score_pwm1_pins, byt_score_pwm_mux),
419c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("ssp2_grp",
420c8f5c4c7SCristina Ciocan 			 byt_score_ssp2_pins, byt_score_pwm_mux),
421c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("sio_spi_grp",
422c8f5c4c7SCristina Ciocan 			 byt_score_sio_spi_pins, byt_score_spi_mux),
423c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("i2c5_grp",
424c8f5c4c7SCristina Ciocan 			 byt_score_i2c5_pins, byt_score_i2c_mux),
425c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("i2c6_grp",
426c8f5c4c7SCristina Ciocan 			 byt_score_i2c6_pins, byt_score_i2c_mux),
427c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("i2c4_grp",
428c8f5c4c7SCristina Ciocan 			 byt_score_i2c4_pins, byt_score_i2c_mux),
429c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("i2c3_grp",
430c8f5c4c7SCristina Ciocan 			 byt_score_i2c3_pins, byt_score_i2c_mux),
431c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("i2c2_grp",
432c8f5c4c7SCristina Ciocan 			 byt_score_i2c2_pins, byt_score_i2c_mux),
433c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("i2c1_grp",
434c8f5c4c7SCristina Ciocan 			 byt_score_i2c1_pins, byt_score_i2c_mux),
435c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("i2c0_grp",
436c8f5c4c7SCristina Ciocan 			 byt_score_i2c0_pins, byt_score_i2c_mux),
437c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("ssp0_grp",
438c8f5c4c7SCristina Ciocan 			 byt_score_ssp0_pins, byt_score_ssp_mux),
439c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("ssp1_grp",
440c8f5c4c7SCristina Ciocan 			 byt_score_ssp1_pins, byt_score_ssp_mux),
441c8f5c4c7SCristina Ciocan 	PIN_GROUP_MIXED("sdcard_grp",
442c8f5c4c7SCristina Ciocan 			byt_score_sdcard_pins, byt_score_sdcard_mux),
443c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("sdio_grp",
444c8f5c4c7SCristina Ciocan 			 byt_score_sdio_pins, byt_score_sdio_mux),
445c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("emmc_grp",
446c8f5c4c7SCristina Ciocan 			 byt_score_emmc_pins, byt_score_emmc_mux),
447c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("lpc_grp",
448c8f5c4c7SCristina Ciocan 			 byt_score_ilb_lpc_pins, byt_score_lpc_mux),
449c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("sata_grp",
450c8f5c4c7SCristina Ciocan 			 byt_score_sata_pins, byt_score_sata_mux),
451c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("plt_clk0_grp",
452c8f5c4c7SCristina Ciocan 			 byt_score_plt_clk0_pins, byt_score_plt_clk_mux),
453c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("plt_clk1_grp",
454c8f5c4c7SCristina Ciocan 			 byt_score_plt_clk1_pins, byt_score_plt_clk_mux),
455c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("plt_clk2_grp",
456c8f5c4c7SCristina Ciocan 			 byt_score_plt_clk2_pins, byt_score_plt_clk_mux),
457c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("plt_clk3_grp",
458c8f5c4c7SCristina Ciocan 			 byt_score_plt_clk3_pins, byt_score_plt_clk_mux),
459c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("plt_clk4_grp",
460c8f5c4c7SCristina Ciocan 			 byt_score_plt_clk4_pins, byt_score_plt_clk_mux),
461c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("plt_clk5_grp",
462c8f5c4c7SCristina Ciocan 			 byt_score_plt_clk5_pins, byt_score_plt_clk_mux),
463c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("smbus_grp",
464c8f5c4c7SCristina Ciocan 			 byt_score_smbus_pins, byt_score_smbus_mux),
465c8f5c4c7SCristina Ciocan };
466c8f5c4c7SCristina Ciocan 
467c8f5c4c7SCristina Ciocan static const char * const byt_score_uart_groups[] = {
468c8f5c4c7SCristina Ciocan 	"uart1_grp", "uart2_grp",
469c8f5c4c7SCristina Ciocan };
470c8f5c4c7SCristina Ciocan static const char * const byt_score_pwm_groups[] = {
471c8f5c4c7SCristina Ciocan 	"pwm0_grp", "pwm1_grp",
472c8f5c4c7SCristina Ciocan };
473c8f5c4c7SCristina Ciocan static const char * const byt_score_ssp_groups[] = {
474c8f5c4c7SCristina Ciocan 	"ssp0_grp", "ssp1_grp", "ssp2_grp",
475c8f5c4c7SCristina Ciocan };
476c8f5c4c7SCristina Ciocan static const char * const byt_score_spi_groups[] = { "sio_spi_grp" };
477c8f5c4c7SCristina Ciocan static const char * const byt_score_i2c_groups[] = {
478c8f5c4c7SCristina Ciocan 	"i2c0_grp", "i2c1_grp", "i2c2_grp", "i2c3_grp", "i2c4_grp", "i2c5_grp",
479c8f5c4c7SCristina Ciocan 	"i2c6_grp",
480c8f5c4c7SCristina Ciocan };
481c8f5c4c7SCristina Ciocan static const char * const byt_score_sdcard_groups[] = { "sdcard_grp" };
482c8f5c4c7SCristina Ciocan static const char * const byt_score_sdio_groups[] = { "sdio_grp" };
483c8f5c4c7SCristina Ciocan static const char * const byt_score_emmc_groups[] = { "emmc_grp" };
484c8f5c4c7SCristina Ciocan static const char * const byt_score_lpc_groups[] = { "lpc_grp" };
485c8f5c4c7SCristina Ciocan static const char * const byt_score_sata_groups[] = { "sata_grp" };
486c8f5c4c7SCristina Ciocan static const char * const byt_score_plt_clk_groups[] = {
487c8f5c4c7SCristina Ciocan 	"plt_clk0_grp", "plt_clk1_grp", "plt_clk2_grp", "plt_clk3_grp",
488c8f5c4c7SCristina Ciocan 	"plt_clk4_grp", "plt_clk5_grp",
489c8f5c4c7SCristina Ciocan };
490c8f5c4c7SCristina Ciocan static const char * const byt_score_smbus_groups[] = { "smbus_grp" };
491c8f5c4c7SCristina Ciocan static const char * const byt_score_gpio_groups[] = {
492c8f5c4c7SCristina Ciocan 	"uart1_grp", "uart2_grp", "pwm0_grp", "pwm1_grp", "ssp0_grp",
493c8f5c4c7SCristina Ciocan 	"ssp1_grp", "ssp2_grp", "sio_spi_grp", "i2c0_grp", "i2c1_grp",
494c8f5c4c7SCristina Ciocan 	"i2c2_grp", "i2c3_grp", "i2c4_grp", "i2c5_grp", "i2c6_grp",
495c8f5c4c7SCristina Ciocan 	"sdcard_grp", "sdio_grp", "emmc_grp", "lpc_grp", "sata_grp",
496c8f5c4c7SCristina Ciocan 	"plt_clk0_grp", "plt_clk1_grp", "plt_clk2_grp", "plt_clk3_grp",
497c8f5c4c7SCristina Ciocan 	"plt_clk4_grp", "plt_clk5_grp", "smbus_grp",
498c8f5c4c7SCristina Ciocan 
499c8f5c4c7SCristina Ciocan };
500c8f5c4c7SCristina Ciocan 
501c8f5c4c7SCristina Ciocan static const struct byt_function byt_score_functions[] = {
502c8f5c4c7SCristina Ciocan 	FUNCTION("uart", byt_score_uart_groups),
503c8f5c4c7SCristina Ciocan 	FUNCTION("pwm", byt_score_pwm_groups),
504c8f5c4c7SCristina Ciocan 	FUNCTION("ssp", byt_score_ssp_groups),
505c8f5c4c7SCristina Ciocan 	FUNCTION("spi", byt_score_spi_groups),
506c8f5c4c7SCristina Ciocan 	FUNCTION("i2c", byt_score_i2c_groups),
507c8f5c4c7SCristina Ciocan 	FUNCTION("sdcard", byt_score_sdcard_groups),
508c8f5c4c7SCristina Ciocan 	FUNCTION("sdio", byt_score_sdio_groups),
509c8f5c4c7SCristina Ciocan 	FUNCTION("emmc", byt_score_emmc_groups),
510c8f5c4c7SCristina Ciocan 	FUNCTION("lpc", byt_score_lpc_groups),
511c8f5c4c7SCristina Ciocan 	FUNCTION("sata", byt_score_sata_groups),
512c8f5c4c7SCristina Ciocan 	FUNCTION("plt_clk", byt_score_plt_clk_groups),
513c8f5c4c7SCristina Ciocan 	FUNCTION("smbus", byt_score_smbus_groups),
514c8f5c4c7SCristina Ciocan 	FUNCTION("gpio", byt_score_gpio_groups),
515c8f5c4c7SCristina Ciocan };
516c8f5c4c7SCristina Ciocan 
517c8f5c4c7SCristina Ciocan static const struct byt_community byt_score_communities[] = {
518c8f5c4c7SCristina Ciocan 	COMMUNITY(0, BYT_NGPIO_SCORE, byt_score_pins_map),
519c8f5c4c7SCristina Ciocan };
520c8f5c4c7SCristina Ciocan 
521c8f5c4c7SCristina Ciocan static const struct byt_pinctrl_soc_data byt_score_soc_data = {
522c8f5c4c7SCristina Ciocan 	.uid		= BYT_SCORE_ACPI_UID,
523c8f5c4c7SCristina Ciocan 	.pins		= byt_score_pins,
524c8f5c4c7SCristina Ciocan 	.npins		= ARRAY_SIZE(byt_score_pins),
525c8f5c4c7SCristina Ciocan 	.groups		= byt_score_groups,
526c8f5c4c7SCristina Ciocan 	.ngroups	= ARRAY_SIZE(byt_score_groups),
527c8f5c4c7SCristina Ciocan 	.functions	= byt_score_functions,
528c8f5c4c7SCristina Ciocan 	.nfunctions	= ARRAY_SIZE(byt_score_functions),
529c8f5c4c7SCristina Ciocan 	.communities	= byt_score_communities,
530c8f5c4c7SCristina Ciocan 	.ncommunities	= ARRAY_SIZE(byt_score_communities),
531c8f5c4c7SCristina Ciocan };
532c8f5c4c7SCristina Ciocan 
533c8f5c4c7SCristina Ciocan /* SUS pins, aka GPIOS_<pin_no> or GPIO_S5[<pin_no>]  */
534c8f5c4c7SCristina Ciocan static const struct pinctrl_pin_desc byt_sus_pins[] = {
535c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(0, "GPIO_S50"),
536c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(1, "GPIO_S51"),
537c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(2, "GPIO_S52"),
538c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(3, "GPIO_S53"),
539c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(4, "GPIO_S54"),
540c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(5, "GPIO_S55"),
541c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(6, "GPIO_S56"),
542c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(7, "GPIO_S57"),
543c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(8, "GPIO_S58"),
544c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(9, "GPIO_S59"),
545c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(10, "GPIO_S510"),
546c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(11, "PMC_SUSPWRDNACK"),
547c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(12, "PMC_SUSCLK0"),
548c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(13, "GPIO_S513"),
549c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(14, "USB_ULPI_RST"),
550c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(15, "PMC_WAKE_PCIE0#"),
551c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(16, "PMC_PWRBTN"),
552c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(17, "GPIO_S517"),
553c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(18, "PMC_SUS_STAT"),
554c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(19, "USB_OC0"),
555c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(20, "USB_OC1"),
556c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(21, "PCU_SPI_CS1"),
557c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(22, "GPIO_S522"),
558c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(23, "GPIO_S523"),
559c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(24, "GPIO_S524"),
560c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(25, "GPIO_S525"),
561c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(26, "GPIO_S526"),
562c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(27, "GPIO_S527"),
563c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(28, "GPIO_S528"),
564c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(29, "GPIO_S529"),
565c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(30, "GPIO_S530"),
566c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(31, "USB_ULPI_CLK"),
567c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(32, "USB_ULPI_DATA0"),
568c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(33, "USB_ULPI_DATA1"),
569c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(34, "USB_ULPI_DATA2"),
570c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(35, "USB_ULPI_DATA3"),
571c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(36, "USB_ULPI_DATA4"),
572c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(37, "USB_ULPI_DATA5"),
573c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(38, "USB_ULPI_DATA6"),
574c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(39, "USB_ULPI_DATA7"),
575c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(40, "USB_ULPI_DIR"),
576c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(41, "USB_ULPI_NXT"),
577c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(42, "USB_ULPI_STP"),
578c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(43, "USB_ULPI_REFCLK"),
579c8f5c4c7SCristina Ciocan };
580c8f5c4c7SCristina Ciocan 
581c8f5c4c7SCristina Ciocan static const unsigned int byt_sus_pins_map[BYT_NGPIO_SUS] = {
582c8f5c4c7SCristina Ciocan 	29, 33, 30, 31, 32, 34, 36, 35, 38, 37,
583c8f5c4c7SCristina Ciocan 	18, 7, 11, 20, 17, 1, 8, 10, 19, 12,
584c8f5c4c7SCristina Ciocan 	0, 2, 23, 39, 28, 27, 22, 21, 24, 25,
585c8f5c4c7SCristina Ciocan 	26, 51, 56, 54, 49, 55, 48, 57, 50, 58,
586c8f5c4c7SCristina Ciocan 	52, 53, 59, 40,
587c8f5c4c7SCristina Ciocan };
588c8f5c4c7SCristina Ciocan 
589c8f5c4c7SCristina Ciocan static const unsigned int byt_sus_usb_over_current_pins[] = { 19, 20 };
590c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_sus_usb_oc_mux[] = {
591c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("usb", 0),
592c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("gpio", 1),
593c8f5c4c7SCristina Ciocan };
594c8f5c4c7SCristina Ciocan 
595c8f5c4c7SCristina Ciocan static const unsigned int byt_sus_usb_ulpi_pins[] = {
596c8f5c4c7SCristina Ciocan 	14, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
597c8f5c4c7SCristina Ciocan };
598c8f5c4c7SCristina Ciocan static const unsigned short byt_sus_usb_ulpi_mode_values[] = {
599c8f5c4c7SCristina Ciocan 	2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
600c8f5c4c7SCristina Ciocan };
601c8f5c4c7SCristina Ciocan static const unsigned short byt_sus_usb_ulpi_gpio_mode_values[] = {
602c8f5c4c7SCristina Ciocan 	1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
603c8f5c4c7SCristina Ciocan };
604c8f5c4c7SCristina Ciocan static const struct byt_mixed_func_mux byt_sus_usb_ulpi_mux[] = {
605c8f5c4c7SCristina Ciocan 	MIXED_FUNC("usb", byt_sus_usb_ulpi_mode_values),
606c8f5c4c7SCristina Ciocan 	MIXED_FUNC("gpio", byt_sus_usb_ulpi_gpio_mode_values),
607c8f5c4c7SCristina Ciocan };
608c8f5c4c7SCristina Ciocan 
609c8f5c4c7SCristina Ciocan static const unsigned int byt_sus_pcu_spi_pins[] = { 21 };
610c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_sus_pcu_spi_mux[] = {
611c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("spi", 0),
612c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("gpio", 1),
613c8f5c4c7SCristina Ciocan };
614c8f5c4c7SCristina Ciocan 
615c8f5c4c7SCristina Ciocan static const struct byt_pingroup byt_sus_groups[] = {
616c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("usb_oc_grp",
617c8f5c4c7SCristina Ciocan 			byt_sus_usb_over_current_pins, byt_sus_usb_oc_mux),
618c8f5c4c7SCristina Ciocan 	PIN_GROUP_MIXED("usb_ulpi_grp",
619c8f5c4c7SCristina Ciocan 			byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_mux),
620c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("pcu_spi_grp",
621c8f5c4c7SCristina Ciocan 			byt_sus_pcu_spi_pins, byt_sus_pcu_spi_mux),
622c8f5c4c7SCristina Ciocan };
623c8f5c4c7SCristina Ciocan 
624c8f5c4c7SCristina Ciocan static const char * const byt_sus_usb_groups[] = {
625c8f5c4c7SCristina Ciocan 	"usb_oc_grp", "usb_ulpi_grp",
626c8f5c4c7SCristina Ciocan };
627c8f5c4c7SCristina Ciocan static const char * const byt_sus_spi_groups[] = { "pcu_spi_grp" };
628c8f5c4c7SCristina Ciocan static const char * const byt_sus_gpio_groups[] = {
629c8f5c4c7SCristina Ciocan 	"usb_oc_grp", "usb_ulpi_grp", "pcu_spi_grp",
630c8f5c4c7SCristina Ciocan };
631c8f5c4c7SCristina Ciocan 
632c8f5c4c7SCristina Ciocan static const struct byt_function byt_sus_functions[] = {
633c8f5c4c7SCristina Ciocan 	FUNCTION("usb", byt_sus_usb_groups),
634c8f5c4c7SCristina Ciocan 	FUNCTION("spi", byt_sus_spi_groups),
635c8f5c4c7SCristina Ciocan 	FUNCTION("gpio", byt_sus_gpio_groups),
636c8f5c4c7SCristina Ciocan };
637c8f5c4c7SCristina Ciocan 
638c8f5c4c7SCristina Ciocan static const struct byt_community byt_sus_communities[] = {
639c8f5c4c7SCristina Ciocan 	COMMUNITY(0, BYT_NGPIO_SUS, byt_sus_pins_map),
640c8f5c4c7SCristina Ciocan };
641c8f5c4c7SCristina Ciocan 
642c8f5c4c7SCristina Ciocan static const struct byt_pinctrl_soc_data byt_sus_soc_data = {
643c8f5c4c7SCristina Ciocan 	.uid		= BYT_SUS_ACPI_UID,
644c8f5c4c7SCristina Ciocan 	.pins		= byt_sus_pins,
645c8f5c4c7SCristina Ciocan 	.npins		= ARRAY_SIZE(byt_sus_pins),
646c8f5c4c7SCristina Ciocan 	.groups		= byt_sus_groups,
647c8f5c4c7SCristina Ciocan 	.ngroups	= ARRAY_SIZE(byt_sus_groups),
648c8f5c4c7SCristina Ciocan 	.functions	= byt_sus_functions,
649c8f5c4c7SCristina Ciocan 	.nfunctions	= ARRAY_SIZE(byt_sus_functions),
650c8f5c4c7SCristina Ciocan 	.communities	= byt_sus_communities,
651c8f5c4c7SCristina Ciocan 	.ncommunities	= ARRAY_SIZE(byt_sus_communities),
652c8f5c4c7SCristina Ciocan };
653c8f5c4c7SCristina Ciocan 
654c8f5c4c7SCristina Ciocan static const struct pinctrl_pin_desc byt_ncore_pins[] = {
655c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(0, "GPIO_NCORE0"),
656c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(1, "GPIO_NCORE1"),
657c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(2, "GPIO_NCORE2"),
658c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(3, "GPIO_NCORE3"),
659c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(4, "GPIO_NCORE4"),
660c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(5, "GPIO_NCORE5"),
661c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(6, "GPIO_NCORE6"),
662c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(7, "GPIO_NCORE7"),
663c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(8, "GPIO_NCORE8"),
664c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(9, "GPIO_NCORE9"),
665c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(10, "GPIO_NCORE10"),
666c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(11, "GPIO_NCORE11"),
667c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(12, "GPIO_NCORE12"),
668c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(13, "GPIO_NCORE13"),
669c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(14, "GPIO_NCORE14"),
670c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(15, "GPIO_NCORE15"),
671c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(16, "GPIO_NCORE16"),
672c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(17, "GPIO_NCORE17"),
673c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(18, "GPIO_NCORE18"),
674c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(19, "GPIO_NCORE19"),
675c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(20, "GPIO_NCORE20"),
676c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(21, "GPIO_NCORE21"),
677c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(22, "GPIO_NCORE22"),
678c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(23, "GPIO_NCORE23"),
679c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(24, "GPIO_NCORE24"),
680c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(25, "GPIO_NCORE25"),
681c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(26, "GPIO_NCORE26"),
682c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(27, "GPIO_NCORE27"),
683c8f5c4c7SCristina Ciocan };
684c8f5c4c7SCristina Ciocan 
685c8f5c4c7SCristina Ciocan static unsigned const byt_ncore_pins_map[BYT_NGPIO_NCORE] = {
686c8f5c4c7SCristina Ciocan 	19, 18, 17, 20, 21, 22, 24, 25, 23, 16,
687c8f5c4c7SCristina Ciocan 	14, 15, 12, 26, 27, 1, 4, 8, 11, 0,
688c8f5c4c7SCristina Ciocan 	3, 6, 10, 13, 2, 5, 9, 7,
689c8f5c4c7SCristina Ciocan };
690c8f5c4c7SCristina Ciocan 
691c8f5c4c7SCristina Ciocan static const struct byt_community byt_ncore_communities[] = {
692c8f5c4c7SCristina Ciocan 	COMMUNITY(0, BYT_NGPIO_NCORE, byt_ncore_pins_map),
693c8f5c4c7SCristina Ciocan };
694c8f5c4c7SCristina Ciocan 
695c8f5c4c7SCristina Ciocan static const struct byt_pinctrl_soc_data byt_ncore_soc_data = {
696c8f5c4c7SCristina Ciocan 	.uid		= BYT_NCORE_ACPI_UID,
697c8f5c4c7SCristina Ciocan 	.pins		= byt_ncore_pins,
698c8f5c4c7SCristina Ciocan 	.npins		= ARRAY_SIZE(byt_ncore_pins),
699c8f5c4c7SCristina Ciocan 	.communities	= byt_ncore_communities,
700c8f5c4c7SCristina Ciocan 	.ncommunities	= ARRAY_SIZE(byt_ncore_communities),
701c8f5c4c7SCristina Ciocan };
702c8f5c4c7SCristina Ciocan 
703c8f5c4c7SCristina Ciocan static const struct byt_pinctrl_soc_data *byt_soc_data[] = {
704c8f5c4c7SCristina Ciocan 	&byt_score_soc_data,
705c8f5c4c7SCristina Ciocan 	&byt_sus_soc_data,
706c8f5c4c7SCristina Ciocan 	&byt_ncore_soc_data,
707c8f5c4c7SCristina Ciocan 	NULL,
708c8f5c4c7SCristina Ciocan };
709c8f5c4c7SCristina Ciocan 
710c501d0b1SCristina Ciocan static struct byt_community *byt_get_community(struct byt_gpio *vg,
711c501d0b1SCristina Ciocan 					       unsigned int pin)
712c501d0b1SCristina Ciocan {
713c501d0b1SCristina Ciocan 	struct byt_community *comm;
714c501d0b1SCristina Ciocan 	int i;
715c501d0b1SCristina Ciocan 
716c501d0b1SCristina Ciocan 	for (i = 0; i < vg->soc_data->ncommunities; i++) {
717c501d0b1SCristina Ciocan 		comm = vg->communities_copy + i;
718c501d0b1SCristina Ciocan 		if (pin < comm->pin_base + comm->npins && pin >= comm->pin_base)
719c501d0b1SCristina Ciocan 			return comm;
720c501d0b1SCristina Ciocan 	}
721c501d0b1SCristina Ciocan 
722c501d0b1SCristina Ciocan 	return NULL;
723c501d0b1SCristina Ciocan }
724c501d0b1SCristina Ciocan 
725c501d0b1SCristina Ciocan static void __iomem *byt_gpio_reg(struct byt_gpio *vg, unsigned int offset,
7265fae8b86SMika Westerberg 				  int reg)
7275fae8b86SMika Westerberg {
728c501d0b1SCristina Ciocan 	struct byt_community *comm = byt_get_community(vg, offset);
7291b89970dSAndy Shevchenko 	u32 reg_offset;
7305fae8b86SMika Westerberg 
731c501d0b1SCristina Ciocan 	if (!comm)
732c501d0b1SCristina Ciocan 		return NULL;
733c501d0b1SCristina Ciocan 
734c501d0b1SCristina Ciocan 	offset -= comm->pin_base;
7351b89970dSAndy Shevchenko 	switch (reg) {
7361b89970dSAndy Shevchenko 	case BYT_INT_STAT_REG:
7375fae8b86SMika Westerberg 		reg_offset = (offset / 32) * 4;
7381b89970dSAndy Shevchenko 		break;
7391b89970dSAndy Shevchenko 	case BYT_DEBOUNCE_REG:
7401b89970dSAndy Shevchenko 		reg_offset = 0;
7411b89970dSAndy Shevchenko 		break;
7421b89970dSAndy Shevchenko 	default:
743c501d0b1SCristina Ciocan 		reg_offset = comm->pad_map[offset] * 16;
7441b89970dSAndy Shevchenko 		break;
7451b89970dSAndy Shevchenko 	}
7465fae8b86SMika Westerberg 
747c501d0b1SCristina Ciocan 	return comm->reg_base + reg_offset + reg;
7485fae8b86SMika Westerberg }
7495fae8b86SMika Westerberg 
750c501d0b1SCristina Ciocan static int byt_get_groups_count(struct pinctrl_dev *pctldev)
75195f0972cSMika Westerberg {
752c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
753c501d0b1SCristina Ciocan 
754c501d0b1SCristina Ciocan 	return vg->soc_data->ngroups;
755c501d0b1SCristina Ciocan }
756c501d0b1SCristina Ciocan 
757c501d0b1SCristina Ciocan static const char *byt_get_group_name(struct pinctrl_dev *pctldev,
758c501d0b1SCristina Ciocan 				      unsigned int selector)
759c501d0b1SCristina Ciocan {
760c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
761c501d0b1SCristina Ciocan 
762c501d0b1SCristina Ciocan 	return vg->soc_data->groups[selector].name;
763c501d0b1SCristina Ciocan }
764c501d0b1SCristina Ciocan 
765c501d0b1SCristina Ciocan static int byt_get_group_pins(struct pinctrl_dev *pctldev,
766c501d0b1SCristina Ciocan 			      unsigned int selector,
767c501d0b1SCristina Ciocan 			      const unsigned int **pins,
768c501d0b1SCristina Ciocan 			      unsigned int *num_pins)
769c501d0b1SCristina Ciocan {
770c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
771c501d0b1SCristina Ciocan 
772c501d0b1SCristina Ciocan 	*pins		= vg->soc_data->groups[selector].pins;
773c501d0b1SCristina Ciocan 	*num_pins	= vg->soc_data->groups[selector].npins;
774c501d0b1SCristina Ciocan 
775c501d0b1SCristina Ciocan 	return 0;
776c501d0b1SCristina Ciocan }
777c501d0b1SCristina Ciocan 
778c501d0b1SCristina Ciocan static const struct pinctrl_ops byt_pinctrl_ops = {
779c501d0b1SCristina Ciocan 	.get_groups_count	= byt_get_groups_count,
780c501d0b1SCristina Ciocan 	.get_group_name		= byt_get_group_name,
781c501d0b1SCristina Ciocan 	.get_group_pins		= byt_get_group_pins,
782c501d0b1SCristina Ciocan };
783c501d0b1SCristina Ciocan 
784c501d0b1SCristina Ciocan static int byt_get_functions_count(struct pinctrl_dev *pctldev)
785c501d0b1SCristina Ciocan {
786c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
787c501d0b1SCristina Ciocan 
788c501d0b1SCristina Ciocan 	return vg->soc_data->nfunctions;
789c501d0b1SCristina Ciocan }
790c501d0b1SCristina Ciocan 
791c501d0b1SCristina Ciocan static const char *byt_get_function_name(struct pinctrl_dev *pctldev,
792c501d0b1SCristina Ciocan 					 unsigned int selector)
793c501d0b1SCristina Ciocan {
794c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
795c501d0b1SCristina Ciocan 
796c501d0b1SCristina Ciocan 	return vg->soc_data->functions[selector].name;
797c501d0b1SCristina Ciocan }
798c501d0b1SCristina Ciocan 
799c501d0b1SCristina Ciocan static int byt_get_function_groups(struct pinctrl_dev *pctldev,
800c501d0b1SCristina Ciocan 				   unsigned int selector,
801c501d0b1SCristina Ciocan 				   const char * const **groups,
802c501d0b1SCristina Ciocan 				   unsigned int *num_groups)
803c501d0b1SCristina Ciocan {
804c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
805c501d0b1SCristina Ciocan 
806c501d0b1SCristina Ciocan 	*groups		= vg->soc_data->functions[selector].groups;
807c501d0b1SCristina Ciocan 	*num_groups	= vg->soc_data->functions[selector].ngroups;
808c501d0b1SCristina Ciocan 
809c501d0b1SCristina Ciocan 	return 0;
810c501d0b1SCristina Ciocan }
811c501d0b1SCristina Ciocan 
812c501d0b1SCristina Ciocan static int byt_get_group_simple_mux(const struct byt_pingroup group,
813c501d0b1SCristina Ciocan 				    const char *func_name,
814c501d0b1SCristina Ciocan 				    unsigned short *func)
815c501d0b1SCristina Ciocan {
816c501d0b1SCristina Ciocan 	int i;
817c501d0b1SCristina Ciocan 
818c501d0b1SCristina Ciocan 	for (i = 0; i < group.nfuncs; i++) {
819c501d0b1SCristina Ciocan 		if (!strcmp(group.simple_funcs[i].name, func_name)) {
820c501d0b1SCristina Ciocan 			*func = group.simple_funcs[i].func;
821c501d0b1SCristina Ciocan 			return 0;
822c501d0b1SCristina Ciocan 		}
823c501d0b1SCristina Ciocan 	}
824c501d0b1SCristina Ciocan 
825c501d0b1SCristina Ciocan 	return 1;
826c501d0b1SCristina Ciocan }
827c501d0b1SCristina Ciocan 
828c501d0b1SCristina Ciocan static int byt_get_group_mixed_mux(const struct byt_pingroup group,
829c501d0b1SCristina Ciocan 				   const char *func_name,
830c501d0b1SCristina Ciocan 				   const unsigned short **func)
831c501d0b1SCristina Ciocan {
832c501d0b1SCristina Ciocan 	int i;
833c501d0b1SCristina Ciocan 
834c501d0b1SCristina Ciocan 	for (i = 0; i < group.nfuncs; i++) {
835c501d0b1SCristina Ciocan 		if (!strcmp(group.mixed_funcs[i].name, func_name)) {
836c501d0b1SCristina Ciocan 			*func = group.mixed_funcs[i].func_values;
837c501d0b1SCristina Ciocan 			return 0;
838c501d0b1SCristina Ciocan 		}
839c501d0b1SCristina Ciocan 	}
840c501d0b1SCristina Ciocan 
841c501d0b1SCristina Ciocan 	return 1;
842c501d0b1SCristina Ciocan }
843c501d0b1SCristina Ciocan 
844c501d0b1SCristina Ciocan static void byt_set_group_simple_mux(struct byt_gpio *vg,
845c501d0b1SCristina Ciocan 				     const struct byt_pingroup group,
846c501d0b1SCristina Ciocan 				     unsigned short func)
847c501d0b1SCristina Ciocan {
848c501d0b1SCristina Ciocan 	unsigned long flags;
849c501d0b1SCristina Ciocan 	int i;
850c501d0b1SCristina Ciocan 
851c501d0b1SCristina Ciocan 	raw_spin_lock_irqsave(&vg->lock, flags);
852c501d0b1SCristina Ciocan 
853c501d0b1SCristina Ciocan 	for (i = 0; i < group.npins; i++) {
854c501d0b1SCristina Ciocan 		void __iomem *padcfg0;
855c501d0b1SCristina Ciocan 		u32 value;
856c501d0b1SCristina Ciocan 
857c501d0b1SCristina Ciocan 		padcfg0 = byt_gpio_reg(vg, group.pins[i], BYT_CONF0_REG);
858c501d0b1SCristina Ciocan 		if (!padcfg0) {
859c501d0b1SCristina Ciocan 			dev_warn(&vg->pdev->dev,
860c501d0b1SCristina Ciocan 				 "Group %s, pin %i not muxed (no padcfg0)\n",
861c501d0b1SCristina Ciocan 				 group.name, i);
862c501d0b1SCristina Ciocan 			continue;
863c501d0b1SCristina Ciocan 		}
864c501d0b1SCristina Ciocan 
865c501d0b1SCristina Ciocan 		value = readl(padcfg0);
866c501d0b1SCristina Ciocan 		value &= ~BYT_PIN_MUX;
867c501d0b1SCristina Ciocan 		value |= func;
868c501d0b1SCristina Ciocan 		writel(value, padcfg0);
869c501d0b1SCristina Ciocan 	}
870c501d0b1SCristina Ciocan 
871c501d0b1SCristina Ciocan 	raw_spin_unlock_irqrestore(&vg->lock, flags);
872c501d0b1SCristina Ciocan }
873c501d0b1SCristina Ciocan 
874c501d0b1SCristina Ciocan static void byt_set_group_mixed_mux(struct byt_gpio *vg,
875c501d0b1SCristina Ciocan 				    const struct byt_pingroup group,
876c501d0b1SCristina Ciocan 				    const unsigned short *func)
877c501d0b1SCristina Ciocan {
878c501d0b1SCristina Ciocan 	unsigned long flags;
879c501d0b1SCristina Ciocan 	int i;
880c501d0b1SCristina Ciocan 
881c501d0b1SCristina Ciocan 	raw_spin_lock_irqsave(&vg->lock, flags);
882c501d0b1SCristina Ciocan 
883c501d0b1SCristina Ciocan 	for (i = 0; i < group.npins; i++) {
884c501d0b1SCristina Ciocan 		void __iomem *padcfg0;
885c501d0b1SCristina Ciocan 		u32 value;
886c501d0b1SCristina Ciocan 
887c501d0b1SCristina Ciocan 		padcfg0 = byt_gpio_reg(vg, group.pins[i], BYT_CONF0_REG);
888c501d0b1SCristina Ciocan 		if (!padcfg0) {
889c501d0b1SCristina Ciocan 			dev_warn(&vg->pdev->dev,
890c501d0b1SCristina Ciocan 				 "Group %s, pin %i not muxed (no padcfg0)\n",
891c501d0b1SCristina Ciocan 				 group.name, i);
892c501d0b1SCristina Ciocan 			continue;
893c501d0b1SCristina Ciocan 		}
894c501d0b1SCristina Ciocan 
895c501d0b1SCristina Ciocan 		value = readl(padcfg0);
896c501d0b1SCristina Ciocan 		value &= ~BYT_PIN_MUX;
897c501d0b1SCristina Ciocan 		value |= func[i];
898c501d0b1SCristina Ciocan 		writel(value, padcfg0);
899c501d0b1SCristina Ciocan 	}
900c501d0b1SCristina Ciocan 
901c501d0b1SCristina Ciocan 	raw_spin_unlock_irqrestore(&vg->lock, flags);
902c501d0b1SCristina Ciocan }
903c501d0b1SCristina Ciocan 
904c501d0b1SCristina Ciocan static int byt_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
905c501d0b1SCristina Ciocan 		       unsigned int group_selector)
906c501d0b1SCristina Ciocan {
907c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
908c501d0b1SCristina Ciocan 	const struct byt_function func = vg->soc_data->functions[func_selector];
909c501d0b1SCristina Ciocan 	const struct byt_pingroup group = vg->soc_data->groups[group_selector];
910c501d0b1SCristina Ciocan 	const unsigned short *mixed_func;
911c501d0b1SCristina Ciocan 	unsigned short simple_func;
912c501d0b1SCristina Ciocan 	int ret = 1;
913c501d0b1SCristina Ciocan 
914c501d0b1SCristina Ciocan 	if (group.has_simple_funcs)
915c501d0b1SCristina Ciocan 		ret = byt_get_group_simple_mux(group, func.name, &simple_func);
916c501d0b1SCristina Ciocan 	else
917c501d0b1SCristina Ciocan 		ret = byt_get_group_mixed_mux(group, func.name, &mixed_func);
918c501d0b1SCristina Ciocan 
919c501d0b1SCristina Ciocan 	if (ret)
920c501d0b1SCristina Ciocan 		byt_set_group_simple_mux(vg, group, BYT_DEFAULT_GPIO_MUX);
921c501d0b1SCristina Ciocan 	else if (group.has_simple_funcs)
922c501d0b1SCristina Ciocan 		byt_set_group_simple_mux(vg, group, simple_func);
923c501d0b1SCristina Ciocan 	else
924c501d0b1SCristina Ciocan 		byt_set_group_mixed_mux(vg, group, mixed_func);
925c501d0b1SCristina Ciocan 
926c501d0b1SCristina Ciocan 	return 0;
927c501d0b1SCristina Ciocan }
928c501d0b1SCristina Ciocan 
929c501d0b1SCristina Ciocan static u32 byt_get_gpio_mux(struct byt_gpio *vg, unsigned offset)
930c501d0b1SCristina Ciocan {
931c501d0b1SCristina Ciocan 	/* SCORE pin 92-93 */
932c501d0b1SCristina Ciocan 	if (!strcmp(vg->soc_data->uid, BYT_SCORE_ACPI_UID) &&
933c501d0b1SCristina Ciocan 	    offset >= 92 && offset <= 93)
934c501d0b1SCristina Ciocan 		return 1;
935c501d0b1SCristina Ciocan 
936c501d0b1SCristina Ciocan 	/* SUS pin 11-21 */
937c501d0b1SCristina Ciocan 	if (!strcmp(vg->soc_data->uid, BYT_SUS_ACPI_UID) &&
938c501d0b1SCristina Ciocan 	    offset >= 11 && offset <= 21)
939c501d0b1SCristina Ciocan 		return 1;
940c501d0b1SCristina Ciocan 
941c501d0b1SCristina Ciocan 	return 0;
942c501d0b1SCristina Ciocan }
943c501d0b1SCristina Ciocan 
944c501d0b1SCristina Ciocan static void byt_gpio_clear_triggering(struct byt_gpio *vg, unsigned int offset)
945c501d0b1SCristina Ciocan {
946c501d0b1SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
94795f0972cSMika Westerberg 	unsigned long flags;
94895f0972cSMika Westerberg 	u32 value;
94995f0972cSMika Westerberg 
95078e1c896SMika Westerberg 	raw_spin_lock_irqsave(&vg->lock, flags);
95195f0972cSMika Westerberg 	value = readl(reg);
95295f0972cSMika Westerberg 	value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
95395f0972cSMika Westerberg 	writel(value, reg);
95478e1c896SMika Westerberg 	raw_spin_unlock_irqrestore(&vg->lock, flags);
95595f0972cSMika Westerberg }
95695f0972cSMika Westerberg 
957c501d0b1SCristina Ciocan static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev,
958c501d0b1SCristina Ciocan 				   struct pinctrl_gpio_range *range,
959c501d0b1SCristina Ciocan 				   unsigned int offset)
9605fae8b86SMika Westerberg {
961c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
962c501d0b1SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
963f8323b6bSMika Westerberg 	u32 value, gpio_mux;
96439ce8150SMika Westerberg 	unsigned long flags;
96539ce8150SMika Westerberg 
96678e1c896SMika Westerberg 	raw_spin_lock_irqsave(&vg->lock, flags);
9675fae8b86SMika Westerberg 
9685fae8b86SMika Westerberg 	/*
9695fae8b86SMika Westerberg 	 * In most cases, func pin mux 000 means GPIO function.
9705fae8b86SMika Westerberg 	 * But, some pins may have func pin mux 001 represents
971f8323b6bSMika Westerberg 	 * GPIO function.
972f8323b6bSMika Westerberg 	 *
973f8323b6bSMika Westerberg 	 * Because there are devices out there where some pins were not
974f8323b6bSMika Westerberg 	 * configured correctly we allow changing the mux value from
975f8323b6bSMika Westerberg 	 * request (but print out warning about that).
9765fae8b86SMika Westerberg 	 */
9775fae8b86SMika Westerberg 	value = readl(reg) & BYT_PIN_MUX;
978f8323b6bSMika Westerberg 	gpio_mux = byt_get_gpio_mux(vg, offset);
979b5894d12SHans de Goede 	if (gpio_mux != value) {
980f8323b6bSMika Westerberg 		value = readl(reg) & ~BYT_PIN_MUX;
981f8323b6bSMika Westerberg 		value |= gpio_mux;
982f8323b6bSMika Westerberg 		writel(value, reg);
983f8323b6bSMika Westerberg 
984b5894d12SHans de Goede 		dev_warn(&vg->pdev->dev, FW_BUG
985f8323b6bSMika Westerberg 			 "pin %u forcibly re-configured as GPIO\n", offset);
9865fae8b86SMika Westerberg 	}
9875fae8b86SMika Westerberg 
98878e1c896SMika Westerberg 	raw_spin_unlock_irqrestore(&vg->lock, flags);
98939ce8150SMika Westerberg 
9905fae8b86SMika Westerberg 	pm_runtime_get(&vg->pdev->dev);
9915fae8b86SMika Westerberg 
9925fae8b86SMika Westerberg 	return 0;
9935fae8b86SMika Westerberg }
9945fae8b86SMika Westerberg 
995c501d0b1SCristina Ciocan static void byt_gpio_disable_free(struct pinctrl_dev *pctl_dev,
996c501d0b1SCristina Ciocan 				  struct pinctrl_gpio_range *range,
997c501d0b1SCristina Ciocan 				  unsigned int offset)
998c501d0b1SCristina Ciocan {
999c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
1000c501d0b1SCristina Ciocan 
1001c501d0b1SCristina Ciocan 	byt_gpio_clear_triggering(vg, offset);
1002c501d0b1SCristina Ciocan 	pm_runtime_put(&vg->pdev->dev);
1003c501d0b1SCristina Ciocan }
1004c501d0b1SCristina Ciocan 
1005c501d0b1SCristina Ciocan static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
1006c501d0b1SCristina Ciocan 				  struct pinctrl_gpio_range *range,
1007c501d0b1SCristina Ciocan 				  unsigned int offset,
1008c501d0b1SCristina Ciocan 				  bool input)
1009c501d0b1SCristina Ciocan {
1010c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
1011c501d0b1SCristina Ciocan 	void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
1012c501d0b1SCristina Ciocan 	void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
1013c501d0b1SCristina Ciocan 	unsigned long flags;
1014c501d0b1SCristina Ciocan 	u32 value;
1015c501d0b1SCristina Ciocan 
1016c501d0b1SCristina Ciocan 	raw_spin_lock_irqsave(&vg->lock, flags);
1017c501d0b1SCristina Ciocan 
1018c501d0b1SCristina Ciocan 	value = readl(val_reg);
1019c501d0b1SCristina Ciocan 	value &= ~BYT_DIR_MASK;
1020c501d0b1SCristina Ciocan 	if (input)
1021c501d0b1SCristina Ciocan 		value |= BYT_OUTPUT_EN;
1022c501d0b1SCristina Ciocan 	else
1023c501d0b1SCristina Ciocan 		/*
1024c501d0b1SCristina Ciocan 		 * Before making any direction modifications, do a check if gpio
1025c501d0b1SCristina Ciocan 		 * is set for direct IRQ.  On baytrail, setting GPIO to output
1026c501d0b1SCristina Ciocan 		 * does not make sense, so let's at least warn the caller before
1027c501d0b1SCristina Ciocan 		 * they shoot themselves in the foot.
1028c501d0b1SCristina Ciocan 		 */
1029c501d0b1SCristina Ciocan 		WARN(readl(conf_reg) & BYT_DIRECT_IRQ_EN,
1030c501d0b1SCristina Ciocan 		     "Potential Error: Setting GPIO with direct_irq_en to output");
1031c501d0b1SCristina Ciocan 	writel(value, val_reg);
1032c501d0b1SCristina Ciocan 
1033c501d0b1SCristina Ciocan 	raw_spin_unlock_irqrestore(&vg->lock, flags);
1034c501d0b1SCristina Ciocan 
1035c501d0b1SCristina Ciocan 	return 0;
1036c501d0b1SCristina Ciocan }
1037c501d0b1SCristina Ciocan 
1038c501d0b1SCristina Ciocan static const struct pinmux_ops byt_pinmux_ops = {
1039c501d0b1SCristina Ciocan 	.get_functions_count	= byt_get_functions_count,
1040c501d0b1SCristina Ciocan 	.get_function_name	= byt_get_function_name,
1041c501d0b1SCristina Ciocan 	.get_function_groups	= byt_get_function_groups,
1042c501d0b1SCristina Ciocan 	.set_mux		= byt_set_mux,
1043c501d0b1SCristina Ciocan 	.gpio_request_enable	= byt_gpio_request_enable,
1044c501d0b1SCristina Ciocan 	.gpio_disable_free	= byt_gpio_disable_free,
1045c501d0b1SCristina Ciocan 	.gpio_set_direction	= byt_gpio_set_direction,
1046c501d0b1SCristina Ciocan };
1047c501d0b1SCristina Ciocan 
1048c501d0b1SCristina Ciocan static void byt_get_pull_strength(u32 reg, u16 *strength)
1049c501d0b1SCristina Ciocan {
1050c501d0b1SCristina Ciocan 	switch (reg & BYT_PULL_STR_MASK) {
1051c501d0b1SCristina Ciocan 	case BYT_PULL_STR_2K:
1052c501d0b1SCristina Ciocan 		*strength = 2000;
1053c501d0b1SCristina Ciocan 		break;
1054c501d0b1SCristina Ciocan 	case BYT_PULL_STR_10K:
1055c501d0b1SCristina Ciocan 		*strength = 10000;
1056c501d0b1SCristina Ciocan 		break;
1057c501d0b1SCristina Ciocan 	case BYT_PULL_STR_20K:
1058c501d0b1SCristina Ciocan 		*strength = 20000;
1059c501d0b1SCristina Ciocan 		break;
1060c501d0b1SCristina Ciocan 	case BYT_PULL_STR_40K:
1061c501d0b1SCristina Ciocan 		*strength = 40000;
1062c501d0b1SCristina Ciocan 		break;
1063c501d0b1SCristina Ciocan 	}
1064c501d0b1SCristina Ciocan }
1065c501d0b1SCristina Ciocan 
1066c501d0b1SCristina Ciocan static int byt_set_pull_strength(u32 *reg, u16 strength)
1067c501d0b1SCristina Ciocan {
1068c501d0b1SCristina Ciocan 	*reg &= ~BYT_PULL_STR_MASK;
1069c501d0b1SCristina Ciocan 
1070c501d0b1SCristina Ciocan 	switch (strength) {
1071c501d0b1SCristina Ciocan 	case 2000:
1072c501d0b1SCristina Ciocan 		*reg |= BYT_PULL_STR_2K;
1073c501d0b1SCristina Ciocan 		break;
1074c501d0b1SCristina Ciocan 	case 10000:
1075c501d0b1SCristina Ciocan 		*reg |= BYT_PULL_STR_10K;
1076c501d0b1SCristina Ciocan 		break;
1077c501d0b1SCristina Ciocan 	case 20000:
1078c501d0b1SCristina Ciocan 		*reg |= BYT_PULL_STR_20K;
1079c501d0b1SCristina Ciocan 		break;
1080c501d0b1SCristina Ciocan 	case 40000:
1081c501d0b1SCristina Ciocan 		*reg |= BYT_PULL_STR_40K;
1082c501d0b1SCristina Ciocan 		break;
1083c501d0b1SCristina Ciocan 	default:
1084c501d0b1SCristina Ciocan 		return -EINVAL;
1085c501d0b1SCristina Ciocan 	}
1086c501d0b1SCristina Ciocan 
1087c501d0b1SCristina Ciocan 	return 0;
1088c501d0b1SCristina Ciocan }
1089c501d0b1SCristina Ciocan 
1090c501d0b1SCristina Ciocan static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset,
1091c501d0b1SCristina Ciocan 			      unsigned long *config)
1092c501d0b1SCristina Ciocan {
1093c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
1094c501d0b1SCristina Ciocan 	enum pin_config_param param = pinconf_to_config_param(*config);
1095c501d0b1SCristina Ciocan 	void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
1096c501d0b1SCristina Ciocan 	void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
109704ff5a09SAndy Shevchenko 	void __iomem *db_reg = byt_gpio_reg(vg, offset, BYT_DEBOUNCE_REG);
1098c501d0b1SCristina Ciocan 	unsigned long flags;
1099658b476cSCristina Ciocan 	u32 conf, pull, val, debounce;
1100c501d0b1SCristina Ciocan 	u16 arg = 0;
1101c501d0b1SCristina Ciocan 
1102c501d0b1SCristina Ciocan 	raw_spin_lock_irqsave(&vg->lock, flags);
1103c501d0b1SCristina Ciocan 	conf = readl(conf_reg);
1104c501d0b1SCristina Ciocan 	pull = conf & BYT_PULL_ASSIGN_MASK;
1105c501d0b1SCristina Ciocan 	val = readl(val_reg);
1106c501d0b1SCristina Ciocan 	raw_spin_unlock_irqrestore(&vg->lock, flags);
1107c501d0b1SCristina Ciocan 
1108c501d0b1SCristina Ciocan 	switch (param) {
1109c501d0b1SCristina Ciocan 	case PIN_CONFIG_BIAS_DISABLE:
1110c501d0b1SCristina Ciocan 		if (pull)
1111c501d0b1SCristina Ciocan 			return -EINVAL;
1112c501d0b1SCristina Ciocan 		break;
1113c501d0b1SCristina Ciocan 	case PIN_CONFIG_BIAS_PULL_DOWN:
1114c501d0b1SCristina Ciocan 		/* Pull assignment is only applicable in input mode */
1115c501d0b1SCristina Ciocan 		if ((val & BYT_INPUT_EN) || pull != BYT_PULL_ASSIGN_DOWN)
1116c501d0b1SCristina Ciocan 			return -EINVAL;
1117c501d0b1SCristina Ciocan 
1118c501d0b1SCristina Ciocan 		byt_get_pull_strength(conf, &arg);
1119c501d0b1SCristina Ciocan 
1120c501d0b1SCristina Ciocan 		break;
1121c501d0b1SCristina Ciocan 	case PIN_CONFIG_BIAS_PULL_UP:
1122c501d0b1SCristina Ciocan 		/* Pull assignment is only applicable in input mode */
1123c501d0b1SCristina Ciocan 		if ((val & BYT_INPUT_EN) || pull != BYT_PULL_ASSIGN_UP)
1124c501d0b1SCristina Ciocan 			return -EINVAL;
1125c501d0b1SCristina Ciocan 
1126c501d0b1SCristina Ciocan 		byt_get_pull_strength(conf, &arg);
1127c501d0b1SCristina Ciocan 
1128c501d0b1SCristina Ciocan 		break;
1129658b476cSCristina Ciocan 	case PIN_CONFIG_INPUT_DEBOUNCE:
1130658b476cSCristina Ciocan 		if (!(conf & BYT_DEBOUNCE_EN))
1131658b476cSCristina Ciocan 			return -EINVAL;
1132658b476cSCristina Ciocan 
1133658b476cSCristina Ciocan 		raw_spin_lock_irqsave(&vg->lock, flags);
113404ff5a09SAndy Shevchenko 		debounce = readl(db_reg);
1135658b476cSCristina Ciocan 		raw_spin_unlock_irqrestore(&vg->lock, flags);
1136658b476cSCristina Ciocan 
1137658b476cSCristina Ciocan 		switch (debounce & BYT_DEBOUNCE_PULSE_MASK) {
1138658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_375US:
1139658b476cSCristina Ciocan 			arg = 375;
1140658b476cSCristina Ciocan 			break;
1141658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_750US:
1142658b476cSCristina Ciocan 			arg = 750;
1143658b476cSCristina Ciocan 			break;
1144658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_1500US:
1145658b476cSCristina Ciocan 			arg = 1500;
1146658b476cSCristina Ciocan 			break;
1147658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_3MS:
1148658b476cSCristina Ciocan 			arg = 3000;
1149658b476cSCristina Ciocan 			break;
1150658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_6MS:
1151658b476cSCristina Ciocan 			arg = 6000;
1152658b476cSCristina Ciocan 			break;
1153658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_12MS:
1154658b476cSCristina Ciocan 			arg = 12000;
1155658b476cSCristina Ciocan 			break;
1156658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_24MS:
1157658b476cSCristina Ciocan 			arg = 24000;
1158658b476cSCristina Ciocan 			break;
1159658b476cSCristina Ciocan 		default:
1160658b476cSCristina Ciocan 			return -EINVAL;
1161658b476cSCristina Ciocan 		}
1162658b476cSCristina Ciocan 
1163658b476cSCristina Ciocan 		break;
1164c501d0b1SCristina Ciocan 	default:
1165c501d0b1SCristina Ciocan 		return -ENOTSUPP;
1166c501d0b1SCristina Ciocan 	}
1167c501d0b1SCristina Ciocan 
1168c501d0b1SCristina Ciocan 	*config = pinconf_to_config_packed(param, arg);
1169c501d0b1SCristina Ciocan 
1170c501d0b1SCristina Ciocan 	return 0;
1171c501d0b1SCristina Ciocan }
1172c501d0b1SCristina Ciocan 
1173c501d0b1SCristina Ciocan static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
1174c501d0b1SCristina Ciocan 			      unsigned int offset,
1175c501d0b1SCristina Ciocan 			      unsigned long *configs,
1176c501d0b1SCristina Ciocan 			      unsigned int num_configs)
1177c501d0b1SCristina Ciocan {
1178c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
1179c501d0b1SCristina Ciocan 	unsigned int param, arg;
1180c501d0b1SCristina Ciocan 	void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
1181c501d0b1SCristina Ciocan 	void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
118204ff5a09SAndy Shevchenko 	void __iomem *db_reg = byt_gpio_reg(vg, offset, BYT_DEBOUNCE_REG);
1183c501d0b1SCristina Ciocan 	unsigned long flags;
1184658b476cSCristina Ciocan 	u32 conf, val, debounce;
1185c501d0b1SCristina Ciocan 	int i, ret = 0;
1186c501d0b1SCristina Ciocan 
1187c501d0b1SCristina Ciocan 	raw_spin_lock_irqsave(&vg->lock, flags);
1188c501d0b1SCristina Ciocan 
1189c501d0b1SCristina Ciocan 	conf = readl(conf_reg);
1190c501d0b1SCristina Ciocan 	val = readl(val_reg);
1191c501d0b1SCristina Ciocan 
1192c501d0b1SCristina Ciocan 	for (i = 0; i < num_configs; i++) {
1193c501d0b1SCristina Ciocan 		param = pinconf_to_config_param(configs[i]);
1194c501d0b1SCristina Ciocan 		arg = pinconf_to_config_argument(configs[i]);
1195c501d0b1SCristina Ciocan 
1196c501d0b1SCristina Ciocan 		switch (param) {
1197c501d0b1SCristina Ciocan 		case PIN_CONFIG_BIAS_DISABLE:
1198c501d0b1SCristina Ciocan 			conf &= ~BYT_PULL_ASSIGN_MASK;
1199c501d0b1SCristina Ciocan 			break;
1200c501d0b1SCristina Ciocan 		case PIN_CONFIG_BIAS_PULL_DOWN:
1201c501d0b1SCristina Ciocan 			/* Set default strength value in case none is given */
1202c501d0b1SCristina Ciocan 			if (arg == 1)
1203c501d0b1SCristina Ciocan 				arg = 2000;
1204c501d0b1SCristina Ciocan 
1205c501d0b1SCristina Ciocan 			/*
1206c501d0b1SCristina Ciocan 			 * Pull assignment is only applicable in input mode. If
1207c501d0b1SCristina Ciocan 			 * chip is not in input mode, set it and warn about it.
1208c501d0b1SCristina Ciocan 			 */
1209c501d0b1SCristina Ciocan 			if (val & BYT_INPUT_EN) {
1210c501d0b1SCristina Ciocan 				val &= ~BYT_INPUT_EN;
1211c501d0b1SCristina Ciocan 				writel(val, val_reg);
1212c501d0b1SCristina Ciocan 				dev_warn(&vg->pdev->dev,
1213c501d0b1SCristina Ciocan 					 "pin %u forcibly set to input mode\n",
1214c501d0b1SCristina Ciocan 					 offset);
1215c501d0b1SCristina Ciocan 			}
1216c501d0b1SCristina Ciocan 
1217c501d0b1SCristina Ciocan 			conf &= ~BYT_PULL_ASSIGN_MASK;
1218c501d0b1SCristina Ciocan 			conf |= BYT_PULL_ASSIGN_DOWN;
1219c501d0b1SCristina Ciocan 			ret = byt_set_pull_strength(&conf, arg);
1220c501d0b1SCristina Ciocan 
1221c501d0b1SCristina Ciocan 			break;
1222c501d0b1SCristina Ciocan 		case PIN_CONFIG_BIAS_PULL_UP:
1223c501d0b1SCristina Ciocan 			/* Set default strength value in case none is given */
1224c501d0b1SCristina Ciocan 			if (arg == 1)
1225c501d0b1SCristina Ciocan 				arg = 2000;
1226c501d0b1SCristina Ciocan 
1227c501d0b1SCristina Ciocan 			/*
1228c501d0b1SCristina Ciocan 			 * Pull assignment is only applicable in input mode. If
1229c501d0b1SCristina Ciocan 			 * chip is not in input mode, set it and warn about it.
1230c501d0b1SCristina Ciocan 			 */
1231c501d0b1SCristina Ciocan 			if (val & BYT_INPUT_EN) {
1232c501d0b1SCristina Ciocan 				val &= ~BYT_INPUT_EN;
1233c501d0b1SCristina Ciocan 				writel(val, val_reg);
1234c501d0b1SCristina Ciocan 				dev_warn(&vg->pdev->dev,
1235c501d0b1SCristina Ciocan 					 "pin %u forcibly set to input mode\n",
1236c501d0b1SCristina Ciocan 					 offset);
1237c501d0b1SCristina Ciocan 			}
1238c501d0b1SCristina Ciocan 
1239c501d0b1SCristina Ciocan 			conf &= ~BYT_PULL_ASSIGN_MASK;
1240c501d0b1SCristina Ciocan 			conf |= BYT_PULL_ASSIGN_UP;
1241c501d0b1SCristina Ciocan 			ret = byt_set_pull_strength(&conf, arg);
1242c501d0b1SCristina Ciocan 
1243c501d0b1SCristina Ciocan 			break;
1244658b476cSCristina Ciocan 		case PIN_CONFIG_INPUT_DEBOUNCE:
124504ff5a09SAndy Shevchenko 			debounce = readl(db_reg);
124604ff5a09SAndy Shevchenko 			debounce &= ~BYT_DEBOUNCE_PULSE_MASK;
1247658b476cSCristina Ciocan 
1248827e1579SAndy Shevchenko 			if (arg)
1249827e1579SAndy Shevchenko 				conf |= BYT_DEBOUNCE_EN;
1250827e1579SAndy Shevchenko 			else
1251827e1579SAndy Shevchenko 				conf &= ~BYT_DEBOUNCE_EN;
1252827e1579SAndy Shevchenko 
1253658b476cSCristina Ciocan 			switch (arg) {
1254658b476cSCristina Ciocan 			case 375:
125504ff5a09SAndy Shevchenko 				debounce |= BYT_DEBOUNCE_PULSE_375US;
1256658b476cSCristina Ciocan 				break;
1257658b476cSCristina Ciocan 			case 750:
125804ff5a09SAndy Shevchenko 				debounce |= BYT_DEBOUNCE_PULSE_750US;
1259658b476cSCristina Ciocan 				break;
1260658b476cSCristina Ciocan 			case 1500:
126104ff5a09SAndy Shevchenko 				debounce |= BYT_DEBOUNCE_PULSE_1500US;
1262658b476cSCristina Ciocan 				break;
1263658b476cSCristina Ciocan 			case 3000:
126404ff5a09SAndy Shevchenko 				debounce |= BYT_DEBOUNCE_PULSE_3MS;
1265658b476cSCristina Ciocan 				break;
1266658b476cSCristina Ciocan 			case 6000:
126704ff5a09SAndy Shevchenko 				debounce |= BYT_DEBOUNCE_PULSE_6MS;
1268658b476cSCristina Ciocan 				break;
1269658b476cSCristina Ciocan 			case 12000:
127004ff5a09SAndy Shevchenko 				debounce |= BYT_DEBOUNCE_PULSE_12MS;
1271658b476cSCristina Ciocan 				break;
1272658b476cSCristina Ciocan 			case 24000:
127304ff5a09SAndy Shevchenko 				debounce |= BYT_DEBOUNCE_PULSE_24MS;
1274658b476cSCristina Ciocan 				break;
1275658b476cSCristina Ciocan 			default:
1276827e1579SAndy Shevchenko 				if (arg)
1277658b476cSCristina Ciocan 					ret = -EINVAL;
1278827e1579SAndy Shevchenko 				break;
1279658b476cSCristina Ciocan 			}
1280658b476cSCristina Ciocan 
128104ff5a09SAndy Shevchenko 			if (!ret)
128204ff5a09SAndy Shevchenko 				writel(debounce, db_reg);
1283658b476cSCristina Ciocan 			break;
1284c501d0b1SCristina Ciocan 		default:
1285c501d0b1SCristina Ciocan 			ret = -ENOTSUPP;
1286c501d0b1SCristina Ciocan 		}
1287c501d0b1SCristina Ciocan 
1288c501d0b1SCristina Ciocan 		if (ret)
1289c501d0b1SCristina Ciocan 			break;
1290c501d0b1SCristina Ciocan 	}
1291c501d0b1SCristina Ciocan 
1292c501d0b1SCristina Ciocan 	if (!ret)
1293c501d0b1SCristina Ciocan 		writel(conf, conf_reg);
1294c501d0b1SCristina Ciocan 
1295c501d0b1SCristina Ciocan 	raw_spin_unlock_irqrestore(&vg->lock, flags);
1296c501d0b1SCristina Ciocan 
1297c501d0b1SCristina Ciocan 	return ret;
1298c501d0b1SCristina Ciocan }
1299c501d0b1SCristina Ciocan 
1300c501d0b1SCristina Ciocan static const struct pinconf_ops byt_pinconf_ops = {
1301c501d0b1SCristina Ciocan 	.is_generic	= true,
1302c501d0b1SCristina Ciocan 	.pin_config_get	= byt_pin_config_get,
1303c501d0b1SCristina Ciocan 	.pin_config_set	= byt_pin_config_set,
1304c501d0b1SCristina Ciocan };
1305c501d0b1SCristina Ciocan 
1306c501d0b1SCristina Ciocan static const struct pinctrl_desc byt_pinctrl_desc = {
1307c501d0b1SCristina Ciocan 	.pctlops	= &byt_pinctrl_ops,
1308c501d0b1SCristina Ciocan 	.pmxops		= &byt_pinmux_ops,
1309c501d0b1SCristina Ciocan 	.confops	= &byt_pinconf_ops,
1310c501d0b1SCristina Ciocan 	.owner		= THIS_MODULE,
1311c501d0b1SCristina Ciocan };
1312c501d0b1SCristina Ciocan 
13135fae8b86SMika Westerberg static int byt_gpio_get(struct gpio_chip *chip, unsigned offset)
13145fae8b86SMika Westerberg {
1315bf9a5c96SLinus Walleij 	struct byt_gpio *vg = gpiochip_get_data(chip);
1316c501d0b1SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
131739ce8150SMika Westerberg 	unsigned long flags;
131839ce8150SMika Westerberg 	u32 val;
131939ce8150SMika Westerberg 
132078e1c896SMika Westerberg 	raw_spin_lock_irqsave(&vg->lock, flags);
132139ce8150SMika Westerberg 	val = readl(reg);
132278e1c896SMika Westerberg 	raw_spin_unlock_irqrestore(&vg->lock, flags);
132339ce8150SMika Westerberg 
13243bde8771SLinus Walleij 	return !!(val & BYT_LEVEL);
13255fae8b86SMika Westerberg }
13265fae8b86SMika Westerberg 
13275fae8b86SMika Westerberg static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
13285fae8b86SMika Westerberg {
1329bf9a5c96SLinus Walleij 	struct byt_gpio *vg = gpiochip_get_data(chip);
1330c501d0b1SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
13315fae8b86SMika Westerberg 	unsigned long flags;
13325fae8b86SMika Westerberg 	u32 old_val;
13335fae8b86SMika Westerberg 
133486e3ef81SCristina Ciocan 	if (!reg)
133586e3ef81SCristina Ciocan 		return;
133686e3ef81SCristina Ciocan 
133778e1c896SMika Westerberg 	raw_spin_lock_irqsave(&vg->lock, flags);
13385fae8b86SMika Westerberg 	old_val = readl(reg);
13395fae8b86SMika Westerberg 	if (value)
13405fae8b86SMika Westerberg 		writel(old_val | BYT_LEVEL, reg);
13415fae8b86SMika Westerberg 	else
13425fae8b86SMika Westerberg 		writel(old_val & ~BYT_LEVEL, reg);
134378e1c896SMika Westerberg 	raw_spin_unlock_irqrestore(&vg->lock, flags);
13445fae8b86SMika Westerberg }
13455fae8b86SMika Westerberg 
134686e3ef81SCristina Ciocan static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
13475fae8b86SMika Westerberg {
1348bf9a5c96SLinus Walleij 	struct byt_gpio *vg = gpiochip_get_data(chip);
1349c501d0b1SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
13505fae8b86SMika Westerberg 	unsigned long flags;
13515fae8b86SMika Westerberg 	u32 value;
13525fae8b86SMika Westerberg 
135386e3ef81SCristina Ciocan 	if (!reg)
135486e3ef81SCristina Ciocan 		return -EINVAL;
135586e3ef81SCristina Ciocan 
135678e1c896SMika Westerberg 	raw_spin_lock_irqsave(&vg->lock, flags);
135786e3ef81SCristina Ciocan 	value = readl(reg);
135878e1c896SMika Westerberg 	raw_spin_unlock_irqrestore(&vg->lock, flags);
13595fae8b86SMika Westerberg 
136086e3ef81SCristina Ciocan 	if (!(value & BYT_OUTPUT_EN))
136186e3ef81SCristina Ciocan 		return GPIOF_DIR_OUT;
136286e3ef81SCristina Ciocan 	if (!(value & BYT_INPUT_EN))
136386e3ef81SCristina Ciocan 		return GPIOF_DIR_IN;
136486e3ef81SCristina Ciocan 
136586e3ef81SCristina Ciocan 	return -EINVAL;
13665fae8b86SMika Westerberg }
13675fae8b86SMika Westerberg 
136886e3ef81SCristina Ciocan static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
13695fae8b86SMika Westerberg {
137086e3ef81SCristina Ciocan 	return pinctrl_gpio_direction_input(chip->base + offset);
137186e3ef81SCristina Ciocan }
13725fae8b86SMika Westerberg 
137386e3ef81SCristina Ciocan static int byt_gpio_direction_output(struct gpio_chip *chip,
137486e3ef81SCristina Ciocan 				     unsigned int offset, int value)
137586e3ef81SCristina Ciocan {
137686e3ef81SCristina Ciocan 	int ret = pinctrl_gpio_direction_output(chip->base + offset);
13775fae8b86SMika Westerberg 
137886e3ef81SCristina Ciocan 	if (ret)
137986e3ef81SCristina Ciocan 		return ret;
138086e3ef81SCristina Ciocan 
138186e3ef81SCristina Ciocan 	byt_gpio_set(chip, offset, value);
13825fae8b86SMika Westerberg 
13835fae8b86SMika Westerberg 	return 0;
13845fae8b86SMika Westerberg }
13855fae8b86SMika Westerberg 
13865fae8b86SMika Westerberg static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
13875fae8b86SMika Westerberg {
1388bf9a5c96SLinus Walleij 	struct byt_gpio *vg = gpiochip_get_data(chip);
13895fae8b86SMika Westerberg 	int i;
139086e3ef81SCristina Ciocan 	u32 conf0, val;
13915fae8b86SMika Westerberg 
139286e3ef81SCristina Ciocan 	for (i = 0; i < vg->soc_data->npins; i++) {
139386e3ef81SCristina Ciocan 		const struct byt_community *comm;
13945fae8b86SMika Westerberg 		const char *pull_str = NULL;
13955fae8b86SMika Westerberg 		const char *pull = NULL;
139686e3ef81SCristina Ciocan 		void __iomem *reg;
139778e1c896SMika Westerberg 		unsigned long flags;
13985fae8b86SMika Westerberg 		const char *label;
139986e3ef81SCristina Ciocan 		unsigned int pin;
140078e1c896SMika Westerberg 
140178e1c896SMika Westerberg 		raw_spin_lock_irqsave(&vg->lock, flags);
140286e3ef81SCristina Ciocan 		pin = vg->soc_data->pins[i].number;
140386e3ef81SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
140486e3ef81SCristina Ciocan 		if (!reg) {
140586e3ef81SCristina Ciocan 			seq_printf(s,
140686e3ef81SCristina Ciocan 				   "Could not retrieve pin %i conf0 reg\n",
140786e3ef81SCristina Ciocan 				   pin);
140822bbd21bSDan Carpenter 			raw_spin_unlock_irqrestore(&vg->lock, flags);
140986e3ef81SCristina Ciocan 			continue;
141086e3ef81SCristina Ciocan 		}
141186e3ef81SCristina Ciocan 		conf0 = readl(reg);
141286e3ef81SCristina Ciocan 
141386e3ef81SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
141486e3ef81SCristina Ciocan 		if (!reg) {
141586e3ef81SCristina Ciocan 			seq_printf(s,
141686e3ef81SCristina Ciocan 				   "Could not retrieve pin %i val reg\n", pin);
141722bbd21bSDan Carpenter 			raw_spin_unlock_irqrestore(&vg->lock, flags);
141822bbd21bSDan Carpenter 			continue;
141986e3ef81SCristina Ciocan 		}
142086e3ef81SCristina Ciocan 		val = readl(reg);
142178e1c896SMika Westerberg 		raw_spin_unlock_irqrestore(&vg->lock, flags);
14225fae8b86SMika Westerberg 
142386e3ef81SCristina Ciocan 		comm = byt_get_community(vg, pin);
142486e3ef81SCristina Ciocan 		if (!comm) {
142586e3ef81SCristina Ciocan 			seq_printf(s,
142686e3ef81SCristina Ciocan 				   "Could not get community for pin %i\n", pin);
142786e3ef81SCristina Ciocan 			continue;
142886e3ef81SCristina Ciocan 		}
14295fae8b86SMika Westerberg 		label = gpiochip_is_requested(chip, i);
14305fae8b86SMika Westerberg 		if (!label)
14315fae8b86SMika Westerberg 			label = "Unrequested";
14325fae8b86SMika Westerberg 
14335fae8b86SMika Westerberg 		switch (conf0 & BYT_PULL_ASSIGN_MASK) {
14345fae8b86SMika Westerberg 		case BYT_PULL_ASSIGN_UP:
14355fae8b86SMika Westerberg 			pull = "up";
14365fae8b86SMika Westerberg 			break;
14375fae8b86SMika Westerberg 		case BYT_PULL_ASSIGN_DOWN:
14385fae8b86SMika Westerberg 			pull = "down";
14395fae8b86SMika Westerberg 			break;
14405fae8b86SMika Westerberg 		}
14415fae8b86SMika Westerberg 
14425fae8b86SMika Westerberg 		switch (conf0 & BYT_PULL_STR_MASK) {
14435fae8b86SMika Westerberg 		case BYT_PULL_STR_2K:
14445fae8b86SMika Westerberg 			pull_str = "2k";
14455fae8b86SMika Westerberg 			break;
14465fae8b86SMika Westerberg 		case BYT_PULL_STR_10K:
14475fae8b86SMika Westerberg 			pull_str = "10k";
14485fae8b86SMika Westerberg 			break;
14495fae8b86SMika Westerberg 		case BYT_PULL_STR_20K:
14505fae8b86SMika Westerberg 			pull_str = "20k";
14515fae8b86SMika Westerberg 			break;
14525fae8b86SMika Westerberg 		case BYT_PULL_STR_40K:
14535fae8b86SMika Westerberg 			pull_str = "40k";
14545fae8b86SMika Westerberg 			break;
14555fae8b86SMika Westerberg 		}
14565fae8b86SMika Westerberg 
14575fae8b86SMika Westerberg 		seq_printf(s,
14585fae8b86SMika Westerberg 			   " gpio-%-3d (%-20.20s) %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s",
145986e3ef81SCristina Ciocan 			   pin,
14605fae8b86SMika Westerberg 			   label,
14615fae8b86SMika Westerberg 			   val & BYT_INPUT_EN ? "  " : "in",
14625fae8b86SMika Westerberg 			   val & BYT_OUTPUT_EN ? "   " : "out",
14635fae8b86SMika Westerberg 			   val & BYT_LEVEL ? "hi" : "lo",
14643655a1caSAlexander Stein 			   comm->pad_map[i], comm->pad_map[i] * 16,
14655fae8b86SMika Westerberg 			   conf0 & 0x7,
14665fae8b86SMika Westerberg 			   conf0 & BYT_TRIG_NEG ? " fall" : "     ",
14675fae8b86SMika Westerberg 			   conf0 & BYT_TRIG_POS ? " rise" : "     ",
14685fae8b86SMika Westerberg 			   conf0 & BYT_TRIG_LVL ? " level" : "      ");
14695fae8b86SMika Westerberg 
14705fae8b86SMika Westerberg 		if (pull && pull_str)
14715fae8b86SMika Westerberg 			seq_printf(s, " %-4s %-3s", pull, pull_str);
14725fae8b86SMika Westerberg 		else
14735fae8b86SMika Westerberg 			seq_puts(s, "          ");
14745fae8b86SMika Westerberg 
14755fae8b86SMika Westerberg 		if (conf0 & BYT_IODEN)
14765fae8b86SMika Westerberg 			seq_puts(s, " open-drain");
14775fae8b86SMika Westerberg 
14785fae8b86SMika Westerberg 		seq_puts(s, "\n");
14795fae8b86SMika Westerberg 	}
14805fae8b86SMika Westerberg }
14815fae8b86SMika Westerberg 
148286e3ef81SCristina Ciocan static const struct gpio_chip byt_gpio_chip = {
148386e3ef81SCristina Ciocan 	.owner			= THIS_MODULE,
148486e3ef81SCristina Ciocan 	.request		= gpiochip_generic_request,
148586e3ef81SCristina Ciocan 	.free			= gpiochip_generic_free,
148686e3ef81SCristina Ciocan 	.get_direction		= byt_gpio_get_direction,
148786e3ef81SCristina Ciocan 	.direction_input	= byt_gpio_direction_input,
148886e3ef81SCristina Ciocan 	.direction_output	= byt_gpio_direction_output,
148986e3ef81SCristina Ciocan 	.get			= byt_gpio_get,
149086e3ef81SCristina Ciocan 	.set			= byt_gpio_set,
149186e3ef81SCristina Ciocan 	.dbg_show		= byt_gpio_dbg_show,
149286e3ef81SCristina Ciocan };
149386e3ef81SCristina Ciocan 
149431e4329fSMika Westerberg static void byt_irq_ack(struct irq_data *d)
149531e4329fSMika Westerberg {
149631e4329fSMika Westerberg 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
1497bf9a5c96SLinus Walleij 	struct byt_gpio *vg = gpiochip_get_data(gc);
149831e4329fSMika Westerberg 	unsigned offset = irqd_to_hwirq(d);
149931e4329fSMika Westerberg 	void __iomem *reg;
150031e4329fSMika Westerberg 
1501c501d0b1SCristina Ciocan 	reg = byt_gpio_reg(vg, offset, BYT_INT_STAT_REG);
15029f573b98SCristina Ciocan 	if (!reg)
15039f573b98SCristina Ciocan 		return;
15049f573b98SCristina Ciocan 
15059f573b98SCristina Ciocan 	raw_spin_lock(&vg->lock);
150631e4329fSMika Westerberg 	writel(BIT(offset % 32), reg);
150778e1c896SMika Westerberg 	raw_spin_unlock(&vg->lock);
150831e4329fSMika Westerberg }
150931e4329fSMika Westerberg 
15109f573b98SCristina Ciocan static void byt_irq_mask(struct irq_data *d)
15119f573b98SCristina Ciocan {
15129f573b98SCristina Ciocan 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
15139f573b98SCristina Ciocan 	struct byt_gpio *vg = gpiochip_get_data(gc);
15149f573b98SCristina Ciocan 
15159f573b98SCristina Ciocan 	byt_gpio_clear_triggering(vg, irqd_to_hwirq(d));
15169f573b98SCristina Ciocan }
15179f573b98SCristina Ciocan 
15185fae8b86SMika Westerberg static void byt_irq_unmask(struct irq_data *d)
15195fae8b86SMika Westerberg {
152031e4329fSMika Westerberg 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
1521bf9a5c96SLinus Walleij 	struct byt_gpio *vg = gpiochip_get_data(gc);
152231e4329fSMika Westerberg 	unsigned offset = irqd_to_hwirq(d);
152331e4329fSMika Westerberg 	unsigned long flags;
152431e4329fSMika Westerberg 	void __iomem *reg;
152531e4329fSMika Westerberg 	u32 value;
152631e4329fSMika Westerberg 
1527c501d0b1SCristina Ciocan 	reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
15289f573b98SCristina Ciocan 	if (!reg)
15299f573b98SCristina Ciocan 		return;
153078e1c896SMika Westerberg 
153178e1c896SMika Westerberg 	raw_spin_lock_irqsave(&vg->lock, flags);
153231e4329fSMika Westerberg 	value = readl(reg);
153331e4329fSMika Westerberg 
153431e4329fSMika Westerberg 	switch (irqd_get_trigger_type(d)) {
153531e4329fSMika Westerberg 	case IRQ_TYPE_LEVEL_HIGH:
153631e4329fSMika Westerberg 		value |= BYT_TRIG_LVL;
1537399476bdSGustavo A. R. Silva 		/* fall through */
153831e4329fSMika Westerberg 	case IRQ_TYPE_EDGE_RISING:
153931e4329fSMika Westerberg 		value |= BYT_TRIG_POS;
154031e4329fSMika Westerberg 		break;
154131e4329fSMika Westerberg 	case IRQ_TYPE_LEVEL_LOW:
154231e4329fSMika Westerberg 		value |= BYT_TRIG_LVL;
1543399476bdSGustavo A. R. Silva 		/* fall through */
154431e4329fSMika Westerberg 	case IRQ_TYPE_EDGE_FALLING:
154531e4329fSMika Westerberg 		value |= BYT_TRIG_NEG;
154631e4329fSMika Westerberg 		break;
154731e4329fSMika Westerberg 	case IRQ_TYPE_EDGE_BOTH:
154831e4329fSMika Westerberg 		value |= (BYT_TRIG_NEG | BYT_TRIG_POS);
154931e4329fSMika Westerberg 		break;
155031e4329fSMika Westerberg 	}
155131e4329fSMika Westerberg 
155231e4329fSMika Westerberg 	writel(value, reg);
155331e4329fSMika Westerberg 
155478e1c896SMika Westerberg 	raw_spin_unlock_irqrestore(&vg->lock, flags);
15555fae8b86SMika Westerberg }
15565fae8b86SMika Westerberg 
15579f573b98SCristina Ciocan static int byt_irq_type(struct irq_data *d, unsigned int type)
15585fae8b86SMika Westerberg {
15599f573b98SCristina Ciocan 	struct byt_gpio *vg = gpiochip_get_data(irq_data_get_irq_chip_data(d));
15609f573b98SCristina Ciocan 	u32 offset = irqd_to_hwirq(d);
15619f573b98SCristina Ciocan 	u32 value;
15629f573b98SCristina Ciocan 	unsigned long flags;
15639f573b98SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
156431e4329fSMika Westerberg 
15659f573b98SCristina Ciocan 	if (!reg || offset >= vg->chip.ngpio)
15669f573b98SCristina Ciocan 		return -EINVAL;
15679f573b98SCristina Ciocan 
15689f573b98SCristina Ciocan 	raw_spin_lock_irqsave(&vg->lock, flags);
15699f573b98SCristina Ciocan 	value = readl(reg);
15709f573b98SCristina Ciocan 
15719f573b98SCristina Ciocan 	WARN(value & BYT_DIRECT_IRQ_EN,
15729f573b98SCristina Ciocan 	     "Bad pad config for io mode, force direct_irq_en bit clearing");
15739f573b98SCristina Ciocan 
15749f573b98SCristina Ciocan 	/* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits
15759f573b98SCristina Ciocan 	 * are used to indicate high and low level triggering
15769f573b98SCristina Ciocan 	 */
15779f573b98SCristina Ciocan 	value &= ~(BYT_DIRECT_IRQ_EN | BYT_TRIG_POS | BYT_TRIG_NEG |
15789f573b98SCristina Ciocan 		   BYT_TRIG_LVL);
15799291c65bSHans de Goede 	/* Enable glitch filtering */
15809291c65bSHans de Goede 	value |= BYT_GLITCH_FILTER_EN | BYT_GLITCH_F_SLOW_CLK |
15819291c65bSHans de Goede 		 BYT_GLITCH_F_FAST_CLK;
15829f573b98SCristina Ciocan 
15839f573b98SCristina Ciocan 	writel(value, reg);
15849f573b98SCristina Ciocan 
15859f573b98SCristina Ciocan 	if (type & IRQ_TYPE_EDGE_BOTH)
15869f573b98SCristina Ciocan 		irq_set_handler_locked(d, handle_edge_irq);
15879f573b98SCristina Ciocan 	else if (type & IRQ_TYPE_LEVEL_MASK)
15889f573b98SCristina Ciocan 		irq_set_handler_locked(d, handle_level_irq);
15899f573b98SCristina Ciocan 
15909f573b98SCristina Ciocan 	raw_spin_unlock_irqrestore(&vg->lock, flags);
15919f573b98SCristina Ciocan 
15929f573b98SCristina Ciocan 	return 0;
15935fae8b86SMika Westerberg }
15945fae8b86SMika Westerberg 
15955fae8b86SMika Westerberg static struct irq_chip byt_irqchip = {
15965fae8b86SMika Westerberg 	.name		= "BYT-GPIO",
159731e4329fSMika Westerberg 	.irq_ack	= byt_irq_ack,
15985fae8b86SMika Westerberg 	.irq_mask	= byt_irq_mask,
15995fae8b86SMika Westerberg 	.irq_unmask	= byt_irq_unmask,
16005fae8b86SMika Westerberg 	.irq_set_type	= byt_irq_type,
16015fae8b86SMika Westerberg 	.flags		= IRQCHIP_SKIP_SET_WAKE,
16025fae8b86SMika Westerberg };
16035fae8b86SMika Westerberg 
160471e6ca61SCristina Ciocan static void byt_gpio_irq_handler(struct irq_desc *desc)
160571e6ca61SCristina Ciocan {
160671e6ca61SCristina Ciocan 	struct irq_data *data = irq_desc_get_irq_data(desc);
160771e6ca61SCristina Ciocan 	struct byt_gpio *vg = gpiochip_get_data(
160871e6ca61SCristina Ciocan 				irq_desc_get_handler_data(desc));
160971e6ca61SCristina Ciocan 	struct irq_chip *chip = irq_data_get_irq_chip(data);
161071e6ca61SCristina Ciocan 	u32 base, pin;
161171e6ca61SCristina Ciocan 	void __iomem *reg;
161271e6ca61SCristina Ciocan 	unsigned long pending;
161371e6ca61SCristina Ciocan 	unsigned int virq;
161471e6ca61SCristina Ciocan 
161571e6ca61SCristina Ciocan 	/* check from GPIO controller which pin triggered the interrupt */
161671e6ca61SCristina Ciocan 	for (base = 0; base < vg->chip.ngpio; base += 32) {
161771e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG);
161871e6ca61SCristina Ciocan 
161971e6ca61SCristina Ciocan 		if (!reg) {
162071e6ca61SCristina Ciocan 			dev_warn(&vg->pdev->dev,
162171e6ca61SCristina Ciocan 				 "Pin %i: could not retrieve interrupt status register\n",
162271e6ca61SCristina Ciocan 				 base);
162371e6ca61SCristina Ciocan 			continue;
162471e6ca61SCristina Ciocan 		}
162571e6ca61SCristina Ciocan 
1626cdca06e4SAlexander Stein 		raw_spin_lock(&vg->lock);
162771e6ca61SCristina Ciocan 		pending = readl(reg);
1628cdca06e4SAlexander Stein 		raw_spin_unlock(&vg->lock);
162971e6ca61SCristina Ciocan 		for_each_set_bit(pin, &pending, 32) {
1630f0fbe7bcSThierry Reding 			virq = irq_find_mapping(vg->chip.irq.domain, base + pin);
163171e6ca61SCristina Ciocan 			generic_handle_irq(virq);
163271e6ca61SCristina Ciocan 		}
163371e6ca61SCristina Ciocan 	}
163471e6ca61SCristina Ciocan 	chip->irq_eoi(data);
163571e6ca61SCristina Ciocan }
163671e6ca61SCristina Ciocan 
16375fae8b86SMika Westerberg static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
16385fae8b86SMika Westerberg {
163949c03096SAndy Shevchenko 	struct gpio_chip *gc = &vg->chip;
164049c03096SAndy Shevchenko 	struct device *dev = &vg->pdev->dev;
16415fae8b86SMika Westerberg 	void __iomem *reg;
16425fae8b86SMika Westerberg 	u32 base, value;
164395f0972cSMika Westerberg 	int i;
164495f0972cSMika Westerberg 
164595f0972cSMika Westerberg 	/*
164695f0972cSMika Westerberg 	 * Clear interrupt triggers for all pins that are GPIOs and
164795f0972cSMika Westerberg 	 * do not use direct IRQ mode. This will prevent spurious
164895f0972cSMika Westerberg 	 * interrupts from misconfigured pins.
164995f0972cSMika Westerberg 	 */
165071e6ca61SCristina Ciocan 	for (i = 0; i < vg->soc_data->npins; i++) {
165171e6ca61SCristina Ciocan 		unsigned int pin = vg->soc_data->pins[i].number;
165271e6ca61SCristina Ciocan 
165371e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
165471e6ca61SCristina Ciocan 		if (!reg) {
165571e6ca61SCristina Ciocan 			dev_warn(&vg->pdev->dev,
165671e6ca61SCristina Ciocan 				 "Pin %i: could not retrieve conf0 register\n",
165771e6ca61SCristina Ciocan 				 i);
165871e6ca61SCristina Ciocan 			continue;
165971e6ca61SCristina Ciocan 		}
166071e6ca61SCristina Ciocan 
166171e6ca61SCristina Ciocan 		value = readl(reg);
166249c03096SAndy Shevchenko 		if (value & BYT_DIRECT_IRQ_EN) {
1663dc7b0387SThierry Reding 			clear_bit(i, gc->irq.valid_mask);
166449c03096SAndy Shevchenko 			dev_dbg(dev, "excluding GPIO %d from IRQ domain\n", i);
166549c03096SAndy Shevchenko 		} else if ((value & BYT_PIN_MUX) == byt_get_gpio_mux(vg, i)) {
166695f0972cSMika Westerberg 			byt_gpio_clear_triggering(vg, i);
166749c03096SAndy Shevchenko 			dev_dbg(dev, "disabling GPIO %d\n", i);
166895f0972cSMika Westerberg 		}
166995f0972cSMika Westerberg 	}
16705fae8b86SMika Westerberg 
16715fae8b86SMika Westerberg 	/* clear interrupt status trigger registers */
167271e6ca61SCristina Ciocan 	for (base = 0; base < vg->soc_data->npins; base += 32) {
1673c501d0b1SCristina Ciocan 		reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG);
167471e6ca61SCristina Ciocan 
167571e6ca61SCristina Ciocan 		if (!reg) {
167671e6ca61SCristina Ciocan 			dev_warn(&vg->pdev->dev,
167771e6ca61SCristina Ciocan 				 "Pin %i: could not retrieve irq status reg\n",
167871e6ca61SCristina Ciocan 				 base);
167971e6ca61SCristina Ciocan 			continue;
168071e6ca61SCristina Ciocan 		}
168171e6ca61SCristina Ciocan 
16825fae8b86SMika Westerberg 		writel(0xffffffff, reg);
16835fae8b86SMika Westerberg 		/* make sure trigger bits are cleared, if not then a pin
16845fae8b86SMika Westerberg 		   might be misconfigured in bios */
16855fae8b86SMika Westerberg 		value = readl(reg);
16865fae8b86SMika Westerberg 		if (value)
16875fae8b86SMika Westerberg 			dev_err(&vg->pdev->dev,
16885fae8b86SMika Westerberg 				"GPIO interrupt error, pins misconfigured\n");
16895fae8b86SMika Westerberg 	}
16905fae8b86SMika Westerberg }
16915fae8b86SMika Westerberg 
169271e6ca61SCristina Ciocan static int byt_gpio_probe(struct byt_gpio *vg)
16935fae8b86SMika Westerberg {
16945fae8b86SMika Westerberg 	struct gpio_chip *gc;
169571e6ca61SCristina Ciocan 	struct resource *irq_rc;
16965fae8b86SMika Westerberg 	int ret;
16975fae8b86SMika Westerberg 
169871e6ca61SCristina Ciocan 	/* Set up gpio chip */
169971e6ca61SCristina Ciocan 	vg->chip	= byt_gpio_chip;
17005fae8b86SMika Westerberg 	gc		= &vg->chip;
170171e6ca61SCristina Ciocan 	gc->label	= dev_name(&vg->pdev->dev);
17025fae8b86SMika Westerberg 	gc->base	= -1;
17035fae8b86SMika Westerberg 	gc->can_sleep	= false;
170471e6ca61SCristina Ciocan 	gc->parent	= &vg->pdev->dev;
170571e6ca61SCristina Ciocan 	gc->ngpio	= vg->soc_data->npins;
1706dc7b0387SThierry Reding 	gc->irq.need_valid_mask	= true;
17075fae8b86SMika Westerberg 
1708fcc18debSMika Westerberg #ifdef CONFIG_PM_SLEEP
170971e6ca61SCristina Ciocan 	vg->saved_context = devm_kcalloc(&vg->pdev->dev, gc->ngpio,
1710fcc18debSMika Westerberg 				       sizeof(*vg->saved_context), GFP_KERNEL);
1711fcc18debSMika Westerberg #endif
17120612413fSAndy Shevchenko 	ret = devm_gpiochip_add_data(&vg->pdev->dev, gc, vg);
17135fae8b86SMika Westerberg 	if (ret) {
171471e6ca61SCristina Ciocan 		dev_err(&vg->pdev->dev, "failed adding byt-gpio chip\n");
17155fae8b86SMika Westerberg 		return ret;
17165fae8b86SMika Westerberg 	}
17175fae8b86SMika Westerberg 
171871e6ca61SCristina Ciocan 	ret = gpiochip_add_pin_range(&vg->chip, dev_name(&vg->pdev->dev),
171971e6ca61SCristina Ciocan 				     0, 0, vg->soc_data->npins);
172071e6ca61SCristina Ciocan 	if (ret) {
172171e6ca61SCristina Ciocan 		dev_err(&vg->pdev->dev, "failed to add GPIO pin range\n");
17220612413fSAndy Shevchenko 		return ret;
172371e6ca61SCristina Ciocan 	}
172471e6ca61SCristina Ciocan 
17255fae8b86SMika Westerberg 	/* set up interrupts  */
172671e6ca61SCristina Ciocan 	irq_rc = platform_get_resource(vg->pdev, IORESOURCE_IRQ, 0);
17275fae8b86SMika Westerberg 	if (irq_rc && irq_rc->start) {
17285fae8b86SMika Westerberg 		byt_gpio_irq_init_hw(vg);
17295fae8b86SMika Westerberg 		ret = gpiochip_irqchip_add(gc, &byt_irqchip, 0,
17303ae02c14SAndy Shevchenko 					   handle_bad_irq, IRQ_TYPE_NONE);
17315fae8b86SMika Westerberg 		if (ret) {
173271e6ca61SCristina Ciocan 			dev_err(&vg->pdev->dev, "failed to add irqchip\n");
17330612413fSAndy Shevchenko 			return ret;
17345fae8b86SMika Westerberg 		}
17355fae8b86SMika Westerberg 
17365fae8b86SMika Westerberg 		gpiochip_set_chained_irqchip(gc, &byt_irqchip,
17375fae8b86SMika Westerberg 					     (unsigned)irq_rc->start,
17385fae8b86SMika Westerberg 					     byt_gpio_irq_handler);
17395fae8b86SMika Westerberg 	}
17405fae8b86SMika Westerberg 
174171e6ca61SCristina Ciocan 	return ret;
174271e6ca61SCristina Ciocan }
174371e6ca61SCristina Ciocan 
174471e6ca61SCristina Ciocan static int byt_set_soc_data(struct byt_gpio *vg,
174571e6ca61SCristina Ciocan 			    const struct byt_pinctrl_soc_data *soc_data)
174671e6ca61SCristina Ciocan {
174771e6ca61SCristina Ciocan 	int i;
174871e6ca61SCristina Ciocan 
174971e6ca61SCristina Ciocan 	vg->soc_data = soc_data;
175071e6ca61SCristina Ciocan 	vg->communities_copy = devm_kcalloc(&vg->pdev->dev,
175171e6ca61SCristina Ciocan 					    soc_data->ncommunities,
175271e6ca61SCristina Ciocan 					    sizeof(*vg->communities_copy),
175371e6ca61SCristina Ciocan 					    GFP_KERNEL);
175471e6ca61SCristina Ciocan 	if (!vg->communities_copy)
175571e6ca61SCristina Ciocan 		return -ENOMEM;
175671e6ca61SCristina Ciocan 
175771e6ca61SCristina Ciocan 	for (i = 0; i < soc_data->ncommunities; i++) {
175871e6ca61SCristina Ciocan 		struct byt_community *comm = vg->communities_copy + i;
175971e6ca61SCristina Ciocan 		struct resource *mem_rc;
176071e6ca61SCristina Ciocan 
176171e6ca61SCristina Ciocan 		*comm = vg->soc_data->communities[i];
176271e6ca61SCristina Ciocan 
176371e6ca61SCristina Ciocan 		mem_rc = platform_get_resource(vg->pdev, IORESOURCE_MEM, 0);
176471e6ca61SCristina Ciocan 		comm->reg_base = devm_ioremap_resource(&vg->pdev->dev, mem_rc);
176571e6ca61SCristina Ciocan 		if (IS_ERR(comm->reg_base))
176671e6ca61SCristina Ciocan 			return PTR_ERR(comm->reg_base);
176771e6ca61SCristina Ciocan 	}
176871e6ca61SCristina Ciocan 
176971e6ca61SCristina Ciocan 	return 0;
177071e6ca61SCristina Ciocan }
177171e6ca61SCristina Ciocan 
177271e6ca61SCristina Ciocan static const struct acpi_device_id byt_gpio_acpi_match[] = {
177371e6ca61SCristina Ciocan 	{ "INT33B2", (kernel_ulong_t)byt_soc_data },
177471e6ca61SCristina Ciocan 	{ "INT33FC", (kernel_ulong_t)byt_soc_data },
177571e6ca61SCristina Ciocan 	{ }
177671e6ca61SCristina Ciocan };
177771e6ca61SCristina Ciocan MODULE_DEVICE_TABLE(acpi, byt_gpio_acpi_match);
177871e6ca61SCristina Ciocan 
177971e6ca61SCristina Ciocan static int byt_pinctrl_probe(struct platform_device *pdev)
178071e6ca61SCristina Ciocan {
178171e6ca61SCristina Ciocan 	const struct byt_pinctrl_soc_data *soc_data = NULL;
178271e6ca61SCristina Ciocan 	const struct byt_pinctrl_soc_data **soc_table;
178371e6ca61SCristina Ciocan 	const struct acpi_device_id *acpi_id;
178471e6ca61SCristina Ciocan 	struct acpi_device *acpi_dev;
178571e6ca61SCristina Ciocan 	struct byt_gpio *vg;
178671e6ca61SCristina Ciocan 	int i, ret;
178771e6ca61SCristina Ciocan 
178871e6ca61SCristina Ciocan 	acpi_dev = ACPI_COMPANION(&pdev->dev);
178971e6ca61SCristina Ciocan 	if (!acpi_dev)
179071e6ca61SCristina Ciocan 		return -ENODEV;
179171e6ca61SCristina Ciocan 
179271e6ca61SCristina Ciocan 	acpi_id = acpi_match_device(byt_gpio_acpi_match, &pdev->dev);
179371e6ca61SCristina Ciocan 	if (!acpi_id)
179471e6ca61SCristina Ciocan 		return -ENODEV;
179571e6ca61SCristina Ciocan 
179671e6ca61SCristina Ciocan 	soc_table = (const struct byt_pinctrl_soc_data **)acpi_id->driver_data;
179771e6ca61SCristina Ciocan 
179871e6ca61SCristina Ciocan 	for (i = 0; soc_table[i]; i++) {
179971e6ca61SCristina Ciocan 		if (!strcmp(acpi_dev->pnp.unique_id, soc_table[i]->uid)) {
180071e6ca61SCristina Ciocan 			soc_data = soc_table[i];
180171e6ca61SCristina Ciocan 			break;
180271e6ca61SCristina Ciocan 		}
180371e6ca61SCristina Ciocan 	}
180471e6ca61SCristina Ciocan 
180571e6ca61SCristina Ciocan 	if (!soc_data)
180671e6ca61SCristina Ciocan 		return -ENODEV;
180771e6ca61SCristina Ciocan 
180871e6ca61SCristina Ciocan 	vg = devm_kzalloc(&pdev->dev, sizeof(*vg), GFP_KERNEL);
180971e6ca61SCristina Ciocan 	if (!vg)
181071e6ca61SCristina Ciocan 		return -ENOMEM;
181171e6ca61SCristina Ciocan 
181271e6ca61SCristina Ciocan 	vg->pdev = pdev;
181371e6ca61SCristina Ciocan 	ret = byt_set_soc_data(vg, soc_data);
181471e6ca61SCristina Ciocan 	if (ret) {
181571e6ca61SCristina Ciocan 		dev_err(&pdev->dev, "failed to set soc data\n");
181671e6ca61SCristina Ciocan 		return ret;
181771e6ca61SCristina Ciocan 	}
181871e6ca61SCristina Ciocan 
181971e6ca61SCristina Ciocan 	vg->pctl_desc		= byt_pinctrl_desc;
182071e6ca61SCristina Ciocan 	vg->pctl_desc.name	= dev_name(&pdev->dev);
182171e6ca61SCristina Ciocan 	vg->pctl_desc.pins	= vg->soc_data->pins;
182271e6ca61SCristina Ciocan 	vg->pctl_desc.npins	= vg->soc_data->npins;
182371e6ca61SCristina Ciocan 
18240612413fSAndy Shevchenko 	vg->pctl_dev = devm_pinctrl_register(&pdev->dev, &vg->pctl_desc, vg);
182571e6ca61SCristina Ciocan 	if (IS_ERR(vg->pctl_dev)) {
182671e6ca61SCristina Ciocan 		dev_err(&pdev->dev, "failed to register pinctrl driver\n");
182771e6ca61SCristina Ciocan 		return PTR_ERR(vg->pctl_dev);
182871e6ca61SCristina Ciocan 	}
182971e6ca61SCristina Ciocan 
1830a171bc51SVille Syrjälä 	raw_spin_lock_init(&vg->lock);
1831a171bc51SVille Syrjälä 
183271e6ca61SCristina Ciocan 	ret = byt_gpio_probe(vg);
18330612413fSAndy Shevchenko 	if (ret)
183471e6ca61SCristina Ciocan 		return ret;
183571e6ca61SCristina Ciocan 
183671e6ca61SCristina Ciocan 	platform_set_drvdata(pdev, vg);
183771e6ca61SCristina Ciocan 	pm_runtime_enable(&pdev->dev);
183871e6ca61SCristina Ciocan 
183971e6ca61SCristina Ciocan 	return 0;
184071e6ca61SCristina Ciocan }
184171e6ca61SCristina Ciocan 
1842fcc18debSMika Westerberg #ifdef CONFIG_PM_SLEEP
1843fcc18debSMika Westerberg static int byt_gpio_suspend(struct device *dev)
1844fcc18debSMika Westerberg {
1845fcc18debSMika Westerberg 	struct platform_device *pdev = to_platform_device(dev);
1846fcc18debSMika Westerberg 	struct byt_gpio *vg = platform_get_drvdata(pdev);
1847fcc18debSMika Westerberg 	int i;
1848fcc18debSMika Westerberg 
184971e6ca61SCristina Ciocan 	for (i = 0; i < vg->soc_data->npins; i++) {
1850fcc18debSMika Westerberg 		void __iomem *reg;
1851fcc18debSMika Westerberg 		u32 value;
185271e6ca61SCristina Ciocan 		unsigned int pin = vg->soc_data->pins[i].number;
1853fcc18debSMika Westerberg 
185471e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
185571e6ca61SCristina Ciocan 		if (!reg) {
185671e6ca61SCristina Ciocan 			dev_warn(&vg->pdev->dev,
185771e6ca61SCristina Ciocan 				 "Pin %i: could not retrieve conf0 register\n",
185871e6ca61SCristina Ciocan 				 i);
185971e6ca61SCristina Ciocan 			continue;
186071e6ca61SCristina Ciocan 		}
1861fcc18debSMika Westerberg 		value = readl(reg) & BYT_CONF0_RESTORE_MASK;
1862fcc18debSMika Westerberg 		vg->saved_context[i].conf0 = value;
1863fcc18debSMika Westerberg 
186471e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
1865fcc18debSMika Westerberg 		value = readl(reg) & BYT_VAL_RESTORE_MASK;
1866fcc18debSMika Westerberg 		vg->saved_context[i].val = value;
1867fcc18debSMika Westerberg 	}
1868fcc18debSMika Westerberg 
1869fcc18debSMika Westerberg 	return 0;
1870fcc18debSMika Westerberg }
1871fcc18debSMika Westerberg 
1872fcc18debSMika Westerberg static int byt_gpio_resume(struct device *dev)
1873fcc18debSMika Westerberg {
1874fcc18debSMika Westerberg 	struct platform_device *pdev = to_platform_device(dev);
1875fcc18debSMika Westerberg 	struct byt_gpio *vg = platform_get_drvdata(pdev);
1876fcc18debSMika Westerberg 	int i;
1877fcc18debSMika Westerberg 
187871e6ca61SCristina Ciocan 	for (i = 0; i < vg->soc_data->npins; i++) {
1879fcc18debSMika Westerberg 		void __iomem *reg;
1880fcc18debSMika Westerberg 		u32 value;
188171e6ca61SCristina Ciocan 		unsigned int pin = vg->soc_data->pins[i].number;
1882fcc18debSMika Westerberg 
188371e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
188471e6ca61SCristina Ciocan 		if (!reg) {
188571e6ca61SCristina Ciocan 			dev_warn(&vg->pdev->dev,
188671e6ca61SCristina Ciocan 				 "Pin %i: could not retrieve conf0 register\n",
188771e6ca61SCristina Ciocan 				 i);
188871e6ca61SCristina Ciocan 			continue;
188971e6ca61SCristina Ciocan 		}
1890fcc18debSMika Westerberg 		value = readl(reg);
1891fcc18debSMika Westerberg 		if ((value & BYT_CONF0_RESTORE_MASK) !=
1892fcc18debSMika Westerberg 		     vg->saved_context[i].conf0) {
1893fcc18debSMika Westerberg 			value &= ~BYT_CONF0_RESTORE_MASK;
1894fcc18debSMika Westerberg 			value |= vg->saved_context[i].conf0;
1895fcc18debSMika Westerberg 			writel(value, reg);
1896fcc18debSMika Westerberg 			dev_info(dev, "restored pin %d conf0 %#08x", i, value);
1897fcc18debSMika Westerberg 		}
1898fcc18debSMika Westerberg 
189971e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
1900fcc18debSMika Westerberg 		value = readl(reg);
1901fcc18debSMika Westerberg 		if ((value & BYT_VAL_RESTORE_MASK) !=
1902fcc18debSMika Westerberg 		     vg->saved_context[i].val) {
1903fcc18debSMika Westerberg 			u32 v;
1904fcc18debSMika Westerberg 
1905fcc18debSMika Westerberg 			v = value & ~BYT_VAL_RESTORE_MASK;
1906fcc18debSMika Westerberg 			v |= vg->saved_context[i].val;
1907fcc18debSMika Westerberg 			if (v != value) {
1908fcc18debSMika Westerberg 				writel(v, reg);
1909fcc18debSMika Westerberg 				dev_dbg(dev, "restored pin %d val %#08x\n",
1910fcc18debSMika Westerberg 					i, v);
1911fcc18debSMika Westerberg 			}
1912fcc18debSMika Westerberg 		}
1913fcc18debSMika Westerberg 	}
1914fcc18debSMika Westerberg 
1915fcc18debSMika Westerberg 	return 0;
1916fcc18debSMika Westerberg }
1917fcc18debSMika Westerberg #endif
1918fcc18debSMika Westerberg 
1919ec879f12SMika Westerberg #ifdef CONFIG_PM
19205fae8b86SMika Westerberg static int byt_gpio_runtime_suspend(struct device *dev)
19215fae8b86SMika Westerberg {
19225fae8b86SMika Westerberg 	return 0;
19235fae8b86SMika Westerberg }
19245fae8b86SMika Westerberg 
19255fae8b86SMika Westerberg static int byt_gpio_runtime_resume(struct device *dev)
19265fae8b86SMika Westerberg {
19275fae8b86SMika Westerberg 	return 0;
19285fae8b86SMika Westerberg }
1929ec879f12SMika Westerberg #endif
19305fae8b86SMika Westerberg 
19315fae8b86SMika Westerberg static const struct dev_pm_ops byt_gpio_pm_ops = {
1932fcc18debSMika Westerberg 	SET_LATE_SYSTEM_SLEEP_PM_OPS(byt_gpio_suspend, byt_gpio_resume)
1933fcc18debSMika Westerberg 	SET_RUNTIME_PM_OPS(byt_gpio_runtime_suspend, byt_gpio_runtime_resume,
1934fcc18debSMika Westerberg 			   NULL)
19355fae8b86SMika Westerberg };
19365fae8b86SMika Westerberg 
19375fae8b86SMika Westerberg static struct platform_driver byt_gpio_driver = {
193871e6ca61SCristina Ciocan 	.probe          = byt_pinctrl_probe,
19395fae8b86SMika Westerberg 	.driver         = {
19405fae8b86SMika Westerberg 		.name			= "byt_gpio",
19415fae8b86SMika Westerberg 		.pm			= &byt_gpio_pm_ops,
1942360943a8SPaul Gortmaker 		.suppress_bind_attrs	= true,
1943360943a8SPaul Gortmaker 
19445fae8b86SMika Westerberg 		.acpi_match_table = ACPI_PTR(byt_gpio_acpi_match),
19455fae8b86SMika Westerberg 	},
19465fae8b86SMika Westerberg };
19475fae8b86SMika Westerberg 
19485fae8b86SMika Westerberg static int __init byt_gpio_init(void)
19495fae8b86SMika Westerberg {
19505fae8b86SMika Westerberg 	return platform_driver_register(&byt_gpio_driver);
19515fae8b86SMika Westerberg }
19525fae8b86SMika Westerberg subsys_initcall(byt_gpio_init);
1953