From d6cb77228e3ae070061195a6fff6ba7c3c0b8e47 Mon Sep 17 00:00:00 2001 From: Aditya Pakki Date: Tue, 12 Mar 2019 10:05:52 -0500 Subject: pinctrl: baytrail: Fix potential NULL pointer dereference saved-context in byt_gpio_probe is allocated via devm_kcalloc and is used without checking for NULL in later functions. This patch avoids such a scenario. Signed-off-by: Aditya Pakki Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-baytrail.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/pinctrl') diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c index 241384ead4ed..18d9ad504194 100644 --- a/drivers/pinctrl/intel/pinctrl-baytrail.c +++ b/drivers/pinctrl/intel/pinctrl-baytrail.c @@ -1710,6 +1710,8 @@ static int byt_gpio_probe(struct byt_gpio *vg) #ifdef CONFIG_PM_SLEEP vg->saved_context = devm_kcalloc(&vg->pdev->dev, gc->ngpio, sizeof(*vg->saved_context), GFP_KERNEL); + if (!vg->saved_context) + return -ENOMEM; #endif ret = devm_gpiochip_add_data(&vg->pdev->dev, gc, vg); if (ret) { -- cgit From 10d64c871c309afb2403a3fadf5ff3ab7d96d8ed Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 13 Mar 2019 13:58:25 +0200 Subject: pinctrl: cedarfork: Update pin names according to v1.13c Version 1.13c of pin list has some changes in pin names for Intel Cedarfork. Update the driver accordingly. Signed-off-by: Andy Shevchenko Acked-by: Mika Westerberg Acked-by: Linus Walleij --- drivers/pinctrl/intel/pinctrl-cedarfork.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/pinctrl') diff --git a/drivers/pinctrl/intel/pinctrl-cedarfork.c b/drivers/pinctrl/intel/pinctrl-cedarfork.c index b7d632f1dbf6..aa6f9040d3d8 100644 --- a/drivers/pinctrl/intel/pinctrl-cedarfork.c +++ b/drivers/pinctrl/intel/pinctrl-cedarfork.c @@ -91,13 +91,13 @@ static const struct pinctrl_pin_desc cdf_pins[] = { PINCTRL_PIN(43, "MEMTRIP_N"), PINCTRL_PIN(44, "UART0_RXD"), PINCTRL_PIN(45, "UART0_TXD"), - PINCTRL_PIN(46, "UART1_RXD"), - PINCTRL_PIN(47, "UART1_TXD"), + PINCTRL_PIN(46, "GBE_UART_RXD"), + PINCTRL_PIN(47, "GBE_UART_TXD"), /* WEST01 */ PINCTRL_PIN(48, "GBE_GPIO13"), PINCTRL_PIN(49, "AUX_PWR"), - PINCTRL_PIN(50, "CPU_GP_2"), - PINCTRL_PIN(51, "CPU_GP_3"), + PINCTRL_PIN(50, "UART0_RTS"), + PINCTRL_PIN(51, "UART0_CTS"), PINCTRL_PIN(52, "FAN_PWM_0"), PINCTRL_PIN(53, "FAN_PWM_1"), PINCTRL_PIN(54, "FAN_PWM_2"), @@ -201,8 +201,8 @@ static const struct pinctrl_pin_desc cdf_pins[] = { /* WESTF */ PINCTRL_PIN(145, "NAC_RMII_CLK"), PINCTRL_PIN(146, "NAC_RGMII_CLK"), - PINCTRL_PIN(147, "NAC_SPARE0"), - PINCTRL_PIN(148, "NAC_SPARE1"), + PINCTRL_PIN(147, "NAC_GBE_SMB_CLK_TX_N2S"), + PINCTRL_PIN(148, "NAC_GBE_SMB_DATA_TX_N2S"), PINCTRL_PIN(149, "NAC_SPARE2"), PINCTRL_PIN(150, "NAC_INIT_SX_WAKE_N"), PINCTRL_PIN(151, "NAC_GBE_GPIO0_S2N"), @@ -219,8 +219,8 @@ static const struct pinctrl_pin_desc cdf_pins[] = { PINCTRL_PIN(162, "NAC_NCSI_TXD1"), PINCTRL_PIN(163, "NAC_NCSI_ARB_OUT"), PINCTRL_PIN(164, "NAC_NCSI_OE_N"), - PINCTRL_PIN(165, "NAC_GBE_SMB_CLK"), - PINCTRL_PIN(166, "NAC_GBE_SMB_DATA"), + PINCTRL_PIN(165, "NAC_GBE_SMB_CLK_RX_S2N"), + PINCTRL_PIN(166, "NAC_GBE_SMB_DATA_RX_S2N"), PINCTRL_PIN(167, "NAC_GBE_SMB_ALRT_N"), /* EAST2 */ PINCTRL_PIN(168, "USB_OC0_N"), @@ -232,7 +232,7 @@ static const struct pinctrl_pin_desc cdf_pins[] = { PINCTRL_PIN(174, "GBE_GPIO5"), PINCTRL_PIN(175, "GBE_GPIO6"), PINCTRL_PIN(176, "GBE_GPIO7"), - PINCTRL_PIN(177, "GBE_GPIO8"), + PINCTRL_PIN(177, "SPI_TPM_CS_N"), PINCTRL_PIN(178, "GBE_GPIO9"), PINCTRL_PIN(179, "GBE_GPIO10"), PINCTRL_PIN(180, "GBE_GPIO11"), -- cgit From 2fef32766861c6e171f436ab99c89198cf0ca6e1 Mon Sep 17 00:00:00 2001 From: Binbin Wu Date: Mon, 8 Apr 2019 18:49:26 +0800 Subject: pinctrl: pinctrl-intel: move gpio suspend/resume to noirq phase In current driver, SET_LATE_SYSTEM_SLEEP_PM_OPS is used to install the callbacks for suspend/resume. GPIO pin may be used as the interrupt pin by some device. However, using SET_LATE_SYSTEM_SLEEP_PM_OPS() to install the callbacks, the resume callback is called after resume_device_irqs(). Unintended interrupts may arrive due to resuming device irqs first, but the GPIO controller is not properly restored. Normally, for a SMP system, there are multiple cores, so even when there are unintended interrupts, BSP gets the chance to initialize the GPIO chip soon. But when there is only 1 core is active (other cores are offlined or single core) during resume, it is more easily to observe the unintended interrupts. This patch renames the suspend/resume function by adding suffix "_noirq", and installs the callbacks using SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(). Signed-off-by: Binbin Wu Acked-by: Mika Westerberg Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-intel.c | 8 ++++---- drivers/pinctrl/intel/pinctrl-intel.h | 11 ++++++----- 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers/pinctrl') diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index 3b1818184207..70638b74f9d6 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -1466,7 +1466,7 @@ static bool intel_pinctrl_should_save(struct intel_pinctrl *pctrl, unsigned int return false; } -int intel_pinctrl_suspend(struct device *dev) +int intel_pinctrl_suspend_noirq(struct device *dev) { struct intel_pinctrl *pctrl = dev_get_drvdata(dev); struct intel_community_context *communities; @@ -1505,7 +1505,7 @@ int intel_pinctrl_suspend(struct device *dev) return 0; } -EXPORT_SYMBOL_GPL(intel_pinctrl_suspend); +EXPORT_SYMBOL_GPL(intel_pinctrl_suspend_noirq); static void intel_gpio_irq_init(struct intel_pinctrl *pctrl) { @@ -1527,7 +1527,7 @@ static void intel_gpio_irq_init(struct intel_pinctrl *pctrl) } } -int intel_pinctrl_resume(struct device *dev) +int intel_pinctrl_resume_noirq(struct device *dev) { struct intel_pinctrl *pctrl = dev_get_drvdata(dev); const struct intel_community_context *communities; @@ -1589,7 +1589,7 @@ int intel_pinctrl_resume(struct device *dev) return 0; } -EXPORT_SYMBOL_GPL(intel_pinctrl_resume); +EXPORT_SYMBOL_GPL(intel_pinctrl_resume_noirq); #endif MODULE_AUTHOR("Mathias Nyman "); diff --git a/drivers/pinctrl/intel/pinctrl-intel.h b/drivers/pinctrl/intel/pinctrl-intel.h index b8a07d37d18f..a8e958f1dcf5 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.h +++ b/drivers/pinctrl/intel/pinctrl-intel.h @@ -177,13 +177,14 @@ int intel_pinctrl_probe_by_hid(struct platform_device *pdev); int intel_pinctrl_probe_by_uid(struct platform_device *pdev); #ifdef CONFIG_PM_SLEEP -int intel_pinctrl_suspend(struct device *dev); -int intel_pinctrl_resume(struct device *dev); +int intel_pinctrl_suspend_noirq(struct device *dev); +int intel_pinctrl_resume_noirq(struct device *dev); #endif -#define INTEL_PINCTRL_PM_OPS(_name) \ -const struct dev_pm_ops _name = { \ - SET_LATE_SYSTEM_SLEEP_PM_OPS(intel_pinctrl_suspend, intel_pinctrl_resume) \ +#define INTEL_PINCTRL_PM_OPS(_name) \ +const struct dev_pm_ops _name = { \ + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(intel_pinctrl_suspend_noirq, \ + intel_pinctrl_resume_noirq) \ } #endif /* PINCTRL_INTEL_H */ -- cgit From a0a5f7661e1c49de0c1f93ca435ba2880b88fc5c Mon Sep 17 00:00:00 2001 From: Chris Chiu Date: Mon, 15 Apr 2019 13:53:58 +0800 Subject: pinctrl: intel: Retain HOSTSW_OWN for requested gpio pin The touchpad of the ASUS laptops E403NA, X540NA, X541NA are not responsive after suspend/resume. The following error message shows after resume. i2c_hid i2c-ELAN1200:00: failed to reset device. On these laptops, the touchpad interrupt is connected via a GPIO pin which is controlled by Intel pinctrl. After system resumes, the GPIO is in ACPI mode and no longer works as an IRQ. This commit saves the HOSTSW_OWN value during suspend, make sure the HOSTSW_OWN mode remains the same after resume. Signed-off-by: Chris Chiu Acked-by: Mika Westerberg Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-intel.c | 56 ++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) (limited to 'drivers/pinctrl') diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index 70638b74f9d6..1c85cc807a8f 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -81,6 +81,7 @@ struct intel_pad_context { struct intel_community_context { u32 *intmask; + u32 *hostown; }; struct intel_pinctrl_context { @@ -1284,7 +1285,7 @@ static int intel_pinctrl_pm_init(struct intel_pinctrl *pctrl) for (i = 0; i < pctrl->ncommunities; i++) { struct intel_community *community = &pctrl->communities[i]; - u32 *intmask; + u32 *intmask, *hostown; intmask = devm_kcalloc(pctrl->dev, community->ngpps, sizeof(*intmask), GFP_KERNEL); @@ -1292,6 +1293,13 @@ static int intel_pinctrl_pm_init(struct intel_pinctrl *pctrl) return -ENOMEM; communities[i].intmask = intmask; + + hostown = devm_kcalloc(pctrl->dev, community->ngpps, + sizeof(*hostown), GFP_KERNEL); + if (!hostown) + return -ENOMEM; + + communities[i].hostown = hostown; } pctrl->context.pads = pads; @@ -1501,6 +1509,10 @@ int intel_pinctrl_suspend_noirq(struct device *dev) base = community->regs + community->ie_offset; for (gpp = 0; gpp < community->ngpps; gpp++) communities[i].intmask[gpp] = readl(base + gpp * 4); + + base = community->regs + community->hostown_offset; + for (gpp = 0; gpp < community->ngpps; gpp++) + communities[i].hostown[gpp] = readl(base + gpp * 4); } return 0; @@ -1527,6 +1539,29 @@ static void intel_gpio_irq_init(struct intel_pinctrl *pctrl) } } +static u32 +intel_gpio_is_requested(struct gpio_chip *chip, int base, unsigned int size) +{ + u32 requested = 0; + unsigned int i; + + for (i = 0; i < size; i++) + if (gpiochip_is_requested(chip, base + i)) + requested |= BIT(i); + + return requested; +} + +static u32 +intel_gpio_update_pad_mode(void __iomem *hostown, u32 mask, u32 value) +{ + u32 curr = readl(hostown); + u32 updated = (curr & ~mask) | (value & mask); + + writel(updated, hostown); + return curr; +} + int intel_pinctrl_resume_noirq(struct device *dev) { struct intel_pinctrl *pctrl = dev_get_drvdata(dev); @@ -1585,6 +1620,25 @@ int intel_pinctrl_resume_noirq(struct device *dev) dev_dbg(dev, "restored mask %d/%u %#08x\n", i, gpp, readl(base + gpp * 4)); } + + base = community->regs + community->hostown_offset; + for (gpp = 0; gpp < community->ngpps; gpp++) { + const struct intel_padgroup *padgrp = &community->gpps[gpp]; + u32 requested = 0, value = 0; + u32 saved = communities[i].hostown[gpp]; + + if (padgrp->gpio_base < 0) + continue; + + requested = intel_gpio_is_requested(&pctrl->chip, + padgrp->gpio_base, padgrp->size); + value = intel_gpio_update_pad_mode(base + gpp * 4, + requested, saved); + if ((value ^ saved) & requested) { + dev_warn(dev, "restore hostown %d/%u %#8x->%#8x\n", + i, gpp, value, saved); + } + } } return 0; -- cgit From 5f61d9517f17069dbedb94aa71034f0a22e014ef Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sun, 28 Apr 2019 20:19:06 +0300 Subject: pinctrl: intel: Increase readability of intel_gpio_update_pad_mode() We better to use usual pattern for read-modify-update, than doing some operations in definition block. No functional change. Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-intel.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/pinctrl') diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index 1c85cc807a8f..d7acbb79cdf7 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -1555,10 +1555,12 @@ intel_gpio_is_requested(struct gpio_chip *chip, int base, unsigned int size) static u32 intel_gpio_update_pad_mode(void __iomem *hostown, u32 mask, u32 value) { - u32 curr = readl(hostown); - u32 updated = (curr & ~mask) | (value & mask); + u32 curr, updated; + curr = readl(hostown); + updated = (curr & ~mask) | (value & mask); writel(updated, hostown); + return curr; } -- cgit