1875a92b3SAndy Shevchenko // SPDX-License-Identifier: GPL-2.0 26e08d6bbSMika Westerberg /* 36e08d6bbSMika Westerberg * Cherryview/Braswell pinctrl driver 46e08d6bbSMika Westerberg * 5293428f9SAndy Shevchenko * Copyright (C) 2014, 2020 Intel Corporation 66e08d6bbSMika Westerberg * Author: Mika Westerberg <mika.westerberg@linux.intel.com> 76e08d6bbSMika Westerberg * 86e08d6bbSMika Westerberg * This driver is based on the original Cherryview GPIO driver by 96e08d6bbSMika Westerberg * Ning Li <ning.li@intel.com> 106e08d6bbSMika Westerberg * Alan Cox <alan@linux.intel.com> 116e08d6bbSMika Westerberg */ 126e08d6bbSMika Westerberg 13994f8865SAndy Shevchenko #include <linux/acpi.h> 1470365027SMika Westerberg #include <linux/dmi.h> 15994f8865SAndy Shevchenko #include <linux/gpio/driver.h> 166e08d6bbSMika Westerberg #include <linux/kernel.h> 176e08d6bbSMika Westerberg #include <linux/module.h> 18994f8865SAndy Shevchenko #include <linux/platform_device.h> 196e08d6bbSMika Westerberg #include <linux/types.h> 20994f8865SAndy Shevchenko 216e08d6bbSMika Westerberg #include <linux/pinctrl/pinctrl.h> 226e08d6bbSMika Westerberg #include <linux/pinctrl/pinmux.h> 236e08d6bbSMika Westerberg #include <linux/pinctrl/pinconf.h> 246e08d6bbSMika Westerberg #include <linux/pinctrl/pinconf-generic.h> 256e08d6bbSMika Westerberg 265458b7ceSAndy Shevchenko #include "pinctrl-intel.h" 275458b7ceSAndy Shevchenko 286e08d6bbSMika Westerberg #define CHV_INTSTAT 0x300 296e08d6bbSMika Westerberg #define CHV_INTMASK 0x380 306e08d6bbSMika Westerberg 316e08d6bbSMika Westerberg #define FAMILY_PAD_REGS_OFF 0x4400 326e08d6bbSMika Westerberg #define FAMILY_PAD_REGS_SIZE 0x400 336e08d6bbSMika Westerberg #define MAX_FAMILY_PAD_GPIO_NO 15 346e08d6bbSMika Westerberg #define GPIO_REGS_SIZE 8 356e08d6bbSMika Westerberg 366e08d6bbSMika Westerberg #define CHV_PADCTRL0 0x000 376e08d6bbSMika Westerberg #define CHV_PADCTRL0_INTSEL_SHIFT 28 385707dd73SAndy Shevchenko #define CHV_PADCTRL0_INTSEL_MASK GENMASK(31, 28) 396e08d6bbSMika Westerberg #define CHV_PADCTRL0_TERM_UP BIT(23) 406e08d6bbSMika Westerberg #define CHV_PADCTRL0_TERM_SHIFT 20 415707dd73SAndy Shevchenko #define CHV_PADCTRL0_TERM_MASK GENMASK(22, 20) 426e08d6bbSMika Westerberg #define CHV_PADCTRL0_TERM_20K 1 436e08d6bbSMika Westerberg #define CHV_PADCTRL0_TERM_5K 2 446e08d6bbSMika Westerberg #define CHV_PADCTRL0_TERM_1K 4 456e08d6bbSMika Westerberg #define CHV_PADCTRL0_PMODE_SHIFT 16 465707dd73SAndy Shevchenko #define CHV_PADCTRL0_PMODE_MASK GENMASK(19, 16) 476e08d6bbSMika Westerberg #define CHV_PADCTRL0_GPIOEN BIT(15) 486e08d6bbSMika Westerberg #define CHV_PADCTRL0_GPIOCFG_SHIFT 8 495707dd73SAndy Shevchenko #define CHV_PADCTRL0_GPIOCFG_MASK GENMASK(10, 8) 506e08d6bbSMika Westerberg #define CHV_PADCTRL0_GPIOCFG_GPIO 0 516e08d6bbSMika Westerberg #define CHV_PADCTRL0_GPIOCFG_GPO 1 526e08d6bbSMika Westerberg #define CHV_PADCTRL0_GPIOCFG_GPI 2 536e08d6bbSMika Westerberg #define CHV_PADCTRL0_GPIOCFG_HIZ 3 546e08d6bbSMika Westerberg #define CHV_PADCTRL0_GPIOTXSTATE BIT(1) 556e08d6bbSMika Westerberg #define CHV_PADCTRL0_GPIORXSTATE BIT(0) 566e08d6bbSMika Westerberg 576e08d6bbSMika Westerberg #define CHV_PADCTRL1 0x004 586e08d6bbSMika Westerberg #define CHV_PADCTRL1_CFGLOCK BIT(31) 596e08d6bbSMika Westerberg #define CHV_PADCTRL1_INVRXTX_SHIFT 4 605707dd73SAndy Shevchenko #define CHV_PADCTRL1_INVRXTX_MASK GENMASK(7, 4) 615707dd73SAndy Shevchenko #define CHV_PADCTRL1_INVRXTX_RXDATA BIT(6) 625707dd73SAndy Shevchenko #define CHV_PADCTRL1_INVRXTX_TXENABLE BIT(5) 636e08d6bbSMika Westerberg #define CHV_PADCTRL1_ODEN BIT(3) 645707dd73SAndy Shevchenko #define CHV_PADCTRL1_INTWAKECFG_MASK GENMASK(2, 0) 656e08d6bbSMika Westerberg #define CHV_PADCTRL1_INTWAKECFG_FALLING 1 666e08d6bbSMika Westerberg #define CHV_PADCTRL1_INTWAKECFG_RISING 2 676e08d6bbSMika Westerberg #define CHV_PADCTRL1_INTWAKECFG_BOTH 3 686e08d6bbSMika Westerberg #define CHV_PADCTRL1_INTWAKECFG_LEVEL 4 696e08d6bbSMika Westerberg 70293428f9SAndy Shevchenko struct intel_pad_context { 719eb457b5SMika Westerberg u32 padctrl0; 729eb457b5SMika Westerberg u32 padctrl1; 739eb457b5SMika Westerberg }; 749eb457b5SMika Westerberg 756e08d6bbSMika Westerberg /** 768a828570SAndy Shevchenko * struct intel_community_context - community context for Cherryview 778a828570SAndy Shevchenko * @intr_lines: Mapping between 16 HW interrupt wires and GPIO offset (in GPIO number space) 788a828570SAndy Shevchenko * @saved_intmask: Interrupt mask saved for system sleep 798a828570SAndy Shevchenko */ 808a828570SAndy Shevchenko struct intel_community_context { 818a828570SAndy Shevchenko unsigned int intr_lines[16]; 828a828570SAndy Shevchenko u32 saved_intmask; 838a828570SAndy Shevchenko }; 848a828570SAndy Shevchenko 8536ad7b24SAndy Shevchenko #define PINMODE_INVERT_OE BIT(15) 866e08d6bbSMika Westerberg 8736ad7b24SAndy Shevchenko #define PINMODE(m, i) ((m) | ((i) * PINMODE_INVERT_OE)) 886e08d6bbSMika Westerberg 8936ad7b24SAndy Shevchenko #define CHV_GPP(start, end) \ 906e08d6bbSMika Westerberg { \ 916e08d6bbSMika Westerberg .base = (start), \ 9236ad7b24SAndy Shevchenko .size = (end) - (start) + 1, \ 936e08d6bbSMika Westerberg } 946e08d6bbSMika Westerberg 95293428f9SAndy Shevchenko #define CHV_COMMUNITY(g, i, a) \ 96293428f9SAndy Shevchenko { \ 97293428f9SAndy Shevchenko .gpps = (g), \ 98293428f9SAndy Shevchenko .ngpps = ARRAY_SIZE(g), \ 99293428f9SAndy Shevchenko .nirqs = (i), \ 100293428f9SAndy Shevchenko .acpi_space_id = (a), \ 101293428f9SAndy Shevchenko } 102293428f9SAndy Shevchenko 1036e08d6bbSMika Westerberg static const struct pinctrl_pin_desc southwest_pins[] = { 1046e08d6bbSMika Westerberg PINCTRL_PIN(0, "FST_SPI_D2"), 1056e08d6bbSMika Westerberg PINCTRL_PIN(1, "FST_SPI_D0"), 1066e08d6bbSMika Westerberg PINCTRL_PIN(2, "FST_SPI_CLK"), 1076e08d6bbSMika Westerberg PINCTRL_PIN(3, "FST_SPI_D3"), 1086e08d6bbSMika Westerberg PINCTRL_PIN(4, "FST_SPI_CS1_B"), 1096e08d6bbSMika Westerberg PINCTRL_PIN(5, "FST_SPI_D1"), 1106e08d6bbSMika Westerberg PINCTRL_PIN(6, "FST_SPI_CS0_B"), 1116e08d6bbSMika Westerberg PINCTRL_PIN(7, "FST_SPI_CS2_B"), 1126e08d6bbSMika Westerberg 1136e08d6bbSMika Westerberg PINCTRL_PIN(15, "UART1_RTS_B"), 1146e08d6bbSMika Westerberg PINCTRL_PIN(16, "UART1_RXD"), 1156e08d6bbSMika Westerberg PINCTRL_PIN(17, "UART2_RXD"), 1166e08d6bbSMika Westerberg PINCTRL_PIN(18, "UART1_CTS_B"), 1176e08d6bbSMika Westerberg PINCTRL_PIN(19, "UART2_RTS_B"), 1186e08d6bbSMika Westerberg PINCTRL_PIN(20, "UART1_TXD"), 1196e08d6bbSMika Westerberg PINCTRL_PIN(21, "UART2_TXD"), 1206e08d6bbSMika Westerberg PINCTRL_PIN(22, "UART2_CTS_B"), 1216e08d6bbSMika Westerberg 1226e08d6bbSMika Westerberg PINCTRL_PIN(30, "MF_HDA_CLK"), 1236e08d6bbSMika Westerberg PINCTRL_PIN(31, "MF_HDA_RSTB"), 1246e08d6bbSMika Westerberg PINCTRL_PIN(32, "MF_HDA_SDIO"), 1256e08d6bbSMika Westerberg PINCTRL_PIN(33, "MF_HDA_SDO"), 1266e08d6bbSMika Westerberg PINCTRL_PIN(34, "MF_HDA_DOCKRSTB"), 1276e08d6bbSMika Westerberg PINCTRL_PIN(35, "MF_HDA_SYNC"), 1286e08d6bbSMika Westerberg PINCTRL_PIN(36, "MF_HDA_SDI1"), 1296e08d6bbSMika Westerberg PINCTRL_PIN(37, "MF_HDA_DOCKENB"), 1306e08d6bbSMika Westerberg 1316e08d6bbSMika Westerberg PINCTRL_PIN(45, "I2C5_SDA"), 1326e08d6bbSMika Westerberg PINCTRL_PIN(46, "I2C4_SDA"), 1336e08d6bbSMika Westerberg PINCTRL_PIN(47, "I2C6_SDA"), 1346e08d6bbSMika Westerberg PINCTRL_PIN(48, "I2C5_SCL"), 1356e08d6bbSMika Westerberg PINCTRL_PIN(49, "I2C_NFC_SDA"), 1366e08d6bbSMika Westerberg PINCTRL_PIN(50, "I2C4_SCL"), 1376e08d6bbSMika Westerberg PINCTRL_PIN(51, "I2C6_SCL"), 1386e08d6bbSMika Westerberg PINCTRL_PIN(52, "I2C_NFC_SCL"), 1396e08d6bbSMika Westerberg 1406e08d6bbSMika Westerberg PINCTRL_PIN(60, "I2C1_SDA"), 1416e08d6bbSMika Westerberg PINCTRL_PIN(61, "I2C0_SDA"), 1426e08d6bbSMika Westerberg PINCTRL_PIN(62, "I2C2_SDA"), 1436e08d6bbSMika Westerberg PINCTRL_PIN(63, "I2C1_SCL"), 1446e08d6bbSMika Westerberg PINCTRL_PIN(64, "I2C3_SDA"), 1456e08d6bbSMika Westerberg PINCTRL_PIN(65, "I2C0_SCL"), 1466e08d6bbSMika Westerberg PINCTRL_PIN(66, "I2C2_SCL"), 1476e08d6bbSMika Westerberg PINCTRL_PIN(67, "I2C3_SCL"), 1486e08d6bbSMika Westerberg 1496e08d6bbSMika Westerberg PINCTRL_PIN(75, "SATA_GP0"), 1506e08d6bbSMika Westerberg PINCTRL_PIN(76, "SATA_GP1"), 1516e08d6bbSMika Westerberg PINCTRL_PIN(77, "SATA_LEDN"), 1526e08d6bbSMika Westerberg PINCTRL_PIN(78, "SATA_GP2"), 1536e08d6bbSMika Westerberg PINCTRL_PIN(79, "MF_SMB_ALERTB"), 1546e08d6bbSMika Westerberg PINCTRL_PIN(80, "SATA_GP3"), 1556e08d6bbSMika Westerberg PINCTRL_PIN(81, "MF_SMB_CLK"), 1566e08d6bbSMika Westerberg PINCTRL_PIN(82, "MF_SMB_DATA"), 1576e08d6bbSMika Westerberg 1586e08d6bbSMika Westerberg PINCTRL_PIN(90, "PCIE_CLKREQ0B"), 1596e08d6bbSMika Westerberg PINCTRL_PIN(91, "PCIE_CLKREQ1B"), 1606e08d6bbSMika Westerberg PINCTRL_PIN(92, "GP_SSP_2_CLK"), 1616e08d6bbSMika Westerberg PINCTRL_PIN(93, "PCIE_CLKREQ2B"), 1626e08d6bbSMika Westerberg PINCTRL_PIN(94, "GP_SSP_2_RXD"), 1636e08d6bbSMika Westerberg PINCTRL_PIN(95, "PCIE_CLKREQ3B"), 1646e08d6bbSMika Westerberg PINCTRL_PIN(96, "GP_SSP_2_FS"), 1656e08d6bbSMika Westerberg PINCTRL_PIN(97, "GP_SSP_2_TXD"), 1666e08d6bbSMika Westerberg }; 1676e08d6bbSMika Westerberg 1686e08d6bbSMika Westerberg static const unsigned southwest_uart0_pins[] = { 16, 20 }; 1696e08d6bbSMika Westerberg static const unsigned southwest_uart1_pins[] = { 15, 16, 18, 20 }; 1706e08d6bbSMika Westerberg static const unsigned southwest_uart2_pins[] = { 17, 19, 21, 22 }; 1716e08d6bbSMika Westerberg static const unsigned southwest_i2c0_pins[] = { 61, 65 }; 1726e08d6bbSMika Westerberg static const unsigned southwest_hda_pins[] = { 30, 31, 32, 33, 34, 35, 36, 37 }; 1736e08d6bbSMika Westerberg static const unsigned southwest_lpe_pins[] = { 1746e08d6bbSMika Westerberg 30, 31, 32, 33, 34, 35, 36, 37, 92, 94, 96, 97, 1756e08d6bbSMika Westerberg }; 1766e08d6bbSMika Westerberg static const unsigned southwest_i2c1_pins[] = { 60, 63 }; 1776e08d6bbSMika Westerberg static const unsigned southwest_i2c2_pins[] = { 62, 66 }; 1786e08d6bbSMika Westerberg static const unsigned southwest_i2c3_pins[] = { 64, 67 }; 1796e08d6bbSMika Westerberg static const unsigned southwest_i2c4_pins[] = { 46, 50 }; 1806e08d6bbSMika Westerberg static const unsigned southwest_i2c5_pins[] = { 45, 48 }; 1816e08d6bbSMika Westerberg static const unsigned southwest_i2c6_pins[] = { 47, 51 }; 1826e08d6bbSMika Westerberg static const unsigned southwest_i2c_nfc_pins[] = { 49, 52 }; 1836e08d6bbSMika Westerberg static const unsigned southwest_spi3_pins[] = { 76, 79, 80, 81, 82 }; 1846e08d6bbSMika Westerberg 18536ad7b24SAndy Shevchenko /* Some of LPE I2S TXD pins need to have OE inversion set */ 18636ad7b24SAndy Shevchenko static const unsigned int southwest_lpe_altfuncs[] = { 18736ad7b24SAndy Shevchenko PINMODE(1, 1), PINMODE(1, 0), PINMODE(1, 0), PINMODE(1, 0), /* 30, 31, 32, 33 */ 18836ad7b24SAndy Shevchenko PINMODE(1, 1), PINMODE(1, 0), PINMODE(1, 0), PINMODE(1, 0), /* 34, 35, 36, 37 */ 18936ad7b24SAndy Shevchenko PINMODE(1, 0), PINMODE(1, 0), PINMODE(1, 0), PINMODE(1, 1), /* 92, 94, 96, 97 */ 1906e08d6bbSMika Westerberg }; 1916e08d6bbSMika Westerberg 1926e08d6bbSMika Westerberg /* 1936e08d6bbSMika Westerberg * Two spi3 chipselects are available in different mode than the main spi3 19436ad7b24SAndy Shevchenko * functionality, which is using mode 2. 1956e08d6bbSMika Westerberg */ 19636ad7b24SAndy Shevchenko static const unsigned int southwest_spi3_altfuncs[] = { 19736ad7b24SAndy Shevchenko PINMODE(3, 0), PINMODE(2, 0), PINMODE(3, 0), PINMODE(2, 0), /* 76, 79, 80, 81 */ 19836ad7b24SAndy Shevchenko PINMODE(2, 0), /* 82 */ 1996e08d6bbSMika Westerberg }; 2006e08d6bbSMika Westerberg 20136ad7b24SAndy Shevchenko static const struct intel_pingroup southwest_groups[] = { 20236ad7b24SAndy Shevchenko PIN_GROUP("uart0_grp", southwest_uart0_pins, PINMODE(2, 0)), 20336ad7b24SAndy Shevchenko PIN_GROUP("uart1_grp", southwest_uart1_pins, PINMODE(1, 0)), 20436ad7b24SAndy Shevchenko PIN_GROUP("uart2_grp", southwest_uart2_pins, PINMODE(1, 0)), 20536ad7b24SAndy Shevchenko PIN_GROUP("hda_grp", southwest_hda_pins, PINMODE(2, 0)), 20636ad7b24SAndy Shevchenko PIN_GROUP("i2c0_grp", southwest_i2c0_pins, PINMODE(1, 1)), 20736ad7b24SAndy Shevchenko PIN_GROUP("i2c1_grp", southwest_i2c1_pins, PINMODE(1, 1)), 20836ad7b24SAndy Shevchenko PIN_GROUP("i2c2_grp", southwest_i2c2_pins, PINMODE(1, 1)), 20936ad7b24SAndy Shevchenko PIN_GROUP("i2c3_grp", southwest_i2c3_pins, PINMODE(1, 1)), 21036ad7b24SAndy Shevchenko PIN_GROUP("i2c4_grp", southwest_i2c4_pins, PINMODE(1, 1)), 21136ad7b24SAndy Shevchenko PIN_GROUP("i2c5_grp", southwest_i2c5_pins, PINMODE(1, 1)), 21236ad7b24SAndy Shevchenko PIN_GROUP("i2c6_grp", southwest_i2c6_pins, PINMODE(1, 1)), 21336ad7b24SAndy Shevchenko PIN_GROUP("i2c_nfc_grp", southwest_i2c_nfc_pins, PINMODE(2, 1)), 21436ad7b24SAndy Shevchenko PIN_GROUP("lpe_grp", southwest_lpe_pins, southwest_lpe_altfuncs), 21536ad7b24SAndy Shevchenko PIN_GROUP("spi3_grp", southwest_spi3_pins, southwest_spi3_altfuncs), 2166e08d6bbSMika Westerberg }; 2176e08d6bbSMika Westerberg 2186e08d6bbSMika Westerberg static const char * const southwest_uart0_groups[] = { "uart0_grp" }; 2196e08d6bbSMika Westerberg static const char * const southwest_uart1_groups[] = { "uart1_grp" }; 2206e08d6bbSMika Westerberg static const char * const southwest_uart2_groups[] = { "uart2_grp" }; 2216e08d6bbSMika Westerberg static const char * const southwest_hda_groups[] = { "hda_grp" }; 2226e08d6bbSMika Westerberg static const char * const southwest_lpe_groups[] = { "lpe_grp" }; 2236e08d6bbSMika Westerberg static const char * const southwest_i2c0_groups[] = { "i2c0_grp" }; 2246e08d6bbSMika Westerberg static const char * const southwest_i2c1_groups[] = { "i2c1_grp" }; 2256e08d6bbSMika Westerberg static const char * const southwest_i2c2_groups[] = { "i2c2_grp" }; 2266e08d6bbSMika Westerberg static const char * const southwest_i2c3_groups[] = { "i2c3_grp" }; 2276e08d6bbSMika Westerberg static const char * const southwest_i2c4_groups[] = { "i2c4_grp" }; 2286e08d6bbSMika Westerberg static const char * const southwest_i2c5_groups[] = { "i2c5_grp" }; 2296e08d6bbSMika Westerberg static const char * const southwest_i2c6_groups[] = { "i2c6_grp" }; 2306e08d6bbSMika Westerberg static const char * const southwest_i2c_nfc_groups[] = { "i2c_nfc_grp" }; 2316e08d6bbSMika Westerberg static const char * const southwest_spi3_groups[] = { "spi3_grp" }; 2326e08d6bbSMika Westerberg 2336e08d6bbSMika Westerberg /* 2346e08d6bbSMika Westerberg * Only do pinmuxing for certain LPSS devices for now. Rest of the pins are 2356e08d6bbSMika Westerberg * enabled only as GPIOs. 2366e08d6bbSMika Westerberg */ 2375458b7ceSAndy Shevchenko static const struct intel_function southwest_functions[] = { 2386e08d6bbSMika Westerberg FUNCTION("uart0", southwest_uart0_groups), 2396e08d6bbSMika Westerberg FUNCTION("uart1", southwest_uart1_groups), 2406e08d6bbSMika Westerberg FUNCTION("uart2", southwest_uart2_groups), 2416e08d6bbSMika Westerberg FUNCTION("hda", southwest_hda_groups), 2426e08d6bbSMika Westerberg FUNCTION("lpe", southwest_lpe_groups), 2436e08d6bbSMika Westerberg FUNCTION("i2c0", southwest_i2c0_groups), 2446e08d6bbSMika Westerberg FUNCTION("i2c1", southwest_i2c1_groups), 2456e08d6bbSMika Westerberg FUNCTION("i2c2", southwest_i2c2_groups), 2466e08d6bbSMika Westerberg FUNCTION("i2c3", southwest_i2c3_groups), 2476e08d6bbSMika Westerberg FUNCTION("i2c4", southwest_i2c4_groups), 2486e08d6bbSMika Westerberg FUNCTION("i2c5", southwest_i2c5_groups), 2496e08d6bbSMika Westerberg FUNCTION("i2c6", southwest_i2c6_groups), 2506e08d6bbSMika Westerberg FUNCTION("i2c_nfc", southwest_i2c_nfc_groups), 2516e08d6bbSMika Westerberg FUNCTION("spi3", southwest_spi3_groups), 2526e08d6bbSMika Westerberg }; 2536e08d6bbSMika Westerberg 25436ad7b24SAndy Shevchenko static const struct intel_padgroup southwest_gpps[] = { 25536ad7b24SAndy Shevchenko CHV_GPP(0, 7), 25636ad7b24SAndy Shevchenko CHV_GPP(15, 22), 25736ad7b24SAndy Shevchenko CHV_GPP(30, 37), 25836ad7b24SAndy Shevchenko CHV_GPP(45, 52), 25936ad7b24SAndy Shevchenko CHV_GPP(60, 67), 26036ad7b24SAndy Shevchenko CHV_GPP(75, 82), 26136ad7b24SAndy Shevchenko CHV_GPP(90, 97), 2626e08d6bbSMika Westerberg }; 2636e08d6bbSMika Westerberg 264293428f9SAndy Shevchenko /* 265293428f9SAndy Shevchenko * Southwest community can generate GPIO interrupts only for the first 8 266293428f9SAndy Shevchenko * interrupts. The upper half (8-15) can only be used to trigger GPEs. 267293428f9SAndy Shevchenko */ 268293428f9SAndy Shevchenko static const struct intel_community southwest_communities[] = { 269293428f9SAndy Shevchenko CHV_COMMUNITY(southwest_gpps, 8, 0x91), 270293428f9SAndy Shevchenko }; 271293428f9SAndy Shevchenko 272293428f9SAndy Shevchenko static const struct intel_pinctrl_soc_data southwest_soc_data = { 2736e08d6bbSMika Westerberg .uid = "1", 2746e08d6bbSMika Westerberg .pins = southwest_pins, 2756e08d6bbSMika Westerberg .npins = ARRAY_SIZE(southwest_pins), 2766e08d6bbSMika Westerberg .groups = southwest_groups, 2776e08d6bbSMika Westerberg .ngroups = ARRAY_SIZE(southwest_groups), 2786e08d6bbSMika Westerberg .functions = southwest_functions, 2796e08d6bbSMika Westerberg .nfunctions = ARRAY_SIZE(southwest_functions), 280293428f9SAndy Shevchenko .communities = southwest_communities, 281293428f9SAndy Shevchenko .ncommunities = ARRAY_SIZE(southwest_communities), 2826e08d6bbSMika Westerberg }; 2836e08d6bbSMika Westerberg 2846e08d6bbSMika Westerberg static const struct pinctrl_pin_desc north_pins[] = { 2856e08d6bbSMika Westerberg PINCTRL_PIN(0, "GPIO_DFX_0"), 2866e08d6bbSMika Westerberg PINCTRL_PIN(1, "GPIO_DFX_3"), 2876e08d6bbSMika Westerberg PINCTRL_PIN(2, "GPIO_DFX_7"), 2886e08d6bbSMika Westerberg PINCTRL_PIN(3, "GPIO_DFX_1"), 2896e08d6bbSMika Westerberg PINCTRL_PIN(4, "GPIO_DFX_5"), 2906e08d6bbSMika Westerberg PINCTRL_PIN(5, "GPIO_DFX_4"), 2916e08d6bbSMika Westerberg PINCTRL_PIN(6, "GPIO_DFX_8"), 2926e08d6bbSMika Westerberg PINCTRL_PIN(7, "GPIO_DFX_2"), 2936e08d6bbSMika Westerberg PINCTRL_PIN(8, "GPIO_DFX_6"), 2946e08d6bbSMika Westerberg 2956e08d6bbSMika Westerberg PINCTRL_PIN(15, "GPIO_SUS0"), 2966e08d6bbSMika Westerberg PINCTRL_PIN(16, "SEC_GPIO_SUS10"), 2976e08d6bbSMika Westerberg PINCTRL_PIN(17, "GPIO_SUS3"), 2986e08d6bbSMika Westerberg PINCTRL_PIN(18, "GPIO_SUS7"), 2996e08d6bbSMika Westerberg PINCTRL_PIN(19, "GPIO_SUS1"), 3006e08d6bbSMika Westerberg PINCTRL_PIN(20, "GPIO_SUS5"), 3016e08d6bbSMika Westerberg PINCTRL_PIN(21, "SEC_GPIO_SUS11"), 3026e08d6bbSMika Westerberg PINCTRL_PIN(22, "GPIO_SUS4"), 3036e08d6bbSMika Westerberg PINCTRL_PIN(23, "SEC_GPIO_SUS8"), 3046e08d6bbSMika Westerberg PINCTRL_PIN(24, "GPIO_SUS2"), 3056e08d6bbSMika Westerberg PINCTRL_PIN(25, "GPIO_SUS6"), 3066e08d6bbSMika Westerberg PINCTRL_PIN(26, "CX_PREQ_B"), 3076e08d6bbSMika Westerberg PINCTRL_PIN(27, "SEC_GPIO_SUS9"), 3086e08d6bbSMika Westerberg 3096e08d6bbSMika Westerberg PINCTRL_PIN(30, "TRST_B"), 3106e08d6bbSMika Westerberg PINCTRL_PIN(31, "TCK"), 3116e08d6bbSMika Westerberg PINCTRL_PIN(32, "PROCHOT_B"), 3126e08d6bbSMika Westerberg PINCTRL_PIN(33, "SVIDO_DATA"), 3136e08d6bbSMika Westerberg PINCTRL_PIN(34, "TMS"), 3146e08d6bbSMika Westerberg PINCTRL_PIN(35, "CX_PRDY_B_2"), 3156e08d6bbSMika Westerberg PINCTRL_PIN(36, "TDO_2"), 3166e08d6bbSMika Westerberg PINCTRL_PIN(37, "CX_PRDY_B"), 3176e08d6bbSMika Westerberg PINCTRL_PIN(38, "SVIDO_ALERT_B"), 3186e08d6bbSMika Westerberg PINCTRL_PIN(39, "TDO"), 3196e08d6bbSMika Westerberg PINCTRL_PIN(40, "SVIDO_CLK"), 3206e08d6bbSMika Westerberg PINCTRL_PIN(41, "TDI"), 3216e08d6bbSMika Westerberg 3226e08d6bbSMika Westerberg PINCTRL_PIN(45, "GP_CAMERASB_05"), 3236e08d6bbSMika Westerberg PINCTRL_PIN(46, "GP_CAMERASB_02"), 3246e08d6bbSMika Westerberg PINCTRL_PIN(47, "GP_CAMERASB_08"), 3256e08d6bbSMika Westerberg PINCTRL_PIN(48, "GP_CAMERASB_00"), 3266e08d6bbSMika Westerberg PINCTRL_PIN(49, "GP_CAMERASB_06"), 3276e08d6bbSMika Westerberg PINCTRL_PIN(50, "GP_CAMERASB_10"), 3286e08d6bbSMika Westerberg PINCTRL_PIN(51, "GP_CAMERASB_03"), 3296e08d6bbSMika Westerberg PINCTRL_PIN(52, "GP_CAMERASB_09"), 3306e08d6bbSMika Westerberg PINCTRL_PIN(53, "GP_CAMERASB_01"), 3316e08d6bbSMika Westerberg PINCTRL_PIN(54, "GP_CAMERASB_07"), 3326e08d6bbSMika Westerberg PINCTRL_PIN(55, "GP_CAMERASB_11"), 3336e08d6bbSMika Westerberg PINCTRL_PIN(56, "GP_CAMERASB_04"), 3346e08d6bbSMika Westerberg 3356e08d6bbSMika Westerberg PINCTRL_PIN(60, "PANEL0_BKLTEN"), 3366e08d6bbSMika Westerberg PINCTRL_PIN(61, "HV_DDI0_HPD"), 3376e08d6bbSMika Westerberg PINCTRL_PIN(62, "HV_DDI2_DDC_SDA"), 3386e08d6bbSMika Westerberg PINCTRL_PIN(63, "PANEL1_BKLTCTL"), 3396e08d6bbSMika Westerberg PINCTRL_PIN(64, "HV_DDI1_HPD"), 3406e08d6bbSMika Westerberg PINCTRL_PIN(65, "PANEL0_BKLTCTL"), 3416e08d6bbSMika Westerberg PINCTRL_PIN(66, "HV_DDI0_DDC_SDA"), 3426e08d6bbSMika Westerberg PINCTRL_PIN(67, "HV_DDI2_DDC_SCL"), 3436e08d6bbSMika Westerberg PINCTRL_PIN(68, "HV_DDI2_HPD"), 3446e08d6bbSMika Westerberg PINCTRL_PIN(69, "PANEL1_VDDEN"), 3456e08d6bbSMika Westerberg PINCTRL_PIN(70, "PANEL1_BKLTEN"), 3466e08d6bbSMika Westerberg PINCTRL_PIN(71, "HV_DDI0_DDC_SCL"), 3476e08d6bbSMika Westerberg PINCTRL_PIN(72, "PANEL0_VDDEN"), 3486e08d6bbSMika Westerberg }; 3496e08d6bbSMika Westerberg 35036ad7b24SAndy Shevchenko static const struct intel_padgroup north_gpps[] = { 35136ad7b24SAndy Shevchenko CHV_GPP(0, 8), 35236ad7b24SAndy Shevchenko CHV_GPP(15, 27), 35336ad7b24SAndy Shevchenko CHV_GPP(30, 41), 35436ad7b24SAndy Shevchenko CHV_GPP(45, 56), 35536ad7b24SAndy Shevchenko CHV_GPP(60, 72), 3566e08d6bbSMika Westerberg }; 3576e08d6bbSMika Westerberg 358293428f9SAndy Shevchenko /* 359293428f9SAndy Shevchenko * North community can generate GPIO interrupts only for the first 8 360293428f9SAndy Shevchenko * interrupts. The upper half (8-15) can only be used to trigger GPEs. 361293428f9SAndy Shevchenko */ 362293428f9SAndy Shevchenko static const struct intel_community north_communities[] = { 363293428f9SAndy Shevchenko CHV_COMMUNITY(north_gpps, 8, 0x92), 364293428f9SAndy Shevchenko }; 365293428f9SAndy Shevchenko 366293428f9SAndy Shevchenko static const struct intel_pinctrl_soc_data north_soc_data = { 3676e08d6bbSMika Westerberg .uid = "2", 3686e08d6bbSMika Westerberg .pins = north_pins, 3696e08d6bbSMika Westerberg .npins = ARRAY_SIZE(north_pins), 370293428f9SAndy Shevchenko .communities = north_communities, 371293428f9SAndy Shevchenko .ncommunities = ARRAY_SIZE(north_communities), 3726e08d6bbSMika Westerberg }; 3736e08d6bbSMika Westerberg 3746e08d6bbSMika Westerberg static const struct pinctrl_pin_desc east_pins[] = { 3756e08d6bbSMika Westerberg PINCTRL_PIN(0, "PMU_SLP_S3_B"), 3766e08d6bbSMika Westerberg PINCTRL_PIN(1, "PMU_BATLOW_B"), 3776e08d6bbSMika Westerberg PINCTRL_PIN(2, "SUS_STAT_B"), 3786e08d6bbSMika Westerberg PINCTRL_PIN(3, "PMU_SLP_S0IX_B"), 3796e08d6bbSMika Westerberg PINCTRL_PIN(4, "PMU_AC_PRESENT"), 3806e08d6bbSMika Westerberg PINCTRL_PIN(5, "PMU_PLTRST_B"), 3816e08d6bbSMika Westerberg PINCTRL_PIN(6, "PMU_SUSCLK"), 3826e08d6bbSMika Westerberg PINCTRL_PIN(7, "PMU_SLP_LAN_B"), 3836e08d6bbSMika Westerberg PINCTRL_PIN(8, "PMU_PWRBTN_B"), 3846e08d6bbSMika Westerberg PINCTRL_PIN(9, "PMU_SLP_S4_B"), 3856e08d6bbSMika Westerberg PINCTRL_PIN(10, "PMU_WAKE_B"), 3866e08d6bbSMika Westerberg PINCTRL_PIN(11, "PMU_WAKE_LAN_B"), 3876e08d6bbSMika Westerberg 3886e08d6bbSMika Westerberg PINCTRL_PIN(15, "MF_ISH_GPIO_3"), 3896e08d6bbSMika Westerberg PINCTRL_PIN(16, "MF_ISH_GPIO_7"), 3906e08d6bbSMika Westerberg PINCTRL_PIN(17, "MF_ISH_I2C1_SCL"), 3916e08d6bbSMika Westerberg PINCTRL_PIN(18, "MF_ISH_GPIO_1"), 3926e08d6bbSMika Westerberg PINCTRL_PIN(19, "MF_ISH_GPIO_5"), 3936e08d6bbSMika Westerberg PINCTRL_PIN(20, "MF_ISH_GPIO_9"), 3946e08d6bbSMika Westerberg PINCTRL_PIN(21, "MF_ISH_GPIO_0"), 3956e08d6bbSMika Westerberg PINCTRL_PIN(22, "MF_ISH_GPIO_4"), 3966e08d6bbSMika Westerberg PINCTRL_PIN(23, "MF_ISH_GPIO_8"), 3976e08d6bbSMika Westerberg PINCTRL_PIN(24, "MF_ISH_GPIO_2"), 3986e08d6bbSMika Westerberg PINCTRL_PIN(25, "MF_ISH_GPIO_6"), 3996e08d6bbSMika Westerberg PINCTRL_PIN(26, "MF_ISH_I2C1_SDA"), 4006e08d6bbSMika Westerberg }; 4016e08d6bbSMika Westerberg 40236ad7b24SAndy Shevchenko static const struct intel_padgroup east_gpps[] = { 40336ad7b24SAndy Shevchenko CHV_GPP(0, 11), 40436ad7b24SAndy Shevchenko CHV_GPP(15, 26), 4056e08d6bbSMika Westerberg }; 4066e08d6bbSMika Westerberg 407293428f9SAndy Shevchenko static const struct intel_community east_communities[] = { 408293428f9SAndy Shevchenko CHV_COMMUNITY(east_gpps, 16, 0x93), 409293428f9SAndy Shevchenko }; 410293428f9SAndy Shevchenko 411293428f9SAndy Shevchenko static const struct intel_pinctrl_soc_data east_soc_data = { 4126e08d6bbSMika Westerberg .uid = "3", 4136e08d6bbSMika Westerberg .pins = east_pins, 4146e08d6bbSMika Westerberg .npins = ARRAY_SIZE(east_pins), 415293428f9SAndy Shevchenko .communities = east_communities, 416293428f9SAndy Shevchenko .ncommunities = ARRAY_SIZE(east_communities), 4176e08d6bbSMika Westerberg }; 4186e08d6bbSMika Westerberg 4196e08d6bbSMika Westerberg static const struct pinctrl_pin_desc southeast_pins[] = { 4206e08d6bbSMika Westerberg PINCTRL_PIN(0, "MF_PLT_CLK0"), 4216e08d6bbSMika Westerberg PINCTRL_PIN(1, "PWM1"), 4226e08d6bbSMika Westerberg PINCTRL_PIN(2, "MF_PLT_CLK1"), 4236e08d6bbSMika Westerberg PINCTRL_PIN(3, "MF_PLT_CLK4"), 4246e08d6bbSMika Westerberg PINCTRL_PIN(4, "MF_PLT_CLK3"), 4256e08d6bbSMika Westerberg PINCTRL_PIN(5, "PWM0"), 4266e08d6bbSMika Westerberg PINCTRL_PIN(6, "MF_PLT_CLK5"), 4276e08d6bbSMika Westerberg PINCTRL_PIN(7, "MF_PLT_CLK2"), 4286e08d6bbSMika Westerberg 4296e08d6bbSMika Westerberg PINCTRL_PIN(15, "SDMMC2_D3_CD_B"), 4306e08d6bbSMika Westerberg PINCTRL_PIN(16, "SDMMC1_CLK"), 4316e08d6bbSMika Westerberg PINCTRL_PIN(17, "SDMMC1_D0"), 4326e08d6bbSMika Westerberg PINCTRL_PIN(18, "SDMMC2_D1"), 4336e08d6bbSMika Westerberg PINCTRL_PIN(19, "SDMMC2_CLK"), 4346e08d6bbSMika Westerberg PINCTRL_PIN(20, "SDMMC1_D2"), 4356e08d6bbSMika Westerberg PINCTRL_PIN(21, "SDMMC2_D2"), 4366e08d6bbSMika Westerberg PINCTRL_PIN(22, "SDMMC2_CMD"), 4376e08d6bbSMika Westerberg PINCTRL_PIN(23, "SDMMC1_CMD"), 4386e08d6bbSMika Westerberg PINCTRL_PIN(24, "SDMMC1_D1"), 4396e08d6bbSMika Westerberg PINCTRL_PIN(25, "SDMMC2_D0"), 4406e08d6bbSMika Westerberg PINCTRL_PIN(26, "SDMMC1_D3_CD_B"), 4416e08d6bbSMika Westerberg 4426e08d6bbSMika Westerberg PINCTRL_PIN(30, "SDMMC3_D1"), 4436e08d6bbSMika Westerberg PINCTRL_PIN(31, "SDMMC3_CLK"), 4446e08d6bbSMika Westerberg PINCTRL_PIN(32, "SDMMC3_D3"), 4456e08d6bbSMika Westerberg PINCTRL_PIN(33, "SDMMC3_D2"), 4466e08d6bbSMika Westerberg PINCTRL_PIN(34, "SDMMC3_CMD"), 4476e08d6bbSMika Westerberg PINCTRL_PIN(35, "SDMMC3_D0"), 4486e08d6bbSMika Westerberg 4496e08d6bbSMika Westerberg PINCTRL_PIN(45, "MF_LPC_AD2"), 4506e08d6bbSMika Westerberg PINCTRL_PIN(46, "LPC_CLKRUNB"), 4516e08d6bbSMika Westerberg PINCTRL_PIN(47, "MF_LPC_AD0"), 4526e08d6bbSMika Westerberg PINCTRL_PIN(48, "LPC_FRAMEB"), 4536e08d6bbSMika Westerberg PINCTRL_PIN(49, "MF_LPC_CLKOUT1"), 4546e08d6bbSMika Westerberg PINCTRL_PIN(50, "MF_LPC_AD3"), 4556e08d6bbSMika Westerberg PINCTRL_PIN(51, "MF_LPC_CLKOUT0"), 4566e08d6bbSMika Westerberg PINCTRL_PIN(52, "MF_LPC_AD1"), 4576e08d6bbSMika Westerberg 4586e08d6bbSMika Westerberg PINCTRL_PIN(60, "SPI1_MISO"), 4596e08d6bbSMika Westerberg PINCTRL_PIN(61, "SPI1_CSO_B"), 4606e08d6bbSMika Westerberg PINCTRL_PIN(62, "SPI1_CLK"), 4616e08d6bbSMika Westerberg PINCTRL_PIN(63, "MMC1_D6"), 4626e08d6bbSMika Westerberg PINCTRL_PIN(64, "SPI1_MOSI"), 4636e08d6bbSMika Westerberg PINCTRL_PIN(65, "MMC1_D5"), 4646e08d6bbSMika Westerberg PINCTRL_PIN(66, "SPI1_CS1_B"), 4656e08d6bbSMika Westerberg PINCTRL_PIN(67, "MMC1_D4_SD_WE"), 4666e08d6bbSMika Westerberg PINCTRL_PIN(68, "MMC1_D7"), 4676e08d6bbSMika Westerberg PINCTRL_PIN(69, "MMC1_RCLK"), 4686e08d6bbSMika Westerberg 4696e08d6bbSMika Westerberg PINCTRL_PIN(75, "USB_OC1_B"), 4706e08d6bbSMika Westerberg PINCTRL_PIN(76, "PMU_RESETBUTTON_B"), 4716e08d6bbSMika Westerberg PINCTRL_PIN(77, "GPIO_ALERT"), 4726e08d6bbSMika Westerberg PINCTRL_PIN(78, "SDMMC3_PWR_EN_B"), 4736e08d6bbSMika Westerberg PINCTRL_PIN(79, "ILB_SERIRQ"), 4746e08d6bbSMika Westerberg PINCTRL_PIN(80, "USB_OC0_B"), 4756e08d6bbSMika Westerberg PINCTRL_PIN(81, "SDMMC3_CD_B"), 4766e08d6bbSMika Westerberg PINCTRL_PIN(82, "SPKR"), 4776e08d6bbSMika Westerberg PINCTRL_PIN(83, "SUSPWRDNACK"), 4786e08d6bbSMika Westerberg PINCTRL_PIN(84, "SPARE_PIN"), 4796e08d6bbSMika Westerberg PINCTRL_PIN(85, "SDMMC3_1P8_EN"), 4806e08d6bbSMika Westerberg }; 4816e08d6bbSMika Westerberg 4826e08d6bbSMika Westerberg static const unsigned southeast_pwm0_pins[] = { 5 }; 4836e08d6bbSMika Westerberg static const unsigned southeast_pwm1_pins[] = { 1 }; 4846e08d6bbSMika Westerberg static const unsigned southeast_sdmmc1_pins[] = { 4856e08d6bbSMika Westerberg 16, 17, 20, 23, 24, 26, 63, 65, 67, 68, 69, 4866e08d6bbSMika Westerberg }; 4876e08d6bbSMika Westerberg static const unsigned southeast_sdmmc2_pins[] = { 15, 18, 19, 21, 22, 25 }; 4886e08d6bbSMika Westerberg static const unsigned southeast_sdmmc3_pins[] = { 4896e08d6bbSMika Westerberg 30, 31, 32, 33, 34, 35, 78, 81, 85, 4906e08d6bbSMika Westerberg }; 4916e08d6bbSMika Westerberg static const unsigned southeast_spi1_pins[] = { 60, 61, 62, 64, 66 }; 4926e08d6bbSMika Westerberg static const unsigned southeast_spi2_pins[] = { 2, 3, 4, 6, 7 }; 4936e08d6bbSMika Westerberg 49436ad7b24SAndy Shevchenko static const struct intel_pingroup southeast_groups[] = { 49536ad7b24SAndy Shevchenko PIN_GROUP("pwm0_grp", southeast_pwm0_pins, PINMODE(1, 0)), 49636ad7b24SAndy Shevchenko PIN_GROUP("pwm1_grp", southeast_pwm1_pins, PINMODE(1, 0)), 49736ad7b24SAndy Shevchenko PIN_GROUP("sdmmc1_grp", southeast_sdmmc1_pins, PINMODE(1, 0)), 49836ad7b24SAndy Shevchenko PIN_GROUP("sdmmc2_grp", southeast_sdmmc2_pins, PINMODE(1, 0)), 49936ad7b24SAndy Shevchenko PIN_GROUP("sdmmc3_grp", southeast_sdmmc3_pins, PINMODE(1, 0)), 50036ad7b24SAndy Shevchenko PIN_GROUP("spi1_grp", southeast_spi1_pins, PINMODE(1, 0)), 50136ad7b24SAndy Shevchenko PIN_GROUP("spi2_grp", southeast_spi2_pins, PINMODE(4, 0)), 5026e08d6bbSMika Westerberg }; 5036e08d6bbSMika Westerberg 5046e08d6bbSMika Westerberg static const char * const southeast_pwm0_groups[] = { "pwm0_grp" }; 5056e08d6bbSMika Westerberg static const char * const southeast_pwm1_groups[] = { "pwm1_grp" }; 5066e08d6bbSMika Westerberg static const char * const southeast_sdmmc1_groups[] = { "sdmmc1_grp" }; 5076e08d6bbSMika Westerberg static const char * const southeast_sdmmc2_groups[] = { "sdmmc2_grp" }; 5086e08d6bbSMika Westerberg static const char * const southeast_sdmmc3_groups[] = { "sdmmc3_grp" }; 5096e08d6bbSMika Westerberg static const char * const southeast_spi1_groups[] = { "spi1_grp" }; 5106e08d6bbSMika Westerberg static const char * const southeast_spi2_groups[] = { "spi2_grp" }; 5116e08d6bbSMika Westerberg 5125458b7ceSAndy Shevchenko static const struct intel_function southeast_functions[] = { 5136e08d6bbSMika Westerberg FUNCTION("pwm0", southeast_pwm0_groups), 5146e08d6bbSMika Westerberg FUNCTION("pwm1", southeast_pwm1_groups), 5156e08d6bbSMika Westerberg FUNCTION("sdmmc1", southeast_sdmmc1_groups), 5166e08d6bbSMika Westerberg FUNCTION("sdmmc2", southeast_sdmmc2_groups), 5176e08d6bbSMika Westerberg FUNCTION("sdmmc3", southeast_sdmmc3_groups), 5186e08d6bbSMika Westerberg FUNCTION("spi1", southeast_spi1_groups), 5196e08d6bbSMika Westerberg FUNCTION("spi2", southeast_spi2_groups), 5206e08d6bbSMika Westerberg }; 5216e08d6bbSMika Westerberg 52236ad7b24SAndy Shevchenko static const struct intel_padgroup southeast_gpps[] = { 52336ad7b24SAndy Shevchenko CHV_GPP(0, 7), 52436ad7b24SAndy Shevchenko CHV_GPP(15, 26), 52536ad7b24SAndy Shevchenko CHV_GPP(30, 35), 52636ad7b24SAndy Shevchenko CHV_GPP(45, 52), 52736ad7b24SAndy Shevchenko CHV_GPP(60, 69), 52836ad7b24SAndy Shevchenko CHV_GPP(75, 85), 5296e08d6bbSMika Westerberg }; 5306e08d6bbSMika Westerberg 531293428f9SAndy Shevchenko static const struct intel_community southeast_communities[] = { 532293428f9SAndy Shevchenko CHV_COMMUNITY(southeast_gpps, 16, 0x94), 533293428f9SAndy Shevchenko }; 534293428f9SAndy Shevchenko 535293428f9SAndy Shevchenko static const struct intel_pinctrl_soc_data southeast_soc_data = { 5366e08d6bbSMika Westerberg .uid = "4", 5376e08d6bbSMika Westerberg .pins = southeast_pins, 5386e08d6bbSMika Westerberg .npins = ARRAY_SIZE(southeast_pins), 5396e08d6bbSMika Westerberg .groups = southeast_groups, 5406e08d6bbSMika Westerberg .ngroups = ARRAY_SIZE(southeast_groups), 5416e08d6bbSMika Westerberg .functions = southeast_functions, 5426e08d6bbSMika Westerberg .nfunctions = ARRAY_SIZE(southeast_functions), 543293428f9SAndy Shevchenko .communities = southeast_communities, 544293428f9SAndy Shevchenko .ncommunities = ARRAY_SIZE(southeast_communities), 5456e08d6bbSMika Westerberg }; 5466e08d6bbSMika Westerberg 547293428f9SAndy Shevchenko static const struct intel_pinctrl_soc_data *chv_soc_data[] = { 548293428f9SAndy Shevchenko &southwest_soc_data, 549293428f9SAndy Shevchenko &north_soc_data, 550293428f9SAndy Shevchenko &east_soc_data, 551293428f9SAndy Shevchenko &southeast_soc_data, 552293428f9SAndy Shevchenko NULL 5536e08d6bbSMika Westerberg }; 5546e08d6bbSMika Westerberg 5550bd50d71SDan O'Donovan /* 5560bd50d71SDan O'Donovan * Lock to serialize register accesses 5570bd50d71SDan O'Donovan * 5580bd50d71SDan O'Donovan * Due to a silicon issue, a shared lock must be used to prevent 5590bd50d71SDan O'Donovan * concurrent accesses across the 4 GPIO controllers. 5600bd50d71SDan O'Donovan * 5610bd50d71SDan O'Donovan * See Intel Atom Z8000 Processor Series Specification Update (Rev. 005), 5620bd50d71SDan O'Donovan * errata #CHT34, for further information. 5630bd50d71SDan O'Donovan */ 5640bd50d71SDan O'Donovan static DEFINE_RAW_SPINLOCK(chv_lock); 5650bd50d71SDan O'Donovan 5663ea2e2caSAndy Shevchenko static u32 chv_pctrl_readl(struct intel_pinctrl *pctrl, unsigned int offset) 56799fd6512SAndy Shevchenko { 568293428f9SAndy Shevchenko const struct intel_community *community = &pctrl->communities[0]; 569293428f9SAndy Shevchenko 570293428f9SAndy Shevchenko return readl(community->regs + offset); 57199fd6512SAndy Shevchenko } 57299fd6512SAndy Shevchenko 5733ea2e2caSAndy Shevchenko static void chv_pctrl_writel(struct intel_pinctrl *pctrl, unsigned int offset, u32 value) 57499fd6512SAndy Shevchenko { 575293428f9SAndy Shevchenko const struct intel_community *community = &pctrl->communities[0]; 576293428f9SAndy Shevchenko void __iomem *reg = community->regs + offset; 57799fd6512SAndy Shevchenko 57899fd6512SAndy Shevchenko /* Write and simple read back to confirm the bus transferring done */ 57999fd6512SAndy Shevchenko writel(value, reg); 58099fd6512SAndy Shevchenko readl(reg); 58199fd6512SAndy Shevchenko } 58299fd6512SAndy Shevchenko 5833ea2e2caSAndy Shevchenko static void __iomem *chv_padreg(struct intel_pinctrl *pctrl, unsigned int offset, 5844e737af8SAndy Shevchenko unsigned int reg) 5856e08d6bbSMika Westerberg { 586293428f9SAndy Shevchenko const struct intel_community *community = &pctrl->communities[0]; 5874e737af8SAndy Shevchenko unsigned int family_no = offset / MAX_FAMILY_PAD_GPIO_NO; 5884e737af8SAndy Shevchenko unsigned int pad_no = offset % MAX_FAMILY_PAD_GPIO_NO; 5896e08d6bbSMika Westerberg 590293428f9SAndy Shevchenko offset = FAMILY_PAD_REGS_SIZE * family_no + GPIO_REGS_SIZE * pad_no; 5916e08d6bbSMika Westerberg 592293428f9SAndy Shevchenko return community->pad_regs + offset + reg; 5936e08d6bbSMika Westerberg } 5946e08d6bbSMika Westerberg 5953ea2e2caSAndy Shevchenko static u32 chv_readl(struct intel_pinctrl *pctrl, unsigned int pin, unsigned int offset) 5964e7293e3SAndy Shevchenko { 5974e7293e3SAndy Shevchenko return readl(chv_padreg(pctrl, pin, offset)); 5984e7293e3SAndy Shevchenko } 5994e7293e3SAndy Shevchenko 6003ea2e2caSAndy Shevchenko static void chv_writel(struct intel_pinctrl *pctrl, unsigned int pin, unsigned int offset, u32 value) 6016e08d6bbSMika Westerberg { 602bfc8a4baSAndy Shevchenko void __iomem *reg = chv_padreg(pctrl, pin, offset); 603bfc8a4baSAndy Shevchenko 604bfc8a4baSAndy Shevchenko /* Write and simple read back to confirm the bus transferring done */ 6056e08d6bbSMika Westerberg writel(value, reg); 6066e08d6bbSMika Westerberg readl(reg); 6076e08d6bbSMika Westerberg } 6086e08d6bbSMika Westerberg 6096e08d6bbSMika Westerberg /* When Pad Cfg is locked, driver can only change GPIOTXState or GPIORXState */ 6103ea2e2caSAndy Shevchenko static bool chv_pad_locked(struct intel_pinctrl *pctrl, unsigned int offset) 6116e08d6bbSMika Westerberg { 6124e7293e3SAndy Shevchenko return chv_readl(pctrl, offset, CHV_PADCTRL1) & CHV_PADCTRL1_CFGLOCK; 6136e08d6bbSMika Westerberg } 6146e08d6bbSMika Westerberg 6156e08d6bbSMika Westerberg static int chv_get_groups_count(struct pinctrl_dev *pctldev) 6166e08d6bbSMika Westerberg { 6173ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 6186e08d6bbSMika Westerberg 619293428f9SAndy Shevchenko return pctrl->soc->ngroups; 6206e08d6bbSMika Westerberg } 6216e08d6bbSMika Westerberg 6226e08d6bbSMika Westerberg static const char *chv_get_group_name(struct pinctrl_dev *pctldev, 6234e737af8SAndy Shevchenko unsigned int group) 6246e08d6bbSMika Westerberg { 6253ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 6266e08d6bbSMika Westerberg 627293428f9SAndy Shevchenko return pctrl->soc->groups[group].name; 6286e08d6bbSMika Westerberg } 6296e08d6bbSMika Westerberg 6304e737af8SAndy Shevchenko static int chv_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group, 6314e737af8SAndy Shevchenko const unsigned int **pins, unsigned int *npins) 6326e08d6bbSMika Westerberg { 6333ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 6346e08d6bbSMika Westerberg 635293428f9SAndy Shevchenko *pins = pctrl->soc->groups[group].pins; 636293428f9SAndy Shevchenko *npins = pctrl->soc->groups[group].npins; 6376e08d6bbSMika Westerberg return 0; 6386e08d6bbSMika Westerberg } 6396e08d6bbSMika Westerberg 6406e08d6bbSMika Westerberg static void chv_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, 6414e737af8SAndy Shevchenko unsigned int offset) 6426e08d6bbSMika Westerberg { 6433ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 6446e08d6bbSMika Westerberg unsigned long flags; 6456e08d6bbSMika Westerberg u32 ctrl0, ctrl1; 6466e08d6bbSMika Westerberg bool locked; 6476e08d6bbSMika Westerberg 6480bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 6496e08d6bbSMika Westerberg 6504e7293e3SAndy Shevchenko ctrl0 = chv_readl(pctrl, offset, CHV_PADCTRL0); 6514e7293e3SAndy Shevchenko ctrl1 = chv_readl(pctrl, offset, CHV_PADCTRL1); 6526e08d6bbSMika Westerberg locked = chv_pad_locked(pctrl, offset); 6536e08d6bbSMika Westerberg 6540bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 6556e08d6bbSMika Westerberg 6566e08d6bbSMika Westerberg if (ctrl0 & CHV_PADCTRL0_GPIOEN) { 6576e08d6bbSMika Westerberg seq_puts(s, "GPIO "); 6586e08d6bbSMika Westerberg } else { 6596e08d6bbSMika Westerberg u32 mode; 6606e08d6bbSMika Westerberg 6616e08d6bbSMika Westerberg mode = ctrl0 & CHV_PADCTRL0_PMODE_MASK; 6626e08d6bbSMika Westerberg mode >>= CHV_PADCTRL0_PMODE_SHIFT; 6636e08d6bbSMika Westerberg 6646e08d6bbSMika Westerberg seq_printf(s, "mode %d ", mode); 6656e08d6bbSMika Westerberg } 6666e08d6bbSMika Westerberg 667684373eaSMika Westerberg seq_printf(s, "0x%08x 0x%08x", ctrl0, ctrl1); 6686e08d6bbSMika Westerberg 6696e08d6bbSMika Westerberg if (locked) 6706e08d6bbSMika Westerberg seq_puts(s, " [LOCKED]"); 6716e08d6bbSMika Westerberg } 6726e08d6bbSMika Westerberg 6736e08d6bbSMika Westerberg static const struct pinctrl_ops chv_pinctrl_ops = { 6746e08d6bbSMika Westerberg .get_groups_count = chv_get_groups_count, 6756e08d6bbSMika Westerberg .get_group_name = chv_get_group_name, 6766e08d6bbSMika Westerberg .get_group_pins = chv_get_group_pins, 6776e08d6bbSMika Westerberg .pin_dbg_show = chv_pin_dbg_show, 6786e08d6bbSMika Westerberg }; 6796e08d6bbSMika Westerberg 6806e08d6bbSMika Westerberg static int chv_get_functions_count(struct pinctrl_dev *pctldev) 6816e08d6bbSMika Westerberg { 6823ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 6836e08d6bbSMika Westerberg 684293428f9SAndy Shevchenko return pctrl->soc->nfunctions; 6856e08d6bbSMika Westerberg } 6866e08d6bbSMika Westerberg 6876e08d6bbSMika Westerberg static const char *chv_get_function_name(struct pinctrl_dev *pctldev, 6884e737af8SAndy Shevchenko unsigned int function) 6896e08d6bbSMika Westerberg { 6903ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 6916e08d6bbSMika Westerberg 692293428f9SAndy Shevchenko return pctrl->soc->functions[function].name; 6936e08d6bbSMika Westerberg } 6946e08d6bbSMika Westerberg 6956e08d6bbSMika Westerberg static int chv_get_function_groups(struct pinctrl_dev *pctldev, 6964e737af8SAndy Shevchenko unsigned int function, 6976e08d6bbSMika Westerberg const char * const **groups, 6984e737af8SAndy Shevchenko unsigned int * const ngroups) 6996e08d6bbSMika Westerberg { 7003ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 7016e08d6bbSMika Westerberg 702293428f9SAndy Shevchenko *groups = pctrl->soc->functions[function].groups; 703293428f9SAndy Shevchenko *ngroups = pctrl->soc->functions[function].ngroups; 7046e08d6bbSMika Westerberg return 0; 7056e08d6bbSMika Westerberg } 7066e08d6bbSMika Westerberg 7074e737af8SAndy Shevchenko static int chv_pinmux_set_mux(struct pinctrl_dev *pctldev, 7084e737af8SAndy Shevchenko unsigned int function, unsigned int group) 7096e08d6bbSMika Westerberg { 7103ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 71136ad7b24SAndy Shevchenko const struct intel_pingroup *grp; 7126e08d6bbSMika Westerberg unsigned long flags; 7136e08d6bbSMika Westerberg int i; 7146e08d6bbSMika Westerberg 715293428f9SAndy Shevchenko grp = &pctrl->soc->groups[group]; 7166e08d6bbSMika Westerberg 7170bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 7186e08d6bbSMika Westerberg 7196e08d6bbSMika Westerberg /* Check first that the pad is not locked */ 7206e08d6bbSMika Westerberg for (i = 0; i < grp->npins; i++) { 7216e08d6bbSMika Westerberg if (chv_pad_locked(pctrl, grp->pins[i])) { 7226e08d6bbSMika Westerberg dev_warn(pctrl->dev, "unable to set mode for locked pin %u\n", 7236e08d6bbSMika Westerberg grp->pins[i]); 7240bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 7256e08d6bbSMika Westerberg return -EBUSY; 7266e08d6bbSMika Westerberg } 7276e08d6bbSMika Westerberg } 7286e08d6bbSMika Westerberg 7296e08d6bbSMika Westerberg for (i = 0; i < grp->npins; i++) { 7306e08d6bbSMika Westerberg int pin = grp->pins[i]; 73136ad7b24SAndy Shevchenko unsigned int mode; 73236ad7b24SAndy Shevchenko bool invert_oe; 7336e08d6bbSMika Westerberg u32 value; 7346e08d6bbSMika Westerberg 7356e08d6bbSMika Westerberg /* Check if there is pin-specific config */ 73636ad7b24SAndy Shevchenko if (grp->modes) 73736ad7b24SAndy Shevchenko mode = grp->modes[i]; 73836ad7b24SAndy Shevchenko else 73936ad7b24SAndy Shevchenko mode = grp->mode; 7406e08d6bbSMika Westerberg 74136ad7b24SAndy Shevchenko /* Extract OE inversion */ 74236ad7b24SAndy Shevchenko invert_oe = mode & PINMODE_INVERT_OE; 74336ad7b24SAndy Shevchenko mode &= ~PINMODE_INVERT_OE; 7446e08d6bbSMika Westerberg 7454e7293e3SAndy Shevchenko value = chv_readl(pctrl, pin, CHV_PADCTRL0); 7466e08d6bbSMika Westerberg /* Disable GPIO mode */ 7476e08d6bbSMika Westerberg value &= ~CHV_PADCTRL0_GPIOEN; 7486e08d6bbSMika Westerberg /* Set to desired mode */ 7496e08d6bbSMika Westerberg value &= ~CHV_PADCTRL0_PMODE_MASK; 75036ad7b24SAndy Shevchenko value |= mode << CHV_PADCTRL0_PMODE_SHIFT; 751bfc8a4baSAndy Shevchenko chv_writel(pctrl, pin, CHV_PADCTRL0, value); 7526e08d6bbSMika Westerberg 7536e08d6bbSMika Westerberg /* Update for invert_oe */ 7544e7293e3SAndy Shevchenko value = chv_readl(pctrl, pin, CHV_PADCTRL1) & ~CHV_PADCTRL1_INVRXTX_MASK; 75536ad7b24SAndy Shevchenko if (invert_oe) 7566e08d6bbSMika Westerberg value |= CHV_PADCTRL1_INVRXTX_TXENABLE; 757bfc8a4baSAndy Shevchenko chv_writel(pctrl, pin, CHV_PADCTRL1, value); 7586e08d6bbSMika Westerberg 7596e08d6bbSMika Westerberg dev_dbg(pctrl->dev, "configured pin %u mode %u OE %sinverted\n", 76036ad7b24SAndy Shevchenko pin, mode, invert_oe ? "" : "not "); 7616e08d6bbSMika Westerberg } 7626e08d6bbSMika Westerberg 7630bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 7646e08d6bbSMika Westerberg 7656e08d6bbSMika Westerberg return 0; 7666e08d6bbSMika Westerberg } 7676e08d6bbSMika Westerberg 7683ea2e2caSAndy Shevchenko static void chv_gpio_clear_triggering(struct intel_pinctrl *pctrl, 769b6fb6e11SHans de Goede unsigned int offset) 770b6fb6e11SHans de Goede { 771b6fb6e11SHans de Goede u32 value; 772b6fb6e11SHans de Goede 7734e7293e3SAndy Shevchenko value = chv_readl(pctrl, offset, CHV_PADCTRL1); 774b6fb6e11SHans de Goede value &= ~CHV_PADCTRL1_INTWAKECFG_MASK; 775b6fb6e11SHans de Goede value &= ~CHV_PADCTRL1_INVRXTX_MASK; 776bfc8a4baSAndy Shevchenko chv_writel(pctrl, offset, CHV_PADCTRL1, value); 777b6fb6e11SHans de Goede } 778b6fb6e11SHans de Goede 7796e08d6bbSMika Westerberg static int chv_gpio_request_enable(struct pinctrl_dev *pctldev, 7806e08d6bbSMika Westerberg struct pinctrl_gpio_range *range, 7814e737af8SAndy Shevchenko unsigned int offset) 7826e08d6bbSMika Westerberg { 7833ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 7846e08d6bbSMika Westerberg unsigned long flags; 7856e08d6bbSMika Westerberg u32 value; 7866e08d6bbSMika Westerberg 7870bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 7886e08d6bbSMika Westerberg 7896e08d6bbSMika Westerberg if (chv_pad_locked(pctrl, offset)) { 7904e7293e3SAndy Shevchenko value = chv_readl(pctrl, offset, CHV_PADCTRL0); 7916e08d6bbSMika Westerberg if (!(value & CHV_PADCTRL0_GPIOEN)) { 7926e08d6bbSMika Westerberg /* Locked so cannot enable */ 7930bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 7946e08d6bbSMika Westerberg return -EBUSY; 7956e08d6bbSMika Westerberg } 7966e08d6bbSMika Westerberg } else { 7978a828570SAndy Shevchenko struct intel_community_context *cctx = &pctrl->context.communities[0]; 7986e08d6bbSMika Westerberg int i; 7996e08d6bbSMika Westerberg 8006e08d6bbSMika Westerberg /* Reset the interrupt mapping */ 8018a828570SAndy Shevchenko for (i = 0; i < ARRAY_SIZE(cctx->intr_lines); i++) { 8028a828570SAndy Shevchenko if (cctx->intr_lines[i] == offset) { 8038a828570SAndy Shevchenko cctx->intr_lines[i] = 0; 8046e08d6bbSMika Westerberg break; 8056e08d6bbSMika Westerberg } 8066e08d6bbSMika Westerberg } 8076e08d6bbSMika Westerberg 8086e08d6bbSMika Westerberg /* Disable interrupt generation */ 809b6fb6e11SHans de Goede chv_gpio_clear_triggering(pctrl, offset); 8106e08d6bbSMika Westerberg 8114e7293e3SAndy Shevchenko value = chv_readl(pctrl, offset, CHV_PADCTRL0); 8122479c730SMika Westerberg 8132479c730SMika Westerberg /* 8142479c730SMika Westerberg * If the pin is in HiZ mode (both TX and RX buffers are 8152479c730SMika Westerberg * disabled) we turn it to be input now. 8162479c730SMika Westerberg */ 8172479c730SMika Westerberg if ((value & CHV_PADCTRL0_GPIOCFG_MASK) == 8182479c730SMika Westerberg (CHV_PADCTRL0_GPIOCFG_HIZ << CHV_PADCTRL0_GPIOCFG_SHIFT)) { 8192479c730SMika Westerberg value &= ~CHV_PADCTRL0_GPIOCFG_MASK; 820bfc8a4baSAndy Shevchenko value |= CHV_PADCTRL0_GPIOCFG_GPI << CHV_PADCTRL0_GPIOCFG_SHIFT; 8212479c730SMika Westerberg } 8222479c730SMika Westerberg 8232479c730SMika Westerberg /* Switch to a GPIO mode */ 8242479c730SMika Westerberg value |= CHV_PADCTRL0_GPIOEN; 825bfc8a4baSAndy Shevchenko chv_writel(pctrl, offset, CHV_PADCTRL0, value); 8266e08d6bbSMika Westerberg } 8276e08d6bbSMika Westerberg 8280bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 8296e08d6bbSMika Westerberg 8306e08d6bbSMika Westerberg return 0; 8316e08d6bbSMika Westerberg } 8326e08d6bbSMika Westerberg 8336e08d6bbSMika Westerberg static void chv_gpio_disable_free(struct pinctrl_dev *pctldev, 8346e08d6bbSMika Westerberg struct pinctrl_gpio_range *range, 8354e737af8SAndy Shevchenko unsigned int offset) 8366e08d6bbSMika Westerberg { 8373ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 8386e08d6bbSMika Westerberg unsigned long flags; 8396e08d6bbSMika Westerberg 8400bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 8416e08d6bbSMika Westerberg 8421adde32aSHans de Goede if (!chv_pad_locked(pctrl, offset)) 8431adde32aSHans de Goede chv_gpio_clear_triggering(pctrl, offset); 8446e08d6bbSMika Westerberg 8450bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 8466e08d6bbSMika Westerberg } 8476e08d6bbSMika Westerberg 8486e08d6bbSMika Westerberg static int chv_gpio_set_direction(struct pinctrl_dev *pctldev, 8496e08d6bbSMika Westerberg struct pinctrl_gpio_range *range, 8504e737af8SAndy Shevchenko unsigned int offset, bool input) 8516e08d6bbSMika Westerberg { 8523ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 8536e08d6bbSMika Westerberg unsigned long flags; 8546e08d6bbSMika Westerberg u32 ctrl0; 8556e08d6bbSMika Westerberg 8560bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 8576e08d6bbSMika Westerberg 8584e7293e3SAndy Shevchenko ctrl0 = chv_readl(pctrl, offset, CHV_PADCTRL0) & ~CHV_PADCTRL0_GPIOCFG_MASK; 8596e08d6bbSMika Westerberg if (input) 8606e08d6bbSMika Westerberg ctrl0 |= CHV_PADCTRL0_GPIOCFG_GPI << CHV_PADCTRL0_GPIOCFG_SHIFT; 8616e08d6bbSMika Westerberg else 8626e08d6bbSMika Westerberg ctrl0 |= CHV_PADCTRL0_GPIOCFG_GPO << CHV_PADCTRL0_GPIOCFG_SHIFT; 863bfc8a4baSAndy Shevchenko chv_writel(pctrl, offset, CHV_PADCTRL0, ctrl0); 8646e08d6bbSMika Westerberg 8650bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 8666e08d6bbSMika Westerberg 8676e08d6bbSMika Westerberg return 0; 8686e08d6bbSMika Westerberg } 8696e08d6bbSMika Westerberg 8706e08d6bbSMika Westerberg static const struct pinmux_ops chv_pinmux_ops = { 8716e08d6bbSMika Westerberg .get_functions_count = chv_get_functions_count, 8726e08d6bbSMika Westerberg .get_function_name = chv_get_function_name, 8736e08d6bbSMika Westerberg .get_function_groups = chv_get_function_groups, 8746e08d6bbSMika Westerberg .set_mux = chv_pinmux_set_mux, 8756e08d6bbSMika Westerberg .gpio_request_enable = chv_gpio_request_enable, 8766e08d6bbSMika Westerberg .gpio_disable_free = chv_gpio_disable_free, 8776e08d6bbSMika Westerberg .gpio_set_direction = chv_gpio_set_direction, 8786e08d6bbSMika Westerberg }; 8796e08d6bbSMika Westerberg 8804e737af8SAndy Shevchenko static int chv_config_get(struct pinctrl_dev *pctldev, unsigned int pin, 8816e08d6bbSMika Westerberg unsigned long *config) 8826e08d6bbSMika Westerberg { 8833ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 8846e08d6bbSMika Westerberg enum pin_config_param param = pinconf_to_config_param(*config); 8856e08d6bbSMika Westerberg unsigned long flags; 8866e08d6bbSMika Westerberg u32 ctrl0, ctrl1; 8876e08d6bbSMika Westerberg u16 arg = 0; 8886e08d6bbSMika Westerberg u32 term; 8896e08d6bbSMika Westerberg 8900bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 8914e7293e3SAndy Shevchenko ctrl0 = chv_readl(pctrl, pin, CHV_PADCTRL0); 8924e7293e3SAndy Shevchenko ctrl1 = chv_readl(pctrl, pin, CHV_PADCTRL1); 8930bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 8946e08d6bbSMika Westerberg 8956e08d6bbSMika Westerberg term = (ctrl0 & CHV_PADCTRL0_TERM_MASK) >> CHV_PADCTRL0_TERM_SHIFT; 8966e08d6bbSMika Westerberg 8976e08d6bbSMika Westerberg switch (param) { 8986e08d6bbSMika Westerberg case PIN_CONFIG_BIAS_DISABLE: 8996e08d6bbSMika Westerberg if (term) 9006e08d6bbSMika Westerberg return -EINVAL; 9016e08d6bbSMika Westerberg break; 9026e08d6bbSMika Westerberg 9036e08d6bbSMika Westerberg case PIN_CONFIG_BIAS_PULL_UP: 9046e08d6bbSMika Westerberg if (!(ctrl0 & CHV_PADCTRL0_TERM_UP)) 9056e08d6bbSMika Westerberg return -EINVAL; 9066e08d6bbSMika Westerberg 9076e08d6bbSMika Westerberg switch (term) { 9086e08d6bbSMika Westerberg case CHV_PADCTRL0_TERM_20K: 9096e08d6bbSMika Westerberg arg = 20000; 9106e08d6bbSMika Westerberg break; 9116e08d6bbSMika Westerberg case CHV_PADCTRL0_TERM_5K: 9126e08d6bbSMika Westerberg arg = 5000; 9136e08d6bbSMika Westerberg break; 9146e08d6bbSMika Westerberg case CHV_PADCTRL0_TERM_1K: 9156e08d6bbSMika Westerberg arg = 1000; 9166e08d6bbSMika Westerberg break; 9176e08d6bbSMika Westerberg } 9186e08d6bbSMika Westerberg 9196e08d6bbSMika Westerberg break; 9206e08d6bbSMika Westerberg 9216e08d6bbSMika Westerberg case PIN_CONFIG_BIAS_PULL_DOWN: 9226e08d6bbSMika Westerberg if (!term || (ctrl0 & CHV_PADCTRL0_TERM_UP)) 9236e08d6bbSMika Westerberg return -EINVAL; 9246e08d6bbSMika Westerberg 9256e08d6bbSMika Westerberg switch (term) { 9266e08d6bbSMika Westerberg case CHV_PADCTRL0_TERM_20K: 9276e08d6bbSMika Westerberg arg = 20000; 9286e08d6bbSMika Westerberg break; 9296e08d6bbSMika Westerberg case CHV_PADCTRL0_TERM_5K: 9306e08d6bbSMika Westerberg arg = 5000; 9316e08d6bbSMika Westerberg break; 9326e08d6bbSMika Westerberg } 9336e08d6bbSMika Westerberg 9346e08d6bbSMika Westerberg break; 9356e08d6bbSMika Westerberg 9366e08d6bbSMika Westerberg case PIN_CONFIG_DRIVE_OPEN_DRAIN: 9376e08d6bbSMika Westerberg if (!(ctrl1 & CHV_PADCTRL1_ODEN)) 9386e08d6bbSMika Westerberg return -EINVAL; 9396e08d6bbSMika Westerberg break; 9406e08d6bbSMika Westerberg 9416e08d6bbSMika Westerberg case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: { 9426e08d6bbSMika Westerberg u32 cfg; 9436e08d6bbSMika Westerberg 9446e08d6bbSMika Westerberg cfg = ctrl0 & CHV_PADCTRL0_GPIOCFG_MASK; 9456e08d6bbSMika Westerberg cfg >>= CHV_PADCTRL0_GPIOCFG_SHIFT; 9466e08d6bbSMika Westerberg if (cfg != CHV_PADCTRL0_GPIOCFG_HIZ) 9476e08d6bbSMika Westerberg return -EINVAL; 9486e08d6bbSMika Westerberg 9496e08d6bbSMika Westerberg break; 9506e08d6bbSMika Westerberg } 9516e08d6bbSMika Westerberg 9526e08d6bbSMika Westerberg default: 9536e08d6bbSMika Westerberg return -ENOTSUPP; 9546e08d6bbSMika Westerberg } 9556e08d6bbSMika Westerberg 9566e08d6bbSMika Westerberg *config = pinconf_to_config_packed(param, arg); 9576e08d6bbSMika Westerberg return 0; 9586e08d6bbSMika Westerberg } 9596e08d6bbSMika Westerberg 9603ea2e2caSAndy Shevchenko static int chv_config_set_pull(struct intel_pinctrl *pctrl, unsigned int pin, 96158957d2eSMika Westerberg enum pin_config_param param, u32 arg) 9626e08d6bbSMika Westerberg { 9636e08d6bbSMika Westerberg unsigned long flags; 9646e08d6bbSMika Westerberg u32 ctrl0, pull; 9656e08d6bbSMika Westerberg 9660bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 9674e7293e3SAndy Shevchenko ctrl0 = chv_readl(pctrl, pin, CHV_PADCTRL0); 9686e08d6bbSMika Westerberg 9696e08d6bbSMika Westerberg switch (param) { 9706e08d6bbSMika Westerberg case PIN_CONFIG_BIAS_DISABLE: 9716e08d6bbSMika Westerberg ctrl0 &= ~(CHV_PADCTRL0_TERM_MASK | CHV_PADCTRL0_TERM_UP); 9726e08d6bbSMika Westerberg break; 9736e08d6bbSMika Westerberg 9746e08d6bbSMika Westerberg case PIN_CONFIG_BIAS_PULL_UP: 9756e08d6bbSMika Westerberg ctrl0 &= ~(CHV_PADCTRL0_TERM_MASK | CHV_PADCTRL0_TERM_UP); 9766e08d6bbSMika Westerberg 9776e08d6bbSMika Westerberg switch (arg) { 9786e08d6bbSMika Westerberg case 1000: 9796e08d6bbSMika Westerberg /* For 1k there is only pull up */ 9806e08d6bbSMika Westerberg pull = CHV_PADCTRL0_TERM_1K << CHV_PADCTRL0_TERM_SHIFT; 9816e08d6bbSMika Westerberg break; 9826e08d6bbSMika Westerberg case 5000: 9836e08d6bbSMika Westerberg pull = CHV_PADCTRL0_TERM_5K << CHV_PADCTRL0_TERM_SHIFT; 9846e08d6bbSMika Westerberg break; 9856e08d6bbSMika Westerberg case 20000: 9866e08d6bbSMika Westerberg pull = CHV_PADCTRL0_TERM_20K << CHV_PADCTRL0_TERM_SHIFT; 9876e08d6bbSMika Westerberg break; 9886e08d6bbSMika Westerberg default: 9890bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 9906e08d6bbSMika Westerberg return -EINVAL; 9916e08d6bbSMika Westerberg } 9926e08d6bbSMika Westerberg 9936e08d6bbSMika Westerberg ctrl0 |= CHV_PADCTRL0_TERM_UP | pull; 9946e08d6bbSMika Westerberg break; 9956e08d6bbSMika Westerberg 9966e08d6bbSMika Westerberg case PIN_CONFIG_BIAS_PULL_DOWN: 9976e08d6bbSMika Westerberg ctrl0 &= ~(CHV_PADCTRL0_TERM_MASK | CHV_PADCTRL0_TERM_UP); 9986e08d6bbSMika Westerberg 9996e08d6bbSMika Westerberg switch (arg) { 10006e08d6bbSMika Westerberg case 5000: 10016e08d6bbSMika Westerberg pull = CHV_PADCTRL0_TERM_5K << CHV_PADCTRL0_TERM_SHIFT; 10026e08d6bbSMika Westerberg break; 10036e08d6bbSMika Westerberg case 20000: 10046e08d6bbSMika Westerberg pull = CHV_PADCTRL0_TERM_20K << CHV_PADCTRL0_TERM_SHIFT; 10056e08d6bbSMika Westerberg break; 10066e08d6bbSMika Westerberg default: 10070bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 10086e08d6bbSMika Westerberg return -EINVAL; 10096e08d6bbSMika Westerberg } 10106e08d6bbSMika Westerberg 10116e08d6bbSMika Westerberg ctrl0 |= pull; 10126e08d6bbSMika Westerberg break; 10136e08d6bbSMika Westerberg 10146e08d6bbSMika Westerberg default: 10150bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 10166e08d6bbSMika Westerberg return -EINVAL; 10176e08d6bbSMika Westerberg } 10186e08d6bbSMika Westerberg 1019bfc8a4baSAndy Shevchenko chv_writel(pctrl, pin, CHV_PADCTRL0, ctrl0); 10200bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 10216e08d6bbSMika Westerberg 10226e08d6bbSMika Westerberg return 0; 10236e08d6bbSMika Westerberg } 10246e08d6bbSMika Westerberg 10253ea2e2caSAndy Shevchenko static int chv_config_set_oden(struct intel_pinctrl *pctrl, unsigned int pin, 1026ccdf81d0SDan O'Donovan bool enable) 1027ccdf81d0SDan O'Donovan { 1028ccdf81d0SDan O'Donovan unsigned long flags; 1029ccdf81d0SDan O'Donovan u32 ctrl1; 1030ccdf81d0SDan O'Donovan 1031ccdf81d0SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 10324e7293e3SAndy Shevchenko ctrl1 = chv_readl(pctrl, pin, CHV_PADCTRL1); 1033ccdf81d0SDan O'Donovan 1034ccdf81d0SDan O'Donovan if (enable) 1035ccdf81d0SDan O'Donovan ctrl1 |= CHV_PADCTRL1_ODEN; 1036ccdf81d0SDan O'Donovan else 1037ccdf81d0SDan O'Donovan ctrl1 &= ~CHV_PADCTRL1_ODEN; 1038ccdf81d0SDan O'Donovan 1039bfc8a4baSAndy Shevchenko chv_writel(pctrl, pin, CHV_PADCTRL1, ctrl1); 1040ccdf81d0SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 1041ccdf81d0SDan O'Donovan 1042ccdf81d0SDan O'Donovan return 0; 1043ccdf81d0SDan O'Donovan } 1044ccdf81d0SDan O'Donovan 10454e737af8SAndy Shevchenko static int chv_config_set(struct pinctrl_dev *pctldev, unsigned int pin, 10464e737af8SAndy Shevchenko unsigned long *configs, unsigned int nconfigs) 10476e08d6bbSMika Westerberg { 10483ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 10496e08d6bbSMika Westerberg enum pin_config_param param; 10506e08d6bbSMika Westerberg int i, ret; 105158957d2eSMika Westerberg u32 arg; 10526e08d6bbSMika Westerberg 10536e08d6bbSMika Westerberg if (chv_pad_locked(pctrl, pin)) 10546e08d6bbSMika Westerberg return -EBUSY; 10556e08d6bbSMika Westerberg 10566e08d6bbSMika Westerberg for (i = 0; i < nconfigs; i++) { 10576e08d6bbSMika Westerberg param = pinconf_to_config_param(configs[i]); 10586e08d6bbSMika Westerberg arg = pinconf_to_config_argument(configs[i]); 10596e08d6bbSMika Westerberg 10606e08d6bbSMika Westerberg switch (param) { 10616e08d6bbSMika Westerberg case PIN_CONFIG_BIAS_DISABLE: 10626e08d6bbSMika Westerberg case PIN_CONFIG_BIAS_PULL_UP: 10636e08d6bbSMika Westerberg case PIN_CONFIG_BIAS_PULL_DOWN: 10646e08d6bbSMika Westerberg ret = chv_config_set_pull(pctrl, pin, param, arg); 10656e08d6bbSMika Westerberg if (ret) 10666e08d6bbSMika Westerberg return ret; 10676e08d6bbSMika Westerberg break; 10686e08d6bbSMika Westerberg 1069ccdf81d0SDan O'Donovan case PIN_CONFIG_DRIVE_PUSH_PULL: 1070ccdf81d0SDan O'Donovan ret = chv_config_set_oden(pctrl, pin, false); 1071ccdf81d0SDan O'Donovan if (ret) 1072ccdf81d0SDan O'Donovan return ret; 1073ccdf81d0SDan O'Donovan break; 1074ccdf81d0SDan O'Donovan 1075ccdf81d0SDan O'Donovan case PIN_CONFIG_DRIVE_OPEN_DRAIN: 1076ccdf81d0SDan O'Donovan ret = chv_config_set_oden(pctrl, pin, true); 1077ccdf81d0SDan O'Donovan if (ret) 1078ccdf81d0SDan O'Donovan return ret; 1079ccdf81d0SDan O'Donovan break; 1080ccdf81d0SDan O'Donovan 10816e08d6bbSMika Westerberg default: 10826e08d6bbSMika Westerberg return -ENOTSUPP; 10836e08d6bbSMika Westerberg } 10846e08d6bbSMika Westerberg 10856e08d6bbSMika Westerberg dev_dbg(pctrl->dev, "pin %d set config %d arg %u\n", pin, 10866e08d6bbSMika Westerberg param, arg); 10876e08d6bbSMika Westerberg } 10886e08d6bbSMika Westerberg 10896e08d6bbSMika Westerberg return 0; 10906e08d6bbSMika Westerberg } 10916e08d6bbSMika Westerberg 109277401d7fSDan O'Donovan static int chv_config_group_get(struct pinctrl_dev *pctldev, 109377401d7fSDan O'Donovan unsigned int group, 109477401d7fSDan O'Donovan unsigned long *config) 109577401d7fSDan O'Donovan { 109677401d7fSDan O'Donovan const unsigned int *pins; 109777401d7fSDan O'Donovan unsigned int npins; 109877401d7fSDan O'Donovan int ret; 109977401d7fSDan O'Donovan 110077401d7fSDan O'Donovan ret = chv_get_group_pins(pctldev, group, &pins, &npins); 110177401d7fSDan O'Donovan if (ret) 110277401d7fSDan O'Donovan return ret; 110377401d7fSDan O'Donovan 110477401d7fSDan O'Donovan ret = chv_config_get(pctldev, pins[0], config); 110577401d7fSDan O'Donovan if (ret) 110677401d7fSDan O'Donovan return ret; 110777401d7fSDan O'Donovan 110877401d7fSDan O'Donovan return 0; 110977401d7fSDan O'Donovan } 111077401d7fSDan O'Donovan 111177401d7fSDan O'Donovan static int chv_config_group_set(struct pinctrl_dev *pctldev, 111277401d7fSDan O'Donovan unsigned int group, unsigned long *configs, 111377401d7fSDan O'Donovan unsigned int num_configs) 111477401d7fSDan O'Donovan { 111577401d7fSDan O'Donovan const unsigned int *pins; 111677401d7fSDan O'Donovan unsigned int npins; 111777401d7fSDan O'Donovan int i, ret; 111877401d7fSDan O'Donovan 111977401d7fSDan O'Donovan ret = chv_get_group_pins(pctldev, group, &pins, &npins); 112077401d7fSDan O'Donovan if (ret) 112177401d7fSDan O'Donovan return ret; 112277401d7fSDan O'Donovan 112377401d7fSDan O'Donovan for (i = 0; i < npins; i++) { 112477401d7fSDan O'Donovan ret = chv_config_set(pctldev, pins[i], configs, num_configs); 112577401d7fSDan O'Donovan if (ret) 112677401d7fSDan O'Donovan return ret; 112777401d7fSDan O'Donovan } 112877401d7fSDan O'Donovan 112977401d7fSDan O'Donovan return 0; 113077401d7fSDan O'Donovan } 113177401d7fSDan O'Donovan 11326e08d6bbSMika Westerberg static const struct pinconf_ops chv_pinconf_ops = { 11336e08d6bbSMika Westerberg .is_generic = true, 11346e08d6bbSMika Westerberg .pin_config_set = chv_config_set, 11356e08d6bbSMika Westerberg .pin_config_get = chv_config_get, 113677401d7fSDan O'Donovan .pin_config_group_get = chv_config_group_get, 113777401d7fSDan O'Donovan .pin_config_group_set = chv_config_group_set, 11386e08d6bbSMika Westerberg }; 11396e08d6bbSMika Westerberg 11406e08d6bbSMika Westerberg static struct pinctrl_desc chv_pinctrl_desc = { 11416e08d6bbSMika Westerberg .pctlops = &chv_pinctrl_ops, 11426e08d6bbSMika Westerberg .pmxops = &chv_pinmux_ops, 11436e08d6bbSMika Westerberg .confops = &chv_pinconf_ops, 11446e08d6bbSMika Westerberg .owner = THIS_MODULE, 11456e08d6bbSMika Westerberg }; 11466e08d6bbSMika Westerberg 11474e737af8SAndy Shevchenko static int chv_gpio_get(struct gpio_chip *chip, unsigned int offset) 11486e08d6bbSMika Westerberg { 11493ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = gpiochip_get_data(chip); 11504585b000SMika Westerberg unsigned long flags; 11516e08d6bbSMika Westerberg u32 ctrl0, cfg; 11526e08d6bbSMika Westerberg 11530bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 11544e7293e3SAndy Shevchenko ctrl0 = chv_readl(pctrl, offset, CHV_PADCTRL0); 11550bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 11566e08d6bbSMika Westerberg 11576e08d6bbSMika Westerberg cfg = ctrl0 & CHV_PADCTRL0_GPIOCFG_MASK; 11586e08d6bbSMika Westerberg cfg >>= CHV_PADCTRL0_GPIOCFG_SHIFT; 11596e08d6bbSMika Westerberg 11606e08d6bbSMika Westerberg if (cfg == CHV_PADCTRL0_GPIOCFG_GPO) 11616e08d6bbSMika Westerberg return !!(ctrl0 & CHV_PADCTRL0_GPIOTXSTATE); 11626e08d6bbSMika Westerberg return !!(ctrl0 & CHV_PADCTRL0_GPIORXSTATE); 11636e08d6bbSMika Westerberg } 11646e08d6bbSMika Westerberg 11654e737af8SAndy Shevchenko static void chv_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) 11666e08d6bbSMika Westerberg { 11673ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = gpiochip_get_data(chip); 11686e08d6bbSMika Westerberg unsigned long flags; 11696e08d6bbSMika Westerberg u32 ctrl0; 11706e08d6bbSMika Westerberg 11710bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 11726e08d6bbSMika Westerberg 11734e7293e3SAndy Shevchenko ctrl0 = chv_readl(pctrl, offset, CHV_PADCTRL0); 11746e08d6bbSMika Westerberg 11756e08d6bbSMika Westerberg if (value) 11766e08d6bbSMika Westerberg ctrl0 |= CHV_PADCTRL0_GPIOTXSTATE; 11776e08d6bbSMika Westerberg else 11786e08d6bbSMika Westerberg ctrl0 &= ~CHV_PADCTRL0_GPIOTXSTATE; 11796e08d6bbSMika Westerberg 1180bfc8a4baSAndy Shevchenko chv_writel(pctrl, offset, CHV_PADCTRL0, ctrl0); 11816e08d6bbSMika Westerberg 11820bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 11836e08d6bbSMika Westerberg } 11846e08d6bbSMika Westerberg 11854e737af8SAndy Shevchenko static int chv_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) 11866e08d6bbSMika Westerberg { 11873ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = gpiochip_get_data(chip); 11886e08d6bbSMika Westerberg u32 ctrl0, direction; 11894585b000SMika Westerberg unsigned long flags; 11906e08d6bbSMika Westerberg 11910bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 11924e7293e3SAndy Shevchenko ctrl0 = chv_readl(pctrl, offset, CHV_PADCTRL0); 11930bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 11946e08d6bbSMika Westerberg 11956e08d6bbSMika Westerberg direction = ctrl0 & CHV_PADCTRL0_GPIOCFG_MASK; 11966e08d6bbSMika Westerberg direction >>= CHV_PADCTRL0_GPIOCFG_SHIFT; 11976e08d6bbSMika Westerberg 119890a1eb18SMatti Vaittinen if (direction == CHV_PADCTRL0_GPIOCFG_GPO) 119990a1eb18SMatti Vaittinen return GPIO_LINE_DIRECTION_OUT; 120090a1eb18SMatti Vaittinen 120190a1eb18SMatti Vaittinen return GPIO_LINE_DIRECTION_IN; 12026e08d6bbSMika Westerberg } 12036e08d6bbSMika Westerberg 12044e737af8SAndy Shevchenko static int chv_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) 12056e08d6bbSMika Westerberg { 12066e08d6bbSMika Westerberg return pinctrl_gpio_direction_input(chip->base + offset); 12076e08d6bbSMika Westerberg } 12086e08d6bbSMika Westerberg 12094e737af8SAndy Shevchenko static int chv_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, 12106e08d6bbSMika Westerberg int value) 12116e08d6bbSMika Westerberg { 1212549e783fSqipeng.zha chv_gpio_set(chip, offset, value); 12136e08d6bbSMika Westerberg return pinctrl_gpio_direction_output(chip->base + offset); 12146e08d6bbSMika Westerberg } 12156e08d6bbSMika Westerberg 12166e08d6bbSMika Westerberg static const struct gpio_chip chv_gpio_chip = { 12176e08d6bbSMika Westerberg .owner = THIS_MODULE, 121898c85d58SJonas Gorski .request = gpiochip_generic_request, 121998c85d58SJonas Gorski .free = gpiochip_generic_free, 12206e08d6bbSMika Westerberg .get_direction = chv_gpio_get_direction, 12216e08d6bbSMika Westerberg .direction_input = chv_gpio_direction_input, 12226e08d6bbSMika Westerberg .direction_output = chv_gpio_direction_output, 12236e08d6bbSMika Westerberg .get = chv_gpio_get, 12246e08d6bbSMika Westerberg .set = chv_gpio_set, 12256e08d6bbSMika Westerberg }; 12266e08d6bbSMika Westerberg 12276e08d6bbSMika Westerberg static void chv_gpio_irq_ack(struct irq_data *d) 12286e08d6bbSMika Westerberg { 12296e08d6bbSMika Westerberg struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 12303ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = gpiochip_get_data(gc); 123103c4749dSMika Westerberg int pin = irqd_to_hwirq(d); 12326e08d6bbSMika Westerberg u32 intr_line; 12336e08d6bbSMika Westerberg 12340bd50d71SDan O'Donovan raw_spin_lock(&chv_lock); 12356e08d6bbSMika Westerberg 12364e7293e3SAndy Shevchenko intr_line = chv_readl(pctrl, pin, CHV_PADCTRL0); 12376e08d6bbSMika Westerberg intr_line &= CHV_PADCTRL0_INTSEL_MASK; 12386e08d6bbSMika Westerberg intr_line >>= CHV_PADCTRL0_INTSEL_SHIFT; 123999fd6512SAndy Shevchenko chv_pctrl_writel(pctrl, CHV_INTSTAT, BIT(intr_line)); 12406e08d6bbSMika Westerberg 12410bd50d71SDan O'Donovan raw_spin_unlock(&chv_lock); 12426e08d6bbSMika Westerberg } 12436e08d6bbSMika Westerberg 12446e08d6bbSMika Westerberg static void chv_gpio_irq_mask_unmask(struct irq_data *d, bool mask) 12456e08d6bbSMika Westerberg { 12466e08d6bbSMika Westerberg struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 12473ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = gpiochip_get_data(gc); 124803c4749dSMika Westerberg int pin = irqd_to_hwirq(d); 12496e08d6bbSMika Westerberg u32 value, intr_line; 12506e08d6bbSMika Westerberg unsigned long flags; 12516e08d6bbSMika Westerberg 12520bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 12536e08d6bbSMika Westerberg 12544e7293e3SAndy Shevchenko intr_line = chv_readl(pctrl, pin, CHV_PADCTRL0); 12556e08d6bbSMika Westerberg intr_line &= CHV_PADCTRL0_INTSEL_MASK; 12566e08d6bbSMika Westerberg intr_line >>= CHV_PADCTRL0_INTSEL_SHIFT; 12576e08d6bbSMika Westerberg 125899fd6512SAndy Shevchenko value = chv_pctrl_readl(pctrl, CHV_INTMASK); 12596e08d6bbSMika Westerberg if (mask) 12606e08d6bbSMika Westerberg value &= ~BIT(intr_line); 12616e08d6bbSMika Westerberg else 12626e08d6bbSMika Westerberg value |= BIT(intr_line); 126399fd6512SAndy Shevchenko chv_pctrl_writel(pctrl, CHV_INTMASK, value); 12646e08d6bbSMika Westerberg 12650bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 12666e08d6bbSMika Westerberg } 12676e08d6bbSMika Westerberg 12686e08d6bbSMika Westerberg static void chv_gpio_irq_mask(struct irq_data *d) 12696e08d6bbSMika Westerberg { 12706e08d6bbSMika Westerberg chv_gpio_irq_mask_unmask(d, true); 12716e08d6bbSMika Westerberg } 12726e08d6bbSMika Westerberg 12736e08d6bbSMika Westerberg static void chv_gpio_irq_unmask(struct irq_data *d) 12746e08d6bbSMika Westerberg { 12756e08d6bbSMika Westerberg chv_gpio_irq_mask_unmask(d, false); 12766e08d6bbSMika Westerberg } 12776e08d6bbSMika Westerberg 1278e6c906deSMika Westerberg static unsigned chv_gpio_irq_startup(struct irq_data *d) 1279e6c906deSMika Westerberg { 1280e6c906deSMika Westerberg /* 1281e6c906deSMika Westerberg * Check if the interrupt has been requested with 0 as triggering 1282e6c906deSMika Westerberg * type. In that case it is assumed that the current values 1283e6c906deSMika Westerberg * programmed to the hardware are used (e.g BIOS configured 1284e6c906deSMika Westerberg * defaults). 1285e6c906deSMika Westerberg * 1286e6c906deSMika Westerberg * In that case ->irq_set_type() will never be called so we need to 1287e6c906deSMika Westerberg * read back the values from hardware now, set correct flow handler 1288e6c906deSMika Westerberg * and update mappings before the interrupt is being used. 1289e6c906deSMika Westerberg */ 1290e6c906deSMika Westerberg if (irqd_get_trigger_type(d) == IRQ_TYPE_NONE) { 1291e6c906deSMika Westerberg struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 12923ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = gpiochip_get_data(gc); 12938a828570SAndy Shevchenko struct intel_community_context *cctx = &pctrl->context.communities[0]; 12944e737af8SAndy Shevchenko unsigned int pin = irqd_to_hwirq(d); 1295e6c906deSMika Westerberg irq_flow_handler_t handler; 1296e6c906deSMika Westerberg unsigned long flags; 1297e6c906deSMika Westerberg u32 intsel, value; 1298e6c906deSMika Westerberg 12990bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 13004e7293e3SAndy Shevchenko intsel = chv_readl(pctrl, pin, CHV_PADCTRL0); 1301e6c906deSMika Westerberg intsel &= CHV_PADCTRL0_INTSEL_MASK; 1302e6c906deSMika Westerberg intsel >>= CHV_PADCTRL0_INTSEL_SHIFT; 1303e6c906deSMika Westerberg 13044e7293e3SAndy Shevchenko value = chv_readl(pctrl, pin, CHV_PADCTRL1); 1305e6c906deSMika Westerberg if (value & CHV_PADCTRL1_INTWAKECFG_LEVEL) 1306e6c906deSMika Westerberg handler = handle_level_irq; 1307e6c906deSMika Westerberg else 1308e6c906deSMika Westerberg handler = handle_edge_irq; 1309e6c906deSMika Westerberg 13108a828570SAndy Shevchenko if (!cctx->intr_lines[intsel]) { 1311a4e3f783SThomas Gleixner irq_set_handler_locked(d, handler); 13128a828570SAndy Shevchenko cctx->intr_lines[intsel] = pin; 1313e6c906deSMika Westerberg } 13140bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 1315e6c906deSMika Westerberg } 1316e6c906deSMika Westerberg 1317e6c906deSMika Westerberg chv_gpio_irq_unmask(d); 1318e6c906deSMika Westerberg return 0; 1319e6c906deSMika Westerberg } 1320e6c906deSMika Westerberg 13214e737af8SAndy Shevchenko static int chv_gpio_irq_type(struct irq_data *d, unsigned int type) 13226e08d6bbSMika Westerberg { 13236e08d6bbSMika Westerberg struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 13243ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = gpiochip_get_data(gc); 13258a828570SAndy Shevchenko struct intel_community_context *cctx = &pctrl->context.communities[0]; 13264e737af8SAndy Shevchenko unsigned int pin = irqd_to_hwirq(d); 13276e08d6bbSMika Westerberg unsigned long flags; 13286e08d6bbSMika Westerberg u32 value; 13296e08d6bbSMika Westerberg 13300bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 13316e08d6bbSMika Westerberg 13326e08d6bbSMika Westerberg /* 13336e08d6bbSMika Westerberg * Pins which can be used as shared interrupt are configured in 13346e08d6bbSMika Westerberg * BIOS. Driver trusts BIOS configurations and assigns different 13356e08d6bbSMika Westerberg * handler according to the irq type. 13366e08d6bbSMika Westerberg * 13376e08d6bbSMika Westerberg * Driver needs to save the mapping between each pin and 13386e08d6bbSMika Westerberg * its interrupt line. 13396e08d6bbSMika Westerberg * 1. If the pin cfg is locked in BIOS: 13406e08d6bbSMika Westerberg * Trust BIOS has programmed IntWakeCfg bits correctly, 13416e08d6bbSMika Westerberg * driver just needs to save the mapping. 13426e08d6bbSMika Westerberg * 2. If the pin cfg is not locked in BIOS: 13436e08d6bbSMika Westerberg * Driver programs the IntWakeCfg bits and save the mapping. 13446e08d6bbSMika Westerberg */ 13456e08d6bbSMika Westerberg if (!chv_pad_locked(pctrl, pin)) { 13464e7293e3SAndy Shevchenko value = chv_readl(pctrl, pin, CHV_PADCTRL1); 13476e08d6bbSMika Westerberg value &= ~CHV_PADCTRL1_INTWAKECFG_MASK; 13486e08d6bbSMika Westerberg value &= ~CHV_PADCTRL1_INVRXTX_MASK; 13496e08d6bbSMika Westerberg 13506e08d6bbSMika Westerberg if (type & IRQ_TYPE_EDGE_BOTH) { 13516e08d6bbSMika Westerberg if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) 13526e08d6bbSMika Westerberg value |= CHV_PADCTRL1_INTWAKECFG_BOTH; 13536e08d6bbSMika Westerberg else if (type & IRQ_TYPE_EDGE_RISING) 13546e08d6bbSMika Westerberg value |= CHV_PADCTRL1_INTWAKECFG_RISING; 13556e08d6bbSMika Westerberg else if (type & IRQ_TYPE_EDGE_FALLING) 13566e08d6bbSMika Westerberg value |= CHV_PADCTRL1_INTWAKECFG_FALLING; 13576e08d6bbSMika Westerberg } else if (type & IRQ_TYPE_LEVEL_MASK) { 13586e08d6bbSMika Westerberg value |= CHV_PADCTRL1_INTWAKECFG_LEVEL; 13596e08d6bbSMika Westerberg if (type & IRQ_TYPE_LEVEL_LOW) 13606e08d6bbSMika Westerberg value |= CHV_PADCTRL1_INVRXTX_RXDATA; 13616e08d6bbSMika Westerberg } 13626e08d6bbSMika Westerberg 1363bfc8a4baSAndy Shevchenko chv_writel(pctrl, pin, CHV_PADCTRL1, value); 13646e08d6bbSMika Westerberg } 13656e08d6bbSMika Westerberg 13664e7293e3SAndy Shevchenko value = chv_readl(pctrl, pin, CHV_PADCTRL0); 13676e08d6bbSMika Westerberg value &= CHV_PADCTRL0_INTSEL_MASK; 13686e08d6bbSMika Westerberg value >>= CHV_PADCTRL0_INTSEL_SHIFT; 13696e08d6bbSMika Westerberg 13708a828570SAndy Shevchenko cctx->intr_lines[value] = pin; 13716e08d6bbSMika Westerberg 13726e08d6bbSMika Westerberg if (type & IRQ_TYPE_EDGE_BOTH) 1373a4e3f783SThomas Gleixner irq_set_handler_locked(d, handle_edge_irq); 13746e08d6bbSMika Westerberg else if (type & IRQ_TYPE_LEVEL_MASK) 1375a4e3f783SThomas Gleixner irq_set_handler_locked(d, handle_level_irq); 13766e08d6bbSMika Westerberg 13770bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 13786e08d6bbSMika Westerberg 13796e08d6bbSMika Westerberg return 0; 13806e08d6bbSMika Westerberg } 13816e08d6bbSMika Westerberg 1382bd0b9ac4SThomas Gleixner static void chv_gpio_irq_handler(struct irq_desc *desc) 13836e08d6bbSMika Westerberg { 13846e08d6bbSMika Westerberg struct gpio_chip *gc = irq_desc_get_handler_data(desc); 13853ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = gpiochip_get_data(gc); 1386293428f9SAndy Shevchenko const struct intel_community *community = &pctrl->communities[0]; 13878a828570SAndy Shevchenko struct intel_community_context *cctx = &pctrl->context.communities[0]; 13885663bb27SJiang Liu struct irq_chip *chip = irq_desc_get_chip(desc); 13896e08d6bbSMika Westerberg unsigned long pending; 13903dbf1ee6SGrace Kao unsigned long flags; 13916e08d6bbSMika Westerberg u32 intr_line; 13926e08d6bbSMika Westerberg 13936e08d6bbSMika Westerberg chained_irq_enter(chip, desc); 13946e08d6bbSMika Westerberg 13953dbf1ee6SGrace Kao raw_spin_lock_irqsave(&chv_lock, flags); 139699fd6512SAndy Shevchenko pending = chv_pctrl_readl(pctrl, CHV_INTSTAT); 13973dbf1ee6SGrace Kao raw_spin_unlock_irqrestore(&chv_lock, flags); 13983dbf1ee6SGrace Kao 1399293428f9SAndy Shevchenko for_each_set_bit(intr_line, &pending, community->nirqs) { 14008ae93b5eSAndy Shevchenko unsigned int irq, offset; 14016e08d6bbSMika Westerberg 14028a828570SAndy Shevchenko offset = cctx->intr_lines[intr_line]; 1403f0fbe7bcSThierry Reding irq = irq_find_mapping(gc->irq.domain, offset); 14046e08d6bbSMika Westerberg generic_handle_irq(irq); 14056e08d6bbSMika Westerberg } 14066e08d6bbSMika Westerberg 14076e08d6bbSMika Westerberg chained_irq_exit(chip, desc); 14086e08d6bbSMika Westerberg } 14096e08d6bbSMika Westerberg 141070365027SMika Westerberg /* 141170365027SMika Westerberg * Certain machines seem to hardcode Linux IRQ numbers in their ACPI 141270365027SMika Westerberg * tables. Since we leave GPIOs that are not capable of generating 141370365027SMika Westerberg * interrupts out of the irqdomain the numbering will be different and 141470365027SMika Westerberg * cause devices using the hardcoded IRQ numbers fail. In order not to 141570365027SMika Westerberg * break such machines we will only mask pins from irqdomain if the machine 141670365027SMika Westerberg * is not listed below. 141770365027SMika Westerberg */ 141870365027SMika Westerberg static const struct dmi_system_id chv_no_valid_mask[] = { 141970365027SMika Westerberg /* See https://bugzilla.kernel.org/show_bug.cgi?id=194945 */ 14202a8209faSMika Westerberg { 14212a8209faSMika Westerberg .ident = "Intel_Strago based Chromebooks (All models)", 142270365027SMika Westerberg .matches = { 142370365027SMika Westerberg DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), 14242a8209faSMika Westerberg DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_Strago"), 14252a8209faSMika Westerberg }, 14262a8209faSMika Westerberg }, 14272a8209faSMika Westerberg { 14282d80bd3fSAndy Shevchenko .ident = "HP Chromebook 11 G5 (Setzer)", 14292d80bd3fSAndy Shevchenko .matches = { 14302d80bd3fSAndy Shevchenko DMI_MATCH(DMI_SYS_VENDOR, "HP"), 14312d80bd3fSAndy Shevchenko DMI_MATCH(DMI_PRODUCT_NAME, "Setzer"), 14322d80bd3fSAndy Shevchenko }, 14332d80bd3fSAndy Shevchenko }, 14342d80bd3fSAndy Shevchenko { 14352a8209faSMika Westerberg .ident = "Acer Chromebook R11 (Cyan)", 14362a8209faSMika Westerberg .matches = { 14372a8209faSMika Westerberg DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), 14382a8209faSMika Westerberg DMI_MATCH(DMI_PRODUCT_NAME, "Cyan"), 14392a8209faSMika Westerberg }, 14402a8209faSMika Westerberg }, 14412a8209faSMika Westerberg { 14422a8209faSMika Westerberg .ident = "Samsung Chromebook 3 (Celes)", 14432a8209faSMika Westerberg .matches = { 14442a8209faSMika Westerberg DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), 14452a8209faSMika Westerberg DMI_MATCH(DMI_PRODUCT_NAME, "Celes"), 144670365027SMika Westerberg }, 1447a9de080bSWei Yongjun }, 1448a9de080bSWei Yongjun {} 144970365027SMika Westerberg }; 145070365027SMika Westerberg 14515fbe5b58SLinus Walleij static void chv_init_irq_valid_mask(struct gpio_chip *chip, 14525fbe5b58SLinus Walleij unsigned long *valid_mask, 14535fbe5b58SLinus Walleij unsigned int ngpios) 14545fbe5b58SLinus Walleij { 14553ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = gpiochip_get_data(chip); 1456293428f9SAndy Shevchenko const struct intel_community *community = &pctrl->communities[0]; 14575fbe5b58SLinus Walleij int i; 14585fbe5b58SLinus Walleij 14595fbe5b58SLinus Walleij /* Do not add GPIOs that can only generate GPEs to the IRQ domain */ 1460293428f9SAndy Shevchenko for (i = 0; i < pctrl->soc->npins; i++) { 14615fbe5b58SLinus Walleij const struct pinctrl_pin_desc *desc; 14625fbe5b58SLinus Walleij u32 intsel; 14635fbe5b58SLinus Walleij 1464293428f9SAndy Shevchenko desc = &pctrl->soc->pins[i]; 14655fbe5b58SLinus Walleij 14664e7293e3SAndy Shevchenko intsel = chv_readl(pctrl, desc->number, CHV_PADCTRL0); 14675fbe5b58SLinus Walleij intsel &= CHV_PADCTRL0_INTSEL_MASK; 14685fbe5b58SLinus Walleij intsel >>= CHV_PADCTRL0_INTSEL_SHIFT; 14695fbe5b58SLinus Walleij 14705fbe5b58SLinus Walleij if (intsel >= community->nirqs) 147137398985SHans de Goede clear_bit(desc->number, valid_mask); 14725fbe5b58SLinus Walleij } 14735fbe5b58SLinus Walleij } 14745fbe5b58SLinus Walleij 147582d9beb4SHans de Goede static int chv_gpio_irq_init_hw(struct gpio_chip *chip) 147682d9beb4SHans de Goede { 14773ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = gpiochip_get_data(chip); 1478293428f9SAndy Shevchenko const struct intel_community *community = &pctrl->communities[0]; 147982d9beb4SHans de Goede 148082d9beb4SHans de Goede /* 148182d9beb4SHans de Goede * The same set of machines in chv_no_valid_mask[] have incorrectly 148282d9beb4SHans de Goede * configured GPIOs that generate spurious interrupts so we use 148382d9beb4SHans de Goede * this same list to apply another quirk for them. 148482d9beb4SHans de Goede * 148582d9beb4SHans de Goede * See also https://bugzilla.kernel.org/show_bug.cgi?id=197953. 148682d9beb4SHans de Goede */ 148782d9beb4SHans de Goede if (!pctrl->chip.irq.init_valid_mask) { 148882d9beb4SHans de Goede /* 148982d9beb4SHans de Goede * Mask all interrupts the community is able to generate 149082d9beb4SHans de Goede * but leave the ones that can only generate GPEs unmasked. 149182d9beb4SHans de Goede */ 1492293428f9SAndy Shevchenko chv_pctrl_writel(pctrl, CHV_INTMASK, GENMASK(31, community->nirqs)); 149382d9beb4SHans de Goede } 149482d9beb4SHans de Goede 149582d9beb4SHans de Goede /* Clear all interrupts */ 149699fd6512SAndy Shevchenko chv_pctrl_writel(pctrl, CHV_INTSTAT, 0xffff); 149782d9beb4SHans de Goede 149882d9beb4SHans de Goede return 0; 149982d9beb4SHans de Goede } 150082d9beb4SHans de Goede 1501bd90633aSHans de Goede static int chv_gpio_add_pin_ranges(struct gpio_chip *chip) 1502bd90633aSHans de Goede { 15033ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = gpiochip_get_data(chip); 1504293428f9SAndy Shevchenko const struct intel_community *community = &pctrl->communities[0]; 150536ad7b24SAndy Shevchenko const struct intel_padgroup *gpp; 1506bd90633aSHans de Goede int ret, i; 1507bd90633aSHans de Goede 150836ad7b24SAndy Shevchenko for (i = 0; i < community->ngpps; i++) { 150936ad7b24SAndy Shevchenko gpp = &community->gpps[i]; 1510bd90633aSHans de Goede ret = gpiochip_add_pin_range(chip, dev_name(pctrl->dev), 151136ad7b24SAndy Shevchenko gpp->base, gpp->base, 151236ad7b24SAndy Shevchenko gpp->size); 1513bd90633aSHans de Goede if (ret) { 1514bd90633aSHans de Goede dev_err(pctrl->dev, "failed to add GPIO pin range\n"); 1515bd90633aSHans de Goede return ret; 1516bd90633aSHans de Goede } 1517bd90633aSHans de Goede } 1518bd90633aSHans de Goede 1519bd90633aSHans de Goede return 0; 1520bd90633aSHans de Goede } 1521bd90633aSHans de Goede 15223ea2e2caSAndy Shevchenko static int chv_gpio_probe(struct intel_pinctrl *pctrl, int irq) 15236e08d6bbSMika Westerberg { 1524293428f9SAndy Shevchenko const struct intel_community *community = &pctrl->communities[0]; 152536ad7b24SAndy Shevchenko const struct intel_padgroup *gpp; 15266e08d6bbSMika Westerberg struct gpio_chip *chip = &pctrl->chip; 152770365027SMika Westerberg bool need_valid_mask = !dmi_check_system(chv_no_valid_mask); 152803c4749dSMika Westerberg int ret, i, irq_base; 15296e08d6bbSMika Westerberg 15306e08d6bbSMika Westerberg *chip = chv_gpio_chip; 15316e08d6bbSMika Westerberg 1532293428f9SAndy Shevchenko chip->ngpio = pctrl->soc->pins[pctrl->soc->npins - 1].number + 1; 15336e08d6bbSMika Westerberg chip->label = dev_name(pctrl->dev); 1534bd90633aSHans de Goede chip->add_pin_ranges = chv_gpio_add_pin_ranges; 153558383c78SLinus Walleij chip->parent = pctrl->dev; 15366e08d6bbSMika Westerberg chip->base = -1; 15376e08d6bbSMika Westerberg 1538b9a19bdbSHans de Goede pctrl->irq = irq; 1539e58e1773SAndy Shevchenko pctrl->irqchip.name = "chv-gpio"; 1540e58e1773SAndy Shevchenko pctrl->irqchip.irq_startup = chv_gpio_irq_startup; 1541e58e1773SAndy Shevchenko pctrl->irqchip.irq_ack = chv_gpio_irq_ack; 1542e58e1773SAndy Shevchenko pctrl->irqchip.irq_mask = chv_gpio_irq_mask; 1543e58e1773SAndy Shevchenko pctrl->irqchip.irq_unmask = chv_gpio_irq_unmask; 1544e58e1773SAndy Shevchenko pctrl->irqchip.irq_set_type = chv_gpio_irq_type; 1545e58e1773SAndy Shevchenko pctrl->irqchip.flags = IRQCHIP_SKIP_SET_WAKE; 1546e58e1773SAndy Shevchenko 1547b9a19bdbSHans de Goede chip->irq.chip = &pctrl->irqchip; 1548b9a19bdbSHans de Goede chip->irq.init_hw = chv_gpio_irq_init_hw; 1549b9a19bdbSHans de Goede chip->irq.parent_handler = chv_gpio_irq_handler; 1550b9a19bdbSHans de Goede chip->irq.num_parents = 1; 1551b9a19bdbSHans de Goede chip->irq.parents = &pctrl->irq; 1552b9a19bdbSHans de Goede chip->irq.default_type = IRQ_TYPE_NONE; 1553b9a19bdbSHans de Goede chip->irq.handler = handle_bad_irq; 1554b9a19bdbSHans de Goede if (need_valid_mask) { 1555b9a19bdbSHans de Goede chip->irq.init_valid_mask = chv_init_irq_valid_mask; 1556b9a19bdbSHans de Goede } else { 1557b9a19bdbSHans de Goede irq_base = devm_irq_alloc_descs(pctrl->dev, -1, 0, 1558293428f9SAndy Shevchenko pctrl->soc->npins, NUMA_NO_NODE); 1559b9a19bdbSHans de Goede if (irq_base < 0) { 1560b9a19bdbSHans de Goede dev_err(pctrl->dev, "Failed to allocate IRQ numbers\n"); 1561b9a19bdbSHans de Goede return irq_base; 1562b9a19bdbSHans de Goede } 1563b9a19bdbSHans de Goede } 1564b9a19bdbSHans de Goede 1565b9a19bdbSHans de Goede ret = devm_gpiochip_add_data(pctrl->dev, chip, pctrl); 15666e08d6bbSMika Westerberg if (ret) { 1567b9a19bdbSHans de Goede dev_err(pctrl->dev, "Failed to register gpiochip\n"); 1568d1073418SMika Westerberg return ret; 15696e08d6bbSMika Westerberg } 15706e08d6bbSMika Westerberg 157183b9dc11SMika Westerberg if (!need_valid_mask) { 157236ad7b24SAndy Shevchenko for (i = 0; i < community->ngpps; i++) { 157336ad7b24SAndy Shevchenko gpp = &community->gpps[i]; 157483b9dc11SMika Westerberg 157583b9dc11SMika Westerberg irq_domain_associate_many(chip->irq.domain, irq_base, 157636ad7b24SAndy Shevchenko gpp->base, gpp->size); 157736ad7b24SAndy Shevchenko irq_base += gpp->size; 157883b9dc11SMika Westerberg } 157983b9dc11SMika Westerberg } 158083b9dc11SMika Westerberg 15816e08d6bbSMika Westerberg return 0; 15826e08d6bbSMika Westerberg } 15836e08d6bbSMika Westerberg 1584a0b02859SHans de Goede static acpi_status chv_pinctrl_mmio_access_handler(u32 function, 1585a0b02859SHans de Goede acpi_physical_address address, u32 bits, u64 *value, 1586a0b02859SHans de Goede void *handler_context, void *region_context) 1587a0b02859SHans de Goede { 15883ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = region_context; 1589a0b02859SHans de Goede unsigned long flags; 1590a0b02859SHans de Goede acpi_status ret = AE_OK; 1591a0b02859SHans de Goede 1592a0b02859SHans de Goede raw_spin_lock_irqsave(&chv_lock, flags); 1593a0b02859SHans de Goede 1594a0b02859SHans de Goede if (function == ACPI_WRITE) 159599fd6512SAndy Shevchenko chv_pctrl_writel(pctrl, address, *value); 1596a0b02859SHans de Goede else if (function == ACPI_READ) 159799fd6512SAndy Shevchenko *value = chv_pctrl_readl(pctrl, address); 1598a0b02859SHans de Goede else 1599a0b02859SHans de Goede ret = AE_BAD_PARAMETER; 1600a0b02859SHans de Goede 1601a0b02859SHans de Goede raw_spin_unlock_irqrestore(&chv_lock, flags); 1602a0b02859SHans de Goede 1603a0b02859SHans de Goede return ret; 1604a0b02859SHans de Goede } 1605a0b02859SHans de Goede 16066e08d6bbSMika Westerberg static int chv_pinctrl_probe(struct platform_device *pdev) 16076e08d6bbSMika Westerberg { 1608293428f9SAndy Shevchenko const struct intel_pinctrl_soc_data *soc_data = NULL; 1609293428f9SAndy Shevchenko const struct intel_pinctrl_soc_data **soc_table; 1610293428f9SAndy Shevchenko struct intel_community *community; 1611293428f9SAndy Shevchenko struct device *dev = &pdev->dev; 16123ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl; 16136e08d6bbSMika Westerberg struct acpi_device *adev; 1614a0b02859SHans de Goede acpi_status status; 16156e08d6bbSMika Westerberg int ret, irq, i; 16166e08d6bbSMika Westerberg 16176e08d6bbSMika Westerberg adev = ACPI_COMPANION(&pdev->dev); 16186e08d6bbSMika Westerberg if (!adev) 16196e08d6bbSMika Westerberg return -ENODEV; 16206e08d6bbSMika Westerberg 1621293428f9SAndy Shevchenko soc_table = (const struct intel_pinctrl_soc_data **)device_get_match_data(dev); 1622293428f9SAndy Shevchenko for (i = 0; soc_table[i]; i++) { 1623293428f9SAndy Shevchenko if (!strcmp(adev->pnp.unique_id, soc_table[i]->uid)) { 1624293428f9SAndy Shevchenko soc_data = soc_table[i]; 1625293428f9SAndy Shevchenko break; 1626293428f9SAndy Shevchenko } 1627293428f9SAndy Shevchenko } 1628293428f9SAndy Shevchenko if (!soc_data) 1629293428f9SAndy Shevchenko return -ENODEV; 1630293428f9SAndy Shevchenko 1631293428f9SAndy Shevchenko pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL); 16326e08d6bbSMika Westerberg if (!pctrl) 16336e08d6bbSMika Westerberg return -ENOMEM; 16346e08d6bbSMika Westerberg 1635359164faSAndy Shevchenko pctrl->dev = dev; 1636293428f9SAndy Shevchenko pctrl->soc = soc_data; 1637293428f9SAndy Shevchenko 1638293428f9SAndy Shevchenko pctrl->ncommunities = pctrl->soc->ncommunities; 1639293428f9SAndy Shevchenko pctrl->communities = devm_kmemdup(dev, pctrl->soc->communities, 1640293428f9SAndy Shevchenko pctrl->ncommunities * sizeof(*pctrl->communities), 1641293428f9SAndy Shevchenko GFP_KERNEL); 1642293428f9SAndy Shevchenko if (!pctrl->communities) 1643293428f9SAndy Shevchenko return -ENOMEM; 1644293428f9SAndy Shevchenko 1645293428f9SAndy Shevchenko community = &pctrl->communities[0]; 1646293428f9SAndy Shevchenko community->regs = devm_platform_ioremap_resource(pdev, 0); 1647293428f9SAndy Shevchenko if (IS_ERR(community->regs)) 1648293428f9SAndy Shevchenko return PTR_ERR(community->regs); 1649293428f9SAndy Shevchenko 1650293428f9SAndy Shevchenko community->pad_regs = community->regs + FAMILY_PAD_REGS_OFF; 16516e08d6bbSMika Westerberg 16529eb457b5SMika Westerberg #ifdef CONFIG_PM_SLEEP 1653293428f9SAndy Shevchenko pctrl->context.pads = devm_kcalloc(dev, pctrl->soc->npins, 1654293428f9SAndy Shevchenko sizeof(*pctrl->context.pads), 16559eb457b5SMika Westerberg GFP_KERNEL); 1656293428f9SAndy Shevchenko if (!pctrl->context.pads) 16579eb457b5SMika Westerberg return -ENOMEM; 16589eb457b5SMika Westerberg #endif 16599eb457b5SMika Westerberg 16608a828570SAndy Shevchenko pctrl->context.communities = devm_kcalloc(dev, pctrl->soc->ncommunities, 16618a828570SAndy Shevchenko sizeof(*pctrl->context.communities), 16628a828570SAndy Shevchenko GFP_KERNEL); 16638a828570SAndy Shevchenko if (!pctrl->context.communities) 16648a828570SAndy Shevchenko return -ENOMEM; 16658a828570SAndy Shevchenko 16666e08d6bbSMika Westerberg irq = platform_get_irq(pdev, 0); 166757afe3eaSStephen Boyd if (irq < 0) 16686e08d6bbSMika Westerberg return irq; 16696e08d6bbSMika Westerberg 16706e08d6bbSMika Westerberg pctrl->pctldesc = chv_pinctrl_desc; 1671359164faSAndy Shevchenko pctrl->pctldesc.name = dev_name(dev); 1672293428f9SAndy Shevchenko pctrl->pctldesc.pins = pctrl->soc->pins; 1673293428f9SAndy Shevchenko pctrl->pctldesc.npins = pctrl->soc->npins; 16746e08d6bbSMika Westerberg 1675359164faSAndy Shevchenko pctrl->pctldev = devm_pinctrl_register(dev, &pctrl->pctldesc, pctrl); 1676323de9efSMasahiro Yamada if (IS_ERR(pctrl->pctldev)) { 1677359164faSAndy Shevchenko dev_err(dev, "failed to register pinctrl driver\n"); 1678323de9efSMasahiro Yamada return PTR_ERR(pctrl->pctldev); 16796e08d6bbSMika Westerberg } 16806e08d6bbSMika Westerberg 16816e08d6bbSMika Westerberg ret = chv_gpio_probe(pctrl, irq); 16827cf061faSLaxman Dewangan if (ret) 16836e08d6bbSMika Westerberg return ret; 16846e08d6bbSMika Westerberg 1685a0b02859SHans de Goede status = acpi_install_address_space_handler(adev->handle, 1686293428f9SAndy Shevchenko community->acpi_space_id, 1687a0b02859SHans de Goede chv_pinctrl_mmio_access_handler, 1688a0b02859SHans de Goede NULL, pctrl); 1689a0b02859SHans de Goede if (ACPI_FAILURE(status)) 1690359164faSAndy Shevchenko dev_err(dev, "failed to install ACPI addr space handler\n"); 1691a0b02859SHans de Goede 16926e08d6bbSMika Westerberg platform_set_drvdata(pdev, pctrl); 16936e08d6bbSMika Westerberg 16946e08d6bbSMika Westerberg return 0; 16956e08d6bbSMika Westerberg } 16966e08d6bbSMika Westerberg 1697a0b02859SHans de Goede static int chv_pinctrl_remove(struct platform_device *pdev) 1698a0b02859SHans de Goede { 16993ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = platform_get_drvdata(pdev); 1700293428f9SAndy Shevchenko const struct intel_community *community = &pctrl->communities[0]; 1701a0b02859SHans de Goede 1702a0b02859SHans de Goede acpi_remove_address_space_handler(ACPI_COMPANION(&pdev->dev), 1703293428f9SAndy Shevchenko community->acpi_space_id, 1704a0b02859SHans de Goede chv_pinctrl_mmio_access_handler); 1705a0b02859SHans de Goede 1706a0b02859SHans de Goede return 0; 1707a0b02859SHans de Goede } 1708a0b02859SHans de Goede 17099eb457b5SMika Westerberg #ifdef CONFIG_PM_SLEEP 1710d2cdf5dcSMika Westerberg static int chv_pinctrl_suspend_noirq(struct device *dev) 17119eb457b5SMika Westerberg { 17123ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = dev_get_drvdata(dev); 17138a828570SAndy Shevchenko struct intel_community_context *cctx = &pctrl->context.communities[0]; 171456211121SMika Westerberg unsigned long flags; 17159eb457b5SMika Westerberg int i; 17169eb457b5SMika Westerberg 171756211121SMika Westerberg raw_spin_lock_irqsave(&chv_lock, flags); 171856211121SMika Westerberg 17198a828570SAndy Shevchenko cctx->saved_intmask = chv_pctrl_readl(pctrl, CHV_INTMASK); 17209eb457b5SMika Westerberg 1721293428f9SAndy Shevchenko for (i = 0; i < pctrl->soc->npins; i++) { 17229eb457b5SMika Westerberg const struct pinctrl_pin_desc *desc; 1723293428f9SAndy Shevchenko struct intel_pad_context *ctx = &pctrl->context.pads[i]; 17249eb457b5SMika Westerberg 1725293428f9SAndy Shevchenko desc = &pctrl->soc->pins[i]; 17269eb457b5SMika Westerberg if (chv_pad_locked(pctrl, desc->number)) 17279eb457b5SMika Westerberg continue; 17289eb457b5SMika Westerberg 17294e7293e3SAndy Shevchenko ctx->padctrl0 = chv_readl(pctrl, desc->number, CHV_PADCTRL0); 17304e7293e3SAndy Shevchenko ctx->padctrl0 &= ~CHV_PADCTRL0_GPIORXSTATE; 17319eb457b5SMika Westerberg 17324e7293e3SAndy Shevchenko ctx->padctrl1 = chv_readl(pctrl, desc->number, CHV_PADCTRL1); 17339eb457b5SMika Westerberg } 17349eb457b5SMika Westerberg 173556211121SMika Westerberg raw_spin_unlock_irqrestore(&chv_lock, flags); 173656211121SMika Westerberg 17379eb457b5SMika Westerberg return 0; 17389eb457b5SMika Westerberg } 17399eb457b5SMika Westerberg 1740d2cdf5dcSMika Westerberg static int chv_pinctrl_resume_noirq(struct device *dev) 17419eb457b5SMika Westerberg { 17423ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = dev_get_drvdata(dev); 17438a828570SAndy Shevchenko struct intel_community_context *cctx = &pctrl->context.communities[0]; 174456211121SMika Westerberg unsigned long flags; 17459eb457b5SMika Westerberg int i; 17469eb457b5SMika Westerberg 174756211121SMika Westerberg raw_spin_lock_irqsave(&chv_lock, flags); 174856211121SMika Westerberg 17499eb457b5SMika Westerberg /* 17509eb457b5SMika Westerberg * Mask all interrupts before restoring per-pin configuration 17519eb457b5SMika Westerberg * registers because we don't know in which state BIOS left them 17529eb457b5SMika Westerberg * upon exiting suspend. 17539eb457b5SMika Westerberg */ 175499fd6512SAndy Shevchenko chv_pctrl_writel(pctrl, CHV_INTMASK, 0x0000); 17559eb457b5SMika Westerberg 1756293428f9SAndy Shevchenko for (i = 0; i < pctrl->soc->npins; i++) { 17579eb457b5SMika Westerberg const struct pinctrl_pin_desc *desc; 1758293428f9SAndy Shevchenko struct intel_pad_context *ctx = &pctrl->context.pads[i]; 17599eb457b5SMika Westerberg u32 val; 17609eb457b5SMika Westerberg 1761293428f9SAndy Shevchenko desc = &pctrl->soc->pins[i]; 17629eb457b5SMika Westerberg if (chv_pad_locked(pctrl, desc->number)) 17639eb457b5SMika Westerberg continue; 17649eb457b5SMika Westerberg 17659eb457b5SMika Westerberg /* Only restore if our saved state differs from the current */ 17664e7293e3SAndy Shevchenko val = chv_readl(pctrl, desc->number, CHV_PADCTRL0); 17674e7293e3SAndy Shevchenko val &= ~CHV_PADCTRL0_GPIORXSTATE; 17689eb457b5SMika Westerberg if (ctx->padctrl0 != val) { 1769bfc8a4baSAndy Shevchenko chv_writel(pctrl, desc->number, CHV_PADCTRL0, ctx->padctrl0); 17709eb457b5SMika Westerberg dev_dbg(pctrl->dev, "restored pin %2u ctrl0 0x%08x\n", 17714e7293e3SAndy Shevchenko desc->number, chv_readl(pctrl, desc->number, CHV_PADCTRL0)); 17729eb457b5SMika Westerberg } 17739eb457b5SMika Westerberg 17744e7293e3SAndy Shevchenko val = chv_readl(pctrl, desc->number, CHV_PADCTRL1); 17759eb457b5SMika Westerberg if (ctx->padctrl1 != val) { 1776bfc8a4baSAndy Shevchenko chv_writel(pctrl, desc->number, CHV_PADCTRL1, ctx->padctrl1); 17779eb457b5SMika Westerberg dev_dbg(pctrl->dev, "restored pin %2u ctrl1 0x%08x\n", 17784e7293e3SAndy Shevchenko desc->number, chv_readl(pctrl, desc->number, CHV_PADCTRL1)); 17799eb457b5SMika Westerberg } 17809eb457b5SMika Westerberg } 17819eb457b5SMika Westerberg 17829eb457b5SMika Westerberg /* 17839eb457b5SMika Westerberg * Now that all pins are restored to known state, we can restore 17849eb457b5SMika Westerberg * the interrupt mask register as well. 17859eb457b5SMika Westerberg */ 178699fd6512SAndy Shevchenko chv_pctrl_writel(pctrl, CHV_INTSTAT, 0xffff); 17878a828570SAndy Shevchenko chv_pctrl_writel(pctrl, CHV_INTMASK, cctx->saved_intmask); 17889eb457b5SMika Westerberg 178956211121SMika Westerberg raw_spin_unlock_irqrestore(&chv_lock, flags); 179056211121SMika Westerberg 17919eb457b5SMika Westerberg return 0; 17929eb457b5SMika Westerberg } 17939eb457b5SMika Westerberg #endif 17949eb457b5SMika Westerberg 17959eb457b5SMika Westerberg static const struct dev_pm_ops chv_pinctrl_pm_ops = { 1796d2cdf5dcSMika Westerberg SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(chv_pinctrl_suspend_noirq, 1797d2cdf5dcSMika Westerberg chv_pinctrl_resume_noirq) 17989eb457b5SMika Westerberg }; 17999eb457b5SMika Westerberg 18006e08d6bbSMika Westerberg static const struct acpi_device_id chv_pinctrl_acpi_match[] = { 1801293428f9SAndy Shevchenko { "INT33FF", (kernel_ulong_t)chv_soc_data }, 18026e08d6bbSMika Westerberg { } 18036e08d6bbSMika Westerberg }; 18046e08d6bbSMika Westerberg MODULE_DEVICE_TABLE(acpi, chv_pinctrl_acpi_match); 18056e08d6bbSMika Westerberg 18066e08d6bbSMika Westerberg static struct platform_driver chv_pinctrl_driver = { 18076e08d6bbSMika Westerberg .probe = chv_pinctrl_probe, 1808a0b02859SHans de Goede .remove = chv_pinctrl_remove, 18096e08d6bbSMika Westerberg .driver = { 18106e08d6bbSMika Westerberg .name = "cherryview-pinctrl", 18119eb457b5SMika Westerberg .pm = &chv_pinctrl_pm_ops, 18126e08d6bbSMika Westerberg .acpi_match_table = chv_pinctrl_acpi_match, 18136e08d6bbSMika Westerberg }, 18146e08d6bbSMika Westerberg }; 18156e08d6bbSMika Westerberg 18166e08d6bbSMika Westerberg static int __init chv_pinctrl_init(void) 18176e08d6bbSMika Westerberg { 18186e08d6bbSMika Westerberg return platform_driver_register(&chv_pinctrl_driver); 18196e08d6bbSMika Westerberg } 18206e08d6bbSMika Westerberg subsys_initcall(chv_pinctrl_init); 18216e08d6bbSMika Westerberg 18226e08d6bbSMika Westerberg static void __exit chv_pinctrl_exit(void) 18236e08d6bbSMika Westerberg { 18246e08d6bbSMika Westerberg platform_driver_unregister(&chv_pinctrl_driver); 18256e08d6bbSMika Westerberg } 18266e08d6bbSMika Westerberg module_exit(chv_pinctrl_exit); 18276e08d6bbSMika Westerberg 18286e08d6bbSMika Westerberg MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); 18296e08d6bbSMika Westerberg MODULE_DESCRIPTION("Intel Cherryview/Braswell pinctrl driver"); 18306e08d6bbSMika Westerberg MODULE_LICENSE("GPL v2"); 1831