All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dmitry Osipenko <dmitry.osipenko@collabora.com>
To: "Thierry Reding" <thierry.reding@gmail.com>,
	"Jonathan Hunter" <jonathanh@nvidia.com>,
	"Russell King" <linux@armlinux.org.uk>,
	"Catalin Marinas" <catalin.marinas@arm.com>,
	"Will Deacon" <will@kernel.org>, "Guo Ren" <guoren@kernel.org>,
	"Geert Uytterhoeven" <geert@linux-m68k.org>,
	"Greg Ungerer" <gerg@linux-m68k.org>,
	"Joshua Thompson" <funaho@jurai.org>,
	"Thomas Bogendoerfer" <tsbogend@alpha.franken.de>,
	"Sebastian Reichel" <sre@kernel.org>,
	"Linus Walleij" <linus.walleij@linaro.org>,
	"Philipp Zabel" <p.zabel@pengutronix.de>,
	"Greentime Hu" <green.hu@gmail.com>,
	"Vincent Chen" <deanbo422@gmail.com>,
	"James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>,
	"Helge Deller" <deller@gmx.de>,
	"Michael Ellerman" <mpe@ellerman.id.au>,
	"Benjamin Herrenschmidt" <benh@kernel.crashing.org>,
	"Paul Mackerras" <paulus@samba.org>,
	"Paul Walmsley" <paul.walmsley@sifive.com>,
	"Palmer Dabbelt" <palmer@dabbelt.com>,
	"Albert Ou" <aou@eecs.berkeley.edu>,
	"Yoshinori Sato" <ysato@users.sourceforge.jp>,
	"Rich Felker" <dalias@libc.org>,
	"Thomas Gleixner" <tglx@linutronix.de>,
	"Ingo Molnar" <mingo@redhat.com>,
	"Borislav Petkov" <bp@alien8.de>,
	"Dave Hansen" <dave.hansen@linux.intel.com>,
	x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>,
	"Boris Ostrovsky" <boris.ostrovsky@oracle.com>,
	"Juergen Gross" <jgross@suse.com>,
	"Stefano Stabellini" <sstabellini@kernel.org>,
	"Rafael J. Wysocki" <rafael@kernel.org>,
	"Len Brown" <lenb@kernel.org>,
	"Santosh Shilimkar" <ssantosh@kernel.org>,
	"Krzysztof Kozlowski" <krzk@kernel.org>,
	"Liam Girdwood" <lgirdwood@gmail.com>,
	"Mark Brown" <broonie@kernel.org>, "Pavel Machek" <pavel@ucw.cz>,
	"Lee Jones" <lee.jones@linaro.org>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	"Guenter Roeck" <linux@roeck-us.net>,
	"Daniel Lezcano" <daniel.lezcano@linaro.org>,
	"Andy Shevchenko" <andriy.shevchenko@linux.intel.com>,
	"Ulf Hansson" <ulf.hansson@linaro.org>,
	"Michał Mirosław" <mirq-linux@rere.qmqm.pl>
Cc: linux-kernel@vger.kernel.org, linux-csky@vger.kernel.org,
	linux-ia64@vger.kernel.org, linux-m68k@lists.linux-m68k.org,
	linux-mips@vger.kernel.org, linux-parisc@vger.kernel.org,
	linux-riscv@lists.infradead.org, linux-sh@vger.kernel.org,
	xen-devel@lists.xenproject.org, linux-acpi@vger.kernel.org,
	linux-pm@vger.kernel.org, linux-tegra@vger.kernel.org
Subject: [PATCH v8 25/27] soc/tegra: pmc: Use sys-off handler API to power off Nexus 7 properly
Date: Tue, 10 May 2022 02:32:33 +0300	[thread overview]
Message-ID: <20220509233235.995021-26-dmitry.osipenko@collabora.com> (raw)
In-Reply-To: <20220509233235.995021-1-dmitry.osipenko@collabora.com>

Nexus 7 Android tablet can be turned off using a special bootloader
command which is conveyed to bootloader by putting magic value into the
special scratch register and then rebooting normally. This power-off
method should be invoked if USB cable is connected. Bootloader then will
display battery status and power off the device. This behaviour is
borrowed from downstream kernel and matches user expectations, otherwise
it looks like device got hung during power-off and it may wake up on
USB disconnect.

Switch PMC driver to sys-off handler API, which provides drivers with
chained power-off callbacks functionality that is required for powering-off
devices properly. It also brings resource-managed API for the restart
handler registration that makes PMC driver code cleaner.

Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
---
 drivers/soc/tegra/pmc.c | 87 +++++++++++++++++++++++++++++------------
 1 file changed, 62 insertions(+), 25 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index c77ecf61818b..5611d14d3ba2 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -39,6 +39,7 @@
 #include <linux/platform_device.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_opp.h>
