aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Valerio Riedel <hvr@gnu.org>2007-12-16 17:42:31 +0100
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-01-26 15:04:04 +0000
commit8f86dda3ed8f05748f2351ae967926227a91ca2a (patch)
treed6a5c23676d3c9fca7171b77911f28718e562e35
parent[ARM] Orion: add support for QNAP TS-109/TS-209 (diff)
downloadlinux-dev-8f86dda3ed8f05748f2351ae967926227a91ca2a.tar.xz
linux-dev-8f86dda3ed8f05748f2351ae967926227a91ca2a.zip
[ARM] Orion: implement power-off method for QNAP TS-109/209
Since the PIC is attached to UART1, it doesn't need a kernel device driver of its own; but powering off is something that the kernel should do, so this patch forcefully configures the UART1 for 19200 baud and sends the character that tells the PIC to cut the power. Signed-off-by: Herbert Valerio Riedel <hvr@gnu.org> Cc: Byron Bradley <byron.bbradley@gmail.com> Acked-by: Nicolas Pitre <nico@marvell.com>
-rw-r--r--arch/arm/mach-orion/ts209-setup.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/arch/arm/mach-orion/ts209-setup.c b/arch/arm/mach-orion/ts209-setup.c
index 34f88ac24ac8..e3e930efd155 100644
--- a/arch/arm/mach-orion/ts209-setup.c
+++ b/arch/arm/mach-orion/ts209-setup.c
@@ -20,6 +20,7 @@
#include <linux/gpio_keys.h>
#include <linux/input.h>
#include <linux/i2c.h>
+#include <linux/serial_reg.h>
#include <asm/mach-types.h>
#include <asm/gpio.h>
#include <asm/mach/arch.h>
@@ -239,6 +240,32 @@ static struct platform_device *qnap_ts209_devices[] __initdata = {
&qnap_ts209_button_device,
};
+/*
+ * QNAP TS-[12]09 specific power off method via UART1-attached PIC
+ */
+
+#define UART1_REG(x) (UART1_BASE + ((UART_##x) << 2))
+
+static void qnap_ts209_power_off(void)
+{
+ /* 19200 baud divisor */
+ const unsigned divisor = ((ORION_TCLK + (8 * 19200)) / (16 * 19200));
+
+ pr_info("%s: triggering power-off...\n", __func__);
+
+ /* hijack uart1 and reset into sane state (19200,8n1) */
+ orion_write(UART1_REG(LCR), 0x83);
+ orion_write(UART1_REG(DLL), divisor & 0xff);
+ orion_write(UART1_REG(DLM), (divisor >> 8) & 0xff);
+ orion_write(UART1_REG(LCR), 0x03);
+ orion_write(UART1_REG(IER), 0x00);
+ orion_write(UART1_REG(FCR), 0x00);
+ orion_write(UART1_REG(MCR), 0x00);
+
+ /* send the power-off command 'A' to PIC */
+ orion_write(UART1_REG(TX), 'A');
+}
+
static void __init qnap_ts209_init(void)
{
/*
@@ -287,6 +314,9 @@ static void __init qnap_ts209_init(void)
orion_write(MPP_16_19_CTRL, 0x5500);
orion_gpio_set_valid_pins(0x3cc0fff);
+ /* register ts209 specific power-off method */
+ pm_power_off = qnap_ts209_power_off;
+
platform_add_devices(qnap_ts209_devices,
ARRAY_SIZE(qnap_ts209_devices));
i2c_register_board_info(0, &qnap_ts209_i2c_rtc, 1);