aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorHerbert Valerio Riedel <hvr@gnu.org>2007-12-16 11:42:31 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-01-26 10:04:04 -0500
commit8f86dda3ed8f05748f2351ae967926227a91ca2a (patch)
treed6a5c23676d3c9fca7171b77911f28718e562e35 /arch/arm
parent3faf2ee870c26f6a809af3f32368f96c357ed91b (diff)
[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>
Diffstat (limited to 'arch/arm')
-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 @@
20#include <linux/gpio_keys.h> 20#include <linux/gpio_keys.h>
21#include <linux/input.h> 21#include <linux/input.h>
22#include <linux/i2c.h> 22#include <linux/i2c.h>
23#include <linux/serial_reg.h>
23#include <asm/mach-types.h> 24#include <asm/mach-types.h>
24#include <asm/gpio.h> 25#include <asm/gpio.h>
25#include <asm/mach/arch.h> 26#include <asm/mach/arch.h>
@@ -239,6 +240,32 @@ static struct platform_device *qnap_ts209_devices[] __initdata = {
239 &qnap_ts209_button_device, 240 &qnap_ts209_button_device,
240}; 241};
241 242
243/*
244 * QNAP TS-[12]09 specific power off method via UART1-attached PIC
245 */
246
247#define UART1_REG(x) (UART1_BASE + ((UART_##x) << 2))
248
249static void qnap_ts209_power_off(void)
250{
251 /* 19200 baud divisor */
252 const unsigned divisor = ((ORION_TCLK + (8 * 19200)) / (16 * 19200));
253
254 pr_info("%s: triggering power-off...\n", __func__);
255
256 /* hijack uart1 and reset into sane state (19200,8n1) */
257 orion_write(UART1_REG(LCR), 0x83);
258 orion_write(UART1_REG(DLL), divisor & 0xff);
259 orion_write(UART1_REG(DLM), (divisor >> 8) & 0xff);
260 orion_write(UART1_REG(LCR), 0x03);
261 orion_write(UART1_REG(IER), 0x00);
262 orion_write(UART1_REG(FCR), 0x00);
263 orion_write(UART1_REG(MCR), 0x00);
264
265 /* send the power-off command 'A' to PIC */
266 orion_write(UART1_REG(TX), 'A');
267}
268
242static void __init qnap_ts209_init(void) 269static void __init qnap_ts209_init(void)
243{ 270{
244 /* 271 /*
@@ -287,6 +314,9 @@ static void __init qnap_ts209_init(void)
287 orion_write(MPP_16_19_CTRL, 0x5500); 314 orion_write(MPP_16_19_CTRL, 0x5500);
288 orion_gpio_set_valid_pins(0x3cc0fff); 315 orion_gpio_set_valid_pins(0x3cc0fff);
289 316
317 /* register ts209 specific power-off method */
318 pm_power_off = qnap_ts209_power_off;
319
290 platform_add_devices(qnap_ts209_devices, 320 platform_add_devices(qnap_ts209_devices,
291 ARRAY_SIZE(qnap_ts209_devices)); 321 ARRAY_SIZE(qnap_ts209_devices));
292 i2c_register_board_info(0, &qnap_ts209_i2c_rtc, 1); 322 i2c_register_board_info(0, &qnap_ts209_i2c_rtc, 1);