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) 61a0bf06dcSHans de Goede #define CHV_PADCTRL1_INVRXTX_TXDATA BIT(7) 625707dd73SAndy Shevchenko #define CHV_PADCTRL1_INVRXTX_RXDATA BIT(6) 635707dd73SAndy Shevchenko #define CHV_PADCTRL1_INVRXTX_TXENABLE BIT(5) 646e08d6bbSMika Westerberg #define CHV_PADCTRL1_ODEN BIT(3) 655707dd73SAndy Shevchenko #define CHV_PADCTRL1_INTWAKECFG_MASK GENMASK(2, 0) 666e08d6bbSMika Westerberg #define CHV_PADCTRL1_INTWAKECFG_FALLING 1 676e08d6bbSMika Westerberg #define CHV_PADCTRL1_INTWAKECFG_RISING 2 686e08d6bbSMika Westerberg #define CHV_PADCTRL1_INTWAKECFG_BOTH 3 696e08d6bbSMika Westerberg #define CHV_PADCTRL1_INTWAKECFG_LEVEL 4 706e08d6bbSMika Westerberg 71293428f9SAndy Shevchenko struct intel_pad_context { 729eb457b5SMika Westerberg u32 padctrl0; 739eb457b5SMika Westerberg u32 padctrl1; 749eb457b5SMika Westerberg }; 759eb457b5SMika Westerberg 766e08d6bbSMika Westerberg /** 778a828570SAndy Shevchenko * struct intel_community_context - community context for Cherryview 788a828570SAndy Shevchenko * @intr_lines: Mapping between 16 HW interrupt wires and GPIO offset (in GPIO number space) 798a828570SAndy Shevchenko * @saved_intmask: Interrupt mask saved for system sleep 808a828570SAndy Shevchenko */ 818a828570SAndy Shevchenko struct intel_community_context { 828a828570SAndy Shevchenko unsigned int intr_lines[16]; 838a828570SAndy Shevchenko u32 saved_intmask; 848a828570SAndy Shevchenko }; 858a828570SAndy Shevchenko 8636ad7b24SAndy Shevchenko #define PINMODE_INVERT_OE BIT(15) 876e08d6bbSMika Westerberg 8836ad7b24SAndy Shevchenko #define PINMODE(m, i) ((m) | ((i) * PINMODE_INVERT_OE)) 896e08d6bbSMika Westerberg 9036ad7b24SAndy Shevchenko #define CHV_GPP(start, end) \ 916e08d6bbSMika Westerberg { \ 926e08d6bbSMika Westerberg .base = (start), \ 9336ad7b24SAndy Shevchenko .size = (end) - (start) + 1, \ 946e08d6bbSMika Westerberg } 956e08d6bbSMika Westerberg 96293428f9SAndy Shevchenko #define CHV_COMMUNITY(g, i, a) \ 97293428f9SAndy Shevchenko { \ 98293428f9SAndy Shevchenko .gpps = (g), \ 99293428f9SAndy Shevchenko .ngpps = ARRAY_SIZE(g), \ 100293428f9SAndy Shevchenko .nirqs = (i), \ 101293428f9SAndy Shevchenko .acpi_space_id = (a), \ 102293428f9SAndy Shevchenko } 103293428f9SAndy Shevchenko 1046e08d6bbSMika Westerberg static const struct pinctrl_pin_desc southwest_pins[] = { 1056e08d6bbSMika Westerberg PINCTRL_PIN(0, "FST_SPI_D2"), 1066e08d6bbSMika Westerberg PINCTRL_PIN(1, "FST_SPI_D0"), 1076e08d6bbSMika Westerberg PINCTRL_PIN(2, "FST_SPI_CLK"), 1086e08d6bbSMika Westerberg PINCTRL_PIN(3, "FST_SPI_D3"), 1096e08d6bbSMika Westerberg PINCTRL_PIN(4, "FST_SPI_CS1_B"), 1106e08d6bbSMika Westerberg PINCTRL_PIN(5, "FST_SPI_D1"), 1116e08d6bbSMika Westerberg PINCTRL_PIN(6, "FST_SPI_CS0_B"), 1126e08d6bbSMika Westerberg PINCTRL_PIN(7, "FST_SPI_CS2_B"), 1136e08d6bbSMika Westerberg 1146e08d6bbSMika Westerberg PINCTRL_PIN(15, "UART1_RTS_B"), 1156e08d6bbSMika Westerberg PINCTRL_PIN(16, "UART1_RXD"), 1166e08d6bbSMika Westerberg PINCTRL_PIN(17, "UART2_RXD"), 1176e08d6bbSMika Westerberg PINCTRL_PIN(18, "UART1_CTS_B"), 1186e08d6bbSMika Westerberg PINCTRL_PIN(19, "UART2_RTS_B"), 1196e08d6bbSMika Westerberg PINCTRL_PIN(20, "UART1_TXD"), 1206e08d6bbSMika Westerberg PINCTRL_PIN(21, "UART2_TXD"), 1216e08d6bbSMika Westerberg PINCTRL_PIN(22, "UART2_CTS_B"), 1226e08d6bbSMika Westerberg 1236e08d6bbSMika Westerberg PINCTRL_PIN(30, "MF_HDA_CLK"), 1246e08d6bbSMika Westerberg PINCTRL_PIN(31, "MF_HDA_RSTB"), 1256e08d6bbSMika Westerberg PINCTRL_PIN(32, "MF_HDA_SDIO"), 1266e08d6bbSMika Westerberg PINCTRL_PIN(33, "MF_HDA_SDO"), 1276e08d6bbSMika Westerberg PINCTRL_PIN(34, "MF_HDA_DOCKRSTB"), 1286e08d6bbSMika Westerberg PINCTRL_PIN(35, "MF_HDA_SYNC"), 1296e08d6bbSMika Westerberg PINCTRL_PIN(36, "MF_HDA_SDI1"), 1306e08d6bbSMika Westerberg PINCTRL_PIN(37, "MF_HDA_DOCKENB"), 1316e08d6bbSMika Westerberg 1326e08d6bbSMika Westerberg PINCTRL_PIN(45, "I2C5_SDA"), 1336e08d6bbSMika Westerberg PINCTRL_PIN(46, "I2C4_SDA"), 1346e08d6bbSMika Westerberg PINCTRL_PIN(47, "I2C6_SDA"), 1356e08d6bbSMika Westerberg PINCTRL_PIN(48, "I2C5_SCL"), 1366e08d6bbSMika Westerberg PINCTRL_PIN(49, "I2C_NFC_SDA"), 1376e08d6bbSMika Westerberg PINCTRL_PIN(50, "I2C4_SCL"), 1386e08d6bbSMika Westerberg PINCTRL_PIN(51, "I2C6_SCL"), 1396e08d6bbSMika Westerberg PINCTRL_PIN(52, "I2C_NFC_SCL"), 1406e08d6bbSMika Westerberg 1416e08d6bbSMika Westerberg PINCTRL_PIN(60, "I2C1_SDA"), 1426e08d6bbSMika Westerberg PINCTRL_PIN(61, "I2C0_SDA"), 1436e08d6bbSMika Westerberg PINCTRL_PIN(62, "I2C2_SDA"), 1446e08d6bbSMika Westerberg PINCTRL_PIN(63, "I2C1_SCL"), 1456e08d6bbSMika Westerberg PINCTRL_PIN(64, "I2C3_SDA"), 1466e08d6bbSMika Westerberg PINCTRL_PIN(65, "I2C0_SCL"), 1476e08d6bbSMika Westerberg PINCTRL_PIN(66, "I2C2_SCL"), 1486e08d6bbSMika Westerberg PINCTRL_PIN(67, "I2C3_SCL"), 1496e08d6bbSMika Westerberg 1506e08d6bbSMika Westerberg PINCTRL_PIN(75, "SATA_GP0"), 1516e08d6bbSMika Westerberg PINCTRL_PIN(76, "SATA_GP1"), 1526e08d6bbSMika Westerberg PINCTRL_PIN(77, "SATA_LEDN"), 1536e08d6bbSMika Westerberg PINCTRL_PIN(78, "SATA_GP2"), 1546e08d6bbSMika Westerberg PINCTRL_PIN(79, "MF_SMB_ALERTB"), 1556e08d6bbSMika Westerberg PINCTRL_PIN(80, "SATA_GP3"), 1566e08d6bbSMika Westerberg PINCTRL_PIN(81, "MF_SMB_CLK"), 1576e08d6bbSMika Westerberg PINCTRL_PIN(82, "MF_SMB_DATA"), 1586e08d6bbSMika Westerberg 1596e08d6bbSMika Westerberg PINCTRL_PIN(90, "PCIE_CLKREQ0B"), 1606e08d6bbSMika Westerberg PINCTRL_PIN(91, "PCIE_CLKREQ1B"), 1616e08d6bbSMika Westerberg PINCTRL_PIN(92, "GP_SSP_2_CLK"), 1626e08d6bbSMika Westerberg PINCTRL_PIN(93, "PCIE_CLKREQ2B"), 1636e08d6bbSMika Westerberg PINCTRL_PIN(94, "GP_SSP_2_RXD"), 1646e08d6bbSMika Westerberg PINCTRL_PIN(95, "PCIE_CLKREQ3B"), 1656e08d6bbSMika Westerberg PINCTRL_PIN(96, "GP_SSP_2_FS"), 1666e08d6bbSMika Westerberg PINCTRL_PIN(97, "GP_SSP_2_TXD"), 1676e08d6bbSMika Westerberg }; 1686e08d6bbSMika Westerberg 1696e08d6bbSMika Westerberg static const unsigned southwest_uart0_pins[] = { 16, 20 }; 1706e08d6bbSMika Westerberg static const unsigned southwest_uart1_pins[] = { 15, 16, 18, 20 }; 1716e08d6bbSMika Westerberg static const unsigned southwest_uart2_pins[] = { 17, 19, 21, 22 }; 1726e08d6bbSMika Westerberg static const unsigned southwest_i2c0_pins[] = { 61, 65 }; 1736e08d6bbSMika Westerberg static const unsigned southwest_hda_pins[] = { 30, 31, 32, 33, 34, 35, 36, 37 }; 1746e08d6bbSMika Westerberg static const unsigned southwest_lpe_pins[] = { 1756e08d6bbSMika Westerberg 30, 31, 32, 33, 34, 35, 36, 37, 92, 94, 96, 97, 1766e08d6bbSMika Westerberg }; 1776e08d6bbSMika Westerberg static const unsigned southwest_i2c1_pins[] = { 60, 63 }; 1786e08d6bbSMika Westerberg static const unsigned southwest_i2c2_pins[] = { 62, 66 }; 1796e08d6bbSMika Westerberg static const unsigned southwest_i2c3_pins[] = { 64, 67 }; 1806e08d6bbSMika Westerberg static const unsigned southwest_i2c4_pins[] = { 46, 50 }; 1816e08d6bbSMika Westerberg static const unsigned southwest_i2c5_pins[] = { 45, 48 }; 1826e08d6bbSMika Westerberg static const unsigned southwest_i2c6_pins[] = { 47, 51 }; 1836e08d6bbSMika Westerberg static const unsigned southwest_i2c_nfc_pins[] = { 49, 52 }; 1846e08d6bbSMika Westerberg static const unsigned southwest_spi3_pins[] = { 76, 79, 80, 81, 82 }; 1856e08d6bbSMika Westerberg 18636ad7b24SAndy Shevchenko /* Some of LPE I2S TXD pins need to have OE inversion set */ 18736ad7b24SAndy Shevchenko static const unsigned int southwest_lpe_altfuncs[] = { 18836ad7b24SAndy Shevchenko PINMODE(1, 1), PINMODE(1, 0), PINMODE(1, 0), PINMODE(1, 0), /* 30, 31, 32, 33 */ 18936ad7b24SAndy Shevchenko PINMODE(1, 1), PINMODE(1, 0), PINMODE(1, 0), PINMODE(1, 0), /* 34, 35, 36, 37 */ 19036ad7b24SAndy Shevchenko PINMODE(1, 0), PINMODE(1, 0), PINMODE(1, 0), PINMODE(1, 1), /* 92, 94, 96, 97 */ 1916e08d6bbSMika Westerberg }; 1926e08d6bbSMika Westerberg 1936e08d6bbSMika Westerberg /* 1946e08d6bbSMika Westerberg * Two spi3 chipselects are available in different mode than the main spi3 19536ad7b24SAndy Shevchenko * functionality, which is using mode 2. 1966e08d6bbSMika Westerberg */ 19736ad7b24SAndy Shevchenko static const unsigned int southwest_spi3_altfuncs[] = { 19836ad7b24SAndy Shevchenko PINMODE(3, 0), PINMODE(2, 0), PINMODE(3, 0), PINMODE(2, 0), /* 76, 79, 80, 81 */ 19936ad7b24SAndy Shevchenko PINMODE(2, 0), /* 82 */ 2006e08d6bbSMika Westerberg }; 2016e08d6bbSMika Westerberg 20236ad7b24SAndy Shevchenko static const struct intel_pingroup southwest_groups[] = { 20336ad7b24SAndy Shevchenko PIN_GROUP("uart0_grp", southwest_uart0_pins, PINMODE(2, 0)), 20436ad7b24SAndy Shevchenko PIN_GROUP("uart1_grp", southwest_uart1_pins, PINMODE(1, 0)), 20536ad7b24SAndy Shevchenko PIN_GROUP("uart2_grp", southwest_uart2_pins, PINMODE(1, 0)), 20636ad7b24SAndy Shevchenko PIN_GROUP("hda_grp", southwest_hda_pins, PINMODE(2, 0)), 20736ad7b24SAndy Shevchenko PIN_GROUP("i2c0_grp", southwest_i2c0_pins, PINMODE(1, 1)), 20836ad7b24SAndy Shevchenko PIN_GROUP("i2c1_grp", southwest_i2c1_pins, PINMODE(1, 1)), 20936ad7b24SAndy Shevchenko PIN_GROUP("i2c2_grp", southwest_i2c2_pins, PINMODE(1, 1)), 21036ad7b24SAndy Shevchenko PIN_GROUP("i2c3_grp", southwest_i2c3_pins, PINMODE(1, 1)), 21136ad7b24SAndy Shevchenko PIN_GROUP("i2c4_grp", southwest_i2c4_pins, PINMODE(1, 1)), 21236ad7b24SAndy Shevchenko PIN_GROUP("i2c5_grp", southwest_i2c5_pins, PINMODE(1, 1)), 21336ad7b24SAndy Shevchenko PIN_GROUP("i2c6_grp", southwest_i2c6_pins, PINMODE(1, 1)), 21436ad7b24SAndy Shevchenko PIN_GROUP("i2c_nfc_grp", southwest_i2c_nfc_pins, PINMODE(2, 1)), 21536ad7b24SAndy Shevchenko PIN_GROUP("lpe_grp", southwest_lpe_pins, southwest_lpe_altfuncs), 21636ad7b24SAndy Shevchenko PIN_GROUP("spi3_grp", southwest_spi3_pins, southwest_spi3_altfuncs), 2176e08d6bbSMika Westerberg }; 2186e08d6bbSMika Westerberg 2196e08d6bbSMika Westerberg static const char * const southwest_uart0_groups[] = { "uart0_grp" }; 2206e08d6bbSMika Westerberg static const char * const southwest_uart1_groups[] = { "uart1_grp" }; 2216e08d6bbSMika Westerberg static const char * const southwest_uart2_groups[] = { "uart2_grp" }; 2226e08d6bbSMika Westerberg static const char * const southwest_hda_groups[] = { "hda_grp" }; 2236e08d6bbSMika Westerberg static const char * const southwest_lpe_groups[] = { "lpe_grp" }; 2246e08d6bbSMika Westerberg static const char * const southwest_i2c0_groups[] = { "i2c0_grp" }; 2256e08d6bbSMika Westerberg static const char * const southwest_i2c1_groups[] = { "i2c1_grp" }; 2266e08d6bbSMika Westerberg static const char * const southwest_i2c2_groups[] = { "i2c2_grp" }; 2276e08d6bbSMika Westerberg static const char * const southwest_i2c3_groups[] = { "i2c3_grp" }; 2286e08d6bbSMika Westerberg static const char * const southwest_i2c4_groups[] = { "i2c4_grp" }; 2296e08d6bbSMika Westerberg static const char * const southwest_i2c5_groups[] = { "i2c5_grp" }; 2306e08d6bbSMika Westerberg static const char * const southwest_i2c6_groups[] = { "i2c6_grp" }; 2316e08d6bbSMika Westerberg static const char * const southwest_i2c_nfc_groups[] = { "i2c_nfc_grp" }; 2326e08d6bbSMika Westerberg static const char * const southwest_spi3_groups[] = { "spi3_grp" }; 2336e08d6bbSMika Westerberg 2346e08d6bbSMika Westerberg /* 2356e08d6bbSMika Westerberg * Only do pinmuxing for certain LPSS devices for now. Rest of the pins are 2366e08d6bbSMika Westerberg * enabled only as GPIOs. 2376e08d6bbSMika Westerberg */ 2385458b7ceSAndy Shevchenko static const struct intel_function southwest_functions[] = { 2396e08d6bbSMika Westerberg FUNCTION("uart0", southwest_uart0_groups), 2406e08d6bbSMika Westerberg FUNCTION("uart1", southwest_uart1_groups), 2416e08d6bbSMika Westerberg FUNCTION("uart2", southwest_uart2_groups), 2426e08d6bbSMika Westerberg FUNCTION("hda", southwest_hda_groups), 2436e08d6bbSMika Westerberg FUNCTION("lpe", southwest_lpe_groups), 2446e08d6bbSMika Westerberg FUNCTION("i2c0", southwest_i2c0_groups), 2456e08d6bbSMika Westerberg FUNCTION("i2c1", southwest_i2c1_groups), 2466e08d6bbSMika Westerberg FUNCTION("i2c2", southwest_i2c2_groups), 2476e08d6bbSMika Westerberg FUNCTION("i2c3", southwest_i2c3_groups), 2486e08d6bbSMika Westerberg FUNCTION("i2c4", southwest_i2c4_groups), 2496e08d6bbSMika Westerberg FUNCTION("i2c5", southwest_i2c5_groups), 2506e08d6bbSMika Westerberg FUNCTION("i2c6", southwest_i2c6_groups), 2516e08d6bbSMika Westerberg FUNCTION("i2c_nfc", southwest_i2c_nfc_groups), 2526e08d6bbSMika Westerberg FUNCTION("spi3", southwest_spi3_groups), 2536e08d6bbSMika Westerberg }; 2546e08d6bbSMika Westerberg 25536ad7b24SAndy Shevchenko static const struct intel_padgroup southwest_gpps[] = { 25636ad7b24SAndy Shevchenko CHV_GPP(0, 7), 25736ad7b24SAndy Shevchenko CHV_GPP(15, 22), 25836ad7b24SAndy Shevchenko CHV_GPP(30, 37), 25936ad7b24SAndy Shevchenko CHV_GPP(45, 52), 26036ad7b24SAndy Shevchenko CHV_GPP(60, 67), 26136ad7b24SAndy Shevchenko CHV_GPP(75, 82), 26236ad7b24SAndy Shevchenko CHV_GPP(90, 97), 2636e08d6bbSMika Westerberg }; 2646e08d6bbSMika Westerberg 265293428f9SAndy Shevchenko /* 266293428f9SAndy Shevchenko * Southwest community can generate GPIO interrupts only for the first 8 267293428f9SAndy Shevchenko * interrupts. The upper half (8-15) can only be used to trigger GPEs. 268293428f9SAndy Shevchenko */ 269293428f9SAndy Shevchenko static const struct intel_community southwest_communities[] = { 270293428f9SAndy Shevchenko CHV_COMMUNITY(southwest_gpps, 8, 0x91), 271293428f9SAndy Shevchenko }; 272293428f9SAndy Shevchenko 273293428f9SAndy Shevchenko static const struct intel_pinctrl_soc_data southwest_soc_data = { 2746e08d6bbSMika Westerberg .uid = "1", 2756e08d6bbSMika Westerberg .pins = southwest_pins, 2766e08d6bbSMika Westerberg .npins = ARRAY_SIZE(southwest_pins), 2776e08d6bbSMika Westerberg .groups = southwest_groups, 2786e08d6bbSMika Westerberg .ngroups = ARRAY_SIZE(southwest_groups), 2796e08d6bbSMika Westerberg .functions = southwest_functions, 2806e08d6bbSMika Westerberg .nfunctions = ARRAY_SIZE(southwest_functions), 281293428f9SAndy Shevchenko .communities = southwest_communities, 282293428f9SAndy Shevchenko .ncommunities = ARRAY_SIZE(southwest_communities), 2836e08d6bbSMika Westerberg }; 2846e08d6bbSMika Westerberg 2856e08d6bbSMika Westerberg static const struct pinctrl_pin_desc north_pins[] = { 2866e08d6bbSMika Westerberg PINCTRL_PIN(0, "GPIO_DFX_0"), 2876e08d6bbSMika Westerberg PINCTRL_PIN(1, "GPIO_DFX_3"), 2886e08d6bbSMika Westerberg PINCTRL_PIN(2, "GPIO_DFX_7"), 2896e08d6bbSMika Westerberg PINCTRL_PIN(3, "GPIO_DFX_1"), 2906e08d6bbSMika Westerberg PINCTRL_PIN(4, "GPIO_DFX_5"), 2916e08d6bbSMika Westerberg PINCTRL_PIN(5, "GPIO_DFX_4"), 2926e08d6bbSMika Westerberg PINCTRL_PIN(6, "GPIO_DFX_8"), 2936e08d6bbSMika Westerberg PINCTRL_PIN(7, "GPIO_DFX_2"), 2946e08d6bbSMika Westerberg PINCTRL_PIN(8, "GPIO_DFX_6"), 2956e08d6bbSMika Westerberg 2966e08d6bbSMika Westerberg PINCTRL_PIN(15, "GPIO_SUS0"), 2976e08d6bbSMika Westerberg PINCTRL_PIN(16, "SEC_GPIO_SUS10"), 2986e08d6bbSMika Westerberg PINCTRL_PIN(17, "GPIO_SUS3"), 2996e08d6bbSMika Westerberg PINCTRL_PIN(18, "GPIO_SUS7"), 3006e08d6bbSMika Westerberg PINCTRL_PIN(19, "GPIO_SUS1"), 3016e08d6bbSMika Westerberg PINCTRL_PIN(20, "GPIO_SUS5"), 3026e08d6bbSMika Westerberg PINCTRL_PIN(21, "SEC_GPIO_SUS11"), 3036e08d6bbSMika Westerberg PINCTRL_PIN(22, "GPIO_SUS4"), 3046e08d6bbSMika Westerberg PINCTRL_PIN(23, "SEC_GPIO_SUS8"), 3056e08d6bbSMika Westerberg PINCTRL_PIN(24, "GPIO_SUS2"), 3066e08d6bbSMika Westerberg PINCTRL_PIN(25, "GPIO_SUS6"), 3076e08d6bbSMika Westerberg PINCTRL_PIN(26, "CX_PREQ_B"), 3086e08d6bbSMika Westerberg PINCTRL_PIN(27, "SEC_GPIO_SUS9"), 3096e08d6bbSMika Westerberg 3106e08d6bbSMika Westerberg PINCTRL_PIN(30, "TRST_B"), 3116e08d6bbSMika Westerberg PINCTRL_PIN(31, "TCK"), 3126e08d6bbSMika Westerberg PINCTRL_PIN(32, "PROCHOT_B"), 3136e08d6bbSMika Westerberg PINCTRL_PIN(33, "SVIDO_DATA"), 3146e08d6bbSMika Westerberg PINCTRL_PIN(34, "TMS"), 3156e08d6bbSMika Westerberg PINCTRL_PIN(35, "CX_PRDY_B_2"), 3166e08d6bbSMika Westerberg PINCTRL_PIN(36, "TDO_2"), 3176e08d6bbSMika Westerberg PINCTRL_PIN(37, "CX_PRDY_B"), 3186e08d6bbSMika Westerberg PINCTRL_PIN(38, "SVIDO_ALERT_B"), 3196e08d6bbSMika Westerberg PINCTRL_PIN(39, "TDO"), 3206e08d6bbSMika Westerberg PINCTRL_PIN(40, "SVIDO_CLK"), 3216e08d6bbSMika Westerberg PINCTRL_PIN(41, "TDI"), 3226e08d6bbSMika Westerberg 3236e08d6bbSMika Westerberg PINCTRL_PIN(45, "GP_CAMERASB_05"), 3246e08d6bbSMika Westerberg PINCTRL_PIN(46, "GP_CAMERASB_02"), 3256e08d6bbSMika Westerberg PINCTRL_PIN(47, "GP_CAMERASB_08"), 3266e08d6bbSMika Westerberg PINCTRL_PIN(48, "GP_CAMERASB_00"), 3276e08d6bbSMika Westerberg PINCTRL_PIN(49, "GP_CAMERASB_06"), 3286e08d6bbSMika Westerberg PINCTRL_PIN(50, "GP_CAMERASB_10"), 3296e08d6bbSMika Westerberg PINCTRL_PIN(51, "GP_CAMERASB_03"), 3306e08d6bbSMika Westerberg PINCTRL_PIN(52, "GP_CAMERASB_09"), 3316e08d6bbSMika Westerberg PINCTRL_PIN(53, "GP_CAMERASB_01"), 3326e08d6bbSMika Westerberg PINCTRL_PIN(54, "GP_CAMERASB_07"), 3336e08d6bbSMika Westerberg PINCTRL_PIN(55, "GP_CAMERASB_11"), 3346e08d6bbSMika Westerberg PINCTRL_PIN(56, "GP_CAMERASB_04"), 3356e08d6bbSMika Westerberg 3366e08d6bbSMika Westerberg PINCTRL_PIN(60, "PANEL0_BKLTEN"), 3376e08d6bbSMika Westerberg PINCTRL_PIN(61, "HV_DDI0_HPD"), 3386e08d6bbSMika Westerberg PINCTRL_PIN(62, "HV_DDI2_DDC_SDA"), 3396e08d6bbSMika Westerberg PINCTRL_PIN(63, "PANEL1_BKLTCTL"), 3406e08d6bbSMika Westerberg PINCTRL_PIN(64, "HV_DDI1_HPD"), 3416e08d6bbSMika Westerberg PINCTRL_PIN(65, "PANEL0_BKLTCTL"), 3426e08d6bbSMika Westerberg PINCTRL_PIN(66, "HV_DDI0_DDC_SDA"), 3436e08d6bbSMika Westerberg PINCTRL_PIN(67, "HV_DDI2_DDC_SCL"), 3446e08d6bbSMika Westerberg PINCTRL_PIN(68, "HV_DDI2_HPD"), 3456e08d6bbSMika Westerberg PINCTRL_PIN(69, "PANEL1_VDDEN"), 3466e08d6bbSMika Westerberg PINCTRL_PIN(70, "PANEL1_BKLTEN"), 3476e08d6bbSMika Westerberg PINCTRL_PIN(71, "HV_DDI0_DDC_SCL"), 3486e08d6bbSMika Westerberg PINCTRL_PIN(72, "PANEL0_VDDEN"), 3496e08d6bbSMika Westerberg }; 3506e08d6bbSMika Westerberg 35136ad7b24SAndy Shevchenko static const struct intel_padgroup north_gpps[] = { 35236ad7b24SAndy Shevchenko CHV_GPP(0, 8), 35336ad7b24SAndy Shevchenko CHV_GPP(15, 27), 35436ad7b24SAndy Shevchenko CHV_GPP(30, 41), 35536ad7b24SAndy Shevchenko CHV_GPP(45, 56), 35636ad7b24SAndy Shevchenko CHV_GPP(60, 72), 3576e08d6bbSMika Westerberg }; 3586e08d6bbSMika Westerberg 359293428f9SAndy Shevchenko /* 360293428f9SAndy Shevchenko * North community can generate GPIO interrupts only for the first 8 361293428f9SAndy Shevchenko * interrupts. The upper half (8-15) can only be used to trigger GPEs. 362293428f9SAndy Shevchenko */ 363293428f9SAndy Shevchenko static const struct intel_community north_communities[] = { 364293428f9SAndy Shevchenko CHV_COMMUNITY(north_gpps, 8, 0x92), 365293428f9SAndy Shevchenko }; 366293428f9SAndy Shevchenko 367293428f9SAndy Shevchenko static const struct intel_pinctrl_soc_data north_soc_data = { 3686e08d6bbSMika Westerberg .uid = "2", 3696e08d6bbSMika Westerberg .pins = north_pins, 3706e08d6bbSMika Westerberg .npins = ARRAY_SIZE(north_pins), 371293428f9SAndy Shevchenko .communities = north_communities, 372293428f9SAndy Shevchenko .ncommunities = ARRAY_SIZE(north_communities), 3736e08d6bbSMika Westerberg }; 3746e08d6bbSMika Westerberg 3756e08d6bbSMika Westerberg static const struct pinctrl_pin_desc east_pins[] = { 3766e08d6bbSMika Westerberg PINCTRL_PIN(0, "PMU_SLP_S3_B"), 3776e08d6bbSMika Westerberg PINCTRL_PIN(1, "PMU_BATLOW_B"), 3786e08d6bbSMika Westerberg PINCTRL_PIN(2, "SUS_STAT_B"), 3796e08d6bbSMika Westerberg PINCTRL_PIN(3, "PMU_SLP_S0IX_B"), 3806e08d6bbSMika Westerberg PINCTRL_PIN(4, "PMU_AC_PRESENT"), 3816e08d6bbSMika Westerberg PINCTRL_PIN(5, "PMU_PLTRST_B"), 3826e08d6bbSMika Westerberg PINCTRL_PIN(6, "PMU_SUSCLK"), 3836e08d6bbSMika Westerberg PINCTRL_PIN(7, "PMU_SLP_LAN_B"), 3846e08d6bbSMika Westerberg PINCTRL_PIN(8, "PMU_PWRBTN_B"), 3856e08d6bbSMika Westerberg PINCTRL_PIN(9, "PMU_SLP_S4_B"), 3866e08d6bbSMika Westerberg PINCTRL_PIN(10, "PMU_WAKE_B"), 3876e08d6bbSMika Westerberg PINCTRL_PIN(11, "PMU_WAKE_LAN_B"), 3886e08d6bbSMika Westerberg 3896e08d6bbSMika Westerberg PINCTRL_PIN(15, "MF_ISH_GPIO_3"), 3906e08d6bbSMika Westerberg PINCTRL_PIN(16, "MF_ISH_GPIO_7"), 3916e08d6bbSMika Westerberg PINCTRL_PIN(17, "MF_ISH_I2C1_SCL"), 3926e08d6bbSMika Westerberg PINCTRL_PIN(18, "MF_ISH_GPIO_1"), 3936e08d6bbSMika Westerberg PINCTRL_PIN(19, "MF_ISH_GPIO_5"), 3946e08d6bbSMika Westerberg PINCTRL_PIN(20, "MF_ISH_GPIO_9"), 3956e08d6bbSMika Westerberg PINCTRL_PIN(21, "MF_ISH_GPIO_0"), 3966e08d6bbSMika Westerberg PINCTRL_PIN(22, "MF_ISH_GPIO_4"), 3976e08d6bbSMika Westerberg PINCTRL_PIN(23, "MF_ISH_GPIO_8"), 3986e08d6bbSMika Westerberg PINCTRL_PIN(24, "MF_ISH_GPIO_2"), 3996e08d6bbSMika Westerberg PINCTRL_PIN(25, "MF_ISH_GPIO_6"), 4006e08d6bbSMika Westerberg PINCTRL_PIN(26, "MF_ISH_I2C1_SDA"), 4016e08d6bbSMika Westerberg }; 4026e08d6bbSMika Westerberg 40336ad7b24SAndy Shevchenko static const struct intel_padgroup east_gpps[] = { 40436ad7b24SAndy Shevchenko CHV_GPP(0, 11), 40536ad7b24SAndy Shevchenko CHV_GPP(15, 26), 4066e08d6bbSMika Westerberg }; 4076e08d6bbSMika Westerberg 408293428f9SAndy Shevchenko static const struct intel_community east_communities[] = { 409293428f9SAndy Shevchenko CHV_COMMUNITY(east_gpps, 16, 0x93), 410293428f9SAndy Shevchenko }; 411293428f9SAndy Shevchenko 412293428f9SAndy Shevchenko static const struct intel_pinctrl_soc_data east_soc_data = { 4136e08d6bbSMika Westerberg .uid = "3", 4146e08d6bbSMika Westerberg .pins = east_pins, 4156e08d6bbSMika Westerberg .npins = ARRAY_SIZE(east_pins), 416293428f9SAndy Shevchenko .communities = east_communities, 417293428f9SAndy Shevchenko .ncommunities = ARRAY_SIZE(east_communities), 4186e08d6bbSMika Westerberg }; 4196e08d6bbSMika Westerberg 4206e08d6bbSMika Westerberg static const struct pinctrl_pin_desc southeast_pins[] = { 4216e08d6bbSMika Westerberg PINCTRL_PIN(0, "MF_PLT_CLK0"), 4226e08d6bbSMika Westerberg PINCTRL_PIN(1, "PWM1"), 4236e08d6bbSMika Westerberg PINCTRL_PIN(2, "MF_PLT_CLK1"), 4246e08d6bbSMika Westerberg PINCTRL_PIN(3, "MF_PLT_CLK4"), 4256e08d6bbSMika Westerberg PINCTRL_PIN(4, "MF_PLT_CLK3"), 4266e08d6bbSMika Westerberg PINCTRL_PIN(5, "PWM0"), 4276e08d6bbSMika Westerberg PINCTRL_PIN(6, "MF_PLT_CLK5"), 4286e08d6bbSMika Westerberg PINCTRL_PIN(7, "MF_PLT_CLK2"), 4296e08d6bbSMika Westerberg 4306e08d6bbSMika Westerberg PINCTRL_PIN(15, "SDMMC2_D3_CD_B"), 4316e08d6bbSMika Westerberg PINCTRL_PIN(16, "SDMMC1_CLK"), 4326e08d6bbSMika Westerberg PINCTRL_PIN(17, "SDMMC1_D0"), 4336e08d6bbSMika Westerberg PINCTRL_PIN(18, "SDMMC2_D1"), 4346e08d6bbSMika Westerberg PINCTRL_PIN(19, "SDMMC2_CLK"), 4356e08d6bbSMika Westerberg PINCTRL_PIN(20, "SDMMC1_D2"), 4366e08d6bbSMika Westerberg PINCTRL_PIN(21, "SDMMC2_D2"), 4376e08d6bbSMika Westerberg PINCTRL_PIN(22, "SDMMC2_CMD"), 4386e08d6bbSMika Westerberg PINCTRL_PIN(23, "SDMMC1_CMD"), 4396e08d6bbSMika Westerberg PINCTRL_PIN(24, "SDMMC1_D1"), 4406e08d6bbSMika Westerberg PINCTRL_PIN(25, "SDMMC2_D0"), 4416e08d6bbSMika Westerberg PINCTRL_PIN(26, "SDMMC1_D3_CD_B"), 4426e08d6bbSMika Westerberg 4436e08d6bbSMika Westerberg PINCTRL_PIN(30, "SDMMC3_D1"), 4446e08d6bbSMika Westerberg PINCTRL_PIN(31, "SDMMC3_CLK"), 4456e08d6bbSMika Westerberg PINCTRL_PIN(32, "SDMMC3_D3"), 4466e08d6bbSMika Westerberg PINCTRL_PIN(33, "SDMMC3_D2"), 4476e08d6bbSMika Westerberg PINCTRL_PIN(34, "SDMMC3_CMD"), 4486e08d6bbSMika Westerberg PINCTRL_PIN(35, "SDMMC3_D0"), 4496e08d6bbSMika Westerberg 4506e08d6bbSMika Westerberg PINCTRL_PIN(45, "MF_LPC_AD2"), 4516e08d6bbSMika Westerberg PINCTRL_PIN(46, "LPC_CLKRUNB"), 4526e08d6bbSMika Westerberg PINCTRL_PIN(47, "MF_LPC_AD0"), 4536e08d6bbSMika Westerberg PINCTRL_PIN(48, "LPC_FRAMEB"), 4546e08d6bbSMika Westerberg PINCTRL_PIN(49, "MF_LPC_CLKOUT1"), 4556e08d6bbSMika Westerberg PINCTRL_PIN(50, "MF_LPC_AD3"), 4566e08d6bbSMika Westerberg PINCTRL_PIN(51, "MF_LPC_CLKOUT0"), 4576e08d6bbSMika Westerberg PINCTRL_PIN(52, "MF_LPC_AD1"), 4586e08d6bbSMika Westerberg 4596e08d6bbSMika Westerberg PINCTRL_PIN(60, "SPI1_MISO"), 4606e08d6bbSMika Westerberg PINCTRL_PIN(61, "SPI1_CSO_B"), 4616e08d6bbSMika Westerberg PINCTRL_PIN(62, "SPI1_CLK"), 4626e08d6bbSMika Westerberg PINCTRL_PIN(63, "MMC1_D6"), 4636e08d6bbSMika Westerberg PINCTRL_PIN(64, "SPI1_MOSI"), 4646e08d6bbSMika Westerberg PINCTRL_PIN(65, "MMC1_D5"), 4656e08d6bbSMika Westerberg PINCTRL_PIN(66, "SPI1_CS1_B"), 4666e08d6bbSMika Westerberg PINCTRL_PIN(67, "MMC1_D4_SD_WE"), 4676e08d6bbSMika Westerberg PINCTRL_PIN(68, "MMC1_D7"), 4686e08d6bbSMika Westerberg PINCTRL_PIN(69, "MMC1_RCLK"), 4696e08d6bbSMika Westerberg 4706e08d6bbSMika Westerberg PINCTRL_PIN(75, "USB_OC1_B"), 4716e08d6bbSMika Westerberg PINCTRL_PIN(76, "PMU_RESETBUTTON_B"), 4726e08d6bbSMika Westerberg PINCTRL_PIN(77, "GPIO_ALERT"), 4736e08d6bbSMika Westerberg PINCTRL_PIN(78, "SDMMC3_PWR_EN_B"), 4746e08d6bbSMika Westerberg PINCTRL_PIN(79, "ILB_SERIRQ"), 4756e08d6bbSMika Westerberg PINCTRL_PIN(80, "USB_OC0_B"), 4766e08d6bbSMika Westerberg PINCTRL_PIN(81, "SDMMC3_CD_B"), 4776e08d6bbSMika Westerberg PINCTRL_PIN(82, "SPKR"), 4786e08d6bbSMika Westerberg PINCTRL_PIN(83, "SUSPWRDNACK"), 4796e08d6bbSMika Westerberg PINCTRL_PIN(84, "SPARE_PIN"), 4806e08d6bbSMika Westerberg PINCTRL_PIN(85, "SDMMC3_1P8_EN"), 4816e08d6bbSMika Westerberg }; 4826e08d6bbSMika Westerberg 4836e08d6bbSMika Westerberg static const unsigned southeast_pwm0_pins[] = { 5 }; 4846e08d6bbSMika Westerberg static const unsigned southeast_pwm1_pins[] = { 1 }; 4856e08d6bbSMika Westerberg static const unsigned southeast_sdmmc1_pins[] = { 4866e08d6bbSMika Westerberg 16, 17, 20, 23, 24, 26, 63, 65, 67, 68, 69, 4876e08d6bbSMika Westerberg }; 4886e08d6bbSMika Westerberg static const unsigned southeast_sdmmc2_pins[] = { 15, 18, 19, 21, 22, 25 }; 4896e08d6bbSMika Westerberg static const unsigned southeast_sdmmc3_pins[] = { 4906e08d6bbSMika Westerberg 30, 31, 32, 33, 34, 35, 78, 81, 85, 4916e08d6bbSMika Westerberg }; 4926e08d6bbSMika Westerberg static const unsigned southeast_spi1_pins[] = { 60, 61, 62, 64, 66 }; 4936e08d6bbSMika Westerberg static const unsigned southeast_spi2_pins[] = { 2, 3, 4, 6, 7 }; 4946e08d6bbSMika Westerberg 49536ad7b24SAndy Shevchenko static const struct intel_pingroup southeast_groups[] = { 49636ad7b24SAndy Shevchenko PIN_GROUP("pwm0_grp", southeast_pwm0_pins, PINMODE(1, 0)), 49736ad7b24SAndy Shevchenko PIN_GROUP("pwm1_grp", southeast_pwm1_pins, PINMODE(1, 0)), 49836ad7b24SAndy Shevchenko PIN_GROUP("sdmmc1_grp", southeast_sdmmc1_pins, PINMODE(1, 0)), 49936ad7b24SAndy Shevchenko PIN_GROUP("sdmmc2_grp", southeast_sdmmc2_pins, PINMODE(1, 0)), 50036ad7b24SAndy Shevchenko PIN_GROUP("sdmmc3_grp", southeast_sdmmc3_pins, PINMODE(1, 0)), 50136ad7b24SAndy Shevchenko PIN_GROUP("spi1_grp", southeast_spi1_pins, PINMODE(1, 0)), 50236ad7b24SAndy Shevchenko PIN_GROUP("spi2_grp", southeast_spi2_pins, PINMODE(4, 0)), 5036e08d6bbSMika Westerberg }; 5046e08d6bbSMika Westerberg 5056e08d6bbSMika Westerberg static const char * const southeast_pwm0_groups[] = { "pwm0_grp" }; 5066e08d6bbSMika Westerberg static const char * const southeast_pwm1_groups[] = { "pwm1_grp" }; 5076e08d6bbSMika Westerberg static const char * const southeast_sdmmc1_groups[] = { "sdmmc1_grp" }; 5086e08d6bbSMika Westerberg static const char * const southeast_sdmmc2_groups[] = { "sdmmc2_grp" }; 5096e08d6bbSMika Westerberg static const char * const southeast_sdmmc3_groups[] = { "sdmmc3_grp" }; 5106e08d6bbSMika Westerberg static const char * const southeast_spi1_groups[] = { "spi1_grp" }; 5116e08d6bbSMika Westerberg static const char * const southeast_spi2_groups[] = { "spi2_grp" }; 5126e08d6bbSMika Westerberg 5135458b7ceSAndy Shevchenko static const struct intel_function southeast_functions[] = { 5146e08d6bbSMika Westerberg FUNCTION("pwm0", southeast_pwm0_groups), 5156e08d6bbSMika Westerberg FUNCTION("pwm1", southeast_pwm1_groups), 5166e08d6bbSMika Westerberg FUNCTION("sdmmc1", southeast_sdmmc1_groups), 5176e08d6bbSMika Westerberg FUNCTION("sdmmc2", southeast_sdmmc2_groups), 5186e08d6bbSMika Westerberg FUNCTION("sdmmc3", southeast_sdmmc3_groups), 5196e08d6bbSMika Westerberg FUNCTION("spi1", southeast_spi1_groups), 5206e08d6bbSMika Westerberg FUNCTION("spi2", southeast_spi2_groups), 5216e08d6bbSMika Westerberg }; 5226e08d6bbSMika Westerberg 52336ad7b24SAndy Shevchenko static const struct intel_padgroup southeast_gpps[] = { 52436ad7b24SAndy Shevchenko CHV_GPP(0, 7), 52536ad7b24SAndy Shevchenko CHV_GPP(15, 26), 52636ad7b24SAndy Shevchenko CHV_GPP(30, 35), 52736ad7b24SAndy Shevchenko CHV_GPP(45, 52), 52836ad7b24SAndy Shevchenko CHV_GPP(60, 69), 52936ad7b24SAndy Shevchenko CHV_GPP(75, 85), 5306e08d6bbSMika Westerberg }; 5316e08d6bbSMika Westerberg 532293428f9SAndy Shevchenko static const struct intel_community southeast_communities[] = { 533293428f9SAndy Shevchenko CHV_COMMUNITY(southeast_gpps, 16, 0x94), 534293428f9SAndy Shevchenko }; 535293428f9SAndy Shevchenko 536293428f9SAndy Shevchenko static const struct intel_pinctrl_soc_data southeast_soc_data = { 5376e08d6bbSMika Westerberg .uid = "4", 5386e08d6bbSMika Westerberg .pins = southeast_pins, 5396e08d6bbSMika Westerberg .npins = ARRAY_SIZE(southeast_pins), 5406e08d6bbSMika Westerberg .groups = southeast_groups, 5416e08d6bbSMika Westerberg .ngroups = ARRAY_SIZE(southeast_groups), 5426e08d6bbSMika Westerberg .functions = southeast_functions, 5436e08d6bbSMika Westerberg .nfunctions = ARRAY_SIZE(southeast_functions), 544293428f9SAndy Shevchenko .communities = southeast_communities, 545293428f9SAndy Shevchenko .ncommunities = ARRAY_SIZE(southeast_communities), 5466e08d6bbSMika Westerberg }; 5476e08d6bbSMika Westerberg 548293428f9SAndy Shevchenko static const struct intel_pinctrl_soc_data *chv_soc_data[] = { 549293428f9SAndy Shevchenko &southwest_soc_data, 550293428f9SAndy Shevchenko &north_soc_data, 551293428f9SAndy Shevchenko &east_soc_data, 552293428f9SAndy Shevchenko &southeast_soc_data, 553293428f9SAndy Shevchenko NULL 5546e08d6bbSMika Westerberg }; 5556e08d6bbSMika Westerberg 5560bd50d71SDan O'Donovan /* 5570bd50d71SDan O'Donovan * Lock to serialize register accesses 5580bd50d71SDan O'Donovan * 5590bd50d71SDan O'Donovan * Due to a silicon issue, a shared lock must be used to prevent 5600bd50d71SDan O'Donovan * concurrent accesses across the 4 GPIO controllers. 5610bd50d71SDan O'Donovan * 5620bd50d71SDan O'Donovan * See Intel Atom Z8000 Processor Series Specification Update (Rev. 005), 5630bd50d71SDan O'Donovan * errata #CHT34, for further information. 5640bd50d71SDan O'Donovan */ 5650bd50d71SDan O'Donovan static DEFINE_RAW_SPINLOCK(chv_lock); 5660bd50d71SDan O'Donovan 5673ea2e2caSAndy Shevchenko static u32 chv_pctrl_readl(struct intel_pinctrl *pctrl, unsigned int offset) 56899fd6512SAndy Shevchenko { 569293428f9SAndy Shevchenko const struct intel_community *community = &pctrl->communities[0]; 570293428f9SAndy Shevchenko 571293428f9SAndy Shevchenko return readl(community->regs + offset); 57299fd6512SAndy Shevchenko } 57399fd6512SAndy Shevchenko 5743ea2e2caSAndy Shevchenko static void chv_pctrl_writel(struct intel_pinctrl *pctrl, unsigned int offset, u32 value) 57599fd6512SAndy Shevchenko { 576293428f9SAndy Shevchenko const struct intel_community *community = &pctrl->communities[0]; 577293428f9SAndy Shevchenko void __iomem *reg = community->regs + offset; 57899fd6512SAndy Shevchenko 57999fd6512SAndy Shevchenko /* Write and simple read back to confirm the bus transferring done */ 58099fd6512SAndy Shevchenko writel(value, reg); 58199fd6512SAndy Shevchenko readl(reg); 58299fd6512SAndy Shevchenko } 58399fd6512SAndy Shevchenko 5843ea2e2caSAndy Shevchenko static void __iomem *chv_padreg(struct intel_pinctrl *pctrl, unsigned int offset, 5854e737af8SAndy Shevchenko unsigned int reg) 5866e08d6bbSMika Westerberg { 587293428f9SAndy Shevchenko const struct intel_community *community = &pctrl->communities[0]; 5884e737af8SAndy Shevchenko unsigned int family_no = offset / MAX_FAMILY_PAD_GPIO_NO; 5894e737af8SAndy Shevchenko unsigned int pad_no = offset % MAX_FAMILY_PAD_GPIO_NO; 5906e08d6bbSMika Westerberg 591293428f9SAndy Shevchenko offset = FAMILY_PAD_REGS_SIZE * family_no + GPIO_REGS_SIZE * pad_no; 5926e08d6bbSMika Westerberg 593293428f9SAndy Shevchenko return community->pad_regs + offset + reg; 5946e08d6bbSMika Westerberg } 5956e08d6bbSMika Westerberg 5963ea2e2caSAndy Shevchenko static u32 chv_readl(struct intel_pinctrl *pctrl, unsigned int pin, unsigned int offset) 5974e7293e3SAndy Shevchenko { 5984e7293e3SAndy Shevchenko return readl(chv_padreg(pctrl, pin, offset)); 5994e7293e3SAndy Shevchenko } 6004e7293e3SAndy Shevchenko 6013ea2e2caSAndy Shevchenko static void chv_writel(struct intel_pinctrl *pctrl, unsigned int pin, unsigned int offset, u32 value) 6026e08d6bbSMika Westerberg { 603bfc8a4baSAndy Shevchenko void __iomem *reg = chv_padreg(pctrl, pin, offset); 604bfc8a4baSAndy Shevchenko 605bfc8a4baSAndy Shevchenko /* Write and simple read back to confirm the bus transferring done */ 6066e08d6bbSMika Westerberg writel(value, reg); 6076e08d6bbSMika Westerberg readl(reg); 6086e08d6bbSMika Westerberg } 6096e08d6bbSMika Westerberg 6106e08d6bbSMika Westerberg /* When Pad Cfg is locked, driver can only change GPIOTXState or GPIORXState */ 6113ea2e2caSAndy Shevchenko static bool chv_pad_locked(struct intel_pinctrl *pctrl, unsigned int offset) 6126e08d6bbSMika Westerberg { 6134e7293e3SAndy Shevchenko return chv_readl(pctrl, offset, CHV_PADCTRL1) & CHV_PADCTRL1_CFGLOCK; 6146e08d6bbSMika Westerberg } 6156e08d6bbSMika Westerberg 6166e08d6bbSMika Westerberg static int chv_get_groups_count(struct pinctrl_dev *pctldev) 6176e08d6bbSMika Westerberg { 6183ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 6196e08d6bbSMika Westerberg 620293428f9SAndy Shevchenko return pctrl->soc->ngroups; 6216e08d6bbSMika Westerberg } 6226e08d6bbSMika Westerberg 6236e08d6bbSMika Westerberg static const char *chv_get_group_name(struct pinctrl_dev *pctldev, 6244e737af8SAndy Shevchenko unsigned int group) 6256e08d6bbSMika Westerberg { 6263ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 6276e08d6bbSMika Westerberg 628293428f9SAndy Shevchenko return pctrl->soc->groups[group].name; 6296e08d6bbSMika Westerberg } 6306e08d6bbSMika Westerberg 6314e737af8SAndy Shevchenko static int chv_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group, 6324e737af8SAndy Shevchenko const unsigned int **pins, unsigned int *npins) 6336e08d6bbSMika Westerberg { 6343ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 6356e08d6bbSMika Westerberg 636293428f9SAndy Shevchenko *pins = pctrl->soc->groups[group].pins; 637293428f9SAndy Shevchenko *npins = pctrl->soc->groups[group].npins; 6386e08d6bbSMika Westerberg return 0; 6396e08d6bbSMika Westerberg } 6406e08d6bbSMika Westerberg 6416e08d6bbSMika Westerberg static void chv_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, 6424e737af8SAndy Shevchenko unsigned int offset) 6436e08d6bbSMika Westerberg { 6443ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 6456e08d6bbSMika Westerberg unsigned long flags; 6466e08d6bbSMika Westerberg u32 ctrl0, ctrl1; 6476e08d6bbSMika Westerberg bool locked; 6486e08d6bbSMika Westerberg 6490bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 6506e08d6bbSMika Westerberg 6514e7293e3SAndy Shevchenko ctrl0 = chv_readl(pctrl, offset, CHV_PADCTRL0); 6524e7293e3SAndy Shevchenko ctrl1 = chv_readl(pctrl, offset, CHV_PADCTRL1); 6536e08d6bbSMika Westerberg locked = chv_pad_locked(pctrl, offset); 6546e08d6bbSMika Westerberg 6550bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 6566e08d6bbSMika Westerberg 6576e08d6bbSMika Westerberg if (ctrl0 & CHV_PADCTRL0_GPIOEN) { 6586e08d6bbSMika Westerberg seq_puts(s, "GPIO "); 6596e08d6bbSMika Westerberg } else { 6606e08d6bbSMika Westerberg u32 mode; 6616e08d6bbSMika Westerberg 6626e08d6bbSMika Westerberg mode = ctrl0 & CHV_PADCTRL0_PMODE_MASK; 6636e08d6bbSMika Westerberg mode >>= CHV_PADCTRL0_PMODE_SHIFT; 6646e08d6bbSMika Westerberg 6656e08d6bbSMika Westerberg seq_printf(s, "mode %d ", mode); 6666e08d6bbSMika Westerberg } 6676e08d6bbSMika Westerberg 668684373eaSMika Westerberg seq_printf(s, "0x%08x 0x%08x", ctrl0, ctrl1); 6696e08d6bbSMika Westerberg 6706e08d6bbSMika Westerberg if (locked) 6716e08d6bbSMika Westerberg seq_puts(s, " [LOCKED]"); 6726e08d6bbSMika Westerberg } 6736e08d6bbSMika Westerberg 6746e08d6bbSMika Westerberg static const struct pinctrl_ops chv_pinctrl_ops = { 6756e08d6bbSMika Westerberg .get_groups_count = chv_get_groups_count, 6766e08d6bbSMika Westerberg .get_group_name = chv_get_group_name, 6776e08d6bbSMika Westerberg .get_group_pins = chv_get_group_pins, 6786e08d6bbSMika Westerberg .pin_dbg_show = chv_pin_dbg_show, 6796e08d6bbSMika Westerberg }; 6806e08d6bbSMika Westerberg 6816e08d6bbSMika Westerberg static int chv_get_functions_count(struct pinctrl_dev *pctldev) 6826e08d6bbSMika Westerberg { 6833ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 6846e08d6bbSMika Westerberg 685293428f9SAndy Shevchenko return pctrl->soc->nfunctions; 6866e08d6bbSMika Westerberg } 6876e08d6bbSMika Westerberg 6886e08d6bbSMika Westerberg static const char *chv_get_function_name(struct pinctrl_dev *pctldev, 6894e737af8SAndy Shevchenko unsigned int function) 6906e08d6bbSMika Westerberg { 6913ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 6926e08d6bbSMika Westerberg 693293428f9SAndy Shevchenko return pctrl->soc->functions[function].name; 6946e08d6bbSMika Westerberg } 6956e08d6bbSMika Westerberg 6966e08d6bbSMika Westerberg static int chv_get_function_groups(struct pinctrl_dev *pctldev, 6974e737af8SAndy Shevchenko unsigned int function, 6986e08d6bbSMika Westerberg const char * const **groups, 6994e737af8SAndy Shevchenko unsigned int * const ngroups) 7006e08d6bbSMika Westerberg { 7013ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 7026e08d6bbSMika Westerberg 703293428f9SAndy Shevchenko *groups = pctrl->soc->functions[function].groups; 704293428f9SAndy Shevchenko *ngroups = pctrl->soc->functions[function].ngroups; 7056e08d6bbSMika Westerberg return 0; 7066e08d6bbSMika Westerberg } 7076e08d6bbSMika Westerberg 7084e737af8SAndy Shevchenko static int chv_pinmux_set_mux(struct pinctrl_dev *pctldev, 7094e737af8SAndy Shevchenko unsigned int function, unsigned int group) 7106e08d6bbSMika Westerberg { 7113ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 71236ad7b24SAndy Shevchenko const struct intel_pingroup *grp; 7136e08d6bbSMika Westerberg unsigned long flags; 7146e08d6bbSMika Westerberg int i; 7156e08d6bbSMika Westerberg 716293428f9SAndy Shevchenko grp = &pctrl->soc->groups[group]; 7176e08d6bbSMika Westerberg 7180bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 7196e08d6bbSMika Westerberg 7206e08d6bbSMika Westerberg /* Check first that the pad is not locked */ 7216e08d6bbSMika Westerberg for (i = 0; i < grp->npins; i++) { 7226e08d6bbSMika Westerberg if (chv_pad_locked(pctrl, grp->pins[i])) { 7236e08d6bbSMika Westerberg dev_warn(pctrl->dev, "unable to set mode for locked pin %u\n", 7246e08d6bbSMika Westerberg grp->pins[i]); 7250bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 7266e08d6bbSMika Westerberg return -EBUSY; 7276e08d6bbSMika Westerberg } 7286e08d6bbSMika Westerberg } 7296e08d6bbSMika Westerberg 7306e08d6bbSMika Westerberg for (i = 0; i < grp->npins; i++) { 7316e08d6bbSMika Westerberg int pin = grp->pins[i]; 73236ad7b24SAndy Shevchenko unsigned int mode; 73336ad7b24SAndy Shevchenko bool invert_oe; 7346e08d6bbSMika Westerberg u32 value; 7356e08d6bbSMika Westerberg 7366e08d6bbSMika Westerberg /* Check if there is pin-specific config */ 73736ad7b24SAndy Shevchenko if (grp->modes) 73836ad7b24SAndy Shevchenko mode = grp->modes[i]; 73936ad7b24SAndy Shevchenko else 74036ad7b24SAndy Shevchenko mode = grp->mode; 7416e08d6bbSMika Westerberg 74236ad7b24SAndy Shevchenko /* Extract OE inversion */ 74336ad7b24SAndy Shevchenko invert_oe = mode & PINMODE_INVERT_OE; 74436ad7b24SAndy Shevchenko mode &= ~PINMODE_INVERT_OE; 7456e08d6bbSMika Westerberg 7464e7293e3SAndy Shevchenko value = chv_readl(pctrl, pin, CHV_PADCTRL0); 7476e08d6bbSMika Westerberg /* Disable GPIO mode */ 7486e08d6bbSMika Westerberg value &= ~CHV_PADCTRL0_GPIOEN; 7496e08d6bbSMika Westerberg /* Set to desired mode */ 7506e08d6bbSMika Westerberg value &= ~CHV_PADCTRL0_PMODE_MASK; 75136ad7b24SAndy Shevchenko value |= mode << CHV_PADCTRL0_PMODE_SHIFT; 752bfc8a4baSAndy Shevchenko chv_writel(pctrl, pin, CHV_PADCTRL0, value); 7536e08d6bbSMika Westerberg 7546e08d6bbSMika Westerberg /* Update for invert_oe */ 7554e7293e3SAndy Shevchenko value = chv_readl(pctrl, pin, CHV_PADCTRL1) & ~CHV_PADCTRL1_INVRXTX_MASK; 75636ad7b24SAndy Shevchenko if (invert_oe) 7576e08d6bbSMika Westerberg value |= CHV_PADCTRL1_INVRXTX_TXENABLE; 758bfc8a4baSAndy Shevchenko chv_writel(pctrl, pin, CHV_PADCTRL1, value); 7596e08d6bbSMika Westerberg 7606e08d6bbSMika Westerberg dev_dbg(pctrl->dev, "configured pin %u mode %u OE %sinverted\n", 76136ad7b24SAndy Shevchenko pin, mode, invert_oe ? "" : "not "); 7626e08d6bbSMika Westerberg } 7636e08d6bbSMika Westerberg 7640bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 7656e08d6bbSMika Westerberg 7666e08d6bbSMika Westerberg return 0; 7676e08d6bbSMika Westerberg } 7686e08d6bbSMika Westerberg 7693ea2e2caSAndy Shevchenko static void chv_gpio_clear_triggering(struct intel_pinctrl *pctrl, 770b6fb6e11SHans de Goede unsigned int offset) 771b6fb6e11SHans de Goede { 772a0bf06dcSHans de Goede u32 invrxtx_mask = CHV_PADCTRL1_INVRXTX_MASK; 773b6fb6e11SHans de Goede u32 value; 774b6fb6e11SHans de Goede 775a0bf06dcSHans de Goede /* 776a0bf06dcSHans de Goede * One some devices the GPIO should output the inverted value from what 777a0bf06dcSHans de Goede * device-drivers / ACPI code expects (inverted external buffer?). The 778a0bf06dcSHans de Goede * BIOS makes this work by setting the CHV_PADCTRL1_INVRXTX_TXDATA flag, 779a0bf06dcSHans de Goede * preserve this flag if the pin is already setup as GPIO. 780a0bf06dcSHans de Goede */ 781a0bf06dcSHans de Goede value = chv_readl(pctrl, offset, CHV_PADCTRL0); 782a0bf06dcSHans de Goede if (value & CHV_PADCTRL0_GPIOEN) 783a0bf06dcSHans de Goede invrxtx_mask &= ~CHV_PADCTRL1_INVRXTX_TXDATA; 784a0bf06dcSHans de Goede 7854e7293e3SAndy Shevchenko value = chv_readl(pctrl, offset, CHV_PADCTRL1); 786b6fb6e11SHans de Goede value &= ~CHV_PADCTRL1_INTWAKECFG_MASK; 787a0bf06dcSHans de Goede value &= ~invrxtx_mask; 788bfc8a4baSAndy Shevchenko chv_writel(pctrl, offset, CHV_PADCTRL1, value); 789b6fb6e11SHans de Goede } 790b6fb6e11SHans de Goede 7916e08d6bbSMika Westerberg static int chv_gpio_request_enable(struct pinctrl_dev *pctldev, 7926e08d6bbSMika Westerberg struct pinctrl_gpio_range *range, 7934e737af8SAndy Shevchenko unsigned int offset) 7946e08d6bbSMika Westerberg { 7953ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 7966e08d6bbSMika Westerberg unsigned long flags; 7976e08d6bbSMika Westerberg u32 value; 7986e08d6bbSMika Westerberg 7990bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 8006e08d6bbSMika Westerberg 8016e08d6bbSMika Westerberg if (chv_pad_locked(pctrl, offset)) { 8024e7293e3SAndy Shevchenko value = chv_readl(pctrl, offset, CHV_PADCTRL0); 8036e08d6bbSMika Westerberg if (!(value & CHV_PADCTRL0_GPIOEN)) { 8046e08d6bbSMika Westerberg /* Locked so cannot enable */ 8050bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 8066e08d6bbSMika Westerberg return -EBUSY; 8076e08d6bbSMika Westerberg } 8086e08d6bbSMika Westerberg } else { 8098a828570SAndy Shevchenko struct intel_community_context *cctx = &pctrl->context.communities[0]; 8106e08d6bbSMika Westerberg int i; 8116e08d6bbSMika Westerberg 8126e08d6bbSMika Westerberg /* Reset the interrupt mapping */ 8138a828570SAndy Shevchenko for (i = 0; i < ARRAY_SIZE(cctx->intr_lines); i++) { 8148a828570SAndy Shevchenko if (cctx->intr_lines[i] == offset) { 8158a828570SAndy Shevchenko cctx->intr_lines[i] = 0; 8166e08d6bbSMika Westerberg break; 8176e08d6bbSMika Westerberg } 8186e08d6bbSMika Westerberg } 8196e08d6bbSMika Westerberg 8206e08d6bbSMika Westerberg /* Disable interrupt generation */ 821b6fb6e11SHans de Goede chv_gpio_clear_triggering(pctrl, offset); 8226e08d6bbSMika Westerberg 8234e7293e3SAndy Shevchenko value = chv_readl(pctrl, offset, CHV_PADCTRL0); 8242479c730SMika Westerberg 8252479c730SMika Westerberg /* 8262479c730SMika Westerberg * If the pin is in HiZ mode (both TX and RX buffers are 8272479c730SMika Westerberg * disabled) we turn it to be input now. 8282479c730SMika Westerberg */ 8292479c730SMika Westerberg if ((value & CHV_PADCTRL0_GPIOCFG_MASK) == 8302479c730SMika Westerberg (CHV_PADCTRL0_GPIOCFG_HIZ << CHV_PADCTRL0_GPIOCFG_SHIFT)) { 8312479c730SMika Westerberg value &= ~CHV_PADCTRL0_GPIOCFG_MASK; 832bfc8a4baSAndy Shevchenko value |= CHV_PADCTRL0_GPIOCFG_GPI << CHV_PADCTRL0_GPIOCFG_SHIFT; 8332479c730SMika Westerberg } 8342479c730SMika Westerberg 8352479c730SMika Westerberg /* Switch to a GPIO mode */ 8362479c730SMika Westerberg value |= CHV_PADCTRL0_GPIOEN; 837bfc8a4baSAndy Shevchenko chv_writel(pctrl, offset, CHV_PADCTRL0, value); 8386e08d6bbSMika Westerberg } 8396e08d6bbSMika Westerberg 8400bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 8416e08d6bbSMika Westerberg 8426e08d6bbSMika Westerberg return 0; 8436e08d6bbSMika Westerberg } 8446e08d6bbSMika Westerberg 8456e08d6bbSMika Westerberg static void chv_gpio_disable_free(struct pinctrl_dev *pctldev, 8466e08d6bbSMika Westerberg struct pinctrl_gpio_range *range, 8474e737af8SAndy Shevchenko unsigned int offset) 8486e08d6bbSMika Westerberg { 8493ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 8506e08d6bbSMika Westerberg unsigned long flags; 8516e08d6bbSMika Westerberg 8520bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 8536e08d6bbSMika Westerberg 8541adde32aSHans de Goede if (!chv_pad_locked(pctrl, offset)) 8551adde32aSHans de Goede chv_gpio_clear_triggering(pctrl, offset); 8566e08d6bbSMika Westerberg 8570bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 8586e08d6bbSMika Westerberg } 8596e08d6bbSMika Westerberg 8606e08d6bbSMika Westerberg static int chv_gpio_set_direction(struct pinctrl_dev *pctldev, 8616e08d6bbSMika Westerberg struct pinctrl_gpio_range *range, 8624e737af8SAndy Shevchenko unsigned int offset, bool input) 8636e08d6bbSMika Westerberg { 8643ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 8656e08d6bbSMika Westerberg unsigned long flags; 8666e08d6bbSMika Westerberg u32 ctrl0; 8676e08d6bbSMika Westerberg 8680bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 8696e08d6bbSMika Westerberg 8704e7293e3SAndy Shevchenko ctrl0 = chv_readl(pctrl, offset, CHV_PADCTRL0) & ~CHV_PADCTRL0_GPIOCFG_MASK; 8716e08d6bbSMika Westerberg if (input) 8726e08d6bbSMika Westerberg ctrl0 |= CHV_PADCTRL0_GPIOCFG_GPI << CHV_PADCTRL0_GPIOCFG_SHIFT; 8736e08d6bbSMika Westerberg else 8746e08d6bbSMika Westerberg ctrl0 |= CHV_PADCTRL0_GPIOCFG_GPO << CHV_PADCTRL0_GPIOCFG_SHIFT; 875bfc8a4baSAndy Shevchenko chv_writel(pctrl, offset, CHV_PADCTRL0, ctrl0); 8766e08d6bbSMika Westerberg 8770bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 8786e08d6bbSMika Westerberg 8796e08d6bbSMika Westerberg return 0; 8806e08d6bbSMika Westerberg } 8816e08d6bbSMika Westerberg 8826e08d6bbSMika Westerberg static const struct pinmux_ops chv_pinmux_ops = { 8836e08d6bbSMika Westerberg .get_functions_count = chv_get_functions_count, 8846e08d6bbSMika Westerberg .get_function_name = chv_get_function_name, 8856e08d6bbSMika Westerberg .get_function_groups = chv_get_function_groups, 8866e08d6bbSMika Westerberg .set_mux = chv_pinmux_set_mux, 8876e08d6bbSMika Westerberg .gpio_request_enable = chv_gpio_request_enable, 8886e08d6bbSMika Westerberg .gpio_disable_free = chv_gpio_disable_free, 8896e08d6bbSMika Westerberg .gpio_set_direction = chv_gpio_set_direction, 8906e08d6bbSMika Westerberg }; 8916e08d6bbSMika Westerberg 8924e737af8SAndy Shevchenko static int chv_config_get(struct pinctrl_dev *pctldev, unsigned int pin, 8936e08d6bbSMika Westerberg unsigned long *config) 8946e08d6bbSMika Westerberg { 8953ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 8966e08d6bbSMika Westerberg enum pin_config_param param = pinconf_to_config_param(*config); 8976e08d6bbSMika Westerberg unsigned long flags; 8986e08d6bbSMika Westerberg u32 ctrl0, ctrl1; 8996e08d6bbSMika Westerberg u16 arg = 0; 9006e08d6bbSMika Westerberg u32 term; 9016e08d6bbSMika Westerberg 9020bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 9034e7293e3SAndy Shevchenko ctrl0 = chv_readl(pctrl, pin, CHV_PADCTRL0); 9044e7293e3SAndy Shevchenko ctrl1 = chv_readl(pctrl, pin, CHV_PADCTRL1); 9050bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 9066e08d6bbSMika Westerberg 9076e08d6bbSMika Westerberg term = (ctrl0 & CHV_PADCTRL0_TERM_MASK) >> CHV_PADCTRL0_TERM_SHIFT; 9086e08d6bbSMika Westerberg 9096e08d6bbSMika Westerberg switch (param) { 9106e08d6bbSMika Westerberg case PIN_CONFIG_BIAS_DISABLE: 9116e08d6bbSMika Westerberg if (term) 9126e08d6bbSMika Westerberg return -EINVAL; 9136e08d6bbSMika Westerberg break; 9146e08d6bbSMika Westerberg 9156e08d6bbSMika Westerberg case PIN_CONFIG_BIAS_PULL_UP: 9166e08d6bbSMika Westerberg if (!(ctrl0 & CHV_PADCTRL0_TERM_UP)) 9176e08d6bbSMika Westerberg return -EINVAL; 9186e08d6bbSMika Westerberg 9196e08d6bbSMika Westerberg switch (term) { 9206e08d6bbSMika Westerberg case CHV_PADCTRL0_TERM_20K: 9216e08d6bbSMika Westerberg arg = 20000; 9226e08d6bbSMika Westerberg break; 9236e08d6bbSMika Westerberg case CHV_PADCTRL0_TERM_5K: 9246e08d6bbSMika Westerberg arg = 5000; 9256e08d6bbSMika Westerberg break; 9266e08d6bbSMika Westerberg case CHV_PADCTRL0_TERM_1K: 9276e08d6bbSMika Westerberg arg = 1000; 9286e08d6bbSMika Westerberg break; 9296e08d6bbSMika Westerberg } 9306e08d6bbSMika Westerberg 9316e08d6bbSMika Westerberg break; 9326e08d6bbSMika Westerberg 9336e08d6bbSMika Westerberg case PIN_CONFIG_BIAS_PULL_DOWN: 9346e08d6bbSMika Westerberg if (!term || (ctrl0 & CHV_PADCTRL0_TERM_UP)) 9356e08d6bbSMika Westerberg return -EINVAL; 9366e08d6bbSMika Westerberg 9376e08d6bbSMika Westerberg switch (term) { 9386e08d6bbSMika Westerberg case CHV_PADCTRL0_TERM_20K: 9396e08d6bbSMika Westerberg arg = 20000; 9406e08d6bbSMika Westerberg break; 9416e08d6bbSMika Westerberg case CHV_PADCTRL0_TERM_5K: 9426e08d6bbSMika Westerberg arg = 5000; 9436e08d6bbSMika Westerberg break; 9446e08d6bbSMika Westerberg } 9456e08d6bbSMika Westerberg 9466e08d6bbSMika Westerberg break; 9476e08d6bbSMika Westerberg 9486e08d6bbSMika Westerberg case PIN_CONFIG_DRIVE_OPEN_DRAIN: 9496e08d6bbSMika Westerberg if (!(ctrl1 & CHV_PADCTRL1_ODEN)) 9506e08d6bbSMika Westerberg return -EINVAL; 9516e08d6bbSMika Westerberg break; 9526e08d6bbSMika Westerberg 9536e08d6bbSMika Westerberg case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: { 9546e08d6bbSMika Westerberg u32 cfg; 9556e08d6bbSMika Westerberg 9566e08d6bbSMika Westerberg cfg = ctrl0 & CHV_PADCTRL0_GPIOCFG_MASK; 9576e08d6bbSMika Westerberg cfg >>= CHV_PADCTRL0_GPIOCFG_SHIFT; 9586e08d6bbSMika Westerberg if (cfg != CHV_PADCTRL0_GPIOCFG_HIZ) 9596e08d6bbSMika Westerberg return -EINVAL; 9606e08d6bbSMika Westerberg 9616e08d6bbSMika Westerberg break; 9626e08d6bbSMika Westerberg } 9636e08d6bbSMika Westerberg 9646e08d6bbSMika Westerberg default: 9656e08d6bbSMika Westerberg return -ENOTSUPP; 9666e08d6bbSMika Westerberg } 9676e08d6bbSMika Westerberg 9686e08d6bbSMika Westerberg *config = pinconf_to_config_packed(param, arg); 9696e08d6bbSMika Westerberg return 0; 9706e08d6bbSMika Westerberg } 9716e08d6bbSMika Westerberg 9723ea2e2caSAndy Shevchenko static int chv_config_set_pull(struct intel_pinctrl *pctrl, unsigned int pin, 97358957d2eSMika Westerberg enum pin_config_param param, u32 arg) 9746e08d6bbSMika Westerberg { 9756e08d6bbSMika Westerberg unsigned long flags; 9766e08d6bbSMika Westerberg u32 ctrl0, pull; 9776e08d6bbSMika Westerberg 9780bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 9794e7293e3SAndy Shevchenko ctrl0 = chv_readl(pctrl, pin, CHV_PADCTRL0); 9806e08d6bbSMika Westerberg 9816e08d6bbSMika Westerberg switch (param) { 9826e08d6bbSMika Westerberg case PIN_CONFIG_BIAS_DISABLE: 9836e08d6bbSMika Westerberg ctrl0 &= ~(CHV_PADCTRL0_TERM_MASK | CHV_PADCTRL0_TERM_UP); 9846e08d6bbSMika Westerberg break; 9856e08d6bbSMika Westerberg 9866e08d6bbSMika Westerberg case PIN_CONFIG_BIAS_PULL_UP: 9876e08d6bbSMika Westerberg ctrl0 &= ~(CHV_PADCTRL0_TERM_MASK | CHV_PADCTRL0_TERM_UP); 9886e08d6bbSMika Westerberg 9896e08d6bbSMika Westerberg switch (arg) { 9906e08d6bbSMika Westerberg case 1000: 9916e08d6bbSMika Westerberg /* For 1k there is only pull up */ 9926e08d6bbSMika Westerberg pull = CHV_PADCTRL0_TERM_1K << CHV_PADCTRL0_TERM_SHIFT; 9936e08d6bbSMika Westerberg break; 9946e08d6bbSMika Westerberg case 5000: 9956e08d6bbSMika Westerberg pull = CHV_PADCTRL0_TERM_5K << CHV_PADCTRL0_TERM_SHIFT; 9966e08d6bbSMika Westerberg break; 9976e08d6bbSMika Westerberg case 20000: 9986e08d6bbSMika Westerberg pull = CHV_PADCTRL0_TERM_20K << CHV_PADCTRL0_TERM_SHIFT; 9996e08d6bbSMika Westerberg break; 10006e08d6bbSMika Westerberg default: 10010bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 10026e08d6bbSMika Westerberg return -EINVAL; 10036e08d6bbSMika Westerberg } 10046e08d6bbSMika Westerberg 10056e08d6bbSMika Westerberg ctrl0 |= CHV_PADCTRL0_TERM_UP | pull; 10066e08d6bbSMika Westerberg break; 10076e08d6bbSMika Westerberg 10086e08d6bbSMika Westerberg case PIN_CONFIG_BIAS_PULL_DOWN: 10096e08d6bbSMika Westerberg ctrl0 &= ~(CHV_PADCTRL0_TERM_MASK | CHV_PADCTRL0_TERM_UP); 10106e08d6bbSMika Westerberg 10116e08d6bbSMika Westerberg switch (arg) { 10126e08d6bbSMika Westerberg case 5000: 10136e08d6bbSMika Westerberg pull = CHV_PADCTRL0_TERM_5K << CHV_PADCTRL0_TERM_SHIFT; 10146e08d6bbSMika Westerberg break; 10156e08d6bbSMika Westerberg case 20000: 10166e08d6bbSMika Westerberg pull = CHV_PADCTRL0_TERM_20K << CHV_PADCTRL0_TERM_SHIFT; 10176e08d6bbSMika Westerberg break; 10186e08d6bbSMika Westerberg default: 10190bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 10206e08d6bbSMika Westerberg return -EINVAL; 10216e08d6bbSMika Westerberg } 10226e08d6bbSMika Westerberg 10236e08d6bbSMika Westerberg ctrl0 |= pull; 10246e08d6bbSMika Westerberg break; 10256e08d6bbSMika Westerberg 10266e08d6bbSMika Westerberg default: 10270bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 10286e08d6bbSMika Westerberg return -EINVAL; 10296e08d6bbSMika Westerberg } 10306e08d6bbSMika Westerberg 1031bfc8a4baSAndy Shevchenko chv_writel(pctrl, pin, CHV_PADCTRL0, ctrl0); 10320bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 10336e08d6bbSMika Westerberg 10346e08d6bbSMika Westerberg return 0; 10356e08d6bbSMika Westerberg } 10366e08d6bbSMika Westerberg 10373ea2e2caSAndy Shevchenko static int chv_config_set_oden(struct intel_pinctrl *pctrl, unsigned int pin, 1038ccdf81d0SDan O'Donovan bool enable) 1039ccdf81d0SDan O'Donovan { 1040ccdf81d0SDan O'Donovan unsigned long flags; 1041ccdf81d0SDan O'Donovan u32 ctrl1; 1042ccdf81d0SDan O'Donovan 1043ccdf81d0SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 10444e7293e3SAndy Shevchenko ctrl1 = chv_readl(pctrl, pin, CHV_PADCTRL1); 1045ccdf81d0SDan O'Donovan 1046ccdf81d0SDan O'Donovan if (enable) 1047ccdf81d0SDan O'Donovan ctrl1 |= CHV_PADCTRL1_ODEN; 1048ccdf81d0SDan O'Donovan else 1049ccdf81d0SDan O'Donovan ctrl1 &= ~CHV_PADCTRL1_ODEN; 1050ccdf81d0SDan O'Donovan 1051bfc8a4baSAndy Shevchenko chv_writel(pctrl, pin, CHV_PADCTRL1, ctrl1); 1052ccdf81d0SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 1053ccdf81d0SDan O'Donovan 1054ccdf81d0SDan O'Donovan return 0; 1055ccdf81d0SDan O'Donovan } 1056ccdf81d0SDan O'Donovan 10574e737af8SAndy Shevchenko static int chv_config_set(struct pinctrl_dev *pctldev, unsigned int pin, 10584e737af8SAndy Shevchenko unsigned long *configs, unsigned int nconfigs) 10596e08d6bbSMika Westerberg { 10603ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 10616e08d6bbSMika Westerberg enum pin_config_param param; 10626e08d6bbSMika Westerberg int i, ret; 106358957d2eSMika Westerberg u32 arg; 10646e08d6bbSMika Westerberg 10656e08d6bbSMika Westerberg if (chv_pad_locked(pctrl, pin)) 10666e08d6bbSMika Westerberg return -EBUSY; 10676e08d6bbSMika Westerberg 10686e08d6bbSMika Westerberg for (i = 0; i < nconfigs; i++) { 10696e08d6bbSMika Westerberg param = pinconf_to_config_param(configs[i]); 10706e08d6bbSMika Westerberg arg = pinconf_to_config_argument(configs[i]); 10716e08d6bbSMika Westerberg 10726e08d6bbSMika Westerberg switch (param) { 10736e08d6bbSMika Westerberg case PIN_CONFIG_BIAS_DISABLE: 10746e08d6bbSMika Westerberg case PIN_CONFIG_BIAS_PULL_UP: 10756e08d6bbSMika Westerberg case PIN_CONFIG_BIAS_PULL_DOWN: 10766e08d6bbSMika Westerberg ret = chv_config_set_pull(pctrl, pin, param, arg); 10776e08d6bbSMika Westerberg if (ret) 10786e08d6bbSMika Westerberg return ret; 10796e08d6bbSMika Westerberg break; 10806e08d6bbSMika Westerberg 1081ccdf81d0SDan O'Donovan case PIN_CONFIG_DRIVE_PUSH_PULL: 1082ccdf81d0SDan O'Donovan ret = chv_config_set_oden(pctrl, pin, false); 1083ccdf81d0SDan O'Donovan if (ret) 1084ccdf81d0SDan O'Donovan return ret; 1085ccdf81d0SDan O'Donovan break; 1086ccdf81d0SDan O'Donovan 1087ccdf81d0SDan O'Donovan case PIN_CONFIG_DRIVE_OPEN_DRAIN: 1088ccdf81d0SDan O'Donovan ret = chv_config_set_oden(pctrl, pin, true); 1089ccdf81d0SDan O'Donovan if (ret) 1090ccdf81d0SDan O'Donovan return ret; 1091ccdf81d0SDan O'Donovan break; 1092ccdf81d0SDan O'Donovan 10936e08d6bbSMika Westerberg default: 10946e08d6bbSMika Westerberg return -ENOTSUPP; 10956e08d6bbSMika Westerberg } 10966e08d6bbSMika Westerberg 10976e08d6bbSMika Westerberg dev_dbg(pctrl->dev, "pin %d set config %d arg %u\n", pin, 10986e08d6bbSMika Westerberg param, arg); 10996e08d6bbSMika Westerberg } 11006e08d6bbSMika Westerberg 11016e08d6bbSMika Westerberg return 0; 11026e08d6bbSMika Westerberg } 11036e08d6bbSMika Westerberg 110477401d7fSDan O'Donovan static int chv_config_group_get(struct pinctrl_dev *pctldev, 110577401d7fSDan O'Donovan unsigned int group, 110677401d7fSDan O'Donovan unsigned long *config) 110777401d7fSDan O'Donovan { 110877401d7fSDan O'Donovan const unsigned int *pins; 110977401d7fSDan O'Donovan unsigned int npins; 111077401d7fSDan O'Donovan int ret; 111177401d7fSDan O'Donovan 111277401d7fSDan O'Donovan ret = chv_get_group_pins(pctldev, group, &pins, &npins); 111377401d7fSDan O'Donovan if (ret) 111477401d7fSDan O'Donovan return ret; 111577401d7fSDan O'Donovan 111677401d7fSDan O'Donovan ret = chv_config_get(pctldev, pins[0], config); 111777401d7fSDan O'Donovan if (ret) 111877401d7fSDan O'Donovan return ret; 111977401d7fSDan O'Donovan 112077401d7fSDan O'Donovan return 0; 112177401d7fSDan O'Donovan } 112277401d7fSDan O'Donovan 112377401d7fSDan O'Donovan static int chv_config_group_set(struct pinctrl_dev *pctldev, 112477401d7fSDan O'Donovan unsigned int group, unsigned long *configs, 112577401d7fSDan O'Donovan unsigned int num_configs) 112677401d7fSDan O'Donovan { 112777401d7fSDan O'Donovan const unsigned int *pins; 112877401d7fSDan O'Donovan unsigned int npins; 112977401d7fSDan O'Donovan int i, ret; 113077401d7fSDan O'Donovan 113177401d7fSDan O'Donovan ret = chv_get_group_pins(pctldev, group, &pins, &npins); 113277401d7fSDan O'Donovan if (ret) 113377401d7fSDan O'Donovan return ret; 113477401d7fSDan O'Donovan 113577401d7fSDan O'Donovan for (i = 0; i < npins; i++) { 113677401d7fSDan O'Donovan ret = chv_config_set(pctldev, pins[i], configs, num_configs); 113777401d7fSDan O'Donovan if (ret) 113877401d7fSDan O'Donovan return ret; 113977401d7fSDan O'Donovan } 114077401d7fSDan O'Donovan 114177401d7fSDan O'Donovan return 0; 114277401d7fSDan O'Donovan } 114377401d7fSDan O'Donovan 11446e08d6bbSMika Westerberg static const struct pinconf_ops chv_pinconf_ops = { 11456e08d6bbSMika Westerberg .is_generic = true, 11466e08d6bbSMika Westerberg .pin_config_set = chv_config_set, 11476e08d6bbSMika Westerberg .pin_config_get = chv_config_get, 114877401d7fSDan O'Donovan .pin_config_group_get = chv_config_group_get, 114977401d7fSDan O'Donovan .pin_config_group_set = chv_config_group_set, 11506e08d6bbSMika Westerberg }; 11516e08d6bbSMika Westerberg 11526e08d6bbSMika Westerberg static struct pinctrl_desc chv_pinctrl_desc = { 11536e08d6bbSMika Westerberg .pctlops = &chv_pinctrl_ops, 11546e08d6bbSMika Westerberg .pmxops = &chv_pinmux_ops, 11556e08d6bbSMika Westerberg .confops = &chv_pinconf_ops, 11566e08d6bbSMika Westerberg .owner = THIS_MODULE, 11576e08d6bbSMika Westerberg }; 11586e08d6bbSMika Westerberg 11594e737af8SAndy Shevchenko static int chv_gpio_get(struct gpio_chip *chip, unsigned int offset) 11606e08d6bbSMika Westerberg { 11613ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = gpiochip_get_data(chip); 11624585b000SMika Westerberg unsigned long flags; 11636e08d6bbSMika Westerberg u32 ctrl0, cfg; 11646e08d6bbSMika Westerberg 11650bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 11664e7293e3SAndy Shevchenko ctrl0 = chv_readl(pctrl, offset, CHV_PADCTRL0); 11670bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 11686e08d6bbSMika Westerberg 11696e08d6bbSMika Westerberg cfg = ctrl0 & CHV_PADCTRL0_GPIOCFG_MASK; 11706e08d6bbSMika Westerberg cfg >>= CHV_PADCTRL0_GPIOCFG_SHIFT; 11716e08d6bbSMika Westerberg 11726e08d6bbSMika Westerberg if (cfg == CHV_PADCTRL0_GPIOCFG_GPO) 11736e08d6bbSMika Westerberg return !!(ctrl0 & CHV_PADCTRL0_GPIOTXSTATE); 11746e08d6bbSMika Westerberg return !!(ctrl0 & CHV_PADCTRL0_GPIORXSTATE); 11756e08d6bbSMika Westerberg } 11766e08d6bbSMika Westerberg 11774e737af8SAndy Shevchenko static void chv_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) 11786e08d6bbSMika Westerberg { 11793ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = gpiochip_get_data(chip); 11806e08d6bbSMika Westerberg unsigned long flags; 11816e08d6bbSMika Westerberg u32 ctrl0; 11826e08d6bbSMika Westerberg 11830bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 11846e08d6bbSMika Westerberg 11854e7293e3SAndy Shevchenko ctrl0 = chv_readl(pctrl, offset, CHV_PADCTRL0); 11866e08d6bbSMika Westerberg 11876e08d6bbSMika Westerberg if (value) 11886e08d6bbSMika Westerberg ctrl0 |= CHV_PADCTRL0_GPIOTXSTATE; 11896e08d6bbSMika Westerberg else 11906e08d6bbSMika Westerberg ctrl0 &= ~CHV_PADCTRL0_GPIOTXSTATE; 11916e08d6bbSMika Westerberg 1192bfc8a4baSAndy Shevchenko chv_writel(pctrl, offset, CHV_PADCTRL0, ctrl0); 11936e08d6bbSMika Westerberg 11940bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 11956e08d6bbSMika Westerberg } 11966e08d6bbSMika Westerberg 11974e737af8SAndy Shevchenko static int chv_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) 11986e08d6bbSMika Westerberg { 11993ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = gpiochip_get_data(chip); 12006e08d6bbSMika Westerberg u32 ctrl0, direction; 12014585b000SMika Westerberg unsigned long flags; 12026e08d6bbSMika Westerberg 12030bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 12044e7293e3SAndy Shevchenko ctrl0 = chv_readl(pctrl, offset, CHV_PADCTRL0); 12050bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 12066e08d6bbSMika Westerberg 12076e08d6bbSMika Westerberg direction = ctrl0 & CHV_PADCTRL0_GPIOCFG_MASK; 12086e08d6bbSMika Westerberg direction >>= CHV_PADCTRL0_GPIOCFG_SHIFT; 12096e08d6bbSMika Westerberg 121090a1eb18SMatti Vaittinen if (direction == CHV_PADCTRL0_GPIOCFG_GPO) 121190a1eb18SMatti Vaittinen return GPIO_LINE_DIRECTION_OUT; 121290a1eb18SMatti Vaittinen 121390a1eb18SMatti Vaittinen return GPIO_LINE_DIRECTION_IN; 12146e08d6bbSMika Westerberg } 12156e08d6bbSMika Westerberg 12164e737af8SAndy Shevchenko static int chv_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) 12176e08d6bbSMika Westerberg { 12186e08d6bbSMika Westerberg return pinctrl_gpio_direction_input(chip->base + offset); 12196e08d6bbSMika Westerberg } 12206e08d6bbSMika Westerberg 12214e737af8SAndy Shevchenko static int chv_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, 12226e08d6bbSMika Westerberg int value) 12236e08d6bbSMika Westerberg { 1224549e783fSqipeng.zha chv_gpio_set(chip, offset, value); 12256e08d6bbSMika Westerberg return pinctrl_gpio_direction_output(chip->base + offset); 12266e08d6bbSMika Westerberg } 12276e08d6bbSMika Westerberg 12286e08d6bbSMika Westerberg static const struct gpio_chip chv_gpio_chip = { 12296e08d6bbSMika Westerberg .owner = THIS_MODULE, 123098c85d58SJonas Gorski .request = gpiochip_generic_request, 123198c85d58SJonas Gorski .free = gpiochip_generic_free, 12326e08d6bbSMika Westerberg .get_direction = chv_gpio_get_direction, 12336e08d6bbSMika Westerberg .direction_input = chv_gpio_direction_input, 12346e08d6bbSMika Westerberg .direction_output = chv_gpio_direction_output, 12356e08d6bbSMika Westerberg .get = chv_gpio_get, 12366e08d6bbSMika Westerberg .set = chv_gpio_set, 12376e08d6bbSMika Westerberg }; 12386e08d6bbSMika Westerberg 12396e08d6bbSMika Westerberg static void chv_gpio_irq_ack(struct irq_data *d) 12406e08d6bbSMika Westerberg { 12416e08d6bbSMika Westerberg struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 12423ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = gpiochip_get_data(gc); 124303c4749dSMika Westerberg int pin = irqd_to_hwirq(d); 12446e08d6bbSMika Westerberg u32 intr_line; 12456e08d6bbSMika Westerberg 12460bd50d71SDan O'Donovan raw_spin_lock(&chv_lock); 12476e08d6bbSMika Westerberg 12484e7293e3SAndy Shevchenko intr_line = chv_readl(pctrl, pin, CHV_PADCTRL0); 12496e08d6bbSMika Westerberg intr_line &= CHV_PADCTRL0_INTSEL_MASK; 12506e08d6bbSMika Westerberg intr_line >>= CHV_PADCTRL0_INTSEL_SHIFT; 125199fd6512SAndy Shevchenko chv_pctrl_writel(pctrl, CHV_INTSTAT, BIT(intr_line)); 12526e08d6bbSMika Westerberg 12530bd50d71SDan O'Donovan raw_spin_unlock(&chv_lock); 12546e08d6bbSMika Westerberg } 12556e08d6bbSMika Westerberg 12566e08d6bbSMika Westerberg static void chv_gpio_irq_mask_unmask(struct irq_data *d, bool mask) 12576e08d6bbSMika Westerberg { 12586e08d6bbSMika Westerberg struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 12593ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = gpiochip_get_data(gc); 126003c4749dSMika Westerberg int pin = irqd_to_hwirq(d); 12616e08d6bbSMika Westerberg u32 value, intr_line; 12626e08d6bbSMika Westerberg unsigned long flags; 12636e08d6bbSMika Westerberg 12640bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 12656e08d6bbSMika Westerberg 12664e7293e3SAndy Shevchenko intr_line = chv_readl(pctrl, pin, CHV_PADCTRL0); 12676e08d6bbSMika Westerberg intr_line &= CHV_PADCTRL0_INTSEL_MASK; 12686e08d6bbSMika Westerberg intr_line >>= CHV_PADCTRL0_INTSEL_SHIFT; 12696e08d6bbSMika Westerberg 127099fd6512SAndy Shevchenko value = chv_pctrl_readl(pctrl, CHV_INTMASK); 12716e08d6bbSMika Westerberg if (mask) 12726e08d6bbSMika Westerberg value &= ~BIT(intr_line); 12736e08d6bbSMika Westerberg else 12746e08d6bbSMika Westerberg value |= BIT(intr_line); 127599fd6512SAndy Shevchenko chv_pctrl_writel(pctrl, CHV_INTMASK, value); 12766e08d6bbSMika Westerberg 12770bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 12786e08d6bbSMika Westerberg } 12796e08d6bbSMika Westerberg 12806e08d6bbSMika Westerberg static void chv_gpio_irq_mask(struct irq_data *d) 12816e08d6bbSMika Westerberg { 12826e08d6bbSMika Westerberg chv_gpio_irq_mask_unmask(d, true); 12836e08d6bbSMika Westerberg } 12846e08d6bbSMika Westerberg 12856e08d6bbSMika Westerberg static void chv_gpio_irq_unmask(struct irq_data *d) 12866e08d6bbSMika Westerberg { 12876e08d6bbSMika Westerberg chv_gpio_irq_mask_unmask(d, false); 12886e08d6bbSMika Westerberg } 12896e08d6bbSMika Westerberg 1290e6c906deSMika Westerberg static unsigned chv_gpio_irq_startup(struct irq_data *d) 1291e6c906deSMika Westerberg { 1292e6c906deSMika Westerberg /* 1293e6c906deSMika Westerberg * Check if the interrupt has been requested with 0 as triggering 1294e6c906deSMika Westerberg * type. In that case it is assumed that the current values 1295e6c906deSMika Westerberg * programmed to the hardware are used (e.g BIOS configured 1296e6c906deSMika Westerberg * defaults). 1297e6c906deSMika Westerberg * 1298e6c906deSMika Westerberg * In that case ->irq_set_type() will never be called so we need to 1299e6c906deSMika Westerberg * read back the values from hardware now, set correct flow handler 1300e6c906deSMika Westerberg * and update mappings before the interrupt is being used. 1301e6c906deSMika Westerberg */ 1302e6c906deSMika Westerberg if (irqd_get_trigger_type(d) == IRQ_TYPE_NONE) { 1303e6c906deSMika Westerberg struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 13043ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = gpiochip_get_data(gc); 13058a828570SAndy Shevchenko struct intel_community_context *cctx = &pctrl->context.communities[0]; 13064e737af8SAndy Shevchenko unsigned int pin = irqd_to_hwirq(d); 1307e6c906deSMika Westerberg irq_flow_handler_t handler; 1308e6c906deSMika Westerberg unsigned long flags; 1309e6c906deSMika Westerberg u32 intsel, value; 1310e6c906deSMika Westerberg 13110bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 13124e7293e3SAndy Shevchenko intsel = chv_readl(pctrl, pin, CHV_PADCTRL0); 1313e6c906deSMika Westerberg intsel &= CHV_PADCTRL0_INTSEL_MASK; 1314e6c906deSMika Westerberg intsel >>= CHV_PADCTRL0_INTSEL_SHIFT; 1315e6c906deSMika Westerberg 13164e7293e3SAndy Shevchenko value = chv_readl(pctrl, pin, CHV_PADCTRL1); 1317e6c906deSMika Westerberg if (value & CHV_PADCTRL1_INTWAKECFG_LEVEL) 1318e6c906deSMika Westerberg handler = handle_level_irq; 1319e6c906deSMika Westerberg else 1320e6c906deSMika Westerberg handler = handle_edge_irq; 1321e6c906deSMika Westerberg 13228a828570SAndy Shevchenko if (!cctx->intr_lines[intsel]) { 1323a4e3f783SThomas Gleixner irq_set_handler_locked(d, handler); 13248a828570SAndy Shevchenko cctx->intr_lines[intsel] = pin; 1325e6c906deSMika Westerberg } 13260bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 1327e6c906deSMika Westerberg } 1328e6c906deSMika Westerberg 1329e6c906deSMika Westerberg chv_gpio_irq_unmask(d); 1330e6c906deSMika Westerberg return 0; 1331e6c906deSMika Westerberg } 1332e6c906deSMika Westerberg 13334e737af8SAndy Shevchenko static int chv_gpio_irq_type(struct irq_data *d, unsigned int type) 13346e08d6bbSMika Westerberg { 13356e08d6bbSMika Westerberg struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 13363ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = gpiochip_get_data(gc); 13378a828570SAndy Shevchenko struct intel_community_context *cctx = &pctrl->context.communities[0]; 13384e737af8SAndy Shevchenko unsigned int pin = irqd_to_hwirq(d); 13396e08d6bbSMika Westerberg unsigned long flags; 13406e08d6bbSMika Westerberg u32 value; 13416e08d6bbSMika Westerberg 13420bd50d71SDan O'Donovan raw_spin_lock_irqsave(&chv_lock, flags); 13436e08d6bbSMika Westerberg 13446e08d6bbSMika Westerberg /* 13456e08d6bbSMika Westerberg * Pins which can be used as shared interrupt are configured in 13466e08d6bbSMika Westerberg * BIOS. Driver trusts BIOS configurations and assigns different 13476e08d6bbSMika Westerberg * handler according to the irq type. 13486e08d6bbSMika Westerberg * 13496e08d6bbSMika Westerberg * Driver needs to save the mapping between each pin and 13506e08d6bbSMika Westerberg * its interrupt line. 13516e08d6bbSMika Westerberg * 1. If the pin cfg is locked in BIOS: 13526e08d6bbSMika Westerberg * Trust BIOS has programmed IntWakeCfg bits correctly, 13536e08d6bbSMika Westerberg * driver just needs to save the mapping. 13546e08d6bbSMika Westerberg * 2. If the pin cfg is not locked in BIOS: 13556e08d6bbSMika Westerberg * Driver programs the IntWakeCfg bits and save the mapping. 13566e08d6bbSMika Westerberg */ 13576e08d6bbSMika Westerberg if (!chv_pad_locked(pctrl, pin)) { 13584e7293e3SAndy Shevchenko value = chv_readl(pctrl, pin, CHV_PADCTRL1); 13596e08d6bbSMika Westerberg value &= ~CHV_PADCTRL1_INTWAKECFG_MASK; 13606e08d6bbSMika Westerberg value &= ~CHV_PADCTRL1_INVRXTX_MASK; 13616e08d6bbSMika Westerberg 13626e08d6bbSMika Westerberg if (type & IRQ_TYPE_EDGE_BOTH) { 13636e08d6bbSMika Westerberg if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) 13646e08d6bbSMika Westerberg value |= CHV_PADCTRL1_INTWAKECFG_BOTH; 13656e08d6bbSMika Westerberg else if (type & IRQ_TYPE_EDGE_RISING) 13666e08d6bbSMika Westerberg value |= CHV_PADCTRL1_INTWAKECFG_RISING; 13676e08d6bbSMika Westerberg else if (type & IRQ_TYPE_EDGE_FALLING) 13686e08d6bbSMika Westerberg value |= CHV_PADCTRL1_INTWAKECFG_FALLING; 13696e08d6bbSMika Westerberg } else if (type & IRQ_TYPE_LEVEL_MASK) { 13706e08d6bbSMika Westerberg value |= CHV_PADCTRL1_INTWAKECFG_LEVEL; 13716e08d6bbSMika Westerberg if (type & IRQ_TYPE_LEVEL_LOW) 13726e08d6bbSMika Westerberg value |= CHV_PADCTRL1_INVRXTX_RXDATA; 13736e08d6bbSMika Westerberg } 13746e08d6bbSMika Westerberg 1375bfc8a4baSAndy Shevchenko chv_writel(pctrl, pin, CHV_PADCTRL1, value); 13766e08d6bbSMika Westerberg } 13776e08d6bbSMika Westerberg 13784e7293e3SAndy Shevchenko value = chv_readl(pctrl, pin, CHV_PADCTRL0); 13796e08d6bbSMika Westerberg value &= CHV_PADCTRL0_INTSEL_MASK; 13806e08d6bbSMika Westerberg value >>= CHV_PADCTRL0_INTSEL_SHIFT; 13816e08d6bbSMika Westerberg 13828a828570SAndy Shevchenko cctx->intr_lines[value] = pin; 13836e08d6bbSMika Westerberg 13846e08d6bbSMika Westerberg if (type & IRQ_TYPE_EDGE_BOTH) 1385a4e3f783SThomas Gleixner irq_set_handler_locked(d, handle_edge_irq); 13866e08d6bbSMika Westerberg else if (type & IRQ_TYPE_LEVEL_MASK) 1387a4e3f783SThomas Gleixner irq_set_handler_locked(d, handle_level_irq); 13886e08d6bbSMika Westerberg 13890bd50d71SDan O'Donovan raw_spin_unlock_irqrestore(&chv_lock, flags); 13906e08d6bbSMika Westerberg 13916e08d6bbSMika Westerberg return 0; 13926e08d6bbSMika Westerberg } 13936e08d6bbSMika Westerberg 1394bd0b9ac4SThomas Gleixner static void chv_gpio_irq_handler(struct irq_desc *desc) 13956e08d6bbSMika Westerberg { 13966e08d6bbSMika Westerberg struct gpio_chip *gc = irq_desc_get_handler_data(desc); 13973ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = gpiochip_get_data(gc); 1398293428f9SAndy Shevchenko const struct intel_community *community = &pctrl->communities[0]; 13998a828570SAndy Shevchenko struct intel_community_context *cctx = &pctrl->context.communities[0]; 14005663bb27SJiang Liu struct irq_chip *chip = irq_desc_get_chip(desc); 14016e08d6bbSMika Westerberg unsigned long pending; 14023dbf1ee6SGrace Kao unsigned long flags; 14036e08d6bbSMika Westerberg u32 intr_line; 14046e08d6bbSMika Westerberg 14056e08d6bbSMika Westerberg chained_irq_enter(chip, desc); 14066e08d6bbSMika Westerberg 14073dbf1ee6SGrace Kao raw_spin_lock_irqsave(&chv_lock, flags); 140899fd6512SAndy Shevchenko pending = chv_pctrl_readl(pctrl, CHV_INTSTAT); 14093dbf1ee6SGrace Kao raw_spin_unlock_irqrestore(&chv_lock, flags); 14103dbf1ee6SGrace Kao 1411293428f9SAndy Shevchenko for_each_set_bit(intr_line, &pending, community->nirqs) { 1412*a9cb09b7SMarc Zyngier unsigned int offset; 14136e08d6bbSMika Westerberg 14148a828570SAndy Shevchenko offset = cctx->intr_lines[intr_line]; 1415*a9cb09b7SMarc Zyngier generic_handle_domain_irq(gc->irq.domain, offset); 14166e08d6bbSMika Westerberg } 14176e08d6bbSMika Westerberg 14186e08d6bbSMika Westerberg chained_irq_exit(chip, desc); 14196e08d6bbSMika Westerberg } 14206e08d6bbSMika Westerberg 142170365027SMika Westerberg /* 142270365027SMika Westerberg * Certain machines seem to hardcode Linux IRQ numbers in their ACPI 142370365027SMika Westerberg * tables. Since we leave GPIOs that are not capable of generating 142470365027SMika Westerberg * interrupts out of the irqdomain the numbering will be different and 142570365027SMika Westerberg * cause devices using the hardcoded IRQ numbers fail. In order not to 142670365027SMika Westerberg * break such machines we will only mask pins from irqdomain if the machine 142770365027SMika Westerberg * is not listed below. 142870365027SMika Westerberg */ 142970365027SMika Westerberg static const struct dmi_system_id chv_no_valid_mask[] = { 143070365027SMika Westerberg /* See https://bugzilla.kernel.org/show_bug.cgi?id=194945 */ 14312a8209faSMika Westerberg { 14322a8209faSMika Westerberg .ident = "Intel_Strago based Chromebooks (All models)", 143370365027SMika Westerberg .matches = { 143470365027SMika Westerberg DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), 14352a8209faSMika Westerberg DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_Strago"), 14362a8209faSMika Westerberg }, 14372a8209faSMika Westerberg }, 14382a8209faSMika Westerberg { 14392d80bd3fSAndy Shevchenko .ident = "HP Chromebook 11 G5 (Setzer)", 14402d80bd3fSAndy Shevchenko .matches = { 14412d80bd3fSAndy Shevchenko DMI_MATCH(DMI_SYS_VENDOR, "HP"), 14422d80bd3fSAndy Shevchenko DMI_MATCH(DMI_PRODUCT_NAME, "Setzer"), 14432d80bd3fSAndy Shevchenko }, 14442d80bd3fSAndy Shevchenko }, 14452d80bd3fSAndy Shevchenko { 14462a8209faSMika Westerberg .ident = "Acer Chromebook R11 (Cyan)", 14472a8209faSMika Westerberg .matches = { 14482a8209faSMika Westerberg DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), 14492a8209faSMika Westerberg DMI_MATCH(DMI_PRODUCT_NAME, "Cyan"), 14502a8209faSMika Westerberg }, 14512a8209faSMika Westerberg }, 14522a8209faSMika Westerberg { 14532a8209faSMika Westerberg .ident = "Samsung Chromebook 3 (Celes)", 14542a8209faSMika Westerberg .matches = { 14552a8209faSMika Westerberg DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), 14562a8209faSMika Westerberg DMI_MATCH(DMI_PRODUCT_NAME, "Celes"), 145770365027SMika Westerberg }, 1458a9de080bSWei Yongjun }, 1459a9de080bSWei Yongjun {} 146070365027SMika Westerberg }; 146170365027SMika Westerberg 14625fbe5b58SLinus Walleij static void chv_init_irq_valid_mask(struct gpio_chip *chip, 14635fbe5b58SLinus Walleij unsigned long *valid_mask, 14645fbe5b58SLinus Walleij unsigned int ngpios) 14655fbe5b58SLinus Walleij { 14663ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = gpiochip_get_data(chip); 1467293428f9SAndy Shevchenko const struct intel_community *community = &pctrl->communities[0]; 14685fbe5b58SLinus Walleij int i; 14695fbe5b58SLinus Walleij 14705fbe5b58SLinus Walleij /* Do not add GPIOs that can only generate GPEs to the IRQ domain */ 1471293428f9SAndy Shevchenko for (i = 0; i < pctrl->soc->npins; i++) { 14725fbe5b58SLinus Walleij const struct pinctrl_pin_desc *desc; 14735fbe5b58SLinus Walleij u32 intsel; 14745fbe5b58SLinus Walleij 1475293428f9SAndy Shevchenko desc = &pctrl->soc->pins[i]; 14765fbe5b58SLinus Walleij 14774e7293e3SAndy Shevchenko intsel = chv_readl(pctrl, desc->number, CHV_PADCTRL0); 14785fbe5b58SLinus Walleij intsel &= CHV_PADCTRL0_INTSEL_MASK; 14795fbe5b58SLinus Walleij intsel >>= CHV_PADCTRL0_INTSEL_SHIFT; 14805fbe5b58SLinus Walleij 14815fbe5b58SLinus Walleij if (intsel >= community->nirqs) 148237398985SHans de Goede clear_bit(desc->number, valid_mask); 14835fbe5b58SLinus Walleij } 14845fbe5b58SLinus Walleij } 14855fbe5b58SLinus Walleij 148682d9beb4SHans de Goede static int chv_gpio_irq_init_hw(struct gpio_chip *chip) 148782d9beb4SHans de Goede { 14883ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = gpiochip_get_data(chip); 1489293428f9SAndy Shevchenko const struct intel_community *community = &pctrl->communities[0]; 149082d9beb4SHans de Goede 149182d9beb4SHans de Goede /* 149282d9beb4SHans de Goede * The same set of machines in chv_no_valid_mask[] have incorrectly 149382d9beb4SHans de Goede * configured GPIOs that generate spurious interrupts so we use 149482d9beb4SHans de Goede * this same list to apply another quirk for them. 149582d9beb4SHans de Goede * 149682d9beb4SHans de Goede * See also https://bugzilla.kernel.org/show_bug.cgi?id=197953. 149782d9beb4SHans de Goede */ 149882d9beb4SHans de Goede if (!pctrl->chip.irq.init_valid_mask) { 149982d9beb4SHans de Goede /* 150082d9beb4SHans de Goede * Mask all interrupts the community is able to generate 150182d9beb4SHans de Goede * but leave the ones that can only generate GPEs unmasked. 150282d9beb4SHans de Goede */ 1503293428f9SAndy Shevchenko chv_pctrl_writel(pctrl, CHV_INTMASK, GENMASK(31, community->nirqs)); 150482d9beb4SHans de Goede } 150582d9beb4SHans de Goede 150682d9beb4SHans de Goede /* Clear all interrupts */ 150799fd6512SAndy Shevchenko chv_pctrl_writel(pctrl, CHV_INTSTAT, 0xffff); 150882d9beb4SHans de Goede 150982d9beb4SHans de Goede return 0; 151082d9beb4SHans de Goede } 151182d9beb4SHans de Goede 1512bd90633aSHans de Goede static int chv_gpio_add_pin_ranges(struct gpio_chip *chip) 1513bd90633aSHans de Goede { 15143ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = gpiochip_get_data(chip); 1515293428f9SAndy Shevchenko const struct intel_community *community = &pctrl->communities[0]; 151636ad7b24SAndy Shevchenko const struct intel_padgroup *gpp; 1517bd90633aSHans de Goede int ret, i; 1518bd90633aSHans de Goede 151936ad7b24SAndy Shevchenko for (i = 0; i < community->ngpps; i++) { 152036ad7b24SAndy Shevchenko gpp = &community->gpps[i]; 1521bd90633aSHans de Goede ret = gpiochip_add_pin_range(chip, dev_name(pctrl->dev), 152236ad7b24SAndy Shevchenko gpp->base, gpp->base, 152336ad7b24SAndy Shevchenko gpp->size); 1524bd90633aSHans de Goede if (ret) { 1525bd90633aSHans de Goede dev_err(pctrl->dev, "failed to add GPIO pin range\n"); 1526bd90633aSHans de Goede return ret; 1527bd90633aSHans de Goede } 1528bd90633aSHans de Goede } 1529bd90633aSHans de Goede 1530bd90633aSHans de Goede return 0; 1531bd90633aSHans de Goede } 1532bd90633aSHans de Goede 15333ea2e2caSAndy Shevchenko static int chv_gpio_probe(struct intel_pinctrl *pctrl, int irq) 15346e08d6bbSMika Westerberg { 1535293428f9SAndy Shevchenko const struct intel_community *community = &pctrl->communities[0]; 153636ad7b24SAndy Shevchenko const struct intel_padgroup *gpp; 15376e08d6bbSMika Westerberg struct gpio_chip *chip = &pctrl->chip; 153870365027SMika Westerberg bool need_valid_mask = !dmi_check_system(chv_no_valid_mask); 153903c4749dSMika Westerberg int ret, i, irq_base; 15406e08d6bbSMika Westerberg 15416e08d6bbSMika Westerberg *chip = chv_gpio_chip; 15426e08d6bbSMika Westerberg 1543293428f9SAndy Shevchenko chip->ngpio = pctrl->soc->pins[pctrl->soc->npins - 1].number + 1; 15446e08d6bbSMika Westerberg chip->label = dev_name(pctrl->dev); 1545bd90633aSHans de Goede chip->add_pin_ranges = chv_gpio_add_pin_ranges; 154658383c78SLinus Walleij chip->parent = pctrl->dev; 15476e08d6bbSMika Westerberg chip->base = -1; 15486e08d6bbSMika Westerberg 1549b9a19bdbSHans de Goede pctrl->irq = irq; 1550e58e1773SAndy Shevchenko pctrl->irqchip.name = "chv-gpio"; 1551e58e1773SAndy Shevchenko pctrl->irqchip.irq_startup = chv_gpio_irq_startup; 1552e58e1773SAndy Shevchenko pctrl->irqchip.irq_ack = chv_gpio_irq_ack; 1553e58e1773SAndy Shevchenko pctrl->irqchip.irq_mask = chv_gpio_irq_mask; 1554e58e1773SAndy Shevchenko pctrl->irqchip.irq_unmask = chv_gpio_irq_unmask; 1555e58e1773SAndy Shevchenko pctrl->irqchip.irq_set_type = chv_gpio_irq_type; 1556e58e1773SAndy Shevchenko pctrl->irqchip.flags = IRQCHIP_SKIP_SET_WAKE; 1557e58e1773SAndy Shevchenko 1558b9a19bdbSHans de Goede chip->irq.chip = &pctrl->irqchip; 1559b9a19bdbSHans de Goede chip->irq.init_hw = chv_gpio_irq_init_hw; 1560b9a19bdbSHans de Goede chip->irq.parent_handler = chv_gpio_irq_handler; 1561b9a19bdbSHans de Goede chip->irq.num_parents = 1; 1562b9a19bdbSHans de Goede chip->irq.parents = &pctrl->irq; 1563b9a19bdbSHans de Goede chip->irq.default_type = IRQ_TYPE_NONE; 1564b9a19bdbSHans de Goede chip->irq.handler = handle_bad_irq; 1565b9a19bdbSHans de Goede if (need_valid_mask) { 1566b9a19bdbSHans de Goede chip->irq.init_valid_mask = chv_init_irq_valid_mask; 1567b9a19bdbSHans de Goede } else { 1568b9a19bdbSHans de Goede irq_base = devm_irq_alloc_descs(pctrl->dev, -1, 0, 1569293428f9SAndy Shevchenko pctrl->soc->npins, NUMA_NO_NODE); 1570b9a19bdbSHans de Goede if (irq_base < 0) { 1571b9a19bdbSHans de Goede dev_err(pctrl->dev, "Failed to allocate IRQ numbers\n"); 1572b9a19bdbSHans de Goede return irq_base; 1573b9a19bdbSHans de Goede } 1574b9a19bdbSHans de Goede } 1575b9a19bdbSHans de Goede 1576b9a19bdbSHans de Goede ret = devm_gpiochip_add_data(pctrl->dev, chip, pctrl); 15776e08d6bbSMika Westerberg if (ret) { 1578b9a19bdbSHans de Goede dev_err(pctrl->dev, "Failed to register gpiochip\n"); 1579d1073418SMika Westerberg return ret; 15806e08d6bbSMika Westerberg } 15816e08d6bbSMika Westerberg 158283b9dc11SMika Westerberg if (!need_valid_mask) { 158336ad7b24SAndy Shevchenko for (i = 0; i < community->ngpps; i++) { 158436ad7b24SAndy Shevchenko gpp = &community->gpps[i]; 158583b9dc11SMika Westerberg 158683b9dc11SMika Westerberg irq_domain_associate_many(chip->irq.domain, irq_base, 158736ad7b24SAndy Shevchenko gpp->base, gpp->size); 158836ad7b24SAndy Shevchenko irq_base += gpp->size; 158983b9dc11SMika Westerberg } 159083b9dc11SMika Westerberg } 159183b9dc11SMika Westerberg 15926e08d6bbSMika Westerberg return 0; 15936e08d6bbSMika Westerberg } 15946e08d6bbSMika Westerberg 1595a0b02859SHans de Goede static acpi_status chv_pinctrl_mmio_access_handler(u32 function, 1596a0b02859SHans de Goede acpi_physical_address address, u32 bits, u64 *value, 1597a0b02859SHans de Goede void *handler_context, void *region_context) 1598a0b02859SHans de Goede { 15993ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl = region_context; 1600a0b02859SHans de Goede unsigned long flags; 1601a0b02859SHans de Goede acpi_status ret = AE_OK; 1602a0b02859SHans de Goede 1603a0b02859SHans de Goede raw_spin_lock_irqsave(&chv_lock, flags); 1604a0b02859SHans de Goede 1605a0b02859SHans de Goede if (function == ACPI_WRITE) 160699fd6512SAndy Shevchenko chv_pctrl_writel(pctrl, address, *value); 1607a0b02859SHans de Goede else if (function == ACPI_READ) 160899fd6512SAndy Shevchenko *value = chv_pctrl_readl(pctrl, address); 1609a0b02859SHans de Goede else 1610a0b02859SHans de Goede ret = AE_BAD_PARAMETER; 1611a0b02859SHans de Goede 1612a0b02859SHans de Goede raw_spin_unlock_irqrestore(&chv_lock, flags); 1613a0b02859SHans de Goede 1614a0b02859SHans de Goede return ret; 1615a0b02859SHans de Goede } 1616a0b02859SHans de Goede 16176e08d6bbSMika Westerberg static int chv_pinctrl_probe(struct platform_device *pdev) 16186e08d6bbSMika Westerberg { 161910c857f0SAndy Shevchenko const struct intel_pinctrl_soc_data *soc_data; 1620293428f9SAndy Shevchenko struct intel_community *community; 1621293428f9SAndy Shevchenko struct device *dev = &pdev->dev; 162210c857f0SAndy Shevchenko struct acpi_device *adev = ACPI_COMPANION(dev); 16233ea2e2caSAndy Shevchenko struct intel_pinctrl *pctrl; 1624a0b02859SHans de Goede acpi_status status; 162510c857f0SAndy Shevchenko int ret, irq; 16266e08d6bbSMika Westerberg 162710c857f0SAndy Shevchenko soc_data = intel_pinctrl_get_soc_data(pdev); 162810c857f0SAndy Shevchenko if (IS_ERR(soc_data)) 162910c857f0SAndy Shevchenko return PTR_ERR(soc_data); 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