1eb83479eSAndy Shevchenko // SPDX-License-Identifier: GPL-2.0 2eb83479eSAndy Shevchenko /* 33a67fe38SAndy Shevchenko * Intel Lynxpoint PCH pinctrl/GPIO driver 4eb83479eSAndy Shevchenko * 53a67fe38SAndy Shevchenko * Copyright (c) 2012, 2019, Intel Corporation 63a67fe38SAndy Shevchenko * Authors: Mathias Nyman <mathias.nyman@linux.intel.com> 73a67fe38SAndy Shevchenko * Andy Shevchenko <andriy.shevchenko@linux.intel.com> 8eb83479eSAndy Shevchenko */ 9eb83479eSAndy Shevchenko 10eb83479eSAndy Shevchenko #include <linux/acpi.h> 11eb83479eSAndy Shevchenko #include <linux/bitops.h> 12eb83479eSAndy Shevchenko #include <linux/gpio/driver.h> 13eb83479eSAndy Shevchenko #include <linux/interrupt.h> 14eb83479eSAndy Shevchenko #include <linux/io.h> 15eb83479eSAndy Shevchenko #include <linux/kernel.h> 16eb83479eSAndy Shevchenko #include <linux/module.h> 17eb83479eSAndy Shevchenko #include <linux/platform_device.h> 18eb83479eSAndy Shevchenko #include <linux/pm_runtime.h> 19eb83479eSAndy Shevchenko #include <linux/slab.h> 20eb83479eSAndy Shevchenko #include <linux/types.h> 21eb83479eSAndy Shevchenko 22cecddda7SAndy Shevchenko #include <linux/pinctrl/pinctrl.h> 23cecddda7SAndy Shevchenko #include <linux/pinctrl/pinmux.h> 24cecddda7SAndy Shevchenko #include <linux/pinctrl/pinconf.h> 25cecddda7SAndy Shevchenko #include <linux/pinctrl/pinconf-generic.h> 26cecddda7SAndy Shevchenko 27cecddda7SAndy Shevchenko #include "pinctrl-intel.h" 28cecddda7SAndy Shevchenko 29cecddda7SAndy Shevchenko #define COMMUNITY(p, n) \ 30cecddda7SAndy Shevchenko { \ 31cecddda7SAndy Shevchenko .pin_base = (p), \ 32cecddda7SAndy Shevchenko .npins = (n), \ 33cecddda7SAndy Shevchenko } 34cecddda7SAndy Shevchenko 35cecddda7SAndy Shevchenko static const struct pinctrl_pin_desc lptlp_pins[] = { 36cecddda7SAndy Shevchenko PINCTRL_PIN(0, "GP0_UART1_RXD"), 37cecddda7SAndy Shevchenko PINCTRL_PIN(1, "GP1_UART1_TXD"), 38cecddda7SAndy Shevchenko PINCTRL_PIN(2, "GP2_UART1_RTSB"), 39cecddda7SAndy Shevchenko PINCTRL_PIN(3, "GP3_UART1_CTSB"), 40cecddda7SAndy Shevchenko PINCTRL_PIN(4, "GP4_I2C0_SDA"), 41cecddda7SAndy Shevchenko PINCTRL_PIN(5, "GP5_I2C0_SCL"), 42cecddda7SAndy Shevchenko PINCTRL_PIN(6, "GP6_I2C1_SDA"), 43cecddda7SAndy Shevchenko PINCTRL_PIN(7, "GP7_I2C1_SCL"), 44cecddda7SAndy Shevchenko PINCTRL_PIN(8, "GP8"), 45cecddda7SAndy Shevchenko PINCTRL_PIN(9, "GP9"), 46cecddda7SAndy Shevchenko PINCTRL_PIN(10, "GP10"), 47cecddda7SAndy Shevchenko PINCTRL_PIN(11, "GP11_SMBALERTB"), 48cecddda7SAndy Shevchenko PINCTRL_PIN(12, "GP12_LANPHYPC"), 49cecddda7SAndy Shevchenko PINCTRL_PIN(13, "GP13"), 50cecddda7SAndy Shevchenko PINCTRL_PIN(14, "GP14"), 51cecddda7SAndy Shevchenko PINCTRL_PIN(15, "GP15"), 52cecddda7SAndy Shevchenko PINCTRL_PIN(16, "GP16_MGPIO9"), 53cecddda7SAndy Shevchenko PINCTRL_PIN(17, "GP17_MGPIO10"), 54cecddda7SAndy Shevchenko PINCTRL_PIN(18, "GP18_SRC0CLKRQB"), 55cecddda7SAndy Shevchenko PINCTRL_PIN(19, "GP19_SRC1CLKRQB"), 56cecddda7SAndy Shevchenko PINCTRL_PIN(20, "GP20_SRC2CLKRQB"), 57cecddda7SAndy Shevchenko PINCTRL_PIN(21, "GP21_SRC3CLKRQB"), 58cecddda7SAndy Shevchenko PINCTRL_PIN(22, "GP22_SRC4CLKRQB_TRST2"), 59cecddda7SAndy Shevchenko PINCTRL_PIN(23, "GP23_SRC5CLKRQB_TDI2"), 60cecddda7SAndy Shevchenko PINCTRL_PIN(24, "GP24_MGPIO0"), 61cecddda7SAndy Shevchenko PINCTRL_PIN(25, "GP25_USBWAKEOUTB"), 62cecddda7SAndy Shevchenko PINCTRL_PIN(26, "GP26_MGPIO5"), 63cecddda7SAndy Shevchenko PINCTRL_PIN(27, "GP27_MGPIO6"), 64cecddda7SAndy Shevchenko PINCTRL_PIN(28, "GP28_MGPIO7"), 65cecddda7SAndy Shevchenko PINCTRL_PIN(29, "GP29_SLP_WLANB_MGPIO3"), 66cecddda7SAndy Shevchenko PINCTRL_PIN(30, "GP30_SUSWARNB_SUSPWRDNACK_MGPIO1"), 67cecddda7SAndy Shevchenko PINCTRL_PIN(31, "GP31_ACPRESENT_MGPIO2"), 68cecddda7SAndy Shevchenko PINCTRL_PIN(32, "GP32_CLKRUNB"), 69cecddda7SAndy Shevchenko PINCTRL_PIN(33, "GP33_DEVSLP0"), 70cecddda7SAndy Shevchenko PINCTRL_PIN(34, "GP34_SATA0XPCIE6L3B_SATA0GP"), 71cecddda7SAndy Shevchenko PINCTRL_PIN(35, "GP35_SATA1XPCIE6L2B_SATA1GP"), 72cecddda7SAndy Shevchenko PINCTRL_PIN(36, "GP36_SATA2XPCIE6L1B_SATA2GP"), 73cecddda7SAndy Shevchenko PINCTRL_PIN(37, "GP37_SATA3XPCIE6L0B_SATA3GP"), 74cecddda7SAndy Shevchenko PINCTRL_PIN(38, "GP38_DEVSLP1"), 75cecddda7SAndy Shevchenko PINCTRL_PIN(39, "GP39_DEVSLP2"), 76cecddda7SAndy Shevchenko PINCTRL_PIN(40, "GP40_OC0B"), 77cecddda7SAndy Shevchenko PINCTRL_PIN(41, "GP41_OC1B"), 78cecddda7SAndy Shevchenko PINCTRL_PIN(42, "GP42_OC2B"), 79cecddda7SAndy Shevchenko PINCTRL_PIN(43, "GP43_OC3B"), 80cecddda7SAndy Shevchenko PINCTRL_PIN(44, "GP44"), 81cecddda7SAndy Shevchenko PINCTRL_PIN(45, "GP45_TMS2"), 82cecddda7SAndy Shevchenko PINCTRL_PIN(46, "GP46_TDO2"), 83cecddda7SAndy Shevchenko PINCTRL_PIN(47, "GP47"), 84cecddda7SAndy Shevchenko PINCTRL_PIN(48, "GP48"), 85cecddda7SAndy Shevchenko PINCTRL_PIN(49, "GP49"), 86cecddda7SAndy Shevchenko PINCTRL_PIN(50, "GP50"), 87cecddda7SAndy Shevchenko PINCTRL_PIN(51, "GP51_GSXDOUT"), 88cecddda7SAndy Shevchenko PINCTRL_PIN(52, "GP52_GSXSLOAD"), 89cecddda7SAndy Shevchenko PINCTRL_PIN(53, "GP53_GSXDIN"), 90cecddda7SAndy Shevchenko PINCTRL_PIN(54, "GP54_GSXSRESETB"), 91cecddda7SAndy Shevchenko PINCTRL_PIN(55, "GP55_GSXCLK"), 92cecddda7SAndy Shevchenko PINCTRL_PIN(56, "GP56"), 93cecddda7SAndy Shevchenko PINCTRL_PIN(57, "GP57"), 94cecddda7SAndy Shevchenko PINCTRL_PIN(58, "GP58"), 95cecddda7SAndy Shevchenko PINCTRL_PIN(59, "GP59"), 96cecddda7SAndy Shevchenko PINCTRL_PIN(60, "GP60_SML0ALERTB_MGPIO4"), 97cecddda7SAndy Shevchenko PINCTRL_PIN(61, "GP61_SUS_STATB"), 98cecddda7SAndy Shevchenko PINCTRL_PIN(62, "GP62_SUSCLK"), 99cecddda7SAndy Shevchenko PINCTRL_PIN(63, "GP63_SLP_S5B"), 100cecddda7SAndy Shevchenko PINCTRL_PIN(64, "GP64_SDIO_CLK"), 101cecddda7SAndy Shevchenko PINCTRL_PIN(65, "GP65_SDIO_CMD"), 102cecddda7SAndy Shevchenko PINCTRL_PIN(66, "GP66_SDIO_D0"), 103cecddda7SAndy Shevchenko PINCTRL_PIN(67, "GP67_SDIO_D1"), 104cecddda7SAndy Shevchenko PINCTRL_PIN(68, "GP68_SDIO_D2"), 105cecddda7SAndy Shevchenko PINCTRL_PIN(69, "GP69_SDIO_D3"), 106cecddda7SAndy Shevchenko PINCTRL_PIN(70, "GP70_SDIO_POWER_EN"), 107cecddda7SAndy Shevchenko PINCTRL_PIN(71, "GP71_MPHYPC"), 108cecddda7SAndy Shevchenko PINCTRL_PIN(72, "GP72_BATLOWB"), 109cecddda7SAndy Shevchenko PINCTRL_PIN(73, "GP73_SML1ALERTB_PCHHOTB_MGPIO8"), 110cecddda7SAndy Shevchenko PINCTRL_PIN(74, "GP74_SML1DATA_MGPIO12"), 111cecddda7SAndy Shevchenko PINCTRL_PIN(75, "GP75_SML1CLK_MGPIO11"), 112cecddda7SAndy Shevchenko PINCTRL_PIN(76, "GP76_BMBUSYB"), 113cecddda7SAndy Shevchenko PINCTRL_PIN(77, "GP77_PIRQAB"), 114cecddda7SAndy Shevchenko PINCTRL_PIN(78, "GP78_PIRQBB"), 115cecddda7SAndy Shevchenko PINCTRL_PIN(79, "GP79_PIRQCB"), 116cecddda7SAndy Shevchenko PINCTRL_PIN(80, "GP80_PIRQDB"), 117cecddda7SAndy Shevchenko PINCTRL_PIN(81, "GP81_SPKR"), 118cecddda7SAndy Shevchenko PINCTRL_PIN(82, "GP82_RCINB"), 119cecddda7SAndy Shevchenko PINCTRL_PIN(83, "GP83_GSPI0_CSB"), 120cecddda7SAndy Shevchenko PINCTRL_PIN(84, "GP84_GSPI0_CLK"), 121cecddda7SAndy Shevchenko PINCTRL_PIN(85, "GP85_GSPI0_MISO"), 122cecddda7SAndy Shevchenko PINCTRL_PIN(86, "GP86_GSPI0_MOSI"), 123cecddda7SAndy Shevchenko PINCTRL_PIN(87, "GP87_GSPI1_CSB"), 124cecddda7SAndy Shevchenko PINCTRL_PIN(88, "GP88_GSPI1_CLK"), 125cecddda7SAndy Shevchenko PINCTRL_PIN(89, "GP89_GSPI1_MISO"), 126cecddda7SAndy Shevchenko PINCTRL_PIN(90, "GP90_GSPI1_MOSI"), 127cecddda7SAndy Shevchenko PINCTRL_PIN(91, "GP91_UART0_RXD"), 128cecddda7SAndy Shevchenko PINCTRL_PIN(92, "GP92_UART0_TXD"), 129cecddda7SAndy Shevchenko PINCTRL_PIN(93, "GP93_UART0_RTSB"), 130cecddda7SAndy Shevchenko PINCTRL_PIN(94, "GP94_UART0_CTSB"), 131cecddda7SAndy Shevchenko }; 132cecddda7SAndy Shevchenko 133cecddda7SAndy Shevchenko static const struct intel_community lptlp_communities[] = { 134cecddda7SAndy Shevchenko COMMUNITY(0, 95), 135cecddda7SAndy Shevchenko }; 136cecddda7SAndy Shevchenko 137cecddda7SAndy Shevchenko static const struct intel_pinctrl_soc_data lptlp_soc_data = { 138cecddda7SAndy Shevchenko .pins = lptlp_pins, 139cecddda7SAndy Shevchenko .npins = ARRAY_SIZE(lptlp_pins), 140cecddda7SAndy Shevchenko .communities = lptlp_communities, 141cecddda7SAndy Shevchenko .ncommunities = ARRAY_SIZE(lptlp_communities), 142cecddda7SAndy Shevchenko }; 143cecddda7SAndy Shevchenko 1447c0bc7bbSAndy Shevchenko /* LynxPoint chipset has support for 95 GPIO pins */ 145eb83479eSAndy Shevchenko 1467c0bc7bbSAndy Shevchenko #define LP_NUM_GPIO 95 147eb83479eSAndy Shevchenko 148eb83479eSAndy Shevchenko /* Bitmapped register offsets */ 149eb83479eSAndy Shevchenko #define LP_ACPI_OWNED 0x00 /* Bitmap, set by bios, 0: pin reserved for ACPI */ 1507f32d370SAndy Shevchenko #define LP_IRQ2IOXAPIC 0x10 /* Bitmap, set by bios, 1: pin routed to IOxAPIC */ 151eb83479eSAndy Shevchenko #define LP_GC 0x7C /* set APIC IRQ to IRQ14 or IRQ15 for all pins */ 152eb83479eSAndy Shevchenko #define LP_INT_STAT 0x80 153eb83479eSAndy Shevchenko #define LP_INT_ENABLE 0x90 154eb83479eSAndy Shevchenko 155eb83479eSAndy Shevchenko /* Each pin has two 32 bit config registers, starting at 0x100 */ 156eb83479eSAndy Shevchenko #define LP_CONFIG1 0x100 157eb83479eSAndy Shevchenko #define LP_CONFIG2 0x104 158eb83479eSAndy Shevchenko 159eb83479eSAndy Shevchenko /* LP_CONFIG1 reg bits */ 160eb83479eSAndy Shevchenko #define OUT_LVL_BIT BIT(31) 161eb83479eSAndy Shevchenko #define IN_LVL_BIT BIT(30) 162eb83479eSAndy Shevchenko #define TRIG_SEL_BIT BIT(4) /* 0: Edge, 1: Level */ 163eb83479eSAndy Shevchenko #define INT_INV_BIT BIT(3) /* Invert interrupt triggering */ 164eb83479eSAndy Shevchenko #define DIR_BIT BIT(2) /* 0: Output, 1: Input */ 16576347d7aSAndy Shevchenko #define USE_SEL_MASK GENMASK(1, 0) /* 0: Native, 1: GPIO, ... */ 16676347d7aSAndy Shevchenko #define USE_SEL_NATIVE (0 << 0) 16776347d7aSAndy Shevchenko #define USE_SEL_GPIO (1 << 0) 168eb83479eSAndy Shevchenko 169eb83479eSAndy Shevchenko /* LP_CONFIG2 reg bits */ 170eb83479eSAndy Shevchenko #define GPINDIS_BIT BIT(2) /* disable input sensing */ 1717f32d370SAndy Shevchenko #define GPIWP_MASK GENMASK(1, 0) /* weak pull options */ 1727f32d370SAndy Shevchenko #define GPIWP_NONE 0 /* none */ 1737f32d370SAndy Shevchenko #define GPIWP_DOWN 1 /* weak pull down */ 1747f32d370SAndy Shevchenko #define GPIWP_UP 2 /* weak pull up */ 175eb83479eSAndy Shevchenko 176eb83479eSAndy Shevchenko /* 177eb83479eSAndy Shevchenko * Lynxpoint gpios are controlled through both bitmapped registers and 178eb83479eSAndy Shevchenko * per gpio specific registers. The bitmapped registers are in chunks of 1797c0bc7bbSAndy Shevchenko * 3 x 32bit registers to cover all 95 GPIOs 180eb83479eSAndy Shevchenko * 181eb83479eSAndy Shevchenko * per gpio specific registers consist of two 32bit registers per gpio 1827c0bc7bbSAndy Shevchenko * (LP_CONFIG1 and LP_CONFIG2), with 95 GPIOs there's a total of 1837c0bc7bbSAndy Shevchenko * 190 config registers. 184eb83479eSAndy Shevchenko * 185eb83479eSAndy Shevchenko * A simplified view of the register layout look like this: 186eb83479eSAndy Shevchenko * 187eb83479eSAndy Shevchenko * LP_ACPI_OWNED[31:0] gpio ownerships for gpios 0-31 (bitmapped registers) 188eb83479eSAndy Shevchenko * LP_ACPI_OWNED[63:32] gpio ownerships for gpios 32-63 189eb83479eSAndy Shevchenko * LP_ACPI_OWNED[94:64] gpio ownerships for gpios 63-94 190eb83479eSAndy Shevchenko * ... 191eb83479eSAndy Shevchenko * LP_INT_ENABLE[31:0] ... 1927c0bc7bbSAndy Shevchenko * LP_INT_ENABLE[63:32] ... 193eb83479eSAndy Shevchenko * LP_INT_ENABLE[94:64] ... 194eb83479eSAndy Shevchenko * LP0_CONFIG1 (gpio 0) config1 reg for gpio 0 (per gpio registers) 195eb83479eSAndy Shevchenko * LP0_CONFIG2 (gpio 0) config2 reg for gpio 0 196eb83479eSAndy Shevchenko * LP1_CONFIG1 (gpio 1) config1 reg for gpio 1 197eb83479eSAndy Shevchenko * LP1_CONFIG2 (gpio 1) config2 reg for gpio 1 198eb83479eSAndy Shevchenko * LP2_CONFIG1 (gpio 2) ... 199eb83479eSAndy Shevchenko * LP2_CONFIG2 (gpio 2) ... 200eb83479eSAndy Shevchenko * ... 201eb83479eSAndy Shevchenko * LP94_CONFIG1 (gpio 94) ... 202eb83479eSAndy Shevchenko * LP94_CONFIG2 (gpio 94) ... 2037f32d370SAndy Shevchenko * 2047f32d370SAndy Shevchenko * IOxAPIC redirection map applies only for gpio 8-10, 13-14, 45-55. 205eb83479eSAndy Shevchenko */ 206eb83479eSAndy Shevchenko 20718213ad4SAndy Shevchenko static struct intel_community *lp_get_community(struct intel_pinctrl *lg, 20818213ad4SAndy Shevchenko unsigned int pin) 20918213ad4SAndy Shevchenko { 21018213ad4SAndy Shevchenko struct intel_community *comm; 21118213ad4SAndy Shevchenko int i; 21218213ad4SAndy Shevchenko 21318213ad4SAndy Shevchenko for (i = 0; i < lg->ncommunities; i++) { 21418213ad4SAndy Shevchenko comm = &lg->communities[i]; 21518213ad4SAndy Shevchenko if (pin < comm->pin_base + comm->npins && pin >= comm->pin_base) 21618213ad4SAndy Shevchenko return comm; 21718213ad4SAndy Shevchenko } 21818213ad4SAndy Shevchenko 21918213ad4SAndy Shevchenko return NULL; 22018213ad4SAndy Shevchenko } 22118213ad4SAndy Shevchenko 222c35f463aSAndy Shevchenko static void __iomem *lp_gpio_reg(struct gpio_chip *chip, unsigned int offset, 223eb83479eSAndy Shevchenko int reg) 224eb83479eSAndy Shevchenko { 22518213ad4SAndy Shevchenko struct intel_pinctrl *lg = gpiochip_get_data(chip); 22618213ad4SAndy Shevchenko struct intel_community *comm; 227eb83479eSAndy Shevchenko int reg_offset; 228eb83479eSAndy Shevchenko 22918213ad4SAndy Shevchenko comm = lp_get_community(lg, offset); 23018213ad4SAndy Shevchenko if (!comm) 23118213ad4SAndy Shevchenko return NULL; 23218213ad4SAndy Shevchenko 23318213ad4SAndy Shevchenko offset -= comm->pin_base; 23418213ad4SAndy Shevchenko 235eb83479eSAndy Shevchenko if (reg == LP_CONFIG1 || reg == LP_CONFIG2) 236eb83479eSAndy Shevchenko /* per gpio specific config registers */ 237eb83479eSAndy Shevchenko reg_offset = offset * 8; 238eb83479eSAndy Shevchenko else 239eb83479eSAndy Shevchenko /* bitmapped registers */ 240eb83479eSAndy Shevchenko reg_offset = (offset / 32) * 4; 241eb83479eSAndy Shevchenko 24218213ad4SAndy Shevchenko return comm->regs + reg_offset + reg; 243eb83479eSAndy Shevchenko } 244eb83479eSAndy Shevchenko 24518213ad4SAndy Shevchenko static bool lp_gpio_acpi_use(struct intel_pinctrl *lg, unsigned int pin) 24621a06495SAndy Shevchenko { 24721a06495SAndy Shevchenko void __iomem *acpi_use; 24821a06495SAndy Shevchenko 24921a06495SAndy Shevchenko acpi_use = lp_gpio_reg(&lg->chip, pin, LP_ACPI_OWNED); 25021a06495SAndy Shevchenko if (!acpi_use) 25121a06495SAndy Shevchenko return true; 25221a06495SAndy Shevchenko 25321a06495SAndy Shevchenko return !(ioread32(acpi_use) & BIT(pin % 32)); 25421a06495SAndy Shevchenko } 25521a06495SAndy Shevchenko 2567f32d370SAndy Shevchenko static bool lp_gpio_ioxapic_use(struct gpio_chip *chip, unsigned int offset) 2577f32d370SAndy Shevchenko { 2587f32d370SAndy Shevchenko void __iomem *ioxapic_use = lp_gpio_reg(chip, offset, LP_IRQ2IOXAPIC); 2597f32d370SAndy Shevchenko u32 value; 2607f32d370SAndy Shevchenko 2617f32d370SAndy Shevchenko value = ioread32(ioxapic_use); 2627f32d370SAndy Shevchenko 2637f32d370SAndy Shevchenko if (offset >= 8 && offset <= 10) 2647f32d370SAndy Shevchenko return !!(value & BIT(offset - 8 + 0)); 2657f32d370SAndy Shevchenko if (offset >= 13 && offset <= 14) 2667f32d370SAndy Shevchenko return !!(value & BIT(offset - 13 + 3)); 2677f32d370SAndy Shevchenko if (offset >= 45 && offset <= 55) 2687f32d370SAndy Shevchenko return !!(value & BIT(offset - 45 + 5)); 2697f32d370SAndy Shevchenko 2707f32d370SAndy Shevchenko return false; 2717f32d370SAndy Shevchenko } 2727f32d370SAndy Shevchenko 2737f32d370SAndy Shevchenko static int lp_get_groups_count(struct pinctrl_dev *pctldev) 2747f32d370SAndy Shevchenko { 2757f32d370SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 2767f32d370SAndy Shevchenko 2777f32d370SAndy Shevchenko return lg->soc->ngroups; 2787f32d370SAndy Shevchenko } 2797f32d370SAndy Shevchenko 2807f32d370SAndy Shevchenko static const char *lp_get_group_name(struct pinctrl_dev *pctldev, 2817f32d370SAndy Shevchenko unsigned int selector) 2827f32d370SAndy Shevchenko { 2837f32d370SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 2847f32d370SAndy Shevchenko 2857f32d370SAndy Shevchenko return lg->soc->groups[selector].name; 2867f32d370SAndy Shevchenko } 2877f32d370SAndy Shevchenko 2887f32d370SAndy Shevchenko static int lp_get_group_pins(struct pinctrl_dev *pctldev, 2897f32d370SAndy Shevchenko unsigned int selector, 2907f32d370SAndy Shevchenko const unsigned int **pins, 2917f32d370SAndy Shevchenko unsigned int *num_pins) 2927f32d370SAndy Shevchenko { 2937f32d370SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 2947f32d370SAndy Shevchenko 2957f32d370SAndy Shevchenko *pins = lg->soc->groups[selector].pins; 2967f32d370SAndy Shevchenko *num_pins = lg->soc->groups[selector].npins; 2977f32d370SAndy Shevchenko 2987f32d370SAndy Shevchenko return 0; 2997f32d370SAndy Shevchenko } 3007f32d370SAndy Shevchenko 30103d9eca7SAndy Shevchenko static void lp_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, 30203d9eca7SAndy Shevchenko unsigned int pin) 30303d9eca7SAndy Shevchenko { 30403d9eca7SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 30503d9eca7SAndy Shevchenko void __iomem *reg = lp_gpio_reg(&lg->chip, pin, LP_CONFIG1); 30603d9eca7SAndy Shevchenko void __iomem *conf2 = lp_gpio_reg(&lg->chip, pin, LP_CONFIG2); 30703d9eca7SAndy Shevchenko u32 value, mode; 30803d9eca7SAndy Shevchenko 30903d9eca7SAndy Shevchenko value = ioread32(reg); 31003d9eca7SAndy Shevchenko 31103d9eca7SAndy Shevchenko mode = value & USE_SEL_MASK; 31203d9eca7SAndy Shevchenko if (mode == USE_SEL_GPIO) 31303d9eca7SAndy Shevchenko seq_puts(s, "GPIO "); 31403d9eca7SAndy Shevchenko else 31503d9eca7SAndy Shevchenko seq_printf(s, "mode %d ", mode); 31603d9eca7SAndy Shevchenko 31703d9eca7SAndy Shevchenko seq_printf(s, "0x%08x 0x%08x", value, ioread32(conf2)); 31803d9eca7SAndy Shevchenko 31903d9eca7SAndy Shevchenko if (lp_gpio_acpi_use(lg, pin)) 32003d9eca7SAndy Shevchenko seq_puts(s, " [ACPI]"); 32103d9eca7SAndy Shevchenko } 32203d9eca7SAndy Shevchenko 3237f32d370SAndy Shevchenko static const struct pinctrl_ops lptlp_pinctrl_ops = { 3247f32d370SAndy Shevchenko .get_groups_count = lp_get_groups_count, 3257f32d370SAndy Shevchenko .get_group_name = lp_get_group_name, 3267f32d370SAndy Shevchenko .get_group_pins = lp_get_group_pins, 32703d9eca7SAndy Shevchenko .pin_dbg_show = lp_pin_dbg_show, 3287f32d370SAndy Shevchenko }; 3297f32d370SAndy Shevchenko 3307f32d370SAndy Shevchenko static int lp_get_functions_count(struct pinctrl_dev *pctldev) 3317f32d370SAndy Shevchenko { 3327f32d370SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 3337f32d370SAndy Shevchenko 3347f32d370SAndy Shevchenko return lg->soc->nfunctions; 3357f32d370SAndy Shevchenko } 3367f32d370SAndy Shevchenko 3377f32d370SAndy Shevchenko static const char *lp_get_function_name(struct pinctrl_dev *pctldev, 3387f32d370SAndy Shevchenko unsigned int selector) 3397f32d370SAndy Shevchenko { 3407f32d370SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 3417f32d370SAndy Shevchenko 3427f32d370SAndy Shevchenko return lg->soc->functions[selector].name; 3437f32d370SAndy Shevchenko } 3447f32d370SAndy Shevchenko 3457f32d370SAndy Shevchenko static int lp_get_function_groups(struct pinctrl_dev *pctldev, 3467f32d370SAndy Shevchenko unsigned int selector, 3477f32d370SAndy Shevchenko const char * const **groups, 3487f32d370SAndy Shevchenko unsigned int *num_groups) 3497f32d370SAndy Shevchenko { 3507f32d370SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 3517f32d370SAndy Shevchenko 3527f32d370SAndy Shevchenko *groups = lg->soc->functions[selector].groups; 3537f32d370SAndy Shevchenko *num_groups = lg->soc->functions[selector].ngroups; 3547f32d370SAndy Shevchenko 3557f32d370SAndy Shevchenko return 0; 3567f32d370SAndy Shevchenko } 3577f32d370SAndy Shevchenko 3587f32d370SAndy Shevchenko static int lp_pinmux_set_mux(struct pinctrl_dev *pctldev, 3597f32d370SAndy Shevchenko unsigned int function, unsigned int group) 3607f32d370SAndy Shevchenko { 3617f32d370SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 3627f32d370SAndy Shevchenko const struct intel_pingroup *grp = &lg->soc->groups[group]; 3637f32d370SAndy Shevchenko unsigned long flags; 3647f32d370SAndy Shevchenko int i; 3657f32d370SAndy Shevchenko 3667f32d370SAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 3677f32d370SAndy Shevchenko 3687f32d370SAndy Shevchenko /* Now enable the mux setting for each pin in the group */ 3697f32d370SAndy Shevchenko for (i = 0; i < grp->npins; i++) { 3707f32d370SAndy Shevchenko void __iomem *reg = lp_gpio_reg(&lg->chip, grp->pins[i], LP_CONFIG1); 3717f32d370SAndy Shevchenko u32 value; 3727f32d370SAndy Shevchenko 3737f32d370SAndy Shevchenko value = ioread32(reg); 3747f32d370SAndy Shevchenko 3757f32d370SAndy Shevchenko value &= ~USE_SEL_MASK; 3767f32d370SAndy Shevchenko if (grp->modes) 3777f32d370SAndy Shevchenko value |= grp->modes[i]; 3787f32d370SAndy Shevchenko else 3797f32d370SAndy Shevchenko value |= grp->mode; 3807f32d370SAndy Shevchenko 3817f32d370SAndy Shevchenko iowrite32(value, reg); 3827f32d370SAndy Shevchenko } 3837f32d370SAndy Shevchenko 3847f32d370SAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 3857f32d370SAndy Shevchenko 3867f32d370SAndy Shevchenko return 0; 3877f32d370SAndy Shevchenko } 3887f32d370SAndy Shevchenko 389*0472567bSAndy Shevchenko static void lp_gpio_enable_input(void __iomem *reg) 390*0472567bSAndy Shevchenko { 391*0472567bSAndy Shevchenko iowrite32(ioread32(reg) & ~GPINDIS_BIT, reg); 392*0472567bSAndy Shevchenko } 393*0472567bSAndy Shevchenko 394*0472567bSAndy Shevchenko static void lp_gpio_disable_input(void __iomem *reg) 395*0472567bSAndy Shevchenko { 396*0472567bSAndy Shevchenko iowrite32(ioread32(reg) | GPINDIS_BIT, reg); 397*0472567bSAndy Shevchenko } 398*0472567bSAndy Shevchenko 3997f32d370SAndy Shevchenko static int lp_gpio_request_enable(struct pinctrl_dev *pctldev, 4007f32d370SAndy Shevchenko struct pinctrl_gpio_range *range, 4017f32d370SAndy Shevchenko unsigned int pin) 4027f32d370SAndy Shevchenko { 4037f32d370SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 4047f32d370SAndy Shevchenko void __iomem *reg = lp_gpio_reg(&lg->chip, pin, LP_CONFIG1); 4057f32d370SAndy Shevchenko void __iomem *conf2 = lp_gpio_reg(&lg->chip, pin, LP_CONFIG2); 4067f32d370SAndy Shevchenko unsigned long flags; 4077f32d370SAndy Shevchenko u32 value; 4087f32d370SAndy Shevchenko 4097f32d370SAndy Shevchenko pm_runtime_get(lg->dev); 4107f32d370SAndy Shevchenko 4117f32d370SAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 4127f32d370SAndy Shevchenko 4137f32d370SAndy Shevchenko /* 4147f32d370SAndy Shevchenko * Reconfigure pin to GPIO mode if needed and issue a warning, 4157f32d370SAndy Shevchenko * since we expect firmware to configure it properly. 4167f32d370SAndy Shevchenko */ 4177f32d370SAndy Shevchenko value = ioread32(reg); 4187f32d370SAndy Shevchenko if ((value & USE_SEL_MASK) != USE_SEL_GPIO) { 4197f32d370SAndy Shevchenko iowrite32((value & USE_SEL_MASK) | USE_SEL_GPIO, reg); 4207f32d370SAndy Shevchenko dev_warn(lg->dev, FW_BUG "pin %u forcibly reconfigured as GPIO\n", pin); 4217f32d370SAndy Shevchenko } 4227f32d370SAndy Shevchenko 4237f32d370SAndy Shevchenko /* Enable input sensing */ 424*0472567bSAndy Shevchenko lp_gpio_enable_input(conf2); 4257f32d370SAndy Shevchenko 4267f32d370SAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 4277f32d370SAndy Shevchenko 4287f32d370SAndy Shevchenko return 0; 4297f32d370SAndy Shevchenko } 4307f32d370SAndy Shevchenko 4317f32d370SAndy Shevchenko static void lp_gpio_disable_free(struct pinctrl_dev *pctldev, 4327f32d370SAndy Shevchenko struct pinctrl_gpio_range *range, 4337f32d370SAndy Shevchenko unsigned int pin) 4347f32d370SAndy Shevchenko { 4357f32d370SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 4367f32d370SAndy Shevchenko void __iomem *conf2 = lp_gpio_reg(&lg->chip, pin, LP_CONFIG2); 4377f32d370SAndy Shevchenko unsigned long flags; 4387f32d370SAndy Shevchenko 4397f32d370SAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 4407f32d370SAndy Shevchenko 4417f32d370SAndy Shevchenko /* Disable input sensing */ 442*0472567bSAndy Shevchenko lp_gpio_disable_input(conf2); 4437f32d370SAndy Shevchenko 4447f32d370SAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 4457f32d370SAndy Shevchenko 4467f32d370SAndy Shevchenko pm_runtime_put(lg->dev); 4477f32d370SAndy Shevchenko } 4487f32d370SAndy Shevchenko 4497f32d370SAndy Shevchenko static int lp_gpio_set_direction(struct pinctrl_dev *pctldev, 4507f32d370SAndy Shevchenko struct pinctrl_gpio_range *range, 4517f32d370SAndy Shevchenko unsigned int pin, bool input) 4527f32d370SAndy Shevchenko { 4537f32d370SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 4547f32d370SAndy Shevchenko void __iomem *reg = lp_gpio_reg(&lg->chip, pin, LP_CONFIG1); 4557f32d370SAndy Shevchenko unsigned long flags; 4567f32d370SAndy Shevchenko u32 value; 4577f32d370SAndy Shevchenko 4587f32d370SAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 4597f32d370SAndy Shevchenko 4607f32d370SAndy Shevchenko value = ioread32(reg); 4617f32d370SAndy Shevchenko value &= ~DIR_BIT; 4627f32d370SAndy Shevchenko if (input) { 4637f32d370SAndy Shevchenko value |= DIR_BIT; 4647f32d370SAndy Shevchenko } else { 4657f32d370SAndy Shevchenko /* 4667f32d370SAndy Shevchenko * Before making any direction modifications, do a check if GPIO 4677f32d370SAndy Shevchenko * is set for direct IRQ. On Lynxpoint, setting GPIO to output 4687f32d370SAndy Shevchenko * does not make sense, so let's at least warn the caller before 4697f32d370SAndy Shevchenko * they shoot themselves in the foot. 4707f32d370SAndy Shevchenko */ 4717f32d370SAndy Shevchenko WARN(lp_gpio_ioxapic_use(&lg->chip, pin), 4727f32d370SAndy Shevchenko "Potential Error: Setting GPIO to output with IOxAPIC redirection"); 4737f32d370SAndy Shevchenko } 4747f32d370SAndy Shevchenko iowrite32(value, reg); 4757f32d370SAndy Shevchenko 4767f32d370SAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 4777f32d370SAndy Shevchenko 4787f32d370SAndy Shevchenko return 0; 4797f32d370SAndy Shevchenko } 4807f32d370SAndy Shevchenko 4817f32d370SAndy Shevchenko static const struct pinmux_ops lptlp_pinmux_ops = { 4827f32d370SAndy Shevchenko .get_functions_count = lp_get_functions_count, 4837f32d370SAndy Shevchenko .get_function_name = lp_get_function_name, 4847f32d370SAndy Shevchenko .get_function_groups = lp_get_function_groups, 4857f32d370SAndy Shevchenko .set_mux = lp_pinmux_set_mux, 4867f32d370SAndy Shevchenko .gpio_request_enable = lp_gpio_request_enable, 4877f32d370SAndy Shevchenko .gpio_disable_free = lp_gpio_disable_free, 4887f32d370SAndy Shevchenko .gpio_set_direction = lp_gpio_set_direction, 4897f32d370SAndy Shevchenko }; 4907f32d370SAndy Shevchenko 4917f32d370SAndy Shevchenko static int lp_pin_config_get(struct pinctrl_dev *pctldev, unsigned int pin, 4927f32d370SAndy Shevchenko unsigned long *config) 4937f32d370SAndy Shevchenko { 4947f32d370SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 4957f32d370SAndy Shevchenko void __iomem *conf2 = lp_gpio_reg(&lg->chip, pin, LP_CONFIG2); 4967f32d370SAndy Shevchenko enum pin_config_param param = pinconf_to_config_param(*config); 4977f32d370SAndy Shevchenko unsigned long flags; 4987f32d370SAndy Shevchenko u32 value, pull; 4997f32d370SAndy Shevchenko u16 arg = 0; 5007f32d370SAndy Shevchenko 5017f32d370SAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 5027f32d370SAndy Shevchenko value = ioread32(conf2); 5037f32d370SAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 5047f32d370SAndy Shevchenko 5057f32d370SAndy Shevchenko pull = value & GPIWP_MASK; 5067f32d370SAndy Shevchenko 5077f32d370SAndy Shevchenko switch (param) { 5087f32d370SAndy Shevchenko case PIN_CONFIG_BIAS_DISABLE: 5097f32d370SAndy Shevchenko if (pull) 5107f32d370SAndy Shevchenko return -EINVAL; 5117f32d370SAndy Shevchenko break; 5127f32d370SAndy Shevchenko case PIN_CONFIG_BIAS_PULL_DOWN: 5137f32d370SAndy Shevchenko if (pull != GPIWP_DOWN) 5147f32d370SAndy Shevchenko return -EINVAL; 5157f32d370SAndy Shevchenko 5167f32d370SAndy Shevchenko arg = 1; 5177f32d370SAndy Shevchenko break; 5187f32d370SAndy Shevchenko case PIN_CONFIG_BIAS_PULL_UP: 5197f32d370SAndy Shevchenko if (pull != GPIWP_UP) 5207f32d370SAndy Shevchenko return -EINVAL; 5217f32d370SAndy Shevchenko 5227f32d370SAndy Shevchenko arg = 1; 5237f32d370SAndy Shevchenko break; 5247f32d370SAndy Shevchenko default: 5257f32d370SAndy Shevchenko return -ENOTSUPP; 5267f32d370SAndy Shevchenko } 5277f32d370SAndy Shevchenko 5287f32d370SAndy Shevchenko *config = pinconf_to_config_packed(param, arg); 5297f32d370SAndy Shevchenko 5307f32d370SAndy Shevchenko return 0; 5317f32d370SAndy Shevchenko } 5327f32d370SAndy Shevchenko 5337f32d370SAndy Shevchenko static int lp_pin_config_set(struct pinctrl_dev *pctldev, unsigned int pin, 5347f32d370SAndy Shevchenko unsigned long *configs, unsigned int num_configs) 5357f32d370SAndy Shevchenko { 5367f32d370SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 5377f32d370SAndy Shevchenko void __iomem *conf2 = lp_gpio_reg(&lg->chip, pin, LP_CONFIG2); 5387f32d370SAndy Shevchenko enum pin_config_param param; 5397f32d370SAndy Shevchenko unsigned long flags; 5407f32d370SAndy Shevchenko int i, ret = 0; 5417f32d370SAndy Shevchenko u32 value; 5427f32d370SAndy Shevchenko 5437f32d370SAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 5447f32d370SAndy Shevchenko 5457f32d370SAndy Shevchenko value = ioread32(conf2); 5467f32d370SAndy Shevchenko 5477f32d370SAndy Shevchenko for (i = 0; i < num_configs; i++) { 5487f32d370SAndy Shevchenko param = pinconf_to_config_param(configs[i]); 5497f32d370SAndy Shevchenko 5507f32d370SAndy Shevchenko switch (param) { 5517f32d370SAndy Shevchenko case PIN_CONFIG_BIAS_DISABLE: 5527f32d370SAndy Shevchenko value &= ~GPIWP_MASK; 5537f32d370SAndy Shevchenko break; 5547f32d370SAndy Shevchenko case PIN_CONFIG_BIAS_PULL_DOWN: 5557f32d370SAndy Shevchenko value &= ~GPIWP_MASK; 5567f32d370SAndy Shevchenko value |= GPIWP_DOWN; 5577f32d370SAndy Shevchenko break; 5587f32d370SAndy Shevchenko case PIN_CONFIG_BIAS_PULL_UP: 5597f32d370SAndy Shevchenko value &= ~GPIWP_MASK; 5607f32d370SAndy Shevchenko value |= GPIWP_UP; 5617f32d370SAndy Shevchenko break; 5627f32d370SAndy Shevchenko default: 5637f32d370SAndy Shevchenko ret = -ENOTSUPP; 5647f32d370SAndy Shevchenko } 5657f32d370SAndy Shevchenko 5667f32d370SAndy Shevchenko if (ret) 5677f32d370SAndy Shevchenko break; 5687f32d370SAndy Shevchenko } 5697f32d370SAndy Shevchenko 5707f32d370SAndy Shevchenko if (!ret) 5717f32d370SAndy Shevchenko iowrite32(value, conf2); 5727f32d370SAndy Shevchenko 5737f32d370SAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 5747f32d370SAndy Shevchenko 5757f32d370SAndy Shevchenko return ret; 5767f32d370SAndy Shevchenko } 5777f32d370SAndy Shevchenko 5787f32d370SAndy Shevchenko static const struct pinconf_ops lptlp_pinconf_ops = { 5797f32d370SAndy Shevchenko .is_generic = true, 5807f32d370SAndy Shevchenko .pin_config_get = lp_pin_config_get, 5817f32d370SAndy Shevchenko .pin_config_set = lp_pin_config_set, 5827f32d370SAndy Shevchenko }; 5837f32d370SAndy Shevchenko 5847f32d370SAndy Shevchenko static const struct pinctrl_desc lptlp_pinctrl_desc = { 5857f32d370SAndy Shevchenko .pctlops = &lptlp_pinctrl_ops, 5867f32d370SAndy Shevchenko .pmxops = &lptlp_pinmux_ops, 5877f32d370SAndy Shevchenko .confops = &lptlp_pinconf_ops, 5887f32d370SAndy Shevchenko .owner = THIS_MODULE, 5897f32d370SAndy Shevchenko }; 5907f32d370SAndy Shevchenko 591c35f463aSAndy Shevchenko static int lp_gpio_get(struct gpio_chip *chip, unsigned int offset) 592eb83479eSAndy Shevchenko { 593e1940adeSAndy Shevchenko void __iomem *reg = lp_gpio_reg(chip, offset, LP_CONFIG1); 594e1940adeSAndy Shevchenko return !!(ioread32(reg) & IN_LVL_BIT); 595eb83479eSAndy Shevchenko } 596eb83479eSAndy Shevchenko 597c35f463aSAndy Shevchenko static void lp_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) 598eb83479eSAndy Shevchenko { 59918213ad4SAndy Shevchenko struct intel_pinctrl *lg = gpiochip_get_data(chip); 600e1940adeSAndy Shevchenko void __iomem *reg = lp_gpio_reg(chip, offset, LP_CONFIG1); 601eb83479eSAndy Shevchenko unsigned long flags; 602eb83479eSAndy Shevchenko 603b2e05d63SAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 604eb83479eSAndy Shevchenko 605eb83479eSAndy Shevchenko if (value) 606e1940adeSAndy Shevchenko iowrite32(ioread32(reg) | OUT_LVL_BIT, reg); 607eb83479eSAndy Shevchenko else 608e1940adeSAndy Shevchenko iowrite32(ioread32(reg) & ~OUT_LVL_BIT, reg); 609eb83479eSAndy Shevchenko 610b2e05d63SAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 611eb83479eSAndy Shevchenko } 612eb83479eSAndy Shevchenko 613c35f463aSAndy Shevchenko static int lp_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) 614eb83479eSAndy Shevchenko { 61564e14e90SAndy Shevchenko return pinctrl_gpio_direction_input(chip->base + offset); 616eb83479eSAndy Shevchenko } 617eb83479eSAndy Shevchenko 618c35f463aSAndy Shevchenko static int lp_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, 619c35f463aSAndy Shevchenko int value) 620eb83479eSAndy Shevchenko { 621eb83479eSAndy Shevchenko lp_gpio_set(chip, offset, value); 622eb83479eSAndy Shevchenko 62364e14e90SAndy Shevchenko return pinctrl_gpio_direction_output(chip->base + offset); 624eb83479eSAndy Shevchenko } 625eb83479eSAndy Shevchenko 62654d371cfSAndy Shevchenko static int lp_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) 62754d371cfSAndy Shevchenko { 62854d371cfSAndy Shevchenko void __iomem *reg = lp_gpio_reg(chip, offset, LP_CONFIG1); 62954d371cfSAndy Shevchenko 63054d371cfSAndy Shevchenko if (ioread32(reg) & DIR_BIT) 63154d371cfSAndy Shevchenko return GPIO_LINE_DIRECTION_IN; 63254d371cfSAndy Shevchenko 63354d371cfSAndy Shevchenko return GPIO_LINE_DIRECTION_OUT; 63454d371cfSAndy Shevchenko } 63554d371cfSAndy Shevchenko 636eb83479eSAndy Shevchenko static void lp_gpio_irq_handler(struct irq_desc *desc) 637eb83479eSAndy Shevchenko { 638eb83479eSAndy Shevchenko struct irq_data *data = irq_desc_get_irq_data(desc); 639eb83479eSAndy Shevchenko struct gpio_chip *gc = irq_desc_get_handler_data(desc); 64018213ad4SAndy Shevchenko struct intel_pinctrl *lg = gpiochip_get_data(gc); 641eb83479eSAndy Shevchenko struct irq_chip *chip = irq_data_get_irq_chip(data); 642e1940adeSAndy Shevchenko void __iomem *reg, *ena; 643e1940adeSAndy Shevchenko unsigned long pending; 644eb83479eSAndy Shevchenko u32 base, pin; 645eb83479eSAndy Shevchenko 646eb83479eSAndy Shevchenko /* check from GPIO controller which pin triggered the interrupt */ 647eb83479eSAndy Shevchenko for (base = 0; base < lg->chip.ngpio; base += 32) { 648eb83479eSAndy Shevchenko reg = lp_gpio_reg(&lg->chip, base, LP_INT_STAT); 649eb83479eSAndy Shevchenko ena = lp_gpio_reg(&lg->chip, base, LP_INT_ENABLE); 650eb83479eSAndy Shevchenko 651eb83479eSAndy Shevchenko /* Only interrupts that are enabled */ 652e1940adeSAndy Shevchenko pending = ioread32(reg) & ioread32(ena); 653eb83479eSAndy Shevchenko 654eb83479eSAndy Shevchenko for_each_set_bit(pin, &pending, 32) { 655c35f463aSAndy Shevchenko unsigned int irq; 656eb83479eSAndy Shevchenko 657eb83479eSAndy Shevchenko irq = irq_find_mapping(lg->chip.irq.domain, base + pin); 658eb83479eSAndy Shevchenko generic_handle_irq(irq); 659eb83479eSAndy Shevchenko } 660eb83479eSAndy Shevchenko } 661eb83479eSAndy Shevchenko chip->irq_eoi(data); 662eb83479eSAndy Shevchenko } 663eb83479eSAndy Shevchenko 6645931e6edSAndy Shevchenko static void lp_irq_ack(struct irq_data *d) 6655931e6edSAndy Shevchenko { 6665931e6edSAndy Shevchenko struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 66718213ad4SAndy Shevchenko struct intel_pinctrl *lg = gpiochip_get_data(gc); 6685931e6edSAndy Shevchenko u32 hwirq = irqd_to_hwirq(d); 6695931e6edSAndy Shevchenko void __iomem *reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_STAT); 6705931e6edSAndy Shevchenko unsigned long flags; 6715931e6edSAndy Shevchenko 6725931e6edSAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 6735931e6edSAndy Shevchenko iowrite32(BIT(hwirq % 32), reg); 6745931e6edSAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 6755931e6edSAndy Shevchenko } 6765931e6edSAndy Shevchenko 677eb83479eSAndy Shevchenko static void lp_irq_unmask(struct irq_data *d) 678eb83479eSAndy Shevchenko { 679eb83479eSAndy Shevchenko } 680eb83479eSAndy Shevchenko 681eb83479eSAndy Shevchenko static void lp_irq_mask(struct irq_data *d) 682eb83479eSAndy Shevchenko { 683eb83479eSAndy Shevchenko } 684eb83479eSAndy Shevchenko 685eb83479eSAndy Shevchenko static void lp_irq_enable(struct irq_data *d) 686eb83479eSAndy Shevchenko { 687eb83479eSAndy Shevchenko struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 68818213ad4SAndy Shevchenko struct intel_pinctrl *lg = gpiochip_get_data(gc); 689eb83479eSAndy Shevchenko u32 hwirq = irqd_to_hwirq(d); 690e1940adeSAndy Shevchenko void __iomem *reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE); 691eb83479eSAndy Shevchenko unsigned long flags; 692eb83479eSAndy Shevchenko 693b2e05d63SAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 694e1940adeSAndy Shevchenko iowrite32(ioread32(reg) | BIT(hwirq % 32), reg); 695b2e05d63SAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 696eb83479eSAndy Shevchenko } 697eb83479eSAndy Shevchenko 698eb83479eSAndy Shevchenko static void lp_irq_disable(struct irq_data *d) 699eb83479eSAndy Shevchenko { 700eb83479eSAndy Shevchenko struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 70118213ad4SAndy Shevchenko struct intel_pinctrl *lg = gpiochip_get_data(gc); 702eb83479eSAndy Shevchenko u32 hwirq = irqd_to_hwirq(d); 703e1940adeSAndy Shevchenko void __iomem *reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE); 704eb83479eSAndy Shevchenko unsigned long flags; 705eb83479eSAndy Shevchenko 706b2e05d63SAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 707e1940adeSAndy Shevchenko iowrite32(ioread32(reg) & ~BIT(hwirq % 32), reg); 708b2e05d63SAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 709eb83479eSAndy Shevchenko } 710eb83479eSAndy Shevchenko 711095f2a67SAndy Shevchenko static int lp_irq_set_type(struct irq_data *d, unsigned int type) 712095f2a67SAndy Shevchenko { 713095f2a67SAndy Shevchenko struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 71418213ad4SAndy Shevchenko struct intel_pinctrl *lg = gpiochip_get_data(gc); 715095f2a67SAndy Shevchenko u32 hwirq = irqd_to_hwirq(d); 716095f2a67SAndy Shevchenko void __iomem *reg = lp_gpio_reg(&lg->chip, hwirq, LP_CONFIG1); 717095f2a67SAndy Shevchenko unsigned long flags; 718095f2a67SAndy Shevchenko u32 value; 719095f2a67SAndy Shevchenko 720095f2a67SAndy Shevchenko if (hwirq >= lg->chip.ngpio) 721095f2a67SAndy Shevchenko return -EINVAL; 722095f2a67SAndy Shevchenko 723540bff18SAndy Shevchenko /* Fail if BIOS reserved pin for ACPI use */ 724540bff18SAndy Shevchenko if (lp_gpio_acpi_use(lg, hwirq)) { 725540bff18SAndy Shevchenko dev_err(lg->dev, "pin %u can't be used as IRQ\n", hwirq); 726540bff18SAndy Shevchenko return -EBUSY; 727540bff18SAndy Shevchenko } 728540bff18SAndy Shevchenko 729095f2a67SAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 730095f2a67SAndy Shevchenko value = ioread32(reg); 731095f2a67SAndy Shevchenko 732095f2a67SAndy Shevchenko /* set both TRIG_SEL and INV bits to 0 for rising edge */ 733095f2a67SAndy Shevchenko if (type & IRQ_TYPE_EDGE_RISING) 734095f2a67SAndy Shevchenko value &= ~(TRIG_SEL_BIT | INT_INV_BIT); 735095f2a67SAndy Shevchenko 736095f2a67SAndy Shevchenko /* TRIG_SEL bit 0, INV bit 1 for falling edge */ 737095f2a67SAndy Shevchenko if (type & IRQ_TYPE_EDGE_FALLING) 738095f2a67SAndy Shevchenko value = (value | INT_INV_BIT) & ~TRIG_SEL_BIT; 739095f2a67SAndy Shevchenko 740095f2a67SAndy Shevchenko /* TRIG_SEL bit 1, INV bit 0 for level low */ 741095f2a67SAndy Shevchenko if (type & IRQ_TYPE_LEVEL_LOW) 742095f2a67SAndy Shevchenko value = (value | TRIG_SEL_BIT) & ~INT_INV_BIT; 743095f2a67SAndy Shevchenko 744095f2a67SAndy Shevchenko /* TRIG_SEL bit 1, INV bit 1 for level high */ 745095f2a67SAndy Shevchenko if (type & IRQ_TYPE_LEVEL_HIGH) 746095f2a67SAndy Shevchenko value |= TRIG_SEL_BIT | INT_INV_BIT; 747095f2a67SAndy Shevchenko 748095f2a67SAndy Shevchenko iowrite32(value, reg); 749095f2a67SAndy Shevchenko 750095f2a67SAndy Shevchenko if (type & IRQ_TYPE_EDGE_BOTH) 751095f2a67SAndy Shevchenko irq_set_handler_locked(d, handle_edge_irq); 752095f2a67SAndy Shevchenko else if (type & IRQ_TYPE_LEVEL_MASK) 753095f2a67SAndy Shevchenko irq_set_handler_locked(d, handle_level_irq); 754095f2a67SAndy Shevchenko 755095f2a67SAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 756095f2a67SAndy Shevchenko 757095f2a67SAndy Shevchenko return 0; 758095f2a67SAndy Shevchenko } 759095f2a67SAndy Shevchenko 760eb83479eSAndy Shevchenko static struct irq_chip lp_irqchip = { 761eb83479eSAndy Shevchenko .name = "LP-GPIO", 7625931e6edSAndy Shevchenko .irq_ack = lp_irq_ack, 763eb83479eSAndy Shevchenko .irq_mask = lp_irq_mask, 764eb83479eSAndy Shevchenko .irq_unmask = lp_irq_unmask, 765eb83479eSAndy Shevchenko .irq_enable = lp_irq_enable, 766eb83479eSAndy Shevchenko .irq_disable = lp_irq_disable, 767095f2a67SAndy Shevchenko .irq_set_type = lp_irq_set_type, 768eb83479eSAndy Shevchenko .flags = IRQCHIP_SKIP_SET_WAKE, 769eb83479eSAndy Shevchenko }; 770eb83479eSAndy Shevchenko 771eb83479eSAndy Shevchenko static int lp_gpio_irq_init_hw(struct gpio_chip *chip) 772eb83479eSAndy Shevchenko { 77318213ad4SAndy Shevchenko struct intel_pinctrl *lg = gpiochip_get_data(chip); 774e1940adeSAndy Shevchenko void __iomem *reg; 775c35f463aSAndy Shevchenko unsigned int base; 776eb83479eSAndy Shevchenko 777eb83479eSAndy Shevchenko for (base = 0; base < lg->chip.ngpio; base += 32) { 778eb83479eSAndy Shevchenko /* disable gpio pin interrupts */ 779eb83479eSAndy Shevchenko reg = lp_gpio_reg(&lg->chip, base, LP_INT_ENABLE); 780e1940adeSAndy Shevchenko iowrite32(0, reg); 781eb83479eSAndy Shevchenko /* Clear interrupt status register */ 782eb83479eSAndy Shevchenko reg = lp_gpio_reg(&lg->chip, base, LP_INT_STAT); 783e1940adeSAndy Shevchenko iowrite32(0xffffffff, reg); 784eb83479eSAndy Shevchenko } 785eb83479eSAndy Shevchenko 786eb83479eSAndy Shevchenko return 0; 787eb83479eSAndy Shevchenko } 788eb83479eSAndy Shevchenko 7893683509cSAndy Shevchenko static int lp_gpio_add_pin_ranges(struct gpio_chip *chip) 7903683509cSAndy Shevchenko { 7913683509cSAndy Shevchenko struct intel_pinctrl *lg = gpiochip_get_data(chip); 7923683509cSAndy Shevchenko struct device *dev = lg->dev; 7933683509cSAndy Shevchenko int ret; 7943683509cSAndy Shevchenko 7953683509cSAndy Shevchenko ret = gpiochip_add_pin_range(chip, dev_name(dev), 0, 0, lg->soc->npins); 7963683509cSAndy Shevchenko if (ret) 7973683509cSAndy Shevchenko dev_err(dev, "failed to add GPIO pin range\n"); 7983683509cSAndy Shevchenko 7993683509cSAndy Shevchenko return ret; 8003683509cSAndy Shevchenko } 8013683509cSAndy Shevchenko 802eb83479eSAndy Shevchenko static int lp_gpio_probe(struct platform_device *pdev) 803eb83479eSAndy Shevchenko { 80418213ad4SAndy Shevchenko const struct intel_pinctrl_soc_data *soc; 80518213ad4SAndy Shevchenko struct intel_pinctrl *lg; 806eb83479eSAndy Shevchenko struct gpio_chip *gc; 807eb83479eSAndy Shevchenko struct device *dev = &pdev->dev; 8085f3b82a1SAndy Shevchenko struct resource *io_rc; 809e1940adeSAndy Shevchenko void __iomem *regs; 81018213ad4SAndy Shevchenko unsigned int i; 8115f3b82a1SAndy Shevchenko int irq, ret; 812eb83479eSAndy Shevchenko 81318213ad4SAndy Shevchenko soc = (const struct intel_pinctrl_soc_data *)device_get_match_data(dev); 81418213ad4SAndy Shevchenko if (!soc) 81518213ad4SAndy Shevchenko return -ENODEV; 81618213ad4SAndy Shevchenko 817a718e68eSAndy Shevchenko lg = devm_kzalloc(dev, sizeof(*lg), GFP_KERNEL); 818eb83479eSAndy Shevchenko if (!lg) 819eb83479eSAndy Shevchenko return -ENOMEM; 820eb83479eSAndy Shevchenko 8211e78ea71SAndy Shevchenko lg->dev = dev; 82218213ad4SAndy Shevchenko lg->soc = soc; 82318213ad4SAndy Shevchenko 82418213ad4SAndy Shevchenko lg->ncommunities = lg->soc->ncommunities; 82518213ad4SAndy Shevchenko lg->communities = devm_kcalloc(dev, lg->ncommunities, 82618213ad4SAndy Shevchenko sizeof(*lg->communities), GFP_KERNEL); 82718213ad4SAndy Shevchenko if (!lg->communities) 82818213ad4SAndy Shevchenko return -ENOMEM; 82918213ad4SAndy Shevchenko 8307f32d370SAndy Shevchenko lg->pctldesc = lptlp_pinctrl_desc; 8317f32d370SAndy Shevchenko lg->pctldesc.name = dev_name(dev); 8327f32d370SAndy Shevchenko lg->pctldesc.pins = lg->soc->pins; 8337f32d370SAndy Shevchenko lg->pctldesc.npins = lg->soc->npins; 8347f32d370SAndy Shevchenko 83564e14e90SAndy Shevchenko lg->pctldev = devm_pinctrl_register(dev, &lg->pctldesc, lg); 83664e14e90SAndy Shevchenko if (IS_ERR(lg->pctldev)) { 83764e14e90SAndy Shevchenko dev_err(dev, "failed to register pinctrl driver\n"); 83864e14e90SAndy Shevchenko return PTR_ERR(lg->pctldev); 83964e14e90SAndy Shevchenko } 84064e14e90SAndy Shevchenko 841eb83479eSAndy Shevchenko platform_set_drvdata(pdev, lg); 842eb83479eSAndy Shevchenko 843eb83479eSAndy Shevchenko io_rc = platform_get_resource(pdev, IORESOURCE_IO, 0); 844eb83479eSAndy Shevchenko if (!io_rc) { 845eb83479eSAndy Shevchenko dev_err(dev, "missing IO resources\n"); 846eb83479eSAndy Shevchenko return -EINVAL; 847eb83479eSAndy Shevchenko } 848eb83479eSAndy Shevchenko 849e1940adeSAndy Shevchenko regs = devm_ioport_map(dev, io_rc->start, resource_size(io_rc)); 850e1940adeSAndy Shevchenko if (!regs) { 851e1940adeSAndy Shevchenko dev_err(dev, "failed mapping IO region %pR\n", &io_rc); 852eb83479eSAndy Shevchenko return -EBUSY; 853eb83479eSAndy Shevchenko } 854eb83479eSAndy Shevchenko 85518213ad4SAndy Shevchenko for (i = 0; i < lg->soc->ncommunities; i++) { 85618213ad4SAndy Shevchenko struct intel_community *comm = &lg->communities[i]; 85718213ad4SAndy Shevchenko 85818213ad4SAndy Shevchenko *comm = lg->soc->communities[i]; 85918213ad4SAndy Shevchenko 86018213ad4SAndy Shevchenko comm->regs = regs; 86118213ad4SAndy Shevchenko comm->pad_regs = regs + 0x100; 86218213ad4SAndy Shevchenko } 863e1940adeSAndy Shevchenko 864b2e05d63SAndy Shevchenko raw_spin_lock_init(&lg->lock); 865eb83479eSAndy Shevchenko 866eb83479eSAndy Shevchenko gc = &lg->chip; 867eb83479eSAndy Shevchenko gc->label = dev_name(dev); 868eb83479eSAndy Shevchenko gc->owner = THIS_MODULE; 86964e14e90SAndy Shevchenko gc->request = gpiochip_generic_request; 87064e14e90SAndy Shevchenko gc->free = gpiochip_generic_free; 871eb83479eSAndy Shevchenko gc->direction_input = lp_gpio_direction_input; 872eb83479eSAndy Shevchenko gc->direction_output = lp_gpio_direction_output; 873eb83479eSAndy Shevchenko gc->get = lp_gpio_get; 874eb83479eSAndy Shevchenko gc->set = lp_gpio_set; 87554d371cfSAndy Shevchenko gc->get_direction = lp_gpio_get_direction; 876eb83479eSAndy Shevchenko gc->base = -1; 877eb83479eSAndy Shevchenko gc->ngpio = LP_NUM_GPIO; 878eb83479eSAndy Shevchenko gc->can_sleep = false; 8793683509cSAndy Shevchenko gc->add_pin_ranges = lp_gpio_add_pin_ranges; 880eb83479eSAndy Shevchenko gc->parent = dev; 881eb83479eSAndy Shevchenko 882eb83479eSAndy Shevchenko /* set up interrupts */ 8835f3b82a1SAndy Shevchenko irq = platform_get_irq_optional(pdev, 0); 8845f3b82a1SAndy Shevchenko if (irq > 0) { 885eb83479eSAndy Shevchenko struct gpio_irq_chip *girq; 886eb83479eSAndy Shevchenko 887eb83479eSAndy Shevchenko girq = &gc->irq; 888eb83479eSAndy Shevchenko girq->chip = &lp_irqchip; 889eb83479eSAndy Shevchenko girq->init_hw = lp_gpio_irq_init_hw; 890eb83479eSAndy Shevchenko girq->parent_handler = lp_gpio_irq_handler; 891eb83479eSAndy Shevchenko girq->num_parents = 1; 8921e78ea71SAndy Shevchenko girq->parents = devm_kcalloc(dev, girq->num_parents, 893eb83479eSAndy Shevchenko sizeof(*girq->parents), 894eb83479eSAndy Shevchenko GFP_KERNEL); 895eb83479eSAndy Shevchenko if (!girq->parents) 896eb83479eSAndy Shevchenko return -ENOMEM; 8975f3b82a1SAndy Shevchenko girq->parents[0] = irq; 898eb83479eSAndy Shevchenko girq->default_type = IRQ_TYPE_NONE; 899eb83479eSAndy Shevchenko girq->handler = handle_bad_irq; 900eb83479eSAndy Shevchenko } 901eb83479eSAndy Shevchenko 902eb83479eSAndy Shevchenko ret = devm_gpiochip_add_data(dev, gc, lg); 903eb83479eSAndy Shevchenko if (ret) { 904eb83479eSAndy Shevchenko dev_err(dev, "failed adding lp-gpio chip\n"); 905eb83479eSAndy Shevchenko return ret; 906eb83479eSAndy Shevchenko } 907eb83479eSAndy Shevchenko 908eb83479eSAndy Shevchenko pm_runtime_enable(dev); 909eb83479eSAndy Shevchenko 910eb83479eSAndy Shevchenko return 0; 911eb83479eSAndy Shevchenko } 912eb83479eSAndy Shevchenko 913d0f2df40SAndy Shevchenko static int lp_gpio_remove(struct platform_device *pdev) 914d0f2df40SAndy Shevchenko { 915d0f2df40SAndy Shevchenko pm_runtime_disable(&pdev->dev); 916d0f2df40SAndy Shevchenko return 0; 917d0f2df40SAndy Shevchenko } 918d0f2df40SAndy Shevchenko 919eb83479eSAndy Shevchenko static int lp_gpio_runtime_suspend(struct device *dev) 920eb83479eSAndy Shevchenko { 921eb83479eSAndy Shevchenko return 0; 922eb83479eSAndy Shevchenko } 923eb83479eSAndy Shevchenko 924eb83479eSAndy Shevchenko static int lp_gpio_runtime_resume(struct device *dev) 925eb83479eSAndy Shevchenko { 926eb83479eSAndy Shevchenko return 0; 927eb83479eSAndy Shevchenko } 928eb83479eSAndy Shevchenko 929eb83479eSAndy Shevchenko static int lp_gpio_resume(struct device *dev) 930eb83479eSAndy Shevchenko { 93118213ad4SAndy Shevchenko struct intel_pinctrl *lg = dev_get_drvdata(dev); 932f3e7d281SAndy Shevchenko struct gpio_chip *chip = &lg->chip; 933f3e7d281SAndy Shevchenko const char *dummy; 934eb83479eSAndy Shevchenko int i; 935eb83479eSAndy Shevchenko 936eb83479eSAndy Shevchenko /* on some hardware suspend clears input sensing, re-enable it here */ 937*0472567bSAndy Shevchenko for_each_requested_gpio(chip, i, dummy) 938*0472567bSAndy Shevchenko lp_gpio_enable_input(lp_gpio_reg(chip, i, LP_CONFIG2)); 939f3e7d281SAndy Shevchenko 940eb83479eSAndy Shevchenko return 0; 941eb83479eSAndy Shevchenko } 942eb83479eSAndy Shevchenko 943eb83479eSAndy Shevchenko static const struct dev_pm_ops lp_gpio_pm_ops = { 944eb83479eSAndy Shevchenko .runtime_suspend = lp_gpio_runtime_suspend, 945eb83479eSAndy Shevchenko .runtime_resume = lp_gpio_runtime_resume, 946eb83479eSAndy Shevchenko .resume = lp_gpio_resume, 947eb83479eSAndy Shevchenko }; 948eb83479eSAndy Shevchenko 949eb83479eSAndy Shevchenko static const struct acpi_device_id lynxpoint_gpio_acpi_match[] = { 950cecddda7SAndy Shevchenko { "INT33C7", (kernel_ulong_t)&lptlp_soc_data }, 951cecddda7SAndy Shevchenko { "INT3437", (kernel_ulong_t)&lptlp_soc_data }, 952eb83479eSAndy Shevchenko { } 953eb83479eSAndy Shevchenko }; 954eb83479eSAndy Shevchenko MODULE_DEVICE_TABLE(acpi, lynxpoint_gpio_acpi_match); 955eb83479eSAndy Shevchenko 956eb83479eSAndy Shevchenko static struct platform_driver lp_gpio_driver = { 957eb83479eSAndy Shevchenko .probe = lp_gpio_probe, 958eb83479eSAndy Shevchenko .remove = lp_gpio_remove, 959eb83479eSAndy Shevchenko .driver = { 960eb83479eSAndy Shevchenko .name = "lp_gpio", 961eb83479eSAndy Shevchenko .pm = &lp_gpio_pm_ops, 962eb83479eSAndy Shevchenko .acpi_match_table = ACPI_PTR(lynxpoint_gpio_acpi_match), 963eb83479eSAndy Shevchenko }, 964eb83479eSAndy Shevchenko }; 965eb83479eSAndy Shevchenko 966eb83479eSAndy Shevchenko static int __init lp_gpio_init(void) 967eb83479eSAndy Shevchenko { 968eb83479eSAndy Shevchenko return platform_driver_register(&lp_gpio_driver); 969eb83479eSAndy Shevchenko } 970eb83479eSAndy Shevchenko 971eb83479eSAndy Shevchenko static void __exit lp_gpio_exit(void) 972eb83479eSAndy Shevchenko { 973eb83479eSAndy Shevchenko platform_driver_unregister(&lp_gpio_driver); 974eb83479eSAndy Shevchenko } 975eb83479eSAndy Shevchenko 976eb83479eSAndy Shevchenko subsys_initcall(lp_gpio_init); 977eb83479eSAndy Shevchenko module_exit(lp_gpio_exit); 978eb83479eSAndy Shevchenko 979eb83479eSAndy Shevchenko MODULE_AUTHOR("Mathias Nyman (Intel)"); 9803a67fe38SAndy Shevchenko MODULE_AUTHOR("Andy Shevchenko (Intel)"); 9813a67fe38SAndy Shevchenko MODULE_DESCRIPTION("Intel Lynxpoint pinctrl driver"); 982eb83479eSAndy Shevchenko MODULE_LICENSE("GPL v2"); 983eb83479eSAndy Shevchenko MODULE_ALIAS("platform:lp_gpio"); 984