linux-pm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Roger Shimizu <rogershimizu@gmail.com>
To: Sebastian Reichel <sre@kernel.org>,
	linux-pm@vger.kernel.org, Andrew Lunn <andrew@lunn.ch>
Cc: Roger Shimizu <rogershimizu@gmail.com>,
	Ryan Tandy <ryan@nardis.ca>, Martin Michlmayr <tbm@cyrius.com>,
	Sylver Bruneau <sylver.bruneau@googlemail.com>,
	Herbert Valerio Riedel <hvr@gnu.org>
Subject: [PATCH 3/3] power: reset: make qnap-poweroff support kurobox-pro
Date: Mon,  5 Dec 2016 21:45:28 +0900	[thread overview]
Message-ID: <20161205124528.2999-4-rogershimizu@gmail.com> (raw)
In-Reply-To: <20161205124528.2999-1-rogershimizu@gmail.com>

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/qnap-poweroff.c                | 143 ++++++++++++++++++++-
 2 files changed, 149 insertions(+), 2 deletions(-)

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/qnap-poweroff.c b/drivers/power/reset/qnap-poweroff.c
index 644478c..8adc887 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>
@@ -8,6 +13,8 @@
  *
  * 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
@@ -23,6 +30,7 @@
 #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
@@ -35,6 +43,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 +61,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 +86,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 +99,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);
@@ -79,6 +110,109 @@ static void __iomem *base;
 static unsigned long tclk;
 static const struct power_off_cfg *cfg;
 
+static int uart1_miconread(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_miconwrite(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;
+}
+
+static int uart1_miconsend(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_miconwrite(data, count);
+
+		/* send checksum */
+		uart1_miconwrite(&checksum, 1);
+
+		if (uart1_miconread(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_miconwrite(send_buf, sizeof(send_buf));
+
+			/* make dummy reads */
+			mdelay(100);
+			uart1_miconread(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 qnap_power_off(void)
 {
 	const unsigned divisor = ((tclk + (8 * cfg->baud)) / (16 * cfg->baud));
@@ -99,6 +233,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_miconsend(&(cfg->cmd[i][1]), cfg->cmd[i][0]);
+		}
+	}
 }
 
 static int qnap_power_off_probe(struct platform_device *pdev)
-- 
2.10.2


  parent reply	other threads:[~2016-12-05 12:46 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-12-05 12:45 [PATCH 0/3] make kurobox-pro be able to shutdown after device-tree migration Roger Shimizu
2016-12-05 12:45 ` [PATCH 1/3] power: reset: make qnap-poweroff flexible on hello magic command to uart1 Roger Shimizu
2016-12-05 12:45 ` [PATCH 2/3] power: reset: make qnap-poweroff flexible on length of power-off command Roger Shimizu
2016-12-05 12:45 ` Roger Shimizu [this message]
2016-12-06 17:34 ` [PATCH 0/3] make kurobox-pro be able to shutdown after device-tree migration Andrew Lunn
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     ` [PATCH v1 3/3] power: reset: make qnap-poweroff support kurobox-pro 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
2016-12-19  0:34       ` Roger Shimizu
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
     [not found]           ` <CAEQ9gEnQEHdcA4ox3teOXKcrdf2AAqUMp=A6W6c7nXhk4VrKiw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2016-12-21 15:59             ` Sebastian Reichel
2016-12-21 16:41               ` Andrew Lunn
     [not found]                 ` <20161221164136.GM30952-g2DYL2Zd6BY@public.gmane.org>
2016-12-22 14:49                   ` Sebastian Reichel
2016-12-26 16:13                     ` Roger Shimizu
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
     [not found]           ` <20161227070611.14852-2-rogershimizu-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2017-01-03  5:19             ` Florian Fainelli
2017-01-03 13:09               ` Andrew Lunn
2017-01-03 14:08                 ` Roger Shimizu
     [not found]                   ` <CAEQ9gE=MoQcr3eX0DAxZtvx0FW9pzgkUGjdxKHcsKwH7_+UsUw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2017-01-03 18:39                     ` Florian Fainelli
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 14:11               ` Roger Shimizu
2017-01-03 17:09           ` Rob Herring
2017-01-06 12:18             ` Roger Shimizu
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
     [not found]           ` <20170107150451.17912-1-rogershimizu-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2017-01-07 15:04             ` [PATCH v4 1/2] power: reset: add linkstation-reset driver Roger Shimizu
2017-01-08 17:02               ` Ryan Tandy
2017-01-09  3:31                 ` Roger Shimizu
2017-01-09  5:43                   ` Ryan Tandy
2017-01-18 12:08               ` Roger Shimizu
2017-01-19  4:43                 ` Sebastian Reichel
2017-01-26 15:28                   ` Gregory CLEMENT
2017-01-26 15:33                     ` Roger Shimizu
2017-01-27  9:15                       ` Gregory CLEMENT
2017-01-07 15:04             ` [PATCH v4 2/2] ARM: DT: add power-off support to linkstation lsgl and kuroboxpro Roger Shimizu

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=20161205124528.2999-4-rogershimizu@gmail.com \
    --to=rogershimizu@gmail.com \
    --cc=andrew@lunn.ch \
    --cc=hvr@gnu.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=ryan@nardis.ca \
    --cc=sre@kernel.org \
    --cc=sylver.bruneau@googlemail.com \
    --cc=tbm@cyrius.com \
    /path/to/YOUR_REPLY

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

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is 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).