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> 14 #include <linux/clkdev.h> 15 #include <linux/can/platform/flexcan.h> 16 #include <linux/delay.h> 17 #include <linux/err.h> 18 #include <linux/gpio.h> 19 #include <linux/init.h> 20 #include <linux/micrel_phy.h> 21 #include <linux/mxsfb.h> 22 #include <linux/of_platform.h> 23 #include <linux/phy.h> 24 #include <linux/pinctrl/consumer.h> 25 #include <asm/mach/arch.h> 26 #include <asm/mach/time.h> 27 #include <mach/common.h> 28 #include <mach/digctl.h> 29 #include <mach/mxs.h> 30 31 static struct fb_videomode mx23evk_video_modes[] = { 32 { 33 .name = "Samsung-LMS430HF02", 34 .refresh = 60, 35 .xres = 480, 36 .yres = 272, 37 .pixclock = 108096, /* picosecond (9.2 MHz) */ 38 .left_margin = 15, 39 .right_margin = 8, 40 .upper_margin = 12, 41 .lower_margin = 4, 42 .hsync_len = 1, 43 .vsync_len = 1, 44 .sync = FB_SYNC_DATA_ENABLE_HIGH_ACT | 45 FB_SYNC_DOTCLK_FAILING_ACT, 46 }, 47 }; 48 49 static struct fb_videomode mx28evk_video_modes[] = { 50 { 51 .name = "Seiko-43WVF1G", 52 .refresh = 60, 53 .xres = 800, 54 .yres = 480, 55 .pixclock = 29851, /* picosecond (33.5 MHz) */ 56 .left_margin = 89, 57 .right_margin = 164, 58 .upper_margin = 23, 59 .lower_margin = 10, 60 .hsync_len = 10, 61 .vsync_len = 10, 62 .sync = FB_SYNC_DATA_ENABLE_HIGH_ACT | 63 FB_SYNC_DOTCLK_FAILING_ACT, 64 }, 65 }; 66 67 static struct fb_videomode m28evk_video_modes[] = { 68 { 69 .name = "Ampire AM-800480R2TMQW-T01H", 70 .refresh = 60, 71 .xres = 800, 72 .yres = 480, 73 .pixclock = 30066, /* picosecond (33.26 MHz) */ 74 .left_margin = 0, 75 .right_margin = 256, 76 .upper_margin = 0, 77 .lower_margin = 45, 78 .hsync_len = 1, 79 .vsync_len = 1, 80 .sync = FB_SYNC_DATA_ENABLE_HIGH_ACT, 81 }, 82 }; 83 84 static struct fb_videomode apx4devkit_video_modes[] = { 85 { 86 .name = "HannStar PJ70112A", 87 .refresh = 60, 88 .xres = 800, 89 .yres = 480, 90 .pixclock = 33333, /* picosecond (30.00 MHz) */ 91 .left_margin = 88, 92 .right_margin = 40, 93 .upper_margin = 32, 94 .lower_margin = 13, 95 .hsync_len = 48, 96 .vsync_len = 3, 97 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | 98 FB_SYNC_DATA_ENABLE_HIGH_ACT | 99 FB_SYNC_DOTCLK_FAILING_ACT, 100 }, 101 }; 102 103 static struct fb_videomode apf28dev_video_modes[] = { 104 { 105 .name = "LW700", 106 .refresh = 60, 107 .xres = 800, 108 .yres = 480, 109 .pixclock = 30303, /* picosecond */ 110 .left_margin = 96, 111 .right_margin = 96, /* at least 3 & 1 */ 112 .upper_margin = 0x14, 113 .lower_margin = 0x15, 114 .hsync_len = 64, 115 .vsync_len = 4, 116 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | 117 FB_SYNC_DATA_ENABLE_HIGH_ACT | 118 FB_SYNC_DOTCLK_FAILING_ACT, 119 }, 120 }; 121 122 static struct mxsfb_platform_data mxsfb_pdata __initdata; 123 124 /* 125 * MX28EVK_FLEXCAN_SWITCH is shared between both flexcan controllers 126 */ 127 #define MX28EVK_FLEXCAN_SWITCH MXS_GPIO_NR(2, 13) 128 129 static int flexcan0_en, flexcan1_en; 130 131 static void mx28evk_flexcan_switch(void) 132 { 133 if (flexcan0_en || flexcan1_en) 134 gpio_set_value(MX28EVK_FLEXCAN_SWITCH, 1); 135 else 136 gpio_set_value(MX28EVK_FLEXCAN_SWITCH, 0); 137 } 138 139 static void mx28evk_flexcan0_switch(int enable) 140 { 141 flexcan0_en = enable; 142 mx28evk_flexcan_switch(); 143 } 144 145 static void mx28evk_flexcan1_switch(int enable) 146 { 147 flexcan1_en = enable; 148 mx28evk_flexcan_switch(); 149 } 150 151 static struct flexcan_platform_data flexcan_pdata[2]; 152 153 static struct of_dev_auxdata mxs_auxdata_lookup[] __initdata = { 154 OF_DEV_AUXDATA("fsl,imx23-lcdif", 0x80030000, NULL, &mxsfb_pdata), 155 OF_DEV_AUXDATA("fsl,imx28-lcdif", 0x80030000, NULL, &mxsfb_pdata), 156 OF_DEV_AUXDATA("fsl,imx28-flexcan", 0x80032000, NULL, &flexcan_pdata[0]), 157 OF_DEV_AUXDATA("fsl,imx28-flexcan", 0x80034000, NULL, &flexcan_pdata[1]), 158 { /* sentinel */ } 159 }; 160 161 static void __init imx23_timer_init(void) 162 { 163 mx23_clocks_init(); 164 } 165 166 static struct sys_timer imx23_timer = { 167 .init = imx23_timer_init, 168 }; 169 170 static void __init imx28_timer_init(void) 171 { 172 mx28_clocks_init(); 173 } 174 175 static struct sys_timer imx28_timer = { 176 .init = imx28_timer_init, 177 }; 178 179 enum mac_oui { 180 OUI_FSL, 181 OUI_DENX, 182 OUI_CRYSTALFONTZ, 183 }; 184 185 static void __init update_fec_mac_prop(enum mac_oui oui) 186 { 187 struct device_node *np, *from = NULL; 188 struct property *newmac; 189 const u32 *ocotp = mxs_get_ocotp(); 190 u8 *macaddr; 191 u32 val; 192 int i; 193 194 for (i = 0; i < 2; i++) { 195 np = of_find_compatible_node(from, NULL, "fsl,imx28-fec"); 196 if (!np) 197 return; 198 199 from = np; 200 201 if (of_get_property(np, "local-mac-address", NULL)) 202 continue; 203 204 newmac = kzalloc(sizeof(*newmac) + 6, GFP_KERNEL); 205 if (!newmac) 206 return; 207 newmac->value = newmac + 1; 208 newmac->length = 6; 209 210 newmac->name = kstrdup("local-mac-address", GFP_KERNEL); 211 if (!newmac->name) { 212 kfree(newmac); 213 return; 214 } 215 216 /* 217 * OCOTP only stores the last 4 octets for each mac address, 218 * so hard-code OUI here. 219 */ 220 macaddr = newmac->value; 221 switch (oui) { 222 case OUI_FSL: 223 macaddr[0] = 0x00; 224 macaddr[1] = 0x04; 225 macaddr[2] = 0x9f; 226 break; 227 case OUI_DENX: 228 macaddr[0] = 0xc0; 229 macaddr[1] = 0xe5; 230 macaddr[2] = 0x4e; 231 break; 232 case OUI_CRYSTALFONTZ: 233 macaddr[0] = 0x58; 234 macaddr[1] = 0xb9; 235 macaddr[2] = 0xe1; 236 break; 237 } 238 val = ocotp[i]; 239 macaddr[3] = (val >> 16) & 0xff; 240 macaddr[4] = (val >> 8) & 0xff; 241 macaddr[5] = (val >> 0) & 0xff; 242 243 of_update_property(np, newmac); 244 } 245 } 246 247 static void __init imx23_evk_init(void) 248 { 249 mxsfb_pdata.mode_list = mx23evk_video_modes; 250 mxsfb_pdata.mode_count = ARRAY_SIZE(mx23evk_video_modes); 251 mxsfb_pdata.default_bpp = 32; 252 mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT; 253 } 254 255 static inline void enable_clk_enet_out(void) 256 { 257 struct clk *clk = clk_get_sys("enet_out", NULL); 258 259 if (!IS_ERR(clk)) 260 clk_prepare_enable(clk); 261 } 262 263 static void __init imx28_evk_init(void) 264 { 265 enable_clk_enet_out(); 266 update_fec_mac_prop(OUI_FSL); 267 268 mxsfb_pdata.mode_list = mx28evk_video_modes; 269 mxsfb_pdata.mode_count = ARRAY_SIZE(mx28evk_video_modes); 270 mxsfb_pdata.default_bpp = 32; 271 mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT; 272 273 mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0); 274 } 275 276 static void __init imx28_evk_post_init(void) 277 { 278 if (!gpio_request_one(MX28EVK_FLEXCAN_SWITCH, GPIOF_DIR_OUT, 279 "flexcan-switch")) { 280 flexcan_pdata[0].transceiver_switch = mx28evk_flexcan0_switch; 281 flexcan_pdata[1].transceiver_switch = mx28evk_flexcan1_switch; 282 } 283 } 284 285 static void __init m28evk_init(void) 286 { 287 mxsfb_pdata.mode_list = m28evk_video_modes; 288 mxsfb_pdata.mode_count = ARRAY_SIZE(m28evk_video_modes); 289 mxsfb_pdata.default_bpp = 16; 290 mxsfb_pdata.ld_intf_width = STMLCDIF_18BIT; 291 } 292 293 static void __init sc_sps1_init(void) 294 { 295 enable_clk_enet_out(); 296 } 297 298 static int apx4devkit_phy_fixup(struct phy_device *phy) 299 { 300 phy->dev_flags |= MICREL_PHY_50MHZ_CLK; 301 return 0; 302 } 303 304 static void __init apx4devkit_init(void) 305 { 306 enable_clk_enet_out(); 307 308 if (IS_BUILTIN(CONFIG_PHYLIB)) 309 phy_register_fixup_for_uid(PHY_ID_KSZ8051, MICREL_PHY_ID_MASK, 310 apx4devkit_phy_fixup); 311 312 mxsfb_pdata.mode_list = apx4devkit_video_modes; 313 mxsfb_pdata.mode_count = ARRAY_SIZE(apx4devkit_video_modes); 314 mxsfb_pdata.default_bpp = 32; 315 mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT; 316 } 317 318 #define ENET0_MDC__GPIO_4_0 MXS_GPIO_NR(4, 0) 319 #define ENET0_MDIO__GPIO_4_1 MXS_GPIO_NR(4, 1) 320 #define ENET0_RX_EN__GPIO_4_2 MXS_GPIO_NR(4, 2) 321 #define ENET0_RXD0__GPIO_4_3 MXS_GPIO_NR(4, 3) 322 #define ENET0_RXD1__GPIO_4_4 MXS_GPIO_NR(4, 4) 323 #define ENET0_TX_EN__GPIO_4_6 MXS_GPIO_NR(4, 6) 324 #define ENET0_TXD0__GPIO_4_7 MXS_GPIO_NR(4, 7) 325 #define ENET0_TXD1__GPIO_4_8 MXS_GPIO_NR(4, 8) 326 #define ENET_CLK__GPIO_4_16 MXS_GPIO_NR(4, 16) 327 328 #define TX28_FEC_PHY_POWER MXS_GPIO_NR(3, 29) 329 #define TX28_FEC_PHY_RESET MXS_GPIO_NR(4, 13) 330 #define TX28_FEC_nINT MXS_GPIO_NR(4, 5) 331 332 static const struct gpio tx28_gpios[] __initconst = { 333 { ENET0_MDC__GPIO_4_0, GPIOF_OUT_INIT_LOW, "GPIO_4_0" }, 334 { ENET0_MDIO__GPIO_4_1, GPIOF_OUT_INIT_LOW, "GPIO_4_1" }, 335 { ENET0_RX_EN__GPIO_4_2, GPIOF_OUT_INIT_LOW, "GPIO_4_2" }, 336 { ENET0_RXD0__GPIO_4_3, GPIOF_OUT_INIT_LOW, "GPIO_4_3" }, 337 { ENET0_RXD1__GPIO_4_4, GPIOF_OUT_INIT_LOW, "GPIO_4_4" }, 338 { ENET0_TX_EN__GPIO_4_6, GPIOF_OUT_INIT_LOW, "GPIO_4_6" }, 339 { ENET0_TXD0__GPIO_4_7, GPIOF_OUT_INIT_LOW, "GPIO_4_7" }, 340 { ENET0_TXD1__GPIO_4_8, GPIOF_OUT_INIT_LOW, "GPIO_4_8" }, 341 { ENET_CLK__GPIO_4_16, GPIOF_OUT_INIT_LOW, "GPIO_4_16" }, 342 { TX28_FEC_PHY_POWER, GPIOF_OUT_INIT_LOW, "fec-phy-power" }, 343 { TX28_FEC_PHY_RESET, GPIOF_OUT_INIT_LOW, "fec-phy-reset" }, 344 { TX28_FEC_nINT, GPIOF_DIR_IN, "fec-int" }, 345 }; 346 347 static void __init tx28_post_init(void) 348 { 349 struct device_node *np; 350 struct platform_device *pdev; 351 struct pinctrl *pctl; 352 int ret; 353 354 enable_clk_enet_out(); 355 356 np = of_find_compatible_node(NULL, NULL, "fsl,imx28-fec"); 357 pdev = of_find_device_by_node(np); 358 if (!pdev) { 359 pr_err("%s: failed to find fec device\n", __func__); 360 return; 361 } 362 363 pctl = pinctrl_get_select(&pdev->dev, "gpio_mode"); 364 if (IS_ERR(pctl)) { 365 pr_err("%s: failed to get pinctrl state\n", __func__); 366 return; 367 } 368 369 ret = gpio_request_array(tx28_gpios, ARRAY_SIZE(tx28_gpios)); 370 if (ret) { 371 pr_err("%s: failed to request gpios: %d\n", __func__, ret); 372 return; 373 } 374 375 /* Power up fec phy */ 376 gpio_set_value(TX28_FEC_PHY_POWER, 1); 377 msleep(26); /* 25ms according to data sheet */ 378 379 /* Mode strap pins */ 380 gpio_set_value(ENET0_RX_EN__GPIO_4_2, 1); 381 gpio_set_value(ENET0_RXD0__GPIO_4_3, 1); 382 gpio_set_value(ENET0_RXD1__GPIO_4_4, 1); 383 384 udelay(100); /* minimum assertion time for nRST */ 385 386 /* Deasserting FEC PHY RESET */ 387 gpio_set_value(TX28_FEC_PHY_RESET, 1); 388 389 pinctrl_put(pctl); 390 } 391 392 static void __init cfa10049_init(void) 393 { 394 enable_clk_enet_out(); 395 update_fec_mac_prop(OUI_CRYSTALFONTZ); 396 } 397 398 static void __init apf28_init(void) 399 { 400 enable_clk_enet_out(); 401 402 mxsfb_pdata.mode_list = apf28dev_video_modes; 403 mxsfb_pdata.mode_count = ARRAY_SIZE(apf28dev_video_modes); 404 mxsfb_pdata.default_bpp = 16; 405 mxsfb_pdata.ld_intf_width = STMLCDIF_16BIT; 406 } 407 408 static void __init mxs_machine_init(void) 409 { 410 if (of_machine_is_compatible("fsl,imx28-evk")) 411 imx28_evk_init(); 412 else if (of_machine_is_compatible("fsl,imx23-evk")) 413 imx23_evk_init(); 414 else if (of_machine_is_compatible("denx,m28evk")) 415 m28evk_init(); 416 else if (of_machine_is_compatible("bluegiga,apx4devkit")) 417 apx4devkit_init(); 418 else if (of_machine_is_compatible("crystalfontz,cfa10049")) 419 cfa10049_init(); 420 else if (of_machine_is_compatible("armadeus,imx28-apf28")) 421 apf28_init(); 422 else if (of_machine_is_compatible("schulercontrol,imx28-sps1")) 423 sc_sps1_init(); 424 425 of_platform_populate(NULL, of_default_bus_match_table, 426 mxs_auxdata_lookup, NULL); 427 428 if (of_machine_is_compatible("karo,tx28")) 429 tx28_post_init(); 430 431 if (of_machine_is_compatible("fsl,imx28-evk")) 432 imx28_evk_post_init(); 433 } 434 435 static const char *imx23_dt_compat[] __initdata = { 436 "fsl,imx23", 437 NULL, 438 }; 439 440 static const char *imx28_dt_compat[] __initdata = { 441 "fsl,imx28", 442 NULL, 443 }; 444 445 DT_MACHINE_START(IMX23, "Freescale i.MX23 (Device Tree)") 446 .map_io = mx23_map_io, 447 .init_irq = icoll_init_irq, 448 .handle_irq = icoll_handle_irq, 449 .timer = &imx23_timer, 450 .init_machine = mxs_machine_init, 451 .dt_compat = imx23_dt_compat, 452 .restart = mxs_restart, 453 MACHINE_END 454 455 DT_MACHINE_START(IMX28, "Freescale i.MX28 (Device Tree)") 456 .map_io = mx28_map_io, 457 .init_irq = icoll_init_irq, 458 .handle_irq = icoll_handle_irq, 459 .timer = &imx28_timer, 460 .init_machine = mxs_machine_init, 461 .dt_compat = imx28_dt_compat, 462 .restart = mxs_restart, 463 MACHINE_END 464