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 mxsfb_platform_data mxsfb_pdata __initdata; 104 105 /* 106 * MX28EVK_FLEXCAN_SWITCH is shared between both flexcan controllers 107 */ 108 #define MX28EVK_FLEXCAN_SWITCH MXS_GPIO_NR(2, 13) 109 110 static int flexcan0_en, flexcan1_en; 111 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); 118 } 119 120 static void mx28evk_flexcan0_switch(int enable) 121 { 122 flexcan0_en = enable; 123 mx28evk_flexcan_switch(); 124 } 125 126 static void mx28evk_flexcan1_switch(int enable) 127 { 128 flexcan1_en = enable; 129 mx28evk_flexcan_switch(); 130 } 131 132 static struct flexcan_platform_data flexcan_pdata[2]; 133 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]), 139 { /* sentinel */ } 140 }; 141 142 static void __init imx23_timer_init(void) 143 { 144 mx23_clocks_init(); 145 } 146 147 static struct sys_timer imx23_timer = { 148 .init = imx23_timer_init, 149 }; 150 151 static void __init imx28_timer_init(void) 152 { 153 mx28_clocks_init(); 154 } 155 156 static struct sys_timer imx28_timer = { 157 .init = imx28_timer_init, 158 }; 159 160 enum mac_oui { 161 OUI_FSL, 162 OUI_DENX, 163 }; 164 165 static void __init update_fec_mac_prop(enum mac_oui oui) 166 { 167 struct device_node *np, *from = NULL; 168 struct property *newmac; 169 const u32 *ocotp = mxs_get_ocotp(); 170 u8 *macaddr; 171 u32 val; 172 int i; 173 174 for (i = 0; i < 2; i++) { 175 np = of_find_compatible_node(from, NULL, "fsl,imx28-fec"); 176 if (!np) 177 return; 178 from = np; 179 180 newmac = kzalloc(sizeof(*newmac) + 6, GFP_KERNEL); 181 if (!newmac) 182 return; 183 newmac->value = newmac + 1; 184 newmac->length = 6; 185 186 newmac->name = kstrdup("local-mac-address", GFP_KERNEL); 187 if (!newmac->name) { 188 kfree(newmac); 189 return; 190 } 191 192 /* 193 * OCOTP only stores the last 4 octets for each mac address, 194 * so hard-code OUI here. 195 */ 196 macaddr = newmac->value; 197 switch (oui) { 198 case OUI_FSL: 199 macaddr[0] = 0x00; 200 macaddr[1] = 0x04; 201 macaddr[2] = 0x9f; 202 break; 203 case OUI_DENX: 204 macaddr[0] = 0xc0; 205 macaddr[1] = 0xe5; 206 macaddr[2] = 0x4e; 207 break; 208 } 209 val = ocotp[i]; 210 macaddr[3] = (val >> 16) & 0xff; 211 macaddr[4] = (val >> 8) & 0xff; 212 macaddr[5] = (val >> 0) & 0xff; 213 214 prom_update_property(np, newmac); 215 } 216 } 217 218 static void __init imx23_evk_init(void) 219 { 220 mxsfb_pdata.mode_list = mx23evk_video_modes; 221 mxsfb_pdata.mode_count = ARRAY_SIZE(mx23evk_video_modes); 222 mxsfb_pdata.default_bpp = 32; 223 mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT; 224 } 225 226 static inline void enable_clk_enet_out(void) 227 { 228 struct clk *clk = clk_get_sys("enet_out", NULL); 229 230 if (!IS_ERR(clk)) 231 clk_prepare_enable(clk); 232 } 233 234 static void __init imx28_evk_init(void) 235 { 236 enable_clk_enet_out(); 237 update_fec_mac_prop(OUI_FSL); 238 239 mxsfb_pdata.mode_list = mx28evk_video_modes; 240 mxsfb_pdata.mode_count = ARRAY_SIZE(mx28evk_video_modes); 241 mxsfb_pdata.default_bpp = 32; 242 mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT; 243 244 mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0); 245 } 246 247 static void __init imx28_evk_post_init(void) 248 { 249 if (!gpio_request_one(MX28EVK_FLEXCAN_SWITCH, GPIOF_DIR_OUT, 250 "flexcan-switch")) { 251 flexcan_pdata[0].transceiver_switch = mx28evk_flexcan0_switch; 252 flexcan_pdata[1].transceiver_switch = mx28evk_flexcan1_switch; 253 } 254 } 255 256 static void __init m28evk_init(void) 257 { 258 mxsfb_pdata.mode_list = m28evk_video_modes; 259 mxsfb_pdata.mode_count = ARRAY_SIZE(m28evk_video_modes); 260 mxsfb_pdata.default_bpp = 16; 261 mxsfb_pdata.ld_intf_width = STMLCDIF_18BIT; 262 } 263 264 static int apx4devkit_phy_fixup(struct phy_device *phy) 265 { 266 phy->dev_flags |= MICREL_PHY_50MHZ_CLK; 267 return 0; 268 } 269 270 static void __init apx4devkit_init(void) 271 { 272 enable_clk_enet_out(); 273 274 if (IS_BUILTIN(CONFIG_PHYLIB)) 275 phy_register_fixup_for_uid(PHY_ID_KSZ8051, MICREL_PHY_ID_MASK, 276 apx4devkit_phy_fixup); 277 278 mxsfb_pdata.mode_list = apx4devkit_video_modes; 279 mxsfb_pdata.mode_count = ARRAY_SIZE(apx4devkit_video_modes); 280 mxsfb_pdata.default_bpp = 32; 281 mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT; 282 } 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 358 static void __init mxs_machine_init(void) 359 { 360 if (of_machine_is_compatible("fsl,imx28-evk")) 361 imx28_evk_init(); 362 else if (of_machine_is_compatible("fsl,imx23-evk")) 363 imx23_evk_init(); 364 else if (of_machine_is_compatible("denx,m28evk")) 365 m28evk_init(); 366 else if (of_machine_is_compatible("bluegiga,apx4devkit")) 367 apx4devkit_init(); 368 369 of_platform_populate(NULL, of_default_bus_match_table, 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(); 377 } 378 379 static const char *imx23_dt_compat[] __initdata = { 380 "fsl,imx23", 381 NULL, 382 }; 383 384 static const char *imx28_dt_compat[] __initdata = { 385 "fsl,imx28", 386 NULL, 387 }; 388 389 DT_MACHINE_START(IMX23, "Freescale i.MX23 (Device Tree)") 390 .map_io = mx23_map_io, 391 .init_irq = icoll_init_irq, 392 .handle_irq = icoll_handle_irq, 393 .timer = &imx23_timer, 394 .init_machine = mxs_machine_init, 395 .dt_compat = imx23_dt_compat, 396 .restart = mxs_restart, 397 MACHINE_END 398 399 DT_MACHINE_START(IMX28, "Freescale i.MX28 (Device Tree)") 400 .map_io = mx28_map_io, 401 .init_irq = icoll_init_irq, 402 .handle_irq = icoll_handle_irq, 403 .timer = &imx28_timer, 404 .init_machine = mxs_machine_init, 405 .dt_compat = imx28_dt_compat, 406 .restart = mxs_restart, 407 MACHINE_END 408