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