diff options
Diffstat (limited to 'arch/arm/mach-mxs/mach-mxs.c')
-rw-r--r-- | arch/arm/mach-mxs/mach-mxs.c | 188 |
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 | |||
49 | static inline void __mxs_setl(u32 mask, void __iomem *reg) | ||
50 | { | ||
51 | __raw_writel(mask, reg + MXS_SET_ADDR); | ||
52 | } | ||
53 | |||
54 | static inline void __mxs_clrl(u32 mask, void __iomem *reg) | ||
55 | { | ||
56 | __raw_writel(mask, reg + MXS_CLR_ADDR); | ||
57 | } | ||
58 | |||
59 | static inline void __mxs_togl(u32 mask, void __iomem *reg) | ||
60 | { | ||
61 | __raw_writel(mask, reg + MXS_TOG_ADDR); | ||
62 | } | ||
30 | 63 | ||
31 | static struct fb_videomode mx23evk_video_modes[] = { | 64 | static 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 | ||
168 | static 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 | ||
173 | static void __init imx28_timer_init(void) | 208 | static DEFINE_MUTEX(ocotp_mutex); |
209 | static u32 ocotp_words[OCOTP_WORD_COUNT]; | ||
210 | |||
211 | static 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 | |||
271 | error_unlock: | ||
272 | mutex_unlock(&ocotp_mutex); | ||
273 | pr_err("%s: timeout in reading OCOTP\n", __func__); | ||
274 | return NULL; | ||
176 | } | 275 | } |
177 | 276 | ||
178 | enum mac_oui { | 277 | enum 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 | ||
457 | static 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 | */ | ||
563 | static 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 | ||
462 | static 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 | |||
586 | soft: | ||
587 | /* We'll take a jump through zero as a poor second */ | ||
588 | soft_restart(0); | ||
589 | } | ||
590 | |||
591 | static 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 | |||
600 | static const char *mxs_dt_compat[] __initdata = { | ||
463 | "fsl,imx28", | 601 | "fsl,imx28", |
602 | "fsl,imx23", | ||
464 | NULL, | 603 | NULL, |
465 | }; | 604 | }; |
466 | 605 | ||
467 | DT_MACHINE_START(IMX23, "Freescale i.MX23 (Device Tree)") | 606 | DT_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, | ||
475 | MACHINE_END | ||
476 | |||
477 | DT_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, |
485 | MACHINE_END | 615 | MACHINE_END |