linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/4] power: reset: Add Gemini poweroff DT bindings
@ 2017-01-30 19:36 Linus Walleij
  2017-01-30 19:36 ` [PATCH 2/4] power: reset: Add a driver for the Gemini poweroff Linus Walleij
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Linus Walleij @ 2017-01-30 19:36 UTC (permalink / raw)
  To: linux-arm-kernel

This adds device tree bindings to the power management controller
in the Gemini SoC.

Cc: devicetree at vger.kernel.org
Cc: Janos Laube <janos.dev@gmail.com>
Cc: Paulius Zaleckas <paulius.zaleckas@gmail.com>
Cc: Hans Ulli Kroll <ulli.kroll@googlemail.com>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
Sebastian: please just merge this when your are pleased
with it. I will funnel the ARM parts through the ARM SoC tree.
---
 .../devicetree/bindings/power/reset/gemini-poweroff.txt | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/power/reset/gemini-poweroff.txt

diff --git a/Documentation/devicetree/bindings/power/reset/gemini-poweroff.txt b/Documentation/devicetree/bindings/power/reset/gemini-poweroff.txt
new file mode 100644
index 000000000000..7fec3e100214
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/reset/gemini-poweroff.txt
@@ -0,0 +1,17 @@
+* Device-Tree bindings for Cortina Systems Gemini Poweroff
+
+This is a special IP block in the Cortina Gemini SoC that only
+deals with different ways to power the system down.
+
+Required properties:
+- compatible: should be "cortina,gemini-power-controller"
+- reg: should contain the physical memory base and size
+- interrupts: should contain the power management interrupt
+
+Example:
+
+power-controller at 4b000000 {
+	compatible = "cortina,gemini-power-controller";
+	reg = <0x4b000000 0x100>;
+	interrupts = <26 IRQ_TYPE_EDGE_FALLING>;
+};
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/4] power: reset: Add a driver for the Gemini poweroff
  2017-01-30 19:36 [PATCH 1/4] power: reset: Add Gemini poweroff DT bindings Linus Walleij
@ 2017-01-30 19:36 ` Linus Walleij
  2017-01-30 19:36 ` [PATCH 3/4] ARM: gemini: select gemini poweroff Linus Walleij
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Linus Walleij @ 2017-01-30 19:36 UTC (permalink / raw)
  To: linux-arm-kernel

The Gemini (SL3516) SoC has a special power controller block
that only deal with shutting down the system.

If you do not register a driver and activate the block, the
power button on the systems utilizing this SoC will do an
uncontrolled power cut, which is why it is important to have
a special poweroff driver.

The most basic functionality is to just shut down the system
by writing a special bit in the control register after the
system has reached pm_poweroff.

It also handles the poweroff from a button or other sources:

When the poweroff button is pressed, or a signal is sent to
poweroff from an infrared remote control, or when the RTC
fires a special alarm (!) the system emits an interrupt.
At this point, Linux must acknowledge the interrupt and
proceed to do an orderly shutdown of the system.

After adding this driver, pressing the poweroff button gives
this dmesg:

root at gemini:/
root at gemini:/ gemini-poweroff 4b000000.power-controller:
poweroff button pressed

calling shutdown scripts..
setting /dev/rtc0 from system time
unmounting file systems...
umount: tmpfs busy - remounted read-only
umount: can't unmount /: Invalid argument
The system is going down NOW!
Sent SIGTERM to all processes
Sent SIGKILL to all processes
Requesting system poweroff
uhci_hcd 0000:00:09.1: HCRESET not completed yet!
uhci_hcd 0000:00:09.0: HCRESET not completed yet!
reboot: Power down
gemini-poweroff 4b000000.power-controller: Gemini power off

Cc: Janos Laube <janos.dev@gmail.com>
Cc: Paulius Zaleckas <paulius.zaleckas@gmail.com>
Cc: Hans Ulli Kroll <ulli.kroll@googlemail.com>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: linux-pm at vger.kernel.org
Cc: Sebastian Reichel <sre@kernel.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
Sebastian: please just merge this when your are pleased
with it. I will funnel the ARM parts through the ARM SoC tree.
---
 drivers/power/reset/Kconfig           |   9 ++
 drivers/power/reset/Makefile          |   1 +
 drivers/power/reset/gemini-poweroff.c | 160 ++++++++++++++++++++++++++++++++++
 3 files changed, 170 insertions(+)
 create mode 100644 drivers/power/reset/gemini-poweroff.c

diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index abeb77217a21..0d2c4183d0ff 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -67,6 +67,15 @@ config POWER_RESET_BRCMSTB
 	  Say Y here if you have a Broadcom STB board and you wish
 	  to have restart support.
 
+config POWER_RESET_GEMINI_POWEROFF
+	bool "Cortina Gemini power-off driver"
+	depends on ARCH_GEMINI || COMPILE_TEST
+	depends on OF && HAS_IOMEM
+	default ARCH_GEMINI
+	help
+	  This driver supports turning off the Cortina Gemini SoC.
+	  Select this if you're building a kernel with Gemini SoC support.
+
 config POWER_RESET_GPIO
 	bool "GPIO power-off driver"
 	depends on OF_GPIO
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index 11dae3b56ff9..58cf5b30559f 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_POWER_RESET_AT91_SAMA5D2_SHDWC) += at91-sama5d2_shdwc.o
 obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o
 obj-$(CONFIG_POWER_RESET_BRCMKONA) += brcm-kona-reset.o
 obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o
+obj-$(CONFIG_POWER_RESET_GEMINI_POWEROFF) += gemini-poweroff.o
 obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
 obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o
 obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o
diff --git a/drivers/power/reset/gemini-poweroff.c b/drivers/power/reset/gemini-poweroff.c
new file mode 100644
index 000000000000..de878fd26f27
--- /dev/null
+++ b/drivers/power/reset/gemini-poweroff.c
@@ -0,0 +1,160 @@
+/*
+ * Gemini power management controller
+ * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
+ *
+ * Inspired by code from the SL3516 board support by Jason Lee
+ * Inspired by code from Janos Laube <janos.dev@gmail.com>
+ */
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/bitops.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/reboot.h>
+
+#define GEMINI_PWC_ID		0x00010500
+#define	GEMINI_PWC_IDREG	0x00
+#define	GEMINI_PWC_CTRLREG	0x04
+#define	GEMINI_PWC_STATREG	0x08
+
+#define GEMINI_CTRL_SHUTDOWN	BIT(0)
+#define GEMINI_CTRL_ENABLE	BIT(1)
+#define GEMINI_CTRL_IRQ_CLR	BIT(2)
+
+#define GEMINI_STAT_CIR		BIT(4)
+#define	GEMINI_STAT_RTC		BIT(5)
+#define	GEMINI_STAT_POWERBUTTON	BIT(6)
+
+struct gemini_powercon {
+        struct device           *dev;
+        void __iomem            *base;
+};
+
+static irqreturn_t gemini_powerbutton_interrupt(int irq, void *data)
+{
+	struct gemini_powercon *gpw = data;
+	u32 val;
+
+	/* ACK the IRQ */
+	val = readl(gpw->base + GEMINI_PWC_CTRLREG);
+	val |= GEMINI_CTRL_IRQ_CLR;
+	writel(val, gpw->base + GEMINI_PWC_CTRLREG);
+
+	val = readl(gpw->base + GEMINI_PWC_STATREG);
+	val &= 0x70U;
+	switch (val) {
+	case GEMINI_STAT_CIR:
+		dev_info(gpw->dev, "infrared poweroff\n");
+		orderly_poweroff(true);
+		break;
+	case GEMINI_STAT_RTC:
+		dev_info(gpw->dev, "RTC poweroff\n");
+		orderly_poweroff(true);
+		break;
+	case GEMINI_STAT_POWERBUTTON:
+		dev_info(gpw->dev, "poweroff button pressed\n");
+		orderly_poweroff(true);
+		break;
+	default:
+		dev_info(gpw->dev, "other power management IRQ\n");
+		break;
+	}
+
+	return IRQ_HANDLED;
+}
+
+/* This callback needs this static local as it has void as argument */
+static struct gemini_powercon *gpw_poweroff;
+
+static void gemini_poweroff(void)
+{
+	struct gemini_powercon *gpw = gpw_poweroff;
+	u32 val;
+
+	dev_crit(gpw->dev, "Gemini power off\n");
+	val = readl(gpw->base + GEMINI_PWC_CTRLREG);
+	val |= GEMINI_CTRL_ENABLE | GEMINI_CTRL_IRQ_CLR;
+	writel(val, gpw->base + GEMINI_PWC_CTRLREG);
+
+	val &= ~GEMINI_CTRL_ENABLE;
+	val |= GEMINI_CTRL_SHUTDOWN;
+	writel(val, gpw->base + GEMINI_PWC_CTRLREG);
+}
+
+static int gemini_poweroff_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct gemini_powercon *gpw;
+	u32 val;
+	int irq;
+	int ret;
+
+	gpw = devm_kzalloc(dev, sizeof(*gpw), GFP_KERNEL);
+	if (!gpw)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	gpw->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(gpw->base))
+		return PTR_ERR(gpw->base);
+
+	irq = platform_get_irq(pdev, 0);
+	if (!irq)
+		return -EINVAL;
+
+	gpw->dev = dev;
+
+	val = readl(gpw->base + GEMINI_PWC_IDREG);
+	val &= 0xFFFFFF00U;
+	if (val != GEMINI_PWC_ID) {
+		dev_err(dev, "wrong power controller ID: %08x\n",
+			val);
+		return -ENODEV;
+	}
+
+	/* Clear the power management IRQ */
+	val = readl(gpw->base + GEMINI_PWC_CTRLREG);
+	val |= GEMINI_CTRL_IRQ_CLR;
+	writel(val, gpw->base + GEMINI_PWC_CTRLREG);
+
+	ret = devm_request_irq(dev, irq, gemini_powerbutton_interrupt, 0,
+			       "poweroff", gpw);
+	if (ret)
+		return ret;
+
+	pm_power_off = gemini_poweroff;
+	gpw_poweroff = gpw;
+
+	/*
+	 * Enable the power controller. This is crucial on Gemini
+	 * systems: if this is not done, pressing the power button
+	 * will result in unconditional poweroff without any warning.
+	 * This makes the kernel handle the poweroff.
+	 */
+	val = readl(gpw->base + GEMINI_PWC_CTRLREG);
+	val |= GEMINI_CTRL_ENABLE;
+	writel(val, gpw->base + GEMINI_PWC_CTRLREG);
+
+	dev_info(dev, "Gemini poweroff driver registered\n");
+
+	return 0;
+}
+
+static const struct of_device_id gemini_poweroff_of_match[] = {
+	{
+		.compatible = "cortina,gemini-power-controller",
+	},
+	{}
+};
+
+static struct platform_driver gemini_poweroff_driver = {
+	.probe = gemini_poweroff_probe,
+	.driver = {
+		.name = "gemini-poweroff",
+		.of_match_table = gemini_poweroff_of_match,
+	},
+};
+builtin_platform_driver(gemini_poweroff_driver);
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/4] ARM: gemini: select gemini poweroff
  2017-01-30 19:36 [PATCH 1/4] power: reset: Add Gemini poweroff DT bindings Linus Walleij
  2017-01-30 19:36 ` [PATCH 2/4] power: reset: Add a driver for the Gemini poweroff Linus Walleij
