Commit | Line | Data |
---|---|---|
bc3a59c1 DA |
1 | /* |
2 | * Copyright 2012 Freescale Semiconductor, Inc. | |
3 | * Copyright 2012 Linaro Ltd. | |
4 | * | |
5 | * The code contained herein is licensed under the GNU General Public | |
6 | * License. You may obtain a copy of the GNU General Public License | |
7 | * Version 2 or later at the following locations: | |
8 | * | |
9 | * http://www.opensource.org/licenses/gpl-license.html | |
10 | * http://www.gnu.org/copyleft/gpl.html | |
11 | */ | |
12 | ||
13 | #include <linux/clk.h> | |
3cb7825b | 14 | #include <linux/clk/mxs.h> |
bc3a59c1 | 15 | #include <linux/clkdev.h> |
2c7c2c1d | 16 | #include <linux/delay.h> |
bc3a59c1 | 17 | #include <linux/err.h> |
2c7c2c1d | 18 | #include <linux/gpio.h> |
bc3a59c1 | 19 | #include <linux/init.h> |
6a8e95b0 | 20 | #include <linux/irqchip/mxs.h> |
7b6d864b | 21 | #include <linux/reboot.h> |
3143bbb4 | 22 | #include <linux/micrel_phy.h> |
974a9af5 | 23 | #include <linux/of_address.h> |
bc3a59c1 | 24 | #include <linux/of_platform.h> |
3143bbb4 | 25 | #include <linux/phy.h> |
2c7c2c1d | 26 | #include <linux/pinctrl/consumer.h> |
2046338d | 27 | #include <linux/sys_soc.h> |
bc3a59c1 | 28 | #include <asm/mach/arch.h> |
1f629564 | 29 | #include <asm/mach/map.h> |
bc3a59c1 | 30 | #include <asm/mach/time.h> |
974a9af5 | 31 | #include <asm/system_misc.h> |
0b48d3a6 | 32 | |
45680995 SG |
33 | #include "pm.h" |
34 | ||
0b48d3a6 SG |
35 | /* MXS DIGCTL SAIF CLKMUX */ |
36 | #define MXS_DIGCTL_SAIF_CLKMUX_DIRECT 0x0 | |
37 | #define MXS_DIGCTL_SAIF_CLKMUX_CROSSINPUT 0x1 | |
38 | #define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0 0x2 | |
39 | #define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR1 0x3 | |
40 | ||
2046338d FE |
41 | #define HW_DIGCTL_CHIPID 0x310 |
42 | #define HW_DIGCTL_CHIPID_MASK (0xffff << 16) | |
43 | #define HW_DIGCTL_REV_MASK 0xff | |
44 | #define HW_DIGCTL_CHIPID_MX23 (0x3780 << 16) | |
45 | #define HW_DIGCTL_CHIPID_MX28 (0x2800 << 16) | |
46 | ||
47 | #define MXS_CHIP_REVISION_1_0 0x10 | |
48 | #define MXS_CHIP_REVISION_1_1 0x11 | |
49 | #define MXS_CHIP_REVISION_1_2 0x12 | |
50 | #define MXS_CHIP_REVISION_1_3 0x13 | |
51 | #define MXS_CHIP_REVISION_1_4 0x14 | |
52 | #define MXS_CHIP_REV_UNKNOWN 0xff | |
53 | ||
0b48d3a6 SG |
54 | #define MXS_GPIO_NR(bank, nr) ((bank) * 32 + (nr)) |
55 | ||
56 | #define MXS_SET_ADDR 0x4 | |
57 | #define MXS_CLR_ADDR 0x8 | |
58 | #define MXS_TOG_ADDR 0xc | |
59 | ||
2046338d FE |
60 | static u32 chipid; |
61 | static u32 socid; | |
62 | ||
56b7eec0 LW |
63 | static void __iomem *reset_addr; |
64 | ||
0b48d3a6 SG |
65 | static inline void __mxs_setl(u32 mask, void __iomem *reg) |
66 | { | |
67 | __raw_writel(mask, reg + MXS_SET_ADDR); | |
68 | } | |
69 | ||
70 | static inline void __mxs_clrl(u32 mask, void __iomem *reg) | |
71 | { | |
72 | __raw_writel(mask, reg + MXS_CLR_ADDR); | |
73 | } | |
74 | ||
75 | static inline void __mxs_togl(u32 mask, void __iomem *reg) | |
76 | { | |
77 | __raw_writel(mask, reg + MXS_TOG_ADDR); | |
78 | } | |
bc3a59c1 | 79 | |
1bff2d76 SG |
80 | #define OCOTP_WORD_OFFSET 0x20 |
81 | #define OCOTP_WORD_COUNT 0x20 | |
82 | ||
83 | #define BM_OCOTP_CTRL_BUSY (1 << 8) | |
84 | #define BM_OCOTP_CTRL_ERROR (1 << 9) | |
85 | #define BM_OCOTP_CTRL_RD_BANK_OPEN (1 << 12) | |
86 | ||
87 | static DEFINE_MUTEX(ocotp_mutex); | |
88 | static u32 ocotp_words[OCOTP_WORD_COUNT]; | |
89 | ||
90 | static const u32 *mxs_get_ocotp(void) | |
91 | { | |
92 | struct device_node *np; | |
93 | void __iomem *ocotp_base; | |
94 | int timeout = 0x400; | |
95 | size_t i; | |
96 | static int once; | |
97 | ||
98 | if (once) | |
99 | return ocotp_words; | |
100 | ||
101 | np = of_find_compatible_node(NULL, NULL, "fsl,ocotp"); | |
102 | ocotp_base = of_iomap(np, 0); | |
103 | WARN_ON(!ocotp_base); | |
104 | ||
105 | mutex_lock(&ocotp_mutex); | |
106 | ||
107 | /* | |
108 | * clk_enable(hbus_clk) for ocotp can be skipped | |
109 | * as it must be on when system is running. | |
110 | */ | |
111 | ||
112 | /* try to clear ERROR bit */ | |
113 | __mxs_clrl(BM_OCOTP_CTRL_ERROR, ocotp_base); | |
114 | ||
115 | /* check both BUSY and ERROR cleared */ | |
116 | while ((__raw_readl(ocotp_base) & | |
117 | (BM_OCOTP_CTRL_BUSY | BM_OCOTP_CTRL_ERROR)) && --timeout) | |
118 | cpu_relax(); | |
119 | ||
120 | if (unlikely(!timeout)) | |
121 | goto error_unlock; | |
122 | ||
123 | /* open OCOTP banks for read */ | |
124 | __mxs_setl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base); | |
125 | ||
126 | /* approximately wait 32 hclk cycles */ | |
127 | udelay(1); | |
128 | ||
129 | /* poll BUSY bit becoming cleared */ | |
130 | timeout = 0x400; | |
131 | while ((__raw_readl(ocotp_base) & BM_OCOTP_CTRL_BUSY) && --timeout) | |
132 | cpu_relax(); | |
133 | ||
134 | if (unlikely(!timeout)) | |
135 | goto error_unlock; | |
136 | ||
137 | for (i = 0; i < OCOTP_WORD_COUNT; i++) | |
138 | ocotp_words[i] = __raw_readl(ocotp_base + OCOTP_WORD_OFFSET + | |
139 | i * 0x10); | |
140 | ||
141 | /* close banks for power saving */ | |
142 | __mxs_clrl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base); | |
143 | ||
144 | once = 1; | |
145 | ||
146 | mutex_unlock(&ocotp_mutex); | |
147 | ||
148 | return ocotp_words; | |
149 | ||
150 | error_unlock: | |
151 | mutex_unlock(&ocotp_mutex); | |
152 | pr_err("%s: timeout in reading OCOTP\n", __func__); | |
153 | return NULL; | |
154 | } | |
155 | ||
5653acc2 SG |
156 | enum mac_oui { |
157 | OUI_FSL, | |
158 | OUI_DENX, | |
8eec4b31 | 159 | OUI_CRYSTALFONTZ, |
df0355f2 | 160 | OUI_I2SE, |
9648b2ef | 161 | OUI_ARMADEUS, |
5653acc2 SG |
162 | }; |
163 | ||
164 | static void __init update_fec_mac_prop(enum mac_oui oui) | |
165 | { | |
166 | struct device_node *np, *from = NULL; | |
fa7c865a | 167 | struct property *newmac; |
5653acc2 SG |
168 | const u32 *ocotp = mxs_get_ocotp(); |
169 | u8 *macaddr; | |
170 | u32 val; | |
171 | int i; | |
172 | ||
173 | for (i = 0; i < 2; i++) { | |
174 | np = of_find_compatible_node(from, NULL, "fsl,imx28-fec"); | |
175 | if (!np) | |
176 | return; | |
16d47701 | 177 | |
5653acc2 SG |
178 | from = np; |
179 | ||
16d47701 MV |
180 | if (of_get_property(np, "local-mac-address", NULL)) |
181 | continue; | |
182 | ||
5653acc2 SG |
183 | newmac = kzalloc(sizeof(*newmac) + 6, GFP_KERNEL); |
184 | if (!newmac) | |
185 | return; | |
186 | newmac->value = newmac + 1; | |
187 | newmac->length = 6; | |
188 | ||
189 | newmac->name = kstrdup("local-mac-address", GFP_KERNEL); | |
190 | if (!newmac->name) { | |
191 | kfree(newmac); | |
192 | return; | |
193 | } | |
194 | ||
195 | /* | |
196 | * OCOTP only stores the last 4 octets for each mac address, | |
197 | * so hard-code OUI here. | |
198 | */ | |
199 | macaddr = newmac->value; | |
200 | switch (oui) { | |
201 | case OUI_FSL: | |
202 | macaddr[0] = 0x00; | |
203 | macaddr[1] = 0x04; | |
204 | macaddr[2] = 0x9f; | |
205 | break; | |
206 | case OUI_DENX: | |
207 | macaddr[0] = 0xc0; | |
208 | macaddr[1] = 0xe5; | |
209 | macaddr[2] = 0x4e; | |
210 | break; | |
8eec4b31 MR |
211 | case OUI_CRYSTALFONTZ: |
212 | macaddr[0] = 0x58; | |
213 | macaddr[1] = 0xb9; | |
214 | macaddr[2] = 0xe1; | |
215 | break; | |
df0355f2 MH |
216 | case OUI_I2SE: |
217 | macaddr[0] = 0x00; | |
218 | macaddr[1] = 0x01; | |
219 | macaddr[2] = 0x87; | |
220 | break; | |
9648b2ef GGM |
221 | case OUI_ARMADEUS: |
222 | macaddr[0] = 0x00; | |
223 | macaddr[1] = 0x1e; | |
224 | macaddr[2] = 0xac; | |
225 | break; | |
5653acc2 SG |
226 | } |
227 | val = ocotp[i]; | |
228 | macaddr[3] = (val >> 16) & 0xff; | |
229 | macaddr[4] = (val >> 8) & 0xff; | |
230 | macaddr[5] = (val >> 0) & 0xff; | |
231 | ||
79d1c712 | 232 | of_update_property(np, newmac); |
5653acc2 SG |
233 | } |
234 | } | |
235 | ||
8fa62e11 | 236 | static inline void enable_clk_enet_out(void) |
bc3a59c1 | 237 | { |
8fa62e11 | 238 | struct clk *clk = clk_get_sys("enet_out", NULL); |
bc3a59c1 | 239 | |
bc3a59c1 DA |
240 | if (!IS_ERR(clk)) |
241 | clk_prepare_enable(clk); | |
8fa62e11 | 242 | } |
5653acc2 | 243 | |
8fa62e11 MV |
244 | static void __init imx28_evk_init(void) |
245 | { | |
5653acc2 | 246 | update_fec_mac_prop(OUI_FSL); |
ab2815c3 | 247 | |
e317317a | 248 | mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0); |
bc3a59c1 DA |
249 | } |
250 | ||
9648b2ef GGM |
251 | static void __init imx28_apf28_init(void) |
252 | { | |
253 | update_fec_mac_prop(OUI_ARMADEUS); | |
254 | } | |
255 | ||
3143bbb4 SG |
256 | static int apx4devkit_phy_fixup(struct phy_device *phy) |
257 | { | |
258 | phy->dev_flags |= MICREL_PHY_50MHZ_CLK; | |
259 | return 0; | |
260 | } | |
261 | ||
262 | static void __init apx4devkit_init(void) | |
263 | { | |
264 | enable_clk_enet_out(); | |
265 | ||
266 | if (IS_BUILTIN(CONFIG_PHYLIB)) | |
510d573f | 267 | phy_register_fixup_for_uid(PHY_ID_KSZ8051, MICREL_PHY_ID_MASK, |
3143bbb4 SG |
268 | apx4devkit_phy_fixup); |
269 | } | |
270 | ||
2c7c2c1d SG |
271 | #define ENET0_MDC__GPIO_4_0 MXS_GPIO_NR(4, 0) |
272 | #define ENET0_MDIO__GPIO_4_1 MXS_GPIO_NR(4, 1) | |
273 | #define ENET0_RX_EN__GPIO_4_2 MXS_GPIO_NR(4, 2) | |
274 | #define ENET0_RXD0__GPIO_4_3 MXS_GPIO_NR(4, 3) | |
275 | #define ENET0_RXD1__GPIO_4_4 MXS_GPIO_NR(4, 4) | |
276 | #define ENET0_TX_EN__GPIO_4_6 MXS_GPIO_NR(4, 6) | |
277 | #define ENET0_TXD0__GPIO_4_7 MXS_GPIO_NR(4, 7) | |
278 | #define ENET0_TXD1__GPIO_4_8 MXS_GPIO_NR(4, 8) | |
279 | #define ENET_CLK__GPIO_4_16 MXS_GPIO_NR(4, 16) | |
280 | ||
281 | #define TX28_FEC_PHY_POWER MXS_GPIO_NR(3, 29) | |
282 | #define TX28_FEC_PHY_RESET MXS_GPIO_NR(4, 13) | |
283 | #define TX28_FEC_nINT MXS_GPIO_NR(4, 5) | |
284 | ||
19c233b7 | 285 | static const struct gpio const tx28_gpios[] __initconst = { |
2c7c2c1d SG |
286 | { ENET0_MDC__GPIO_4_0, GPIOF_OUT_INIT_LOW, "GPIO_4_0" }, |
287 | { ENET0_MDIO__GPIO_4_1, GPIOF_OUT_INIT_LOW, "GPIO_4_1" }, | |
288 | { ENET0_RX_EN__GPIO_4_2, GPIOF_OUT_INIT_LOW, "GPIO_4_2" }, | |
289 | { ENET0_RXD0__GPIO_4_3, GPIOF_OUT_INIT_LOW, "GPIO_4_3" }, | |
290 | { ENET0_RXD1__GPIO_4_4, GPIOF_OUT_INIT_LOW, "GPIO_4_4" }, | |
291 | { ENET0_TX_EN__GPIO_4_6, GPIOF_OUT_INIT_LOW, "GPIO_4_6" }, | |
292 | { ENET0_TXD0__GPIO_4_7, GPIOF_OUT_INIT_LOW, "GPIO_4_7" }, | |
293 | { ENET0_TXD1__GPIO_4_8, GPIOF_OUT_INIT_LOW, "GPIO_4_8" }, | |
294 | { ENET_CLK__GPIO_4_16, GPIOF_OUT_INIT_LOW, "GPIO_4_16" }, | |
295 | { TX28_FEC_PHY_POWER, GPIOF_OUT_INIT_LOW, "fec-phy-power" }, | |
296 | { TX28_FEC_PHY_RESET, GPIOF_OUT_INIT_LOW, "fec-phy-reset" }, | |
297 | { TX28_FEC_nINT, GPIOF_DIR_IN, "fec-int" }, | |
298 | }; | |
299 | ||
300 | static void __init tx28_post_init(void) | |
301 | { | |
302 | struct device_node *np; | |
303 | struct platform_device *pdev; | |
304 | struct pinctrl *pctl; | |
305 | int ret; | |
306 | ||
307 | enable_clk_enet_out(); | |
308 | ||
309 | np = of_find_compatible_node(NULL, NULL, "fsl,imx28-fec"); | |
310 | pdev = of_find_device_by_node(np); | |
311 | if (!pdev) { | |
312 | pr_err("%s: failed to find fec device\n", __func__); | |
313 | return; | |
314 | } | |
315 | ||
316 | pctl = pinctrl_get_select(&pdev->dev, "gpio_mode"); | |
317 | if (IS_ERR(pctl)) { | |
318 | pr_err("%s: failed to get pinctrl state\n", __func__); | |
319 | return; | |
320 | } | |
321 | ||
322 | ret = gpio_request_array(tx28_gpios, ARRAY_SIZE(tx28_gpios)); | |
323 | if (ret) { | |
324 | pr_err("%s: failed to request gpios: %d\n", __func__, ret); | |
325 | return; | |
326 | } | |
327 | ||
328 | /* Power up fec phy */ | |
329 | gpio_set_value(TX28_FEC_PHY_POWER, 1); | |
330 | msleep(26); /* 25ms according to data sheet */ | |
331 | ||
332 | /* Mode strap pins */ | |
333 | gpio_set_value(ENET0_RX_EN__GPIO_4_2, 1); | |
334 | gpio_set_value(ENET0_RXD0__GPIO_4_3, 1); | |
335 | gpio_set_value(ENET0_RXD1__GPIO_4_4, 1); | |
336 | ||
337 | udelay(100); /* minimum assertion time for nRST */ | |
338 | ||
339 | /* Deasserting FEC PHY RESET */ | |
340 | gpio_set_value(TX28_FEC_PHY_RESET, 1); | |
341 | ||
342 | pinctrl_put(pctl); | |
343 | } | |
344 | ||
ed138c36 | 345 | static void __init crystalfontz_init(void) |
8eec4b31 | 346 | { |
8eec4b31 MR |
347 | update_fec_mac_prop(OUI_CRYSTALFONTZ); |
348 | } | |
349 | ||
df0355f2 MH |
350 | static void __init duckbill_init(void) |
351 | { | |
352 | update_fec_mac_prop(OUI_I2SE); | |
353 | } | |
354 | ||
e0ec2f39 MV |
355 | static void __init m28cu3_init(void) |
356 | { | |
357 | update_fec_mac_prop(OUI_DENX); | |
358 | } | |
359 | ||
2046338d | 360 | static const char __init *mxs_get_soc_id(void) |
e0f7d905 | 361 | { |
2046338d FE |
362 | struct device_node *np; |
363 | void __iomem *digctl_base; | |
364 | ||
365 | np = of_find_compatible_node(NULL, NULL, "fsl,imx23-digctl"); | |
366 | digctl_base = of_iomap(np, 0); | |
367 | WARN_ON(!digctl_base); | |
368 | ||
369 | chipid = readl(digctl_base + HW_DIGCTL_CHIPID); | |
370 | socid = chipid & HW_DIGCTL_CHIPID_MASK; | |
371 | ||
372 | iounmap(digctl_base); | |
373 | of_node_put(np); | |
374 | ||
375 | switch (socid) { | |
376 | case HW_DIGCTL_CHIPID_MX23: | |
377 | return "i.MX23"; | |
378 | case HW_DIGCTL_CHIPID_MX28: | |
379 | return "i.MX28"; | |
380 | default: | |
381 | return "Unknown"; | |
382 | } | |
383 | } | |
384 | ||
385 | static u32 __init mxs_get_cpu_rev(void) | |
386 | { | |
387 | u32 rev = chipid & HW_DIGCTL_REV_MASK; | |
388 | ||
389 | switch (socid) { | |
390 | case HW_DIGCTL_CHIPID_MX23: | |
391 | switch (rev) { | |
392 | case 0x0: | |
393 | return MXS_CHIP_REVISION_1_0; | |
394 | case 0x1: | |
395 | return MXS_CHIP_REVISION_1_1; | |
396 | case 0x2: | |
397 | return MXS_CHIP_REVISION_1_2; | |
398 | case 0x3: | |
399 | return MXS_CHIP_REVISION_1_3; | |
400 | case 0x4: | |
401 | return MXS_CHIP_REVISION_1_4; | |
402 | default: | |
403 | return MXS_CHIP_REV_UNKNOWN; | |
404 | } | |
405 | case HW_DIGCTL_CHIPID_MX28: | |
406 | switch (rev) { | |
407 | case 0x0: | |
408 | return MXS_CHIP_REVISION_1_1; | |
409 | case 0x1: | |
410 | return MXS_CHIP_REVISION_1_2; | |
411 | default: | |
412 | return MXS_CHIP_REV_UNKNOWN; | |
413 | } | |
414 | default: | |
415 | return MXS_CHIP_REV_UNKNOWN; | |
416 | } | |
417 | } | |
418 | ||
419 | static const char __init *mxs_get_revision(void) | |
420 | { | |
421 | u32 rev = mxs_get_cpu_rev(); | |
422 | ||
423 | if (rev != MXS_CHIP_REV_UNKNOWN) | |
e115d63c | 424 | return kasprintf(GFP_KERNEL, "%d.%d", (rev >> 4) & 0xf, |
2046338d FE |
425 | rev & 0xf); |
426 | else | |
427 | return kasprintf(GFP_KERNEL, "%s", "Unknown"); | |
e0f7d905 MR |
428 | } |
429 | ||
56b7eec0 LW |
430 | #define MX23_CLKCTRL_RESET_OFFSET 0x120 |
431 | #define MX28_CLKCTRL_RESET_OFFSET 0x1e0 | |
432 | ||
433 | static int __init mxs_restart_init(void) | |
434 | { | |
435 | struct device_node *np; | |
436 | ||
437 | np = of_find_compatible_node(NULL, NULL, "fsl,clkctrl"); | |
438 | reset_addr = of_iomap(np, 0); | |
439 | if (!reset_addr) | |
440 | return -ENODEV; | |
441 | ||
442 | if (of_device_is_compatible(np, "fsl,imx23-clkctrl")) | |
443 | reset_addr += MX23_CLKCTRL_RESET_OFFSET; | |
444 | else | |
445 | reset_addr += MX28_CLKCTRL_RESET_OFFSET; | |
446 | of_node_put(np); | |
447 | ||
448 | return 0; | |
449 | } | |
450 | ||
9a4cc056 EB |
451 | static void __init eukrea_mbmx283lc_init(void) |
452 | { | |
453 | mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0); | |
454 | } | |
455 | ||
bc3a59c1 DA |
456 | static void __init mxs_machine_init(void) |
457 | { | |
2046338d FE |
458 | struct device_node *root; |
459 | struct device *parent; | |
460 | struct soc_device *soc_dev; | |
461 | struct soc_device_attribute *soc_dev_attr; | |
462 | int ret; | |
463 | ||
464 | soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); | |
465 | if (!soc_dev_attr) | |
466 | return; | |
467 | ||
468 | root = of_find_node_by_path("/"); | |
469 | ret = of_property_read_string(root, "model", &soc_dev_attr->machine); | |
470 | if (ret) | |
471 | return; | |
472 | ||
473 | soc_dev_attr->family = "Freescale MXS Family"; | |
474 | soc_dev_attr->soc_id = mxs_get_soc_id(); | |
475 | soc_dev_attr->revision = mxs_get_revision(); | |
476 | ||
477 | soc_dev = soc_device_register(soc_dev_attr); | |
478 | if (IS_ERR(soc_dev)) { | |
479 | kfree(soc_dev_attr->revision); | |
480 | kfree(soc_dev_attr); | |
481 | return; | |
482 | } | |
483 | ||
484 | parent = soc_device_to_device(soc_dev); | |
485 | ||
bc3a59c1 DA |
486 | if (of_machine_is_compatible("fsl,imx28-evk")) |
487 | imx28_evk_init(); | |
9648b2ef GGM |
488 | if (of_machine_is_compatible("armadeus,imx28-apf28")) |
489 | imx28_apf28_init(); | |
3143bbb4 SG |
490 | else if (of_machine_is_compatible("bluegiga,apx4devkit")) |
491 | apx4devkit_init(); | |
f71f2e95 | 492 | else if (of_machine_is_compatible("crystalfontz,cfa10036")) |
ed138c36 | 493 | crystalfontz_init(); |
9a4cc056 EB |
494 | else if (of_machine_is_compatible("eukrea,mbmx283lc")) |
495 | eukrea_mbmx283lc_init(); | |
df0355f2 MH |
496 | else if (of_machine_is_compatible("i2se,duckbill")) |
497 | duckbill_init(); | |
e0ec2f39 MV |
498 | else if (of_machine_is_compatible("msr,m28cu3")) |
499 | m28cu3_init(); | |
bc3a59c1 DA |
500 | |
501 | of_platform_populate(NULL, of_default_bus_match_table, | |
496322bc | 502 | NULL, parent); |
2c7c2c1d | 503 | |
56b7eec0 LW |
504 | mxs_restart_init(); |
505 | ||
2c7c2c1d SG |
506 | if (of_machine_is_compatible("karo,tx28")) |
507 | tx28_post_init(); | |
bc3a59c1 DA |
508 | } |
509 | ||
974a9af5 SG |
510 | #define MXS_CLKCTRL_RESET_CHIP (1 << 1) |
511 | ||
512 | /* | |
513 | * Reset the system. It is called by machine_restart(). | |
514 | */ | |
7b6d864b | 515 | static void mxs_restart(enum reboot_mode mode, const char *cmd) |
974a9af5 | 516 | { |
56b7eec0 LW |
517 | if (reset_addr) { |
518 | /* reset the chip */ | |
519 | __mxs_setl(MXS_CLKCTRL_RESET_CHIP, reset_addr); | |
974a9af5 | 520 | |
56b7eec0 | 521 | pr_err("Failed to assert the chip reset\n"); |
974a9af5 | 522 | |
56b7eec0 LW |
523 | /* Delay to allow the serial port to show the message */ |
524 | mdelay(50); | |
525 | } | |
974a9af5 | 526 | |
974a9af5 SG |
527 | /* We'll take a jump through zero as a poor second */ |
528 | soft_restart(0); | |
529 | } | |
530 | ||
19c233b7 | 531 | static const char *const mxs_dt_compat[] __initconst = { |
bc3a59c1 | 532 | "fsl,imx28", |
39490ab0 | 533 | "fsl,imx23", |
bc3a59c1 DA |
534 | NULL, |
535 | }; | |
536 | ||
39490ab0 | 537 | DT_MACHINE_START(MXS, "Freescale MXS (Device Tree)") |
4e0a1b8c | 538 | .handle_irq = icoll_handle_irq, |
bc3a59c1 | 539 | .init_machine = mxs_machine_init, |
45680995 | 540 | .init_late = mxs_pm_init, |
39490ab0 | 541 | .dt_compat = mxs_dt_compat, |
bc3a59c1 DA |
542 | .restart = mxs_restart, |
543 | MACHINE_END |