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> |
633ef4c7 | 16 | #include <linux/clocksource.h> |
5cd86ef5 | 17 | #include <linux/clk-provider.h> |
2c7c2c1d | 18 | #include <linux/delay.h> |
bc3a59c1 | 19 | #include <linux/err.h> |
2c7c2c1d | 20 | #include <linux/gpio.h> |
bc3a59c1 | 21 | #include <linux/init.h> |
6a8e95b0 | 22 | #include <linux/irqchip/mxs.h> |
7b6d864b | 23 | #include <linux/reboot.h> |
3143bbb4 | 24 | #include <linux/micrel_phy.h> |
974a9af5 | 25 | #include <linux/of_address.h> |
bc3a59c1 | 26 | #include <linux/of_platform.h> |
3143bbb4 | 27 | #include <linux/phy.h> |
2c7c2c1d | 28 | #include <linux/pinctrl/consumer.h> |
2046338d | 29 | #include <linux/sys_soc.h> |
bc3a59c1 | 30 | #include <asm/mach/arch.h> |
1f629564 | 31 | #include <asm/mach/map.h> |
bc3a59c1 | 32 | #include <asm/mach/time.h> |
974a9af5 | 33 | #include <asm/system_misc.h> |
0b48d3a6 | 34 | |
45680995 SG |
35 | #include "pm.h" |
36 | ||
0b48d3a6 SG |
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 | ||
2046338d FE |
43 | #define HW_DIGCTL_CHIPID 0x310 |
44 | #define HW_DIGCTL_CHIPID_MASK (0xffff << 16) | |
45 | #define HW_DIGCTL_REV_MASK 0xff | |
46 | #define HW_DIGCTL_CHIPID_MX23 (0x3780 << 16) | |
47 | #define HW_DIGCTL_CHIPID_MX28 (0x2800 << 16) | |
48 | ||
49 | #define MXS_CHIP_REVISION_1_0 0x10 | |
50 | #define MXS_CHIP_REVISION_1_1 0x11 | |
51 | #define MXS_CHIP_REVISION_1_2 0x12 | |
52 | #define MXS_CHIP_REVISION_1_3 0x13 | |
53 | #define MXS_CHIP_REVISION_1_4 0x14 | |
54 | #define MXS_CHIP_REV_UNKNOWN 0xff | |
55 | ||
0b48d3a6 SG |
56 | #define MXS_GPIO_NR(bank, nr) ((bank) * 32 + (nr)) |
57 | ||
58 | #define MXS_SET_ADDR 0x4 | |
59 | #define MXS_CLR_ADDR 0x8 | |
60 | #define MXS_TOG_ADDR 0xc | |
61 | ||
2046338d FE |
62 | static u32 chipid; |
63 | static u32 socid; | |
64 | ||
56b7eec0 LW |
65 | static void __iomem *reset_addr; |
66 | ||
0b48d3a6 SG |
67 | static inline void __mxs_setl(u32 mask, void __iomem *reg) |
68 | { | |
69 | __raw_writel(mask, reg + MXS_SET_ADDR); | |
70 | } | |
71 | ||
72 | static inline void __mxs_clrl(u32 mask, void __iomem *reg) | |
73 | { | |
74 | __raw_writel(mask, reg + MXS_CLR_ADDR); | |
75 | } | |
76 | ||
77 | static inline void __mxs_togl(u32 mask, void __iomem *reg) | |
78 | { | |
79 | __raw_writel(mask, reg + MXS_TOG_ADDR); | |
80 | } | |
bc3a59c1 | 81 | |
1bff2d76 SG |
82 | #define OCOTP_WORD_OFFSET 0x20 |
83 | #define OCOTP_WORD_COUNT 0x20 | |
84 | ||
85 | #define BM_OCOTP_CTRL_BUSY (1 << 8) | |
86 | #define BM_OCOTP_CTRL_ERROR (1 << 9) | |
87 | #define BM_OCOTP_CTRL_RD_BANK_OPEN (1 << 12) | |
88 | ||
89 | static DEFINE_MUTEX(ocotp_mutex); | |
90 | static u32 ocotp_words[OCOTP_WORD_COUNT]; | |
91 | ||
92 | static const u32 *mxs_get_ocotp(void) | |
93 | { | |
94 | struct device_node *np; | |
95 | void __iomem *ocotp_base; | |
96 | int timeout = 0x400; | |
97 | size_t i; | |
98 | static int once; | |
99 | ||
100 | if (once) | |
101 | return ocotp_words; | |
102 | ||
103 | np = of_find_compatible_node(NULL, NULL, "fsl,ocotp"); | |
104 | ocotp_base = of_iomap(np, 0); | |
105 | WARN_ON(!ocotp_base); | |
106 | ||
107 | mutex_lock(&ocotp_mutex); | |
108 | ||
109 | /* | |
110 | * clk_enable(hbus_clk) for ocotp can be skipped | |
111 | * as it must be on when system is running. | |
112 | */ | |
113 | ||
114 | /* try to clear ERROR bit */ | |
115 | __mxs_clrl(BM_OCOTP_CTRL_ERROR, ocotp_base); | |
116 | ||
117 | /* check both BUSY and ERROR cleared */ | |
118 | while ((__raw_readl(ocotp_base) & | |
119 | (BM_OCOTP_CTRL_BUSY | BM_OCOTP_CTRL_ERROR)) && --timeout) | |
120 | cpu_relax(); | |
121 | ||
122 | if (unlikely(!timeout)) | |
123 | goto error_unlock; | |
124 | ||
125 | /* open OCOTP banks for read */ | |
126 | __mxs_setl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base); | |
127 | ||
128 | /* approximately wait 32 hclk cycles */ | |
129 | udelay(1); | |
130 | ||
131 | /* poll BUSY bit becoming cleared */ | |
132 | timeout = 0x400; | |
133 | while ((__raw_readl(ocotp_base) & BM_OCOTP_CTRL_BUSY) && --timeout) | |
134 | cpu_relax(); | |
135 | ||
136 | if (unlikely(!timeout)) | |
137 | goto error_unlock; | |
138 | ||
139 | for (i = 0; i < OCOTP_WORD_COUNT; i++) | |
140 | ocotp_words[i] = __raw_readl(ocotp_base + OCOTP_WORD_OFFSET + | |
141 | i * 0x10); | |
142 | ||
143 | /* close banks for power saving */ | |
144 | __mxs_clrl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base); | |
145 | ||
146 | once = 1; | |
147 | ||
148 | mutex_unlock(&ocotp_mutex); | |
149 | ||
150 | return ocotp_words; | |
151 | ||
152 | error_unlock: | |
153 | mutex_unlock(&ocotp_mutex); | |
154 | pr_err("%s: timeout in reading OCOTP\n", __func__); | |
155 | return NULL; | |
156 | } | |
157 | ||
5653acc2 SG |
158 | enum mac_oui { |
159 | OUI_FSL, | |
160 | OUI_DENX, | |
8eec4b31 | 161 | OUI_CRYSTALFONTZ, |
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; | |
5653acc2 SG |
216 | } |
217 | val = ocotp[i]; | |
218 | macaddr[3] = (val >> 16) & 0xff; | |
219 | macaddr[4] = (val >> 8) & 0xff; | |
220 | macaddr[5] = (val >> 0) & 0xff; | |
221 | ||
79d1c712 | 222 | of_update_property(np, newmac); |
5653acc2 SG |
223 | } |
224 | } | |
225 | ||
8fa62e11 | 226 | static inline void enable_clk_enet_out(void) |
bc3a59c1 | 227 | { |
8fa62e11 | 228 | struct clk *clk = clk_get_sys("enet_out", NULL); |
bc3a59c1 | 229 | |
bc3a59c1 DA |
230 | if (!IS_ERR(clk)) |
231 | clk_prepare_enable(clk); | |
8fa62e11 | 232 | } |
5653acc2 | 233 | |
8fa62e11 MV |
234 | static void __init imx28_evk_init(void) |
235 | { | |
5653acc2 | 236 | update_fec_mac_prop(OUI_FSL); |
ab2815c3 | 237 | |
e317317a | 238 | mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0); |
bc3a59c1 DA |
239 | } |
240 | ||
3143bbb4 SG |
241 | static int apx4devkit_phy_fixup(struct phy_device *phy) |
242 | { | |
243 | phy->dev_flags |= MICREL_PHY_50MHZ_CLK; | |
244 | return 0; | |
245 | } | |
246 | ||
247 | static void __init apx4devkit_init(void) | |
248 | { | |
249 | enable_clk_enet_out(); | |
250 | ||
251 | if (IS_BUILTIN(CONFIG_PHYLIB)) | |
510d573f | 252 | phy_register_fixup_for_uid(PHY_ID_KSZ8051, MICREL_PHY_ID_MASK, |
3143bbb4 SG |
253 | apx4devkit_phy_fixup); |
254 | } | |
255 | ||
2c7c2c1d SG |
256 | #define ENET0_MDC__GPIO_4_0 MXS_GPIO_NR(4, 0) |
257 | #define ENET0_MDIO__GPIO_4_1 MXS_GPIO_NR(4, 1) | |
258 | #define ENET0_RX_EN__GPIO_4_2 MXS_GPIO_NR(4, 2) | |
259 | #define ENET0_RXD0__GPIO_4_3 MXS_GPIO_NR(4, 3) | |
260 | #define ENET0_RXD1__GPIO_4_4 MXS_GPIO_NR(4, 4) | |
261 | #define ENET0_TX_EN__GPIO_4_6 MXS_GPIO_NR(4, 6) | |
262 | #define ENET0_TXD0__GPIO_4_7 MXS_GPIO_NR(4, 7) | |
263 | #define ENET0_TXD1__GPIO_4_8 MXS_GPIO_NR(4, 8) | |
264 | #define ENET_CLK__GPIO_4_16 MXS_GPIO_NR(4, 16) | |
265 | ||
266 | #define TX28_FEC_PHY_POWER MXS_GPIO_NR(3, 29) | |
267 | #define TX28_FEC_PHY_RESET MXS_GPIO_NR(4, 13) | |
268 | #define TX28_FEC_nINT MXS_GPIO_NR(4, 5) | |
269 | ||
270 | static const struct gpio tx28_gpios[] __initconst = { | |
271 | { ENET0_MDC__GPIO_4_0, GPIOF_OUT_INIT_LOW, "GPIO_4_0" }, | |
272 | { ENET0_MDIO__GPIO_4_1, GPIOF_OUT_INIT_LOW, "GPIO_4_1" }, | |
273 | { ENET0_RX_EN__GPIO_4_2, GPIOF_OUT_INIT_LOW, "GPIO_4_2" }, | |
274 | { ENET0_RXD0__GPIO_4_3, GPIOF_OUT_INIT_LOW, "GPIO_4_3" }, | |
275 | { ENET0_RXD1__GPIO_4_4, GPIOF_OUT_INIT_LOW, "GPIO_4_4" }, | |
276 | { ENET0_TX_EN__GPIO_4_6, GPIOF_OUT_INIT_LOW, "GPIO_4_6" }, | |
277 | { ENET0_TXD0__GPIO_4_7, GPIOF_OUT_INIT_LOW, "GPIO_4_7" }, | |
278 | { ENET0_TXD1__GPIO_4_8, GPIOF_OUT_INIT_LOW, "GPIO_4_8" }, | |
279 | { ENET_CLK__GPIO_4_16, GPIOF_OUT_INIT_LOW, "GPIO_4_16" }, | |
280 | { TX28_FEC_PHY_POWER, GPIOF_OUT_INIT_LOW, "fec-phy-power" }, | |
281 | { TX28_FEC_PHY_RESET, GPIOF_OUT_INIT_LOW, "fec-phy-reset" }, | |
282 | { TX28_FEC_nINT, GPIOF_DIR_IN, "fec-int" }, | |
283 | }; | |
284 | ||
285 | static void __init tx28_post_init(void) | |
286 | { | |
287 | struct device_node *np; | |
288 | struct platform_device *pdev; | |
289 | struct pinctrl *pctl; | |
290 | int ret; | |
291 | ||
292 | enable_clk_enet_out(); | |
293 | ||
294 | np = of_find_compatible_node(NULL, NULL, "fsl,imx28-fec"); | |
295 | pdev = of_find_device_by_node(np); | |
296 | if (!pdev) { | |
297 | pr_err("%s: failed to find fec device\n", __func__); | |
298 | return; | |
299 | } | |
300 | ||
301 | pctl = pinctrl_get_select(&pdev->dev, "gpio_mode"); | |
302 | if (IS_ERR(pctl)) { | |
303 | pr_err("%s: failed to get pinctrl state\n", __func__); | |
304 | return; | |
305 | } | |
306 | ||
307 | ret = gpio_request_array(tx28_gpios, ARRAY_SIZE(tx28_gpios)); | |
308 | if (ret) { | |
309 | pr_err("%s: failed to request gpios: %d\n", __func__, ret); | |
310 | return; | |
311 | } | |
312 | ||
313 | /* Power up fec phy */ | |
314 | gpio_set_value(TX28_FEC_PHY_POWER, 1); | |
315 | msleep(26); /* 25ms according to data sheet */ | |
316 | ||
317 | /* Mode strap pins */ | |
318 | gpio_set_value(ENET0_RX_EN__GPIO_4_2, 1); | |
319 | gpio_set_value(ENET0_RXD0__GPIO_4_3, 1); | |
320 | gpio_set_value(ENET0_RXD1__GPIO_4_4, 1); | |
321 | ||
322 | udelay(100); /* minimum assertion time for nRST */ | |
323 | ||
324 | /* Deasserting FEC PHY RESET */ | |
325 | gpio_set_value(TX28_FEC_PHY_RESET, 1); | |
326 | ||
327 | pinctrl_put(pctl); | |
328 | } | |
329 | ||
ed138c36 | 330 | static void __init crystalfontz_init(void) |
8eec4b31 | 331 | { |
8eec4b31 MR |
332 | update_fec_mac_prop(OUI_CRYSTALFONTZ); |
333 | } | |
334 | ||
2046338d | 335 | static const char __init *mxs_get_soc_id(void) |
e0f7d905 | 336 | { |
2046338d FE |
337 | struct device_node *np; |
338 | void __iomem *digctl_base; | |
339 | ||
340 | np = of_find_compatible_node(NULL, NULL, "fsl,imx23-digctl"); | |
341 | digctl_base = of_iomap(np, 0); | |
342 | WARN_ON(!digctl_base); | |
343 | ||
344 | chipid = readl(digctl_base + HW_DIGCTL_CHIPID); | |
345 | socid = chipid & HW_DIGCTL_CHIPID_MASK; | |
346 | ||
347 | iounmap(digctl_base); | |
348 | of_node_put(np); | |
349 | ||
350 | switch (socid) { | |
351 | case HW_DIGCTL_CHIPID_MX23: | |
352 | return "i.MX23"; | |
353 | case HW_DIGCTL_CHIPID_MX28: | |
354 | return "i.MX28"; | |
355 | default: | |
356 | return "Unknown"; | |
357 | } | |
358 | } | |
359 | ||
360 | static u32 __init mxs_get_cpu_rev(void) | |
361 | { | |
362 | u32 rev = chipid & HW_DIGCTL_REV_MASK; | |
363 | ||
364 | switch (socid) { | |
365 | case HW_DIGCTL_CHIPID_MX23: | |
366 | switch (rev) { | |
367 | case 0x0: | |
368 | return MXS_CHIP_REVISION_1_0; | |
369 | case 0x1: | |
370 | return MXS_CHIP_REVISION_1_1; | |
371 | case 0x2: | |
372 | return MXS_CHIP_REVISION_1_2; | |
373 | case 0x3: | |
374 | return MXS_CHIP_REVISION_1_3; | |
375 | case 0x4: | |
376 | return MXS_CHIP_REVISION_1_4; | |
377 | default: | |
378 | return MXS_CHIP_REV_UNKNOWN; | |
379 | } | |
380 | case HW_DIGCTL_CHIPID_MX28: | |
381 | switch (rev) { | |
382 | case 0x0: | |
383 | return MXS_CHIP_REVISION_1_1; | |
384 | case 0x1: | |
385 | return MXS_CHIP_REVISION_1_2; | |
386 | default: | |
387 | return MXS_CHIP_REV_UNKNOWN; | |
388 | } | |
389 | default: | |
390 | return MXS_CHIP_REV_UNKNOWN; | |
391 | } | |
392 | } | |
393 | ||
394 | static const char __init *mxs_get_revision(void) | |
395 | { | |
396 | u32 rev = mxs_get_cpu_rev(); | |
397 | ||
398 | if (rev != MXS_CHIP_REV_UNKNOWN) | |
399 | return kasprintf(GFP_KERNEL, "TO%d.%d", (rev >> 4) & 0xf, | |
400 | rev & 0xf); | |
401 | else | |
402 | return kasprintf(GFP_KERNEL, "%s", "Unknown"); | |
e0f7d905 MR |
403 | } |
404 | ||
56b7eec0 LW |
405 | #define MX23_CLKCTRL_RESET_OFFSET 0x120 |
406 | #define MX28_CLKCTRL_RESET_OFFSET 0x1e0 | |
407 | ||
408 | static int __init mxs_restart_init(void) | |
409 | { | |
410 | struct device_node *np; | |
411 | ||
412 | np = of_find_compatible_node(NULL, NULL, "fsl,clkctrl"); | |
413 | reset_addr = of_iomap(np, 0); | |
414 | if (!reset_addr) | |
415 | return -ENODEV; | |
416 | ||
417 | if (of_device_is_compatible(np, "fsl,imx23-clkctrl")) | |
418 | reset_addr += MX23_CLKCTRL_RESET_OFFSET; | |
419 | else | |
420 | reset_addr += MX28_CLKCTRL_RESET_OFFSET; | |
421 | of_node_put(np); | |
422 | ||
423 | return 0; | |
424 | } | |
425 | ||
bc3a59c1 DA |
426 | static void __init mxs_machine_init(void) |
427 | { | |
2046338d FE |
428 | struct device_node *root; |
429 | struct device *parent; | |
430 | struct soc_device *soc_dev; | |
431 | struct soc_device_attribute *soc_dev_attr; | |
432 | int ret; | |
433 | ||
434 | soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); | |
435 | if (!soc_dev_attr) | |
436 | return; | |
437 | ||
438 | root = of_find_node_by_path("/"); | |
439 | ret = of_property_read_string(root, "model", &soc_dev_attr->machine); | |
440 | if (ret) | |
441 | return; | |
442 | ||
443 | soc_dev_attr->family = "Freescale MXS Family"; | |
444 | soc_dev_attr->soc_id = mxs_get_soc_id(); | |
445 | soc_dev_attr->revision = mxs_get_revision(); | |
446 | ||
447 | soc_dev = soc_device_register(soc_dev_attr); | |
448 | if (IS_ERR(soc_dev)) { | |
449 | kfree(soc_dev_attr->revision); | |
450 | kfree(soc_dev_attr); | |
451 | return; | |
452 | } | |
453 | ||
454 | parent = soc_device_to_device(soc_dev); | |
455 | ||
bc3a59c1 DA |
456 | if (of_machine_is_compatible("fsl,imx28-evk")) |
457 | imx28_evk_init(); | |
3143bbb4 SG |
458 | else if (of_machine_is_compatible("bluegiga,apx4devkit")) |
459 | apx4devkit_init(); | |
ed138c36 BL |
460 | else if (of_machine_is_compatible("crystalfontz,cfa10037") || |
461 | of_machine_is_compatible("crystalfontz,cfa10049") || | |
d75f3d92 BL |
462 | of_machine_is_compatible("crystalfontz,cfa10055") || |
463 | of_machine_is_compatible("crystalfontz,cfa10057")) | |
ed138c36 | 464 | crystalfontz_init(); |
bc3a59c1 DA |
465 | |
466 | of_platform_populate(NULL, of_default_bus_match_table, | |
496322bc | 467 | NULL, parent); |
2c7c2c1d | 468 | |
56b7eec0 LW |
469 | mxs_restart_init(); |
470 | ||
2c7c2c1d SG |
471 | if (of_machine_is_compatible("karo,tx28")) |
472 | tx28_post_init(); | |
bc3a59c1 DA |
473 | } |
474 | ||
974a9af5 SG |
475 | #define MXS_CLKCTRL_RESET_CHIP (1 << 1) |
476 | ||
477 | /* | |
478 | * Reset the system. It is called by machine_restart(). | |
479 | */ | |
7b6d864b | 480 | static void mxs_restart(enum reboot_mode mode, const char *cmd) |
974a9af5 | 481 | { |
56b7eec0 LW |
482 | if (reset_addr) { |
483 | /* reset the chip */ | |
484 | __mxs_setl(MXS_CLKCTRL_RESET_CHIP, reset_addr); | |
974a9af5 | 485 | |
56b7eec0 | 486 | pr_err("Failed to assert the chip reset\n"); |
974a9af5 | 487 | |
56b7eec0 LW |
488 | /* Delay to allow the serial port to show the message */ |
489 | mdelay(50); | |
490 | } | |
974a9af5 | 491 | |
974a9af5 SG |
492 | /* We'll take a jump through zero as a poor second */ |
493 | soft_restart(0); | |
494 | } | |
495 | ||
39490ab0 SG |
496 | static void __init mxs_timer_init(void) |
497 | { | |
498 | if (of_machine_is_compatible("fsl,imx23")) | |
499 | mx23_clocks_init(); | |
500 | else | |
501 | mx28_clocks_init(); | |
5cd86ef5 | 502 | of_clk_init(NULL); |
39490ab0 SG |
503 | clocksource_of_init(); |
504 | } | |
2954ff39 | 505 | |
39490ab0 | 506 | static const char *mxs_dt_compat[] __initdata = { |
bc3a59c1 | 507 | "fsl,imx28", |
39490ab0 | 508 | "fsl,imx23", |
bc3a59c1 DA |
509 | NULL, |
510 | }; | |
511 | ||
39490ab0 | 512 | DT_MACHINE_START(MXS, "Freescale MXS (Device Tree)") |
4e0a1b8c | 513 | .handle_irq = icoll_handle_irq, |
39490ab0 | 514 | .init_time = mxs_timer_init, |
bc3a59c1 | 515 | .init_machine = mxs_machine_init, |
45680995 | 516 | .init_late = mxs_pm_init, |
39490ab0 | 517 | .dt_compat = mxs_dt_compat, |
bc3a59c1 DA |
518 | .restart = mxs_restart, |
519 | MACHINE_END |