@ 2017-01-30 19:36 ` Linus Walleij
  2017-01-30 19:36 ` [PATCH 4/4] ARM: dts: add power controller to the Gemini DTS Linus Walleij
  2017-02-01 17:11 ` [PATCH 1/4] power: reset: Add Gemini poweroff DT bindings Rob Herring
  3 siblings, 0 replies; 5+ messages in thread
From: Linus Walleij @ 2017-01-30 19:36 UTC (permalink / raw)
  To: linux-arm-kernel

It's especially annoying if the system cannot be properly
powered down so select the poweroff driver from the Kconfig.

Cc: Janos Laube <janos.dev@gmail.com>
Cc: Paulius Zaleckas <paulius.zaleckas@gmail.com>
Cc: Hans Ulli Kroll <ulli.kroll@googlemail.com>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
Sebastian: this patch is just for context.
I will funnel the ARM parts through the ARM SoC tree.
---
 arch/arm/mach-gemini/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-gemini/Kconfig b/arch/arm/mach-gemini/Kconfig
index 91ea52ccf13c..4b5c059d602b 100644
--- a/arch/arm/mach-gemini/Kconfig
+++ b/arch/arm/mach-gemini/Kconfig
@@ -7,6 +7,7 @@ menuconfig ARCH_GEMINI
 	select GPIOLIB
 	select MIGHT_HAVE_PCI
 	select POWER_RESET
+	select POWER_RESET_GEMINI_POWEROFF
 	select POWER_RESET_SYSCON
 	select SERIAL_OF_PLATFORM
 	help
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 4/4] ARM: dts: add power controller to the Gemini DTS
  2017-01-30 19:36 [PATCH 1/4] power: reset: Add Gemini poweroff DT bindings Linus Walleij
  2017-01-30 19:36 ` [PATCH 2/4] power: reset: Add a driver for the Gemini poweroff Linus Walleij
  2017-01-30 19:36 ` [PATCH 3/4] ARM: gemini: select gemini poweroff Linus Walleij
@ 2017-01-30 19:36 ` Linus Walleij
  2017-02-01 17:11 ` [PATCH 1/4] power: reset: Add Gemini poweroff DT bindings Rob Herring
  3 siblings, 0 replies; 5+ messages in thread
From: Linus Walleij @ 2017-01-30 19:36 UTC (permalink / raw)
  To: linux-arm-kernel

This adds the Gemini power controller to the SoC DTSI
file.

Cc: Janos Laube <janos.dev@gmail.com>
Cc: Paulius Zaleckas <paulius.zaleckas@gmail.com>
Cc: Hans Ulli Kroll <ulli.kroll@googlemail.com>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
Sebastian: this patch is just for context.
I will funnel the ARM parts through the ARM SoC tree.
---
 arch/arm/boot/dts/gemini.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/gemini.dtsi b/arch/arm/boot/dts/gemini.dtsi
index df5630958038..8a2501239ae5 100644
--- a/arch/arm/boot/dts/gemini.dtsi
+++ b/arch/arm/boot/dts/gemini.dtsi
@@ -70,6 +70,12 @@
 		#interrupt-cells = <2>;
 	};
 
+	power-controller at 4b000000 {
+		compatible = "cortina,gemini-power-controller";
+		reg = <0x4b000000 0x100>;
+		interrupts = <26 IRQ_TYPE_EDGE_FALLING>;
+	};
+
 	gpio0: gpio at 4d000000 {
 		compatible = "cortina,gemini-gpio";
 		reg = <0x4d000000 0x100>;
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 1/4] power: reset: Add Gemini poweroff DT bindings
  2017-01-30 19:36 [PATCH 1/4] power: reset: Add Gemini poweroff DT bindings Linus Walleij
                   ` (2 preceding siblings ...)
  2017-01-30 19:36 ` [PATCH 4/4] ARM: dts: add power controller to the Gemini DTS Linus Walleij
@ 2017-02-01 17:11 ` Rob Herring
  3 siblings, 0 replies; 5+ messages in thread
