| John Crispin | 8ec6d93 | 2011-03-30 09:27:48 +0200 | [diff] [blame] | 1 | /* | 
|  | 2 | *  This program is free software; you can redistribute it and/or modify it | 
|  | 3 | *  under the terms of the GNU General Public License version 2 as published | 
|  | 4 | *  by the Free Software Foundation. | 
|  | 5 | * | 
|  | 6 | *  Copyright (C) 2010 John Crispin <blogic@openwrt.org> | 
|  | 7 | */ | 
|  | 8 |  | 
|  | 9 | #include <linux/init.h> | 
|  | 10 | #include <linux/io.h> | 
|  | 11 | #include <linux/ioport.h> | 
|  | 12 | #include <linux/pm.h> | 
|  | 13 | #include <linux/module.h> | 
|  | 14 | #include <asm/reboot.h> | 
|  | 15 |  | 
|  | 16 | #include <lantiq_soc.h> | 
|  | 17 |  | 
|  | 18 | #define ltq_rcu_w32(x, y)	ltq_w32((x), ltq_rcu_membase + (y)) | 
|  | 19 | #define ltq_rcu_r32(x)		ltq_r32(ltq_rcu_membase + (x)) | 
|  | 20 |  | 
|  | 21 | /* register definitions */ | 
|  | 22 | #define LTQ_RCU_RST		0x0010 | 
|  | 23 | #define LTQ_RCU_RST_ALL		0x40000000 | 
|  | 24 |  | 
|  | 25 | #define LTQ_RCU_RST_STAT	0x0014 | 
|  | 26 | #define LTQ_RCU_STAT_SHIFT	26 | 
|  | 27 |  | 
|  | 28 | static struct resource ltq_rcu_resource = { | 
|  | 29 | .name   = "rcu", | 
|  | 30 | .start  = LTQ_RCU_BASE_ADDR, | 
|  | 31 | .end    = LTQ_RCU_BASE_ADDR + LTQ_RCU_SIZE - 1, | 
|  | 32 | .flags  = IORESOURCE_MEM, | 
|  | 33 | }; | 
|  | 34 |  | 
|  | 35 | /* remapped base addr of the reset control unit */ | 
|  | 36 | static void __iomem *ltq_rcu_membase; | 
|  | 37 |  | 
|  | 38 | /* This function is used by the watchdog driver */ | 
|  | 39 | int ltq_reset_cause(void) | 
|  | 40 | { | 
|  | 41 | u32 val = ltq_rcu_r32(LTQ_RCU_RST_STAT); | 
|  | 42 | return val >> LTQ_RCU_STAT_SHIFT; | 
|  | 43 | } | 
|  | 44 | EXPORT_SYMBOL_GPL(ltq_reset_cause); | 
|  | 45 |  | 
|  | 46 | static void ltq_machine_restart(char *command) | 
|  | 47 | { | 
|  | 48 | pr_notice("System restart\n"); | 
|  | 49 | local_irq_disable(); | 
|  | 50 | ltq_rcu_w32(ltq_rcu_r32(LTQ_RCU_RST) | LTQ_RCU_RST_ALL, LTQ_RCU_RST); | 
|  | 51 | unreachable(); | 
|  | 52 | } | 
|  | 53 |  | 
|  | 54 | static void ltq_machine_halt(void) | 
|  | 55 | { | 
|  | 56 | pr_notice("System halted.\n"); | 
|  | 57 | local_irq_disable(); | 
|  | 58 | unreachable(); | 
|  | 59 | } | 
|  | 60 |  | 
|  | 61 | static void ltq_machine_power_off(void) | 
|  | 62 | { | 
|  | 63 | pr_notice("Please turn off the power now.\n"); | 
|  | 64 | local_irq_disable(); | 
|  | 65 | unreachable(); | 
|  | 66 | } | 
|  | 67 |  | 
|  | 68 | static int __init mips_reboot_setup(void) | 
|  | 69 | { | 
|  | 70 | /* insert and request the memory region */ | 
|  | 71 | if (insert_resource(&iomem_resource, <q_rcu_resource) < 0) | 
|  | 72 | panic("Failed to insert rcu memory\n"); | 
|  | 73 |  | 
|  | 74 | if (request_mem_region(ltq_rcu_resource.start, | 
|  | 75 | resource_size(<q_rcu_resource), "rcu") < 0) | 
|  | 76 | panic("Failed to request rcu memory\n"); | 
|  | 77 |  | 
|  | 78 | /* remap rcu register range */ | 
|  | 79 | ltq_rcu_membase = ioremap_nocache(ltq_rcu_resource.start, | 
|  | 80 | resource_size(<q_rcu_resource)); | 
|  | 81 | if (!ltq_rcu_membase) | 
|  | 82 | panic("Failed to remap rcu memory\n"); | 
|  | 83 |  | 
|  | 84 | _machine_restart = ltq_machine_restart; | 
|  | 85 | _machine_halt = ltq_machine_halt; | 
|  | 86 | pm_power_off = ltq_machine_power_off; | 
|  | 87 |  | 
|  | 88 | return 0; | 
|  | 89 | } | 
|  | 90 |  | 
|  | 91 | arch_initcall(mips_reboot_setup); |