xref: /linux/drivers/pinctrl/intel/pinctrl-baytrail.c (revision 0227b49b50276657243e54f5609e65c4f0eaaf4d)
1875a92b3SAndy Shevchenko // SPDX-License-Identifier: GPL-2.0
2a5d811bbSMathias Nyman /*
3a5d811bbSMathias Nyman  * Pinctrl GPIO driver for Intel Baytrail
4a5d811bbSMathias Nyman  *
5875a92b3SAndy Shevchenko  * Copyright (c) 2012-2013, Intel Corporation
6a5d811bbSMathias Nyman  * Author: Mathias Nyman <mathias.nyman@linux.intel.com>
7a5d811bbSMathias Nyman  */
8a5d811bbSMathias Nyman 
9a5d811bbSMathias Nyman #include <linux/acpi.h>
10a4877a85SAndy Shevchenko #include <linux/array_size.h>
11e0da3842SAndy Shevchenko #include <linux/bitops.h>
12c73505c8SBartosz Golaszewski #include <linux/cleanup.h>
13e0da3842SAndy Shevchenko #include <linux/gpio/driver.h>
14e0da3842SAndy Shevchenko #include <linux/init.h>
15e0da3842SAndy Shevchenko #include <linux/interrupt.h>
16a5d811bbSMathias Nyman #include <linux/io.h>
174d01688fSRaag Jadav #include <linux/module.h>
18e0da3842SAndy Shevchenko #include <linux/types.h>
19e0da3842SAndy Shevchenko #include <linux/platform_device.h>
208fd51616SRaag Jadav #include <linux/pm.h>
2161db6c9dSAndy Shevchenko #include <linux/property.h>
22e0da3842SAndy Shevchenko #include <linux/seq_file.h>
23c518d31bSAndy Shevchenko #include <linux/string_helpers.h>
2461db6c9dSAndy Shevchenko 
25a5d811bbSMathias Nyman #include <linux/pinctrl/pinctrl.h>
26c501d0b1SCristina Ciocan #include <linux/pinctrl/pinmux.h>
27c501d0b1SCristina Ciocan #include <linux/pinctrl/pinconf.h>
28c501d0b1SCristina Ciocan #include <linux/pinctrl/pinconf-generic.h>
29a5d811bbSMathias Nyman 
304f010b93SAndy Shevchenko #include "pinctrl-intel.h"
314f010b93SAndy Shevchenko 
32a5d811bbSMathias Nyman /* memory mapped register offsets */
33a5d811bbSMathias Nyman #define BYT_CONF0_REG		0x000
34a5d811bbSMathias Nyman #define BYT_CONF1_REG		0x004
35a5d811bbSMathias Nyman #define BYT_VAL_REG		0x008
36a5d811bbSMathias Nyman #define BYT_DFT_REG		0x00c
37a5d811bbSMathias Nyman #define BYT_INT_STAT_REG	0x800
38689e0088SHans de Goede #define BYT_DIRECT_IRQ_REG	0x980
39658b476cSCristina Ciocan #define BYT_DEBOUNCE_REG	0x9d0
40a5d811bbSMathias Nyman 
41a5d811bbSMathias Nyman /* BYT_CONF0_REG register bits */
423ff95885SMika Westerberg #define BYT_IODEN		BIT(31)
43ff998356SEric Ernst #define BYT_DIRECT_IRQ_EN	BIT(27)
44eb0a2daaSAndy Shevchenko #define BYT_TRIG_MASK		GENMASK(26, 24)
45a5d811bbSMathias Nyman #define BYT_TRIG_NEG		BIT(26)
46a5d811bbSMathias Nyman #define BYT_TRIG_POS		BIT(25)
47a5d811bbSMathias Nyman #define BYT_TRIG_LVL		BIT(24)
48658b476cSCristina Ciocan #define BYT_DEBOUNCE_EN		BIT(20)
499291c65bSHans de Goede #define BYT_GLITCH_FILTER_EN	BIT(19)
509291c65bSHans de Goede #define BYT_GLITCH_F_SLOW_CLK	BIT(17)
519291c65bSHans de Goede #define BYT_GLITCH_F_FAST_CLK	BIT(16)
523ff95885SMika Westerberg #define BYT_PULL_STR_SHIFT	9
53eb0a2daaSAndy Shevchenko #define BYT_PULL_STR_MASK	GENMASK(10, 9)
543ff95885SMika Westerberg #define BYT_PULL_STR_2K		(0 << BYT_PULL_STR_SHIFT)
553ff95885SMika Westerberg #define BYT_PULL_STR_10K	(1 << BYT_PULL_STR_SHIFT)
563ff95885SMika Westerberg #define BYT_PULL_STR_20K	(2 << BYT_PULL_STR_SHIFT)
573ff95885SMika Westerberg #define BYT_PULL_STR_40K	(3 << BYT_PULL_STR_SHIFT)
58eb0a2daaSAndy Shevchenko #define BYT_PULL_ASSIGN_MASK	GENMASK(8, 7)
599d712086SAndy Shevchenko #define BYT_PULL_ASSIGN_DOWN	BIT(8)
609d712086SAndy Shevchenko #define BYT_PULL_ASSIGN_UP	BIT(7)
61eb0a2daaSAndy Shevchenko #define BYT_PIN_MUX		GENMASK(2, 0)
62a5d811bbSMathias Nyman 
63a5d811bbSMathias Nyman /* BYT_VAL_REG register bits */
64eb0a2daaSAndy Shevchenko #define BYT_DIR_MASK		GENMASK(2, 1)
65a5d811bbSMathias Nyman #define BYT_INPUT_EN		BIT(2)  /* 0: input enabled (active low)*/
66a5d811bbSMathias Nyman #define BYT_OUTPUT_EN		BIT(1)  /* 0: output enabled (active low)*/
67a5d811bbSMathias Nyman #define BYT_LEVEL		BIT(0)
68a5d811bbSMathias Nyman 
69eb0a2daaSAndy Shevchenko #define BYT_CONF0_RESTORE_MASK	(BYT_DIRECT_IRQ_EN | BYT_TRIG_MASK | BYT_PIN_MUX)
70fcc18debSMika Westerberg #define BYT_VAL_RESTORE_MASK	(BYT_DIR_MASK | BYT_LEVEL)
71fcc18debSMika Westerberg 
72658b476cSCristina Ciocan /* BYT_DEBOUNCE_REG bits */
73eb0a2daaSAndy Shevchenko #define BYT_DEBOUNCE_PULSE_MASK		GENMASK(2, 0)
74658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_375US	1
75658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_750US	2
76658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_1500US	3
77658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_3MS		4
78658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_6MS		5
79658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_12MS		6
80658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_24MS		7
81658b476cSCristina Ciocan 
82a5d811bbSMathias Nyman #define BYT_NGPIO_SCORE		102
83a5d811bbSMathias Nyman #define BYT_NGPIO_NCORE		28
84a5d811bbSMathias Nyman #define BYT_NGPIO_SUS		44
85a5d811bbSMathias Nyman 
8642bd0070SChew, Kean Ho #define BYT_SCORE_ACPI_UID	"1"
8742bd0070SChew, Kean Ho #define BYT_NCORE_ACPI_UID	"2"
8842bd0070SChew, Kean Ho #define BYT_SUS_ACPI_UID	"3"
8942bd0070SChew, Kean Ho 
90c501d0b1SCristina Ciocan /*
91c501d0b1SCristina Ciocan  * This is the function value most pins have for GPIO muxing. If the value
92c501d0b1SCristina Ciocan  * differs from the default one, it must be explicitly mentioned. Otherwise, the
93c501d0b1SCristina Ciocan  * pin control implementation will set the muxing value to default GPIO if it
94c501d0b1SCristina Ciocan  * does not find a match for the requested function.
95c501d0b1SCristina Ciocan  */
96c501d0b1SCristina Ciocan #define BYT_DEFAULT_GPIO_MUX	0
97a705f9c1SAndy Shevchenko #define BYT_ALTER_GPIO_MUX	1
98c501d0b1SCristina Ciocan 
995d33e0ebSAndy Shevchenko struct intel_pad_context {
100c8f5c4c7SCristina Ciocan 	u32 conf0;
101c8f5c4c7SCristina Ciocan 	u32 val;
102c8f5c4c7SCristina Ciocan };
103a5d811bbSMathias Nyman 
104c8f5c4c7SCristina Ciocan #define COMMUNITY(p, n, map)		\
105c8f5c4c7SCristina Ciocan 	{				\
106c8f5c4c7SCristina Ciocan 		.pin_base	= (p),	\
107c8f5c4c7SCristina Ciocan 		.npins		= (n),	\
108c8f5c4c7SCristina Ciocan 		.pad_map	= (map),\
109c8f5c4c7SCristina Ciocan 	}
110c8f5c4c7SCristina Ciocan 
111c8f5c4c7SCristina Ciocan /* SCORE pins, aka GPIOC_<pin_no> or GPIO_S0_SC[<pin_no>] */
112c8f5c4c7SCristina Ciocan static const struct pinctrl_pin_desc byt_score_pins[] = {
113c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(0, "SATA_GP0"),
114c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(1, "SATA_GP1"),
115c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(2, "SATA_LED#"),
116c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(3, "PCIE_CLKREQ0"),
117c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(4, "PCIE_CLKREQ1"),
118c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(5, "PCIE_CLKREQ2"),
119c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(6, "PCIE_CLKREQ3"),
120c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(7, "SD3_WP"),
121c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(8, "HDA_RST"),
122c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(9, "HDA_SYNC"),
123c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(10, "HDA_CLK"),
124c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(11, "HDA_SDO"),
125c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(12, "HDA_SDI0"),
126c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(13, "HDA_SDI1"),
127c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(14, "GPIO_S0_SC14"),
128c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(15, "GPIO_S0_SC15"),
129c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(16, "MMC1_CLK"),
130c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(17, "MMC1_D0"),
131c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(18, "MMC1_D1"),
132c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(19, "MMC1_D2"),
133c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(20, "MMC1_D3"),
134c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(21, "MMC1_D4"),
135c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(22, "MMC1_D5"),
136c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(23, "MMC1_D6"),
137c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(24, "MMC1_D7"),
138c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(25, "MMC1_CMD"),
139c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(26, "MMC1_RST"),
140c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(27, "SD2_CLK"),
141c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(28, "SD2_D0"),
142c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(29, "SD2_D1"),
143c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(30, "SD2_D2"),
144c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(31, "SD2_D3_CD"),
145c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(32, "SD2_CMD"),
146c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(33, "SD3_CLK"),
147c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(34, "SD3_D0"),
148c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(35, "SD3_D1"),
149c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(36, "SD3_D2"),
150c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(37, "SD3_D3"),
151c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(38, "SD3_CD"),
152c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(39, "SD3_CMD"),
153c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(40, "SD3_1P8EN"),
154c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(41, "SD3_PWREN#"),
155c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(42, "ILB_LPC_AD0"),
156c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(43, "ILB_LPC_AD1"),
157c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(44, "ILB_LPC_AD2"),
158c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(45, "ILB_LPC_AD3"),
159c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(46, "ILB_LPC_FRAME"),
160c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(47, "ILB_LPC_CLK0"),
161c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(48, "ILB_LPC_CLK1"),
162c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(49, "ILB_LPC_CLKRUN"),
163c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(50, "ILB_LPC_SERIRQ"),
164c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(51, "PCU_SMB_DATA"),
165c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(52, "PCU_SMB_CLK"),
166c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(53, "PCU_SMB_ALERT"),
167c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(54, "ILB_8254_SPKR"),
168c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(55, "GPIO_S0_SC55"),
169c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(56, "GPIO_S0_SC56"),
170c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(57, "GPIO_S0_SC57"),
171c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(58, "GPIO_S0_SC58"),
172c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(59, "GPIO_S0_SC59"),
173c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(60, "GPIO_S0_SC60"),
174c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(61, "GPIO_S0_SC61"),
175c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(62, "LPE_I2S2_CLK"),
176c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(63, "LPE_I2S2_FRM"),
177c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(64, "LPE_I2S2_DATAIN"),
178c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(65, "LPE_I2S2_DATAOUT"),
179c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(66, "SIO_SPI_CS"),
180c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(67, "SIO_SPI_MISO"),
181c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(68, "SIO_SPI_MOSI"),
182c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(69, "SIO_SPI_CLK"),
183c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(70, "SIO_UART1_RXD"),
184c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(71, "SIO_UART1_TXD"),
185c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(72, "SIO_UART1_RTS"),
186c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(73, "SIO_UART1_CTS"),
187c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(74, "SIO_UART2_RXD"),
188c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(75, "SIO_UART2_TXD"),
189c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(76, "SIO_UART2_RTS"),
190c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(77, "SIO_UART2_CTS"),
191c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(78, "SIO_I2C0_DATA"),
192c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(79, "SIO_I2C0_CLK"),
193c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(80, "SIO_I2C1_DATA"),
194c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(81, "SIO_I2C1_CLK"),
195c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(82, "SIO_I2C2_DATA"),
196c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(83, "SIO_I2C2_CLK"),
197c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(84, "SIO_I2C3_DATA"),
198c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(85, "SIO_I2C3_CLK"),
199c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(86, "SIO_I2C4_DATA"),
200c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(87, "SIO_I2C4_CLK"),
201c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(88, "SIO_I2C5_DATA"),
202c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(89, "SIO_I2C5_CLK"),
203c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(90, "SIO_I2C6_DATA"),
204c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(91, "SIO_I2C6_CLK"),
205c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(92, "GPIO_S0_SC92"),
206c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(93, "GPIO_S0_SC93"),
207c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(94, "SIO_PWM0"),
208c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(95, "SIO_PWM1"),
209c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(96, "PMC_PLT_CLK0"),
210c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(97, "PMC_PLT_CLK1"),
211c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(98, "PMC_PLT_CLK2"),
212c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(99, "PMC_PLT_CLK3"),
213c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(100, "PMC_PLT_CLK4"),
214c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(101, "PMC_PLT_CLK5"),
215c8f5c4c7SCristina Ciocan };
216a5d811bbSMathias Nyman 
217c8f5c4c7SCristina Ciocan static const unsigned int byt_score_pins_map[BYT_NGPIO_SCORE] = {
218c8f5c4c7SCristina Ciocan 	85, 89, 93, 96, 99, 102, 98, 101, 34, 37,
219c8f5c4c7SCristina Ciocan 	36, 38, 39, 35, 40, 84, 62, 61, 64, 59,
220c8f5c4c7SCristina Ciocan 	54, 56, 60, 55, 63, 57, 51, 50, 53, 47,
221c8f5c4c7SCristina Ciocan 	52, 49, 48, 43, 46, 41, 45, 42, 58, 44,
222c8f5c4c7SCristina Ciocan 	95, 105, 70, 68, 67, 66, 69, 71, 65, 72,
223c8f5c4c7SCristina Ciocan 	86, 90, 88, 92, 103, 77, 79, 83, 78, 81,
224c8f5c4c7SCristina Ciocan 	80, 82, 13, 12, 15, 14, 17, 18, 19, 16,
225c8f5c4c7SCristina Ciocan 	2, 1, 0, 4, 6, 7, 9, 8, 33, 32,
226c8f5c4c7SCristina Ciocan 	31, 30, 29, 27, 25, 28, 26, 23, 21, 20,
227c8f5c4c7SCristina Ciocan 	24, 22, 5, 3, 10, 11, 106, 87, 91, 104,
228c8f5c4c7SCristina Ciocan 	97, 100,
229a5d811bbSMathias Nyman };
230a5d811bbSMathias Nyman 
231c8f5c4c7SCristina Ciocan /* SCORE groups */
232c8f5c4c7SCristina Ciocan static const unsigned int byt_score_uart1_pins[] = { 70, 71, 72, 73 };
233c8f5c4c7SCristina Ciocan static const unsigned int byt_score_uart2_pins[] = { 74, 75, 76, 77 };
2345d10a157SHans de Goede static const unsigned int byt_score_uart3_pins[] = { 57, 61 };
235c8f5c4c7SCristina Ciocan 
236c8f5c4c7SCristina Ciocan static const unsigned int byt_score_pwm0_pins[] = { 94 };
237c8f5c4c7SCristina Ciocan static const unsigned int byt_score_pwm1_pins[] = { 95 };
238c8f5c4c7SCristina Ciocan 
239c8f5c4c7SCristina Ciocan static const unsigned int byt_score_sio_spi_pins[] = { 66, 67, 68, 69 };
240c8f5c4c7SCristina Ciocan 
241c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c5_pins[] = { 88, 89 };
242c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c6_pins[] = { 90, 91 };
243c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c4_pins[] = { 86, 87 };
244c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c3_pins[] = { 84, 85 };
245c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c2_pins[] = { 82, 83 };
246c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c1_pins[] = { 80, 81 };
247c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c0_pins[] = { 78, 79 };
248c8f5c4c7SCristina Ciocan 
249c8f5c4c7SCristina Ciocan static const unsigned int byt_score_ssp0_pins[] = { 8, 9, 10, 11 };
250c8f5c4c7SCristina Ciocan static const unsigned int byt_score_ssp1_pins[] = { 12, 13, 14, 15 };
251c8f5c4c7SCristina Ciocan static const unsigned int byt_score_ssp2_pins[] = { 62, 63, 64, 65 };
252c8f5c4c7SCristina Ciocan 
253c8f5c4c7SCristina Ciocan static const unsigned int byt_score_sdcard_pins[] = {
254c8f5c4c7SCristina Ciocan 	7, 33, 34, 35, 36, 37, 38, 39, 40, 41,
255c8f5c4c7SCristina Ciocan };
2564f010b93SAndy Shevchenko static const unsigned int byt_score_sdcard_mux_values[] = {
257c8f5c4c7SCristina Ciocan 	2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
258c8f5c4c7SCristina Ciocan };
259c8f5c4c7SCristina Ciocan 
260c8f5c4c7SCristina Ciocan static const unsigned int byt_score_sdio_pins[] = { 27, 28, 29, 30, 31, 32 };
261c8f5c4c7SCristina Ciocan 
262c8f5c4c7SCristina Ciocan static const unsigned int byt_score_emmc_pins[] = {
263c8f5c4c7SCristina Ciocan 	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
264c8f5c4c7SCristina Ciocan };
265c8f5c4c7SCristina Ciocan 
266c8f5c4c7SCristina Ciocan static const unsigned int byt_score_ilb_lpc_pins[] = {
267c8f5c4c7SCristina Ciocan 	42, 43, 44, 45, 46, 47, 48, 49, 50,
268c8f5c4c7SCristina Ciocan };
269c8f5c4c7SCristina Ciocan 
270c8f5c4c7SCristina Ciocan static const unsigned int byt_score_sata_pins[] = { 0, 1, 2 };
271c8f5c4c7SCristina Ciocan 
272c8f5c4c7SCristina Ciocan static const unsigned int byt_score_plt_clk0_pins[] = { 96 };
273c8f5c4c7SCristina Ciocan static const unsigned int byt_score_plt_clk1_pins[] = { 97 };
274c8f5c4c7SCristina Ciocan static const unsigned int byt_score_plt_clk2_pins[] = { 98 };
275b41aa4f8SCristina Ciocan static const unsigned int byt_score_plt_clk3_pins[] = { 99 };
276b41aa4f8SCristina Ciocan static const unsigned int byt_score_plt_clk4_pins[] = { 100 };
277b41aa4f8SCristina Ciocan static const unsigned int byt_score_plt_clk5_pins[] = { 101 };
278c8f5c4c7SCristina Ciocan 
279c8f5c4c7SCristina Ciocan static const unsigned int byt_score_smbus_pins[] = { 51, 52, 53 };
280c8f5c4c7SCristina Ciocan 
2814f010b93SAndy Shevchenko static const struct intel_pingroup byt_score_groups[] = {
282fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("uart1_grp", byt_score_uart1_pins, 1),
283fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("uart2_grp", byt_score_uart2_pins, 1),
2845d10a157SHans de Goede 	PIN_GROUP_GPIO("uart3_grp", byt_score_uart3_pins, 1),
285fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("pwm0_grp", byt_score_pwm0_pins, 1),
286fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("pwm1_grp", byt_score_pwm1_pins, 1),
287fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("ssp2_grp", byt_score_ssp2_pins, 1),
288fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("sio_spi_grp", byt_score_sio_spi_pins, 1),
289fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("i2c5_grp", byt_score_i2c5_pins, 1),
290fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("i2c6_grp", byt_score_i2c6_pins, 1),
291fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("i2c4_grp", byt_score_i2c4_pins, 1),
292fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("i2c3_grp", byt_score_i2c3_pins, 1),
293fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("i2c2_grp", byt_score_i2c2_pins, 1),
294fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("i2c1_grp", byt_score_i2c1_pins, 1),
295fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("i2c0_grp", byt_score_i2c0_pins, 1),
296fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("ssp0_grp", byt_score_ssp0_pins, 1),
297fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("ssp1_grp", byt_score_ssp1_pins, 1),
298fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("sdcard_grp", byt_score_sdcard_pins, byt_score_sdcard_mux_values),
299fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("sdio_grp", byt_score_sdio_pins, 1),
300fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("emmc_grp", byt_score_emmc_pins, 1),
301fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("lpc_grp", byt_score_ilb_lpc_pins, 1),
302fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("sata_grp", byt_score_sata_pins, 1),
303fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("plt_clk0_grp", byt_score_plt_clk0_pins, 1),
304fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("plt_clk1_grp", byt_score_plt_clk1_pins, 1),
305fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("plt_clk2_grp", byt_score_plt_clk2_pins, 1),
306fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("plt_clk3_grp", byt_score_plt_clk3_pins, 1),
307fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("plt_clk4_grp", byt_score_plt_clk4_pins, 1),
308fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("plt_clk5_grp", byt_score_plt_clk5_pins, 1),
309fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("smbus_grp", byt_score_smbus_pins, 1),
310c8f5c4c7SCristina Ciocan };
311c8f5c4c7SCristina Ciocan 
312c8f5c4c7SCristina Ciocan static const char * const byt_score_uart_groups[] = {
3135d10a157SHans de Goede 	"uart1_grp", "uart2_grp", "uart3_grp",
314c8f5c4c7SCristina Ciocan };
315c8f5c4c7SCristina Ciocan static const char * const byt_score_pwm_groups[] = {
316c8f5c4c7SCristina Ciocan 	"pwm0_grp", "pwm1_grp",
317c8f5c4c7SCristina Ciocan };
318c8f5c4c7SCristina Ciocan static const char * const byt_score_ssp_groups[] = {
319c8f5c4c7SCristina Ciocan 	"ssp0_grp", "ssp1_grp", "ssp2_grp",
320c8f5c4c7SCristina Ciocan };
321c8f5c4c7SCristina Ciocan static const char * const byt_score_spi_groups[] = { "sio_spi_grp" };
322c8f5c4c7SCristina Ciocan static const char * const byt_score_i2c_groups[] = {
323c8f5c4c7SCristina Ciocan 	"i2c0_grp", "i2c1_grp", "i2c2_grp", "i2c3_grp", "i2c4_grp", "i2c5_grp",
324c8f5c4c7SCristina Ciocan 	"i2c6_grp",
325c8f5c4c7SCristina Ciocan };
326c8f5c4c7SCristina Ciocan static const char * const byt_score_sdcard_groups[] = { "sdcard_grp" };
327c8f5c4c7SCristina Ciocan static const char * const byt_score_sdio_groups[] = { "sdio_grp" };
328c8f5c4c7SCristina Ciocan static const char * const byt_score_emmc_groups[] = { "emmc_grp" };
329c8f5c4c7SCristina Ciocan static const char * const byt_score_lpc_groups[] = { "lpc_grp" };
330c8f5c4c7SCristina Ciocan static const char * const byt_score_sata_groups[] = { "sata_grp" };
331c8f5c4c7SCristina Ciocan static const char * const byt_score_plt_clk_groups[] = {
332c8f5c4c7SCristina Ciocan 	"plt_clk0_grp", "plt_clk1_grp", "plt_clk2_grp", "plt_clk3_grp",
333c8f5c4c7SCristina Ciocan 	"plt_clk4_grp", "plt_clk5_grp",
334c8f5c4c7SCristina Ciocan };
335c8f5c4c7SCristina Ciocan static const char * const byt_score_smbus_groups[] = { "smbus_grp" };
336c8f5c4c7SCristina Ciocan static const char * const byt_score_gpio_groups[] = {
3375d10a157SHans de Goede 	"uart1_grp_gpio", "uart2_grp_gpio", "uart3_grp_gpio", "pwm0_grp_gpio",
338fed6d9a8SHans de Goede 	"pwm1_grp_gpio", "ssp0_grp_gpio", "ssp1_grp_gpio", "ssp2_grp_gpio",
339fed6d9a8SHans de Goede 	"sio_spi_grp_gpio", "i2c0_grp_gpio", "i2c1_grp_gpio", "i2c2_grp_gpio",
340fed6d9a8SHans de Goede 	"i2c3_grp_gpio", "i2c4_grp_gpio", "i2c5_grp_gpio", "i2c6_grp_gpio",
341fed6d9a8SHans de Goede 	"sdcard_grp_gpio", "sdio_grp_gpio", "emmc_grp_gpio", "lpc_grp_gpio",
342fed6d9a8SHans de Goede 	"sata_grp_gpio", "plt_clk0_grp_gpio", "plt_clk1_grp_gpio",
343fed6d9a8SHans de Goede 	"plt_clk2_grp_gpio", "plt_clk3_grp_gpio", "plt_clk4_grp_gpio",
344fed6d9a8SHans de Goede 	"plt_clk5_grp_gpio", "smbus_grp_gpio",
345c8f5c4c7SCristina Ciocan };
346c8f5c4c7SCristina Ciocan 
3474f010b93SAndy Shevchenko static const struct intel_function byt_score_functions[] = {
348c8f5c4c7SCristina Ciocan 	FUNCTION("uart", byt_score_uart_groups),
349c8f5c4c7SCristina Ciocan 	FUNCTION("pwm", byt_score_pwm_groups),
350c8f5c4c7SCristina Ciocan 	FUNCTION("ssp", byt_score_ssp_groups),
351c8f5c4c7SCristina Ciocan 	FUNCTION("spi", byt_score_spi_groups),
352c8f5c4c7SCristina Ciocan 	FUNCTION("i2c", byt_score_i2c_groups),
353c8f5c4c7SCristina Ciocan 	FUNCTION("sdcard", byt_score_sdcard_groups),
354c8f5c4c7SCristina Ciocan 	FUNCTION("sdio", byt_score_sdio_groups),
355c8f5c4c7SCristina Ciocan 	FUNCTION("emmc", byt_score_emmc_groups),
356c8f5c4c7SCristina Ciocan 	FUNCTION("lpc", byt_score_lpc_groups),
357c8f5c4c7SCristina Ciocan 	FUNCTION("sata", byt_score_sata_groups),
358c8f5c4c7SCristina Ciocan 	FUNCTION("plt_clk", byt_score_plt_clk_groups),
359c8f5c4c7SCristina Ciocan 	FUNCTION("smbus", byt_score_smbus_groups),
360c8f5c4c7SCristina Ciocan 	FUNCTION("gpio", byt_score_gpio_groups),
361c8f5c4c7SCristina Ciocan };
362c8f5c4c7SCristina Ciocan 
36334e65670SAndy Shevchenko static const struct intel_community byt_score_communities[] = {
364c8f5c4c7SCristina Ciocan 	COMMUNITY(0, BYT_NGPIO_SCORE, byt_score_pins_map),
365c8f5c4c7SCristina Ciocan };
366c8f5c4c7SCristina Ciocan 
36734e65670SAndy Shevchenko static const struct intel_pinctrl_soc_data byt_score_soc_data = {
368c8f5c4c7SCristina Ciocan 	.uid		= BYT_SCORE_ACPI_UID,
369c8f5c4c7SCristina Ciocan 	.pins		= byt_score_pins,
370c8f5c4c7SCristina Ciocan 	.npins		= ARRAY_SIZE(byt_score_pins),
371c8f5c4c7SCristina Ciocan 	.groups		= byt_score_groups,
372c8f5c4c7SCristina Ciocan 	.ngroups	= ARRAY_SIZE(byt_score_groups),
373c8f5c4c7SCristina Ciocan 	.functions	= byt_score_functions,
374c8f5c4c7SCristina Ciocan 	.nfunctions	= ARRAY_SIZE(byt_score_functions),
375c8f5c4c7SCristina Ciocan 	.communities	= byt_score_communities,
376c8f5c4c7SCristina Ciocan 	.ncommunities	= ARRAY_SIZE(byt_score_communities),
377c8f5c4c7SCristina Ciocan };
378c8f5c4c7SCristina Ciocan 
379c8f5c4c7SCristina Ciocan /* SUS pins, aka GPIOS_<pin_no> or GPIO_S5[<pin_no>]  */
380c8f5c4c7SCristina Ciocan static const struct pinctrl_pin_desc byt_sus_pins[] = {
381c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(0, "GPIO_S50"),
382c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(1, "GPIO_S51"),
383c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(2, "GPIO_S52"),
384c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(3, "GPIO_S53"),
385c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(4, "GPIO_S54"),
386c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(5, "GPIO_S55"),
387c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(6, "GPIO_S56"),
388c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(7, "GPIO_S57"),
389c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(8, "GPIO_S58"),
390c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(9, "GPIO_S59"),
391c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(10, "GPIO_S510"),
392c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(11, "PMC_SUSPWRDNACK"),
393c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(12, "PMC_SUSCLK0"),
394c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(13, "GPIO_S513"),
395c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(14, "USB_ULPI_RST"),
396c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(15, "PMC_WAKE_PCIE0#"),
397c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(16, "PMC_PWRBTN"),
398c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(17, "GPIO_S517"),
399c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(18, "PMC_SUS_STAT"),
400c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(19, "USB_OC0"),
401c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(20, "USB_OC1"),
402c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(21, "PCU_SPI_CS1"),
403c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(22, "GPIO_S522"),
404c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(23, "GPIO_S523"),
405c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(24, "GPIO_S524"),
406c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(25, "GPIO_S525"),
407c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(26, "GPIO_S526"),
408c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(27, "GPIO_S527"),
409c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(28, "GPIO_S528"),
410c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(29, "GPIO_S529"),
411c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(30, "GPIO_S530"),
412c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(31, "USB_ULPI_CLK"),
413c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(32, "USB_ULPI_DATA0"),
414c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(33, "USB_ULPI_DATA1"),
415c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(34, "USB_ULPI_DATA2"),
416c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(35, "USB_ULPI_DATA3"),
417c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(36, "USB_ULPI_DATA4"),
418c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(37, "USB_ULPI_DATA5"),
419c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(38, "USB_ULPI_DATA6"),
420c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(39, "USB_ULPI_DATA7"),
421c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(40, "USB_ULPI_DIR"),
422c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(41, "USB_ULPI_NXT"),
423c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(42, "USB_ULPI_STP"),
424c8f5c4c7SCristina Ciocan 	PINCTRL_PIN(43, "USB_ULPI_REFCLK"),
425c8f5c4c7SCristina Ciocan };
426c8f5c4c7SCristina Ciocan 
427c8f5c4c7SCristina Ciocan static const unsigned int byt_sus_pins_map[BYT_NGPIO_SUS] = {
428c8f5c4c7SCristina Ciocan 	29, 33, 30, 31, 32, 34, 36, 35, 38, 37,
429c8f5c4c7SCristina Ciocan 	18, 7, 11, 20, 17, 1, 8, 10, 19, 12,
430c8f5c4c7SCristina Ciocan 	0, 2, 23, 39, 28, 27, 22, 21, 24, 25,
431c8f5c4c7SCristina Ciocan 	26, 51, 56, 54, 49, 55, 48, 57, 50, 58,
432c8f5c4c7SCristina Ciocan 	52, 53, 59, 40,
433c8f5c4c7SCristina Ciocan };
434c8f5c4c7SCristina Ciocan 
435c8f5c4c7SCristina Ciocan static const unsigned int byt_sus_usb_over_current_pins[] = { 19, 20 };
4364f010b93SAndy Shevchenko static const unsigned int byt_sus_usb_over_current_mode_values[] = { 0, 0 };
4374f010b93SAndy Shevchenko static const unsigned int byt_sus_usb_over_current_gpio_mode_values[] = { 1, 1 };
438c8f5c4c7SCristina Ciocan 
439c8f5c4c7SCristina Ciocan static const unsigned int byt_sus_usb_ulpi_pins[] = {
440c8f5c4c7SCristina Ciocan 	14, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
441c8f5c4c7SCristina Ciocan };
4424f010b93SAndy Shevchenko static const unsigned int byt_sus_usb_ulpi_mode_values[] = {
443c8f5c4c7SCristina Ciocan 	2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
444c8f5c4c7SCristina Ciocan };
4454f010b93SAndy Shevchenko static const unsigned int byt_sus_usb_ulpi_gpio_mode_values[] = {
4464f010b93SAndy Shevchenko 	1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
447c8f5c4c7SCristina Ciocan };
448c8f5c4c7SCristina Ciocan 
449c8f5c4c7SCristina Ciocan static const unsigned int byt_sus_pcu_spi_pins[] = { 21 };
4504f010b93SAndy Shevchenko static const unsigned int byt_sus_pcu_spi_mode_values[] = { 0 };
4514f010b93SAndy Shevchenko static const unsigned int byt_sus_pcu_spi_gpio_mode_values[] = { 1 };
452c8f5c4c7SCristina Ciocan 
4532f46d7f7SHans de Goede static const unsigned int byt_sus_pmu_clk1_pins[] = { 5 };
4542f46d7f7SHans de Goede static const unsigned int byt_sus_pmu_clk2_pins[] = { 6 };
4552f46d7f7SHans de Goede 
4564f010b93SAndy Shevchenko static const struct intel_pingroup byt_sus_groups[] = {
4574f010b93SAndy Shevchenko 	PIN_GROUP("usb_oc_grp", byt_sus_usb_over_current_pins, byt_sus_usb_over_current_mode_values),
4584f010b93SAndy Shevchenko 	PIN_GROUP("usb_ulpi_grp", byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_mode_values),
4594f010b93SAndy Shevchenko 	PIN_GROUP("pcu_spi_grp", byt_sus_pcu_spi_pins, byt_sus_pcu_spi_mode_values),
4604f010b93SAndy Shevchenko 	PIN_GROUP("usb_oc_grp_gpio", byt_sus_usb_over_current_pins, byt_sus_usb_over_current_gpio_mode_values),
4614f010b93SAndy Shevchenko 	PIN_GROUP("usb_ulpi_grp_gpio", byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_gpio_mode_values),
4624f010b93SAndy Shevchenko 	PIN_GROUP("pcu_spi_grp_gpio", byt_sus_pcu_spi_pins, byt_sus_pcu_spi_gpio_mode_values),
463fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("pmu_clk1_grp", byt_sus_pmu_clk1_pins, 1),
464fed6d9a8SHans de Goede 	PIN_GROUP_GPIO("pmu_clk2_grp", byt_sus_pmu_clk2_pins, 1),
465c8f5c4c7SCristina Ciocan };
466c8f5c4c7SCristina Ciocan 
467c8f5c4c7SCristina Ciocan static const char * const byt_sus_usb_groups[] = {
468c8f5c4c7SCristina Ciocan 	"usb_oc_grp", "usb_ulpi_grp",
469c8f5c4c7SCristina Ciocan };
470c8f5c4c7SCristina Ciocan static const char * const byt_sus_spi_groups[] = { "pcu_spi_grp" };
4712f46d7f7SHans de Goede static const char * const byt_sus_pmu_clk_groups[] = {
4722f46d7f7SHans de Goede 	"pmu_clk1_grp", "pmu_clk2_grp",
4732f46d7f7SHans de Goede };
474c8f5c4c7SCristina Ciocan static const char * const byt_sus_gpio_groups[] = {
4754f010b93SAndy Shevchenko 	"usb_oc_grp_gpio", "usb_ulpi_grp_gpio", "pcu_spi_grp_gpio",
476fed6d9a8SHans de Goede 	"pmu_clk1_grp_gpio", "pmu_clk2_grp_gpio",
477c8f5c4c7SCristina Ciocan };
478c8f5c4c7SCristina Ciocan 
4794f010b93SAndy Shevchenko static const struct intel_function byt_sus_functions[] = {
480c8f5c4c7SCristina Ciocan 	FUNCTION("usb", byt_sus_usb_groups),
481c8f5c4c7SCristina Ciocan 	FUNCTION("spi", byt_sus_spi_groups),
482c8f5c4c7SCristina Ciocan 	FUNCTION("gpio", byt_sus_gpio_groups),
4832f46d7f7SHans de Goede 	FUNCTION("pmu_clk", byt_sus_pmu_clk_groups),
484c8f5c4c7SCristina Ciocan };
485c8f5c4c7SCristina Ciocan 
48634e65670SAndy Shevchenko static const struct intel_community byt_sus_communities[] = {
487c8f5c4c7SCristina Ciocan 	COMMUNITY(0, BYT_NGPIO_SUS, byt_sus_pins_map),
488c8f5c4c7SCristina Ciocan };
489c8f5c4c7SCristina Ciocan 
49034e65670SAndy Shevchenko static const struct intel_pinctrl_soc_data byt_sus_soc_data = {
491c8f5c4c7SCristina Ciocan 	.uid		= BYT_SUS_ACPI_UID,
492c8f5c4c7SCristina Ciocan 	.pins		= byt_sus_pins,
493c8f5c4c7SCristina Ciocan 	.npins		= ARRAY_SIZE(byt_sus_pins),
494c8f5c4c7SCristina Ciocan 	.groups		= byt_sus_groups,
495c8f5c4c7SCristina Ciocan 	.ngroups	= ARRAY_SIZE(byt_sus_groups),
496c8f5c4c7SCristina Ciocan 	.functions	= byt_sus_functions,
497c8f5c4c7SCristina Ciocan 	.nfunctions	= ARRAY_SIZE(byt_sus_functions),
498c8f5c4c7SCristina Ciocan 	.communities	= byt_sus_communities,
499c8f5c4c7SCristina Ciocan 	.ncommunities	= ARRAY_SIZE(byt_sus_communities),
500c8f5c4c7SCristina Ciocan };
501c8f5c4c7SCristina Ciocan 
502c8f5c4c7SCristina Ciocan static const struct pinctrl_pin_desc byt_ncore_pins[] = {
503b30b736aSAndy Shevchenko 	PINCTRL_PIN(0, "HV_DDI0_HPD"),
504b30b736aSAndy Shevchenko 	PINCTRL_PIN(1, "HV_DDI0_DDC_SDA"),
505b30b736aSAndy Shevchenko 	PINCTRL_PIN(2, "HV_DDI0_DDC_SCL"),
506b30b736aSAndy Shevchenko 	PINCTRL_PIN(3, "PANEL0_VDDEN"),
507b30b736aSAndy Shevchenko 	PINCTRL_PIN(4, "PANEL0_BKLTEN"),
508b30b736aSAndy Shevchenko 	PINCTRL_PIN(5, "PANEL0_BKLTCTL"),
509b30b736aSAndy Shevchenko 	PINCTRL_PIN(6, "HV_DDI1_HPD"),
510b30b736aSAndy Shevchenko 	PINCTRL_PIN(7, "HV_DDI1_DDC_SDA"),
511b30b736aSAndy Shevchenko 	PINCTRL_PIN(8, "HV_DDI1_DDC_SCL"),
512b30b736aSAndy Shevchenko 	PINCTRL_PIN(9, "PANEL1_VDDEN"),
513b30b736aSAndy Shevchenko 	PINCTRL_PIN(10, "PANEL1_BKLTEN"),
514b30b736aSAndy Shevchenko 	PINCTRL_PIN(11, "PANEL1_BKLTCTL"),
515b30b736aSAndy Shevchenko 	PINCTRL_PIN(12, "GP_INTD_DSI_TE1"),
516b30b736aSAndy Shevchenko 	PINCTRL_PIN(13, "HV_DDI2_DDC_SDA"),
517b30b736aSAndy Shevchenko 	PINCTRL_PIN(14, "HV_DDI2_DDC_SCL"),
518b30b736aSAndy Shevchenko 	PINCTRL_PIN(15, "GP_CAMERASB00"),
519b30b736aSAndy Shevchenko 	PINCTRL_PIN(16, "GP_CAMERASB01"),
520b30b736aSAndy Shevchenko 	PINCTRL_PIN(17, "GP_CAMERASB02"),
521b30b736aSAndy Shevchenko 	PINCTRL_PIN(18, "GP_CAMERASB03"),
522b30b736aSAndy Shevchenko 	PINCTRL_PIN(19, "GP_CAMERASB04"),
523b30b736aSAndy Shevchenko 	PINCTRL_PIN(20, "GP_CAMERASB05"),
524b30b736aSAndy Shevchenko 	PINCTRL_PIN(21, "GP_CAMERASB06"),
525b30b736aSAndy Shevchenko 	PINCTRL_PIN(22, "GP_CAMERASB07"),
526b30b736aSAndy Shevchenko 	PINCTRL_PIN(23, "GP_CAMERASB08"),
527b30b736aSAndy Shevchenko 	PINCTRL_PIN(24, "GP_CAMERASB09"),
528b30b736aSAndy Shevchenko 	PINCTRL_PIN(25, "GP_CAMERASB10"),
529b30b736aSAndy Shevchenko 	PINCTRL_PIN(26, "GP_CAMERASB11"),
530b30b736aSAndy Shevchenko 	PINCTRL_PIN(27, "GP_INTD_DSI_TE2"),
531c8f5c4c7SCristina Ciocan };
532c8f5c4c7SCristina Ciocan 
533939330d7SAndy Shevchenko static const unsigned int byt_ncore_pins_map[BYT_NGPIO_NCORE] = {
534c8f5c4c7SCristina Ciocan 	19, 18, 17, 20, 21, 22, 24, 25, 23, 16,
535c8f5c4c7SCristina Ciocan 	14, 15, 12, 26, 27, 1, 4, 8, 11, 0,
536c8f5c4c7SCristina Ciocan 	3, 6, 10, 13, 2, 5, 9, 7,
537c8f5c4c7SCristina Ciocan };
538c8f5c4c7SCristina Ciocan 
53934e65670SAndy Shevchenko static const struct intel_community byt_ncore_communities[] = {
540c8f5c4c7SCristina Ciocan 	COMMUNITY(0, BYT_NGPIO_NCORE, byt_ncore_pins_map),
541c8f5c4c7SCristina Ciocan };
542c8f5c4c7SCristina Ciocan 
54334e65670SAndy Shevchenko static const struct intel_pinctrl_soc_data byt_ncore_soc_data = {
544c8f5c4c7SCristina Ciocan 	.uid		= BYT_NCORE_ACPI_UID,
545c8f5c4c7SCristina Ciocan 	.pins		= byt_ncore_pins,
546c8f5c4c7SCristina Ciocan 	.npins		= ARRAY_SIZE(byt_ncore_pins),
547c8f5c4c7SCristina Ciocan 	.communities	= byt_ncore_communities,
548c8f5c4c7SCristina Ciocan 	.ncommunities	= ARRAY_SIZE(byt_ncore_communities),
549c8f5c4c7SCristina Ciocan };
550c8f5c4c7SCristina Ciocan 
55134e65670SAndy Shevchenko static const struct intel_pinctrl_soc_data *byt_soc_data[] = {
552c8f5c4c7SCristina Ciocan 	&byt_score_soc_data,
553c8f5c4c7SCristina Ciocan 	&byt_sus_soc_data,
554c8f5c4c7SCristina Ciocan 	&byt_ncore_soc_data,
555166d6e2aSAndy Shevchenko 	NULL
556c8f5c4c7SCristina Ciocan };
557c8f5c4c7SCristina Ciocan 
55840ecab55SHans de Goede static DEFINE_RAW_SPINLOCK(byt_lock);
55940ecab55SHans de Goede 
byt_gpio_reg(struct intel_pinctrl * vg,unsigned int offset,int reg)5605d33e0ebSAndy Shevchenko static void __iomem *byt_gpio_reg(struct intel_pinctrl *vg, unsigned int offset,
561a5d811bbSMathias Nyman 				  int reg)
562a5d811bbSMathias Nyman {
563e075cbfeSAndy Shevchenko 	const struct intel_community *comm;
5641b89970dSAndy Shevchenko 	u32 reg_offset;
565a5d811bbSMathias Nyman 
566e075cbfeSAndy Shevchenko 	comm = intel_get_community(vg, offset);
567c501d0b1SCristina Ciocan 	if (!comm)
568c501d0b1SCristina Ciocan 		return NULL;
569c501d0b1SCristina Ciocan 
570c501d0b1SCristina Ciocan 	offset -= comm->pin_base;
5711b89970dSAndy Shevchenko 	switch (reg) {
5721b89970dSAndy Shevchenko 	case BYT_INT_STAT_REG:
573a5d811bbSMathias Nyman 		reg_offset = (offset / 32) * 4;
5741b89970dSAndy Shevchenko 		break;
5751b89970dSAndy Shevchenko 	case BYT_DEBOUNCE_REG:
5761b89970dSAndy Shevchenko 		reg_offset = 0;
5771b89970dSAndy Shevchenko 		break;
5781b89970dSAndy Shevchenko 	default:
579c501d0b1SCristina Ciocan 		reg_offset = comm->pad_map[offset] * 16;
5801b89970dSAndy Shevchenko 		break;
5811b89970dSAndy Shevchenko 	}
582a5d811bbSMathias Nyman 
58334e65670SAndy Shevchenko 	return comm->pad_regs + reg_offset + reg;
584a5d811bbSMathias Nyman }
585a5d811bbSMathias Nyman 
586c501d0b1SCristina Ciocan static const struct pinctrl_ops byt_pinctrl_ops = {
5874d01688fSRaag Jadav 	.get_groups_count	= intel_get_groups_count,
5884d01688fSRaag Jadav 	.get_group_name		= intel_get_group_name,
5894d01688fSRaag Jadav 	.get_group_pins		= intel_get_group_pins,
590c501d0b1SCristina Ciocan };
591c501d0b1SCristina Ciocan 
byt_set_group_simple_mux(struct intel_pinctrl * vg,const struct intel_pingroup group,unsigned int func)5925d33e0ebSAndy Shevchenko static void byt_set_group_simple_mux(struct intel_pinctrl *vg,
5934f010b93SAndy Shevchenko 				     const struct intel_pingroup group,
5944f010b93SAndy Shevchenko 				     unsigned int func)
595c501d0b1SCristina Ciocan {
596c501d0b1SCristina Ciocan 	int i;
597c501d0b1SCristina Ciocan 
5986191e49dSAndy Shevchenko 	guard(raw_spinlock_irqsave)(&byt_lock);
599c501d0b1SCristina Ciocan 
600770f53d4SAndy Shevchenko 	for (i = 0; i < group.grp.npins; i++) {
601c501d0b1SCristina Ciocan 		void __iomem *padcfg0;
602c501d0b1SCristina Ciocan 		u32 value;
603c501d0b1SCristina Ciocan 
604770f53d4SAndy Shevchenko 		padcfg0 = byt_gpio_reg(vg, group.grp.pins[i], BYT_CONF0_REG);
605c501d0b1SCristina Ciocan 		if (!padcfg0) {
606b9e18434SAndy Shevchenko 			dev_warn(vg->dev, "Group %s, pin %i not muxed (can't retrieve CONF0)\n",
607770f53d4SAndy Shevchenko 				 group.grp.name, i);
608c501d0b1SCristina Ciocan 			continue;
609c501d0b1SCristina Ciocan 		}
610c501d0b1SCristina Ciocan 
611c501d0b1SCristina Ciocan 		value = readl(padcfg0);
612c501d0b1SCristina Ciocan 		value &= ~BYT_PIN_MUX;
613c501d0b1SCristina Ciocan 		value |= func;
614c501d0b1SCristina Ciocan 		writel(value, padcfg0);
615c501d0b1SCristina Ciocan 	}
616c501d0b1SCristina Ciocan }
617c501d0b1SCristina Ciocan 
byt_set_group_mixed_mux(struct intel_pinctrl * vg,const struct intel_pingroup group,const unsigned int * func)6185d33e0ebSAndy Shevchenko static void byt_set_group_mixed_mux(struct intel_pinctrl *vg,
6194f010b93SAndy Shevchenko 				    const struct intel_pingroup group,
6204f010b93SAndy Shevchenko 				    const unsigned int *func)
621c501d0b1SCristina Ciocan {
622c501d0b1SCristina Ciocan 	int i;
623c501d0b1SCristina Ciocan 
6246191e49dSAndy Shevchenko 	guard(raw_spinlock_irqsave)(&byt_lock);
625c501d0b1SCristina Ciocan 
626770f53d4SAndy Shevchenko 	for (i = 0; i < group.grp.npins; i++) {
627c501d0b1SCristina Ciocan 		void __iomem *padcfg0;
628c501d0b1SCristina Ciocan 		u32 value;
629c501d0b1SCristina Ciocan 
630770f53d4SAndy Shevchenko 		padcfg0 = byt_gpio_reg(vg, group.grp.pins[i], BYT_CONF0_REG);
631c501d0b1SCristina Ciocan 		if (!padcfg0) {
632b9e18434SAndy Shevchenko 			dev_warn(vg->dev, "Group %s, pin %i not muxed (can't retrieve CONF0)\n",
633770f53d4SAndy Shevchenko 				 group.grp.name, i);
634c501d0b1SCristina Ciocan 			continue;
635c501d0b1SCristina Ciocan 		}
636c501d0b1SCristina Ciocan 
637c501d0b1SCristina Ciocan 		value = readl(padcfg0);
638c501d0b1SCristina Ciocan 		value &= ~BYT_PIN_MUX;
639c501d0b1SCristina Ciocan 		value |= func[i];
640c501d0b1SCristina Ciocan 		writel(value, padcfg0);
641c501d0b1SCristina Ciocan 	}
642c501d0b1SCristina Ciocan }
643c501d0b1SCristina Ciocan 
byt_set_mux(struct pinctrl_dev * pctldev,unsigned int func_selector,unsigned int group_selector)644c501d0b1SCristina Ciocan static int byt_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
645c501d0b1SCristina Ciocan 		       unsigned int group_selector)
646c501d0b1SCristina Ciocan {
6475d33e0ebSAndy Shevchenko 	struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev);
6485d33e0ebSAndy Shevchenko 	const struct intel_function func = vg->soc->functions[func_selector];
6495d33e0ebSAndy Shevchenko 	const struct intel_pingroup group = vg->soc->groups[group_selector];
650c501d0b1SCristina Ciocan 
6514f010b93SAndy Shevchenko 	if (group.modes)
6524f010b93SAndy Shevchenko 		byt_set_group_mixed_mux(vg, group, group.modes);
653988ac1a4SAndy Shevchenko 	else if (!strcmp(func.func.name, "gpio"))
654c501d0b1SCristina Ciocan 		byt_set_group_simple_mux(vg, group, BYT_DEFAULT_GPIO_MUX);
655c501d0b1SCristina Ciocan 	else
6564f010b93SAndy Shevchenko 		byt_set_group_simple_mux(vg, group, group.mode);
657c501d0b1SCristina Ciocan 
658c501d0b1SCristina Ciocan 	return 0;
659c501d0b1SCristina Ciocan }
660c501d0b1SCristina Ciocan 
byt_get_gpio_mux(struct intel_pinctrl * vg,unsigned int offset)6615d33e0ebSAndy Shevchenko static u32 byt_get_gpio_mux(struct intel_pinctrl *vg, unsigned int offset)
662c501d0b1SCristina Ciocan {
663c501d0b1SCristina Ciocan 	/* SCORE pin 92-93 */
6645d33e0ebSAndy Shevchenko 	if (!strcmp(vg->soc->uid, BYT_SCORE_ACPI_UID) &&
665c501d0b1SCristina Ciocan 	    offset >= 92 && offset <= 93)
666a705f9c1SAndy Shevchenko 		return BYT_ALTER_GPIO_MUX;
667c501d0b1SCristina Ciocan 
668c501d0b1SCristina Ciocan 	/* SUS pin 11-21 */
6695d33e0ebSAndy Shevchenko 	if (!strcmp(vg->soc->uid, BYT_SUS_ACPI_UID) &&
670c501d0b1SCristina Ciocan 	    offset >= 11 && offset <= 21)
671a705f9c1SAndy Shevchenko 		return BYT_ALTER_GPIO_MUX;
672c501d0b1SCristina Ciocan 
673a705f9c1SAndy Shevchenko 	return BYT_DEFAULT_GPIO_MUX;
674c501d0b1SCristina Ciocan }
675c501d0b1SCristina Ciocan 
byt_gpio_clear_triggering(struct intel_pinctrl * vg,unsigned int offset)6765d33e0ebSAndy Shevchenko static void byt_gpio_clear_triggering(struct intel_pinctrl *vg, unsigned int offset)
677c501d0b1SCristina Ciocan {
678c501d0b1SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
67995f0972cSMika Westerberg 	u32 value;
68095f0972cSMika Westerberg 
6816191e49dSAndy Shevchenko 	guard(raw_spinlock_irqsave)(&byt_lock);
6826191e49dSAndy Shevchenko 
68395f0972cSMika Westerberg 	value = readl(reg);
684a2368059SHans de Goede 
685a2368059SHans de Goede 	/* Do not clear direct-irq enabled IRQs (from gpio_disable_free) */
686605ba256SRaag Jadav 	if (!(value & BYT_DIRECT_IRQ_EN))
68795f0972cSMika Westerberg 		value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
688a2368059SHans de Goede 
68995f0972cSMika Westerberg 	writel(value, reg);
69095f0972cSMika Westerberg }
69195f0972cSMika Westerberg 
byt_gpio_request_enable(struct pinctrl_dev * pctl_dev,struct pinctrl_gpio_range * range,unsigned int offset)692c501d0b1SCristina Ciocan static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev,
693c501d0b1SCristina Ciocan 				   struct pinctrl_gpio_range *range,
694c501d0b1SCristina Ciocan 				   unsigned int offset)
69542bd0070SChew, Kean Ho {
6965d33e0ebSAndy Shevchenko 	struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctl_dev);
697c501d0b1SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
698f8323b6bSMika Westerberg 	u32 value, gpio_mux;
69939ce8150SMika Westerberg 
7006191e49dSAndy Shevchenko 	guard(raw_spinlock_irqsave)(&byt_lock);
70142bd0070SChew, Kean Ho 
70242bd0070SChew, Kean Ho 	/*
70342bd0070SChew, Kean Ho 	 * In most cases, func pin mux 000 means GPIO function.
70442bd0070SChew, Kean Ho 	 * But, some pins may have func pin mux 001 represents
705f8323b6bSMika Westerberg 	 * GPIO function.
706f8323b6bSMika Westerberg 	 *
707f8323b6bSMika Westerberg 	 * Because there are devices out there where some pins were not
708f8323b6bSMika Westerberg 	 * configured correctly we allow changing the mux value from
709f8323b6bSMika Westerberg 	 * request (but print out warning about that).
71042bd0070SChew, Kean Ho 	 */
71142bd0070SChew, Kean Ho 	value = readl(reg) & BYT_PIN_MUX;
712f8323b6bSMika Westerberg 	gpio_mux = byt_get_gpio_mux(vg, offset);
7136191e49dSAndy Shevchenko 	if (gpio_mux == value)
7146191e49dSAndy Shevchenko 		return 0;
7156191e49dSAndy Shevchenko 
716f8323b6bSMika Westerberg 	value = readl(reg) & ~BYT_PIN_MUX;
717f8323b6bSMika Westerberg 	value |= gpio_mux;
718f8323b6bSMika Westerberg 	writel(value, reg);
719f8323b6bSMika Westerberg 
720b9e18434SAndy Shevchenko 	dev_warn(vg->dev, FW_BUG "Pin %i: forcibly re-configured as GPIO\n", offset);
72139ce8150SMika Westerberg 
722a5d811bbSMathias Nyman 	return 0;
723a5d811bbSMathias Nyman }
724a5d811bbSMathias Nyman 
byt_gpio_disable_free(struct pinctrl_dev * pctl_dev,struct pinctrl_gpio_range * range,unsigned int offset)725c501d0b1SCristina Ciocan static void byt_gpio_disable_free(struct pinctrl_dev *pctl_dev,
726c501d0b1SCristina Ciocan 				  struct pinctrl_gpio_range *range,
727c501d0b1SCristina Ciocan 				  unsigned int offset)
728c501d0b1SCristina Ciocan {
7295d33e0ebSAndy Shevchenko 	struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctl_dev);
730c501d0b1SCristina Ciocan 
731c501d0b1SCristina Ciocan 	byt_gpio_clear_triggering(vg, offset);
732c501d0b1SCristina Ciocan }
733c501d0b1SCristina Ciocan 
byt_gpio_direct_irq_check(struct intel_pinctrl * vg,unsigned int offset)734156abe29SHans de Goede static void byt_gpio_direct_irq_check(struct intel_pinctrl *vg,
735156abe29SHans de Goede 				      unsigned int offset)
736156abe29SHans de Goede {
737156abe29SHans de Goede 	void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
738156abe29SHans de Goede 
739156abe29SHans de Goede 	/*
740156abe29SHans de Goede 	 * Before making any direction modifications, do a check if gpio is set
741156abe29SHans de Goede 	 * for direct IRQ. On Bay Trail, setting GPIO to output does not make
742156abe29SHans de Goede 	 * sense, so let's at least inform the caller before they shoot
743156abe29SHans de Goede 	 * themselves in the foot.
744156abe29SHans de Goede 	 */
745156abe29SHans de Goede 	if (readl(conf_reg) & BYT_DIRECT_IRQ_EN)
746b9e18434SAndy Shevchenko 		dev_info_once(vg->dev,
747b9e18434SAndy Shevchenko 			      "Potential Error: Pin %i: forcibly set GPIO with DIRECT_IRQ_EN to output\n",
748b9e18434SAndy Shevchenko 			      offset);
749156abe29SHans de Goede }
750156abe29SHans de Goede 
byt_gpio_set_direction(struct pinctrl_dev * pctl_dev,struct pinctrl_gpio_range * range,unsigned int offset,bool input)751c501d0b1SCristina Ciocan static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
752c501d0b1SCristina Ciocan 				  struct pinctrl_gpio_range *range,
753c501d0b1SCristina Ciocan 				  unsigned int offset,
754c501d0b1SCristina Ciocan 				  bool input)
755c501d0b1SCristina Ciocan {
7565d33e0ebSAndy Shevchenko 	struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctl_dev);
757c501d0b1SCristina Ciocan 	void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
758c501d0b1SCristina Ciocan 	u32 value;
759c501d0b1SCristina Ciocan 
7606191e49dSAndy Shevchenko 	guard(raw_spinlock_irqsave)(&byt_lock);
761c501d0b1SCristina Ciocan 
762c501d0b1SCristina Ciocan 	value = readl(val_reg);
763c501d0b1SCristina Ciocan 	value &= ~BYT_DIR_MASK;
764c501d0b1SCristina Ciocan 	if (input)
765c501d0b1SCristina Ciocan 		value |= BYT_OUTPUT_EN;
766156abe29SHans de Goede 	else
767156abe29SHans de Goede 		byt_gpio_direct_irq_check(vg, offset);
768e2b74419SHans de Goede 
769c501d0b1SCristina Ciocan 	writel(value, val_reg);
770c501d0b1SCristina Ciocan 
771c501d0b1SCristina Ciocan 	return 0;
772c501d0b1SCristina Ciocan }
773c501d0b1SCristina Ciocan 
774c501d0b1SCristina Ciocan static const struct pinmux_ops byt_pinmux_ops = {
7754d01688fSRaag Jadav 	.get_functions_count	= intel_get_functions_count,
7764d01688fSRaag Jadav 	.get_function_name	= intel_get_function_name,
7774d01688fSRaag Jadav 	.get_function_groups	= intel_get_function_groups,
778c501d0b1SCristina Ciocan 	.set_mux		= byt_set_mux,
779c501d0b1SCristina Ciocan 	.gpio_request_enable	= byt_gpio_request_enable,
780c501d0b1SCristina Ciocan 	.gpio_disable_free	= byt_gpio_disable_free,
781c501d0b1SCristina Ciocan 	.gpio_set_direction	= byt_gpio_set_direction,
782c501d0b1SCristina Ciocan };
783c501d0b1SCristina Ciocan 
byt_get_pull_strength(u32 reg,u16 * strength)784c501d0b1SCristina Ciocan static void byt_get_pull_strength(u32 reg, u16 *strength)
785c501d0b1SCristina Ciocan {
786c501d0b1SCristina Ciocan 	switch (reg & BYT_PULL_STR_MASK) {
787c501d0b1SCristina Ciocan 	case BYT_PULL_STR_2K:
788c501d0b1SCristina Ciocan 		*strength = 2000;
789c501d0b1SCristina Ciocan 		break;
790c501d0b1SCristina Ciocan 	case BYT_PULL_STR_10K:
791c501d0b1SCristina Ciocan 		*strength = 10000;
792c501d0b1SCristina Ciocan 		break;
793c501d0b1SCristina Ciocan 	case BYT_PULL_STR_20K:
794c501d0b1SCristina Ciocan 		*strength = 20000;
795c501d0b1SCristina Ciocan 		break;
796c501d0b1SCristina Ciocan 	case BYT_PULL_STR_40K:
797c501d0b1SCristina Ciocan 		*strength = 40000;
798c501d0b1SCristina Ciocan 		break;
799c501d0b1SCristina Ciocan 	}
800c501d0b1SCristina Ciocan }
801c501d0b1SCristina Ciocan 
byt_set_pull_strength(u32 * reg,u16 strength)802c501d0b1SCristina Ciocan static int byt_set_pull_strength(u32 *reg, u16 strength)
803c501d0b1SCristina Ciocan {
804c501d0b1SCristina Ciocan 	*reg &= ~BYT_PULL_STR_MASK;
805c501d0b1SCristina Ciocan 
806c501d0b1SCristina Ciocan 	switch (strength) {
807078d8303SAndy Shevchenko 	case 1: /* Set default strength value in case none is given */
808c501d0b1SCristina Ciocan 	case 2000:
809c501d0b1SCristina Ciocan 		*reg |= BYT_PULL_STR_2K;
810c501d0b1SCristina Ciocan 		break;
811c501d0b1SCristina Ciocan 	case 10000:
812c501d0b1SCristina Ciocan 		*reg |= BYT_PULL_STR_10K;
813c501d0b1SCristina Ciocan 		break;
814c501d0b1SCristina Ciocan 	case 20000:
815c501d0b1SCristina Ciocan 		*reg |= BYT_PULL_STR_20K;
816c501d0b1SCristina Ciocan 		break;
817c501d0b1SCristina Ciocan 	case 40000:
818c501d0b1SCristina Ciocan 		*reg |= BYT_PULL_STR_40K;
819c501d0b1SCristina Ciocan 		break;
820c501d0b1SCristina Ciocan 	default:
821c501d0b1SCristina Ciocan 		return -EINVAL;
822c501d0b1SCristina Ciocan 	}
823c501d0b1SCristina Ciocan 
824c501d0b1SCristina Ciocan 	return 0;
825c501d0b1SCristina Ciocan }
826c501d0b1SCristina Ciocan 
byt_gpio_force_input_mode(struct intel_pinctrl * vg,unsigned int offset)8275398a0e2SAndy Shevchenko static void byt_gpio_force_input_mode(struct intel_pinctrl *vg, unsigned int offset)
8285398a0e2SAndy Shevchenko {
8295398a0e2SAndy Shevchenko 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
8305398a0e2SAndy Shevchenko 	u32 value;
8315398a0e2SAndy Shevchenko 
8325398a0e2SAndy Shevchenko 	value = readl(reg);
8335398a0e2SAndy Shevchenko 	if (!(value & BYT_INPUT_EN))
8345398a0e2SAndy Shevchenko 		return;
8355398a0e2SAndy Shevchenko 
8365398a0e2SAndy Shevchenko 	/*
8375398a0e2SAndy Shevchenko 	 * Pull assignment is only applicable in input mode. If
8385398a0e2SAndy Shevchenko 	 * chip is not in input mode, set it and warn about it.
8395398a0e2SAndy Shevchenko 	 */
8405398a0e2SAndy Shevchenko 	value &= ~BYT_INPUT_EN;
8415398a0e2SAndy Shevchenko 	writel(value, reg);
8425398a0e2SAndy Shevchenko 	dev_warn(vg->dev, "Pin %i: forcibly set to input mode\n", offset);
8435398a0e2SAndy Shevchenko }
8445398a0e2SAndy Shevchenko 
byt_pin_config_get(struct pinctrl_dev * pctl_dev,unsigned int offset,unsigned long * config)845c501d0b1SCristina Ciocan static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset,
846c501d0b1SCristina Ciocan 			      unsigned long *config)
847c501d0b1SCristina Ciocan {
8485d33e0ebSAndy Shevchenko 	struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctl_dev);
849c501d0b1SCristina Ciocan 	enum pin_config_param param = pinconf_to_config_param(*config);
850c501d0b1SCristina Ciocan 	void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
851c501d0b1SCristina Ciocan 	void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
85204ff5a09SAndy Shevchenko 	void __iomem *db_reg = byt_gpio_reg(vg, offset, BYT_DEBOUNCE_REG);
853658b476cSCristina Ciocan 	u32 conf, pull, val, debounce;
854c501d0b1SCristina Ciocan 	u16 arg = 0;
855c501d0b1SCristina Ciocan 
8566191e49dSAndy Shevchenko 	scoped_guard(raw_spinlock_irqsave, &byt_lock) {
857c501d0b1SCristina Ciocan 		conf = readl(conf_reg);
858c501d0b1SCristina Ciocan 		val = readl(val_reg);
8596191e49dSAndy Shevchenko 	}
8606191e49dSAndy Shevchenko 
8616191e49dSAndy Shevchenko 	pull = conf & BYT_PULL_ASSIGN_MASK;
862c501d0b1SCristina Ciocan 
863c501d0b1SCristina Ciocan 	switch (param) {
864c501d0b1SCristina Ciocan 	case PIN_CONFIG_BIAS_DISABLE:
865c501d0b1SCristina Ciocan 		if (pull)
866c501d0b1SCristina Ciocan 			return -EINVAL;
867c501d0b1SCristina Ciocan 		break;
868c501d0b1SCristina Ciocan 	case PIN_CONFIG_BIAS_PULL_DOWN:
869c501d0b1SCristina Ciocan 		/* Pull assignment is only applicable in input mode */
870c501d0b1SCristina Ciocan 		if ((val & BYT_INPUT_EN) || pull != BYT_PULL_ASSIGN_DOWN)
871c501d0b1SCristina Ciocan 			return -EINVAL;
872c501d0b1SCristina Ciocan 
873c501d0b1SCristina Ciocan 		byt_get_pull_strength(conf, &arg);
874c501d0b1SCristina Ciocan 
875c501d0b1SCristina Ciocan 		break;
876c501d0b1SCristina Ciocan 	case PIN_CONFIG_BIAS_PULL_UP:
877c501d0b1SCristina Ciocan 		/* Pull assignment is only applicable in input mode */
878c501d0b1SCristina Ciocan 		if ((val & BYT_INPUT_EN) || pull != BYT_PULL_ASSIGN_UP)
879c501d0b1SCristina Ciocan 			return -EINVAL;
880c501d0b1SCristina Ciocan 
881c501d0b1SCristina Ciocan 		byt_get_pull_strength(conf, &arg);
882c501d0b1SCristina Ciocan 
883c501d0b1SCristina Ciocan 		break;
884658b476cSCristina Ciocan 	case PIN_CONFIG_INPUT_DEBOUNCE:
885658b476cSCristina Ciocan 		if (!(conf & BYT_DEBOUNCE_EN))
886658b476cSCristina Ciocan 			return -EINVAL;
887658b476cSCristina Ciocan 
8886191e49dSAndy Shevchenko 		scoped_guard(raw_spinlock_irqsave, &byt_lock)
88904ff5a09SAndy Shevchenko 			debounce = readl(db_reg);
890658b476cSCristina Ciocan 
891658b476cSCristina Ciocan 		switch (debounce & BYT_DEBOUNCE_PULSE_MASK) {
892658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_375US:
893658b476cSCristina Ciocan 			arg = 375;
894658b476cSCristina Ciocan 			break;
895658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_750US:
896658b476cSCristina Ciocan 			arg = 750;
897658b476cSCristina Ciocan 			break;
898658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_1500US:
899658b476cSCristina Ciocan 			arg = 1500;
900658b476cSCristina Ciocan 			break;
901658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_3MS:
902658b476cSCristina Ciocan 			arg = 3000;
903658b476cSCristina Ciocan 			break;
904658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_6MS:
905658b476cSCristina Ciocan 			arg = 6000;
906658b476cSCristina Ciocan 			break;
907658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_12MS:
908658b476cSCristina Ciocan 			arg = 12000;
909658b476cSCristina Ciocan 			break;
910658b476cSCristina Ciocan 		case BYT_DEBOUNCE_PULSE_24MS:
911658b476cSCristina Ciocan 			arg = 24000;
912658b476cSCristina Ciocan 			break;
913658b476cSCristina Ciocan 		default:
914658b476cSCristina Ciocan 			return -EINVAL;
915658b476cSCristina Ciocan 		}
916658b476cSCristina Ciocan 
917658b476cSCristina Ciocan 		break;
918c501d0b1SCristina Ciocan 	default:
919c501d0b1SCristina Ciocan 		return -ENOTSUPP;
920c501d0b1SCristina Ciocan 	}
921c501d0b1SCristina Ciocan 
922c501d0b1SCristina Ciocan 	*config = pinconf_to_config_packed(param, arg);
923c501d0b1SCristina Ciocan 
924c501d0b1SCristina Ciocan 	return 0;
925c501d0b1SCristina Ciocan }
926c501d0b1SCristina Ciocan 
byt_pin_config_set(struct pinctrl_dev * pctl_dev,unsigned int offset,unsigned long * configs,unsigned int num_configs)927c501d0b1SCristina Ciocan static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
928c501d0b1SCristina Ciocan 			      unsigned int offset,
929c501d0b1SCristina Ciocan 			      unsigned long *configs,
930c501d0b1SCristina Ciocan 			      unsigned int num_configs)
931c501d0b1SCristina Ciocan {
9325d33e0ebSAndy Shevchenko 	struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctl_dev);
933c501d0b1SCristina Ciocan 	void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
93404ff5a09SAndy Shevchenko 	void __iomem *db_reg = byt_gpio_reg(vg, offset, BYT_DEBOUNCE_REG);
9355398a0e2SAndy Shevchenko 	u32 conf, db_pulse, debounce;
9361a856a22SAndy Shevchenko 	enum pin_config_param param;
9376191e49dSAndy Shevchenko 	int i, ret;
9381a856a22SAndy Shevchenko 	u32 arg;
939c501d0b1SCristina Ciocan 
9406191e49dSAndy Shevchenko 	guard(raw_spinlock_irqsave)(&byt_lock);
941c501d0b1SCristina Ciocan 
942c501d0b1SCristina Ciocan 	conf = readl(conf_reg);
943c501d0b1SCristina Ciocan 
944c501d0b1SCristina Ciocan 	for (i = 0; i < num_configs; i++) {
945c501d0b1SCristina Ciocan 		param = pinconf_to_config_param(configs[i]);
946c501d0b1SCristina Ciocan 		arg = pinconf_to_config_argument(configs[i]);
947c501d0b1SCristina Ciocan 
948c501d0b1SCristina Ciocan 		switch (param) {
949c501d0b1SCristina Ciocan 		case PIN_CONFIG_BIAS_DISABLE:
950c501d0b1SCristina Ciocan 			conf &= ~BYT_PULL_ASSIGN_MASK;
951c501d0b1SCristina Ciocan 			break;
952c501d0b1SCristina Ciocan 		case PIN_CONFIG_BIAS_PULL_DOWN:
9535398a0e2SAndy Shevchenko 			byt_gpio_force_input_mode(vg, offset);
954c501d0b1SCristina Ciocan 
955c501d0b1SCristina Ciocan 			conf &= ~BYT_PULL_ASSIGN_MASK;
956c501d0b1SCristina Ciocan 			conf |= BYT_PULL_ASSIGN_DOWN;
957c501d0b1SCristina Ciocan 			ret = byt_set_pull_strength(&conf, arg);
9586191e49dSAndy Shevchenko 			if (ret)
9596191e49dSAndy Shevchenko 				return ret;
960c501d0b1SCristina Ciocan 
961c501d0b1SCristina Ciocan 			break;
962c501d0b1SCristina Ciocan 		case PIN_CONFIG_BIAS_PULL_UP:
9635398a0e2SAndy Shevchenko 			byt_gpio_force_input_mode(vg, offset);
964c501d0b1SCristina Ciocan 
965c501d0b1SCristina Ciocan 			conf &= ~BYT_PULL_ASSIGN_MASK;
966c501d0b1SCristina Ciocan 			conf |= BYT_PULL_ASSIGN_UP;
967c501d0b1SCristina Ciocan 			ret = byt_set_pull_strength(&conf, arg);
9686191e49dSAndy Shevchenko 			if (ret)
9696191e49dSAndy Shevchenko 				return ret;
970c501d0b1SCristina Ciocan 
971c501d0b1SCristina Ciocan 			break;
972658b476cSCristina Ciocan 		case PIN_CONFIG_INPUT_DEBOUNCE:
973658b476cSCristina Ciocan 			switch (arg) {
9746191e49dSAndy Shevchenko 			case 0:
9756191e49dSAndy Shevchenko 				db_pulse = 0;
9766191e49dSAndy Shevchenko 				break;
977658b476cSCristina Ciocan 			case 375:
9784cfff5b7SRaag Jadav 				db_pulse = BYT_DEBOUNCE_PULSE_375US;
979658b476cSCristina Ciocan 				break;
980658b476cSCristina Ciocan 			case 750:
9814cfff5b7SRaag Jadav 				db_pulse = BYT_DEBOUNCE_PULSE_750US;
982658b476cSCristina Ciocan 				break;
983658b476cSCristina Ciocan 			case 1500:
9844cfff5b7SRaag Jadav 				db_pulse = BYT_DEBOUNCE_PULSE_1500US;
985658b476cSCristina Ciocan 				break;
986658b476cSCristina Ciocan 			case 3000:
9874cfff5b7SRaag Jadav 				db_pulse = BYT_DEBOUNCE_PULSE_3MS;
988658b476cSCristina Ciocan 				break;
989658b476cSCristina Ciocan 			case 6000:
9904cfff5b7SRaag Jadav 				db_pulse = BYT_DEBOUNCE_PULSE_6MS;
991658b476cSCristina Ciocan 				break;
992658b476cSCristina Ciocan 			case 12000:
9934cfff5b7SRaag Jadav 				db_pulse = BYT_DEBOUNCE_PULSE_12MS;
994658b476cSCristina Ciocan 				break;
995658b476cSCristina Ciocan 			case 24000:
9964cfff5b7SRaag Jadav 				db_pulse = BYT_DEBOUNCE_PULSE_24MS;
997658b476cSCristina Ciocan 				break;
998658b476cSCristina Ciocan 			default:
9996191e49dSAndy Shevchenko 				return -EINVAL;
1000658b476cSCristina Ciocan 			}
1001658b476cSCristina Ciocan 
10026191e49dSAndy Shevchenko 			if (db_pulse) {
10034cfff5b7SRaag Jadav 				debounce = readl(db_reg);
10044cfff5b7SRaag Jadav 				debounce = (debounce & ~BYT_DEBOUNCE_PULSE_MASK) | db_pulse;
100504ff5a09SAndy Shevchenko 				writel(debounce, db_reg);
10064cfff5b7SRaag Jadav 
10076191e49dSAndy Shevchenko 				conf |= BYT_DEBOUNCE_EN;
10086191e49dSAndy Shevchenko 			} else {
10096191e49dSAndy Shevchenko 				conf &= ~BYT_DEBOUNCE_EN;
10106191e49dSAndy Shevchenko 			}
10116191e49dSAndy Shevchenko 
1012658b476cSCristina Ciocan 			break;
1013c501d0b1SCristina Ciocan 		default:
10146191e49dSAndy Shevchenko 			return -ENOTSUPP;
10156191e49dSAndy Shevchenko 		}
1016c501d0b1SCristina Ciocan 	}
1017c501d0b1SCristina Ciocan 
1018c501d0b1SCristina Ciocan 	writel(conf, conf_reg);
1019c501d0b1SCristina Ciocan 
10206191e49dSAndy Shevchenko 	return 0;
1021c501d0b1SCristina Ciocan }
1022c501d0b1SCristina Ciocan 
1023c501d0b1SCristina Ciocan static const struct pinconf_ops byt_pinconf_ops = {
1024c501d0b1SCristina Ciocan 	.is_generic	= true,
1025c501d0b1SCristina Ciocan 	.pin_config_get	= byt_pin_config_get,
1026c501d0b1SCristina Ciocan 	.pin_config_set	= byt_pin_config_set,
1027c501d0b1SCristina Ciocan };
1028c501d0b1SCristina Ciocan 
1029c501d0b1SCristina Ciocan static const struct pinctrl_desc byt_pinctrl_desc = {
1030c501d0b1SCristina Ciocan 	.pctlops	= &byt_pinctrl_ops,
1031c501d0b1SCristina Ciocan 	.pmxops		= &byt_pinmux_ops,
1032c501d0b1SCristina Ciocan 	.confops	= &byt_pinconf_ops,
1033c501d0b1SCristina Ciocan 	.owner		= THIS_MODULE,
1034c501d0b1SCristina Ciocan };
1035c501d0b1SCristina Ciocan 
byt_gpio_get(struct gpio_chip * chip,unsigned int offset)1036939330d7SAndy Shevchenko static int byt_gpio_get(struct gpio_chip *chip, unsigned int offset)
1037a5d811bbSMathias Nyman {
10385d33e0ebSAndy Shevchenko 	struct intel_pinctrl *vg = gpiochip_get_data(chip);
1039c501d0b1SCristina Ciocan 	void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
104039ce8150SMika Westerberg 	u32 val;
104139ce8150SMika Westerberg 
10426191e49dSAndy Shevchenko 	scoped_guard(raw_spinlock_irqsave, &byt_lock)
104339ce8150SMika Westerberg 		val = readl(reg);
104439ce8150SMika Westerberg 
10453bde8771SLinus Walleij 	return !!(val & BYT_LEVEL);
1046a5d811bbSMathias Nyman }
1047a5d811bbSMathias Nyman 
byt_gpio_set(struct gpio_chip * chip,unsigned int offset,int value)10484863d750SBartosz Golaszewski static int byt_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
1049a5d811bbSMathias Nyman {
10505d33e0ebSAndy Shevchenko 	struct intel_pinctrl *vg = gpiochip_get_data(chip);
10516191e49dSAndy Shevchenko 	void __iomem *reg;
1052a5d811bbSMathias Nyman 	u32 old_val;
1053a5d811bbSMathias Nyman 
10546191e49dSAndy Shevchenko 	reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
105586e3ef81SCristina Ciocan 	if (!reg)
10564863d750SBartosz Golaszewski 		return -EINVAL;
105786e3ef81SCristina Ciocan 
10586191e49dSAndy Shevchenko 	guard(raw_spinlock_irqsave)(&byt_lock);
10596191e49dSAndy Shevchenko 
1060a5d811bbSMathias Nyman 	old_val = readl(reg);
1061a5d811bbSMathias Nyman 	if (value)
1062a5d811bbSMathias Nyman 		writel(old_val | BYT_LEVEL, reg);
1063a5d811bbSMathias Nyman 	else
1064a5d811bbSMathias Nyman 		writel(old_val & ~BYT_LEVEL, reg);
10654863d750SBartosz Golaszewski 
10664863d750SBartosz Golaszewski 	return 0;
1067a5d811bbSMathias Nyman }
1068a5d811bbSMathias Nyman 
byt_gpio_get_direction(struct gpio_chip * chip,unsigned int offset)106986e3ef81SCristina Ciocan static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
1070a5d811bbSMathias Nyman {
10715d33e0ebSAndy Shevchenko 	struct intel_pinctrl *vg = gpiochip_get_data(chip);
10726191e49dSAndy Shevchenko 	void __iomem *reg;
1073a5d811bbSMathias Nyman 	u32 value;
1074a5d811bbSMathias Nyman 
10756191e49dSAndy Shevchenko 	reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
107686e3ef81SCristina Ciocan 	if (!reg)
107786e3ef81SCristina Ciocan 		return -EINVAL;
107886e3ef81SCristina Ciocan 
10796191e49dSAndy Shevchenko 	scoped_guard(raw_spinlock_irqsave, &byt_lock)
108086e3ef81SCristina Ciocan 		value = readl(reg);
1081a5d811bbSMathias Nyman 
108286e3ef81SCristina Ciocan 	if (!(value & BYT_OUTPUT_EN))
1083faf86c0cSMatti Vaittinen 		return GPIO_LINE_DIRECTION_OUT;
108486e3ef81SCristina Ciocan 	if (!(value & BYT_INPUT_EN))
1085faf86c0cSMatti Vaittinen 		return GPIO_LINE_DIRECTION_IN;
108686e3ef81SCristina Ciocan 
108786e3ef81SCristina Ciocan 	return -EINVAL;
1088a5d811bbSMathias Nyman }
1089a5d811bbSMathias Nyman 
byt_gpio_direction_input(struct gpio_chip * chip,unsigned int offset)109086e3ef81SCristina Ciocan static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
1091a5d811bbSMathias Nyman {
1092156abe29SHans de Goede 	struct intel_pinctrl *vg = gpiochip_get_data(chip);
1093156abe29SHans de Goede 	void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
1094156abe29SHans de Goede 	u32 reg;
1095156abe29SHans de Goede 
10966191e49dSAndy Shevchenko 	guard(raw_spinlock_irqsave)(&byt_lock);
1097156abe29SHans de Goede 
1098156abe29SHans de Goede 	reg = readl(val_reg);
1099156abe29SHans de Goede 	reg &= ~BYT_DIR_MASK;
1100156abe29SHans de Goede 	reg |= BYT_OUTPUT_EN;
1101156abe29SHans de Goede 	writel(reg, val_reg);
1102156abe29SHans de Goede 
1103156abe29SHans de Goede 	return 0;
110486e3ef81SCristina Ciocan }
1105496940c1SAndy Shevchenko 
1106156abe29SHans de Goede /*
1107156abe29SHans de Goede  * Note despite the temptation this MUST NOT be converted into a call to
1108156abe29SHans de Goede  * pinctrl_gpio_direction_output() + byt_gpio_set() that does not work this
1109156abe29SHans de Goede  * MUST be done as a single BYT_VAL_REG register write.
1110156abe29SHans de Goede  * See the commit message of the commit adding this comment for details.
1111156abe29SHans de Goede  */
byt_gpio_direction_output(struct gpio_chip * chip,unsigned int offset,int value)111286e3ef81SCristina Ciocan static int byt_gpio_direction_output(struct gpio_chip *chip,
111386e3ef81SCristina Ciocan 				     unsigned int offset, int value)
111486e3ef81SCristina Ciocan {
1115156abe29SHans de Goede 	struct intel_pinctrl *vg = gpiochip_get_data(chip);
1116156abe29SHans de Goede 	void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
1117156abe29SHans de Goede 	u32 reg;
1118a5d811bbSMathias Nyman 
11196191e49dSAndy Shevchenko 	guard(raw_spinlock_irqsave)(&byt_lock);
112086e3ef81SCristina Ciocan 
1121156abe29SHans de Goede 	byt_gpio_direct_irq_check(vg, offset);
1122a5d811bbSMathias Nyman 
1123156abe29SHans de Goede 	reg = readl(val_reg);
1124156abe29SHans de Goede 	reg &= ~BYT_DIR_MASK;
1125156abe29SHans de Goede 	if (value)
1126156abe29SHans de Goede 		reg |= BYT_LEVEL;
1127156abe29SHans de Goede 	else
1128156abe29SHans de Goede 		reg &= ~BYT_LEVEL;
1129156abe29SHans de Goede 
1130156abe29SHans de Goede 	writel(reg, val_reg);
1131156abe29SHans de Goede 
1132a5d811bbSMathias Nyman 	return 0;
1133a5d811bbSMathias Nyman }
1134a5d811bbSMathias Nyman 
byt_gpio_dbg_show(struct seq_file * s,struct gpio_chip * chip)1135a5d811bbSMathias Nyman static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
1136a5d811bbSMathias Nyman {
11375d33e0ebSAndy Shevchenko 	struct intel_pinctrl *vg = gpiochip_get_data(chip);
1138a5d811bbSMathias Nyman 	int i;
113986e3ef81SCristina Ciocan 	u32 conf0, val;
1140a5d811bbSMathias Nyman 
11415d33e0ebSAndy Shevchenko 	for (i = 0; i < vg->soc->npins; i++) {
114234e65670SAndy Shevchenko 		const struct intel_community *comm;
11435a9fa4c2SRaag Jadav 		void __iomem *conf_reg, *val_reg;
11443ff95885SMika Westerberg 		const char *pull_str = NULL;
11453ff95885SMika Westerberg 		const char *pull = NULL;
114686e3ef81SCristina Ciocan 		unsigned int pin;
114778e1c896SMika Westerberg 
11485d33e0ebSAndy Shevchenko 		pin = vg->soc->pins[i].number;
114986e3ef81SCristina Ciocan 
11505a9fa4c2SRaag Jadav 		conf_reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
11515a9fa4c2SRaag Jadav 		if (!conf_reg) {
11525a9fa4c2SRaag Jadav 			seq_printf(s, "Pin %i: can't retrieve CONF0\n", pin);
115322bbd21bSDan Carpenter 			continue;
115486e3ef81SCristina Ciocan 		}
11555a9fa4c2SRaag Jadav 
11565a9fa4c2SRaag Jadav 		val_reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
11575a9fa4c2SRaag Jadav 		if (!val_reg) {
11585a9fa4c2SRaag Jadav 			seq_printf(s, "Pin %i: can't retrieve VAL\n", pin);
11595a9fa4c2SRaag Jadav 			continue;
11605a9fa4c2SRaag Jadav 		}
11615a9fa4c2SRaag Jadav 
11626191e49dSAndy Shevchenko 		scoped_guard(raw_spinlock_irqsave, &byt_lock) {
11635a9fa4c2SRaag Jadav 			conf0 = readl(conf_reg);
11645a9fa4c2SRaag Jadav 			val = readl(val_reg);
11656191e49dSAndy Shevchenko 		}
1166a5d811bbSMathias Nyman 
11674d01688fSRaag Jadav 		comm = intel_get_community(vg, pin);
116886e3ef81SCristina Ciocan 		if (!comm) {
1169b9e18434SAndy Shevchenko 			seq_printf(s, "Pin %i: can't retrieve community\n", pin);
117086e3ef81SCristina Ciocan 			continue;
117186e3ef81SCristina Ciocan 		}
1172c73505c8SBartosz Golaszewski 
1173c73505c8SBartosz Golaszewski 		char *label __free(kfree) = gpiochip_dup_line_label(chip, i);
1174c73505c8SBartosz Golaszewski 		if (IS_ERR(label))
1175c73505c8SBartosz Golaszewski 			continue;
1176a4d8d6daSMathias Nyman 
11773ff95885SMika Westerberg 		switch (conf0 & BYT_PULL_ASSIGN_MASK) {
11783ff95885SMika Westerberg 		case BYT_PULL_ASSIGN_UP:
11793ff95885SMika Westerberg 			pull = "up";
11803ff95885SMika Westerberg 			break;
11813ff95885SMika Westerberg 		case BYT_PULL_ASSIGN_DOWN:
11823ff95885SMika Westerberg 			pull = "down";
11833ff95885SMika Westerberg 			break;
11843ff95885SMika Westerberg 		}
11853ff95885SMika Westerberg 
11863ff95885SMika Westerberg 		switch (conf0 & BYT_PULL_STR_MASK) {
11873ff95885SMika Westerberg 		case BYT_PULL_STR_2K:
11883ff95885SMika Westerberg 			pull_str = "2k";
11893ff95885SMika Westerberg 			break;
11903ff95885SMika Westerberg 		case BYT_PULL_STR_10K:
11913ff95885SMika Westerberg 			pull_str = "10k";
11923ff95885SMika Westerberg 			break;
11933ff95885SMika Westerberg 		case BYT_PULL_STR_20K:
11943ff95885SMika Westerberg 			pull_str = "20k";
11953ff95885SMika Westerberg 			break;
11963ff95885SMika Westerberg 		case BYT_PULL_STR_40K:
11973ff95885SMika Westerberg 			pull_str = "40k";
11983ff95885SMika Westerberg 			break;
11993ff95885SMika Westerberg 		}
12003ff95885SMika Westerberg 
1201a5d811bbSMathias Nyman 		seq_printf(s,
12023ff95885SMika Westerberg 			   " gpio-%-3d (%-20.20s) %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s",
120386e3ef81SCristina Ciocan 			   pin,
1204c73505c8SBartosz Golaszewski 			   label ?: "Unrequested",
1205a5d811bbSMathias Nyman 			   val & BYT_INPUT_EN ? "  " : "in",
1206a5d811bbSMathias Nyman 			   val & BYT_OUTPUT_EN ? "   " : "out",
1207c518d31bSAndy Shevchenko 			   str_hi_lo(val & BYT_LEVEL),
12083655a1caSAlexander Stein 			   comm->pad_map[i], comm->pad_map[i] * 16,
1209a5d811bbSMathias Nyman 			   conf0 & 0x7,
1210a5d811bbSMathias Nyman 			   conf0 & BYT_TRIG_NEG ? " fall" : "     ",
1211a5d811bbSMathias Nyman 			   conf0 & BYT_TRIG_POS ? " rise" : "     ",
12121583449eSAndy Shevchenko 			   conf0 & BYT_TRIG_LVL ? " level" : "      ");
12133ff95885SMika Westerberg 
12143ff95885SMika Westerberg 		if (pull && pull_str)
12153ff95885SMika Westerberg 			seq_printf(s, " %-4s %-3s", pull, pull_str);
12163ff95885SMika Westerberg 		else
12173ff95885SMika Westerberg 			seq_puts(s, "          ");
12183ff95885SMika Westerberg 
12193ff95885SMika Westerberg 		if (conf0 & BYT_IODEN)
12203ff95885SMika Westerberg 			seq_puts(s, " open-drain");
12213ff95885SMika Westerberg 
12223ff95885SMika Westerberg 		seq_puts(s, "\n");
1223a5d811bbSMathias Nyman 	}
1224a5d811bbSMathias Nyman }
1225a5d811bbSMathias Nyman 
122686e3ef81SCristina Ciocan static const struct gpio_chip byt_gpio_chip = {
122786e3ef81SCristina Ciocan 	.owner			= THIS_MODULE,
122886e3ef81SCristina Ciocan 	.request		= gpiochip_generic_request,
122986e3ef81SCristina Ciocan 	.free			= gpiochip_generic_free,
123086e3ef81SCristina Ciocan 	.get_direction		= byt_gpio_get_direction,
123186e3ef81SCristina Ciocan 	.direction_input	= byt_gpio_direction_input,
123286e3ef81SCristina Ciocan 	.direction_output	= byt_gpio_direction_output,
123386e3ef81SCristina Ciocan 	.get			= byt_gpio_get,
1234*d9d87d90SBartosz Golaszewski 	.set			= byt_gpio_set,
1235ccd025eaSAndy Shevchenko 	.set_config		= gpiochip_generic_config,
123686e3ef81SCristina Ciocan 	.dbg_show		= byt_gpio_dbg_show,
123786e3ef81SCristina Ciocan };
123886e3ef81SCristina Ciocan 
byt_irq_ack(struct irq_data * d)123931e4329fSMika Westerberg static void byt_irq_ack(struct irq_data *d)
124031e4329fSMika Westerberg {
124131e4329fSMika Westerberg 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
12425d33e0ebSAndy Shevchenko 	struct intel_pinctrl *vg = gpiochip_get_data(gc);
12436d209b42SAndy Shevchenko 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
124431e4329fSMika Westerberg 	void __iomem *reg;
124531e4329fSMika Westerberg 
12466d209b42SAndy Shevchenko 	reg = byt_gpio_reg(vg, hwirq, BYT_INT_STAT_REG);
12479f573b98SCristina Ciocan 	if (!reg)
12489f573b98SCristina Ciocan 		return;
12499f573b98SCristina Ciocan 
12506191e49dSAndy Shevchenko 	guard(raw_spinlock)(&byt_lock);
12516191e49dSAndy Shevchenko 
12526d209b42SAndy Shevchenko 	writel(BIT(hwirq % 32), reg);
125331e4329fSMika Westerberg }
125431e4329fSMika Westerberg 
byt_irq_mask(struct irq_data * d)12559f573b98SCristina Ciocan static void byt_irq_mask(struct irq_data *d)
12569f573b98SCristina Ciocan {
12579f573b98SCristina Ciocan 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
12585d33e0ebSAndy Shevchenko 	struct intel_pinctrl *vg = gpiochip_get_data(gc);
12596d209b42SAndy Shevchenko 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
12609f573b98SCristina Ciocan 
12616d209b42SAndy Shevchenko 	byt_gpio_clear_triggering(vg, hwirq);
12626d209b42SAndy Shevchenko 	gpiochip_disable_irq(gc, hwirq);
12639f573b98SCristina Ciocan }
12649f573b98SCristina Ciocan 
byt_irq_unmask(struct irq_data * d)1265a5d811bbSMathias Nyman static void byt_irq_unmask(struct irq_data *d)
1266a5d811bbSMathias Nyman {
126731e4329fSMika Westerberg 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
12685d33e0ebSAndy Shevchenko 	struct intel_pinctrl *vg = gpiochip_get_data(gc);
12696d209b42SAndy Shevchenko 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
127031e4329fSMika Westerberg 	void __iomem *reg;
127131e4329fSMika Westerberg 	u32 value;
127231e4329fSMika Westerberg 
12736d209b42SAndy Shevchenko 	gpiochip_enable_irq(gc, hwirq);
12746d209b42SAndy Shevchenko 
12756d209b42SAndy Shevchenko 	reg = byt_gpio_reg(vg, hwirq, BYT_CONF0_REG);
12769f573b98SCristina Ciocan 	if (!reg)
12779f573b98SCristina Ciocan 		return;
127878e1c896SMika Westerberg 
12796191e49dSAndy Shevchenko 	guard(raw_spinlock_irqsave)(&byt_lock);
12806191e49dSAndy Shevchenko 
128131e4329fSMika Westerberg 	value = readl(reg);
128231e4329fSMika Westerberg 
128331e4329fSMika Westerberg 	switch (irqd_get_trigger_type(d)) {
128431e4329fSMika Westerberg 	case IRQ_TYPE_LEVEL_HIGH:
128531e4329fSMika Westerberg 		value |= BYT_TRIG_LVL;
12860a093020SGustavo A. R. Silva 		fallthrough;
128731e4329fSMika Westerberg 	case IRQ_TYPE_EDGE_RISING:
128831e4329fSMika Westerberg 		value |= BYT_TRIG_POS;
128931e4329fSMika Westerberg 		break;
129031e4329fSMika Westerberg 	case IRQ_TYPE_LEVEL_LOW:
129131e4329fSMika Westerberg 		value |= BYT_TRIG_LVL;
12920a093020SGustavo A. R. Silva 		fallthrough;
129331e4329fSMika Westerberg 	case IRQ_TYPE_EDGE_FALLING:
129431e4329fSMika Westerberg 		value |= BYT_TRIG_NEG;
129531e4329fSMika Westerberg 		break;
129631e4329fSMika Westerberg 	case IRQ_TYPE_EDGE_BOTH:
129731e4329fSMika Westerberg 		value |= (BYT_TRIG_NEG | BYT_TRIG_POS);
129831e4329fSMika Westerberg 		break;
129931e4329fSMika Westerberg 	}
130031e4329fSMika Westerberg 
130131e4329fSMika Westerberg 	writel(value, reg);
1302a5d811bbSMathias Nyman }
1303a5d811bbSMathias Nyman 
byt_irq_type(struct irq_data * d,unsigned int type)13049f573b98SCristina Ciocan static int byt_irq_type(struct irq_data *d, unsigned int type)
1305a5d811bbSMathias Nyman {
13065d33e0ebSAndy Shevchenko 	struct intel_pinctrl *vg = gpiochip_get_data(irq_data_get_irq_chip_data(d));
13076d209b42SAndy Shevchenko 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
13086d209b42SAndy Shevchenko 	void __iomem *reg;
13096191e49dSAndy Shevchenko 	u32 value;
131031e4329fSMika Westerberg 
13116d209b42SAndy Shevchenko 	reg = byt_gpio_reg(vg, hwirq, BYT_CONF0_REG);
13126d209b42SAndy Shevchenko 	if (!reg)
13139f573b98SCristina Ciocan 		return -EINVAL;
13149f573b98SCristina Ciocan 
13156191e49dSAndy Shevchenko 	guard(raw_spinlock_irqsave)(&byt_lock);
13166191e49dSAndy Shevchenko 
13179f573b98SCristina Ciocan 	value = readl(reg);
13189f573b98SCristina Ciocan 
13199f573b98SCristina Ciocan 	WARN(value & BYT_DIRECT_IRQ_EN,
1320b9e18434SAndy Shevchenko 	     "Bad pad config for IO mode, force DIRECT_IRQ_EN bit clearing");
13219f573b98SCristina Ciocan 
13229f573b98SCristina Ciocan 	/* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits
13239f573b98SCristina Ciocan 	 * are used to indicate high and low level triggering
13249f573b98SCristina Ciocan 	 */
13259f573b98SCristina Ciocan 	value &= ~(BYT_DIRECT_IRQ_EN | BYT_TRIG_POS | BYT_TRIG_NEG |
13269f573b98SCristina Ciocan 		   BYT_TRIG_LVL);
13279291c65bSHans de Goede 	/* Enable glitch filtering */
13289291c65bSHans de Goede 	value |= BYT_GLITCH_FILTER_EN | BYT_GLITCH_F_SLOW_CLK |
13299291c65bSHans de Goede 		 BYT_GLITCH_F_FAST_CLK;
13309f573b98SCristina Ciocan 
13319f573b98SCristina Ciocan 	writel(value, reg);
13329f573b98SCristina Ciocan 
13339f573b98SCristina Ciocan 	if (type & IRQ_TYPE_EDGE_BOTH)
13349f573b98SCristina Ciocan 		irq_set_handler_locked(d, handle_edge_irq);
13359f573b98SCristina Ciocan 	else if (type & IRQ_TYPE_LEVEL_MASK)
13369f573b98SCristina Ciocan 		irq_set_handler_locked(d, handle_level_irq);
13379f573b98SCristina Ciocan 
13389f573b98SCristina Ciocan 	return 0;
1339a5d811bbSMathias Nyman }
1340a5d811bbSMathias Nyman 
13416d209b42SAndy Shevchenko static const struct irq_chip byt_gpio_irq_chip = {
13426d209b42SAndy Shevchenko 	.name		= "BYT-GPIO",
13436d209b42SAndy Shevchenko 	.irq_ack	= byt_irq_ack,
13446d209b42SAndy Shevchenko 	.irq_mask	= byt_irq_mask,
13456d209b42SAndy Shevchenko 	.irq_unmask	= byt_irq_unmask,
13466d209b42SAndy Shevchenko 	.irq_set_type	= byt_irq_type,
13476d209b42SAndy Shevchenko 	.flags		= IRQCHIP_SKIP_SET_WAKE | IRQCHIP_SET_TYPE_MASKED | IRQCHIP_IMMUTABLE,
13486d209b42SAndy Shevchenko 	GPIOCHIP_IRQ_RESOURCE_HELPERS,
13496d209b42SAndy Shevchenko };
13506d209b42SAndy Shevchenko 
byt_gpio_irq_handler(struct irq_desc * desc)135171e6ca61SCristina Ciocan static void byt_gpio_irq_handler(struct irq_desc *desc)
135271e6ca61SCristina Ciocan {
135371e6ca61SCristina Ciocan 	struct irq_data *data = irq_desc_get_irq_data(desc);
13545d33e0ebSAndy Shevchenko 	struct intel_pinctrl *vg = gpiochip_get_data(irq_desc_get_handler_data(desc));
135571e6ca61SCristina Ciocan 	struct irq_chip *chip = irq_data_get_irq_chip(data);
135671e6ca61SCristina Ciocan 	u32 base, pin;
135771e6ca61SCristina Ciocan 	void __iomem *reg;
135871e6ca61SCristina Ciocan 	unsigned long pending;
135971e6ca61SCristina Ciocan 
13608e54033bSAndy Shevchenko 	chained_irq_enter(chip, desc);
13618e54033bSAndy Shevchenko 
136271e6ca61SCristina Ciocan 	/* check from GPIO controller which pin triggered the interrupt */
136371e6ca61SCristina Ciocan 	for (base = 0; base < vg->chip.ngpio; base += 32) {
136471e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG);
136571e6ca61SCristina Ciocan 
136671e6ca61SCristina Ciocan 		if (!reg) {
1367b9e18434SAndy Shevchenko 			dev_warn(vg->dev, "Pin %i: can't retrieve INT_STAT%u\n", base / 32, base);
136871e6ca61SCristina Ciocan 			continue;
136971e6ca61SCristina Ciocan 		}
137071e6ca61SCristina Ciocan 
13716191e49dSAndy Shevchenko 		scoped_guard(raw_spinlock, &byt_lock)
137271e6ca61SCristina Ciocan 			pending = readl(reg);
1373a9cb09b7SMarc Zyngier 		for_each_set_bit(pin, &pending, 32)
1374a9cb09b7SMarc Zyngier 			generic_handle_domain_irq(vg->chip.irq.domain, base + pin);
137571e6ca61SCristina Ciocan 	}
13768e54033bSAndy Shevchenko 
13778e54033bSAndy Shevchenko 	chained_irq_exit(chip, desc);
137871e6ca61SCristina Ciocan }
137971e6ca61SCristina Ciocan 
byt_direct_irq_sanity_check(struct intel_pinctrl * vg,int pin,u32 conf0)1380689e0088SHans de Goede static bool byt_direct_irq_sanity_check(struct intel_pinctrl *vg, int pin, u32 conf0)
1381689e0088SHans de Goede {
1382689e0088SHans de Goede 	int direct_irq, ioapic_direct_irq_base;
1383689e0088SHans de Goede 	u8 *match, direct_irq_mux[16];
1384689e0088SHans de Goede 	u32 trig;
1385689e0088SHans de Goede 
1386689e0088SHans de Goede 	memcpy_fromio(direct_irq_mux, vg->communities->pad_regs + BYT_DIRECT_IRQ_REG,
1387689e0088SHans de Goede 		      sizeof(direct_irq_mux));
1388689e0088SHans de Goede 	match = memchr(direct_irq_mux, pin, sizeof(direct_irq_mux));
1389689e0088SHans de Goede 	if (!match) {
1390b9e18434SAndy Shevchenko 		dev_warn(vg->dev, FW_BUG "Pin %i: DIRECT_IRQ_EN set but no IRQ assigned, clearing\n", pin);
1391689e0088SHans de Goede 		return false;
1392689e0088SHans de Goede 	}
1393689e0088SHans de Goede 
1394689e0088SHans de Goede 	direct_irq = match - direct_irq_mux;
1395689e0088SHans de Goede 	/* Base IO-APIC pin numbers come from atom-e3800-family-datasheet.pdf */
1396689e0088SHans de Goede 	ioapic_direct_irq_base = (vg->communities->npins == BYT_NGPIO_SCORE) ? 51 : 67;
1397689e0088SHans de Goede 	dev_dbg(vg->dev, "Pin %i: uses direct IRQ %d (IO-APIC %d)\n", pin,
1398689e0088SHans de Goede 		direct_irq, direct_irq + ioapic_direct_irq_base);
1399689e0088SHans de Goede 
1400689e0088SHans de Goede 	/*
1401689e0088SHans de Goede 	 * Testing has shown that the way direct IRQs work is that the combination of the
1402689e0088SHans de Goede 	 * direct-irq-en flag and the direct IRQ mux connect the output of the GPIO's IRQ
1403689e0088SHans de Goede 	 * trigger block, which normally sets the status flag in the IRQ status reg at
1404689e0088SHans de Goede 	 * 0x800, to one of the IO-APIC pins according to the mux registers.
1405689e0088SHans de Goede 	 *
1406689e0088SHans de Goede 	 * This means that:
1407689e0088SHans de Goede 	 * 1. The TRIG_MASK bits must be set to configure the GPIO's IRQ trigger block
1408689e0088SHans de Goede 	 * 2. The TRIG_LVL bit *must* be set, so that the GPIO's input value is directly
1409689e0088SHans de Goede 	 *    passed (1:1 or inverted) to the IO-APIC pin, if TRIG_LVL is not set,
1410689e0088SHans de Goede 	 *    selecting edge mode operation then on the first edge the IO-APIC pin goes
1411689e0088SHans de Goede 	 *    high, but since no write-to-clear write will be done to the IRQ status reg
1412689e0088SHans de Goede 	 *    at 0x800, the detected edge condition will never get cleared.
1413689e0088SHans de Goede 	 */
1414689e0088SHans de Goede 	trig = conf0 & BYT_TRIG_MASK;
1415689e0088SHans de Goede 	if (trig != (BYT_TRIG_POS | BYT_TRIG_LVL) &&
1416689e0088SHans de Goede 	    trig != (BYT_TRIG_NEG | BYT_TRIG_LVL)) {
1417b9e18434SAndy Shevchenko 		dev_warn(vg->dev,
1418b9e18434SAndy Shevchenko 			 FW_BUG "Pin %i: DIRECT_IRQ_EN set without trigger (CONF0: %#08x), clearing\n",
1419689e0088SHans de Goede 			 pin, conf0);
1420689e0088SHans de Goede 		return false;
1421689e0088SHans de Goede 	}
1422689e0088SHans de Goede 
1423689e0088SHans de Goede 	return true;
1424689e0088SHans de Goede }
1425689e0088SHans de Goede 
byt_init_irq_valid_mask(struct gpio_chip * chip,unsigned long * valid_mask,unsigned int ngpios)14265fbe5b58SLinus Walleij static void byt_init_irq_valid_mask(struct gpio_chip *chip,
14275fbe5b58SLinus Walleij 				    unsigned long *valid_mask,
14285fbe5b58SLinus Walleij 				    unsigned int ngpios)
14295fbe5b58SLinus Walleij {
14305d33e0ebSAndy Shevchenko 	struct intel_pinctrl *vg = gpiochip_get_data(chip);
1431a5d811bbSMathias Nyman 	void __iomem *reg;
1432e70982b3SAndy Shevchenko 	u32 value;
143395f0972cSMika Westerberg 	int i;
143495f0972cSMika Westerberg 
143595f0972cSMika Westerberg 	/*
143695f0972cSMika Westerberg 	 * Clear interrupt triggers for all pins that are GPIOs and
143795f0972cSMika Westerberg 	 * do not use direct IRQ mode. This will prevent spurious
143895f0972cSMika Westerberg 	 * interrupts from misconfigured pins.
143995f0972cSMika Westerberg 	 */
14405d33e0ebSAndy Shevchenko 	for (i = 0; i < vg->soc->npins; i++) {
14415d33e0ebSAndy Shevchenko 		unsigned int pin = vg->soc->pins[i].number;
144271e6ca61SCristina Ciocan 
144371e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
144471e6ca61SCristina Ciocan 		if (!reg) {
1445b9e18434SAndy Shevchenko 			dev_warn(vg->dev, "Pin %i: could not retrieve CONF0\n", i);
144671e6ca61SCristina Ciocan 			continue;
144771e6ca61SCristina Ciocan 		}
144871e6ca61SCristina Ciocan 
144971e6ca61SCristina Ciocan 		value = readl(reg);
145049c03096SAndy Shevchenko 		if (value & BYT_DIRECT_IRQ_EN) {
1451689e0088SHans de Goede 			if (byt_direct_irq_sanity_check(vg, i, value)) {
1452e70982b3SAndy Shevchenko 				clear_bit(i, valid_mask);
1453689e0088SHans de Goede 			} else {
1454689e0088SHans de Goede 				value &= ~(BYT_DIRECT_IRQ_EN | BYT_TRIG_POS |
1455689e0088SHans de Goede 					   BYT_TRIG_NEG | BYT_TRIG_LVL);
1456689e0088SHans de Goede 				writel(value, reg);
1457689e0088SHans de Goede 			}
145849c03096SAndy Shevchenko 		} else if ((value & BYT_PIN_MUX) == byt_get_gpio_mux(vg, i)) {
145995f0972cSMika Westerberg 			byt_gpio_clear_triggering(vg, i);
1460990ec243SAndy Shevchenko 			dev_dbg(vg->dev, "disabling GPIO %d\n", i);
146195f0972cSMika Westerberg 		}
146295f0972cSMika Westerberg 	}
1463e70982b3SAndy Shevchenko }
1464e70982b3SAndy Shevchenko 
byt_gpio_irq_init_hw(struct gpio_chip * chip)1465e70982b3SAndy Shevchenko static int byt_gpio_irq_init_hw(struct gpio_chip *chip)
1466e70982b3SAndy Shevchenko {
14675d33e0ebSAndy Shevchenko 	struct intel_pinctrl *vg = gpiochip_get_data(chip);
1468e70982b3SAndy Shevchenko 	void __iomem *reg;
1469e70982b3SAndy Shevchenko 	u32 base, value;
1470a5d811bbSMathias Nyman 
1471a5d811bbSMathias Nyman 	/* clear interrupt status trigger registers */
14725d33e0ebSAndy Shevchenko 	for (base = 0; base < vg->soc->npins; base += 32) {
1473c501d0b1SCristina Ciocan 		reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG);
147471e6ca61SCristina Ciocan 
147571e6ca61SCristina Ciocan 		if (!reg) {
1476b9e18434SAndy Shevchenko 			dev_warn(vg->dev, "Pin %i: can't retrieve INT_STAT%u\n", base / 32, base);
147771e6ca61SCristina Ciocan 			continue;
147871e6ca61SCristina Ciocan 		}
147971e6ca61SCristina Ciocan 
1480a5d811bbSMathias Nyman 		writel(0xffffffff, reg);
1481a5d811bbSMathias Nyman 		/* make sure trigger bits are cleared, if not then a pin
1482a5d811bbSMathias Nyman 		   might be misconfigured in bios */
1483a5d811bbSMathias Nyman 		value = readl(reg);
1484a5d811bbSMathias Nyman 		if (value)
1485990ec243SAndy Shevchenko 			dev_err(vg->dev,
1486b9e18434SAndy Shevchenko 				"GPIO interrupt error, pins misconfigured. INT_STAT%u: %#08x\n",
1487973232e2SAlexander Stein 				base / 32, value);
1488a5d811bbSMathias Nyman 	}
1489ca8a958eSAndy Shevchenko 
1490ca8a958eSAndy Shevchenko 	return 0;
1491a5d811bbSMathias Nyman }
1492a5d811bbSMathias Nyman 
byt_gpio_add_pin_ranges(struct gpio_chip * chip)1493ed3c1564SAndy Shevchenko static int byt_gpio_add_pin_ranges(struct gpio_chip *chip)
1494ed3c1564SAndy Shevchenko {
14955d33e0ebSAndy Shevchenko 	struct intel_pinctrl *vg = gpiochip_get_data(chip);
1496990ec243SAndy Shevchenko 	struct device *dev = vg->dev;
1497ed3c1564SAndy Shevchenko 	int ret;
1498ed3c1564SAndy Shevchenko 
14995d33e0ebSAndy Shevchenko 	ret = gpiochip_add_pin_range(chip, dev_name(dev), 0, 0, vg->soc->npins);
1500ed3c1564SAndy Shevchenko 	if (ret)
1501ed3c1564SAndy Shevchenko 		dev_err(dev, "failed to add GPIO pin range\n");
1502ed3c1564SAndy Shevchenko 
1503ed3c1564SAndy Shevchenko 	return ret;
1504ed3c1564SAndy Shevchenko }
1505ed3c1564SAndy Shevchenko 
byt_gpio_probe(struct intel_pinctrl * vg)15065d33e0ebSAndy Shevchenko static int byt_gpio_probe(struct intel_pinctrl *vg)
1507a5d811bbSMathias Nyman {
1508990ec243SAndy Shevchenko 	struct platform_device *pdev = to_platform_device(vg->dev);
1509a5d811bbSMathias Nyman 	struct gpio_chip *gc;
1510f86a1bb5SAndy Shevchenko 	int irq, ret;
1511a5d811bbSMathias Nyman 
151271e6ca61SCristina Ciocan 	/* Set up gpio chip */
151371e6ca61SCristina Ciocan 	vg->chip	= byt_gpio_chip;
1514a5d811bbSMathias Nyman 	gc		= &vg->chip;
1515990ec243SAndy Shevchenko 	gc->label	= dev_name(vg->dev);
1516a5d811bbSMathias Nyman 	gc->base	= -1;
15179fb1f39eSLinus Walleij 	gc->can_sleep	= false;
1518ed3c1564SAndy Shevchenko 	gc->add_pin_ranges = byt_gpio_add_pin_ranges;
1519990ec243SAndy Shevchenko 	gc->parent	= vg->dev;
15205d33e0ebSAndy Shevchenko 	gc->ngpio	= vg->soc->npins;
1521a5d811bbSMathias Nyman 
1522fcc18debSMika Westerberg #ifdef CONFIG_PM_SLEEP
15235d33e0ebSAndy Shevchenko 	vg->context.pads = devm_kcalloc(vg->dev, gc->ngpio, sizeof(*vg->context.pads),
15245d33e0ebSAndy Shevchenko 					GFP_KERNEL);
15255d33e0ebSAndy Shevchenko 	if (!vg->context.pads)
1526d6cb7722SAditya Pakki 		return -ENOMEM;
1527fcc18debSMika Westerberg #endif
1528605a7bcaSJin Yao 
1529e1ee5c57SMika Westerberg 	/* set up interrupts  */
1530f86a1bb5SAndy Shevchenko 	irq = platform_get_irq_optional(pdev, 0);
1531f86a1bb5SAndy Shevchenko 	if (irq > 0) {
1532ca8a958eSAndy Shevchenko 		struct gpio_irq_chip *girq;
1533ca8a958eSAndy Shevchenko 
1534ca8a958eSAndy Shevchenko 		girq = &gc->irq;
15356d209b42SAndy Shevchenko 		gpio_irq_chip_set_chip(girq, &byt_gpio_irq_chip);
1536ca8a958eSAndy Shevchenko 		girq->init_hw = byt_gpio_irq_init_hw;
1537ab68b220SAndy Shevchenko 		girq->init_valid_mask = byt_init_irq_valid_mask;
1538ca8a958eSAndy Shevchenko 		girq->parent_handler = byt_gpio_irq_handler;
1539ca8a958eSAndy Shevchenko 		girq->num_parents = 1;
1540990ec243SAndy Shevchenko 		girq->parents = devm_kcalloc(vg->dev, girq->num_parents,
1541ca8a958eSAndy Shevchenko 					     sizeof(*girq->parents), GFP_KERNEL);
1542ca8a958eSAndy Shevchenko 		if (!girq->parents)
1543ca8a958eSAndy Shevchenko 			return -ENOMEM;
1544f86a1bb5SAndy Shevchenko 		girq->parents[0] = irq;
1545ca8a958eSAndy Shevchenko 		girq->default_type = IRQ_TYPE_NONE;
1546ca8a958eSAndy Shevchenko 		girq->handler = handle_bad_irq;
1547e1ee5c57SMika Westerberg 	}
1548e1ee5c57SMika Westerberg 
1549990ec243SAndy Shevchenko 	ret = devm_gpiochip_add_data(vg->dev, gc, vg);
1550bda2f1c2SAndy Shevchenko 	if (ret)
1551990ec243SAndy Shevchenko 		dev_err(vg->dev, "failed adding byt-gpio chip\n");
1552e1ee5c57SMika Westerberg 
155371e6ca61SCristina Ciocan 	return ret;
155471e6ca61SCristina Ciocan }
155571e6ca61SCristina Ciocan 
byt_set_soc_data(struct intel_pinctrl * vg,const struct intel_pinctrl_soc_data * soc)15565d33e0ebSAndy Shevchenko static int byt_set_soc_data(struct intel_pinctrl *vg,
15575d33e0ebSAndy Shevchenko 			    const struct intel_pinctrl_soc_data *soc)
155871e6ca61SCristina Ciocan {
1559990ec243SAndy Shevchenko 	struct platform_device *pdev = to_platform_device(vg->dev);
156071e6ca61SCristina Ciocan 	int i;
156171e6ca61SCristina Ciocan 
15625d33e0ebSAndy Shevchenko 	vg->soc = soc;
15635d33e0ebSAndy Shevchenko 
15645d33e0ebSAndy Shevchenko 	vg->ncommunities = vg->soc->ncommunities;
1565f192c844SRaag Jadav 	vg->communities = devm_kmemdup_array(vg->dev, vg->soc->communities, vg->ncommunities,
1566f192c844SRaag Jadav 					     sizeof(*vg->soc->communities), GFP_KERNEL);
15675d33e0ebSAndy Shevchenko 	if (!vg->communities)
156871e6ca61SCristina Ciocan 		return -ENOMEM;
156971e6ca61SCristina Ciocan 
15705d33e0ebSAndy Shevchenko 	for (i = 0; i < vg->soc->ncommunities; i++) {
15715d33e0ebSAndy Shevchenko 		struct intel_community *comm = vg->communities + i;
157271e6ca61SCristina Ciocan 
1573990ec243SAndy Shevchenko 		comm->pad_regs = devm_platform_ioremap_resource(pdev, 0);
157434e65670SAndy Shevchenko 		if (IS_ERR(comm->pad_regs))
157534e65670SAndy Shevchenko 			return PTR_ERR(comm->pad_regs);
157671e6ca61SCristina Ciocan 	}
157771e6ca61SCristina Ciocan 
157871e6ca61SCristina Ciocan 	return 0;
157971e6ca61SCristina Ciocan }
158071e6ca61SCristina Ciocan 
158171e6ca61SCristina Ciocan static const struct acpi_device_id byt_gpio_acpi_match[] = {
158271e6ca61SCristina Ciocan 	{ "INT33B2", (kernel_ulong_t)byt_soc_data },
158371e6ca61SCristina Ciocan 	{ "INT33FC", (kernel_ulong_t)byt_soc_data },
158471e6ca61SCristina Ciocan 	{ }
158571e6ca61SCristina Ciocan };
158671e6ca61SCristina Ciocan 
byt_pinctrl_probe(struct platform_device * pdev)158771e6ca61SCristina Ciocan static int byt_pinctrl_probe(struct platform_device *pdev)
158871e6ca61SCristina Ciocan {
1589ce7793e9SAndy Shevchenko 	const struct intel_pinctrl_soc_data *soc_data;
15902c02af70SAndy Shevchenko 	struct device *dev = &pdev->dev;
15915d33e0ebSAndy Shevchenko 	struct intel_pinctrl *vg;
1592ce7793e9SAndy Shevchenko 	int ret;
159371e6ca61SCristina Ciocan 
1594ce7793e9SAndy Shevchenko 	soc_data = intel_pinctrl_get_soc_data(pdev);
1595ce7793e9SAndy Shevchenko 	if (IS_ERR(soc_data))
1596ce7793e9SAndy Shevchenko 		return PTR_ERR(soc_data);
159771e6ca61SCristina Ciocan 
15982c02af70SAndy Shevchenko 	vg = devm_kzalloc(dev, sizeof(*vg), GFP_KERNEL);
159971e6ca61SCristina Ciocan 	if (!vg)
160071e6ca61SCristina Ciocan 		return -ENOMEM;
160171e6ca61SCristina Ciocan 
16022c02af70SAndy Shevchenko 	vg->dev = dev;
160371e6ca61SCristina Ciocan 	ret = byt_set_soc_data(vg, soc_data);
160471e6ca61SCristina Ciocan 	if (ret) {
16052c02af70SAndy Shevchenko 		dev_err(dev, "failed to set soc data\n");
160671e6ca61SCristina Ciocan 		return ret;
160771e6ca61SCristina Ciocan 	}
160871e6ca61SCristina Ciocan 
16095d33e0ebSAndy Shevchenko 	vg->pctldesc		= byt_pinctrl_desc;
16105d33e0ebSAndy Shevchenko 	vg->pctldesc.name	= dev_name(dev);
16115d33e0ebSAndy Shevchenko 	vg->pctldesc.pins	= vg->soc->pins;
16125d33e0ebSAndy Shevchenko 	vg->pctldesc.npins	= vg->soc->npins;
161371e6ca61SCristina Ciocan 
16145d33e0ebSAndy Shevchenko 	vg->pctldev = devm_pinctrl_register(dev, &vg->pctldesc, vg);
16155d33e0ebSAndy Shevchenko 	if (IS_ERR(vg->pctldev)) {
16162c02af70SAndy Shevchenko 		dev_err(dev, "failed to register pinctrl driver\n");
16175d33e0ebSAndy Shevchenko 		return PTR_ERR(vg->pctldev);
161871e6ca61SCristina Ciocan 	}
161971e6ca61SCristina Ciocan 
162071e6ca61SCristina Ciocan 	ret = byt_gpio_probe(vg);
16210612413fSAndy Shevchenko 	if (ret)
162271e6ca61SCristina Ciocan 		return ret;
162371e6ca61SCristina Ciocan 
162471e6ca61SCristina Ciocan 	platform_set_drvdata(pdev, vg);
162571e6ca61SCristina Ciocan 
162671e6ca61SCristina Ciocan 	return 0;
162771e6ca61SCristina Ciocan }
162871e6ca61SCristina Ciocan 
byt_gpio_suspend(struct device * dev)1629fcc18debSMika Westerberg static int byt_gpio_suspend(struct device *dev)
1630fcc18debSMika Westerberg {
16315d33e0ebSAndy Shevchenko 	struct intel_pinctrl *vg = dev_get_drvdata(dev);
1632fcc18debSMika Westerberg 	int i;
1633fcc18debSMika Westerberg 
16346191e49dSAndy Shevchenko 	guard(raw_spinlock_irqsave)(&byt_lock);
163540ecab55SHans de Goede 
16365d33e0ebSAndy Shevchenko 	for (i = 0; i < vg->soc->npins; i++) {
1637fcc18debSMika Westerberg 		void __iomem *reg;
1638fcc18debSMika Westerberg 		u32 value;
16395d33e0ebSAndy Shevchenko 		unsigned int pin = vg->soc->pins[i].number;
1640fcc18debSMika Westerberg 
164171e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
164271e6ca61SCristina Ciocan 		if (!reg) {
1643b9e18434SAndy Shevchenko 			dev_warn(vg->dev, "Pin %i: can't retrieve CONF0\n", i);
164471e6ca61SCristina Ciocan 			continue;
164571e6ca61SCristina Ciocan 		}
1646fcc18debSMika Westerberg 		value = readl(reg) & BYT_CONF0_RESTORE_MASK;
16475d33e0ebSAndy Shevchenko 		vg->context.pads[i].conf0 = value;
1648fcc18debSMika Westerberg 
164971e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
16509d49882eSRaag Jadav 		if (!reg) {
16519d49882eSRaag Jadav 			dev_warn(vg->dev, "Pin %i: can't retrieve VAL\n", i);
16529d49882eSRaag Jadav 			continue;
16539d49882eSRaag Jadav 		}
1654fcc18debSMika Westerberg 		value = readl(reg) & BYT_VAL_RESTORE_MASK;
16555d33e0ebSAndy Shevchenko 		vg->context.pads[i].val = value;
1656fcc18debSMika Westerberg 	}
1657fcc18debSMika Westerberg 
1658fcc18debSMika Westerberg 	return 0;
1659fcc18debSMika Westerberg }
1660fcc18debSMika Westerberg 
byt_gpio_resume(struct device * dev)1661fcc18debSMika Westerberg static int byt_gpio_resume(struct device *dev)
1662fcc18debSMika Westerberg {
16635d33e0ebSAndy Shevchenko 	struct intel_pinctrl *vg = dev_get_drvdata(dev);
1664fcc18debSMika Westerberg 	int i;
1665fcc18debSMika Westerberg 
16666191e49dSAndy Shevchenko 	guard(raw_spinlock_irqsave)(&byt_lock);
166740ecab55SHans de Goede 
16685d33e0ebSAndy Shevchenko 	for (i = 0; i < vg->soc->npins; i++) {
1669fcc18debSMika Westerberg 		void __iomem *reg;
1670fcc18debSMika Westerberg 		u32 value;
16715d33e0ebSAndy Shevchenko 		unsigned int pin = vg->soc->pins[i].number;
1672fcc18debSMika Westerberg 
167371e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
167471e6ca61SCristina Ciocan 		if (!reg) {
1675b9e18434SAndy Shevchenko 			dev_warn(vg->dev, "Pin %i: can't retrieve CONF0\n", i);
167671e6ca61SCristina Ciocan 			continue;
167771e6ca61SCristina Ciocan 		}
1678fcc18debSMika Westerberg 		value = readl(reg);
1679fcc18debSMika Westerberg 		if ((value & BYT_CONF0_RESTORE_MASK) !=
16805d33e0ebSAndy Shevchenko 		     vg->context.pads[i].conf0) {
1681fcc18debSMika Westerberg 			value &= ~BYT_CONF0_RESTORE_MASK;
16825d33e0ebSAndy Shevchenko 			value |= vg->context.pads[i].conf0;
1683fcc18debSMika Westerberg 			writel(value, reg);
1684b9e18434SAndy Shevchenko 			dev_info(dev, "restored pin %d CONF0 %#08x", i, value);
1685fcc18debSMika Westerberg 		}
1686fcc18debSMika Westerberg 
168771e6ca61SCristina Ciocan 		reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
16889d49882eSRaag Jadav 		if (!reg) {
16899d49882eSRaag Jadav 			dev_warn(vg->dev, "Pin %i: can't retrieve VAL\n", i);
16909d49882eSRaag Jadav 			continue;
16919d49882eSRaag Jadav 		}
1692fcc18debSMika Westerberg 		value = readl(reg);
1693fcc18debSMika Westerberg 		if ((value & BYT_VAL_RESTORE_MASK) !=
16945d33e0ebSAndy Shevchenko 		     vg->context.pads[i].val) {
1695fcc18debSMika Westerberg 			u32 v;
1696fcc18debSMika Westerberg 
1697fcc18debSMika Westerberg 			v = value & ~BYT_VAL_RESTORE_MASK;
16985d33e0ebSAndy Shevchenko 			v |= vg->context.pads[i].val;
1699fcc18debSMika Westerberg 			if (v != value) {
1700fcc18debSMika Westerberg 				writel(v, reg);
1701b9e18434SAndy Shevchenko 				dev_dbg(dev, "restored pin %d VAL %#08x\n", i, v);
1702fcc18debSMika Westerberg 			}
1703fcc18debSMika Westerberg 		}
1704fcc18debSMika Westerberg 	}
1705fcc18debSMika Westerberg 
1706fcc18debSMika Westerberg 	return 0;
1707fcc18debSMika Westerberg }
1708fcc18debSMika Westerberg 
1709a5d811bbSMathias Nyman static const struct dev_pm_ops byt_gpio_pm_ops = {
1710df660f66SAndy Shevchenko 	LATE_SYSTEM_SLEEP_PM_OPS(byt_gpio_suspend, byt_gpio_resume)
1711a5d811bbSMathias Nyman };
1712a5d811bbSMathias Nyman 
1713a5d811bbSMathias Nyman static struct platform_driver byt_gpio_driver = {
171471e6ca61SCristina Ciocan 	.probe          = byt_pinctrl_probe,
1715a5d811bbSMathias Nyman 	.driver         = {
1716a5d811bbSMathias Nyman 		.name			= "byt_gpio",
17178fd51616SRaag Jadav 		.pm			= pm_sleep_ptr(&byt_gpio_pm_ops),
1718e87daf0bSAndy Shevchenko 		.acpi_match_table	= byt_gpio_acpi_match,
1719360943a8SPaul Gortmaker 		.suppress_bind_attrs	= true,
1720a5d811bbSMathias Nyman 	},
1721a5d811bbSMathias Nyman };
1722a5d811bbSMathias Nyman 
byt_gpio_init(void)1723a5d811bbSMathias Nyman static int __init byt_gpio_init(void)
1724a5d811bbSMathias Nyman {
1725a5d811bbSMathias Nyman 	return platform_driver_register(&byt_gpio_driver);
1726a5d811bbSMathias Nyman }
1727a5d811bbSMathias Nyman subsys_initcall(byt_gpio_init);
17284d01688fSRaag Jadav 
1729cdd30ebbSPeter Zijlstra MODULE_IMPORT_NS("PINCTRL_INTEL");
1730