1875a92b3SAndy Shevchenko // SPDX-License-Identifier: GPL-2.0 25fae8b86SMika Westerberg /* 35fae8b86SMika Westerberg * Pinctrl GPIO driver for Intel Baytrail 45fae8b86SMika Westerberg * 5875a92b3SAndy Shevchenko * Copyright (c) 2012-2013, Intel Corporation 65fae8b86SMika Westerberg * Author: Mathias Nyman <mathias.nyman@linux.intel.com> 75fae8b86SMika Westerberg */ 85fae8b86SMika Westerberg 95fae8b86SMika Westerberg #include <linux/acpi.h> 10e0da3842SAndy Shevchenko #include <linux/bitops.h> 11e0da3842SAndy Shevchenko #include <linux/gpio/driver.h> 12e0da3842SAndy Shevchenko #include <linux/init.h> 13e0da3842SAndy Shevchenko #include <linux/interrupt.h> 145fae8b86SMika Westerberg #include <linux/io.h> 15e0da3842SAndy Shevchenko #include <linux/kernel.h> 16e0da3842SAndy Shevchenko #include <linux/types.h> 17e0da3842SAndy Shevchenko #include <linux/platform_device.h> 185fae8b86SMika Westerberg #include <linux/pm_runtime.h> 1961db6c9dSAndy Shevchenko #include <linux/property.h> 20e0da3842SAndy Shevchenko #include <linux/seq_file.h> 2161db6c9dSAndy Shevchenko 225fae8b86SMika Westerberg #include <linux/pinctrl/pinctrl.h> 23c501d0b1SCristina Ciocan #include <linux/pinctrl/pinmux.h> 24c501d0b1SCristina Ciocan #include <linux/pinctrl/pinconf.h> 25c501d0b1SCristina Ciocan #include <linux/pinctrl/pinconf-generic.h> 265fae8b86SMika Westerberg 274f010b93SAndy Shevchenko #include "pinctrl-intel.h" 284f010b93SAndy Shevchenko 295fae8b86SMika Westerberg /* memory mapped register offsets */ 305fae8b86SMika Westerberg #define BYT_CONF0_REG 0x000 315fae8b86SMika Westerberg #define BYT_CONF1_REG 0x004 325fae8b86SMika Westerberg #define BYT_VAL_REG 0x008 335fae8b86SMika Westerberg #define BYT_DFT_REG 0x00c 345fae8b86SMika Westerberg #define BYT_INT_STAT_REG 0x800 35689e0088SHans de Goede #define BYT_DIRECT_IRQ_REG 0x980 36658b476cSCristina Ciocan #define BYT_DEBOUNCE_REG 0x9d0 375fae8b86SMika Westerberg 385fae8b86SMika Westerberg /* BYT_CONF0_REG register bits */ 395fae8b86SMika Westerberg #define BYT_IODEN BIT(31) 405fae8b86SMika Westerberg #define BYT_DIRECT_IRQ_EN BIT(27) 41eb0a2daaSAndy Shevchenko #define BYT_TRIG_MASK GENMASK(26, 24) 425fae8b86SMika Westerberg #define BYT_TRIG_NEG BIT(26) 435fae8b86SMika Westerberg #define BYT_TRIG_POS BIT(25) 445fae8b86SMika Westerberg #define BYT_TRIG_LVL BIT(24) 45658b476cSCristina Ciocan #define BYT_DEBOUNCE_EN BIT(20) 469291c65bSHans de Goede #define BYT_GLITCH_FILTER_EN BIT(19) 479291c65bSHans de Goede #define BYT_GLITCH_F_SLOW_CLK BIT(17) 489291c65bSHans de Goede #define BYT_GLITCH_F_FAST_CLK BIT(16) 495fae8b86SMika Westerberg #define BYT_PULL_STR_SHIFT 9 50eb0a2daaSAndy Shevchenko #define BYT_PULL_STR_MASK GENMASK(10, 9) 515fae8b86SMika Westerberg #define BYT_PULL_STR_2K (0 << BYT_PULL_STR_SHIFT) 525fae8b86SMika Westerberg #define BYT_PULL_STR_10K (1 << BYT_PULL_STR_SHIFT) 535fae8b86SMika Westerberg #define BYT_PULL_STR_20K (2 << BYT_PULL_STR_SHIFT) 545fae8b86SMika Westerberg #define BYT_PULL_STR_40K (3 << BYT_PULL_STR_SHIFT) 555fae8b86SMika Westerberg #define BYT_PULL_ASSIGN_SHIFT 7 56eb0a2daaSAndy Shevchenko #define BYT_PULL_ASSIGN_MASK GENMASK(8, 7) 575fae8b86SMika Westerberg #define BYT_PULL_ASSIGN_UP (1 << BYT_PULL_ASSIGN_SHIFT) 585fae8b86SMika Westerberg #define BYT_PULL_ASSIGN_DOWN (2 << BYT_PULL_ASSIGN_SHIFT) 59eb0a2daaSAndy Shevchenko #define BYT_PIN_MUX GENMASK(2, 0) 605fae8b86SMika Westerberg 615fae8b86SMika Westerberg /* BYT_VAL_REG register bits */ 62eb0a2daaSAndy Shevchenko #define BYT_DIR_MASK GENMASK(2, 1) 635fae8b86SMika Westerberg #define BYT_INPUT_EN BIT(2) /* 0: input enabled (active low)*/ 645fae8b86SMika Westerberg #define BYT_OUTPUT_EN BIT(1) /* 0: output enabled (active low)*/ 655fae8b86SMika Westerberg #define BYT_LEVEL BIT(0) 665fae8b86SMika Westerberg 67eb0a2daaSAndy Shevchenko #define BYT_CONF0_RESTORE_MASK (BYT_DIRECT_IRQ_EN | BYT_TRIG_MASK | BYT_PIN_MUX) 68fcc18debSMika Westerberg #define BYT_VAL_RESTORE_MASK (BYT_DIR_MASK | BYT_LEVEL) 69fcc18debSMika Westerberg 70658b476cSCristina Ciocan /* BYT_DEBOUNCE_REG bits */ 71eb0a2daaSAndy Shevchenko #define BYT_DEBOUNCE_PULSE_MASK GENMASK(2, 0) 72658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_375US 1 73658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_750US 2 74658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_1500US 3 75658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_3MS 4 76658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_6MS 5 77658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_12MS 6 78658b476cSCristina Ciocan #define BYT_DEBOUNCE_PULSE_24MS 7 79658b476cSCristina Ciocan 805fae8b86SMika Westerberg #define BYT_NGPIO_SCORE 102 815fae8b86SMika Westerberg #define BYT_NGPIO_NCORE 28 825fae8b86SMika Westerberg #define BYT_NGPIO_SUS 44 835fae8b86SMika Westerberg 845fae8b86SMika Westerberg #define BYT_SCORE_ACPI_UID "1" 855fae8b86SMika Westerberg #define BYT_NCORE_ACPI_UID "2" 865fae8b86SMika Westerberg #define BYT_SUS_ACPI_UID "3" 875fae8b86SMika Westerberg 88c501d0b1SCristina Ciocan /* 89c501d0b1SCristina Ciocan * This is the function value most pins have for GPIO muxing. If the value 90c501d0b1SCristina Ciocan * differs from the default one, it must be explicitly mentioned. Otherwise, the 91c501d0b1SCristina Ciocan * pin control implementation will set the muxing value to default GPIO if it 92c501d0b1SCristina Ciocan * does not find a match for the requested function. 93c501d0b1SCristina Ciocan */ 94c501d0b1SCristina Ciocan #define BYT_DEFAULT_GPIO_MUX 0 95a705f9c1SAndy Shevchenko #define BYT_ALTER_GPIO_MUX 1 96c501d0b1SCristina Ciocan 975d33e0ebSAndy Shevchenko struct intel_pad_context { 98c8f5c4c7SCristina Ciocan u32 conf0; 99c8f5c4c7SCristina Ciocan u32 val; 100c8f5c4c7SCristina Ciocan }; 1015fae8b86SMika Westerberg 102c8f5c4c7SCristina Ciocan #define COMMUNITY(p, n, map) \ 103c8f5c4c7SCristina Ciocan { \ 104c8f5c4c7SCristina Ciocan .pin_base = (p), \ 105c8f5c4c7SCristina Ciocan .npins = (n), \ 106c8f5c4c7SCristina Ciocan .pad_map = (map),\ 107c8f5c4c7SCristina Ciocan } 108c8f5c4c7SCristina Ciocan 109c8f5c4c7SCristina Ciocan /* SCORE pins, aka GPIOC_<pin_no> or GPIO_S0_SC[<pin_no>] */ 110c8f5c4c7SCristina Ciocan static const struct pinctrl_pin_desc byt_score_pins[] = { 111c8f5c4c7SCristina Ciocan PINCTRL_PIN(0, "SATA_GP0"), 112c8f5c4c7SCristina Ciocan PINCTRL_PIN(1, "SATA_GP1"), 113c8f5c4c7SCristina Ciocan PINCTRL_PIN(2, "SATA_LED#"), 114c8f5c4c7SCristina Ciocan PINCTRL_PIN(3, "PCIE_CLKREQ0"), 115c8f5c4c7SCristina Ciocan PINCTRL_PIN(4, "PCIE_CLKREQ1"), 116c8f5c4c7SCristina Ciocan PINCTRL_PIN(5, "PCIE_CLKREQ2"), 117c8f5c4c7SCristina Ciocan PINCTRL_PIN(6, "PCIE_CLKREQ3"), 118c8f5c4c7SCristina Ciocan PINCTRL_PIN(7, "SD3_WP"), 119c8f5c4c7SCristina Ciocan PINCTRL_PIN(8, "HDA_RST"), 120c8f5c4c7SCristina Ciocan PINCTRL_PIN(9, "HDA_SYNC"), 121c8f5c4c7SCristina Ciocan PINCTRL_PIN(10, "HDA_CLK"), 122c8f5c4c7SCristina Ciocan PINCTRL_PIN(11, "HDA_SDO"), 123c8f5c4c7SCristina Ciocan PINCTRL_PIN(12, "HDA_SDI0"), 124c8f5c4c7SCristina Ciocan PINCTRL_PIN(13, "HDA_SDI1"), 125c8f5c4c7SCristina Ciocan PINCTRL_PIN(14, "GPIO_S0_SC14"), 126c8f5c4c7SCristina Ciocan PINCTRL_PIN(15, "GPIO_S0_SC15"), 127c8f5c4c7SCristina Ciocan PINCTRL_PIN(16, "MMC1_CLK"), 128c8f5c4c7SCristina Ciocan PINCTRL_PIN(17, "MMC1_D0"), 129c8f5c4c7SCristina Ciocan PINCTRL_PIN(18, "MMC1_D1"), 130c8f5c4c7SCristina Ciocan PINCTRL_PIN(19, "MMC1_D2"), 131c8f5c4c7SCristina Ciocan PINCTRL_PIN(20, "MMC1_D3"), 132c8f5c4c7SCristina Ciocan PINCTRL_PIN(21, "MMC1_D4"), 133c8f5c4c7SCristina Ciocan PINCTRL_PIN(22, "MMC1_D5"), 134c8f5c4c7SCristina Ciocan PINCTRL_PIN(23, "MMC1_D6"), 135c8f5c4c7SCristina Ciocan PINCTRL_PIN(24, "MMC1_D7"), 136c8f5c4c7SCristina Ciocan PINCTRL_PIN(25, "MMC1_CMD"), 137c8f5c4c7SCristina Ciocan PINCTRL_PIN(26, "MMC1_RST"), 138c8f5c4c7SCristina Ciocan PINCTRL_PIN(27, "SD2_CLK"), 139c8f5c4c7SCristina Ciocan PINCTRL_PIN(28, "SD2_D0"), 140c8f5c4c7SCristina Ciocan PINCTRL_PIN(29, "SD2_D1"), 141c8f5c4c7SCristina Ciocan PINCTRL_PIN(30, "SD2_D2"), 142c8f5c4c7SCristina Ciocan PINCTRL_PIN(31, "SD2_D3_CD"), 143c8f5c4c7SCristina Ciocan PINCTRL_PIN(32, "SD2_CMD"), 144c8f5c4c7SCristina Ciocan PINCTRL_PIN(33, "SD3_CLK"), 145c8f5c4c7SCristina Ciocan PINCTRL_PIN(34, "SD3_D0"), 146c8f5c4c7SCristina Ciocan PINCTRL_PIN(35, "SD3_D1"), 147c8f5c4c7SCristina Ciocan PINCTRL_PIN(36, "SD3_D2"), 148c8f5c4c7SCristina Ciocan PINCTRL_PIN(37, "SD3_D3"), 149c8f5c4c7SCristina Ciocan PINCTRL_PIN(38, "SD3_CD"), 150c8f5c4c7SCristina Ciocan PINCTRL_PIN(39, "SD3_CMD"), 151c8f5c4c7SCristina Ciocan PINCTRL_PIN(40, "SD3_1P8EN"), 152c8f5c4c7SCristina Ciocan PINCTRL_PIN(41, "SD3_PWREN#"), 153c8f5c4c7SCristina Ciocan PINCTRL_PIN(42, "ILB_LPC_AD0"), 154c8f5c4c7SCristina Ciocan PINCTRL_PIN(43, "ILB_LPC_AD1"), 155c8f5c4c7SCristina Ciocan PINCTRL_PIN(44, "ILB_LPC_AD2"), 156c8f5c4c7SCristina Ciocan PINCTRL_PIN(45, "ILB_LPC_AD3"), 157c8f5c4c7SCristina Ciocan PINCTRL_PIN(46, "ILB_LPC_FRAME"), 158c8f5c4c7SCristina Ciocan PINCTRL_PIN(47, "ILB_LPC_CLK0"), 159c8f5c4c7SCristina Ciocan PINCTRL_PIN(48, "ILB_LPC_CLK1"), 160c8f5c4c7SCristina Ciocan PINCTRL_PIN(49, "ILB_LPC_CLKRUN"), 161c8f5c4c7SCristina Ciocan PINCTRL_PIN(50, "ILB_LPC_SERIRQ"), 162c8f5c4c7SCristina Ciocan PINCTRL_PIN(51, "PCU_SMB_DATA"), 163c8f5c4c7SCristina Ciocan PINCTRL_PIN(52, "PCU_SMB_CLK"), 164c8f5c4c7SCristina Ciocan PINCTRL_PIN(53, "PCU_SMB_ALERT"), 165c8f5c4c7SCristina Ciocan PINCTRL_PIN(54, "ILB_8254_SPKR"), 166c8f5c4c7SCristina Ciocan PINCTRL_PIN(55, "GPIO_S0_SC55"), 167c8f5c4c7SCristina Ciocan PINCTRL_PIN(56, "GPIO_S0_SC56"), 168c8f5c4c7SCristina Ciocan PINCTRL_PIN(57, "GPIO_S0_SC57"), 169c8f5c4c7SCristina Ciocan PINCTRL_PIN(58, "GPIO_S0_SC58"), 170c8f5c4c7SCristina Ciocan PINCTRL_PIN(59, "GPIO_S0_SC59"), 171c8f5c4c7SCristina Ciocan PINCTRL_PIN(60, "GPIO_S0_SC60"), 172c8f5c4c7SCristina Ciocan PINCTRL_PIN(61, "GPIO_S0_SC61"), 173c8f5c4c7SCristina Ciocan PINCTRL_PIN(62, "LPE_I2S2_CLK"), 174c8f5c4c7SCristina Ciocan PINCTRL_PIN(63, "LPE_I2S2_FRM"), 175c8f5c4c7SCristina Ciocan PINCTRL_PIN(64, "LPE_I2S2_DATAIN"), 176c8f5c4c7SCristina Ciocan PINCTRL_PIN(65, "LPE_I2S2_DATAOUT"), 177c8f5c4c7SCristina Ciocan PINCTRL_PIN(66, "SIO_SPI_CS"), 178c8f5c4c7SCristina Ciocan PINCTRL_PIN(67, "SIO_SPI_MISO"), 179c8f5c4c7SCristina Ciocan PINCTRL_PIN(68, "SIO_SPI_MOSI"), 180c8f5c4c7SCristina Ciocan PINCTRL_PIN(69, "SIO_SPI_CLK"), 181c8f5c4c7SCristina Ciocan PINCTRL_PIN(70, "SIO_UART1_RXD"), 182c8f5c4c7SCristina Ciocan PINCTRL_PIN(71, "SIO_UART1_TXD"), 183c8f5c4c7SCristina Ciocan PINCTRL_PIN(72, "SIO_UART1_RTS"), 184c8f5c4c7SCristina Ciocan PINCTRL_PIN(73, "SIO_UART1_CTS"), 185c8f5c4c7SCristina Ciocan PINCTRL_PIN(74, "SIO_UART2_RXD"), 186c8f5c4c7SCristina Ciocan PINCTRL_PIN(75, "SIO_UART2_TXD"), 187c8f5c4c7SCristina Ciocan PINCTRL_PIN(76, "SIO_UART2_RTS"), 188c8f5c4c7SCristina Ciocan PINCTRL_PIN(77, "SIO_UART2_CTS"), 189c8f5c4c7SCristina Ciocan PINCTRL_PIN(78, "SIO_I2C0_DATA"), 190c8f5c4c7SCristina Ciocan PINCTRL_PIN(79, "SIO_I2C0_CLK"), 191c8f5c4c7SCristina Ciocan PINCTRL_PIN(80, "SIO_I2C1_DATA"), 192c8f5c4c7SCristina Ciocan PINCTRL_PIN(81, "SIO_I2C1_CLK"), 193c8f5c4c7SCristina Ciocan PINCTRL_PIN(82, "SIO_I2C2_DATA"), 194c8f5c4c7SCristina Ciocan PINCTRL_PIN(83, "SIO_I2C2_CLK"), 195c8f5c4c7SCristina Ciocan PINCTRL_PIN(84, "SIO_I2C3_DATA"), 196c8f5c4c7SCristina Ciocan PINCTRL_PIN(85, "SIO_I2C3_CLK"), 197c8f5c4c7SCristina Ciocan PINCTRL_PIN(86, "SIO_I2C4_DATA"), 198c8f5c4c7SCristina Ciocan PINCTRL_PIN(87, "SIO_I2C4_CLK"), 199c8f5c4c7SCristina Ciocan PINCTRL_PIN(88, "SIO_I2C5_DATA"), 200c8f5c4c7SCristina Ciocan PINCTRL_PIN(89, "SIO_I2C5_CLK"), 201c8f5c4c7SCristina Ciocan PINCTRL_PIN(90, "SIO_I2C6_DATA"), 202c8f5c4c7SCristina Ciocan PINCTRL_PIN(91, "SIO_I2C6_CLK"), 203c8f5c4c7SCristina Ciocan PINCTRL_PIN(92, "GPIO_S0_SC92"), 204c8f5c4c7SCristina Ciocan PINCTRL_PIN(93, "GPIO_S0_SC93"), 205c8f5c4c7SCristina Ciocan PINCTRL_PIN(94, "SIO_PWM0"), 206c8f5c4c7SCristina Ciocan PINCTRL_PIN(95, "SIO_PWM1"), 207c8f5c4c7SCristina Ciocan PINCTRL_PIN(96, "PMC_PLT_CLK0"), 208c8f5c4c7SCristina Ciocan PINCTRL_PIN(97, "PMC_PLT_CLK1"), 209c8f5c4c7SCristina Ciocan PINCTRL_PIN(98, "PMC_PLT_CLK2"), 210c8f5c4c7SCristina Ciocan PINCTRL_PIN(99, "PMC_PLT_CLK3"), 211c8f5c4c7SCristina Ciocan PINCTRL_PIN(100, "PMC_PLT_CLK4"), 212c8f5c4c7SCristina Ciocan PINCTRL_PIN(101, "PMC_PLT_CLK5"), 213c8f5c4c7SCristina Ciocan }; 2145fae8b86SMika Westerberg 215c8f5c4c7SCristina Ciocan static const unsigned int byt_score_pins_map[BYT_NGPIO_SCORE] = { 216c8f5c4c7SCristina Ciocan 85, 89, 93, 96, 99, 102, 98, 101, 34, 37, 217c8f5c4c7SCristina Ciocan 36, 38, 39, 35, 40, 84, 62, 61, 64, 59, 218c8f5c4c7SCristina Ciocan 54, 56, 60, 55, 63, 57, 51, 50, 53, 47, 219c8f5c4c7SCristina Ciocan 52, 49, 48, 43, 46, 41, 45, 42, 58, 44, 220c8f5c4c7SCristina Ciocan 95, 105, 70, 68, 67, 66, 69, 71, 65, 72, 221c8f5c4c7SCristina Ciocan 86, 90, 88, 92, 103, 77, 79, 83, 78, 81, 222c8f5c4c7SCristina Ciocan 80, 82, 13, 12, 15, 14, 17, 18, 19, 16, 223c8f5c4c7SCristina Ciocan 2, 1, 0, 4, 6, 7, 9, 8, 33, 32, 224c8f5c4c7SCristina Ciocan 31, 30, 29, 27, 25, 28, 26, 23, 21, 20, 225c8f5c4c7SCristina Ciocan 24, 22, 5, 3, 10, 11, 106, 87, 91, 104, 226c8f5c4c7SCristina Ciocan 97, 100, 2275fae8b86SMika Westerberg }; 2285fae8b86SMika Westerberg 229c8f5c4c7SCristina Ciocan /* SCORE groups */ 230c8f5c4c7SCristina Ciocan static const unsigned int byt_score_uart1_pins[] = { 70, 71, 72, 73 }; 231c8f5c4c7SCristina Ciocan static const unsigned int byt_score_uart2_pins[] = { 74, 75, 76, 77 }; 232c8f5c4c7SCristina Ciocan 233c8f5c4c7SCristina Ciocan static const unsigned int byt_score_pwm0_pins[] = { 94 }; 234c8f5c4c7SCristina Ciocan static const unsigned int byt_score_pwm1_pins[] = { 95 }; 235c8f5c4c7SCristina Ciocan 236c8f5c4c7SCristina Ciocan static const unsigned int byt_score_sio_spi_pins[] = { 66, 67, 68, 69 }; 237c8f5c4c7SCristina Ciocan 238c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c5_pins[] = { 88, 89 }; 239c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c6_pins[] = { 90, 91 }; 240c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c4_pins[] = { 86, 87 }; 241c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c3_pins[] = { 84, 85 }; 242c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c2_pins[] = { 82, 83 }; 243c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c1_pins[] = { 80, 81 }; 244c8f5c4c7SCristina Ciocan static const unsigned int byt_score_i2c0_pins[] = { 78, 79 }; 245c8f5c4c7SCristina Ciocan 246c8f5c4c7SCristina Ciocan static const unsigned int byt_score_ssp0_pins[] = { 8, 9, 10, 11 }; 247c8f5c4c7SCristina Ciocan static const unsigned int byt_score_ssp1_pins[] = { 12, 13, 14, 15 }; 248c8f5c4c7SCristina Ciocan static const unsigned int byt_score_ssp2_pins[] = { 62, 63, 64, 65 }; 249c8f5c4c7SCristina Ciocan 250c8f5c4c7SCristina Ciocan static const unsigned int byt_score_sdcard_pins[] = { 251c8f5c4c7SCristina Ciocan 7, 33, 34, 35, 36, 37, 38, 39, 40, 41, 252c8f5c4c7SCristina Ciocan }; 2534f010b93SAndy Shevchenko static const unsigned int byt_score_sdcard_mux_values[] = { 254c8f5c4c7SCristina Ciocan 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 255c8f5c4c7SCristina Ciocan }; 256c8f5c4c7SCristina Ciocan 257c8f5c4c7SCristina Ciocan static const unsigned int byt_score_sdio_pins[] = { 27, 28, 29, 30, 31, 32 }; 258c8f5c4c7SCristina Ciocan 259c8f5c4c7SCristina Ciocan static const unsigned int byt_score_emmc_pins[] = { 260c8f5c4c7SCristina Ciocan 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 261c8f5c4c7SCristina Ciocan }; 262c8f5c4c7SCristina Ciocan 263c8f5c4c7SCristina Ciocan static const unsigned int byt_score_ilb_lpc_pins[] = { 264c8f5c4c7SCristina Ciocan 42, 43, 44, 45, 46, 47, 48, 49, 50, 265c8f5c4c7SCristina Ciocan }; 266c8f5c4c7SCristina Ciocan 267c8f5c4c7SCristina Ciocan static const unsigned int byt_score_sata_pins[] = { 0, 1, 2 }; 268c8f5c4c7SCristina Ciocan 269c8f5c4c7SCristina Ciocan static const unsigned int byt_score_plt_clk0_pins[] = { 96 }; 270c8f5c4c7SCristina Ciocan static const unsigned int byt_score_plt_clk1_pins[] = { 97 }; 271c8f5c4c7SCristina Ciocan static const unsigned int byt_score_plt_clk2_pins[] = { 98 }; 272b41aa4f8SCristina Ciocan static const unsigned int byt_score_plt_clk3_pins[] = { 99 }; 273b41aa4f8SCristina Ciocan static const unsigned int byt_score_plt_clk4_pins[] = { 100 }; 274b41aa4f8SCristina Ciocan static const unsigned int byt_score_plt_clk5_pins[] = { 101 }; 275c8f5c4c7SCristina Ciocan 276c8f5c4c7SCristina Ciocan static const unsigned int byt_score_smbus_pins[] = { 51, 52, 53 }; 277c8f5c4c7SCristina Ciocan 2784f010b93SAndy Shevchenko static const struct intel_pingroup byt_score_groups[] = { 2794f010b93SAndy Shevchenko PIN_GROUP("uart1_grp", byt_score_uart1_pins, 1), 2804f010b93SAndy Shevchenko PIN_GROUP("uart2_grp", byt_score_uart2_pins, 1), 2814f010b93SAndy Shevchenko PIN_GROUP("pwm0_grp", byt_score_pwm0_pins, 1), 2824f010b93SAndy Shevchenko PIN_GROUP("pwm1_grp", byt_score_pwm1_pins, 1), 2834f010b93SAndy Shevchenko PIN_GROUP("ssp2_grp", byt_score_ssp2_pins, 1), 2844f010b93SAndy Shevchenko PIN_GROUP("sio_spi_grp", byt_score_sio_spi_pins, 1), 2854f010b93SAndy Shevchenko PIN_GROUP("i2c5_grp", byt_score_i2c5_pins, 1), 2864f010b93SAndy Shevchenko PIN_GROUP("i2c6_grp", byt_score_i2c6_pins, 1), 2874f010b93SAndy Shevchenko PIN_GROUP("i2c4_grp", byt_score_i2c4_pins, 1), 2884f010b93SAndy Shevchenko PIN_GROUP("i2c3_grp", byt_score_i2c3_pins, 1), 2894f010b93SAndy Shevchenko PIN_GROUP("i2c2_grp", byt_score_i2c2_pins, 1), 2904f010b93SAndy Shevchenko PIN_GROUP("i2c1_grp", byt_score_i2c1_pins, 1), 2914f010b93SAndy Shevchenko PIN_GROUP("i2c0_grp", byt_score_i2c0_pins, 1), 2924f010b93SAndy Shevchenko PIN_GROUP("ssp0_grp", byt_score_ssp0_pins, 1), 2934f010b93SAndy Shevchenko PIN_GROUP("ssp1_grp", byt_score_ssp1_pins, 1), 2944f010b93SAndy Shevchenko PIN_GROUP("sdcard_grp", byt_score_sdcard_pins, byt_score_sdcard_mux_values), 2954f010b93SAndy Shevchenko PIN_GROUP("sdio_grp", byt_score_sdio_pins, 1), 2964f010b93SAndy Shevchenko PIN_GROUP("emmc_grp", byt_score_emmc_pins, 1), 2974f010b93SAndy Shevchenko PIN_GROUP("lpc_grp", byt_score_ilb_lpc_pins, 1), 2984f010b93SAndy Shevchenko PIN_GROUP("sata_grp", byt_score_sata_pins, 1), 2994f010b93SAndy Shevchenko PIN_GROUP("plt_clk0_grp", byt_score_plt_clk0_pins, 1), 3004f010b93SAndy Shevchenko PIN_GROUP("plt_clk1_grp", byt_score_plt_clk1_pins, 1), 3014f010b93SAndy Shevchenko PIN_GROUP("plt_clk2_grp", byt_score_plt_clk2_pins, 1), 3024f010b93SAndy Shevchenko PIN_GROUP("plt_clk3_grp", byt_score_plt_clk3_pins, 1), 3034f010b93SAndy Shevchenko PIN_GROUP("plt_clk4_grp", byt_score_plt_clk4_pins, 1), 3044f010b93SAndy Shevchenko PIN_GROUP("plt_clk5_grp", byt_score_plt_clk5_pins, 1), 3054f010b93SAndy Shevchenko PIN_GROUP("smbus_grp", byt_score_smbus_pins, 1), 306c8f5c4c7SCristina Ciocan }; 307c8f5c4c7SCristina Ciocan 308c8f5c4c7SCristina Ciocan static const char * const byt_score_uart_groups[] = { 309c8f5c4c7SCristina Ciocan "uart1_grp", "uart2_grp", 310c8f5c4c7SCristina Ciocan }; 311c8f5c4c7SCristina Ciocan static const char * const byt_score_pwm_groups[] = { 312c8f5c4c7SCristina Ciocan "pwm0_grp", "pwm1_grp", 313c8f5c4c7SCristina Ciocan }; 314c8f5c4c7SCristina Ciocan static const char * const byt_score_ssp_groups[] = { 315c8f5c4c7SCristina Ciocan "ssp0_grp", "ssp1_grp", "ssp2_grp", 316c8f5c4c7SCristina Ciocan }; 317c8f5c4c7SCristina Ciocan static const char * const byt_score_spi_groups[] = { "sio_spi_grp" }; 318c8f5c4c7SCristina Ciocan static const char * const byt_score_i2c_groups[] = { 319c8f5c4c7SCristina Ciocan "i2c0_grp", "i2c1_grp", "i2c2_grp", "i2c3_grp", "i2c4_grp", "i2c5_grp", 320c8f5c4c7SCristina Ciocan "i2c6_grp", 321c8f5c4c7SCristina Ciocan }; 322c8f5c4c7SCristina Ciocan static const char * const byt_score_sdcard_groups[] = { "sdcard_grp" }; 323c8f5c4c7SCristina Ciocan static const char * const byt_score_sdio_groups[] = { "sdio_grp" }; 324c8f5c4c7SCristina Ciocan static const char * const byt_score_emmc_groups[] = { "emmc_grp" }; 325c8f5c4c7SCristina Ciocan static const char * const byt_score_lpc_groups[] = { "lpc_grp" }; 326c8f5c4c7SCristina Ciocan static const char * const byt_score_sata_groups[] = { "sata_grp" }; 327c8f5c4c7SCristina Ciocan static const char * const byt_score_plt_clk_groups[] = { 328c8f5c4c7SCristina Ciocan "plt_clk0_grp", "plt_clk1_grp", "plt_clk2_grp", "plt_clk3_grp", 329c8f5c4c7SCristina Ciocan "plt_clk4_grp", "plt_clk5_grp", 330c8f5c4c7SCristina Ciocan }; 331c8f5c4c7SCristina Ciocan static const char * const byt_score_smbus_groups[] = { "smbus_grp" }; 332c8f5c4c7SCristina Ciocan static const char * const byt_score_gpio_groups[] = { 333c8f5c4c7SCristina Ciocan "uart1_grp", "uart2_grp", "pwm0_grp", "pwm1_grp", "ssp0_grp", 334c8f5c4c7SCristina Ciocan "ssp1_grp", "ssp2_grp", "sio_spi_grp", "i2c0_grp", "i2c1_grp", 335c8f5c4c7SCristina Ciocan "i2c2_grp", "i2c3_grp", "i2c4_grp", "i2c5_grp", "i2c6_grp", 336c8f5c4c7SCristina Ciocan "sdcard_grp", "sdio_grp", "emmc_grp", "lpc_grp", "sata_grp", 337c8f5c4c7SCristina Ciocan "plt_clk0_grp", "plt_clk1_grp", "plt_clk2_grp", "plt_clk3_grp", 338c8f5c4c7SCristina Ciocan "plt_clk4_grp", "plt_clk5_grp", "smbus_grp", 339c8f5c4c7SCristina Ciocan }; 340c8f5c4c7SCristina Ciocan 3414f010b93SAndy Shevchenko static const struct intel_function byt_score_functions[] = { 342c8f5c4c7SCristina Ciocan FUNCTION("uart", byt_score_uart_groups), 343c8f5c4c7SCristina Ciocan FUNCTION("pwm", byt_score_pwm_groups), 344c8f5c4c7SCristina Ciocan FUNCTION("ssp", byt_score_ssp_groups), 345c8f5c4c7SCristina Ciocan FUNCTION("spi", byt_score_spi_groups), 346c8f5c4c7SCristina Ciocan FUNCTION("i2c", byt_score_i2c_groups), 347c8f5c4c7SCristina Ciocan FUNCTION("sdcard", byt_score_sdcard_groups), 348c8f5c4c7SCristina Ciocan FUNCTION("sdio", byt_score_sdio_groups), 349c8f5c4c7SCristina Ciocan FUNCTION("emmc", byt_score_emmc_groups), 350c8f5c4c7SCristina Ciocan FUNCTION("lpc", byt_score_lpc_groups), 351c8f5c4c7SCristina Ciocan FUNCTION("sata", byt_score_sata_groups), 352c8f5c4c7SCristina Ciocan FUNCTION("plt_clk", byt_score_plt_clk_groups), 353c8f5c4c7SCristina Ciocan FUNCTION("smbus", byt_score_smbus_groups), 354c8f5c4c7SCristina Ciocan FUNCTION("gpio", byt_score_gpio_groups), 355c8f5c4c7SCristina Ciocan }; 356c8f5c4c7SCristina Ciocan 35734e65670SAndy Shevchenko static const struct intel_community byt_score_communities[] = { 358c8f5c4c7SCristina Ciocan COMMUNITY(0, BYT_NGPIO_SCORE, byt_score_pins_map), 359c8f5c4c7SCristina Ciocan }; 360c8f5c4c7SCristina Ciocan 36134e65670SAndy Shevchenko static const struct intel_pinctrl_soc_data byt_score_soc_data = { 362c8f5c4c7SCristina Ciocan .uid = BYT_SCORE_ACPI_UID, 363c8f5c4c7SCristina Ciocan .pins = byt_score_pins, 364c8f5c4c7SCristina Ciocan .npins = ARRAY_SIZE(byt_score_pins), 365c8f5c4c7SCristina Ciocan .groups = byt_score_groups, 366c8f5c4c7SCristina Ciocan .ngroups = ARRAY_SIZE(byt_score_groups), 367c8f5c4c7SCristina Ciocan .functions = byt_score_functions, 368c8f5c4c7SCristina Ciocan .nfunctions = ARRAY_SIZE(byt_score_functions), 369c8f5c4c7SCristina Ciocan .communities = byt_score_communities, 370c8f5c4c7SCristina Ciocan .ncommunities = ARRAY_SIZE(byt_score_communities), 371c8f5c4c7SCristina Ciocan }; 372c8f5c4c7SCristina Ciocan 373c8f5c4c7SCristina Ciocan /* SUS pins, aka GPIOS_<pin_no> or GPIO_S5[<pin_no>] */ 374c8f5c4c7SCristina Ciocan static const struct pinctrl_pin_desc byt_sus_pins[] = { 375c8f5c4c7SCristina Ciocan PINCTRL_PIN(0, "GPIO_S50"), 376c8f5c4c7SCristina Ciocan PINCTRL_PIN(1, "GPIO_S51"), 377c8f5c4c7SCristina Ciocan PINCTRL_PIN(2, "GPIO_S52"), 378c8f5c4c7SCristina Ciocan PINCTRL_PIN(3, "GPIO_S53"), 379c8f5c4c7SCristina Ciocan PINCTRL_PIN(4, "GPIO_S54"), 380c8f5c4c7SCristina Ciocan PINCTRL_PIN(5, "GPIO_S55"), 381c8f5c4c7SCristina Ciocan PINCTRL_PIN(6, "GPIO_S56"), 382c8f5c4c7SCristina Ciocan PINCTRL_PIN(7, "GPIO_S57"), 383c8f5c4c7SCristina Ciocan PINCTRL_PIN(8, "GPIO_S58"), 384c8f5c4c7SCristina Ciocan PINCTRL_PIN(9, "GPIO_S59"), 385c8f5c4c7SCristina Ciocan PINCTRL_PIN(10, "GPIO_S510"), 386c8f5c4c7SCristina Ciocan PINCTRL_PIN(11, "PMC_SUSPWRDNACK"), 387c8f5c4c7SCristina Ciocan PINCTRL_PIN(12, "PMC_SUSCLK0"), 388c8f5c4c7SCristina Ciocan PINCTRL_PIN(13, "GPIO_S513"), 389c8f5c4c7SCristina Ciocan PINCTRL_PIN(14, "USB_ULPI_RST"), 390c8f5c4c7SCristina Ciocan PINCTRL_PIN(15, "PMC_WAKE_PCIE0#"), 391c8f5c4c7SCristina Ciocan PINCTRL_PIN(16, "PMC_PWRBTN"), 392c8f5c4c7SCristina Ciocan PINCTRL_PIN(17, "GPIO_S517"), 393c8f5c4c7SCristina Ciocan PINCTRL_PIN(18, "PMC_SUS_STAT"), 394c8f5c4c7SCristina Ciocan PINCTRL_PIN(19, "USB_OC0"), 395c8f5c4c7SCristina Ciocan PINCTRL_PIN(20, "USB_OC1"), 396c8f5c4c7SCristina Ciocan PINCTRL_PIN(21, "PCU_SPI_CS1"), 397c8f5c4c7SCristina Ciocan PINCTRL_PIN(22, "GPIO_S522"), 398c8f5c4c7SCristina Ciocan PINCTRL_PIN(23, "GPIO_S523"), 399c8f5c4c7SCristina Ciocan PINCTRL_PIN(24, "GPIO_S524"), 400c8f5c4c7SCristina Ciocan PINCTRL_PIN(25, "GPIO_S525"), 401c8f5c4c7SCristina Ciocan PINCTRL_PIN(26, "GPIO_S526"), 402c8f5c4c7SCristina Ciocan PINCTRL_PIN(27, "GPIO_S527"), 403c8f5c4c7SCristina Ciocan PINCTRL_PIN(28, "GPIO_S528"), 404c8f5c4c7SCristina Ciocan PINCTRL_PIN(29, "GPIO_S529"), 405c8f5c4c7SCristina Ciocan PINCTRL_PIN(30, "GPIO_S530"), 406c8f5c4c7SCristina Ciocan PINCTRL_PIN(31, "USB_ULPI_CLK"), 407c8f5c4c7SCristina Ciocan PINCTRL_PIN(32, "USB_ULPI_DATA0"), 408c8f5c4c7SCristina Ciocan PINCTRL_PIN(33, "USB_ULPI_DATA1"), 409c8f5c4c7SCristina Ciocan PINCTRL_PIN(34, "USB_ULPI_DATA2"), 410c8f5c4c7SCristina Ciocan PINCTRL_PIN(35, "USB_ULPI_DATA3"), 411c8f5c4c7SCristina Ciocan PINCTRL_PIN(36, "USB_ULPI_DATA4"), 412c8f5c4c7SCristina Ciocan PINCTRL_PIN(37, "USB_ULPI_DATA5"), 413c8f5c4c7SCristina Ciocan PINCTRL_PIN(38, "USB_ULPI_DATA6"), 414c8f5c4c7SCristina Ciocan PINCTRL_PIN(39, "USB_ULPI_DATA7"), 415c8f5c4c7SCristina Ciocan PINCTRL_PIN(40, "USB_ULPI_DIR"), 416c8f5c4c7SCristina Ciocan PINCTRL_PIN(41, "USB_ULPI_NXT"), 417c8f5c4c7SCristina Ciocan PINCTRL_PIN(42, "USB_ULPI_STP"), 418c8f5c4c7SCristina Ciocan PINCTRL_PIN(43, "USB_ULPI_REFCLK"), 419c8f5c4c7SCristina Ciocan }; 420c8f5c4c7SCristina Ciocan 421c8f5c4c7SCristina Ciocan static const unsigned int byt_sus_pins_map[BYT_NGPIO_SUS] = { 422c8f5c4c7SCristina Ciocan 29, 33, 30, 31, 32, 34, 36, 35, 38, 37, 423c8f5c4c7SCristina Ciocan 18, 7, 11, 20, 17, 1, 8, 10, 19, 12, 424c8f5c4c7SCristina Ciocan 0, 2, 23, 39, 28, 27, 22, 21, 24, 25, 425c8f5c4c7SCristina Ciocan 26, 51, 56, 54, 49, 55, 48, 57, 50, 58, 426c8f5c4c7SCristina Ciocan 52, 53, 59, 40, 427c8f5c4c7SCristina Ciocan }; 428c8f5c4c7SCristina Ciocan 429c8f5c4c7SCristina Ciocan static const unsigned int byt_sus_usb_over_current_pins[] = { 19, 20 }; 4304f010b93SAndy Shevchenko static const unsigned int byt_sus_usb_over_current_mode_values[] = { 0, 0 }; 4314f010b93SAndy Shevchenko static const unsigned int byt_sus_usb_over_current_gpio_mode_values[] = { 1, 1 }; 432c8f5c4c7SCristina Ciocan 433c8f5c4c7SCristina Ciocan static const unsigned int byt_sus_usb_ulpi_pins[] = { 434c8f5c4c7SCristina Ciocan 14, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 435c8f5c4c7SCristina Ciocan }; 4364f010b93SAndy Shevchenko static const unsigned int byt_sus_usb_ulpi_mode_values[] = { 437c8f5c4c7SCristina Ciocan 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 438c8f5c4c7SCristina Ciocan }; 4394f010b93SAndy Shevchenko static const unsigned int byt_sus_usb_ulpi_gpio_mode_values[] = { 4404f010b93SAndy Shevchenko 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 441c8f5c4c7SCristina Ciocan }; 442c8f5c4c7SCristina Ciocan 443c8f5c4c7SCristina Ciocan static const unsigned int byt_sus_pcu_spi_pins[] = { 21 }; 4444f010b93SAndy Shevchenko static const unsigned int byt_sus_pcu_spi_mode_values[] = { 0 }; 4454f010b93SAndy Shevchenko static const unsigned int byt_sus_pcu_spi_gpio_mode_values[] = { 1 }; 446c8f5c4c7SCristina Ciocan 4472f46d7f7SHans de Goede static const unsigned int byt_sus_pmu_clk1_pins[] = { 5 }; 4482f46d7f7SHans de Goede static const unsigned int byt_sus_pmu_clk2_pins[] = { 6 }; 4492f46d7f7SHans de Goede 4504f010b93SAndy Shevchenko static const struct intel_pingroup byt_sus_groups[] = { 4514f010b93SAndy Shevchenko PIN_GROUP("usb_oc_grp", byt_sus_usb_over_current_pins, byt_sus_usb_over_current_mode_values), 4524f010b93SAndy Shevchenko PIN_GROUP("usb_ulpi_grp", byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_mode_values), 4534f010b93SAndy Shevchenko PIN_GROUP("pcu_spi_grp", byt_sus_pcu_spi_pins, byt_sus_pcu_spi_mode_values), 4544f010b93SAndy Shevchenko PIN_GROUP("usb_oc_grp_gpio", byt_sus_usb_over_current_pins, byt_sus_usb_over_current_gpio_mode_values), 4554f010b93SAndy Shevchenko PIN_GROUP("usb_ulpi_grp_gpio", byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_gpio_mode_values), 4564f010b93SAndy Shevchenko PIN_GROUP("pcu_spi_grp_gpio", byt_sus_pcu_spi_pins, byt_sus_pcu_spi_gpio_mode_values), 4572f46d7f7SHans de Goede PIN_GROUP("pmu_clk1_grp", byt_sus_pmu_clk1_pins, 1), 4582f46d7f7SHans de Goede PIN_GROUP("pmu_clk2_grp", byt_sus_pmu_clk2_pins, 1), 459c8f5c4c7SCristina Ciocan }; 460c8f5c4c7SCristina Ciocan 461c8f5c4c7SCristina Ciocan static const char * const byt_sus_usb_groups[] = { 462c8f5c4c7SCristina Ciocan "usb_oc_grp", "usb_ulpi_grp", 463c8f5c4c7SCristina Ciocan }; 464c8f5c4c7SCristina Ciocan static const char * const byt_sus_spi_groups[] = { "pcu_spi_grp" }; 4652f46d7f7SHans de Goede static const char * const byt_sus_pmu_clk_groups[] = { 4662f46d7f7SHans de Goede "pmu_clk1_grp", "pmu_clk2_grp", 4672f46d7f7SHans de Goede }; 468c8f5c4c7SCristina Ciocan static const char * const byt_sus_gpio_groups[] = { 4694f010b93SAndy Shevchenko "usb_oc_grp_gpio", "usb_ulpi_grp_gpio", "pcu_spi_grp_gpio", 4702f46d7f7SHans de Goede "pmu_clk1_grp", "pmu_clk2_grp", 471c8f5c4c7SCristina Ciocan }; 472c8f5c4c7SCristina Ciocan 4734f010b93SAndy Shevchenko static const struct intel_function byt_sus_functions[] = { 474c8f5c4c7SCristina Ciocan FUNCTION("usb", byt_sus_usb_groups), 475c8f5c4c7SCristina Ciocan FUNCTION("spi", byt_sus_spi_groups), 476c8f5c4c7SCristina Ciocan FUNCTION("gpio", byt_sus_gpio_groups), 4772f46d7f7SHans de Goede FUNCTION("pmu_clk", byt_sus_pmu_clk_groups), 478c8f5c4c7SCristina Ciocan }; 479c8f5c4c7SCristina Ciocan 48034e65670SAndy Shevchenko static const struct intel_community byt_sus_communities[] = { 481c8f5c4c7SCristina Ciocan COMMUNITY(0, BYT_NGPIO_SUS, byt_sus_pins_map), 482c8f5c4c7SCristina Ciocan }; 483c8f5c4c7SCristina Ciocan 48434e65670SAndy Shevchenko static const struct intel_pinctrl_soc_data byt_sus_soc_data = { 485c8f5c4c7SCristina Ciocan .uid = BYT_SUS_ACPI_UID, 486c8f5c4c7SCristina Ciocan .pins = byt_sus_pins, 487c8f5c4c7SCristina Ciocan .npins = ARRAY_SIZE(byt_sus_pins), 488c8f5c4c7SCristina Ciocan .groups = byt_sus_groups, 489c8f5c4c7SCristina Ciocan .ngroups = ARRAY_SIZE(byt_sus_groups), 490c8f5c4c7SCristina Ciocan .functions = byt_sus_functions, 491c8f5c4c7SCristina Ciocan .nfunctions = ARRAY_SIZE(byt_sus_functions), 492c8f5c4c7SCristina Ciocan .communities = byt_sus_communities, 493c8f5c4c7SCristina Ciocan .ncommunities = ARRAY_SIZE(byt_sus_communities), 494c8f5c4c7SCristina Ciocan }; 495c8f5c4c7SCristina Ciocan 496c8f5c4c7SCristina Ciocan static const struct pinctrl_pin_desc byt_ncore_pins[] = { 497b30b736aSAndy Shevchenko PINCTRL_PIN(0, "HV_DDI0_HPD"), 498b30b736aSAndy Shevchenko PINCTRL_PIN(1, "HV_DDI0_DDC_SDA"), 499b30b736aSAndy Shevchenko PINCTRL_PIN(2, "HV_DDI0_DDC_SCL"), 500b30b736aSAndy Shevchenko PINCTRL_PIN(3, "PANEL0_VDDEN"), 501b30b736aSAndy Shevchenko PINCTRL_PIN(4, "PANEL0_BKLTEN"), 502b30b736aSAndy Shevchenko PINCTRL_PIN(5, "PANEL0_BKLTCTL"), 503b30b736aSAndy Shevchenko PINCTRL_PIN(6, "HV_DDI1_HPD"), 504b30b736aSAndy Shevchenko PINCTRL_PIN(7, "HV_DDI1_DDC_SDA"), 505b30b736aSAndy Shevchenko PINCTRL_PIN(8, "HV_DDI1_DDC_SCL"), 506b30b736aSAndy Shevchenko PINCTRL_PIN(9, "PANEL1_VDDEN"), 507b30b736aSAndy Shevchenko PINCTRL_PIN(10, "PANEL1_BKLTEN"), 508b30b736aSAndy Shevchenko PINCTRL_PIN(11, "PANEL1_BKLTCTL"), 509b30b736aSAndy Shevchenko PINCTRL_PIN(12, "GP_INTD_DSI_TE1"), 510b30b736aSAndy Shevchenko PINCTRL_PIN(13, "HV_DDI2_DDC_SDA"), 511b30b736aSAndy Shevchenko PINCTRL_PIN(14, "HV_DDI2_DDC_SCL"), 512b30b736aSAndy Shevchenko PINCTRL_PIN(15, "GP_CAMERASB00"), 513b30b736aSAndy Shevchenko PINCTRL_PIN(16, "GP_CAMERASB01"), 514b30b736aSAndy Shevchenko PINCTRL_PIN(17, "GP_CAMERASB02"), 515b30b736aSAndy Shevchenko PINCTRL_PIN(18, "GP_CAMERASB03"), 516b30b736aSAndy Shevchenko PINCTRL_PIN(19, "GP_CAMERASB04"), 517b30b736aSAndy Shevchenko PINCTRL_PIN(20, "GP_CAMERASB05"), 518b30b736aSAndy Shevchenko PINCTRL_PIN(21, "GP_CAMERASB06"), 519b30b736aSAndy Shevchenko PINCTRL_PIN(22, "GP_CAMERASB07"), 520b30b736aSAndy Shevchenko PINCTRL_PIN(23, "GP_CAMERASB08"), 521b30b736aSAndy Shevchenko PINCTRL_PIN(24, "GP_CAMERASB09"), 522b30b736aSAndy Shevchenko PINCTRL_PIN(25, "GP_CAMERASB10"), 523b30b736aSAndy Shevchenko PINCTRL_PIN(26, "GP_CAMERASB11"), 524b30b736aSAndy Shevchenko PINCTRL_PIN(27, "GP_INTD_DSI_TE2"), 525c8f5c4c7SCristina Ciocan }; 526c8f5c4c7SCristina Ciocan 527939330d7SAndy Shevchenko static const unsigned int byt_ncore_pins_map[BYT_NGPIO_NCORE] = { 528c8f5c4c7SCristina Ciocan 19, 18, 17, 20, 21, 22, 24, 25, 23, 16, 529c8f5c4c7SCristina Ciocan 14, 15, 12, 26, 27, 1, 4, 8, 11, 0, 530c8f5c4c7SCristina Ciocan 3, 6, 10, 13, 2, 5, 9, 7, 531c8f5c4c7SCristina Ciocan }; 532c8f5c4c7SCristina Ciocan 53334e65670SAndy Shevchenko static const struct intel_community byt_ncore_communities[] = { 534c8f5c4c7SCristina Ciocan COMMUNITY(0, BYT_NGPIO_NCORE, byt_ncore_pins_map), 535c8f5c4c7SCristina Ciocan }; 536c8f5c4c7SCristina Ciocan 53734e65670SAndy Shevchenko static const struct intel_pinctrl_soc_data byt_ncore_soc_data = { 538c8f5c4c7SCristina Ciocan .uid = BYT_NCORE_ACPI_UID, 539c8f5c4c7SCristina Ciocan .pins = byt_ncore_pins, 540c8f5c4c7SCristina Ciocan .npins = ARRAY_SIZE(byt_ncore_pins), 541c8f5c4c7SCristina Ciocan .communities = byt_ncore_communities, 542c8f5c4c7SCristina Ciocan .ncommunities = ARRAY_SIZE(byt_ncore_communities), 543c8f5c4c7SCristina Ciocan }; 544c8f5c4c7SCristina Ciocan 54534e65670SAndy Shevchenko static const struct intel_pinctrl_soc_data *byt_soc_data[] = { 546c8f5c4c7SCristina Ciocan &byt_score_soc_data, 547c8f5c4c7SCristina Ciocan &byt_sus_soc_data, 548c8f5c4c7SCristina Ciocan &byt_ncore_soc_data, 549166d6e2aSAndy Shevchenko NULL 550c8f5c4c7SCristina Ciocan }; 551c8f5c4c7SCristina Ciocan 55240ecab55SHans de Goede static DEFINE_RAW_SPINLOCK(byt_lock); 55340ecab55SHans de Goede 5545d33e0ebSAndy Shevchenko static struct intel_community *byt_get_community(struct intel_pinctrl *vg, 555c501d0b1SCristina Ciocan unsigned int pin) 556c501d0b1SCristina Ciocan { 55734e65670SAndy Shevchenko struct intel_community *comm; 558c501d0b1SCristina Ciocan int i; 559c501d0b1SCristina Ciocan 5605d33e0ebSAndy Shevchenko for (i = 0; i < vg->ncommunities; i++) { 5615d33e0ebSAndy Shevchenko comm = vg->communities + i; 562c501d0b1SCristina Ciocan if (pin < comm->pin_base + comm->npins && pin >= comm->pin_base) 563c501d0b1SCristina Ciocan return comm; 564c501d0b1SCristina Ciocan } 565c501d0b1SCristina Ciocan 566c501d0b1SCristina Ciocan return NULL; 567c501d0b1SCristina Ciocan } 568c501d0b1SCristina Ciocan 5695d33e0ebSAndy Shevchenko static void __iomem *byt_gpio_reg(struct intel_pinctrl *vg, unsigned int offset, 5705fae8b86SMika Westerberg int reg) 5715fae8b86SMika Westerberg { 57234e65670SAndy Shevchenko struct intel_community *comm = byt_get_community(vg, offset); 5731b89970dSAndy Shevchenko u32 reg_offset; 5745fae8b86SMika Westerberg 575c501d0b1SCristina Ciocan if (!comm) 576c501d0b1SCristina Ciocan return NULL; 577c501d0b1SCristina Ciocan 578c501d0b1SCristina Ciocan offset -= comm->pin_base; 5791b89970dSAndy Shevchenko switch (reg) { 5801b89970dSAndy Shevchenko case BYT_INT_STAT_REG: 5815fae8b86SMika Westerberg reg_offset = (offset / 32) * 4; 5821b89970dSAndy Shevchenko break; 5831b89970dSAndy Shevchenko case BYT_DEBOUNCE_REG: 5841b89970dSAndy Shevchenko reg_offset = 0; 5851b89970dSAndy Shevchenko break; 5861b89970dSAndy Shevchenko default: 587c501d0b1SCristina Ciocan reg_offset = comm->pad_map[offset] * 16; 5881b89970dSAndy Shevchenko break; 5891b89970dSAndy Shevchenko } 5905fae8b86SMika Westerberg 59134e65670SAndy Shevchenko return comm->pad_regs + reg_offset + reg; 5925fae8b86SMika Westerberg } 5935fae8b86SMika Westerberg 594c501d0b1SCristina Ciocan static int byt_get_groups_count(struct pinctrl_dev *pctldev) 59595f0972cSMika Westerberg { 5965d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev); 597c501d0b1SCristina Ciocan 5985d33e0ebSAndy Shevchenko return vg->soc->ngroups; 599c501d0b1SCristina Ciocan } 600c501d0b1SCristina Ciocan 601c501d0b1SCristina Ciocan static const char *byt_get_group_name(struct pinctrl_dev *pctldev, 602c501d0b1SCristina Ciocan unsigned int selector) 603c501d0b1SCristina Ciocan { 6045d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev); 605c501d0b1SCristina Ciocan 606*770f53d4SAndy Shevchenko return vg->soc->groups[selector].grp.name; 607c501d0b1SCristina Ciocan } 608c501d0b1SCristina Ciocan 609c501d0b1SCristina Ciocan static int byt_get_group_pins(struct pinctrl_dev *pctldev, 610c501d0b1SCristina Ciocan unsigned int selector, 611c501d0b1SCristina Ciocan const unsigned int **pins, 612c501d0b1SCristina Ciocan unsigned int *num_pins) 613c501d0b1SCristina Ciocan { 6145d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev); 615c501d0b1SCristina Ciocan 616*770f53d4SAndy Shevchenko *pins = vg->soc->groups[selector].grp.pins; 617*770f53d4SAndy Shevchenko *num_pins = vg->soc->groups[selector].grp.npins; 618c501d0b1SCristina Ciocan 619c501d0b1SCristina Ciocan return 0; 620c501d0b1SCristina Ciocan } 621c501d0b1SCristina Ciocan 622c501d0b1SCristina Ciocan static const struct pinctrl_ops byt_pinctrl_ops = { 623c501d0b1SCristina Ciocan .get_groups_count = byt_get_groups_count, 624c501d0b1SCristina Ciocan .get_group_name = byt_get_group_name, 625c501d0b1SCristina Ciocan .get_group_pins = byt_get_group_pins, 626c501d0b1SCristina Ciocan }; 627c501d0b1SCristina Ciocan 628c501d0b1SCristina Ciocan static int byt_get_functions_count(struct pinctrl_dev *pctldev) 629c501d0b1SCristina Ciocan { 6305d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev); 631c501d0b1SCristina Ciocan 6325d33e0ebSAndy Shevchenko return vg->soc->nfunctions; 633c501d0b1SCristina Ciocan } 634c501d0b1SCristina Ciocan 635c501d0b1SCristina Ciocan static const char *byt_get_function_name(struct pinctrl_dev *pctldev, 636c501d0b1SCristina Ciocan unsigned int selector) 637c501d0b1SCristina Ciocan { 6385d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev); 639c501d0b1SCristina Ciocan 6405d33e0ebSAndy Shevchenko return vg->soc->functions[selector].name; 641c501d0b1SCristina Ciocan } 642c501d0b1SCristina Ciocan 643c501d0b1SCristina Ciocan static int byt_get_function_groups(struct pinctrl_dev *pctldev, 644c501d0b1SCristina Ciocan unsigned int selector, 645c501d0b1SCristina Ciocan const char * const **groups, 646c501d0b1SCristina Ciocan unsigned int *num_groups) 647c501d0b1SCristina Ciocan { 6485d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev); 649c501d0b1SCristina Ciocan 6505d33e0ebSAndy Shevchenko *groups = vg->soc->functions[selector].groups; 6515d33e0ebSAndy Shevchenko *num_groups = vg->soc->functions[selector].ngroups; 652c501d0b1SCristina Ciocan 653c501d0b1SCristina Ciocan return 0; 654c501d0b1SCristina Ciocan } 655c501d0b1SCristina Ciocan 6565d33e0ebSAndy Shevchenko static void byt_set_group_simple_mux(struct intel_pinctrl *vg, 6574f010b93SAndy Shevchenko const struct intel_pingroup group, 6584f010b93SAndy Shevchenko unsigned int func) 659c501d0b1SCristina Ciocan { 660c501d0b1SCristina Ciocan unsigned long flags; 661c501d0b1SCristina Ciocan int i; 662c501d0b1SCristina Ciocan 66340ecab55SHans de Goede raw_spin_lock_irqsave(&byt_lock, flags); 664c501d0b1SCristina Ciocan 665*770f53d4SAndy Shevchenko for (i = 0; i < group.grp.npins; i++) { 666c501d0b1SCristina Ciocan void __iomem *padcfg0; 667c501d0b1SCristina Ciocan u32 value; 668c501d0b1SCristina Ciocan 669*770f53d4SAndy Shevchenko padcfg0 = byt_gpio_reg(vg, group.grp.pins[i], BYT_CONF0_REG); 670c501d0b1SCristina Ciocan if (!padcfg0) { 671990ec243SAndy Shevchenko dev_warn(vg->dev, 672c501d0b1SCristina Ciocan "Group %s, pin %i not muxed (no padcfg0)\n", 673*770f53d4SAndy Shevchenko group.grp.name, i); 674c501d0b1SCristina Ciocan continue; 675c501d0b1SCristina Ciocan } 676c501d0b1SCristina Ciocan 677c501d0b1SCristina Ciocan value = readl(padcfg0); 678c501d0b1SCristina Ciocan value &= ~BYT_PIN_MUX; 679c501d0b1SCristina Ciocan value |= func; 680c501d0b1SCristina Ciocan writel(value, padcfg0); 681c501d0b1SCristina Ciocan } 682c501d0b1SCristina Ciocan 68340ecab55SHans de Goede raw_spin_unlock_irqrestore(&byt_lock, flags); 684c501d0b1SCristina Ciocan } 685c501d0b1SCristina Ciocan 6865d33e0ebSAndy Shevchenko static void byt_set_group_mixed_mux(struct intel_pinctrl *vg, 6874f010b93SAndy Shevchenko const struct intel_pingroup group, 6884f010b93SAndy Shevchenko const unsigned int *func) 689c501d0b1SCristina Ciocan { 690c501d0b1SCristina Ciocan unsigned long flags; 691c501d0b1SCristina Ciocan int i; 692c501d0b1SCristina Ciocan 69340ecab55SHans de Goede raw_spin_lock_irqsave(&byt_lock, flags); 694c501d0b1SCristina Ciocan 695*770f53d4SAndy Shevchenko for (i = 0; i < group.grp.npins; i++) { 696c501d0b1SCristina Ciocan void __iomem *padcfg0; 697c501d0b1SCristina Ciocan u32 value; 698c501d0b1SCristina Ciocan 699*770f53d4SAndy Shevchenko padcfg0 = byt_gpio_reg(vg, group.grp.pins[i], BYT_CONF0_REG); 700c501d0b1SCristina Ciocan if (!padcfg0) { 701990ec243SAndy Shevchenko dev_warn(vg->dev, 702c501d0b1SCristina Ciocan "Group %s, pin %i not muxed (no padcfg0)\n", 703*770f53d4SAndy Shevchenko group.grp.name, i); 704c501d0b1SCristina Ciocan continue; 705c501d0b1SCristina Ciocan } 706c501d0b1SCristina Ciocan 707c501d0b1SCristina Ciocan value = readl(padcfg0); 708c501d0b1SCristina Ciocan value &= ~BYT_PIN_MUX; 709c501d0b1SCristina Ciocan value |= func[i]; 710c501d0b1SCristina Ciocan writel(value, padcfg0); 711c501d0b1SCristina Ciocan } 712c501d0b1SCristina Ciocan 71340ecab55SHans de Goede raw_spin_unlock_irqrestore(&byt_lock, flags); 714c501d0b1SCristina Ciocan } 715c501d0b1SCristina Ciocan 716c501d0b1SCristina Ciocan static int byt_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector, 717c501d0b1SCristina Ciocan unsigned int group_selector) 718c501d0b1SCristina Ciocan { 7195d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctldev); 7205d33e0ebSAndy Shevchenko const struct intel_function func = vg->soc->functions[func_selector]; 7215d33e0ebSAndy Shevchenko const struct intel_pingroup group = vg->soc->groups[group_selector]; 722c501d0b1SCristina Ciocan 7234f010b93SAndy Shevchenko if (group.modes) 7244f010b93SAndy Shevchenko byt_set_group_mixed_mux(vg, group, group.modes); 7254f010b93SAndy Shevchenko else if (!strcmp(func.name, "gpio")) 726c501d0b1SCristina Ciocan byt_set_group_simple_mux(vg, group, BYT_DEFAULT_GPIO_MUX); 727c501d0b1SCristina Ciocan else 7284f010b93SAndy Shevchenko byt_set_group_simple_mux(vg, group, group.mode); 729c501d0b1SCristina Ciocan 730c501d0b1SCristina Ciocan return 0; 731c501d0b1SCristina Ciocan } 732c501d0b1SCristina Ciocan 7335d33e0ebSAndy Shevchenko static u32 byt_get_gpio_mux(struct intel_pinctrl *vg, unsigned int offset) 734c501d0b1SCristina Ciocan { 735c501d0b1SCristina Ciocan /* SCORE pin 92-93 */ 7365d33e0ebSAndy Shevchenko if (!strcmp(vg->soc->uid, BYT_SCORE_ACPI_UID) && 737c501d0b1SCristina Ciocan offset >= 92 && offset <= 93) 738a705f9c1SAndy Shevchenko return BYT_ALTER_GPIO_MUX; 739c501d0b1SCristina Ciocan 740c501d0b1SCristina Ciocan /* SUS pin 11-21 */ 7415d33e0ebSAndy Shevchenko if (!strcmp(vg->soc->uid, BYT_SUS_ACPI_UID) && 742c501d0b1SCristina Ciocan offset >= 11 && offset <= 21) 743a705f9c1SAndy Shevchenko return BYT_ALTER_GPIO_MUX; 744c501d0b1SCristina Ciocan 745a705f9c1SAndy Shevchenko return BYT_DEFAULT_GPIO_MUX; 746c501d0b1SCristina Ciocan } 747c501d0b1SCristina Ciocan 7485d33e0ebSAndy Shevchenko static void byt_gpio_clear_triggering(struct intel_pinctrl *vg, unsigned int offset) 749c501d0b1SCristina Ciocan { 750c501d0b1SCristina Ciocan void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); 75195f0972cSMika Westerberg unsigned long flags; 75295f0972cSMika Westerberg u32 value; 75395f0972cSMika Westerberg 75440ecab55SHans de Goede raw_spin_lock_irqsave(&byt_lock, flags); 75595f0972cSMika Westerberg value = readl(reg); 756a2368059SHans de Goede 757a2368059SHans de Goede /* Do not clear direct-irq enabled IRQs (from gpio_disable_free) */ 758a2368059SHans de Goede if (value & BYT_DIRECT_IRQ_EN) 759a2368059SHans de Goede /* nothing to do */ ; 760a2368059SHans de Goede else 76195f0972cSMika Westerberg value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL); 762a2368059SHans de Goede 76395f0972cSMika Westerberg writel(value, reg); 76440ecab55SHans de Goede raw_spin_unlock_irqrestore(&byt_lock, flags); 76595f0972cSMika Westerberg } 76695f0972cSMika Westerberg 767c501d0b1SCristina Ciocan static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev, 768c501d0b1SCristina Ciocan struct pinctrl_gpio_range *range, 769c501d0b1SCristina Ciocan unsigned int offset) 7705fae8b86SMika Westerberg { 7715d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctl_dev); 772c501d0b1SCristina Ciocan void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); 773f8323b6bSMika Westerberg u32 value, gpio_mux; 77439ce8150SMika Westerberg unsigned long flags; 77539ce8150SMika Westerberg 77640ecab55SHans de Goede raw_spin_lock_irqsave(&byt_lock, flags); 7775fae8b86SMika Westerberg 7785fae8b86SMika Westerberg /* 7795fae8b86SMika Westerberg * In most cases, func pin mux 000 means GPIO function. 7805fae8b86SMika Westerberg * But, some pins may have func pin mux 001 represents 781f8323b6bSMika Westerberg * GPIO function. 782f8323b6bSMika Westerberg * 783f8323b6bSMika Westerberg * Because there are devices out there where some pins were not 784f8323b6bSMika Westerberg * configured correctly we allow changing the mux value from 785f8323b6bSMika Westerberg * request (but print out warning about that). 7865fae8b86SMika Westerberg */ 7875fae8b86SMika Westerberg value = readl(reg) & BYT_PIN_MUX; 788f8323b6bSMika Westerberg gpio_mux = byt_get_gpio_mux(vg, offset); 789b5894d12SHans de Goede if (gpio_mux != value) { 790f8323b6bSMika Westerberg value = readl(reg) & ~BYT_PIN_MUX; 791f8323b6bSMika Westerberg value |= gpio_mux; 792f8323b6bSMika Westerberg writel(value, reg); 793f8323b6bSMika Westerberg 794990ec243SAndy Shevchenko dev_warn(vg->dev, FW_BUG "pin %u forcibly re-configured as GPIO\n", offset); 7955fae8b86SMika Westerberg } 7965fae8b86SMika Westerberg 79740ecab55SHans de Goede raw_spin_unlock_irqrestore(&byt_lock, flags); 79839ce8150SMika Westerberg 799990ec243SAndy Shevchenko pm_runtime_get(vg->dev); 8005fae8b86SMika Westerberg 8015fae8b86SMika Westerberg return 0; 8025fae8b86SMika Westerberg } 8035fae8b86SMika Westerberg 804c501d0b1SCristina Ciocan static void byt_gpio_disable_free(struct pinctrl_dev *pctl_dev, 805c501d0b1SCristina Ciocan struct pinctrl_gpio_range *range, 806c501d0b1SCristina Ciocan unsigned int offset) 807c501d0b1SCristina Ciocan { 8085d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctl_dev); 809c501d0b1SCristina Ciocan 810c501d0b1SCristina Ciocan byt_gpio_clear_triggering(vg, offset); 811990ec243SAndy Shevchenko pm_runtime_put(vg->dev); 812c501d0b1SCristina Ciocan } 813c501d0b1SCristina Ciocan 814156abe29SHans de Goede static void byt_gpio_direct_irq_check(struct intel_pinctrl *vg, 815156abe29SHans de Goede unsigned int offset) 816156abe29SHans de Goede { 817156abe29SHans de Goede void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); 818156abe29SHans de Goede 819156abe29SHans de Goede /* 820156abe29SHans de Goede * Before making any direction modifications, do a check if gpio is set 821156abe29SHans de Goede * for direct IRQ. On Bay Trail, setting GPIO to output does not make 822156abe29SHans de Goede * sense, so let's at least inform the caller before they shoot 823156abe29SHans de Goede * themselves in the foot. 824156abe29SHans de Goede */ 825156abe29SHans de Goede if (readl(conf_reg) & BYT_DIRECT_IRQ_EN) 826156abe29SHans de Goede dev_info_once(vg->dev, "Potential Error: Setting GPIO with direct_irq_en to output"); 827156abe29SHans de Goede } 828156abe29SHans de Goede 829c501d0b1SCristina Ciocan static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev, 830c501d0b1SCristina Ciocan struct pinctrl_gpio_range *range, 831c501d0b1SCristina Ciocan unsigned int offset, 832c501d0b1SCristina Ciocan bool input) 833c501d0b1SCristina Ciocan { 8345d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctl_dev); 835c501d0b1SCristina Ciocan void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); 836c501d0b1SCristina Ciocan unsigned long flags; 837c501d0b1SCristina Ciocan u32 value; 838c501d0b1SCristina Ciocan 83940ecab55SHans de Goede raw_spin_lock_irqsave(&byt_lock, flags); 840c501d0b1SCristina Ciocan 841c501d0b1SCristina Ciocan value = readl(val_reg); 842c501d0b1SCristina Ciocan value &= ~BYT_DIR_MASK; 843c501d0b1SCristina Ciocan if (input) 844c501d0b1SCristina Ciocan value |= BYT_OUTPUT_EN; 845156abe29SHans de Goede else 846156abe29SHans de Goede byt_gpio_direct_irq_check(vg, offset); 847e2b74419SHans de Goede 848c501d0b1SCristina Ciocan writel(value, val_reg); 849c501d0b1SCristina Ciocan 85040ecab55SHans de Goede raw_spin_unlock_irqrestore(&byt_lock, flags); 851c501d0b1SCristina Ciocan 852c501d0b1SCristina Ciocan return 0; 853c501d0b1SCristina Ciocan } 854c501d0b1SCristina Ciocan 855c501d0b1SCristina Ciocan static const struct pinmux_ops byt_pinmux_ops = { 856c501d0b1SCristina Ciocan .get_functions_count = byt_get_functions_count, 857c501d0b1SCristina Ciocan .get_function_name = byt_get_function_name, 858c501d0b1SCristina Ciocan .get_function_groups = byt_get_function_groups, 859c501d0b1SCristina Ciocan .set_mux = byt_set_mux, 860c501d0b1SCristina Ciocan .gpio_request_enable = byt_gpio_request_enable, 861c501d0b1SCristina Ciocan .gpio_disable_free = byt_gpio_disable_free, 862c501d0b1SCristina Ciocan .gpio_set_direction = byt_gpio_set_direction, 863c501d0b1SCristina Ciocan }; 864c501d0b1SCristina Ciocan 865c501d0b1SCristina Ciocan static void byt_get_pull_strength(u32 reg, u16 *strength) 866c501d0b1SCristina Ciocan { 867c501d0b1SCristina Ciocan switch (reg & BYT_PULL_STR_MASK) { 868c501d0b1SCristina Ciocan case BYT_PULL_STR_2K: 869c501d0b1SCristina Ciocan *strength = 2000; 870c501d0b1SCristina Ciocan break; 871c501d0b1SCristina Ciocan case BYT_PULL_STR_10K: 872c501d0b1SCristina Ciocan *strength = 10000; 873c501d0b1SCristina Ciocan break; 874c501d0b1SCristina Ciocan case BYT_PULL_STR_20K: 875c501d0b1SCristina Ciocan *strength = 20000; 876c501d0b1SCristina Ciocan break; 877c501d0b1SCristina Ciocan case BYT_PULL_STR_40K: 878c501d0b1SCristina Ciocan *strength = 40000; 879c501d0b1SCristina Ciocan break; 880c501d0b1SCristina Ciocan } 881c501d0b1SCristina Ciocan } 882c501d0b1SCristina Ciocan 883c501d0b1SCristina Ciocan static int byt_set_pull_strength(u32 *reg, u16 strength) 884c501d0b1SCristina Ciocan { 885c501d0b1SCristina Ciocan *reg &= ~BYT_PULL_STR_MASK; 886c501d0b1SCristina Ciocan 887c501d0b1SCristina Ciocan switch (strength) { 888c501d0b1SCristina Ciocan case 2000: 889c501d0b1SCristina Ciocan *reg |= BYT_PULL_STR_2K; 890c501d0b1SCristina Ciocan break; 891c501d0b1SCristina Ciocan case 10000: 892c501d0b1SCristina Ciocan *reg |= BYT_PULL_STR_10K; 893c501d0b1SCristina Ciocan break; 894c501d0b1SCristina Ciocan case 20000: 895c501d0b1SCristina Ciocan *reg |= BYT_PULL_STR_20K; 896c501d0b1SCristina Ciocan break; 897c501d0b1SCristina Ciocan case 40000: 898c501d0b1SCristina Ciocan *reg |= BYT_PULL_STR_40K; 899c501d0b1SCristina Ciocan break; 900c501d0b1SCristina Ciocan default: 901c501d0b1SCristina Ciocan return -EINVAL; 902c501d0b1SCristina Ciocan } 903c501d0b1SCristina Ciocan 904c501d0b1SCristina Ciocan return 0; 905c501d0b1SCristina Ciocan } 906c501d0b1SCristina Ciocan 907c501d0b1SCristina Ciocan static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset, 908c501d0b1SCristina Ciocan unsigned long *config) 909c501d0b1SCristina Ciocan { 9105d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctl_dev); 911c501d0b1SCristina Ciocan enum pin_config_param param = pinconf_to_config_param(*config); 912c501d0b1SCristina Ciocan void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); 913c501d0b1SCristina Ciocan void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); 91404ff5a09SAndy Shevchenko void __iomem *db_reg = byt_gpio_reg(vg, offset, BYT_DEBOUNCE_REG); 915c501d0b1SCristina Ciocan unsigned long flags; 916658b476cSCristina Ciocan u32 conf, pull, val, debounce; 917c501d0b1SCristina Ciocan u16 arg = 0; 918c501d0b1SCristina Ciocan 91940ecab55SHans de Goede raw_spin_lock_irqsave(&byt_lock, flags); 920c501d0b1SCristina Ciocan conf = readl(conf_reg); 921c501d0b1SCristina Ciocan pull = conf & BYT_PULL_ASSIGN_MASK; 922c501d0b1SCristina Ciocan val = readl(val_reg); 92340ecab55SHans de Goede raw_spin_unlock_irqrestore(&byt_lock, flags); 924c501d0b1SCristina Ciocan 925c501d0b1SCristina Ciocan switch (param) { 926c501d0b1SCristina Ciocan case PIN_CONFIG_BIAS_DISABLE: 927c501d0b1SCristina Ciocan if (pull) 928c501d0b1SCristina Ciocan return -EINVAL; 929c501d0b1SCristina Ciocan break; 930c501d0b1SCristina Ciocan case PIN_CONFIG_BIAS_PULL_DOWN: 931c501d0b1SCristina Ciocan /* Pull assignment is only applicable in input mode */ 932c501d0b1SCristina Ciocan if ((val & BYT_INPUT_EN) || pull != BYT_PULL_ASSIGN_DOWN) 933c501d0b1SCristina Ciocan return -EINVAL; 934c501d0b1SCristina Ciocan 935c501d0b1SCristina Ciocan byt_get_pull_strength(conf, &arg); 936c501d0b1SCristina Ciocan 937c501d0b1SCristina Ciocan break; 938c501d0b1SCristina Ciocan case PIN_CONFIG_BIAS_PULL_UP: 939c501d0b1SCristina Ciocan /* Pull assignment is only applicable in input mode */ 940c501d0b1SCristina Ciocan if ((val & BYT_INPUT_EN) || pull != BYT_PULL_ASSIGN_UP) 941c501d0b1SCristina Ciocan return -EINVAL; 942c501d0b1SCristina Ciocan 943c501d0b1SCristina Ciocan byt_get_pull_strength(conf, &arg); 944c501d0b1SCristina Ciocan 945c501d0b1SCristina Ciocan break; 946658b476cSCristina Ciocan case PIN_CONFIG_INPUT_DEBOUNCE: 947658b476cSCristina Ciocan if (!(conf & BYT_DEBOUNCE_EN)) 948658b476cSCristina Ciocan return -EINVAL; 949658b476cSCristina Ciocan 95040ecab55SHans de Goede raw_spin_lock_irqsave(&byt_lock, flags); 95104ff5a09SAndy Shevchenko debounce = readl(db_reg); 95240ecab55SHans de Goede raw_spin_unlock_irqrestore(&byt_lock, flags); 953658b476cSCristina Ciocan 954658b476cSCristina Ciocan switch (debounce & BYT_DEBOUNCE_PULSE_MASK) { 955658b476cSCristina Ciocan case BYT_DEBOUNCE_PULSE_375US: 956658b476cSCristina Ciocan arg = 375; 957658b476cSCristina Ciocan break; 958658b476cSCristina Ciocan case BYT_DEBOUNCE_PULSE_750US: 959658b476cSCristina Ciocan arg = 750; 960658b476cSCristina Ciocan break; 961658b476cSCristina Ciocan case BYT_DEBOUNCE_PULSE_1500US: 962658b476cSCristina Ciocan arg = 1500; 963658b476cSCristina Ciocan break; 964658b476cSCristina Ciocan case BYT_DEBOUNCE_PULSE_3MS: 965658b476cSCristina Ciocan arg = 3000; 966658b476cSCristina Ciocan break; 967658b476cSCristina Ciocan case BYT_DEBOUNCE_PULSE_6MS: 968658b476cSCristina Ciocan arg = 6000; 969658b476cSCristina Ciocan break; 970658b476cSCristina Ciocan case BYT_DEBOUNCE_PULSE_12MS: 971658b476cSCristina Ciocan arg = 12000; 972658b476cSCristina Ciocan break; 973658b476cSCristina Ciocan case BYT_DEBOUNCE_PULSE_24MS: 974658b476cSCristina Ciocan arg = 24000; 975658b476cSCristina Ciocan break; 976658b476cSCristina Ciocan default: 977658b476cSCristina Ciocan return -EINVAL; 978658b476cSCristina Ciocan } 979658b476cSCristina Ciocan 980658b476cSCristina Ciocan break; 981c501d0b1SCristina Ciocan default: 982c501d0b1SCristina Ciocan return -ENOTSUPP; 983c501d0b1SCristina Ciocan } 984c501d0b1SCristina Ciocan 985c501d0b1SCristina Ciocan *config = pinconf_to_config_packed(param, arg); 986c501d0b1SCristina Ciocan 987c501d0b1SCristina Ciocan return 0; 988c501d0b1SCristina Ciocan } 989c501d0b1SCristina Ciocan 990c501d0b1SCristina Ciocan static int byt_pin_config_set(struct pinctrl_dev *pctl_dev, 991c501d0b1SCristina Ciocan unsigned int offset, 992c501d0b1SCristina Ciocan unsigned long *configs, 993c501d0b1SCristina Ciocan unsigned int num_configs) 994c501d0b1SCristina Ciocan { 9955d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = pinctrl_dev_get_drvdata(pctl_dev); 996c501d0b1SCristina Ciocan unsigned int param, arg; 997c501d0b1SCristina Ciocan void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); 998c501d0b1SCristina Ciocan void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); 99904ff5a09SAndy Shevchenko void __iomem *db_reg = byt_gpio_reg(vg, offset, BYT_DEBOUNCE_REG); 1000c501d0b1SCristina Ciocan unsigned long flags; 1001658b476cSCristina Ciocan u32 conf, val, debounce; 1002c501d0b1SCristina Ciocan int i, ret = 0; 1003c501d0b1SCristina Ciocan 100440ecab55SHans de Goede raw_spin_lock_irqsave(&byt_lock, flags); 1005c501d0b1SCristina Ciocan 1006c501d0b1SCristina Ciocan conf = readl(conf_reg); 1007c501d0b1SCristina Ciocan val = readl(val_reg); 1008c501d0b1SCristina Ciocan 1009c501d0b1SCristina Ciocan for (i = 0; i < num_configs; i++) { 1010c501d0b1SCristina Ciocan param = pinconf_to_config_param(configs[i]); 1011c501d0b1SCristina Ciocan arg = pinconf_to_config_argument(configs[i]); 1012c501d0b1SCristina Ciocan 1013c501d0b1SCristina Ciocan switch (param) { 1014c501d0b1SCristina Ciocan case PIN_CONFIG_BIAS_DISABLE: 1015c501d0b1SCristina Ciocan conf &= ~BYT_PULL_ASSIGN_MASK; 1016c501d0b1SCristina Ciocan break; 1017c501d0b1SCristina Ciocan case PIN_CONFIG_BIAS_PULL_DOWN: 1018c501d0b1SCristina Ciocan /* Set default strength value in case none is given */ 1019c501d0b1SCristina Ciocan if (arg == 1) 1020c501d0b1SCristina Ciocan arg = 2000; 1021c501d0b1SCristina Ciocan 1022c501d0b1SCristina Ciocan /* 1023c501d0b1SCristina Ciocan * Pull assignment is only applicable in input mode. If 1024c501d0b1SCristina Ciocan * chip is not in input mode, set it and warn about it. 1025c501d0b1SCristina Ciocan */ 1026c501d0b1SCristina Ciocan if (val & BYT_INPUT_EN) { 1027c501d0b1SCristina Ciocan val &= ~BYT_INPUT_EN; 1028c501d0b1SCristina Ciocan writel(val, val_reg); 1029990ec243SAndy Shevchenko dev_warn(vg->dev, 1030c501d0b1SCristina Ciocan "pin %u forcibly set to input mode\n", 1031c501d0b1SCristina Ciocan offset); 1032c501d0b1SCristina Ciocan } 1033c501d0b1SCristina Ciocan 1034c501d0b1SCristina Ciocan conf &= ~BYT_PULL_ASSIGN_MASK; 1035c501d0b1SCristina Ciocan conf |= BYT_PULL_ASSIGN_DOWN; 1036c501d0b1SCristina Ciocan ret = byt_set_pull_strength(&conf, arg); 1037c501d0b1SCristina Ciocan 1038c501d0b1SCristina Ciocan break; 1039c501d0b1SCristina Ciocan case PIN_CONFIG_BIAS_PULL_UP: 1040c501d0b1SCristina Ciocan /* Set default strength value in case none is given */ 1041c501d0b1SCristina Ciocan if (arg == 1) 1042c501d0b1SCristina Ciocan arg = 2000; 1043c501d0b1SCristina Ciocan 1044c501d0b1SCristina Ciocan /* 1045c501d0b1SCristina Ciocan * Pull assignment is only applicable in input mode. If 1046c501d0b1SCristina Ciocan * chip is not in input mode, set it and warn about it. 1047c501d0b1SCristina Ciocan */ 1048c501d0b1SCristina Ciocan if (val & BYT_INPUT_EN) { 1049c501d0b1SCristina Ciocan val &= ~BYT_INPUT_EN; 1050c501d0b1SCristina Ciocan writel(val, val_reg); 1051990ec243SAndy Shevchenko dev_warn(vg->dev, 1052c501d0b1SCristina Ciocan "pin %u forcibly set to input mode\n", 1053c501d0b1SCristina Ciocan offset); 1054c501d0b1SCristina Ciocan } 1055c501d0b1SCristina Ciocan 1056c501d0b1SCristina Ciocan conf &= ~BYT_PULL_ASSIGN_MASK; 1057c501d0b1SCristina Ciocan conf |= BYT_PULL_ASSIGN_UP; 1058c501d0b1SCristina Ciocan ret = byt_set_pull_strength(&conf, arg); 1059c501d0b1SCristina Ciocan 1060c501d0b1SCristina Ciocan break; 1061658b476cSCristina Ciocan case PIN_CONFIG_INPUT_DEBOUNCE: 106204ff5a09SAndy Shevchenko debounce = readl(db_reg); 1063658b476cSCristina Ciocan 1064827e1579SAndy Shevchenko if (arg) 1065827e1579SAndy Shevchenko conf |= BYT_DEBOUNCE_EN; 1066827e1579SAndy Shevchenko else 1067827e1579SAndy Shevchenko conf &= ~BYT_DEBOUNCE_EN; 1068827e1579SAndy Shevchenko 1069658b476cSCristina Ciocan switch (arg) { 1070658b476cSCristina Ciocan case 375: 10715f714771SAndy Shevchenko debounce &= ~BYT_DEBOUNCE_PULSE_MASK; 107204ff5a09SAndy Shevchenko debounce |= BYT_DEBOUNCE_PULSE_375US; 1073658b476cSCristina Ciocan break; 1074658b476cSCristina Ciocan case 750: 10755f714771SAndy Shevchenko debounce &= ~BYT_DEBOUNCE_PULSE_MASK; 107604ff5a09SAndy Shevchenko debounce |= BYT_DEBOUNCE_PULSE_750US; 1077658b476cSCristina Ciocan break; 1078658b476cSCristina Ciocan case 1500: 10795f714771SAndy Shevchenko debounce &= ~BYT_DEBOUNCE_PULSE_MASK; 108004ff5a09SAndy Shevchenko debounce |= BYT_DEBOUNCE_PULSE_1500US; 1081658b476cSCristina Ciocan break; 1082658b476cSCristina Ciocan case 3000: 10835f714771SAndy Shevchenko debounce &= ~BYT_DEBOUNCE_PULSE_MASK; 108404ff5a09SAndy Shevchenko debounce |= BYT_DEBOUNCE_PULSE_3MS; 1085658b476cSCristina Ciocan break; 1086658b476cSCristina Ciocan case 6000: 10875f714771SAndy Shevchenko debounce &= ~BYT_DEBOUNCE_PULSE_MASK; 108804ff5a09SAndy Shevchenko debounce |= BYT_DEBOUNCE_PULSE_6MS; 1089658b476cSCristina Ciocan break; 1090658b476cSCristina Ciocan case 12000: 10915f714771SAndy Shevchenko debounce &= ~BYT_DEBOUNCE_PULSE_MASK; 109204ff5a09SAndy Shevchenko debounce |= BYT_DEBOUNCE_PULSE_12MS; 1093658b476cSCristina Ciocan break; 1094658b476cSCristina Ciocan case 24000: 10955f714771SAndy Shevchenko debounce &= ~BYT_DEBOUNCE_PULSE_MASK; 109604ff5a09SAndy Shevchenko debounce |= BYT_DEBOUNCE_PULSE_24MS; 1097658b476cSCristina Ciocan break; 1098658b476cSCristina Ciocan default: 1099827e1579SAndy Shevchenko if (arg) 1100658b476cSCristina Ciocan ret = -EINVAL; 1101827e1579SAndy Shevchenko break; 1102658b476cSCristina Ciocan } 1103658b476cSCristina Ciocan 110404ff5a09SAndy Shevchenko if (!ret) 110504ff5a09SAndy Shevchenko writel(debounce, db_reg); 1106658b476cSCristina Ciocan break; 1107c501d0b1SCristina Ciocan default: 1108c501d0b1SCristina Ciocan ret = -ENOTSUPP; 1109c501d0b1SCristina Ciocan } 1110c501d0b1SCristina Ciocan 1111c501d0b1SCristina Ciocan if (ret) 1112c501d0b1SCristina Ciocan break; 1113c501d0b1SCristina Ciocan } 1114c501d0b1SCristina Ciocan 1115c501d0b1SCristina Ciocan if (!ret) 1116c501d0b1SCristina Ciocan writel(conf, conf_reg); 1117c501d0b1SCristina Ciocan 111840ecab55SHans de Goede raw_spin_unlock_irqrestore(&byt_lock, flags); 1119c501d0b1SCristina Ciocan 1120c501d0b1SCristina Ciocan return ret; 1121c501d0b1SCristina Ciocan } 1122c501d0b1SCristina Ciocan 1123c501d0b1SCristina Ciocan static const struct pinconf_ops byt_pinconf_ops = { 1124c501d0b1SCristina Ciocan .is_generic = true, 1125c501d0b1SCristina Ciocan .pin_config_get = byt_pin_config_get, 1126c501d0b1SCristina Ciocan .pin_config_set = byt_pin_config_set, 1127c501d0b1SCristina Ciocan }; 1128c501d0b1SCristina Ciocan 1129c501d0b1SCristina Ciocan static const struct pinctrl_desc byt_pinctrl_desc = { 1130c501d0b1SCristina Ciocan .pctlops = &byt_pinctrl_ops, 1131c501d0b1SCristina Ciocan .pmxops = &byt_pinmux_ops, 1132c501d0b1SCristina Ciocan .confops = &byt_pinconf_ops, 1133c501d0b1SCristina Ciocan .owner = THIS_MODULE, 1134c501d0b1SCristina Ciocan }; 1135c501d0b1SCristina Ciocan 1136939330d7SAndy Shevchenko static int byt_gpio_get(struct gpio_chip *chip, unsigned int offset) 11375fae8b86SMika Westerberg { 11385d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = gpiochip_get_data(chip); 1139c501d0b1SCristina Ciocan void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); 114039ce8150SMika Westerberg unsigned long flags; 114139ce8150SMika Westerberg u32 val; 114239ce8150SMika Westerberg 114340ecab55SHans de Goede raw_spin_lock_irqsave(&byt_lock, flags); 114439ce8150SMika Westerberg val = readl(reg); 114540ecab55SHans de Goede raw_spin_unlock_irqrestore(&byt_lock, flags); 114639ce8150SMika Westerberg 11473bde8771SLinus Walleij return !!(val & BYT_LEVEL); 11485fae8b86SMika Westerberg } 11495fae8b86SMika Westerberg 1150939330d7SAndy Shevchenko static void byt_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) 11515fae8b86SMika Westerberg { 11525d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = gpiochip_get_data(chip); 1153c501d0b1SCristina Ciocan void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); 11545fae8b86SMika Westerberg unsigned long flags; 11555fae8b86SMika Westerberg u32 old_val; 11565fae8b86SMika Westerberg 115786e3ef81SCristina Ciocan if (!reg) 115886e3ef81SCristina Ciocan return; 115986e3ef81SCristina Ciocan 116040ecab55SHans de Goede raw_spin_lock_irqsave(&byt_lock, flags); 11615fae8b86SMika Westerberg old_val = readl(reg); 11625fae8b86SMika Westerberg if (value) 11635fae8b86SMika Westerberg writel(old_val | BYT_LEVEL, reg); 11645fae8b86SMika Westerberg else 11655fae8b86SMika Westerberg writel(old_val & ~BYT_LEVEL, reg); 116640ecab55SHans de Goede raw_spin_unlock_irqrestore(&byt_lock, flags); 11675fae8b86SMika Westerberg } 11685fae8b86SMika Westerberg 116986e3ef81SCristina Ciocan static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) 11705fae8b86SMika Westerberg { 11715d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = gpiochip_get_data(chip); 1172c501d0b1SCristina Ciocan void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); 11735fae8b86SMika Westerberg unsigned long flags; 11745fae8b86SMika Westerberg u32 value; 11755fae8b86SMika Westerberg 117686e3ef81SCristina Ciocan if (!reg) 117786e3ef81SCristina Ciocan return -EINVAL; 117886e3ef81SCristina Ciocan 117940ecab55SHans de Goede raw_spin_lock_irqsave(&byt_lock, flags); 118086e3ef81SCristina Ciocan value = readl(reg); 118140ecab55SHans de Goede raw_spin_unlock_irqrestore(&byt_lock, flags); 11825fae8b86SMika Westerberg 118386e3ef81SCristina Ciocan if (!(value & BYT_OUTPUT_EN)) 1184faf86c0cSMatti Vaittinen return GPIO_LINE_DIRECTION_OUT; 118586e3ef81SCristina Ciocan if (!(value & BYT_INPUT_EN)) 1186faf86c0cSMatti Vaittinen return GPIO_LINE_DIRECTION_IN; 118786e3ef81SCristina Ciocan 118886e3ef81SCristina Ciocan return -EINVAL; 11895fae8b86SMika Westerberg } 11905fae8b86SMika Westerberg 119186e3ef81SCristina Ciocan static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) 11925fae8b86SMika Westerberg { 1193156abe29SHans de Goede struct intel_pinctrl *vg = gpiochip_get_data(chip); 1194156abe29SHans de Goede void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); 1195156abe29SHans de Goede unsigned long flags; 1196156abe29SHans de Goede u32 reg; 1197156abe29SHans de Goede 1198156abe29SHans de Goede raw_spin_lock_irqsave(&byt_lock, flags); 1199156abe29SHans de Goede 1200156abe29SHans de Goede reg = readl(val_reg); 1201156abe29SHans de Goede reg &= ~BYT_DIR_MASK; 1202156abe29SHans de Goede reg |= BYT_OUTPUT_EN; 1203156abe29SHans de Goede writel(reg, val_reg); 1204156abe29SHans de Goede 1205156abe29SHans de Goede raw_spin_unlock_irqrestore(&byt_lock, flags); 1206156abe29SHans de Goede return 0; 120786e3ef81SCristina Ciocan } 12085fae8b86SMika Westerberg 1209156abe29SHans de Goede /* 1210156abe29SHans de Goede * Note despite the temptation this MUST NOT be converted into a call to 1211156abe29SHans de Goede * pinctrl_gpio_direction_output() + byt_gpio_set() that does not work this 1212156abe29SHans de Goede * MUST be done as a single BYT_VAL_REG register write. 1213156abe29SHans de Goede * See the commit message of the commit adding this comment for details. 1214156abe29SHans de Goede */ 121586e3ef81SCristina Ciocan static int byt_gpio_direction_output(struct gpio_chip *chip, 121686e3ef81SCristina Ciocan unsigned int offset, int value) 121786e3ef81SCristina Ciocan { 1218156abe29SHans de Goede struct intel_pinctrl *vg = gpiochip_get_data(chip); 1219156abe29SHans de Goede void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); 1220156abe29SHans de Goede unsigned long flags; 1221156abe29SHans de Goede u32 reg; 12225fae8b86SMika Westerberg 1223156abe29SHans de Goede raw_spin_lock_irqsave(&byt_lock, flags); 122486e3ef81SCristina Ciocan 1225156abe29SHans de Goede byt_gpio_direct_irq_check(vg, offset); 12265fae8b86SMika Westerberg 1227156abe29SHans de Goede reg = readl(val_reg); 1228156abe29SHans de Goede reg &= ~BYT_DIR_MASK; 1229156abe29SHans de Goede if (value) 1230156abe29SHans de Goede reg |= BYT_LEVEL; 1231156abe29SHans de Goede else 1232156abe29SHans de Goede reg &= ~BYT_LEVEL; 1233156abe29SHans de Goede 1234156abe29SHans de Goede writel(reg, val_reg); 1235156abe29SHans de Goede 1236156abe29SHans de Goede raw_spin_unlock_irqrestore(&byt_lock, flags); 12375fae8b86SMika Westerberg return 0; 12385fae8b86SMika Westerberg } 12395fae8b86SMika Westerberg 12405fae8b86SMika Westerberg static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) 12415fae8b86SMika Westerberg { 12425d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = gpiochip_get_data(chip); 12435fae8b86SMika Westerberg int i; 124486e3ef81SCristina Ciocan u32 conf0, val; 12455fae8b86SMika Westerberg 12465d33e0ebSAndy Shevchenko for (i = 0; i < vg->soc->npins; i++) { 124734e65670SAndy Shevchenko const struct intel_community *comm; 12485fae8b86SMika Westerberg const char *pull_str = NULL; 12495fae8b86SMika Westerberg const char *pull = NULL; 125086e3ef81SCristina Ciocan void __iomem *reg; 125178e1c896SMika Westerberg unsigned long flags; 12525fae8b86SMika Westerberg const char *label; 125386e3ef81SCristina Ciocan unsigned int pin; 125478e1c896SMika Westerberg 125540ecab55SHans de Goede raw_spin_lock_irqsave(&byt_lock, flags); 12565d33e0ebSAndy Shevchenko pin = vg->soc->pins[i].number; 125786e3ef81SCristina Ciocan reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG); 125886e3ef81SCristina Ciocan if (!reg) { 125986e3ef81SCristina Ciocan seq_printf(s, 126086e3ef81SCristina Ciocan "Could not retrieve pin %i conf0 reg\n", 126186e3ef81SCristina Ciocan pin); 126240ecab55SHans de Goede raw_spin_unlock_irqrestore(&byt_lock, flags); 126386e3ef81SCristina Ciocan continue; 126486e3ef81SCristina Ciocan } 126586e3ef81SCristina Ciocan conf0 = readl(reg); 126686e3ef81SCristina Ciocan 126786e3ef81SCristina Ciocan reg = byt_gpio_reg(vg, pin, BYT_VAL_REG); 126886e3ef81SCristina Ciocan if (!reg) { 126986e3ef81SCristina Ciocan seq_printf(s, 127086e3ef81SCristina Ciocan "Could not retrieve pin %i val reg\n", pin); 127140ecab55SHans de Goede raw_spin_unlock_irqrestore(&byt_lock, flags); 127222bbd21bSDan Carpenter continue; 127386e3ef81SCristina Ciocan } 127486e3ef81SCristina Ciocan val = readl(reg); 127540ecab55SHans de Goede raw_spin_unlock_irqrestore(&byt_lock, flags); 12765fae8b86SMika Westerberg 127786e3ef81SCristina Ciocan comm = byt_get_community(vg, pin); 127886e3ef81SCristina Ciocan if (!comm) { 127986e3ef81SCristina Ciocan seq_printf(s, 128086e3ef81SCristina Ciocan "Could not get community for pin %i\n", pin); 128186e3ef81SCristina Ciocan continue; 128286e3ef81SCristina Ciocan } 12835fae8b86SMika Westerberg label = gpiochip_is_requested(chip, i); 12845fae8b86SMika Westerberg if (!label) 12855fae8b86SMika Westerberg label = "Unrequested"; 12865fae8b86SMika Westerberg 12875fae8b86SMika Westerberg switch (conf0 & BYT_PULL_ASSIGN_MASK) { 12885fae8b86SMika Westerberg case BYT_PULL_ASSIGN_UP: 12895fae8b86SMika Westerberg pull = "up"; 12905fae8b86SMika Westerberg break; 12915fae8b86SMika Westerberg case BYT_PULL_ASSIGN_DOWN: 12925fae8b86SMika Westerberg pull = "down"; 12935fae8b86SMika Westerberg break; 12945fae8b86SMika Westerberg } 12955fae8b86SMika Westerberg 12965fae8b86SMika Westerberg switch (conf0 & BYT_PULL_STR_MASK) { 12975fae8b86SMika Westerberg case BYT_PULL_STR_2K: 12985fae8b86SMika Westerberg pull_str = "2k"; 12995fae8b86SMika Westerberg break; 13005fae8b86SMika Westerberg case BYT_PULL_STR_10K: 13015fae8b86SMika Westerberg pull_str = "10k"; 13025fae8b86SMika Westerberg break; 13035fae8b86SMika Westerberg case BYT_PULL_STR_20K: 13045fae8b86SMika Westerberg pull_str = "20k"; 13055fae8b86SMika Westerberg break; 13065fae8b86SMika Westerberg case BYT_PULL_STR_40K: 13075fae8b86SMika Westerberg pull_str = "40k"; 13085fae8b86SMika Westerberg break; 13095fae8b86SMika Westerberg } 13105fae8b86SMika Westerberg 13115fae8b86SMika Westerberg seq_printf(s, 13125fae8b86SMika Westerberg " gpio-%-3d (%-20.20s) %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s", 131386e3ef81SCristina Ciocan pin, 13145fae8b86SMika Westerberg label, 13155fae8b86SMika Westerberg val & BYT_INPUT_EN ? " " : "in", 13165fae8b86SMika Westerberg val & BYT_OUTPUT_EN ? " " : "out", 13175fae8b86SMika Westerberg val & BYT_LEVEL ? "hi" : "lo", 13183655a1caSAlexander Stein comm->pad_map[i], comm->pad_map[i] * 16, 13195fae8b86SMika Westerberg conf0 & 0x7, 13205fae8b86SMika Westerberg conf0 & BYT_TRIG_NEG ? " fall" : " ", 13215fae8b86SMika Westerberg conf0 & BYT_TRIG_POS ? " rise" : " ", 13225fae8b86SMika Westerberg conf0 & BYT_TRIG_LVL ? " level" : " "); 13235fae8b86SMika Westerberg 13245fae8b86SMika Westerberg if (pull && pull_str) 13255fae8b86SMika Westerberg seq_printf(s, " %-4s %-3s", pull, pull_str); 13265fae8b86SMika Westerberg else 13275fae8b86SMika Westerberg seq_puts(s, " "); 13285fae8b86SMika Westerberg 13295fae8b86SMika Westerberg if (conf0 & BYT_IODEN) 13305fae8b86SMika Westerberg seq_puts(s, " open-drain"); 13315fae8b86SMika Westerberg 13325fae8b86SMika Westerberg seq_puts(s, "\n"); 13335fae8b86SMika Westerberg } 13345fae8b86SMika Westerberg } 13355fae8b86SMika Westerberg 133686e3ef81SCristina Ciocan static const struct gpio_chip byt_gpio_chip = { 133786e3ef81SCristina Ciocan .owner = THIS_MODULE, 133886e3ef81SCristina Ciocan .request = gpiochip_generic_request, 133986e3ef81SCristina Ciocan .free = gpiochip_generic_free, 134086e3ef81SCristina Ciocan .get_direction = byt_gpio_get_direction, 134186e3ef81SCristina Ciocan .direction_input = byt_gpio_direction_input, 134286e3ef81SCristina Ciocan .direction_output = byt_gpio_direction_output, 134386e3ef81SCristina Ciocan .get = byt_gpio_get, 134486e3ef81SCristina Ciocan .set = byt_gpio_set, 1345ccd025eaSAndy Shevchenko .set_config = gpiochip_generic_config, 134686e3ef81SCristina Ciocan .dbg_show = byt_gpio_dbg_show, 134786e3ef81SCristina Ciocan }; 134886e3ef81SCristina Ciocan 134931e4329fSMika Westerberg static void byt_irq_ack(struct irq_data *d) 135031e4329fSMika Westerberg { 135131e4329fSMika Westerberg struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 13525d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = gpiochip_get_data(gc); 13536d209b42SAndy Shevchenko irq_hw_number_t hwirq = irqd_to_hwirq(d); 135431e4329fSMika Westerberg void __iomem *reg; 135531e4329fSMika Westerberg 13566d209b42SAndy Shevchenko reg = byt_gpio_reg(vg, hwirq, BYT_INT_STAT_REG); 13579f573b98SCristina Ciocan if (!reg) 13589f573b98SCristina Ciocan return; 13599f573b98SCristina Ciocan 136040ecab55SHans de Goede raw_spin_lock(&byt_lock); 13616d209b42SAndy Shevchenko writel(BIT(hwirq % 32), reg); 136240ecab55SHans de Goede raw_spin_unlock(&byt_lock); 136331e4329fSMika Westerberg } 136431e4329fSMika Westerberg 13659f573b98SCristina Ciocan static void byt_irq_mask(struct irq_data *d) 13669f573b98SCristina Ciocan { 13679f573b98SCristina Ciocan struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 13685d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = gpiochip_get_data(gc); 13696d209b42SAndy Shevchenko irq_hw_number_t hwirq = irqd_to_hwirq(d); 13709f573b98SCristina Ciocan 13716d209b42SAndy Shevchenko byt_gpio_clear_triggering(vg, hwirq); 13726d209b42SAndy Shevchenko gpiochip_disable_irq(gc, hwirq); 13739f573b98SCristina Ciocan } 13749f573b98SCristina Ciocan 13755fae8b86SMika Westerberg static void byt_irq_unmask(struct irq_data *d) 13765fae8b86SMika Westerberg { 137731e4329fSMika Westerberg struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 13785d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = gpiochip_get_data(gc); 13796d209b42SAndy Shevchenko irq_hw_number_t hwirq = irqd_to_hwirq(d); 138031e4329fSMika Westerberg unsigned long flags; 138131e4329fSMika Westerberg void __iomem *reg; 138231e4329fSMika Westerberg u32 value; 138331e4329fSMika Westerberg 13846d209b42SAndy Shevchenko gpiochip_enable_irq(gc, hwirq); 13856d209b42SAndy Shevchenko 13866d209b42SAndy Shevchenko reg = byt_gpio_reg(vg, hwirq, BYT_CONF0_REG); 13879f573b98SCristina Ciocan if (!reg) 13889f573b98SCristina Ciocan return; 138978e1c896SMika Westerberg 139040ecab55SHans de Goede raw_spin_lock_irqsave(&byt_lock, flags); 139131e4329fSMika Westerberg value = readl(reg); 139231e4329fSMika Westerberg 139331e4329fSMika Westerberg switch (irqd_get_trigger_type(d)) { 139431e4329fSMika Westerberg case IRQ_TYPE_LEVEL_HIGH: 139531e4329fSMika Westerberg value |= BYT_TRIG_LVL; 13960a093020SGustavo A. R. Silva fallthrough; 139731e4329fSMika Westerberg case IRQ_TYPE_EDGE_RISING: 139831e4329fSMika Westerberg value |= BYT_TRIG_POS; 139931e4329fSMika Westerberg break; 140031e4329fSMika Westerberg case IRQ_TYPE_LEVEL_LOW: 140131e4329fSMika Westerberg value |= BYT_TRIG_LVL; 14020a093020SGustavo A. R. Silva fallthrough; 140331e4329fSMika Westerberg case IRQ_TYPE_EDGE_FALLING: 140431e4329fSMika Westerberg value |= BYT_TRIG_NEG; 140531e4329fSMika Westerberg break; 140631e4329fSMika Westerberg case IRQ_TYPE_EDGE_BOTH: 140731e4329fSMika Westerberg value |= (BYT_TRIG_NEG | BYT_TRIG_POS); 140831e4329fSMika Westerberg break; 140931e4329fSMika Westerberg } 141031e4329fSMika Westerberg 141131e4329fSMika Westerberg writel(value, reg); 141231e4329fSMika Westerberg 141340ecab55SHans de Goede raw_spin_unlock_irqrestore(&byt_lock, flags); 14145fae8b86SMika Westerberg } 14155fae8b86SMika Westerberg 14169f573b98SCristina Ciocan static int byt_irq_type(struct irq_data *d, unsigned int type) 14175fae8b86SMika Westerberg { 14185d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = gpiochip_get_data(irq_data_get_irq_chip_data(d)); 14196d209b42SAndy Shevchenko irq_hw_number_t hwirq = irqd_to_hwirq(d); 14209f573b98SCristina Ciocan u32 value; 14219f573b98SCristina Ciocan unsigned long flags; 14226d209b42SAndy Shevchenko void __iomem *reg; 142331e4329fSMika Westerberg 14246d209b42SAndy Shevchenko reg = byt_gpio_reg(vg, hwirq, BYT_CONF0_REG); 14256d209b42SAndy Shevchenko if (!reg) 14269f573b98SCristina Ciocan return -EINVAL; 14279f573b98SCristina Ciocan 142840ecab55SHans de Goede raw_spin_lock_irqsave(&byt_lock, flags); 14299f573b98SCristina Ciocan value = readl(reg); 14309f573b98SCristina Ciocan 14319f573b98SCristina Ciocan WARN(value & BYT_DIRECT_IRQ_EN, 14329f573b98SCristina Ciocan "Bad pad config for io mode, force direct_irq_en bit clearing"); 14339f573b98SCristina Ciocan 14349f573b98SCristina Ciocan /* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits 14359f573b98SCristina Ciocan * are used to indicate high and low level triggering 14369f573b98SCristina Ciocan */ 14379f573b98SCristina Ciocan value &= ~(BYT_DIRECT_IRQ_EN | BYT_TRIG_POS | BYT_TRIG_NEG | 14389f573b98SCristina Ciocan BYT_TRIG_LVL); 14399291c65bSHans de Goede /* Enable glitch filtering */ 14409291c65bSHans de Goede value |= BYT_GLITCH_FILTER_EN | BYT_GLITCH_F_SLOW_CLK | 14419291c65bSHans de Goede BYT_GLITCH_F_FAST_CLK; 14429f573b98SCristina Ciocan 14439f573b98SCristina Ciocan writel(value, reg); 14449f573b98SCristina Ciocan 14459f573b98SCristina Ciocan if (type & IRQ_TYPE_EDGE_BOTH) 14469f573b98SCristina Ciocan irq_set_handler_locked(d, handle_edge_irq); 14479f573b98SCristina Ciocan else if (type & IRQ_TYPE_LEVEL_MASK) 14489f573b98SCristina Ciocan irq_set_handler_locked(d, handle_level_irq); 14499f573b98SCristina Ciocan 145040ecab55SHans de Goede raw_spin_unlock_irqrestore(&byt_lock, flags); 14519f573b98SCristina Ciocan 14529f573b98SCristina Ciocan return 0; 14535fae8b86SMika Westerberg } 14545fae8b86SMika Westerberg 14556d209b42SAndy Shevchenko static const struct irq_chip byt_gpio_irq_chip = { 14566d209b42SAndy Shevchenko .name = "BYT-GPIO", 14576d209b42SAndy Shevchenko .irq_ack = byt_irq_ack, 14586d209b42SAndy Shevchenko .irq_mask = byt_irq_mask, 14596d209b42SAndy Shevchenko .irq_unmask = byt_irq_unmask, 14606d209b42SAndy Shevchenko .irq_set_type = byt_irq_type, 14616d209b42SAndy Shevchenko .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_SET_TYPE_MASKED | IRQCHIP_IMMUTABLE, 14626d209b42SAndy Shevchenko GPIOCHIP_IRQ_RESOURCE_HELPERS, 14636d209b42SAndy Shevchenko }; 14646d209b42SAndy Shevchenko 146571e6ca61SCristina Ciocan static void byt_gpio_irq_handler(struct irq_desc *desc) 146671e6ca61SCristina Ciocan { 146771e6ca61SCristina Ciocan struct irq_data *data = irq_desc_get_irq_data(desc); 14685d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = gpiochip_get_data(irq_desc_get_handler_data(desc)); 146971e6ca61SCristina Ciocan struct irq_chip *chip = irq_data_get_irq_chip(data); 147071e6ca61SCristina Ciocan u32 base, pin; 147171e6ca61SCristina Ciocan void __iomem *reg; 147271e6ca61SCristina Ciocan unsigned long pending; 147371e6ca61SCristina Ciocan 147471e6ca61SCristina Ciocan /* check from GPIO controller which pin triggered the interrupt */ 147571e6ca61SCristina Ciocan for (base = 0; base < vg->chip.ngpio; base += 32) { 147671e6ca61SCristina Ciocan reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG); 147771e6ca61SCristina Ciocan 147871e6ca61SCristina Ciocan if (!reg) { 1479990ec243SAndy Shevchenko dev_warn(vg->dev, 148071e6ca61SCristina Ciocan "Pin %i: could not retrieve interrupt status register\n", 148171e6ca61SCristina Ciocan base); 148271e6ca61SCristina Ciocan continue; 148371e6ca61SCristina Ciocan } 148471e6ca61SCristina Ciocan 148540ecab55SHans de Goede raw_spin_lock(&byt_lock); 148671e6ca61SCristina Ciocan pending = readl(reg); 148740ecab55SHans de Goede raw_spin_unlock(&byt_lock); 1488a9cb09b7SMarc Zyngier for_each_set_bit(pin, &pending, 32) 1489a9cb09b7SMarc Zyngier generic_handle_domain_irq(vg->chip.irq.domain, base + pin); 149071e6ca61SCristina Ciocan } 149171e6ca61SCristina Ciocan chip->irq_eoi(data); 149271e6ca61SCristina Ciocan } 149371e6ca61SCristina Ciocan 1494689e0088SHans de Goede static bool byt_direct_irq_sanity_check(struct intel_pinctrl *vg, int pin, u32 conf0) 1495689e0088SHans de Goede { 1496689e0088SHans de Goede int direct_irq, ioapic_direct_irq_base; 1497689e0088SHans de Goede u8 *match, direct_irq_mux[16]; 1498689e0088SHans de Goede u32 trig; 1499689e0088SHans de Goede 1500689e0088SHans de Goede memcpy_fromio(direct_irq_mux, vg->communities->pad_regs + BYT_DIRECT_IRQ_REG, 1501689e0088SHans de Goede sizeof(direct_irq_mux)); 1502689e0088SHans de Goede match = memchr(direct_irq_mux, pin, sizeof(direct_irq_mux)); 1503689e0088SHans de Goede if (!match) { 1504689e0088SHans de Goede dev_warn(vg->dev, FW_BUG "pin %i: direct_irq_en set but no IRQ assigned, clearing\n", pin); 1505689e0088SHans de Goede return false; 1506689e0088SHans de Goede } 1507689e0088SHans de Goede 1508689e0088SHans de Goede direct_irq = match - direct_irq_mux; 1509689e0088SHans de Goede /* Base IO-APIC pin numbers come from atom-e3800-family-datasheet.pdf */ 1510689e0088SHans de Goede ioapic_direct_irq_base = (vg->communities->npins == BYT_NGPIO_SCORE) ? 51 : 67; 1511689e0088SHans de Goede dev_dbg(vg->dev, "Pin %i: uses direct IRQ %d (IO-APIC %d)\n", pin, 1512689e0088SHans de Goede direct_irq, direct_irq + ioapic_direct_irq_base); 1513689e0088SHans de Goede 1514689e0088SHans de Goede /* 1515689e0088SHans de Goede * Testing has shown that the way direct IRQs work is that the combination of the 1516689e0088SHans de Goede * direct-irq-en flag and the direct IRQ mux connect the output of the GPIO's IRQ 1517689e0088SHans de Goede * trigger block, which normally sets the status flag in the IRQ status reg at 1518689e0088SHans de Goede * 0x800, to one of the IO-APIC pins according to the mux registers. 1519689e0088SHans de Goede * 1520689e0088SHans de Goede * This means that: 1521689e0088SHans de Goede * 1. The TRIG_MASK bits must be set to configure the GPIO's IRQ trigger block 1522689e0088SHans de Goede * 2. The TRIG_LVL bit *must* be set, so that the GPIO's input value is directly 1523689e0088SHans de Goede * passed (1:1 or inverted) to the IO-APIC pin, if TRIG_LVL is not set, 1524689e0088SHans de Goede * selecting edge mode operation then on the first edge the IO-APIC pin goes 1525689e0088SHans de Goede * high, but since no write-to-clear write will be done to the IRQ status reg 1526689e0088SHans de Goede * at 0x800, the detected edge condition will never get cleared. 1527689e0088SHans de Goede */ 1528689e0088SHans de Goede trig = conf0 & BYT_TRIG_MASK; 1529689e0088SHans de Goede if (trig != (BYT_TRIG_POS | BYT_TRIG_LVL) && 1530689e0088SHans de Goede trig != (BYT_TRIG_NEG | BYT_TRIG_LVL)) { 1531689e0088SHans de Goede dev_warn(vg->dev, FW_BUG "pin %i: direct_irq_en set without trigger (conf0: %xh), clearing\n", 1532689e0088SHans de Goede pin, conf0); 1533689e0088SHans de Goede return false; 1534689e0088SHans de Goede } 1535689e0088SHans de Goede 1536689e0088SHans de Goede return true; 1537689e0088SHans de Goede } 1538689e0088SHans de Goede 15395fbe5b58SLinus Walleij static void byt_init_irq_valid_mask(struct gpio_chip *chip, 15405fbe5b58SLinus Walleij unsigned long *valid_mask, 15415fbe5b58SLinus Walleij unsigned int ngpios) 15425fbe5b58SLinus Walleij { 15435d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = gpiochip_get_data(chip); 15445fae8b86SMika Westerberg void __iomem *reg; 1545e70982b3SAndy Shevchenko u32 value; 154695f0972cSMika Westerberg int i; 154795f0972cSMika Westerberg 154895f0972cSMika Westerberg /* 154995f0972cSMika Westerberg * Clear interrupt triggers for all pins that are GPIOs and 155095f0972cSMika Westerberg * do not use direct IRQ mode. This will prevent spurious 155195f0972cSMika Westerberg * interrupts from misconfigured pins. 155295f0972cSMika Westerberg */ 15535d33e0ebSAndy Shevchenko for (i = 0; i < vg->soc->npins; i++) { 15545d33e0ebSAndy Shevchenko unsigned int pin = vg->soc->pins[i].number; 155571e6ca61SCristina Ciocan 155671e6ca61SCristina Ciocan reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG); 155771e6ca61SCristina Ciocan if (!reg) { 1558990ec243SAndy Shevchenko dev_warn(vg->dev, 155971e6ca61SCristina Ciocan "Pin %i: could not retrieve conf0 register\n", 156071e6ca61SCristina Ciocan i); 156171e6ca61SCristina Ciocan continue; 156271e6ca61SCristina Ciocan } 156371e6ca61SCristina Ciocan 156471e6ca61SCristina Ciocan value = readl(reg); 156549c03096SAndy Shevchenko if (value & BYT_DIRECT_IRQ_EN) { 1566689e0088SHans de Goede if (byt_direct_irq_sanity_check(vg, i, value)) { 1567e70982b3SAndy Shevchenko clear_bit(i, valid_mask); 1568689e0088SHans de Goede } else { 1569689e0088SHans de Goede value &= ~(BYT_DIRECT_IRQ_EN | BYT_TRIG_POS | 1570689e0088SHans de Goede BYT_TRIG_NEG | BYT_TRIG_LVL); 1571689e0088SHans de Goede writel(value, reg); 1572689e0088SHans de Goede } 157349c03096SAndy Shevchenko } else if ((value & BYT_PIN_MUX) == byt_get_gpio_mux(vg, i)) { 157495f0972cSMika Westerberg byt_gpio_clear_triggering(vg, i); 1575990ec243SAndy Shevchenko dev_dbg(vg->dev, "disabling GPIO %d\n", i); 157695f0972cSMika Westerberg } 157795f0972cSMika Westerberg } 1578e70982b3SAndy Shevchenko } 1579e70982b3SAndy Shevchenko 1580e70982b3SAndy Shevchenko static int byt_gpio_irq_init_hw(struct gpio_chip *chip) 1581e70982b3SAndy Shevchenko { 15825d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = gpiochip_get_data(chip); 1583e70982b3SAndy Shevchenko void __iomem *reg; 1584e70982b3SAndy Shevchenko u32 base, value; 15855fae8b86SMika Westerberg 15865fae8b86SMika Westerberg /* clear interrupt status trigger registers */ 15875d33e0ebSAndy Shevchenko for (base = 0; base < vg->soc->npins; base += 32) { 1588c501d0b1SCristina Ciocan reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG); 158971e6ca61SCristina Ciocan 159071e6ca61SCristina Ciocan if (!reg) { 1591990ec243SAndy Shevchenko dev_warn(vg->dev, 159271e6ca61SCristina Ciocan "Pin %i: could not retrieve irq status reg\n", 159371e6ca61SCristina Ciocan base); 159471e6ca61SCristina Ciocan continue; 159571e6ca61SCristina Ciocan } 159671e6ca61SCristina Ciocan 15975fae8b86SMika Westerberg writel(0xffffffff, reg); 15985fae8b86SMika Westerberg /* make sure trigger bits are cleared, if not then a pin 15995fae8b86SMika Westerberg might be misconfigured in bios */ 16005fae8b86SMika Westerberg value = readl(reg); 16015fae8b86SMika Westerberg if (value) 1602990ec243SAndy Shevchenko dev_err(vg->dev, 1603973232e2SAlexander Stein "GPIO interrupt error, pins misconfigured. INT_STAT%u: 0x%08x\n", 1604973232e2SAlexander Stein base / 32, value); 16055fae8b86SMika Westerberg } 1606ca8a958eSAndy Shevchenko 1607ca8a958eSAndy Shevchenko return 0; 16085fae8b86SMika Westerberg } 16095fae8b86SMika Westerberg 1610ed3c1564SAndy Shevchenko static int byt_gpio_add_pin_ranges(struct gpio_chip *chip) 1611ed3c1564SAndy Shevchenko { 16125d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = gpiochip_get_data(chip); 1613990ec243SAndy Shevchenko struct device *dev = vg->dev; 1614ed3c1564SAndy Shevchenko int ret; 1615ed3c1564SAndy Shevchenko 16165d33e0ebSAndy Shevchenko ret = gpiochip_add_pin_range(chip, dev_name(dev), 0, 0, vg->soc->npins); 1617ed3c1564SAndy Shevchenko if (ret) 1618ed3c1564SAndy Shevchenko dev_err(dev, "failed to add GPIO pin range\n"); 1619ed3c1564SAndy Shevchenko 1620ed3c1564SAndy Shevchenko return ret; 1621ed3c1564SAndy Shevchenko } 1622ed3c1564SAndy Shevchenko 16235d33e0ebSAndy Shevchenko static int byt_gpio_probe(struct intel_pinctrl *vg) 16245fae8b86SMika Westerberg { 1625990ec243SAndy Shevchenko struct platform_device *pdev = to_platform_device(vg->dev); 16265fae8b86SMika Westerberg struct gpio_chip *gc; 1627f86a1bb5SAndy Shevchenko int irq, ret; 16285fae8b86SMika Westerberg 162971e6ca61SCristina Ciocan /* Set up gpio chip */ 163071e6ca61SCristina Ciocan vg->chip = byt_gpio_chip; 16315fae8b86SMika Westerberg gc = &vg->chip; 1632990ec243SAndy Shevchenko gc->label = dev_name(vg->dev); 16335fae8b86SMika Westerberg gc->base = -1; 16345fae8b86SMika Westerberg gc->can_sleep = false; 1635ed3c1564SAndy Shevchenko gc->add_pin_ranges = byt_gpio_add_pin_ranges; 1636990ec243SAndy Shevchenko gc->parent = vg->dev; 16375d33e0ebSAndy Shevchenko gc->ngpio = vg->soc->npins; 16385fae8b86SMika Westerberg 1639fcc18debSMika Westerberg #ifdef CONFIG_PM_SLEEP 16405d33e0ebSAndy Shevchenko vg->context.pads = devm_kcalloc(vg->dev, gc->ngpio, sizeof(*vg->context.pads), 16415d33e0ebSAndy Shevchenko GFP_KERNEL); 16425d33e0ebSAndy Shevchenko if (!vg->context.pads) 1643d6cb7722SAditya Pakki return -ENOMEM; 1644fcc18debSMika Westerberg #endif 16455fae8b86SMika Westerberg 16465fae8b86SMika Westerberg /* set up interrupts */ 1647f86a1bb5SAndy Shevchenko irq = platform_get_irq_optional(pdev, 0); 1648f86a1bb5SAndy Shevchenko if (irq > 0) { 1649ca8a958eSAndy Shevchenko struct gpio_irq_chip *girq; 1650ca8a958eSAndy Shevchenko 1651ca8a958eSAndy Shevchenko girq = &gc->irq; 16526d209b42SAndy Shevchenko gpio_irq_chip_set_chip(girq, &byt_gpio_irq_chip); 1653ca8a958eSAndy Shevchenko girq->init_hw = byt_gpio_irq_init_hw; 1654ab68b220SAndy Shevchenko girq->init_valid_mask = byt_init_irq_valid_mask; 1655ca8a958eSAndy Shevchenko girq->parent_handler = byt_gpio_irq_handler; 1656ca8a958eSAndy Shevchenko girq->num_parents = 1; 1657990ec243SAndy Shevchenko girq->parents = devm_kcalloc(vg->dev, girq->num_parents, 1658ca8a958eSAndy Shevchenko sizeof(*girq->parents), GFP_KERNEL); 1659ca8a958eSAndy Shevchenko if (!girq->parents) 1660ca8a958eSAndy Shevchenko return -ENOMEM; 1661f86a1bb5SAndy Shevchenko girq->parents[0] = irq; 1662ca8a958eSAndy Shevchenko girq->default_type = IRQ_TYPE_NONE; 1663ca8a958eSAndy Shevchenko girq->handler = handle_bad_irq; 16645fae8b86SMika Westerberg } 16655fae8b86SMika Westerberg 1666990ec243SAndy Shevchenko ret = devm_gpiochip_add_data(vg->dev, gc, vg); 1667ca8a958eSAndy Shevchenko if (ret) { 1668990ec243SAndy Shevchenko dev_err(vg->dev, "failed adding byt-gpio chip\n"); 1669ca8a958eSAndy Shevchenko return ret; 16705fae8b86SMika Westerberg } 16715fae8b86SMika Westerberg 167271e6ca61SCristina Ciocan return ret; 167371e6ca61SCristina Ciocan } 167471e6ca61SCristina Ciocan 16755d33e0ebSAndy Shevchenko static int byt_set_soc_data(struct intel_pinctrl *vg, 16765d33e0ebSAndy Shevchenko const struct intel_pinctrl_soc_data *soc) 167771e6ca61SCristina Ciocan { 1678990ec243SAndy Shevchenko struct platform_device *pdev = to_platform_device(vg->dev); 167971e6ca61SCristina Ciocan int i; 168071e6ca61SCristina Ciocan 16815d33e0ebSAndy Shevchenko vg->soc = soc; 16825d33e0ebSAndy Shevchenko 16835d33e0ebSAndy Shevchenko vg->ncommunities = vg->soc->ncommunities; 16845d33e0ebSAndy Shevchenko vg->communities = devm_kcalloc(vg->dev, vg->ncommunities, 16855d33e0ebSAndy Shevchenko sizeof(*vg->communities), GFP_KERNEL); 16865d33e0ebSAndy Shevchenko if (!vg->communities) 168771e6ca61SCristina Ciocan return -ENOMEM; 168871e6ca61SCristina Ciocan 16895d33e0ebSAndy Shevchenko for (i = 0; i < vg->soc->ncommunities; i++) { 16905d33e0ebSAndy Shevchenko struct intel_community *comm = vg->communities + i; 169171e6ca61SCristina Ciocan 16925d33e0ebSAndy Shevchenko *comm = vg->soc->communities[i]; 169371e6ca61SCristina Ciocan 1694990ec243SAndy Shevchenko comm->pad_regs = devm_platform_ioremap_resource(pdev, 0); 169534e65670SAndy Shevchenko if (IS_ERR(comm->pad_regs)) 169634e65670SAndy Shevchenko return PTR_ERR(comm->pad_regs); 169771e6ca61SCristina Ciocan } 169871e6ca61SCristina Ciocan 169971e6ca61SCristina Ciocan return 0; 170071e6ca61SCristina Ciocan } 170171e6ca61SCristina Ciocan 170271e6ca61SCristina Ciocan static const struct acpi_device_id byt_gpio_acpi_match[] = { 170371e6ca61SCristina Ciocan { "INT33B2", (kernel_ulong_t)byt_soc_data }, 170471e6ca61SCristina Ciocan { "INT33FC", (kernel_ulong_t)byt_soc_data }, 170571e6ca61SCristina Ciocan { } 170671e6ca61SCristina Ciocan }; 170771e6ca61SCristina Ciocan 170871e6ca61SCristina Ciocan static int byt_pinctrl_probe(struct platform_device *pdev) 170971e6ca61SCristina Ciocan { 1710ce7793e9SAndy Shevchenko const struct intel_pinctrl_soc_data *soc_data; 17112c02af70SAndy Shevchenko struct device *dev = &pdev->dev; 17125d33e0ebSAndy Shevchenko struct intel_pinctrl *vg; 1713ce7793e9SAndy Shevchenko int ret; 171471e6ca61SCristina Ciocan 1715ce7793e9SAndy Shevchenko soc_data = intel_pinctrl_get_soc_data(pdev); 1716ce7793e9SAndy Shevchenko if (IS_ERR(soc_data)) 1717ce7793e9SAndy Shevchenko return PTR_ERR(soc_data); 171871e6ca61SCristina Ciocan 17192c02af70SAndy Shevchenko vg = devm_kzalloc(dev, sizeof(*vg), GFP_KERNEL); 172071e6ca61SCristina Ciocan if (!vg) 172171e6ca61SCristina Ciocan return -ENOMEM; 172271e6ca61SCristina Ciocan 17232c02af70SAndy Shevchenko vg->dev = dev; 172471e6ca61SCristina Ciocan ret = byt_set_soc_data(vg, soc_data); 172571e6ca61SCristina Ciocan if (ret) { 17262c02af70SAndy Shevchenko dev_err(dev, "failed to set soc data\n"); 172771e6ca61SCristina Ciocan return ret; 172871e6ca61SCristina Ciocan } 172971e6ca61SCristina Ciocan 17305d33e0ebSAndy Shevchenko vg->pctldesc = byt_pinctrl_desc; 17315d33e0ebSAndy Shevchenko vg->pctldesc.name = dev_name(dev); 17325d33e0ebSAndy Shevchenko vg->pctldesc.pins = vg->soc->pins; 17335d33e0ebSAndy Shevchenko vg->pctldesc.npins = vg->soc->npins; 173471e6ca61SCristina Ciocan 17355d33e0ebSAndy Shevchenko vg->pctldev = devm_pinctrl_register(dev, &vg->pctldesc, vg); 17365d33e0ebSAndy Shevchenko if (IS_ERR(vg->pctldev)) { 17372c02af70SAndy Shevchenko dev_err(dev, "failed to register pinctrl driver\n"); 17385d33e0ebSAndy Shevchenko return PTR_ERR(vg->pctldev); 173971e6ca61SCristina Ciocan } 174071e6ca61SCristina Ciocan 174171e6ca61SCristina Ciocan ret = byt_gpio_probe(vg); 17420612413fSAndy Shevchenko if (ret) 174371e6ca61SCristina Ciocan return ret; 174471e6ca61SCristina Ciocan 174571e6ca61SCristina Ciocan platform_set_drvdata(pdev, vg); 17462c02af70SAndy Shevchenko pm_runtime_enable(dev); 174771e6ca61SCristina Ciocan 174871e6ca61SCristina Ciocan return 0; 174971e6ca61SCristina Ciocan } 175071e6ca61SCristina Ciocan 1751fcc18debSMika Westerberg #ifdef CONFIG_PM_SLEEP 1752fcc18debSMika Westerberg static int byt_gpio_suspend(struct device *dev) 1753fcc18debSMika Westerberg { 17545d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = dev_get_drvdata(dev); 175540ecab55SHans de Goede unsigned long flags; 1756fcc18debSMika Westerberg int i; 1757fcc18debSMika Westerberg 175840ecab55SHans de Goede raw_spin_lock_irqsave(&byt_lock, flags); 175940ecab55SHans de Goede 17605d33e0ebSAndy Shevchenko for (i = 0; i < vg->soc->npins; i++) { 1761fcc18debSMika Westerberg void __iomem *reg; 1762fcc18debSMika Westerberg u32 value; 17635d33e0ebSAndy Shevchenko unsigned int pin = vg->soc->pins[i].number; 1764fcc18debSMika Westerberg 176571e6ca61SCristina Ciocan reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG); 176671e6ca61SCristina Ciocan if (!reg) { 1767990ec243SAndy Shevchenko dev_warn(vg->dev, 176871e6ca61SCristina Ciocan "Pin %i: could not retrieve conf0 register\n", 176971e6ca61SCristina Ciocan i); 177071e6ca61SCristina Ciocan continue; 177171e6ca61SCristina Ciocan } 1772fcc18debSMika Westerberg value = readl(reg) & BYT_CONF0_RESTORE_MASK; 17735d33e0ebSAndy Shevchenko vg->context.pads[i].conf0 = value; 1774fcc18debSMika Westerberg 177571e6ca61SCristina Ciocan reg = byt_gpio_reg(vg, pin, BYT_VAL_REG); 1776fcc18debSMika Westerberg value = readl(reg) & BYT_VAL_RESTORE_MASK; 17775d33e0ebSAndy Shevchenko vg->context.pads[i].val = value; 1778fcc18debSMika Westerberg } 1779fcc18debSMika Westerberg 178040ecab55SHans de Goede raw_spin_unlock_irqrestore(&byt_lock, flags); 1781fcc18debSMika Westerberg return 0; 1782fcc18debSMika Westerberg } 1783fcc18debSMika Westerberg 1784fcc18debSMika Westerberg static int byt_gpio_resume(struct device *dev) 1785fcc18debSMika Westerberg { 17865d33e0ebSAndy Shevchenko struct intel_pinctrl *vg = dev_get_drvdata(dev); 178740ecab55SHans de Goede unsigned long flags; 1788fcc18debSMika Westerberg int i; 1789fcc18debSMika Westerberg 179040ecab55SHans de Goede raw_spin_lock_irqsave(&byt_lock, flags); 179140ecab55SHans de Goede 17925d33e0ebSAndy Shevchenko for (i = 0; i < vg->soc->npins; i++) { 1793fcc18debSMika Westerberg void __iomem *reg; 1794fcc18debSMika Westerberg u32 value; 17955d33e0ebSAndy Shevchenko unsigned int pin = vg->soc->pins[i].number; 1796fcc18debSMika Westerberg 179771e6ca61SCristina Ciocan reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG); 179871e6ca61SCristina Ciocan if (!reg) { 1799990ec243SAndy Shevchenko dev_warn(vg->dev, 180071e6ca61SCristina Ciocan "Pin %i: could not retrieve conf0 register\n", 180171e6ca61SCristina Ciocan i); 180271e6ca61SCristina Ciocan continue; 180371e6ca61SCristina Ciocan } 1804fcc18debSMika Westerberg value = readl(reg); 1805fcc18debSMika Westerberg if ((value & BYT_CONF0_RESTORE_MASK) != 18065d33e0ebSAndy Shevchenko vg->context.pads[i].conf0) { 1807fcc18debSMika Westerberg value &= ~BYT_CONF0_RESTORE_MASK; 18085d33e0ebSAndy Shevchenko value |= vg->context.pads[i].conf0; 1809fcc18debSMika Westerberg writel(value, reg); 1810fcc18debSMika Westerberg dev_info(dev, "restored pin %d conf0 %#08x", i, value); 1811fcc18debSMika Westerberg } 1812fcc18debSMika Westerberg 181371e6ca61SCristina Ciocan reg = byt_gpio_reg(vg, pin, BYT_VAL_REG); 1814fcc18debSMika Westerberg value = readl(reg); 1815fcc18debSMika Westerberg if ((value & BYT_VAL_RESTORE_MASK) != 18165d33e0ebSAndy Shevchenko vg->context.pads[i].val) { 1817fcc18debSMika Westerberg u32 v; 1818fcc18debSMika Westerberg 1819fcc18debSMika Westerberg v = value & ~BYT_VAL_RESTORE_MASK; 18205d33e0ebSAndy Shevchenko v |= vg->context.pads[i].val; 1821fcc18debSMika Westerberg if (v != value) { 1822fcc18debSMika Westerberg writel(v, reg); 1823fcc18debSMika Westerberg dev_dbg(dev, "restored pin %d val %#08x\n", 1824fcc18debSMika Westerberg i, v); 1825fcc18debSMika Westerberg } 1826fcc18debSMika Westerberg } 1827fcc18debSMika Westerberg } 1828fcc18debSMika Westerberg 182940ecab55SHans de Goede raw_spin_unlock_irqrestore(&byt_lock, flags); 1830fcc18debSMika Westerberg return 0; 1831fcc18debSMika Westerberg } 1832fcc18debSMika Westerberg #endif 1833fcc18debSMika Westerberg 1834ec879f12SMika Westerberg #ifdef CONFIG_PM 18355fae8b86SMika Westerberg static int byt_gpio_runtime_suspend(struct device *dev) 18365fae8b86SMika Westerberg { 18375fae8b86SMika Westerberg return 0; 18385fae8b86SMika Westerberg } 18395fae8b86SMika Westerberg 18405fae8b86SMika Westerberg static int byt_gpio_runtime_resume(struct device *dev) 18415fae8b86SMika Westerberg { 18425fae8b86SMika Westerberg return 0; 18435fae8b86SMika Westerberg } 1844ec879f12SMika Westerberg #endif 18455fae8b86SMika Westerberg 18465fae8b86SMika Westerberg static const struct dev_pm_ops byt_gpio_pm_ops = { 1847fcc18debSMika Westerberg SET_LATE_SYSTEM_SLEEP_PM_OPS(byt_gpio_suspend, byt_gpio_resume) 1848fcc18debSMika Westerberg SET_RUNTIME_PM_OPS(byt_gpio_runtime_suspend, byt_gpio_runtime_resume, 1849fcc18debSMika Westerberg NULL) 18505fae8b86SMika Westerberg }; 18515fae8b86SMika Westerberg 18525fae8b86SMika Westerberg static struct platform_driver byt_gpio_driver = { 185371e6ca61SCristina Ciocan .probe = byt_pinctrl_probe, 18545fae8b86SMika Westerberg .driver = { 18555fae8b86SMika Westerberg .name = "byt_gpio", 18565fae8b86SMika Westerberg .pm = &byt_gpio_pm_ops, 1857e87daf0bSAndy Shevchenko .acpi_match_table = byt_gpio_acpi_match, 1858360943a8SPaul Gortmaker .suppress_bind_attrs = true, 18595fae8b86SMika Westerberg }, 18605fae8b86SMika Westerberg }; 18615fae8b86SMika Westerberg 18625fae8b86SMika Westerberg static int __init byt_gpio_init(void) 18635fae8b86SMika Westerberg { 18645fae8b86SMika Westerberg return platform_driver_register(&byt_gpio_driver); 18655fae8b86SMika Westerberg } 18665fae8b86SMika Westerberg subsys_initcall(byt_gpio_init); 1867