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 3890472567bSAndy Shevchenko static void lp_gpio_enable_input(void __iomem *reg) 3900472567bSAndy Shevchenko { 3910472567bSAndy Shevchenko iowrite32(ioread32(reg) & ~GPINDIS_BIT, reg); 3920472567bSAndy Shevchenko } 3930472567bSAndy Shevchenko 3940472567bSAndy Shevchenko static void lp_gpio_disable_input(void __iomem *reg) 3950472567bSAndy Shevchenko { 3960472567bSAndy Shevchenko iowrite32(ioread32(reg) | GPINDIS_BIT, reg); 3970472567bSAndy Shevchenko } 3980472567bSAndy 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 */ 4240472567bSAndy 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 */ 4420472567bSAndy 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; 499d25dd66aSAndy Shevchenko u16 arg; 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: 509d25dd66aSAndy Shevchenko if (pull != GPIWP_NONE) 5107f32d370SAndy Shevchenko return -EINVAL; 511d25dd66aSAndy Shevchenko arg = 0; 5127f32d370SAndy Shevchenko break; 5137f32d370SAndy Shevchenko case PIN_CONFIG_BIAS_PULL_DOWN: 5147f32d370SAndy Shevchenko if (pull != GPIWP_DOWN) 5157f32d370SAndy Shevchenko return -EINVAL; 5167f32d370SAndy Shevchenko 5177f32d370SAndy Shevchenko arg = 1; 5187f32d370SAndy Shevchenko break; 5197f32d370SAndy Shevchenko case PIN_CONFIG_BIAS_PULL_UP: 5207f32d370SAndy Shevchenko if (pull != GPIWP_UP) 5217f32d370SAndy Shevchenko return -EINVAL; 5227f32d370SAndy Shevchenko 5237f32d370SAndy Shevchenko arg = 1; 5247f32d370SAndy Shevchenko break; 5257f32d370SAndy Shevchenko default: 5267f32d370SAndy Shevchenko return -ENOTSUPP; 5277f32d370SAndy Shevchenko } 5287f32d370SAndy Shevchenko 5297f32d370SAndy Shevchenko *config = pinconf_to_config_packed(param, arg); 5307f32d370SAndy Shevchenko 5317f32d370SAndy Shevchenko return 0; 5327f32d370SAndy Shevchenko } 5337f32d370SAndy Shevchenko 5347f32d370SAndy Shevchenko static int lp_pin_config_set(struct pinctrl_dev *pctldev, unsigned int pin, 5357f32d370SAndy Shevchenko unsigned long *configs, unsigned int num_configs) 5367f32d370SAndy Shevchenko { 5377f32d370SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 5387f32d370SAndy Shevchenko void __iomem *conf2 = lp_gpio_reg(&lg->chip, pin, LP_CONFIG2); 5397f32d370SAndy Shevchenko enum pin_config_param param; 5407f32d370SAndy Shevchenko unsigned long flags; 5417f32d370SAndy Shevchenko int i, ret = 0; 5427f32d370SAndy Shevchenko u32 value; 5437f32d370SAndy Shevchenko 5447f32d370SAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 5457f32d370SAndy Shevchenko 5467f32d370SAndy Shevchenko value = ioread32(conf2); 5477f32d370SAndy Shevchenko 5487f32d370SAndy Shevchenko for (i = 0; i < num_configs; i++) { 5497f32d370SAndy Shevchenko param = pinconf_to_config_param(configs[i]); 5507f32d370SAndy Shevchenko 5517f32d370SAndy Shevchenko switch (param) { 5527f32d370SAndy Shevchenko case PIN_CONFIG_BIAS_DISABLE: 5537f32d370SAndy Shevchenko value &= ~GPIWP_MASK; 554d25dd66aSAndy Shevchenko value |= GPIWP_NONE; 5557f32d370SAndy Shevchenko break; 5567f32d370SAndy Shevchenko case PIN_CONFIG_BIAS_PULL_DOWN: 5577f32d370SAndy Shevchenko value &= ~GPIWP_MASK; 5587f32d370SAndy Shevchenko value |= GPIWP_DOWN; 5597f32d370SAndy Shevchenko break; 5607f32d370SAndy Shevchenko case PIN_CONFIG_BIAS_PULL_UP: 5617f32d370SAndy Shevchenko value &= ~GPIWP_MASK; 5627f32d370SAndy Shevchenko value |= GPIWP_UP; 5637f32d370SAndy Shevchenko break; 5647f32d370SAndy Shevchenko default: 5657f32d370SAndy Shevchenko ret = -ENOTSUPP; 5667f32d370SAndy Shevchenko } 5677f32d370SAndy Shevchenko 5687f32d370SAndy Shevchenko if (ret) 5697f32d370SAndy Shevchenko break; 5707f32d370SAndy Shevchenko } 5717f32d370SAndy Shevchenko 5727f32d370SAndy Shevchenko if (!ret) 5737f32d370SAndy Shevchenko iowrite32(value, conf2); 5747f32d370SAndy Shevchenko 5757f32d370SAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 5767f32d370SAndy Shevchenko 5777f32d370SAndy Shevchenko return ret; 5787f32d370SAndy Shevchenko } 5797f32d370SAndy Shevchenko 5807f32d370SAndy Shevchenko static const struct pinconf_ops lptlp_pinconf_ops = { 5817f32d370SAndy Shevchenko .is_generic = true, 5827f32d370SAndy Shevchenko .pin_config_get = lp_pin_config_get, 5837f32d370SAndy Shevchenko .pin_config_set = lp_pin_config_set, 5847f32d370SAndy Shevchenko }; 5857f32d370SAndy Shevchenko 5867f32d370SAndy Shevchenko static const struct pinctrl_desc lptlp_pinctrl_desc = { 5877f32d370SAndy Shevchenko .pctlops = &lptlp_pinctrl_ops, 5887f32d370SAndy Shevchenko .pmxops = &lptlp_pinmux_ops, 5897f32d370SAndy Shevchenko .confops = &lptlp_pinconf_ops, 5907f32d370SAndy Shevchenko .owner = THIS_MODULE, 5917f32d370SAndy Shevchenko }; 5927f32d370SAndy Shevchenko 593c35f463aSAndy Shevchenko static int lp_gpio_get(struct gpio_chip *chip, unsigned int offset) 594eb83479eSAndy Shevchenko { 595e1940adeSAndy Shevchenko void __iomem *reg = lp_gpio_reg(chip, offset, LP_CONFIG1); 596e1940adeSAndy Shevchenko return !!(ioread32(reg) & IN_LVL_BIT); 597eb83479eSAndy Shevchenko } 598eb83479eSAndy Shevchenko 599c35f463aSAndy Shevchenko static void lp_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) 600eb83479eSAndy Shevchenko { 60118213ad4SAndy Shevchenko struct intel_pinctrl *lg = gpiochip_get_data(chip); 602e1940adeSAndy Shevchenko void __iomem *reg = lp_gpio_reg(chip, offset, LP_CONFIG1); 603eb83479eSAndy Shevchenko unsigned long flags; 604eb83479eSAndy Shevchenko 605b2e05d63SAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 606eb83479eSAndy Shevchenko 607eb83479eSAndy Shevchenko if (value) 608e1940adeSAndy Shevchenko iowrite32(ioread32(reg) | OUT_LVL_BIT, reg); 609eb83479eSAndy Shevchenko else 610e1940adeSAndy Shevchenko iowrite32(ioread32(reg) & ~OUT_LVL_BIT, reg); 611eb83479eSAndy Shevchenko 612b2e05d63SAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 613eb83479eSAndy Shevchenko } 614eb83479eSAndy Shevchenko 615c35f463aSAndy Shevchenko static int lp_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) 616eb83479eSAndy Shevchenko { 61764e14e90SAndy Shevchenko return pinctrl_gpio_direction_input(chip->base + offset); 618eb83479eSAndy Shevchenko } 619eb83479eSAndy Shevchenko 620c35f463aSAndy Shevchenko static int lp_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, 621c35f463aSAndy Shevchenko int value) 622eb83479eSAndy Shevchenko { 623eb83479eSAndy Shevchenko lp_gpio_set(chip, offset, value); 624eb83479eSAndy Shevchenko 62564e14e90SAndy Shevchenko return pinctrl_gpio_direction_output(chip->base + offset); 626eb83479eSAndy Shevchenko } 627eb83479eSAndy Shevchenko 62854d371cfSAndy Shevchenko static int lp_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) 62954d371cfSAndy Shevchenko { 63054d371cfSAndy Shevchenko void __iomem *reg = lp_gpio_reg(chip, offset, LP_CONFIG1); 63154d371cfSAndy Shevchenko 63254d371cfSAndy Shevchenko if (ioread32(reg) & DIR_BIT) 63354d371cfSAndy Shevchenko return GPIO_LINE_DIRECTION_IN; 63454d371cfSAndy Shevchenko 63554d371cfSAndy Shevchenko return GPIO_LINE_DIRECTION_OUT; 63654d371cfSAndy Shevchenko } 63754d371cfSAndy Shevchenko 638eb83479eSAndy Shevchenko static void lp_gpio_irq_handler(struct irq_desc *desc) 639eb83479eSAndy Shevchenko { 640eb83479eSAndy Shevchenko struct irq_data *data = irq_desc_get_irq_data(desc); 641eb83479eSAndy Shevchenko struct gpio_chip *gc = irq_desc_get_handler_data(desc); 64218213ad4SAndy Shevchenko struct intel_pinctrl *lg = gpiochip_get_data(gc); 643eb83479eSAndy Shevchenko struct irq_chip *chip = irq_data_get_irq_chip(data); 644e1940adeSAndy Shevchenko void __iomem *reg, *ena; 645e1940adeSAndy Shevchenko unsigned long pending; 646eb83479eSAndy Shevchenko u32 base, pin; 647eb83479eSAndy Shevchenko 648eb83479eSAndy Shevchenko /* check from GPIO controller which pin triggered the interrupt */ 649eb83479eSAndy Shevchenko for (base = 0; base < lg->chip.ngpio; base += 32) { 650eb83479eSAndy Shevchenko reg = lp_gpio_reg(&lg->chip, base, LP_INT_STAT); 651eb83479eSAndy Shevchenko ena = lp_gpio_reg(&lg->chip, base, LP_INT_ENABLE); 652eb83479eSAndy Shevchenko 653eb83479eSAndy Shevchenko /* Only interrupts that are enabled */ 654e1940adeSAndy Shevchenko pending = ioread32(reg) & ioread32(ena); 655eb83479eSAndy Shevchenko 656eb83479eSAndy Shevchenko for_each_set_bit(pin, &pending, 32) { 657c35f463aSAndy Shevchenko unsigned int irq; 658eb83479eSAndy Shevchenko 659eb83479eSAndy Shevchenko irq = irq_find_mapping(lg->chip.irq.domain, base + pin); 660eb83479eSAndy Shevchenko generic_handle_irq(irq); 661eb83479eSAndy Shevchenko } 662eb83479eSAndy Shevchenko } 663eb83479eSAndy Shevchenko chip->irq_eoi(data); 664eb83479eSAndy Shevchenko } 665eb83479eSAndy Shevchenko 6665931e6edSAndy Shevchenko static void lp_irq_ack(struct irq_data *d) 6675931e6edSAndy Shevchenko { 6685931e6edSAndy Shevchenko struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 66918213ad4SAndy Shevchenko struct intel_pinctrl *lg = gpiochip_get_data(gc); 6705931e6edSAndy Shevchenko u32 hwirq = irqd_to_hwirq(d); 6715931e6edSAndy Shevchenko void __iomem *reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_STAT); 6725931e6edSAndy Shevchenko unsigned long flags; 6735931e6edSAndy Shevchenko 6745931e6edSAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 6755931e6edSAndy Shevchenko iowrite32(BIT(hwirq % 32), reg); 6765931e6edSAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 6775931e6edSAndy Shevchenko } 6785931e6edSAndy Shevchenko 679eb83479eSAndy Shevchenko static void lp_irq_unmask(struct irq_data *d) 680eb83479eSAndy Shevchenko { 681eb83479eSAndy Shevchenko } 682eb83479eSAndy Shevchenko 683eb83479eSAndy Shevchenko static void lp_irq_mask(struct irq_data *d) 684eb83479eSAndy Shevchenko { 685eb83479eSAndy Shevchenko } 686eb83479eSAndy Shevchenko 687eb83479eSAndy Shevchenko static void lp_irq_enable(struct irq_data *d) 688eb83479eSAndy Shevchenko { 689eb83479eSAndy Shevchenko struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 69018213ad4SAndy Shevchenko struct intel_pinctrl *lg = gpiochip_get_data(gc); 691eb83479eSAndy Shevchenko u32 hwirq = irqd_to_hwirq(d); 692e1940adeSAndy Shevchenko void __iomem *reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE); 693eb83479eSAndy Shevchenko unsigned long flags; 694eb83479eSAndy Shevchenko 695b2e05d63SAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 696e1940adeSAndy Shevchenko iowrite32(ioread32(reg) | BIT(hwirq % 32), reg); 697b2e05d63SAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 698eb83479eSAndy Shevchenko } 699eb83479eSAndy Shevchenko 700eb83479eSAndy Shevchenko static void lp_irq_disable(struct irq_data *d) 701eb83479eSAndy Shevchenko { 702eb83479eSAndy Shevchenko struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 70318213ad4SAndy Shevchenko struct intel_pinctrl *lg = gpiochip_get_data(gc); 704eb83479eSAndy Shevchenko u32 hwirq = irqd_to_hwirq(d); 705e1940adeSAndy Shevchenko void __iomem *reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE); 706eb83479eSAndy Shevchenko unsigned long flags; 707eb83479eSAndy Shevchenko 708b2e05d63SAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 709e1940adeSAndy Shevchenko iowrite32(ioread32(reg) & ~BIT(hwirq % 32), reg); 710b2e05d63SAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 711eb83479eSAndy Shevchenko } 712eb83479eSAndy Shevchenko 713095f2a67SAndy Shevchenko static int lp_irq_set_type(struct irq_data *d, unsigned int type) 714095f2a67SAndy Shevchenko { 715095f2a67SAndy Shevchenko struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 71618213ad4SAndy Shevchenko struct intel_pinctrl *lg = gpiochip_get_data(gc); 717095f2a67SAndy Shevchenko u32 hwirq = irqd_to_hwirq(d); 718095f2a67SAndy Shevchenko void __iomem *reg = lp_gpio_reg(&lg->chip, hwirq, LP_CONFIG1); 719095f2a67SAndy Shevchenko unsigned long flags; 720095f2a67SAndy Shevchenko u32 value; 721095f2a67SAndy Shevchenko 722095f2a67SAndy Shevchenko if (hwirq >= lg->chip.ngpio) 723095f2a67SAndy Shevchenko return -EINVAL; 724095f2a67SAndy Shevchenko 725540bff18SAndy Shevchenko /* Fail if BIOS reserved pin for ACPI use */ 726540bff18SAndy Shevchenko if (lp_gpio_acpi_use(lg, hwirq)) { 727540bff18SAndy Shevchenko dev_err(lg->dev, "pin %u can't be used as IRQ\n", hwirq); 728540bff18SAndy Shevchenko return -EBUSY; 729540bff18SAndy Shevchenko } 730540bff18SAndy Shevchenko 731095f2a67SAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 732095f2a67SAndy Shevchenko value = ioread32(reg); 733095f2a67SAndy Shevchenko 734095f2a67SAndy Shevchenko /* set both TRIG_SEL and INV bits to 0 for rising edge */ 735095f2a67SAndy Shevchenko if (type & IRQ_TYPE_EDGE_RISING) 736095f2a67SAndy Shevchenko value &= ~(TRIG_SEL_BIT | INT_INV_BIT); 737095f2a67SAndy Shevchenko 738095f2a67SAndy Shevchenko /* TRIG_SEL bit 0, INV bit 1 for falling edge */ 739095f2a67SAndy Shevchenko if (type & IRQ_TYPE_EDGE_FALLING) 740095f2a67SAndy Shevchenko value = (value | INT_INV_BIT) & ~TRIG_SEL_BIT; 741095f2a67SAndy Shevchenko 742095f2a67SAndy Shevchenko /* TRIG_SEL bit 1, INV bit 0 for level low */ 743095f2a67SAndy Shevchenko if (type & IRQ_TYPE_LEVEL_LOW) 744095f2a67SAndy Shevchenko value = (value | TRIG_SEL_BIT) & ~INT_INV_BIT; 745095f2a67SAndy Shevchenko 746095f2a67SAndy Shevchenko /* TRIG_SEL bit 1, INV bit 1 for level high */ 747095f2a67SAndy Shevchenko if (type & IRQ_TYPE_LEVEL_HIGH) 748095f2a67SAndy Shevchenko value |= TRIG_SEL_BIT | INT_INV_BIT; 749095f2a67SAndy Shevchenko 750095f2a67SAndy Shevchenko iowrite32(value, reg); 751095f2a67SAndy Shevchenko 752095f2a67SAndy Shevchenko if (type & IRQ_TYPE_EDGE_BOTH) 753095f2a67SAndy Shevchenko irq_set_handler_locked(d, handle_edge_irq); 754095f2a67SAndy Shevchenko else if (type & IRQ_TYPE_LEVEL_MASK) 755095f2a67SAndy Shevchenko irq_set_handler_locked(d, handle_level_irq); 756095f2a67SAndy Shevchenko 757095f2a67SAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 758095f2a67SAndy Shevchenko 759095f2a67SAndy Shevchenko return 0; 760095f2a67SAndy Shevchenko } 761095f2a67SAndy Shevchenko 762eb83479eSAndy Shevchenko static struct irq_chip lp_irqchip = { 763eb83479eSAndy Shevchenko .name = "LP-GPIO", 7645931e6edSAndy Shevchenko .irq_ack = lp_irq_ack, 765eb83479eSAndy Shevchenko .irq_mask = lp_irq_mask, 766eb83479eSAndy Shevchenko .irq_unmask = lp_irq_unmask, 767eb83479eSAndy Shevchenko .irq_enable = lp_irq_enable, 768eb83479eSAndy Shevchenko .irq_disable = lp_irq_disable, 769095f2a67SAndy Shevchenko .irq_set_type = lp_irq_set_type, 770eb83479eSAndy Shevchenko .flags = IRQCHIP_SKIP_SET_WAKE, 771eb83479eSAndy Shevchenko }; 772eb83479eSAndy Shevchenko 773eb83479eSAndy Shevchenko static int lp_gpio_irq_init_hw(struct gpio_chip *chip) 774eb83479eSAndy Shevchenko { 77518213ad4SAndy Shevchenko struct intel_pinctrl *lg = gpiochip_get_data(chip); 776e1940adeSAndy Shevchenko void __iomem *reg; 777c35f463aSAndy Shevchenko unsigned int base; 778eb83479eSAndy Shevchenko 779eb83479eSAndy Shevchenko for (base = 0; base < lg->chip.ngpio; base += 32) { 780eb83479eSAndy Shevchenko /* disable gpio pin interrupts */ 781eb83479eSAndy Shevchenko reg = lp_gpio_reg(&lg->chip, base, LP_INT_ENABLE); 782e1940adeSAndy Shevchenko iowrite32(0, reg); 783eb83479eSAndy Shevchenko /* Clear interrupt status register */ 784eb83479eSAndy Shevchenko reg = lp_gpio_reg(&lg->chip, base, LP_INT_STAT); 785e1940adeSAndy Shevchenko iowrite32(0xffffffff, reg); 786eb83479eSAndy Shevchenko } 787eb83479eSAndy Shevchenko 788eb83479eSAndy Shevchenko return 0; 789eb83479eSAndy Shevchenko } 790eb83479eSAndy Shevchenko 7913683509cSAndy Shevchenko static int lp_gpio_add_pin_ranges(struct gpio_chip *chip) 7923683509cSAndy Shevchenko { 7933683509cSAndy Shevchenko struct intel_pinctrl *lg = gpiochip_get_data(chip); 7943683509cSAndy Shevchenko struct device *dev = lg->dev; 7953683509cSAndy Shevchenko int ret; 7963683509cSAndy Shevchenko 7973683509cSAndy Shevchenko ret = gpiochip_add_pin_range(chip, dev_name(dev), 0, 0, lg->soc->npins); 7983683509cSAndy Shevchenko if (ret) 7993683509cSAndy Shevchenko dev_err(dev, "failed to add GPIO pin range\n"); 8003683509cSAndy Shevchenko 8013683509cSAndy Shevchenko return ret; 8023683509cSAndy Shevchenko } 8033683509cSAndy Shevchenko 804eb83479eSAndy Shevchenko static int lp_gpio_probe(struct platform_device *pdev) 805eb83479eSAndy Shevchenko { 80618213ad4SAndy Shevchenko const struct intel_pinctrl_soc_data *soc; 80718213ad4SAndy Shevchenko struct intel_pinctrl *lg; 808eb83479eSAndy Shevchenko struct gpio_chip *gc; 809eb83479eSAndy Shevchenko struct device *dev = &pdev->dev; 8105f3b82a1SAndy Shevchenko struct resource *io_rc; 811e1940adeSAndy Shevchenko void __iomem *regs; 81218213ad4SAndy Shevchenko unsigned int i; 8135f3b82a1SAndy Shevchenko int irq, ret; 814eb83479eSAndy Shevchenko 81518213ad4SAndy Shevchenko soc = (const struct intel_pinctrl_soc_data *)device_get_match_data(dev); 81618213ad4SAndy Shevchenko if (!soc) 81718213ad4SAndy Shevchenko return -ENODEV; 81818213ad4SAndy Shevchenko 819a718e68eSAndy Shevchenko lg = devm_kzalloc(dev, sizeof(*lg), GFP_KERNEL); 820eb83479eSAndy Shevchenko if (!lg) 821eb83479eSAndy Shevchenko return -ENOMEM; 822eb83479eSAndy Shevchenko 8231e78ea71SAndy Shevchenko lg->dev = dev; 82418213ad4SAndy Shevchenko lg->soc = soc; 82518213ad4SAndy Shevchenko 82618213ad4SAndy Shevchenko lg->ncommunities = lg->soc->ncommunities; 82718213ad4SAndy Shevchenko lg->communities = devm_kcalloc(dev, lg->ncommunities, 82818213ad4SAndy Shevchenko sizeof(*lg->communities), GFP_KERNEL); 82918213ad4SAndy Shevchenko if (!lg->communities) 83018213ad4SAndy Shevchenko return -ENOMEM; 83118213ad4SAndy Shevchenko 8327f32d370SAndy Shevchenko lg->pctldesc = lptlp_pinctrl_desc; 8337f32d370SAndy Shevchenko lg->pctldesc.name = dev_name(dev); 8347f32d370SAndy Shevchenko lg->pctldesc.pins = lg->soc->pins; 8357f32d370SAndy Shevchenko lg->pctldesc.npins = lg->soc->npins; 8367f32d370SAndy Shevchenko 83764e14e90SAndy Shevchenko lg->pctldev = devm_pinctrl_register(dev, &lg->pctldesc, lg); 83864e14e90SAndy Shevchenko if (IS_ERR(lg->pctldev)) { 83964e14e90SAndy Shevchenko dev_err(dev, "failed to register pinctrl driver\n"); 84064e14e90SAndy Shevchenko return PTR_ERR(lg->pctldev); 84164e14e90SAndy Shevchenko } 84264e14e90SAndy Shevchenko 843eb83479eSAndy Shevchenko platform_set_drvdata(pdev, lg); 844eb83479eSAndy Shevchenko 845eb83479eSAndy Shevchenko io_rc = platform_get_resource(pdev, IORESOURCE_IO, 0); 846eb83479eSAndy Shevchenko if (!io_rc) { 847eb83479eSAndy Shevchenko dev_err(dev, "missing IO resources\n"); 848eb83479eSAndy Shevchenko return -EINVAL; 849eb83479eSAndy Shevchenko } 850eb83479eSAndy Shevchenko 851e1940adeSAndy Shevchenko regs = devm_ioport_map(dev, io_rc->start, resource_size(io_rc)); 852e1940adeSAndy Shevchenko if (!regs) { 853e1940adeSAndy Shevchenko dev_err(dev, "failed mapping IO region %pR\n", &io_rc); 854eb83479eSAndy Shevchenko return -EBUSY; 855eb83479eSAndy Shevchenko } 856eb83479eSAndy Shevchenko 85718213ad4SAndy Shevchenko for (i = 0; i < lg->soc->ncommunities; i++) { 85818213ad4SAndy Shevchenko struct intel_community *comm = &lg->communities[i]; 85918213ad4SAndy Shevchenko 86018213ad4SAndy Shevchenko *comm = lg->soc->communities[i]; 86118213ad4SAndy Shevchenko 86218213ad4SAndy Shevchenko comm->regs = regs; 86318213ad4SAndy Shevchenko comm->pad_regs = regs + 0x100; 86418213ad4SAndy Shevchenko } 865e1940adeSAndy Shevchenko 866b2e05d63SAndy Shevchenko raw_spin_lock_init(&lg->lock); 867eb83479eSAndy Shevchenko 868eb83479eSAndy Shevchenko gc = &lg->chip; 869eb83479eSAndy Shevchenko gc->label = dev_name(dev); 870eb83479eSAndy Shevchenko gc->owner = THIS_MODULE; 87164e14e90SAndy Shevchenko gc->request = gpiochip_generic_request; 87264e14e90SAndy Shevchenko gc->free = gpiochip_generic_free; 873eb83479eSAndy Shevchenko gc->direction_input = lp_gpio_direction_input; 874eb83479eSAndy Shevchenko gc->direction_output = lp_gpio_direction_output; 875eb83479eSAndy Shevchenko gc->get = lp_gpio_get; 876eb83479eSAndy Shevchenko gc->set = lp_gpio_set; 877*1d112baaSAndy Shevchenko gc->set_config = gpiochip_generic_config; 87854d371cfSAndy Shevchenko gc->get_direction = lp_gpio_get_direction; 879eb83479eSAndy Shevchenko gc->base = -1; 880eb83479eSAndy Shevchenko gc->ngpio = LP_NUM_GPIO; 881eb83479eSAndy Shevchenko gc->can_sleep = false; 8823683509cSAndy Shevchenko gc->add_pin_ranges = lp_gpio_add_pin_ranges; 883eb83479eSAndy Shevchenko gc->parent = dev; 884eb83479eSAndy Shevchenko 885eb83479eSAndy Shevchenko /* set up interrupts */ 8865f3b82a1SAndy Shevchenko irq = platform_get_irq_optional(pdev, 0); 8875f3b82a1SAndy Shevchenko if (irq > 0) { 888eb83479eSAndy Shevchenko struct gpio_irq_chip *girq; 889eb83479eSAndy Shevchenko 890eb83479eSAndy Shevchenko girq = &gc->irq; 891eb83479eSAndy Shevchenko girq->chip = &lp_irqchip; 892eb83479eSAndy Shevchenko girq->init_hw = lp_gpio_irq_init_hw; 893eb83479eSAndy Shevchenko girq->parent_handler = lp_gpio_irq_handler; 894eb83479eSAndy Shevchenko girq->num_parents = 1; 8951e78ea71SAndy Shevchenko girq->parents = devm_kcalloc(dev, girq->num_parents, 896eb83479eSAndy Shevchenko sizeof(*girq->parents), 897eb83479eSAndy Shevchenko GFP_KERNEL); 898eb83479eSAndy Shevchenko if (!girq->parents) 899eb83479eSAndy Shevchenko return -ENOMEM; 9005f3b82a1SAndy Shevchenko girq->parents[0] = irq; 901eb83479eSAndy Shevchenko girq->default_type = IRQ_TYPE_NONE; 902eb83479eSAndy Shevchenko girq->handler = handle_bad_irq; 903eb83479eSAndy Shevchenko } 904eb83479eSAndy Shevchenko 905eb83479eSAndy Shevchenko ret = devm_gpiochip_add_data(dev, gc, lg); 906eb83479eSAndy Shevchenko if (ret) { 907eb83479eSAndy Shevchenko dev_err(dev, "failed adding lp-gpio chip\n"); 908eb83479eSAndy Shevchenko return ret; 909eb83479eSAndy Shevchenko } 910eb83479eSAndy Shevchenko 911eb83479eSAndy Shevchenko pm_runtime_enable(dev); 912eb83479eSAndy Shevchenko 913eb83479eSAndy Shevchenko return 0; 914eb83479eSAndy Shevchenko } 915eb83479eSAndy Shevchenko 916d0f2df40SAndy Shevchenko static int lp_gpio_remove(struct platform_device *pdev) 917d0f2df40SAndy Shevchenko { 918d0f2df40SAndy Shevchenko pm_runtime_disable(&pdev->dev); 919d0f2df40SAndy Shevchenko return 0; 920d0f2df40SAndy Shevchenko } 921d0f2df40SAndy Shevchenko 922eb83479eSAndy Shevchenko static int lp_gpio_runtime_suspend(struct device *dev) 923eb83479eSAndy Shevchenko { 924eb83479eSAndy Shevchenko return 0; 925eb83479eSAndy Shevchenko } 926eb83479eSAndy Shevchenko 927eb83479eSAndy Shevchenko static int lp_gpio_runtime_resume(struct device *dev) 928eb83479eSAndy Shevchenko { 929eb83479eSAndy Shevchenko return 0; 930eb83479eSAndy Shevchenko } 931eb83479eSAndy Shevchenko 932eb83479eSAndy Shevchenko static int lp_gpio_resume(struct device *dev) 933eb83479eSAndy Shevchenko { 93418213ad4SAndy Shevchenko struct intel_pinctrl *lg = dev_get_drvdata(dev); 935f3e7d281SAndy Shevchenko struct gpio_chip *chip = &lg->chip; 936f3e7d281SAndy Shevchenko const char *dummy; 937eb83479eSAndy Shevchenko int i; 938eb83479eSAndy Shevchenko 939eb83479eSAndy Shevchenko /* on some hardware suspend clears input sensing, re-enable it here */ 9400472567bSAndy Shevchenko for_each_requested_gpio(chip, i, dummy) 9410472567bSAndy Shevchenko lp_gpio_enable_input(lp_gpio_reg(chip, i, LP_CONFIG2)); 942f3e7d281SAndy Shevchenko 943eb83479eSAndy Shevchenko return 0; 944eb83479eSAndy Shevchenko } 945eb83479eSAndy Shevchenko 946eb83479eSAndy Shevchenko static const struct dev_pm_ops lp_gpio_pm_ops = { 947eb83479eSAndy Shevchenko .runtime_suspend = lp_gpio_runtime_suspend, 948eb83479eSAndy Shevchenko .runtime_resume = lp_gpio_runtime_resume, 949eb83479eSAndy Shevchenko .resume = lp_gpio_resume, 950eb83479eSAndy Shevchenko }; 951eb83479eSAndy Shevchenko 952eb83479eSAndy Shevchenko static const struct acpi_device_id lynxpoint_gpio_acpi_match[] = { 953cecddda7SAndy Shevchenko { "INT33C7", (kernel_ulong_t)&lptlp_soc_data }, 954cecddda7SAndy Shevchenko { "INT3437", (kernel_ulong_t)&lptlp_soc_data }, 955eb83479eSAndy Shevchenko { } 956eb83479eSAndy Shevchenko }; 957eb83479eSAndy Shevchenko MODULE_DEVICE_TABLE(acpi, lynxpoint_gpio_acpi_match); 958eb83479eSAndy Shevchenko 959eb83479eSAndy Shevchenko static struct platform_driver lp_gpio_driver = { 960eb83479eSAndy Shevchenko .probe = lp_gpio_probe, 961eb83479eSAndy Shevchenko .remove = lp_gpio_remove, 962eb83479eSAndy Shevchenko .driver = { 963eb83479eSAndy Shevchenko .name = "lp_gpio", 964eb83479eSAndy Shevchenko .pm = &lp_gpio_pm_ops, 965e359a6f0SAndy Shevchenko .acpi_match_table = lynxpoint_gpio_acpi_match, 966eb83479eSAndy Shevchenko }, 967eb83479eSAndy Shevchenko }; 968eb83479eSAndy Shevchenko 969eb83479eSAndy Shevchenko static int __init lp_gpio_init(void) 970eb83479eSAndy Shevchenko { 971eb83479eSAndy Shevchenko return platform_driver_register(&lp_gpio_driver); 972eb83479eSAndy Shevchenko } 9730ddebf85SAndy Shevchenko subsys_initcall(lp_gpio_init); 974eb83479eSAndy Shevchenko 975eb83479eSAndy Shevchenko static void __exit lp_gpio_exit(void) 976eb83479eSAndy Shevchenko { 977eb83479eSAndy Shevchenko platform_driver_unregister(&lp_gpio_driver); 978eb83479eSAndy Shevchenko } 979eb83479eSAndy Shevchenko module_exit(lp_gpio_exit); 980eb83479eSAndy Shevchenko 981eb83479eSAndy Shevchenko MODULE_AUTHOR("Mathias Nyman (Intel)"); 9823a67fe38SAndy Shevchenko MODULE_AUTHOR("Andy Shevchenko (Intel)"); 9833a67fe38SAndy Shevchenko MODULE_DESCRIPTION("Intel Lynxpoint pinctrl driver"); 984eb83479eSAndy Shevchenko MODULE_LICENSE("GPL v2"); 985eb83479eSAndy Shevchenko MODULE_ALIAS("platform:lp_gpio"); 986