1eb83479eSAndy Shevchenko // SPDX-License-Identifier: GPL-2.0 2eb83479eSAndy Shevchenko /* 3eb83479eSAndy Shevchenko * GPIO controller driver for Intel Lynxpoint PCH chipset> 4eb83479eSAndy Shevchenko * Copyright (c) 2012, Intel Corporation. 5eb83479eSAndy Shevchenko * 6eb83479eSAndy Shevchenko * Author: Mathias Nyman <mathias.nyman@linux.intel.com> 7eb83479eSAndy Shevchenko */ 8eb83479eSAndy Shevchenko 9eb83479eSAndy Shevchenko #include <linux/acpi.h> 10eb83479eSAndy Shevchenko #include <linux/bitops.h> 11eb83479eSAndy Shevchenko #include <linux/gpio/driver.h> 12eb83479eSAndy Shevchenko #include <linux/interrupt.h> 13eb83479eSAndy Shevchenko #include <linux/io.h> 14eb83479eSAndy Shevchenko #include <linux/kernel.h> 15eb83479eSAndy Shevchenko #include <linux/module.h> 16eb83479eSAndy Shevchenko #include <linux/platform_device.h> 17eb83479eSAndy Shevchenko #include <linux/pm_runtime.h> 18eb83479eSAndy Shevchenko #include <linux/slab.h> 19eb83479eSAndy Shevchenko #include <linux/types.h> 20eb83479eSAndy Shevchenko 21cecddda7SAndy Shevchenko #include <linux/pinctrl/pinctrl.h> 22cecddda7SAndy Shevchenko #include <linux/pinctrl/pinmux.h> 23cecddda7SAndy Shevchenko #include <linux/pinctrl/pinconf.h> 24cecddda7SAndy Shevchenko #include <linux/pinctrl/pinconf-generic.h> 25cecddda7SAndy Shevchenko 26cecddda7SAndy Shevchenko #include "pinctrl-intel.h" 27cecddda7SAndy Shevchenko 28cecddda7SAndy Shevchenko #define COMMUNITY(p, n) \ 29cecddda7SAndy Shevchenko { \ 30cecddda7SAndy Shevchenko .pin_base = (p), \ 31cecddda7SAndy Shevchenko .npins = (n), \ 32cecddda7SAndy Shevchenko } 33cecddda7SAndy Shevchenko 34cecddda7SAndy Shevchenko static const struct pinctrl_pin_desc lptlp_pins[] = { 35cecddda7SAndy Shevchenko PINCTRL_PIN(0, "GP0_UART1_RXD"), 36cecddda7SAndy Shevchenko PINCTRL_PIN(1, "GP1_UART1_TXD"), 37cecddda7SAndy Shevchenko PINCTRL_PIN(2, "GP2_UART1_RTSB"), 38cecddda7SAndy Shevchenko PINCTRL_PIN(3, "GP3_UART1_CTSB"), 39cecddda7SAndy Shevchenko PINCTRL_PIN(4, "GP4_I2C0_SDA"), 40cecddda7SAndy Shevchenko PINCTRL_PIN(5, "GP5_I2C0_SCL"), 41cecddda7SAndy Shevchenko PINCTRL_PIN(6, "GP6_I2C1_SDA"), 42cecddda7SAndy Shevchenko PINCTRL_PIN(7, "GP7_I2C1_SCL"), 43cecddda7SAndy Shevchenko PINCTRL_PIN(8, "GP8"), 44cecddda7SAndy Shevchenko PINCTRL_PIN(9, "GP9"), 45cecddda7SAndy Shevchenko PINCTRL_PIN(10, "GP10"), 46cecddda7SAndy Shevchenko PINCTRL_PIN(11, "GP11_SMBALERTB"), 47cecddda7SAndy Shevchenko PINCTRL_PIN(12, "GP12_LANPHYPC"), 48cecddda7SAndy Shevchenko PINCTRL_PIN(13, "GP13"), 49cecddda7SAndy Shevchenko PINCTRL_PIN(14, "GP14"), 50cecddda7SAndy Shevchenko PINCTRL_PIN(15, "GP15"), 51cecddda7SAndy Shevchenko PINCTRL_PIN(16, "GP16_MGPIO9"), 52cecddda7SAndy Shevchenko PINCTRL_PIN(17, "GP17_MGPIO10"), 53cecddda7SAndy Shevchenko PINCTRL_PIN(18, "GP18_SRC0CLKRQB"), 54cecddda7SAndy Shevchenko PINCTRL_PIN(19, "GP19_SRC1CLKRQB"), 55cecddda7SAndy Shevchenko PINCTRL_PIN(20, "GP20_SRC2CLKRQB"), 56cecddda7SAndy Shevchenko PINCTRL_PIN(21, "GP21_SRC3CLKRQB"), 57cecddda7SAndy Shevchenko PINCTRL_PIN(22, "GP22_SRC4CLKRQB_TRST2"), 58cecddda7SAndy Shevchenko PINCTRL_PIN(23, "GP23_SRC5CLKRQB_TDI2"), 59cecddda7SAndy Shevchenko PINCTRL_PIN(24, "GP24_MGPIO0"), 60cecddda7SAndy Shevchenko PINCTRL_PIN(25, "GP25_USBWAKEOUTB"), 61cecddda7SAndy Shevchenko PINCTRL_PIN(26, "GP26_MGPIO5"), 62cecddda7SAndy Shevchenko PINCTRL_PIN(27, "GP27_MGPIO6"), 63cecddda7SAndy Shevchenko PINCTRL_PIN(28, "GP28_MGPIO7"), 64cecddda7SAndy Shevchenko PINCTRL_PIN(29, "GP29_SLP_WLANB_MGPIO3"), 65cecddda7SAndy Shevchenko PINCTRL_PIN(30, "GP30_SUSWARNB_SUSPWRDNACK_MGPIO1"), 66cecddda7SAndy Shevchenko PINCTRL_PIN(31, "GP31_ACPRESENT_MGPIO2"), 67cecddda7SAndy Shevchenko PINCTRL_PIN(32, "GP32_CLKRUNB"), 68cecddda7SAndy Shevchenko PINCTRL_PIN(33, "GP33_DEVSLP0"), 69cecddda7SAndy Shevchenko PINCTRL_PIN(34, "GP34_SATA0XPCIE6L3B_SATA0GP"), 70cecddda7SAndy Shevchenko PINCTRL_PIN(35, "GP35_SATA1XPCIE6L2B_SATA1GP"), 71cecddda7SAndy Shevchenko PINCTRL_PIN(36, "GP36_SATA2XPCIE6L1B_SATA2GP"), 72cecddda7SAndy Shevchenko PINCTRL_PIN(37, "GP37_SATA3XPCIE6L0B_SATA3GP"), 73cecddda7SAndy Shevchenko PINCTRL_PIN(38, "GP38_DEVSLP1"), 74cecddda7SAndy Shevchenko PINCTRL_PIN(39, "GP39_DEVSLP2"), 75cecddda7SAndy Shevchenko PINCTRL_PIN(40, "GP40_OC0B"), 76cecddda7SAndy Shevchenko PINCTRL_PIN(41, "GP41_OC1B"), 77cecddda7SAndy Shevchenko PINCTRL_PIN(42, "GP42_OC2B"), 78cecddda7SAndy Shevchenko PINCTRL_PIN(43, "GP43_OC3B"), 79cecddda7SAndy Shevchenko PINCTRL_PIN(44, "GP44"), 80cecddda7SAndy Shevchenko PINCTRL_PIN(45, "GP45_TMS2"), 81cecddda7SAndy Shevchenko PINCTRL_PIN(46, "GP46_TDO2"), 82cecddda7SAndy Shevchenko PINCTRL_PIN(47, "GP47"), 83cecddda7SAndy Shevchenko PINCTRL_PIN(48, "GP48"), 84cecddda7SAndy Shevchenko PINCTRL_PIN(49, "GP49"), 85cecddda7SAndy Shevchenko PINCTRL_PIN(50, "GP50"), 86cecddda7SAndy Shevchenko PINCTRL_PIN(51, "GP51_GSXDOUT"), 87cecddda7SAndy Shevchenko PINCTRL_PIN(52, "GP52_GSXSLOAD"), 88cecddda7SAndy Shevchenko PINCTRL_PIN(53, "GP53_GSXDIN"), 89cecddda7SAndy Shevchenko PINCTRL_PIN(54, "GP54_GSXSRESETB"), 90cecddda7SAndy Shevchenko PINCTRL_PIN(55, "GP55_GSXCLK"), 91cecddda7SAndy Shevchenko PINCTRL_PIN(56, "GP56"), 92cecddda7SAndy Shevchenko PINCTRL_PIN(57, "GP57"), 93cecddda7SAndy Shevchenko PINCTRL_PIN(58, "GP58"), 94cecddda7SAndy Shevchenko PINCTRL_PIN(59, "GP59"), 95cecddda7SAndy Shevchenko PINCTRL_PIN(60, "GP60_SML0ALERTB_MGPIO4"), 96cecddda7SAndy Shevchenko PINCTRL_PIN(61, "GP61_SUS_STATB"), 97cecddda7SAndy Shevchenko PINCTRL_PIN(62, "GP62_SUSCLK"), 98cecddda7SAndy Shevchenko PINCTRL_PIN(63, "GP63_SLP_S5B"), 99cecddda7SAndy Shevchenko PINCTRL_PIN(64, "GP64_SDIO_CLK"), 100cecddda7SAndy Shevchenko PINCTRL_PIN(65, "GP65_SDIO_CMD"), 101cecddda7SAndy Shevchenko PINCTRL_PIN(66, "GP66_SDIO_D0"), 102cecddda7SAndy Shevchenko PINCTRL_PIN(67, "GP67_SDIO_D1"), 103cecddda7SAndy Shevchenko PINCTRL_PIN(68, "GP68_SDIO_D2"), 104cecddda7SAndy Shevchenko PINCTRL_PIN(69, "GP69_SDIO_D3"), 105cecddda7SAndy Shevchenko PINCTRL_PIN(70, "GP70_SDIO_POWER_EN"), 106cecddda7SAndy Shevchenko PINCTRL_PIN(71, "GP71_MPHYPC"), 107cecddda7SAndy Shevchenko PINCTRL_PIN(72, "GP72_BATLOWB"), 108cecddda7SAndy Shevchenko PINCTRL_PIN(73, "GP73_SML1ALERTB_PCHHOTB_MGPIO8"), 109cecddda7SAndy Shevchenko PINCTRL_PIN(74, "GP74_SML1DATA_MGPIO12"), 110cecddda7SAndy Shevchenko PINCTRL_PIN(75, "GP75_SML1CLK_MGPIO11"), 111cecddda7SAndy Shevchenko PINCTRL_PIN(76, "GP76_BMBUSYB"), 112cecddda7SAndy Shevchenko PINCTRL_PIN(77, "GP77_PIRQAB"), 113cecddda7SAndy Shevchenko PINCTRL_PIN(78, "GP78_PIRQBB"), 114cecddda7SAndy Shevchenko PINCTRL_PIN(79, "GP79_PIRQCB"), 115cecddda7SAndy Shevchenko PINCTRL_PIN(80, "GP80_PIRQDB"), 116cecddda7SAndy Shevchenko PINCTRL_PIN(81, "GP81_SPKR"), 117cecddda7SAndy Shevchenko PINCTRL_PIN(82, "GP82_RCINB"), 118cecddda7SAndy Shevchenko PINCTRL_PIN(83, "GP83_GSPI0_CSB"), 119cecddda7SAndy Shevchenko PINCTRL_PIN(84, "GP84_GSPI0_CLK"), 120cecddda7SAndy Shevchenko PINCTRL_PIN(85, "GP85_GSPI0_MISO"), 121cecddda7SAndy Shevchenko PINCTRL_PIN(86, "GP86_GSPI0_MOSI"), 122cecddda7SAndy Shevchenko PINCTRL_PIN(87, "GP87_GSPI1_CSB"), 123cecddda7SAndy Shevchenko PINCTRL_PIN(88, "GP88_GSPI1_CLK"), 124cecddda7SAndy Shevchenko PINCTRL_PIN(89, "GP89_GSPI1_MISO"), 125cecddda7SAndy Shevchenko PINCTRL_PIN(90, "GP90_GSPI1_MOSI"), 126cecddda7SAndy Shevchenko PINCTRL_PIN(91, "GP91_UART0_RXD"), 127cecddda7SAndy Shevchenko PINCTRL_PIN(92, "GP92_UART0_TXD"), 128cecddda7SAndy Shevchenko PINCTRL_PIN(93, "GP93_UART0_RTSB"), 129cecddda7SAndy Shevchenko PINCTRL_PIN(94, "GP94_UART0_CTSB"), 130cecddda7SAndy Shevchenko }; 131cecddda7SAndy Shevchenko 132cecddda7SAndy Shevchenko static const struct intel_community lptlp_communities[] = { 133cecddda7SAndy Shevchenko COMMUNITY(0, 95), 134cecddda7SAndy Shevchenko }; 135cecddda7SAndy Shevchenko 136cecddda7SAndy Shevchenko static const struct intel_pinctrl_soc_data lptlp_soc_data = { 137cecddda7SAndy Shevchenko .pins = lptlp_pins, 138cecddda7SAndy Shevchenko .npins = ARRAY_SIZE(lptlp_pins), 139cecddda7SAndy Shevchenko .communities = lptlp_communities, 140cecddda7SAndy Shevchenko .ncommunities = ARRAY_SIZE(lptlp_communities), 141cecddda7SAndy Shevchenko }; 142cecddda7SAndy Shevchenko 1437c0bc7bbSAndy Shevchenko /* LynxPoint chipset has support for 95 GPIO pins */ 144eb83479eSAndy Shevchenko 1457c0bc7bbSAndy Shevchenko #define LP_NUM_GPIO 95 146eb83479eSAndy Shevchenko 147eb83479eSAndy Shevchenko /* Bitmapped register offsets */ 148eb83479eSAndy Shevchenko #define LP_ACPI_OWNED 0x00 /* Bitmap, set by bios, 0: pin reserved for ACPI */ 1497f32d370SAndy Shevchenko #define LP_IRQ2IOXAPIC 0x10 /* Bitmap, set by bios, 1: pin routed to IOxAPIC */ 150eb83479eSAndy Shevchenko #define LP_GC 0x7C /* set APIC IRQ to IRQ14 or IRQ15 for all pins */ 151eb83479eSAndy Shevchenko #define LP_INT_STAT 0x80 152eb83479eSAndy Shevchenko #define LP_INT_ENABLE 0x90 153eb83479eSAndy Shevchenko 154eb83479eSAndy Shevchenko /* Each pin has two 32 bit config registers, starting at 0x100 */ 155eb83479eSAndy Shevchenko #define LP_CONFIG1 0x100 156eb83479eSAndy Shevchenko #define LP_CONFIG2 0x104 157eb83479eSAndy Shevchenko 158eb83479eSAndy Shevchenko /* LP_CONFIG1 reg bits */ 159eb83479eSAndy Shevchenko #define OUT_LVL_BIT BIT(31) 160eb83479eSAndy Shevchenko #define IN_LVL_BIT BIT(30) 161eb83479eSAndy Shevchenko #define TRIG_SEL_BIT BIT(4) /* 0: Edge, 1: Level */ 162eb83479eSAndy Shevchenko #define INT_INV_BIT BIT(3) /* Invert interrupt triggering */ 163eb83479eSAndy Shevchenko #define DIR_BIT BIT(2) /* 0: Output, 1: Input */ 16476347d7aSAndy Shevchenko #define USE_SEL_MASK GENMASK(1, 0) /* 0: Native, 1: GPIO, ... */ 16576347d7aSAndy Shevchenko #define USE_SEL_NATIVE (0 << 0) 16676347d7aSAndy Shevchenko #define USE_SEL_GPIO (1 << 0) 167eb83479eSAndy Shevchenko 168eb83479eSAndy Shevchenko /* LP_CONFIG2 reg bits */ 169eb83479eSAndy Shevchenko #define GPINDIS_BIT BIT(2) /* disable input sensing */ 1707f32d370SAndy Shevchenko #define GPIWP_MASK GENMASK(1, 0) /* weak pull options */ 1717f32d370SAndy Shevchenko #define GPIWP_NONE 0 /* none */ 1727f32d370SAndy Shevchenko #define GPIWP_DOWN 1 /* weak pull down */ 1737f32d370SAndy Shevchenko #define GPIWP_UP 2 /* weak pull up */ 174eb83479eSAndy Shevchenko 175eb83479eSAndy Shevchenko /* 176eb83479eSAndy Shevchenko * Lynxpoint gpios are controlled through both bitmapped registers and 177eb83479eSAndy Shevchenko * per gpio specific registers. The bitmapped registers are in chunks of 1787c0bc7bbSAndy Shevchenko * 3 x 32bit registers to cover all 95 GPIOs 179eb83479eSAndy Shevchenko * 180eb83479eSAndy Shevchenko * per gpio specific registers consist of two 32bit registers per gpio 1817c0bc7bbSAndy Shevchenko * (LP_CONFIG1 and LP_CONFIG2), with 95 GPIOs there's a total of 1827c0bc7bbSAndy Shevchenko * 190 config registers. 183eb83479eSAndy Shevchenko * 184eb83479eSAndy Shevchenko * A simplified view of the register layout look like this: 185eb83479eSAndy Shevchenko * 186eb83479eSAndy Shevchenko * LP_ACPI_OWNED[31:0] gpio ownerships for gpios 0-31 (bitmapped registers) 187eb83479eSAndy Shevchenko * LP_ACPI_OWNED[63:32] gpio ownerships for gpios 32-63 188eb83479eSAndy Shevchenko * LP_ACPI_OWNED[94:64] gpio ownerships for gpios 63-94 189eb83479eSAndy Shevchenko * ... 190eb83479eSAndy Shevchenko * LP_INT_ENABLE[31:0] ... 1917c0bc7bbSAndy Shevchenko * LP_INT_ENABLE[63:32] ... 192eb83479eSAndy Shevchenko * LP_INT_ENABLE[94:64] ... 193eb83479eSAndy Shevchenko * LP0_CONFIG1 (gpio 0) config1 reg for gpio 0 (per gpio registers) 194eb83479eSAndy Shevchenko * LP0_CONFIG2 (gpio 0) config2 reg for gpio 0 195eb83479eSAndy Shevchenko * LP1_CONFIG1 (gpio 1) config1 reg for gpio 1 196eb83479eSAndy Shevchenko * LP1_CONFIG2 (gpio 1) config2 reg for gpio 1 197eb83479eSAndy Shevchenko * LP2_CONFIG1 (gpio 2) ... 198eb83479eSAndy Shevchenko * LP2_CONFIG2 (gpio 2) ... 199eb83479eSAndy Shevchenko * ... 200eb83479eSAndy Shevchenko * LP94_CONFIG1 (gpio 94) ... 201eb83479eSAndy Shevchenko * LP94_CONFIG2 (gpio 94) ... 2027f32d370SAndy Shevchenko * 2037f32d370SAndy Shevchenko * IOxAPIC redirection map applies only for gpio 8-10, 13-14, 45-55. 204eb83479eSAndy Shevchenko */ 205eb83479eSAndy Shevchenko 20618213ad4SAndy Shevchenko static struct intel_community *lp_get_community(struct intel_pinctrl *lg, 20718213ad4SAndy Shevchenko unsigned int pin) 20818213ad4SAndy Shevchenko { 20918213ad4SAndy Shevchenko struct intel_community *comm; 21018213ad4SAndy Shevchenko int i; 21118213ad4SAndy Shevchenko 21218213ad4SAndy Shevchenko for (i = 0; i < lg->ncommunities; i++) { 21318213ad4SAndy Shevchenko comm = &lg->communities[i]; 21418213ad4SAndy Shevchenko if (pin < comm->pin_base + comm->npins && pin >= comm->pin_base) 21518213ad4SAndy Shevchenko return comm; 21618213ad4SAndy Shevchenko } 21718213ad4SAndy Shevchenko 21818213ad4SAndy Shevchenko return NULL; 21918213ad4SAndy Shevchenko } 22018213ad4SAndy Shevchenko 221c35f463aSAndy Shevchenko static void __iomem *lp_gpio_reg(struct gpio_chip *chip, unsigned int offset, 222eb83479eSAndy Shevchenko int reg) 223eb83479eSAndy Shevchenko { 22418213ad4SAndy Shevchenko struct intel_pinctrl *lg = gpiochip_get_data(chip); 22518213ad4SAndy Shevchenko struct intel_community *comm; 226eb83479eSAndy Shevchenko int reg_offset; 227eb83479eSAndy Shevchenko 22818213ad4SAndy Shevchenko comm = lp_get_community(lg, offset); 22918213ad4SAndy Shevchenko if (!comm) 23018213ad4SAndy Shevchenko return NULL; 23118213ad4SAndy Shevchenko 23218213ad4SAndy Shevchenko offset -= comm->pin_base; 23318213ad4SAndy Shevchenko 234eb83479eSAndy Shevchenko if (reg == LP_CONFIG1 || reg == LP_CONFIG2) 235eb83479eSAndy Shevchenko /* per gpio specific config registers */ 236eb83479eSAndy Shevchenko reg_offset = offset * 8; 237eb83479eSAndy Shevchenko else 238eb83479eSAndy Shevchenko /* bitmapped registers */ 239eb83479eSAndy Shevchenko reg_offset = (offset / 32) * 4; 240eb83479eSAndy Shevchenko 24118213ad4SAndy Shevchenko return comm->regs + reg_offset + reg; 242eb83479eSAndy Shevchenko } 243eb83479eSAndy Shevchenko 24418213ad4SAndy Shevchenko static bool lp_gpio_acpi_use(struct intel_pinctrl *lg, unsigned int pin) 24521a06495SAndy Shevchenko { 24621a06495SAndy Shevchenko void __iomem *acpi_use; 24721a06495SAndy Shevchenko 24821a06495SAndy Shevchenko acpi_use = lp_gpio_reg(&lg->chip, pin, LP_ACPI_OWNED); 24921a06495SAndy Shevchenko if (!acpi_use) 25021a06495SAndy Shevchenko return true; 25121a06495SAndy Shevchenko 25221a06495SAndy Shevchenko return !(ioread32(acpi_use) & BIT(pin % 32)); 25321a06495SAndy Shevchenko } 25421a06495SAndy Shevchenko 2557f32d370SAndy Shevchenko static bool lp_gpio_ioxapic_use(struct gpio_chip *chip, unsigned int offset) 2567f32d370SAndy Shevchenko { 2577f32d370SAndy Shevchenko void __iomem *ioxapic_use = lp_gpio_reg(chip, offset, LP_IRQ2IOXAPIC); 2587f32d370SAndy Shevchenko u32 value; 2597f32d370SAndy Shevchenko 2607f32d370SAndy Shevchenko value = ioread32(ioxapic_use); 2617f32d370SAndy Shevchenko 2627f32d370SAndy Shevchenko if (offset >= 8 && offset <= 10) 2637f32d370SAndy Shevchenko return !!(value & BIT(offset - 8 + 0)); 2647f32d370SAndy Shevchenko if (offset >= 13 && offset <= 14) 2657f32d370SAndy Shevchenko return !!(value & BIT(offset - 13 + 3)); 2667f32d370SAndy Shevchenko if (offset >= 45 && offset <= 55) 2677f32d370SAndy Shevchenko return !!(value & BIT(offset - 45 + 5)); 2687f32d370SAndy Shevchenko 2697f32d370SAndy Shevchenko return false; 2707f32d370SAndy Shevchenko } 2717f32d370SAndy Shevchenko 2727f32d370SAndy Shevchenko static int lp_get_groups_count(struct pinctrl_dev *pctldev) 2737f32d370SAndy Shevchenko { 2747f32d370SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 2757f32d370SAndy Shevchenko 2767f32d370SAndy Shevchenko return lg->soc->ngroups; 2777f32d370SAndy Shevchenko } 2787f32d370SAndy Shevchenko 2797f32d370SAndy Shevchenko static const char *lp_get_group_name(struct pinctrl_dev *pctldev, 2807f32d370SAndy Shevchenko unsigned int selector) 2817f32d370SAndy Shevchenko { 2827f32d370SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 2837f32d370SAndy Shevchenko 2847f32d370SAndy Shevchenko return lg->soc->groups[selector].name; 2857f32d370SAndy Shevchenko } 2867f32d370SAndy Shevchenko 2877f32d370SAndy Shevchenko static int lp_get_group_pins(struct pinctrl_dev *pctldev, 2887f32d370SAndy Shevchenko unsigned int selector, 2897f32d370SAndy Shevchenko const unsigned int **pins, 2907f32d370SAndy Shevchenko unsigned int *num_pins) 2917f32d370SAndy Shevchenko { 2927f32d370SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 2937f32d370SAndy Shevchenko 2947f32d370SAndy Shevchenko *pins = lg->soc->groups[selector].pins; 2957f32d370SAndy Shevchenko *num_pins = lg->soc->groups[selector].npins; 2967f32d370SAndy Shevchenko 2977f32d370SAndy Shevchenko return 0; 2987f32d370SAndy Shevchenko } 2997f32d370SAndy Shevchenko 30003d9eca7SAndy Shevchenko static void lp_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, 30103d9eca7SAndy Shevchenko unsigned int pin) 30203d9eca7SAndy Shevchenko { 30303d9eca7SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 30403d9eca7SAndy Shevchenko void __iomem *reg = lp_gpio_reg(&lg->chip, pin, LP_CONFIG1); 30503d9eca7SAndy Shevchenko void __iomem *conf2 = lp_gpio_reg(&lg->chip, pin, LP_CONFIG2); 30603d9eca7SAndy Shevchenko u32 value, mode; 30703d9eca7SAndy Shevchenko 30803d9eca7SAndy Shevchenko value = ioread32(reg); 30903d9eca7SAndy Shevchenko 31003d9eca7SAndy Shevchenko mode = value & USE_SEL_MASK; 31103d9eca7SAndy Shevchenko if (mode == USE_SEL_GPIO) 31203d9eca7SAndy Shevchenko seq_puts(s, "GPIO "); 31303d9eca7SAndy Shevchenko else 31403d9eca7SAndy Shevchenko seq_printf(s, "mode %d ", mode); 31503d9eca7SAndy Shevchenko 31603d9eca7SAndy Shevchenko seq_printf(s, "0x%08x 0x%08x", value, ioread32(conf2)); 31703d9eca7SAndy Shevchenko 31803d9eca7SAndy Shevchenko if (lp_gpio_acpi_use(lg, pin)) 31903d9eca7SAndy Shevchenko seq_puts(s, " [ACPI]"); 32003d9eca7SAndy Shevchenko } 32103d9eca7SAndy Shevchenko 3227f32d370SAndy Shevchenko static const struct pinctrl_ops lptlp_pinctrl_ops = { 3237f32d370SAndy Shevchenko .get_groups_count = lp_get_groups_count, 3247f32d370SAndy Shevchenko .get_group_name = lp_get_group_name, 3257f32d370SAndy Shevchenko .get_group_pins = lp_get_group_pins, 32603d9eca7SAndy Shevchenko .pin_dbg_show = lp_pin_dbg_show, 3277f32d370SAndy Shevchenko }; 3287f32d370SAndy Shevchenko 3297f32d370SAndy Shevchenko static int lp_get_functions_count(struct pinctrl_dev *pctldev) 3307f32d370SAndy Shevchenko { 3317f32d370SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 3327f32d370SAndy Shevchenko 3337f32d370SAndy Shevchenko return lg->soc->nfunctions; 3347f32d370SAndy Shevchenko } 3357f32d370SAndy Shevchenko 3367f32d370SAndy Shevchenko static const char *lp_get_function_name(struct pinctrl_dev *pctldev, 3377f32d370SAndy Shevchenko unsigned int selector) 3387f32d370SAndy Shevchenko { 3397f32d370SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 3407f32d370SAndy Shevchenko 3417f32d370SAndy Shevchenko return lg->soc->functions[selector].name; 3427f32d370SAndy Shevchenko } 3437f32d370SAndy Shevchenko 3447f32d370SAndy Shevchenko static int lp_get_function_groups(struct pinctrl_dev *pctldev, 3457f32d370SAndy Shevchenko unsigned int selector, 3467f32d370SAndy Shevchenko const char * const **groups, 3477f32d370SAndy Shevchenko unsigned int *num_groups) 3487f32d370SAndy Shevchenko { 3497f32d370SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 3507f32d370SAndy Shevchenko 3517f32d370SAndy Shevchenko *groups = lg->soc->functions[selector].groups; 3527f32d370SAndy Shevchenko *num_groups = lg->soc->functions[selector].ngroups; 3537f32d370SAndy Shevchenko 3547f32d370SAndy Shevchenko return 0; 3557f32d370SAndy Shevchenko } 3567f32d370SAndy Shevchenko 3577f32d370SAndy Shevchenko static int lp_pinmux_set_mux(struct pinctrl_dev *pctldev, 3587f32d370SAndy Shevchenko unsigned int function, unsigned int group) 3597f32d370SAndy Shevchenko { 3607f32d370SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 3617f32d370SAndy Shevchenko const struct intel_pingroup *grp = &lg->soc->groups[group]; 3627f32d370SAndy Shevchenko unsigned long flags; 3637f32d370SAndy Shevchenko int i; 3647f32d370SAndy Shevchenko 3657f32d370SAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 3667f32d370SAndy Shevchenko 3677f32d370SAndy Shevchenko /* Now enable the mux setting for each pin in the group */ 3687f32d370SAndy Shevchenko for (i = 0; i < grp->npins; i++) { 3697f32d370SAndy Shevchenko void __iomem *reg = lp_gpio_reg(&lg->chip, grp->pins[i], LP_CONFIG1); 3707f32d370SAndy Shevchenko u32 value; 3717f32d370SAndy Shevchenko 3727f32d370SAndy Shevchenko value = ioread32(reg); 3737f32d370SAndy Shevchenko 3747f32d370SAndy Shevchenko value &= ~USE_SEL_MASK; 3757f32d370SAndy Shevchenko if (grp->modes) 3767f32d370SAndy Shevchenko value |= grp->modes[i]; 3777f32d370SAndy Shevchenko else 3787f32d370SAndy Shevchenko value |= grp->mode; 3797f32d370SAndy Shevchenko 3807f32d370SAndy Shevchenko iowrite32(value, reg); 3817f32d370SAndy Shevchenko } 3827f32d370SAndy Shevchenko 3837f32d370SAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 3847f32d370SAndy Shevchenko 3857f32d370SAndy Shevchenko return 0; 3867f32d370SAndy Shevchenko } 3877f32d370SAndy Shevchenko 3887f32d370SAndy Shevchenko static int lp_gpio_request_enable(struct pinctrl_dev *pctldev, 3897f32d370SAndy Shevchenko struct pinctrl_gpio_range *range, 3907f32d370SAndy Shevchenko unsigned int pin) 3917f32d370SAndy Shevchenko { 3927f32d370SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 3937f32d370SAndy Shevchenko void __iomem *reg = lp_gpio_reg(&lg->chip, pin, LP_CONFIG1); 3947f32d370SAndy Shevchenko void __iomem *conf2 = lp_gpio_reg(&lg->chip, pin, LP_CONFIG2); 3957f32d370SAndy Shevchenko unsigned long flags; 3967f32d370SAndy Shevchenko u32 value; 3977f32d370SAndy Shevchenko 3987f32d370SAndy Shevchenko pm_runtime_get(lg->dev); 3997f32d370SAndy Shevchenko 4007f32d370SAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 4017f32d370SAndy Shevchenko 4027f32d370SAndy Shevchenko /* 4037f32d370SAndy Shevchenko * Reconfigure pin to GPIO mode if needed and issue a warning, 4047f32d370SAndy Shevchenko * since we expect firmware to configure it properly. 4057f32d370SAndy Shevchenko */ 4067f32d370SAndy Shevchenko value = ioread32(reg); 4077f32d370SAndy Shevchenko if ((value & USE_SEL_MASK) != USE_SEL_GPIO) { 4087f32d370SAndy Shevchenko iowrite32((value & USE_SEL_MASK) | USE_SEL_GPIO, reg); 4097f32d370SAndy Shevchenko dev_warn(lg->dev, FW_BUG "pin %u forcibly reconfigured as GPIO\n", pin); 4107f32d370SAndy Shevchenko } 4117f32d370SAndy Shevchenko 4127f32d370SAndy Shevchenko /* Enable input sensing */ 4137f32d370SAndy Shevchenko iowrite32(ioread32(conf2) & ~GPINDIS_BIT, conf2); 4147f32d370SAndy Shevchenko 4157f32d370SAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 4167f32d370SAndy Shevchenko 4177f32d370SAndy Shevchenko return 0; 4187f32d370SAndy Shevchenko } 4197f32d370SAndy Shevchenko 4207f32d370SAndy Shevchenko static void lp_gpio_disable_free(struct pinctrl_dev *pctldev, 4217f32d370SAndy Shevchenko struct pinctrl_gpio_range *range, 4227f32d370SAndy Shevchenko unsigned int pin) 4237f32d370SAndy Shevchenko { 4247f32d370SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 4257f32d370SAndy Shevchenko void __iomem *conf2 = lp_gpio_reg(&lg->chip, pin, LP_CONFIG2); 4267f32d370SAndy Shevchenko unsigned long flags; 4277f32d370SAndy Shevchenko 4287f32d370SAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 4297f32d370SAndy Shevchenko 4307f32d370SAndy Shevchenko /* Disable input sensing */ 4317f32d370SAndy Shevchenko iowrite32(ioread32(conf2) | GPINDIS_BIT, conf2); 4327f32d370SAndy Shevchenko 4337f32d370SAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 4347f32d370SAndy Shevchenko 4357f32d370SAndy Shevchenko pm_runtime_put(lg->dev); 4367f32d370SAndy Shevchenko } 4377f32d370SAndy Shevchenko 4387f32d370SAndy Shevchenko static int lp_gpio_set_direction(struct pinctrl_dev *pctldev, 4397f32d370SAndy Shevchenko struct pinctrl_gpio_range *range, 4407f32d370SAndy Shevchenko unsigned int pin, bool input) 4417f32d370SAndy Shevchenko { 4427f32d370SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 4437f32d370SAndy Shevchenko void __iomem *reg = lp_gpio_reg(&lg->chip, pin, LP_CONFIG1); 4447f32d370SAndy Shevchenko unsigned long flags; 4457f32d370SAndy Shevchenko u32 value; 4467f32d370SAndy Shevchenko 4477f32d370SAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 4487f32d370SAndy Shevchenko 4497f32d370SAndy Shevchenko value = ioread32(reg); 4507f32d370SAndy Shevchenko value &= ~DIR_BIT; 4517f32d370SAndy Shevchenko if (input) { 4527f32d370SAndy Shevchenko value |= DIR_BIT; 4537f32d370SAndy Shevchenko } else { 4547f32d370SAndy Shevchenko /* 4557f32d370SAndy Shevchenko * Before making any direction modifications, do a check if GPIO 4567f32d370SAndy Shevchenko * is set for direct IRQ. On Lynxpoint, setting GPIO to output 4577f32d370SAndy Shevchenko * does not make sense, so let's at least warn the caller before 4587f32d370SAndy Shevchenko * they shoot themselves in the foot. 4597f32d370SAndy Shevchenko */ 4607f32d370SAndy Shevchenko WARN(lp_gpio_ioxapic_use(&lg->chip, pin), 4617f32d370SAndy Shevchenko "Potential Error: Setting GPIO to output with IOxAPIC redirection"); 4627f32d370SAndy Shevchenko } 4637f32d370SAndy Shevchenko iowrite32(value, reg); 4647f32d370SAndy Shevchenko 4657f32d370SAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 4667f32d370SAndy Shevchenko 4677f32d370SAndy Shevchenko return 0; 4687f32d370SAndy Shevchenko } 4697f32d370SAndy Shevchenko 4707f32d370SAndy Shevchenko static const struct pinmux_ops lptlp_pinmux_ops = { 4717f32d370SAndy Shevchenko .get_functions_count = lp_get_functions_count, 4727f32d370SAndy Shevchenko .get_function_name = lp_get_function_name, 4737f32d370SAndy Shevchenko .get_function_groups = lp_get_function_groups, 4747f32d370SAndy Shevchenko .set_mux = lp_pinmux_set_mux, 4757f32d370SAndy Shevchenko .gpio_request_enable = lp_gpio_request_enable, 4767f32d370SAndy Shevchenko .gpio_disable_free = lp_gpio_disable_free, 4777f32d370SAndy Shevchenko .gpio_set_direction = lp_gpio_set_direction, 4787f32d370SAndy Shevchenko }; 4797f32d370SAndy Shevchenko 4807f32d370SAndy Shevchenko static int lp_pin_config_get(struct pinctrl_dev *pctldev, unsigned int pin, 4817f32d370SAndy Shevchenko unsigned long *config) 4827f32d370SAndy Shevchenko { 4837f32d370SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 4847f32d370SAndy Shevchenko void __iomem *conf2 = lp_gpio_reg(&lg->chip, pin, LP_CONFIG2); 4857f32d370SAndy Shevchenko enum pin_config_param param = pinconf_to_config_param(*config); 4867f32d370SAndy Shevchenko unsigned long flags; 4877f32d370SAndy Shevchenko u32 value, pull; 4887f32d370SAndy Shevchenko u16 arg = 0; 4897f32d370SAndy Shevchenko 4907f32d370SAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 4917f32d370SAndy Shevchenko value = ioread32(conf2); 4927f32d370SAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 4937f32d370SAndy Shevchenko 4947f32d370SAndy Shevchenko pull = value & GPIWP_MASK; 4957f32d370SAndy Shevchenko 4967f32d370SAndy Shevchenko switch (param) { 4977f32d370SAndy Shevchenko case PIN_CONFIG_BIAS_DISABLE: 4987f32d370SAndy Shevchenko if (pull) 4997f32d370SAndy Shevchenko return -EINVAL; 5007f32d370SAndy Shevchenko break; 5017f32d370SAndy Shevchenko case PIN_CONFIG_BIAS_PULL_DOWN: 5027f32d370SAndy Shevchenko if (pull != GPIWP_DOWN) 5037f32d370SAndy Shevchenko return -EINVAL; 5047f32d370SAndy Shevchenko 5057f32d370SAndy Shevchenko arg = 1; 5067f32d370SAndy Shevchenko break; 5077f32d370SAndy Shevchenko case PIN_CONFIG_BIAS_PULL_UP: 5087f32d370SAndy Shevchenko if (pull != GPIWP_UP) 5097f32d370SAndy Shevchenko return -EINVAL; 5107f32d370SAndy Shevchenko 5117f32d370SAndy Shevchenko arg = 1; 5127f32d370SAndy Shevchenko break; 5137f32d370SAndy Shevchenko default: 5147f32d370SAndy Shevchenko return -ENOTSUPP; 5157f32d370SAndy Shevchenko } 5167f32d370SAndy Shevchenko 5177f32d370SAndy Shevchenko *config = pinconf_to_config_packed(param, arg); 5187f32d370SAndy Shevchenko 5197f32d370SAndy Shevchenko return 0; 5207f32d370SAndy Shevchenko } 5217f32d370SAndy Shevchenko 5227f32d370SAndy Shevchenko static int lp_pin_config_set(struct pinctrl_dev *pctldev, unsigned int pin, 5237f32d370SAndy Shevchenko unsigned long *configs, unsigned int num_configs) 5247f32d370SAndy Shevchenko { 5257f32d370SAndy Shevchenko struct intel_pinctrl *lg = pinctrl_dev_get_drvdata(pctldev); 5267f32d370SAndy Shevchenko void __iomem *conf2 = lp_gpio_reg(&lg->chip, pin, LP_CONFIG2); 5277f32d370SAndy Shevchenko enum pin_config_param param; 5287f32d370SAndy Shevchenko unsigned long flags; 5297f32d370SAndy Shevchenko int i, ret = 0; 5307f32d370SAndy Shevchenko u32 value; 5317f32d370SAndy Shevchenko 5327f32d370SAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 5337f32d370SAndy Shevchenko 5347f32d370SAndy Shevchenko value = ioread32(conf2); 5357f32d370SAndy Shevchenko 5367f32d370SAndy Shevchenko for (i = 0; i < num_configs; i++) { 5377f32d370SAndy Shevchenko param = pinconf_to_config_param(configs[i]); 5387f32d370SAndy Shevchenko 5397f32d370SAndy Shevchenko switch (param) { 5407f32d370SAndy Shevchenko case PIN_CONFIG_BIAS_DISABLE: 5417f32d370SAndy Shevchenko value &= ~GPIWP_MASK; 5427f32d370SAndy Shevchenko break; 5437f32d370SAndy Shevchenko case PIN_CONFIG_BIAS_PULL_DOWN: 5447f32d370SAndy Shevchenko value &= ~GPIWP_MASK; 5457f32d370SAndy Shevchenko value |= GPIWP_DOWN; 5467f32d370SAndy Shevchenko break; 5477f32d370SAndy Shevchenko case PIN_CONFIG_BIAS_PULL_UP: 5487f32d370SAndy Shevchenko value &= ~GPIWP_MASK; 5497f32d370SAndy Shevchenko value |= GPIWP_UP; 5507f32d370SAndy Shevchenko break; 5517f32d370SAndy Shevchenko default: 5527f32d370SAndy Shevchenko ret = -ENOTSUPP; 5537f32d370SAndy Shevchenko } 5547f32d370SAndy Shevchenko 5557f32d370SAndy Shevchenko if (ret) 5567f32d370SAndy Shevchenko break; 5577f32d370SAndy Shevchenko } 5587f32d370SAndy Shevchenko 5597f32d370SAndy Shevchenko if (!ret) 5607f32d370SAndy Shevchenko iowrite32(value, conf2); 5617f32d370SAndy Shevchenko 5627f32d370SAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 5637f32d370SAndy Shevchenko 5647f32d370SAndy Shevchenko return ret; 5657f32d370SAndy Shevchenko } 5667f32d370SAndy Shevchenko 5677f32d370SAndy Shevchenko static const struct pinconf_ops lptlp_pinconf_ops = { 5687f32d370SAndy Shevchenko .is_generic = true, 5697f32d370SAndy Shevchenko .pin_config_get = lp_pin_config_get, 5707f32d370SAndy Shevchenko .pin_config_set = lp_pin_config_set, 5717f32d370SAndy Shevchenko }; 5727f32d370SAndy Shevchenko 5737f32d370SAndy Shevchenko static const struct pinctrl_desc lptlp_pinctrl_desc = { 5747f32d370SAndy Shevchenko .pctlops = &lptlp_pinctrl_ops, 5757f32d370SAndy Shevchenko .pmxops = &lptlp_pinmux_ops, 5767f32d370SAndy Shevchenko .confops = &lptlp_pinconf_ops, 5777f32d370SAndy Shevchenko .owner = THIS_MODULE, 5787f32d370SAndy Shevchenko }; 5797f32d370SAndy Shevchenko 580c35f463aSAndy Shevchenko static int lp_gpio_get(struct gpio_chip *chip, unsigned int offset) 581eb83479eSAndy Shevchenko { 582e1940adeSAndy Shevchenko void __iomem *reg = lp_gpio_reg(chip, offset, LP_CONFIG1); 583e1940adeSAndy Shevchenko return !!(ioread32(reg) & IN_LVL_BIT); 584eb83479eSAndy Shevchenko } 585eb83479eSAndy Shevchenko 586c35f463aSAndy Shevchenko static void lp_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) 587eb83479eSAndy Shevchenko { 58818213ad4SAndy Shevchenko struct intel_pinctrl *lg = gpiochip_get_data(chip); 589e1940adeSAndy Shevchenko void __iomem *reg = lp_gpio_reg(chip, offset, LP_CONFIG1); 590eb83479eSAndy Shevchenko unsigned long flags; 591eb83479eSAndy Shevchenko 592b2e05d63SAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 593eb83479eSAndy Shevchenko 594eb83479eSAndy Shevchenko if (value) 595e1940adeSAndy Shevchenko iowrite32(ioread32(reg) | OUT_LVL_BIT, reg); 596eb83479eSAndy Shevchenko else 597e1940adeSAndy Shevchenko iowrite32(ioread32(reg) & ~OUT_LVL_BIT, reg); 598eb83479eSAndy Shevchenko 599b2e05d63SAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 600eb83479eSAndy Shevchenko } 601eb83479eSAndy Shevchenko 602c35f463aSAndy Shevchenko static int lp_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) 603eb83479eSAndy Shevchenko { 604*64e14e90SAndy Shevchenko return pinctrl_gpio_direction_input(chip->base + offset); 605eb83479eSAndy Shevchenko } 606eb83479eSAndy Shevchenko 607c35f463aSAndy Shevchenko static int lp_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, 608c35f463aSAndy Shevchenko int value) 609eb83479eSAndy Shevchenko { 610eb83479eSAndy Shevchenko lp_gpio_set(chip, offset, value); 611eb83479eSAndy Shevchenko 612*64e14e90SAndy Shevchenko return pinctrl_gpio_direction_output(chip->base + offset); 613eb83479eSAndy Shevchenko } 614eb83479eSAndy Shevchenko 61554d371cfSAndy Shevchenko static int lp_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) 61654d371cfSAndy Shevchenko { 61754d371cfSAndy Shevchenko void __iomem *reg = lp_gpio_reg(chip, offset, LP_CONFIG1); 61854d371cfSAndy Shevchenko 61954d371cfSAndy Shevchenko if (ioread32(reg) & DIR_BIT) 62054d371cfSAndy Shevchenko return GPIO_LINE_DIRECTION_IN; 62154d371cfSAndy Shevchenko 62254d371cfSAndy Shevchenko return GPIO_LINE_DIRECTION_OUT; 62354d371cfSAndy Shevchenko } 62454d371cfSAndy Shevchenko 625eb83479eSAndy Shevchenko static void lp_gpio_irq_handler(struct irq_desc *desc) 626eb83479eSAndy Shevchenko { 627eb83479eSAndy Shevchenko struct irq_data *data = irq_desc_get_irq_data(desc); 628eb83479eSAndy Shevchenko struct gpio_chip *gc = irq_desc_get_handler_data(desc); 62918213ad4SAndy Shevchenko struct intel_pinctrl *lg = gpiochip_get_data(gc); 630eb83479eSAndy Shevchenko struct irq_chip *chip = irq_data_get_irq_chip(data); 631e1940adeSAndy Shevchenko void __iomem *reg, *ena; 632e1940adeSAndy Shevchenko unsigned long pending; 633eb83479eSAndy Shevchenko u32 base, pin; 634eb83479eSAndy Shevchenko 635eb83479eSAndy Shevchenko /* check from GPIO controller which pin triggered the interrupt */ 636eb83479eSAndy Shevchenko for (base = 0; base < lg->chip.ngpio; base += 32) { 637eb83479eSAndy Shevchenko reg = lp_gpio_reg(&lg->chip, base, LP_INT_STAT); 638eb83479eSAndy Shevchenko ena = lp_gpio_reg(&lg->chip, base, LP_INT_ENABLE); 639eb83479eSAndy Shevchenko 640eb83479eSAndy Shevchenko /* Only interrupts that are enabled */ 641e1940adeSAndy Shevchenko pending = ioread32(reg) & ioread32(ena); 642eb83479eSAndy Shevchenko 643eb83479eSAndy Shevchenko for_each_set_bit(pin, &pending, 32) { 644c35f463aSAndy Shevchenko unsigned int irq; 645eb83479eSAndy Shevchenko 646eb83479eSAndy Shevchenko irq = irq_find_mapping(lg->chip.irq.domain, base + pin); 647eb83479eSAndy Shevchenko generic_handle_irq(irq); 648eb83479eSAndy Shevchenko } 649eb83479eSAndy Shevchenko } 650eb83479eSAndy Shevchenko chip->irq_eoi(data); 651eb83479eSAndy Shevchenko } 652eb83479eSAndy Shevchenko 6535931e6edSAndy Shevchenko static void lp_irq_ack(struct irq_data *d) 6545931e6edSAndy Shevchenko { 6555931e6edSAndy Shevchenko struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 65618213ad4SAndy Shevchenko struct intel_pinctrl *lg = gpiochip_get_data(gc); 6575931e6edSAndy Shevchenko u32 hwirq = irqd_to_hwirq(d); 6585931e6edSAndy Shevchenko void __iomem *reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_STAT); 6595931e6edSAndy Shevchenko unsigned long flags; 6605931e6edSAndy Shevchenko 6615931e6edSAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 6625931e6edSAndy Shevchenko iowrite32(BIT(hwirq % 32), reg); 6635931e6edSAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 6645931e6edSAndy Shevchenko } 6655931e6edSAndy Shevchenko 666eb83479eSAndy Shevchenko static void lp_irq_unmask(struct irq_data *d) 667eb83479eSAndy Shevchenko { 668eb83479eSAndy Shevchenko } 669eb83479eSAndy Shevchenko 670eb83479eSAndy Shevchenko static void lp_irq_mask(struct irq_data *d) 671eb83479eSAndy Shevchenko { 672eb83479eSAndy Shevchenko } 673eb83479eSAndy Shevchenko 674eb83479eSAndy Shevchenko static void lp_irq_enable(struct irq_data *d) 675eb83479eSAndy Shevchenko { 676eb83479eSAndy Shevchenko struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 67718213ad4SAndy Shevchenko struct intel_pinctrl *lg = gpiochip_get_data(gc); 678eb83479eSAndy Shevchenko u32 hwirq = irqd_to_hwirq(d); 679e1940adeSAndy Shevchenko void __iomem *reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE); 680eb83479eSAndy Shevchenko unsigned long flags; 681eb83479eSAndy Shevchenko 682b2e05d63SAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 683e1940adeSAndy Shevchenko iowrite32(ioread32(reg) | BIT(hwirq % 32), reg); 684b2e05d63SAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 685eb83479eSAndy Shevchenko } 686eb83479eSAndy Shevchenko 687eb83479eSAndy Shevchenko static void lp_irq_disable(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 700095f2a67SAndy Shevchenko static int lp_irq_set_type(struct irq_data *d, unsigned int type) 701095f2a67SAndy Shevchenko { 702095f2a67SAndy Shevchenko struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 70318213ad4SAndy Shevchenko struct intel_pinctrl *lg = gpiochip_get_data(gc); 704095f2a67SAndy Shevchenko u32 hwirq = irqd_to_hwirq(d); 705095f2a67SAndy Shevchenko void __iomem *reg = lp_gpio_reg(&lg->chip, hwirq, LP_CONFIG1); 706095f2a67SAndy Shevchenko unsigned long flags; 707095f2a67SAndy Shevchenko u32 value; 708095f2a67SAndy Shevchenko 709095f2a67SAndy Shevchenko if (hwirq >= lg->chip.ngpio) 710095f2a67SAndy Shevchenko return -EINVAL; 711095f2a67SAndy Shevchenko 712540bff18SAndy Shevchenko /* Fail if BIOS reserved pin for ACPI use */ 713540bff18SAndy Shevchenko if (lp_gpio_acpi_use(lg, hwirq)) { 714540bff18SAndy Shevchenko dev_err(lg->dev, "pin %u can't be used as IRQ\n", hwirq); 715540bff18SAndy Shevchenko return -EBUSY; 716540bff18SAndy Shevchenko } 717540bff18SAndy Shevchenko 718095f2a67SAndy Shevchenko raw_spin_lock_irqsave(&lg->lock, flags); 719095f2a67SAndy Shevchenko value = ioread32(reg); 720095f2a67SAndy Shevchenko 721095f2a67SAndy Shevchenko /* set both TRIG_SEL and INV bits to 0 for rising edge */ 722095f2a67SAndy Shevchenko if (type & IRQ_TYPE_EDGE_RISING) 723095f2a67SAndy Shevchenko value &= ~(TRIG_SEL_BIT | INT_INV_BIT); 724095f2a67SAndy Shevchenko 725095f2a67SAndy Shevchenko /* TRIG_SEL bit 0, INV bit 1 for falling edge */ 726095f2a67SAndy Shevchenko if (type & IRQ_TYPE_EDGE_FALLING) 727095f2a67SAndy Shevchenko value = (value | INT_INV_BIT) & ~TRIG_SEL_BIT; 728095f2a67SAndy Shevchenko 729095f2a67SAndy Shevchenko /* TRIG_SEL bit 1, INV bit 0 for level low */ 730095f2a67SAndy Shevchenko if (type & IRQ_TYPE_LEVEL_LOW) 731095f2a67SAndy Shevchenko value = (value | TRIG_SEL_BIT) & ~INT_INV_BIT; 732095f2a67SAndy Shevchenko 733095f2a67SAndy Shevchenko /* TRIG_SEL bit 1, INV bit 1 for level high */ 734095f2a67SAndy Shevchenko if (type & IRQ_TYPE_LEVEL_HIGH) 735095f2a67SAndy Shevchenko value |= TRIG_SEL_BIT | INT_INV_BIT; 736095f2a67SAndy Shevchenko 737095f2a67SAndy Shevchenko iowrite32(value, reg); 738095f2a67SAndy Shevchenko 739095f2a67SAndy Shevchenko if (type & IRQ_TYPE_EDGE_BOTH) 740095f2a67SAndy Shevchenko irq_set_handler_locked(d, handle_edge_irq); 741095f2a67SAndy Shevchenko else if (type & IRQ_TYPE_LEVEL_MASK) 742095f2a67SAndy Shevchenko irq_set_handler_locked(d, handle_level_irq); 743095f2a67SAndy Shevchenko 744095f2a67SAndy Shevchenko raw_spin_unlock_irqrestore(&lg->lock, flags); 745095f2a67SAndy Shevchenko 746095f2a67SAndy Shevchenko return 0; 747095f2a67SAndy Shevchenko } 748095f2a67SAndy Shevchenko 749eb83479eSAndy Shevchenko static struct irq_chip lp_irqchip = { 750eb83479eSAndy Shevchenko .name = "LP-GPIO", 7515931e6edSAndy Shevchenko .irq_ack = lp_irq_ack, 752eb83479eSAndy Shevchenko .irq_mask = lp_irq_mask, 753eb83479eSAndy Shevchenko .irq_unmask = lp_irq_unmask, 754eb83479eSAndy Shevchenko .irq_enable = lp_irq_enable, 755eb83479eSAndy Shevchenko .irq_disable = lp_irq_disable, 756095f2a67SAndy Shevchenko .irq_set_type = lp_irq_set_type, 757eb83479eSAndy Shevchenko .flags = IRQCHIP_SKIP_SET_WAKE, 758eb83479eSAndy Shevchenko }; 759eb83479eSAndy Shevchenko 760eb83479eSAndy Shevchenko static int lp_gpio_irq_init_hw(struct gpio_chip *chip) 761eb83479eSAndy Shevchenko { 76218213ad4SAndy Shevchenko struct intel_pinctrl *lg = gpiochip_get_data(chip); 763e1940adeSAndy Shevchenko void __iomem *reg; 764c35f463aSAndy Shevchenko unsigned int base; 765eb83479eSAndy Shevchenko 766eb83479eSAndy Shevchenko for (base = 0; base < lg->chip.ngpio; base += 32) { 767eb83479eSAndy Shevchenko /* disable gpio pin interrupts */ 768eb83479eSAndy Shevchenko reg = lp_gpio_reg(&lg->chip, base, LP_INT_ENABLE); 769e1940adeSAndy Shevchenko iowrite32(0, reg); 770eb83479eSAndy Shevchenko /* Clear interrupt status register */ 771eb83479eSAndy Shevchenko reg = lp_gpio_reg(&lg->chip, base, LP_INT_STAT); 772e1940adeSAndy Shevchenko iowrite32(0xffffffff, reg); 773eb83479eSAndy Shevchenko } 774eb83479eSAndy Shevchenko 775eb83479eSAndy Shevchenko return 0; 776eb83479eSAndy Shevchenko } 777eb83479eSAndy Shevchenko 7783683509cSAndy Shevchenko static int lp_gpio_add_pin_ranges(struct gpio_chip *chip) 7793683509cSAndy Shevchenko { 7803683509cSAndy Shevchenko struct intel_pinctrl *lg = gpiochip_get_data(chip); 7813683509cSAndy Shevchenko struct device *dev = lg->dev; 7823683509cSAndy Shevchenko int ret; 7833683509cSAndy Shevchenko 7843683509cSAndy Shevchenko ret = gpiochip_add_pin_range(chip, dev_name(dev), 0, 0, lg->soc->npins); 7853683509cSAndy Shevchenko if (ret) 7863683509cSAndy Shevchenko dev_err(dev, "failed to add GPIO pin range\n"); 7873683509cSAndy Shevchenko 7883683509cSAndy Shevchenko return ret; 7893683509cSAndy Shevchenko } 7903683509cSAndy Shevchenko 791eb83479eSAndy Shevchenko static int lp_gpio_probe(struct platform_device *pdev) 792eb83479eSAndy Shevchenko { 79318213ad4SAndy Shevchenko const struct intel_pinctrl_soc_data *soc; 79418213ad4SAndy Shevchenko struct intel_pinctrl *lg; 795eb83479eSAndy Shevchenko struct gpio_chip *gc; 796eb83479eSAndy Shevchenko struct resource *io_rc, *irq_rc; 797eb83479eSAndy Shevchenko struct device *dev = &pdev->dev; 798e1940adeSAndy Shevchenko void __iomem *regs; 79918213ad4SAndy Shevchenko unsigned int i; 8003b4c2d8eSAndy Shevchenko int ret; 801eb83479eSAndy Shevchenko 80218213ad4SAndy Shevchenko soc = (const struct intel_pinctrl_soc_data *)device_get_match_data(dev); 80318213ad4SAndy Shevchenko if (!soc) 80418213ad4SAndy Shevchenko return -ENODEV; 80518213ad4SAndy Shevchenko 806a718e68eSAndy Shevchenko lg = devm_kzalloc(dev, sizeof(*lg), GFP_KERNEL); 807eb83479eSAndy Shevchenko if (!lg) 808eb83479eSAndy Shevchenko return -ENOMEM; 809eb83479eSAndy Shevchenko 8101e78ea71SAndy Shevchenko lg->dev = dev; 81118213ad4SAndy Shevchenko lg->soc = soc; 81218213ad4SAndy Shevchenko 81318213ad4SAndy Shevchenko lg->ncommunities = lg->soc->ncommunities; 81418213ad4SAndy Shevchenko lg->communities = devm_kcalloc(dev, lg->ncommunities, 81518213ad4SAndy Shevchenko sizeof(*lg->communities), GFP_KERNEL); 81618213ad4SAndy Shevchenko if (!lg->communities) 81718213ad4SAndy Shevchenko return -ENOMEM; 81818213ad4SAndy Shevchenko 8197f32d370SAndy Shevchenko lg->pctldesc = lptlp_pinctrl_desc; 8207f32d370SAndy Shevchenko lg->pctldesc.name = dev_name(dev); 8217f32d370SAndy Shevchenko lg->pctldesc.pins = lg->soc->pins; 8227f32d370SAndy Shevchenko lg->pctldesc.npins = lg->soc->npins; 8237f32d370SAndy Shevchenko 824*64e14e90SAndy Shevchenko lg->pctldev = devm_pinctrl_register(dev, &lg->pctldesc, lg); 825*64e14e90SAndy Shevchenko if (IS_ERR(lg->pctldev)) { 826*64e14e90SAndy Shevchenko dev_err(dev, "failed to register pinctrl driver\n"); 827*64e14e90SAndy Shevchenko return PTR_ERR(lg->pctldev); 828*64e14e90SAndy Shevchenko } 829*64e14e90SAndy Shevchenko 830eb83479eSAndy Shevchenko platform_set_drvdata(pdev, lg); 831eb83479eSAndy Shevchenko 832eb83479eSAndy Shevchenko io_rc = platform_get_resource(pdev, IORESOURCE_IO, 0); 833eb83479eSAndy Shevchenko if (!io_rc) { 834eb83479eSAndy Shevchenko dev_err(dev, "missing IO resources\n"); 835eb83479eSAndy Shevchenko return -EINVAL; 836eb83479eSAndy Shevchenko } 837eb83479eSAndy Shevchenko 838e1940adeSAndy Shevchenko regs = devm_ioport_map(dev, io_rc->start, resource_size(io_rc)); 839e1940adeSAndy Shevchenko if (!regs) { 840e1940adeSAndy Shevchenko dev_err(dev, "failed mapping IO region %pR\n", &io_rc); 841eb83479eSAndy Shevchenko return -EBUSY; 842eb83479eSAndy Shevchenko } 843eb83479eSAndy Shevchenko 84418213ad4SAndy Shevchenko for (i = 0; i < lg->soc->ncommunities; i++) { 84518213ad4SAndy Shevchenko struct intel_community *comm = &lg->communities[i]; 84618213ad4SAndy Shevchenko 84718213ad4SAndy Shevchenko *comm = lg->soc->communities[i]; 84818213ad4SAndy Shevchenko 84918213ad4SAndy Shevchenko comm->regs = regs; 85018213ad4SAndy Shevchenko comm->pad_regs = regs + 0x100; 85118213ad4SAndy Shevchenko } 852e1940adeSAndy Shevchenko 853b2e05d63SAndy Shevchenko raw_spin_lock_init(&lg->lock); 854eb83479eSAndy Shevchenko 855eb83479eSAndy Shevchenko gc = &lg->chip; 856eb83479eSAndy Shevchenko gc->label = dev_name(dev); 857eb83479eSAndy Shevchenko gc->owner = THIS_MODULE; 858*64e14e90SAndy Shevchenko gc->request = gpiochip_generic_request; 859*64e14e90SAndy Shevchenko gc->free = gpiochip_generic_free; 860eb83479eSAndy Shevchenko gc->direction_input = lp_gpio_direction_input; 861eb83479eSAndy Shevchenko gc->direction_output = lp_gpio_direction_output; 862eb83479eSAndy Shevchenko gc->get = lp_gpio_get; 863eb83479eSAndy Shevchenko gc->set = lp_gpio_set; 86454d371cfSAndy Shevchenko gc->get_direction = lp_gpio_get_direction; 865eb83479eSAndy Shevchenko gc->base = -1; 866eb83479eSAndy Shevchenko gc->ngpio = LP_NUM_GPIO; 867eb83479eSAndy Shevchenko gc->can_sleep = false; 8683683509cSAndy Shevchenko gc->add_pin_ranges = lp_gpio_add_pin_ranges; 869eb83479eSAndy Shevchenko gc->parent = dev; 870eb83479eSAndy Shevchenko 871eb83479eSAndy Shevchenko /* set up interrupts */ 872e1940adeSAndy Shevchenko irq_rc = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 873eb83479eSAndy Shevchenko if (irq_rc && irq_rc->start) { 874eb83479eSAndy Shevchenko struct gpio_irq_chip *girq; 875eb83479eSAndy Shevchenko 876eb83479eSAndy Shevchenko girq = &gc->irq; 877eb83479eSAndy Shevchenko girq->chip = &lp_irqchip; 878eb83479eSAndy Shevchenko girq->init_hw = lp_gpio_irq_init_hw; 879eb83479eSAndy Shevchenko girq->parent_handler = lp_gpio_irq_handler; 880eb83479eSAndy Shevchenko girq->num_parents = 1; 8811e78ea71SAndy Shevchenko girq->parents = devm_kcalloc(dev, girq->num_parents, 882eb83479eSAndy Shevchenko sizeof(*girq->parents), 883eb83479eSAndy Shevchenko GFP_KERNEL); 884eb83479eSAndy Shevchenko if (!girq->parents) 885eb83479eSAndy Shevchenko return -ENOMEM; 886c35f463aSAndy Shevchenko girq->parents[0] = (unsigned int)irq_rc->start; 887eb83479eSAndy Shevchenko girq->default_type = IRQ_TYPE_NONE; 888eb83479eSAndy Shevchenko girq->handler = handle_bad_irq; 889eb83479eSAndy Shevchenko } 890eb83479eSAndy Shevchenko 891eb83479eSAndy Shevchenko ret = devm_gpiochip_add_data(dev, gc, lg); 892eb83479eSAndy Shevchenko if (ret) { 893eb83479eSAndy Shevchenko dev_err(dev, "failed adding lp-gpio chip\n"); 894eb83479eSAndy Shevchenko return ret; 895eb83479eSAndy Shevchenko } 896eb83479eSAndy Shevchenko 897eb83479eSAndy Shevchenko pm_runtime_enable(dev); 898eb83479eSAndy Shevchenko 899eb83479eSAndy Shevchenko return 0; 900eb83479eSAndy Shevchenko } 901eb83479eSAndy Shevchenko 902d0f2df40SAndy Shevchenko static int lp_gpio_remove(struct platform_device *pdev) 903d0f2df40SAndy Shevchenko { 904d0f2df40SAndy Shevchenko pm_runtime_disable(&pdev->dev); 905d0f2df40SAndy Shevchenko return 0; 906d0f2df40SAndy Shevchenko } 907d0f2df40SAndy Shevchenko 908eb83479eSAndy Shevchenko static int lp_gpio_runtime_suspend(struct device *dev) 909eb83479eSAndy Shevchenko { 910eb83479eSAndy Shevchenko return 0; 911eb83479eSAndy Shevchenko } 912eb83479eSAndy Shevchenko 913eb83479eSAndy Shevchenko static int lp_gpio_runtime_resume(struct device *dev) 914eb83479eSAndy Shevchenko { 915eb83479eSAndy Shevchenko return 0; 916eb83479eSAndy Shevchenko } 917eb83479eSAndy Shevchenko 918eb83479eSAndy Shevchenko static int lp_gpio_resume(struct device *dev) 919eb83479eSAndy Shevchenko { 92018213ad4SAndy Shevchenko struct intel_pinctrl *lg = dev_get_drvdata(dev); 921e1940adeSAndy Shevchenko void __iomem *reg; 922eb83479eSAndy Shevchenko int i; 923eb83479eSAndy Shevchenko 924eb83479eSAndy Shevchenko /* on some hardware suspend clears input sensing, re-enable it here */ 925eb83479eSAndy Shevchenko for (i = 0; i < lg->chip.ngpio; i++) { 926eb83479eSAndy Shevchenko if (gpiochip_is_requested(&lg->chip, i) != NULL) { 927eb83479eSAndy Shevchenko reg = lp_gpio_reg(&lg->chip, i, LP_CONFIG2); 928e1940adeSAndy Shevchenko iowrite32(ioread32(reg) & ~GPINDIS_BIT, reg); 929eb83479eSAndy Shevchenko } 930eb83479eSAndy Shevchenko } 931eb83479eSAndy Shevchenko return 0; 932eb83479eSAndy Shevchenko } 933eb83479eSAndy Shevchenko 934eb83479eSAndy Shevchenko static const struct dev_pm_ops lp_gpio_pm_ops = { 935eb83479eSAndy Shevchenko .runtime_suspend = lp_gpio_runtime_suspend, 936eb83479eSAndy Shevchenko .runtime_resume = lp_gpio_runtime_resume, 937eb83479eSAndy Shevchenko .resume = lp_gpio_resume, 938eb83479eSAndy Shevchenko }; 939eb83479eSAndy Shevchenko 940eb83479eSAndy Shevchenko static const struct acpi_device_id lynxpoint_gpio_acpi_match[] = { 941cecddda7SAndy Shevchenko { "INT33C7", (kernel_ulong_t)&lptlp_soc_data }, 942cecddda7SAndy Shevchenko { "INT3437", (kernel_ulong_t)&lptlp_soc_data }, 943eb83479eSAndy Shevchenko { } 944eb83479eSAndy Shevchenko }; 945eb83479eSAndy Shevchenko MODULE_DEVICE_TABLE(acpi, lynxpoint_gpio_acpi_match); 946eb83479eSAndy Shevchenko 947eb83479eSAndy Shevchenko static struct platform_driver lp_gpio_driver = { 948eb83479eSAndy Shevchenko .probe = lp_gpio_probe, 949eb83479eSAndy Shevchenko .remove = lp_gpio_remove, 950eb83479eSAndy Shevchenko .driver = { 951eb83479eSAndy Shevchenko .name = "lp_gpio", 952eb83479eSAndy Shevchenko .pm = &lp_gpio_pm_ops, 953eb83479eSAndy Shevchenko .acpi_match_table = ACPI_PTR(lynxpoint_gpio_acpi_match), 954eb83479eSAndy Shevchenko }, 955eb83479eSAndy Shevchenko }; 956eb83479eSAndy Shevchenko 957eb83479eSAndy Shevchenko static int __init lp_gpio_init(void) 958eb83479eSAndy Shevchenko { 959eb83479eSAndy Shevchenko return platform_driver_register(&lp_gpio_driver); 960eb83479eSAndy Shevchenko } 961eb83479eSAndy Shevchenko 962eb83479eSAndy Shevchenko static void __exit lp_gpio_exit(void) 963eb83479eSAndy Shevchenko { 964eb83479eSAndy Shevchenko platform_driver_unregister(&lp_gpio_driver); 965eb83479eSAndy Shevchenko } 966eb83479eSAndy Shevchenko 967eb83479eSAndy Shevchenko subsys_initcall(lp_gpio_init); 968eb83479eSAndy Shevchenko module_exit(lp_gpio_exit); 969eb83479eSAndy Shevchenko 970eb83479eSAndy Shevchenko MODULE_AUTHOR("Mathias Nyman (Intel)"); 971eb83479eSAndy Shevchenko MODULE_DESCRIPTION("GPIO interface for Intel Lynxpoint"); 972eb83479eSAndy Shevchenko MODULE_LICENSE("GPL v2"); 973eb83479eSAndy Shevchenko MODULE_ALIAS("platform:lp_gpio"); 974