aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-mxs/include/mach/system.h27
-rw-r--r--arch/arm/mach-mxs/system.c137
2 files changed, 164 insertions, 0 deletions
diff --git a/arch/arm/mach-mxs/include/mach/system.h b/arch/arm/mach-mxs/include/mach/system.h
new file mode 100644
index 000000000000..0e428239b433
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/system.h
@@ -0,0 +1,27 @@
1/*
2 * Copyright (C) 1999 ARM Limited
3 * Copyright (C) 2000 Deep Blue Solutions Ltd
4 * Copyright 2004-2008 Freescale Semiconductor, Inc. All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#ifndef __MACH_MXS_SYSTEM_H__
18#define __MACH_MXS_SYSTEM_H__
19
20static inline void arch_idle(void)
21{
22 cpu_do_idle();
23}
24
25void arch_reset(char mode, const char *cmd);
26
27#endif /* __MACH_MXS_SYSTEM_H__ */
diff --git a/arch/arm/mach-mxs/system.c b/arch/arm/mach-mxs/system.c
new file mode 100644
index 000000000000..9343d7edd4f6
--- /dev/null
+++ b/arch/arm/mach-mxs/system.c
@@ -0,0 +1,137 @@
1/*
2 * Copyright (C) 1999 ARM Limited
3 * Copyright (C) 2000 Deep Blue Solutions Ltd
4 * Copyright 2006-2007,2010 Freescale Semiconductor, Inc. All Rights Reserved.
5 * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
6 * Copyright 2009 Ilya Yanok, Emcraft Systems Ltd, yanok@emcraft.com
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
18
19#include <linux/kernel.h>
20#include <linux/clk.h>
21#include <linux/io.h>
22#include <linux/err.h>
23#include <linux/delay.h>
24#include <linux/init.h>
25
26#include <asm/proc-fns.h>
27#include <asm/system.h>
28
29#include <mach/mxs.h>
30#include <mach/common.h>
31
32#define MX23_CLKCTRL_RESET_OFFSET 0x120
33#define MX28_CLKCTRL_RESET_OFFSET 0x1e0
34#define MXS_CLKCTRL_RESET_CHIP (1 << 1)
35
36#define MXS_MODULE_CLKGATE (1 << 30)
37#define MXS_MODULE_SFTRST (1 << 31)
38
39static void __iomem *mxs_clkctrl_reset_addr;
40
41/*
42 * Reset the system. It is called by machine_restart().
43 */
44void arch_reset(char mode, const char *cmd)
45{
46 /* reset the chip */
47 __mxs_setl(MXS_CLKCTRL_RESET_CHIP, mxs_clkctrl_reset_addr);
48
49 pr_err("Failed to assert the chip reset\n");
50
51 /* Delay to allow the serial port to show the message */
52 mdelay(50);
53
54 /* We'll take a jump through zero as a poor second */
55 cpu_reset(0);
56}
57
58static int __init mxs_arch_reset_init(void)
59{
60 struct clk *clk;
61
62 mxs_clkctrl_reset_addr = MXS_IO_ADDRESS(MXS_CLKCTRL_BASE_ADDR) +
63 (cpu_is_mx23() ? MX23_CLKCTRL_RESET_OFFSET :
64 MX28_CLKCTRL_RESET_OFFSET);
65
66 clk = clk_get_sys("rtc", NULL);
67 if (!IS_ERR(clk))
68 clk_enable(clk);
69
70 return 0;
71}
72core_initcall(mxs_arch_reset_init);
73
74/*
75 * Clear the bit and poll it cleared. This is usually called with
76 * a reset address and mask being either SFTRST(bit 31) or CLKGATE
77 * (bit 30).
78 */
79static int clear_poll_bit(void __iomem *addr, u32 mask)
80{
81 int timeout = 0x400;
82
83 /* clear the bit */
84 __mxs_clrl(mask, addr);
85
86 /*
87 * SFTRST needs 3 GPMI clocks to settle, the reference manual
88 * recommends to wait 1us.
89 */
90 udelay(1);
91
92 /* poll the bit becoming clear */
93 while ((__raw_readl(addr) & mask) && --timeout)
94 /* nothing */;
95
96 return !timeout;
97}
98
99int mxs_reset_block(void __iomem *reset_addr)
100{
101 int ret;
102 int timeout = 0x400;
103
104 /* clear and poll SFTRST */
105 ret = clear_poll_bit(reset_addr, MXS_MODULE_SFTRST);
106 if (unlikely(ret))
107 goto error;
108
109 /* clear CLKGATE */
110 __mxs_clrl(MXS_MODULE_CLKGATE, reset_addr);
111
112 /* set SFTRST to reset the block */
113 __mxs_setl(MXS_MODULE_SFTRST, reset_addr);
114 udelay(1);
115
116 /* poll CLKGATE becoming set */
117 while ((!(__raw_readl(reset_addr) & MXS_MODULE_CLKGATE)) && --timeout)
118 /* nothing */;
119 if (unlikely(!timeout))
120 goto error;
121
122 /* clear and poll SFTRST */
123 ret = clear_poll_bit(reset_addr, MXS_MODULE_SFTRST);
124 if (unlikely(ret))
125 goto error;
126
127 /* clear and poll CLKGATE */
128 ret = clear_poll_bit(reset_addr, MXS_MODULE_CLKGATE);
129 if (unlikely(ret))
130 goto error;
131
132 return 0;
133
134error:
135 pr_err("%s(%p): module reset timeout\n", __func__, reset_addr);
136 return -ETIMEDOUT;
137}