diff options
Diffstat (limited to 'arch/arm/mach-mxs/mach-mxs.c')
-rw-r--r-- | arch/arm/mach-mxs/mach-mxs.c | 169 |
1 files changed, 127 insertions, 42 deletions
diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c index ff886e01a0b..4748ec551a6 100644 --- a/arch/arm/mach-mxs/mach-mxs.c +++ b/arch/arm/mach-mxs/mach-mxs.c | |||
@@ -12,18 +12,21 @@ | |||
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> |
18 | #include <linux/gpio.h> | ||
16 | #include <linux/init.h> | 19 | #include <linux/init.h> |
17 | #include <linux/init.h> | ||
18 | #include <linux/irqdomain.h> | ||
19 | #include <linux/micrel_phy.h> | 20 | #include <linux/micrel_phy.h> |
20 | #include <linux/mxsfb.h> | 21 | #include <linux/mxsfb.h> |
21 | #include <linux/of_irq.h> | ||
22 | #include <linux/of_platform.h> | 22 | #include <linux/of_platform.h> |
23 | #include <linux/phy.h> | 23 | #include <linux/phy.h> |
24 | #include <linux/pinctrl/consumer.h> | ||
24 | #include <asm/mach/arch.h> | 25 | #include <asm/mach/arch.h> |
25 | #include <asm/mach/time.h> | 26 | #include <asm/mach/time.h> |
26 | #include <mach/common.h> | 27 | #include <mach/common.h> |
28 | #include <mach/digctl.h> | ||
29 | #include <mach/mxs.h> | ||
27 | 30 | ||
28 | static struct fb_videomode mx23evk_video_modes[] = { | 31 | static struct fb_videomode mx23evk_video_modes[] = { |
29 | { | 32 | { |
@@ -99,43 +102,43 @@ static struct fb_videomode apx4devkit_video_modes[] = { | |||
99 | 102 | ||
100 | static struct mxsfb_platform_data mxsfb_pdata __initdata; | 103 | static struct mxsfb_platform_data mxsfb_pdata __initdata; |
101 | 104 | ||
102 | static struct of_dev_auxdata mxs_auxdata_lookup[] __initdata = { | 105 | /* |
103 | OF_DEV_AUXDATA("fsl,imx23-lcdif", 0x80030000, NULL, &mxsfb_pdata), | 106 | * MX28EVK_FLEXCAN_SWITCH is shared between both flexcan controllers |
104 | OF_DEV_AUXDATA("fsl,imx28-lcdif", 0x80030000, NULL, &mxsfb_pdata), | 107 | */ |
105 | { /* sentinel */ } | 108 | #define MX28EVK_FLEXCAN_SWITCH MXS_GPIO_NR(2, 13) |
106 | }; | ||
107 | 109 | ||
108 | static int __init mxs_icoll_add_irq_domain(struct device_node *np, | 110 | static int flexcan0_en, flexcan1_en; |
109 | struct device_node *interrupt_parent) | ||
110 | { | ||
111 | irq_domain_add_legacy(np, 128, 0, 0, &irq_domain_simple_ops, NULL); | ||
112 | 111 | ||
113 | return 0; | 112 | static void mx28evk_flexcan_switch(void) |
113 | { | ||
114 | if (flexcan0_en || flexcan1_en) | ||
115 | gpio_set_value(MX28EVK_FLEXCAN_SWITCH, 1); | ||
116 | else | ||
117 | gpio_set_value(MX28EVK_FLEXCAN_SWITCH, 0); | ||
114 | } | 118 | } |
115 | 119 | ||
116 | static int __init mxs_gpio_add_irq_domain(struct device_node *np, | 120 | static void mx28evk_flexcan0_switch(int enable) |
117 | struct device_node *interrupt_parent) | ||
118 | { | 121 | { |
119 | static int gpio_irq_base = MXS_GPIO_IRQ_START; | 122 | flexcan0_en = enable; |
120 | 123 | mx28evk_flexcan_switch(); | |
121 | irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops, NULL); | 124 | } |
122 | gpio_irq_base += 32; | ||
123 | 125 | ||
124 | return 0; | 126 | static void mx28evk_flexcan1_switch(int enable) |
127 | { | ||
128 | flexcan1_en = enable; | ||
129 | mx28evk_flexcan_switch(); | ||
125 | } | 130 | } |
126 | 131 | ||
127 | static const struct of_device_id mxs_irq_match[] __initconst = { | 132 | static struct flexcan_platform_data flexcan_pdata[2]; |
128 | { .compatible = "fsl,mxs-icoll", .data = mxs_icoll_add_irq_domain, }, | 133 | |
129 | { .compatible = "fsl,mxs-gpio", .data = mxs_gpio_add_irq_domain, }, | 134 | static struct of_dev_auxdata mxs_auxdata_lookup[] __initdata = { |
135 | OF_DEV_AUXDATA("fsl,imx23-lcdif", 0x80030000, NULL, &mxsfb_pdata), | ||
136 | OF_DEV_AUXDATA("fsl,imx28-lcdif", 0x80030000, NULL, &mxsfb_pdata), | ||
137 | OF_DEV_AUXDATA("fsl,imx28-flexcan", 0x80032000, NULL, &flexcan_pdata[0]), | ||
138 | OF_DEV_AUXDATA("fsl,imx28-flexcan", 0x80034000, NULL, &flexcan_pdata[1]), | ||
130 | { /* sentinel */ } | 139 | { /* sentinel */ } |
131 | }; | 140 | }; |
132 | 141 | ||
133 | static void __init mxs_dt_init_irq(void) | ||
134 | { | ||
135 | icoll_init_irq(); | ||
136 | of_irq_init(mxs_irq_match); | ||
137 | } | ||
138 | |||
139 | static void __init imx23_timer_init(void) | 142 | static void __init imx23_timer_init(void) |
140 | { | 143 | { |
141 | mx23_clocks_init(); | 144 | mx23_clocks_init(); |
@@ -237,13 +240,21 @@ static void __init imx28_evk_init(void) | |||
237 | mxsfb_pdata.mode_count = ARRAY_SIZE(mx28evk_video_modes); | 240 | mxsfb_pdata.mode_count = ARRAY_SIZE(mx28evk_video_modes); |
238 | mxsfb_pdata.default_bpp = 32; | 241 | mxsfb_pdata.default_bpp = 32; |
239 | mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT; | 242 | mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT; |
243 | |||
244 | mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0); | ||
240 | } | 245 | } |
241 | 246 | ||
242 | static void __init m28evk_init(void) | 247 | static void __init imx28_evk_post_init(void) |
243 | { | 248 | { |
244 | enable_clk_enet_out(); | 249 | if (!gpio_request_one(MX28EVK_FLEXCAN_SWITCH, GPIOF_DIR_OUT, |
245 | update_fec_mac_prop(OUI_DENX); | 250 | "flexcan-switch")) { |
251 | flexcan_pdata[0].transceiver_switch = mx28evk_flexcan0_switch; | ||
252 | flexcan_pdata[1].transceiver_switch = mx28evk_flexcan1_switch; | ||
253 | } | ||
254 | } | ||
246 | 255 | ||
256 | static void __init m28evk_init(void) | ||
257 | { | ||
247 | mxsfb_pdata.mode_list = m28evk_video_modes; | 258 | mxsfb_pdata.mode_list = m28evk_video_modes; |
248 | mxsfb_pdata.mode_count = ARRAY_SIZE(m28evk_video_modes); | 259 | mxsfb_pdata.mode_count = ARRAY_SIZE(m28evk_video_modes); |
249 | mxsfb_pdata.default_bpp = 16; | 260 | mxsfb_pdata.default_bpp = 16; |
@@ -270,6 +281,80 @@ static void __init apx4devkit_init(void) | |||
270 | mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT; | 281 | mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT; |
271 | } | 282 | } |
272 | 283 | ||
284 | #define ENET0_MDC__GPIO_4_0 MXS_GPIO_NR(4, 0) | ||
285 | #define ENET0_MDIO__GPIO_4_1 MXS_GPIO_NR(4, 1) | ||
286 | #define ENET0_RX_EN__GPIO_4_2 MXS_GPIO_NR(4, 2) | ||
287 | #define ENET0_RXD0__GPIO_4_3 MXS_GPIO_NR(4, 3) | ||
288 | #define ENET0_RXD1__GPIO_4_4 MXS_GPIO_NR(4, 4) | ||
289 | #define ENET0_TX_EN__GPIO_4_6 MXS_GPIO_NR(4, 6) | ||
290 | #define ENET0_TXD0__GPIO_4_7 MXS_GPIO_NR(4, 7) | ||
291 | #define ENET0_TXD1__GPIO_4_8 MXS_GPIO_NR(4, 8) | ||
292 | #define ENET_CLK__GPIO_4_16 MXS_GPIO_NR(4, 16) | ||
293 | |||
294 | #define TX28_FEC_PHY_POWER MXS_GPIO_NR(3, 29) | ||
295 | #define TX28_FEC_PHY_RESET MXS_GPIO_NR(4, 13) | ||
296 | #define TX28_FEC_nINT MXS_GPIO_NR(4, 5) | ||
297 | |||
298 | static const struct gpio tx28_gpios[] __initconst = { | ||
299 | { ENET0_MDC__GPIO_4_0, GPIOF_OUT_INIT_LOW, "GPIO_4_0" }, | ||
300 | { ENET0_MDIO__GPIO_4_1, GPIOF_OUT_INIT_LOW, "GPIO_4_1" }, | ||
301 | { ENET0_RX_EN__GPIO_4_2, GPIOF_OUT_INIT_LOW, "GPIO_4_2" }, | ||
302 | { ENET0_RXD0__GPIO_4_3, GPIOF_OUT_INIT_LOW, "GPIO_4_3" }, | ||
303 | { ENET0_RXD1__GPIO_4_4, GPIOF_OUT_INIT_LOW, "GPIO_4_4" }, | ||
304 | { ENET0_TX_EN__GPIO_4_6, GPIOF_OUT_INIT_LOW, "GPIO_4_6" }, | ||
305 | { ENET0_TXD0__GPIO_4_7, GPIOF_OUT_INIT_LOW, "GPIO_4_7" }, | ||
306 | { ENET0_TXD1__GPIO_4_8, GPIOF_OUT_INIT_LOW, "GPIO_4_8" }, | ||
307 | { ENET_CLK__GPIO_4_16, GPIOF_OUT_INIT_LOW, "GPIO_4_16" }, | ||
308 | { TX28_FEC_PHY_POWER, GPIOF_OUT_INIT_LOW, "fec-phy-power" }, | ||
309 | { TX28_FEC_PHY_RESET, GPIOF_OUT_INIT_LOW, "fec-phy-reset" }, | ||
310 | { TX28_FEC_nINT, GPIOF_DIR_IN, "fec-int" }, | ||
311 | }; | ||
312 | |||
313 | static void __init tx28_post_init(void) | ||
314 | { | ||
315 | struct device_node *np; | ||
316 | struct platform_device *pdev; | ||
317 | struct pinctrl *pctl; | ||
318 | int ret; | ||
319 | |||
320 | enable_clk_enet_out(); | ||
321 | |||
322 | np = of_find_compatible_node(NULL, NULL, "fsl,imx28-fec"); | ||
323 | pdev = of_find_device_by_node(np); | ||
324 | if (!pdev) { | ||
325 | pr_err("%s: failed to find fec device\n", __func__); | ||
326 | return; | ||
327 | } | ||
328 | |||
329 | pctl = pinctrl_get_select(&pdev->dev, "gpio_mode"); | ||
330 | if (IS_ERR(pctl)) { | ||
331 | pr_err("%s: failed to get pinctrl state\n", __func__); | ||
332 | return; | ||
333 | } | ||
334 | |||
335 | ret = gpio_request_array(tx28_gpios, ARRAY_SIZE(tx28_gpios)); | ||
336 | if (ret) { | ||
337 | pr_err("%s: failed to request gpios: %d\n", __func__, ret); | ||
338 | return; | ||
339 | } | ||
340 | |||
341 | /* Power up fec phy */ | ||
342 | gpio_set_value(TX28_FEC_PHY_POWER, 1); | ||
343 | msleep(26); /* 25ms according to data sheet */ | ||
344 | |||
345 | /* Mode strap pins */ | ||
346 | gpio_set_value(ENET0_RX_EN__GPIO_4_2, 1); | ||
347 | gpio_set_value(ENET0_RXD0__GPIO_4_3, 1); | ||
348 | gpio_set_value(ENET0_RXD1__GPIO_4_4, 1); | ||
349 | |||
350 | udelay(100); /* minimum assertion time for nRST */ | ||
351 | |||
352 | /* Deasserting FEC PHY RESET */ | ||
353 | gpio_set_value(TX28_FEC_PHY_RESET, 1); | ||
354 | |||
355 | pinctrl_put(pctl); | ||
356 | } | ||
357 | |||
273 | static void __init mxs_machine_init(void) | 358 | static void __init mxs_machine_init(void) |
274 | { | 359 | { |
275 | if (of_machine_is_compatible("fsl,imx28-evk")) | 360 | if (of_machine_is_compatible("fsl,imx28-evk")) |
@@ -283,29 +368,28 @@ static void __init mxs_machine_init(void) | |||
283 | 368 | ||
284 | of_platform_populate(NULL, of_default_bus_match_table, | 369 | of_platform_populate(NULL, of_default_bus_match_table, |
285 | mxs_auxdata_lookup, NULL); | 370 | mxs_auxdata_lookup, NULL); |
371 | |||
372 | if (of_machine_is_compatible("karo,tx28")) | ||
373 | tx28_post_init(); | ||
374 | |||
375 | if (of_machine_is_compatible("fsl,imx28-evk")) | ||
376 | imx28_evk_post_init(); | ||
286 | } | 377 | } |
287 | 378 | ||
288 | static const char *imx23_dt_compat[] __initdata = { | 379 | static const char *imx23_dt_compat[] __initdata = { |
289 | "fsl,imx23-evk", | ||
290 | "fsl,stmp378x_devb" | ||
291 | "olimex,imx23-olinuxino", | ||
292 | "fsl,imx23", | 380 | "fsl,imx23", |
293 | NULL, | 381 | NULL, |
294 | }; | 382 | }; |
295 | 383 | ||
296 | static const char *imx28_dt_compat[] __initdata = { | 384 | 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", | 385 | "fsl,imx28", |
303 | NULL, | 386 | NULL, |
304 | }; | 387 | }; |
305 | 388 | ||
306 | DT_MACHINE_START(IMX23, "Freescale i.MX23 (Device Tree)") | 389 | DT_MACHINE_START(IMX23, "Freescale i.MX23 (Device Tree)") |
307 | .map_io = mx23_map_io, | 390 | .map_io = mx23_map_io, |
308 | .init_irq = mxs_dt_init_irq, | 391 | .init_irq = icoll_init_irq, |
392 | .handle_irq = icoll_handle_irq, | ||
309 | .timer = &imx23_timer, | 393 | .timer = &imx23_timer, |
310 | .init_machine = mxs_machine_init, | 394 | .init_machine = mxs_machine_init, |
311 | .dt_compat = imx23_dt_compat, | 395 | .dt_compat = imx23_dt_compat, |
@@ -314,7 +398,8 @@ MACHINE_END | |||
314 | 398 | ||
315 | DT_MACHINE_START(IMX28, "Freescale i.MX28 (Device Tree)") | 399 | DT_MACHINE_START(IMX28, "Freescale i.MX28 (Device Tree)") |
316 | .map_io = mx28_map_io, | 400 | .map_io = mx28_map_io, |
317 | .init_irq = mxs_dt_init_irq, | 401 | .init_irq = icoll_init_irq, |
402 | .handle_irq = icoll_handle_irq, | ||
318 | .timer = &imx28_timer, | 403 | .timer = &imx28_timer, |
319 | .init_machine = mxs_machine_init, | 404 | .init_machine = mxs_machine_init, |
320 | .dt_compat = imx28_dt_compat, | 405 | .dt_compat = imx28_dt_compat, |