15fae8b86SMika Westerberg /*
25fae8b86SMika Westerberg  * Pinctrl GPIO driver for Intel Baytrail
35fae8b86SMika Westerberg  * Copyright (c) 2012-2013, Intel Corporation.
45fae8b86SMika Westerberg  *
55fae8b86SMika Westerberg  * Author: Mathias Nyman <mathias.nyman@linux.intel.com>
65fae8b86SMika Westerberg  *
75fae8b86SMika Westerberg  * This program is free software; you can redistribute it and/or modify it
85fae8b86SMika Westerberg  * under the terms and conditions of the GNU General Public License,
95fae8b86SMika Westerberg  * version 2, as published by the Free Software Foundation.
105fae8b86SMika Westerberg  *
115fae8b86SMika Westerberg  * This program is distributed in the hope it will be useful, but WITHOUT
125fae8b86SMika Westerberg  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
135fae8b86SMika Westerberg  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
145fae8b86SMika Westerberg  * more details.
155fae8b86SMika Westerberg  */
165fae8b86SMika Westerberg 
175fae8b86SMika Westerberg #include <linux/kernel.h>
185fae8b86SMika Westerberg #include <linux/module.h>
195fae8b86SMika Westerberg #include <linux/init.h>
205fae8b86SMika Westerberg #include <linux/types.h>
215fae8b86SMika Westerberg #include <linux/bitops.h>
225fae8b86SMika Westerberg #include <linux/interrupt.h>
2386e3ef81SCristina Ciocan #include <linux/gpio.h>
24bf9a5c96SLinus Walleij #include <linux/gpio/driver.h>
255fae8b86SMika Westerberg #include <linux/acpi.h>
265fae8b86SMika Westerberg #include <linux/platform_device.h>
275fae8b86SMika Westerberg #include <linux/seq_file.h>
285fae8b86SMika Westerberg #include <linux/io.h>
295fae8b86SMika Westerberg #include <linux/pm_runtime.h>
305fae8b86SMika Westerberg #include <linux/pinctrl/pinctrl.h>
31c501d0b1SCristina Ciocan #include <linux/pinctrl/pinmux.h>
32c501d0b1SCristina Ciocan #include <linux/pinctrl/pinconf.h>
33c501d0b1SCristina Ciocan #include <linux/pinctrl/pinconf-generic.h>
345fae8b86SMika Westerberg 
355fae8b86SMika Westerberg /* memory mapped register offsets */
365fae8b86SMika Westerberg #define BYT_CONF0_REG		0x000
375fae8b86SMika Westerberg #define BYT_CONF1_REG		0x004
385fae8b86SMika Westerberg #define BYT_VAL_REG		0x008
395fae8b86SMika Westerberg #define BYT_DFT_REG		0x00c
405fae8b86SMika Westerberg #define BYT_INT_STAT_REG	0x800
41658b476cSCristina Ciocan #define BYT_DEBOUNCE_REG	0x9d0
425fae8b86SMika Westerberg 
435fae8b86SMika Westerberg /* BYT_CONF0_REG register bits */
445fae8b86SMika Westerberg #define BYT_IODEN		BIT(31)
455fae8b86SMika Westerberg #define BYT_DIRECT_IRQ_EN	BIT(27)
465fae8b86SMika Westerberg #define BYT_TRIG_NEG		BIT(26)
475fae8b86SMika Westerberg #define BYT_TRIG_POS		BIT(25)
485fae8b86SMika Westerberg #define BYT_TRIG_LVL		BIT(24)
49658b476cSCristina Ciocan #define BYT_DEBOUNCE_EN		BIT(20)
505fae8b86SMika Westerberg #define BYT_PULL_STR_SHIFT	9
515fae8b86SMika Westerberg #define BYT_PULL_STR_MASK	(3 << BYT_PULL_STR_SHIFT)
525fae8b86SMika Westerberg #define BYT_PULL_STR_2K		(0 << BYT_PULL_STR_SHIFT)
535fae8b86SMika Westerberg #define BYT_PULL_STR_10K	(1 << BYT_PULL_STR_SHIFT)
545fae8b86SMika Westerberg #define BYT_PULL_STR_20K	(2 << BYT_PULL_STR_SHIFT)
555fae8b86SMika Westerberg #define BYT_PULL_STR_40K	(3 << BYT_PULL_STR_SHIFT)
565fae8b86SMika Westerberg #define BYT_PULL_ASSIGN_SHIFT	7
575fae8b86SMika Westerberg #define BYT_PULL_ASSIGN_MASK	(3 << BYT_PULL_ASSIGN_SHIFT)
585fae8b86SMika Westerberg #define BYT_PULL_ASSIGN_UP	(1 << BYT_PULL_ASSIGN_SHIFT)
595fae8b86SMika Westerberg #define BYT_PULL_ASSIGN_DOWN	(2 << BYT_PULL_ASSIGN_SHIFT)
605fae8b86SMika Westerberg #define BYT_PIN_MUX		0x07
615fae8b86SMika Westerberg 
625fae8b86SMika Westerberg /* BYT_VAL_REG register bits */
635fae8b86SMika Westerberg #define BYT_INPUT_EN		BIT(2)  /* 0: input enabled (active low)*/
645fae8b86SMika Westerberg #define BYT_OUTPUT_EN		BIT(1)  /* 0: output enabled (active low)*/
655fae8b86SMika Westerberg #define BYT_LEVEL		BIT(0)
665fae8b86SMika Westerberg 
675fae8b86SMika Westerberg #define BYT_DIR_MASK		(BIT(1) | BIT(2))
685fae8b86SMika Westerberg #define BYT_TRIG_MASK		(BIT(26) | BIT(25) | BIT(24))
695fae8b86SMika Westerberg 
70fcc18debSMika Westerberg #define BYT_CONF0_RESTORE_MASK	(BYT_DIRECT_IRQ_EN | BYT_TRIG_MASK | \
71fcc18debSMika Westerberg 				 BYT_PIN_MUX)
72fcc18debSMika Westerberg #define BYT_VAL_RESTORE_MASK	(BYT_DIR_MASK | BYT_LEVEL)
73fcc18debSMika Westerberg 
74658b476cSCristina Ciocan /* BYT_DEBOUNCE_REG bits */
75658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_MASK		0x7
76658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_375US	1
77658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_750US	2
78658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_1500US	3
79658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_3MS		4
80658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_6MS		5
81658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_12MS		6
82658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_24MS		7
83658b476cSCristina Ciocan 
845fae8b86SMika Westerberg #define BYT_NGPIO_SCORE		102
855fae8b86SMika Westerberg #define BYT_NGPIO_NCORE		28
865fae8b86SMika Westerberg #define BYT_NGPIO_SUS		44
875fae8b86SMika Westerberg 
885fae8b86SMika Westerberg #define BYT_SCORE_ACPI_UID	"1"
895fae8b86SMika Westerberg #define BYT_NCORE_ACPI_UID	"2"
905fae8b86SMika Westerberg #define BYT_SUS_ACPI_UID	"3"
915fae8b86SMika Westerberg 
92c501d0b1SCristina Ciocan /*
93c501d0b1SCristina Ciocan  * This is the function value most pins have for GPIO muxing. If the value
94c501d0b1SCristina Ciocan  * differs from the default one, it must be explicitly mentioned. Otherwise, the
95c501d0b1SCristina Ciocan  * pin control implementation will set the muxing value to default GPIO if it
96c501d0b1SCristina Ciocan  * does not find a match for the requested function.
97c501d0b1SCristina Ciocan  */
98c501d0b1SCristina Ciocan #define BYT_DEFAULT_GPIO_MUX	0
99c501d0b1SCristina Ciocan 
100c8f5c4c7SCristina Ciocan struct byt_gpio_pin_context {
101c8f5c4c7SCristina Ciocan 	u32 conf0;
102c8f5c4c7SCristina Ciocan 	u32 val;
103c8f5c4c7SCristina Ciocan };
1045fae8b86SMika Westerberg 
105c8f5c4c7SCristina Ciocan struct byt_simple_func_mux {
106c8f5c4c7SCristina Ciocan 	const char *name;
107c8f5c4c7SCristina Ciocan 	unsigned short func;
108c8f5c4c7SCristina Ciocan };
109c8f5c4c7SCristina Ciocan 
110c8f5c4c7SCristina Ciocan struct byt_mixed_func_mux {
111c8f5c4c7SCristina Ciocan 	const char *name;
112c8f5c4c7SCristina Ciocan 	const unsigned short *func_values;
113c8f5c4c7SCristina Ciocan };
114c8f5c4c7SCristina Ciocan 
115c8f5c4c7SCristina Ciocan struct byt_pingroup {
116c8f5c4c7SCristina Ciocan 	const char *name;
117c8f5c4c7SCristina Ciocan 	const unsigned int *pins;
118c8f5c4c7SCristina Ciocan 	size_t npins;
119c8f5c4c7SCristina Ciocan 	unsigned short has_simple_funcs;
120c8f5c4c7SCristina Ciocan 	union {
121c8f5c4c7SCristina Ciocan 		const struct byt_simple_func_mux *simple_funcs;
122c8f5c4c7SCristina Ciocan 		const struct byt_mixed_func_mux *mixed_funcs;
123c8f5c4c7SCristina Ciocan 	};
124c8f5c4c7SCristina Ciocan 	size_t nfuncs;
125c8f5c4c7SCristina Ciocan };
126c8f5c4c7SCristina Ciocan 
127c8f5c4c7SCristina Ciocan struct byt_function {
128c8f5c4c7SCristina Ciocan 	const char *name;
129c8f5c4c7SCristina Ciocan 	const char * const *groups;
130c8f5c4c7SCristina Ciocan 	size_t ngroups;
131c8f5c4c7SCristina Ciocan };
132c8f5c4c7SCristina Ciocan 
133c8f5c4c7SCristina Ciocan struct byt_community {
134c8f5c4c7SCristina Ciocan 	unsigned int pin_base;
135c8f5c4c7SCristina Ciocan 	size_t npins;
136c8f5c4c7SCristina Ciocan 	const unsigned int *pad_map;
137c8f5c4c7SCristina Ciocan 	void __iomem *reg_base;
138c8f5c4c7SCristina Ciocan };
139c8f5c4c7SCristina Ciocan 
140c8f5c4c7SCristina Ciocan #define SIMPLE_FUNC(n, f)	\
141c8f5c4c7SCristina Ciocan 	{			\
142c8f5c4c7SCristina Ciocan 		.name	= (n),	\
143c8f5c4c7SCristina Ciocan 		.func	= (f),	\
144c8f5c4c7SCristina Ciocan 	}
145c8f5c4c7SCristina Ciocan #define MIXED_FUNC(n, f)		\
146c8f5c4c7SCristina Ciocan 	{				\
147c8f5c4c7SCristina Ciocan 		.name		= (n),	\
148c8f5c4c7SCristina Ciocan 		.func_values	= (f),	\
149c8f5c4c7SCristina Ciocan 	}
150c8f5c4c7SCristina Ciocan 
151c8f5c4c7SCristina Ciocan #define PIN_GROUP_SIMPLE(n, p, f)				\
152c8f5c4c7SCristina Ciocan 	{							\
153c8f5c4c7SCristina Ciocan 		.name			= (n),			\
154c8f5c4c7SCristina Ciocan 		.pins			= (p),			\
155c8f5c4c7SCristina Ciocan 		.npins			= ARRAY_SIZE((p)),	\
156c8f5c4c7SCristina Ciocan 		.has_simple_funcs	= 1,			\
157bbccb9c7SAndrew Morton 		{						\
158c8f5c4c7SCristina Ciocan 			.simple_funcs		= (f),		\
159bbccb9c7SAndrew Morton 		},						\
160c8f5c4c7SCristina Ciocan 		.nfuncs			= ARRAY_SIZE((f)),	\
161c8f5c4c7SCristina Ciocan 	}
162c8f5c4c7SCristina Ciocan #define PIN_GROUP_MIXED(n, p, f)				\
163c8f5c4c7SCristina Ciocan 	{							\
164c8f5c4c7SCristina Ciocan 		.name			= (n),			\
165c8f5c4c7SCristina Ciocan 		.pins			= (p),			\
166c8f5c4c7SCristina Ciocan 		.npins			= ARRAY_SIZE((p)),	\
167c8f5c4c7SCristina Ciocan 		.has_simple_funcs	= 0,			\
168bbccb9c7SAndrew Morton 		{						\
169c8f5c4c7SCristina Ciocan 			.mixed_funcs		= (f),		\
170bbccb9c7SAndrew Morton 		},						\
171c8f5c4c7SCristina Ciocan 		.nfuncs			= ARRAY_SIZE((f)),	\
172c8f5c4c7SCristina Ciocan 	}
173c8f5c4c7SCristina Ciocan 
174c8f5c4c7SCristina Ciocan #define FUNCTION(n, g)					\
175c8f5c4c7SCristina Ciocan 	{						\
176c8f5c4c7SCristina Ciocan 		.name		= (n),			\
177c8f5c4c7SCristina Ciocan 		.groups		= (g),			\
178c8f5c4c7SCristina Ciocan 		.ngroups	= ARRAY_SIZE((g)),	\
179c8f5c4c7SCristina Ciocan 	}
180c8f5c4c7SCristina Ciocan 
181c8f5c4c7SCristina Ciocan #define COMMUNITY(p, n, map)		\
182c8f5c4c7SCristina Ciocan 	{				\
183c8f5c4c7SCristina Ciocan 		.pin_base	= (p),	\
184c8f5c4c7SCristina Ciocan 		.npins		= (n),	\
185c8f5c4c7SCristina Ciocan 		.pad_map	= (map),\
186c8f5c4c7SCristina Ciocan 	}
187c8f5c4c7SCristina Ciocan 
188c8f5c4c7SCristina Ciocan struct byt_pinctrl_soc_data {
189c8f5c4c7SCristina Ciocan 	const char *uid;
190c8f5c4c7SCristina Ciocan 	const struct pinctrl_pin_desc *pins;
191c8f5c4c7SCristina Ciocan 	size_t npins;
192c8f5c4c7SCristina Ciocan 	const struct byt_pingroup *groups;
193c8f5c4c7SCristina Ciocan 	size_t ngroups;
194c8f5c4c7SCristina Ciocan 	const struct byt_function *functions;
195c8f5c4c7SCristina Ciocan 	size_t nfunctions;
196c8f5c4c7SCristina Ciocan 	const struct byt_community *communities;
197c8f5c4c7SCristina Ciocan 	size_t ncommunities;
198c8f5c4c7SCristina Ciocan };
199c8f5c4c7SCristina Ciocan 
20071e6ca61SCristina Ciocan struct byt_gpio {
20171e6ca61SCristina Ciocan 	struct gpio_chip chip;
20271e6ca61SCristina Ciocan 	struct platform_device *pdev;
20371e6ca61SCristina Ciocan 	struct pinctrl_dev *pctl_dev;
20471e6ca61SCristina Ciocan 	struct pinctrl_desc pctl_desc;
20571e6ca61SCristina Ciocan 	raw_spinlock_t lock;
20671e6ca61SCristina Ciocan 	const struct byt_pinctrl_soc_data *soc_data;
20771e6ca61SCristina Ciocan 	struct byt_community *communities_copy;
20871e6ca61SCristina Ciocan 	struct byt_gpio_pin_context *saved_context;
20971e6ca61SCristina Ciocan };
21071e6ca61SCristina Ciocan 
211c8f5c4c7SCristina Ciocan /* SCORE pins, aka GPIOC_<pin_no> or GPIO_S0_SC[<pin_no>] */
212c8f5c4c7SCristina Ciocan static const struct pinctrl_pin_desc byt_score_pins[] = {
213c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(0, "SATA_GP0"),
214c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(1, "SATA_GP1"),
215c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(2, "SATA_LED#"),
216c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(3, "PCIE_CLKREQ0"),
217c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(4, "PCIE_CLKREQ1"),
218c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(5, "PCIE_CLKREQ2"),
219c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(6, "PCIE_CLKREQ3"),
220c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(7, "SD3_WP"),
221c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(8, "HDA_RST"),
222c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(9, "HDA_SYNC"),
223c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(10, "HDA_CLK"),
224c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(11, "HDA_SDO"),
225c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(12, "HDA_SDI0"),
226c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(13, "HDA_SDI1"),
227c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(14, "GPIO_S0_SC14"),
228c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(15, "GPIO_S0_SC15"),
229c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(16, "MMC1_CLK"),
230c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(17, "MMC1_D0"),
231c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(18, "MMC1_D1"),
232c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(19, "MMC1_D2"),
233c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(20, "MMC1_D3"),
234c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(21, "MMC1_D4"),
235c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(22, "MMC1_D5"),
236c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(23, "MMC1_D6"),
237c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(24, "MMC1_D7"),
238c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(25, "MMC1_CMD"),
239c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(26, "MMC1_RST"),
240c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(27, "SD2_CLK"),
241c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(28, "SD2_D0"),
242c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(29, "SD2_D1"),
243c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(30, "SD2_D2"),
244c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(31, "SD2_D3_CD"),
245c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(32, "SD2_CMD"),
246c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(33, "SD3_CLK"),
247c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(34, "SD3_D0"),
248c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(35, "SD3_D1"),
249c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(36, "SD3_D2"),
250c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(37, "SD3_D3"),
251c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(38, "SD3_CD"),
252c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(39, "SD3_CMD"),
253c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(40, "SD3_1P8EN"),
254c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(41, "SD3_PWREN#"),
255c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(42, "ILB_LPC_AD0"),
256c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(43, "ILB_LPC_AD1"),
257c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(44, "ILB_LPC_AD2"),
258c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(45, "ILB_LPC_AD3"),
259c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(46, "ILB_LPC_FRAME"),
260c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(47, "ILB_LPC_CLK0"),
261c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(48, "ILB_LPC_CLK1"),
262c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(49, "ILB_LPC_CLKRUN"),
263c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(50, "ILB_LPC_SERIRQ"),
264c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(51, "PCU_SMB_DATA"),
265c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(52, "PCU_SMB_CLK"),
266c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(53, "PCU_SMB_ALERT"),
267c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(54, "ILB_8254_SPKR"),
268c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(55, "GPIO_S0_SC55"),
269c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(56, "GPIO_S0_SC56"),
270c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(57, "GPIO_S0_SC57"),
271c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(58, "GPIO_S0_SC58"),
272c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(59, "GPIO_S0_SC59"),
273c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(60, "GPIO_S0_SC60"),
274c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(61, "GPIO_S0_SC61"),
275c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(62, "LPE_I2S2_CLK"),
276c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(63, "LPE_I2S2_FRM"),
277c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(64, "LPE_I2S2_DATAIN"),
278c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(65, "LPE_I2S2_DATAOUT"),
279c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(66, "SIO_SPI_CS"),
280c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(67, "SIO_SPI_MISO"),
281c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(68, "SIO_SPI_MOSI"),
282c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(69, "SIO_SPI_CLK"),
283c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(70, "SIO_UART1_RXD"),
284c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(71, "SIO_UART1_TXD"),
285c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(72, "SIO_UART1_RTS"),
286c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(73, "SIO_UART1_CTS"),
287c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(74, "SIO_UART2_RXD"),
288c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(75, "SIO_UART2_TXD"),
289c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(76, "SIO_UART2_RTS"),
290c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(77, "SIO_UART2_CTS"),
291c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(78, "SIO_I2C0_DATA"),
292c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(79, "SIO_I2C0_CLK"),
293c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(80, "SIO_I2C1_DATA"),
294c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(81, "SIO_I2C1_CLK"),
295c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(82, "SIO_I2C2_DATA"),
296c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(83, "SIO_I2C2_CLK"),
297c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(84, "SIO_I2C3_DATA"),
298c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(85, "SIO_I2C3_CLK"),
299c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(86, "SIO_I2C4_DATA"),
300c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(87, "SIO_I2C4_CLK"),
301c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(88, "SIO_I2C5_DATA"),
302c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(89, "SIO_I2C5_CLK"),
303c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(90, "SIO_I2C6_DATA"),
304c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(91, "SIO_I2C6_CLK"),
305c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(92, "GPIO_S0_SC92"),
306c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(93, "GPIO_S0_SC93"),
307c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(94, "SIO_PWM0"),
308c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(95, "SIO_PWM1"),
309c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(96, "PMC_PLT_CLK0"),
310c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(97, "PMC_PLT_CLK1"),
311c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(98, "PMC_PLT_CLK2"),
312c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(99, "PMC_PLT_CLK3"),
313c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(100, "PMC_PLT_CLK4"),
314c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(101, "PMC_PLT_CLK5"),
315c8f5c4c7SCristina Ciocan };
3165fae8b86SMika Westerberg 
317c8f5c4c7SCristina Ciocan static const unsigned int byt_score_pins_map[BYT_NGPIO_SCORE] = {
318c8f5c4c7SCristina Ciocan 	85, 89, 93, 96, 99, 102, 98, 101, 34, 37,
319c8f5c4c7SCristina Ciocan 	36, 38, 39, 35, 40, 84, 62, 61, 64, 59,
320c8f5c4c7SCristina Ciocan 	54, 56, 60, 55, 63, 57, 51, 50, 53, 47,
321c8f5c4c7SCristina Ciocan 	52, 49, 48, 43, 46, 41, 45, 42, 58, 44,
322c8f5c4c7SCristina Ciocan 	95, 105, 70, 68, 67, 66, 69, 71, 65, 72,
323c8f5c4c7SCristina Ciocan 	86, 90, 88, 92, 103, 77, 79, 83, 78, 81,
324c8f5c4c7SCristina Ciocan 	80, 82, 13, 12, 15, 14, 17, 18, 19, 16,
325c8f5c4c7SCristina Ciocan 	2, 1, 0, 4, 6, 7, 9, 8, 33, 32,
326c8f5c4c7SCristina Ciocan 	31, 30, 29, 27, 25, 28, 26, 23, 21, 20,
327c8f5c4c7SCristina Ciocan 	24, 22, 5, 3, 10, 11, 106, 87, 91, 104,
328c8f5c4c7SCristina Ciocan 	97, 100,
3295fae8b86SMika Westerberg };
3305fae8b86SMika Westerberg 
331c8f5c4c7SCristina Ciocan /* SCORE groups */
332c8f5c4c7SCristina Ciocan static const unsigned int byt_score_uart1_pins[] = { 70, 71, 72, 73 };
333c8f5c4c7SCristina Ciocan static const unsigned int byt_score_uart2_pins[] = { 74, 75, 76, 77 };
334c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_score_uart_mux[] = {
335c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("uart", 1),
336c8f5c4c7SCristina Ciocan };
337c8f5c4c7SCristina Ciocan 
338c8f5c4c7SCristina Ciocan static const unsigned int byt_score_pwm0_pins[] = { 94 };
339c8f5c4c7SCristina Ciocan static const unsigned int byt_score_pwm1_pins[] = { 95 };
340c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_score_pwm_mux[] = {
341c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("pwm", 1),
342c8f5c4c7SCristina Ciocan };
343c8f5c4c7SCristina Ciocan 
344c8f5c4c7SCristina Ciocan static const unsigned int byt_score_sio_spi_pins[] = { 66, 67, 68, 69 };
345c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_score_spi_mux[] = {
346c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("spi", 1),
347c8f5c4c7SCristina Ciocan };
348c8f5c4c7SCristina Ciocan 
349c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c5_pins[] = { 88, 89 };
350c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c6_pins[] = { 90, 91 };
351c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c4_pins[] = { 86, 87 };
352c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c3_pins[] = { 84, 85 };
353c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c2_pins[] = { 82, 83 };
354c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c1_pins[] = { 80, 81 };
355c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c0_pins[] = { 78, 79 };
356c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_score_i2c_mux[] = {
357c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("i2c", 1),
358c8f5c4c7SCristina Ciocan };
359c8f5c4c7SCristina Ciocan 
360c8f5c4c7SCristina Ciocan static const unsigned int byt_score_ssp0_pins[] = { 8, 9, 10, 11 };
361c8f5c4c7SCristina Ciocan static const unsigned int byt_score_ssp1_pins[] = { 12, 13, 14, 15 };
362c8f5c4c7SCristina Ciocan static const unsigned int byt_score_ssp2_pins[] = { 62, 63, 64, 65 };
363c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_score_ssp_mux[] = {
364c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("ssp", 1),
365c8f5c4c7SCristina Ciocan };
366c8f5c4c7SCristina Ciocan 
367c8f5c4c7SCristina Ciocan static const unsigned int byt_score_sdcard_pins[] = {
368c8f5c4c7SCristina Ciocan 	7, 33, 34, 35, 36, 37, 38, 39, 40, 41,
369c8f5c4c7SCristina Ciocan };
370c8f5c4c7SCristina Ciocan static const unsigned short byt_score_sdcard_mux_values[] = {
371c8f5c4c7SCristina Ciocan 	2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
372c8f5c4c7SCristina Ciocan };
373c8f5c4c7SCristina Ciocan static const struct byt_mixed_func_mux byt_score_sdcard_mux[] = {
374c8f5c4c7SCristina Ciocan 	MIXED_FUNC("sdcard", byt_score_sdcard_mux_values),
375c8f5c4c7SCristina Ciocan };
376c8f5c4c7SCristina Ciocan 
377c8f5c4c7SCristina Ciocan static const unsigned int byt_score_sdio_pins[] = { 27, 28, 29, 30, 31, 32 };
378c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_score_sdio_mux[] = {
379c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("sdio", 1),
380c8f5c4c7SCristina Ciocan };
381c8f5c4c7SCristina Ciocan 
382c8f5c4c7SCristina Ciocan static const unsigned int byt_score_emmc_pins[] = {
383c8f5c4c7SCristina Ciocan 	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
384c8f5c4c7SCristina Ciocan };
385c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_score_emmc_mux[] = {
386c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("emmc", 1),
387c8f5c4c7SCristina Ciocan };
388c8f5c4c7SCristina Ciocan 
389c8f5c4c7SCristina Ciocan static const unsigned int byt_score_ilb_lpc_pins[] = {
390c8f5c4c7SCristina Ciocan 	42, 43, 44, 45, 46, 47, 48, 49, 50,
391c8f5c4c7SCristina Ciocan };
392c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_score_lpc_mux[] = {
393c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("lpc", 1),
394c8f5c4c7SCristina Ciocan };
395c8f5c4c7SCristina Ciocan 
396c8f5c4c7SCristina Ciocan static const unsigned int byt_score_sata_pins[] = { 0, 1, 2 };
397c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_score_sata_mux[] = {
398c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("sata", 1),
399c8f5c4c7SCristina Ciocan };
400c8f5c4c7SCristina Ciocan 
401c8f5c4c7SCristina Ciocan static const unsigned int byt_score_plt_clk0_pins[] = { 96 };
402c8f5c4c7SCristina Ciocan static const unsigned int byt_score_plt_clk1_pins[] = { 97 };
403c8f5c4c7SCristina Ciocan static const unsigned int byt_score_plt_clk2_pins[] = { 98 };
404c8f5c4c7SCristina Ciocan static const unsigned int byt_score_plt_clk4_pins[] = { 99 };
405c8f5c4c7SCristina Ciocan static const unsigned int byt_score_plt_clk5_pins[] = { 100 };
406c8f5c4c7SCristina Ciocan static const unsigned int byt_score_plt_clk3_pins[] = { 101 };
407c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_score_plt_clk_mux[] = {
408c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("plt_clk", 1),
409c8f5c4c7SCristina Ciocan };
410c8f5c4c7SCristina Ciocan 
411c8f5c4c7SCristina Ciocan static const unsigned int byt_score_smbus_pins[] = { 51, 52, 53 };
412c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_score_smbus_mux[] = {
413c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("smbus", 1),
414c8f5c4c7SCristina Ciocan };
415c8f5c4c7SCristina Ciocan 
416c8f5c4c7SCristina Ciocan static const struct byt_pingroup byt_score_groups[] = {
417c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("uart1_grp",
418c8f5c4c7SCristina Ciocan 			 byt_score_uart1_pins, byt_score_uart_mux),
419c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("uart2_grp",
420c8f5c4c7SCristina Ciocan 			 byt_score_uart2_pins, byt_score_uart_mux),
421c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("pwm0_grp",
422c8f5c4c7SCristina Ciocan 			 byt_score_pwm0_pins, byt_score_pwm_mux),
423c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("pwm1_grp",
424c8f5c4c7SCristina Ciocan 			 byt_score_pwm1_pins, byt_score_pwm_mux),
425c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("ssp2_grp",
426c8f5c4c7SCristina Ciocan 			 byt_score_ssp2_pins, byt_score_pwm_mux),
427c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("sio_spi_grp",
428c8f5c4c7SCristina Ciocan 			 byt_score_sio_spi_pins, byt_score_spi_mux),
429c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("i2c5_grp",
430c8f5c4c7SCristina Ciocan 			 byt_score_i2c5_pins, byt_score_i2c_mux),
431c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("i2c6_grp",
432c8f5c4c7SCristina Ciocan 			 byt_score_i2c6_pins, byt_score_i2c_mux),
433c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("i2c4_grp",
434c8f5c4c7SCristina Ciocan 			 byt_score_i2c4_pins, byt_score_i2c_mux),
435c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("i2c3_grp",
436c8f5c4c7SCristina Ciocan 			 byt_score_i2c3_pins, byt_score_i2c_mux),
437c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("i2c2_grp",
438c8f5c4c7SCristina Ciocan 			 byt_score_i2c2_pins, byt_score_i2c_mux),
439c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("i2c1_grp",
440c8f5c4c7SCristina Ciocan 			 byt_score_i2c1_pins, byt_score_i2c_mux),
441c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("i2c0_grp",
442c8f5c4c7SCristina Ciocan 			 byt_score_i2c0_pins, byt_score_i2c_mux),
443c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("ssp0_grp",
444c8f5c4c7SCristina Ciocan 			 byt_score_ssp0_pins, byt_score_ssp_mux),
445c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("ssp1_grp",
446c8f5c4c7SCristina Ciocan 			 byt_score_ssp1_pins, byt_score_ssp_mux),
447c8f5c4c7SCristina Ciocan 	PIN_GROUP_MIXED("sdcard_grp",
448c8f5c4c7SCristina Ciocan 			byt_score_sdcard_pins, byt_score_sdcard_mux),
449c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("sdio_grp",
450c8f5c4c7SCristina Ciocan 			 byt_score_sdio_pins, byt_score_sdio_mux),
451c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("emmc_grp",
452c8f5c4c7SCristina Ciocan 			 byt_score_emmc_pins, byt_score_emmc_mux),
453c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("lpc_grp",
454c8f5c4c7SCristina Ciocan 			 byt_score_ilb_lpc_pins, byt_score_lpc_mux),
455c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("sata_grp",
456c8f5c4c7SCristina Ciocan 			 byt_score_sata_pins, byt_score_sata_mux),
457c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("plt_clk0_grp",
458c8f5c4c7SCristina Ciocan 			 byt_score_plt_clk0_pins, byt_score_plt_clk_mux),
459c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("plt_clk1_grp",
460c8f5c4c7SCristina Ciocan 			 byt_score_plt_clk1_pins, byt_score_plt_clk_mux),
461c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("plt_clk2_grp",
462c8f5c4c7SCristina Ciocan 			 byt_score_plt_clk2_pins, byt_score_plt_clk_mux),
463c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("plt_clk3_grp",
464c8f5c4c7SCristina Ciocan 			 byt_score_plt_clk3_pins, byt_score_plt_clk_mux),
465c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("plt_clk4_grp",
466c8f5c4c7SCristina Ciocan 			 byt_score_plt_clk4_pins, byt_score_plt_clk_mux),
467c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("plt_clk5_grp",
468c8f5c4c7SCristina Ciocan 			 byt_score_plt_clk5_pins, byt_score_plt_clk_mux),
469c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("smbus_grp",
470c8f5c4c7SCristina Ciocan 			 byt_score_smbus_pins, byt_score_smbus_mux),
471c8f5c4c7SCristina Ciocan };
472c8f5c4c7SCristina Ciocan 
473c8f5c4c7SCristina Ciocan static const char * const byt_score_uart_groups[] = {
474c8f5c4c7SCristina Ciocan 	"uart1_grp", "uart2_grp",
475c8f5c4c7SCristina Ciocan };
476c8f5c4c7SCristina Ciocan static const char * const byt_score_pwm_groups[] = {
477c8f5c4c7SCristina Ciocan 	"pwm0_grp", "pwm1_grp",
478c8f5c4c7SCristina Ciocan };
479c8f5c4c7SCristina Ciocan static const char * const byt_score_ssp_groups[] = {
480c8f5c4c7SCristina Ciocan 	"ssp0_grp", "ssp1_grp", "ssp2_grp",
481c8f5c4c7SCristina Ciocan };
482c8f5c4c7SCristina Ciocan static const char * const byt_score_spi_groups[] = { "sio_spi_grp" };
483c8f5c4c7SCristina Ciocan static const char * const byt_score_i2c_groups[] = {
484c8f5c4c7SCristina Ciocan 	"i2c0_grp", "i2c1_grp", "i2c2_grp", "i2c3_grp", "i2c4_grp", "i2c5_grp",
485c8f5c4c7SCristina Ciocan 	"i2c6_grp",
486c8f5c4c7SCristina Ciocan };
487c8f5c4c7SCristina Ciocan static const char * const byt_score_sdcard_groups[] = { "sdcard_grp" };
488c8f5c4c7SCristina Ciocan static const char * const byt_score_sdio_groups[] = { "sdio_grp" };
489c8f5c4c7SCristina Ciocan static const char * const byt_score_emmc_groups[] = { "emmc_grp" };
490c8f5c4c7SCristina Ciocan static const char * const byt_score_lpc_groups[] = { "lpc_grp" };
491c8f5c4c7SCristina Ciocan static const char * const byt_score_sata_groups[] = { "sata_grp" };
492c8f5c4c7SCristina Ciocan static const char * const byt_score_plt_clk_groups[] = {
493c8f5c4c7SCristina Ciocan 	"plt_clk0_grp", "plt_clk1_grp", "plt_clk2_grp", "plt_clk3_grp",
494c8f5c4c7SCristina Ciocan 	"plt_clk4_grp", "plt_clk5_grp",
495c8f5c4c7SCristina Ciocan };
496c8f5c4c7SCristina Ciocan static const char * const byt_score_smbus_groups[] = { "smbus_grp" };
497c8f5c4c7SCristina Ciocan static const char * const byt_score_gpio_groups[] = {
498c8f5c4c7SCristina Ciocan 	"uart1_grp", "uart2_grp", "pwm0_grp", "pwm1_grp", "ssp0_grp",
499c8f5c4c7SCristina Ciocan 	"ssp1_grp", "ssp2_grp", "sio_spi_grp", "i2c0_grp", "i2c1_grp",
500c8f5c4c7SCristina Ciocan 	"i2c2_grp", "i2c3_grp", "i2c4_grp", "i2c5_grp", "i2c6_grp",
501c8f5c4c7SCristina Ciocan 	"sdcard_grp", "sdio_grp", "emmc_grp", "lpc_grp", "sata_grp",
502c8f5c4c7SCristina Ciocan 	"plt_clk0_grp", "plt_clk1_grp", "plt_clk2_grp", "plt_clk3_grp",
503c8f5c4c7SCristina Ciocan 	"plt_clk4_grp", "plt_clk5_grp", "smbus_grp",
504c8f5c4c7SCristina Ciocan 
505c8f5c4c7SCristina Ciocan };
506c8f5c4c7SCristina Ciocan 
507c8f5c4c7SCristina Ciocan static const struct byt_function byt_score_functions[] = {
508c8f5c4c7SCristina Ciocan 	FUNCTION("uart", byt_score_uart_groups),
509c8f5c4c7SCristina Ciocan 	FUNCTION("pwm", byt_score_pwm_groups),
510c8f5c4c7SCristina Ciocan 	FUNCTION("ssp", byt_score_ssp_groups),
511c8f5c4c7SCristina Ciocan 	FUNCTION("spi", byt_score_spi_groups),
512c8f5c4c7SCristina Ciocan 	FUNCTION("i2c", byt_score_i2c_groups),
513c8f5c4c7SCristina Ciocan 	FUNCTION("sdcard", byt_score_sdcard_groups),
514c8f5c4c7SCristina Ciocan 	FUNCTION("sdio", byt_score_sdio_groups),
515c8f5c4c7SCristina Ciocan 	FUNCTION("emmc", byt_score_emmc_groups),
516c8f5c4c7SCristina Ciocan 	FUNCTION("lpc", byt_score_lpc_groups),
517c8f5c4c7SCristina Ciocan 	FUNCTION("sata", byt_score_sata_groups),
518c8f5c4c7SCristina Ciocan 	FUNCTION("plt_clk", byt_score_plt_clk_groups),
519c8f5c4c7SCristina Ciocan 	FUNCTION("smbus", byt_score_smbus_groups),
520c8f5c4c7SCristina Ciocan 	FUNCTION("gpio", byt_score_gpio_groups),
521c8f5c4c7SCristina Ciocan };
522c8f5c4c7SCristina Ciocan 
523c8f5c4c7SCristina Ciocan static const struct byt_community byt_score_communities[] = {
524c8f5c4c7SCristina Ciocan 	COMMUNITY(0, BYT_NGPIO_SCORE, byt_score_pins_map),
525c8f5c4c7SCristina Ciocan };
526c8f5c4c7SCristina Ciocan 
527c8f5c4c7SCristina Ciocan static const struct byt_pinctrl_soc_data byt_score_soc_data = {
528c8f5c4c7SCristina Ciocan 	.uid		= BYT_SCORE_ACPI_UID,
529c8f5c4c7SCristina Ciocan 	.pins		= byt_score_pins,
530c8f5c4c7SCristina Ciocan 	.npins		= ARRAY_SIZE(byt_score_pins),
531c8f5c4c7SCristina Ciocan 	.groups		= byt_score_groups,
532c8f5c4c7SCristina Ciocan 	.ngroups	= ARRAY_SIZE(byt_score_groups),
533c8f5c4c7SCristina Ciocan 	.functions	= byt_score_functions,
534c8f5c4c7SCristina Ciocan 	.nfunctions	= ARRAY_SIZE(byt_score_functions),
535c8f5c4c7SCristina Ciocan 	.communities	= byt_score_communities,
536c8f5c4c7SCristina Ciocan 	.ncommunities	= ARRAY_SIZE(byt_score_communities),
537c8f5c4c7SCristina Ciocan };
538c8f5c4c7SCristina Ciocan 
539c8f5c4c7SCristina Ciocan /* SUS pins, aka GPIOS_<pin_no> or GPIO_S5[<pin_no>]  */
540c8f5c4c7SCristina Ciocan static const struct pinctrl_pin_desc byt_sus_pins[] = {
541c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(0, "GPIO_S50"),
542c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(1, "GPIO_S51"),
543c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(2, "GPIO_S52"),
544c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(3, "GPIO_S53"),
545c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(4, "GPIO_S54"),
546c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(5, "GPIO_S55"),
547c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(6, "GPIO_S56"),
548c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(7, "GPIO_S57"),
549c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(8, "GPIO_S58"),
550c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(9, "GPIO_S59"),
551c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(10, "GPIO_S510"),
552c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(11, "PMC_SUSPWRDNACK"),
553c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(12, "PMC_SUSCLK0"),
554c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(13, "GPIO_S513"),
555c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(14, "USB_ULPI_RST"),
556c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(15, "PMC_WAKE_PCIE0#"),
557c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(16, "PMC_PWRBTN"),
558c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(17, "GPIO_S517"),
559c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(18, "PMC_SUS_STAT"),
560c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(19, "USB_OC0"),
561c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(20, "USB_OC1"),
562c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(21, "PCU_SPI_CS1"),
563c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(22, "GPIO_S522"),
564c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(23, "GPIO_S523"),
565c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(24, "GPIO_S524"),
566c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(25, "GPIO_S525"),
567c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(26, "GPIO_S526"),
568c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(27, "GPIO_S527"),
569c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(28, "GPIO_S528"),
570c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(29, "GPIO_S529"),
571c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(30, "GPIO_S530"),
572c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(31, "USB_ULPI_CLK"),
573c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(32, "USB_ULPI_DATA0"),
574c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(33, "USB_ULPI_DATA1"),
575c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(34, "USB_ULPI_DATA2"),
576c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(35, "USB_ULPI_DATA3"),
577c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(36, "USB_ULPI_DATA4"),
578c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(37, "USB_ULPI_DATA5"),
579c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(38, "USB_ULPI_DATA6"),
580c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(39, "USB_ULPI_DATA7"),
581c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(40, "USB_ULPI_DIR"),
582c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(41, "USB_ULPI_NXT"),
583c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(42, "USB_ULPI_STP"),
584c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(43, "USB_ULPI_REFCLK"),
585c8f5c4c7SCristina Ciocan };
586c8f5c4c7SCristina Ciocan 
587c8f5c4c7SCristina Ciocan static const unsigned int byt_sus_pins_map[BYT_NGPIO_SUS] = {
588c8f5c4c7SCristina Ciocan 	29, 33, 30, 31, 32, 34, 36, 35, 38, 37,
589c8f5c4c7SCristina Ciocan 	18, 7, 11, 20, 17, 1, 8, 10, 19, 12,
590c8f5c4c7SCristina Ciocan 	0, 2, 23, 39, 28, 27, 22, 21, 24, 25,
591c8f5c4c7SCristina Ciocan 	26, 51, 56, 54, 49, 55, 48, 57, 50, 58,
592c8f5c4c7SCristina Ciocan 	52, 53, 59, 40,
593c8f5c4c7SCristina Ciocan };
594c8f5c4c7SCristina Ciocan 
595c8f5c4c7SCristina Ciocan static const unsigned int byt_sus_usb_over_current_pins[] = { 19, 20 };
596c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_sus_usb_oc_mux[] = {
597c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("usb", 0),
598c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("gpio", 1),
599c8f5c4c7SCristina Ciocan };
600c8f5c4c7SCristina Ciocan 
601c8f5c4c7SCristina Ciocan static const unsigned int byt_sus_usb_ulpi_pins[] = {
602c8f5c4c7SCristina Ciocan 	14, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
603c8f5c4c7SCristina Ciocan };
604c8f5c4c7SCristina Ciocan static const unsigned short byt_sus_usb_ulpi_mode_values[] = {
605c8f5c4c7SCristina Ciocan 	2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
606c8f5c4c7SCristina Ciocan };
607c8f5c4c7SCristina Ciocan static const unsigned short byt_sus_usb_ulpi_gpio_mode_values[] = {
608c8f5c4c7SCristina Ciocan 	1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
609c8f5c4c7SCristina Ciocan };
610c8f5c4c7SCristina Ciocan static const struct byt_mixed_func_mux byt_sus_usb_ulpi_mux[] = {
611c8f5c4c7SCristina Ciocan 	MIXED_FUNC("usb", byt_sus_usb_ulpi_mode_values),
612c8f5c4c7SCristina Ciocan 	MIXED_FUNC("gpio", byt_sus_usb_ulpi_gpio_mode_values),
613c8f5c4c7SCristina Ciocan };
614c8f5c4c7SCristina Ciocan 
615c8f5c4c7SCristina Ciocan static const unsigned int byt_sus_pcu_spi_pins[] = { 21 };
616c8f5c4c7SCristina Ciocan static const struct byt_simple_func_mux byt_sus_pcu_spi_mux[] = {
617c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("spi", 0),
618c8f5c4c7SCristina Ciocan 	SIMPLE_FUNC("gpio", 1),
619c8f5c4c7SCristina Ciocan };
620c8f5c4c7SCristina Ciocan 
621c8f5c4c7SCristina Ciocan static const struct byt_pingroup byt_sus_groups[] = {
622c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("usb_oc_grp",
623c8f5c4c7SCristina Ciocan 			byt_sus_usb_over_current_pins, byt_sus_usb_oc_mux),
624c8f5c4c7SCristina Ciocan 	PIN_GROUP_MIXED("usb_ulpi_grp",
625c8f5c4c7SCristina Ciocan 			byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_mux),
626c8f5c4c7SCristina Ciocan 	PIN_GROUP_SIMPLE("pcu_spi_grp",
627c8f5c4c7SCristina Ciocan 			byt_sus_pcu_spi_pins, byt_sus_pcu_spi_mux),
628c8f5c4c7SCristina Ciocan };
629c8f5c4c7SCristina Ciocan 
630c8f5c4c7SCristina Ciocan static const char * const byt_sus_usb_groups[] = {
631c8f5c4c7SCristina Ciocan 	"usb_oc_grp", "usb_ulpi_grp",
632c8f5c4c7SCristina Ciocan };
633c8f5c4c7SCristina Ciocan static const char * const byt_sus_spi_groups[] = { "pcu_spi_grp" };
634c8f5c4c7SCristina Ciocan static const char * const byt_sus_gpio_groups[] = {
635c8f5c4c7SCristina Ciocan 	"usb_oc_grp", "usb_ulpi_grp", "pcu_spi_grp",
636c8f5c4c7SCristina Ciocan };
637c8f5c4c7SCristina Ciocan 
638c8f5c4c7SCristina Ciocan static const struct byt_function byt_sus_functions[] = {
639c8f5c4c7SCristina Ciocan 	FUNCTION("usb", byt_sus_usb_groups),
640c8f5c4c7SCristina Ciocan 	FUNCTION("spi", byt_sus_spi_groups),
641c8f5c4c7SCristina Ciocan 	FUNCTION("gpio", byt_sus_gpio_groups),
642c8f5c4c7SCristina Ciocan };
643c8f5c4c7SCristina Ciocan 
644c8f5c4c7SCristina Ciocan static const struct byt_community byt_sus_communities[] = {
645c8f5c4c7SCristina Ciocan 	COMMUNITY(0, BYT_NGPIO_SUS, byt_sus_pins_map),
646c8f5c4c7SCristina Ciocan };
647c8f5c4c7SCristina Ciocan 
648c8f5c4c7SCristina Ciocan static const struct byt_pinctrl_soc_data byt_sus_soc_data = {
649c8f5c4c7SCristina Ciocan 	.uid		= BYT_SUS_ACPI_UID,
650c8f5c4c7SCristina Ciocan 	.pins		= byt_sus_pins,
651c8f5c4c7SCristina Ciocan 	.npins		= ARRAY_SIZE(byt_sus_pins),
652c8f5c4c7SCristina Ciocan 	.groups		= byt_sus_groups,
653c8f5c4c7SCristina Ciocan 	.ngroups	= ARRAY_SIZE(byt_sus_groups),
654c8f5c4c7SCristina Ciocan 	.functions	= byt_sus_functions,
655c8f5c4c7SCristina Ciocan 	.nfunctions	= ARRAY_SIZE(byt_sus_functions),
656c8f5c4c7SCristina Ciocan 	.communities	= byt_sus_communities,
657c8f5c4c7SCristina Ciocan 	.ncommunities	= ARRAY_SIZE(byt_sus_communities),
658c8f5c4c7SCristina Ciocan };
659c8f5c4c7SCristina Ciocan 
660c8f5c4c7SCristina Ciocan static const struct pinctrl_pin_desc byt_ncore_pins[] = {
661c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(0, "GPIO_NCORE0"),
662c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(1, "GPIO_NCORE1"),
663c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(2, "GPIO_NCORE2"),
664c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(3, "GPIO_NCORE3"),
665c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(4, "GPIO_NCORE4"),
666c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(5, "GPIO_NCORE5"),
667c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(6, "GPIO_NCORE6"),
668c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(7, "GPIO_NCORE7"),
669c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(8, "GPIO_NCORE8"),
670c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(9, "GPIO_NCORE9"),
671c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(10, "GPIO_NCORE10"),
672c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(11, "GPIO_NCORE11"),
673c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(12, "GPIO_NCORE12"),
674c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(13, "GPIO_NCORE13"),
675c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(14, "GPIO_NCORE14"),
676c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(15, "GPIO_NCORE15"),
677c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(16, "GPIO_NCORE16"),
678c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(17, "GPIO_NCORE17"),
679c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(18, "GPIO_NCORE18"),
680c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(19, "GPIO_NCORE19"),
681c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(20, "GPIO_NCORE20"),
682c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(21, "GPIO_NCORE21"),
683c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(22, "GPIO_NCORE22"),
684c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(23, "GPIO_NCORE23"),
685c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(24, "GPIO_NCORE24"),
686c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(25, "GPIO_NCORE25"),
687c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(26, "GPIO_NCORE26"),
688c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(27, "GPIO_NCORE27"),
689c8f5c4c7SCristina Ciocan };
690c8f5c4c7SCristina Ciocan 
691c8f5c4c7SCristina Ciocan static unsigned const byt_ncore_pins_map[BYT_NGPIO_NCORE] = {
692c8f5c4c7SCristina Ciocan 	19, 18, 17, 20, 21, 22, 24, 25, 23, 16,
693c8f5c4c7SCristina Ciocan 	14, 15, 12, 26, 27, 1, 4, 8, 11, 0,
694c8f5c4c7SCristina Ciocan 	3, 6, 10, 13, 2, 5, 9, 7,
695c8f5c4c7SCristina Ciocan };
696c8f5c4c7SCristina Ciocan 
697c8f5c4c7SCristina Ciocan static const struct byt_community byt_ncore_communities[] = {
698c8f5c4c7SCristina Ciocan 	COMMUNITY(0, BYT_NGPIO_NCORE, byt_ncore_pins_map),
699c8f5c4c7SCristina Ciocan };
700c8f5c4c7SCristina Ciocan 
701c8f5c4c7SCristina Ciocan static const struct byt_pinctrl_soc_data byt_ncore_soc_data = {
702c8f5c4c7SCristina Ciocan 	.uid		= BYT_NCORE_ACPI_UID,
703c8f5c4c7SCristina Ciocan 	.pins		= byt_ncore_pins,
704c8f5c4c7SCristina Ciocan 	.npins		= ARRAY_SIZE(byt_ncore_pins),
705c8f5c4c7SCristina Ciocan 	.communities	= byt_ncore_communities,
706c8f5c4c7SCristina Ciocan 	.ncommunities	= ARRAY_SIZE(byt_ncore_communities),
707c8f5c4c7SCristina Ciocan };
708c8f5c4c7SCristina Ciocan 
709c8f5c4c7SCristina Ciocan static const struct byt_pinctrl_soc_data *byt_soc_data[] = {
710c8f5c4c7SCristina Ciocan 	&byt_score_soc_data,
711c8f5c4c7SCristina Ciocan 	&byt_sus_soc_data,
712c8f5c4c7SCristina Ciocan 	&byt_ncore_soc_data,
713c8f5c4c7SCristina Ciocan 	NULL,
714c8f5c4c7SCristina Ciocan };
715c8f5c4c7SCristina Ciocan 
716c501d0b1SCristina Ciocan static struct byt_community *byt_get_community(struct byt_gpio *vg,
717c501d0b1SCristina Ciocan 					       unsigned int pin)
718c501d0b1SCristina Ciocan {
719c501d0b1SCristina Ciocan 	struct byt_community *comm;
720c501d0b1SCristina Ciocan 	int i;
721c501d0b1SCristina Ciocan 
722c501d0b1SCristina Ciocan 	for (i = 0; i < vg->soc_data->ncommunities; i++) {
723c501d0b1SCristina Ciocan 		comm = vg->communities_copy + i;
724c501d0b1SCristina Ciocan 		if (pin < comm->pin_base + comm->npins && pin >= comm->pin_base)
725c501d0b1SCristina Ciocan 			return comm;
726c501d0b1SCristina Ciocan 	}
727c501d0b1SCristina Ciocan 
728c501d0b1SCristina Ciocan 	return NULL;
729c501d0b1SCristina Ciocan }
730c501d0b1SCristina Ciocan 
731c501d0b1SCristina Ciocan static void __iomem *byt_gpio_reg(struct byt_gpio *vg, unsigned int offset,
7325fae8b86SMika Westerberg 				  int reg)
7335fae8b86SMika Westerberg {
734c501d0b1SCristina Ciocan 	struct byt_community *comm = byt_get_community(vg, offset);
735c501d0b1SCristina Ciocan 	u32 reg_offset = 0;
7365fae8b86SMika Westerberg 
737c501d0b1SCristina Ciocan 	if (!comm)
738c501d0b1SCristina Ciocan 		return NULL;
739c501d0b1SCristina Ciocan 
740c501d0b1SCristina Ciocan 	offset -= comm->pin_base;
7415fae8b86SMika Westerberg 	if (reg == BYT_INT_STAT_REG)
7425fae8b86SMika Westerberg 		reg_offset = (offset / 32) * 4;
7435fae8b86SMika Westerberg 	else
744c501d0b1SCristina Ciocan 		reg_offset = comm->pad_map[offset] * 16;
7455fae8b86SMika Westerberg 
746c501d0b1SCristina Ciocan 	return comm->reg_base + reg_offset + reg;
7475fae8b86SMika Westerberg }
7485fae8b86SMika Westerberg 
749c501d0b1SCristina Ciocan static int byt_get_groups_count(struct pinctrl_dev *pctldev)
75095f0972cSMika Westerberg {
751c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
752c501d0b1SCristina Ciocan 
753c501d0b1SCristina Ciocan 	return vg->soc_data->ngroups;
754c501d0b1SCristina Ciocan }
755c501d0b1SCristina Ciocan 
756c501d0b1SCristina Ciocan static const char *byt_get_group_name(struct pinctrl_dev *pctldev,
757c501d0b1SCristina Ciocan 				      unsigned int selector)
758c501d0b1SCristina Ciocan {
759c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
760c501d0b1SCristina Ciocan 
761c501d0b1SCristina Ciocan 	return vg->soc_data->groups[selector].name;
762c501d0b1SCristina Ciocan }
763c501d0b1SCristina Ciocan 
764c501d0b1SCristina Ciocan static int byt_get_group_pins(struct pinctrl_dev *pctldev,
765c501d0b1SCristina Ciocan 			      unsigned int selector,
766c501d0b1SCristina Ciocan 			      const unsigned int **pins,
767c501d0b1SCristina Ciocan 			      unsigned int *num_pins)
768c501d0b1SCristina Ciocan {
769c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
770c501d0b1SCristina Ciocan 
771c501d0b1SCristina Ciocan 	*pins		= vg->soc_data->groups[selector].pins;
772c501d0b1SCristina Ciocan 	*num_pins	= vg->soc_data->groups[selector].npins;
773c501d0b1SCristina Ciocan 
774c501d0b1SCristina Ciocan 	return 0;
775c501d0b1SCristina Ciocan }
776c501d0b1SCristina Ciocan 
777c501d0b1SCristina Ciocan static const struct pinctrl_ops byt_pinctrl_ops = {
778c501d0b1SCristina Ciocan 	.get_groups_count	= byt_get_groups_count,
779c501d0b1SCristina Ciocan 	.get_group_name		= byt_get_group_name,
780c501d0b1SCristina Ciocan 	.get_group_pins		= byt_get_group_pins,
781c501d0b1SCristina Ciocan };
782c501d0b1SCristina Ciocan 
783c501d0b1SCristina Ciocan static int byt_get_functions_count(struct pinctrl_dev *pctldev)
784c501d0b1SCristina Ciocan {
785c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
786c501d0b1SCristina Ciocan 
787c501d0b1SCristina Ciocan 	return vg->soc_data->nfunctions;
788c501d0b1SCristina Ciocan }
789c501d0b1SCristina Ciocan 
790c501d0b1SCristina Ciocan static const char *byt_get_function_name(struct pinctrl_dev *pctldev,
791c501d0b1SCristina Ciocan 					 unsigned int selector)
792c501d0b1SCristina Ciocan {
793c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
794c501d0b1SCristina Ciocan 
795c501d0b1SCristina Ciocan 	return vg->soc_data->functions[selector].name;
796c501d0b1SCristina Ciocan }
797c501d0b1SCristina Ciocan 
798c501d0b1SCristina Ciocan static int byt_get_function_groups(struct pinctrl_dev *pctldev,
799c501d0b1SCristina Ciocan 				   unsigned int selector,
800c501d0b1SCristina Ciocan 				   const char * const **groups,
801c501d0b1SCristina Ciocan 				   unsigned int *num_groups)
802c501d0b1SCristina Ciocan {
803c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
804c501d0b1SCristina Ciocan 
805c501d0b1SCristina Ciocan 	*groups		= vg->soc_data->functions[selector].groups;
806c501d0b1SCristina Ciocan 	*num_groups	= vg->soc_data->functions[selector].ngroups;
807c501d0b1SCristina Ciocan 
808c501d0b1SCristina Ciocan 	return 0;
809c501d0b1SCristina Ciocan }
810c501d0b1SCristina Ciocan 
811c501d0b1SCristina Ciocan static int byt_get_group_simple_mux(const struct byt_pingroup group,
812c501d0b1SCristina Ciocan 				    const char *func_name,
813c501d0b1SCristina Ciocan 				    unsigned short *func)
814c501d0b1SCristina Ciocan {
815c501d0b1SCristina Ciocan 	int i;
816c501d0b1SCristina Ciocan 
817c501d0b1SCristina Ciocan 	for (i = 0; i < group.nfuncs; i++) {
818c501d0b1SCristina Ciocan 		if (!strcmp(group.simple_funcs[i].name, func_name)) {
819c501d0b1SCristina Ciocan 			*func = group.simple_funcs[i].func;
820c501d0b1SCristina Ciocan 			return 0;
821c501d0b1SCristina Ciocan 		}
822c501d0b1SCristina Ciocan 	}
823c501d0b1SCristina Ciocan 
824c501d0b1SCristina Ciocan 	return 1;
825c501d0b1SCristina Ciocan }
826c501d0b1SCristina Ciocan 
827c501d0b1SCristina Ciocan static int byt_get_group_mixed_mux(const struct byt_pingroup group,
828c501d0b1SCristina Ciocan 				   const char *func_name,
829c501d0b1SCristina Ciocan 				   const unsigned short **func)
830c501d0b1SCristina Ciocan {
831c501d0b1SCristina Ciocan 	int i;
832c501d0b1SCristina Ciocan 
833c501d0b1SCristina Ciocan 	for (i = 0; i < group.nfuncs; i++) {
834c501d0b1SCristina Ciocan 		if (!strcmp(group.mixed_funcs[i].name, func_name)) {
835c501d0b1SCristina Ciocan 			*func = group.mixed_funcs[i].func_values;
836c501d0b1SCristina Ciocan 			return 0;
837c501d0b1SCristina Ciocan 		}
838c501d0b1SCristina Ciocan 	}
839c501d0b1SCristina Ciocan 
840c501d0b1SCristina Ciocan 	return 1;
841c501d0b1SCristina Ciocan }
842c501d0b1SCristina Ciocan 
843c501d0b1SCristina Ciocan static void byt_set_group_simple_mux(struct byt_gpio *vg,
844c501d0b1SCristina Ciocan 				     const struct byt_pingroup group,
845c501d0b1SCristina Ciocan 				     unsigned short func)
846c501d0b1SCristina Ciocan {
847c501d0b1SCristina Ciocan 	unsigned long flags;
848c501d0b1SCristina Ciocan 	int i;
849c501d0b1SCristina Ciocan 
850c501d0b1SCristina Ciocan 	raw_spin_lock_irqsave(&vg->lock, flags);
851c501d0b1SCristina Ciocan 
852c501d0b1SCristina Ciocan 	for (i = 0; i < group.npins; i++) {
853c501d0b1SCristina Ciocan 		void __iomem *padcfg0;
854c501d0b1SCristina Ciocan 		u32 value;
855c501d0b1SCristina Ciocan 
856c501d0b1SCristina Ciocan 		padcfg0 = byt_gpio_reg(vg, group.pins[i], BYT_CONF0_REG);
857c501d0b1SCristina Ciocan 		if (!padcfg0) {
858c501d0b1SCristina Ciocan 			dev_warn(&vg->pdev->dev,
859c501d0b1SCristina Ciocan 				 "Group %s, pin %i not muxed (no padcfg0)\n",
860c501d0b1SCristina Ciocan 				 group.name, i);
861c501d0b1SCristina Ciocan 			continue;
862c501d0b1SCristina Ciocan 		}
863c501d0b1SCristina Ciocan 
864c501d0b1SCristina Ciocan 		value = readl(padcfg0);
865c501d0b1SCristina Ciocan 		value &= ~BYT_PIN_MUX;
866c501d0b1SCristina Ciocan 		value |= func;
867c501d0b1SCristina Ciocan 		writel(value, padcfg0);
868c501d0b1SCristina Ciocan 	}
869c501d0b1SCristina Ciocan 
870c501d0b1SCristina Ciocan 	raw_spin_unlock_irqrestore(&vg->lock, flags);
871c501d0b1SCristina Ciocan }
872c501d0b1SCristina Ciocan 
873c501d0b1SCristina Ciocan static void byt_set_group_mixed_mux(struct byt_gpio *vg,
874c501d0b1SCristina Ciocan 				    const struct byt_pingroup group,
875c501d0b1SCristina Ciocan 				    const unsigned short *func)
876c501d0b1SCristina Ciocan {
877c501d0b1SCristina Ciocan 	unsigned long flags;
878c501d0b1SCristina Ciocan 	int i;
879c501d0b1SCristina Ciocan 
880c501d0b1SCristina Ciocan 	raw_spin_lock_irqsave(&vg->lock, flags);
881c501d0b1SCristina Ciocan 
882c501d0b1SCristina Ciocan 	for (i = 0; i < group.npins; i++) {
883c501d0b1SCristina Ciocan 		void __iomem *padcfg0;
884c501d0b1SCristina Ciocan 		u32 value;
885c501d0b1SCristina Ciocan 
886c501d0b1SCristina Ciocan 		padcfg0 = byt_gpio_reg(vg, group.pins[i], BYT_CONF0_REG);
887c501d0b1SCristina Ciocan 		if (!padcfg0) {
888c501d0b1SCristina Ciocan 			dev_warn(&vg->pdev->dev,
889c501d0b1SCristina Ciocan 				 "Group %s, pin %i not muxed (no padcfg0)\n",
890c501d0b1SCristina Ciocan 				 group.name, i);
891c501d0b1SCristina Ciocan 			continue;
892c501d0b1SCristina Ciocan 		}
893c501d0b1SCristina Ciocan 
894c501d0b1SCristina Ciocan 		value = readl(padcfg0);
895c501d0b1SCristina Ciocan 		value &= ~BYT_PIN_MUX;
896c501d0b1SCristina Ciocan 		value |= func[i];
897c501d0b1SCristina Ciocan 		writel(value, padcfg0);
898c501d0b1SCristina Ciocan 	}
899c501d0b1SCristina Ciocan 
900c501d0b1SCristina Ciocan 	raw_spin_unlock_irqrestore(&vg->lock, flags);
901c501d0b1SCristina Ciocan }
902c501d0b1SCristina Ciocan 
903c501d0b1SCristina Ciocan static int byt_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
904c501d0b1SCristina Ciocan 		       unsigned int group_selector)
905c501d0b1SCristina Ciocan {
906c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
907c501d0b1SCristina Ciocan 	const struct byt_function func = vg->soc_data->functions[func_selector];
908c501d0b1SCristina Ciocan 	const struct byt_pingroup group = vg->soc_data->groups[group_selector];
909c501d0b1SCristina Ciocan 	const unsigned short *mixed_func;
910c501d0b1SCristina Ciocan 	unsigned short simple_func;
911c501d0b1SCristina Ciocan 	int ret = 1;
912c501d0b1SCristina Ciocan 
913c501d0b1SCristina Ciocan 	if (group.has_simple_funcs)
914c501d0b1SCristina Ciocan 		ret = byt_get_group_simple_mux(group, func.name, &simple_func);
915c501d0b1SCristina Ciocan 	else
916c501d0b1SCristina Ciocan 		ret = byt_get_group_mixed_mux(group, func.name, &mixed_func);
917c501d0b1SCristina Ciocan 
918c501d0b1SCristina Ciocan 	if (ret)
919c501d0b1SCristina Ciocan 		byt_set_group_simple_mux(vg, group, BYT_DEFAULT_GPIO_MUX);
920c501d0b1SCristina Ciocan 	else if (group.has_simple_funcs)
921c501d0b1SCristina Ciocan 		byt_set_group_simple_mux(vg, group, simple_func);
922c501d0b1SCristina Ciocan 	else
923c501d0b1SCristina Ciocan 		byt_set_group_mixed_mux(vg, group, mixed_func);
924c501d0b1SCristina Ciocan 
925c501d0b1SCristina Ciocan 	return 0;
926c501d0b1SCristina Ciocan }
927c501d0b1SCristina Ciocan 
928c501d0b1SCristina Ciocan static u32 byt_get_gpio_mux(struct byt_gpio *vg, unsigned offset)
929c501d0b1SCristina Ciocan {
930c501d0b1SCristina Ciocan 	/* SCORE pin 92-93 */
931c501d0b1SCristina Ciocan 	if (!strcmp(vg->soc_data->uid, BYT_SCORE_ACPI_UID) &&
932c501d0b1SCristina Ciocan 	    offset >= 92 && offset <= 93)
933c501d0b1SCristina Ciocan 		return 1;
934c501d0b1SCristina Ciocan 
935c501d0b1SCristina Ciocan 	/* SUS pin 11-21 */
936c501d0b1SCristina Ciocan 	if (!strcmp(vg->soc_data->uid, BYT_SUS_ACPI_UID) &&
937c501d0b1SCristina Ciocan 	    offset >= 11 && offset <= 21)
938c501d0b1SCristina Ciocan 		return 1;
939c501d0b1SCristina Ciocan 
940c501d0b1SCristina Ciocan 	return 0;
941c501d0b1SCristina Ciocan }
942c501d0b1SCristina Ciocan 
943c501d0b1SCristina Ciocan static void byt_gpio_clear_triggering(struct byt_gpio *vg, unsigned int offset)
944c501d0b1SCristina Ciocan {
945c501d0b1SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
94695f0972cSMika Westerberg 	unsigned long flags;
94795f0972cSMika Westerberg 	u32 value;
94895f0972cSMika Westerberg 
94978e1c896SMika Westerberg 	raw_spin_lock_irqsave(&vg->lock, flags);
95095f0972cSMika Westerberg 	value = readl(reg);
95195f0972cSMika Westerberg 	value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
95295f0972cSMika Westerberg 	writel(value, reg);
95378e1c896SMika Westerberg 	raw_spin_unlock_irqrestore(&vg->lock, flags);
95495f0972cSMika Westerberg }
95595f0972cSMika Westerberg 
956c501d0b1SCristina Ciocan static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev,
957c501d0b1SCristina Ciocan 				   struct pinctrl_gpio_range *range,
958c501d0b1SCristina Ciocan 				   unsigned int offset)
9595fae8b86SMika Westerberg {
960c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
961c501d0b1SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
962f8323b6bSMika Westerberg 	u32 value, gpio_mux;
96339ce8150SMika Westerberg 	unsigned long flags;
96439ce8150SMika Westerberg 
96578e1c896SMika Westerberg 	raw_spin_lock_irqsave(&vg->lock, flags);
9665fae8b86SMika Westerberg 
9675fae8b86SMika Westerberg 	/*
9685fae8b86SMika Westerberg 	 * In most cases, func pin mux 000 means GPIO function.
9695fae8b86SMika Westerberg 	 * But, some pins may have func pin mux 001 represents
970f8323b6bSMika Westerberg 	 * GPIO function.
971f8323b6bSMika Westerberg 	 *
972f8323b6bSMika Westerberg 	 * Because there are devices out there where some pins were not
973f8323b6bSMika Westerberg 	 * configured correctly we allow changing the mux value from
974f8323b6bSMika Westerberg 	 * request (but print out warning about that).
9755fae8b86SMika Westerberg 	 */
9765fae8b86SMika Westerberg 	value = readl(reg) & BYT_PIN_MUX;
977f8323b6bSMika Westerberg 	gpio_mux = byt_get_gpio_mux(vg, offset);
978f8323b6bSMika Westerberg 	if (WARN_ON(gpio_mux != value)) {
979f8323b6bSMika Westerberg 		value = readl(reg) & ~BYT_PIN_MUX;
980f8323b6bSMika Westerberg 		value |= gpio_mux;
981f8323b6bSMika Westerberg 		writel(value, reg);
982f8323b6bSMika Westerberg 
983f8323b6bSMika Westerberg 		dev_warn(&vg->pdev->dev,
984f8323b6bSMika Westerberg 			 "pin %u forcibly re-configured as GPIO\n", offset);
9855fae8b86SMika Westerberg 	}
9865fae8b86SMika Westerberg 
98778e1c896SMika Westerberg 	raw_spin_unlock_irqrestore(&vg->lock, flags);
98839ce8150SMika Westerberg 
9895fae8b86SMika Westerberg 	pm_runtime_get(&vg->pdev->dev);
9905fae8b86SMika Westerberg 
9915fae8b86SMika Westerberg 	return 0;
9925fae8b86SMika Westerberg }
9935fae8b86SMika Westerberg 
994c501d0b1SCristina Ciocan static void byt_gpio_disable_free(struct pinctrl_dev *pctl_dev,
995c501d0b1SCristina Ciocan 				  struct pinctrl_gpio_range *range,
996c501d0b1SCristina Ciocan 				  unsigned int offset)
997c501d0b1SCristina Ciocan {
998c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
999c501d0b1SCristina Ciocan 
1000c501d0b1SCristina Ciocan 	byt_gpio_clear_triggering(vg, offset);
1001c501d0b1SCristina Ciocan 	pm_runtime_put(&vg->pdev->dev);
1002c501d0b1SCristina Ciocan }
1003c501d0b1SCristina Ciocan 
1004c501d0b1SCristina Ciocan static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
1005c501d0b1SCristina Ciocan 				  struct pinctrl_gpio_range *range,
1006c501d0b1SCristina Ciocan 				  unsigned int offset,
1007c501d0b1SCristina Ciocan 				  bool input)
1008c501d0b1SCristina Ciocan {
1009c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
1010c501d0b1SCristina Ciocan 	void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
1011c501d0b1SCristina Ciocan 	void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
1012c501d0b1SCristina Ciocan 	unsigned long flags;
1013c501d0b1SCristina Ciocan 	u32 value;
1014c501d0b1SCristina Ciocan 
1015c501d0b1SCristina Ciocan 	raw_spin_lock_irqsave(&vg->lock, flags);
1016c501d0b1SCristina Ciocan 
1017c501d0b1SCristina Ciocan 	value = readl(val_reg);
1018c501d0b1SCristina Ciocan 	value &= ~BYT_DIR_MASK;
1019c501d0b1SCristina Ciocan 	if (input)
1020c501d0b1SCristina Ciocan 		value |= BYT_OUTPUT_EN;
1021c501d0b1SCristina Ciocan 	else
1022c501d0b1SCristina Ciocan 		/*
1023c501d0b1SCristina Ciocan 		 * Before making any direction modifications, do a check if gpio
1024c501d0b1SCristina Ciocan 		 * is set for direct IRQ.  On baytrail, setting GPIO to output
1025c501d0b1SCristina Ciocan 		 * does not make sense, so let's at least warn the caller before
1026c501d0b1SCristina Ciocan 		 * they shoot themselves in the foot.
1027c501d0b1SCristina Ciocan 		 */
1028c501d0b1SCristina Ciocan 		WARN(readl(conf_reg) & BYT_DIRECT_IRQ_EN,
1029c501d0b1SCristina Ciocan 		     "Potential Error: Setting GPIO with direct_irq_en to output");
1030c501d0b1SCristina Ciocan 	writel(value, val_reg);
1031c501d0b1SCristina Ciocan 
1032c501d0b1SCristina Ciocan 	raw_spin_unlock_irqrestore(&vg->lock, flags);
1033c501d0b1SCristina Ciocan 
1034c501d0b1SCristina Ciocan 	return 0;
1035c501d0b1SCristina Ciocan }
1036c501d0b1SCristina Ciocan 
1037c501d0b1SCristina Ciocan static const struct pinmux_ops byt_pinmux_ops = {
1038c501d0b1SCristina Ciocan 	.get_functions_count	= byt_get_functions_count,
1039c501d0b1SCristina Ciocan 	.get_function_name	= byt_get_function_name,
1040c501d0b1SCristina Ciocan 	.get_function_groups	= byt_get_function_groups,
1041c501d0b1SCristina Ciocan 	.set_mux		= byt_set_mux,
1042c501d0b1SCristina Ciocan 	.gpio_request_enable	= byt_gpio_request_enable,
1043c501d0b1SCristina Ciocan 	.gpio_disable_free	= byt_gpio_disable_free,
1044c501d0b1SCristina Ciocan 	.gpio_set_direction	= byt_gpio_set_direction,
1045c501d0b1SCristina Ciocan };
1046c501d0b1SCristina Ciocan 
1047c501d0b1SCristina Ciocan static void byt_get_pull_strength(u32 reg, u16 *strength)
1048c501d0b1SCristina Ciocan {
1049c501d0b1SCristina Ciocan 	switch (reg & BYT_PULL_STR_MASK) {
1050c501d0b1SCristina Ciocan 	case BYT_PULL_STR_2K:
1051c501d0b1SCristina Ciocan 		*strength = 2000;
1052c501d0b1SCristina Ciocan 		break;
1053c501d0b1SCristina Ciocan 	case BYT_PULL_STR_10K:
1054c501d0b1SCristina Ciocan 		*strength = 10000;
1055c501d0b1SCristina Ciocan 		break;
1056c501d0b1SCristina Ciocan 	case BYT_PULL_STR_20K:
1057c501d0b1SCristina Ciocan 		*strength = 20000;
1058c501d0b1SCristina Ciocan 		break;
1059c501d0b1SCristina Ciocan 	case BYT_PULL_STR_40K:
1060c501d0b1SCristina Ciocan 		*strength = 40000;
1061c501d0b1SCristina Ciocan 		break;
1062c501d0b1SCristina Ciocan 	}
1063c501d0b1SCristina Ciocan }
1064c501d0b1SCristina Ciocan 
1065c501d0b1SCristina Ciocan static int byt_set_pull_strength(u32 *reg, u16 strength)
1066c501d0b1SCristina Ciocan {
1067c501d0b1SCristina Ciocan 	*reg &= ~BYT_PULL_STR_MASK;
1068c501d0b1SCristina Ciocan 
1069c501d0b1SCristina Ciocan 	switch (strength) {
1070c501d0b1SCristina Ciocan 	case 2000:
1071c501d0b1SCristina Ciocan 		*reg |= BYT_PULL_STR_2K;
1072c501d0b1SCristina Ciocan 		break;
1073c501d0b1SCristina Ciocan 	case 10000:
1074c501d0b1SCristina Ciocan 		*reg |= BYT_PULL_STR_10K;
1075c501d0b1SCristina Ciocan 		break;
1076c501d0b1SCristina Ciocan 	case 20000:
1077c501d0b1SCristina Ciocan 		*reg |= BYT_PULL_STR_20K;
1078c501d0b1SCristina Ciocan 		break;
1079c501d0b1SCristina Ciocan 	case 40000:
1080c501d0b1SCristina Ciocan 		*reg |= BYT_PULL_STR_40K;
1081c501d0b1SCristina Ciocan 		break;
1082c501d0b1SCristina Ciocan 	default:
1083c501d0b1SCristina Ciocan 		return -EINVAL;
1084c501d0b1SCristina Ciocan 	}
1085c501d0b1SCristina Ciocan 
1086c501d0b1SCristina Ciocan 	return 0;
1087c501d0b1SCristina Ciocan }
1088c501d0b1SCristina Ciocan 
1089c501d0b1SCristina Ciocan static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset,
1090c501d0b1SCristina Ciocan 			      unsigned long *config)
1091c501d0b1SCristina Ciocan {
1092c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
1093c501d0b1SCristina Ciocan 	enum pin_config_param param = pinconf_to_config_param(*config);
1094c501d0b1SCristina Ciocan 	void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
1095c501d0b1SCristina Ciocan 	void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
1096c501d0b1SCristina Ciocan 	unsigned long flags;
1097658b476cSCristina Ciocan 	u32 conf, pull, val, debounce;
1098c501d0b1SCristina Ciocan 	u16 arg = 0;
1099c501d0b1SCristina Ciocan 
1100c501d0b1SCristina Ciocan 	raw_spin_lock_irqsave(&vg->lock, flags);
1101c501d0b1SCristina Ciocan 	conf = readl(conf_reg);
1102c501d0b1SCristina Ciocan 	pull = conf & BYT_PULL_ASSIGN_MASK;
1103c501d0b1SCristina Ciocan 	val = readl(val_reg);
1104c501d0b1SCristina Ciocan 	raw_spin_unlock_irqrestore(&vg->lock, flags);
1105c501d0b1SCristina Ciocan 
1106c501d0b1SCristina Ciocan 	switch (param) {
1107c501d0b1SCristina Ciocan 	case PIN_CONFIG_BIAS_DISABLE:
1108c501d0b1SCristina Ciocan 		if (pull)
1109c501d0b1SCristina Ciocan 			return -EINVAL;
1110c501d0b1SCristina Ciocan 		break;
1111c501d0b1SCristina Ciocan 	case PIN_CONFIG_BIAS_PULL_DOWN:
1112c501d0b1SCristina Ciocan 		/* Pull assignment is only applicable in input mode */
1113c501d0b1SCristina Ciocan 		if ((val & BYT_INPUT_EN) || pull != BYT_PULL_ASSIGN_DOWN)
1114c501d0b1SCristina Ciocan 			return -EINVAL;
1115c501d0b1SCristina Ciocan 
1116c501d0b1SCristina Ciocan 		byt_get_pull_strength(conf, &arg);
1117c501d0b1SCristina Ciocan 
1118c501d0b1SCristina Ciocan 		break;
1119c501d0b1SCristina Ciocan 	case PIN_CONFIG_BIAS_PULL_UP:
1120c501d0b1SCristina Ciocan 		/* Pull assignment is only applicable in input mode */
1121c501d0b1SCristina Ciocan 		if ((val & BYT_INPUT_EN) || pull != BYT_PULL_ASSIGN_UP)
1122c501d0b1SCristina Ciocan 			return -EINVAL;
1123c501d0b1SCristina Ciocan 
1124c501d0b1SCristina Ciocan 		byt_get_pull_strength(conf, &arg);
1125c501d0b1SCristina Ciocan 
1126c501d0b1SCristina Ciocan 		break;
1127658b476cSCristina Ciocan 	case PIN_CONFIG_INPUT_DEBOUNCE:
1128658b476cSCristina Ciocan 		if (!(conf & BYT_DEBOUNCE_EN))
1129658b476cSCristina Ciocan 			return -EINVAL;
1130658b476cSCristina Ciocan 
1131658b476cSCristina Ciocan 		raw_spin_lock_irqsave(&vg->lock, flags);
1132658b476cSCristina Ciocan 		debounce = readl(byt_gpio_reg(vg, offset, BYT_DEBOUNCE_REG));
1133658b476cSCristina Ciocan 		raw_spin_unlock_irqrestore(&vg->lock, flags);
1134658b476cSCristina Ciocan 
1135658b476cSCristina Ciocan 		switch (debounce & BYT_DEBOUNCE_PULSE_MASK) {
1136658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_375US:
1137658b476cSCristina Ciocan 			arg = 375;
1138658b476cSCristina Ciocan 			break;
1139658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_750US:
1140658b476cSCristina Ciocan 			arg = 750;
1141658b476cSCristina Ciocan 			break;
1142658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_1500US:
1143658b476cSCristina Ciocan 			arg = 1500;
1144658b476cSCristina Ciocan 			break;
1145658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_3MS:
1146658b476cSCristina Ciocan 			arg = 3000;
1147658b476cSCristina Ciocan 			break;
1148658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_6MS:
1149658b476cSCristina Ciocan 			arg = 6000;
1150658b476cSCristina Ciocan 			break;
1151658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_12MS:
1152658b476cSCristina Ciocan 			arg = 12000;
1153658b476cSCristina Ciocan 			break;
1154658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_24MS:
1155658b476cSCristina Ciocan 			arg = 24000;
1156658b476cSCristina Ciocan 			break;
1157658b476cSCristina Ciocan 		default:
1158658b476cSCristina Ciocan 			return -EINVAL;
1159658b476cSCristina Ciocan 		}
1160658b476cSCristina Ciocan 
1161658b476cSCristina Ciocan 		break;
1162c501d0b1SCristina Ciocan 	default:
1163c501d0b1SCristina Ciocan 		return -ENOTSUPP;
1164c501d0b1SCristina Ciocan 	}
1165c501d0b1SCristina Ciocan 
1166c501d0b1SCristina Ciocan 	*config = pinconf_to_config_packed(param, arg);
1167c501d0b1SCristina Ciocan 
1168c501d0b1SCristina Ciocan 	return 0;
1169c501d0b1SCristina Ciocan }
1170c501d0b1SCristina Ciocan 
1171c501d0b1SCristina Ciocan static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
1172c501d0b1SCristina Ciocan 			      unsigned int offset,
1173c501d0b1SCristina Ciocan 			      unsigned long *configs,
1174c501d0b1SCristina Ciocan 			      unsigned int num_configs)
1175c501d0b1SCristina Ciocan {
1176c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
1177c501d0b1SCristina Ciocan 	unsigned int param, arg;
1178c501d0b1SCristina Ciocan 	void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
1179c501d0b1SCristina Ciocan 	void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
1180c501d0b1SCristina Ciocan 	unsigned long flags;
1181658b476cSCristina Ciocan 	u32 conf, val, debounce;
1182c501d0b1SCristina Ciocan 	int i, ret = 0;
1183c501d0b1SCristina Ciocan 
1184c501d0b1SCristina Ciocan 	raw_spin_lock_irqsave(&vg->lock, flags);
1185c501d0b1SCristina Ciocan 
1186c501d0b1SCristina Ciocan 	conf = readl(conf_reg);
1187c501d0b1SCristina Ciocan 	val = readl(val_reg);
1188c501d0b1SCristina Ciocan 
1189c501d0b1SCristina Ciocan 	for (i = 0; i < num_configs; i++) {
1190c501d0b1SCristina Ciocan 		param = pinconf_to_config_param(configs[i]);
1191c501d0b1SCristina Ciocan 		arg = pinconf_to_config_argument(configs[i]);
1192c501d0b1SCristina Ciocan 
1193c501d0b1SCristina Ciocan 		switch (param) {
1194c501d0b1SCristina Ciocan 		case PIN_CONFIG_BIAS_DISABLE:
1195c501d0b1SCristina Ciocan 			conf &= ~BYT_PULL_ASSIGN_MASK;
1196c501d0b1SCristina Ciocan 			break;
1197c501d0b1SCristina Ciocan 		case PIN_CONFIG_BIAS_PULL_DOWN:
1198c501d0b1SCristina Ciocan 			/* Set default strength value in case none is given */
1199c501d0b1SCristina Ciocan 			if (arg == 1)
1200c501d0b1SCristina Ciocan 				arg = 2000;
1201c501d0b1SCristina Ciocan 
1202c501d0b1SCristina Ciocan 			/*
1203c501d0b1SCristina Ciocan 			 * Pull assignment is only applicable in input mode. If
1204c501d0b1SCristina Ciocan 			 * chip is not in input mode, set it and warn about it.
1205c501d0b1SCristina Ciocan 			 */
1206c501d0b1SCristina Ciocan 			if (val & BYT_INPUT_EN) {
1207c501d0b1SCristina Ciocan 				val &= ~BYT_INPUT_EN;
1208c501d0b1SCristina Ciocan 				writel(val, val_reg);
1209c501d0b1SCristina Ciocan 				dev_warn(&vg->pdev->dev,
1210c501d0b1SCristina Ciocan 					 "pin %u forcibly set to input mode\n",
1211c501d0b1SCristina Ciocan 					 offset);
1212c501d0b1SCristina Ciocan 			}
1213c501d0b1SCristina Ciocan 
1214c501d0b1SCristina Ciocan 			conf &= ~BYT_PULL_ASSIGN_MASK;
1215c501d0b1SCristina Ciocan 			conf |= BYT_PULL_ASSIGN_DOWN;
1216c501d0b1SCristina Ciocan 			ret = byt_set_pull_strength(&conf, arg);
1217c501d0b1SCristina Ciocan 
1218c501d0b1SCristina Ciocan 			break;
1219c501d0b1SCristina Ciocan 		case PIN_CONFIG_BIAS_PULL_UP:
1220c501d0b1SCristina Ciocan 			/* Set default strength value in case none is given */
1221c501d0b1SCristina Ciocan 			if (arg == 1)
1222c501d0b1SCristina Ciocan 				arg = 2000;
1223c501d0b1SCristina Ciocan 
1224c501d0b1SCristina Ciocan 			/*
1225c501d0b1SCristina Ciocan 			 * Pull assignment is only applicable in input mode. If
1226c501d0b1SCristina Ciocan 			 * chip is not in input mode, set it and warn about it.
1227c501d0b1SCristina Ciocan 			 */
1228c501d0b1SCristina Ciocan 			if (val & BYT_INPUT_EN) {
1229c501d0b1SCristina Ciocan 				val &= ~BYT_INPUT_EN;
1230c501d0b1SCristina Ciocan 				writel(val, val_reg);
1231c501d0b1SCristina Ciocan 				dev_warn(&vg->pdev->dev,
1232c501d0b1SCristina Ciocan 					 "pin %u forcibly set to input mode\n",
1233c501d0b1SCristina Ciocan 					 offset);
1234c501d0b1SCristina Ciocan 			}
1235c501d0b1SCristina Ciocan 
1236c501d0b1SCristina Ciocan 			conf &= ~BYT_PULL_ASSIGN_MASK;
1237c501d0b1SCristina Ciocan 			conf |= BYT_PULL_ASSIGN_UP;
1238c501d0b1SCristina Ciocan 			ret = byt_set_pull_strength(&conf, arg);
1239c501d0b1SCristina Ciocan 
1240c501d0b1SCristina Ciocan 			break;
1241658b476cSCristina Ciocan 		case PIN_CONFIG_INPUT_DEBOUNCE:
1242658b476cSCristina Ciocan 			debounce = readl(byt_gpio_reg(vg, offset,
1243658b476cSCristina Ciocan 						      BYT_DEBOUNCE_REG));
1244658b476cSCristina Ciocan 			conf &= ~BYT_DEBOUNCE_PULSE_MASK;
1245658b476cSCristina Ciocan 
1246658b476cSCristina Ciocan 			switch (arg) {
1247658b476cSCristina Ciocan 			case 375:
1248658b476cSCristina Ciocan 				conf |= BYT_DEBOUNCE_PULSE_375US;
1249658b476cSCristina Ciocan 				break;
1250658b476cSCristina Ciocan 			case 750:
1251658b476cSCristina Ciocan 				conf |= BYT_DEBOUNCE_PULSE_750US;
1252658b476cSCristina Ciocan 				break;
1253658b476cSCristina Ciocan 			case 1500:
1254658b476cSCristina Ciocan 				conf |= BYT_DEBOUNCE_PULSE_1500US;
1255658b476cSCristina Ciocan 				break;
1256658b476cSCristina Ciocan 			case 3000:
1257658b476cSCristina Ciocan 				conf |= BYT_DEBOUNCE_PULSE_3MS;
1258658b476cSCristina Ciocan 				break;
1259658b476cSCristina Ciocan 			case 6000:
1260658b476cSCristina Ciocan 				conf |= BYT_DEBOUNCE_PULSE_6MS;
1261658b476cSCristina Ciocan 				break;
1262658b476cSCristina Ciocan 			case 12000:
1263658b476cSCristina Ciocan 				conf |= BYT_DEBOUNCE_PULSE_12MS;
1264658b476cSCristina Ciocan 				break;
1265658b476cSCristina Ciocan 			case 24000:
1266658b476cSCristina Ciocan 				conf |= BYT_DEBOUNCE_PULSE_24MS;
1267658b476cSCristina Ciocan 				break;
1268658b476cSCristina Ciocan 			default:
1269658b476cSCristina Ciocan 				ret = -EINVAL;
1270658b476cSCristina Ciocan 			}
1271658b476cSCristina Ciocan 
1272658b476cSCristina Ciocan 			break;
1273c501d0b1SCristina Ciocan 		default:
1274c501d0b1SCristina Ciocan 			ret = -ENOTSUPP;
1275c501d0b1SCristina Ciocan 		}
1276c501d0b1SCristina Ciocan 
1277c501d0b1SCristina Ciocan 		if (ret)
1278c501d0b1SCristina Ciocan 			break;
1279c501d0b1SCristina Ciocan 	}
1280c501d0b1SCristina Ciocan 
1281c501d0b1SCristina Ciocan 	if (!ret)
1282c501d0b1SCristina Ciocan 		writel(conf, conf_reg);
1283c501d0b1SCristina Ciocan 
1284c501d0b1SCristina Ciocan 	raw_spin_unlock_irqrestore(&vg->lock, flags);
1285c501d0b1SCristina Ciocan 
1286c501d0b1SCristina Ciocan 	return ret;
1287c501d0b1SCristina Ciocan }
1288c501d0b1SCristina Ciocan 
1289c501d0b1SCristina Ciocan static const struct pinconf_ops byt_pinconf_ops = {
1290c501d0b1SCristina Ciocan 	.is_generic	= true,
1291c501d0b1SCristina Ciocan 	.pin_config_get	= byt_pin_config_get,
1292c501d0b1SCristina Ciocan 	.pin_config_set	= byt_pin_config_set,
1293c501d0b1SCristina Ciocan };
1294c501d0b1SCristina Ciocan 
1295c501d0b1SCristina Ciocan static const struct pinctrl_desc byt_pinctrl_desc = {
1296c501d0b1SCristina Ciocan 	.pctlops	= &byt_pinctrl_ops,
1297c501d0b1SCristina Ciocan 	.pmxops		= &byt_pinmux_ops,
1298c501d0b1SCristina Ciocan 	.confops	= &byt_pinconf_ops,
1299c501d0b1SCristina Ciocan 	.owner		= THIS_MODULE,
1300c501d0b1SCristina Ciocan };
1301c501d0b1SCristina Ciocan 
13025fae8b86SMika Westerberg static int byt_gpio_get(struct gpio_chip *chip, unsigned offset)
13035fae8b86SMika Westerberg {
1304bf9a5c96SLinus Walleij 	struct byt_gpio *vg = gpiochip_get_data(chip);
1305c501d0b1SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
130639ce8150SMika Westerberg 	unsigned long flags;
130739ce8150SMika Westerberg 	u32 val;
130839ce8150SMika Westerberg 
130978e1c896SMika Westerberg 	raw_spin_lock_irqsave(&vg->lock, flags);
131039ce8150SMika Westerberg 	val = readl(reg);
131178e1c896SMika Westerberg 	raw_spin_unlock_irqrestore(&vg->lock, flags);
131239ce8150SMika Westerberg 
13133bde8771SLinus Walleij 	return !!(val & BYT_LEVEL);
13145fae8b86SMika Westerberg }
13155fae8b86SMika Westerberg 
13165fae8b86SMika Westerberg static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
13175fae8b86SMika Westerberg {
1318bf9a5c96SLinus Walleij 	struct byt_gpio *vg = gpiochip_get_data(chip);
1319c501d0b1SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
13205fae8b86SMika Westerberg 	unsigned long flags;
13215fae8b86SMika Westerberg 	u32 old_val;
13225fae8b86SMika Westerberg 
132386e3ef81SCristina Ciocan 	if (!reg)
132486e3ef81SCristina Ciocan 		return;
132586e3ef81SCristina Ciocan 
132678e1c896SMika Westerberg 	raw_spin_lock_irqsave(&vg->lock, flags);
13275fae8b86SMika Westerberg 	old_val = readl(reg);
13285fae8b86SMika Westerberg 	if (value)
13295fae8b86SMika Westerberg 		writel(old_val | BYT_LEVEL, reg);
13305fae8b86SMika Westerberg 	else
13315fae8b86SMika Westerberg 		writel(old_val & ~BYT_LEVEL, reg);
133278e1c896SMika Westerberg 	raw_spin_unlock_irqrestore(&vg->lock, flags);
13335fae8b86SMika Westerberg }
13345fae8b86SMika Westerberg 
133586e3ef81SCristina Ciocan static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
13365fae8b86SMika Westerberg {
1337bf9a5c96SLinus Walleij 	struct byt_gpio *vg = gpiochip_get_data(chip);
1338c501d0b1SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
13395fae8b86SMika Westerberg 	unsigned long flags;
13405fae8b86SMika Westerberg 	u32 value;
13415fae8b86SMika Westerberg 
134286e3ef81SCristina Ciocan 	if (!reg)
134386e3ef81SCristina Ciocan 		return -EINVAL;
134486e3ef81SCristina Ciocan 
134578e1c896SMika Westerberg 	raw_spin_lock_irqsave(&vg->lock, flags);
134686e3ef81SCristina Ciocan 	value = readl(reg);
134778e1c896SMika Westerberg 	raw_spin_unlock_irqrestore(&vg->lock, flags);
13485fae8b86SMika Westerberg 
134986e3ef81SCristina Ciocan 	if (!(value & BYT_OUTPUT_EN))
135086e3ef81SCristina Ciocan 		return GPIOF_DIR_OUT;
135186e3ef81SCristina Ciocan 	if (!(value & BYT_INPUT_EN))
135286e3ef81SCristina Ciocan 		return GPIOF_DIR_IN;
135386e3ef81SCristina Ciocan 
135486e3ef81SCristina Ciocan 	return -EINVAL;
13555fae8b86SMika Westerberg }
13565fae8b86SMika Westerberg 
135786e3ef81SCristina Ciocan static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
13585fae8b86SMika Westerberg {
135986e3ef81SCristina Ciocan 	return pinctrl_gpio_direction_input(chip->base + offset);
136086e3ef81SCristina Ciocan }
13615fae8b86SMika Westerberg 
136286e3ef81SCristina Ciocan static int byt_gpio_direction_output(struct gpio_chip *chip,
136386e3ef81SCristina Ciocan 				     unsigned int offset, int value)
136486e3ef81SCristina Ciocan {
136586e3ef81SCristina Ciocan 	int ret = pinctrl_gpio_direction_output(chip->base + offset);
13665fae8b86SMika Westerberg 
136786e3ef81SCristina Ciocan 	if (ret)
136886e3ef81SCristina Ciocan 		return ret;
136986e3ef81SCristina Ciocan 
137086e3ef81SCristina Ciocan 	byt_gpio_set(chip, offset, value);
13715fae8b86SMika Westerberg 
13725fae8b86SMika Westerberg 	return 0;
13735fae8b86SMika Westerberg }
13745fae8b86SMika Westerberg 
13755fae8b86SMika Westerberg static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
13765fae8b86SMika Westerberg {
1377bf9a5c96SLinus Walleij 	struct byt_gpio *vg = gpiochip_get_data(chip);
13785fae8b86SMika Westerberg 	int i;
137986e3ef81SCristina Ciocan 	u32 conf0, val;
13805fae8b86SMika Westerberg 
138186e3ef81SCristina Ciocan 	for (i = 0; i < vg->soc_data->npins; i++) {
138286e3ef81SCristina Ciocan 		const struct byt_community *comm;
13835fae8b86SMika Westerberg 		const char *pull_str = NULL;
13845fae8b86SMika Westerberg 		const char *pull = NULL;
138586e3ef81SCristina Ciocan 		void __iomem *reg;
138678e1c896SMika Westerberg 		unsigned long flags;
13875fae8b86SMika Westerberg 		const char *label;
138886e3ef81SCristina Ciocan 		unsigned int pin;
138978e1c896SMika Westerberg 
139078e1c896SMika Westerberg 		raw_spin_lock_irqsave(&vg->lock, flags);
139186e3ef81SCristina Ciocan 		pin = vg->soc_data->pins[i].number;
139286e3ef81SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
139386e3ef81SCristina Ciocan 		if (!reg) {
139486e3ef81SCristina Ciocan 			seq_printf(s,
139586e3ef81SCristina Ciocan 				   "Could not retrieve pin %i conf0 reg\n",
139686e3ef81SCristina Ciocan 				   pin);
139722bbd21bSDan Carpenter 			raw_spin_unlock_irqrestore(&vg->lock, flags);
139886e3ef81SCristina Ciocan 			continue;
139986e3ef81SCristina Ciocan 		}
140086e3ef81SCristina Ciocan 		conf0 = readl(reg);
140186e3ef81SCristina Ciocan 
140286e3ef81SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
140386e3ef81SCristina Ciocan 		if (!reg) {
140486e3ef81SCristina Ciocan 			seq_printf(s,
140586e3ef81SCristina Ciocan 				   "Could not retrieve pin %i val reg\n", pin);
140622bbd21bSDan Carpenter 			raw_spin_unlock_irqrestore(&vg->lock, flags);
140722bbd21bSDan Carpenter 			continue;
140886e3ef81SCristina Ciocan 		}
140986e3ef81SCristina Ciocan 		val = readl(reg);
141078e1c896SMika Westerberg 		raw_spin_unlock_irqrestore(&vg->lock, flags);
14115fae8b86SMika Westerberg 
141286e3ef81SCristina Ciocan 		comm = byt_get_community(vg, pin);
141386e3ef81SCristina Ciocan 		if (!comm) {
141486e3ef81SCristina Ciocan 			seq_printf(s,
141586e3ef81SCristina Ciocan 				   "Could not get community for pin %i\n", pin);
141686e3ef81SCristina Ciocan 			continue;
141786e3ef81SCristina Ciocan 		}
14185fae8b86SMika Westerberg 		label = gpiochip_is_requested(chip, i);
14195fae8b86SMika Westerberg 		if (!label)
14205fae8b86SMika Westerberg 			label = "Unrequested";
14215fae8b86SMika Westerberg 
14225fae8b86SMika Westerberg 		switch (conf0 & BYT_PULL_ASSIGN_MASK) {
14235fae8b86SMika Westerberg 		case BYT_PULL_ASSIGN_UP:
14245fae8b86SMika Westerberg 			pull = "up";
14255fae8b86SMika Westerberg 			break;
14265fae8b86SMika Westerberg 		case BYT_PULL_ASSIGN_DOWN:
14275fae8b86SMika Westerberg 			pull = "down";
14285fae8b86SMika Westerberg 			break;
14295fae8b86SMika Westerberg 		}
14305fae8b86SMika Westerberg 
14315fae8b86SMika Westerberg 		switch (conf0 & BYT_PULL_STR_MASK) {
14325fae8b86SMika Westerberg 		case BYT_PULL_STR_2K:
14335fae8b86SMika Westerberg 			pull_str = "2k";
14345fae8b86SMika Westerberg 			break;
14355fae8b86SMika Westerberg 		case BYT_PULL_STR_10K:
14365fae8b86SMika Westerberg 			pull_str = "10k";
14375fae8b86SMika Westerberg 			break;
14385fae8b86SMika Westerberg 		case BYT_PULL_STR_20K:
14395fae8b86SMika Westerberg 			pull_str = "20k";
14405fae8b86SMika Westerberg 			break;
14415fae8b86SMika Westerberg 		case BYT_PULL_STR_40K:
14425fae8b86SMika Westerberg 			pull_str = "40k";
14435fae8b86SMika Westerberg 			break;
14445fae8b86SMika Westerberg 		}
14455fae8b86SMika Westerberg 
14465fae8b86SMika Westerberg 		seq_printf(s,
14475fae8b86SMika Westerberg 			   " gpio-%-3d (%-20.20s) %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s",
144886e3ef81SCristina Ciocan 			   pin,
14495fae8b86SMika Westerberg 			   label,
14505fae8b86SMika Westerberg 			   val & BYT_INPUT_EN ? "  " : "in",
14515fae8b86SMika Westerberg 			   val & BYT_OUTPUT_EN ? "   " : "out",
14525fae8b86SMika Westerberg 			   val & BYT_LEVEL ? "hi" : "lo",
145386e3ef81SCristina Ciocan 			   comm->pad_map[i], comm->pad_map[i] * 32,
14545fae8b86SMika Westerberg 			   conf0 & 0x7,
14555fae8b86SMika Westerberg 			   conf0 & BYT_TRIG_NEG ? " fall" : "     ",
14565fae8b86SMika Westerberg 			   conf0 & BYT_TRIG_POS ? " rise" : "     ",
14575fae8b86SMika Westerberg 			   conf0 & BYT_TRIG_LVL ? " level" : "      ");
14585fae8b86SMika Westerberg 
14595fae8b86SMika Westerberg 		if (pull && pull_str)
14605fae8b86SMika Westerberg 			seq_printf(s, " %-4s %-3s", pull, pull_str);
14615fae8b86SMika Westerberg 		else
14625fae8b86SMika Westerberg 			seq_puts(s, "          ");
14635fae8b86SMika Westerberg 
14645fae8b86SMika Westerberg 		if (conf0 & BYT_IODEN)
14655fae8b86SMika Westerberg 			seq_puts(s, " open-drain");
14665fae8b86SMika Westerberg 
14675fae8b86SMika Westerberg 		seq_puts(s, "\n");
14685fae8b86SMika Westerberg 	}
14695fae8b86SMika Westerberg }
14705fae8b86SMika Westerberg 
147186e3ef81SCristina Ciocan static const struct gpio_chip byt_gpio_chip = {
147286e3ef81SCristina Ciocan 	.owner			= THIS_MODULE,
147386e3ef81SCristina Ciocan 	.request		= gpiochip_generic_request,
147486e3ef81SCristina Ciocan 	.free			= gpiochip_generic_free,
147586e3ef81SCristina Ciocan 	.get_direction		= byt_gpio_get_direction,
147686e3ef81SCristina Ciocan 	.direction_input	= byt_gpio_direction_input,
147786e3ef81SCristina Ciocan 	.direction_output	= byt_gpio_direction_output,
147886e3ef81SCristina Ciocan 	.get			= byt_gpio_get,
147986e3ef81SCristina Ciocan 	.set			= byt_gpio_set,
148086e3ef81SCristina Ciocan 	.dbg_show		= byt_gpio_dbg_show,
148186e3ef81SCristina Ciocan };
148286e3ef81SCristina Ciocan 
148331e4329fSMika Westerberg static void byt_irq_ack(struct irq_data *d)
148431e4329fSMika Westerberg {
148531e4329fSMika Westerberg 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
1486bf9a5c96SLinus Walleij 	struct byt_gpio *vg = gpiochip_get_data(gc);
148731e4329fSMika Westerberg 	unsigned offset = irqd_to_hwirq(d);
148831e4329fSMika Westerberg 	void __iomem *reg;
148931e4329fSMika Westerberg 
1490c501d0b1SCristina Ciocan 	reg = byt_gpio_reg(vg, offset, BYT_INT_STAT_REG);
14919f573b98SCristina Ciocan 	if (!reg)
14929f573b98SCristina Ciocan 		return;
14939f573b98SCristina Ciocan 
14949f573b98SCristina Ciocan 	raw_spin_lock(&vg->lock);
149531e4329fSMika Westerberg 	writel(BIT(offset % 32), reg);
149678e1c896SMika Westerberg 	raw_spin_unlock(&vg->lock);
149731e4329fSMika Westerberg }
149831e4329fSMika Westerberg 
14999f573b98SCristina Ciocan static void byt_irq_mask(struct irq_data *d)
15009f573b98SCristina Ciocan {
15019f573b98SCristina Ciocan 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
15029f573b98SCristina Ciocan 	struct byt_gpio *vg = gpiochip_get_data(gc);
15039f573b98SCristina Ciocan 
15049f573b98SCristina Ciocan 	byt_gpio_clear_triggering(vg, irqd_to_hwirq(d));
15059f573b98SCristina Ciocan }
15069f573b98SCristina Ciocan 
15075fae8b86SMika Westerberg static void byt_irq_unmask(struct irq_data *d)
15085fae8b86SMika Westerberg {
150931e4329fSMika Westerberg 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
1510bf9a5c96SLinus Walleij 	struct byt_gpio *vg = gpiochip_get_data(gc);
151131e4329fSMika Westerberg 	unsigned offset = irqd_to_hwirq(d);
151231e4329fSMika Westerberg 	unsigned long flags;
151331e4329fSMika Westerberg 	void __iomem *reg;
151431e4329fSMika Westerberg 	u32 value;
151531e4329fSMika Westerberg 
1516c501d0b1SCristina Ciocan 	reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
15179f573b98SCristina Ciocan 	if (!reg)
15189f573b98SCristina Ciocan 		return;
151978e1c896SMika Westerberg 
152078e1c896SMika Westerberg 	raw_spin_lock_irqsave(&vg->lock, flags);
152131e4329fSMika Westerberg 	value = readl(reg);
152231e4329fSMika Westerberg 
152331e4329fSMika Westerberg 	switch (irqd_get_trigger_type(d)) {
152431e4329fSMika Westerberg 	case IRQ_TYPE_LEVEL_HIGH:
152531e4329fSMika Westerberg 		value |= BYT_TRIG_LVL;
152631e4329fSMika Westerberg 	case IRQ_TYPE_EDGE_RISING:
152731e4329fSMika Westerberg 		value |= BYT_TRIG_POS;
152831e4329fSMika Westerberg 		break;
152931e4329fSMika Westerberg 	case IRQ_TYPE_LEVEL_LOW:
153031e4329fSMika Westerberg 		value |= BYT_TRIG_LVL;
153131e4329fSMika Westerberg 	case IRQ_TYPE_EDGE_FALLING:
153231e4329fSMika Westerberg 		value |= BYT_TRIG_NEG;
153331e4329fSMika Westerberg 		break;
153431e4329fSMika Westerberg 	case IRQ_TYPE_EDGE_BOTH:
153531e4329fSMika Westerberg 		value |= (BYT_TRIG_NEG | BYT_TRIG_POS);
153631e4329fSMika Westerberg 		break;
153731e4329fSMika Westerberg 	}
153831e4329fSMika Westerberg 
153931e4329fSMika Westerberg 	writel(value, reg);
154031e4329fSMika Westerberg 
154178e1c896SMika Westerberg 	raw_spin_unlock_irqrestore(&vg->lock, flags);
15425fae8b86SMika Westerberg }
15435fae8b86SMika Westerberg 
15449f573b98SCristina Ciocan static int byt_irq_type(struct irq_data *d, unsigned int type)
15455fae8b86SMika Westerberg {
15469f573b98SCristina Ciocan 	struct byt_gpio *vg = gpiochip_get_data(irq_data_get_irq_chip_data(d));
15479f573b98SCristina Ciocan 	u32 offset = irqd_to_hwirq(d);
15489f573b98SCristina Ciocan 	u32 value;
15499f573b98SCristina Ciocan 	unsigned long flags;
15509f573b98SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
155131e4329fSMika Westerberg 
15529f573b98SCristina Ciocan 	if (!reg || offset >= vg->chip.ngpio)
15539f573b98SCristina Ciocan 		return -EINVAL;
15549f573b98SCristina Ciocan 
15559f573b98SCristina Ciocan 	raw_spin_lock_irqsave(&vg->lock, flags);
15569f573b98SCristina Ciocan 	value = readl(reg);
15579f573b98SCristina Ciocan 
15589f573b98SCristina Ciocan 	WARN(value & BYT_DIRECT_IRQ_EN,
15599f573b98SCristina Ciocan 	     "Bad pad config for io mode, force direct_irq_en bit clearing");
15609f573b98SCristina Ciocan 
15619f573b98SCristina Ciocan 	/* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits
15629f573b98SCristina Ciocan 	 * are used to indicate high and low level triggering
15639f573b98SCristina Ciocan 	 */
15649f573b98SCristina Ciocan 	value &= ~(BYT_DIRECT_IRQ_EN | BYT_TRIG_POS | BYT_TRIG_NEG |
15659f573b98SCristina Ciocan 		   BYT_TRIG_LVL);
15669f573b98SCristina Ciocan 
15679f573b98SCristina Ciocan 	writel(value, reg);
15689f573b98SCristina Ciocan 
15699f573b98SCristina Ciocan 	if (type & IRQ_TYPE_EDGE_BOTH)
15709f573b98SCristina Ciocan 		irq_set_handler_locked(d, handle_edge_irq);
15719f573b98SCristina Ciocan 	else if (type & IRQ_TYPE_LEVEL_MASK)
15729f573b98SCristina Ciocan 		irq_set_handler_locked(d, handle_level_irq);
15739f573b98SCristina Ciocan 
15749f573b98SCristina Ciocan 	raw_spin_unlock_irqrestore(&vg->lock, flags);
15759f573b98SCristina Ciocan 
15769f573b98SCristina Ciocan 	return 0;
15775fae8b86SMika Westerberg }
15785fae8b86SMika Westerberg 
15795fae8b86SMika Westerberg static struct irq_chip byt_irqchip = {
15805fae8b86SMika Westerberg 	.name		= "BYT-GPIO",
158131e4329fSMika Westerberg 	.irq_ack	= byt_irq_ack,
15825fae8b86SMika Westerberg 	.irq_mask	= byt_irq_mask,
15835fae8b86SMika Westerberg 	.irq_unmask	= byt_irq_unmask,
15845fae8b86SMika Westerberg 	.irq_set_type	= byt_irq_type,
15855fae8b86SMika Westerberg 	.flags		= IRQCHIP_SKIP_SET_WAKE,
15865fae8b86SMika Westerberg };
15875fae8b86SMika Westerberg 
158871e6ca61SCristina Ciocan static void byt_gpio_irq_handler(struct irq_desc *desc)
158971e6ca61SCristina Ciocan {
159071e6ca61SCristina Ciocan 	struct irq_data *data = irq_desc_get_irq_data(desc);
159171e6ca61SCristina Ciocan 	struct byt_gpio *vg = gpiochip_get_data(
159271e6ca61SCristina Ciocan 				irq_desc_get_handler_data(desc));
159371e6ca61SCristina Ciocan 	struct irq_chip *chip = irq_data_get_irq_chip(data);
159471e6ca61SCristina Ciocan 	u32 base, pin;
159571e6ca61SCristina Ciocan 	void __iomem *reg;
159671e6ca61SCristina Ciocan 	unsigned long pending;
159771e6ca61SCristina Ciocan 	unsigned int virq;
159871e6ca61SCristina Ciocan 
159971e6ca61SCristina Ciocan 	/* check from GPIO controller which pin triggered the interrupt */
160071e6ca61SCristina Ciocan 	for (base = 0; base < vg->chip.ngpio; base += 32) {
160171e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG);
160271e6ca61SCristina Ciocan 
160371e6ca61SCristina Ciocan 		if (!reg) {
160471e6ca61SCristina Ciocan 			dev_warn(&vg->pdev->dev,
160571e6ca61SCristina Ciocan 				 "Pin %i: could not retrieve interrupt status register\n",
160671e6ca61SCristina Ciocan 				 base);
160771e6ca61SCristina Ciocan 			continue;
160871e6ca61SCristina Ciocan 		}
160971e6ca61SCristina Ciocan 
161071e6ca61SCristina Ciocan 		pending = readl(reg);
161171e6ca61SCristina Ciocan 		for_each_set_bit(pin, &pending, 32) {
161271e6ca61SCristina Ciocan 			virq = irq_find_mapping(vg->chip.irqdomain, base + pin);
161371e6ca61SCristina Ciocan 			generic_handle_irq(virq);
161471e6ca61SCristina Ciocan 		}
161571e6ca61SCristina Ciocan 	}
161671e6ca61SCristina Ciocan 	chip->irq_eoi(data);
161771e6ca61SCristina Ciocan }
161871e6ca61SCristina Ciocan 
16195fae8b86SMika Westerberg static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
16205fae8b86SMika Westerberg {
16215fae8b86SMika Westerberg 	void __iomem *reg;
16225fae8b86SMika Westerberg 	u32 base, value;
162395f0972cSMika Westerberg 	int i;
162495f0972cSMika Westerberg 
162595f0972cSMika Westerberg 	/*
162695f0972cSMika Westerberg 	 * Clear interrupt triggers for all pins that are GPIOs and
162795f0972cSMika Westerberg 	 * do not use direct IRQ mode. This will prevent spurious
162895f0972cSMika Westerberg 	 * interrupts from misconfigured pins.
162995f0972cSMika Westerberg 	 */
163071e6ca61SCristina Ciocan 	for (i = 0; i < vg->soc_data->npins; i++) {
163171e6ca61SCristina Ciocan 		unsigned int pin = vg->soc_data->pins[i].number;
163271e6ca61SCristina Ciocan 
163371e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
163471e6ca61SCristina Ciocan 		if (!reg) {
163571e6ca61SCristina Ciocan 			dev_warn(&vg->pdev->dev,
163671e6ca61SCristina Ciocan 				 "Pin %i: could not retrieve conf0 register\n",
163771e6ca61SCristina Ciocan 				 i);
163871e6ca61SCristina Ciocan 			continue;
163971e6ca61SCristina Ciocan 		}
164071e6ca61SCristina Ciocan 
164171e6ca61SCristina Ciocan 		value = readl(reg);
164295f0972cSMika Westerberg 		if ((value & BYT_PIN_MUX) == byt_get_gpio_mux(vg, i) &&
164395f0972cSMika Westerberg 		    !(value & BYT_DIRECT_IRQ_EN)) {
164495f0972cSMika Westerberg 			byt_gpio_clear_triggering(vg, i);
164595f0972cSMika Westerberg 			dev_dbg(&vg->pdev->dev, "disabling GPIO %d\n", i);
164695f0972cSMika Westerberg 		}
164795f0972cSMika Westerberg 	}
16485fae8b86SMika Westerberg 
16495fae8b86SMika Westerberg 	/* clear interrupt status trigger registers */
165071e6ca61SCristina Ciocan 	for (base = 0; base < vg->soc_data->npins; base += 32) {
1651c501d0b1SCristina Ciocan 		reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG);
165271e6ca61SCristina Ciocan 
165371e6ca61SCristina Ciocan 		if (!reg) {
165471e6ca61SCristina Ciocan 			dev_warn(&vg->pdev->dev,
165571e6ca61SCristina Ciocan 				 "Pin %i: could not retrieve irq status reg\n",
165671e6ca61SCristina Ciocan 				 base);
165771e6ca61SCristina Ciocan 			continue;
165871e6ca61SCristina Ciocan 		}
165971e6ca61SCristina Ciocan 
16605fae8b86SMika Westerberg 		writel(0xffffffff, reg);
16615fae8b86SMika Westerberg 		/* make sure trigger bits are cleared, if not then a pin
16625fae8b86SMika Westerberg 		   might be misconfigured in bios */
16635fae8b86SMika Westerberg 		value = readl(reg);
16645fae8b86SMika Westerberg 		if (value)
16655fae8b86SMika Westerberg 			dev_err(&vg->pdev->dev,
16665fae8b86SMika Westerberg 				"GPIO interrupt error, pins misconfigured\n");
16675fae8b86SMika Westerberg 	}
16685fae8b86SMika Westerberg }
16695fae8b86SMika Westerberg 
167071e6ca61SCristina Ciocan static int byt_gpio_probe(struct byt_gpio *vg)
16715fae8b86SMika Westerberg {
16725fae8b86SMika Westerberg 	struct gpio_chip *gc;
167371e6ca61SCristina Ciocan 	struct resource *irq_rc;
16745fae8b86SMika Westerberg 	int ret;
16755fae8b86SMika Westerberg 
167671e6ca61SCristina Ciocan 	/* Set up gpio chip */
167771e6ca61SCristina Ciocan 	vg->chip	= byt_gpio_chip;
16785fae8b86SMika Westerberg 	gc		= &vg->chip;
167971e6ca61SCristina Ciocan 	gc->label	= dev_name(&vg->pdev->dev);
16805fae8b86SMika Westerberg 	gc->base	= -1;
16815fae8b86SMika Westerberg 	gc->can_sleep	= false;
168271e6ca61SCristina Ciocan 	gc->parent	= &vg->pdev->dev;
168371e6ca61SCristina Ciocan 	gc->ngpio	= vg->soc_data->npins;
16845fae8b86SMika Westerberg 
1685fcc18debSMika Westerberg #ifdef CONFIG_PM_SLEEP
168671e6ca61SCristina Ciocan 	vg->saved_context = devm_kcalloc(&vg->pdev->dev, gc->ngpio,
1687fcc18debSMika Westerberg 				       sizeof(*vg->saved_context), GFP_KERNEL);
1688fcc18debSMika Westerberg #endif
1689bf9a5c96SLinus Walleij 	ret = gpiochip_add_data(gc, vg);
16905fae8b86SMika Westerberg 	if (ret) {
169171e6ca61SCristina Ciocan 		dev_err(&vg->pdev->dev, "failed adding byt-gpio chip\n");
16925fae8b86SMika Westerberg 		return ret;
16935fae8b86SMika Westerberg 	}
16945fae8b86SMika Westerberg 
169571e6ca61SCristina Ciocan 	ret = gpiochip_add_pin_range(&vg->chip, dev_name(&vg->pdev->dev),
169671e6ca61SCristina Ciocan 				     0, 0, vg->soc_data->npins);
169771e6ca61SCristina Ciocan 	if (ret) {
169871e6ca61SCristina Ciocan 		dev_err(&vg->pdev->dev, "failed to add GPIO pin range\n");
169971e6ca61SCristina Ciocan 		goto fail;
170071e6ca61SCristina Ciocan 	}
170171e6ca61SCristina Ciocan 
17025fae8b86SMika Westerberg 	/* set up interrupts  */
170371e6ca61SCristina Ciocan 	irq_rc = platform_get_resource(vg->pdev, IORESOURCE_IRQ, 0);
17045fae8b86SMika Westerberg 	if (irq_rc && irq_rc->start) {
17055fae8b86SMika Westerberg 		byt_gpio_irq_init_hw(vg);
17065fae8b86SMika Westerberg 		ret = gpiochip_irqchip_add(gc, &byt_irqchip, 0,
17075fae8b86SMika Westerberg 					   handle_simple_irq, IRQ_TYPE_NONE);
17085fae8b86SMika Westerberg 		if (ret) {
170971e6ca61SCristina Ciocan 			dev_err(&vg->pdev->dev, "failed to add irqchip\n");
171071e6ca61SCristina Ciocan 			goto fail;
17115fae8b86SMika Westerberg 		}
17125fae8b86SMika Westerberg 
17135fae8b86SMika Westerberg 		gpiochip_set_chained_irqchip(gc, &byt_irqchip,
17145fae8b86SMika Westerberg 					     (unsigned)irq_rc->start,
17155fae8b86SMika Westerberg 					     byt_gpio_irq_handler);
17165fae8b86SMika Westerberg 	}
17175fae8b86SMika Westerberg 
171871e6ca61SCristina Ciocan 	return ret;
171971e6ca61SCristina Ciocan 
172071e6ca61SCristina Ciocan fail:
172171e6ca61SCristina Ciocan 	gpiochip_remove(&vg->chip);
172271e6ca61SCristina Ciocan 
172371e6ca61SCristina Ciocan 	return ret;
172471e6ca61SCristina Ciocan }
172571e6ca61SCristina Ciocan 
172671e6ca61SCristina Ciocan static int byt_set_soc_data(struct byt_gpio *vg,
172771e6ca61SCristina Ciocan 			    const struct byt_pinctrl_soc_data *soc_data)
172871e6ca61SCristina Ciocan {
172971e6ca61SCristina Ciocan 	int i;
173071e6ca61SCristina Ciocan 
173171e6ca61SCristina Ciocan 	vg->soc_data = soc_data;
173271e6ca61SCristina Ciocan 	vg->communities_copy = devm_kcalloc(&vg->pdev->dev,
173371e6ca61SCristina Ciocan 					    soc_data->ncommunities,
173471e6ca61SCristina Ciocan 					    sizeof(*vg->communities_copy),
173571e6ca61SCristina Ciocan 					    GFP_KERNEL);
173671e6ca61SCristina Ciocan 	if (!vg->communities_copy)
173771e6ca61SCristina Ciocan 		return -ENOMEM;
173871e6ca61SCristina Ciocan 
173971e6ca61SCristina Ciocan 	for (i = 0; i < soc_data->ncommunities; i++) {
174071e6ca61SCristina Ciocan 		struct byt_community *comm = vg->communities_copy + i;
174171e6ca61SCristina Ciocan 		struct resource *mem_rc;
174271e6ca61SCristina Ciocan 
174371e6ca61SCristina Ciocan 		*comm = vg->soc_data->communities[i];
174471e6ca61SCristina Ciocan 
174571e6ca61SCristina Ciocan 		mem_rc = platform_get_resource(vg->pdev, IORESOURCE_MEM, 0);
174671e6ca61SCristina Ciocan 		comm->reg_base = devm_ioremap_resource(&vg->pdev->dev, mem_rc);
174771e6ca61SCristina Ciocan 		if (IS_ERR(comm->reg_base))
174871e6ca61SCristina Ciocan 			return PTR_ERR(comm->reg_base);
174971e6ca61SCristina Ciocan 	}
175071e6ca61SCristina Ciocan 
175171e6ca61SCristina Ciocan 	return 0;
175271e6ca61SCristina Ciocan }
175371e6ca61SCristina Ciocan 
175471e6ca61SCristina Ciocan static const struct acpi_device_id byt_gpio_acpi_match[] = {
175571e6ca61SCristina Ciocan 	{ "INT33B2", (kernel_ulong_t)byt_soc_data },
175671e6ca61SCristina Ciocan 	{ "INT33FC", (kernel_ulong_t)byt_soc_data },
175771e6ca61SCristina Ciocan 	{ }
175871e6ca61SCristina Ciocan };
175971e6ca61SCristina Ciocan MODULE_DEVICE_TABLE(acpi, byt_gpio_acpi_match);
176071e6ca61SCristina Ciocan 
176171e6ca61SCristina Ciocan static int byt_pinctrl_probe(struct platform_device *pdev)
176271e6ca61SCristina Ciocan {
176371e6ca61SCristina Ciocan 	const struct byt_pinctrl_soc_data *soc_data = NULL;
176471e6ca61SCristina Ciocan 	const struct byt_pinctrl_soc_data **soc_table;
176571e6ca61SCristina Ciocan 	const struct acpi_device_id *acpi_id;
176671e6ca61SCristina Ciocan 	struct acpi_device *acpi_dev;
176771e6ca61SCristina Ciocan 	struct byt_gpio *vg;
176871e6ca61SCristina Ciocan 	int i, ret;
176971e6ca61SCristina Ciocan 
177071e6ca61SCristina Ciocan 	acpi_dev = ACPI_COMPANION(&pdev->dev);
177171e6ca61SCristina Ciocan 	if (!acpi_dev)
177271e6ca61SCristina Ciocan 		return -ENODEV;
177371e6ca61SCristina Ciocan 
177471e6ca61SCristina Ciocan 	acpi_id = acpi_match_device(byt_gpio_acpi_match, &pdev->dev);
177571e6ca61SCristina Ciocan 	if (!acpi_id)
177671e6ca61SCristina Ciocan 		return -ENODEV;
177771e6ca61SCristina Ciocan 
177871e6ca61SCristina Ciocan 	soc_table = (const struct byt_pinctrl_soc_data **)acpi_id->driver_data;
177971e6ca61SCristina Ciocan 
178071e6ca61SCristina Ciocan 	for (i = 0; soc_table[i]; i++) {
178171e6ca61SCristina Ciocan 		if (!strcmp(acpi_dev->pnp.unique_id, soc_table[i]->uid)) {
178271e6ca61SCristina Ciocan 			soc_data = soc_table[i];
178371e6ca61SCristina Ciocan 			break;
178471e6ca61SCristina Ciocan 		}
178571e6ca61SCristina Ciocan 	}
178671e6ca61SCristina Ciocan 
178771e6ca61SCristina Ciocan 	if (!soc_data)
178871e6ca61SCristina Ciocan 		return -ENODEV;
178971e6ca61SCristina Ciocan 
179071e6ca61SCristina Ciocan 	vg = devm_kzalloc(&pdev->dev, sizeof(*vg), GFP_KERNEL);
179171e6ca61SCristina Ciocan 	if (!vg)
179271e6ca61SCristina Ciocan 		return -ENOMEM;
179371e6ca61SCristina Ciocan 
179471e6ca61SCristina Ciocan 	vg->pdev = pdev;
179571e6ca61SCristina Ciocan 	ret = byt_set_soc_data(vg, soc_data);
179671e6ca61SCristina Ciocan 	if (ret) {
179771e6ca61SCristina Ciocan 		dev_err(&pdev->dev, "failed to set soc data\n");
179871e6ca61SCristina Ciocan 		return ret;
179971e6ca61SCristina Ciocan 	}
180071e6ca61SCristina Ciocan 
180171e6ca61SCristina Ciocan 	vg->pctl_desc		= byt_pinctrl_desc;
180271e6ca61SCristina Ciocan 	vg->pctl_desc.name	= dev_name(&pdev->dev);
180371e6ca61SCristina Ciocan 	vg->pctl_desc.pins	= vg->soc_data->pins;
180471e6ca61SCristina Ciocan 	vg->pctl_desc.npins	= vg->soc_data->npins;
180571e6ca61SCristina Ciocan 
180671e6ca61SCristina Ciocan 	vg->pctl_dev = pinctrl_register(&vg->pctl_desc, &pdev->dev, vg);
180771e6ca61SCristina Ciocan 	if (IS_ERR(vg->pctl_dev)) {
180871e6ca61SCristina Ciocan 		dev_err(&pdev->dev, "failed to register pinctrl driver\n");
180971e6ca61SCristina Ciocan 		return PTR_ERR(vg->pctl_dev);
181071e6ca61SCristina Ciocan 	}
181171e6ca61SCristina Ciocan 
181271e6ca61SCristina Ciocan 	ret = byt_gpio_probe(vg);
181371e6ca61SCristina Ciocan 	if (ret) {
181471e6ca61SCristina Ciocan 		pinctrl_unregister(vg->pctl_dev);
181571e6ca61SCristina Ciocan 		return ret;
181671e6ca61SCristina Ciocan 	}
181771e6ca61SCristina Ciocan 
181871e6ca61SCristina Ciocan 	platform_set_drvdata(pdev, vg);
181971e6ca61SCristina Ciocan 	raw_spin_lock_init(&vg->lock);
182071e6ca61SCristina Ciocan 	pm_runtime_enable(&pdev->dev);
182171e6ca61SCristina Ciocan 
182271e6ca61SCristina Ciocan 	return 0;
182371e6ca61SCristina Ciocan }
182471e6ca61SCristina Ciocan 
182571e6ca61SCristina Ciocan static int byt_pinctrl_remove(struct platform_device *pdev)
182671e6ca61SCristina Ciocan {
182771e6ca61SCristina Ciocan 	struct byt_gpio *vg = platform_get_drvdata(pdev);
182871e6ca61SCristina Ciocan 
182971e6ca61SCristina Ciocan 	pm_runtime_disable(&pdev->dev);
183071e6ca61SCristina Ciocan 	gpiochip_remove(&vg->chip);
183171e6ca61SCristina Ciocan 	pinctrl_unregister(vg->pctl_dev);
18325fae8b86SMika Westerberg 
18335fae8b86SMika Westerberg 	return 0;
18345fae8b86SMika Westerberg }
18355fae8b86SMika Westerberg 
1836fcc18debSMika Westerberg #ifdef CONFIG_PM_SLEEP
1837fcc18debSMika Westerberg static int byt_gpio_suspend(struct device *dev)
1838fcc18debSMika Westerberg {
1839fcc18debSMika Westerberg 	struct platform_device *pdev = to_platform_device(dev);
1840fcc18debSMika Westerberg 	struct byt_gpio *vg = platform_get_drvdata(pdev);
1841fcc18debSMika Westerberg 	int i;
1842fcc18debSMika Westerberg 
184371e6ca61SCristina Ciocan 	for (i = 0; i < vg->soc_data->npins; i++) {
1844fcc18debSMika Westerberg 		void __iomem *reg;
1845fcc18debSMika Westerberg 		u32 value;
184671e6ca61SCristina Ciocan 		unsigned int pin = vg->soc_data->pins[i].number;
1847fcc18debSMika Westerberg 
184871e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
184971e6ca61SCristina Ciocan 		if (!reg) {
185071e6ca61SCristina Ciocan 			dev_warn(&vg->pdev->dev,
185171e6ca61SCristina Ciocan 				 "Pin %i: could not retrieve conf0 register\n",
185271e6ca61SCristina Ciocan 				 i);
185371e6ca61SCristina Ciocan 			continue;
185471e6ca61SCristina Ciocan 		}
1855fcc18debSMika Westerberg 		value = readl(reg) & BYT_CONF0_RESTORE_MASK;
1856fcc18debSMika Westerberg 		vg->saved_context[i].conf0 = value;
1857fcc18debSMika Westerberg 
185871e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
1859fcc18debSMika Westerberg 		value = readl(reg) & BYT_VAL_RESTORE_MASK;
1860fcc18debSMika Westerberg 		vg->saved_context[i].val = value;
1861fcc18debSMika Westerberg 	}
1862fcc18debSMika Westerberg 
1863fcc18debSMika Westerberg 	return 0;
1864fcc18debSMika Westerberg }
1865fcc18debSMika Westerberg 
1866fcc18debSMika Westerberg static int byt_gpio_resume(struct device *dev)
1867fcc18debSMika Westerberg {
1868fcc18debSMika Westerberg 	struct platform_device *pdev = to_platform_device(dev);
1869fcc18debSMika Westerberg 	struct byt_gpio *vg = platform_get_drvdata(pdev);
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,
193371e6ca61SCristina Ciocan 	.remove         = byt_pinctrl_remove,
19345fae8b86SMika Westerberg 	.driver         = {
19355fae8b86SMika Westerberg 		.name   = "byt_gpio",
19365fae8b86SMika Westerberg 		.pm	= &byt_gpio_pm_ops,
19375fae8b86SMika Westerberg 		.acpi_match_table = ACPI_PTR(byt_gpio_acpi_match),
19385fae8b86SMika Westerberg 	},
19395fae8b86SMika Westerberg };
19405fae8b86SMika Westerberg 
19415fae8b86SMika Westerberg static int __init byt_gpio_init(void)
19425fae8b86SMika Westerberg {
19435fae8b86SMika Westerberg 	return platform_driver_register(&byt_gpio_driver);
19445fae8b86SMika Westerberg }
19455fae8b86SMika Westerberg subsys_initcall(byt_gpio_init);
19465fae8b86SMika Westerberg 
19475fae8b86SMika Westerberg static void __exit byt_gpio_exit(void)
19485fae8b86SMika Westerberg {
19495fae8b86SMika Westerberg 	platform_driver_unregister(&byt_gpio_driver);
19505fae8b86SMika Westerberg }
19515fae8b86SMika Westerberg module_exit(byt_gpio_exit);
1952