aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power/reset
diff options
context:
space:
mode:
authorAndrew Lunn <andrew@lunn.ch>2014-02-19 15:02:35 -0500
committerJason Cooper <jason@lakedaemon.net>2014-03-03 22:48:41 -0500
commit200c0a3e404beab02be83e5cbf111d26b9f6ce22 (patch)
tree4cfcb9d5f37a1ea3435c8d33ad4271572a8f8b07 /drivers/power/reset
parentff1f0018cf66080d8e6f59791e552615648a033a (diff)
Power: Reset: Generalize qnap-poweroff to work on Synology devices.
The Synology NAS devices use a very similar mechanism to QNAP NAS devices to power off. Both send a single charactor command to a PIC, over the second serial port. However the baud rate and the command differ. Generalize the driver to support this. Signed-off-by: Ben Peddell <klightspeed@killerwolves.net> Signed-off-by: Andrew Lunn <andrew@lunn.ch> Acked-by: Jason Cooper <jason@lakedaemon.net> Cc: Anton Vorontsov <anton@enomsg.org> Cc: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> Cc: David Woodhouse <dwmw2@infradead.org> Signed-off-by: Jason Cooper <jason@lakedaemon.net>
Diffstat (limited to 'drivers/power/reset')
-rw-r--r--drivers/power/reset/qnap-poweroff.c49
1 files changed, 37 insertions, 12 deletions
diff --git a/drivers/power/reset/qnap-poweroff.c b/drivers/power/reset/qnap-poweroff.c
index 37f56f7ee926..a75db7f8a92f 100644
--- a/drivers/power/reset/qnap-poweroff.c
+++ b/drivers/power/reset/qnap-poweroff.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * QNAP Turbo NAS Board power off 2 * QNAP Turbo NAS Board power off. Can also be used on Synology devices.
3 * 3 *
4 * Copyright (C) 2012 Andrew Lunn <andrew@lunn.ch> 4 * Copyright (C) 2012 Andrew Lunn <andrew@lunn.ch>
5 * 5 *
@@ -25,17 +25,43 @@
25 25
26#define UART1_REG(x) (base + ((UART_##x) << 2)) 26#define UART1_REG(x) (base + ((UART_##x) << 2))
27 27
28struct power_off_cfg {
29 u32 baud;
30 char cmd;
31};
32
33static const struct power_off_cfg qnap_power_off_cfg = {
34 .baud = 19200,
35 .cmd = 'A',
36};
37
38static const struct power_off_cfg synology_power_off_cfg = {
39 .baud = 9600,
40 .cmd = '1',
41};
42
43static const struct of_device_id qnap_power_off_of_match_table[] = {
44 { .compatible = "qnap,power-off",
45 .data = &qnap_power_off_cfg,
46 },
47 { .compatible = "synology,power-off",
48 .data = &synology_power_off_cfg,
49 },
50 {}
51};
52MODULE_DEVICE_TABLE(of, qnap_power_off_of_match_table);
53
28static void __iomem *base; 54static void __iomem *base;
29static unsigned long tclk; 55static unsigned long tclk;
56static const struct power_off_cfg *cfg;
30 57
31static void qnap_power_off(void) 58static void qnap_power_off(void)
32{ 59{
33 /* 19200 baud divisor */ 60 const unsigned divisor = ((tclk + (8 * cfg->baud)) / (16 * cfg->baud));
34 const unsigned divisor = ((tclk + (8 * 19200)) / (16 * 19200));
35 61
36 pr_err("%s: triggering power-off...\n", __func__); 62 pr_err("%s: triggering power-off...\n", __func__);
37 63
38 /* hijack UART1 and reset into sane state (19200,8n1) */ 64 /* hijack UART1 and reset into sane state */
39 writel(0x83, UART1_REG(LCR)); 65 writel(0x83, UART1_REG(LCR));
40 writel(divisor & 0xff, UART1_REG(DLL)); 66 writel(divisor & 0xff, UART1_REG(DLL));
41 writel((divisor >> 8) & 0xff, UART1_REG(DLM)); 67 writel((divisor >> 8) & 0xff, UART1_REG(DLM));
@@ -44,16 +70,21 @@ static void qnap_power_off(void)
44 writel(0x00, UART1_REG(FCR)); 70 writel(0x00, UART1_REG(FCR));
45 writel(0x00, UART1_REG(MCR)); 71 writel(0x00, UART1_REG(MCR));
46 72
47 /* send the power-off command 'A' to PIC */ 73 /* send the power-off command to PIC */
48 writel('A', UART1_REG(TX)); 74 writel(cfg->cmd, UART1_REG(TX));
49} 75}
50 76
51static int qnap_power_off_probe(struct platform_device *pdev) 77static int qnap_power_off_probe(struct platform_device *pdev)
52{ 78{
79 struct device_node *np = pdev->dev.of_node;
53 struct resource *res; 80 struct resource *res;
54 struct clk *clk; 81 struct clk *clk;
55 char symname[KSYM_NAME_LEN]; 82 char symname[KSYM_NAME_LEN];
56 83
84 const struct of_device_id *match =
85 of_match_node(qnap_power_off_of_match_table, np);
86 cfg = match->data;
87
57 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 88 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
58 if (!res) { 89 if (!res) {
59 dev_err(&pdev->dev, "Missing resource"); 90 dev_err(&pdev->dev, "Missing resource");
@@ -94,12 +125,6 @@ static int qnap_power_off_remove(struct platform_device *pdev)
94 return 0; 125 return 0;
95} 126}
96 127
97static const struct of_device_id qnap_power_off_of_match_table[] = {
98 { .compatible = "qnap,power-off", },
99 {}
100};
101MODULE_DEVICE_TABLE(of, qnap_power_off_of_match_table);
102
103static struct platform_driver qnap_power_off_driver = { 128static struct platform_driver qnap_power_off_driver = {
104 .probe = qnap_power_off_probe, 129 .probe = qnap_power_off_probe,
105 .remove = qnap_power_off_remove, 130 .remove = qnap_power_off_remove,