Merge branch 'drm-nouveau-next' of git://git.freedesktop.org/git/nouveau/linux-2...
[pandora-kernel.git] / arch / arm / mach-mxs / system.c
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
39 static void __iomem *mxs_clkctrl_reset_addr;
40
41 /*
42  * Reset the system. It is called by machine_restart().
43  */
44 void 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
58 static 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 }
72 core_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  */
79 static 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
99 int 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
134 error:
135         pr_err("%s(%p): module reset timeout\n", __func__, reset_addr);
136         return -ETIMEDOUT;
137 }