Re: [PATCH 1/2] gpio: tegra186: Implement system suspend/resume support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 10/2/19 7:45 AM, Thierry Reding wrote:
From: Thierry Reding <treding@xxxxxxxxxx>

Backup GPIO control registers on suspend and restore them on resume to
ensure that the GPIOs' configuration remains the same across suspend and
resume.

Signed-off-by: Thierry Reding <treding@xxxxxxxxxx>
---
  drivers/gpio/gpio-tegra186.c | 51 ++++++++++++++++++++++++++++++++++++
  1 file changed, 51 insertions(+)

diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c
index a9058fda187e..3ded6ba2f997 100644
--- a/drivers/gpio/gpio-tegra186.c
+++ b/drivers/gpio/gpio-tegra186.c
@@ -64,6 +64,12 @@ struct tegra_gpio {
  	const struct tegra_gpio_soc *soc;
void __iomem *base;
+
+	struct tegra_gpio_context {
+		u32 value;
+		u32 control;
+		u32 config;
+	} *context;
  };
static const struct tegra_gpio_port *
@@ -455,6 +461,11 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
  	for (i = 0; i < gpio->soc->num_ports; i++)
  		gpio->gpio.ngpio += gpio->soc->ports[i].pins;
+ gpio->context = devm_kmalloc_array(gpio->gpio.parent, gpio->gpio.ngpio,
+					   sizeof(*gpio->context), GFP_KERNEL);
+	if (!gpio->context)
+		return -ENOMEM;
+
  	names = devm_kcalloc(gpio->gpio.parent, gpio->gpio.ngpio,
  			     sizeof(*names), GFP_KERNEL);
  	if (!names)
@@ -526,6 +537,45 @@ static int tegra186_gpio_remove(struct platform_device *pdev)
  	return 0;
  }
+static int tegra186_gpio_suspend(struct device *dev)
+{
+	struct tegra_gpio *gpio = dev_get_drvdata(dev);
+	unsigned int i;
+
+	for (i = 0; i < gpio->gpio.ngpio; i++) {
+		struct tegra_gpio_context *context = &gpio->context[i];
+		void __iomem *base = tegra186_gpio_get_base(gpio, i);
+
+		context->config = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);
+		context->control = readl(base + TEGRA186_GPIO_OUTPUT_CONTROL);
+		context->value = readl(base + TEGRA186_GPIO_OUTPUT_VALUE);
+	}
+
+	return 0;
+}
+
+static int tegra186_gpio_resume(struct device *dev)
+{
+	struct tegra_gpio *gpio = dev_get_drvdata(dev);
+	unsigned int i;
+
+	for (i = 0; i < gpio->gpio.ngpio; i++) {
+		struct tegra_gpio_context *context = &gpio->context[i];
+		void __iomem *base = tegra186_gpio_get_base(gpio, i);
+
+		writel(context->value, base + TEGRA186_GPIO_OUTPUT_VALUE);
+		writel(context->control, base + TEGRA186_GPIO_OUTPUT_CONTROL);
+		writel(context->config, base + TEGRA186_GPIO_ENABLE_CONFIG);
+	}
+
+	return 0;
+}
+
+static const struct dev_pm_ops tegra186_gpio_pm = {
+	.suspend_late = tegra186_gpio_suspend,
+	.resume_early = tegra186_gpio_resume,
+};
+
  #define TEGRA186_MAIN_GPIO_PORT(port, base, count, controller)	\
  	[TEGRA186_MAIN_GPIO_PORT_##port] = {			\
  		.name = #port,					\
@@ -680,6 +730,7 @@ static struct platform_driver tegra186_gpio_driver = {
  	.driver = {
  		.name = "tegra186-gpio",
  		.of_match_table = tegra186_gpio_of_match,
+		.pm = &tegra186_gpio_pm,
  	},
  	.probe = tegra186_gpio_probe,
  	.remove = tegra186_gpio_remove,


I see jetson Xavier RTC wakeup test fail with this patch. It no longer reaches the UART shell after suspend exit. Jetson-TX2 works fine with this patch. There seems to be some hang on Xavier.


-regards,
 Bitan






[Index of Archives]     [ARM Kernel]     [Linux ARM]     [Linux ARM MSM]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux