diff options
Diffstat (limited to 'drivers/pinctrl/intel')
-rw-r--r-- | drivers/pinctrl/intel/Kconfig | 8 | ||||
-rw-r--r-- | drivers/pinctrl/intel/Makefile | 1 | ||||
-rw-r--r-- | drivers/pinctrl/intel/pinctrl-baytrail.c | 79 | ||||
-rw-r--r-- | drivers/pinctrl/intel/pinctrl-broxton.c | 7 | ||||
-rw-r--r-- | drivers/pinctrl/intel/pinctrl-cherryview.c | 4 | ||||
-rw-r--r-- | drivers/pinctrl/intel/pinctrl-geminilake.c | 512 | ||||
-rw-r--r-- | drivers/pinctrl/intel/pinctrl-intel.c | 201 | ||||
-rw-r--r-- | drivers/pinctrl/intel/pinctrl-intel.h | 8 | ||||
-rw-r--r-- | drivers/pinctrl/intel/pinctrl-merrifield.c | 3 | ||||
-rw-r--r-- | drivers/pinctrl/intel/pinctrl-sunrisepoint.c | 1 |
10 files changed, 752 insertions, 72 deletions
diff --git a/drivers/pinctrl/intel/Kconfig b/drivers/pinctrl/intel/Kconfig index 00fb055a4897..396830a41127 100644 --- a/drivers/pinctrl/intel/Kconfig +++ b/drivers/pinctrl/intel/Kconfig @@ -56,6 +56,14 @@ config PINCTRL_BROXTON Broxton pinctrl driver provides an interface that allows configuring of SoC pins and using them as GPIOs. +config PINCTRL_GEMINILAKE + tristate "Intel Gemini Lake SoC pinctrl and GPIO driver" + depends on ACPI + select PINCTRL_INTEL + help + This pinctrl driver provides an interface that allows configuring + of Intel Gemini Lake SoC pins and using them as GPIOs. + config PINCTRL_SUNRISEPOINT tristate "Intel Sunrisepoint pinctrl and GPIO driver" depends on ACPI diff --git a/drivers/pinctrl/intel/Makefile b/drivers/pinctrl/intel/Makefile index 30803078f09e..12f3af5b2ca5 100644 --- a/drivers/pinctrl/intel/Makefile +++ b/drivers/pinctrl/intel/Makefile @@ -5,4 +5,5 @@ obj-$(CONFIG_PINCTRL_CHERRYVIEW) += pinctrl-cherryview.o obj-$(CONFIG_PINCTRL_MERRIFIELD) += pinctrl-merrifield.o obj-$(CONFIG_PINCTRL_INTEL) += pinctrl-intel.o obj-$(CONFIG_PINCTRL_BROXTON) += pinctrl-broxton.o +obj-$(CONFIG_PINCTRL_GEMINILAKE) += pinctrl-geminilake.o obj-$(CONFIG_PINCTRL_SUNRISEPOINT) += pinctrl-sunrisepoint.o diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c index 37300634b7d2..fa3c5758ac67 100644 --- a/drivers/pinctrl/intel/pinctrl-baytrail.c +++ b/drivers/pinctrl/intel/pinctrl-baytrail.c @@ -731,16 +731,23 @@ static void __iomem *byt_gpio_reg(struct byt_gpio *vg, unsigned int offset, int reg) { struct byt_community *comm = byt_get_community(vg, offset); - u32 reg_offset = 0; + u32 reg_offset; if (!comm) return NULL; offset -= comm->pin_base; - if (reg == BYT_INT_STAT_REG) + switch (reg) { + case BYT_INT_STAT_REG: reg_offset = (offset / 32) * 4; - else + break; + case BYT_DEBOUNCE_REG: + reg_offset = 0; + break; + default: reg_offset = comm->pad_map[offset] * 16; + break; + } return comm->reg_base + reg_offset + reg; } @@ -1092,6 +1099,7 @@ static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset, enum pin_config_param param = pinconf_to_config_param(*config); void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); + void __iomem *db_reg = byt_gpio_reg(vg, offset, BYT_DEBOUNCE_REG); unsigned long flags; u32 conf, pull, val, debounce; u16 arg = 0; @@ -1128,7 +1136,7 @@ static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset, return -EINVAL; raw_spin_lock_irqsave(&vg->lock, flags); - debounce = readl(byt_gpio_reg(vg, offset, BYT_DEBOUNCE_REG)); + debounce = readl(db_reg); raw_spin_unlock_irqrestore(&vg->lock, flags); switch (debounce & BYT_DEBOUNCE_PULSE_MASK) { @@ -1176,6 +1184,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev, unsigned int param, arg; void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); + void __iomem *db_reg = byt_gpio_reg(vg, offset, BYT_DEBOUNCE_REG); unsigned long flags; u32 conf, val, debounce; int i, ret = 0; @@ -1238,36 +1247,44 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev, break; case PIN_CONFIG_INPUT_DEBOUNCE: - debounce = readl(byt_gpio_reg(vg, offset, - BYT_DEBOUNCE_REG)); - conf &= ~BYT_DEBOUNCE_PULSE_MASK; + debounce = readl(db_reg); + debounce &= ~BYT_DEBOUNCE_PULSE_MASK; + + if (arg) + conf |= BYT_DEBOUNCE_EN; + else + conf &= ~BYT_DEBOUNCE_EN; switch (arg) { case 375: - conf |= BYT_DEBOUNCE_PULSE_375US; + debounce |= BYT_DEBOUNCE_PULSE_375US; break; case 750: - conf |= BYT_DEBOUNCE_PULSE_750US; + debounce |= BYT_DEBOUNCE_PULSE_750US; break; case 1500: - conf |= BYT_DEBOUNCE_PULSE_1500US; + debounce |= BYT_DEBOUNCE_PULSE_1500US; break; case 3000: - conf |= BYT_DEBOUNCE_PULSE_3MS; + debounce |= BYT_DEBOUNCE_PULSE_3MS; break; case 6000: - conf |= BYT_DEBOUNCE_PULSE_6MS; + debounce |= BYT_DEBOUNCE_PULSE_6MS; break; case 12000: - conf |= BYT_DEBOUNCE_PULSE_12MS; + debounce |= BYT_DEBOUNCE_PULSE_12MS; break; case 24000: - conf |= BYT_DEBOUNCE_PULSE_24MS; + debounce |= BYT_DEBOUNCE_PULSE_24MS; break; default: - ret = -EINVAL; + if (arg) + ret = -EINVAL; + break; } + if (!ret) + writel(debounce, db_reg); break; default: ret = -ENOTSUPP; @@ -1449,7 +1466,7 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) val & BYT_INPUT_EN ? " " : "in", val & BYT_OUTPUT_EN ? " " : "out", val & BYT_LEVEL ? "hi" : "lo", - comm->pad_map[i], comm->pad_map[i] * 32, + comm->pad_map[i], comm->pad_map[i] * 16, conf0 & 0x7, conf0 & BYT_TRIG_NEG ? " fall" : " ", conf0 & BYT_TRIG_POS ? " rise" : " ", @@ -1606,7 +1623,9 @@ static void byt_gpio_irq_handler(struct irq_desc *desc) continue; } + raw_spin_lock(&vg->lock); pending = readl(reg); + raw_spin_unlock(&vg->lock); for_each_set_bit(pin, &pending, 32) { virq = irq_find_mapping(vg->chip.irqdomain, base + pin); generic_handle_irq(virq); @@ -1617,6 +1636,8 @@ static void byt_gpio_irq_handler(struct irq_desc *desc) static void byt_gpio_irq_init_hw(struct byt_gpio *vg) { + struct gpio_chip *gc = &vg->chip; + struct device *dev = &vg->pdev->dev; void __iomem *reg; u32 base, value; int i; @@ -1638,10 +1659,12 @@ static void byt_gpio_irq_init_hw(struct byt_gpio *vg) } value = readl(reg); - if ((value & BYT_PIN_MUX) == byt_get_gpio_mux(vg, i) && - !(value & BYT_DIRECT_IRQ_EN)) { + if (value & BYT_DIRECT_IRQ_EN) { + clear_bit(i, gc->irq_valid_mask); + dev_dbg(dev, "excluding GPIO %d from IRQ domain\n", i); + } else if ((value & BYT_PIN_MUX) == byt_get_gpio_mux(vg, i)) { byt_gpio_clear_triggering(vg, i); - dev_dbg(&vg->pdev->dev, "disabling GPIO %d\n", i); + dev_dbg(dev, "disabling GPIO %d\n", i); } } @@ -1680,12 +1703,13 @@ static int byt_gpio_probe(struct byt_gpio *vg) gc->can_sleep = false; gc->parent = &vg->pdev->dev; gc->ngpio = vg->soc_data->npins; + gc->irq_need_valid_mask = true; #ifdef CONFIG_PM_SLEEP vg->saved_context = devm_kcalloc(&vg->pdev->dev, gc->ngpio, sizeof(*vg->saved_context), GFP_KERNEL); #endif - ret = gpiochip_add_data(gc, vg); + ret = devm_gpiochip_add_data(&vg->pdev->dev, gc, vg); if (ret) { dev_err(&vg->pdev->dev, "failed adding byt-gpio chip\n"); return ret; @@ -1695,7 +1719,7 @@ static int byt_gpio_probe(struct byt_gpio *vg) 0, 0, vg->soc_data->npins); if (ret) { dev_err(&vg->pdev->dev, "failed to add GPIO pin range\n"); - goto fail; + return ret; } /* set up interrupts */ @@ -1706,7 +1730,7 @@ static int byt_gpio_probe(struct byt_gpio *vg) handle_bad_irq, IRQ_TYPE_NONE); if (ret) { dev_err(&vg->pdev->dev, "failed to add irqchip\n"); - goto fail; + return ret; } gpiochip_set_chained_irqchip(gc, &byt_irqchip, @@ -1715,11 +1739,6 @@ static int byt_gpio_probe(struct byt_gpio *vg) } return ret; - -fail: - gpiochip_remove(&vg->chip); - - return ret; } static int byt_set_soc_data(struct byt_gpio *vg, @@ -1802,7 +1821,7 @@ static int byt_pinctrl_probe(struct platform_device *pdev) vg->pctl_desc.pins = vg->soc_data->pins; vg->pctl_desc.npins = vg->soc_data->npins; - vg->pctl_dev = pinctrl_register(&vg->pctl_desc, &pdev->dev, vg); + vg->pctl_dev = devm_pinctrl_register(&pdev->dev, &vg->pctl_desc, vg); if (IS_ERR(vg->pctl_dev)) { dev_err(&pdev->dev, "failed to register pinctrl driver\n"); return PTR_ERR(vg->pctl_dev); @@ -1811,10 +1830,8 @@ static int byt_pinctrl_probe(struct platform_device *pdev) raw_spin_lock_init(&vg->lock); ret = byt_gpio_probe(vg); - if (ret) { - pinctrl_unregister(vg->pctl_dev); + if (ret) return ret; - } platform_set_drvdata(pdev, vg); pm_runtime_enable(&pdev->dev); diff --git a/drivers/pinctrl/intel/pinctrl-broxton.c b/drivers/pinctrl/intel/pinctrl-broxton.c index 59cb7a6fc5be..e6e6fd112585 100644 --- a/drivers/pinctrl/intel/pinctrl-broxton.c +++ b/drivers/pinctrl/intel/pinctrl-broxton.c @@ -19,7 +19,7 @@ #define BXT_PAD_OWN 0x020 #define BXT_HOSTSW_OWN 0x080 -#define BXT_PADCFGLOCK 0x090 +#define BXT_PADCFGLOCK 0x060 #define BXT_GPI_IE 0x110 #define BXT_COMMUNITY(s, e) \ @@ -1004,8 +1004,8 @@ static const struct acpi_device_id bxt_pinctrl_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, bxt_pinctrl_acpi_match); static const struct platform_device_id bxt_pinctrl_platform_ids[] = { - { "apl-pinctrl", (kernel_ulong_t)&apl_pinctrl_soc_data }, - { "broxton-pinctrl", (kernel_ulong_t)&bxt_pinctrl_soc_data }, + { "apollolake-pinctrl", (kernel_ulong_t)apl_pinctrl_soc_data }, + { "broxton-pinctrl", (kernel_ulong_t)bxt_pinctrl_soc_data }, { }, }; @@ -1058,7 +1058,6 @@ static const struct dev_pm_ops bxt_pinctrl_pm_ops = { static struct platform_driver bxt_pinctrl_driver = { .probe = bxt_pinctrl_probe, - .remove = intel_pinctrl_remove, .driver = { .name = "broxton-pinctrl", .acpi_match_table = bxt_pinctrl_acpi_match, diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index 5e66860a5e67..f80134e3e0b6 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -1059,7 +1059,7 @@ static int chv_config_get(struct pinctrl_dev *pctldev, unsigned pin, } static int chv_config_set_pull(struct chv_pinctrl *pctrl, unsigned pin, - enum pin_config_param param, u16 arg) + enum pin_config_param param, u32 arg) { void __iomem *reg = chv_padreg(pctrl, pin, CHV_PADCTRL0); unsigned long flags; @@ -1151,7 +1151,7 @@ static int chv_config_set(struct pinctrl_dev *pctldev, unsigned pin, struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); enum pin_config_param param; int i, ret; - u16 arg; + u32 arg; if (chv_pad_locked(pctrl, pin)) return -EBUSY; diff --git a/drivers/pinctrl/intel/pinctrl-geminilake.c b/drivers/pinctrl/intel/pinctrl-geminilake.c new file mode 100644 index 000000000000..a6b94c930007 --- /dev/null +++ b/drivers/pinctrl/intel/pinctrl-geminilake.c @@ -0,0 +1,512 @@ +/* + * Intel Gemini Lake SoC pinctrl/GPIO driver + * + * Copyright (C) 2017 Intel Corporation + * Author: Mika Westerberg <mika.westerberg@linux.intel.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/acpi.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/pm.h> +#include <linux/pinctrl/pinctrl.h> + +#include "pinctrl-intel.h" + +#define GLK_PAD_OWN 0x020 +#define GLK_HOSTSW_OWN 0x0b0 +#define GLK_PADCFGLOCK 0x080 +#define GLK_GPI_IE 0x110 + +#define GLK_COMMUNITY(s, e) \ + { \ + .padown_offset = GLK_PAD_OWN, \ + .padcfglock_offset = GLK_PADCFGLOCK, \ + .hostown_offset = GLK_HOSTSW_OWN, \ + .ie_offset = GLK_GPI_IE, \ + .gpp_size = 32, \ + .pin_base = (s), \ + .npins = ((e) - (s) + 1), \ + } + +/* GLK */ +static const struct pinctrl_pin_desc glk_northwest_pins[] = { + PINCTRL_PIN(0, "TCK"), + PINCTRL_PIN(1, "TRST_B"), + PINCTRL_PIN(2, "TMS"), + PINCTRL_PIN(3, "TDI"), + PINCTRL_PIN(4, "TDO"), + PINCTRL_PIN(5, "JTAGX"), + PINCTRL_PIN(6, "CX_PREQ_B"), + PINCTRL_PIN(7, "CX_PRDY_B"), + PINCTRL_PIN(8, "GPIO_8"), + PINCTRL_PIN(9, "GPIO_9"), + PINCTRL_PIN(10, "GPIO_10"), + PINCTRL_PIN(11, "GPIO_11"), + PINCTRL_PIN(12, "GPIO_12"), + PINCTRL_PIN(13, "GPIO_13"), + PINCTRL_PIN(14, "GPIO_14"), + PINCTRL_PIN(15, "GPIO_15"), + PINCTRL_PIN(16, "GPIO_16"), + PINCTRL_PIN(17, "GPIO_17"), + PINCTRL_PIN(18, "GPIO_18"), + PINCTRL_PIN(19, "GPIO_19"), + PINCTRL_PIN(20, "GPIO_20"), + PINCTRL_PIN(21, "GPIO_21"), + PINCTRL_PIN(22, "GPIO_22"), + PINCTRL_PIN(23, "GPIO_23"), + PINCTRL_PIN(24, "GPIO_24"), + PINCTRL_PIN(25, "GPIO_25"), + PINCTRL_PIN(26, "GPIO_26"), + PINCTRL_PIN(27, "GPIO_27"), + PINCTRL_PIN(28, "GPIO_28"), + PINCTRL_PIN(29, "GPIO_29"), + PINCTRL_PIN(30, "GPIO_30"), + PINCTRL_PIN(31, "GPIO_31"), + PINCTRL_PIN(32, "GPIO_32"), + PINCTRL_PIN(33, "GPIO_33"), + PINCTRL_PIN(34, "GPIO_34"), + PINCTRL_PIN(35, "GPIO_35"), + PINCTRL_PIN(36, "GPIO_36"), + PINCTRL_PIN(37, "GPIO_37"), + PINCTRL_PIN(38, "GPIO_38"), + PINCTRL_PIN(39, "GPIO_39"), + PINCTRL_PIN(40, "GPIO_40"), + PINCTRL_PIN(41, "GPIO_41"), + PINCTRL_PIN(42, "GP_INTD_DSI_TE1"), + PINCTRL_PIN(43, "GP_INTD_DSI_TE2"), + PINCTRL_PIN(44, "USB_OC0_B"), + PINCTRL_PIN(45, "USB_OC1_B"), + PINCTRL_PIN(46, "DSI_I2C_SDA"), + PINCTRL_PIN(47, "DSI_I2C_SCL"), + PINCTRL_PIN(48, "PMC_I2C_SDA"), + PINCTRL_PIN(49, "PMC_I2C_SCL"), + PINCTRL_PIN(50, "LPSS_I2C0_SDA"), + PINCTRL_PIN(51, "LPSS_I2C0_SCL"), + PINCTRL_PIN(52, "LPSS_I2C1_SDA"), + PINCTRL_PIN(53, "LPSS_I2C1_SCL"), + PINCTRL_PIN(54, "LPSS_I2C2_SDA"), + PINCTRL_PIN(55, "LPSS_I2C2_SCL"), + PINCTRL_PIN(56, "LPSS_I2C3_SDA"), + PINCTRL_PIN(57, "LPSS_I2C3_SCL"), + PINCTRL_PIN(58, "LPSS_I2C4_SDA"), + PINCTRL_PIN(59, "LPSS_I2C4_SCL"), + PINCTRL_PIN(60, "LPSS_UART0_RXD"), + PINCTRL_PIN(61, "LPSS_UART0_TXD"), + PINCTRL_PIN(62, "LPSS_UART0_RTS_B"), + PINCTRL_PIN(63, "LPSS_UART0_CTS_B"), + PINCTRL_PIN(64, "LPSS_UART2_RXD"), + PINCTRL_PIN(65, "LPSS_UART2_TXD"), + PINCTRL_PIN(66, "LPSS_UART2_RTS_B"), + PINCTRL_PIN(67, "LPSS_UART2_CTS_B"), + PINCTRL_PIN(68, "PMC_SPI_FS0"), + PINCTRL_PIN(69, "PMC_SPI_FS1"), + PINCTRL_PIN(70, "PMC_SPI_FS2"), + PINCTRL_PIN(71, "PMC_SPI_RXD"), + PINCTRL_PIN(72, "PMC_SPI_TXD"), + PINCTRL_PIN(73, "PMC_SPI_CLK"), + PINCTRL_PIN(74, "THERMTRIP_B"), + PINCTRL_PIN(75, "PROCHOT_B"), + PINCTRL_PIN(76, "EMMC_RST_B"), + PINCTRL_PIN(77, "GPIO_212"), + PINCTRL_PIN(78, "GPIO_213"), + PINCTRL_PIN(79, "GPIO_214"), +}; + +static const unsigned int glk_northwest_uart1_pins[] = { 26, 27, 28, 29 }; +static const unsigned int glk_northwest_pwm0_pins[] = { 42 }; +static const unsigned int glk_northwest_pwm1_pins[] = { 43 }; +static const unsigned int glk_northwest_pwm2_pins[] = { 44 }; +static const unsigned int glk_northwest_pwm3_pins[] = { 45 }; +static const unsigned int glk_northwest_i2c0_pins[] = { 50, 51 }; +static const unsigned int glk_northwest_i2c1_pins[] = { 52, 53 }; +static const unsigned int glk_northwest_i2c2_pins[] = { 54, 55 }; +static const unsigned int glk_northwest_i2c3_pins[] = { 56, 57 }; +static const unsigned int glk_northwest_i2c4_pins[] = { 58, 59 }; +static const unsigned int glk_northwest_uart0_pins[] = { 60, 61, 62, 63 }; +static const unsigned int glk_northwest_uart2_pins[] = { 64, 65, 66, 67 }; + +static const struct intel_pingroup glk_northwest_groups[] = { + PIN_GROUP("uart1_grp", glk_northwest_uart1_pins, 2), + PIN_GROUP("pwm0_grp", glk_northwest_pwm0_pins, 2), + PIN_GROUP("pwm1_grp", glk_northwest_pwm1_pins, 2), + PIN_GROUP("pwm2_grp", glk_northwest_pwm2_pins, 2), + PIN_GROUP("pwm3_grp", glk_northwest_pwm3_pins, 2), + PIN_GROUP("i2c0_grp", glk_northwest_i2c0_pins, 1), + PIN_GROUP("i2c1_grp", glk_northwest_i2c1_pins, 1), + PIN_GROUP("i2c2_grp", glk_northwest_i2c2_pins, 1), + PIN_GROUP("i2c3_grp", glk_northwest_i2c3_pins, 1), + PIN_GROUP("i2c4_grp", glk_northwest_i2c4_pins, 1), + PIN_GROUP("uart0_grp", glk_northwest_uart0_pins, 1), + PIN_GROUP("uart2_grp", glk_northwest_uart2_pins, 1), +}; + +static const char * const glk_northwest_uart1_groups[] = { "uart1_grp" }; +static const char * const glk_northwest_pwm0_groups[] = { "pwm0_grp" }; +static const char * const glk_northwest_pwm1_groups[] = { "pwm1_grp" }; +static const char * const glk_northwest_pwm2_groups[] = { "pwm2_grp" }; +static const char * const glk_northwest_pwm3_groups[] = { "pwm3_grp" }; +static const char * const glk_northwest_i2c0_groups[] = { "i2c0_grp" }; +static const char * const glk_northwest_i2c1_groups[] = { "i2c1_grp" }; +static const char * const glk_northwest_i2c2_groups[] = { "i2c2_grp" }; +static const char * const glk_northwest_i2c3_groups[] = { "i2c3_grp" }; +static const char * const glk_northwest_i2c4_groups[] = { "i2c4_grp" }; +static const char * const glk_northwest_uart0_groups[] = { "uart0_grp" }; +static const char * const glk_northwest_uart2_groups[] = { "uart2_grp" }; + +static const struct intel_function glk_northwest_functions[] = { + FUNCTION("uart1", glk_northwest_uart1_groups), + FUNCTION("pmw0", glk_northwest_pwm0_groups), + FUNCTION("pmw1", glk_northwest_pwm1_groups), + FUNCTION("pmw2", glk_northwest_pwm2_groups), + FUNCTION("pmw3", glk_northwest_pwm3_groups), + FUNCTION("i2c0", glk_northwest_i2c0_groups), + FUNCTION("i2c1", glk_northwest_i2c1_groups), + FUNCTION("i2c2", glk_northwest_i2c2_groups), + FUNCTION("i2c3", glk_northwest_i2c3_groups), + FUNCTION("i2c4", glk_northwest_i2c4_groups), + FUNCTION("uart0", glk_northwest_uart0_groups), + FUNCTION("uart2", glk_northwest_uart2_groups), +}; + +static const struct intel_community glk_northwest_communities[] = { + GLK_COMMUNITY(0, 79), +}; + +static const struct intel_pinctrl_soc_data glk_northwest_soc_data = { + .uid = "1", + .pins = glk_northwest_pins, + .npins = ARRAY_SIZE(glk_northwest_pins), + .groups = glk_northwest_groups, + .ngroups = ARRAY_SIZE(glk_northwest_groups), + .functions = glk_northwest_functions, + .nfunctions = ARRAY_SIZE(glk_northwest_functions), + .communities = glk_northwest_communities, + .ncommunities = ARRAY_SIZE(glk_northwest_communities), +}; + +static const struct pinctrl_pin_desc glk_north_pins[] = { + PINCTRL_PIN(0, "SVID0_ALERT_B"), + PINCTRL_PIN(1, "SVID0_DATA"), + PINCTRL_PIN(2, "SVID0_CLK"), + PINCTRL_PIN(3, "LPSS_SPI_0_CLK"), + PINCTRL_PIN(4, "LPSS_SPI_0_FS0"), + PINCTRL_PIN(5, "LPSS_SPI_0_FS1"), + PINCTRL_PIN(6, "LPSS_SPI_0_RXD"), + PINCTRL_PIN(7, "LPSS_SPI_0_TXD"), + PINCTRL_PIN(8, "LPSS_SPI_1_CLK"), + PINCTRL_PIN(9, "LPSS_SPI_1_FS0"), + PINCTRL_PIN(10, "LPSS_SPI_1_FS1"), + PINCTRL_PIN(11, "LPSS_SPI_1_FS2"), + PINCTRL_PIN(12, "LPSS_SPI_1_RXD"), + PINCTRL_PIN(13, "LPSS_SPI_1_TXD"), + PINCTRL_PIN(14, "FST_SPI_CS0_B"), + PINCTRL_PIN(15, "FST_SPI_CS1_B"), + PINCTRL_PIN(16, "FST_SPI_MOSI_IO0"), + PINCTRL_PIN(17, "FST_SPI_MISO_IO1"), + PINCTRL_PIN(18, "FST_SPI_IO2"), + PINCTRL_PIN(19, "FST_SPI_IO3"), + PINCTRL_PIN(20, "FST_SPI_CLK"), + PINCTRL_PIN(21, "FST_SPI_CLK_FB"), + PINCTRL_PIN(22, "PMU_PLTRST_B"), + PINCTRL_PIN(23, "PMU_PWRBTN_B"), + PINCTRL_PIN(24, "PMU_SLP_S0_B"), + PINCTRL_PIN(25, "PMU_SLP_S3_B"), + PINCTRL_PIN(26, "PMU_SLP_S4_B"), + PINCTRL_PIN(27, "SUSPWRDNACK"), + PINCTRL_PIN(28, "EMMC_PWR_EN_B"), + PINCTRL_PIN(29, "PMU_AC_PRESENT"), + PINCTRL_PIN(30, "PMU_BATLOW_B"), + PINCTRL_PIN(31, "PMU_RESETBUTTON_B"), + PINCTRL_PIN(32, "PMU_SUSCLK"), + PINCTRL_PIN(33, "SUS_STAT_B"), + PINCTRL_PIN(34, "LPSS_I2C5_SDA"), + PINCTRL_PIN(35, "LPSS_I2C5_SCL"), + PINCTRL_PIN(36, "LPSS_I2C6_SDA"), + PINCTRL_PIN(37, "LPSS_I2C6_SCL"), + PINCTRL_PIN(38, "LPSS_I2C7_SDA"), + PINCTRL_PIN(39, "LPSS_I2C7_SCL"), + PINCTRL_PIN(40, "PCIE_WAKE0_B"), + PINCTRL_PIN(41, "PCIE_WAKE1_B"), + PINCTRL_PIN(42, "PCIE_WAKE2_B"), + PINCTRL_PIN(43, "PCIE_WAKE3_B"), + PINCTRL_PIN(44, "PCIE_CLKREQ0_B"), + PINCTRL_PIN(45, "PCIE_CLKREQ1_B"), + PINCTRL_PIN(46, "PCIE_CLKREQ2_B"), + PINCTRL_PIN(47, "PCIE_CLKREQ3_B"), + PINCTRL_PIN(48, "HV_DDI0_DDC_SDA"), + PINCTRL_PIN(49, "HV_DDI0_DDC_SCL"), + PINCTRL_PIN(50, "HV_DDI1_DDC_SDA"), + PINCTRL_PIN(51, "HV_DDI1_DDC_SCL"), + PINCTRL_PIN(52, "PANEL0_VDDEN"), + PINCTRL_PIN(53, "PANEL0_BKLTEN"), + PINCTRL_PIN(54, "PANEL0_BKLTCTL"), + PINCTRL_PIN(55, "HV_DDI0_HPD"), + PINCTRL_PIN(56, "HV_DDI1_HPD"), + PINCTRL_PIN(57, "HV_EDP_HPD"), + PINCTRL_PIN(58, "GPIO_134"), + PINCTRL_PIN(59, "GPIO_135"), + PINCTRL_PIN(60, "GPIO_136"), + PINCTRL_PIN(61, "GPIO_137"), + PINCTRL_PIN(62, "GPIO_138"), + PINCTRL_PIN(63, "GPIO_139"), + PINCTRL_PIN(64, "GPIO_140"), + PINCTRL_PIN(65, "GPIO_141"), + PINCTRL_PIN(66, "GPIO_142"), + PINCTRL_PIN(67, "GPIO_143"), + PINCTRL_PIN(68, "GPIO_144"), + PINCTRL_PIN(69, "GPIO_145"), + PINCTRL_PIN(70, "GPIO_146"), + PINCTRL_PIN(71, "LPC_ILB_SERIRQ"), + PINCTRL_PIN(72, "LPC_CLKOUT0"), + PINCTRL_PIN(73, "LPC_CLKOUT1"), + PINCTRL_PIN(74, "LPC_AD0"), + PINCTRL_PIN(75, "LPC_AD1"), + PINCTRL_PIN(76, "LPC_AD2"), + PINCTRL_PIN(77, "LPC_AD3"), + PINCTRL_PIN(78, "LPC_CLKRUNB"), + PINCTRL_PIN(79, "LPC_FRAMEB"), +}; + +static const unsigned int glk_north_spi0_pins[] = { 3, 4, 5, 6, 7 }; +static const unsigned int glk_north_spi1_pins[] = { 8, 9, 10, 11, 12, 13 }; +static const unsigned int glk_north_i2c5_pins[] = { 34, 35 }; +static const unsigned int glk_north_i2c6_pins[] = { 36, 37 }; +static const unsigned int glk_north_i2c7_pins[] = { 38, 39 }; +static const unsigned int glk_north_uart0_pins[] = { 62, 63, 64, 65 }; +static const unsigned int glk_north_spi0b_pins[] = { 66, 67, 68, 69, 70 }; + +static const struct intel_pingroup glk_north_groups[] = { + PIN_GROUP("spi0_grp", glk_north_spi0_pins, 1), + PIN_GROUP("spi1_grp", glk_north_spi1_pins, 1), + PIN_GROUP("i2c5_grp", glk_north_i2c5_pins, 1), + PIN_GROUP("i2c6_grp", glk_north_i2c6_pins, 1), + PIN_GROUP("i2c7_grp", glk_north_i2c7_pins, 1), + PIN_GROUP("uart0_grp", glk_north_uart0_pins, 2), + PIN_GROUP("spi0b_grp", glk_north_spi0b_pins, 2), +}; + +static const char * const glk_north_spi0_groups[] = { "spi0_grp", "spi0b_grp" }; +static const char * const glk_north_spi1_groups[] = { "spi1_grp" }; +static const char * const glk_north_i2c5_groups[] = { "i2c5_grp" }; +static const char * const glk_north_i2c6_groups[] = { "i2c6_grp" }; +static const char * const glk_north_i2c7_groups[] = { "i2c7_grp" }; +static const char * const glk_north_uart0_groups[] = { "uart0_grp" }; + +static const struct intel_function glk_north_functions[] = { + FUNCTION("spi0", glk_north_spi0_groups), + FUNCTION("spi1", glk_north_spi1_groups), + FUNCTION("i2c5", glk_north_i2c5_groups), + FUNCTION("i2c6", glk_north_i2c6_groups), + FUNCTION("i2c7", glk_north_i2c7_groups), + FUNCTION("uart0", glk_north_uart0_groups), +}; + +static const struct intel_community glk_north_communities[] = { + GLK_COMMUNITY(0, 79), +}; + +static const struct intel_pinctrl_soc_data glk_north_soc_data = { + .uid = "2", + .pins = glk_north_pins, + .npins = ARRAY_SIZE(glk_north_pins), + .groups = glk_north_groups, + .ngroups = ARRAY_SIZE(glk_north_groups), + .functions = glk_north_functions, + .nfunctions = ARRAY_SIZE(glk_north_functions), + .communities = glk_north_communities, + .ncommunities = ARRAY_SIZE(glk_north_communities), +}; + +static const struct pinctrl_pin_desc glk_audio_pins[] = { + PINCTRL_PIN(0, "AVS_I2S0_MCLK"), + PINCTRL_PIN(1, "AVS_I2S0_BCLK"), + PINCTRL_PIN(2, "AVS_I2S0_WS_SYNC"), + PINCTRL_PIN(3, "AVS_I2S0_SDI"), + PINCTRL_PIN(4, "AVS_I2S0_SDO"), + PINCTRL_PIN(5, "AVS_I2S1_MCLK"), + PINCTRL_PIN(6, "AVS_I2S1_BCLK"), + PINCTRL_PIN(7, "AVS_I2S1_WS_SYNC"), + PINCTRL_PIN(8, "AVS_I2S1_SDI"), + PINCTRL_PIN(9, "AVS_I2S1_SDO"), + PINCTRL_PIN(10, "AVS_HDA_BCLK"), + PINCTRL_PIN(11, "AVS_HDA_WS_SYNC"), + PINCTRL_PIN(12, "AVS_HDA_SDI"), + PINCTRL_PIN(13, "AVS_HDA_SDO"), + PINCTRL_PIN(14, "AVS_HDA_RSTB"), + PINCTRL_PIN(15, "AVS_M_CLK_A1"), + PINCTRL_PIN(16, "AVS_M_CLK_B1"), + PINCTRL_PIN(17, "AVS_M_DATA_1"), + PINCTRL_PIN(18, "AVS_M_CLK_AB2"), + PINCTRL_PIN(19, "AVS_M_DATA_2"), +}; + +static const struct intel_community glk_audio_communities[] = { + GLK_COMMUNITY(0, 19), +}; + +static const struct intel_pinctrl_soc_data glk_audio_soc_data = { + .uid = "3", + .pins = glk_audio_pins, + .npins = ARRAY_SIZE(glk_audio_pins), + .communities = glk_audio_communities, + .ncommunities = ARRAY_SIZE(glk_audio_communities), +}; + +static const struct pinctrl_pin_desc glk_scc_pins[] = { + PINCTRL_PIN(0, "SMB_ALERTB"), + PINCTRL_PIN(1, "SMB_CLK"), + PINCTRL_PIN(2, "SMB_DATA"), + PINCTRL_PIN(3, "SDCARD_LVL_WP"), + PINCTRL_PIN(4, "SDCARD_CLK"), + PINCTRL_PIN(5, "SDCARD_CLK_FB"), + PINCTRL_PIN(6, "SDCARD_D0"), + PINCTRL_PIN(7, "SDCARD_D1"), + PINCTRL_PIN(8, "SDCARD_D2"), + PINCTRL_PIN(9, "SDCARD_D3"), + PINCTRL_PIN(10, "SDCARD_CMD"), + PINCTRL_PIN(11, "SDCARD_CD_B"), + PINCTRL_PIN(12, "SDCARD_PWR_DOWN_B"), + PINCTRL_PIN(13, "GPIO_210"), + PINCTRL_PIN(14, "OSC_CLK_OUT_0"), + PINCTRL_PIN(15, "OSC_CLK_OUT_1"), + PINCTRL_PIN(16, "CNV_BRI_DT"), + PINCTRL_PIN(17, "CNV_BRI_RSP"), + PINCTRL_PIN(18, "CNV_RGI_DT"), + PINCTRL_PIN(19, "CNV_RGI_RSP"), + PINCTRL_PIN(20, "CNV_RF_RESET_B"), + PINCTRL_PIN(21, "XTAL_CLKREQ"), + PINCTRL_PIN(22, "SDIO_CLK_FB"), + PINCTRL_PIN(23, "EMMC0_CLK"), + PINCTRL_PIN(24, "EMMC0_CLK_FB"), + PINCTRL_PIN(25, "EMMC0_D0"), + PINCTRL_PIN(26, "EMMC0_D1"), + PINCTRL_PIN(27, "EMMC0_D2"), + PINCTRL_PIN(28, "EMMC0_D3"), + PINCTRL_PIN(29, "EMMC0_D4"), + PINCTRL_PIN(30, "EMMC0_D5"), + PINCTRL_PIN(31, "EMMC0_D6"), + PINCTRL_PIN(32, "EMMC0_D7"), + PINCTRL_PIN(33, "EMMC0_CMD"), + PINCTRL_PIN(34, "EMMC0_STROBE"), +}; + +static const unsigned int glk_scc_i2c7_pins[] = { 1, 2 }; +static const unsigned int glk_scc_sdcard_pins[] = { + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, +}; +static const unsigned int glk_scc_sdio_pins[] = { 16, 17, 18, 19, 20, 21, 22 }; +static const unsigned int glk_scc_uart1_pins[] = { 16, 17, 18, 19 }; +static const unsigned int glk_scc_emmc_pins[] = { + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, +}; + +static const struct intel_pingroup glk_scc_groups[] = { + PIN_GROUP("i2c7_grp", glk_scc_i2c7_pins, 2), + PIN_GROUP("sdcard_grp", glk_scc_sdcard_pins, 1), + PIN_GROUP("sdio_grp", glk_scc_sdio_pins, 2), + PIN_GROUP("uart1_grp", glk_scc_uart1_pins, 3), + PIN_GROUP("emmc_grp", glk_scc_emmc_pins, 1), +}; + +static const char * const glk_scc_i2c7_groups[] = { "i2c7_grp" }; +static const char * const glk_scc_sdcard_groups[] = { "sdcard_grp" }; +static const char * const glk_scc_sdio_groups[] = { "sdio_grp" }; +static const char * const glk_scc_uart1_groups[] = { "uart1_grp" }; +static const char * const glk_scc_emmc_groups[] = { "emmc_grp" }; + +static const struct intel_function glk_scc_functions[] = { + FUNCTION("i2c7", glk_scc_i2c7_groups), + FUNCTION("sdcard", glk_scc_sdcard_groups), + FUNCTION("sdio", glk_scc_sdio_groups), + FUNCTION("uart1", glk_scc_uart1_groups), + FUNCTION("emmc", glk_scc_emmc_groups), +}; + +static const struct intel_community glk_scc_communities[] = { + GLK_COMMUNITY(0, 34), +}; + +static const struct intel_pinctrl_soc_data glk_scc_soc_data = { + .uid = "4", + .pins = glk_scc_pins, + .npins = ARRAY_SIZE(glk_scc_pins), + .groups = glk_scc_groups, + .ngroups = ARRAY_SIZE(glk_scc_groups), + .functions = glk_scc_functions, + .nfunctions = ARRAY_SIZE(glk_scc_functions), + .communities = glk_scc_communities, + .ncommunities = ARRAY_SIZE(glk_scc_communities), +}; + +static const struct intel_pinctrl_soc_data *glk_pinctrl_soc_data[] = { + &glk_northwest_soc_data, + &glk_north_soc_data, + &glk_audio_soc_data, + &glk_scc_soc_data, + NULL, +}; + +static const struct acpi_device_id glk_pinctrl_acpi_match[] = { + { "INT3453" }, + { } +}; +MODULE_DEVICE_TABLE(acpi, glk_pinctrl_acpi_match); + +static int glk_pinctrl_probe(struct platform_device *pdev) +{ + const struct intel_pinctrl_soc_data *soc_data = NULL; + struct acpi_device *adev; + int i; + + adev = ACPI_COMPANION(&pdev->dev); + if (!adev) + return -ENODEV; + + for (i = 0; glk_pinctrl_soc_data[i]; i++) { + if (!strcmp(adev->pnp.unique_id, + glk_pinctrl_soc_data[i]->uid)) { + soc_data = glk_pinctrl_soc_data[i]; + break; + } + } + + if (!soc_data) + return -ENODEV; + + return intel_pinctrl_probe(pdev, soc_data); +} + +static const struct dev_pm_ops glk_pinctrl_pm_ops = { + SET_LATE_SYSTEM_SLEEP_PM_OPS(intel_pinctrl_suspend, + intel_pinctrl_resume) +}; + +static struct platform_driver glk_pinctrl_driver = { + .probe = glk_pinctrl_probe, + .driver = { + .name = "geminilake-pinctrl", + .acpi_match_table = glk_pinctrl_acpi_match, + .pm = &glk_pinctrl_pm_ops, + }, +}; + +static int __init glk_pinctrl_init(void) +{ + return platform_driver_register(&glk_pinctrl_driver); +} +subsys_initcall(glk_pinctrl_init); + +static void __exit glk_pinctrl_exit(void) +{ + platform_driver_unregister(&glk_pinctrl_driver); +} +module_exit(glk_pinctrl_exit); + +MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); +MODULE_DESCRIPTION("Intel Gemini Lake SoC pinctrl/GPIO driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index 1e139672f1af..592b465e981e 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -13,6 +13,7 @@ #include <linux/module.h> #include <linux/interrupt.h> #include <linux/gpio/driver.h> +#include <linux/log2.h> #include <linux/platform_device.h> #include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinmux.h> @@ -23,6 +24,10 @@ #include "pinctrl-intel.h" /* Offset from regs */ +#define REVID 0x000 +#define REVID_SHIFT 16 +#define REVID_MASK GENMASK(31, 16) + #define PADBAR 0x00c #define GPI_IS 0x100 #define GPI_GPE_STS 0x140 @@ -41,6 +46,7 @@ #define PADCFG0_RXEVCFG_EDGE 1 #define PADCFG0_RXEVCFG_DISABLED 2 #define PADCFG0_RXEVCFG_EDGE_BOTH 3 +#define PADCFG0_PREGFRXSEL BIT(24) #define PADCFG0_RXINV BIT(23) #define PADCFG0_GPIROUTIOXAPIC BIT(20) #define PADCFG0_GPIROUTSCI BIT(19) @@ -62,9 +68,17 @@ #define PADCFG1_TERM_5K 2 #define PADCFG1_TERM_1K 1 +#define PADCFG2 0x008 +#define PADCFG2_DEBEN BIT(0) +#define PADCFG2_DEBOUNCE_SHIFT 1 +#define PADCFG2_DEBOUNCE_MASK GENMASK(4, 1) + +#define DEBOUNCE_PERIOD 31250 /* ns */ + struct intel_pad_context { u32 padcfg0; u32 padcfg1; + u32 padcfg2; }; struct intel_community_context { @@ -126,13 +140,19 @@ static void __iomem *intel_get_padcfg(struct intel_pinctrl *pctrl, unsigned pin, { const struct intel_community *community; unsigned padno; + size_t nregs; community = intel_get_community(pctrl, pin); if (!community) return NULL; padno = pin_to_padno(community, pin); - return community->pad_regs + reg + padno * 8; + nregs = (community->features & PINCTRL_FEATURE_DEBOUNCE) ? 4 : 2; + + if (reg == PADCFG2 && !(community->features & PINCTRL_FEATURE_DEBOUNCE)) + return NULL; + + return community->pad_regs + reg + padno * nregs * 4; } static bool intel_pad_owned_by_host(struct intel_pinctrl *pctrl, unsigned pin) @@ -244,6 +264,7 @@ static void intel_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, unsigned pin) { struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + void __iomem *padcfg; u32 cfg0, cfg1, mode; bool locked, acpi; @@ -263,6 +284,11 @@ static void intel_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, seq_printf(s, "0x%08x 0x%08x", cfg0, cfg1); + /* Dump the additional PADCFG registers if available */ + padcfg = intel_get_padcfg(pctrl, pin, PADCFG2); + if (padcfg) + seq_printf(s, " 0x%08x", readl(padcfg)); + locked = intel_pad_locked(pctrl, pin); acpi = intel_pad_acpi_mode(pctrl, pin); @@ -353,6 +379,21 @@ static int intel_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned function, return 0; } +static void __intel_gpio_set_direction(void __iomem *padcfg0, bool input) +{ + u32 value; + + value = readl(padcfg0); + if (input) { + value &= ~PADCFG0_GPIORXDIS; + value |= PADCFG0_GPIOTXDIS; + } else { + value &= ~PADCFG0_GPIOTXDIS; + value |= PADCFG0_GPIORXDIS; + } + writel(value, padcfg0); +} + static int intel_gpio_request_enable(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, unsigned pin) @@ -375,11 +416,11 @@ static int intel_gpio_request_enable(struct pinctrl_dev *pctldev, /* Disable SCI/SMI/NMI generation */ value &= ~(PADCFG0_GPIROUTIOXAPIC | PADCFG0_GPIROUTSCI); value &= ~(PADCFG0_GPIROUTSMI | PADCFG0_GPIROUTNMI); - /* Disable TX buffer and enable RX (this will be input) */ - value &= ~PADCFG0_GPIORXDIS; - value |= PADCFG0_GPIOTXDIS; writel(value, padcfg0); + /* Disable TX buffer and enable RX (this will be input) */ + __intel_gpio_set_direction(padcfg0, true); + raw_spin_unlock_irqrestore(&pctrl->lock, flags); return 0; @@ -392,18 +433,11 @@ static int intel_gpio_set_direction(struct pinctrl_dev *pctldev, struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); void __iomem *padcfg0; unsigned long flags; - u32 value; raw_spin_lock_irqsave(&pctrl->lock, flags); padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0); - - value = readl(padcfg0); - if (input) - value |= PADCFG0_GPIOTXDIS; - else - value &= ~PADCFG0_GPIOTXDIS; - writel(value, padcfg0); + __intel_gpio_set_direction(padcfg0, input); raw_spin_unlock_irqrestore(&pctrl->lock, flags); @@ -424,12 +458,14 @@ static int intel_config_get(struct pinctrl_dev *pctldev, unsigned pin, { struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); enum pin_config_param param = pinconf_to_config_param(*config); + const struct intel_community *community; u32 value, term; - u16 arg = 0; + u32 arg = 0; if (!intel_pad_owned_by_host(pctrl, pin)) return -ENOTSUPP; + community = intel_get_community(pctrl, pin); value = readl(intel_get_padcfg(pctrl, pin, PADCFG1)); term = (value & PADCFG1_TERM_MASK) >> PADCFG1_TERM_SHIFT; @@ -465,6 +501,11 @@ static int intel_config_get(struct pinctrl_dev *pctldev, unsigned pin, return -EINVAL; switch (term) { + case PADCFG1_TERM_1K: + if (!(community->features & PINCTRL_FEATURE_1K_PD)) + return -EINVAL; + arg = 1000; + break; case PADCFG1_TERM_5K: arg = 5000; break; @@ -475,6 +516,24 @@ static int intel_config_get(struct pinctrl_dev *pctldev, unsigned pin, break; + case PIN_CONFIG_INPUT_DEBOUNCE: { + void __iomem *padcfg2; + u32 v; + + padcfg2 = intel_get_padcfg(pctrl, pin, PADCFG2); + if (!padcfg2) + return -ENOTSUPP; + + v = readl(padcfg2); + if (!(v & PADCFG2_DEBEN)) + return -EINVAL; + + v = (v & PADCFG2_DEBOUNCE_MASK) >> PADCFG2_DEBOUNCE_SHIFT; + arg = BIT(v) * DEBOUNCE_PERIOD / 1000; + + break; + } + default: return -ENOTSUPP; } @@ -488,6 +547,7 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned pin, { unsigned param = pinconf_to_config_param(config); unsigned arg = pinconf_to_config_argument(config); + const struct intel_community *community; void __iomem *padcfg1; unsigned long flags; int ret = 0; @@ -495,6 +555,7 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned pin, raw_spin_lock_irqsave(&pctrl->lock, flags); + community = intel_get_community(pctrl, pin); padcfg1 = intel_get_padcfg(pctrl, pin, PADCFG1); value = readl(padcfg1); @@ -537,6 +598,13 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned pin, case 5000: value |= PADCFG1_TERM_5K << PADCFG1_TERM_SHIFT; break; + case 1000: + if (!(community->features & PINCTRL_FEATURE_1K_PD)) { + ret = -EINVAL; + break; + } + value |= PADCFG1_TERM_1K << PADCFG1_TERM_SHIFT; + break; default: ret = -EINVAL; } @@ -552,6 +620,53 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned pin, return ret; } +static int intel_config_set_debounce(struct intel_pinctrl *pctrl, unsigned pin, + unsigned debounce) +{ + void __iomem *padcfg0, *padcfg2; + unsigned long flags; + u32 value0, value2; + int ret = 0; + + padcfg2 = intel_get_padcfg(pctrl, pin, PADCFG2); + if (!padcfg2) + return -ENOTSUPP; + + padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0); + + raw_spin_lock_irqsave(&pctrl->lock, flags); + + value0 = readl(padcfg0); + value2 = readl(padcfg2); + + /* Disable glitch filter and debouncer */ + value0 &= ~PADCFG0_PREGFRXSEL; + value2 &= ~(PADCFG2_DEBEN | PADCFG2_DEBOUNCE_MASK); + + if (debounce) { + unsigned long v; + + v = order_base_2(debounce * 1000 / DEBOUNCE_PERIOD); + if (v < 3 || v > 15) { + ret = -EINVAL; + goto exit_unlock; + } else { + /* Enable glitch filter and debouncer */ + value0 |= PADCFG0_PREGFRXSEL; + value2 |= v << PADCFG2_DEBOUNCE_SHIFT; + value2 |= PADCFG2_DEBEN; + } + } + + writel(value0, padcfg0); + writel(value2, padcfg2); + +exit_unlock: + raw_spin_unlock_irqrestore(&pctrl->lock, flags); + + return ret; +} + static int intel_config_set(struct pinctrl_dev *pctldev, unsigned pin, unsigned long *configs, unsigned nconfigs) { @@ -571,6 +686,13 @@ static int intel_config_set(struct pinctrl_dev *pctldev, unsigned pin, return ret; break; + case PIN_CONFIG_INPUT_DEBOUNCE: + ret = intel_config_set_debounce(pctrl, pin, + pinconf_to_config_argument(configs[i])); + if (ret) + return ret; + break; + default: return -ENOTSUPP; } @@ -645,6 +767,7 @@ static const struct gpio_chip intel_gpio_chip = { .direction_output = intel_gpio_direction_output, .get = intel_gpio_get, .set = intel_gpio_set, + .set_config = gpiochip_generic_config, }; static void intel_gpio_irq_ack(struct irq_data *d) @@ -884,7 +1007,7 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq) pctrl->chip.base = -1; pctrl->irq = irq; - ret = gpiochip_add_data(&pctrl->chip, pctrl); + ret = devm_gpiochip_add_data(pctrl->dev, &pctrl->chip, pctrl); if (ret) { dev_err(pctrl->dev, "failed to register gpiochip\n"); return ret; @@ -894,7 +1017,7 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq) 0, 0, pctrl->soc->npins); if (ret) { dev_err(pctrl->dev, "failed to add GPIO pin range\n"); - goto fail; + return ret; } /* @@ -907,24 +1030,19 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq) dev_name(pctrl->dev), pctrl); if (ret) { dev_err(pctrl->dev, "failed to request interrupt\n"); - goto fail; + return ret; } ret = gpiochip_irqchip_add(&pctrl->chip, &intel_gpio_irqchip, 0, handle_bad_irq, IRQ_TYPE_NONE); if (ret) { dev_err(pctrl->dev, "failed to add irqchip\n"); - goto fail; + return ret; } gpiochip_set_chained_irqchip(&pctrl->chip, &intel_gpio_irqchip, irq, NULL); return 0; - -fail: - gpiochip_remove(&pctrl->chip); - - return ret; } static int intel_pinctrl_pm_init(struct intel_pinctrl *pctrl) @@ -1005,6 +1123,20 @@ int intel_pinctrl_probe(struct platform_device *pdev, if (IS_ERR(regs)) return PTR_ERR(regs); + /* + * Determine community features based on the revision if + * not specified already. + */ + if (!community->features) { + u32 rev; + + rev = (readl(regs + REVID) & REVID_MASK) >> REVID_SHIFT; + if (rev >= 0x94) { + community->features |= PINCTRL_FEATURE_DEBOUNCE; + community->features |= PINCTRL_FEATURE_1K_PD; + } + } + /* Read offset of the pad configuration registers */ padbar = readl(regs + PADBAR); @@ -1046,16 +1178,6 @@ int intel_pinctrl_probe(struct platform_device *pdev, } EXPORT_SYMBOL_GPL(intel_pinctrl_probe); -int intel_pinctrl_remove(struct platform_device *pdev) -{ - struct intel_pinctrl *pctrl = platform_get_drvdata(pdev); - - gpiochip_remove(&pctrl->chip); - - return 0; -} -EXPORT_SYMBOL_GPL(intel_pinctrl_remove); - #ifdef CONFIG_PM_SLEEP static bool intel_pinctrl_should_save(struct intel_pinctrl *pctrl, unsigned pin) { @@ -1088,6 +1210,7 @@ int intel_pinctrl_suspend(struct device *dev) pads = pctrl->context.pads; for (i = 0; i < pctrl->soc->npins; i++) { const struct pinctrl_pin_desc *desc = &pctrl->soc->pins[i]; + void __iomem *padcfg; u32 val; if (!intel_pinctrl_should_save(pctrl, desc->number)) @@ -1097,6 +1220,10 @@ int intel_pinctrl_suspend(struct device *dev) pads[i].padcfg0 = val & ~PADCFG0_GPIORXSTATE; val = readl(intel_get_padcfg(pctrl, desc->number, PADCFG1)); pads[i].padcfg1 = val; + + padcfg = intel_get_padcfg(pctrl, desc->number, PADCFG2); + if (padcfg) + pads[i].padcfg2 = readl(padcfg); } communities = pctrl->context.communities; @@ -1169,6 +1296,16 @@ int intel_pinctrl_resume(struct device *dev) dev_dbg(dev, "restored pin %u padcfg1 %#08x\n", desc->number, readl(padcfg)); } + + padcfg = intel_get_padcfg(pctrl, desc->number, PADCFG2); + if (padcfg) { + val = readl(padcfg); + if (val != pads[i].padcfg2) { + writel(pads[i].padcfg2, padcfg); + dev_dbg(dev, "restored pin %u padcfg2 %#08x\n", + desc->number, readl(padcfg)); + } + } } communities = pctrl->context.communities; diff --git a/drivers/pinctrl/intel/pinctrl-intel.h b/drivers/pinctrl/intel/pinctrl-intel.h index b60215793017..fe9521f345b5 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.h +++ b/drivers/pinctrl/intel/pinctrl-intel.h @@ -58,6 +58,7 @@ struct intel_function { * @gpp_size: Maximum number of pads in each group, such as PADCFGLOCK, * HOSTSW_OWN, GPI_IS, GPI_IE, etc. * @npins: Number of pins in this community + * @features: Additional features supported by the hardware * @regs: Community specific common registers (reserved for core driver) * @pad_regs: Community specific pad registers (reserved for core driver) * @ngpps: Number of groups (hw groups) in this community (reserved for @@ -72,11 +73,16 @@ struct intel_community { unsigned pin_base; unsigned gpp_size; size_t npins; + unsigned features; void __iomem *regs; void __iomem *pad_regs; size_t ngpps; }; +/* Additional features supported by the hardware */ +#define PINCTRL_FEATURE_DEBOUNCE BIT(0) +#define PINCTRL_FEATURE_1K_PD BIT(1) + #define PIN_GROUP(n, p, m) \ { \ .name = (n), \ @@ -121,8 +127,6 @@ struct intel_pinctrl_soc_data { int intel_pinctrl_probe(struct platform_device *pdev, const struct intel_pinctrl_soc_data *soc_data); -int intel_pinctrl_remove(struct platform_device *pdev); - #ifdef CONFIG_PM_SLEEP int intel_pinctrl_suspend(struct device *dev); int intel_pinctrl_resume(struct device *dev); diff --git a/drivers/pinctrl/intel/pinctrl-merrifield.c b/drivers/pinctrl/intel/pinctrl-merrifield.c index b21896126f76..4d4ef42a39b5 100644 --- a/drivers/pinctrl/intel/pinctrl-merrifield.c +++ b/drivers/pinctrl/intel/pinctrl-merrifield.c @@ -794,6 +794,9 @@ static int mrfld_config_set(struct pinctrl_dev *pctldev, unsigned int pin, unsigned int i; int ret; + if (!mrfld_buf_available(mp, pin)) + return -ENOTSUPP; + for (i = 0; i < nconfigs; i++) { switch (pinconf_to_config_param(configs[i])) { case PIN_CONFIG_BIAS_DISABLE: diff --git a/drivers/pinctrl/intel/pinctrl-sunrisepoint.c b/drivers/pinctrl/intel/pinctrl-sunrisepoint.c index c725a5313b4e..9877526c0807 100644 --- a/drivers/pinctrl/intel/pinctrl-sunrisepoint.c +++ b/drivers/pinctrl/intel/pinctrl-sunrisepoint.c @@ -574,7 +574,6 @@ static const struct dev_pm_ops spt_pinctrl_pm_ops = { static struct platform_driver spt_pinctrl_driver = { .probe = spt_pinctrl_probe, - .remove = intel_pinctrl_remove, .driver = { .name = "sunrisepoint-pinctrl", .acpi_match_table = spt_pinctrl_acpi_match, |