pinctrl/amd: save pin registers over suspend/resume

The touchpad in the Asus laptop models X505BA/BP and X542BA/BP is
unresponsive after suspend/resume. The following error appears during
resume:

i2c_hid i2c-ELAN1300:00: failed to reset device.

The problem here is that i2c_hid does not notice the interrupt being
generated at this point, because the GPIO is no longer configured
for interrupts.

Fix this by saving pinctrl-amd pin registers during suspend and
restoring them at resume time.

Based on code from pinctrl-intel.

Cc: stable@vger.kernel.org
Signed-off-by: Daniel Drake <drake@endlessm.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

authored by

Daniel Drake and committed by
Linus Walleij
79d2c8be a9a1a483

+76
+75
drivers/pinctrl/pinctrl-amd.c
··· 36 36 #include <linux/pinctrl/pinconf.h> 37 37 #include <linux/pinctrl/pinconf-generic.h> 38 38 39 + #include "core.h" 39 40 #include "pinctrl-utils.h" 40 41 #include "pinctrl-amd.h" 41 42 ··· 726 725 .pin_config_group_set = amd_pinconf_group_set, 727 726 }; 728 727 728 + #ifdef CONFIG_PM_SLEEP 729 + static bool amd_gpio_should_save(struct amd_gpio *gpio_dev, unsigned int pin) 730 + { 731 + const struct pin_desc *pd = pin_desc_get(gpio_dev->pctrl, pin); 732 + 733 + if (!pd) 734 + return false; 735 + 736 + /* 737 + * Only restore the pin if it is actually in use by the kernel (or 738 + * by userspace). 739 + */ 740 + if (pd->mux_owner || pd->gpio_owner || 741 + gpiochip_line_is_irq(&gpio_dev->gc, pin)) 742 + return true; 743 + 744 + return false; 745 + } 746 + 747 + int amd_gpio_suspend(struct device *dev) 748 + { 749 + struct platform_device *pdev = to_platform_device(dev); 750 + struct amd_gpio *gpio_dev = platform_get_drvdata(pdev); 751 + struct pinctrl_desc *desc = gpio_dev->pctrl->desc; 752 + int i; 753 + 754 + for (i = 0; i < desc->npins; i++) { 755 + int pin = desc->pins[i].number; 756 + 757 + if (!amd_gpio_should_save(gpio_dev, pin)) 758 + continue; 759 + 760 + gpio_dev->saved_regs[i] = readl(gpio_dev->base + pin*4); 761 + } 762 + 763 + return 0; 764 + } 765 + 766 + int amd_gpio_resume(struct device *dev) 767 + { 768 + struct platform_device *pdev = to_platform_device(dev); 769 + struct amd_gpio *gpio_dev = platform_get_drvdata(pdev); 770 + struct pinctrl_desc *desc = gpio_dev->pctrl->desc; 771 + int i; 772 + 773 + for (i = 0; i < desc->npins; i++) { 774 + int pin = desc->pins[i].number; 775 + 776 + if (!amd_gpio_should_save(gpio_dev, pin)) 777 + continue; 778 + 779 + writel(gpio_dev->saved_regs[i], gpio_dev->base + pin*4); 780 + } 781 + 782 + return 0; 783 + } 784 + 785 + static const struct dev_pm_ops amd_gpio_pm_ops = { 786 + SET_LATE_SYSTEM_SLEEP_PM_OPS(amd_gpio_suspend, 787 + amd_gpio_resume) 788 + }; 789 + #endif 790 + 729 791 static struct pinctrl_desc amd_pinctrl_desc = { 730 792 .pins = kerncz_pins, 731 793 .npins = ARRAY_SIZE(kerncz_pins), ··· 827 763 dev_err(&pdev->dev, "Failed to get gpio IRQ: %d\n", irq_base); 828 764 return irq_base; 829 765 } 766 + 767 + #ifdef CONFIG_PM_SLEEP 768 + gpio_dev->saved_regs = devm_kcalloc(&pdev->dev, amd_pinctrl_desc.npins, 769 + sizeof(*gpio_dev->saved_regs), 770 + GFP_KERNEL); 771 + if (!gpio_dev->saved_regs) 772 + return -ENOMEM; 773 + #endif 830 774 831 775 gpio_dev->pdev = pdev; 832 776 gpio_dev->gc.direction_input = amd_gpio_direction_input; ··· 925 853 .driver = { 926 854 .name = "amd_gpio", 927 855 .acpi_match_table = ACPI_PTR(amd_gpio_acpi_match), 856 + #ifdef CONFIG_PM_SLEEP 857 + .pm = &amd_gpio_pm_ops, 858 + #endif 928 859 }, 929 860 .probe = amd_gpio_probe, 930 861 .remove = amd_gpio_remove,
+1
drivers/pinctrl/pinctrl-amd.h
··· 97 97 unsigned int hwbank_num; 98 98 struct resource *res; 99 99 struct platform_device *pdev; 100 + u32 *saved_regs; 100 101 }; 101 102 102 103 /* KERNCZ configuration*/