+#include <linux/power_supply.h>
 #include <linux/reboot.h>
 #include <linux/regmap.h>
 #include <linux/reset.h>
@@ -108,6 +109,7 @@
 #define PMC_USB_DEBOUNCE_DEL		0xec
 #define PMC_USB_AO			0xf0
 
+#define PMC_SCRATCH37			0x130
 #define PMC_SCRATCH41			0x140
 
 #define PMC_WAKE2_MASK			0x160
@@ -1101,8 +1103,7 @@ static struct notifier_block tegra_pmc_reboot_notifier = {
 	.notifier_call = tegra_pmc_reboot_notify,
 };
 
-static int tegra_pmc_restart_notify(struct notifier_block *this,
-				    unsigned long action, void *data)
+static void tegra_pmc_restart(void)
 {
 	u32 value;
 
@@ -1110,14 +1111,31 @@ static int tegra_pmc_restart_notify(struct notifier_block *this,
 	value = tegra_pmc_readl(pmc, PMC_CNTRL);
 	value |= PMC_CNTRL_MAIN_RST;
 	tegra_pmc_writel(pmc, value, PMC_CNTRL);
+}
+
+static int tegra_pmc_restart_handler(struct sys_off_data *data)
+{
+	tegra_pmc_restart();
 
 	return NOTIFY_DONE;
 }
 
-static struct notifier_block tegra_pmc_restart_handler = {
-	.notifier_call = tegra_pmc_restart_notify,
-	.priority = 128,
-};
+static int tegra_pmc_power_off_handler(struct sys_off_data *data)
+{
+	/*
+	 * Reboot Nexus 7 into special bootloader mode if USB cable is
+	 * connected in order to display battery status and power off.
+	 */
+	if (of_machine_is_compatible("asus,grouper") &&
+	    power_supply_is_system_supplied()) {
+		const u32 go_to_charger_mode = 0xa5a55a5a;
+
+		tegra_pmc_writel(pmc, go_to_charger_mode, PMC_SCRATCH37);
+		tegra_pmc_restart();
+	}
+
+	return NOTIFY_DONE;
+}
 
 static int powergate_show(struct seq_file *s, void *data)
 {
@@ -2879,6 +2897,42 @@ static int tegra_pmc_probe(struct platform_device *pdev)
 		pmc->clk = NULL;
 	}
 
+	/*
+	 * PMC should be last resort for restarting since it soft-resets
+	 * CPU without resetting everything else.
+	 */
+	err = devm_register_reboot_notifier(&pdev->dev,
+					    &tegra_pmc_reboot_notifier);
+	if (err) {
+		dev_err(&pdev->dev, "unable to register reboot notifier, %d\n",
+			err);
+		return err;
+	}
+
+	err = devm_register_sys_off_handler(&pdev->dev,
+					    SYS_OFF_MODE_RESTART,
+					    SYS_OFF_PRIO_LOW,
+					    tegra_pmc_restart_handler, NULL);
+	if (err) {
+		dev_err(&pdev->dev, "failed to register sys-off handler: %d\n",
+			err);
+		return err;
+	}
+
+	/*
+	 * PMC should be primary power-off method if it soft-resets CPU,
+	 * asking bootloader to shutdown hardware.
+	 */
+	err = devm_register_sys_off_handler(&pdev->dev,
+					    SYS_OFF_MODE_POWER_OFF,
+					    SYS_OFF_PRIO_FIRMWARE,
+					    tegra_pmc_power_off_handler, NULL);
+	if (err) {
+		dev_err(&pdev->dev, "failed to register sys-off handler: %d\n",
+			err);
+		return err;
+	}
+
 	/*
 	 * PCLK clock rate can't be retrieved using CLK API because it
 	 * causes lockup if CPU enters LP2 idle state from some other
@@ -2910,28 +2964,13 @@ static int tegra_pmc_probe(struct platform_device *pdev)
 			goto cleanup_sysfs;
 	}
 
-	err = devm_register_reboot_notifier(&pdev->dev,
-					    &tegra_pmc_reboot_notifier);
-	if (err) {
-		dev_err(&pdev->dev, "unable to register reboot notifier, %d\n",
-			err);
-		goto cleanup_debugfs;
-	}
-
-	err = register_restart_handler(&tegra_pmc_restart_handler);
-	if (err) {
-		dev_err(&pdev->dev, "unable to register restart handler, %d\n",
-			err);
-		goto cleanup_debugfs;
-	}
-
 	err = tegra_pmc_pinctrl_init(pmc);
 	if (err)
-		goto cleanup_restart_handler;
+		goto cleanup_debugfs;
 
 	err = tegra_pmc_regmap_init(pmc);
 	if (err < 0)
-		goto cleanup_restart_handler;
+		goto cleanup_debugfs;
 
 	err = tegra_powergate_init(pmc, pdev->dev.of_node);
 	if (err < 0)
@@ -2954,8 +2993,6 @@ static int tegra_pmc_probe(struct platform_device *pdev)
 
 cleanup_powergates:
 	tegra_powergate_remove_all(pdev->dev.of_node);
-cleanup_restart_handler:
-	unregister_restart_handler(&tegra_pmc_restart_handler);
 cleanup_debugfs:
 	debugfs_remove(pmc->debugfs);
 cleanup_sysfs:
-- 
2.35.1


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

WARNING: multiple messages have this Message-ID (diff)
From: Dmitry Osipenko <dmitry.osipenko@collabora.com>
To: "Thierry Reding" <thierry.reding@gmail.com>,
	"Jonathan Hunter" <jonathanh@nvidia.com>,
	"Russell King" <linux@armlinux.org.uk>,
	"Catalin Marinas" <catalin.marinas@arm.com>,
	"Will Deacon" <will@kernel.org>, "Guo Ren" <guoren@kernel.org>,
	"Geert Uytterhoeven" <geert@linux-m68k.org>,
	"Greg Ungerer" <gerg@linux-m68k.org>,
	"Joshua Thompson" <funaho@jurai.org>,
	"Thomas Bogendoerfer" <tsbogend@alpha.franken.de>,
	"Sebastian Reichel" <sre@kernel.org>,
	"Linus Walleij" <linus.walleij@linaro.org>,
	"Philipp Zabel" <p.zabel@pengutronix.de>,
	"Greentime Hu" <green.hu@gmail.com>,
	"Vincent Chen" <deanbo422@gmail.com>,
	"James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>,
	"Helge Deller" <deller@gmx.de>,
	"Michael Ellerman" <mpe@ellerman.id.au>,
	"Benjamin Herrenschmidt" <benh@kernel.crashing.org>,
	"Paul Mackerras" <paulus@samba.org>,
	"Paul Walmsley" <paul.walmsley@sifive.com>,
	"Palmer Dabbelt" <palmer@dabbelt.com>,
	"Albert Ou" <aou@eecs.berkeley.edu>,
	"Yoshinori Sato" <ysato@users.sourceforge.jp>,
	"Rich Felker" <dalias@libc.org>,
	"Thomas Gleixner" <tglx@linutronix.de>,
	"Ingo Molnar" <mingo@redhat.com>,
	"Borislav Petkov" <bp@alien8.de>,
	"Dave Hansen" <dave.hansen@linux.intel.com>,
	x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>,
	"Boris Ostrovsky" <boris.ostrovsky@oracle.com>,
	"Juergen Gross" <jgross@suse.com>,
	"Stefano Stabellini" <sstabellini@kernel.org>,
	"Rafael J. Wysocki" <rafael@kernel.org>,
	"Len Brown" <lenb@kernel.org>,
	"Santosh Shilimkar" <ssantosh@kernel.org>,
	"Krzysztof Kozlowski" <krzk@kernel.org>,
	"Liam Girdwood" <lgirdwood@gmail.com>,
	"Mark Brown" <broonie@kernel.org>, "Pavel Machek" <pavel@ucw.cz>,
	"Lee Jones" <lee.jones@linaro.org>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	"Guenter Roeck" <linux@roeck-us.net>,
	"Daniel Lezcano" <daniel.lezcano@linaro.org>,
	"Andy Shevchenko" <andriy.shevchenko@linux.intel.com>,
	"Ulf Hansson" <ulf.hansson@linaro.org>,
	"Michał Mirosław" <mirq-linux@rere.qmqm.pl>
Cc: linux-kernel@vger.kernel.org, linux-csky@vger.kernel.org,
	linux-ia64@vger.kernel.org, linux-m68k@lists.linux-m68k.org,
	linux-mips@vger.kernel.org, linux-parisc@vger.kernel.org,
	linux-riscv@lists.infradead.org, linux-sh@vger.kernel.org,
	xen-devel@lists.xenproject.org, linux-acpi@vger.kernel.org,
	linux-pm@vger.kernel.org, linux-tegra@vger.kernel.org
Subject: [PATCH v8 25/27] soc/tegra: pmc: Use sys-off handler API to power off Nexus 7 properly
Date: Tue, 10 May 2022 02:32:33 +0300	[thread overview]
Message-ID: <20220509233235.995021-26-dmitry.osipenko@collabora.com> (raw)
In-Reply-To: <20220509233235.995021-1-dmitry.osipenko@collabora.com>

Nexus 7 Android tablet can be turned off using a special bootloader
command which is conveyed to bootloader by putting magic value into the
special scratch register and then rebooting normally. This power-off
method should be invoked if USB cable is connected. Bootloader then will
display battery status and power off the device. This behaviour is
borrowed from downstream kernel and matches user expectations, otherwise
it looks like device got hung during power-off and it may wake up on
USB disconnect.

Switch PMC driver to sys-off handler API, which provides drivers with
chained power-off callbacks functionality that is required for powering-off
devices properly. It also brings resource-managed API for the restart
handler registration that makes PMC driver code cleaner.

Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
---
 drivers/soc/tegra/pmc.c | 87 +++++++++++++++++++++++++++++------------
 1 file changed, 62 insertions(+), 25 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index c77ecf61818b..5611d14d3ba2 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -39,6 +39,7 @@
 #include <linux/platform_device.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_opp.h>
+#include <linux/power_supply.h>
 #include <linux/reboot.h>
 #include <linux/regmap.h>
 #include <linux/reset.h>
@@ -108,6 +109,7 @@
 #define PMC_USB_DEBOUNCE_DEL		0xec
 #define PMC_USB_AO			0xf0
 
+#define PMC_SCRATCH37			0x130
 #define PMC_SCRATCH41			0x140
 
 #define PMC_WAKE2_MASK			0x160
@@ -1101,8 +1103,7 @@ static struct notifier_block tegra_pmc_reboot_notifier = {
 	.notifier_call = tegra_pmc_reboot_notify,
 };
 
-static int tegra_pmc_restart_notify(struct notifier_block *this,
-				    unsigned long action, void *data)
+static void tegra_pmc_restart(void)
 {
 	u32 value;
 
@@ -1110,14 +1111,31 @@ static int tegra_pmc_restart_notify(struct notifier_block *this,
 	value = tegra_pmc_readl(pmc, PMC_CNTRL);
 	value |= PMC_CNTRL_MAIN_RST;
 	tegra_pmc_writel(pmc, value, PMC_CNTRL);
+}
+
+static int tegra_pmc_restart_handler(struct sys_off_data *data)
+{
+	tegra_pmc_restart();
 
 	return NOTIFY_DONE;
 }
 
-static struct notifier_block tegra_pmc_restart_handler = {
-	.notifier_call = tegra_pmc_restart_notify,
-	.priority = 128,
-};
+static int tegra_pmc_power_off_handler(struct sys_off_data *data)
+{
+	/*
+	 * Reboot Nexus 7 into special bootloader mode if USB cable is
+	 * connected in order to display battery status and power off.
+	 */
+	if (of_machine_is_compatible("asus,grouper") &&
+	    power_supply_is_system_supplied()) {
+		const u32 go_to_charger_mode = 0xa5a55a5a;
+
+		tegra_pmc_writel(pmc, go_to_charger_mode, PMC_SCRATCH37);
+		tegra_pmc_restart();
+	}
+
+	return NOTIFY_DONE;
+}
 
 static int powergate_show(struct seq_file *s, void *data)
 {
@@ -2879,6 +2897,42 @@ static int tegra_pmc_probe(struct platform_device *pdev)
 		pmc->clk = NULL;
 	}
 