From: Rob Herring @ 2017-02-01 17:11 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jan 30, 2017 at 08:36:32PM +0100, Linus Walleij wrote:
> This adds device tree bindings to the power management controller
> in the Gemini SoC.
> 
> Cc: devicetree at vger.kernel.org
> Cc: Janos Laube <janos.dev@gmail.com>
> Cc: Paulius Zaleckas <paulius.zaleckas@gmail.com>
> Cc: Hans Ulli Kroll <ulli.kroll@googlemail.com>
> Cc: Florian Fainelli <f.fainelli@gmail.com>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> Sebastian: please just merge this when your are pleased
> with it. I will funnel the ARM parts through the ARM SoC tree.
> ---
>  .../devicetree/bindings/power/reset/gemini-poweroff.txt | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/power/reset/gemini-poweroff.txt

Acked-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2017-02-01 17:11 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-01-30 19:36 [PATCH 1/4] power: reset: Add Gemini poweroff DT bindings Linus Walleij
2017-01-30 19:36 ` [PATCH 2/4] power: reset: Add a driver for the Gemini poweroff Linus Walleij
2017-01-30 19:36 ` [PATCH 3/4] ARM: gemini: select gemini poweroff Linus Walleij
2017-01-30 19:36 ` [PATCH 4/4] ARM: dts: add power controller to the Gemini DTS Linus Walleij
2017-02-01 17:11 ` [PATCH 1/4] power: reset: Add Gemini poweroff DT bindings Rob Herring

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).