diff options
Diffstat (limited to 'arch/arm/mach-mxs/mach-mxs.c')
-rw-r--r-- | arch/arm/mach-mxs/mach-mxs.c | 140 |
1 files changed, 128 insertions, 12 deletions
diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c index ff886e01a0b0..cf43e5effb91 100644 --- a/arch/arm/mach-mxs/mach-mxs.c +++ b/arch/arm/mach-mxs/mach-mxs.c | |||
@@ -12,8 +12,10 @@ | |||
12 | 12 | ||
13 | #include <linux/clk.h> | 13 | #include <linux/clk.h> |
14 | #include <linux/clkdev.h> | 14 | #include <linux/clkdev.h> |
15 | #include <linux/can/platform/flexcan.h> | ||
16 | #include <linux/delay.h> | ||
15 | #include <linux/err.h> | 17 | #include <linux/err.h> |
16 | #include <linux/init.h> | 18 | #include <linux/gpio.h> |
17 | #include <linux/init.h> | 19 | #include <linux/init.h> |
18 | #include <linux/irqdomain.h> | 20 | #include <linux/irqdomain.h> |
19 | #include <linux/micrel_phy.h> | 21 | #include <linux/micrel_phy.h> |
@@ -21,9 +23,12 @@ | |||
21 | #include <linux/of_irq.h> | 23 | #include <linux/of_irq.h> |
22 | #include <linux/of_platform.h> | 24 | #include <linux/of_platform.h> |
23 | #include <linux/phy.h> | 25 | #include <linux/phy.h> |
26 | #include <linux/pinctrl/consumer.h> | ||
24 | #include <asm/mach/arch.h> | 27 | #include <asm/mach/arch.h> |
25 | #include <asm/mach/time.h> | 28 | #include <asm/mach/time.h> |
26 | #include <mach/common.h> | 29 | #include <mach/common.h> |
30 | #include <mach/digctl.h> | ||
31 | #include <mach/mxs.h> | ||
27 | 32 | ||
28 | static struct fb_videomode mx23evk_video_modes[] = { | 33 | static struct fb_videomode mx23evk_video_modes[] = { |
29 | { | 34 | { |
@@ -99,9 +104,40 @@ static struct fb_videomode apx4devkit_video_modes[] = { | |||
99 | 104 | ||
100 | static struct mxsfb_platform_data mxsfb_pdata __initdata; | 105 | static struct mxsfb_platform_data mxsfb_pdata __initdata; |
101 | 106 | ||
107 | /* | ||
108 | * MX28EVK_FLEXCAN_SWITCH is shared between both flexcan controllers | ||
109 | */ | ||
110 | #define MX28EVK_FLEXCAN_SWITCH MXS_GPIO_NR(2, 13) | ||
111 | |||
112 | static int flexcan0_en, flexcan1_en; | ||
113 | |||
114 | static void mx28evk_flexcan_switch(void) | ||
115 | { | ||
116 | if (flexcan0_en || flexcan1_en) | ||
117 | gpio_set_value(MX28EVK_FLEXCAN_SWITCH, 1); | ||
118 | else | ||
119 | gpio_set_value(MX28EVK_FLEXCAN_SWITCH, 0); | ||
120 | } | ||
121 | |||
122 | static void mx28evk_flexcan0_switch(int enable) | ||
123 | { | ||
124 | flexcan0_en = enable; | ||
125 | mx28evk_flexcan_switch(); | ||
126 | } | ||
127 | |||
128 | static void mx28evk_flexcan1_switch(int enable) | ||
129 | { | ||
130 | flexcan1_en = enable; | ||
131 | mx28evk_flexcan_switch(); | ||
132 | } | ||
133 | |||
134 | static struct flexcan_platform_data flexcan_pdata[2]; | ||
135 | |||
102 | static struct of_dev_auxdata mxs_auxdata_lookup[] __initdata = { | 136 | static struct of_dev_auxdata mxs_auxdata_lookup[] __initdata = { |
103 | OF_DEV_AUXDATA("fsl,imx23-lcdif", 0x80030000, NULL, &mxsfb_pdata), | 137 | OF_DEV_AUXDATA("fsl,imx23-lcdif", 0x80030000, NULL, &mxsfb_pdata), |
104 | OF_DEV_AUXDATA("fsl,imx28-lcdif", 0x80030000, NULL, &mxsfb_pdata), | 138 | OF_DEV_AUXDATA("fsl,imx28-lcdif", 0x80030000, NULL, &mxsfb_pdata), |
139 | OF_DEV_AUXDATA("fsl,imx28-flexcan", 0x80032000, NULL, &flexcan_pdata[0]), | ||
140 | OF_DEV_AUXDATA("fsl,imx28-flexcan", 0x80034000, NULL, &flexcan_pdata[1]), | ||
105 | { /* sentinel */ } | 141 | { /* sentinel */ } |
106 | }; | 142 | }; |
107 | 143 | ||
@@ -237,13 +273,21 @@ static void __init imx28_evk_init(void) | |||
237 | mxsfb_pdata.mode_count = ARRAY_SIZE(mx28evk_video_modes); | 273 | mxsfb_pdata.mode_count = ARRAY_SIZE(mx28evk_video_modes); |
238 | mxsfb_pdata.default_bpp = 32; | 274 | mxsfb_pdata.default_bpp = 32; |
239 | mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT; | 275 | mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT; |
276 | |||
277 | mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0); | ||
240 | } | 278 | } |
241 | 279 | ||
242 | static void __init m28evk_init(void) | 280 | static void __init imx28_evk_post_init(void) |
243 | { | 281 | { |
244 | enable_clk_enet_out(); | 282 | if (!gpio_request_one(MX28EVK_FLEXCAN_SWITCH, GPIOF_DIR_OUT, |
245 | update_fec_mac_prop(OUI_DENX); | 283 | "flexcan-switch")) { |
284 | flexcan_pdata[0].transceiver_switch = mx28evk_flexcan0_switch; | ||
285 | flexcan_pdata[1].transceiver_switch = mx28evk_flexcan1_switch; | ||
286 | } | ||
287 | } | ||
246 | 288 | ||
289 | static void __init m28evk_init(void) | ||
290 | { | ||
247 | mxsfb_pdata.mode_list = m28evk_video_modes; | 291 | mxsfb_pdata.mode_list = m28evk_video_modes; |
248 | mxsfb_pdata.mode_count = ARRAY_SIZE(m28evk_video_modes); | 292 | mxsfb_pdata.mode_count = ARRAY_SIZE(m28evk_video_modes); |
249 | mxsfb_pdata.default_bpp = 16; | 293 | mxsfb_pdata.default_bpp = 16; |
@@ -270,6 +314,80 @@ static void __init apx4devkit_init(void) | |||
270 | mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT; | 314 | mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT; |
271 | } | 315 | } |
272 | 316 | ||
317 | #define ENET0_MDC__GPIO_4_0 MXS_GPIO_NR(4, 0) | ||
318 | #define ENET0_MDIO__GPIO_4_1 MXS_GPIO_NR(4, 1) | ||
319 | #define ENET0_RX_EN__GPIO_4_2 MXS_GPIO_NR(4, 2) | ||
320 | #define ENET0_RXD0__GPIO_4_3 MXS_GPIO_NR(4, 3) | ||
321 | #define ENET0_RXD1__GPIO_4_4 MXS_GPIO_NR(4, 4) | ||
322 | #define ENET0_TX_EN__GPIO_4_6 MXS_GPIO_NR(4, 6) | ||
323 | #define ENET0_TXD0__GPIO_4_7 MXS_GPIO_NR(4, 7) | ||
324 | #define ENET0_TXD1__GPIO_4_8 MXS_GPIO_NR(4, 8) | ||
325 | #define ENET_CLK__GPIO_4_16 MXS_GPIO_NR(4, 16) | ||
326 | |||
327 | #define TX28_FEC_PHY_POWER MXS_GPIO_NR(3, 29) | ||
328 | #define TX28_FEC_PHY_RESET MXS_GPIO_NR(4, 13) | ||
329 | #define TX28_FEC_nINT MXS_GPIO_NR(4, 5) | ||
330 | |||
331 | static const struct gpio tx28_gpios[] __initconst = { | ||
332 | { ENET0_MDC__GPIO_4_0, GPIOF_OUT_INIT_LOW, "GPIO_4_0" }, | ||
333 | { ENET0_MDIO__GPIO_4_1, GPIOF_OUT_INIT_LOW, "GPIO_4_1" }, | ||
334 | { ENET0_RX_EN__GPIO_4_2, GPIOF_OUT_INIT_LOW, "GPIO_4_2" }, | ||
335 | { ENET0_RXD0__GPIO_4_3, GPIOF_OUT_INIT_LOW, "GPIO_4_3" }, | ||
336 | { ENET0_RXD1__GPIO_4_4, GPIOF_OUT_INIT_LOW, "GPIO_4_4" }, | ||
337 | { ENET0_TX_EN__GPIO_4_6, GPIOF_OUT_INIT_LOW, "GPIO_4_6" }, | ||
338 | { ENET0_TXD0__GPIO_4_7, GPIOF_OUT_INIT_LOW, "GPIO_4_7" }, | ||
339 | { ENET0_TXD1__GPIO_4_8, GPIOF_OUT_INIT_LOW, "GPIO_4_8" }, | ||
340 | { ENET_CLK__GPIO_4_16, GPIOF_OUT_INIT_LOW, "GPIO_4_16" }, | ||
341 | { TX28_FEC_PHY_POWER, GPIOF_OUT_INIT_LOW, "fec-phy-power" }, | ||
342 | { TX28_FEC_PHY_RESET, GPIOF_OUT_INIT_LOW, "fec-phy-reset" }, | ||
343 | { TX28_FEC_nINT, GPIOF_DIR_IN, "fec-int" }, | ||
344 | }; | ||
345 | |||
346 | static void __init tx28_post_init(void) | ||
347 | { | ||
348 | struct device_node *np; | ||
349 | struct platform_device *pdev; | ||
350 | struct pinctrl *pctl; | ||
351 | int ret; | ||
352 | |||
353 | enable_clk_enet_out(); | ||
354 | |||
355 | np = of_find_compatible_node(NULL, NULL, "fsl,imx28-fec"); | ||
356 | pdev = of_find_device_by_node(np); | ||
357 | if (!pdev) { | ||
358 | pr_err("%s: failed to find fec device\n", __func__); | ||
359 | return; | ||
360 | } | ||
361 | |||
362 | pctl = pinctrl_get_select(&pdev->dev, "gpio_mode"); | ||
363 | if (IS_ERR(pctl)) { | ||
364 | pr_err("%s: failed to get pinctrl state\n", __func__); | ||
365 | return; | ||
366 | } | ||
367 | |||
368 | ret = gpio_request_array(tx28_gpios, ARRAY_SIZE(tx28_gpios)); | ||
369 | if (ret) { | ||
370 | pr_err("%s: failed to request gpios: %d\n", __func__, ret); | ||
371 | return; | ||
372 | } | ||
373 | |||
374 | /* Power up fec phy */ | ||
375 | gpio_set_value(TX28_FEC_PHY_POWER, 1); | ||
376 | msleep(26); /* 25ms according to data sheet */ | ||
377 | |||
378 | /* Mode strap pins */ | ||
379 | gpio_set_value(ENET0_RX_EN__GPIO_4_2, 1); | ||
380 | gpio_set_value(ENET0_RXD0__GPIO_4_3, 1); | ||
381 | gpio_set_value(ENET0_RXD1__GPIO_4_4, 1); | ||
382 | |||
383 | udelay(100); /* minimum assertion time for nRST */ | ||
384 | |||
385 | /* Deasserting FEC PHY RESET */ | ||
386 | gpio_set_value(TX28_FEC_PHY_RESET, 1); | ||
387 | |||
388 | pinctrl_put(pctl); | ||
389 | } | ||
390 | |||
273 | static void __init mxs_machine_init(void) | 391 | static void __init mxs_machine_init(void) |
274 | { | 392 | { |
275 | if (of_machine_is_compatible("fsl,imx28-evk")) | 393 | if (of_machine_is_compatible("fsl,imx28-evk")) |
@@ -283,22 +401,20 @@ static void __init mxs_machine_init(void) | |||
283 | 401 | ||
284 | of_platform_populate(NULL, of_default_bus_match_table, | 402 | of_platform_populate(NULL, of_default_bus_match_table, |
285 | mxs_auxdata_lookup, NULL); | 403 | mxs_auxdata_lookup, NULL); |
404 | |||
405 | if (of_machine_is_compatible("karo,tx28")) | ||
406 | tx28_post_init(); | ||
407 | |||
408 | if (of_machine_is_compatible("fsl,imx28-evk")) | ||
409 | imx28_evk_post_init(); | ||
286 | } | 410 | } |
287 | 411 | ||
288 | static const char *imx23_dt_compat[] __initdata = { | 412 | static const char *imx23_dt_compat[] __initdata = { |
289 | "fsl,imx23-evk", | ||
290 | "fsl,stmp378x_devb" | ||
291 | "olimex,imx23-olinuxino", | ||
292 | "fsl,imx23", | 413 | "fsl,imx23", |
293 | NULL, | 414 | NULL, |
294 | }; | 415 | }; |
295 | 416 | ||
296 | static const char *imx28_dt_compat[] __initdata = { | 417 | static const char *imx28_dt_compat[] __initdata = { |
297 | "bluegiga,apx4devkit", | ||
298 | "crystalfontz,cfa10036", | ||
299 | "denx,m28evk", | ||
300 | "fsl,imx28-evk", | ||
301 | "karo,tx28", | ||
302 | "fsl,imx28", | 418 | "fsl,imx28", |
303 | NULL, | 419 | NULL, |
304 | }; | 420 | }; |