aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-mxs/mach-mxs.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-mxs/mach-mxs.c')
-rw-r--r--arch/arm/mach-mxs/mach-mxs.c169
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
28static struct fb_videomode mx23evk_video_modes[] = { 31static struct fb_videomode mx23evk_video_modes[] = {
29 { 32 {
@@ -99,43 +102,43 @@ static struct fb_videomode apx4devkit_video_modes[] = {
99 102
100static struct mxsfb_platform_data mxsfb_pdata __initdata; 103static struct mxsfb_platform_data mxsfb_pdata __initdata;
101 104
102static 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
108static int __init mxs_icoll_add_irq_domain(struct device_node *np, 110static 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; 112static 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
116static int __init mxs_gpio_add_irq_domain(struct device_node *np, 120static 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; 126static void mx28evk_flexcan1_switch(int enable)
127{
128 flexcan1_en = enable;
129 mx28evk_flexcan_switch();
125} 130}
126 131
127static const struct of_device_id mxs_irq_match[] __initconst = { 132static 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, }, 134static 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
133static void __init mxs_dt_init_irq(void)
134{
135 icoll_init_irq();
136 of_irq_init(mxs_irq_match);
137}
138
139static void __init imx23_timer_init(void) 142static 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
242static void __init m28evk_init(void) 247static 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
256static 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
298static 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
313static 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
273static void __init mxs_machine_init(void) 358static 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
288static const char *imx23_dt_compat[] __initdata = { 379static 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
296static const char *imx28_dt_compat[] __initdata = { 384static 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
306DT_MACHINE_START(IMX23, "Freescale i.MX23 (Device Tree)") 389DT_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
315DT_MACHINE_START(IMX28, "Freescale i.MX28 (Device Tree)") 399DT_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,