+	/*
+	 * PMC should be last resort for restarting since it soft-resets
+	 * CPU without resetting everything else.
+	 */
+	err = devm_register_reboot_notifier(&pdev->dev,
+					    &tegra_pmc_reboot_notifier);
+	if (err) {
+		dev_err(&pdev->dev, "unable to register reboot notifier, %d\n",
+			err);
+		return err;
+	}
+
+	err = devm_register_sys_off_handler(&pdev->dev,
+					    SYS_OFF_MODE_RESTART,
+					    SYS_OFF_PRIO_LOW,
+					    tegra_pmc_restart_handler, NULL);
+	if (err) {
+		dev_err(&pdev->dev, "failed to register sys-off handler: %d\n",
+			err);
+		return err;
+	}
+
+	/*
+	 * PMC should be primary power-off method if it soft-resets CPU,
+	 * asking bootloader to shutdown hardware.
+	 */
+	err = devm_register_sys_off_handler(&pdev->dev,
+					    SYS_OFF_MODE_POWER_OFF,
+					    SYS_OFF_PRIO_FIRMWARE,
+					    tegra_pmc_power_off_handler, NULL);
+	if (err) {
+		dev_err(&pdev->dev, "failed to register sys-off handler: %d\n",
+			err);
+		return err;
+	}
+
 	/*
 	 * PCLK clock rate can't be retrieved using CLK API because it
 	 * causes lockup if CPU enters LP2 idle state from some other
@@ -2910,28 +2964,13 @@ static int tegra_pmc_probe(struct platform_device *pdev)
 			goto cleanup_sysfs;
 	}
 
-	err = devm_register_reboot_notifier(&pdev->dev,
-					    &tegra_pmc_reboot_notifier);
-	if (err) {
-		dev_err(&pdev->dev, "unable to register reboot notifier, %d\n",
-			err);
-		goto cleanup_debugfs;
-	}
-
-	err = register_restart_handler(&tegra_pmc_restart_handler);
-	if (err) {
-		dev_err(&pdev->dev, "unable to register restart handler, %d\n",
-			err);
-		goto cleanup_debugfs;
-	}
-
 	err = tegra_pmc_pinctrl_init(pmc);
 	if (err)
-		goto cleanup_restart_handler;
+		goto cleanup_debugfs;
 
 	err = tegra_pmc_regmap_init(pmc);
 	if (err < 0)
-		goto cleanup_restart_handler;
+		goto cleanup_debugfs;
 
 	err = tegra_powergate_init(pmc, pdev->dev.of_node);
 	if (err < 0)
@@ -2954,8 +2993,6 @@ static int tegra_pmc_probe(struct platform_device *pdev)
 
 cleanup_powergates:
 	tegra_powergate_remove_all(pdev->dev.of_node);
-cleanup_restart_handler:
-	unregister_restart_handler(&tegra_pmc_restart_handler);
 cleanup_debugfs:
 	debugfs_remove(pmc->debugfs);
 cleanup_sysfs:
-- 
2.35.1


WARNING: multiple messages have this Message-ID (diff)
From: Dmitry Osipenko <dmitry.osipenko@collabora.com>
To: "Thierry Reding" <thierry.reding@gmail.com>,
	"Jonathan Hunter" <jonathanh@nvidia.com>,
	"Russell King" <linux@armlinux.org.uk>,
	"Catalin Marinas" <catalin.marinas@arm.com>,
	"Will Deacon" <will@kernel.org>, "Guo Ren" <guoren@kernel.org>,
	"Geert Uytterhoeven" <geert@linux-m68k.org>,
	"Greg Ungerer" <gerg@linux-m68k.org>,
	"Joshua Thompson" <funaho@jurai.org>,
	"Thomas Bogendoerfer" <tsbogend@alpha.franken.de>,
	"Sebastian Reichel" <sre@kernel.org>,
	"Linus Walleij" <linus.walleij@linaro.org>,
	"Philipp Zabel" <p.zabel@pengutronix.de>,
	"Greentime Hu" <green.hu@gmail.com>,
	"Vincent Chen" <deanbo422@gmail.com>,
	"James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>,
	"Helge Deller" <deller@gmx.de>,
	"Michael Ellerman" <mpe@ellerman.id.au>,
	"Benjamin Herrenschmidt" <benh@kernel.crashing.org>,
	"Paul Mackerras" <paulus@samba.org>,
	"Paul Walmsley" <paul.walmsley@sifive.com>,
	"Palmer Dabbelt" <palmer@dabbelt.com>,
	"Albert Ou" <aou@eecs.berkeley.edu>,
	"Yoshinori Sato" <ysato@users.sourceforge.jp>,
	"Rich Felker" <dalias@libc.org>,
	"Thomas Gleixner" <tglx@linutronix.de>,
	"Ingo Molnar" <mingo@redhat.com>,
	"Borislav Petkov" <bp@alien8.de>,
	"Dave Hansen" <dave.hansen@linux.intel.com>,
	x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>,
	"Boris Ostrovsky" <boris.ostrovsky@oracle.com>,
	"Juergen Gross" <jgross@suse.com>,
	"Stefano Stabellini" <sstabellini@kernel.org>,
	"Rafael J. Wysocki" <rafael@kernel.org>,
	"Len Brown" <lenb@kernel.org>,
	"Santosh Shilimkar" <ssantosh@kernel.org>,
	"Krzysztof Kozlowski" <krzk@kernel.org>,
	"Liam Girdwood" <lgirdwood@gmail.com>,
	"Mark Brown" <broonie@kernel.org>, "Pavel Machek" <pavel@ucw.cz>,
	"Lee Jones" <lee.jones@linaro.org>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	"Guenter Roeck" <linux@roeck-us.net>,
	"Daniel Lezcano" <daniel.lezcano@linaro.org>,
	"Andy Shevchenko" <andriy.shevchenko@linux.intel.com>,
	"Ulf Hansson" <ulf.hansson@linaro.org>,
	"Michał Mirosław" <mirq-linux@rere.qmqm.pl>
Cc: linux-kernel@vger.kernel.org, linux-csky@vger.kernel.org,
	linux-ia64@vger.kernel.org, linux-m68k@lists.linux-m68k.org,
	linux-mips@vger.kernel.org, linux-parisc@vger.kernel.org,
	linux-riscv@lists.infradead.org, linux-sh@vger.kernel.org,
	xen-devel@lists.xenproject.org, linux-acpi@vger.kernel.org,
	linux-pm@vger.kernel.org, linux-tegra@vger.kernel.org
Subject: [PATCH v8 25/27] soc/tegra: pmc: Use sys-off handler API to power off Nexus 7 properly
Date: Mon, 09 May 2022 23:32:33 +0000	[thread overview]
Message-ID: <20220509233235.995021-26-dmitry.osipenko@collabora.com> (raw)
In-Reply-To: <20220509233235.995021-1-dmitry.osipenko@collabora.com>

Nexus 7 Android tablet can be turned off using a special bootloader
command which is conveyed to bootloader by putting magic value into the
special scratch register and then rebooting normally. This power-off
method should be invoked if USB cable is connected. Bootloader then will
display battery status and power off the device. This behaviour is
borrowed from downstream kernel and matches user expectations, otherwise
it looks like device got hung during power-off and it may wake up on
USB disconnect.

Switch PMC driver to sys-off handler API, which provides drivers with
chained power-off callbacks functionality that is required for powering-off
devices properly. It also brings resource-managed API for the restart
handler registration that makes PMC driver code cleaner.

Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
---
 drivers/soc/tegra/pmc.c | 87 +++++++++++++++++++++++++++++------------
 1 file changed, 62 insertions(+), 25 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index c77ecf61818b..5611d14d3ba2 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -39,6 +39,7 @@
 #include <linux/platform_device.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_opp.h>
+#include <linux/power_supply.h>
 #include <linux/reboot.h>
 #include <linux/regmap.h>
 #include <linux/reset.h>
@@ -108,6 +109,7 @@
 #define PMC_USB_DEBOUNCE_DEL		0xec
 #define PMC_USB_AO			0xf0
 
+#define PMC_SCRATCH37			0x130
 #define PMC_SCRATCH41			0x140
 
 #define PMC_WAKE2_MASK			0x160
@@ -1101,8 +1103,7 @@ static struct notifier_block tegra_pmc_reboot_notifier = {
 	.notifier_call = tegra_pmc_reboot_notify,
 };
 
-static int tegra_pmc_restart_notify(struct notifier_block *this,
-				    unsigned long action, void *data)
+static void tegra_pmc_restart(void)
 {
 	u32 value;
 
@@ -1110,14 +1111,31 @@ static int tegra_pmc_restart_notify(struct notifier_block *this,
 	value = tegra_pmc_readl(pmc, PMC_CNTRL);
 	value |= PMC_CNTRL_MAIN_RST;
 	tegra_pmc_writel(pmc, value, PMC_CNTRL);
+}
+
+static int tegra_pmc_restart_handler(struct sys_off_data *data)
+{
+	tegra_pmc_restart();
 
 	return NOTIFY_DONE;
 }
 
-static struct notifier_block tegra_pmc_restart_handler = {
-	.notifier_call = tegra_pmc_restart_notify,
-	.priority = 128,
-};
+static int tegra_pmc_power_off_handler(struct sys_off_data *data)
+{
+	/*
+	 * Reboot Nexus 7 into special bootloader mode if USB cable is
+	 * connected in order to display battery status and power off.
+	 */
+	if (of_machine_is_compatible("asus,grouper") &&
+	    power_supply_is_system_supplied()) {
+		const u32 go_to_charger_mode = 0xa5a55a5a;
+
+		tegra_pmc_writel(pmc, go_to_charger_mode, PMC_SCRATCH37);
+		tegra_pmc_restart();
+	}
+
+	return NOTIFY_DONE;
+}
 
 static int powergate_show(struct seq_file *s, void *data)
 {
@@ -2879,6 +2897,42 @@ static int tegra_pmc_probe(struct platform_device *pdev)
 		pmc->clk = NULL;
 	}
 
