aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-mxs/mach-mxs.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-mxs/mach-mxs.c')
-rw-r--r--arch/arm/mach-mxs/mach-mxs.c188
1 files changed, 159 insertions, 29 deletions
diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c
index e7b781d3788f..b5c1bdd3dcdf 100644
--- a/arch/arm/mach-mxs/mach-mxs.c
+++ b/arch/arm/mach-mxs/mach-mxs.c
@@ -11,22 +11,55 @@
11 */ 11 */
12 12
13#include <linux/clk.h> 13#include <linux/clk.h>
14#include <linux/clk/mxs.h>
14#include <linux/clkdev.h> 15#include <linux/clkdev.h>
16#include <linux/clocksource.h>
15#include <linux/can/platform/flexcan.h> 17#include <linux/can/platform/flexcan.h>
16#include <linux/delay.h> 18#include <linux/delay.h>
17#include <linux/err.h> 19#include <linux/err.h>
18#include <linux/gpio.h> 20#include <linux/gpio.h>
19#include <linux/init.h> 21#include <linux/init.h>
22#include <linux/irqchip.h>
23#include <linux/irqchip/mxs.h>
20#include <linux/micrel_phy.h> 24#include <linux/micrel_phy.h>
21#include <linux/mxsfb.h> 25#include <linux/mxsfb.h>
26#include <linux/of_address.h>
22#include <linux/of_platform.h> 27#include <linux/of_platform.h>
23#include <linux/phy.h> 28#include <linux/phy.h>
24#include <linux/pinctrl/consumer.h> 29#include <linux/pinctrl/consumer.h>
25#include <asm/mach/arch.h> 30#include <asm/mach/arch.h>
31#include <asm/mach/map.h>
26#include <asm/mach/time.h> 32#include <asm/mach/time.h>
27#include <mach/common.h> 33#include <asm/system_misc.h>
28#include <mach/digctl.h> 34
29#include <mach/mxs.h> 35#include "pm.h"
36
37/* MXS DIGCTL SAIF CLKMUX */
38#define MXS_DIGCTL_SAIF_CLKMUX_DIRECT 0x0
39#define MXS_DIGCTL_SAIF_CLKMUX_CROSSINPUT 0x1
40#define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0 0x2
41#define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR1 0x3
42
43#define MXS_GPIO_NR(bank, nr) ((bank) * 32 + (nr))
44
45#define MXS_SET_ADDR 0x4
46#define MXS_CLR_ADDR 0x8
47#define MXS_TOG_ADDR 0xc
48
49static inline void __mxs_setl(u32 mask, void __iomem *reg)
50{
51 __raw_writel(mask, reg + MXS_SET_ADDR);
52}
53
54static inline void __mxs_clrl(u32 mask, void __iomem *reg)
55{
56 __raw_writel(mask, reg + MXS_CLR_ADDR);
57}
58
59static inline void __mxs_togl(u32 mask, void __iomem *reg)
60{
61 __raw_writel(mask, reg + MXS_TOG_ADDR);
62}
30 63
31static struct fb_videomode mx23evk_video_modes[] = { 64static struct fb_videomode mx23evk_video_modes[] = {
32 { 65 {
@@ -165,14 +198,80 @@ static struct of_dev_auxdata mxs_auxdata_lookup[] __initdata = {
165 { /* sentinel */ } 198 { /* sentinel */ }
166}; 199};
167 200
168static void __init imx23_timer_init(void) 201#define OCOTP_WORD_OFFSET 0x20
169{ 202#define OCOTP_WORD_COUNT 0x20
170 mx23_clocks_init(); 203
171} 204#define BM_OCOTP_CTRL_BUSY (1 << 8)
205#define BM_OCOTP_CTRL_ERROR (1 << 9)
206#define BM_OCOTP_CTRL_RD_BANK_OPEN (1 << 12)
172 207
173static void __init imx28_timer_init(void) 208static DEFINE_MUTEX(ocotp_mutex);
209static u32 ocotp_words[OCOTP_WORD_COUNT];
210
211static const u32 *mxs_get_ocotp(void)
174{ 212{
175 mx28_clocks_init(); 213 struct device_node *np;
214 void __iomem *ocotp_base;
215 int timeout = 0x400;
216 size_t i;
217 static int once;
218
219 if (once)
220 return ocotp_words;
221
222 np = of_find_compatible_node(NULL, NULL, "fsl,ocotp");
223 ocotp_base = of_iomap(np, 0);
224 WARN_ON(!ocotp_base);
225
226 mutex_lock(&ocotp_mutex);
227
228 /*
229 * clk_enable(hbus_clk) for ocotp can be skipped
230 * as it must be on when system is running.
231 */
232
233 /* try to clear ERROR bit */
234 __mxs_clrl(BM_OCOTP_CTRL_ERROR, ocotp_base);
235
236 /* check both BUSY and ERROR cleared */
237 while ((__raw_readl(ocotp_base) &
238 (BM_OCOTP_CTRL_BUSY | BM_OCOTP_CTRL_ERROR)) && --timeout)
239 cpu_relax();
240
241 if (unlikely(!timeout))
242 goto error_unlock;
243
244 /* open OCOTP banks for read */
245 __mxs_setl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base);
246
247 /* approximately wait 32 hclk cycles */
248 udelay(1);
249
250 /* poll BUSY bit becoming cleared */
251 timeout = 0x400;
252 while ((__raw_readl(ocotp_base) & BM_OCOTP_CTRL_BUSY) && --timeout)
253 cpu_relax();
254
255 if (unlikely(!timeout))
256 goto error_unlock;
257
258 for (i = 0; i < OCOTP_WORD_COUNT; i++)
259 ocotp_words[i] = __raw_readl(ocotp_base + OCOTP_WORD_OFFSET +
260 i * 0x10);
261
262 /* close banks for power saving */
263 __mxs_clrl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base);
264
265 once = 1;
266
267 mutex_unlock(&ocotp_mutex);
268
269 return ocotp_words;
270
271error_unlock:
272 mutex_unlock(&ocotp_mutex);
273 pr_err("%s: timeout in reading OCOTP\n", __func__);
274 return NULL;
176} 275}
177 276
178enum mac_oui { 277enum mac_oui {
@@ -454,32 +553,63 @@ static void __init mxs_machine_init(void)
454 imx28_evk_post_init(); 553 imx28_evk_post_init();
455} 554}
456 555
457static const char *imx23_dt_compat[] __initdata = { 556#define MX23_CLKCTRL_RESET_OFFSET 0x120
458 "fsl,imx23", 557#define MX28_CLKCTRL_RESET_OFFSET 0x1e0
459 NULL, 558#define MXS_CLKCTRL_RESET_CHIP (1 << 1)
460}; 559
560/*
561 * Reset the system. It is called by machine_restart().
562 */
563static void mxs_restart(char mode, const char *cmd)
564{
565 struct device_node *np;
566 void __iomem *reset_addr;
567
568 np = of_find_compatible_node(NULL, NULL, "fsl,clkctrl");
569 reset_addr = of_iomap(np, 0);
570 if (!reset_addr)
571 goto soft;
572
573 if (of_device_is_compatible(np, "fsl,imx23-clkctrl"))
574 reset_addr += MX23_CLKCTRL_RESET_OFFSET;
575 else
576 reset_addr += MX28_CLKCTRL_RESET_OFFSET;
461 577
462static const char *imx28_dt_compat[] __initdata = { 578 /* reset the chip */
579 __mxs_setl(MXS_CLKCTRL_RESET_CHIP, reset_addr);
580
581 pr_err("Failed to assert the chip reset\n");
582
583 /* Delay to allow the serial port to show the message */
584 mdelay(50);
585
586soft:
587 /* We'll take a jump through zero as a poor second */
588 soft_restart(0);
589}
590
591static void __init mxs_timer_init(void)
592{
593 if (of_machine_is_compatible("fsl,imx23"))
594 mx23_clocks_init();
595 else
596 mx28_clocks_init();
597 clocksource_of_init();
598}
599
600static const char *mxs_dt_compat[] __initdata = {
463 "fsl,imx28", 601 "fsl,imx28",
602 "fsl,imx23",
464 NULL, 603 NULL,
465}; 604};
466 605
467DT_MACHINE_START(IMX23, "Freescale i.MX23 (Device Tree)") 606DT_MACHINE_START(MXS, "Freescale MXS (Device Tree)")
468 .map_io = mx23_map_io, 607 .map_io = debug_ll_io_init,
469 .init_irq = icoll_init_irq, 608 .init_irq = irqchip_init,
470 .handle_irq = icoll_handle_irq,
471 .init_time = imx23_timer_init,
472 .init_machine = mxs_machine_init,
473 .dt_compat = imx23_dt_compat,
474 .restart = mxs_restart,
475MACHINE_END
476
477DT_MACHINE_START(IMX28, "Freescale i.MX28 (Device Tree)")
478 .map_io = mx28_map_io,
479 .init_irq = icoll_init_irq,
480 .handle_irq = icoll_handle_irq, 609 .handle_irq = icoll_handle_irq,
481 .init_time = imx28_timer_init, 610 .init_time = mxs_timer_init,
482 .init_machine = mxs_machine_init, 611 .init_machine = mxs_machine_init,
483 .dt_compat = imx28_dt_compat, 612 .init_late = mxs_pm_init,
613 .dt_compat = mxs_dt_compat,
484 .restart = mxs_restart, 614 .restart = mxs_restart,
485MACHINE_END 615MACHINE_END