1875a92b3SAndy Shevchenko // SPDX-License-Identifier: GPL-2.0
25fae8b86SMika Westerberg /*
35fae8b86SMika Westerberg  * Pinctrl GPIO driver for Intel Baytrail
45fae8b86SMika Westerberg  *
5875a92b3SAndy Shevchenko  * Copyright (c) 2012-2013, Intel Corporation
65fae8b86SMika Westerberg  * Author: Mathias Nyman <mathias.nyman@linux.intel.com>
75fae8b86SMika Westerberg  */
85fae8b86SMika Westerberg 
95fae8b86SMika Westerberg #include <linux/acpi.h>
10e0da3842SAndy Shevchenko #include <linux/bitops.h>
11e0da3842SAndy Shevchenko #include <linux/gpio/driver.h>
12e0da3842SAndy Shevchenko #include <linux/init.h>
13e0da3842SAndy Shevchenko #include <linux/interrupt.h>
145fae8b86SMika Westerberg #include <linux/io.h>
15e0da3842SAndy Shevchenko #include <linux/kernel.h>
16e0da3842SAndy Shevchenko #include <linux/types.h>
17e0da3842SAndy Shevchenko #include <linux/platform_device.h>
185fae8b86SMika Westerberg #include <linux/pm_runtime.h>
1961db6c9dSAndy Shevchenko #include <linux/property.h>
20e0da3842SAndy Shevchenko #include <linux/seq_file.h>
2161db6c9dSAndy Shevchenko 
225fae8b86SMika Westerberg #include <linux/pinctrl/pinctrl.h>
23c501d0b1SCristina Ciocan #include <linux/pinctrl/pinmux.h>
24c501d0b1SCristina Ciocan #include <linux/pinctrl/pinconf.h>
25c501d0b1SCristina Ciocan #include <linux/pinctrl/pinconf-generic.h>
265fae8b86SMika Westerberg 
274f010b93SAndy Shevchenko #include "pinctrl-intel.h"
284f010b93SAndy Shevchenko 
295fae8b86SMika Westerberg /* memory mapped register offsets */
305fae8b86SMika Westerberg #define BYT_CONF0_REG		0x000
315fae8b86SMika Westerberg #define BYT_CONF1_REG		0x004
325fae8b86SMika Westerberg #define BYT_VAL_REG		0x008
335fae8b86SMika Westerberg #define BYT_DFT_REG		0x00c
345fae8b86SMika Westerberg #define BYT_INT_STAT_REG	0x800
35658b476cSCristina Ciocan #define BYT_DEBOUNCE_REG	0x9d0
365fae8b86SMika Westerberg 
375fae8b86SMika Westerberg /* BYT_CONF0_REG register bits */
385fae8b86SMika Westerberg #define BYT_IODEN		BIT(31)
395fae8b86SMika Westerberg #define BYT_DIRECT_IRQ_EN	BIT(27)
405fae8b86SMika Westerberg #define BYT_TRIG_NEG		BIT(26)
415fae8b86SMika Westerberg #define BYT_TRIG_POS		BIT(25)
425fae8b86SMika Westerberg #define BYT_TRIG_LVL		BIT(24)
43658b476cSCristina Ciocan #define BYT_DEBOUNCE_EN		BIT(20)
449291c65bSHans de Goede #define BYT_GLITCH_FILTER_EN	BIT(19)
459291c65bSHans de Goede #define BYT_GLITCH_F_SLOW_CLK	BIT(17)
469291c65bSHans de Goede #define BYT_GLITCH_F_FAST_CLK	BIT(16)
475fae8b86SMika Westerberg #define BYT_PULL_STR_SHIFT	9
485fae8b86SMika Westerberg #define BYT_PULL_STR_MASK	(3 << BYT_PULL_STR_SHIFT)
495fae8b86SMika Westerberg #define BYT_PULL_STR_2K		(0 << BYT_PULL_STR_SHIFT)
505fae8b86SMika Westerberg #define BYT_PULL_STR_10K	(1 << BYT_PULL_STR_SHIFT)
515fae8b86SMika Westerberg #define BYT_PULL_STR_20K	(2 << BYT_PULL_STR_SHIFT)
525fae8b86SMika Westerberg #define BYT_PULL_STR_40K	(3 << BYT_PULL_STR_SHIFT)
535fae8b86SMika Westerberg #define BYT_PULL_ASSIGN_SHIFT	7
545fae8b86SMika Westerberg #define BYT_PULL_ASSIGN_MASK	(3 << BYT_PULL_ASSIGN_SHIFT)
555fae8b86SMika Westerberg #define BYT_PULL_ASSIGN_UP	(1 << BYT_PULL_ASSIGN_SHIFT)
565fae8b86SMika Westerberg #define BYT_PULL_ASSIGN_DOWN	(2 << BYT_PULL_ASSIGN_SHIFT)
575fae8b86SMika Westerberg #define BYT_PIN_MUX		0x07
585fae8b86SMika Westerberg 
595fae8b86SMika Westerberg /* BYT_VAL_REG register bits */
605fae8b86SMika Westerberg #define BYT_INPUT_EN		BIT(2)  /* 0: input enabled (active low)*/
615fae8b86SMika Westerberg #define BYT_OUTPUT_EN		BIT(1)  /* 0: output enabled (active low)*/
625fae8b86SMika Westerberg #define BYT_LEVEL		BIT(0)
635fae8b86SMika Westerberg 
645fae8b86SMika Westerberg #define BYT_DIR_MASK		(BIT(1) | BIT(2))
655fae8b86SMika Westerberg #define BYT_TRIG_MASK		(BIT(26) | BIT(25) | BIT(24))
665fae8b86SMika Westerberg 
67fcc18debSMika Westerberg #define BYT_CONF0_RESTORE_MASK	(BYT_DIRECT_IRQ_EN | BYT_TRIG_MASK | \
68fcc18debSMika Westerberg 				 BYT_PIN_MUX)
69fcc18debSMika Westerberg #define BYT_VAL_RESTORE_MASK	(BYT_DIR_MASK | BYT_LEVEL)
70fcc18debSMika Westerberg 
71658b476cSCristina Ciocan /* BYT_DEBOUNCE_REG bits */
72658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_MASK		0x7
73658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_375US	1
74658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_750US	2
75658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_1500US	3
76658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_3MS		4
77658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_6MS		5
78658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_12MS		6
79658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_24MS		7
80658b476cSCristina Ciocan 
815fae8b86SMika Westerberg #define BYT_NGPIO_SCORE		102
825fae8b86SMika Westerberg #define BYT_NGPIO_NCORE		28
835fae8b86SMika Westerberg #define BYT_NGPIO_SUS		44
845fae8b86SMika Westerberg 
855fae8b86SMika Westerberg #define BYT_SCORE_ACPI_UID	"1"
865fae8b86SMika Westerberg #define BYT_NCORE_ACPI_UID	"2"
875fae8b86SMika Westerberg #define BYT_SUS_ACPI_UID	"3"
885fae8b86SMika Westerberg 
89c501d0b1SCristina Ciocan /*
90c501d0b1SCristina Ciocan  * This is the function value most pins have for GPIO muxing. If the value
91c501d0b1SCristina Ciocan  * differs from the default one, it must be explicitly mentioned. Otherwise, the
92c501d0b1SCristina Ciocan  * pin control implementation will set the muxing value to default GPIO if it
93c501d0b1SCristina Ciocan  * does not find a match for the requested function.
94c501d0b1SCristina Ciocan  */
95c501d0b1SCristina Ciocan #define BYT_DEFAULT_GPIO_MUX	0
96a705f9c1SAndy Shevchenko #define BYT_ALTER_GPIO_MUX	1
97c501d0b1SCristina Ciocan 
98c8f5c4c7SCristina Ciocan struct byt_gpio_pin_context {
99c8f5c4c7SCristina Ciocan 	u32 conf0;
100c8f5c4c7SCristina Ciocan 	u32 val;
101c8f5c4c7SCristina Ciocan };
1025fae8b86SMika Westerberg 
103c8f5c4c7SCristina Ciocan struct byt_community {
104c8f5c4c7SCristina Ciocan 	unsigned int pin_base;
105c8f5c4c7SCristina Ciocan 	size_t npins;
106c8f5c4c7SCristina Ciocan 	const unsigned int *pad_map;
107c8f5c4c7SCristina Ciocan 	void __iomem *reg_base;
108c8f5c4c7SCristina Ciocan };
109c8f5c4c7SCristina Ciocan 
110c8f5c4c7SCristina Ciocan #define COMMUNITY(p, n, map)		\
111c8f5c4c7SCristina Ciocan 	{				\
112c8f5c4c7SCristina Ciocan 		.pin_base	= (p),	\
113c8f5c4c7SCristina Ciocan 		.npins		= (n),	\
114c8f5c4c7SCristina Ciocan 		.pad_map	= (map),\
115c8f5c4c7SCristina Ciocan 	}
116c8f5c4c7SCristina Ciocan 
117c8f5c4c7SCristina Ciocan struct byt_pinctrl_soc_data {
118c8f5c4c7SCristina Ciocan 	const char *uid;
119c8f5c4c7SCristina Ciocan 	const struct pinctrl_pin_desc *pins;
120c8f5c4c7SCristina Ciocan 	size_t npins;
1214f010b93SAndy Shevchenko 	const struct intel_pingroup *groups;
122c8f5c4c7SCristina Ciocan 	size_t ngroups;
1234f010b93SAndy Shevchenko 	const struct intel_function *functions;
124c8f5c4c7SCristina Ciocan 	size_t nfunctions;
125c8f5c4c7SCristina Ciocan 	const struct byt_community *communities;
126c8f5c4c7SCristina Ciocan 	size_t ncommunities;
127c8f5c4c7SCristina Ciocan };
128c8f5c4c7SCristina Ciocan 
12971e6ca61SCristina Ciocan struct byt_gpio {
13071e6ca61SCristina Ciocan 	struct gpio_chip chip;
13171e6ca61SCristina Ciocan 	struct platform_device *pdev;
13271e6ca61SCristina Ciocan 	struct pinctrl_dev *pctl_dev;
13371e6ca61SCristina Ciocan 	struct pinctrl_desc pctl_desc;
13471e6ca61SCristina Ciocan 	raw_spinlock_t lock;
13571e6ca61SCristina Ciocan 	const struct byt_pinctrl_soc_data *soc_data;
13671e6ca61SCristina Ciocan 	struct byt_community *communities_copy;
13771e6ca61SCristina Ciocan 	struct byt_gpio_pin_context *saved_context;
13871e6ca61SCristina Ciocan };
13971e6ca61SCristina Ciocan 
140c8f5c4c7SCristina Ciocan /* SCORE pins, aka GPIOC_<pin_no> or GPIO_S0_SC[<pin_no>] */
141c8f5c4c7SCristina Ciocan static const struct pinctrl_pin_desc byt_score_pins[] = {
142c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(0, "SATA_GP0"),
143c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(1, "SATA_GP1"),
144c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(2, "SATA_LED#"),
145c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(3, "PCIE_CLKREQ0"),
146c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(4, "PCIE_CLKREQ1"),
147c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(5, "PCIE_CLKREQ2"),
148c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(6, "PCIE_CLKREQ3"),
149c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(7, "SD3_WP"),
150c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(8, "HDA_RST"),
151c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(9, "HDA_SYNC"),
152c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(10, "HDA_CLK"),
153c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(11, "HDA_SDO"),
154c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(12, "HDA_SDI0"),
155c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(13, "HDA_SDI1"),
156c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(14, "GPIO_S0_SC14"),
157c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(15, "GPIO_S0_SC15"),
158c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(16, "MMC1_CLK"),
159c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(17, "MMC1_D0"),
160c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(18, "MMC1_D1"),
161c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(19, "MMC1_D2"),
162c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(20, "MMC1_D3"),
163c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(21, "MMC1_D4"),
164c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(22, "MMC1_D5"),
165c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(23, "MMC1_D6"),
166c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(24, "MMC1_D7"),
167c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(25, "MMC1_CMD"),
168c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(26, "MMC1_RST"),
169c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(27, "SD2_CLK"),
170c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(28, "SD2_D0"),
171c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(29, "SD2_D1"),
172c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(30, "SD2_D2"),
173c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(31, "SD2_D3_CD"),
174c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(32, "SD2_CMD"),
175c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(33, "SD3_CLK"),
176c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(34, "SD3_D0"),
177c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(35, "SD3_D1"),
178c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(36, "SD3_D2"),
179c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(37, "SD3_D3"),
180c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(38, "SD3_CD"),
181c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(39, "SD3_CMD"),
182c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(40, "SD3_1P8EN"),
183c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(41, "SD3_PWREN#"),
184c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(42, "ILB_LPC_AD0"),
185c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(43, "ILB_LPC_AD1"),
186c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(44, "ILB_LPC_AD2"),
187c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(45, "ILB_LPC_AD3"),
188c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(46, "ILB_LPC_FRAME"),
189c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(47, "ILB_LPC_CLK0"),
190c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(48, "ILB_LPC_CLK1"),
191c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(49, "ILB_LPC_CLKRUN"),
192c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(50, "ILB_LPC_SERIRQ"),
193c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(51, "PCU_SMB_DATA"),
194c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(52, "PCU_SMB_CLK"),
195c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(53, "PCU_SMB_ALERT"),
196c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(54, "ILB_8254_SPKR"),
197c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(55, "GPIO_S0_SC55"),
198c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(56, "GPIO_S0_SC56"),
199c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(57, "GPIO_S0_SC57"),
200c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(58, "GPIO_S0_SC58"),
201c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(59, "GPIO_S0_SC59"),
202c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(60, "GPIO_S0_SC60"),
203c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(61, "GPIO_S0_SC61"),
204c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(62, "LPE_I2S2_CLK"),
205c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(63, "LPE_I2S2_FRM"),
206c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(64, "LPE_I2S2_DATAIN"),
207c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(65, "LPE_I2S2_DATAOUT"),
208c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(66, "SIO_SPI_CS"),
209c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(67, "SIO_SPI_MISO"),
210c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(68, "SIO_SPI_MOSI"),
211c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(69, "SIO_SPI_CLK"),
212c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(70, "SIO_UART1_RXD"),
213c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(71, "SIO_UART1_TXD"),
214c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(72, "SIO_UART1_RTS"),
215c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(73, "SIO_UART1_CTS"),
216c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(74, "SIO_UART2_RXD"),
217c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(75, "SIO_UART2_TXD"),
218c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(76, "SIO_UART2_RTS"),
219c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(77, "SIO_UART2_CTS"),
220c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(78, "SIO_I2C0_DATA"),
221c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(79, "SIO_I2C0_CLK"),
222c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(80, "SIO_I2C1_DATA"),
223c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(81, "SIO_I2C1_CLK"),
224c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(82, "SIO_I2C2_DATA"),
225c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(83, "SIO_I2C2_CLK"),
226c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(84, "SIO_I2C3_DATA"),
227c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(85, "SIO_I2C3_CLK"),
228c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(86, "SIO_I2C4_DATA"),
229c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(87, "SIO_I2C4_CLK"),
230c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(88, "SIO_I2C5_DATA"),
231c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(89, "SIO_I2C5_CLK"),
232c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(90, "SIO_I2C6_DATA"),
233c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(91, "SIO_I2C6_CLK"),
234c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(92, "GPIO_S0_SC92"),
235c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(93, "GPIO_S0_SC93"),
236c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(94, "SIO_PWM0"),
237c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(95, "SIO_PWM1"),
238c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(96, "PMC_PLT_CLK0"),
239c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(97, "PMC_PLT_CLK1"),
240c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(98, "PMC_PLT_CLK2"),
241c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(99, "PMC_PLT_CLK3"),
242c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(100, "PMC_PLT_CLK4"),
243c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(101, "PMC_PLT_CLK5"),
244c8f5c4c7SCristina Ciocan };
2455fae8b86SMika Westerberg 
246c8f5c4c7SCristina Ciocan static const unsigned int byt_score_pins_map[BYT_NGPIO_SCORE] = {
247c8f5c4c7SCristina Ciocan 	85, 89, 93, 96, 99, 102, 98, 101, 34, 37,
248c8f5c4c7SCristina Ciocan 	36, 38, 39, 35, 40, 84, 62, 61, 64, 59,
249c8f5c4c7SCristina Ciocan 	54, 56, 60, 55, 63, 57, 51, 50, 53, 47,
250c8f5c4c7SCristina Ciocan 	52, 49, 48, 43, 46, 41, 45, 42, 58, 44,
251c8f5c4c7SCristina Ciocan 	95, 105, 70, 68, 67, 66, 69, 71, 65, 72,
252c8f5c4c7SCristina Ciocan 	86, 90, 88, 92, 103, 77, 79, 83, 78, 81,
253c8f5c4c7SCristina Ciocan 	80, 82, 13, 12, 15, 14, 17, 18, 19, 16,
254c8f5c4c7SCristina Ciocan 	2, 1, 0, 4, 6, 7, 9, 8, 33, 32,
255c8f5c4c7SCristina Ciocan 	31, 30, 29, 27, 25, 28, 26, 23, 21, 20,
256c8f5c4c7SCristina Ciocan 	24, 22, 5, 3, 10, 11, 106, 87, 91, 104,
257c8f5c4c7SCristina Ciocan 	97, 100,
2585fae8b86SMika Westerberg };
2595fae8b86SMika Westerberg 
260c8f5c4c7SCristina Ciocan /* SCORE groups */
261c8f5c4c7SCristina Ciocan static const unsigned int byt_score_uart1_pins[] = { 70, 71, 72, 73 };
262c8f5c4c7SCristina Ciocan static const unsigned int byt_score_uart2_pins[] = { 74, 75, 76, 77 };
263c8f5c4c7SCristina Ciocan 
264c8f5c4c7SCristina Ciocan static const unsigned int byt_score_pwm0_pins[] = { 94 };
265c8f5c4c7SCristina Ciocan static const unsigned int byt_score_pwm1_pins[] = { 95 };
266c8f5c4c7SCristina Ciocan 
267c8f5c4c7SCristina Ciocan static const unsigned int byt_score_sio_spi_pins[] = { 66, 67, 68, 69 };
268c8f5c4c7SCristina Ciocan 
269c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c5_pins[] = { 88, 89 };
270c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c6_pins[] = { 90, 91 };
271c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c4_pins[] = { 86, 87 };
272c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c3_pins[] = { 84, 85 };
273c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c2_pins[] = { 82, 83 };
274c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c1_pins[] = { 80, 81 };
275c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c0_pins[] = { 78, 79 };
276c8f5c4c7SCristina Ciocan 
277c8f5c4c7SCristina Ciocan static const unsigned int byt_score_ssp0_pins[] = { 8, 9, 10, 11 };
278c8f5c4c7SCristina Ciocan static const unsigned int byt_score_ssp1_pins[] = { 12, 13, 14, 15 };
279c8f5c4c7SCristina Ciocan static const unsigned int byt_score_ssp2_pins[] = { 62, 63, 64, 65 };
280c8f5c4c7SCristina Ciocan 
281c8f5c4c7SCristina Ciocan static const unsigned int byt_score_sdcard_pins[] = {
282c8f5c4c7SCristina Ciocan 	7, 33, 34, 35, 36, 37, 38, 39, 40, 41,
283c8f5c4c7SCristina Ciocan };
2844f010b93SAndy Shevchenko static const unsigned int byt_score_sdcard_mux_values[] = {
285c8f5c4c7SCristina Ciocan 	2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
286c8f5c4c7SCristina Ciocan };
287c8f5c4c7SCristina Ciocan 
288c8f5c4c7SCristina Ciocan static const unsigned int byt_score_sdio_pins[] = { 27, 28, 29, 30, 31, 32 };
289c8f5c4c7SCristina Ciocan 
290c8f5c4c7SCristina Ciocan static const unsigned int byt_score_emmc_pins[] = {
291c8f5c4c7SCristina Ciocan 	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
292c8f5c4c7SCristina Ciocan };
293c8f5c4c7SCristina Ciocan 
294c8f5c4c7SCristina Ciocan static const unsigned int byt_score_ilb_lpc_pins[] = {
295c8f5c4c7SCristina Ciocan 	42, 43, 44, 45, 46, 47, 48, 49, 50,
296c8f5c4c7SCristina Ciocan };
297c8f5c4c7SCristina Ciocan 
298c8f5c4c7SCristina Ciocan static const unsigned int byt_score_sata_pins[] = { 0, 1, 2 };
299c8f5c4c7SCristina Ciocan 
300c8f5c4c7SCristina Ciocan static const unsigned int byt_score_plt_clk0_pins[] = { 96 };
301c8f5c4c7SCristina Ciocan static const unsigned int byt_score_plt_clk1_pins[] = { 97 };
302c8f5c4c7SCristina Ciocan static const unsigned int byt_score_plt_clk2_pins[] = { 98 };
303b41aa4f8SCristina Ciocan static const unsigned int byt_score_plt_clk3_pins[] = { 99 };
304b41aa4f8SCristina Ciocan static const unsigned int byt_score_plt_clk4_pins[] = { 100 };
305b41aa4f8SCristina Ciocan static const unsigned int byt_score_plt_clk5_pins[] = { 101 };
306c8f5c4c7SCristina Ciocan 
307c8f5c4c7SCristina Ciocan static const unsigned int byt_score_smbus_pins[] = { 51, 52, 53 };
308c8f5c4c7SCristina Ciocan 
3094f010b93SAndy Shevchenko static const struct intel_pingroup byt_score_groups[] = {
3104f010b93SAndy Shevchenko 	PIN_GROUP("uart1_grp", byt_score_uart1_pins, 1),
3114f010b93SAndy Shevchenko 	PIN_GROUP("uart2_grp", byt_score_uart2_pins, 1),
3124f010b93SAndy Shevchenko 	PIN_GROUP("pwm0_grp", byt_score_pwm0_pins, 1),
3134f010b93SAndy Shevchenko 	PIN_GROUP("pwm1_grp", byt_score_pwm1_pins, 1),
3144f010b93SAndy Shevchenko 	PIN_GROUP("ssp2_grp", byt_score_ssp2_pins, 1),
3154f010b93SAndy Shevchenko 	PIN_GROUP("sio_spi_grp", byt_score_sio_spi_pins, 1),
3164f010b93SAndy Shevchenko 	PIN_GROUP("i2c5_grp", byt_score_i2c5_pins, 1),
3174f010b93SAndy Shevchenko 	PIN_GROUP("i2c6_grp", byt_score_i2c6_pins, 1),
3184f010b93SAndy Shevchenko 	PIN_GROUP("i2c4_grp", byt_score_i2c4_pins, 1),
3194f010b93SAndy Shevchenko 	PIN_GROUP("i2c3_grp", byt_score_i2c3_pins, 1),
3204f010b93SAndy Shevchenko 	PIN_GROUP("i2c2_grp", byt_score_i2c2_pins, 1),
3214f010b93SAndy Shevchenko 	PIN_GROUP("i2c1_grp", byt_score_i2c1_pins, 1),
3224f010b93SAndy Shevchenko 	PIN_GROUP("i2c0_grp", byt_score_i2c0_pins, 1),
3234f010b93SAndy Shevchenko 	PIN_GROUP("ssp0_grp", byt_score_ssp0_pins, 1),
3244f010b93SAndy Shevchenko 	PIN_GROUP("ssp1_grp", byt_score_ssp1_pins, 1),
3254f010b93SAndy Shevchenko 	PIN_GROUP("sdcard_grp", byt_score_sdcard_pins, byt_score_sdcard_mux_values),
3264f010b93SAndy Shevchenko 	PIN_GROUP("sdio_grp", byt_score_sdio_pins, 1),
3274f010b93SAndy Shevchenko 	PIN_GROUP("emmc_grp", byt_score_emmc_pins, 1),
3284f010b93SAndy Shevchenko 	PIN_GROUP("lpc_grp", byt_score_ilb_lpc_pins, 1),
3294f010b93SAndy Shevchenko 	PIN_GROUP("sata_grp", byt_score_sata_pins, 1),
3304f010b93SAndy Shevchenko 	PIN_GROUP("plt_clk0_grp", byt_score_plt_clk0_pins, 1),
3314f010b93SAndy Shevchenko 	PIN_GROUP("plt_clk1_grp", byt_score_plt_clk1_pins, 1),
3324f010b93SAndy Shevchenko 	PIN_GROUP("plt_clk2_grp", byt_score_plt_clk2_pins, 1),
3334f010b93SAndy Shevchenko 	PIN_GROUP("plt_clk3_grp", byt_score_plt_clk3_pins, 1),
3344f010b93SAndy Shevchenko 	PIN_GROUP("plt_clk4_grp", byt_score_plt_clk4_pins, 1),
3354f010b93SAndy Shevchenko 	PIN_GROUP("plt_clk5_grp", byt_score_plt_clk5_pins, 1),
3364f010b93SAndy Shevchenko 	PIN_GROUP("smbus_grp", byt_score_smbus_pins, 1),
337c8f5c4c7SCristina Ciocan };
338c8f5c4c7SCristina Ciocan 
339c8f5c4c7SCristina Ciocan static const char * const byt_score_uart_groups[] = {
340c8f5c4c7SCristina Ciocan 	"uart1_grp", "uart2_grp",
341c8f5c4c7SCristina Ciocan };
342c8f5c4c7SCristina Ciocan static const char * const byt_score_pwm_groups[] = {
343c8f5c4c7SCristina Ciocan 	"pwm0_grp", "pwm1_grp",
344c8f5c4c7SCristina Ciocan };
345c8f5c4c7SCristina Ciocan static const char * const byt_score_ssp_groups[] = {
346c8f5c4c7SCristina Ciocan 	"ssp0_grp", "ssp1_grp", "ssp2_grp",
347c8f5c4c7SCristina Ciocan };
348c8f5c4c7SCristina Ciocan static const char * const byt_score_spi_groups[] = { "sio_spi_grp" };
349c8f5c4c7SCristina Ciocan static const char * const byt_score_i2c_groups[] = {
350c8f5c4c7SCristina Ciocan 	"i2c0_grp", "i2c1_grp", "i2c2_grp", "i2c3_grp", "i2c4_grp", "i2c5_grp",
351c8f5c4c7SCristina Ciocan 	"i2c6_grp",
352c8f5c4c7SCristina Ciocan };
353c8f5c4c7SCristina Ciocan static const char * const byt_score_sdcard_groups[] = { "sdcard_grp" };
354c8f5c4c7SCristina Ciocan static const char * const byt_score_sdio_groups[] = { "sdio_grp" };
355c8f5c4c7SCristina Ciocan static const char * const byt_score_emmc_groups[] = { "emmc_grp" };
356c8f5c4c7SCristina Ciocan static const char * const byt_score_lpc_groups[] = { "lpc_grp" };
357c8f5c4c7SCristina Ciocan static const char * const byt_score_sata_groups[] = { "sata_grp" };
358c8f5c4c7SCristina Ciocan static const char * const byt_score_plt_clk_groups[] = {
359c8f5c4c7SCristina Ciocan 	"plt_clk0_grp", "plt_clk1_grp", "plt_clk2_grp", "plt_clk3_grp",
360c8f5c4c7SCristina Ciocan 	"plt_clk4_grp", "plt_clk5_grp",
361c8f5c4c7SCristina Ciocan };
362c8f5c4c7SCristina Ciocan static const char * const byt_score_smbus_groups[] = { "smbus_grp" };
363c8f5c4c7SCristina Ciocan static const char * const byt_score_gpio_groups[] = {
364c8f5c4c7SCristina Ciocan 	"uart1_grp", "uart2_grp", "pwm0_grp", "pwm1_grp", "ssp0_grp",
365c8f5c4c7SCristina Ciocan 	"ssp1_grp", "ssp2_grp", "sio_spi_grp", "i2c0_grp", "i2c1_grp",
366c8f5c4c7SCristina Ciocan 	"i2c2_grp", "i2c3_grp", "i2c4_grp", "i2c5_grp", "i2c6_grp",
367c8f5c4c7SCristina Ciocan 	"sdcard_grp", "sdio_grp", "emmc_grp", "lpc_grp", "sata_grp",
368c8f5c4c7SCristina Ciocan 	"plt_clk0_grp", "plt_clk1_grp", "plt_clk2_grp", "plt_clk3_grp",
369c8f5c4c7SCristina Ciocan 	"plt_clk4_grp", "plt_clk5_grp", "smbus_grp",
370c8f5c4c7SCristina Ciocan };
371c8f5c4c7SCristina Ciocan 
3724f010b93SAndy Shevchenko static const struct intel_function byt_score_functions[] = {
373c8f5c4c7SCristina Ciocan 	FUNCTION("uart", byt_score_uart_groups),
374c8f5c4c7SCristina Ciocan 	FUNCTION("pwm", byt_score_pwm_groups),
375c8f5c4c7SCristina Ciocan 	FUNCTION("ssp", byt_score_ssp_groups),
376c8f5c4c7SCristina Ciocan 	FUNCTION("spi", byt_score_spi_groups),
377c8f5c4c7SCristina Ciocan 	FUNCTION("i2c", byt_score_i2c_groups),
378c8f5c4c7SCristina Ciocan 	FUNCTION("sdcard", byt_score_sdcard_groups),
379c8f5c4c7SCristina Ciocan 	FUNCTION("sdio", byt_score_sdio_groups),
380c8f5c4c7SCristina Ciocan 	FUNCTION("emmc", byt_score_emmc_groups),
381c8f5c4c7SCristina Ciocan 	FUNCTION("lpc", byt_score_lpc_groups),
382c8f5c4c7SCristina Ciocan 	FUNCTION("sata", byt_score_sata_groups),
383c8f5c4c7SCristina Ciocan 	FUNCTION("plt_clk", byt_score_plt_clk_groups),
384c8f5c4c7SCristina Ciocan 	FUNCTION("smbus", byt_score_smbus_groups),
385c8f5c4c7SCristina Ciocan 	FUNCTION("gpio", byt_score_gpio_groups),
386c8f5c4c7SCristina Ciocan };
387c8f5c4c7SCristina Ciocan 
388c8f5c4c7SCristina Ciocan static const struct byt_community byt_score_communities[] = {
389c8f5c4c7SCristina Ciocan 	COMMUNITY(0, BYT_NGPIO_SCORE, byt_score_pins_map),
390c8f5c4c7SCristina Ciocan };
391c8f5c4c7SCristina Ciocan 
392c8f5c4c7SCristina Ciocan static const struct byt_pinctrl_soc_data byt_score_soc_data = {
393c8f5c4c7SCristina Ciocan 	.uid		= BYT_SCORE_ACPI_UID,
394c8f5c4c7SCristina Ciocan 	.pins		= byt_score_pins,
395c8f5c4c7SCristina Ciocan 	.npins		= ARRAY_SIZE(byt_score_pins),
396c8f5c4c7SCristina Ciocan 	.groups		= byt_score_groups,
397c8f5c4c7SCristina Ciocan 	.ngroups	= ARRAY_SIZE(byt_score_groups),
398c8f5c4c7SCristina Ciocan 	.functions	= byt_score_functions,
399c8f5c4c7SCristina Ciocan 	.nfunctions	= ARRAY_SIZE(byt_score_functions),
400c8f5c4c7SCristina Ciocan 	.communities	= byt_score_communities,
401c8f5c4c7SCristina Ciocan 	.ncommunities	= ARRAY_SIZE(byt_score_communities),
402c8f5c4c7SCristina Ciocan };
403c8f5c4c7SCristina Ciocan 
404c8f5c4c7SCristina Ciocan /* SUS pins, aka GPIOS_<pin_no> or GPIO_S5[<pin_no>]  */
405c8f5c4c7SCristina Ciocan static const struct pinctrl_pin_desc byt_sus_pins[] = {
406c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(0, "GPIO_S50"),
407c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(1, "GPIO_S51"),
408c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(2, "GPIO_S52"),
409c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(3, "GPIO_S53"),
410c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(4, "GPIO_S54"),
411c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(5, "GPIO_S55"),
412c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(6, "GPIO_S56"),
413c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(7, "GPIO_S57"),
414c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(8, "GPIO_S58"),
415c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(9, "GPIO_S59"),
416c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(10, "GPIO_S510"),
417c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(11, "PMC_SUSPWRDNACK"),
418c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(12, "PMC_SUSCLK0"),
419c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(13, "GPIO_S513"),
420c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(14, "USB_ULPI_RST"),
421c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(15, "PMC_WAKE_PCIE0#"),
422c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(16, "PMC_PWRBTN"),
423c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(17, "GPIO_S517"),
424c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(18, "PMC_SUS_STAT"),
425c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(19, "USB_OC0"),
426c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(20, "USB_OC1"),
427c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(21, "PCU_SPI_CS1"),
428c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(22, "GPIO_S522"),
429c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(23, "GPIO_S523"),
430c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(24, "GPIO_S524"),
431c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(25, "GPIO_S525"),
432c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(26, "GPIO_S526"),
433c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(27, "GPIO_S527"),
434c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(28, "GPIO_S528"),
435c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(29, "GPIO_S529"),
436c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(30, "GPIO_S530"),
437c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(31, "USB_ULPI_CLK"),
438c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(32, "USB_ULPI_DATA0"),
439c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(33, "USB_ULPI_DATA1"),
440c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(34, "USB_ULPI_DATA2"),
441c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(35, "USB_ULPI_DATA3"),
442c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(36, "USB_ULPI_DATA4"),
443c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(37, "USB_ULPI_DATA5"),
444c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(38, "USB_ULPI_DATA6"),
445c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(39, "USB_ULPI_DATA7"),
446c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(40, "USB_ULPI_DIR"),
447c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(41, "USB_ULPI_NXT"),
448c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(42, "USB_ULPI_STP"),
449c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(43, "USB_ULPI_REFCLK"),
450c8f5c4c7SCristina Ciocan };
451c8f5c4c7SCristina Ciocan 
452c8f5c4c7SCristina Ciocan static const unsigned int byt_sus_pins_map[BYT_NGPIO_SUS] = {
453c8f5c4c7SCristina Ciocan 	29, 33, 30, 31, 32, 34, 36, 35, 38, 37,
454c8f5c4c7SCristina Ciocan 	18, 7, 11, 20, 17, 1, 8, 10, 19, 12,
455c8f5c4c7SCristina Ciocan 	0, 2, 23, 39, 28, 27, 22, 21, 24, 25,
456c8f5c4c7SCristina Ciocan 	26, 51, 56, 54, 49, 55, 48, 57, 50, 58,
457c8f5c4c7SCristina Ciocan 	52, 53, 59, 40,
458c8f5c4c7SCristina Ciocan };
459c8f5c4c7SCristina Ciocan 
460c8f5c4c7SCristina Ciocan static const unsigned int byt_sus_usb_over_current_pins[] = { 19, 20 };
4614f010b93SAndy Shevchenko static const unsigned int byt_sus_usb_over_current_mode_values[] = { 0, 0 };
4624f010b93SAndy Shevchenko static const unsigned int byt_sus_usb_over_current_gpio_mode_values[] = { 1, 1 };
463c8f5c4c7SCristina Ciocan 
464c8f5c4c7SCristina Ciocan static const unsigned int byt_sus_usb_ulpi_pins[] = {
465c8f5c4c7SCristina Ciocan 	14, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
466c8f5c4c7SCristina Ciocan };
4674f010b93SAndy Shevchenko static const unsigned int byt_sus_usb_ulpi_mode_values[] = {
468c8f5c4c7SCristina Ciocan 	2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
469c8f5c4c7SCristina Ciocan };
4704f010b93SAndy Shevchenko static const unsigned int byt_sus_usb_ulpi_gpio_mode_values[] = {
4714f010b93SAndy Shevchenko 	1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
472c8f5c4c7SCristina Ciocan };
473c8f5c4c7SCristina Ciocan 
474c8f5c4c7SCristina Ciocan static const unsigned int byt_sus_pcu_spi_pins[] = { 21 };
4754f010b93SAndy Shevchenko static const unsigned int byt_sus_pcu_spi_mode_values[] = { 0 };
4764f010b93SAndy Shevchenko static const unsigned int byt_sus_pcu_spi_gpio_mode_values[] = { 1 };
477c8f5c4c7SCristina Ciocan 
4784f010b93SAndy Shevchenko static const struct intel_pingroup byt_sus_groups[] = {
4794f010b93SAndy Shevchenko 	PIN_GROUP("usb_oc_grp", byt_sus_usb_over_current_pins, byt_sus_usb_over_current_mode_values),
4804f010b93SAndy Shevchenko 	PIN_GROUP("usb_ulpi_grp", byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_mode_values),
4814f010b93SAndy Shevchenko 	PIN_GROUP("pcu_spi_grp", byt_sus_pcu_spi_pins, byt_sus_pcu_spi_mode_values),
4824f010b93SAndy Shevchenko 	PIN_GROUP("usb_oc_grp_gpio", byt_sus_usb_over_current_pins, byt_sus_usb_over_current_gpio_mode_values),
4834f010b93SAndy Shevchenko 	PIN_GROUP("usb_ulpi_grp_gpio", byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_gpio_mode_values),
4844f010b93SAndy Shevchenko 	PIN_GROUP("pcu_spi_grp_gpio", byt_sus_pcu_spi_pins, byt_sus_pcu_spi_gpio_mode_values),
485c8f5c4c7SCristina Ciocan };
486c8f5c4c7SCristina Ciocan 
487c8f5c4c7SCristina Ciocan static const char * const byt_sus_usb_groups[] = {
488c8f5c4c7SCristina Ciocan 	"usb_oc_grp", "usb_ulpi_grp",
489c8f5c4c7SCristina Ciocan };
490c8f5c4c7SCristina Ciocan static const char * const byt_sus_spi_groups[] = { "pcu_spi_grp" };
491c8f5c4c7SCristina Ciocan static const char * const byt_sus_gpio_groups[] = {
4924f010b93SAndy Shevchenko 	"usb_oc_grp_gpio", "usb_ulpi_grp_gpio", "pcu_spi_grp_gpio",
493c8f5c4c7SCristina Ciocan };
494c8f5c4c7SCristina Ciocan 
4954f010b93SAndy Shevchenko static const struct intel_function byt_sus_functions[] = {
496c8f5c4c7SCristina Ciocan 	FUNCTION("usb", byt_sus_usb_groups),
497c8f5c4c7SCristina Ciocan 	FUNCTION("spi", byt_sus_spi_groups),
498c8f5c4c7SCristina Ciocan 	FUNCTION("gpio", byt_sus_gpio_groups),
499c8f5c4c7SCristina Ciocan };
500c8f5c4c7SCristina Ciocan 
501c8f5c4c7SCristina Ciocan static const struct byt_community byt_sus_communities[] = {
502c8f5c4c7SCristina Ciocan 	COMMUNITY(0, BYT_NGPIO_SUS, byt_sus_pins_map),
503c8f5c4c7SCristina Ciocan };
504c8f5c4c7SCristina Ciocan 
505c8f5c4c7SCristina Ciocan static const struct byt_pinctrl_soc_data byt_sus_soc_data = {
506c8f5c4c7SCristina Ciocan 	.uid		= BYT_SUS_ACPI_UID,
507c8f5c4c7SCristina Ciocan 	.pins		= byt_sus_pins,
508c8f5c4c7SCristina Ciocan 	.npins		= ARRAY_SIZE(byt_sus_pins),
509c8f5c4c7SCristina Ciocan 	.groups		= byt_sus_groups,
510c8f5c4c7SCristina Ciocan 	.ngroups	= ARRAY_SIZE(byt_sus_groups),
511c8f5c4c7SCristina Ciocan 	.functions	= byt_sus_functions,
512c8f5c4c7SCristina Ciocan 	.nfunctions	= ARRAY_SIZE(byt_sus_functions),
513c8f5c4c7SCristina Ciocan 	.communities	= byt_sus_communities,
514c8f5c4c7SCristina Ciocan 	.ncommunities	= ARRAY_SIZE(byt_sus_communities),
515c8f5c4c7SCristina Ciocan };
516c8f5c4c7SCristina Ciocan 
517c8f5c4c7SCristina Ciocan static const struct pinctrl_pin_desc byt_ncore_pins[] = {
518c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(0, "GPIO_NCORE0"),
519c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(1, "GPIO_NCORE1"),
520c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(2, "GPIO_NCORE2"),
521c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(3, "GPIO_NCORE3"),
522c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(4, "GPIO_NCORE4"),
523c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(5, "GPIO_NCORE5"),
524c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(6, "GPIO_NCORE6"),
525c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(7, "GPIO_NCORE7"),
526c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(8, "GPIO_NCORE8"),
527c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(9, "GPIO_NCORE9"),
528c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(10, "GPIO_NCORE10"),
529c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(11, "GPIO_NCORE11"),
530c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(12, "GPIO_NCORE12"),
531c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(13, "GPIO_NCORE13"),
532c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(14, "GPIO_NCORE14"),
533c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(15, "GPIO_NCORE15"),
534c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(16, "GPIO_NCORE16"),
535c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(17, "GPIO_NCORE17"),
536c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(18, "GPIO_NCORE18"),
537c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(19, "GPIO_NCORE19"),
538c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(20, "GPIO_NCORE20"),
539c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(21, "GPIO_NCORE21"),
540c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(22, "GPIO_NCORE22"),
541c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(23, "GPIO_NCORE23"),
542c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(24, "GPIO_NCORE24"),
543c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(25, "GPIO_NCORE25"),
544c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(26, "GPIO_NCORE26"),
545c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(27, "GPIO_NCORE27"),
546c8f5c4c7SCristina Ciocan };
547c8f5c4c7SCristina Ciocan 
548939330d7SAndy Shevchenko static const unsigned int byt_ncore_pins_map[BYT_NGPIO_NCORE] = {
549c8f5c4c7SCristina Ciocan 	19, 18, 17, 20, 21, 22, 24, 25, 23, 16,
550c8f5c4c7SCristina Ciocan 	14, 15, 12, 26, 27, 1, 4, 8, 11, 0,
551c8f5c4c7SCristina Ciocan 	3, 6, 10, 13, 2, 5, 9, 7,
552c8f5c4c7SCristina Ciocan };
553c8f5c4c7SCristina Ciocan 
554c8f5c4c7SCristina Ciocan static const struct byt_community byt_ncore_communities[] = {
555c8f5c4c7SCristina Ciocan 	COMMUNITY(0, BYT_NGPIO_NCORE, byt_ncore_pins_map),
556c8f5c4c7SCristina Ciocan };
557c8f5c4c7SCristina Ciocan 
558c8f5c4c7SCristina Ciocan static const struct byt_pinctrl_soc_data byt_ncore_soc_data = {
559c8f5c4c7SCristina Ciocan 	.uid		= BYT_NCORE_ACPI_UID,
560c8f5c4c7SCristina Ciocan 	.pins		= byt_ncore_pins,
561c8f5c4c7SCristina Ciocan 	.npins		= ARRAY_SIZE(byt_ncore_pins),
562c8f5c4c7SCristina Ciocan 	.communities	= byt_ncore_communities,
563c8f5c4c7SCristina Ciocan 	.ncommunities	= ARRAY_SIZE(byt_ncore_communities),
564c8f5c4c7SCristina Ciocan };
565c8f5c4c7SCristina Ciocan 
566c8f5c4c7SCristina Ciocan static const struct byt_pinctrl_soc_data *byt_soc_data[] = {
567c8f5c4c7SCristina Ciocan 	&byt_score_soc_data,
568c8f5c4c7SCristina Ciocan 	&byt_sus_soc_data,
569c8f5c4c7SCristina Ciocan 	&byt_ncore_soc_data,
570166d6e2aSAndy Shevchenko 	NULL
571c8f5c4c7SCristina Ciocan };
572c8f5c4c7SCristina Ciocan 
573c501d0b1SCristina Ciocan static struct byt_community *byt_get_community(struct byt_gpio *vg,
574c501d0b1SCristina Ciocan 					       unsigned int pin)
575c501d0b1SCristina Ciocan {
576c501d0b1SCristina Ciocan 	struct byt_community *comm;
577c501d0b1SCristina Ciocan 	int i;
578c501d0b1SCristina Ciocan 
579c501d0b1SCristina Ciocan 	for (i = 0; i < vg->soc_data->ncommunities; i++) {
580c501d0b1SCristina Ciocan 		comm = vg->communities_copy + i;
581c501d0b1SCristina Ciocan 		if (pin < comm->pin_base + comm->npins && pin >= comm->pin_base)
582c501d0b1SCristina Ciocan 			return comm;
583c501d0b1SCristina Ciocan 	}
584c501d0b1SCristina Ciocan 
585c501d0b1SCristina Ciocan 	return NULL;
586c501d0b1SCristina Ciocan }
587c501d0b1SCristina Ciocan 
588c501d0b1SCristina Ciocan static void __iomem *byt_gpio_reg(struct byt_gpio *vg, unsigned int offset,
5895fae8b86SMika Westerberg 				  int reg)
5905fae8b86SMika Westerberg {
591c501d0b1SCristina Ciocan 	struct byt_community *comm = byt_get_community(vg, offset);
5921b89970dSAndy Shevchenko 	u32 reg_offset;
5935fae8b86SMika Westerberg 
594c501d0b1SCristina Ciocan 	if (!comm)
595c501d0b1SCristina Ciocan 		return NULL;
596c501d0b1SCristina Ciocan 
597c501d0b1SCristina Ciocan 	offset -= comm->pin_base;
5981b89970dSAndy Shevchenko 	switch (reg) {
5991b89970dSAndy Shevchenko 	case BYT_INT_STAT_REG:
6005fae8b86SMika Westerberg 		reg_offset = (offset / 32) * 4;
6011b89970dSAndy Shevchenko 		break;
6021b89970dSAndy Shevchenko 	case BYT_DEBOUNCE_REG:
6031b89970dSAndy Shevchenko 		reg_offset = 0;
6041b89970dSAndy Shevchenko 		break;
6051b89970dSAndy Shevchenko 	default:
606c501d0b1SCristina Ciocan 		reg_offset = comm->pad_map[offset] * 16;
6071b89970dSAndy Shevchenko 		break;
6081b89970dSAndy Shevchenko 	}
6095fae8b86SMika Westerberg 
610c501d0b1SCristina Ciocan 	return comm->reg_base + reg_offset + reg;
6115fae8b86SMika Westerberg }
6125fae8b86SMika Westerberg 
613c501d0b1SCristina Ciocan static int byt_get_groups_count(struct pinctrl_dev *pctldev)
61495f0972cSMika Westerberg {
615c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
616c501d0b1SCristina Ciocan 
617c501d0b1SCristina Ciocan 	return vg->soc_data->ngroups;
618c501d0b1SCristina Ciocan }
619c501d0b1SCristina Ciocan 
620c501d0b1SCristina Ciocan static const char *byt_get_group_name(struct pinctrl_dev *pctldev,
621c501d0b1SCristina Ciocan 				      unsigned int selector)
622c501d0b1SCristina Ciocan {
623c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
624c501d0b1SCristina Ciocan 
625c501d0b1SCristina Ciocan 	return vg->soc_data->groups[selector].name;
626c501d0b1SCristina Ciocan }
627c501d0b1SCristina Ciocan 
628c501d0b1SCristina Ciocan static int byt_get_group_pins(struct pinctrl_dev *pctldev,
629c501d0b1SCristina Ciocan 			      unsigned int selector,
630c501d0b1SCristina Ciocan 			      const unsigned int **pins,
631c501d0b1SCristina Ciocan 			      unsigned int *num_pins)
632c501d0b1SCristina Ciocan {
633c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
634c501d0b1SCristina Ciocan 
635c501d0b1SCristina Ciocan 	*pins		= vg->soc_data->groups[selector].pins;
636c501d0b1SCristina Ciocan 	*num_pins	= vg->soc_data->groups[selector].npins;
637c501d0b1SCristina Ciocan 
638c501d0b1SCristina Ciocan 	return 0;
639c501d0b1SCristina Ciocan }
640c501d0b1SCristina Ciocan 
641c501d0b1SCristina Ciocan static const struct pinctrl_ops byt_pinctrl_ops = {
642c501d0b1SCristina Ciocan 	.get_groups_count	= byt_get_groups_count,
643c501d0b1SCristina Ciocan 	.get_group_name		= byt_get_group_name,
644c501d0b1SCristina Ciocan 	.get_group_pins		= byt_get_group_pins,
645c501d0b1SCristina Ciocan };
646c501d0b1SCristina Ciocan 
647c501d0b1SCristina Ciocan static int byt_get_functions_count(struct pinctrl_dev *pctldev)
648c501d0b1SCristina Ciocan {
649c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
650c501d0b1SCristina Ciocan 
651c501d0b1SCristina Ciocan 	return vg->soc_data->nfunctions;
652c501d0b1SCristina Ciocan }
653c501d0b1SCristina Ciocan 
654c501d0b1SCristina Ciocan static const char *byt_get_function_name(struct pinctrl_dev *pctldev,
655c501d0b1SCristina Ciocan 					 unsigned int selector)
656c501d0b1SCristina Ciocan {
657c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
658c501d0b1SCristina Ciocan 
659c501d0b1SCristina Ciocan 	return vg->soc_data->functions[selector].name;
660c501d0b1SCristina Ciocan }
661c501d0b1SCristina Ciocan 
662c501d0b1SCristina Ciocan static int byt_get_function_groups(struct pinctrl_dev *pctldev,
663c501d0b1SCristina Ciocan 				   unsigned int selector,
664c501d0b1SCristina Ciocan 				   const char * const **groups,
665c501d0b1SCristina Ciocan 				   unsigned int *num_groups)
666c501d0b1SCristina Ciocan {
667c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
668c501d0b1SCristina Ciocan 
669c501d0b1SCristina Ciocan 	*groups		= vg->soc_data->functions[selector].groups;
670c501d0b1SCristina Ciocan 	*num_groups	= vg->soc_data->functions[selector].ngroups;
671c501d0b1SCristina Ciocan 
672c501d0b1SCristina Ciocan 	return 0;
673c501d0b1SCristina Ciocan }
674c501d0b1SCristina Ciocan 
675c501d0b1SCristina Ciocan static void byt_set_group_simple_mux(struct byt_gpio *vg,
6764f010b93SAndy Shevchenko 				     const struct intel_pingroup group,
6774f010b93SAndy Shevchenko 				     unsigned int func)
678c501d0b1SCristina Ciocan {
679c501d0b1SCristina Ciocan 	unsigned long flags;
680c501d0b1SCristina Ciocan 	int i;
681c501d0b1SCristina Ciocan 
682c501d0b1SCristina Ciocan 	raw_spin_lock_irqsave(&vg->lock, flags);
683c501d0b1SCristina Ciocan 
684c501d0b1SCristina Ciocan 	for (i = 0; i < group.npins; i++) {
685c501d0b1SCristina Ciocan 		void __iomem *padcfg0;
686c501d0b1SCristina Ciocan 		u32 value;
687c501d0b1SCristina Ciocan 
688c501d0b1SCristina Ciocan 		padcfg0 = byt_gpio_reg(vg, group.pins[i], BYT_CONF0_REG);
689c501d0b1SCristina Ciocan 		if (!padcfg0) {
690c501d0b1SCristina Ciocan 			dev_warn(&vg->pdev->dev,
691c501d0b1SCristina Ciocan 				 "Group %s, pin %i not muxed (no padcfg0)\n",
692c501d0b1SCristina Ciocan 				 group.name, i);
693c501d0b1SCristina Ciocan 			continue;
694c501d0b1SCristina Ciocan 		}
695c501d0b1SCristina Ciocan 
696c501d0b1SCristina Ciocan 		value = readl(padcfg0);
697c501d0b1SCristina Ciocan 		value &= ~BYT_PIN_MUX;
698c501d0b1SCristina Ciocan 		value |= func;
699c501d0b1SCristina Ciocan 		writel(value, padcfg0);
700c501d0b1SCristina Ciocan 	}
701c501d0b1SCristina Ciocan 
702c501d0b1SCristina Ciocan 	raw_spin_unlock_irqrestore(&vg->lock, flags);
703c501d0b1SCristina Ciocan }
704c501d0b1SCristina Ciocan 
705c501d0b1SCristina Ciocan static void byt_set_group_mixed_mux(struct byt_gpio *vg,
7064f010b93SAndy Shevchenko 				    const struct intel_pingroup group,
7074f010b93SAndy Shevchenko 				    const unsigned int *func)
708c501d0b1SCristina Ciocan {
709c501d0b1SCristina Ciocan 	unsigned long flags;
710c501d0b1SCristina Ciocan 	int i;
711c501d0b1SCristina Ciocan 
712c501d0b1SCristina Ciocan 	raw_spin_lock_irqsave(&vg->lock, flags);
713c501d0b1SCristina Ciocan 
714c501d0b1SCristina Ciocan 	for (i = 0; i < group.npins; i++) {
715c501d0b1SCristina Ciocan 		void __iomem *padcfg0;
716c501d0b1SCristina Ciocan 		u32 value;
717c501d0b1SCristina Ciocan 
718c501d0b1SCristina Ciocan 		padcfg0 = byt_gpio_reg(vg, group.pins[i], BYT_CONF0_REG);
719c501d0b1SCristina Ciocan 		if (!padcfg0) {
720c501d0b1SCristina Ciocan 			dev_warn(&vg->pdev->dev,
721c501d0b1SCristina Ciocan 				 "Group %s, pin %i not muxed (no padcfg0)\n",
722c501d0b1SCristina Ciocan 				 group.name, i);
723c501d0b1SCristina Ciocan 			continue;
724c501d0b1SCristina Ciocan 		}
725c501d0b1SCristina Ciocan 
726c501d0b1SCristina Ciocan 		value = readl(padcfg0);
727c501d0b1SCristina Ciocan 		value &= ~BYT_PIN_MUX;
728c501d0b1SCristina Ciocan 		value |= func[i];
729c501d0b1SCristina Ciocan 		writel(value, padcfg0);
730c501d0b1SCristina Ciocan 	}
731c501d0b1SCristina Ciocan 
732c501d0b1SCristina Ciocan 	raw_spin_unlock_irqrestore(&vg->lock, flags);
733c501d0b1SCristina Ciocan }
734c501d0b1SCristina Ciocan 
735c501d0b1SCristina Ciocan static int byt_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
736c501d0b1SCristina Ciocan 		       unsigned int group_selector)
737c501d0b1SCristina Ciocan {
738c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
7394f010b93SAndy Shevchenko 	const struct intel_function func = vg->soc_data->functions[func_selector];
7404f010b93SAndy Shevchenko 	const struct intel_pingroup group = vg->soc_data->groups[group_selector];
741c501d0b1SCristina Ciocan 
7424f010b93SAndy Shevchenko 	if (group.modes)
7434f010b93SAndy Shevchenko 		byt_set_group_mixed_mux(vg, group, group.modes);
7444f010b93SAndy Shevchenko 	else if (!strcmp(func.name, "gpio"))
745c501d0b1SCristina Ciocan 		byt_set_group_simple_mux(vg, group, BYT_DEFAULT_GPIO_MUX);
746c501d0b1SCristina Ciocan 	else
7474f010b93SAndy Shevchenko 		byt_set_group_simple_mux(vg, group, group.mode);
748c501d0b1SCristina Ciocan 
749c501d0b1SCristina Ciocan 	return 0;
750c501d0b1SCristina Ciocan }
751c501d0b1SCristina Ciocan 
752939330d7SAndy Shevchenko static u32 byt_get_gpio_mux(struct byt_gpio *vg, unsigned int offset)
753c501d0b1SCristina Ciocan {
754c501d0b1SCristina Ciocan 	/* SCORE pin 92-93 */
755c501d0b1SCristina Ciocan 	if (!strcmp(vg->soc_data->uid, BYT_SCORE_ACPI_UID) &&
756c501d0b1SCristina Ciocan 	    offset >= 92 && offset <= 93)
757a705f9c1SAndy Shevchenko 		return BYT_ALTER_GPIO_MUX;
758c501d0b1SCristina Ciocan 
759c501d0b1SCristina Ciocan 	/* SUS pin 11-21 */
760c501d0b1SCristina Ciocan 	if (!strcmp(vg->soc_data->uid, BYT_SUS_ACPI_UID) &&
761c501d0b1SCristina Ciocan 	    offset >= 11 && offset <= 21)
762a705f9c1SAndy Shevchenko 		return BYT_ALTER_GPIO_MUX;
763c501d0b1SCristina Ciocan 
764a705f9c1SAndy Shevchenko 	return BYT_DEFAULT_GPIO_MUX;
765c501d0b1SCristina Ciocan }
766c501d0b1SCristina Ciocan 
767c501d0b1SCristina Ciocan static void byt_gpio_clear_triggering(struct byt_gpio *vg, unsigned int offset)
768c501d0b1SCristina Ciocan {
769c501d0b1SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
77095f0972cSMika Westerberg 	unsigned long flags;
77195f0972cSMika Westerberg 	u32 value;
77295f0972cSMika Westerberg 
77378e1c896SMika Westerberg 	raw_spin_lock_irqsave(&vg->lock, flags);
77495f0972cSMika Westerberg 	value = readl(reg);
77595f0972cSMika Westerberg 	value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
77695f0972cSMika Westerberg 	writel(value, reg);
77778e1c896SMika Westerberg 	raw_spin_unlock_irqrestore(&vg->lock, flags);
77895f0972cSMika Westerberg }
77995f0972cSMika Westerberg 
780c501d0b1SCristina Ciocan static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev,
781c501d0b1SCristina Ciocan 				   struct pinctrl_gpio_range *range,
782c501d0b1SCristina Ciocan 				   unsigned int offset)
7835fae8b86SMika Westerberg {
784c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
785c501d0b1SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
786f8323b6bSMika Westerberg 	u32 value, gpio_mux;
78739ce8150SMika Westerberg 	unsigned long flags;
78839ce8150SMika Westerberg 
78978e1c896SMika Westerberg 	raw_spin_lock_irqsave(&vg->lock, flags);
7905fae8b86SMika Westerberg 
7915fae8b86SMika Westerberg 	/*
7925fae8b86SMika Westerberg 	 * In most cases, func pin mux 000 means GPIO function.
7935fae8b86SMika Westerberg 	 * But, some pins may have func pin mux 001 represents
794f8323b6bSMika Westerberg 	 * GPIO function.
795f8323b6bSMika Westerberg 	 *
796f8323b6bSMika Westerberg 	 * Because there are devices out there where some pins were not
797f8323b6bSMika Westerberg 	 * configured correctly we allow changing the mux value from
798f8323b6bSMika Westerberg 	 * request (but print out warning about that).
7995fae8b86SMika Westerberg 	 */
8005fae8b86SMika Westerberg 	value = readl(reg) & BYT_PIN_MUX;
801f8323b6bSMika Westerberg 	gpio_mux = byt_get_gpio_mux(vg, offset);
802b5894d12SHans de Goede 	if (gpio_mux != value) {
803f8323b6bSMika Westerberg 		value = readl(reg) & ~BYT_PIN_MUX;
804f8323b6bSMika Westerberg 		value |= gpio_mux;
805f8323b6bSMika Westerberg 		writel(value, reg);
806f8323b6bSMika Westerberg 
807b5894d12SHans de Goede 		dev_warn(&vg->pdev->dev, FW_BUG
808f8323b6bSMika Westerberg 			 "pin %u forcibly re-configured as GPIO\n", offset);
8095fae8b86SMika Westerberg 	}
8105fae8b86SMika Westerberg 
81178e1c896SMika Westerberg 	raw_spin_unlock_irqrestore(&vg->lock, flags);
81239ce8150SMika Westerberg 
8135fae8b86SMika Westerberg 	pm_runtime_get(&vg->pdev->dev);
8145fae8b86SMika Westerberg 
8155fae8b86SMika Westerberg 	return 0;
8165fae8b86SMika Westerberg }
8175fae8b86SMika Westerberg 
818c501d0b1SCristina Ciocan static void byt_gpio_disable_free(struct pinctrl_dev *pctl_dev,
819c501d0b1SCristina Ciocan 				  struct pinctrl_gpio_range *range,
820c501d0b1SCristina Ciocan 				  unsigned int offset)
821c501d0b1SCristina Ciocan {
822c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
823c501d0b1SCristina Ciocan 
824c501d0b1SCristina Ciocan 	byt_gpio_clear_triggering(vg, offset);
825c501d0b1SCristina Ciocan 	pm_runtime_put(&vg->pdev->dev);
826c501d0b1SCristina Ciocan }
827c501d0b1SCristina Ciocan 
828c501d0b1SCristina Ciocan static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
829c501d0b1SCristina Ciocan 				  struct pinctrl_gpio_range *range,
830c501d0b1SCristina Ciocan 				  unsigned int offset,
831c501d0b1SCristina Ciocan 				  bool input)
832c501d0b1SCristina Ciocan {
833c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
834c501d0b1SCristina Ciocan 	void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
835c501d0b1SCristina Ciocan 	void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
836c501d0b1SCristina Ciocan 	unsigned long flags;
837c501d0b1SCristina Ciocan 	u32 value;
838c501d0b1SCristina Ciocan 
839c501d0b1SCristina Ciocan 	raw_spin_lock_irqsave(&vg->lock, flags);
840c501d0b1SCristina Ciocan 
841c501d0b1SCristina Ciocan 	value = readl(val_reg);
842c501d0b1SCristina Ciocan 	value &= ~BYT_DIR_MASK;
843c501d0b1SCristina Ciocan 	if (input)
844c501d0b1SCristina Ciocan 		value |= BYT_OUTPUT_EN;
845c501d0b1SCristina Ciocan 	else
846c501d0b1SCristina Ciocan 		/*
847c501d0b1SCristina Ciocan 		 * Before making any direction modifications, do a check if gpio
848c501d0b1SCristina Ciocan 		 * is set for direct IRQ.  On baytrail, setting GPIO to output
849c501d0b1SCristina Ciocan 		 * does not make sense, so let's at least warn the caller before
850c501d0b1SCristina Ciocan 		 * they shoot themselves in the foot.
851c501d0b1SCristina Ciocan 		 */
852c501d0b1SCristina Ciocan 		WARN(readl(conf_reg) & BYT_DIRECT_IRQ_EN,
853c501d0b1SCristina Ciocan 		     "Potential Error: Setting GPIO with direct_irq_en to output");
854c501d0b1SCristina Ciocan 	writel(value, val_reg);
855c501d0b1SCristina Ciocan 
856c501d0b1SCristina Ciocan 	raw_spin_unlock_irqrestore(&vg->lock, flags);
857c501d0b1SCristina Ciocan 
858c501d0b1SCristina Ciocan 	return 0;
859c501d0b1SCristina Ciocan }
860c501d0b1SCristina Ciocan 
861c501d0b1SCristina Ciocan static const struct pinmux_ops byt_pinmux_ops = {
862c501d0b1SCristina Ciocan 	.get_functions_count	= byt_get_functions_count,
863c501d0b1SCristina Ciocan 	.get_function_name	= byt_get_function_name,
864c501d0b1SCristina Ciocan 	.get_function_groups	= byt_get_function_groups,
865c501d0b1SCristina Ciocan 	.set_mux		= byt_set_mux,
866c501d0b1SCristina Ciocan 	.gpio_request_enable	= byt_gpio_request_enable,
867c501d0b1SCristina Ciocan 	.gpio_disable_free	= byt_gpio_disable_free,
868c501d0b1SCristina Ciocan 	.gpio_set_direction	= byt_gpio_set_direction,
869c501d0b1SCristina Ciocan };
870c501d0b1SCristina Ciocan 
871c501d0b1SCristina Ciocan static void byt_get_pull_strength(u32 reg, u16 *strength)
872c501d0b1SCristina Ciocan {
873c501d0b1SCristina Ciocan 	switch (reg & BYT_PULL_STR_MASK) {
874c501d0b1SCristina Ciocan 	case BYT_PULL_STR_2K:
875c501d0b1SCristina Ciocan 		*strength = 2000;
876c501d0b1SCristina Ciocan 		break;
877c501d0b1SCristina Ciocan 	case BYT_PULL_STR_10K:
878c501d0b1SCristina Ciocan 		*strength = 10000;
879c501d0b1SCristina Ciocan 		break;
880c501d0b1SCristina Ciocan 	case BYT_PULL_STR_20K:
881c501d0b1SCristina Ciocan 		*strength = 20000;
882c501d0b1SCristina Ciocan 		break;
883c501d0b1SCristina Ciocan 	case BYT_PULL_STR_40K:
884c501d0b1SCristina Ciocan 		*strength = 40000;
885c501d0b1SCristina Ciocan 		break;
886c501d0b1SCristina Ciocan 	}
887c501d0b1SCristina Ciocan }
888c501d0b1SCristina Ciocan 
889c501d0b1SCristina Ciocan static int byt_set_pull_strength(u32 *reg, u16 strength)
890c501d0b1SCristina Ciocan {
891c501d0b1SCristina Ciocan 	*reg &= ~BYT_PULL_STR_MASK;
892c501d0b1SCristina Ciocan 
893c501d0b1SCristina Ciocan 	switch (strength) {
894c501d0b1SCristina Ciocan 	case 2000:
895c501d0b1SCristina Ciocan 		*reg |= BYT_PULL_STR_2K;
896c501d0b1SCristina Ciocan 		break;
897c501d0b1SCristina Ciocan 	case 10000:
898c501d0b1SCristina Ciocan 		*reg |= BYT_PULL_STR_10K;
899c501d0b1SCristina Ciocan 		break;
900c501d0b1SCristina Ciocan 	case 20000:
901c501d0b1SCristina Ciocan 		*reg |= BYT_PULL_STR_20K;
902c501d0b1SCristina Ciocan 		break;
903c501d0b1SCristina Ciocan 	case 40000:
904c501d0b1SCristina Ciocan 		*reg |= BYT_PULL_STR_40K;
905c501d0b1SCristina Ciocan 		break;
906c501d0b1SCristina Ciocan 	default:
907c501d0b1SCristina Ciocan 		return -EINVAL;
908c501d0b1SCristina Ciocan 	}
909c501d0b1SCristina Ciocan 
910c501d0b1SCristina Ciocan 	return 0;
911c501d0b1SCristina Ciocan }
912c501d0b1SCristina Ciocan 
913c501d0b1SCristina Ciocan static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset,
914c501d0b1SCristina Ciocan 			      unsigned long *config)
915c501d0b1SCristina Ciocan {
916c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
917c501d0b1SCristina Ciocan 	enum pin_config_param param = pinconf_to_config_param(*config);
918c501d0b1SCristina Ciocan 	void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
919c501d0b1SCristina Ciocan 	void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
92004ff5a09SAndy Shevchenko 	void __iomem *db_reg = byt_gpio_reg(vg, offset, BYT_DEBOUNCE_REG);
921c501d0b1SCristina Ciocan 	unsigned long flags;
922658b476cSCristina Ciocan 	u32 conf, pull, val, debounce;
923c501d0b1SCristina Ciocan 	u16 arg = 0;
924c501d0b1SCristina Ciocan 
925c501d0b1SCristina Ciocan 	raw_spin_lock_irqsave(&vg->lock, flags);
926c501d0b1SCristina Ciocan 	conf = readl(conf_reg);
927c501d0b1SCristina Ciocan 	pull = conf & BYT_PULL_ASSIGN_MASK;
928c501d0b1SCristina Ciocan 	val = readl(val_reg);
929c501d0b1SCristina Ciocan 	raw_spin_unlock_irqrestore(&vg->lock, flags);
930c501d0b1SCristina Ciocan 
931c501d0b1SCristina Ciocan 	switch (param) {
932c501d0b1SCristina Ciocan 	case PIN_CONFIG_BIAS_DISABLE:
933c501d0b1SCristina Ciocan 		if (pull)
934c501d0b1SCristina Ciocan 			return -EINVAL;
935c501d0b1SCristina Ciocan 		break;
936c501d0b1SCristina Ciocan 	case PIN_CONFIG_BIAS_PULL_DOWN:
937c501d0b1SCristina Ciocan 		/* Pull assignment is only applicable in input mode */
938c501d0b1SCristina Ciocan 		if ((val & BYT_INPUT_EN) || pull != BYT_PULL_ASSIGN_DOWN)
939c501d0b1SCristina Ciocan 			return -EINVAL;
940c501d0b1SCristina Ciocan 
941c501d0b1SCristina Ciocan 		byt_get_pull_strength(conf, &arg);
942c501d0b1SCristina Ciocan 
943c501d0b1SCristina Ciocan 		break;
944c501d0b1SCristina Ciocan 	case PIN_CONFIG_BIAS_PULL_UP:
945c501d0b1SCristina Ciocan 		/* Pull assignment is only applicable in input mode */
946c501d0b1SCristina Ciocan 		if ((val & BYT_INPUT_EN) || pull != BYT_PULL_ASSIGN_UP)
947c501d0b1SCristina Ciocan 			return -EINVAL;
948c501d0b1SCristina Ciocan 
949c501d0b1SCristina Ciocan 		byt_get_pull_strength(conf, &arg);
950c501d0b1SCristina Ciocan 
951c501d0b1SCristina Ciocan 		break;
952658b476cSCristina Ciocan 	case PIN_CONFIG_INPUT_DEBOUNCE:
953658b476cSCristina Ciocan 		if (!(conf & BYT_DEBOUNCE_EN))
954658b476cSCristina Ciocan 			return -EINVAL;
955658b476cSCristina Ciocan 
956658b476cSCristina Ciocan 		raw_spin_lock_irqsave(&vg->lock, flags);
95704ff5a09SAndy Shevchenko 		debounce = readl(db_reg);
958658b476cSCristina Ciocan 		raw_spin_unlock_irqrestore(&vg->lock, flags);
959658b476cSCristina Ciocan 
960658b476cSCristina Ciocan 		switch (debounce & BYT_DEBOUNCE_PULSE_MASK) {
961658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_375US:
962658b476cSCristina Ciocan 			arg = 375;
963658b476cSCristina Ciocan 			break;
964658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_750US:
965658b476cSCristina Ciocan 			arg = 750;
966658b476cSCristina Ciocan 			break;
967658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_1500US:
968658b476cSCristina Ciocan 			arg = 1500;
969658b476cSCristina Ciocan 			break;
970658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_3MS:
971658b476cSCristina Ciocan 			arg = 3000;
972658b476cSCristina Ciocan 			break;
973658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_6MS:
974658b476cSCristina Ciocan 			arg = 6000;
975658b476cSCristina Ciocan 			break;
976658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_12MS:
977658b476cSCristina Ciocan 			arg = 12000;
978658b476cSCristina Ciocan 			break;
979658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_24MS:
980658b476cSCristina Ciocan 			arg = 24000;
981658b476cSCristina Ciocan 			break;
982658b476cSCristina Ciocan 		default:
983658b476cSCristina Ciocan 			return -EINVAL;
984658b476cSCristina Ciocan 		}
985658b476cSCristina Ciocan 
986658b476cSCristina Ciocan 		break;
987c501d0b1SCristina Ciocan 	default:
988c501d0b1SCristina Ciocan 		return -ENOTSUPP;
989c501d0b1SCristina Ciocan 	}
990c501d0b1SCristina Ciocan 
991c501d0b1SCristina Ciocan 	*config = pinconf_to_config_packed(param, arg);
992c501d0b1SCristina Ciocan 
993c501d0b1SCristina Ciocan 	return 0;
994c501d0b1SCristina Ciocan }
995c501d0b1SCristina Ciocan 
996c501d0b1SCristina Ciocan static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
997c501d0b1SCristina Ciocan 			      unsigned int offset,
998c501d0b1SCristina Ciocan 			      unsigned long *configs,
999c501d0b1SCristina Ciocan 			      unsigned int num_configs)
1000c501d0b1SCristina Ciocan {
1001c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
1002c501d0b1SCristina Ciocan 	unsigned int param, arg;
1003c501d0b1SCristina Ciocan 	void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
1004c501d0b1SCristina Ciocan 	void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
100504ff5a09SAndy Shevchenko 	void __iomem *db_reg = byt_gpio_reg(vg, offset, BYT_DEBOUNCE_REG);
1006c501d0b1SCristina Ciocan 	unsigned long flags;
1007658b476cSCristina Ciocan 	u32 conf, val, debounce;
1008c501d0b1SCristina Ciocan 	int i, ret = 0;
1009c501d0b1SCristina Ciocan 
1010c501d0b1SCristina Ciocan 	raw_spin_lock_irqsave(&vg->lock, flags);
1011c501d0b1SCristina Ciocan 
1012c501d0b1SCristina Ciocan 	conf = readl(conf_reg);
1013c501d0b1SCristina Ciocan 	val = readl(val_reg);
1014c501d0b1SCristina Ciocan 
1015c501d0b1SCristina Ciocan 	for (i = 0; i < num_configs; i++) {
1016c501d0b1SCristina Ciocan 		param = pinconf_to_config_param(configs[i]);
1017c501d0b1SCristina Ciocan 		arg = pinconf_to_config_argument(configs[i]);
1018c501d0b1SCristina Ciocan 
1019c501d0b1SCristina Ciocan 		switch (param) {
1020c501d0b1SCristina Ciocan 		case PIN_CONFIG_BIAS_DISABLE:
1021c501d0b1SCristina Ciocan 			conf &= ~BYT_PULL_ASSIGN_MASK;
1022c501d0b1SCristina Ciocan 			break;
1023c501d0b1SCristina Ciocan 		case PIN_CONFIG_BIAS_PULL_DOWN:
1024c501d0b1SCristina Ciocan 			/* Set default strength value in case none is given */
1025c501d0b1SCristina Ciocan 			if (arg == 1)
1026c501d0b1SCristina Ciocan 				arg = 2000;
1027c501d0b1SCristina Ciocan 
1028c501d0b1SCristina Ciocan 			/*
1029c501d0b1SCristina Ciocan 			 * Pull assignment is only applicable in input mode. If
1030c501d0b1SCristina Ciocan 			 * chip is not in input mode, set it and warn about it.
1031c501d0b1SCristina Ciocan 			 */
1032c501d0b1SCristina Ciocan 			if (val & BYT_INPUT_EN) {
1033c501d0b1SCristina Ciocan 				val &= ~BYT_INPUT_EN;
1034c501d0b1SCristina Ciocan 				writel(val, val_reg);
1035c501d0b1SCristina Ciocan 				dev_warn(&vg->pdev->dev,
1036c501d0b1SCristina Ciocan 					 "pin %u forcibly set to input mode\n",
1037c501d0b1SCristina Ciocan 					 offset);
1038c501d0b1SCristina Ciocan 			}
1039c501d0b1SCristina Ciocan 
1040c501d0b1SCristina Ciocan 			conf &= ~BYT_PULL_ASSIGN_MASK;
1041c501d0b1SCristina Ciocan 			conf |= BYT_PULL_ASSIGN_DOWN;
1042c501d0b1SCristina Ciocan 			ret = byt_set_pull_strength(&conf, arg);
1043c501d0b1SCristina Ciocan 
1044c501d0b1SCristina Ciocan 			break;
1045c501d0b1SCristina Ciocan 		case PIN_CONFIG_BIAS_PULL_UP:
1046c501d0b1SCristina Ciocan 			/* Set default strength value in case none is given */
1047c501d0b1SCristina Ciocan 			if (arg == 1)
1048c501d0b1SCristina Ciocan 				arg = 2000;
1049c501d0b1SCristina Ciocan 
1050c501d0b1SCristina Ciocan 			/*
1051c501d0b1SCristina Ciocan 			 * Pull assignment is only applicable in input mode. If
1052c501d0b1SCristina Ciocan 			 * chip is not in input mode, set it and warn about it.
1053c501d0b1SCristina Ciocan 			 */
1054c501d0b1SCristina Ciocan 			if (val & BYT_INPUT_EN) {
1055c501d0b1SCristina Ciocan 				val &= ~BYT_INPUT_EN;
1056c501d0b1SCristina Ciocan 				writel(val, val_reg);
1057c501d0b1SCristina Ciocan 				dev_warn(&vg->pdev->dev,
1058c501d0b1SCristina Ciocan 					 "pin %u forcibly set to input mode\n",
1059c501d0b1SCristina Ciocan 					 offset);
1060c501d0b1SCristina Ciocan 			}
1061c501d0b1SCristina Ciocan 
1062c501d0b1SCristina Ciocan 			conf &= ~BYT_PULL_ASSIGN_MASK;
1063c501d0b1SCristina Ciocan 			conf |= BYT_PULL_ASSIGN_UP;
1064c501d0b1SCristina Ciocan 			ret = byt_set_pull_strength(&conf, arg);
1065c501d0b1SCristina Ciocan 
1066c501d0b1SCristina Ciocan 			break;
1067658b476cSCristina Ciocan 		case PIN_CONFIG_INPUT_DEBOUNCE:
106804ff5a09SAndy Shevchenko 			debounce = readl(db_reg);
106904ff5a09SAndy Shevchenko 			debounce &= ~BYT_DEBOUNCE_PULSE_MASK;
1070658b476cSCristina Ciocan 
1071827e1579SAndy Shevchenko 			if (arg)
1072827e1579SAndy Shevchenko 				conf |= BYT_DEBOUNCE_EN;
1073827e1579SAndy Shevchenko 			else
1074827e1579SAndy Shevchenko 				conf &= ~BYT_DEBOUNCE_EN;
1075827e1579SAndy Shevchenko 
1076658b476cSCristina Ciocan 			switch (arg) {
1077658b476cSCristina Ciocan 			case 375:
107804ff5a09SAndy Shevchenko 				debounce |= BYT_DEBOUNCE_PULSE_375US;
1079658b476cSCristina Ciocan 				break;
1080658b476cSCristina Ciocan 			case 750:
108104ff5a09SAndy Shevchenko 				debounce |= BYT_DEBOUNCE_PULSE_750US;
1082658b476cSCristina Ciocan 				break;
1083658b476cSCristina Ciocan 			case 1500:
108404ff5a09SAndy Shevchenko 				debounce |= BYT_DEBOUNCE_PULSE_1500US;
1085658b476cSCristina Ciocan 				break;
1086658b476cSCristina Ciocan 			case 3000:
108704ff5a09SAndy Shevchenko 				debounce |= BYT_DEBOUNCE_PULSE_3MS;
1088658b476cSCristina Ciocan 				break;
1089658b476cSCristina Ciocan 			case 6000:
109004ff5a09SAndy Shevchenko 				debounce |= BYT_DEBOUNCE_PULSE_6MS;
1091658b476cSCristina Ciocan 				break;
1092658b476cSCristina Ciocan 			case 12000:
109304ff5a09SAndy Shevchenko 				debounce |= BYT_DEBOUNCE_PULSE_12MS;
1094658b476cSCristina Ciocan 				break;
1095658b476cSCristina Ciocan 			case 24000:
109604ff5a09SAndy Shevchenko 				debounce |= BYT_DEBOUNCE_PULSE_24MS;
1097658b476cSCristina Ciocan 				break;
1098658b476cSCristina Ciocan 			default:
1099827e1579SAndy Shevchenko 				if (arg)
1100658b476cSCristina Ciocan 					ret = -EINVAL;
1101827e1579SAndy Shevchenko 				break;
1102658b476cSCristina Ciocan 			}
1103658b476cSCristina Ciocan 
110404ff5a09SAndy Shevchenko 			if (!ret)
110504ff5a09SAndy Shevchenko 				writel(debounce, db_reg);
1106658b476cSCristina Ciocan 			break;
1107c501d0b1SCristina Ciocan 		default:
1108c501d0b1SCristina Ciocan 			ret = -ENOTSUPP;
1109c501d0b1SCristina Ciocan 		}
1110c501d0b1SCristina Ciocan 
1111c501d0b1SCristina Ciocan 		if (ret)
1112c501d0b1SCristina Ciocan 			break;
1113c501d0b1SCristina Ciocan 	}
1114c501d0b1SCristina Ciocan 
1115c501d0b1SCristina Ciocan 	if (!ret)
1116c501d0b1SCristina Ciocan 		writel(conf, conf_reg);
1117c501d0b1SCristina Ciocan 
1118c501d0b1SCristina Ciocan 	raw_spin_unlock_irqrestore(&vg->lock, flags);
1119c501d0b1SCristina Ciocan 
1120c501d0b1SCristina Ciocan 	return ret;
1121c501d0b1SCristina Ciocan }
1122c501d0b1SCristina Ciocan 
1123c501d0b1SCristina Ciocan static const struct pinconf_ops byt_pinconf_ops = {
1124c501d0b1SCristina Ciocan 	.is_generic	= true,
1125c501d0b1SCristina Ciocan 	.pin_config_get	= byt_pin_config_get,
1126c501d0b1SCristina Ciocan 	.pin_config_set	= byt_pin_config_set,
1127c501d0b1SCristina Ciocan };
1128c501d0b1SCristina Ciocan 
1129c501d0b1SCristina Ciocan static const struct pinctrl_desc byt_pinctrl_desc = {
1130c501d0b1SCristina Ciocan 	.pctlops	= &byt_pinctrl_ops,
1131c501d0b1SCristina Ciocan 	.pmxops		= &byt_pinmux_ops,
1132c501d0b1SCristina Ciocan 	.confops	= &byt_pinconf_ops,
1133c501d0b1SCristina Ciocan 	.owner		= THIS_MODULE,
1134c501d0b1SCristina Ciocan };
1135c501d0b1SCristina Ciocan 
1136939330d7SAndy Shevchenko static int byt_gpio_get(struct gpio_chip *chip, unsigned int offset)
11375fae8b86SMika Westerberg {
1138bf9a5c96SLinus Walleij 	struct byt_gpio *vg = gpiochip_get_data(chip);
1139c501d0b1SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
114039ce8150SMika Westerberg 	unsigned long flags;
114139ce8150SMika Westerberg 	u32 val;
114239ce8150SMika Westerberg 
114378e1c896SMika Westerberg 	raw_spin_lock_irqsave(&vg->lock, flags);
114439ce8150SMika Westerberg 	val = readl(reg);
114578e1c896SMika Westerberg 	raw_spin_unlock_irqrestore(&vg->lock, flags);
114639ce8150SMika Westerberg 
11473bde8771SLinus Walleij 	return !!(val & BYT_LEVEL);
11485fae8b86SMika Westerberg }
11495fae8b86SMika Westerberg 
1150939330d7SAndy Shevchenko static void byt_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
11515fae8b86SMika Westerberg {
1152bf9a5c96SLinus Walleij 	struct byt_gpio *vg = gpiochip_get_data(chip);
1153c501d0b1SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
11545fae8b86SMika Westerberg 	unsigned long flags;
11555fae8b86SMika Westerberg 	u32 old_val;
11565fae8b86SMika Westerberg 
115786e3ef81SCristina Ciocan 	if (!reg)
115886e3ef81SCristina Ciocan 		return;
115986e3ef81SCristina Ciocan 
116078e1c896SMika Westerberg 	raw_spin_lock_irqsave(&vg->lock, flags);
11615fae8b86SMika Westerberg 	old_val = readl(reg);
11625fae8b86SMika Westerberg 	if (value)
11635fae8b86SMika Westerberg 		writel(old_val | BYT_LEVEL, reg);
11645fae8b86SMika Westerberg 	else
11655fae8b86SMika Westerberg 		writel(old_val & ~BYT_LEVEL, reg);
116678e1c896SMika Westerberg 	raw_spin_unlock_irqrestore(&vg->lock, flags);
11675fae8b86SMika Westerberg }
11685fae8b86SMika Westerberg 
116986e3ef81SCristina Ciocan static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
11705fae8b86SMika Westerberg {
1171bf9a5c96SLinus Walleij 	struct byt_gpio *vg = gpiochip_get_data(chip);
1172c501d0b1SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
11735fae8b86SMika Westerberg 	unsigned long flags;
11745fae8b86SMika Westerberg 	u32 value;
11755fae8b86SMika Westerberg 
117686e3ef81SCristina Ciocan 	if (!reg)
117786e3ef81SCristina Ciocan 		return -EINVAL;
117886e3ef81SCristina Ciocan 
117978e1c896SMika Westerberg 	raw_spin_lock_irqsave(&vg->lock, flags);
118086e3ef81SCristina Ciocan 	value = readl(reg);
118178e1c896SMika Westerberg 	raw_spin_unlock_irqrestore(&vg->lock, flags);
11825fae8b86SMika Westerberg 
118386e3ef81SCristina Ciocan 	if (!(value & BYT_OUTPUT_EN))
11841c5fb66aSLinus Walleij 		return 0;
118586e3ef81SCristina Ciocan 	if (!(value & BYT_INPUT_EN))
11861c5fb66aSLinus Walleij 		return 1;
118786e3ef81SCristina Ciocan 
118886e3ef81SCristina Ciocan 	return -EINVAL;
11895fae8b86SMika Westerberg }
11905fae8b86SMika Westerberg 
119186e3ef81SCristina Ciocan static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
11925fae8b86SMika Westerberg {
119386e3ef81SCristina Ciocan 	return pinctrl_gpio_direction_input(chip->base + offset);
119486e3ef81SCristina Ciocan }
11955fae8b86SMika Westerberg 
119686e3ef81SCristina Ciocan static int byt_gpio_direction_output(struct gpio_chip *chip,
119786e3ef81SCristina Ciocan 				     unsigned int offset, int value)
119886e3ef81SCristina Ciocan {
119986e3ef81SCristina Ciocan 	int ret = pinctrl_gpio_direction_output(chip->base + offset);
12005fae8b86SMika Westerberg 
120186e3ef81SCristina Ciocan 	if (ret)
120286e3ef81SCristina Ciocan 		return ret;
120386e3ef81SCristina Ciocan 
120486e3ef81SCristina Ciocan 	byt_gpio_set(chip, offset, value);
12055fae8b86SMika Westerberg 
12065fae8b86SMika Westerberg 	return 0;
12075fae8b86SMika Westerberg }
12085fae8b86SMika Westerberg 
12095fae8b86SMika Westerberg static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
12105fae8b86SMika Westerberg {
1211bf9a5c96SLinus Walleij 	struct byt_gpio *vg = gpiochip_get_data(chip);
12125fae8b86SMika Westerberg 	int i;
121386e3ef81SCristina Ciocan 	u32 conf0, val;
12145fae8b86SMika Westerberg 
121586e3ef81SCristina Ciocan 	for (i = 0; i < vg->soc_data->npins; i++) {
121686e3ef81SCristina Ciocan 		const struct byt_community *comm;
12175fae8b86SMika Westerberg 		const char *pull_str = NULL;
12185fae8b86SMika Westerberg 		const char *pull = NULL;
121986e3ef81SCristina Ciocan 		void __iomem *reg;
122078e1c896SMika Westerberg 		unsigned long flags;
12215fae8b86SMika Westerberg 		const char *label;
122286e3ef81SCristina Ciocan 		unsigned int pin;
122378e1c896SMika Westerberg 
122478e1c896SMika Westerberg 		raw_spin_lock_irqsave(&vg->lock, flags);
122586e3ef81SCristina Ciocan 		pin = vg->soc_data->pins[i].number;
122686e3ef81SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
122786e3ef81SCristina Ciocan 		if (!reg) {
122886e3ef81SCristina Ciocan 			seq_printf(s,
122986e3ef81SCristina Ciocan 				   "Could not retrieve pin %i conf0 reg\n",
123086e3ef81SCristina Ciocan 				   pin);
123122bbd21bSDan Carpenter 			raw_spin_unlock_irqrestore(&vg->lock, flags);
123286e3ef81SCristina Ciocan 			continue;
123386e3ef81SCristina Ciocan 		}
123486e3ef81SCristina Ciocan 		conf0 = readl(reg);
123586e3ef81SCristina Ciocan 
123686e3ef81SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
123786e3ef81SCristina Ciocan 		if (!reg) {
123886e3ef81SCristina Ciocan 			seq_printf(s,
123986e3ef81SCristina Ciocan 				   "Could not retrieve pin %i val reg\n", pin);
124022bbd21bSDan Carpenter 			raw_spin_unlock_irqrestore(&vg->lock, flags);
124122bbd21bSDan Carpenter 			continue;
124286e3ef81SCristina Ciocan 		}
124386e3ef81SCristina Ciocan 		val = readl(reg);
124478e1c896SMika Westerberg 		raw_spin_unlock_irqrestore(&vg->lock, flags);
12455fae8b86SMika Westerberg 
124686e3ef81SCristina Ciocan 		comm = byt_get_community(vg, pin);
124786e3ef81SCristina Ciocan 		if (!comm) {
124886e3ef81SCristina Ciocan 			seq_printf(s,
124986e3ef81SCristina Ciocan 				   "Could not get community for pin %i\n", pin);
125086e3ef81SCristina Ciocan 			continue;
125186e3ef81SCristina Ciocan 		}
12525fae8b86SMika Westerberg 		label = gpiochip_is_requested(chip, i);
12535fae8b86SMika Westerberg 		if (!label)
12545fae8b86SMika Westerberg 			label = "Unrequested";
12555fae8b86SMika Westerberg 
12565fae8b86SMika Westerberg 		switch (conf0 & BYT_PULL_ASSIGN_MASK) {
12575fae8b86SMika Westerberg 		case BYT_PULL_ASSIGN_UP:
12585fae8b86SMika Westerberg 			pull = "up";
12595fae8b86SMika Westerberg 			break;
12605fae8b86SMika Westerberg 		case BYT_PULL_ASSIGN_DOWN:
12615fae8b86SMika Westerberg 			pull = "down";
12625fae8b86SMika Westerberg 			break;
12635fae8b86SMika Westerberg 		}
12645fae8b86SMika Westerberg 
12655fae8b86SMika Westerberg 		switch (conf0 & BYT_PULL_STR_MASK) {
12665fae8b86SMika Westerberg 		case BYT_PULL_STR_2K:
12675fae8b86SMika Westerberg 			pull_str = "2k";
12685fae8b86SMika Westerberg 			break;
12695fae8b86SMika Westerberg 		case BYT_PULL_STR_10K:
12705fae8b86SMika Westerberg 			pull_str = "10k";
12715fae8b86SMika Westerberg 			break;
12725fae8b86SMika Westerberg 		case BYT_PULL_STR_20K:
12735fae8b86SMika Westerberg 			pull_str = "20k";
12745fae8b86SMika Westerberg 			break;
12755fae8b86SMika Westerberg 		case BYT_PULL_STR_40K:
12765fae8b86SMika Westerberg 			pull_str = "40k";
12775fae8b86SMika Westerberg 			break;
12785fae8b86SMika Westerberg 		}
12795fae8b86SMika Westerberg 
12805fae8b86SMika Westerberg 		seq_printf(s,
12815fae8b86SMika Westerberg 			   " gpio-%-3d (%-20.20s) %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s",
128286e3ef81SCristina Ciocan 			   pin,
12835fae8b86SMika Westerberg 			   label,
12845fae8b86SMika Westerberg 			   val & BYT_INPUT_EN ? "  " : "in",
12855fae8b86SMika Westerberg 			   val & BYT_OUTPUT_EN ? "   " : "out",
12865fae8b86SMika Westerberg 			   val & BYT_LEVEL ? "hi" : "lo",
12873655a1caSAlexander Stein 			   comm->pad_map[i], comm->pad_map[i] * 16,
12885fae8b86SMika Westerberg 			   conf0 & 0x7,
12895fae8b86SMika Westerberg 			   conf0 & BYT_TRIG_NEG ? " fall" : "     ",
12905fae8b86SMika Westerberg 			   conf0 & BYT_TRIG_POS ? " rise" : "     ",
12915fae8b86SMika Westerberg 			   conf0 & BYT_TRIG_LVL ? " level" : "      ");
12925fae8b86SMika Westerberg 
12935fae8b86SMika Westerberg 		if (pull && pull_str)
12945fae8b86SMika Westerberg 			seq_printf(s, " %-4s %-3s", pull, pull_str);
12955fae8b86SMika Westerberg 		else
12965fae8b86SMika Westerberg 			seq_puts(s, "          ");
12975fae8b86SMika Westerberg 
12985fae8b86SMika Westerberg 		if (conf0 & BYT_IODEN)
12995fae8b86SMika Westerberg 			seq_puts(s, " open-drain");
13005fae8b86SMika Westerberg 
13015fae8b86SMika Westerberg 		seq_puts(s, "\n");
13025fae8b86SMika Westerberg 	}
13035fae8b86SMika Westerberg }
13045fae8b86SMika Westerberg 
130586e3ef81SCristina Ciocan static const struct gpio_chip byt_gpio_chip = {
130686e3ef81SCristina Ciocan 	.owner			= THIS_MODULE,
130786e3ef81SCristina Ciocan 	.request		= gpiochip_generic_request,
130886e3ef81SCristina Ciocan 	.free			= gpiochip_generic_free,
130986e3ef81SCristina Ciocan 	.get_direction		= byt_gpio_get_direction,
131086e3ef81SCristina Ciocan 	.direction_input	= byt_gpio_direction_input,
131186e3ef81SCristina Ciocan 	.direction_output	= byt_gpio_direction_output,
131286e3ef81SCristina Ciocan 	.get			= byt_gpio_get,
131386e3ef81SCristina Ciocan 	.set			= byt_gpio_set,
131486e3ef81SCristina Ciocan 	.dbg_show		= byt_gpio_dbg_show,
131586e3ef81SCristina Ciocan };
131686e3ef81SCristina Ciocan 
131731e4329fSMika Westerberg static void byt_irq_ack(struct irq_data *d)
131831e4329fSMika Westerberg {
131931e4329fSMika Westerberg 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
1320bf9a5c96SLinus Walleij 	struct byt_gpio *vg = gpiochip_get_data(gc);
1321939330d7SAndy Shevchenko 	unsigned int offset = irqd_to_hwirq(d);
132231e4329fSMika Westerberg 	void __iomem *reg;
132331e4329fSMika Westerberg 
1324c501d0b1SCristina Ciocan 	reg = byt_gpio_reg(vg, offset, BYT_INT_STAT_REG);
13259f573b98SCristina Ciocan 	if (!reg)
13269f573b98SCristina Ciocan 		return;
13279f573b98SCristina Ciocan 
13289f573b98SCristina Ciocan 	raw_spin_lock(&vg->lock);
132931e4329fSMika Westerberg 	writel(BIT(offset % 32), reg);
133078e1c896SMika Westerberg 	raw_spin_unlock(&vg->lock);
133131e4329fSMika Westerberg }
133231e4329fSMika Westerberg 
13339f573b98SCristina Ciocan static void byt_irq_mask(struct irq_data *d)
13349f573b98SCristina Ciocan {
13359f573b98SCristina Ciocan 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
13369f573b98SCristina Ciocan 	struct byt_gpio *vg = gpiochip_get_data(gc);
13379f573b98SCristina Ciocan 
13389f573b98SCristina Ciocan 	byt_gpio_clear_triggering(vg, irqd_to_hwirq(d));
13399f573b98SCristina Ciocan }
13409f573b98SCristina Ciocan 
13415fae8b86SMika Westerberg static void byt_irq_unmask(struct irq_data *d)
13425fae8b86SMika Westerberg {
134331e4329fSMika Westerberg 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
1344bf9a5c96SLinus Walleij 	struct byt_gpio *vg = gpiochip_get_data(gc);
1345939330d7SAndy Shevchenko 	unsigned int offset = irqd_to_hwirq(d);
134631e4329fSMika Westerberg 	unsigned long flags;
134731e4329fSMika Westerberg 	void __iomem *reg;
134831e4329fSMika Westerberg 	u32 value;
134931e4329fSMika Westerberg 
1350c501d0b1SCristina Ciocan 	reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
13519f573b98SCristina Ciocan 	if (!reg)
13529f573b98SCristina Ciocan 		return;
135378e1c896SMika Westerberg 
135478e1c896SMika Westerberg 	raw_spin_lock_irqsave(&vg->lock, flags);
135531e4329fSMika Westerberg 	value = readl(reg);
135631e4329fSMika Westerberg 
135731e4329fSMika Westerberg 	switch (irqd_get_trigger_type(d)) {
135831e4329fSMika Westerberg 	case IRQ_TYPE_LEVEL_HIGH:
135931e4329fSMika Westerberg 		value |= BYT_TRIG_LVL;
1360399476bdSGustavo A. R. Silva 		/* fall through */
136131e4329fSMika Westerberg 	case IRQ_TYPE_EDGE_RISING:
136231e4329fSMika Westerberg 		value |= BYT_TRIG_POS;
136331e4329fSMika Westerberg 		break;
136431e4329fSMika Westerberg 	case IRQ_TYPE_LEVEL_LOW:
136531e4329fSMika Westerberg 		value |= BYT_TRIG_LVL;
1366399476bdSGustavo A. R. Silva 		/* fall through */
136731e4329fSMika Westerberg 	case IRQ_TYPE_EDGE_FALLING:
136831e4329fSMika Westerberg 		value |= BYT_TRIG_NEG;
136931e4329fSMika Westerberg 		break;
137031e4329fSMika Westerberg 	case IRQ_TYPE_EDGE_BOTH:
137131e4329fSMika Westerberg 		value |= (BYT_TRIG_NEG | BYT_TRIG_POS);
137231e4329fSMika Westerberg 		break;
137331e4329fSMika Westerberg 	}
137431e4329fSMika Westerberg 
137531e4329fSMika Westerberg 	writel(value, reg);
137631e4329fSMika Westerberg 
137778e1c896SMika Westerberg 	raw_spin_unlock_irqrestore(&vg->lock, flags);
13785fae8b86SMika Westerberg }
13795fae8b86SMika Westerberg 
13809f573b98SCristina Ciocan static int byt_irq_type(struct irq_data *d, unsigned int type)
13815fae8b86SMika Westerberg {
13829f573b98SCristina Ciocan 	struct byt_gpio *vg = gpiochip_get_data(irq_data_get_irq_chip_data(d));
13839f573b98SCristina Ciocan 	u32 offset = irqd_to_hwirq(d);
13849f573b98SCristina Ciocan 	u32 value;
13859f573b98SCristina Ciocan 	unsigned long flags;
13869f573b98SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
138731e4329fSMika Westerberg 
13889f573b98SCristina Ciocan 	if (!reg || offset >= vg->chip.ngpio)
13899f573b98SCristina Ciocan 		return -EINVAL;
13909f573b98SCristina Ciocan 
13919f573b98SCristina Ciocan 	raw_spin_lock_irqsave(&vg->lock, flags);
13929f573b98SCristina Ciocan 	value = readl(reg);
13939f573b98SCristina Ciocan 
13949f573b98SCristina Ciocan 	WARN(value & BYT_DIRECT_IRQ_EN,
13959f573b98SCristina Ciocan 	     "Bad pad config for io mode, force direct_irq_en bit clearing");
13969f573b98SCristina Ciocan 
13979f573b98SCristina Ciocan 	/* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits
13989f573b98SCristina Ciocan 	 * are used to indicate high and low level triggering
13999f573b98SCristina Ciocan 	 */
14009f573b98SCristina Ciocan 	value &= ~(BYT_DIRECT_IRQ_EN | BYT_TRIG_POS | BYT_TRIG_NEG |
14019f573b98SCristina Ciocan 		   BYT_TRIG_LVL);
14029291c65bSHans de Goede 	/* Enable glitch filtering */
14039291c65bSHans de Goede 	value |= BYT_GLITCH_FILTER_EN | BYT_GLITCH_F_SLOW_CLK |
14049291c65bSHans de Goede 		 BYT_GLITCH_F_FAST_CLK;
14059f573b98SCristina Ciocan 
14069f573b98SCristina Ciocan 	writel(value, reg);
14079f573b98SCristina Ciocan 
14089f573b98SCristina Ciocan 	if (type & IRQ_TYPE_EDGE_BOTH)
14099f573b98SCristina Ciocan 		irq_set_handler_locked(d, handle_edge_irq);
14109f573b98SCristina Ciocan 	else if (type & IRQ_TYPE_LEVEL_MASK)
14119f573b98SCristina Ciocan 		irq_set_handler_locked(d, handle_level_irq);
14129f573b98SCristina Ciocan 
14139f573b98SCristina Ciocan 	raw_spin_unlock_irqrestore(&vg->lock, flags);
14149f573b98SCristina Ciocan 
14159f573b98SCristina Ciocan 	return 0;
14165fae8b86SMika Westerberg }
14175fae8b86SMika Westerberg 
14185fae8b86SMika Westerberg static struct irq_chip byt_irqchip = {
14195fae8b86SMika Westerberg 	.name		= "BYT-GPIO",
142031e4329fSMika Westerberg 	.irq_ack	= byt_irq_ack,
14215fae8b86SMika Westerberg 	.irq_mask	= byt_irq_mask,
14225fae8b86SMika Westerberg 	.irq_unmask	= byt_irq_unmask,
14235fae8b86SMika Westerberg 	.irq_set_type	= byt_irq_type,
14245fae8b86SMika Westerberg 	.flags		= IRQCHIP_SKIP_SET_WAKE,
14255fae8b86SMika Westerberg };
14265fae8b86SMika Westerberg 
142771e6ca61SCristina Ciocan static void byt_gpio_irq_handler(struct irq_desc *desc)
142871e6ca61SCristina Ciocan {
142971e6ca61SCristina Ciocan 	struct irq_data *data = irq_desc_get_irq_data(desc);
143071e6ca61SCristina Ciocan 	struct byt_gpio *vg = gpiochip_get_data(
143171e6ca61SCristina Ciocan 				irq_desc_get_handler_data(desc));
143271e6ca61SCristina Ciocan 	struct irq_chip *chip = irq_data_get_irq_chip(data);
143371e6ca61SCristina Ciocan 	u32 base, pin;
143471e6ca61SCristina Ciocan 	void __iomem *reg;
143571e6ca61SCristina Ciocan 	unsigned long pending;
143671e6ca61SCristina Ciocan 	unsigned int virq;
143771e6ca61SCristina Ciocan 
143871e6ca61SCristina Ciocan 	/* check from GPIO controller which pin triggered the interrupt */
143971e6ca61SCristina Ciocan 	for (base = 0; base < vg->chip.ngpio; base += 32) {
144071e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG);
144171e6ca61SCristina Ciocan 
144271e6ca61SCristina Ciocan 		if (!reg) {
144371e6ca61SCristina Ciocan 			dev_warn(&vg->pdev->dev,
144471e6ca61SCristina Ciocan 				 "Pin %i: could not retrieve interrupt status register\n",
144571e6ca61SCristina Ciocan 				 base);
144671e6ca61SCristina Ciocan 			continue;
144771e6ca61SCristina Ciocan 		}
144871e6ca61SCristina Ciocan 
1449cdca06e4SAlexander Stein 		raw_spin_lock(&vg->lock);
145071e6ca61SCristina Ciocan 		pending = readl(reg);
1451cdca06e4SAlexander Stein 		raw_spin_unlock(&vg->lock);
145271e6ca61SCristina Ciocan 		for_each_set_bit(pin, &pending, 32) {
1453f0fbe7bcSThierry Reding 			virq = irq_find_mapping(vg->chip.irq.domain, base + pin);
145471e6ca61SCristina Ciocan 			generic_handle_irq(virq);
145571e6ca61SCristina Ciocan 		}
145671e6ca61SCristina Ciocan 	}
145771e6ca61SCristina Ciocan 	chip->irq_eoi(data);
145871e6ca61SCristina Ciocan }
145971e6ca61SCristina Ciocan 
14605fae8b86SMika Westerberg static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
14615fae8b86SMika Westerberg {
146249c03096SAndy Shevchenko 	struct gpio_chip *gc = &vg->chip;
146349c03096SAndy Shevchenko 	struct device *dev = &vg->pdev->dev;
14645fae8b86SMika Westerberg 	void __iomem *reg;
14655fae8b86SMika Westerberg 	u32 base, value;
146695f0972cSMika Westerberg 	int i;
146795f0972cSMika Westerberg 
146895f0972cSMika Westerberg 	/*
146995f0972cSMika Westerberg 	 * Clear interrupt triggers for all pins that are GPIOs and
147095f0972cSMika Westerberg 	 * do not use direct IRQ mode. This will prevent spurious
147195f0972cSMika Westerberg 	 * interrupts from misconfigured pins.
147295f0972cSMika Westerberg 	 */
147371e6ca61SCristina Ciocan 	for (i = 0; i < vg->soc_data->npins; i++) {
147471e6ca61SCristina Ciocan 		unsigned int pin = vg->soc_data->pins[i].number;
147571e6ca61SCristina Ciocan 
147671e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
147771e6ca61SCristina Ciocan 		if (!reg) {
147871e6ca61SCristina Ciocan 			dev_warn(&vg->pdev->dev,
147971e6ca61SCristina Ciocan 				 "Pin %i: could not retrieve conf0 register\n",
148071e6ca61SCristina Ciocan 				 i);
148171e6ca61SCristina Ciocan 			continue;
148271e6ca61SCristina Ciocan 		}
148371e6ca61SCristina Ciocan 
148471e6ca61SCristina Ciocan 		value = readl(reg);
148549c03096SAndy Shevchenko 		if (value & BYT_DIRECT_IRQ_EN) {
1486dc7b0387SThierry Reding 			clear_bit(i, gc->irq.valid_mask);
148749c03096SAndy Shevchenko 			dev_dbg(dev, "excluding GPIO %d from IRQ domain\n", i);
148849c03096SAndy Shevchenko 		} else if ((value & BYT_PIN_MUX) == byt_get_gpio_mux(vg, i)) {
148995f0972cSMika Westerberg 			byt_gpio_clear_triggering(vg, i);
149049c03096SAndy Shevchenko 			dev_dbg(dev, "disabling GPIO %d\n", i);
149195f0972cSMika Westerberg 		}
149295f0972cSMika Westerberg 	}
14935fae8b86SMika Westerberg 
14945fae8b86SMika Westerberg 	/* clear interrupt status trigger registers */
149571e6ca61SCristina Ciocan 	for (base = 0; base < vg->soc_data->npins; base += 32) {
1496c501d0b1SCristina Ciocan 		reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG);
149771e6ca61SCristina Ciocan 
149871e6ca61SCristina Ciocan 		if (!reg) {
149971e6ca61SCristina Ciocan 			dev_warn(&vg->pdev->dev,
150071e6ca61SCristina Ciocan 				 "Pin %i: could not retrieve irq status reg\n",
150171e6ca61SCristina Ciocan 				 base);
150271e6ca61SCristina Ciocan 			continue;
150371e6ca61SCristina Ciocan 		}
150471e6ca61SCristina Ciocan 
15055fae8b86SMika Westerberg 		writel(0xffffffff, reg);
15065fae8b86SMika Westerberg 		/* make sure trigger bits are cleared, if not then a pin
15075fae8b86SMika Westerberg 		   might be misconfigured in bios */
15085fae8b86SMika Westerberg 		value = readl(reg);
15095fae8b86SMika Westerberg 		if (value)
15105fae8b86SMika Westerberg 			dev_err(&vg->pdev->dev,
1511973232e2SAlexander Stein 				"GPIO interrupt error, pins misconfigured. INT_STAT%u: 0x%08x\n",
1512973232e2SAlexander Stein 				base / 32, value);
15135fae8b86SMika Westerberg 	}
15145fae8b86SMika Westerberg }
15155fae8b86SMika Westerberg 
151671e6ca61SCristina Ciocan static int byt_gpio_probe(struct byt_gpio *vg)
15175fae8b86SMika Westerberg {
15185fae8b86SMika Westerberg 	struct gpio_chip *gc;
151971e6ca61SCristina Ciocan 	struct resource *irq_rc;
15205fae8b86SMika Westerberg 	int ret;
15215fae8b86SMika Westerberg 
152271e6ca61SCristina Ciocan 	/* Set up gpio chip */
152371e6ca61SCristina Ciocan 	vg->chip	= byt_gpio_chip;
15245fae8b86SMika Westerberg 	gc		= &vg->chip;
152571e6ca61SCristina Ciocan 	gc->label	= dev_name(&vg->pdev->dev);
15265fae8b86SMika Westerberg 	gc->base	= -1;
15275fae8b86SMika Westerberg 	gc->can_sleep	= false;
152871e6ca61SCristina Ciocan 	gc->parent	= &vg->pdev->dev;
152971e6ca61SCristina Ciocan 	gc->ngpio	= vg->soc_data->npins;
1530dc7b0387SThierry Reding 	gc->irq.need_valid_mask	= true;
15315fae8b86SMika Westerberg 
1532fcc18debSMika Westerberg #ifdef CONFIG_PM_SLEEP
153371e6ca61SCristina Ciocan 	vg->saved_context = devm_kcalloc(&vg->pdev->dev, gc->ngpio,
1534fcc18debSMika Westerberg 				       sizeof(*vg->saved_context), GFP_KERNEL);
1535d6cb7722SAditya Pakki 	if (!vg->saved_context)
1536d6cb7722SAditya Pakki 		return -ENOMEM;
1537fcc18debSMika Westerberg #endif
15380612413fSAndy Shevchenko 	ret = devm_gpiochip_add_data(&vg->pdev->dev, gc, vg);
15395fae8b86SMika Westerberg 	if (ret) {
154071e6ca61SCristina Ciocan 		dev_err(&vg->pdev->dev, "failed adding byt-gpio chip\n");
15415fae8b86SMika Westerberg 		return ret;
15425fae8b86SMika Westerberg 	}
15435fae8b86SMika Westerberg 
154471e6ca61SCristina Ciocan 	ret = gpiochip_add_pin_range(&vg->chip, dev_name(&vg->pdev->dev),
154571e6ca61SCristina Ciocan 				     0, 0, vg->soc_data->npins);
154671e6ca61SCristina Ciocan 	if (ret) {
154771e6ca61SCristina Ciocan 		dev_err(&vg->pdev->dev, "failed to add GPIO pin range\n");
15480612413fSAndy Shevchenko 		return ret;
154971e6ca61SCristina Ciocan 	}
155071e6ca61SCristina Ciocan 
15515fae8b86SMika Westerberg 	/* set up interrupts  */
155271e6ca61SCristina Ciocan 	irq_rc = platform_get_resource(vg->pdev, IORESOURCE_IRQ, 0);
15535fae8b86SMika Westerberg 	if (irq_rc && irq_rc->start) {
15545fae8b86SMika Westerberg 		byt_gpio_irq_init_hw(vg);
15555fae8b86SMika Westerberg 		ret = gpiochip_irqchip_add(gc, &byt_irqchip, 0,
15563ae02c14SAndy Shevchenko 					   handle_bad_irq, IRQ_TYPE_NONE);
15575fae8b86SMika Westerberg 		if (ret) {
155871e6ca61SCristina Ciocan 			dev_err(&vg->pdev->dev, "failed to add irqchip\n");
15590612413fSAndy Shevchenko 			return ret;
15605fae8b86SMika Westerberg 		}
15615fae8b86SMika Westerberg 
15625fae8b86SMika Westerberg 		gpiochip_set_chained_irqchip(gc, &byt_irqchip,
15635fae8b86SMika Westerberg 					     (unsigned)irq_rc->start,
15645fae8b86SMika Westerberg 					     byt_gpio_irq_handler);
15655fae8b86SMika Westerberg 	}
15665fae8b86SMika Westerberg 
156771e6ca61SCristina Ciocan 	return ret;
156871e6ca61SCristina Ciocan }
156971e6ca61SCristina Ciocan 
157071e6ca61SCristina Ciocan static int byt_set_soc_data(struct byt_gpio *vg,
157171e6ca61SCristina Ciocan 			    const struct byt_pinctrl_soc_data *soc_data)
157271e6ca61SCristina Ciocan {
157371e6ca61SCristina Ciocan 	int i;
157471e6ca61SCristina Ciocan 
157571e6ca61SCristina Ciocan 	vg->soc_data = soc_data;
157671e6ca61SCristina Ciocan 	vg->communities_copy = devm_kcalloc(&vg->pdev->dev,
157771e6ca61SCristina Ciocan 					    soc_data->ncommunities,
157871e6ca61SCristina Ciocan 					    sizeof(*vg->communities_copy),
157971e6ca61SCristina Ciocan 					    GFP_KERNEL);
158071e6ca61SCristina Ciocan 	if (!vg->communities_copy)
158171e6ca61SCristina Ciocan 		return -ENOMEM;
158271e6ca61SCristina Ciocan 
158371e6ca61SCristina Ciocan 	for (i = 0; i < soc_data->ncommunities; i++) {
158471e6ca61SCristina Ciocan 		struct byt_community *comm = vg->communities_copy + i;
158571e6ca61SCristina Ciocan 		struct resource *mem_rc;
158671e6ca61SCristina Ciocan 
158771e6ca61SCristina Ciocan 		*comm = vg->soc_data->communities[i];
158871e6ca61SCristina Ciocan 
158971e6ca61SCristina Ciocan 		mem_rc = platform_get_resource(vg->pdev, IORESOURCE_MEM, 0);
159071e6ca61SCristina Ciocan 		comm->reg_base = devm_ioremap_resource(&vg->pdev->dev, mem_rc);
159171e6ca61SCristina Ciocan 		if (IS_ERR(comm->reg_base))
159271e6ca61SCristina Ciocan 			return PTR_ERR(comm->reg_base);
159371e6ca61SCristina Ciocan 	}
159471e6ca61SCristina Ciocan 
159571e6ca61SCristina Ciocan 	return 0;
159671e6ca61SCristina Ciocan }
159771e6ca61SCristina Ciocan 
159871e6ca61SCristina Ciocan static const struct acpi_device_id byt_gpio_acpi_match[] = {
159971e6ca61SCristina Ciocan 	{ "INT33B2", (kernel_ulong_t)byt_soc_data },
160071e6ca61SCristina Ciocan 	{ "INT33FC", (kernel_ulong_t)byt_soc_data },
160171e6ca61SCristina Ciocan 	{ }
160271e6ca61SCristina Ciocan };
160371e6ca61SCristina Ciocan 
160471e6ca61SCristina Ciocan static int byt_pinctrl_probe(struct platform_device *pdev)
160571e6ca61SCristina Ciocan {
160671e6ca61SCristina Ciocan 	const struct byt_pinctrl_soc_data *soc_data = NULL;
160771e6ca61SCristina Ciocan 	const struct byt_pinctrl_soc_data **soc_table;
160871e6ca61SCristina Ciocan 	struct acpi_device *acpi_dev;
160971e6ca61SCristina Ciocan 	struct byt_gpio *vg;
161071e6ca61SCristina Ciocan 	int i, ret;
161171e6ca61SCristina Ciocan 
161271e6ca61SCristina Ciocan 	acpi_dev = ACPI_COMPANION(&pdev->dev);
161371e6ca61SCristina Ciocan 	if (!acpi_dev)
161471e6ca61SCristina Ciocan 		return -ENODEV;
161571e6ca61SCristina Ciocan 
161661db6c9dSAndy Shevchenko 	soc_table = (const struct byt_pinctrl_soc_data **)device_get_match_data(&pdev->dev);
161771e6ca61SCristina Ciocan 
161871e6ca61SCristina Ciocan 	for (i = 0; soc_table[i]; i++) {
161971e6ca61SCristina Ciocan 		if (!strcmp(acpi_dev->pnp.unique_id, soc_table[i]->uid)) {
162071e6ca61SCristina Ciocan 			soc_data = soc_table[i];
162171e6ca61SCristina Ciocan 			break;
162271e6ca61SCristina Ciocan 		}
162371e6ca61SCristina Ciocan 	}
162471e6ca61SCristina Ciocan 
162571e6ca61SCristina Ciocan 	if (!soc_data)
162671e6ca61SCristina Ciocan 		return -ENODEV;
162771e6ca61SCristina Ciocan 
162871e6ca61SCristina Ciocan 	vg = devm_kzalloc(&pdev->dev, sizeof(*vg), GFP_KERNEL);
162971e6ca61SCristina Ciocan 	if (!vg)
163071e6ca61SCristina Ciocan 		return -ENOMEM;
163171e6ca61SCristina Ciocan 
163271e6ca61SCristina Ciocan 	vg->pdev = pdev;
163371e6ca61SCristina Ciocan 	ret = byt_set_soc_data(vg, soc_data);
163471e6ca61SCristina Ciocan 	if (ret) {
163571e6ca61SCristina Ciocan 		dev_err(&pdev->dev, "failed to set soc data\n");
163671e6ca61SCristina Ciocan 		return ret;
163771e6ca61SCristina Ciocan 	}
163871e6ca61SCristina Ciocan 
163971e6ca61SCristina Ciocan 	vg->pctl_desc		= byt_pinctrl_desc;
164071e6ca61SCristina Ciocan 	vg->pctl_desc.name	= dev_name(&pdev->dev);
164171e6ca61SCristina Ciocan 	vg->pctl_desc.pins	= vg->soc_data->pins;
164271e6ca61SCristina Ciocan 	vg->pctl_desc.npins	= vg->soc_data->npins;
164371e6ca61SCristina Ciocan 
16440612413fSAndy Shevchenko 	vg->pctl_dev = devm_pinctrl_register(&pdev->dev, &vg->pctl_desc, vg);
164571e6ca61SCristina Ciocan 	if (IS_ERR(vg->pctl_dev)) {
164671e6ca61SCristina Ciocan 		dev_err(&pdev->dev, "failed to register pinctrl driver\n");
164771e6ca61SCristina Ciocan 		return PTR_ERR(vg->pctl_dev);
164871e6ca61SCristina Ciocan 	}
164971e6ca61SCristina Ciocan 
1650a171bc51SVille Syrjälä 	raw_spin_lock_init(&vg->lock);
1651a171bc51SVille Syrjälä 
165271e6ca61SCristina Ciocan 	ret = byt_gpio_probe(vg);
16530612413fSAndy Shevchenko 	if (ret)
165471e6ca61SCristina Ciocan 		return ret;
165571e6ca61SCristina Ciocan 
165671e6ca61SCristina Ciocan 	platform_set_drvdata(pdev, vg);
165771e6ca61SCristina Ciocan 	pm_runtime_enable(&pdev->dev);
165871e6ca61SCristina Ciocan 
165971e6ca61SCristina Ciocan 	return 0;
166071e6ca61SCristina Ciocan }
166171e6ca61SCristina Ciocan 
1662fcc18debSMika Westerberg #ifdef CONFIG_PM_SLEEP
1663fcc18debSMika Westerberg static int byt_gpio_suspend(struct device *dev)
1664fcc18debSMika Westerberg {
1665d481de47SWolfram Sang 	struct byt_gpio *vg = dev_get_drvdata(dev);
1666fcc18debSMika Westerberg 	int i;
1667fcc18debSMika Westerberg 
166871e6ca61SCristina Ciocan 	for (i = 0; i < vg->soc_data->npins; i++) {
1669fcc18debSMika Westerberg 		void __iomem *reg;
1670fcc18debSMika Westerberg 		u32 value;
167171e6ca61SCristina Ciocan 		unsigned int pin = vg->soc_data->pins[i].number;
1672fcc18debSMika Westerberg 
167371e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
167471e6ca61SCristina Ciocan 		if (!reg) {
167571e6ca61SCristina Ciocan 			dev_warn(&vg->pdev->dev,
167671e6ca61SCristina Ciocan 				 "Pin %i: could not retrieve conf0 register\n",
167771e6ca61SCristina Ciocan 				 i);
167871e6ca61SCristina Ciocan 			continue;
167971e6ca61SCristina Ciocan 		}
1680fcc18debSMika Westerberg 		value = readl(reg) & BYT_CONF0_RESTORE_MASK;
1681fcc18debSMika Westerberg 		vg->saved_context[i].conf0 = value;
1682fcc18debSMika Westerberg 
168371e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
1684fcc18debSMika Westerberg 		value = readl(reg) & BYT_VAL_RESTORE_MASK;
1685fcc18debSMika Westerberg 		vg->saved_context[i].val = value;
1686fcc18debSMika Westerberg 	}
1687fcc18debSMika Westerberg 
1688fcc18debSMika Westerberg 	return 0;
1689fcc18debSMika Westerberg }
1690fcc18debSMika Westerberg 
1691fcc18debSMika Westerberg static int byt_gpio_resume(struct device *dev)
1692fcc18debSMika Westerberg {
1693d481de47SWolfram Sang 	struct byt_gpio *vg = dev_get_drvdata(dev);
1694fcc18debSMika Westerberg 	int i;
1695fcc18debSMika Westerberg 
169671e6ca61SCristina Ciocan 	for (i = 0; i < vg->soc_data->npins; i++) {
1697fcc18debSMika Westerberg 		void __iomem *reg;
1698fcc18debSMika Westerberg 		u32 value;
169971e6ca61SCristina Ciocan 		unsigned int pin = vg->soc_data->pins[i].number;
1700fcc18debSMika Westerberg 
170171e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
170271e6ca61SCristina Ciocan 		if (!reg) {
170371e6ca61SCristina Ciocan 			dev_warn(&vg->pdev->dev,
170471e6ca61SCristina Ciocan 				 "Pin %i: could not retrieve conf0 register\n",
170571e6ca61SCristina Ciocan 				 i);
170671e6ca61SCristina Ciocan 			continue;
170771e6ca61SCristina Ciocan 		}
1708fcc18debSMika Westerberg 		value = readl(reg);
1709fcc18debSMika Westerberg 		if ((value & BYT_CONF0_RESTORE_MASK) !=
1710fcc18debSMika Westerberg 		     vg->saved_context[i].conf0) {
1711fcc18debSMika Westerberg 			value &= ~BYT_CONF0_RESTORE_MASK;
1712fcc18debSMika Westerberg 			value |= vg->saved_context[i].conf0;
1713fcc18debSMika Westerberg 			writel(value, reg);
1714fcc18debSMika Westerberg 			dev_info(dev, "restored pin %d conf0 %#08x", i, value);
1715fcc18debSMika Westerberg 		}
1716fcc18debSMika Westerberg 
171771e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
1718fcc18debSMika Westerberg 		value = readl(reg);
1719fcc18debSMika Westerberg 		if ((value & BYT_VAL_RESTORE_MASK) !=
1720fcc18debSMika Westerberg 		     vg->saved_context[i].val) {
1721fcc18debSMika Westerberg 			u32 v;
1722fcc18debSMika Westerberg 
1723fcc18debSMika Westerberg 			v = value & ~BYT_VAL_RESTORE_MASK;
1724fcc18debSMika Westerberg 			v |= vg->saved_context[i].val;
1725fcc18debSMika Westerberg 			if (v != value) {
1726fcc18debSMika Westerberg 				writel(v, reg);
1727fcc18debSMika Westerberg 				dev_dbg(dev, "restored pin %d val %#08x\n",
1728fcc18debSMika Westerberg 					i, v);
1729fcc18debSMika Westerberg 			}
1730fcc18debSMika Westerberg 		}
1731fcc18debSMika Westerberg 	}
1732fcc18debSMika Westerberg 
1733fcc18debSMika Westerberg 	return 0;
1734fcc18debSMika Westerberg }
1735fcc18debSMika Westerberg #endif
1736fcc18debSMika Westerberg 
1737ec879f12SMika Westerberg #ifdef CONFIG_PM
17385fae8b86SMika Westerberg static int byt_gpio_runtime_suspend(struct device *dev)
17395fae8b86SMika Westerberg {
17405fae8b86SMika Westerberg 	return 0;
17415fae8b86SMika Westerberg }
17425fae8b86SMika Westerberg 
17435fae8b86SMika Westerberg static int byt_gpio_runtime_resume(struct device *dev)
17445fae8b86SMika Westerberg {
17455fae8b86SMika Westerberg 	return 0;
17465fae8b86SMika Westerberg }
1747ec879f12SMika Westerberg #endif
17485fae8b86SMika Westerberg 
17495fae8b86SMika Westerberg static const struct dev_pm_ops byt_gpio_pm_ops = {
1750fcc18debSMika Westerberg 	SET_LATE_SYSTEM_SLEEP_PM_OPS(byt_gpio_suspend, byt_gpio_resume)
1751fcc18debSMika Westerberg 	SET_RUNTIME_PM_OPS(byt_gpio_runtime_suspend, byt_gpio_runtime_resume,
1752fcc18debSMika Westerberg 			   NULL)
17535fae8b86SMika Westerberg };
17545fae8b86SMika Westerberg 
17555fae8b86SMika Westerberg static struct platform_driver byt_gpio_driver = {
175671e6ca61SCristina Ciocan 	.probe          = byt_pinctrl_probe,
17575fae8b86SMika Westerberg 	.driver         = {
17585fae8b86SMika Westerberg 		.name			= "byt_gpio",
17595fae8b86SMika Westerberg 		.pm			= &byt_gpio_pm_ops,
1760360943a8SPaul Gortmaker 		.suppress_bind_attrs	= true,
1761360943a8SPaul Gortmaker 
17625fae8b86SMika Westerberg 		.acpi_match_table = ACPI_PTR(byt_gpio_acpi_match),
17635fae8b86SMika Westerberg 	},
17645fae8b86SMika Westerberg };
17655fae8b86SMika Westerberg 
17665fae8b86SMika Westerberg static int __init byt_gpio_init(void)
17675fae8b86SMika Westerberg {
17685fae8b86SMika Westerberg 	return platform_driver_register(&byt_gpio_driver);
17695fae8b86SMika Westerberg }
17705fae8b86SMika Westerberg subsys_initcall(byt_gpio_init);
1771