+	/*
+	 * PMC should be last resort for restarting since it soft-resets
+	 * CPU without resetting everything else.
+	 */
+	err = devm_register_reboot_notifier(&pdev->dev,
+					    &tegra_pmc_reboot_notifier);
+	if (err) {
+		dev_err(&pdev->dev, "unable to register reboot notifier, %d\n",
+			err);
+		return err;
+	}
+
+	err = devm_register_sys_off_handler(&pdev->dev,
+					    SYS_OFF_MODE_RESTART,
+					    SYS_OFF_PRIO_LOW,
+					    tegra_pmc_restart_handler, NULL);
+	if (err) {
+		dev_err(&pdev->dev, "failed to register sys-off handler: %d\n",
+			err);
+		return err;
+	}
+
+	/*
+	 * PMC should be primary power-off method if it soft-resets CPU,
+	 * asking bootloader to shutdown hardware.
+	 */
+	err = devm_register_sys_off_handler(&pdev->dev,
+					    SYS_OFF_MODE_POWER_OFF,
+					    SYS_OFF_PRIO_FIRMWARE,
+					    tegra_pmc_power_off_handler, NULL);
+	if (err) {
+		dev_err(&pdev->dev, "failed to register sys-off handler: %d\n",
+			err);
+		return err;
+	}
+
 	/*
 	 * PCLK clock rate can't be retrieved using CLK API because it
 	 * causes lockup if CPU enters LP2 idle state from some other
@@ -2910,28 +2964,13 @@ static int tegra_pmc_probe(struct platform_device *pdev)
 			goto cleanup_sysfs;
 	}
 
-	err = devm_register_reboot_notifier(&pdev->dev,
-					    &tegra_pmc_reboot_notifier);
-	if (err) {
-		dev_err(&pdev->dev, "unable to register reboot notifier, %d\n",
-			err);
-		goto cleanup_debugfs;
-	}
-
-	err = register_restart_handler(&tegra_pmc_restart_handler);
-	if (err) {
-		dev_err(&pdev->dev, "unable to register restart handler, %d\n",
-			err);
-		goto cleanup_debugfs;
-	}
-
 	err = tegra_pmc_pinctrl_init(pmc);
 	if (err)
-		goto cleanup_restart_handler;
+		goto cleanup_debugfs;
 
 	err = tegra_pmc_regmap_init(pmc);
 	if (err < 0)
-		goto cleanup_restart_handler;
+		goto cleanup_debugfs;
 
 	err = tegra_powergate_init(pmc, pdev->dev.of_node);
 	if (err < 0)
@@ -2954,8 +2993,6 @@ static int tegra_pmc_probe(struct platform_device *pdev)
 
 cleanup_powergates:
 	tegra_powergate_remove_all(pdev->dev.of_node);
-cleanup_restart_handler:
-	unregister_restart_handler(&tegra_pmc_restart_handler);
 cleanup_debugfs:
 	debugfs_remove(pmc->debugfs);
 cleanup_sysfs:
-- 
2.35.1

  parent reply	other threads:[~2022-05-09 23:35 UTC|newest]

Thread overview: 120+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-09 23:32 [PATCH v8 00/27] Introduce power-off+restart call chain API Dmitry Osipenko
2022-05-09 23:32 ` Dmitry Osipenko
2022-05-09 23:32 ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 01/27] notifier: Add atomic_notifier_call_chain_is_empty() Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-10 18:14   ` Rafael J. Wysocki
2022-05-10 18:14     ` Rafael J. Wysocki
2022-05-10 18:14     ` Rafael J. Wysocki
2022-05-11 10:12     ` Dmitry Osipenko
2022-05-11 10:12       ` Dmitry Osipenko
2022-05-11 10:12       ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 02/27] notifier: Add blocking/atomic_notifier_chain_register_unique_prio() Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 03/27] kernel/reboot: Introduce sys-off handler API Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 04/27] kernel/reboot: Wrap legacy power-off callbacks into sys-off handlers Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 05/27] kernel/reboot: Add do_kernel_power_off() Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 06/27] kernel/reboot: Add stub for pm_power_off Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 07/27] kernel/reboot: Add kernel_can_power_off() Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-24 13:14   ` Geert Uytterhoeven
2022-05-24 13:14     ` Geert Uytterhoeven
2022-05-24 13:14     ` Geert Uytterhoeven
2022-05-24 13:41     ` Dmitry Osipenko
2022-05-24 13:41       ` Dmitry Osipenko
2022-05-24 13:41       ` Dmitry Osipenko
2022-05-24 15:03       ` Geert Uytterhoeven
2022-05-24 15:03         ` Geert Uytterhoeven
2022-05-24 15:03         ` Geert Uytterhoeven
2022-05-24 20:16         ` Dmitry Osipenko
2022-05-24 20:16           ` Dmitry Osipenko
2022-05-24 20:16           ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 08/27] kernel/reboot: Add register_platform_power_off() Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 09/27] ARM: Use do_kernel_power_off() Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 10/27] csky: " Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 11/27] riscv: " Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 12/27] arm64: " Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 13/27] parisc: " Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 14/27] xen/x86: " Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 15/27] powerpc: " Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 16/27] m68k: Switch to new sys-off handler API Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-31 19:04   ` Geert Uytterhoeven
2022-05-31 19:04     ` Geert Uytterhoeven
2022-05-31 19:04     ` Geert Uytterhoeven
2022-05-31 21:24     ` Dmitry Osipenko
2022-05-31 21:24       ` Dmitry Osipenko
2022-05-31 21:24       ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 17/27] sh: Use do_kernel_power_off() Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 18/27] x86: " Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 19/27] ia64: " Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 20/27] mips: " Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 21/27] memory: emif: Use kernel_can_power_off() Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 22/27] ACPI: power: Switch to sys-off handler API Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 23/27] regulator: pfuze100: Use devm_register_sys_off_handler() Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 24/27] reboot: Remove pm_power_off_prepare() Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32 ` Dmitry Osipenko [this message]
2022-05-09 23:32   ` [PATCH v8 25/27] soc/tegra: pmc: Use sys-off handler API to power off Nexus 7 properly Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 26/27] kernel/reboot: Add devm_register_power_off_handler() Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32 ` [PATCH v8 27/27] kernel/reboot: Add devm_register_restart_handler() Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-09 23:32   ` Dmitry Osipenko
2022-05-18 14:46 ` [PATCH v8 00/27] Introduce power-off+restart call chain API Rafael J. Wysocki
2022-05-18 14:46   ` Rafael J. Wysocki
2022-05-18 14:46   ` Rafael J. Wysocki
2022-05-19 10:57   ` Dmitry Osipenko
2022-05-19 10:57     ` Dmitry Osipenko
2022-05-19 10:57     ` Dmitry Osipenko
2022-05-23 18:00   ` Geert Uytterhoeven
2022-05-23 18:00     ` Geert Uytterhoeven
2022-05-23 18:00     ` Geert Uytterhoeven
2022-05-24 13:43     ` Rafael J. Wysocki
2022-05-24 13:43       ` Rafael J. Wysocki
2022-05-24 13:43       ` Rafael J. Wysocki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220509233235.995021-26-dmitry.osipenko@collabora.com \
    --to=dmitry.osipenko@collabora.com \
    --cc=James.Bottomley@HansenPartnership.com \
    --cc=akpm@linux-foundation.org \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=aou@eecs.berkeley.edu \
    --cc=benh@kernel.crashing.org \
    --cc=boris.ostrovsky@oracle.com \
    --cc=bp@alien8.de \
    --cc=broonie@kernel.org \
    --cc=catalin.marinas@arm.com \
    --cc=dalias@libc.org \
    --cc=daniel.lezcano@linaro.org \
    --cc=dave.hansen@linux.intel.com \
    --cc=deanbo422@gmail.com \
    --cc=deller@gmx.de \
    --cc=funaho@jurai.org \
    --cc=geert@linux-m68k.org \
    --cc=gerg@linux-m68k.org \
    --cc=green.hu@gmail.com \
    --cc=guoren@kernel.org \
    --cc=hpa@zytor.com \
    --cc=jgross@suse.com \
    --cc=jonathanh@nvidia.com \
    --cc=krzk@kernel.org \
    --cc=lee.jones@linaro.org \
    --cc=lenb@kernel.org \
    --cc=lgirdwood@gmail.com \
    --cc=linus.walleij@linaro.org \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-csky@vger.kernel.org \
    --cc=linux-ia64@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-m68k@lists.linux-m68k.org \
    --cc=linux-mips@vger.kernel.org \
    --cc=linux-parisc@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=linux-riscv@lists.infradead.org \
    --cc=linux-sh@vger.kernel.org \
    --cc=linux-tegra@vger.kernel.org \
    --cc=linux@armlinux.org.uk \
    --cc=linux@roeck-us.net \
    --cc=mingo@redhat.com \
    --cc=mirq-linux@rere.qmqm.pl \
    --cc=mpe@ellerman.id.au \
    --cc=p.zabel@pengutronix.de \
    --cc=palmer@dabbelt.com \
    --cc=paul.walmsley@sifive.com \
    --cc=paulus@samba.org \
    --cc=pavel@ucw.cz \
    --cc=rafael@kernel.org \
    --cc=sre@kernel.org \
    --cc=ssantosh@kernel.org \
    --cc=sstabellini@kernel.org \
    --cc=tglx@linutronix.de \
    --cc=thierry.reding@gmail.com \
    --cc=tsbogend@alpha.franken.de \
    --cc=ulf.hansson@linaro.org \
    --cc=will@kernel.org \
    --cc=x86@kernel.org \
    --cc=xen-devel@lists.xenproject.org \
    --cc=ysato@users.sourceforge.jp \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.