wandboard.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. /*
  2. * Copyright (C) 2013 Freescale Semiconductor, Inc.
  3. *
  4. * Author: Fabio Estevam <fabio.estevam@freescale.com>
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation; either version 2 of
  9. * the License, or (at your option) any later version.
  10. */
  11. #include <asm/arch/clock.h>
  12. #include <asm/arch/crm_regs.h>
  13. #include <asm/arch/iomux.h>
  14. #include <asm/arch/imx-regs.h>
  15. #include <asm/arch/mx6-pins.h>
  16. #include <asm/arch/mxc_hdmi.h>
  17. #include <asm/arch/sys_proto.h>
  18. #include <asm/gpio.h>
  19. #include <asm/imx-common/iomux-v3.h>
  20. #include <asm/imx-common/boot_mode.h>
  21. #include <asm/io.h>
  22. #include <asm/sizes.h>
  23. #include <common.h>
  24. #include <fsl_esdhc.h>
  25. #include <ipu_pixfmt.h>
  26. #include <mmc.h>
  27. #include <miiphy.h>
  28. #include <netdev.h>
  29. #include <linux/fb.h>
  30. DECLARE_GLOBAL_DATA_PTR;
  31. #define UART_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
  32. PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \
  33. PAD_CTL_SRE_FAST | PAD_CTL_HYS)
  34. #define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP | \
  35. PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm | \
  36. PAD_CTL_SRE_FAST | PAD_CTL_HYS)
  37. #define ENET_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
  38. PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
  39. #define USDHC1_CD_GPIO IMX_GPIO_NR(1, 2)
  40. #define USDHC3_CD_GPIO IMX_GPIO_NR(3, 9)
  41. #define ETH_PHY_RESET IMX_GPIO_NR(3, 29)
  42. int dram_init(void)
  43. {
  44. gd->ram_size = CONFIG_DDR_MB * SZ_1M;
  45. return 0;
  46. }
  47. static iomux_v3_cfg_t const uart1_pads[] = {
  48. MX6_PAD_CSI0_DAT10__UART1_TXD | MUX_PAD_CTRL(UART_PAD_CTRL),
  49. MX6_PAD_CSI0_DAT11__UART1_RXD | MUX_PAD_CTRL(UART_PAD_CTRL),
  50. };
  51. iomux_v3_cfg_t const usdhc1_pads[] = {
  52. MX6_PAD_SD1_CLK__USDHC1_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  53. MX6_PAD_SD1_CMD__USDHC1_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  54. MX6_PAD_SD1_DAT0__USDHC1_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  55. MX6_PAD_SD1_DAT1__USDHC1_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  56. MX6_PAD_SD1_DAT2__USDHC1_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  57. MX6_PAD_SD1_DAT3__USDHC1_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  58. /* Carrier MicroSD Card Detect */
  59. MX6_PAD_GPIO_2__GPIO_1_2 | MUX_PAD_CTRL(NO_PAD_CTRL),
  60. };
  61. static iomux_v3_cfg_t const usdhc3_pads[] = {
  62. MX6_PAD_SD3_CLK__USDHC3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  63. MX6_PAD_SD3_CMD__USDHC3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  64. MX6_PAD_SD3_DAT0__USDHC3_DAT0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  65. MX6_PAD_SD3_DAT1__USDHC3_DAT1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  66. MX6_PAD_SD3_DAT2__USDHC3_DAT2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  67. MX6_PAD_SD3_DAT3__USDHC3_DAT3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  68. /* SOM MicroSD Card Detect */
  69. MX6_PAD_EIM_DA9__GPIO_3_9 | MUX_PAD_CTRL(NO_PAD_CTRL),
  70. };
  71. static iomux_v3_cfg_t const enet_pads[] = {
  72. MX6_PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL),
  73. MX6_PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
  74. MX6_PAD_RGMII_TXC__ENET_RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
  75. MX6_PAD_RGMII_TD0__ENET_RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  76. MX6_PAD_RGMII_TD1__ENET_RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  77. MX6_PAD_RGMII_TD2__ENET_RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  78. MX6_PAD_RGMII_TD3__ENET_RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  79. MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
  80. MX6_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL),
  81. MX6_PAD_RGMII_RXC__ENET_RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
  82. MX6_PAD_RGMII_RD0__ENET_RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  83. MX6_PAD_RGMII_RD1__ENET_RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  84. MX6_PAD_RGMII_RD2__ENET_RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  85. MX6_PAD_RGMII_RD3__ENET_RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  86. MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
  87. /* AR8031 PHY Reset */
  88. MX6_PAD_EIM_D29__GPIO_3_29 | MUX_PAD_CTRL(NO_PAD_CTRL),
  89. };
  90. static void setup_iomux_uart(void)
  91. {
  92. imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
  93. }
  94. static void setup_iomux_enet(void)
  95. {
  96. imx_iomux_v3_setup_multiple_pads(enet_pads, ARRAY_SIZE(enet_pads));
  97. /* Reset AR8031 PHY */
  98. gpio_direction_output(ETH_PHY_RESET, 0);
  99. udelay(500);
  100. gpio_set_value(ETH_PHY_RESET, 1);
  101. }
  102. static struct fsl_esdhc_cfg usdhc_cfg[2] = {
  103. {USDHC3_BASE_ADDR},
  104. {USDHC1_BASE_ADDR},
  105. };
  106. int board_mmc_getcd(struct mmc *mmc)
  107. {
  108. struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
  109. int ret = 0;
  110. switch (cfg->esdhc_base) {
  111. case USDHC1_BASE_ADDR:
  112. ret = !gpio_get_value(USDHC1_CD_GPIO);
  113. break;
  114. case USDHC3_BASE_ADDR:
  115. ret = !gpio_get_value(USDHC3_CD_GPIO);
  116. break;
  117. }
  118. return ret;
  119. }
  120. int board_mmc_init(bd_t *bis)
  121. {
  122. s32 status = 0;
  123. u32 index = 0;
  124. /*
  125. * Following map is done:
  126. * (U-boot device node) (Physical Port)
  127. * mmc0 SOM MicroSD
  128. * mmc1 Carrier board MicroSD
  129. */
  130. for (index = 0; index < CONFIG_SYS_FSL_USDHC_NUM; ++index) {
  131. switch (index) {
  132. case 0:
  133. imx_iomux_v3_setup_multiple_pads(
  134. usdhc3_pads, ARRAY_SIZE(usdhc3_pads));
  135. usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
  136. usdhc_cfg[0].max_bus_width = 4;
  137. gpio_direction_input(USDHC3_CD_GPIO);
  138. break;
  139. case 1:
  140. imx_iomux_v3_setup_multiple_pads(
  141. usdhc1_pads, ARRAY_SIZE(usdhc1_pads));
  142. usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
  143. usdhc_cfg[1].max_bus_width = 4;
  144. gpio_direction_input(USDHC1_CD_GPIO);
  145. break;
  146. default:
  147. printf("Warning: you configured more USDHC controllers"
  148. "(%d) then supported by the board (%d)\n",
  149. index + 1, CONFIG_SYS_FSL_USDHC_NUM);
  150. return status;
  151. }
  152. status |= fsl_esdhc_initialize(bis, &usdhc_cfg[index]);
  153. }
  154. return status;
  155. }
  156. static int mx6_rgmii_rework(struct phy_device *phydev)
  157. {
  158. unsigned short val;
  159. /* To enable AR8031 ouput a 125MHz clk from CLK_25M */
  160. phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x7);
  161. phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x8016);
  162. phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4007);
  163. val = phy_read(phydev, MDIO_DEVAD_NONE, 0xe);
  164. val &= 0xffe3;
  165. val |= 0x18;
  166. phy_write(phydev, MDIO_DEVAD_NONE, 0xe, val);
  167. /* introduce tx clock delay */
  168. phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x5);
  169. val = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e);
  170. val |= 0x0100;
  171. phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, val);
  172. return 0;
  173. }
  174. int board_phy_config(struct phy_device *phydev)
  175. {
  176. mx6_rgmii_rework(phydev);
  177. if (phydev->drv->config)
  178. phydev->drv->config(phydev);
  179. return 0;
  180. }
  181. #if defined(CONFIG_VIDEO_IPUV3)
  182. static void enable_hdmi(void)
  183. {
  184. struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
  185. u8 reg;
  186. reg = readb(&hdmi->phy_conf0);
  187. reg |= HDMI_PHY_CONF0_PDZ_MASK;
  188. writeb(reg, &hdmi->phy_conf0);
  189. udelay(3000);
  190. reg |= HDMI_PHY_CONF0_ENTMDS_MASK;
  191. writeb(reg, &hdmi->phy_conf0);
  192. udelay(3000);
  193. reg |= HDMI_PHY_CONF0_GEN2_TXPWRON_MASK;
  194. writeb(reg, &hdmi->phy_conf0);
  195. writeb(HDMI_MC_PHYRSTZ_ASSERT, &hdmi->mc_phyrstz);
  196. }
  197. static struct fb_videomode const hdmi = {
  198. .name = "HDMI",
  199. .refresh = 60,
  200. .xres = 1024,
  201. .yres = 768,
  202. .pixclock = 15385,
  203. .left_margin = 220,
  204. .right_margin = 40,
  205. .upper_margin = 21,
  206. .lower_margin = 7,
  207. .hsync_len = 60,
  208. .vsync_len = 10,
  209. .sync = FB_SYNC_EXT,
  210. .vmode = FB_VMODE_NONINTERLACED
  211. };
  212. int board_video_skip(void)
  213. {
  214. int ret;
  215. ret = ipuv3_fb_init(&hdmi, 0, IPU_PIX_FMT_RGB24);
  216. if (ret)
  217. printf("HDMI cannot be configured: %d\n", ret);
  218. enable_hdmi();
  219. return ret;
  220. }
  221. static void setup_display(void)
  222. {
  223. struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
  224. struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
  225. int reg;
  226. /* Turn on IPU clock */
  227. reg = readl(&mxc_ccm->CCGR3);
  228. reg |= MXC_CCM_CCGR3_IPU1_IPU_DI0_OFFSET;
  229. writel(reg, &mxc_ccm->CCGR3);
  230. /* Turn on HDMI PHY clock */
  231. reg = readl(&mxc_ccm->CCGR2);
  232. reg |= MXC_CCM_CCGR2_HDMI_TX_IAHBCLK_MASK
  233. | MXC_CCM_CCGR2_HDMI_TX_ISFRCLK_MASK;
  234. writel(reg, &mxc_ccm->CCGR2);
  235. /* clear HDMI PHY reset */
  236. writeb(HDMI_MC_PHYRSTZ_DEASSERT, &hdmi->mc_phyrstz);
  237. reg = readl(&mxc_ccm->chsccdr);
  238. reg &= ~(MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK
  239. | MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK
  240. | MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK);
  241. reg |= (CHSCCDR_CLK_SEL_LDB_DI0
  242. << MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET)
  243. | (CHSCCDR_PODF_DIVIDE_BY_3
  244. << MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET)
  245. | (CHSCCDR_IPU_PRE_CLK_540M_PFD
  246. << MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET);
  247. writel(reg, &mxc_ccm->chsccdr);
  248. }
  249. #endif /* CONFIG_VIDEO_IPUV3 */
  250. int board_eth_init(bd_t *bis)
  251. {
  252. int ret;
  253. setup_iomux_enet();
  254. ret = cpu_eth_init(bis);
  255. if (ret)
  256. printf("FEC MXC: %s:failed\n", __func__);
  257. return 0;
  258. }
  259. int board_early_init_f(void)
  260. {
  261. setup_iomux_uart();
  262. #if defined(CONFIG_VIDEO_IPUV3)
  263. setup_display();
  264. #endif
  265. return 0;
  266. }
  267. /*
  268. * Do not overwrite the console
  269. * Use always serial for U-Boot console
  270. */
  271. int overwrite_console(void)
  272. {
  273. return 1;
  274. }
  275. #ifdef CONFIG_CMD_BMODE
  276. static const struct boot_mode board_boot_modes[] = {
  277. /* 4 bit bus width */
  278. {"mmc0", MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)},
  279. {"mmc1", MAKE_CFGVAL(0x40, 0x20, 0x00, 0x00)},
  280. {NULL, 0},
  281. };
  282. #endif
  283. int board_late_init(void)
  284. {
  285. #ifdef CONFIG_CMD_BMODE
  286. add_board_boot_modes(board_boot_modes);
  287. #endif
  288. return 0;
  289. }
  290. int board_init(void)
  291. {
  292. /* address of boot parameters */
  293. gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
  294. return 0;
  295. }
  296. int checkboard(void)
  297. {
  298. puts("Board: Wandboard\n");
  299. return 0;
  300. }