* [PATCH v1 1/3] power: reset: make qnap-poweroff flexible on hello magic command to uart1
2016-12-07 17:24 ` [PATCH v1 " Roger Shimizu
@ 2016-12-07 17:24 ` Roger Shimizu
2016-12-07 17:24 ` [PATCH v1 2/3] power: reset: make qnap-poweroff flexible on length of power-off command Roger Shimizu
` (3 subsequent siblings)
4 siblings, 0 replies; 44+ messages in thread
From: Roger Shimizu @ 2016-12-07 17:24 UTC (permalink / raw)
To: Sebastian Reichel, linux-pm, Andrew Lunn
Cc: Roger Shimizu, Ryan Tandy, Martin Michlmayr, Sylver Bruneau,
Herbert Valerio Riedel
Current hello magic command sending to UART1 is fixed in
qnap_power_off().
In order to support more devices, it's necessary to make hello magic
command as an argument in device configuration.
Signed-off-by: Roger Shimizu <rogershimizu@gmail.com>
---
drivers/power/reset/qnap-poweroff.c | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/drivers/power/reset/qnap-poweroff.c b/drivers/power/reset/qnap-poweroff.c
index 2789a61..47ed120 100644
--- a/drivers/power/reset/qnap-poweroff.c
+++ b/drivers/power/reset/qnap-poweroff.c
@@ -2,6 +2,7 @@
* QNAP Turbo NAS Board power off. Can also be used on Synology devices.
*
* Copyright (C) 2012 Andrew Lunn <andrew@lunn.ch>
+ * Copyright (C) 2016 Roger Shimizu <rogershimizu@gmail.com>
*
* Based on the code from:
*
@@ -25,18 +26,29 @@
#define UART1_REG(x) (base + ((UART_##x) << 2))
+/* 4-byte magic hello command to UART1-attached microcontroller */
+static const unsigned char qnap_micon_magic[] = {
+ 0x03,
+ 0x00,
+ 0x00,
+ 0x00
+};
+
struct power_off_cfg {
u32 baud;
+ const unsigned char *magic;
char cmd;
};
static const struct power_off_cfg qnap_power_off_cfg = {
.baud = 19200,
+ .magic = qnap_micon_magic,
.cmd = 'A',
};
static const struct power_off_cfg synology_power_off_cfg = {
.baud = 9600,
+ .magic = qnap_micon_magic,
.cmd = '1',
};
@@ -65,10 +77,10 @@ static void qnap_power_off(void)
writel(0x83, UART1_REG(LCR));
writel(divisor & 0xff, UART1_REG(DLL));
writel((divisor >> 8) & 0xff, UART1_REG(DLM));
- writel(0x03, UART1_REG(LCR));
- writel(0x00, UART1_REG(IER));
- writel(0x00, UART1_REG(FCR));
- writel(0x00, UART1_REG(MCR));
+ writel(cfg->magic[0], UART1_REG(LCR));
+ writel(cfg->magic[1], UART1_REG(IER));
+ writel(cfg->magic[2], UART1_REG(FCR));
+ writel(cfg->magic[3], UART1_REG(MCR));
/* send the power-off command to PIC */
writel(cfg->cmd, UART1_REG(TX));
--
2.10.2
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [PATCH v1 2/3] power: reset: make qnap-poweroff flexible on length of power-off command
2016-12-07 17:24 ` [PATCH v1 " Roger Shimizu
2016-12-07 17:24 ` [PATCH v1 1/3] power: reset: make qnap-poweroff flexible on hello magic command to uart1 Roger Shimizu
@ 2016-12-07 17:24 ` Roger Shimizu
2016-12-07 17:24 ` [PATCH v1 3/3] power: reset: make qnap-poweroff support kurobox-pro Roger Shimizu
` (2 subsequent siblings)
4 siblings, 0 replies; 44+ messages in thread
From: Roger Shimizu @ 2016-12-07 17:24 UTC (permalink / raw)
To: Sebastian Reichel, linux-pm, Andrew Lunn
Cc: Roger Shimizu, Ryan Tandy, Martin Michlmayr, Sylver Bruneau,
Herbert Valerio Riedel
Current power-off command sending to UART1 is fixed to one-byte.
In order to support more devices, it's necessary to make power-off
command as 2-D array argument of device configuration.
By using 2-D array, power-off command may consist a few commands, each
of which may consist a few bytes.
Signed-off-by: Roger Shimizu <rogershimizu@gmail.com>
---
drivers/power/reset/qnap-poweroff.c | 23 +++++++++++++++++++----
1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/drivers/power/reset/qnap-poweroff.c b/drivers/power/reset/qnap-poweroff.c
index 47ed120..644478c 100644
--- a/drivers/power/reset/qnap-poweroff.c
+++ b/drivers/power/reset/qnap-poweroff.c
@@ -25,6 +25,7 @@
#include <linux/clk.h>
#define UART1_REG(x) (base + ((UART_##x) << 2))
+#define MICON_CMD_SIZE 4
/* 4-byte magic hello command to UART1-attached microcontroller */
static const unsigned char qnap_micon_magic[] = {
@@ -34,22 +35,33 @@ static const unsigned char qnap_micon_magic[] = {
0x00
};
+// for each row, first byte is the size of command
+static const unsigned char qnap_power_off_cmd[][MICON_CMD_SIZE] = {
+ { 1, 'A'},
+ {}
+};
+
+static const unsigned char synology_power_off_cmd[][MICON_CMD_SIZE] = {
+ { 1, '1'},
+ {}
+};
+
struct power_off_cfg {
u32 baud;
const unsigned char *magic;
- char cmd;
+ const unsigned char (*cmd)[MICON_CMD_SIZE];
};
static const struct power_off_cfg qnap_power_off_cfg = {
.baud = 19200,
.magic = qnap_micon_magic,
- .cmd = 'A',
+ .cmd = qnap_power_off_cmd,
};
static const struct power_off_cfg synology_power_off_cfg = {
.baud = 9600,
.magic = qnap_micon_magic,
- .cmd = '1',
+ .cmd = synology_power_off_cmd,
};
static const struct of_device_id qnap_power_off_of_match_table[] = {
@@ -83,7 +95,10 @@ static void qnap_power_off(void)
writel(cfg->magic[3], UART1_REG(MCR));
/* send the power-off command to PIC */
- writel(cfg->cmd, UART1_REG(TX));
+ if(cfg->cmd[0][0] == 1 && cfg->cmd[1][0] == 0) {
+ /* for qnap and synology, it's simply one-byte command */
+ writel(cfg->cmd[0][1], UART1_REG(TX));
+ }
}
static int qnap_power_off_probe(struct platform_device *pdev)
--
2.10.2
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [PATCH v1 3/3] power: reset: make qnap-poweroff support kurobox-pro
2016-12-07 17:24 ` [PATCH v1 " Roger Shimizu
2016-12-07 17:24 ` [PATCH v1 1/3] power: reset: make qnap-poweroff flexible on hello magic command to uart1 Roger Shimizu
2016-12-07 17:24 ` [PATCH v1 2/3] power: reset: make qnap-poweroff flexible on length of power-off command Roger Shimizu
@ 2016-12-07 17:24 ` Roger Shimizu
2016-12-07 18:04 ` [PATCH v1 0/3] make kurobox-pro be able to shutdown after device-tree migration Andrew Lunn
2016-12-16 10:05 ` [PATCH v2] power: reset: add linkstation-reset driver Roger Shimizu
4 siblings, 0 replies; 44+ messages in thread
From: Roger Shimizu @ 2016-12-07 17:24 UTC (permalink / raw)
To: Sebastian Reichel, linux-pm, Andrew Lunn
Cc: Roger Shimizu, Ryan Tandy, Martin Michlmayr, Sylver Bruneau,
Herbert Valerio Riedel
Add KuroBox-Pro and Terastation Pro II/Live support on qnap-poweroff
The magic command and function of sending multi-byte command come
from files listed below:
- arch/arm/mach-orion5x/kurobox_pro-setup.c
- arch/arm/mach-orion5x/terastation_pro2-setup.c
Reported-by: Ryan Tandy <ryan@nardis.ca>
Signed-off-by: Roger Shimizu <rogershimizu@gmail.com>
---
.../bindings/power/reset/qnap-poweroff.txt | 8 +-
drivers/power/reset/Makefile | 2 +-
drivers/power/reset/kuroboxpro-common.c | 128 +++++++++++++++++++++
drivers/power/reset/kuroboxpro-common.h | 8 ++
drivers/power/reset/qnap-poweroff.c | 39 ++++++-
5 files changed, 181 insertions(+), 4 deletions(-)
create mode 100644 drivers/power/reset/kuroboxpro-common.c
create mode 100644 drivers/power/reset/kuroboxpro-common.h
diff --git a/Documentation/devicetree/bindings/power/reset/qnap-poweroff.txt b/Documentation/devicetree/bindings/power/reset/qnap-poweroff.txt
index af25e77..410993d 100644
--- a/Documentation/devicetree/bindings/power/reset/qnap-poweroff.txt
+++ b/Documentation/devicetree/bindings/power/reset/qnap-poweroff.txt
@@ -9,8 +9,14 @@ pm_power_off which is called to turn the power off.
Synology NAS devices use a similar scheme, but a different baud rate,
9600, and a different character, '1'.
+KuroBox Pro, Buffalo Linkstation LS-GL (also known as
+Buffalo Linkstation Pro/Live) and Buffalo Terastation Pro II/Live
+are similar, however it has even higher baud rate and need more
+commands to feed the UART1 before power off.
+
Required Properties:
-- compatible: Should be "qnap,power-off" or "synology,power-off"
+- compatible: Should be "qnap,power-off", "synology,power-off"
+ or "kuroboxpro,power-off"
- reg: Address and length of the register set for UART1
- clocks: tclk clock
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index 1be307c..df48285 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -11,7 +11,7 @@ obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o
obj-$(CONFIG_POWER_RESET_IMX) += imx-snvs-poweroff.o
obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
obj-$(CONFIG_POWER_RESET_LTC2952) += ltc2952-poweroff.o
-obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
+obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o kuroboxpro-common.o
obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o
obj-$(CONFIG_POWER_RESET_ST) += st-poweroff.o
obj-$(CONFIG_POWER_RESET_VERSATILE) += arm-versatile-reboot.o
diff --git a/drivers/power/reset/kuroboxpro-common.c b/drivers/power/reset/kuroboxpro-common.c
new file mode 100644
index 0000000..ef417e6
--- /dev/null
+++ b/drivers/power/reset/kuroboxpro-common.c
@@ -0,0 +1,128 @@
+/*
+ * Common control routine of micro-controller of KuroBox-Pro
+ * and it's variants.
+ * It can be used on following devices:
+ * - KuroBox Pro
+ * - Buffalo Linkstation Pro (LS-GL)
+ * - Buffalo Terastation Pro II/Live
+ *
+ * Copyright (C) 2016 Roger Shimizu <rogershimizu@gmail.com>
+ *
+ * Based on the code from:
+ *
+ * Copyright (C) 2008 Sylver Bruneau <sylver.bruneau@googlemail.com>
+ * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/serial_reg.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include "kuroboxpro-common.h"
+
+static int uart1_micon_read(void *base, unsigned char *buf, int count)
+{
+ int i;
+ int timeout;
+
+ for (i = 0; i < count; i++) {
+ timeout = 10;
+
+ while (!(readl(UART1_REG(LSR)) & UART_LSR_DR)) {
+ if (--timeout == 0)
+ break;
+ udelay(1000);
+ }
+
+ if (timeout == 0)
+ break;
+ buf[i] = readl(UART1_REG(RX));
+ }
+
+ /* return read bytes */
+ return i;
+}
+
+static int uart1_micon_write(void *base, const unsigned char *buf, int count)
+{
+ int i = 0;
+
+ while (count--) {
+ while (!(readl(UART1_REG(LSR)) & UART_LSR_THRE))
+ barrier();
+ writel(buf[i++], UART1_REG(TX));
+ }
+
+ return 0;
+}
+
+int uart1_micon_send(void *base, const unsigned char *data, int count)
+{
+ int i;
+ unsigned char checksum = 0;
+ unsigned char recv_buf[40];
+ unsigned char send_buf[40];
+ unsigned char correct_ack[3];
+ int retry = 2;
+
+ /* Generate checksum */
+ for (i = 0; i < count; i++)
+ checksum -= data[i];
+
+ do {
+ /* Send data */
+ uart1_micon_write(base, data, count);
+
+ /* send checksum */
+ uart1_micon_write(base, &checksum, 1);
+
+ if (uart1_micon_read(base, recv_buf, sizeof(recv_buf)) <= 3) {
+ printk(KERN_ERR ">%s: receive failed.\n", __func__);
+
+ /* send preamble to clear the receive buffer */
+ memset(&send_buf, 0xff, sizeof(send_buf));
+ uart1_micon_write(base, send_buf, sizeof(send_buf));
+
+ /* make dummy reads */
+ mdelay(100);
+ uart1_micon_read(base, recv_buf, sizeof(recv_buf));
+ } else {
+ /* Generate expected ack */
+ correct_ack[0] = 0x01;
+ correct_ack[1] = data[1];
+ correct_ack[2] = 0x00;
+
+ /* checksum Check */
+ if ((recv_buf[0] + recv_buf[1] + recv_buf[2] +
+ recv_buf[3]) & 0xFF) {
+ printk(KERN_ERR ">%s: Checksum Error : "
+ "Received data[%02x, %02x, %02x, %02x]"
+ "\n", __func__, recv_buf[0],
+ recv_buf[1], recv_buf[2], recv_buf[3]);
+ } else {
+ /* Check Received Data */
+ if (correct_ack[0] == recv_buf[0] &&
+ correct_ack[1] == recv_buf[1] &&
+ correct_ack[2] == recv_buf[2]) {
+ /* Interval for next command */
+ mdelay(10);
+
+ /* Receive ACK */
+ return 0;
+ }
+ }
+ /* Received NAK or illegal Data */
+ printk(KERN_ERR ">%s: Error : NAK or Illegal Data "
+ "Received\n", __func__);
+ }
+ } while (retry--);
+
+ /* Interval for next command */
+ mdelay(10);
+
+ return -1;
+}
diff --git a/drivers/power/reset/kuroboxpro-common.h b/drivers/power/reset/kuroboxpro-common.h
new file mode 100644
index 0000000..58d5ee6
--- /dev/null
+++ b/drivers/power/reset/kuroboxpro-common.h
@@ -0,0 +1,8 @@
+#ifndef __KUROBOXPRO_COMMON_H__
+#define __KUROBOXPRO_COMMON_H__
+
+#define UART1_REG(x) (base + ((UART_##x) << 2))
+
+int uart1_micon_send(void *base, const unsigned char *data, int count);
+
+#endif
diff --git a/drivers/power/reset/qnap-poweroff.c b/drivers/power/reset/qnap-poweroff.c
index 644478c..5ae7f1b 100644
--- a/drivers/power/reset/qnap-poweroff.c
+++ b/drivers/power/reset/qnap-poweroff.c
@@ -1,5 +1,10 @@
/*
- * QNAP Turbo NAS Board power off. Can also be used on Synology devices.
+ * QNAP Turbo NAS Board power off.
+ * It can also be used on following devices:
+ * - Synology devices
+ * - KuroBox Pro
+ * - Buffalo Linkstation Pro (LS-GL)
+ * - Buffalo Terastation Pro II/Live
*
* Copyright (C) 2012 Andrew Lunn <andrew@lunn.ch>
* Copyright (C) 2016 Roger Shimizu <rogershimizu@gmail.com>
@@ -23,8 +28,8 @@
#include <linux/of.h>
#include <linux/io.h>
#include <linux/clk.h>
+#include "kuroboxpro-common.h"
-#define UART1_REG(x) (base + ((UART_##x) << 2))
#define MICON_CMD_SIZE 4
/* 4-byte magic hello command to UART1-attached microcontroller */
@@ -35,6 +40,13 @@ static const unsigned char qnap_micon_magic[] = {
0x00
};
+static const unsigned char kuroboxpro_micon_magic[] = {
+ 0x1b,
+ 0x00,
+ 0x07,
+ 0x00
+};
+
// for each row, first byte is the size of command
static const unsigned char qnap_power_off_cmd[][MICON_CMD_SIZE] = {
{ 1, 'A'},
@@ -46,6 +58,13 @@ static const unsigned char synology_power_off_cmd[][MICON_CMD_SIZE] = {
{}
};
+static const unsigned char kuroboxpro_power_off_cmd[][MICON_CMD_SIZE] = {
+ { 3, 0x01, 0x35, 0x00},
+ { 2, 0x00, 0x0c},
+ { 2, 0x00, 0x06},
+ {}
+};
+
struct power_off_cfg {
u32 baud;
const unsigned char *magic;
@@ -64,6 +83,12 @@ static const struct power_off_cfg synology_power_off_cfg = {
.cmd = synology_power_off_cmd,
};
+static const struct power_off_cfg kuroboxpro_power_off_cfg = {
+ .baud = 38400,
+ .magic = kuroboxpro_micon_magic,
+ .cmd = kuroboxpro_power_off_cmd,
+};
+
static const struct of_device_id qnap_power_off_of_match_table[] = {
{ .compatible = "qnap,power-off",
.data = &qnap_power_off_cfg,
@@ -71,6 +96,9 @@ static const struct of_device_id qnap_power_off_of_match_table[] = {
{ .compatible = "synology,power-off",
.data = &synology_power_off_cfg,
},
+ { .compatible = "kuroboxpro,power-off",
+ .data = &kuroboxpro_power_off_cfg,
+ },
{}
};
MODULE_DEVICE_TABLE(of, qnap_power_off_of_match_table);
@@ -99,6 +127,13 @@ static void qnap_power_off(void)
/* for qnap and synology, it's simply one-byte command */
writel(cfg->cmd[0][1], UART1_REG(TX));
}
+ else {
+ int i;
+ for(i = 0; cfg->cmd[i][0] > 0; i ++) {
+ /* [0] is size of the command; command starts from [1] */
+ uart1_micon_send(base, &(cfg->cmd[i][1]), cfg->cmd[i][0]);
+ }
+ }
}
static int qnap_power_off_probe(struct platform_device *pdev)
--
2.10.2
^ permalink raw reply related [flat|nested] 44+ messages in thread
* Re: [PATCH v1 0/3] make kurobox-pro be able to shutdown after device-tree migration
2016-12-07 17:24 ` [PATCH v1 " Roger Shimizu
` (2 preceding siblings ...)
2016-12-07 17:24 ` [PATCH v1 3/3] power: reset: make qnap-poweroff support kurobox-pro Roger Shimizu
@ 2016-12-07 18:04 ` Andrew Lunn
2016-12-16 10:05 ` [PATCH v2] power: reset: add linkstation-reset driver Roger Shimizu
4 siblings, 0 replies; 44+ messages in thread
From: Andrew Lunn @ 2016-12-07 18:04 UTC (permalink / raw)
To: Roger Shimizu
Cc: Sebastian Reichel, linux-pm, Ryan Tandy, Martin Michlmayr,
Sylver Bruneau, Herbert Valerio Riedel
> Dear Andrew,
>
> Thanks for your review!
>
> I split off most of kurobox-pro releated code into separated files.
> Hope you can accept this series.
Hi Roger
I still think it should be a separate driver. The 128 lines of
kuroboxpro-common.c is only slightly smaller than the unmodified
driver.
What code are you actually sharing? The probe and remove functions,
which is mostly boiler plate, the same in all driver, and the baud
rate generation. So there is very little actually common and re-used.
Andrew
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH v2] power: reset: add linkstation-reset driver
2016-12-07 17:24 ` [PATCH v1 " Roger Shimizu
` (3 preceding siblings ...)
2016-12-07 18:04 ` [PATCH v1 0/3] make kurobox-pro be able to shutdown after device-tree migration Andrew Lunn
@ 2016-12-16 10:05 ` Roger Shimizu
2016-12-19 0:34 ` Roger Shimizu
` (2 more replies)
4 siblings, 3 replies; 44+ messages in thread
From: Roger Shimizu @ 2016-12-16 10:05 UTC (permalink / raw)
To: Sebastian Reichel, linux-pm, Andrew Lunn
Cc: Roger Shimizu, Ryan Tandy, Martin Michlmayr, Sylver Bruneau,
Herbert Valerio Riedel
Buffalo Linkstation / KuroBox and their variants need magic command
sending to UART1 to power-off.
Power driver linkstation-reset implements the magic command and I/O
routine, which come from files listed below:
- arch/arm/mach-orion5x/kurobox_pro-setup.c
- arch/arm/mach-orion5x/terastation_pro2-setup.c
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Martin Michlmayr <tbm@cyrius.com>
Cc: Sylver Bruneau <sylver.bruneau@googlemail.com>
Cc: Herbert Valerio Riedel <hvr@gnu.org>
Reported-by: Ryan Tandy <ryan@nardis.ca>
Signed-off-by: Roger Shimizu <rogershimizu@gmail.com>
---
Dear Sebastian,
Kurobox-Pro (and variants) need more commands sending to UART1 to shutdown.
So here I make this patch series to let current qnap-poweroff implementation
be able to handle such case.
I already tested this change on Kurobox-Pro and Linkstation LS-GL devices,
with a modified device-tree file. (Previous device-tree of kurobox-pro invokes
restart-poweroff, so it simply restarts.)
Thank you and look forward to your feedback!
Dear Andrew,
Thanks for your 2nd review!
So I accept your suggestion and make the new driver for linkstation series.
Changes:
v0 => v1:
- Update 0003 to split kuroboxpro related code into kuroboxpro-common.c
v1 => v2:
- Slipt off linkstation/kuroboxpro related code to linkstation-reset.c
Because linkstation before kuroboxpro also need this driver to power
off properly. It's more proper to call it linkstation driver.
Cheers,
--
Roger Shimizu, GMT +9 Tokyo
PGP/GPG: 4096R/6C6ACD6417B3ACB1
.../bindings/power/reset/linkstation-reset.txt | 26 ++++
drivers/power/reset/Kconfig | 10 ++
drivers/power/reset/Makefile | 1 +
drivers/power/reset/linkstation-common.c | 124 +++++++++++++++
drivers/power/reset/linkstation-common.h | 8 +
drivers/power/reset/linkstation-reset.c | 172 +++++++++++++++++++++
6 files changed, 341 insertions(+)
create mode 100644 Documentation/devicetree/bindings/power/reset/linkstation-reset.txt
create mode 100644 drivers/power/reset/linkstation-common.c
create mode 100644 drivers/power/reset/linkstation-common.h
create mode 100644 drivers/power/reset/linkstation-reset.c
diff --git a/Documentation/devicetree/bindings/power/reset/linkstation-reset.txt b/Documentation/devicetree/bindings/power/reset/linkstation-reset.txt
new file mode 100644
index 0000000..815e340
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/reset/linkstation-reset.txt
@@ -0,0 +1,26 @@
+* Buffalo Linkstation Reset Driver
+
+Power of some Buffalo Linkstation or KuroBox Pro is managed by
+micro-controller, which connects to UART1. After being fed from UART1
+by a few magic numbers, the so-called power-off command,
+the micro-controller will turn power off the device.
+
+This is very similar to QNAP or Synology NAS devices, which is
+described in qnap-poweroff.txt, however the command is much simpler,
+only 1-byte long and without checksums.
+
+This driver adds a handler to pm_power_off which is called to turn the
+power off.
+
+Required Properties:
+- compatible: Should be "linkstation,power-off"
+- reg: Address and length of the register set for UART1
+- clocks: tclk clock
+
+Example:
+
+ reset {
+ compatible = "linkstation,power-off";
+ reg = <0x12100 0x100>;
+ clocks = <&core_clk 0>;
+ };
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index c74c3f6..77c44ca 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -98,6 +98,16 @@ config POWER_RESET_IMX
say N here or disable in dts to make sure pm_power_off never be
overwrote wrongly by this driver.
+config POWER_RESET_LINKSTATION
+ bool "Buffalo Linkstation and its variants reset driver"
+ depends on OF_GPIO && PLAT_ORION
+ help
+ This driver supports power off Buffalo Linkstation / KuroBox Pro
+ NAS and their variants by sending commands to the micro-controller
+ which controls the main power.
+
+ Say Y if you have a Buffalo Linkstation / KuroBox Pro NAS.
+
config POWER_RESET_MSM
bool "Qualcomm MSM power-off driver"
depends on ARCH_QCOM
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index 1be307c..520afbe 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -9,6 +9,7 @@ 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
obj-$(CONFIG_POWER_RESET_IMX) += imx-snvs-poweroff.o
+obj-$(CONFIG_POWER_RESET_LINKSTATION) += linkstation-reset.o linkstation-common.o
obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
obj-$(CONFIG_POWER_RESET_LTC2952) += ltc2952-poweroff.o
obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
diff --git a/drivers/power/reset/linkstation-common.c b/drivers/power/reset/linkstation-common.c
new file mode 100644
index 0000000..a6d0930
--- /dev/null
+++ b/drivers/power/reset/linkstation-common.c
@@ -0,0 +1,124 @@
+/*
+ * Common I/O routine for micro-controller of Buffalo Linkstation
+ * and its variants.
+ *
+ * Copyright (C) 2016 Roger Shimizu <rogershimizu@gmail.com>
+ *
+ * Based on the code from:
+ *
+ * Copyright (C) 2008 Sylver Bruneau <sylver.bruneau@googlemail.com>
+ * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/serial_reg.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include "linkstation-common.h"
+
+static int uart1_micon_read(void *base, unsigned char *buf, int count)
+{
+ int i;
+ int timeout;
+
+ for (i = 0; i < count; i++) {
+ timeout = 10;
+
+ while (!(readl(UART1_REG(LSR)) & UART_LSR_DR)) {
+ if (--timeout == 0)
+ break;
+ udelay(1000);
+ }
+
+ if (timeout == 0)
+ break;
+ buf[i] = readl(UART1_REG(RX));
+ }
+
+ /* return read bytes */
+ return i;
+}
+
+static int uart1_micon_write(void *base, const unsigned char *buf, int count)
+{
+ int i = 0;
+
+ while (count--) {
+ while (!(readl(UART1_REG(LSR)) & UART_LSR_THRE))
+ barrier();
+ writel(buf[i++], UART1_REG(TX));
+ }
+
+ return 0;
+}
+
+int uart1_micon_send(void *base, const unsigned char *data, int count)
+{
+ int i;
+ unsigned char checksum = 0;
+ unsigned char recv_buf[40];
+ unsigned char send_buf[40];
+ unsigned char correct_ack[3];
+ int retry = 2;
+
+ /* Generate checksum */
+ for (i = 0; i < count; i++)
+ checksum -= data[i];
+
+ do {
+ /* Send data */
+ uart1_micon_write(base, data, count);
+
+ /* send checksum */
+ uart1_micon_write(base, &checksum, 1);
+
+ if (uart1_micon_read(base, recv_buf, sizeof(recv_buf)) <= 3) {
+ printk(KERN_ERR ">%s: receive failed.\n", __func__);
+
+ /* send preamble to clear the receive buffer */
+ memset(&send_buf, 0xff, sizeof(send_buf));
+ uart1_micon_write(base, send_buf, sizeof(send_buf));
+
+ /* make dummy reads */
+ mdelay(100);
+ uart1_micon_read(base, recv_buf, sizeof(recv_buf));
+ } else {
+ /* Generate expected ack */
+ correct_ack[0] = 0x01;
+ correct_ack[1] = data[1];
+ correct_ack[2] = 0x00;
+
+ /* checksum Check */
+ if ((recv_buf[0] + recv_buf[1] + recv_buf[2] +
+ recv_buf[3]) & 0xFF) {
+ printk(KERN_ERR ">%s: Checksum Error : "
+ "Received data[%02x, %02x, %02x, %02x]"
+ "\n", __func__, recv_buf[0],
+ recv_buf[1], recv_buf[2], recv_buf[3]);
+ } else {
+ /* Check Received Data */
+ if (correct_ack[0] == recv_buf[0] &&
+ correct_ack[1] == recv_buf[1] &&
+ correct_ack[2] == recv_buf[2]) {
+ /* Interval for next command */
+ mdelay(10);
+
+ /* Receive ACK */
+ return 0;
+ }
+ }
+ /* Received NAK or illegal Data */
+ printk(KERN_ERR ">%s: Error : NAK or Illegal Data "
+ "Received\n", __func__);
+ }
+ } while (retry--);
+
+ /* Interval for next command */
+ mdelay(10);
+
+ return -1;
+}
diff --git a/drivers/power/reset/linkstation-common.h b/drivers/power/reset/linkstation-common.h
new file mode 100644
index 0000000..89c64a9
--- /dev/null
+++ b/drivers/power/reset/linkstation-common.h
@@ -0,0 +1,8 @@
+#ifndef __LINKSTATION_COMMON_H__
+#define __LINKSTATION_COMMON_H__
+
+#define UART1_REG(x) (base + ((UART_##x) << 2))
+
+int uart1_micon_send(void *base, const unsigned char *data, int count);
+
+#endif
diff --git a/drivers/power/reset/linkstation-reset.c b/drivers/power/reset/linkstation-reset.c
new file mode 100644
index 0000000..78a0137
--- /dev/null
+++ b/drivers/power/reset/linkstation-reset.c
@@ -0,0 +1,172 @@
+/*
+ * Buffalo Linkstation power reset driver.
+ * It may also be used on following devices:
+ * - Buffalo Linkstation HG
+ * - KuroBox HG
+ * - Buffalo KURO-NAS/T4
+ * - KuroBox Pro
+ * - Buffalo Linkstation Pro (LS-GL)
+ * - Buffalo Terastation Pro II/Live
+ * - Buffalo Linkstation Duo (LS-WTGL)
+ * - Buffalo Linkstation Mini (LS-WSGL)
+ *
+ * Copyright (C) 2016 Roger Shimizu <rogershimizu@gmail.com>
+ *
+ * Based on the code from:
+ *
+ * Copyright (C) 2012 Andrew Lunn <andrew@lunn.ch>
+ * Copyright (C) 2009 Martin Michlmayr <tbm@cyrius.com>
+ * Copyright (C) 2008 Byron Bradley <byron.bbradley@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/serial_reg.h>
+#include <linux/kallsyms.h>
+#include <linux/of.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include "linkstation-common.h"
+
+#define MICON_CMD_SIZE 4
+
+/* 4-byte magic hello command to UART1-attached microcontroller */
+static const unsigned char linkstation_micon_magic[] = {
+ 0x1b,
+ 0x00,
+ 0x07,
+ 0x00
+};
+
+// for each row, first byte is the size of command
+static const unsigned char linkstation_power_off_cmd[][MICON_CMD_SIZE] = {
+ { 3, 0x01, 0x35, 0x00},
+ { 2, 0x00, 0x0c},
+ { 2, 0x00, 0x06},
+ {}
+};
+
+struct reset_cfg {
+ u32 baud;
+ const unsigned char *magic;
+ const unsigned char (*cmd)[MICON_CMD_SIZE];
+};
+
+static const struct reset_cfg linkstation_power_off_cfg = {
+ .baud = 38400,
+ .magic = linkstation_micon_magic,
+ .cmd = linkstation_power_off_cmd,
+};
+
+static const struct of_device_id linkstation_reset_of_match_table[] = {
+ { .compatible = "linkstation,power-off",
+ .data = &linkstation_power_off_cfg,
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, linkstation_reset_of_match_table);
+
+static void __iomem *base;
+static unsigned long tclk;
+static const struct reset_cfg *cfg;
+
+static void linkstation_reset(void)
+{
+ const unsigned divisor = ((tclk + (8 * cfg->baud)) / (16 * cfg->baud));
+
+ pr_err("%s: triggering power-off...\n", __func__);
+
+ /* hijack UART1 and reset into sane state */
+ writel(0x83, UART1_REG(LCR));
+ writel(divisor & 0xff, UART1_REG(DLL));
+ writel((divisor >> 8) & 0xff, UART1_REG(DLM));
+ writel(cfg->magic[0], UART1_REG(LCR));
+ writel(cfg->magic[1], UART1_REG(IER));
+ writel(cfg->magic[2], UART1_REG(FCR));
+ writel(cfg->magic[3], UART1_REG(MCR));
+
+ /* send the power-off command to PIC */
+ if(cfg->cmd[0][0] == 1 && cfg->cmd[1][0] == 0) {
+ /* if it's simply one-byte command, send it directly */
+ writel(cfg->cmd[0][1], UART1_REG(TX));
+ }
+ else {
+ int i;
+ for(i = 0; cfg->cmd[i][0] > 0; i ++) {
+ /* [0] is size of the command; command starts from [1] */
+ uart1_micon_send(base, &(cfg->cmd[i][1]), cfg->cmd[i][0]);
+ }
+ }
+}
+
+static int linkstation_reset_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct resource *res;
+ struct clk *clk;
+ char symname[KSYM_NAME_LEN];
+
+ const struct of_device_id *match =
+ of_match_node(linkstation_reset_of_match_table, np);
+ cfg = match->data;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "Missing resource");
+ return -EINVAL;
+ }
+
+ base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!base) {
+ dev_err(&pdev->dev, "Unable to map resource");
+ return -EINVAL;
+ }
+
+ /* We need to know tclk in order to calculate the UART divisor */
+ clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "Clk missing");
+ return PTR_ERR(clk);
+ }
+
+ tclk = clk_get_rate(clk);
+
+ /* Check that nothing else has already setup a handler */
+ if (pm_power_off) {
+ lookup_symbol_name((ulong)pm_power_off, symname);
+ dev_err(&pdev->dev,
+ "pm_power_off already claimed %p %s",
+ pm_power_off, symname);
+ return -EBUSY;
+ }
+ pm_power_off = linkstation_reset;
+
+ return 0;
+}
+
+static int linkstation_reset_remove(struct platform_device *pdev)
+{
+ pm_power_off = NULL;
+ return 0;
+}
+
+static struct platform_driver linkstation_reset_driver = {
+ .probe = linkstation_reset_probe,
+ .remove = linkstation_reset_remove,
+ .driver = {
+ .name = "linkstation_reset",
+ .of_match_table = of_match_ptr(linkstation_reset_of_match_table),
+ },
+};
+
+module_platform_driver(linkstation_reset_driver);
+
+MODULE_AUTHOR("Roger Shimizu <rogershimizu@gmail.com>");
+MODULE_DESCRIPTION("KuroBox Pro Reset driver");
+MODULE_LICENSE("GPL v2");
--
2.10.2
^ permalink raw reply related [flat|nested] 44+ messages in thread
* Re: [PATCH v2] power: reset: add linkstation-reset driver
2016-12-16 10:05 ` [PATCH v2] power: reset: add linkstation-reset driver Roger Shimizu
@ 2016-12-19 0:34 ` Roger Shimizu
2016-12-19 15:38 ` Sebastian Reichel
2016-12-27 7:06 ` [PATCH v3 0/3] make kurobox-pro be able to shutdown after device-tree migration Roger Shimizu
2 siblings, 0 replies; 44+ messages in thread
From: Roger Shimizu @ 2016-12-19 0:34 UTC (permalink / raw)
To: Sebastian Reichel, linux-pm
Cc: Andrew Lunn, Ryan Tandy, Martin Michlmayr, Sylver Bruneau,
Herbert Valerio Riedel
On Fri, 16 Dec 2016 19:05:01 +0900
Roger Shimizu <rogershimizu@gmail.com> wrote:
> Buffalo Linkstation / KuroBox and their variants need magic command
> sending to UART1 to power-off.
>
> Power driver linkstation-reset implements the magic command and I/O
> routine, which come from files listed below:
> - arch/arm/mach-orion5x/kurobox_pro-setup.c
> - arch/arm/mach-orion5x/terastation_pro2-setup.c
>
> Cc: Andrew Lunn <andrew@lunn.ch>
> Cc: Martin Michlmayr <tbm@cyrius.com>
> Cc: Sylver Bruneau <sylver.bruneau@googlemail.com>
> Cc: Herbert Valerio Riedel <hvr@gnu.org>
> Reported-by: Ryan Tandy <ryan@nardis.ca>
> Signed-off-by: Roger Shimizu <rogershimizu@gmail.com>
> ---
Original reporter Ryan Tandy told me in a separate email that he has confirmed my patch works on his Linkstation Pro device.
So please add:
Tested-by: Ryan Tandy <ryan@nardis.ca>
when merging this patch. Thank you!
Cheers,
--
Roger Shimizu, GMT +9 Tokyo
PGP/GPG: 4096R/6C6ACD6417B3ACB1
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH v2] power: reset: add linkstation-reset driver
2016-12-16 10:05 ` [PATCH v2] power: reset: add linkstation-reset driver Roger Shimizu
2016-12-19 0:34 ` Roger Shimizu
@ 2016-12-19 15:38 ` Sebastian Reichel
2016-12-19 16:03 ` Andrew Lunn
2016-12-19 17:37 ` Roger Shimizu
2016-12-27 7:06 ` [PATCH v3 0/3] make kurobox-pro be able to shutdown after device-tree migration Roger Shimizu
2 siblings, 2 replies; 44+ messages in thread
From: Sebastian Reichel @ 2016-12-19 15:38 UTC (permalink / raw)
To: Roger Shimizu, Rob Herring
Cc: linux-pm, Andrew Lunn, Ryan Tandy, Martin Michlmayr,
Sylver Bruneau, Herbert Valerio Riedel, Mark Rutland, devicetree
[-- Attachment #1: Type: text/plain, Size: 15717 bytes --]
Hi Roger,
On Fri, Dec 16, 2016 at 07:05:01PM +0900, Roger Shimizu wrote:
> Buffalo Linkstation / KuroBox and their variants need magic command
> sending to UART1 to power-off.
>
> Power driver linkstation-reset implements the magic command and I/O
> routine, which come from files listed below:
> - arch/arm/mach-orion5x/kurobox_pro-setup.c
> - arch/arm/mach-orion5x/terastation_pro2-setup.c
Ok.
> Cc: Andrew Lunn <andrew@lunn.ch>
> Cc: Martin Michlmayr <tbm@cyrius.com>
> Cc: Sylver Bruneau <sylver.bruneau@googlemail.com>
> Cc: Herbert Valerio Riedel <hvr@gnu.org>
> Reported-by: Ryan Tandy <ryan@nardis.ca>
> Signed-off-by: Roger Shimizu <rogershimizu@gmail.com>
> ---
> Dear Sebastian,
>
> Kurobox-Pro (and variants) need more commands sending to UART1 to shutdown.
> So here I make this patch series to let current qnap-poweroff implementation
> be able to handle such case.
>
> I already tested this change on Kurobox-Pro and Linkstation LS-GL devices,
> with a modified device-tree file. (Previous device-tree of kurobox-pro invokes
> restart-poweroff, so it simply restarts.)
>
> Thank you and look forward to your feedback!
>
> Dear Andrew,
>
> Thanks for your 2nd review!
>
> So I accept your suggestion and make the new driver for linkstation series.
>
> Changes:
> v0 => v1:
> - Update 0003 to split kuroboxpro related code into kuroboxpro-common.c
> v1 => v2:
> - Slipt off linkstation/kuroboxpro related code to linkstation-reset.c
> Because linkstation before kuroboxpro also need this driver to power
> off properly. It's more proper to call it linkstation driver.
>
> Cheers,
> --
> Roger Shimizu, GMT +9 Tokyo
> PGP/GPG: 4096R/6C6ACD6417B3ACB1
>
> .../bindings/power/reset/linkstation-reset.txt | 26 ++++
> drivers/power/reset/Kconfig | 10 ++
> drivers/power/reset/Makefile | 1 +
> drivers/power/reset/linkstation-common.c | 124 +++++++++++++++
> drivers/power/reset/linkstation-common.h | 8 +
> drivers/power/reset/linkstation-reset.c | 172 +++++++++++++++++++++
> 6 files changed, 341 insertions(+)
With this being its own driver please merge linkstation-common and
linkstation-reset. The common part is only used by linkstation-reset
anyways.
> create mode 100644 Documentation/devicetree/bindings/power/reset/linkstation-reset.txt
This patch is missing Cc for DT binding people (check "OPEN FIRMWARE
AND FLATTENED DEVICE TREE BINDINGS" in MAINTAINERS file).
> create mode 100644 drivers/power/reset/linkstation-common.c
> create mode 100644 drivers/power/reset/linkstation-common.h
> create mode 100644 drivers/power/reset/linkstation-reset.c
>
> diff --git a/Documentation/devicetree/bindings/power/reset/linkstation-reset.txt b/Documentation/devicetree/bindings/power/reset/linkstation-reset.txt
> new file mode 100644
> index 0000000..815e340
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/power/reset/linkstation-reset.txt
> @@ -0,0 +1,26 @@
> +* Buffalo Linkstation Reset Driver
> +
> +Power of some Buffalo Linkstation or KuroBox Pro is managed by
> +micro-controller, which connects to UART1. After being fed from UART1
> +by a few magic numbers, the so-called power-off command,
> +the micro-controller will turn power off the device.
> +
> +This is very similar to QNAP or Synology NAS devices, which is
> +described in qnap-poweroff.txt, however the command is much simpler,
> +only 1-byte long and without checksums.
> +
> +This driver adds a handler to pm_power_off which is called to turn the
> +power off.
> +
> +Required Properties:
> +- compatible: Should be "linkstation,power-off"
> +- reg: Address and length of the register set for UART1
> +- clocks: tclk clock
> +
> +Example:
> +
> + reset {
> + compatible = "linkstation,power-off";
> + reg = <0x12100 0x100>;
> + clocks = <&core_clk 0>;
> + };
This might be another user for UART slave device [0].
[0] https://lkml.org/lkml/2016/8/24/769
Is the UART port used for anything else besides the reset
controller?
> diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
> index c74c3f6..77c44ca 100644
> --- a/drivers/power/reset/Kconfig
> +++ b/drivers/power/reset/Kconfig
> @@ -98,6 +98,16 @@ config POWER_RESET_IMX
> say N here or disable in dts to make sure pm_power_off never be
> overwrote wrongly by this driver.
>
> +config POWER_RESET_LINKSTATION
> + bool "Buffalo Linkstation and its variants reset driver"
> + depends on OF_GPIO && PLAT_ORION
> + help
> + This driver supports power off Buffalo Linkstation / KuroBox Pro
> + NAS and their variants by sending commands to the micro-controller
> + which controls the main power.
> +
> + Say Y if you have a Buffalo Linkstation / KuroBox Pro NAS.
> +
> config POWER_RESET_MSM
> bool "Qualcomm MSM power-off driver"
> depends on ARCH_QCOM
> diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
> index 1be307c..520afbe 100644
> --- a/drivers/power/reset/Makefile
> +++ b/drivers/power/reset/Makefile
> @@ -9,6 +9,7 @@ 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
> obj-$(CONFIG_POWER_RESET_IMX) += imx-snvs-poweroff.o
> +obj-$(CONFIG_POWER_RESET_LINKSTATION) += linkstation-reset.o linkstation-common.o
> obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
> obj-$(CONFIG_POWER_RESET_LTC2952) += ltc2952-poweroff.o
> obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
> diff --git a/drivers/power/reset/linkstation-common.c b/drivers/power/reset/linkstation-common.c
> new file mode 100644
> index 0000000..a6d0930
> --- /dev/null
> +++ b/drivers/power/reset/linkstation-common.c
> @@ -0,0 +1,124 @@
> +/*
> + * Common I/O routine for micro-controller of Buffalo Linkstation
> + * and its variants.
> + *
> + * Copyright (C) 2016 Roger Shimizu <rogershimizu@gmail.com>
> + *
> + * Based on the code from:
> + *
> + * Copyright (C) 2008 Sylver Bruneau <sylver.bruneau@googlemail.com>
> + * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version
> + * 2 of the License, or (at your option) any later version.
> + */
> +
> +#include <linux/serial_reg.h>
> +#include <linux/io.h>
> +#include <linux/delay.h>
> +#include "linkstation-common.h"
> +
> +static int uart1_micon_read(void *base, unsigned char *buf, int count)
> +{
> + int i;
> + int timeout;
> +
> + for (i = 0; i < count; i++) {
> + timeout = 10;
> +
> + while (!(readl(UART1_REG(LSR)) & UART_LSR_DR)) {
> + if (--timeout == 0)
> + break;
> + udelay(1000);
> + }
> +
> + if (timeout == 0)
> + break;
> + buf[i] = readl(UART1_REG(RX));
> + }
> +
> + /* return read bytes */
> + return i;
> +}
> +
> +static int uart1_micon_write(void *base, const unsigned char *buf, int count)
> +{
> + int i = 0;
> +
> + while (count--) {
> + while (!(readl(UART1_REG(LSR)) & UART_LSR_THRE))
> + barrier();
> + writel(buf[i++], UART1_REG(TX));
> + }
> +
> + return 0;
> +}
> +
> +int uart1_micon_send(void *base, const unsigned char *data, int count)
> +{
> + int i;
> + unsigned char checksum = 0;
> + unsigned char recv_buf[40];
> + unsigned char send_buf[40];
> + unsigned char correct_ack[3];
> + int retry = 2;
> +
> + /* Generate checksum */
> + for (i = 0; i < count; i++)
> + checksum -= data[i];
> +
> + do {
> + /* Send data */
> + uart1_micon_write(base, data, count);
> +
> + /* send checksum */
> + uart1_micon_write(base, &checksum, 1);
> +
> + if (uart1_micon_read(base, recv_buf, sizeof(recv_buf)) <= 3) {
> + printk(KERN_ERR ">%s: receive failed.\n", __func__);
> +
> + /* send preamble to clear the receive buffer */
> + memset(&send_buf, 0xff, sizeof(send_buf));
> + uart1_micon_write(base, send_buf, sizeof(send_buf));
> +
> + /* make dummy reads */
> + mdelay(100);
> + uart1_micon_read(base, recv_buf, sizeof(recv_buf));
> + } else {
> + /* Generate expected ack */
> + correct_ack[0] = 0x01;
> + correct_ack[1] = data[1];
> + correct_ack[2] = 0x00;
> +
> + /* checksum Check */
> + if ((recv_buf[0] + recv_buf[1] + recv_buf[2] +
> + recv_buf[3]) & 0xFF) {
> + printk(KERN_ERR ">%s: Checksum Error : "
> + "Received data[%02x, %02x, %02x, %02x]"
> + "\n", __func__, recv_buf[0],
> + recv_buf[1], recv_buf[2], recv_buf[3]);
> + } else {
> + /* Check Received Data */
> + if (correct_ack[0] == recv_buf[0] &&
> + correct_ack[1] == recv_buf[1] &&
> + correct_ack[2] == recv_buf[2]) {
> + /* Interval for next command */
> + mdelay(10);
> +
> + /* Receive ACK */
> + return 0;
> + }
> + }
> + /* Received NAK or illegal Data */
> + printk(KERN_ERR ">%s: Error : NAK or Illegal Data "
> + "Received\n", __func__);
> + }
> + } while (retry--);
> +
> + /* Interval for next command */
> + mdelay(10);
> +
> + return -1;
> +}
> diff --git a/drivers/power/reset/linkstation-common.h b/drivers/power/reset/linkstation-common.h
> new file mode 100644
> index 0000000..89c64a9
> --- /dev/null
> +++ b/drivers/power/reset/linkstation-common.h
> @@ -0,0 +1,8 @@
> +#ifndef __LINKSTATION_COMMON_H__
> +#define __LINKSTATION_COMMON_H__
> +
> +#define UART1_REG(x) (base + ((UART_##x) << 2))
> +
> +int uart1_micon_send(void *base, const unsigned char *data, int count);
> +
> +#endif
> diff --git a/drivers/power/reset/linkstation-reset.c b/drivers/power/reset/linkstation-reset.c
> new file mode 100644
> index 0000000..78a0137
> --- /dev/null
> +++ b/drivers/power/reset/linkstation-reset.c
> @@ -0,0 +1,172 @@
> +/*
> + * Buffalo Linkstation power reset driver.
> + * It may also be used on following devices:
> + * - Buffalo Linkstation HG
> + * - KuroBox HG
> + * - Buffalo KURO-NAS/T4
> + * - KuroBox Pro
> + * - Buffalo Linkstation Pro (LS-GL)
> + * - Buffalo Terastation Pro II/Live
> + * - Buffalo Linkstation Duo (LS-WTGL)
> + * - Buffalo Linkstation Mini (LS-WSGL)
> + *
> + * Copyright (C) 2016 Roger Shimizu <rogershimizu@gmail.com>
> + *
> + * Based on the code from:
> + *
> + * Copyright (C) 2012 Andrew Lunn <andrew@lunn.ch>
> + * Copyright (C) 2009 Martin Michlmayr <tbm@cyrius.com>
> + * Copyright (C) 2008 Byron Bradley <byron.bbradley@gmail.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version
> + * 2 of the License, or (at your option) any later version.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/serial_reg.h>
> +#include <linux/kallsyms.h>
> +#include <linux/of.h>
> +#include <linux/io.h>
> +#include <linux/clk.h>
> +#include "linkstation-common.h"
> +
> +#define MICON_CMD_SIZE 4
> +
> +/* 4-byte magic hello command to UART1-attached microcontroller */
> +static const unsigned char linkstation_micon_magic[] = {
> + 0x1b,
> + 0x00,
> + 0x07,
> + 0x00
> +};
4-byte magic hello command? Those are used as uart configuration as
far as I can see. Just move this directly into reset_cfg:
struct reset_cfg {
u32 baud;
u8 lcr;
u8 ier;
u8 fcr;
u8 mcr;
const unsigned char (*cmd)[MICON_CMD_SIZE];
};
> +// for each row, first byte is the size of command
> +static const unsigned char linkstation_power_off_cmd[][MICON_CMD_SIZE] = {
> + { 3, 0x01, 0x35, 0x00},
> + { 2, 0x00, 0x0c},
> + { 2, 0x00, 0x06},
> + {}
> +};
> +
> +struct reset_cfg {
> + u32 baud;
> + const unsigned char *magic;
> + const unsigned char (*cmd)[MICON_CMD_SIZE];
> +};
> +
> +static const struct reset_cfg linkstation_power_off_cfg = {
> + .baud = 38400,
> + .magic = linkstation_micon_magic,
> + .cmd = linkstation_power_off_cmd,
> +};
> +
> +static const struct of_device_id linkstation_reset_of_match_table[] = {
> + { .compatible = "linkstation,power-off",
> + .data = &linkstation_power_off_cfg,
> + },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, linkstation_reset_of_match_table);
> +
> +static void __iomem *base;
> +static unsigned long tclk;
> +static const struct reset_cfg *cfg;
> +
> +static void linkstation_reset(void)
> +{
> + const unsigned divisor = ((tclk + (8 * cfg->baud)) / (16 * cfg->baud));
> +
> + pr_err("%s: triggering power-off...\n", __func__);
> +
> + /* hijack UART1 and reset into sane state */
> + writel(0x83, UART1_REG(LCR));
> + writel(divisor & 0xff, UART1_REG(DLL));
> + writel((divisor >> 8) & 0xff, UART1_REG(DLM));
> + writel(cfg->magic[0], UART1_REG(LCR));
> + writel(cfg->magic[1], UART1_REG(IER));
> + writel(cfg->magic[2], UART1_REG(FCR));
> + writel(cfg->magic[3], UART1_REG(MCR));
> +
> + /* send the power-off command to PIC */
> + if(cfg->cmd[0][0] == 1 && cfg->cmd[1][0] == 0) {
> + /* if it's simply one-byte command, send it directly */
> + writel(cfg->cmd[0][1], UART1_REG(TX));
> + }
I guess this optimization can be dropped and you can directly
call the for loop with uart1_micon_send().
> + else {
> + int i;
> + for(i = 0; cfg->cmd[i][0] > 0; i ++) {
> + /* [0] is size of the command; command starts from [1] */
> + uart1_micon_send(base, &(cfg->cmd[i][1]), cfg->cmd[i][0]);
> + }
> + }
> +}
> +
> +static int linkstation_reset_probe(struct platform_device *pdev)
> +{
> + struct device_node *np = pdev->dev.of_node;
> + struct resource *res;
> + struct clk *clk;
> + char symname[KSYM_NAME_LEN];
> +
> + const struct of_device_id *match =
> + of_match_node(linkstation_reset_of_match_table, np);
> + cfg = match->data;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!res) {
> + dev_err(&pdev->dev, "Missing resource");
> + return -EINVAL;
> + }
> +
> + base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
> + if (!base) {
> + dev_err(&pdev->dev, "Unable to map resource");
> + return -EINVAL;
> + }
> +
> + /* We need to know tclk in order to calculate the UART divisor */
> + clk = devm_clk_get(&pdev->dev, NULL);
> + if (IS_ERR(clk)) {
> + dev_err(&pdev->dev, "Clk missing");
> + return PTR_ERR(clk);
> + }
> +
> + tclk = clk_get_rate(clk);
> +
> + /* Check that nothing else has already setup a handler */
> + if (pm_power_off) {
> + lookup_symbol_name((ulong)pm_power_off, symname);
> + dev_err(&pdev->dev,
> + "pm_power_off already claimed %p %s",
> + pm_power_off, symname);
> + return -EBUSY;
> + }
> + pm_power_off = linkstation_reset;
> +
> + return 0;
> +}
> +
> +static int linkstation_reset_remove(struct platform_device *pdev)
> +{
> + pm_power_off = NULL;
> + return 0;
> +}
> +
> +static struct platform_driver linkstation_reset_driver = {
> + .probe = linkstation_reset_probe,
> + .remove = linkstation_reset_remove,
> + .driver = {
> + .name = "linkstation_reset",
> + .of_match_table = of_match_ptr(linkstation_reset_of_match_table),
> + },
> +};
> +
> +module_platform_driver(linkstation_reset_driver);
> +
> +MODULE_AUTHOR("Roger Shimizu <rogershimizu@gmail.com>");
> +MODULE_DESCRIPTION("KuroBox Pro Reset driver");
> +MODULE_LICENSE("GPL v2");
-- Sebastian
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH v2] power: reset: add linkstation-reset driver
2016-12-19 15:38 ` Sebastian Reichel
@ 2016-12-19 16:03 ` Andrew Lunn
2016-12-19 16:12 ` Roger Shimizu
2016-12-19 17:37 ` Roger Shimizu
1 sibling, 1 reply; 44+ messages in thread
From: Andrew Lunn @ 2016-12-19 16:03 UTC (permalink / raw)
To: Sebastian Reichel
Cc: Roger Shimizu, Rob Herring, linux-pm, Ryan Tandy,
Martin Michlmayr, Sylver Bruneau, Herbert Valerio Riedel,
Mark Rutland, devicetree
> > + reset {
> > + compatible = "linkstation,power-off";
> > + reg = <0x12100 0x100>;
> > + clocks = <&core_clk 0>;
> > + };
>
> This might be another user for UART slave device [0].
> [0] https://lkml.org/lkml/2016/8/24/769
>
> Is the UART port used for anything else besides the reset
> controller?
I don't know much about these specific devices, but the qnap
equivalent, there is a user space daemon which also talks to the
microcontroller, for things like a temperature sensor, buzzer, etc.
https://www.hellion.org.uk/qcontrol/
So the UART can be in a messed up state, which is why the QNAP driver,
which this code is modelled on, reset it back to a good state.
Andrew
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH v2] power: reset: add linkstation-reset driver
2016-12-19 16:03 ` Andrew Lunn
@ 2016-12-19 16:12 ` Roger Shimizu
0 siblings, 0 replies; 44+ messages in thread
From: Roger Shimizu @ 2016-12-19 16:12 UTC (permalink / raw)
To: Andrew Lunn, Sebastian Reichel
Cc: Rob Herring, linux-pm, Ryan Tandy, Martin Michlmayr,
Sylver Bruneau, Herbert Valerio Riedel, Mark Rutland, devicetree
Thanks for your review!
On Tue, Dec 20, 2016 at 1:03 AM, Andrew Lunn <andrew@lunn.ch> wrote:
>> > + reset {
>> > + compatible = "linkstation,power-off";
>> > + reg = <0x12100 0x100>;
>> > + clocks = <&core_clk 0>;
>> > + };
>>
>> This might be another user for UART slave device [0].
>> [0] https://lkml.org/lkml/2016/8/24/769
>>
>> Is the UART port used for anything else besides the reset
>> controller?
>
> I don't know much about these specific devices, but the qnap
> equivalent, there is a user space daemon which also talks to the
> microcontroller, for things like a temperature sensor, buzzer, etc.
>
> https://www.hellion.org.uk/qcontrol/
>
> So the UART can be in a messed up state, which is why the QNAP driver,
> which this code is modelled on, reset it back to a good state.
For Linkstation/KuroBox-Pro, it's quite similar, and the user-land program is
called micro-evtd [0], which is co-maintained by Ryan Tandy and me in Debian.
[0] https://tracker.debian.org/pkg/micro-evtd
>> [0] https://lkml.org/lkml/2016/8/24/769
Do I need to modify anything related to the above UART slave device?
Cheers,
--
Roger Shimizu, GMT +9 Tokyo
PGP/GPG: 4096R/6C6ACD6417B3ACB1
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH v2] power: reset: add linkstation-reset driver
2016-12-19 15:38 ` Sebastian Reichel
2016-12-19 16:03 ` Andrew Lunn
@ 2016-12-19 17:37 ` Roger Shimizu
[not found] ` <CAEQ9gEnQEHdcA4ox3teOXKcrdf2AAqUMp=A6W6c7nXhk4VrKiw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
1 sibling, 1 reply; 44+ messages in thread
From: Roger Shimizu @ 2016-12-19 17:37 UTC (permalink / raw)
To: Sebastian Reichel, Rob Herring
Cc: linux-pm, Andrew Lunn, Ryan Tandy, Martin Michlmayr,
Sylver Bruneau, Herbert Valerio Riedel, Mark Rutland, devicetree
Dear Sebastian,
Thanks for your review!
On Tue, Dec 20, 2016 at 12:38 AM, Sebastian Reichel <sre@kernel.org> wrote:
>>
>> .../bindings/power/reset/linkstation-reset.txt | 26 ++++
>> drivers/power/reset/Kconfig | 10 ++
>> drivers/power/reset/Makefile | 1 +
>> drivers/power/reset/linkstation-common.c | 124 +++++++++++++++
>> drivers/power/reset/linkstation-common.h | 8 +
>> drivers/power/reset/linkstation-reset.c | 172 +++++++++++++++++++++
>> 6 files changed, 341 insertions(+)
>
> With this being its own driver please merge linkstation-common and
> linkstation-reset. The common part is only used by linkstation-reset
> anyways.
I'll add them into To/Cc list.
>> +/* 4-byte magic hello command to UART1-attached microcontroller */
>> +static const unsigned char linkstation_micon_magic[] = {
>> + 0x1b,
>> + 0x00,
>> + 0x07,
>> + 0x00
>> +};
>
> 4-byte magic hello command? Those are used as uart configuration as
> far as I can see. Just move this directly into reset_cfg:
>
> struct reset_cfg {
> u32 baud;
> u8 lcr;
> u8 ier;
> u8 fcr;
> u8 mcr;
> const unsigned char (*cmd)[MICON_CMD_SIZE];
> };
>
>> +static void linkstation_reset(void)
>> +{
>> + const unsigned divisor = ((tclk + (8 * cfg->baud)) / (16 * cfg->baud));
>> +
>> + pr_err("%s: triggering power-off...\n", __func__);
>> +
>> + /* hijack UART1 and reset into sane state */
>> + writel(0x83, UART1_REG(LCR));
>> + writel(divisor & 0xff, UART1_REG(DLL));
>> + writel((divisor >> 8) & 0xff, UART1_REG(DLM));
>> + writel(cfg->magic[0], UART1_REG(LCR));
>> + writel(cfg->magic[1], UART1_REG(IER));
>> + writel(cfg->magic[2], UART1_REG(FCR));
>> + writel(cfg->magic[3], UART1_REG(MCR));
>> +
>> + /* send the power-off command to PIC */
>> + if(cfg->cmd[0][0] == 1 && cfg->cmd[1][0] == 0) {
>> + /* if it's simply one-byte command, send it directly */
>> + writel(cfg->cmd[0][1], UART1_REG(TX));
>> + }
>
> I guess this optimization can be dropped and you can directly
> call the for loop with uart1_micon_send().
Same response regarding above two comments.
The code is extensible because I want to extend in the future.
Current implementation is just for Linkstation Pro / KuroBox Pro to be
able to power-off.
But for some other model of Linkstation, restart also need similar
command via UART1.
Just one example, Linkstation Pro is ARM based, but it was PowerPC based before.
And the device support still exists in kernel tree:
arch/powerpc/platforms/embedded6xx/linkstation.c
arch/powerpc/platforms/embedded6xx/ls_uart.c
It shows sending "C" to restart and sending "E" to power-off for
PowerPC based Linkstation.
I'm not actually interested in PowerPC based Linkstation, it's just an
example to show the reason to be flexible.
If other part is fine, may I send the v3 patch after merging
linkstation-common.c into linkstation-reset.c?
Thank you!
Cheers,
--
Roger Shimizu, GMT +9 Tokyo
PGP/GPG: 4096R/6C6ACD6417B3ACB1
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH v3 0/3] make kurobox-pro be able to shutdown after device-tree migration
2016-12-16 10:05 ` [PATCH v2] power: reset: add linkstation-reset driver Roger Shimizu
2016-12-19 0:34 ` Roger Shimizu
2016-12-19 15:38 ` Sebastian Reichel
@ 2016-12-27 7:06 ` Roger Shimizu
2016-12-27 7:06 ` [PATCH v3 1/3] power: reset: add linkstation-reset driver Roger Shimizu
` (3 more replies)
2 siblings, 4 replies; 44+ messages in thread
From: Roger Shimizu @ 2016-12-27 7:06 UTC (permalink / raw)
To: Sebastian Reichel, Rob Herring, Mark Rutland, Jason Cooper,
Andrew Lunn, Gregory Clement, Sebastian Hesselbarth
Cc: Roger Shimizu, Ryan Tandy, linux-pm, devicetree, linux-arm-kernel
Dear Kernel Maintainers,
Kurobox-Pro (and variants) need more commands sending to UART1 to shutdown.
So here I make this patch series to let current qnap-poweroff implementation
be able to handle such case.
Here I give 3 patches, for 3 different kernel subsystems respectivelay:
- Patch 1/3: System reset/shutdown driver
- Patch 2/3: Open firmware and flattened device tree bindings
- Patch 3/3: ARM/Marvell Dove/MV78xx0/Orion SOC support
Ryan Tandy, the issue reporter, and I have already tested those changes on
Linkstation/KuroBoxPro devices, and confirmed it's working well.
Merry Xmax and look forward to your feedback!
Changes:
v0 => v1:
- Update 0003 to split kuroboxpro related code into kuroboxpro-common.c
v1 => v2:
- Split off linkstation/kuroboxpro related code to linkstation-reset.c
Because linkstation before kuroboxpro also need this driver to power
off properly. It's more proper to call it linkstation driver.
v2 => v3:
- Split off devicetree bindings doc into a separate patch.
- Add device-tree patch to make Linkstation LS-GL and KuroBox Pro to
use the newly created linkstation-reset driver.
- Remove the unused one-byte command sending case in linkstation-reset
driver.
Cheers,
Roger Shimizu, GMT +9 Tokyo
PGP/GPG: 4096R/6C6ACD6417B3ACB1
Roger Shimizu (3):
power: reset: add linkstation-reset driver
DT: bingdings: power: reset: add linkstation-reset doc
ARM: DT: add power-off support to linkstation lsgl and kuroboxpro
.../bindings/power/reset/linkstation-reset.txt | 26 ++
arch/arm/boot/dts/orion5x-kuroboxpro.dts | 8 +
arch/arm/boot/dts/orion5x-linkstation-lsgl.dts | 10 +
arch/arm/boot/dts/orion5x-linkstation-lswtgl.dts | 4 +
arch/arm/boot/dts/orion5x-linkstation.dtsi | 4 -
drivers/power/reset/Kconfig | 10 +
drivers/power/reset/Makefile | 1 +
drivers/power/reset/linkstation-reset.c | 269 +++++++++++++++++++++
8 files changed, 328 insertions(+), 4 deletions(-)
create mode 100644 Documentation/devicetree/bindings/power/reset/linkstation-reset.txt
create mode 100644 drivers/power/reset/linkstation-reset.c
--
2.11.0
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH v3 1/3] power: reset: add linkstation-reset driver
2016-12-27 7:06 ` [PATCH v3 0/3] make kurobox-pro be able to shutdown after device-tree migration Roger Shimizu
@ 2016-12-27 7:06 ` Roger Shimizu
[not found] ` <20161227070611.14852-2-rogershimizu-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2016-12-27 7:06 ` [PATCH v3 2/3] DT: bingdings: power: reset: add linkstation-reset doc Roger Shimizu
` (2 subsequent siblings)
3 siblings, 1 reply; 44+ messages in thread
From: Roger Shimizu @ 2016-12-27 7:06 UTC (permalink / raw)
To: Sebastian Reichel
Cc: Roger Shimizu, Andrew Lunn, Martin Michlmayr, Sylver Bruneau,
Herbert Valerio Riedel, Ryan Tandy, linux-pm, devicetree,
linux-arm-kernel
Buffalo Linkstation / KuroBox and their variants need magic command
sending to UART1 to power-off.
Power driver linkstation-reset implements the magic command and I/O
routine, which come from files listed below:
- arch/arm/mach-orion5x/kurobox_pro-setup.c
- arch/arm/mach-orion5x/terastation_pro2-setup.c
To: Sebastian Reichel <sre@kernel.org>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Martin Michlmayr <tbm@cyrius.com>
Cc: Sylver Bruneau <sylver.bruneau@googlemail.com>
Cc: Herbert Valerio Riedel <hvr@gnu.org>
Cc: Ryan Tandy <ryan@nardis.ca>
Cc: linux-pm@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Reported-by: Ryan Tandy <ryan@nardis.ca>
Tested-by: Ryan Tandy <ryan@nardis.ca>
Signed-off-by: Roger Shimizu <rogershimizu@gmail.com>
---
drivers/power/reset/Kconfig | 10 ++
drivers/power/reset/Makefile | 1 +
drivers/power/reset/linkstation-reset.c | 269 ++++++++++++++++++++++++++++++++
3 files changed, 280 insertions(+)
create mode 100644 drivers/power/reset/linkstation-reset.c
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index c74c3f67b8da..77c44cad7ece 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -98,6 +98,16 @@ config POWER_RESET_IMX
say N here or disable in dts to make sure pm_power_off never be
overwrote wrongly by this driver.
+config POWER_RESET_LINKSTATION
+ bool "Buffalo Linkstation and its variants reset driver"
+ depends on OF_GPIO && PLAT_ORION
+ help
+ This driver supports power off Buffalo Linkstation / KuroBox Pro
+ NAS and their variants by sending commands to the micro-controller
+ which controls the main power.
+
+ Say Y if you have a Buffalo Linkstation / KuroBox Pro NAS.
+
config POWER_RESET_MSM
bool "Qualcomm MSM power-off driver"
depends on ARCH_QCOM
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index 1be307c7fc25..692ba6417cfb 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -9,6 +9,7 @@ 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
obj-$(CONFIG_POWER_RESET_IMX) += imx-snvs-poweroff.o
+obj-$(CONFIG_POWER_RESET_LINKSTATION) += linkstation-reset.o
obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
obj-$(CONFIG_POWER_RESET_LTC2952) += ltc2952-poweroff.o
obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
diff --git a/drivers/power/reset/linkstation-reset.c b/drivers/power/reset/linkstation-reset.c
new file mode 100644
index 000000000000..4390495dfe0e
--- /dev/null
+++ b/drivers/power/reset/linkstation-reset.c
@@ -0,0 +1,269 @@
+/*
+ * Buffalo Linkstation power reset driver.
+ * It may also be used on following devices:
+ * - KuroBox Pro
+ * - Buffalo Linkstation Pro (LS-GL)
+ * - Buffalo Terastation Pro II/Live
+ * - Buffalo Linkstation Duo (LS-WTGL)
+ * - Buffalo Linkstation Mini (LS-WSGL)
+ *
+ * Copyright (C) 2016 Roger Shimizu <rogershimizu@gmail.com>
+ *
+ * Based on the code from:
+ *
+ * Copyright (C) 2012 Andrew Lunn <andrew@lunn.ch>
+ * Copyright (C) 2009 Martin Michlmayr <tbm@cyrius.com>
+ * Copyright (C) 2008 Byron Bradley <byron.bbradley@gmail.com>
+ * Copyright (C) 2008 Sylver Bruneau <sylver.bruneau@googlemail.com>
+ * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/serial_reg.h>
+#include <linux/kallsyms.h>
+#include <linux/of.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+
+#define UART1_REG(x) (base + ((UART_##x) << 2))
+#define MICON_CMD_SIZE 4
+
+/* 4-byte magic hello command to UART1-attached microcontroller */
+static const unsigned char linkstation_micon_magic[] = {
+ 0x1b,
+ 0x00,
+ 0x07,
+ 0x00
+};
+
+/* for each row, first byte is the size of command */
+static const unsigned char linkstation_power_off_cmd[][MICON_CMD_SIZE] = {
+ { 3, 0x01, 0x35, 0x00},
+ { 2, 0x00, 0x0c},
+ { 2, 0x00, 0x06},
+ {}
+};
+
+struct reset_cfg {
+ u32 baud;
+ const unsigned char *magic;
+ const unsigned char (*cmd)[MICON_CMD_SIZE];
+};
+
+static const struct reset_cfg linkstation_power_off_cfg = {
+ .baud = 38400,
+ .magic = linkstation_micon_magic,
+ .cmd = linkstation_power_off_cmd,
+};
+
+static const struct of_device_id linkstation_reset_of_match_table[] = {
+ { .compatible = "linkstation,power-off",
+ .data = &linkstation_power_off_cfg,
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, linkstation_reset_of_match_table);
+
+static int uart1_micon_read(void *base, unsigned char *buf, int count)
+{
+ int i;
+ int timeout;
+
+ for (i = 0; i < count; i++) {
+ timeout = 10;
+
+ while (!(readl(UART1_REG(LSR)) & UART_LSR_DR)) {
+ if (--timeout == 0)
+ break;
+ udelay(1000);
+ }
+
+ if (timeout == 0)
+ break;
+ buf[i] = readl(UART1_REG(RX));
+ }
+
+ /* return read bytes */
+ return i;
+}
+
+static int uart1_micon_write(void *base, const unsigned char *buf, int count)
+{
+ int i = 0;
+
+ while (count--) {
+ while (!(readl(UART1_REG(LSR)) & UART_LSR_THRE))
+ barrier();
+ writel(buf[i++], UART1_REG(TX));
+ }
+
+ return 0;
+}
+
+int uart1_micon_send(void *base, const unsigned char *data, int count)
+{
+ int i;
+ unsigned char checksum = 0;
+ unsigned char recv_buf[40];
+ unsigned char send_buf[40];
+ unsigned char correct_ack[3];
+ int retry = 2;
+
+ /* Generate checksum */
+ for (i = 0; i < count; i++)
+ checksum -= data[i];
+
+ do {
+ /* Send data */
+ uart1_micon_write(base, data, count);
+
+ /* send checksum */
+ uart1_micon_write(base, &checksum, 1);
+
+ if (uart1_micon_read(base, recv_buf, sizeof(recv_buf)) <= 3) {
+ printk(KERN_ERR ">%s: receive failed.\n", __func__);
+
+ /* send preamble to clear the receive buffer */
+ memset(&send_buf, 0xff, sizeof(send_buf));
+ uart1_micon_write(base, send_buf, sizeof(send_buf));
+
+ /* make dummy reads */
+ mdelay(100);
+ uart1_micon_read(base, recv_buf, sizeof(recv_buf));
+ } else {
+ /* Generate expected ack */
+ correct_ack[0] = 0x01;
+ correct_ack[1] = data[1];
+ correct_ack[2] = 0x00;
+
+ /* checksum Check */
+ if ((recv_buf[0] + recv_buf[1] + recv_buf[2] +
+ recv_buf[3]) & 0xFF) {
+ printk(KERN_ERR ">%s: Checksum Error : "
+ "Received data[%02x, %02x, %02x, %02x]"
+ "\n", __func__, recv_buf[0],
+ recv_buf[1], recv_buf[2], recv_buf[3]);
+ } else {
+ /* Check Received Data */
+ if (correct_ack[0] == recv_buf[0] &&
+ correct_ack[1] == recv_buf[1] &&
+ correct_ack[2] == recv_buf[2]) {
+ /* Interval for next command */
+ mdelay(10);
+
+ /* Receive ACK */
+ return 0;
+ }
+ }
+ /* Received NAK or illegal Data */
+ printk(KERN_ERR ">%s: Error : NAK or Illegal Data "
+ "Received\n", __func__);
+ }
+ } while (retry--);
+
+ /* Interval for next command */
+ mdelay(10);
+
+ return -1;
+}
+
+static void __iomem *base;
+static unsigned long tclk;
+static const struct reset_cfg *cfg;
+
+static void linkstation_reset(void)
+{
+ const unsigned divisor = ((tclk + (8 * cfg->baud)) / (16 * cfg->baud));
+ int i;
+
+ pr_err("%s: triggering power-off...\n", __func__);
+
+ /* hijack UART1 and reset into sane state */
+ writel(0x83, UART1_REG(LCR));
+ writel(divisor & 0xff, UART1_REG(DLL));
+ writel((divisor >> 8) & 0xff, UART1_REG(DLM));
+ writel(cfg->magic[0], UART1_REG(LCR));
+ writel(cfg->magic[1], UART1_REG(IER));
+ writel(cfg->magic[2], UART1_REG(FCR));
+ writel(cfg->magic[3], UART1_REG(MCR));
+
+ /* send the power-off command to PIC */
+ for(i = 0; cfg->cmd[i][0] > 0; i ++) {
+ /* [0] is size of the command; command starts from [1] */
+ uart1_micon_send(base, &(cfg->cmd[i][1]), cfg->cmd[i][0]);
+ }
+}
+
+static int linkstation_reset_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct resource *res;
+ struct clk *clk;
+ char symname[KSYM_NAME_LEN];
+
+ const struct of_device_id *match =
+ of_match_node(linkstation_reset_of_match_table, np);
+ cfg = match->data;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "Missing resource");
+ return -EINVAL;
+ }
+
+ base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!base) {
+ dev_err(&pdev->dev, "Unable to map resource");
+ return -EINVAL;
+ }
+
+ /* We need to know tclk in order to calculate the UART divisor */
+ clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "Clk missing");
+ return PTR_ERR(clk);
+ }
+
+ tclk = clk_get_rate(clk);
+
+ /* Check that nothing else has already setup a handler */
+ if (pm_power_off) {
+ lookup_symbol_name((ulong)pm_power_off, symname);
+ dev_err(&pdev->dev,
+ "pm_power_off already claimed %p %s",
+ pm_power_off, symname);
+ return -EBUSY;
+ }
+ pm_power_off = linkstation_reset;
+
+ return 0;
+}
+
+static int linkstation_reset_remove(struct platform_device *pdev)
+{
+ pm_power_off = NULL;
+ return 0;
+}
+
+static struct platform_driver linkstation_reset_driver = {
+ .probe = linkstation_reset_probe,
+ .remove = linkstation_reset_remove,
+ .driver = {
+ .name = "linkstation_reset",
+ .of_match_table = of_match_ptr(linkstation_reset_of_match_table),
+ },
+};
+
+module_platform_driver(linkstation_reset_driver);
+
+MODULE_AUTHOR("Roger Shimizu <rogershimizu@gmail.com>");
+MODULE_DESCRIPTION("Linkstation Reset driver");
+MODULE_LICENSE("GPL v2");
--
2.11.0
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [PATCH v3 2/3] DT: bingdings: power: reset: add linkstation-reset doc
2016-12-27 7:06 ` [PATCH v3 0/3] make kurobox-pro be able to shutdown after device-tree migration Roger Shimizu
2016-12-27 7:06 ` [PATCH v3 1/3] power: reset: add linkstation-reset driver Roger Shimizu
@ 2016-12-27 7:06 ` Roger Shimizu
2017-01-03 5:21 ` Florian Fainelli
2017-01-03 17:09 ` Rob Herring
2016-12-27 7:06 ` [PATCH v3 3/3] ARM: DT: add power-off support to linkstation lsgl and kuroboxpro Roger Shimizu
2017-01-07 15:04 ` [PATCH v4 0/2] make kurobox-pro be able to shutdown after device-tree migration Roger Shimizu
3 siblings, 2 replies; 44+ messages in thread
From: Roger Shimizu @ 2016-12-27 7:06 UTC (permalink / raw)
To: Sebastian Reichel, Rob Herring, Mark Rutland
Cc: Roger Shimizu, Andrew Lunn, Ryan Tandy, linux-pm, devicetree,
linux-arm-kernel
Add linkstation-reset doc to describe the newly added
POWER_RESET_LINKSTATION driver, which controls magic command
sending to UART1 to power-off Buffalo Linkstation / KuroBox
and their variants.
To: Sebastian Reichel <sre@kernel.org>
To: Rob Herring <robh+dt@kernel.org>
To: Mark Rutland <mark.rutland@arm.com>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Ryan Tandy <ryan@nardis.ca>
Cc: linux-pm@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Signed-off-by: Roger Shimizu <rogershimizu@gmail.com>
---
.../bindings/power/reset/linkstation-reset.txt | 26 ++++++++++++++++++++++
1 file changed, 26 insertions(+)
create mode 100644 Documentation/devicetree/bindings/power/reset/linkstation-reset.txt
diff --git a/Documentation/devicetree/bindings/power/reset/linkstation-reset.txt b/Documentation/devicetree/bindings/power/reset/linkstation-reset.txt
new file mode 100644
index 000000000000..815e340318f3
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/reset/linkstation-reset.txt
@@ -0,0 +1,26 @@
+* Buffalo Linkstation Reset Driver
+
+Power of some Buffalo Linkstation or KuroBox Pro is managed by
+micro-controller, which connects to UART1. After being fed from UART1
+by a few magic numbers, the so-called power-off command,
+the micro-controller will turn power off the device.
+
+This is very similar to QNAP or Synology NAS devices, which is
+described in qnap-poweroff.txt, however the command is much simpler,
+only 1-byte long and without checksums.
+
+This driver adds a handler to pm_power_off which is called to turn the
+power off.
+
+Required Properties:
+- compatible: Should be "linkstation,power-off"
+- reg: Address and length of the register set for UART1
+- clocks: tclk clock
+
+Example:
+
+ reset {
+ compatible = "linkstation,power-off";
+ reg = <0x12100 0x100>;
+ clocks = <&core_clk 0>;
+ };
--
2.11.0
^ permalink raw reply related [flat|nested] 44+ messages in thread
* Re: [PATCH v3 2/3] DT: bingdings: power: reset: add linkstation-reset doc
2016-12-27 7:06 ` [PATCH v3 2/3] DT: bingdings: power: reset: add linkstation-reset doc Roger Shimizu
@ 2017-01-03 5:21 ` Florian Fainelli
2017-01-03 13:12 ` Andrew Lunn
2017-01-03 17:09 ` Rob Herring
1 sibling, 1 reply; 44+ messages in thread
From: Florian Fainelli @ 2017-01-03 5:21 UTC (permalink / raw)
To: Roger Shimizu, Sebastian Reichel, Rob Herring, Mark Rutland
Cc: Andrew Lunn, Ryan Tandy, linux-pm, devicetree, linux-arm-kernel
On 12/26/2016 11:06 PM, Roger Shimizu wrote:
> Add linkstation-reset doc to describe the newly added
> POWER_RESET_LINKSTATION driver, which controls magic command
> sending to UART1 to power-off Buffalo Linkstation / KuroBox
> and their variants.
>
> To: Sebastian Reichel <sre@kernel.org>
> To: Rob Herring <robh+dt@kernel.org>
> To: Mark Rutland <mark.rutland@arm.com>
> Cc: Andrew Lunn <andrew@lunn.ch>
> Cc: Ryan Tandy <ryan@nardis.ca>
> Cc: linux-pm@vger.kernel.org
> Cc: devicetree@vger.kernel.org
> Cc: linux-arm-kernel@lists.infradead.org
>
> Signed-off-by: Roger Shimizu <rogershimizu@gmail.com>
> ---
> .../bindings/power/reset/linkstation-reset.txt | 26 ++++++++++++++++++++++
> 1 file changed, 26 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/power/reset/linkstation-reset.txt
>
> diff --git a/Documentation/devicetree/bindings/power/reset/linkstation-reset.txt b/Documentation/devicetree/bindings/power/reset/linkstation-reset.txt
> new file mode 100644
> index 000000000000..815e340318f3
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/power/reset/linkstation-reset.txt
> @@ -0,0 +1,26 @@
> +* Buffalo Linkstation Reset Driver
> +
> +Power of some Buffalo Linkstation or KuroBox Pro is managed by
> +micro-controller, which connects to UART1. After being fed from UART1
> +by a few magic numbers, the so-called power-off command,
> +the micro-controller will turn power off the device.
> +
> +This is very similar to QNAP or Synology NAS devices, which is
> +described in qnap-poweroff.txt, however the command is much simpler,
> +only 1-byte long and without checksums.
> +
> +This driver adds a handler to pm_power_off which is called to turn the
> +power off.
This is a driver implementation detail, so does not really belong in the
DT here.
> +
> +Required Properties:
> +- compatible: Should be "linkstation,power-off"
> +- reg: Address and length of the register set for UART1
Humm, should we instead have a phandle to the uart1 node?
> +- clocks: tclk clock
> +
> +Example:
> +
> + reset {
> + compatible = "linkstation,power-off";
> + reg = <0x12100 0x100>;
> + clocks = <&core_clk 0>;
> + };
>
--
Florian
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH v3 2/3] DT: bingdings: power: reset: add linkstation-reset doc
2017-01-03 5:21 ` Florian Fainelli
@ 2017-01-03 13:12 ` Andrew Lunn
2017-01-03 14:11 ` Roger Shimizu
0 siblings, 1 reply; 44+ messages in thread
From: Andrew Lunn @ 2017-01-03 13:12 UTC (permalink / raw)
To: Florian Fainelli
Cc: Mark Rutland, devicetree, Ryan Tandy, linux-pm, Sebastian Reichel,
Rob Herring, Roger Shimizu, linux-arm-kernel
> > +
> > +Required Properties:
> > +- compatible: Should be "linkstation,power-off"
> > +- reg: Address and length of the register set for UART1
>
> Humm, should we instead have a phandle to the uart1 node?
Probably. Again, this is to do with copying the QNAP driver. I was
young, new to device tree, and i just did a logical conversion of the
existing code, and did not at the time understand phandles, etc.
Andrew
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH v3 2/3] DT: bingdings: power: reset: add linkstation-reset doc
2017-01-03 13:12 ` Andrew Lunn
@ 2017-01-03 14:11 ` Roger Shimizu
0 siblings, 0 replies; 44+ messages in thread
From: Roger Shimizu @ 2017-01-03 14:11 UTC (permalink / raw)
To: Andrew Lunn
Cc: Mark Rutland, devicetree, Florian Fainelli, Ryan Tandy, linux-pm,
Sebastian Reichel, Rob Herring, linux-arm-kernel
Dear Florian, Andrew,
Thanks for your comments!
On Tue, Jan 3, 2017 at 10:12 PM, Andrew Lunn <andrew@lunn.ch> wrote:
>> > +
>> > +Required Properties:
>> > +- compatible: Should be "linkstation,power-off"
>> > +- reg: Address and length of the register set for UART1
>>
>> Humm, should we instead have a phandle to the uart1 node?
>
> Probably. Again, this is to do with copying the QNAP driver. I was
> young, new to device tree, and i just did a logical conversion of the
> existing code, and did not at the time understand phandles, etc.
Can you tell me where should I place this document?
or simply remove it?
Cheers,
--
Roger Shimizu, GMT +9 Tokyo
PGP/GPG: 4096R/6C6ACD6417B3ACB1
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH v3 2/3] DT: bingdings: power: reset: add linkstation-reset doc
2016-12-27 7:06 ` [PATCH v3 2/3] DT: bingdings: power: reset: add linkstation-reset doc Roger Shimizu
2017-01-03 5:21 ` Florian Fainelli
@ 2017-01-03 17:09 ` Rob Herring
2017-01-06 12:18 ` Roger Shimizu
1 sibling, 1 reply; 44+ messages in thread
From: Rob Herring @ 2017-01-03 17:09 UTC (permalink / raw)
To: Roger Shimizu
Cc: Mark Rutland, Andrew Lunn, Ryan Tandy, devicetree, linux-pm,
Sebastian Reichel, linux-arm-kernel
On Tue, Dec 27, 2016 at 04:06:10PM +0900, Roger Shimizu wrote:
> Add linkstation-reset doc to describe the newly added
> POWER_RESET_LINKSTATION driver, which controls magic command
> sending to UART1 to power-off Buffalo Linkstation / KuroBox
> and their variants.
>
> To: Sebastian Reichel <sre@kernel.org>
> To: Rob Herring <robh+dt@kernel.org>
> To: Mark Rutland <mark.rutland@arm.com>
> Cc: Andrew Lunn <andrew@lunn.ch>
> Cc: Ryan Tandy <ryan@nardis.ca>
> Cc: linux-pm@vger.kernel.org
> Cc: devicetree@vger.kernel.org
> Cc: linux-arm-kernel@lists.infradead.org
>
> Signed-off-by: Roger Shimizu <rogershimizu@gmail.com>
> ---
> .../bindings/power/reset/linkstation-reset.txt | 26 ++++++++++++++++++++++
> 1 file changed, 26 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/power/reset/linkstation-reset.txt
>
> diff --git a/Documentation/devicetree/bindings/power/reset/linkstation-reset.txt b/Documentation/devicetree/bindings/power/reset/linkstation-reset.txt
> new file mode 100644
> index 000000000000..815e340318f3
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/power/reset/linkstation-reset.txt
> @@ -0,0 +1,26 @@
> +* Buffalo Linkstation Reset Driver
> +
> +Power of some Buffalo Linkstation or KuroBox Pro is managed by
> +micro-controller, which connects to UART1. After being fed from UART1
> +by a few magic numbers, the so-called power-off command,
> +the micro-controller will turn power off the device.
This needs to model the uC connected to the UART rather than some node
that defines only some portion of the functionality. I'm working on
bindings and proper bus support for this[1], but it's not done yet.
Though, the binding side is pretty simple.
Rob
[1] https://git.kernel.org/cgit/linux/kernel/git/robh/linux.git/log/?h=serial-bus-v2
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH v3 2/3] DT: bingdings: power: reset: add linkstation-reset doc
2017-01-03 17:09 ` Rob Herring
@ 2017-01-06 12:18 ` Roger Shimizu
0 siblings, 0 replies; 44+ messages in thread
From: Roger Shimizu @ 2017-01-06 12:18 UTC (permalink / raw)
To: Rob Herring, Florian Fainelli
Cc: Mark Rutland, Andrew Lunn, Ryan Tandy, devicetree, linux-pm,
Sebastian Reichel, linux-arm-kernel
Dear Rob,
Thanks for your comments!
On Wed, Jan 4, 2017 at 2:09 AM, Rob Herring <robh@kernel.org> wrote:
>
> This needs to model the uC connected to the UART rather than some node
> that defines only some portion of the functionality. I'm working on
> bindings and proper bus support for this[1], but it's not done yet.
> Though, the binding side is pretty simple.
>
> Rob
>
> [1] https://git.kernel.org/cgit/linux/kernel/git/robh/linux.git/log/?h=serial-bus-v2
Actually I have limited knowledge on DT binding.
I think it should be OK to remove the 2/3 patch (this thread) in my
next series, and I'll do my homework when you finish it.
Thank you!
Cheers,
--
Roger Shimizu, GMT +9 Tokyo
PGP/GPG: 4096R/6C6ACD6417B3ACB1
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH v3 3/3] ARM: DT: add power-off support to linkstation lsgl and kuroboxpro
2016-12-27 7:06 ` [PATCH v3 0/3] make kurobox-pro be able to shutdown after device-tree migration Roger Shimizu
2016-12-27 7:06 ` [PATCH v3 1/3] power: reset: add linkstation-reset driver Roger Shimizu
2016-12-27 7:06 ` [PATCH v3 2/3] DT: bingdings: power: reset: add linkstation-reset doc Roger Shimizu
@ 2016-12-27 7:06 ` Roger Shimizu
2017-01-07 15:04 ` [PATCH v4 0/2] make kurobox-pro be able to shutdown after device-tree migration Roger Shimizu
3 siblings, 0 replies; 44+ messages in thread
From: Roger Shimizu @ 2016-12-27 7:06 UTC (permalink / raw)
To: Jason Cooper, Andrew Lunn, Gregory Clement, Sebastian Hesselbarth
Cc: Roger Shimizu, Ryan Tandy, linux-pm, devicetree, linux-arm-kernel
A few models of Linkstation / KuroBox has micro-controller which
controls the power (as well as FAN, but not related here), while
others not. So remove the restart-poweroff driver in linkstation
common dtsi file, and specify the proper power driver in dts
of each device.
Devices need micro-controler to power-off:
- Linkstation LS-GL
- KuroBox Pro
Device continues using original restart-poweroff driver:
- Linkstation LS-WTGL
To: Jason Cooper <jason@lakedaemon.net>
To: Andrew Lunn <andrew@lunn.ch>
To: Gregory Clement <gregory.clement@free-electrons.com>
To: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Cc: Ryan Tandy <ryan@nardis.ca>
Cc: linux-pm@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Reported-by: Ryan Tandy <ryan@nardis.ca>
Tested-by: Ryan Tandy <ryan@nardis.ca>
Signed-off-by: Roger Shimizu <rogershimizu@gmail.com>
---
arch/arm/boot/dts/orion5x-kuroboxpro.dts | 8 ++++++++
arch/arm/boot/dts/orion5x-linkstation-lsgl.dts | 10 ++++++++++
arch/arm/boot/dts/orion5x-linkstation-lswtgl.dts | 4 ++++
arch/arm/boot/dts/orion5x-linkstation.dtsi | 4 ----
4 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/arch/arm/boot/dts/orion5x-kuroboxpro.dts b/arch/arm/boot/dts/orion5x-kuroboxpro.dts
index 1a672b098d0b..aba38d802bda 100644
--- a/arch/arm/boot/dts/orion5x-kuroboxpro.dts
+++ b/arch/arm/boot/dts/orion5x-kuroboxpro.dts
@@ -60,6 +60,14 @@
<MBUS_ID(0x09, 0x00) 0 0xf2200000 0x800>,
<MBUS_ID(0x01, 0x0f) 0 0xf4000000 0x40000>,
<MBUS_ID(0x01, 0x1e) 0 0xfc000000 0x1000000>;
+
+ internal-regs {
+ power_off {
+ compatible = "linkstation,power-off";
+ reg = <0x12100 0x100>;
+ clocks = <&core_clk 0>;
+ };
+ };
};
memory { /* 128 MB */
diff --git a/arch/arm/boot/dts/orion5x-linkstation-lsgl.dts b/arch/arm/boot/dts/orion5x-linkstation-lsgl.dts
index 51dc734cd5b9..370fc17a6dd9 100644
--- a/arch/arm/boot/dts/orion5x-linkstation-lsgl.dts
+++ b/arch/arm/boot/dts/orion5x-linkstation-lsgl.dts
@@ -56,6 +56,16 @@
model = "Buffalo Linkstation Pro/Live";
compatible = "buffalo,lsgl", "marvell,orion5x-88f5182", "marvell,orion5x";
+ soc {
+ internal-regs {
+ power_off {
+ compatible = "linkstation,power-off";
+ reg = <0x12100 0x100>;
+ clocks = <&core_clk 0>;
+ };
+ };
+ };
+
memory { /* 128 MB */
device_type = "memory";
reg = <0x00000000 0x8000000>;
diff --git a/arch/arm/boot/dts/orion5x-linkstation-lswtgl.dts b/arch/arm/boot/dts/orion5x-linkstation-lswtgl.dts
index 0eead400f427..571a71f5b7ad 100644
--- a/arch/arm/boot/dts/orion5x-linkstation-lswtgl.dts
+++ b/arch/arm/boot/dts/orion5x-linkstation-lswtgl.dts
@@ -59,6 +59,10 @@
reg = <0x00000000 0x4000000>;
};
+ restart_poweroff {
+ compatible = "restart-poweroff";
+ };
+
gpio_keys {
power-on-switch {
gpios = <&gpio0 8 GPIO_ACTIVE_LOW>;
diff --git a/arch/arm/boot/dts/orion5x-linkstation.dtsi b/arch/arm/boot/dts/orion5x-linkstation.dtsi
index ed456ab35fd8..40770a8d4b36 100644
--- a/arch/arm/boot/dts/orion5x-linkstation.dtsi
+++ b/arch/arm/boot/dts/orion5x-linkstation.dtsi
@@ -57,10 +57,6 @@
<MBUS_ID(0x01, 0x0f) 0 0xf4000000 0x40000>;
};
- restart_poweroff {
- compatible = "restart-poweroff";
- };
-
regulators {
compatible = "simple-bus";
#address-cells = <1>;
--
2.11.0
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [PATCH v4 0/2] make kurobox-pro be able to shutdown after device-tree migration
2016-12-27 7:06 ` [PATCH v3 0/3] make kurobox-pro be able to shutdown after device-tree migration Roger Shimizu
` (2 preceding siblings ...)
2016-12-27 7:06 ` [PATCH v3 3/3] ARM: DT: add power-off support to linkstation lsgl and kuroboxpro Roger Shimizu
@ 2017-01-07 15:04 ` Roger Shimizu
[not found] ` <20170107150451.17912-1-rogershimizu-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
3 siblings, 1 reply; 44+ messages in thread
From: Roger Shimizu @ 2017-01-07 15:04 UTC (permalink / raw)
To: Sebastian Reichel, Rob Herring, Mark Rutland, Jason Cooper,
Andrew Lunn, Gregory Clement, Sebastian Hesselbarth
Cc: Roger Shimizu, Ryan Tandy, Florian Fainelli, linux-pm, devicetree,
linux-arm-kernel
Dear Kernel Maintainers,
Kurobox-Pro (and variants) need more commands sending to UART1 to shutdown.
So here I make this patch series to let current qnap-poweroff implementation
be able to handle such case.
Here I give 3 patches, for 3 different kernel subsystems respectivelay:
- Patch 1/3: System reset/shutdown driver
- Patch 2/3: Open firmware and flattened device tree bindings
- Patch 3/3: ARM/Marvell Dove/MV78xx0/Orion SOC support
Ryan Tandy, the issue reporter, and I have already tested those changes on
Linkstation/KuroBoxPro devices, and confirmed it's working well.
Merry Xmax and look forward to your feedback!
Changes:
v0 => v1:
- Update 0003 to split kuroboxpro related code into kuroboxpro-common.c
v1 => v2:
- Split off linkstation/kuroboxpro related code to linkstation-reset.c
Because linkstation before kuroboxpro also need this driver to power
off properly. It's more proper to call it linkstation driver.
v2 => v3:
- Split off devicetree bindings doc into a separate patch.
- Add device-tree patch to make Linkstation LS-GL and KuroBox Pro to
use the newly created linkstation-reset driver.
- Remove the unused one-byte command sending case in linkstation-reset
driver.
v3 => v4:
- Reduce the global singleton variables by moving to structure, which makes
the driver easy to support reboot function in the future. Thanks to
Florian Fainelli.
- Simplify the power_off function registration. Thanks to Florian Fainelli.
- Drop DT binding doc.
Cheers,
Roger Shimizu, GMT +9 Tokyo
PGP/GPG: 4096R/6C6ACD6417B3ACB1
Roger Shimizu (2):
power: reset: add linkstation-reset driver
ARM: DT: add power-off support to linkstation lsgl and kuroboxpro
arch/arm/boot/dts/orion5x-kuroboxpro.dts | 8 +
arch/arm/boot/dts/orion5x-linkstation-lsgl.dts | 10 +
arch/arm/boot/dts/orion5x-linkstation-lswtgl.dts | 4 +
arch/arm/boot/dts/orion5x-linkstation.dtsi | 4 -
drivers/power/reset/Kconfig | 10 +
drivers/power/reset/Makefile | 1 +
drivers/power/reset/linkstation-reset.c | 270 +++++++++++++++++++++++
7 files changed, 303 insertions(+), 4 deletions(-)
create mode 100644 drivers/power/reset/linkstation-reset.c
--
2.11.0
^ permalink raw reply [flat|nested] 44+ messages in thread