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)
40eb0a2daaSAndy Shevchenko #define BYT_TRIG_MASK		GENMASK(26, 24)
415fae8b86SMika Westerberg #define BYT_TRIG_NEG		BIT(26)
425fae8b86SMika Westerberg #define BYT_TRIG_POS		BIT(25)
435fae8b86SMika Westerberg #define BYT_TRIG_LVL		BIT(24)
44658b476cSCristina Ciocan #define BYT_DEBOUNCE_EN		BIT(20)
459291c65bSHans de Goede #define BYT_GLITCH_FILTER_EN	BIT(19)
469291c65bSHans de Goede #define BYT_GLITCH_F_SLOW_CLK	BIT(17)
479291c65bSHans de Goede #define BYT_GLITCH_F_FAST_CLK	BIT(16)
485fae8b86SMika Westerberg #define BYT_PULL_STR_SHIFT	9
49eb0a2daaSAndy Shevchenko #define BYT_PULL_STR_MASK	GENMASK(10, 9)
505fae8b86SMika Westerberg #define BYT_PULL_STR_2K		(0 << BYT_PULL_STR_SHIFT)
515fae8b86SMika Westerberg #define BYT_PULL_STR_10K	(1 << BYT_PULL_STR_SHIFT)
525fae8b86SMika Westerberg #define BYT_PULL_STR_20K	(2 << BYT_PULL_STR_SHIFT)
535fae8b86SMika Westerberg #define BYT_PULL_STR_40K	(3 << BYT_PULL_STR_SHIFT)
545fae8b86SMika Westerberg #define BYT_PULL_ASSIGN_SHIFT	7
55eb0a2daaSAndy Shevchenko #define BYT_PULL_ASSIGN_MASK	GENMASK(8, 7)
565fae8b86SMika Westerberg #define BYT_PULL_ASSIGN_UP	(1 << BYT_PULL_ASSIGN_SHIFT)
575fae8b86SMika Westerberg #define BYT_PULL_ASSIGN_DOWN	(2 << BYT_PULL_ASSIGN_SHIFT)
58eb0a2daaSAndy Shevchenko #define BYT_PIN_MUX		GENMASK(2, 0)
595fae8b86SMika Westerberg 
605fae8b86SMika Westerberg /* BYT_VAL_REG register bits */
61eb0a2daaSAndy Shevchenko #define BYT_DIR_MASK		GENMASK(2, 1)
625fae8b86SMika Westerberg #define BYT_INPUT_EN		BIT(2)  /* 0: input enabled (active low)*/
635fae8b86SMika Westerberg #define BYT_OUTPUT_EN		BIT(1)  /* 0: output enabled (active low)*/
645fae8b86SMika Westerberg #define BYT_LEVEL		BIT(0)
655fae8b86SMika Westerberg 
66eb0a2daaSAndy Shevchenko #define BYT_CONF0_RESTORE_MASK	(BYT_DIRECT_IRQ_EN | BYT_TRIG_MASK | BYT_PIN_MUX)
67fcc18debSMika Westerberg #define BYT_VAL_RESTORE_MASK	(BYT_DIR_MASK | BYT_LEVEL)
68fcc18debSMika Westerberg 
69658b476cSCristina Ciocan /* BYT_DEBOUNCE_REG bits */
70eb0a2daaSAndy Shevchenko #define BYT_DEBOUNCE_PULSE_MASK		GENMASK(2, 0)
71658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_375US	1
72658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_750US	2
73658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_1500US	3
74658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_3MS		4
75658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_6MS		5
76658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_12MS		6
77658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_24MS		7
78658b476cSCristina Ciocan 
795fae8b86SMika Westerberg #define BYT_NGPIO_SCORE		102
805fae8b86SMika Westerberg #define BYT_NGPIO_NCORE		28
815fae8b86SMika Westerberg #define BYT_NGPIO_SUS		44
825fae8b86SMika Westerberg 
835fae8b86SMika Westerberg #define BYT_SCORE_ACPI_UID	"1"
845fae8b86SMika Westerberg #define BYT_NCORE_ACPI_UID	"2"
855fae8b86SMika Westerberg #define BYT_SUS_ACPI_UID	"3"
865fae8b86SMika Westerberg 
87c501d0b1SCristina Ciocan /*
88c501d0b1SCristina Ciocan  * This is the function value most pins have for GPIO muxing. If the value
89c501d0b1SCristina Ciocan  * differs from the default one, it must be explicitly mentioned. Otherwise, the
90c501d0b1SCristina Ciocan  * pin control implementation will set the muxing value to default GPIO if it
91c501d0b1SCristina Ciocan  * does not find a match for the requested function.
92c501d0b1SCristina Ciocan  */
93c501d0b1SCristina Ciocan #define BYT_DEFAULT_GPIO_MUX	0
94a705f9c1SAndy Shevchenko #define BYT_ALTER_GPIO_MUX	1
95c501d0b1SCristina Ciocan 
96c8f5c4c7SCristina Ciocan struct byt_gpio_pin_context {
97c8f5c4c7SCristina Ciocan 	u32 conf0;
98c8f5c4c7SCristina Ciocan 	u32 val;
99c8f5c4c7SCristina Ciocan };
1005fae8b86SMika Westerberg 
101c8f5c4c7SCristina Ciocan #define COMMUNITY(p, n, map)		\
102c8f5c4c7SCristina Ciocan 	{				\
103c8f5c4c7SCristina Ciocan 		.pin_base	= (p),	\
104c8f5c4c7SCristina Ciocan 		.npins		= (n),	\
105c8f5c4c7SCristina Ciocan 		.pad_map	= (map),\
106c8f5c4c7SCristina Ciocan 	}
107c8f5c4c7SCristina Ciocan 
10871e6ca61SCristina Ciocan struct byt_gpio {
10971e6ca61SCristina Ciocan 	struct gpio_chip chip;
11071e6ca61SCristina Ciocan 	struct platform_device *pdev;
11171e6ca61SCristina Ciocan 	struct pinctrl_dev *pctl_dev;
11271e6ca61SCristina Ciocan 	struct pinctrl_desc pctl_desc;
11371e6ca61SCristina Ciocan 	raw_spinlock_t lock;
11434e65670SAndy Shevchenko 	const struct intel_pinctrl_soc_data *soc_data;
11534e65670SAndy Shevchenko 	struct intel_community *communities_copy;
11671e6ca61SCristina Ciocan 	struct byt_gpio_pin_context *saved_context;
11771e6ca61SCristina Ciocan };
11871e6ca61SCristina Ciocan 
119c8f5c4c7SCristina Ciocan /* SCORE pins, aka GPIOC_<pin_no> or GPIO_S0_SC[<pin_no>] */
120c8f5c4c7SCristina Ciocan static const struct pinctrl_pin_desc byt_score_pins[] = {
121c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(0, "SATA_GP0"),
122c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(1, "SATA_GP1"),
123c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(2, "SATA_LED#"),
124c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(3, "PCIE_CLKREQ0"),
125c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(4, "PCIE_CLKREQ1"),
126c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(5, "PCIE_CLKREQ2"),
127c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(6, "PCIE_CLKREQ3"),
128c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(7, "SD3_WP"),
129c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(8, "HDA_RST"),
130c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(9, "HDA_SYNC"),
131c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(10, "HDA_CLK"),
132c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(11, "HDA_SDO"),
133c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(12, "HDA_SDI0"),
134c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(13, "HDA_SDI1"),
135c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(14, "GPIO_S0_SC14"),
136c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(15, "GPIO_S0_SC15"),
137c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(16, "MMC1_CLK"),
138c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(17, "MMC1_D0"),
139c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(18, "MMC1_D1"),
140c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(19, "MMC1_D2"),
141c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(20, "MMC1_D3"),
142c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(21, "MMC1_D4"),
143c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(22, "MMC1_D5"),
144c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(23, "MMC1_D6"),
145c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(24, "MMC1_D7"),
146c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(25, "MMC1_CMD"),
147c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(26, "MMC1_RST"),
148c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(27, "SD2_CLK"),
149c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(28, "SD2_D0"),
150c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(29, "SD2_D1"),
151c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(30, "SD2_D2"),
152c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(31, "SD2_D3_CD"),
153c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(32, "SD2_CMD"),
154c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(33, "SD3_CLK"),
155c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(34, "SD3_D0"),
156c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(35, "SD3_D1"),
157c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(36, "SD3_D2"),
158c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(37, "SD3_D3"),
159c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(38, "SD3_CD"),
160c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(39, "SD3_CMD"),
161c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(40, "SD3_1P8EN"),
162c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(41, "SD3_PWREN#"),
163c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(42, "ILB_LPC_AD0"),
164c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(43, "ILB_LPC_AD1"),
165c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(44, "ILB_LPC_AD2"),
166c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(45, "ILB_LPC_AD3"),
167c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(46, "ILB_LPC_FRAME"),
168c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(47, "ILB_LPC_CLK0"),
169c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(48, "ILB_LPC_CLK1"),
170c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(49, "ILB_LPC_CLKRUN"),
171c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(50, "ILB_LPC_SERIRQ"),
172c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(51, "PCU_SMB_DATA"),
173c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(52, "PCU_SMB_CLK"),
174c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(53, "PCU_SMB_ALERT"),
175c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(54, "ILB_8254_SPKR"),
176c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(55, "GPIO_S0_SC55"),
177c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(56, "GPIO_S0_SC56"),
178c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(57, "GPIO_S0_SC57"),
179c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(58, "GPIO_S0_SC58"),
180c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(59, "GPIO_S0_SC59"),
181c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(60, "GPIO_S0_SC60"),
182c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(61, "GPIO_S0_SC61"),
183c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(62, "LPE_I2S2_CLK"),
184c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(63, "LPE_I2S2_FRM"),
185c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(64, "LPE_I2S2_DATAIN"),
186c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(65, "LPE_I2S2_DATAOUT"),
187c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(66, "SIO_SPI_CS"),
188c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(67, "SIO_SPI_MISO"),
189c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(68, "SIO_SPI_MOSI"),
190c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(69, "SIO_SPI_CLK"),
191c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(70, "SIO_UART1_RXD"),
192c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(71, "SIO_UART1_TXD"),
193c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(72, "SIO_UART1_RTS"),
194c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(73, "SIO_UART1_CTS"),
195c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(74, "SIO_UART2_RXD"),
196c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(75, "SIO_UART2_TXD"),
197c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(76, "SIO_UART2_RTS"),
198c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(77, "SIO_UART2_CTS"),
199c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(78, "SIO_I2C0_DATA"),
200c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(79, "SIO_I2C0_CLK"),
201c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(80, "SIO_I2C1_DATA"),
202c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(81, "SIO_I2C1_CLK"),
203c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(82, "SIO_I2C2_DATA"),
204c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(83, "SIO_I2C2_CLK"),
205c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(84, "SIO_I2C3_DATA"),
206c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(85, "SIO_I2C3_CLK"),
207c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(86, "SIO_I2C4_DATA"),
208c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(87, "SIO_I2C4_CLK"),
209c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(88, "SIO_I2C5_DATA"),
210c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(89, "SIO_I2C5_CLK"),
211c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(90, "SIO_I2C6_DATA"),
212c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(91, "SIO_I2C6_CLK"),
213c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(92, "GPIO_S0_SC92"),
214c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(93, "GPIO_S0_SC93"),
215c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(94, "SIO_PWM0"),
216c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(95, "SIO_PWM1"),
217c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(96, "PMC_PLT_CLK0"),
218c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(97, "PMC_PLT_CLK1"),
219c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(98, "PMC_PLT_CLK2"),
220c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(99, "PMC_PLT_CLK3"),
221c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(100, "PMC_PLT_CLK4"),
222c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(101, "PMC_PLT_CLK5"),
223c8f5c4c7SCristina Ciocan };
2245fae8b86SMika Westerberg 
225c8f5c4c7SCristina Ciocan static const unsigned int byt_score_pins_map[BYT_NGPIO_SCORE] = {
226c8f5c4c7SCristina Ciocan 	85, 89, 93, 96, 99, 102, 98, 101, 34, 37,
227c8f5c4c7SCristina Ciocan 	36, 38, 39, 35, 40, 84, 62, 61, 64, 59,
228c8f5c4c7SCristina Ciocan 	54, 56, 60, 55, 63, 57, 51, 50, 53, 47,
229c8f5c4c7SCristina Ciocan 	52, 49, 48, 43, 46, 41, 45, 42, 58, 44,
230c8f5c4c7SCristina Ciocan 	95, 105, 70, 68, 67, 66, 69, 71, 65, 72,
231c8f5c4c7SCristina Ciocan 	86, 90, 88, 92, 103, 77, 79, 83, 78, 81,
232c8f5c4c7SCristina Ciocan 	80, 82, 13, 12, 15, 14, 17, 18, 19, 16,
233c8f5c4c7SCristina Ciocan 	2, 1, 0, 4, 6, 7, 9, 8, 33, 32,
234c8f5c4c7SCristina Ciocan 	31, 30, 29, 27, 25, 28, 26, 23, 21, 20,
235c8f5c4c7SCristina Ciocan 	24, 22, 5, 3, 10, 11, 106, 87, 91, 104,
236c8f5c4c7SCristina Ciocan 	97, 100,
2375fae8b86SMika Westerberg };
2385fae8b86SMika Westerberg 
239c8f5c4c7SCristina Ciocan /* SCORE groups */
240c8f5c4c7SCristina Ciocan static const unsigned int byt_score_uart1_pins[] = { 70, 71, 72, 73 };
241c8f5c4c7SCristina Ciocan static const unsigned int byt_score_uart2_pins[] = { 74, 75, 76, 77 };
242c8f5c4c7SCristina Ciocan 
243c8f5c4c7SCristina Ciocan static const unsigned int byt_score_pwm0_pins[] = { 94 };
244c8f5c4c7SCristina Ciocan static const unsigned int byt_score_pwm1_pins[] = { 95 };
245c8f5c4c7SCristina Ciocan 
246c8f5c4c7SCristina Ciocan static const unsigned int byt_score_sio_spi_pins[] = { 66, 67, 68, 69 };
247c8f5c4c7SCristina Ciocan 
248c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c5_pins[] = { 88, 89 };
249c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c6_pins[] = { 90, 91 };
250c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c4_pins[] = { 86, 87 };
251c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c3_pins[] = { 84, 85 };
252c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c2_pins[] = { 82, 83 };
253c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c1_pins[] = { 80, 81 };
254c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c0_pins[] = { 78, 79 };
255c8f5c4c7SCristina Ciocan 
256c8f5c4c7SCristina Ciocan static const unsigned int byt_score_ssp0_pins[] = { 8, 9, 10, 11 };
257c8f5c4c7SCristina Ciocan static const unsigned int byt_score_ssp1_pins[] = { 12, 13, 14, 15 };
258c8f5c4c7SCristina Ciocan static const unsigned int byt_score_ssp2_pins[] = { 62, 63, 64, 65 };
259c8f5c4c7SCristina Ciocan 
260c8f5c4c7SCristina Ciocan static const unsigned int byt_score_sdcard_pins[] = {
261c8f5c4c7SCristina Ciocan 	7, 33, 34, 35, 36, 37, 38, 39, 40, 41,
262c8f5c4c7SCristina Ciocan };
2634f010b93SAndy Shevchenko static const unsigned int byt_score_sdcard_mux_values[] = {
264c8f5c4c7SCristina Ciocan 	2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
265c8f5c4c7SCristina Ciocan };
266c8f5c4c7SCristina Ciocan 
267c8f5c4c7SCristina Ciocan static const unsigned int byt_score_sdio_pins[] = { 27, 28, 29, 30, 31, 32 };
268c8f5c4c7SCristina Ciocan 
269c8f5c4c7SCristina Ciocan static const unsigned int byt_score_emmc_pins[] = {
270c8f5c4c7SCristina Ciocan 	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
271c8f5c4c7SCristina Ciocan };
272c8f5c4c7SCristina Ciocan 
273c8f5c4c7SCristina Ciocan static const unsigned int byt_score_ilb_lpc_pins[] = {
274c8f5c4c7SCristina Ciocan 	42, 43, 44, 45, 46, 47, 48, 49, 50,
275c8f5c4c7SCristina Ciocan };
276c8f5c4c7SCristina Ciocan 
277c8f5c4c7SCristina Ciocan static const unsigned int byt_score_sata_pins[] = { 0, 1, 2 };
278c8f5c4c7SCristina Ciocan 
279c8f5c4c7SCristina Ciocan static const unsigned int byt_score_plt_clk0_pins[] = { 96 };
280c8f5c4c7SCristina Ciocan static const unsigned int byt_score_plt_clk1_pins[] = { 97 };
281c8f5c4c7SCristina Ciocan static const unsigned int byt_score_plt_clk2_pins[] = { 98 };
282b41aa4f8SCristina Ciocan static const unsigned int byt_score_plt_clk3_pins[] = { 99 };
283b41aa4f8SCristina Ciocan static const unsigned int byt_score_plt_clk4_pins[] = { 100 };
284b41aa4f8SCristina Ciocan static const unsigned int byt_score_plt_clk5_pins[] = { 101 };
285c8f5c4c7SCristina Ciocan 
286c8f5c4c7SCristina Ciocan static const unsigned int byt_score_smbus_pins[] = { 51, 52, 53 };
287c8f5c4c7SCristina Ciocan 
2884f010b93SAndy Shevchenko static const struct intel_pingroup byt_score_groups[] = {
2894f010b93SAndy Shevchenko 	PIN_GROUP("uart1_grp", byt_score_uart1_pins, 1),
2904f010b93SAndy Shevchenko 	PIN_GROUP("uart2_grp", byt_score_uart2_pins, 1),
2914f010b93SAndy Shevchenko 	PIN_GROUP("pwm0_grp", byt_score_pwm0_pins, 1),
2924f010b93SAndy Shevchenko 	PIN_GROUP("pwm1_grp", byt_score_pwm1_pins, 1),
2934f010b93SAndy Shevchenko 	PIN_GROUP("ssp2_grp", byt_score_ssp2_pins, 1),
2944f010b93SAndy Shevchenko 	PIN_GROUP("sio_spi_grp", byt_score_sio_spi_pins, 1),
2954f010b93SAndy Shevchenko 	PIN_GROUP("i2c5_grp", byt_score_i2c5_pins, 1),
2964f010b93SAndy Shevchenko 	PIN_GROUP("i2c6_grp", byt_score_i2c6_pins, 1),
2974f010b93SAndy Shevchenko 	PIN_GROUP("i2c4_grp", byt_score_i2c4_pins, 1),
2984f010b93SAndy Shevchenko 	PIN_GROUP("i2c3_grp", byt_score_i2c3_pins, 1),
2994f010b93SAndy Shevchenko 	PIN_GROUP("i2c2_grp", byt_score_i2c2_pins, 1),
3004f010b93SAndy Shevchenko 	PIN_GROUP("i2c1_grp", byt_score_i2c1_pins, 1),
3014f010b93SAndy Shevchenko 	PIN_GROUP("i2c0_grp", byt_score_i2c0_pins, 1),
3024f010b93SAndy Shevchenko 	PIN_GROUP("ssp0_grp", byt_score_ssp0_pins, 1),
3034f010b93SAndy Shevchenko 	PIN_GROUP("ssp1_grp", byt_score_ssp1_pins, 1),
3044f010b93SAndy Shevchenko 	PIN_GROUP("sdcard_grp", byt_score_sdcard_pins, byt_score_sdcard_mux_values),
3054f010b93SAndy Shevchenko 	PIN_GROUP("sdio_grp", byt_score_sdio_pins, 1),
3064f010b93SAndy Shevchenko 	PIN_GROUP("emmc_grp", byt_score_emmc_pins, 1),
3074f010b93SAndy Shevchenko 	PIN_GROUP("lpc_grp", byt_score_ilb_lpc_pins, 1),
3084f010b93SAndy Shevchenko 	PIN_GROUP("sata_grp", byt_score_sata_pins, 1),
3094f010b93SAndy Shevchenko 	PIN_GROUP("plt_clk0_grp", byt_score_plt_clk0_pins, 1),
3104f010b93SAndy Shevchenko 	PIN_GROUP("plt_clk1_grp", byt_score_plt_clk1_pins, 1),
3114f010b93SAndy Shevchenko 	PIN_GROUP("plt_clk2_grp", byt_score_plt_clk2_pins, 1),
3124f010b93SAndy Shevchenko 	PIN_GROUP("plt_clk3_grp", byt_score_plt_clk3_pins, 1),
3134f010b93SAndy Shevchenko 	PIN_GROUP("plt_clk4_grp", byt_score_plt_clk4_pins, 1),
3144f010b93SAndy Shevchenko 	PIN_GROUP("plt_clk5_grp", byt_score_plt_clk5_pins, 1),
3154f010b93SAndy Shevchenko 	PIN_GROUP("smbus_grp", byt_score_smbus_pins, 1),
316c8f5c4c7SCristina Ciocan };
317c8f5c4c7SCristina Ciocan 
318c8f5c4c7SCristina Ciocan static const char * const byt_score_uart_groups[] = {
319c8f5c4c7SCristina Ciocan 	"uart1_grp", "uart2_grp",
320c8f5c4c7SCristina Ciocan };
321c8f5c4c7SCristina Ciocan static const char * const byt_score_pwm_groups[] = {
322c8f5c4c7SCristina Ciocan 	"pwm0_grp", "pwm1_grp",
323c8f5c4c7SCristina Ciocan };
324c8f5c4c7SCristina Ciocan static const char * const byt_score_ssp_groups[] = {
325c8f5c4c7SCristina Ciocan 	"ssp0_grp", "ssp1_grp", "ssp2_grp",
326c8f5c4c7SCristina Ciocan };
327c8f5c4c7SCristina Ciocan static const char * const byt_score_spi_groups[] = { "sio_spi_grp" };
328c8f5c4c7SCristina Ciocan static const char * const byt_score_i2c_groups[] = {
329c8f5c4c7SCristina Ciocan 	"i2c0_grp", "i2c1_grp", "i2c2_grp", "i2c3_grp", "i2c4_grp", "i2c5_grp",
330c8f5c4c7SCristina Ciocan 	"i2c6_grp",
331c8f5c4c7SCristina Ciocan };
332c8f5c4c7SCristina Ciocan static const char * const byt_score_sdcard_groups[] = { "sdcard_grp" };
333c8f5c4c7SCristina Ciocan static const char * const byt_score_sdio_groups[] = { "sdio_grp" };
334c8f5c4c7SCristina Ciocan static const char * const byt_score_emmc_groups[] = { "emmc_grp" };
335c8f5c4c7SCristina Ciocan static const char * const byt_score_lpc_groups[] = { "lpc_grp" };
336c8f5c4c7SCristina Ciocan static const char * const byt_score_sata_groups[] = { "sata_grp" };
337c8f5c4c7SCristina Ciocan static const char * const byt_score_plt_clk_groups[] = {
338c8f5c4c7SCristina Ciocan 	"plt_clk0_grp", "plt_clk1_grp", "plt_clk2_grp", "plt_clk3_grp",
339c8f5c4c7SCristina Ciocan 	"plt_clk4_grp", "plt_clk5_grp",
340c8f5c4c7SCristina Ciocan };
341c8f5c4c7SCristina Ciocan static const char * const byt_score_smbus_groups[] = { "smbus_grp" };
342c8f5c4c7SCristina Ciocan static const char * const byt_score_gpio_groups[] = {
343c8f5c4c7SCristina Ciocan 	"uart1_grp", "uart2_grp", "pwm0_grp", "pwm1_grp", "ssp0_grp",
344c8f5c4c7SCristina Ciocan 	"ssp1_grp", "ssp2_grp", "sio_spi_grp", "i2c0_grp", "i2c1_grp",
345c8f5c4c7SCristina Ciocan 	"i2c2_grp", "i2c3_grp", "i2c4_grp", "i2c5_grp", "i2c6_grp",
346c8f5c4c7SCristina Ciocan 	"sdcard_grp", "sdio_grp", "emmc_grp", "lpc_grp", "sata_grp",
347c8f5c4c7SCristina Ciocan 	"plt_clk0_grp", "plt_clk1_grp", "plt_clk2_grp", "plt_clk3_grp",
348c8f5c4c7SCristina Ciocan 	"plt_clk4_grp", "plt_clk5_grp", "smbus_grp",
349c8f5c4c7SCristina Ciocan };
350c8f5c4c7SCristina Ciocan 
3514f010b93SAndy Shevchenko static const struct intel_function byt_score_functions[] = {
352c8f5c4c7SCristina Ciocan 	FUNCTION("uart", byt_score_uart_groups),
353c8f5c4c7SCristina Ciocan 	FUNCTION("pwm", byt_score_pwm_groups),
354c8f5c4c7SCristina Ciocan 	FUNCTION("ssp", byt_score_ssp_groups),
355c8f5c4c7SCristina Ciocan 	FUNCTION("spi", byt_score_spi_groups),
356c8f5c4c7SCristina Ciocan 	FUNCTION("i2c", byt_score_i2c_groups),
357c8f5c4c7SCristina Ciocan 	FUNCTION("sdcard", byt_score_sdcard_groups),
358c8f5c4c7SCristina Ciocan 	FUNCTION("sdio", byt_score_sdio_groups),
359c8f5c4c7SCristina Ciocan 	FUNCTION("emmc", byt_score_emmc_groups),
360c8f5c4c7SCristina Ciocan 	FUNCTION("lpc", byt_score_lpc_groups),
361c8f5c4c7SCristina Ciocan 	FUNCTION("sata", byt_score_sata_groups),
362c8f5c4c7SCristina Ciocan 	FUNCTION("plt_clk", byt_score_plt_clk_groups),
363c8f5c4c7SCristina Ciocan 	FUNCTION("smbus", byt_score_smbus_groups),
364c8f5c4c7SCristina Ciocan 	FUNCTION("gpio", byt_score_gpio_groups),
365c8f5c4c7SCristina Ciocan };
366c8f5c4c7SCristina Ciocan 
36734e65670SAndy Shevchenko static const struct intel_community byt_score_communities[] = {
368c8f5c4c7SCristina Ciocan 	COMMUNITY(0, BYT_NGPIO_SCORE, byt_score_pins_map),
369c8f5c4c7SCristina Ciocan };
370c8f5c4c7SCristina Ciocan 
37134e65670SAndy Shevchenko static const struct intel_pinctrl_soc_data byt_score_soc_data = {
372c8f5c4c7SCristina Ciocan 	.uid		= BYT_SCORE_ACPI_UID,
373c8f5c4c7SCristina Ciocan 	.pins		= byt_score_pins,
374c8f5c4c7SCristina Ciocan 	.npins		= ARRAY_SIZE(byt_score_pins),
375c8f5c4c7SCristina Ciocan 	.groups		= byt_score_groups,
376c8f5c4c7SCristina Ciocan 	.ngroups	= ARRAY_SIZE(byt_score_groups),
377c8f5c4c7SCristina Ciocan 	.functions	= byt_score_functions,
378c8f5c4c7SCristina Ciocan 	.nfunctions	= ARRAY_SIZE(byt_score_functions),
379c8f5c4c7SCristina Ciocan 	.communities	= byt_score_communities,
380c8f5c4c7SCristina Ciocan 	.ncommunities	= ARRAY_SIZE(byt_score_communities),
381c8f5c4c7SCristina Ciocan };
382c8f5c4c7SCristina Ciocan 
383c8f5c4c7SCristina Ciocan /* SUS pins, aka GPIOS_<pin_no> or GPIO_S5[<pin_no>]  */
384c8f5c4c7SCristina Ciocan static const struct pinctrl_pin_desc byt_sus_pins[] = {
385c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(0, "GPIO_S50"),
386c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(1, "GPIO_S51"),
387c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(2, "GPIO_S52"),
388c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(3, "GPIO_S53"),
389c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(4, "GPIO_S54"),
390c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(5, "GPIO_S55"),
391c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(6, "GPIO_S56"),
392c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(7, "GPIO_S57"),
393c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(8, "GPIO_S58"),
394c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(9, "GPIO_S59"),
395c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(10, "GPIO_S510"),
396c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(11, "PMC_SUSPWRDNACK"),
397c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(12, "PMC_SUSCLK0"),
398c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(13, "GPIO_S513"),
399c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(14, "USB_ULPI_RST"),
400c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(15, "PMC_WAKE_PCIE0#"),
401c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(16, "PMC_PWRBTN"),
402c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(17, "GPIO_S517"),
403c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(18, "PMC_SUS_STAT"),
404c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(19, "USB_OC0"),
405c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(20, "USB_OC1"),
406c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(21, "PCU_SPI_CS1"),
407c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(22, "GPIO_S522"),
408c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(23, "GPIO_S523"),
409c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(24, "GPIO_S524"),
410c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(25, "GPIO_S525"),
411c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(26, "GPIO_S526"),
412c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(27, "GPIO_S527"),
413c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(28, "GPIO_S528"),
414c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(29, "GPIO_S529"),
415c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(30, "GPIO_S530"),
416c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(31, "USB_ULPI_CLK"),
417c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(32, "USB_ULPI_DATA0"),
418c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(33, "USB_ULPI_DATA1"),
419c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(34, "USB_ULPI_DATA2"),
420c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(35, "USB_ULPI_DATA3"),
421c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(36, "USB_ULPI_DATA4"),
422c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(37, "USB_ULPI_DATA5"),
423c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(38, "USB_ULPI_DATA6"),
424c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(39, "USB_ULPI_DATA7"),
425c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(40, "USB_ULPI_DIR"),
426c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(41, "USB_ULPI_NXT"),
427c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(42, "USB_ULPI_STP"),
428c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(43, "USB_ULPI_REFCLK"),
429c8f5c4c7SCristina Ciocan };
430c8f5c4c7SCristina Ciocan 
431c8f5c4c7SCristina Ciocan static const unsigned int byt_sus_pins_map[BYT_NGPIO_SUS] = {
432c8f5c4c7SCristina Ciocan 	29, 33, 30, 31, 32, 34, 36, 35, 38, 37,
433c8f5c4c7SCristina Ciocan 	18, 7, 11, 20, 17, 1, 8, 10, 19, 12,
434c8f5c4c7SCristina Ciocan 	0, 2, 23, 39, 28, 27, 22, 21, 24, 25,
435c8f5c4c7SCristina Ciocan 	26, 51, 56, 54, 49, 55, 48, 57, 50, 58,
436c8f5c4c7SCristina Ciocan 	52, 53, 59, 40,
437c8f5c4c7SCristina Ciocan };
438c8f5c4c7SCristina Ciocan 
439c8f5c4c7SCristina Ciocan static const unsigned int byt_sus_usb_over_current_pins[] = { 19, 20 };
4404f010b93SAndy Shevchenko static const unsigned int byt_sus_usb_over_current_mode_values[] = { 0, 0 };
4414f010b93SAndy Shevchenko static const unsigned int byt_sus_usb_over_current_gpio_mode_values[] = { 1, 1 };
442c8f5c4c7SCristina Ciocan 
443c8f5c4c7SCristina Ciocan static const unsigned int byt_sus_usb_ulpi_pins[] = {
444c8f5c4c7SCristina Ciocan 	14, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
445c8f5c4c7SCristina Ciocan };
4464f010b93SAndy Shevchenko static const unsigned int byt_sus_usb_ulpi_mode_values[] = {
447c8f5c4c7SCristina Ciocan 	2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
448c8f5c4c7SCristina Ciocan };
4494f010b93SAndy Shevchenko static const unsigned int byt_sus_usb_ulpi_gpio_mode_values[] = {
4504f010b93SAndy Shevchenko 	1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
451c8f5c4c7SCristina Ciocan };
452c8f5c4c7SCristina Ciocan 
453c8f5c4c7SCristina Ciocan static const unsigned int byt_sus_pcu_spi_pins[] = { 21 };
4544f010b93SAndy Shevchenko static const unsigned int byt_sus_pcu_spi_mode_values[] = { 0 };
4554f010b93SAndy Shevchenko static const unsigned int byt_sus_pcu_spi_gpio_mode_values[] = { 1 };
456c8f5c4c7SCristina Ciocan 
4574f010b93SAndy Shevchenko static const struct intel_pingroup byt_sus_groups[] = {
4584f010b93SAndy Shevchenko 	PIN_GROUP("usb_oc_grp", byt_sus_usb_over_current_pins, byt_sus_usb_over_current_mode_values),
4594f010b93SAndy Shevchenko 	PIN_GROUP("usb_ulpi_grp", byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_mode_values),
4604f010b93SAndy Shevchenko 	PIN_GROUP("pcu_spi_grp", byt_sus_pcu_spi_pins, byt_sus_pcu_spi_mode_values),
4614f010b93SAndy Shevchenko 	PIN_GROUP("usb_oc_grp_gpio", byt_sus_usb_over_current_pins, byt_sus_usb_over_current_gpio_mode_values),
4624f010b93SAndy Shevchenko 	PIN_GROUP("usb_ulpi_grp_gpio", byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_gpio_mode_values),
4634f010b93SAndy Shevchenko 	PIN_GROUP("pcu_spi_grp_gpio", byt_sus_pcu_spi_pins, byt_sus_pcu_spi_gpio_mode_values),
464c8f5c4c7SCristina Ciocan };
465c8f5c4c7SCristina Ciocan 
466c8f5c4c7SCristina Ciocan static const char * const byt_sus_usb_groups[] = {
467c8f5c4c7SCristina Ciocan 	"usb_oc_grp", "usb_ulpi_grp",
468c8f5c4c7SCristina Ciocan };
469c8f5c4c7SCristina Ciocan static const char * const byt_sus_spi_groups[] = { "pcu_spi_grp" };
470c8f5c4c7SCristina Ciocan static const char * const byt_sus_gpio_groups[] = {
4714f010b93SAndy Shevchenko 	"usb_oc_grp_gpio", "usb_ulpi_grp_gpio", "pcu_spi_grp_gpio",
472c8f5c4c7SCristina Ciocan };
473c8f5c4c7SCristina Ciocan 
4744f010b93SAndy Shevchenko static const struct intel_function byt_sus_functions[] = {
475c8f5c4c7SCristina Ciocan 	FUNCTION("usb", byt_sus_usb_groups),
476c8f5c4c7SCristina Ciocan 	FUNCTION("spi", byt_sus_spi_groups),
477c8f5c4c7SCristina Ciocan 	FUNCTION("gpio", byt_sus_gpio_groups),
478c8f5c4c7SCristina Ciocan };
479c8f5c4c7SCristina Ciocan 
48034e65670SAndy Shevchenko static const struct intel_community byt_sus_communities[] = {
481c8f5c4c7SCristina Ciocan 	COMMUNITY(0, BYT_NGPIO_SUS, byt_sus_pins_map),
482c8f5c4c7SCristina Ciocan };
483c8f5c4c7SCristina Ciocan 
48434e65670SAndy Shevchenko static const struct intel_pinctrl_soc_data byt_sus_soc_data = {
485c8f5c4c7SCristina Ciocan 	.uid		= BYT_SUS_ACPI_UID,
486c8f5c4c7SCristina Ciocan 	.pins		= byt_sus_pins,
487c8f5c4c7SCristina Ciocan 	.npins		= ARRAY_SIZE(byt_sus_pins),
488c8f5c4c7SCristina Ciocan 	.groups		= byt_sus_groups,
489c8f5c4c7SCristina Ciocan 	.ngroups	= ARRAY_SIZE(byt_sus_groups),
490c8f5c4c7SCristina Ciocan 	.functions	= byt_sus_functions,
491c8f5c4c7SCristina Ciocan 	.nfunctions	= ARRAY_SIZE(byt_sus_functions),
492c8f5c4c7SCristina Ciocan 	.communities	= byt_sus_communities,
493c8f5c4c7SCristina Ciocan 	.ncommunities	= ARRAY_SIZE(byt_sus_communities),
494c8f5c4c7SCristina Ciocan };
495c8f5c4c7SCristina Ciocan 
496c8f5c4c7SCristina Ciocan static const struct pinctrl_pin_desc byt_ncore_pins[] = {
497c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(0, "GPIO_NCORE0"),
498c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(1, "GPIO_NCORE1"),
499c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(2, "GPIO_NCORE2"),
500c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(3, "GPIO_NCORE3"),
501c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(4, "GPIO_NCORE4"),
502c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(5, "GPIO_NCORE5"),
503c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(6, "GPIO_NCORE6"),
504c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(7, "GPIO_NCORE7"),
505c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(8, "GPIO_NCORE8"),
506c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(9, "GPIO_NCORE9"),
507c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(10, "GPIO_NCORE10"),
508c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(11, "GPIO_NCORE11"),
509c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(12, "GPIO_NCORE12"),
510c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(13, "GPIO_NCORE13"),
511c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(14, "GPIO_NCORE14"),
512c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(15, "GPIO_NCORE15"),
513c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(16, "GPIO_NCORE16"),
514c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(17, "GPIO_NCORE17"),
515c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(18, "GPIO_NCORE18"),
516c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(19, "GPIO_NCORE19"),
517c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(20, "GPIO_NCORE20"),
518c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(21, "GPIO_NCORE21"),
519c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(22, "GPIO_NCORE22"),
520c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(23, "GPIO_NCORE23"),
521c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(24, "GPIO_NCORE24"),
522c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(25, "GPIO_NCORE25"),
523c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(26, "GPIO_NCORE26"),
524c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(27, "GPIO_NCORE27"),
525c8f5c4c7SCristina Ciocan };
526c8f5c4c7SCristina Ciocan 
527939330d7SAndy Shevchenko static const unsigned int byt_ncore_pins_map[BYT_NGPIO_NCORE] = {
528c8f5c4c7SCristina Ciocan 	19, 18, 17, 20, 21, 22, 24, 25, 23, 16,
529c8f5c4c7SCristina Ciocan 	14, 15, 12, 26, 27, 1, 4, 8, 11, 0,
530c8f5c4c7SCristina Ciocan 	3, 6, 10, 13, 2, 5, 9, 7,
531c8f5c4c7SCristina Ciocan };
532c8f5c4c7SCristina Ciocan 
53334e65670SAndy Shevchenko static const struct intel_community byt_ncore_communities[] = {
534c8f5c4c7SCristina Ciocan 	COMMUNITY(0, BYT_NGPIO_NCORE, byt_ncore_pins_map),
535c8f5c4c7SCristina Ciocan };
536c8f5c4c7SCristina Ciocan 
53734e65670SAndy Shevchenko static const struct intel_pinctrl_soc_data byt_ncore_soc_data = {
538c8f5c4c7SCristina Ciocan 	.uid		= BYT_NCORE_ACPI_UID,
539c8f5c4c7SCristina Ciocan 	.pins		= byt_ncore_pins,
540c8f5c4c7SCristina Ciocan 	.npins		= ARRAY_SIZE(byt_ncore_pins),
541c8f5c4c7SCristina Ciocan 	.communities	= byt_ncore_communities,
542c8f5c4c7SCristina Ciocan 	.ncommunities	= ARRAY_SIZE(byt_ncore_communities),
543c8f5c4c7SCristina Ciocan };
544c8f5c4c7SCristina Ciocan 
54534e65670SAndy Shevchenko static const struct intel_pinctrl_soc_data *byt_soc_data[] = {
546c8f5c4c7SCristina Ciocan 	&byt_score_soc_data,
547c8f5c4c7SCristina Ciocan 	&byt_sus_soc_data,
548c8f5c4c7SCristina Ciocan 	&byt_ncore_soc_data,
549166d6e2aSAndy Shevchenko 	NULL
550c8f5c4c7SCristina Ciocan };
551c8f5c4c7SCristina Ciocan 
55234e65670SAndy Shevchenko static struct intel_community *byt_get_community(struct byt_gpio *vg,
553c501d0b1SCristina Ciocan 						 unsigned int pin)
554c501d0b1SCristina Ciocan {
55534e65670SAndy Shevchenko 	struct intel_community *comm;
556c501d0b1SCristina Ciocan 	int i;
557c501d0b1SCristina Ciocan 
558c501d0b1SCristina Ciocan 	for (i = 0; i < vg->soc_data->ncommunities; i++) {
559c501d0b1SCristina Ciocan 		comm = vg->communities_copy + i;
560c501d0b1SCristina Ciocan 		if (pin < comm->pin_base + comm->npins && pin >= comm->pin_base)
561c501d0b1SCristina Ciocan 			return comm;
562c501d0b1SCristina Ciocan 	}
563c501d0b1SCristina Ciocan 
564c501d0b1SCristina Ciocan 	return NULL;
565c501d0b1SCristina Ciocan }
566c501d0b1SCristina Ciocan 
567c501d0b1SCristina Ciocan static void __iomem *byt_gpio_reg(struct byt_gpio *vg, unsigned int offset,
5685fae8b86SMika Westerberg 				  int reg)
5695fae8b86SMika Westerberg {
57034e65670SAndy Shevchenko 	struct intel_community *comm = byt_get_community(vg, offset);
5711b89970dSAndy Shevchenko 	u32 reg_offset;
5725fae8b86SMika Westerberg 
573c501d0b1SCristina Ciocan 	if (!comm)
574c501d0b1SCristina Ciocan 		return NULL;
575c501d0b1SCristina Ciocan 
576c501d0b1SCristina Ciocan 	offset -= comm->pin_base;
5771b89970dSAndy Shevchenko 	switch (reg) {
5781b89970dSAndy Shevchenko 	case BYT_INT_STAT_REG:
5795fae8b86SMika Westerberg 		reg_offset = (offset / 32) * 4;
5801b89970dSAndy Shevchenko 		break;
5811b89970dSAndy Shevchenko 	case BYT_DEBOUNCE_REG:
5821b89970dSAndy Shevchenko 		reg_offset = 0;
5831b89970dSAndy Shevchenko 		break;
5841b89970dSAndy Shevchenko 	default:
585c501d0b1SCristina Ciocan 		reg_offset = comm->pad_map[offset] * 16;
5861b89970dSAndy Shevchenko 		break;
5871b89970dSAndy Shevchenko 	}
5885fae8b86SMika Westerberg 
58934e65670SAndy Shevchenko 	return comm->pad_regs + reg_offset + reg;
5905fae8b86SMika Westerberg }
5915fae8b86SMika Westerberg 
592c501d0b1SCristina Ciocan static int byt_get_groups_count(struct pinctrl_dev *pctldev)
59395f0972cSMika Westerberg {
594c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
595c501d0b1SCristina Ciocan 
596c501d0b1SCristina Ciocan 	return vg->soc_data->ngroups;
597c501d0b1SCristina Ciocan }
598c501d0b1SCristina Ciocan 
599c501d0b1SCristina Ciocan static const char *byt_get_group_name(struct pinctrl_dev *pctldev,
600c501d0b1SCristina Ciocan 				      unsigned int selector)
601c501d0b1SCristina Ciocan {
602c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
603c501d0b1SCristina Ciocan 
604c501d0b1SCristina Ciocan 	return vg->soc_data->groups[selector].name;
605c501d0b1SCristina Ciocan }
606c501d0b1SCristina Ciocan 
607c501d0b1SCristina Ciocan static int byt_get_group_pins(struct pinctrl_dev *pctldev,
608c501d0b1SCristina Ciocan 			      unsigned int selector,
609c501d0b1SCristina Ciocan 			      const unsigned int **pins,
610c501d0b1SCristina Ciocan 			      unsigned int *num_pins)
611c501d0b1SCristina Ciocan {
612c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
613c501d0b1SCristina Ciocan 
614c501d0b1SCristina Ciocan 	*pins		= vg->soc_data->groups[selector].pins;
615c501d0b1SCristina Ciocan 	*num_pins	= vg->soc_data->groups[selector].npins;
616c501d0b1SCristina Ciocan 
617c501d0b1SCristina Ciocan 	return 0;
618c501d0b1SCristina Ciocan }
619c501d0b1SCristina Ciocan 
620c501d0b1SCristina Ciocan static const struct pinctrl_ops byt_pinctrl_ops = {
621c501d0b1SCristina Ciocan 	.get_groups_count	= byt_get_groups_count,
622c501d0b1SCristina Ciocan 	.get_group_name		= byt_get_group_name,
623c501d0b1SCristina Ciocan 	.get_group_pins		= byt_get_group_pins,
624c501d0b1SCristina Ciocan };
625c501d0b1SCristina Ciocan 
626c501d0b1SCristina Ciocan static int byt_get_functions_count(struct pinctrl_dev *pctldev)
627c501d0b1SCristina Ciocan {
628c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
629c501d0b1SCristina Ciocan 
630c501d0b1SCristina Ciocan 	return vg->soc_data->nfunctions;
631c501d0b1SCristina Ciocan }
632c501d0b1SCristina Ciocan 
633c501d0b1SCristina Ciocan static const char *byt_get_function_name(struct pinctrl_dev *pctldev,
634c501d0b1SCristina Ciocan 					 unsigned int selector)
635c501d0b1SCristina Ciocan {
636c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
637c501d0b1SCristina Ciocan 
638c501d0b1SCristina Ciocan 	return vg->soc_data->functions[selector].name;
639c501d0b1SCristina Ciocan }
640c501d0b1SCristina Ciocan 
641c501d0b1SCristina Ciocan static int byt_get_function_groups(struct pinctrl_dev *pctldev,
642c501d0b1SCristina Ciocan 				   unsigned int selector,
643c501d0b1SCristina Ciocan 				   const char * const **groups,
644c501d0b1SCristina Ciocan 				   unsigned int *num_groups)
645c501d0b1SCristina Ciocan {
646c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
647c501d0b1SCristina Ciocan 
648c501d0b1SCristina Ciocan 	*groups		= vg->soc_data->functions[selector].groups;
649c501d0b1SCristina Ciocan 	*num_groups	= vg->soc_data->functions[selector].ngroups;
650c501d0b1SCristina Ciocan 
651c501d0b1SCristina Ciocan 	return 0;
652c501d0b1SCristina Ciocan }
653c501d0b1SCristina Ciocan 
654c501d0b1SCristina Ciocan static void byt_set_group_simple_mux(struct byt_gpio *vg,
6554f010b93SAndy Shevchenko 				     const struct intel_pingroup group,
6564f010b93SAndy Shevchenko 				     unsigned int func)
657c501d0b1SCristina Ciocan {
658c501d0b1SCristina Ciocan 	unsigned long flags;
659c501d0b1SCristina Ciocan 	int i;
660c501d0b1SCristina Ciocan 
661c501d0b1SCristina Ciocan 	raw_spin_lock_irqsave(&vg->lock, flags);
662c501d0b1SCristina Ciocan 
663c501d0b1SCristina Ciocan 	for (i = 0; i < group.npins; i++) {
664c501d0b1SCristina Ciocan 		void __iomem *padcfg0;
665c501d0b1SCristina Ciocan 		u32 value;
666c501d0b1SCristina Ciocan 
667c501d0b1SCristina Ciocan 		padcfg0 = byt_gpio_reg(vg, group.pins[i], BYT_CONF0_REG);
668c501d0b1SCristina Ciocan 		if (!padcfg0) {
669c501d0b1SCristina Ciocan 			dev_warn(&vg->pdev->dev,
670c501d0b1SCristina Ciocan 				 "Group %s, pin %i not muxed (no padcfg0)\n",
671c501d0b1SCristina Ciocan 				 group.name, i);
672c501d0b1SCristina Ciocan 			continue;
673c501d0b1SCristina Ciocan 		}
674c501d0b1SCristina Ciocan 
675c501d0b1SCristina Ciocan 		value = readl(padcfg0);
676c501d0b1SCristina Ciocan 		value &= ~BYT_PIN_MUX;
677c501d0b1SCristina Ciocan 		value |= func;
678c501d0b1SCristina Ciocan 		writel(value, padcfg0);
679c501d0b1SCristina Ciocan 	}
680c501d0b1SCristina Ciocan 
681c501d0b1SCristina Ciocan 	raw_spin_unlock_irqrestore(&vg->lock, flags);
682c501d0b1SCristina Ciocan }
683c501d0b1SCristina Ciocan 
684c501d0b1SCristina Ciocan static void byt_set_group_mixed_mux(struct byt_gpio *vg,
6854f010b93SAndy Shevchenko 				    const struct intel_pingroup group,
6864f010b93SAndy Shevchenko 				    const unsigned int *func)
687c501d0b1SCristina Ciocan {
688c501d0b1SCristina Ciocan 	unsigned long flags;
689c501d0b1SCristina Ciocan 	int i;
690c501d0b1SCristina Ciocan 
691c501d0b1SCristina Ciocan 	raw_spin_lock_irqsave(&vg->lock, flags);
692c501d0b1SCristina Ciocan 
693c501d0b1SCristina Ciocan 	for (i = 0; i < group.npins; i++) {
694c501d0b1SCristina Ciocan 		void __iomem *padcfg0;
695c501d0b1SCristina Ciocan 		u32 value;
696c501d0b1SCristina Ciocan 
697c501d0b1SCristina Ciocan 		padcfg0 = byt_gpio_reg(vg, group.pins[i], BYT_CONF0_REG);
698c501d0b1SCristina Ciocan 		if (!padcfg0) {
699c501d0b1SCristina Ciocan 			dev_warn(&vg->pdev->dev,
700c501d0b1SCristina Ciocan 				 "Group %s, pin %i not muxed (no padcfg0)\n",
701c501d0b1SCristina Ciocan 				 group.name, i);
702c501d0b1SCristina Ciocan 			continue;
703c501d0b1SCristina Ciocan 		}
704c501d0b1SCristina Ciocan 
705c501d0b1SCristina Ciocan 		value = readl(padcfg0);
706c501d0b1SCristina Ciocan 		value &= ~BYT_PIN_MUX;
707c501d0b1SCristina Ciocan 		value |= func[i];
708c501d0b1SCristina Ciocan 		writel(value, padcfg0);
709c501d0b1SCristina Ciocan 	}
710c501d0b1SCristina Ciocan 
711c501d0b1SCristina Ciocan 	raw_spin_unlock_irqrestore(&vg->lock, flags);
712c501d0b1SCristina Ciocan }
713c501d0b1SCristina Ciocan 
714c501d0b1SCristina Ciocan static int byt_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
715c501d0b1SCristina Ciocan 		       unsigned int group_selector)
716c501d0b1SCristina Ciocan {
717c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctldev);
7184f010b93SAndy Shevchenko 	const struct intel_function func = vg->soc_data->functions[func_selector];
7194f010b93SAndy Shevchenko 	const struct intel_pingroup group = vg->soc_data->groups[group_selector];
720c501d0b1SCristina Ciocan 
7214f010b93SAndy Shevchenko 	if (group.modes)
7224f010b93SAndy Shevchenko 		byt_set_group_mixed_mux(vg, group, group.modes);
7234f010b93SAndy Shevchenko 	else if (!strcmp(func.name, "gpio"))
724c501d0b1SCristina Ciocan 		byt_set_group_simple_mux(vg, group, BYT_DEFAULT_GPIO_MUX);
725c501d0b1SCristina Ciocan 	else
7264f010b93SAndy Shevchenko 		byt_set_group_simple_mux(vg, group, group.mode);
727c501d0b1SCristina Ciocan 
728c501d0b1SCristina Ciocan 	return 0;
729c501d0b1SCristina Ciocan }
730c501d0b1SCristina Ciocan 
731939330d7SAndy Shevchenko static u32 byt_get_gpio_mux(struct byt_gpio *vg, unsigned int offset)
732c501d0b1SCristina Ciocan {
733c501d0b1SCristina Ciocan 	/* SCORE pin 92-93 */
734c501d0b1SCristina Ciocan 	if (!strcmp(vg->soc_data->uid, BYT_SCORE_ACPI_UID) &&
735c501d0b1SCristina Ciocan 	    offset >= 92 && offset <= 93)
736a705f9c1SAndy Shevchenko 		return BYT_ALTER_GPIO_MUX;
737c501d0b1SCristina Ciocan 
738c501d0b1SCristina Ciocan 	/* SUS pin 11-21 */
739c501d0b1SCristina Ciocan 	if (!strcmp(vg->soc_data->uid, BYT_SUS_ACPI_UID) &&
740c501d0b1SCristina Ciocan 	    offset >= 11 && offset <= 21)
741a705f9c1SAndy Shevchenko 		return BYT_ALTER_GPIO_MUX;
742c501d0b1SCristina Ciocan 
743a705f9c1SAndy Shevchenko 	return BYT_DEFAULT_GPIO_MUX;
744c501d0b1SCristina Ciocan }
745c501d0b1SCristina Ciocan 
746c501d0b1SCristina Ciocan static void byt_gpio_clear_triggering(struct byt_gpio *vg, unsigned int offset)
747c501d0b1SCristina Ciocan {
748c501d0b1SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
74995f0972cSMika Westerberg 	unsigned long flags;
75095f0972cSMika Westerberg 	u32 value;
75195f0972cSMika Westerberg 
75278e1c896SMika Westerberg 	raw_spin_lock_irqsave(&vg->lock, flags);
75395f0972cSMika Westerberg 	value = readl(reg);
75495f0972cSMika Westerberg 	value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
75595f0972cSMika Westerberg 	writel(value, reg);
75678e1c896SMika Westerberg 	raw_spin_unlock_irqrestore(&vg->lock, flags);
75795f0972cSMika Westerberg }
75895f0972cSMika Westerberg 
759c501d0b1SCristina Ciocan static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev,
760c501d0b1SCristina Ciocan 				   struct pinctrl_gpio_range *range,
761c501d0b1SCristina Ciocan 				   unsigned int offset)
7625fae8b86SMika Westerberg {
763c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
764c501d0b1SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
765f8323b6bSMika Westerberg 	u32 value, gpio_mux;
76639ce8150SMika Westerberg 	unsigned long flags;
76739ce8150SMika Westerberg 
76878e1c896SMika Westerberg 	raw_spin_lock_irqsave(&vg->lock, flags);
7695fae8b86SMika Westerberg 
7705fae8b86SMika Westerberg 	/*
7715fae8b86SMika Westerberg 	 * In most cases, func pin mux 000 means GPIO function.
7725fae8b86SMika Westerberg 	 * But, some pins may have func pin mux 001 represents
773f8323b6bSMika Westerberg 	 * GPIO function.
774f8323b6bSMika Westerberg 	 *
775f8323b6bSMika Westerberg 	 * Because there are devices out there where some pins were not
776f8323b6bSMika Westerberg 	 * configured correctly we allow changing the mux value from
777f8323b6bSMika Westerberg 	 * request (but print out warning about that).
7785fae8b86SMika Westerberg 	 */
7795fae8b86SMika Westerberg 	value = readl(reg) & BYT_PIN_MUX;
780f8323b6bSMika Westerberg 	gpio_mux = byt_get_gpio_mux(vg, offset);
781b5894d12SHans de Goede 	if (gpio_mux != value) {
782f8323b6bSMika Westerberg 		value = readl(reg) & ~BYT_PIN_MUX;
783f8323b6bSMika Westerberg 		value |= gpio_mux;
784f8323b6bSMika Westerberg 		writel(value, reg);
785f8323b6bSMika Westerberg 
786b5894d12SHans de Goede 		dev_warn(&vg->pdev->dev, FW_BUG
787f8323b6bSMika Westerberg 			 "pin %u forcibly re-configured as GPIO\n", offset);
7885fae8b86SMika Westerberg 	}
7895fae8b86SMika Westerberg 
79078e1c896SMika Westerberg 	raw_spin_unlock_irqrestore(&vg->lock, flags);
79139ce8150SMika Westerberg 
7925fae8b86SMika Westerberg 	pm_runtime_get(&vg->pdev->dev);
7935fae8b86SMika Westerberg 
7945fae8b86SMika Westerberg 	return 0;
7955fae8b86SMika Westerberg }
7965fae8b86SMika Westerberg 
797c501d0b1SCristina Ciocan static void byt_gpio_disable_free(struct pinctrl_dev *pctl_dev,
798c501d0b1SCristina Ciocan 				  struct pinctrl_gpio_range *range,
799c501d0b1SCristina Ciocan 				  unsigned int offset)
800c501d0b1SCristina Ciocan {
801c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
802c501d0b1SCristina Ciocan 
803c501d0b1SCristina Ciocan 	byt_gpio_clear_triggering(vg, offset);
804c501d0b1SCristina Ciocan 	pm_runtime_put(&vg->pdev->dev);
805c501d0b1SCristina Ciocan }
806c501d0b1SCristina Ciocan 
807c501d0b1SCristina Ciocan static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
808c501d0b1SCristina Ciocan 				  struct pinctrl_gpio_range *range,
809c501d0b1SCristina Ciocan 				  unsigned int offset,
810c501d0b1SCristina Ciocan 				  bool input)
811c501d0b1SCristina Ciocan {
812c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
813c501d0b1SCristina Ciocan 	void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
814c501d0b1SCristina Ciocan 	void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
815c501d0b1SCristina Ciocan 	unsigned long flags;
816c501d0b1SCristina Ciocan 	u32 value;
817c501d0b1SCristina Ciocan 
818c501d0b1SCristina Ciocan 	raw_spin_lock_irqsave(&vg->lock, flags);
819c501d0b1SCristina Ciocan 
820c501d0b1SCristina Ciocan 	value = readl(val_reg);
821c501d0b1SCristina Ciocan 	value &= ~BYT_DIR_MASK;
822c501d0b1SCristina Ciocan 	if (input)
823c501d0b1SCristina Ciocan 		value |= BYT_OUTPUT_EN;
824c501d0b1SCristina Ciocan 	else
825c501d0b1SCristina Ciocan 		/*
826c501d0b1SCristina Ciocan 		 * Before making any direction modifications, do a check if gpio
827c501d0b1SCristina Ciocan 		 * is set for direct IRQ.  On baytrail, setting GPIO to output
828c501d0b1SCristina Ciocan 		 * does not make sense, so let's at least warn the caller before
829c501d0b1SCristina Ciocan 		 * they shoot themselves in the foot.
830c501d0b1SCristina Ciocan 		 */
831c501d0b1SCristina Ciocan 		WARN(readl(conf_reg) & BYT_DIRECT_IRQ_EN,
832c501d0b1SCristina Ciocan 		     "Potential Error: Setting GPIO with direct_irq_en to output");
833c501d0b1SCristina Ciocan 	writel(value, val_reg);
834c501d0b1SCristina Ciocan 
835c501d0b1SCristina Ciocan 	raw_spin_unlock_irqrestore(&vg->lock, flags);
836c501d0b1SCristina Ciocan 
837c501d0b1SCristina Ciocan 	return 0;
838c501d0b1SCristina Ciocan }
839c501d0b1SCristina Ciocan 
840c501d0b1SCristina Ciocan static const struct pinmux_ops byt_pinmux_ops = {
841c501d0b1SCristina Ciocan 	.get_functions_count	= byt_get_functions_count,
842c501d0b1SCristina Ciocan 	.get_function_name	= byt_get_function_name,
843c501d0b1SCristina Ciocan 	.get_function_groups	= byt_get_function_groups,
844c501d0b1SCristina Ciocan 	.set_mux		= byt_set_mux,
845c501d0b1SCristina Ciocan 	.gpio_request_enable	= byt_gpio_request_enable,
846c501d0b1SCristina Ciocan 	.gpio_disable_free	= byt_gpio_disable_free,
847c501d0b1SCristina Ciocan 	.gpio_set_direction	= byt_gpio_set_direction,
848c501d0b1SCristina Ciocan };
849c501d0b1SCristina Ciocan 
850c501d0b1SCristina Ciocan static void byt_get_pull_strength(u32 reg, u16 *strength)
851c501d0b1SCristina Ciocan {
852c501d0b1SCristina Ciocan 	switch (reg & BYT_PULL_STR_MASK) {
853c501d0b1SCristina Ciocan 	case BYT_PULL_STR_2K:
854c501d0b1SCristina Ciocan 		*strength = 2000;
855c501d0b1SCristina Ciocan 		break;
856c501d0b1SCristina Ciocan 	case BYT_PULL_STR_10K:
857c501d0b1SCristina Ciocan 		*strength = 10000;
858c501d0b1SCristina Ciocan 		break;
859c501d0b1SCristina Ciocan 	case BYT_PULL_STR_20K:
860c501d0b1SCristina Ciocan 		*strength = 20000;
861c501d0b1SCristina Ciocan 		break;
862c501d0b1SCristina Ciocan 	case BYT_PULL_STR_40K:
863c501d0b1SCristina Ciocan 		*strength = 40000;
864c501d0b1SCristina Ciocan 		break;
865c501d0b1SCristina Ciocan 	}
866c501d0b1SCristina Ciocan }
867c501d0b1SCristina Ciocan 
868c501d0b1SCristina Ciocan static int byt_set_pull_strength(u32 *reg, u16 strength)
869c501d0b1SCristina Ciocan {
870c501d0b1SCristina Ciocan 	*reg &= ~BYT_PULL_STR_MASK;
871c501d0b1SCristina Ciocan 
872c501d0b1SCristina Ciocan 	switch (strength) {
873c501d0b1SCristina Ciocan 	case 2000:
874c501d0b1SCristina Ciocan 		*reg |= BYT_PULL_STR_2K;
875c501d0b1SCristina Ciocan 		break;
876c501d0b1SCristina Ciocan 	case 10000:
877c501d0b1SCristina Ciocan 		*reg |= BYT_PULL_STR_10K;
878c501d0b1SCristina Ciocan 		break;
879c501d0b1SCristina Ciocan 	case 20000:
880c501d0b1SCristina Ciocan 		*reg |= BYT_PULL_STR_20K;
881c501d0b1SCristina Ciocan 		break;
882c501d0b1SCristina Ciocan 	case 40000:
883c501d0b1SCristina Ciocan 		*reg |= BYT_PULL_STR_40K;
884c501d0b1SCristina Ciocan 		break;
885c501d0b1SCristina Ciocan 	default:
886c501d0b1SCristina Ciocan 		return -EINVAL;
887c501d0b1SCristina Ciocan 	}
888c501d0b1SCristina Ciocan 
889c501d0b1SCristina Ciocan 	return 0;
890c501d0b1SCristina Ciocan }
891c501d0b1SCristina Ciocan 
892c501d0b1SCristina Ciocan static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset,
893c501d0b1SCristina Ciocan 			      unsigned long *config)
894c501d0b1SCristina Ciocan {
895c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
896c501d0b1SCristina Ciocan 	enum pin_config_param param = pinconf_to_config_param(*config);
897c501d0b1SCristina Ciocan 	void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
898c501d0b1SCristina Ciocan 	void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
89904ff5a09SAndy Shevchenko 	void __iomem *db_reg = byt_gpio_reg(vg, offset, BYT_DEBOUNCE_REG);
900c501d0b1SCristina Ciocan 	unsigned long flags;
901658b476cSCristina Ciocan 	u32 conf, pull, val, debounce;
902c501d0b1SCristina Ciocan 	u16 arg = 0;
903c501d0b1SCristina Ciocan 
904c501d0b1SCristina Ciocan 	raw_spin_lock_irqsave(&vg->lock, flags);
905c501d0b1SCristina Ciocan 	conf = readl(conf_reg);
906c501d0b1SCristina Ciocan 	pull = conf & BYT_PULL_ASSIGN_MASK;
907c501d0b1SCristina Ciocan 	val = readl(val_reg);
908c501d0b1SCristina Ciocan 	raw_spin_unlock_irqrestore(&vg->lock, flags);
909c501d0b1SCristina Ciocan 
910c501d0b1SCristina Ciocan 	switch (param) {
911c501d0b1SCristina Ciocan 	case PIN_CONFIG_BIAS_DISABLE:
912c501d0b1SCristina Ciocan 		if (pull)
913c501d0b1SCristina Ciocan 			return -EINVAL;
914c501d0b1SCristina Ciocan 		break;
915c501d0b1SCristina Ciocan 	case PIN_CONFIG_BIAS_PULL_DOWN:
916c501d0b1SCristina Ciocan 		/* Pull assignment is only applicable in input mode */
917c501d0b1SCristina Ciocan 		if ((val & BYT_INPUT_EN) || pull != BYT_PULL_ASSIGN_DOWN)
918c501d0b1SCristina Ciocan 			return -EINVAL;
919c501d0b1SCristina Ciocan 
920c501d0b1SCristina Ciocan 		byt_get_pull_strength(conf, &arg);
921c501d0b1SCristina Ciocan 
922c501d0b1SCristina Ciocan 		break;
923c501d0b1SCristina Ciocan 	case PIN_CONFIG_BIAS_PULL_UP:
924c501d0b1SCristina Ciocan 		/* Pull assignment is only applicable in input mode */
925c501d0b1SCristina Ciocan 		if ((val & BYT_INPUT_EN) || pull != BYT_PULL_ASSIGN_UP)
926c501d0b1SCristina Ciocan 			return -EINVAL;
927c501d0b1SCristina Ciocan 
928c501d0b1SCristina Ciocan 		byt_get_pull_strength(conf, &arg);
929c501d0b1SCristina Ciocan 
930c501d0b1SCristina Ciocan 		break;
931658b476cSCristina Ciocan 	case PIN_CONFIG_INPUT_DEBOUNCE:
932658b476cSCristina Ciocan 		if (!(conf & BYT_DEBOUNCE_EN))
933658b476cSCristina Ciocan 			return -EINVAL;
934658b476cSCristina Ciocan 
935658b476cSCristina Ciocan 		raw_spin_lock_irqsave(&vg->lock, flags);
93604ff5a09SAndy Shevchenko 		debounce = readl(db_reg);
937658b476cSCristina Ciocan 		raw_spin_unlock_irqrestore(&vg->lock, flags);
938658b476cSCristina Ciocan 
939658b476cSCristina Ciocan 		switch (debounce & BYT_DEBOUNCE_PULSE_MASK) {
940658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_375US:
941658b476cSCristina Ciocan 			arg = 375;
942658b476cSCristina Ciocan 			break;
943658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_750US:
944658b476cSCristina Ciocan 			arg = 750;
945658b476cSCristina Ciocan 			break;
946658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_1500US:
947658b476cSCristina Ciocan 			arg = 1500;
948658b476cSCristina Ciocan 			break;
949658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_3MS:
950658b476cSCristina Ciocan 			arg = 3000;
951658b476cSCristina Ciocan 			break;
952658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_6MS:
953658b476cSCristina Ciocan 			arg = 6000;
954658b476cSCristina Ciocan 			break;
955658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_12MS:
956658b476cSCristina Ciocan 			arg = 12000;
957658b476cSCristina Ciocan 			break;
958658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_24MS:
959658b476cSCristina Ciocan 			arg = 24000;
960658b476cSCristina Ciocan 			break;
961658b476cSCristina Ciocan 		default:
962658b476cSCristina Ciocan 			return -EINVAL;
963658b476cSCristina Ciocan 		}
964658b476cSCristina Ciocan 
965658b476cSCristina Ciocan 		break;
966c501d0b1SCristina Ciocan 	default:
967c501d0b1SCristina Ciocan 		return -ENOTSUPP;
968c501d0b1SCristina Ciocan 	}
969c501d0b1SCristina Ciocan 
970c501d0b1SCristina Ciocan 	*config = pinconf_to_config_packed(param, arg);
971c501d0b1SCristina Ciocan 
972c501d0b1SCristina Ciocan 	return 0;
973c501d0b1SCristina Ciocan }
974c501d0b1SCristina Ciocan 
975c501d0b1SCristina Ciocan static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
976c501d0b1SCristina Ciocan 			      unsigned int offset,
977c501d0b1SCristina Ciocan 			      unsigned long *configs,
978c501d0b1SCristina Ciocan 			      unsigned int num_configs)
979c501d0b1SCristina Ciocan {
980c501d0b1SCristina Ciocan 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
981c501d0b1SCristina Ciocan 	unsigned int param, arg;
982c501d0b1SCristina Ciocan 	void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
983c501d0b1SCristina Ciocan 	void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
98404ff5a09SAndy Shevchenko 	void __iomem *db_reg = byt_gpio_reg(vg, offset, BYT_DEBOUNCE_REG);
985c501d0b1SCristina Ciocan 	unsigned long flags;
986658b476cSCristina Ciocan 	u32 conf, val, debounce;
987c501d0b1SCristina Ciocan 	int i, ret = 0;
988c501d0b1SCristina Ciocan 
989c501d0b1SCristina Ciocan 	raw_spin_lock_irqsave(&vg->lock, flags);
990c501d0b1SCristina Ciocan 
991c501d0b1SCristina Ciocan 	conf = readl(conf_reg);
992c501d0b1SCristina Ciocan 	val = readl(val_reg);
993c501d0b1SCristina Ciocan 
994c501d0b1SCristina Ciocan 	for (i = 0; i < num_configs; i++) {
995c501d0b1SCristina Ciocan 		param = pinconf_to_config_param(configs[i]);
996c501d0b1SCristina Ciocan 		arg = pinconf_to_config_argument(configs[i]);
997c501d0b1SCristina Ciocan 
998c501d0b1SCristina Ciocan 		switch (param) {
999c501d0b1SCristina Ciocan 		case PIN_CONFIG_BIAS_DISABLE:
1000c501d0b1SCristina Ciocan 			conf &= ~BYT_PULL_ASSIGN_MASK;
1001c501d0b1SCristina Ciocan 			break;
1002c501d0b1SCristina Ciocan 		case PIN_CONFIG_BIAS_PULL_DOWN:
1003c501d0b1SCristina Ciocan 			/* Set default strength value in case none is given */
1004c501d0b1SCristina Ciocan 			if (arg == 1)
1005c501d0b1SCristina Ciocan 				arg = 2000;
1006c501d0b1SCristina Ciocan 
1007c501d0b1SCristina Ciocan 			/*
1008c501d0b1SCristina Ciocan 			 * Pull assignment is only applicable in input mode. If
1009c501d0b1SCristina Ciocan 			 * chip is not in input mode, set it and warn about it.
1010c501d0b1SCristina Ciocan 			 */
1011c501d0b1SCristina Ciocan 			if (val & BYT_INPUT_EN) {
1012c501d0b1SCristina Ciocan 				val &= ~BYT_INPUT_EN;
1013c501d0b1SCristina Ciocan 				writel(val, val_reg);
1014c501d0b1SCristina Ciocan 				dev_warn(&vg->pdev->dev,
1015c501d0b1SCristina Ciocan 					 "pin %u forcibly set to input mode\n",
1016c501d0b1SCristina Ciocan 					 offset);
1017c501d0b1SCristina Ciocan 			}
1018c501d0b1SCristina Ciocan 
1019c501d0b1SCristina Ciocan 			conf &= ~BYT_PULL_ASSIGN_MASK;
1020c501d0b1SCristina Ciocan 			conf |= BYT_PULL_ASSIGN_DOWN;
1021c501d0b1SCristina Ciocan 			ret = byt_set_pull_strength(&conf, arg);
1022c501d0b1SCristina Ciocan 
1023c501d0b1SCristina Ciocan 			break;
1024c501d0b1SCristina Ciocan 		case PIN_CONFIG_BIAS_PULL_UP:
1025c501d0b1SCristina Ciocan 			/* Set default strength value in case none is given */
1026c501d0b1SCristina Ciocan 			if (arg == 1)
1027c501d0b1SCristina Ciocan 				arg = 2000;
1028c501d0b1SCristina Ciocan 
1029c501d0b1SCristina Ciocan 			/*
1030c501d0b1SCristina Ciocan 			 * Pull assignment is only applicable in input mode. If
1031c501d0b1SCristina Ciocan 			 * chip is not in input mode, set it and warn about it.
1032c501d0b1SCristina Ciocan 			 */
1033c501d0b1SCristina Ciocan 			if (val & BYT_INPUT_EN) {
1034c501d0b1SCristina Ciocan 				val &= ~BYT_INPUT_EN;
1035c501d0b1SCristina Ciocan 				writel(val, val_reg);
1036c501d0b1SCristina Ciocan 				dev_warn(&vg->pdev->dev,
1037c501d0b1SCristina Ciocan 					 "pin %u forcibly set to input mode\n",
1038c501d0b1SCristina Ciocan 					 offset);
1039c501d0b1SCristina Ciocan 			}
1040c501d0b1SCristina Ciocan 
1041c501d0b1SCristina Ciocan 			conf &= ~BYT_PULL_ASSIGN_MASK;
1042c501d0b1SCristina Ciocan 			conf |= BYT_PULL_ASSIGN_UP;
1043c501d0b1SCristina Ciocan 			ret = byt_set_pull_strength(&conf, arg);
1044c501d0b1SCristina Ciocan 
1045c501d0b1SCristina Ciocan 			break;
1046658b476cSCristina Ciocan 		case PIN_CONFIG_INPUT_DEBOUNCE:
104704ff5a09SAndy Shevchenko 			debounce = readl(db_reg);
104804ff5a09SAndy Shevchenko 			debounce &= ~BYT_DEBOUNCE_PULSE_MASK;
1049658b476cSCristina Ciocan 
1050827e1579SAndy Shevchenko 			if (arg)
1051827e1579SAndy Shevchenko 				conf |= BYT_DEBOUNCE_EN;
1052827e1579SAndy Shevchenko 			else
1053827e1579SAndy Shevchenko 				conf &= ~BYT_DEBOUNCE_EN;
1054827e1579SAndy Shevchenko 
1055658b476cSCristina Ciocan 			switch (arg) {
1056658b476cSCristina Ciocan 			case 375:
105704ff5a09SAndy Shevchenko 				debounce |= BYT_DEBOUNCE_PULSE_375US;
1058658b476cSCristina Ciocan 				break;
1059658b476cSCristina Ciocan 			case 750:
106004ff5a09SAndy Shevchenko 				debounce |= BYT_DEBOUNCE_PULSE_750US;
1061658b476cSCristina Ciocan 				break;
1062658b476cSCristina Ciocan 			case 1500:
106304ff5a09SAndy Shevchenko 				debounce |= BYT_DEBOUNCE_PULSE_1500US;
1064658b476cSCristina Ciocan 				break;
1065658b476cSCristina Ciocan 			case 3000:
106604ff5a09SAndy Shevchenko 				debounce |= BYT_DEBOUNCE_PULSE_3MS;
1067658b476cSCristina Ciocan 				break;
1068658b476cSCristina Ciocan 			case 6000:
106904ff5a09SAndy Shevchenko 				debounce |= BYT_DEBOUNCE_PULSE_6MS;
1070658b476cSCristina Ciocan 				break;
1071658b476cSCristina Ciocan 			case 12000:
107204ff5a09SAndy Shevchenko 				debounce |= BYT_DEBOUNCE_PULSE_12MS;
1073658b476cSCristina Ciocan 				break;
1074658b476cSCristina Ciocan 			case 24000:
107504ff5a09SAndy Shevchenko 				debounce |= BYT_DEBOUNCE_PULSE_24MS;
1076658b476cSCristina Ciocan 				break;
1077658b476cSCristina Ciocan 			default:
1078827e1579SAndy Shevchenko 				if (arg)
1079658b476cSCristina Ciocan 					ret = -EINVAL;
1080827e1579SAndy Shevchenko 				break;
1081658b476cSCristina Ciocan 			}
1082658b476cSCristina Ciocan 
108304ff5a09SAndy Shevchenko 			if (!ret)
108404ff5a09SAndy Shevchenko 				writel(debounce, db_reg);
1085658b476cSCristina Ciocan 			break;
1086c501d0b1SCristina Ciocan 		default:
1087c501d0b1SCristina Ciocan 			ret = -ENOTSUPP;
1088c501d0b1SCristina Ciocan 		}
1089c501d0b1SCristina Ciocan 
1090c501d0b1SCristina Ciocan 		if (ret)
1091c501d0b1SCristina Ciocan 			break;
1092c501d0b1SCristina Ciocan 	}
1093c501d0b1SCristina Ciocan 
1094c501d0b1SCristina Ciocan 	if (!ret)
1095c501d0b1SCristina Ciocan 		writel(conf, conf_reg);
1096c501d0b1SCristina Ciocan 
1097c501d0b1SCristina Ciocan 	raw_spin_unlock_irqrestore(&vg->lock, flags);
1098c501d0b1SCristina Ciocan 
1099c501d0b1SCristina Ciocan 	return ret;
1100c501d0b1SCristina Ciocan }
1101c501d0b1SCristina Ciocan 
1102c501d0b1SCristina Ciocan static const struct pinconf_ops byt_pinconf_ops = {
1103c501d0b1SCristina Ciocan 	.is_generic	= true,
1104c501d0b1SCristina Ciocan 	.pin_config_get	= byt_pin_config_get,
1105c501d0b1SCristina Ciocan 	.pin_config_set	= byt_pin_config_set,
1106c501d0b1SCristina Ciocan };
1107c501d0b1SCristina Ciocan 
1108c501d0b1SCristina Ciocan static const struct pinctrl_desc byt_pinctrl_desc = {
1109c501d0b1SCristina Ciocan 	.pctlops	= &byt_pinctrl_ops,
1110c501d0b1SCristina Ciocan 	.pmxops		= &byt_pinmux_ops,
1111c501d0b1SCristina Ciocan 	.confops	= &byt_pinconf_ops,
1112c501d0b1SCristina Ciocan 	.owner		= THIS_MODULE,
1113c501d0b1SCristina Ciocan };
1114c501d0b1SCristina Ciocan 
1115939330d7SAndy Shevchenko static int byt_gpio_get(struct gpio_chip *chip, unsigned int offset)
11165fae8b86SMika Westerberg {
1117bf9a5c96SLinus Walleij 	struct byt_gpio *vg = gpiochip_get_data(chip);
1118c501d0b1SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
111939ce8150SMika Westerberg 	unsigned long flags;
112039ce8150SMika Westerberg 	u32 val;
112139ce8150SMika Westerberg 
112278e1c896SMika Westerberg 	raw_spin_lock_irqsave(&vg->lock, flags);
112339ce8150SMika Westerberg 	val = readl(reg);
112478e1c896SMika Westerberg 	raw_spin_unlock_irqrestore(&vg->lock, flags);
112539ce8150SMika Westerberg 
11263bde8771SLinus Walleij 	return !!(val & BYT_LEVEL);
11275fae8b86SMika Westerberg }
11285fae8b86SMika Westerberg 
1129939330d7SAndy Shevchenko static void byt_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
11305fae8b86SMika Westerberg {
1131bf9a5c96SLinus Walleij 	struct byt_gpio *vg = gpiochip_get_data(chip);
1132c501d0b1SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
11335fae8b86SMika Westerberg 	unsigned long flags;
11345fae8b86SMika Westerberg 	u32 old_val;
11355fae8b86SMika Westerberg 
113686e3ef81SCristina Ciocan 	if (!reg)
113786e3ef81SCristina Ciocan 		return;
113886e3ef81SCristina Ciocan 
113978e1c896SMika Westerberg 	raw_spin_lock_irqsave(&vg->lock, flags);
11405fae8b86SMika Westerberg 	old_val = readl(reg);
11415fae8b86SMika Westerberg 	if (value)
11425fae8b86SMika Westerberg 		writel(old_val | BYT_LEVEL, reg);
11435fae8b86SMika Westerberg 	else
11445fae8b86SMika Westerberg 		writel(old_val & ~BYT_LEVEL, reg);
114578e1c896SMika Westerberg 	raw_spin_unlock_irqrestore(&vg->lock, flags);
11465fae8b86SMika Westerberg }
11475fae8b86SMika Westerberg 
114886e3ef81SCristina Ciocan static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
11495fae8b86SMika Westerberg {
1150bf9a5c96SLinus Walleij 	struct byt_gpio *vg = gpiochip_get_data(chip);
1151c501d0b1SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
11525fae8b86SMika Westerberg 	unsigned long flags;
11535fae8b86SMika Westerberg 	u32 value;
11545fae8b86SMika Westerberg 
115586e3ef81SCristina Ciocan 	if (!reg)
115686e3ef81SCristina Ciocan 		return -EINVAL;
115786e3ef81SCristina Ciocan 
115878e1c896SMika Westerberg 	raw_spin_lock_irqsave(&vg->lock, flags);
115986e3ef81SCristina Ciocan 	value = readl(reg);
116078e1c896SMika Westerberg 	raw_spin_unlock_irqrestore(&vg->lock, flags);
11615fae8b86SMika Westerberg 
116286e3ef81SCristina Ciocan 	if (!(value & BYT_OUTPUT_EN))
11631c5fb66aSLinus Walleij 		return 0;
116486e3ef81SCristina Ciocan 	if (!(value & BYT_INPUT_EN))
11651c5fb66aSLinus Walleij 		return 1;
116686e3ef81SCristina Ciocan 
116786e3ef81SCristina Ciocan 	return -EINVAL;
11685fae8b86SMika Westerberg }
11695fae8b86SMika Westerberg 
117086e3ef81SCristina Ciocan static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
11715fae8b86SMika Westerberg {
117286e3ef81SCristina Ciocan 	return pinctrl_gpio_direction_input(chip->base + offset);
117386e3ef81SCristina Ciocan }
11745fae8b86SMika Westerberg 
117586e3ef81SCristina Ciocan static int byt_gpio_direction_output(struct gpio_chip *chip,
117686e3ef81SCristina Ciocan 				     unsigned int offset, int value)
117786e3ef81SCristina Ciocan {
117886e3ef81SCristina Ciocan 	int ret = pinctrl_gpio_direction_output(chip->base + offset);
11795fae8b86SMika Westerberg 
118086e3ef81SCristina Ciocan 	if (ret)
118186e3ef81SCristina Ciocan 		return ret;
118286e3ef81SCristina Ciocan 
118386e3ef81SCristina Ciocan 	byt_gpio_set(chip, offset, value);
11845fae8b86SMika Westerberg 
11855fae8b86SMika Westerberg 	return 0;
11865fae8b86SMika Westerberg }
11875fae8b86SMika Westerberg 
11885fae8b86SMika Westerberg static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
11895fae8b86SMika Westerberg {
1190bf9a5c96SLinus Walleij 	struct byt_gpio *vg = gpiochip_get_data(chip);
11915fae8b86SMika Westerberg 	int i;
119286e3ef81SCristina Ciocan 	u32 conf0, val;
11935fae8b86SMika Westerberg 
119486e3ef81SCristina Ciocan 	for (i = 0; i < vg->soc_data->npins; i++) {
119534e65670SAndy Shevchenko 		const struct intel_community *comm;
11965fae8b86SMika Westerberg 		const char *pull_str = NULL;
11975fae8b86SMika Westerberg 		const char *pull = NULL;
119886e3ef81SCristina Ciocan 		void __iomem *reg;
119978e1c896SMika Westerberg 		unsigned long flags;
12005fae8b86SMika Westerberg 		const char *label;
120186e3ef81SCristina Ciocan 		unsigned int pin;
120278e1c896SMika Westerberg 
120378e1c896SMika Westerberg 		raw_spin_lock_irqsave(&vg->lock, flags);
120486e3ef81SCristina Ciocan 		pin = vg->soc_data->pins[i].number;
120586e3ef81SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
120686e3ef81SCristina Ciocan 		if (!reg) {
120786e3ef81SCristina Ciocan 			seq_printf(s,
120886e3ef81SCristina Ciocan 				   "Could not retrieve pin %i conf0 reg\n",
120986e3ef81SCristina Ciocan 				   pin);
121022bbd21bSDan Carpenter 			raw_spin_unlock_irqrestore(&vg->lock, flags);
121186e3ef81SCristina Ciocan 			continue;
121286e3ef81SCristina Ciocan 		}
121386e3ef81SCristina Ciocan 		conf0 = readl(reg);
121486e3ef81SCristina Ciocan 
121586e3ef81SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
121686e3ef81SCristina Ciocan 		if (!reg) {
121786e3ef81SCristina Ciocan 			seq_printf(s,
121886e3ef81SCristina Ciocan 				   "Could not retrieve pin %i val reg\n", pin);
121922bbd21bSDan Carpenter 			raw_spin_unlock_irqrestore(&vg->lock, flags);
122022bbd21bSDan Carpenter 			continue;
122186e3ef81SCristina Ciocan 		}
122286e3ef81SCristina Ciocan 		val = readl(reg);
122378e1c896SMika Westerberg 		raw_spin_unlock_irqrestore(&vg->lock, flags);
12245fae8b86SMika Westerberg 
122586e3ef81SCristina Ciocan 		comm = byt_get_community(vg, pin);
122686e3ef81SCristina Ciocan 		if (!comm) {
122786e3ef81SCristina Ciocan 			seq_printf(s,
122886e3ef81SCristina Ciocan 				   "Could not get community for pin %i\n", pin);
122986e3ef81SCristina Ciocan 			continue;
123086e3ef81SCristina Ciocan 		}
12315fae8b86SMika Westerberg 		label = gpiochip_is_requested(chip, i);
12325fae8b86SMika Westerberg 		if (!label)
12335fae8b86SMika Westerberg 			label = "Unrequested";
12345fae8b86SMika Westerberg 
12355fae8b86SMika Westerberg 		switch (conf0 & BYT_PULL_ASSIGN_MASK) {
12365fae8b86SMika Westerberg 		case BYT_PULL_ASSIGN_UP:
12375fae8b86SMika Westerberg 			pull = "up";
12385fae8b86SMika Westerberg 			break;
12395fae8b86SMika Westerberg 		case BYT_PULL_ASSIGN_DOWN:
12405fae8b86SMika Westerberg 			pull = "down";
12415fae8b86SMika Westerberg 			break;
12425fae8b86SMika Westerberg 		}
12435fae8b86SMika Westerberg 
12445fae8b86SMika Westerberg 		switch (conf0 & BYT_PULL_STR_MASK) {
12455fae8b86SMika Westerberg 		case BYT_PULL_STR_2K:
12465fae8b86SMika Westerberg 			pull_str = "2k";
12475fae8b86SMika Westerberg 			break;
12485fae8b86SMika Westerberg 		case BYT_PULL_STR_10K:
12495fae8b86SMika Westerberg 			pull_str = "10k";
12505fae8b86SMika Westerberg 			break;
12515fae8b86SMika Westerberg 		case BYT_PULL_STR_20K:
12525fae8b86SMika Westerberg 			pull_str = "20k";
12535fae8b86SMika Westerberg 			break;
12545fae8b86SMika Westerberg 		case BYT_PULL_STR_40K:
12555fae8b86SMika Westerberg 			pull_str = "40k";
12565fae8b86SMika Westerberg 			break;
12575fae8b86SMika Westerberg 		}
12585fae8b86SMika Westerberg 
12595fae8b86SMika Westerberg 		seq_printf(s,
12605fae8b86SMika Westerberg 			   " gpio-%-3d (%-20.20s) %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s",
126186e3ef81SCristina Ciocan 			   pin,
12625fae8b86SMika Westerberg 			   label,
12635fae8b86SMika Westerberg 			   val & BYT_INPUT_EN ? "  " : "in",
12645fae8b86SMika Westerberg 			   val & BYT_OUTPUT_EN ? "   " : "out",
12655fae8b86SMika Westerberg 			   val & BYT_LEVEL ? "hi" : "lo",
12663655a1caSAlexander Stein 			   comm->pad_map[i], comm->pad_map[i] * 16,
12675fae8b86SMika Westerberg 			   conf0 & 0x7,
12685fae8b86SMika Westerberg 			   conf0 & BYT_TRIG_NEG ? " fall" : "     ",
12695fae8b86SMika Westerberg 			   conf0 & BYT_TRIG_POS ? " rise" : "     ",
12705fae8b86SMika Westerberg 			   conf0 & BYT_TRIG_LVL ? " level" : "      ");
12715fae8b86SMika Westerberg 
12725fae8b86SMika Westerberg 		if (pull && pull_str)
12735fae8b86SMika Westerberg 			seq_printf(s, " %-4s %-3s", pull, pull_str);
12745fae8b86SMika Westerberg 		else
12755fae8b86SMika Westerberg 			seq_puts(s, "          ");
12765fae8b86SMika Westerberg 
12775fae8b86SMika Westerberg 		if (conf0 & BYT_IODEN)
12785fae8b86SMika Westerberg 			seq_puts(s, " open-drain");
12795fae8b86SMika Westerberg 
12805fae8b86SMika Westerberg 		seq_puts(s, "\n");
12815fae8b86SMika Westerberg 	}
12825fae8b86SMika Westerberg }
12835fae8b86SMika Westerberg 
128486e3ef81SCristina Ciocan static const struct gpio_chip byt_gpio_chip = {
128586e3ef81SCristina Ciocan 	.owner			= THIS_MODULE,
128686e3ef81SCristina Ciocan 	.request		= gpiochip_generic_request,
128786e3ef81SCristina Ciocan 	.free			= gpiochip_generic_free,
128886e3ef81SCristina Ciocan 	.get_direction		= byt_gpio_get_direction,
128986e3ef81SCristina Ciocan 	.direction_input	= byt_gpio_direction_input,
129086e3ef81SCristina Ciocan 	.direction_output	= byt_gpio_direction_output,
129186e3ef81SCristina Ciocan 	.get			= byt_gpio_get,
129286e3ef81SCristina Ciocan 	.set			= byt_gpio_set,
129386e3ef81SCristina Ciocan 	.dbg_show		= byt_gpio_dbg_show,
129486e3ef81SCristina Ciocan };
129586e3ef81SCristina Ciocan 
129631e4329fSMika Westerberg static void byt_irq_ack(struct irq_data *d)
129731e4329fSMika Westerberg {
129831e4329fSMika Westerberg 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
1299bf9a5c96SLinus Walleij 	struct byt_gpio *vg = gpiochip_get_data(gc);
1300939330d7SAndy Shevchenko 	unsigned int offset = irqd_to_hwirq(d);
130131e4329fSMika Westerberg 	void __iomem *reg;
130231e4329fSMika Westerberg 
1303c501d0b1SCristina Ciocan 	reg = byt_gpio_reg(vg, offset, BYT_INT_STAT_REG);
13049f573b98SCristina Ciocan 	if (!reg)
13059f573b98SCristina Ciocan 		return;
13069f573b98SCristina Ciocan 
13079f573b98SCristina Ciocan 	raw_spin_lock(&vg->lock);
130831e4329fSMika Westerberg 	writel(BIT(offset % 32), reg);
130978e1c896SMika Westerberg 	raw_spin_unlock(&vg->lock);
131031e4329fSMika Westerberg }
131131e4329fSMika Westerberg 
13129f573b98SCristina Ciocan static void byt_irq_mask(struct irq_data *d)
13139f573b98SCristina Ciocan {
13149f573b98SCristina Ciocan 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
13159f573b98SCristina Ciocan 	struct byt_gpio *vg = gpiochip_get_data(gc);
13169f573b98SCristina Ciocan 
13179f573b98SCristina Ciocan 	byt_gpio_clear_triggering(vg, irqd_to_hwirq(d));
13189f573b98SCristina Ciocan }
13199f573b98SCristina Ciocan 
13205fae8b86SMika Westerberg static void byt_irq_unmask(struct irq_data *d)
13215fae8b86SMika Westerberg {
132231e4329fSMika Westerberg 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
1323bf9a5c96SLinus Walleij 	struct byt_gpio *vg = gpiochip_get_data(gc);
1324939330d7SAndy Shevchenko 	unsigned int offset = irqd_to_hwirq(d);
132531e4329fSMika Westerberg 	unsigned long flags;
132631e4329fSMika Westerberg 	void __iomem *reg;
132731e4329fSMika Westerberg 	u32 value;
132831e4329fSMika Westerberg 
1329c501d0b1SCristina Ciocan 	reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
13309f573b98SCristina Ciocan 	if (!reg)
13319f573b98SCristina Ciocan 		return;
133278e1c896SMika Westerberg 
133378e1c896SMika Westerberg 	raw_spin_lock_irqsave(&vg->lock, flags);
133431e4329fSMika Westerberg 	value = readl(reg);
133531e4329fSMika Westerberg 
133631e4329fSMika Westerberg 	switch (irqd_get_trigger_type(d)) {
133731e4329fSMika Westerberg 	case IRQ_TYPE_LEVEL_HIGH:
133831e4329fSMika Westerberg 		value |= BYT_TRIG_LVL;
1339399476bdSGustavo A. R. Silva 		/* fall through */
134031e4329fSMika Westerberg 	case IRQ_TYPE_EDGE_RISING:
134131e4329fSMika Westerberg 		value |= BYT_TRIG_POS;
134231e4329fSMika Westerberg 		break;
134331e4329fSMika Westerberg 	case IRQ_TYPE_LEVEL_LOW:
134431e4329fSMika Westerberg 		value |= BYT_TRIG_LVL;
1345399476bdSGustavo A. R. Silva 		/* fall through */
134631e4329fSMika Westerberg 	case IRQ_TYPE_EDGE_FALLING:
134731e4329fSMika Westerberg 		value |= BYT_TRIG_NEG;
134831e4329fSMika Westerberg 		break;
134931e4329fSMika Westerberg 	case IRQ_TYPE_EDGE_BOTH:
135031e4329fSMika Westerberg 		value |= (BYT_TRIG_NEG | BYT_TRIG_POS);
135131e4329fSMika Westerberg 		break;
135231e4329fSMika Westerberg 	}
135331e4329fSMika Westerberg 
135431e4329fSMika Westerberg 	writel(value, reg);
135531e4329fSMika Westerberg 
135678e1c896SMika Westerberg 	raw_spin_unlock_irqrestore(&vg->lock, flags);
13575fae8b86SMika Westerberg }
13585fae8b86SMika Westerberg 
13599f573b98SCristina Ciocan static int byt_irq_type(struct irq_data *d, unsigned int type)
13605fae8b86SMika Westerberg {
13619f573b98SCristina Ciocan 	struct byt_gpio *vg = gpiochip_get_data(irq_data_get_irq_chip_data(d));
13629f573b98SCristina Ciocan 	u32 offset = irqd_to_hwirq(d);
13639f573b98SCristina Ciocan 	u32 value;
13649f573b98SCristina Ciocan 	unsigned long flags;
13659f573b98SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
136631e4329fSMika Westerberg 
13679f573b98SCristina Ciocan 	if (!reg || offset >= vg->chip.ngpio)
13689f573b98SCristina Ciocan 		return -EINVAL;
13699f573b98SCristina Ciocan 
13709f573b98SCristina Ciocan 	raw_spin_lock_irqsave(&vg->lock, flags);
13719f573b98SCristina Ciocan 	value = readl(reg);
13729f573b98SCristina Ciocan 
13739f573b98SCristina Ciocan 	WARN(value & BYT_DIRECT_IRQ_EN,
13749f573b98SCristina Ciocan 	     "Bad pad config for io mode, force direct_irq_en bit clearing");
13759f573b98SCristina Ciocan 
13769f573b98SCristina Ciocan 	/* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits
13779f573b98SCristina Ciocan 	 * are used to indicate high and low level triggering
13789f573b98SCristina Ciocan 	 */
13799f573b98SCristina Ciocan 	value &= ~(BYT_DIRECT_IRQ_EN | BYT_TRIG_POS | BYT_TRIG_NEG |
13809f573b98SCristina Ciocan 		   BYT_TRIG_LVL);
13819291c65bSHans de Goede 	/* Enable glitch filtering */
13829291c65bSHans de Goede 	value |= BYT_GLITCH_FILTER_EN | BYT_GLITCH_F_SLOW_CLK |
13839291c65bSHans de Goede 		 BYT_GLITCH_F_FAST_CLK;
13849f573b98SCristina Ciocan 
13859f573b98SCristina Ciocan 	writel(value, reg);
13869f573b98SCristina Ciocan 
13879f573b98SCristina Ciocan 	if (type & IRQ_TYPE_EDGE_BOTH)
13889f573b98SCristina Ciocan 		irq_set_handler_locked(d, handle_edge_irq);
13899f573b98SCristina Ciocan 	else if (type & IRQ_TYPE_LEVEL_MASK)
13909f573b98SCristina Ciocan 		irq_set_handler_locked(d, handle_level_irq);
13919f573b98SCristina Ciocan 
13929f573b98SCristina Ciocan 	raw_spin_unlock_irqrestore(&vg->lock, flags);
13939f573b98SCristina Ciocan 
13949f573b98SCristina Ciocan 	return 0;
13955fae8b86SMika Westerberg }
13965fae8b86SMika Westerberg 
13975fae8b86SMika Westerberg static struct irq_chip byt_irqchip = {
13985fae8b86SMika Westerberg 	.name		= "BYT-GPIO",
139931e4329fSMika Westerberg 	.irq_ack	= byt_irq_ack,
14005fae8b86SMika Westerberg 	.irq_mask	= byt_irq_mask,
14015fae8b86SMika Westerberg 	.irq_unmask	= byt_irq_unmask,
14025fae8b86SMika Westerberg 	.irq_set_type	= byt_irq_type,
14035fae8b86SMika Westerberg 	.flags		= IRQCHIP_SKIP_SET_WAKE,
14045fae8b86SMika Westerberg };
14055fae8b86SMika Westerberg 
140671e6ca61SCristina Ciocan static void byt_gpio_irq_handler(struct irq_desc *desc)
140771e6ca61SCristina Ciocan {
140871e6ca61SCristina Ciocan 	struct irq_data *data = irq_desc_get_irq_data(desc);
140971e6ca61SCristina Ciocan 	struct byt_gpio *vg = gpiochip_get_data(
141071e6ca61SCristina Ciocan 				irq_desc_get_handler_data(desc));
141171e6ca61SCristina Ciocan 	struct irq_chip *chip = irq_data_get_irq_chip(data);
141271e6ca61SCristina Ciocan 	u32 base, pin;
141371e6ca61SCristina Ciocan 	void __iomem *reg;
141471e6ca61SCristina Ciocan 	unsigned long pending;
141571e6ca61SCristina Ciocan 	unsigned int virq;
141671e6ca61SCristina Ciocan 
141771e6ca61SCristina Ciocan 	/* check from GPIO controller which pin triggered the interrupt */
141871e6ca61SCristina Ciocan 	for (base = 0; base < vg->chip.ngpio; base += 32) {
141971e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG);
142071e6ca61SCristina Ciocan 
142171e6ca61SCristina Ciocan 		if (!reg) {
142271e6ca61SCristina Ciocan 			dev_warn(&vg->pdev->dev,
142371e6ca61SCristina Ciocan 				 "Pin %i: could not retrieve interrupt status register\n",
142471e6ca61SCristina Ciocan 				 base);
142571e6ca61SCristina Ciocan 			continue;
142671e6ca61SCristina Ciocan 		}
142771e6ca61SCristina Ciocan 
1428cdca06e4SAlexander Stein 		raw_spin_lock(&vg->lock);
142971e6ca61SCristina Ciocan 		pending = readl(reg);
1430cdca06e4SAlexander Stein 		raw_spin_unlock(&vg->lock);
143171e6ca61SCristina Ciocan 		for_each_set_bit(pin, &pending, 32) {
1432f0fbe7bcSThierry Reding 			virq = irq_find_mapping(vg->chip.irq.domain, base + pin);
143371e6ca61SCristina Ciocan 			generic_handle_irq(virq);
143471e6ca61SCristina Ciocan 		}
143571e6ca61SCristina Ciocan 	}
143671e6ca61SCristina Ciocan 	chip->irq_eoi(data);
143771e6ca61SCristina Ciocan }
143871e6ca61SCristina Ciocan 
14395fae8b86SMika Westerberg static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
14405fae8b86SMika Westerberg {
144149c03096SAndy Shevchenko 	struct gpio_chip *gc = &vg->chip;
144249c03096SAndy Shevchenko 	struct device *dev = &vg->pdev->dev;
14435fae8b86SMika Westerberg 	void __iomem *reg;
14445fae8b86SMika Westerberg 	u32 base, value;
144595f0972cSMika Westerberg 	int i;
144695f0972cSMika Westerberg 
144795f0972cSMika Westerberg 	/*
144895f0972cSMika Westerberg 	 * Clear interrupt triggers for all pins that are GPIOs and
144995f0972cSMika Westerberg 	 * do not use direct IRQ mode. This will prevent spurious
145095f0972cSMika Westerberg 	 * interrupts from misconfigured pins.
145195f0972cSMika Westerberg 	 */
145271e6ca61SCristina Ciocan 	for (i = 0; i < vg->soc_data->npins; i++) {
145371e6ca61SCristina Ciocan 		unsigned int pin = vg->soc_data->pins[i].number;
145471e6ca61SCristina Ciocan 
145571e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
145671e6ca61SCristina Ciocan 		if (!reg) {
145771e6ca61SCristina Ciocan 			dev_warn(&vg->pdev->dev,
145871e6ca61SCristina Ciocan 				 "Pin %i: could not retrieve conf0 register\n",
145971e6ca61SCristina Ciocan 				 i);
146071e6ca61SCristina Ciocan 			continue;
146171e6ca61SCristina Ciocan 		}
146271e6ca61SCristina Ciocan 
146371e6ca61SCristina Ciocan 		value = readl(reg);
146449c03096SAndy Shevchenko 		if (value & BYT_DIRECT_IRQ_EN) {
1465dc7b0387SThierry Reding 			clear_bit(i, gc->irq.valid_mask);
146649c03096SAndy Shevchenko 			dev_dbg(dev, "excluding GPIO %d from IRQ domain\n", i);
146749c03096SAndy Shevchenko 		} else if ((value & BYT_PIN_MUX) == byt_get_gpio_mux(vg, i)) {
146895f0972cSMika Westerberg 			byt_gpio_clear_triggering(vg, i);
146949c03096SAndy Shevchenko 			dev_dbg(dev, "disabling GPIO %d\n", i);
147095f0972cSMika Westerberg 		}
147195f0972cSMika Westerberg 	}
14725fae8b86SMika Westerberg 
14735fae8b86SMika Westerberg 	/* clear interrupt status trigger registers */
147471e6ca61SCristina Ciocan 	for (base = 0; base < vg->soc_data->npins; base += 32) {
1475c501d0b1SCristina Ciocan 		reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG);
147671e6ca61SCristina Ciocan 
147771e6ca61SCristina Ciocan 		if (!reg) {
147871e6ca61SCristina Ciocan 			dev_warn(&vg->pdev->dev,
147971e6ca61SCristina Ciocan 				 "Pin %i: could not retrieve irq status reg\n",
148071e6ca61SCristina Ciocan 				 base);
148171e6ca61SCristina Ciocan 			continue;
148271e6ca61SCristina Ciocan 		}
148371e6ca61SCristina Ciocan 
14845fae8b86SMika Westerberg 		writel(0xffffffff, reg);
14855fae8b86SMika Westerberg 		/* make sure trigger bits are cleared, if not then a pin
14865fae8b86SMika Westerberg 		   might be misconfigured in bios */
14875fae8b86SMika Westerberg 		value = readl(reg);
14885fae8b86SMika Westerberg 		if (value)
14895fae8b86SMika Westerberg 			dev_err(&vg->pdev->dev,
1490973232e2SAlexander Stein 				"GPIO interrupt error, pins misconfigured. INT_STAT%u: 0x%08x\n",
1491973232e2SAlexander Stein 				base / 32, value);
14925fae8b86SMika Westerberg 	}
14935fae8b86SMika Westerberg }
14945fae8b86SMika Westerberg 
149571e6ca61SCristina Ciocan static int byt_gpio_probe(struct byt_gpio *vg)
14965fae8b86SMika Westerberg {
14975fae8b86SMika Westerberg 	struct gpio_chip *gc;
149871e6ca61SCristina Ciocan 	struct resource *irq_rc;
14995fae8b86SMika Westerberg 	int ret;
15005fae8b86SMika Westerberg 
150171e6ca61SCristina Ciocan 	/* Set up gpio chip */
150271e6ca61SCristina Ciocan 	vg->chip	= byt_gpio_chip;
15035fae8b86SMika Westerberg 	gc		= &vg->chip;
150471e6ca61SCristina Ciocan 	gc->label	= dev_name(&vg->pdev->dev);
15055fae8b86SMika Westerberg 	gc->base	= -1;
15065fae8b86SMika Westerberg 	gc->can_sleep	= false;
150771e6ca61SCristina Ciocan 	gc->parent	= &vg->pdev->dev;
150871e6ca61SCristina Ciocan 	gc->ngpio	= vg->soc_data->npins;
1509dc7b0387SThierry Reding 	gc->irq.need_valid_mask	= true;
15105fae8b86SMika Westerberg 
1511fcc18debSMika Westerberg #ifdef CONFIG_PM_SLEEP
151271e6ca61SCristina Ciocan 	vg->saved_context = devm_kcalloc(&vg->pdev->dev, gc->ngpio,
1513fcc18debSMika Westerberg 				       sizeof(*vg->saved_context), GFP_KERNEL);
1514d6cb7722SAditya Pakki 	if (!vg->saved_context)
1515d6cb7722SAditya Pakki 		return -ENOMEM;
1516fcc18debSMika Westerberg #endif
15170612413fSAndy Shevchenko 	ret = devm_gpiochip_add_data(&vg->pdev->dev, gc, vg);
15185fae8b86SMika Westerberg 	if (ret) {
151971e6ca61SCristina Ciocan 		dev_err(&vg->pdev->dev, "failed adding byt-gpio chip\n");
15205fae8b86SMika Westerberg 		return ret;
15215fae8b86SMika Westerberg 	}
15225fae8b86SMika Westerberg 
152371e6ca61SCristina Ciocan 	ret = gpiochip_add_pin_range(&vg->chip, dev_name(&vg->pdev->dev),
152471e6ca61SCristina Ciocan 				     0, 0, vg->soc_data->npins);
152571e6ca61SCristina Ciocan 	if (ret) {
152671e6ca61SCristina Ciocan 		dev_err(&vg->pdev->dev, "failed to add GPIO pin range\n");
15270612413fSAndy Shevchenko 		return ret;
152871e6ca61SCristina Ciocan 	}
152971e6ca61SCristina Ciocan 
15305fae8b86SMika Westerberg 	/* set up interrupts  */
153171e6ca61SCristina Ciocan 	irq_rc = platform_get_resource(vg->pdev, IORESOURCE_IRQ, 0);
15325fae8b86SMika Westerberg 	if (irq_rc && irq_rc->start) {
15335fae8b86SMika Westerberg 		byt_gpio_irq_init_hw(vg);
15345fae8b86SMika Westerberg 		ret = gpiochip_irqchip_add(gc, &byt_irqchip, 0,
15353ae02c14SAndy Shevchenko 					   handle_bad_irq, IRQ_TYPE_NONE);
15365fae8b86SMika Westerberg 		if (ret) {
153771e6ca61SCristina Ciocan 			dev_err(&vg->pdev->dev, "failed to add irqchip\n");
15380612413fSAndy Shevchenko 			return ret;
15395fae8b86SMika Westerberg 		}
15405fae8b86SMika Westerberg 
15415fae8b86SMika Westerberg 		gpiochip_set_chained_irqchip(gc, &byt_irqchip,
15425fae8b86SMika Westerberg 					     (unsigned)irq_rc->start,
15435fae8b86SMika Westerberg 					     byt_gpio_irq_handler);
15445fae8b86SMika Westerberg 	}
15455fae8b86SMika Westerberg 
154671e6ca61SCristina Ciocan 	return ret;
154771e6ca61SCristina Ciocan }
154871e6ca61SCristina Ciocan 
154971e6ca61SCristina Ciocan static int byt_set_soc_data(struct byt_gpio *vg,
155034e65670SAndy Shevchenko 			    const struct intel_pinctrl_soc_data *soc_data)
155171e6ca61SCristina Ciocan {
155271e6ca61SCristina Ciocan 	int i;
155371e6ca61SCristina Ciocan 
155471e6ca61SCristina Ciocan 	vg->soc_data = soc_data;
155571e6ca61SCristina Ciocan 	vg->communities_copy = devm_kcalloc(&vg->pdev->dev,
155671e6ca61SCristina Ciocan 					    soc_data->ncommunities,
155771e6ca61SCristina Ciocan 					    sizeof(*vg->communities_copy),
155871e6ca61SCristina Ciocan 					    GFP_KERNEL);
155971e6ca61SCristina Ciocan 	if (!vg->communities_copy)
156071e6ca61SCristina Ciocan 		return -ENOMEM;
156171e6ca61SCristina Ciocan 
156271e6ca61SCristina Ciocan 	for (i = 0; i < soc_data->ncommunities; i++) {
156334e65670SAndy Shevchenko 		struct intel_community *comm = vg->communities_copy + i;
156471e6ca61SCristina Ciocan 
156571e6ca61SCristina Ciocan 		*comm = vg->soc_data->communities[i];
156671e6ca61SCristina Ciocan 
156734e65670SAndy Shevchenko 		comm->pad_regs = devm_platform_ioremap_resource(vg->pdev, 0);
156834e65670SAndy Shevchenko 		if (IS_ERR(comm->pad_regs))
156934e65670SAndy Shevchenko 			return PTR_ERR(comm->pad_regs);
157071e6ca61SCristina Ciocan 	}
157171e6ca61SCristina Ciocan 
157271e6ca61SCristina Ciocan 	return 0;
157371e6ca61SCristina Ciocan }
157471e6ca61SCristina Ciocan 
157571e6ca61SCristina Ciocan static const struct acpi_device_id byt_gpio_acpi_match[] = {
157671e6ca61SCristina Ciocan 	{ "INT33B2", (kernel_ulong_t)byt_soc_data },
157771e6ca61SCristina Ciocan 	{ "INT33FC", (kernel_ulong_t)byt_soc_data },
157871e6ca61SCristina Ciocan 	{ }
157971e6ca61SCristina Ciocan };
158071e6ca61SCristina Ciocan 
158171e6ca61SCristina Ciocan static int byt_pinctrl_probe(struct platform_device *pdev)
158271e6ca61SCristina Ciocan {
158334e65670SAndy Shevchenko 	const struct intel_pinctrl_soc_data *soc_data = NULL;
158434e65670SAndy Shevchenko 	const struct intel_pinctrl_soc_data **soc_table;
158571e6ca61SCristina Ciocan 	struct acpi_device *acpi_dev;
158671e6ca61SCristina Ciocan 	struct byt_gpio *vg;
158771e6ca61SCristina Ciocan 	int i, ret;
158871e6ca61SCristina Ciocan 
158971e6ca61SCristina Ciocan 	acpi_dev = ACPI_COMPANION(&pdev->dev);
159071e6ca61SCristina Ciocan 	if (!acpi_dev)
159171e6ca61SCristina Ciocan 		return -ENODEV;
159271e6ca61SCristina Ciocan 
159334e65670SAndy Shevchenko 	soc_table = (const struct intel_pinctrl_soc_data **)device_get_match_data(&pdev->dev);
159471e6ca61SCristina Ciocan 
159571e6ca61SCristina Ciocan 	for (i = 0; soc_table[i]; i++) {
159671e6ca61SCristina Ciocan 		if (!strcmp(acpi_dev->pnp.unique_id, soc_table[i]->uid)) {
159771e6ca61SCristina Ciocan 			soc_data = soc_table[i];
159871e6ca61SCristina Ciocan 			break;
159971e6ca61SCristina Ciocan 		}
160071e6ca61SCristina Ciocan 	}
160171e6ca61SCristina Ciocan 
160271e6ca61SCristina Ciocan 	if (!soc_data)
160371e6ca61SCristina Ciocan 		return -ENODEV;
160471e6ca61SCristina Ciocan 
160571e6ca61SCristina Ciocan 	vg = devm_kzalloc(&pdev->dev, sizeof(*vg), GFP_KERNEL);
160671e6ca61SCristina Ciocan 	if (!vg)
160771e6ca61SCristina Ciocan 		return -ENOMEM;
160871e6ca61SCristina Ciocan 
160971e6ca61SCristina Ciocan 	vg->pdev = pdev;
161071e6ca61SCristina Ciocan 	ret = byt_set_soc_data(vg, soc_data);
161171e6ca61SCristina Ciocan 	if (ret) {
161271e6ca61SCristina Ciocan 		dev_err(&pdev->dev, "failed to set soc data\n");
161371e6ca61SCristina Ciocan 		return ret;
161471e6ca61SCristina Ciocan 	}
161571e6ca61SCristina Ciocan 
161671e6ca61SCristina Ciocan 	vg->pctl_desc		= byt_pinctrl_desc;
161771e6ca61SCristina Ciocan 	vg->pctl_desc.name	= dev_name(&pdev->dev);
161871e6ca61SCristina Ciocan 	vg->pctl_desc.pins	= vg->soc_data->pins;
161971e6ca61SCristina Ciocan 	vg->pctl_desc.npins	= vg->soc_data->npins;
162071e6ca61SCristina Ciocan 
16210612413fSAndy Shevchenko 	vg->pctl_dev = devm_pinctrl_register(&pdev->dev, &vg->pctl_desc, vg);
162271e6ca61SCristina Ciocan 	if (IS_ERR(vg->pctl_dev)) {
162371e6ca61SCristina Ciocan 		dev_err(&pdev->dev, "failed to register pinctrl driver\n");
162471e6ca61SCristina Ciocan 		return PTR_ERR(vg->pctl_dev);
162571e6ca61SCristina Ciocan 	}
162671e6ca61SCristina Ciocan 
1627a171bc51SVille Syrjälä 	raw_spin_lock_init(&vg->lock);
1628a171bc51SVille Syrjälä 
162971e6ca61SCristina Ciocan 	ret = byt_gpio_probe(vg);
16300612413fSAndy Shevchenko 	if (ret)
163171e6ca61SCristina Ciocan 		return ret;
163271e6ca61SCristina Ciocan 
163371e6ca61SCristina Ciocan 	platform_set_drvdata(pdev, vg);
163471e6ca61SCristina Ciocan 	pm_runtime_enable(&pdev->dev);
163571e6ca61SCristina Ciocan 
163671e6ca61SCristina Ciocan 	return 0;
163771e6ca61SCristina Ciocan }
163871e6ca61SCristina Ciocan 
1639fcc18debSMika Westerberg #ifdef CONFIG_PM_SLEEP
1640fcc18debSMika Westerberg static int byt_gpio_suspend(struct device *dev)
1641fcc18debSMika Westerberg {
1642d481de47SWolfram Sang 	struct byt_gpio *vg = dev_get_drvdata(dev);
1643fcc18debSMika Westerberg 	int i;
1644fcc18debSMika Westerberg 
164571e6ca61SCristina Ciocan 	for (i = 0; i < vg->soc_data->npins; i++) {
1646fcc18debSMika Westerberg 		void __iomem *reg;
1647fcc18debSMika Westerberg 		u32 value;
164871e6ca61SCristina Ciocan 		unsigned int pin = vg->soc_data->pins[i].number;
1649fcc18debSMika Westerberg 
165071e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
165171e6ca61SCristina Ciocan 		if (!reg) {
165271e6ca61SCristina Ciocan 			dev_warn(&vg->pdev->dev,
165371e6ca61SCristina Ciocan 				 "Pin %i: could not retrieve conf0 register\n",
165471e6ca61SCristina Ciocan 				 i);
165571e6ca61SCristina Ciocan 			continue;
165671e6ca61SCristina Ciocan 		}
1657fcc18debSMika Westerberg 		value = readl(reg) & BYT_CONF0_RESTORE_MASK;
1658fcc18debSMika Westerberg 		vg->saved_context[i].conf0 = value;
1659fcc18debSMika Westerberg 
166071e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
1661fcc18debSMika Westerberg 		value = readl(reg) & BYT_VAL_RESTORE_MASK;
1662fcc18debSMika Westerberg 		vg->saved_context[i].val = value;
1663fcc18debSMika Westerberg 	}
1664fcc18debSMika Westerberg 
1665fcc18debSMika Westerberg 	return 0;
1666fcc18debSMika Westerberg }
1667fcc18debSMika Westerberg 
1668fcc18debSMika Westerberg static int byt_gpio_resume(struct device *dev)
1669fcc18debSMika Westerberg {
1670d481de47SWolfram Sang 	struct byt_gpio *vg = dev_get_drvdata(dev);
1671fcc18debSMika Westerberg 	int i;
1672fcc18debSMika Westerberg 
167371e6ca61SCristina Ciocan 	for (i = 0; i < vg->soc_data->npins; i++) {
1674fcc18debSMika Westerberg 		void __iomem *reg;
1675fcc18debSMika Westerberg 		u32 value;
167671e6ca61SCristina Ciocan 		unsigned int pin = vg->soc_data->pins[i].number;
1677fcc18debSMika Westerberg 
167871e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
167971e6ca61SCristina Ciocan 		if (!reg) {
168071e6ca61SCristina Ciocan 			dev_warn(&vg->pdev->dev,
168171e6ca61SCristina Ciocan 				 "Pin %i: could not retrieve conf0 register\n",
168271e6ca61SCristina Ciocan 				 i);
168371e6ca61SCristina Ciocan 			continue;
168471e6ca61SCristina Ciocan 		}
1685fcc18debSMika Westerberg 		value = readl(reg);
1686fcc18debSMika Westerberg 		if ((value & BYT_CONF0_RESTORE_MASK) !=
1687fcc18debSMika Westerberg 		     vg->saved_context[i].conf0) {
1688fcc18debSMika Westerberg 			value &= ~BYT_CONF0_RESTORE_MASK;
1689fcc18debSMika Westerberg 			value |= vg->saved_context[i].conf0;
1690fcc18debSMika Westerberg 			writel(value, reg);
1691fcc18debSMika Westerberg 			dev_info(dev, "restored pin %d conf0 %#08x", i, value);
1692fcc18debSMika Westerberg 		}
1693fcc18debSMika Westerberg 
169471e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
1695fcc18debSMika Westerberg 		value = readl(reg);
1696fcc18debSMika Westerberg 		if ((value & BYT_VAL_RESTORE_MASK) !=
1697fcc18debSMika Westerberg 		     vg->saved_context[i].val) {
1698fcc18debSMika Westerberg 			u32 v;
1699fcc18debSMika Westerberg 
1700fcc18debSMika Westerberg 			v = value & ~BYT_VAL_RESTORE_MASK;
1701fcc18debSMika Westerberg 			v |= vg->saved_context[i].val;
1702fcc18debSMika Westerberg 			if (v != value) {
1703fcc18debSMika Westerberg 				writel(v, reg);
1704fcc18debSMika Westerberg 				dev_dbg(dev, "restored pin %d val %#08x\n",
1705fcc18debSMika Westerberg 					i, v);
1706fcc18debSMika Westerberg 			}
1707fcc18debSMika Westerberg 		}
1708fcc18debSMika Westerberg 	}
1709fcc18debSMika Westerberg 
1710fcc18debSMika Westerberg 	return 0;
1711fcc18debSMika Westerberg }
1712fcc18debSMika Westerberg #endif
1713fcc18debSMika Westerberg 
1714ec879f12SMika Westerberg #ifdef CONFIG_PM
17155fae8b86SMika Westerberg static int byt_gpio_runtime_suspend(struct device *dev)
17165fae8b86SMika Westerberg {
17175fae8b86SMika Westerberg 	return 0;
17185fae8b86SMika Westerberg }
17195fae8b86SMika Westerberg 
17205fae8b86SMika Westerberg static int byt_gpio_runtime_resume(struct device *dev)
17215fae8b86SMika Westerberg {
17225fae8b86SMika Westerberg 	return 0;
17235fae8b86SMika Westerberg }
1724ec879f12SMika Westerberg #endif
17255fae8b86SMika Westerberg 
17265fae8b86SMika Westerberg static const struct dev_pm_ops byt_gpio_pm_ops = {
1727fcc18debSMika Westerberg 	SET_LATE_SYSTEM_SLEEP_PM_OPS(byt_gpio_suspend, byt_gpio_resume)
1728fcc18debSMika Westerberg 	SET_RUNTIME_PM_OPS(byt_gpio_runtime_suspend, byt_gpio_runtime_resume,
1729fcc18debSMika Westerberg 			   NULL)
17305fae8b86SMika Westerberg };
17315fae8b86SMika Westerberg 
17325fae8b86SMika Westerberg static struct platform_driver byt_gpio_driver = {
173371e6ca61SCristina Ciocan 	.probe          = byt_pinctrl_probe,
17345fae8b86SMika Westerberg 	.driver         = {
17355fae8b86SMika Westerberg 		.name			= "byt_gpio",
17365fae8b86SMika Westerberg 		.pm			= &byt_gpio_pm_ops,
1737360943a8SPaul Gortmaker 		.suppress_bind_attrs	= true,
1738360943a8SPaul Gortmaker 
17395fae8b86SMika Westerberg 		.acpi_match_table = ACPI_PTR(byt_gpio_acpi_match),
17405fae8b86SMika Westerberg 	},
17415fae8b86SMika Westerberg };
17425fae8b86SMika Westerberg 
17435fae8b86SMika Westerberg static int __init byt_gpio_init(void)
17445fae8b86SMika Westerberg {
17455fae8b86SMika Westerberg 	return platform_driver_register(&byt_gpio_driver);
17465fae8b86SMika Westerberg }
17475fae8b86SMika Westerberg subsys_initcall(byt_gpio_init);
1748