/arch/arm/mach-msm/restart.c
C | 136 lines | 97 code | 22 blank | 17 comment | 11 complexity | a1b3800a3ce6cb0ea95510d191ea57df MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
1/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 *
17 */
18
19#include <linux/module.h>
20#include <linux/kernel.h>
21#include <linux/init.h>
22#include <linux/reboot.h>
23#include <linux/io.h>
24#include <linux/delay.h>
25#include <linux/pm.h>
26#include <linux/mfd/pmic8058.h>
27#include <linux/mfd/pmic8901.h>
28
29#include <mach/msm_iomap.h>
30#include <mach/scm-io.h>
31
32#define TCSR_WDT_CFG 0x30
33
34#define WDT0_RST (MSM_TMR0_BASE + 0x38)
35#define WDT0_EN (MSM_TMR0_BASE + 0x40)
36#define WDT0_BARK_TIME (MSM_TMR0_BASE + 0x4C)
37#define WDT0_BITE_TIME (MSM_TMR0_BASE + 0x5C)
38
39#define PSHOLD_CTL_SU (MSM_TLMM_BASE + 0x820)
40
41#define RESTART_REASON_ADDR 0x2A05F65C
42
43#ifdef CONFIG_MSM_DLOAD_MODE
44static int in_panic;
45
46static int panic_prep_restart(struct notifier_block *this,
47 unsigned long event, void *ptr)
48{
49 in_panic = 1;
50 return NOTIFY_DONE;
51}
52
53static struct notifier_block panic_blk = {
54 .notifier_call = panic_prep_restart,
55};
56
57static void set_dload_mode(int on)
58{
59 void *dload_mode_addr;
60 dload_mode_addr = ioremap_nocache(0x2A05F000, SZ_4K);
61 if (dload_mode_addr) {
62 writel(on ? 0xE47B337D : 0, dload_mode_addr);
63 writel(on ? 0xCE14091A : 0,
64 dload_mode_addr + sizeof(unsigned int));
65 dmb();
66 iounmap(dload_mode_addr);
67 }
68}
69#else
70#define set_dload_mode(x) do {} while (0)
71#endif
72
73static void msm_power_off(void)
74{
75 printk(KERN_NOTICE "Powering off the SoC\n");
76 pm8058_reset_pwr_off(0);
77 pm8901_reset_pwr_off(0);
78 writel(0, PSHOLD_CTL_SU);
79 mdelay(10000);
80 printk(KERN_ERR "Powering off has failed\n");
81 return;
82}
83
84void arch_reset(char mode, const char *cmd)
85{
86 void *restart_reason;
87
88#ifdef CONFIG_MSM_DLOAD_MODE
89 if (in_panic)
90 set_dload_mode(1);
91#endif
92
93 printk(KERN_NOTICE "Going down for restart now\n");
94
95 pm8058_reset_pwr_off(1);
96
97 if (cmd != NULL) {
98 restart_reason = ioremap_nocache(RESTART_REASON_ADDR, SZ_4K);
99 if (!strncmp(cmd, "bootloader", 10)) {
100 writel(0x77665500, restart_reason);
101 } else if (!strncmp(cmd, "recovery", 8)) {
102 writel(0x77665502, restart_reason);
103 } else if (!strncmp(cmd, "oem-", 4)) {
104 unsigned long code;
105 strict_strtoul(cmd + 4, 16, &code);
106 code = code & 0xff;
107 writel(0x6f656d00 | code, restart_reason);
108 } else {
109 writel(0x77665501, restart_reason);
110 }
111 iounmap(restart_reason);
112 }
113
114 writel(1, WDT0_RST);
115 writel(0, WDT0_EN);
116 writel(0x31F3, WDT0_BARK_TIME);
117 writel(0x31F3, WDT0_BITE_TIME);
118 writel(3, WDT0_EN);
119 dmb();
120 secure_writel(3, MSM_TCSR_BASE + TCSR_WDT_CFG);
121
122 mdelay(10000);
123}
124
125static int __init msm_restart_init(void)
126{
127#ifdef CONFIG_MSM_DLOAD_MODE
128 atomic_notifier_chain_register(&panic_notifier_list, &panic_blk);
129#endif
130
131 pm_power_off = msm_power_off;
132
133 return 0;
134}
135
136late_initcall(msm_restart_init);