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> |
44ffb78f | 17 | #include <linux/can/platform/flexcan.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 SG |
22 | #include <linux/irqchip.h> |
23 | #include <linux/irqchip/mxs.h> | |
3143bbb4 | 24 | #include <linux/micrel_phy.h> |
ab2815c3 | 25 | #include <linux/mxsfb.h> |
974a9af5 | 26 | #include <linux/of_address.h> |
bc3a59c1 | 27 | #include <linux/of_platform.h> |
3143bbb4 | 28 | #include <linux/phy.h> |
2c7c2c1d | 29 | #include <linux/pinctrl/consumer.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 | ||
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 | } | |
bc3a59c1 | 63 | |
ab2815c3 SG |
64 | static struct fb_videomode mx23evk_video_modes[] = { |
65 | { | |
66 | .name = "Samsung-LMS430HF02", | |
67 | .refresh = 60, | |
68 | .xres = 480, | |
69 | .yres = 272, | |
70 | .pixclock = 108096, /* picosecond (9.2 MHz) */ | |
71 | .left_margin = 15, | |
72 | .right_margin = 8, | |
73 | .upper_margin = 12, | |
74 | .lower_margin = 4, | |
75 | .hsync_len = 1, | |
76 | .vsync_len = 1, | |
ab2815c3 SG |
77 | }, |
78 | }; | |
79 | ||
80 | static struct fb_videomode mx28evk_video_modes[] = { | |
81 | { | |
82 | .name = "Seiko-43WVF1G", | |
83 | .refresh = 60, | |
84 | .xres = 800, | |
85 | .yres = 480, | |
86 | .pixclock = 29851, /* picosecond (33.5 MHz) */ | |
87 | .left_margin = 89, | |
88 | .right_margin = 164, | |
89 | .upper_margin = 23, | |
90 | .lower_margin = 10, | |
91 | .hsync_len = 10, | |
92 | .vsync_len = 10, | |
ab2815c3 SG |
93 | }, |
94 | }; | |
95 | ||
8fa62e11 MV |
96 | static struct fb_videomode m28evk_video_modes[] = { |
97 | { | |
98 | .name = "Ampire AM-800480R2TMQW-T01H", | |
99 | .refresh = 60, | |
100 | .xres = 800, | |
101 | .yres = 480, | |
102 | .pixclock = 30066, /* picosecond (33.26 MHz) */ | |
103 | .left_margin = 0, | |
104 | .right_margin = 256, | |
105 | .upper_margin = 0, | |
106 | .lower_margin = 45, | |
107 | .hsync_len = 1, | |
108 | .vsync_len = 1, | |
8fa62e11 MV |
109 | }, |
110 | }; | |
111 | ||
d8bb823d LH |
112 | static struct fb_videomode apx4devkit_video_modes[] = { |
113 | { | |
114 | .name = "HannStar PJ70112A", | |
115 | .refresh = 60, | |
116 | .xres = 800, | |
117 | .yres = 480, | |
118 | .pixclock = 33333, /* picosecond (30.00 MHz) */ | |
119 | .left_margin = 88, | |
120 | .right_margin = 40, | |
121 | .upper_margin = 32, | |
122 | .lower_margin = 13, | |
123 | .hsync_len = 48, | |
124 | .vsync_len = 3, | |
6a15075e | 125 | .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
d8bb823d LH |
126 | }, |
127 | }; | |
128 | ||
a4dabca8 GGM |
129 | static struct fb_videomode apf28dev_video_modes[] = { |
130 | { | |
131 | .name = "LW700", | |
132 | .refresh = 60, | |
133 | .xres = 800, | |
134 | .yres = 480, | |
135 | .pixclock = 30303, /* picosecond */ | |
136 | .left_margin = 96, | |
137 | .right_margin = 96, /* at least 3 & 1 */ | |
138 | .upper_margin = 0x14, | |
139 | .lower_margin = 0x15, | |
140 | .hsync_len = 64, | |
141 | .vsync_len = 4, | |
6a15075e | 142 | .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
a4dabca8 GGM |
143 | }, |
144 | }; | |
145 | ||
1fe42740 MR |
146 | static struct fb_videomode cfa10049_video_modes[] = { |
147 | { | |
148 | .name = "Himax HX8357-B", | |
149 | .refresh = 60, | |
150 | .xres = 320, | |
151 | .yres = 480, | |
152 | .pixclock = 108506, /* picosecond (9.216 MHz) */ | |
153 | .left_margin = 2, | |
154 | .right_margin = 2, | |
155 | .upper_margin = 2, | |
156 | .lower_margin = 2, | |
157 | .hsync_len = 15, | |
158 | .vsync_len = 15, | |
1fe42740 MR |
159 | }, |
160 | }; | |
161 | ||
ab2815c3 SG |
162 | static struct mxsfb_platform_data mxsfb_pdata __initdata; |
163 | ||
44ffb78f SG |
164 | /* |
165 | * MX28EVK_FLEXCAN_SWITCH is shared between both flexcan controllers | |
166 | */ | |
167 | #define MX28EVK_FLEXCAN_SWITCH MXS_GPIO_NR(2, 13) | |
168 | ||
169 | static int flexcan0_en, flexcan1_en; | |
170 | ||
171 | static void mx28evk_flexcan_switch(void) | |
172 | { | |
173 | if (flexcan0_en || flexcan1_en) | |
174 | gpio_set_value(MX28EVK_FLEXCAN_SWITCH, 1); | |
175 | else | |
176 | gpio_set_value(MX28EVK_FLEXCAN_SWITCH, 0); | |
177 | } | |
178 | ||
179 | static void mx28evk_flexcan0_switch(int enable) | |
180 | { | |
181 | flexcan0_en = enable; | |
182 | mx28evk_flexcan_switch(); | |
183 | } | |
184 | ||
185 | static void mx28evk_flexcan1_switch(int enable) | |
186 | { | |
187 | flexcan1_en = enable; | |
188 | mx28evk_flexcan_switch(); | |
189 | } | |
190 | ||
191 | static struct flexcan_platform_data flexcan_pdata[2]; | |
192 | ||
ab2815c3 SG |
193 | static struct of_dev_auxdata mxs_auxdata_lookup[] __initdata = { |
194 | OF_DEV_AUXDATA("fsl,imx23-lcdif", 0x80030000, NULL, &mxsfb_pdata), | |
195 | OF_DEV_AUXDATA("fsl,imx28-lcdif", 0x80030000, NULL, &mxsfb_pdata), | |
44ffb78f SG |
196 | OF_DEV_AUXDATA("fsl,imx28-flexcan", 0x80032000, NULL, &flexcan_pdata[0]), |
197 | OF_DEV_AUXDATA("fsl,imx28-flexcan", 0x80034000, NULL, &flexcan_pdata[1]), | |
ab2815c3 SG |
198 | { /* sentinel */ } |
199 | }; | |
200 | ||
1bff2d76 SG |
201 | #define OCOTP_WORD_OFFSET 0x20 |
202 | #define OCOTP_WORD_COUNT 0x20 | |
203 | ||
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) | |
207 | ||
208 | static DEFINE_MUTEX(ocotp_mutex); | |
209 | static u32 ocotp_words[OCOTP_WORD_COUNT]; | |
210 | ||
211 | static const u32 *mxs_get_ocotp(void) | |
212 | { | |
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; | |
275 | } | |
276 | ||
5653acc2 SG |
277 | enum mac_oui { |
278 | OUI_FSL, | |
279 | OUI_DENX, | |
8eec4b31 | 280 | OUI_CRYSTALFONTZ, |
5653acc2 SG |
281 | }; |
282 | ||
283 | static void __init update_fec_mac_prop(enum mac_oui oui) | |
284 | { | |
285 | struct device_node *np, *from = NULL; | |
fa7c865a | 286 | struct property *newmac; |
5653acc2 SG |
287 | const u32 *ocotp = mxs_get_ocotp(); |
288 | u8 *macaddr; | |
289 | u32 val; | |
290 | int i; | |
291 | ||
292 | for (i = 0; i < 2; i++) { | |
293 | np = of_find_compatible_node(from, NULL, "fsl,imx28-fec"); | |
294 | if (!np) | |
295 | return; | |
16d47701 | 296 | |
5653acc2 SG |
297 | from = np; |
298 | ||
16d47701 MV |
299 | if (of_get_property(np, "local-mac-address", NULL)) |
300 | continue; | |
301 | ||
5653acc2 SG |
302 | newmac = kzalloc(sizeof(*newmac) + 6, GFP_KERNEL); |
303 | if (!newmac) | |
304 | return; | |
305 | newmac->value = newmac + 1; | |
306 | newmac->length = 6; | |
307 | ||
308 | newmac->name = kstrdup("local-mac-address", GFP_KERNEL); | |
309 | if (!newmac->name) { | |
310 | kfree(newmac); | |
311 | return; | |
312 | } | |
313 | ||
314 | /* | |
315 | * OCOTP only stores the last 4 octets for each mac address, | |
316 | * so hard-code OUI here. | |
317 | */ | |
318 | macaddr = newmac->value; | |
319 | switch (oui) { | |
320 | case OUI_FSL: | |
321 | macaddr[0] = 0x00; | |
322 | macaddr[1] = 0x04; | |
323 | macaddr[2] = 0x9f; | |
324 | break; | |
325 | case OUI_DENX: | |
326 | macaddr[0] = 0xc0; | |
327 | macaddr[1] = 0xe5; | |
328 | macaddr[2] = 0x4e; | |
329 | break; | |
8eec4b31 MR |
330 | case OUI_CRYSTALFONTZ: |
331 | macaddr[0] = 0x58; | |
332 | macaddr[1] = 0xb9; | |
333 | macaddr[2] = 0xe1; | |
334 | break; | |
5653acc2 SG |
335 | } |
336 | val = ocotp[i]; | |
337 | macaddr[3] = (val >> 16) & 0xff; | |
338 | macaddr[4] = (val >> 8) & 0xff; | |
339 | macaddr[5] = (val >> 0) & 0xff; | |
340 | ||
79d1c712 | 341 | of_update_property(np, newmac); |
5653acc2 SG |
342 | } |
343 | } | |
344 | ||
ab2815c3 SG |
345 | static void __init imx23_evk_init(void) |
346 | { | |
347 | mxsfb_pdata.mode_list = mx23evk_video_modes; | |
348 | mxsfb_pdata.mode_count = ARRAY_SIZE(mx23evk_video_modes); | |
349 | mxsfb_pdata.default_bpp = 32; | |
350 | mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT; | |
6a15075e MV |
351 | mxsfb_pdata.sync = MXSFB_SYNC_DATA_ENABLE_HIGH_ACT | |
352 | MXSFB_SYNC_DOTCLK_FAILING_ACT; | |
ab2815c3 SG |
353 | } |
354 | ||
8fa62e11 | 355 | static inline void enable_clk_enet_out(void) |
bc3a59c1 | 356 | { |
8fa62e11 | 357 | struct clk *clk = clk_get_sys("enet_out", NULL); |
bc3a59c1 | 358 | |
bc3a59c1 DA |
359 | if (!IS_ERR(clk)) |
360 | clk_prepare_enable(clk); | |
8fa62e11 | 361 | } |
5653acc2 | 362 | |
8fa62e11 MV |
363 | static void __init imx28_evk_init(void) |
364 | { | |
365 | enable_clk_enet_out(); | |
5653acc2 | 366 | update_fec_mac_prop(OUI_FSL); |
ab2815c3 SG |
367 | |
368 | mxsfb_pdata.mode_list = mx28evk_video_modes; | |
369 | mxsfb_pdata.mode_count = ARRAY_SIZE(mx28evk_video_modes); | |
370 | mxsfb_pdata.default_bpp = 32; | |
371 | mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT; | |
6a15075e MV |
372 | mxsfb_pdata.sync = MXSFB_SYNC_DATA_ENABLE_HIGH_ACT | |
373 | MXSFB_SYNC_DOTCLK_FAILING_ACT; | |
e317317a DA |
374 | |
375 | mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0); | |
bc3a59c1 DA |
376 | } |
377 | ||
44ffb78f | 378 | static void __init imx28_evk_post_init(void) |
8fa62e11 | 379 | { |
44ffb78f SG |
380 | if (!gpio_request_one(MX28EVK_FLEXCAN_SWITCH, GPIOF_DIR_OUT, |
381 | "flexcan-switch")) { | |
382 | flexcan_pdata[0].transceiver_switch = mx28evk_flexcan0_switch; | |
383 | flexcan_pdata[1].transceiver_switch = mx28evk_flexcan1_switch; | |
384 | } | |
385 | } | |
8fa62e11 | 386 | |
8fa62e11 MV |
387 | static void __init m28evk_init(void) |
388 | { | |
8fa62e11 MV |
389 | mxsfb_pdata.mode_list = m28evk_video_modes; |
390 | mxsfb_pdata.mode_count = ARRAY_SIZE(m28evk_video_modes); | |
391 | mxsfb_pdata.default_bpp = 16; | |
392 | mxsfb_pdata.ld_intf_width = STMLCDIF_18BIT; | |
6a15075e | 393 | mxsfb_pdata.sync = MXSFB_SYNC_DATA_ENABLE_HIGH_ACT; |
8fa62e11 MV |
394 | } |
395 | ||
160d5f27 MV |
396 | static void __init sc_sps1_init(void) |
397 | { | |
398 | enable_clk_enet_out(); | |
399 | } | |
400 | ||
3143bbb4 SG |
401 | static int apx4devkit_phy_fixup(struct phy_device *phy) |
402 | { | |
403 | phy->dev_flags |= MICREL_PHY_50MHZ_CLK; | |
404 | return 0; | |
405 | } | |
406 | ||
407 | static void __init apx4devkit_init(void) | |
408 | { | |
409 | enable_clk_enet_out(); | |
410 | ||
411 | if (IS_BUILTIN(CONFIG_PHYLIB)) | |
510d573f | 412 | phy_register_fixup_for_uid(PHY_ID_KSZ8051, MICREL_PHY_ID_MASK, |
3143bbb4 | 413 | apx4devkit_phy_fixup); |
d8bb823d LH |
414 | |
415 | mxsfb_pdata.mode_list = apx4devkit_video_modes; | |
416 | mxsfb_pdata.mode_count = ARRAY_SIZE(apx4devkit_video_modes); | |
417 | mxsfb_pdata.default_bpp = 32; | |
418 | mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT; | |
6a15075e MV |
419 | mxsfb_pdata.sync = MXSFB_SYNC_DATA_ENABLE_HIGH_ACT | |
420 | MXSFB_SYNC_DOTCLK_FAILING_ACT; | |
3143bbb4 SG |
421 | } |
422 | ||
2c7c2c1d SG |
423 | #define ENET0_MDC__GPIO_4_0 MXS_GPIO_NR(4, 0) |
424 | #define ENET0_MDIO__GPIO_4_1 MXS_GPIO_NR(4, 1) | |
425 | #define ENET0_RX_EN__GPIO_4_2 MXS_GPIO_NR(4, 2) | |
426 | #define ENET0_RXD0__GPIO_4_3 MXS_GPIO_NR(4, 3) | |
427 | #define ENET0_RXD1__GPIO_4_4 MXS_GPIO_NR(4, 4) | |
428 | #define ENET0_TX_EN__GPIO_4_6 MXS_GPIO_NR(4, 6) | |
429 | #define ENET0_TXD0__GPIO_4_7 MXS_GPIO_NR(4, 7) | |
430 | #define ENET0_TXD1__GPIO_4_8 MXS_GPIO_NR(4, 8) | |
431 | #define ENET_CLK__GPIO_4_16 MXS_GPIO_NR(4, 16) | |
432 | ||
433 | #define TX28_FEC_PHY_POWER MXS_GPIO_NR(3, 29) | |
434 | #define TX28_FEC_PHY_RESET MXS_GPIO_NR(4, 13) | |
435 | #define TX28_FEC_nINT MXS_GPIO_NR(4, 5) | |
436 | ||
437 | static const struct gpio tx28_gpios[] __initconst = { | |
438 | { ENET0_MDC__GPIO_4_0, GPIOF_OUT_INIT_LOW, "GPIO_4_0" }, | |
439 | { ENET0_MDIO__GPIO_4_1, GPIOF_OUT_INIT_LOW, "GPIO_4_1" }, | |
440 | { ENET0_RX_EN__GPIO_4_2, GPIOF_OUT_INIT_LOW, "GPIO_4_2" }, | |
441 | { ENET0_RXD0__GPIO_4_3, GPIOF_OUT_INIT_LOW, "GPIO_4_3" }, | |
442 | { ENET0_RXD1__GPIO_4_4, GPIOF_OUT_INIT_LOW, "GPIO_4_4" }, | |
443 | { ENET0_TX_EN__GPIO_4_6, GPIOF_OUT_INIT_LOW, "GPIO_4_6" }, | |
444 | { ENET0_TXD0__GPIO_4_7, GPIOF_OUT_INIT_LOW, "GPIO_4_7" }, | |
445 | { ENET0_TXD1__GPIO_4_8, GPIOF_OUT_INIT_LOW, "GPIO_4_8" }, | |
446 | { ENET_CLK__GPIO_4_16, GPIOF_OUT_INIT_LOW, "GPIO_4_16" }, | |
447 | { TX28_FEC_PHY_POWER, GPIOF_OUT_INIT_LOW, "fec-phy-power" }, | |
448 | { TX28_FEC_PHY_RESET, GPIOF_OUT_INIT_LOW, "fec-phy-reset" }, | |
449 | { TX28_FEC_nINT, GPIOF_DIR_IN, "fec-int" }, | |
450 | }; | |
451 | ||
452 | static void __init tx28_post_init(void) | |
453 | { | |
454 | struct device_node *np; | |
455 | struct platform_device *pdev; | |
456 | struct pinctrl *pctl; | |
457 | int ret; | |
458 | ||
459 | enable_clk_enet_out(); | |
460 | ||
461 | np = of_find_compatible_node(NULL, NULL, "fsl,imx28-fec"); | |
462 | pdev = of_find_device_by_node(np); | |
463 | if (!pdev) { | |
464 | pr_err("%s: failed to find fec device\n", __func__); | |
465 | return; | |
466 | } | |
467 | ||
468 | pctl = pinctrl_get_select(&pdev->dev, "gpio_mode"); | |
469 | if (IS_ERR(pctl)) { | |
470 | pr_err("%s: failed to get pinctrl state\n", __func__); | |
471 | return; | |
472 | } | |
473 | ||
474 | ret = gpio_request_array(tx28_gpios, ARRAY_SIZE(tx28_gpios)); | |
475 | if (ret) { | |
476 | pr_err("%s: failed to request gpios: %d\n", __func__, ret); | |
477 | return; | |
478 | } | |
479 | ||
480 | /* Power up fec phy */ | |
481 | gpio_set_value(TX28_FEC_PHY_POWER, 1); | |
482 | msleep(26); /* 25ms according to data sheet */ | |
483 | ||
484 | /* Mode strap pins */ | |
485 | gpio_set_value(ENET0_RX_EN__GPIO_4_2, 1); | |
486 | gpio_set_value(ENET0_RXD0__GPIO_4_3, 1); | |
487 | gpio_set_value(ENET0_RXD1__GPIO_4_4, 1); | |
488 | ||
489 | udelay(100); /* minimum assertion time for nRST */ | |
490 | ||
491 | /* Deasserting FEC PHY RESET */ | |
492 | gpio_set_value(TX28_FEC_PHY_RESET, 1); | |
493 | ||
494 | pinctrl_put(pctl); | |
495 | } | |
496 | ||
8eec4b31 MR |
497 | static void __init cfa10049_init(void) |
498 | { | |
499 | enable_clk_enet_out(); | |
500 | update_fec_mac_prop(OUI_CRYSTALFONTZ); | |
4a38a850 MR |
501 | |
502 | mxsfb_pdata.mode_list = cfa10049_video_modes; | |
503 | mxsfb_pdata.mode_count = ARRAY_SIZE(cfa10049_video_modes); | |
504 | mxsfb_pdata.default_bpp = 32; | |
505 | mxsfb_pdata.ld_intf_width = STMLCDIF_18BIT; | |
6a15075e | 506 | mxsfb_pdata.sync = MXSFB_SYNC_DATA_ENABLE_HIGH_ACT; |
8eec4b31 MR |
507 | } |
508 | ||
e0f7d905 MR |
509 | static void __init cfa10037_init(void) |
510 | { | |
511 | enable_clk_enet_out(); | |
512 | update_fec_mac_prop(OUI_CRYSTALFONTZ); | |
513 | } | |
514 | ||
a957fdca JB |
515 | static void __init apf28_init(void) |
516 | { | |
517 | enable_clk_enet_out(); | |
a4dabca8 GGM |
518 | |
519 | mxsfb_pdata.mode_list = apf28dev_video_modes; | |
520 | mxsfb_pdata.mode_count = ARRAY_SIZE(apf28dev_video_modes); | |
521 | mxsfb_pdata.default_bpp = 16; | |
522 | mxsfb_pdata.ld_intf_width = STMLCDIF_16BIT; | |
6a15075e MV |
523 | mxsfb_pdata.sync = MXSFB_SYNC_DATA_ENABLE_HIGH_ACT | |
524 | MXSFB_SYNC_DOTCLK_FAILING_ACT; | |
a957fdca JB |
525 | } |
526 | ||
bc3a59c1 DA |
527 | static void __init mxs_machine_init(void) |
528 | { | |
529 | if (of_machine_is_compatible("fsl,imx28-evk")) | |
530 | imx28_evk_init(); | |
ab2815c3 SG |
531 | else if (of_machine_is_compatible("fsl,imx23-evk")) |
532 | imx23_evk_init(); | |
8fa62e11 MV |
533 | else if (of_machine_is_compatible("denx,m28evk")) |
534 | m28evk_init(); | |
3143bbb4 SG |
535 | else if (of_machine_is_compatible("bluegiga,apx4devkit")) |
536 | apx4devkit_init(); | |
e0f7d905 MR |
537 | else if (of_machine_is_compatible("crystalfontz,cfa10037")) |
538 | cfa10037_init(); | |
8eec4b31 MR |
539 | else if (of_machine_is_compatible("crystalfontz,cfa10049")) |
540 | cfa10049_init(); | |
a957fdca JB |
541 | else if (of_machine_is_compatible("armadeus,imx28-apf28")) |
542 | apf28_init(); | |
160d5f27 MV |
543 | else if (of_machine_is_compatible("schulercontrol,imx28-sps1")) |
544 | sc_sps1_init(); | |
bc3a59c1 DA |
545 | |
546 | of_platform_populate(NULL, of_default_bus_match_table, | |
ab2815c3 | 547 | mxs_auxdata_lookup, NULL); |
2c7c2c1d SG |
548 | |
549 | if (of_machine_is_compatible("karo,tx28")) | |
550 | tx28_post_init(); | |
44ffb78f SG |
551 | |
552 | if (of_machine_is_compatible("fsl,imx28-evk")) | |
553 | imx28_evk_post_init(); | |
bc3a59c1 DA |
554 | } |
555 | ||
974a9af5 SG |
556 | #define MX23_CLKCTRL_RESET_OFFSET 0x120 |
557 | #define MX28_CLKCTRL_RESET_OFFSET 0x1e0 | |
558 | #define MXS_CLKCTRL_RESET_CHIP (1 << 1) | |
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; | |
577 | ||
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 | ||
39490ab0 SG |
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 | } | |
2954ff39 | 599 | |
39490ab0 | 600 | static const char *mxs_dt_compat[] __initdata = { |
bc3a59c1 | 601 | "fsl,imx28", |
39490ab0 | 602 | "fsl,imx23", |
bc3a59c1 DA |
603 | NULL, |
604 | }; | |
605 | ||
39490ab0 | 606 | DT_MACHINE_START(MXS, "Freescale MXS (Device Tree)") |
1f629564 | 607 | .map_io = debug_ll_io_init, |
6a8e95b0 | 608 | .init_irq = irqchip_init, |
4e0a1b8c | 609 | .handle_irq = icoll_handle_irq, |
39490ab0 | 610 | .init_time = mxs_timer_init, |
bc3a59c1 | 611 | .init_machine = mxs_machine_init, |
45680995 | 612 | .init_late = mxs_pm_init, |
39490ab0 | 613 | .dt_compat = mxs_dt_compat, |
bc3a59c1 DA |
614 | .restart = mxs_restart, |
615 | MACHINE_END |