Message ID | 20250305220146.3932955-3-superm1@kernel.org |
---|---|
State | New |
Headers | show |
Series | Add LPS0 check() for pinctrl-amd | expand |
On Wed, Mar 5, 2025 at 11:01 PM Mario Limonciello <superm1@kernel.org> wrote: > > From: Mario Limonciello <mario.limonciello@amd.com> > > During suspend the pinctrl_amd driver disables the interrupts for > any GPIOs that are not marked as wake sources. > > This however does not prevent them from changing the wake status > bit during suspend, it just stops the system from waking. > > If the system wakes from hardware sleep for another reason (such > as plugging in the AC adapter) this wake bits might be active. > > This could potentially cause problems with going back to hardware > sleep. Add an extra debugging message when PM debugging is enabled > to help identify if this is happening. > > Acked-by: Linus Walleij <linus.walleij@linaro.org> > Link: https://gitlab.freedesktop.org/drm/amd/-/issues/3929 > Signed-off-by: Mario Limonciello <mario.limonciello@amd.com> > --- > v3: > * Add tag > --- > drivers/pinctrl/pinctrl-amd.c | 28 ++++++++++++++++++++++++++++ > 1 file changed, 28 insertions(+) > > diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c > index 1d7fdcdec4c85..fdda8d1c4f344 100644 > --- a/drivers/pinctrl/pinctrl-amd.c > +++ b/drivers/pinctrl/pinctrl-amd.c > @@ -37,6 +37,8 @@ > #include "pinctrl-utils.h" > #include "pinctrl-amd.h" > > +static struct amd_gpio *pinctrl_dev; > + > static int amd_gpio_get_direction(struct gpio_chip *gc, unsigned offset) > { > unsigned long flags; > @@ -909,6 +911,29 @@ static bool amd_gpio_should_save(struct amd_gpio *gpio_dev, unsigned int pin) > return false; > } > > +static void amd_gpio_check_pending(void) > +{ > + struct amd_gpio *gpio_dev = pinctrl_dev; > + struct pinctrl_desc *desc = gpio_dev->pctrl->desc; > + int i; > + > + if (!pm_debug_messages_on) > + return; > + > + for (i = 0; i < desc->npins; i++) { > + int pin = desc->pins[i].number; > + u32 tmp; > + > + tmp = readl(gpio_dev->base + pin * 4); > + if (tmp & PIN_IRQ_PENDING) > + pm_pr_dbg("%s: GPIO %d is active: 0x%x.\n", __func__, pin, tmp); > + } > +} > + > +static struct acpi_s2idle_dev_ops pinctrl_amd_s2idle_dev_ops = { > + .check = amd_gpio_check_pending, > +}; > + > static int amd_gpio_suspend_hibernate_common(struct device *dev, bool is_suspend) > { > struct amd_gpio *gpio_dev = dev_get_drvdata(dev); > @@ -942,6 +967,7 @@ static int amd_gpio_suspend_hibernate_common(struct device *dev, bool is_suspend > > static int amd_gpio_suspend(struct device *dev) > { > + pinctrl_dev = dev_get_drvdata(dev); > return amd_gpio_suspend_hibernate_common(dev, true); > } > > @@ -1181,6 +1207,7 @@ static int amd_gpio_probe(struct platform_device *pdev) > > platform_set_drvdata(pdev, gpio_dev); > acpi_register_wakeup_handler(gpio_dev->irq, amd_gpio_check_wake, gpio_dev); > + acpi_register_lps0_dev(&pinctrl_amd_s2idle_dev_ops); > > dev_dbg(&pdev->dev, "amd gpio driver loaded\n"); > return ret; > @@ -1199,6 +1226,7 @@ static void amd_gpio_remove(struct platform_device *pdev) > > gpiochip_remove(&gpio_dev->gc); > acpi_unregister_wakeup_handler(amd_gpio_check_wake, gpio_dev); > + acpi_unregister_lps0_dev(&pinctrl_amd_s2idle_dev_ops); > } > > #ifdef CONFIG_ACPI > -- Applied as 6.15 material, thanks!
diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c index 1d7fdcdec4c85..fdda8d1c4f344 100644 --- a/drivers/pinctrl/pinctrl-amd.c +++ b/drivers/pinctrl/pinctrl-amd.c @@ -37,6 +37,8 @@ #include "pinctrl-utils.h" #include "pinctrl-amd.h" +static struct amd_gpio *pinctrl_dev; + static int amd_gpio_get_direction(struct gpio_chip *gc, unsigned offset) { unsigned long flags; @@ -909,6 +911,29 @@ static bool amd_gpio_should_save(struct amd_gpio *gpio_dev, unsigned int pin) return false; } +static void amd_gpio_check_pending(void) +{ + struct amd_gpio *gpio_dev = pinctrl_dev; + struct pinctrl_desc *desc = gpio_dev->pctrl->desc; + int i; + + if (!pm_debug_messages_on) + return; + + for (i = 0; i < desc->npins; i++) { + int pin = desc->pins[i].number; + u32 tmp; + + tmp = readl(gpio_dev->base + pin * 4); + if (tmp & PIN_IRQ_PENDING) + pm_pr_dbg("%s: GPIO %d is active: 0x%x.\n", __func__, pin, tmp); + } +} + +static struct acpi_s2idle_dev_ops pinctrl_amd_s2idle_dev_ops = { + .check = amd_gpio_check_pending, +}; + static int amd_gpio_suspend_hibernate_common(struct device *dev, bool is_suspend) { struct amd_gpio *gpio_dev = dev_get_drvdata(dev); @@ -942,6 +967,7 @@ static int amd_gpio_suspend_hibernate_common(struct device *dev, bool is_suspend static int amd_gpio_suspend(struct device *dev) { + pinctrl_dev = dev_get_drvdata(dev); return amd_gpio_suspend_hibernate_common(dev, true); } @@ -1181,6 +1207,7 @@ static int amd_gpio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, gpio_dev); acpi_register_wakeup_handler(gpio_dev->irq, amd_gpio_check_wake, gpio_dev); + acpi_register_lps0_dev(&pinctrl_amd_s2idle_dev_ops); dev_dbg(&pdev->dev, "amd gpio driver loaded\n"); return ret; @@ -1199,6 +1226,7 @@ static void amd_gpio_remove(struct platform_device *pdev) gpiochip_remove(&gpio_dev->gc); acpi_unregister_wakeup_handler(amd_gpio_check_wake, gpio_dev); + acpi_unregister_lps0_dev(&pinctrl_amd_s2idle_dev_ops); } #ifdef CONFIG_ACPI