mx6cuboxi.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2015 Freescale Semiconductor, Inc.
  4. *
  5. * Author: Fabio Estevam <fabio.estevam@freescale.com>
  6. *
  7. * Copyright (C) 2013 Jon Nettleton <jon.nettleton@gmail.com>
  8. *
  9. * Based on SPL code from Solidrun tree, which is:
  10. * Author: Tungyi Lin <tungyilin1127@gmail.com>
  11. *
  12. * Derived from EDM_CF_IMX6 code by TechNexion,Inc
  13. * Ported to SolidRun microSOM by Rabeeh Khoury <rabeeh@solid-run.com>
  14. */
  15. #include <asm/arch/clock.h>
  16. #include <asm/arch/imx-regs.h>
  17. #include <asm/arch/iomux.h>
  18. #include <asm/arch/mx6-pins.h>
  19. #include <asm/arch/mxc_hdmi.h>
  20. #include <linux/errno.h>
  21. #include <asm/gpio.h>
  22. #include <asm/mach-imx/iomux-v3.h>
  23. #include <asm/mach-imx/sata.h>
  24. #include <asm/mach-imx/video.h>
  25. #include <mmc.h>
  26. #include <fsl_esdhc.h>
  27. #include <malloc.h>
  28. #include <miiphy.h>
  29. #include <netdev.h>
  30. #include <asm/arch/crm_regs.h>
  31. #include <asm/io.h>
  32. #include <asm/arch/sys_proto.h>
  33. #include <spl.h>
  34. #include <usb.h>
  35. #include <usb/ehci-ci.h>
  36. DECLARE_GLOBAL_DATA_PTR;
  37. #define UART_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
  38. PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \
  39. PAD_CTL_SRE_FAST | PAD_CTL_HYS)
  40. #define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP | \
  41. PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm | \
  42. PAD_CTL_SRE_FAST | PAD_CTL_HYS)
  43. #define ENET_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
  44. PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
  45. #define ENET_PAD_CTRL_PD (PAD_CTL_PUS_100K_DOWN | \
  46. PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
  47. #define ENET_PAD_CTRL_CLK ((PAD_CTL_PUS_100K_UP & ~PAD_CTL_PKE) | \
  48. PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST)
  49. #define ETH_PHY_RESET IMX_GPIO_NR(4, 15)
  50. #define USB_H1_VBUS IMX_GPIO_NR(1, 0)
  51. enum board_type {
  52. CUBOXI = 0x00,
  53. HUMMINGBOARD = 0x01,
  54. HUMMINGBOARD2 = 0x02,
  55. UNKNOWN = 0x03,
  56. };
  57. #define MEM_STRIDE 0x4000000
  58. static u32 get_ram_size_stride_test(u32 *base, u32 maxsize)
  59. {
  60. volatile u32 *addr;
  61. u32 save[64];
  62. u32 cnt;
  63. u32 size;
  64. int i = 0;
  65. /* First save the data */
  66. for (cnt = 0; cnt < maxsize; cnt += MEM_STRIDE) {
  67. addr = (volatile u32 *)((u32)base + cnt); /* pointer arith! */
  68. sync ();
  69. save[i++] = *addr;
  70. sync ();
  71. }
  72. /* First write a signature */
  73. * (volatile u32 *)base = 0x12345678;
  74. for (size = MEM_STRIDE; size < maxsize; size += MEM_STRIDE) {
  75. * (volatile u32 *)((u32)base + size) = size;
  76. sync ();
  77. if (* (volatile u32 *)((u32)base) == size) { /* We reached the overlapping address */
  78. break;
  79. }
  80. }
  81. /* Restore the data */
  82. for (cnt = (maxsize - MEM_STRIDE); i > 0; cnt -= MEM_STRIDE) {
  83. addr = (volatile u32 *)((u32)base + cnt); /* pointer arith! */
  84. sync ();
  85. *addr = save[i--];
  86. sync ();
  87. }
  88. return (size);
  89. }
  90. int dram_init(void)
  91. {
  92. u32 max_size = imx_ddr_size();
  93. gd->ram_size = get_ram_size_stride_test((u32 *) CONFIG_SYS_SDRAM_BASE,
  94. (u32)max_size);
  95. return 0;
  96. }
  97. static iomux_v3_cfg_t const uart1_pads[] = {
  98. IOMUX_PADS(PAD_CSI0_DAT10__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)),
  99. IOMUX_PADS(PAD_CSI0_DAT11__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)),
  100. };
  101. static iomux_v3_cfg_t const usdhc2_pads[] = {
  102. IOMUX_PADS(PAD_SD2_CLK__SD2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
  103. IOMUX_PADS(PAD_SD2_CMD__SD2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
  104. IOMUX_PADS(PAD_SD2_DAT0__SD2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
  105. IOMUX_PADS(PAD_SD2_DAT1__SD2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
  106. IOMUX_PADS(PAD_SD2_DAT2__SD2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
  107. IOMUX_PADS(PAD_SD2_DAT3__SD2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
  108. };
  109. static iomux_v3_cfg_t const board_detect[] = {
  110. /* These pins are for sensing if it is a CuBox-i or a HummingBoard */
  111. IOMUX_PADS(PAD_KEY_ROW1__GPIO4_IO09 | MUX_PAD_CTRL(UART_PAD_CTRL)),
  112. IOMUX_PADS(PAD_EIM_DA4__GPIO3_IO04 | MUX_PAD_CTRL(UART_PAD_CTRL)),
  113. IOMUX_PADS(PAD_SD4_DAT0__GPIO2_IO08 | MUX_PAD_CTRL(UART_PAD_CTRL)),
  114. };
  115. static iomux_v3_cfg_t const som_rev_detect[] = {
  116. /* These pins are for sensing if it is a CuBox-i or a HummingBoard */
  117. IOMUX_PADS(PAD_CSI0_DAT14__GPIO6_IO00 | MUX_PAD_CTRL(UART_PAD_CTRL)),
  118. IOMUX_PADS(PAD_CSI0_DAT18__GPIO6_IO04 | MUX_PAD_CTRL(UART_PAD_CTRL)),
  119. };
  120. static iomux_v3_cfg_t const usb_pads[] = {
  121. IOMUX_PADS(PAD_GPIO_0__GPIO1_IO00 | MUX_PAD_CTRL(NO_PAD_CTRL)),
  122. };
  123. static void setup_iomux_uart(void)
  124. {
  125. SETUP_IOMUX_PADS(uart1_pads);
  126. }
  127. static struct fsl_esdhc_cfg usdhc_cfg[1] = {
  128. {USDHC2_BASE_ADDR},
  129. };
  130. int board_mmc_getcd(struct mmc *mmc)
  131. {
  132. return 1; /* uSDHC2 is always present */
  133. }
  134. int board_mmc_init(bd_t *bis)
  135. {
  136. SETUP_IOMUX_PADS(usdhc2_pads);
  137. usdhc_cfg[0].esdhc_base = USDHC2_BASE_ADDR;
  138. usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
  139. gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk;
  140. return fsl_esdhc_initialize(bis, &usdhc_cfg[0]);
  141. }
  142. static iomux_v3_cfg_t const enet_pads[] = {
  143. IOMUX_PADS(PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL)),
  144. IOMUX_PADS(PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL)),
  145. /* AR8035 reset */
  146. IOMUX_PADS(PAD_KEY_ROW4__GPIO4_IO15 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)),
  147. /* AR8035 interrupt */
  148. IOMUX_PADS(PAD_DI0_PIN2__GPIO4_IO18 | MUX_PAD_CTRL(NO_PAD_CTRL)),
  149. /* GPIO16 -> AR8035 25MHz */
  150. IOMUX_PADS(PAD_GPIO_16__ENET_REF_CLK | MUX_PAD_CTRL(NO_PAD_CTRL)),
  151. IOMUX_PADS(PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(NO_PAD_CTRL)),
  152. IOMUX_PADS(PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
  153. IOMUX_PADS(PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
  154. IOMUX_PADS(PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
  155. IOMUX_PADS(PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
  156. IOMUX_PADS(PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL)),
  157. /* AR8035 CLK_25M --> ENET_REF_CLK (V22) */
  158. IOMUX_PADS(PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL_CLK)),
  159. IOMUX_PADS(PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL)),
  160. IOMUX_PADS(PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)),
  161. IOMUX_PADS(PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)),
  162. IOMUX_PADS(PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
  163. IOMUX_PADS(PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
  164. IOMUX_PADS(PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)),
  165. IOMUX_PADS(PAD_ENET_RXD0__GPIO1_IO27 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)),
  166. IOMUX_PADS(PAD_ENET_RXD1__GPIO1_IO26 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD)),
  167. };
  168. static void setup_iomux_enet(void)
  169. {
  170. SETUP_IOMUX_PADS(enet_pads);
  171. gpio_direction_output(ETH_PHY_RESET, 0);
  172. mdelay(10);
  173. gpio_set_value(ETH_PHY_RESET, 1);
  174. udelay(100);
  175. }
  176. int board_phy_config(struct phy_device *phydev)
  177. {
  178. if (phydev->drv->config)
  179. phydev->drv->config(phydev);
  180. return 0;
  181. }
  182. /* On Cuboxi Ethernet PHY can be located at addresses 0x0 or 0x4 */
  183. #define ETH_PHY_MASK ((1 << 0x0) | (1 << 0x4))
  184. int board_eth_init(bd_t *bis)
  185. {
  186. struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
  187. struct mii_dev *bus;
  188. struct phy_device *phydev;
  189. int ret = enable_fec_anatop_clock(0, ENET_25MHZ);
  190. if (ret)
  191. return ret;
  192. /* set gpr1[ENET_CLK_SEL] */
  193. setbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_ENET_CLK_SEL_MASK);
  194. setup_iomux_enet();
  195. bus = fec_get_miibus(IMX_FEC_BASE, -1);
  196. if (!bus)
  197. return -EINVAL;
  198. phydev = phy_find_by_mask(bus, ETH_PHY_MASK, PHY_INTERFACE_MODE_RGMII);
  199. if (!phydev) {
  200. ret = -EINVAL;
  201. goto free_bus;
  202. }
  203. debug("using phy at address %d\n", phydev->addr);
  204. ret = fec_probe(bis, -1, IMX_FEC_BASE, bus, phydev);
  205. if (ret)
  206. goto free_phydev;
  207. return 0;
  208. free_phydev:
  209. free(phydev);
  210. free_bus:
  211. free(bus);
  212. return ret;
  213. }
  214. #ifdef CONFIG_VIDEO_IPUV3
  215. static void do_enable_hdmi(struct display_info_t const *dev)
  216. {
  217. imx_enable_hdmi_phy();
  218. }
  219. struct display_info_t const displays[] = {
  220. {
  221. .bus = -1,
  222. .addr = 0,
  223. .pixfmt = IPU_PIX_FMT_RGB24,
  224. .detect = detect_hdmi,
  225. .enable = do_enable_hdmi,
  226. .mode = {
  227. .name = "HDMI",
  228. /* 1024x768@60Hz (VESA)*/
  229. .refresh = 60,
  230. .xres = 1024,
  231. .yres = 768,
  232. .pixclock = 15384,
  233. .left_margin = 160,
  234. .right_margin = 24,
  235. .upper_margin = 29,
  236. .lower_margin = 3,
  237. .hsync_len = 136,
  238. .vsync_len = 6,
  239. .sync = FB_SYNC_EXT,
  240. .vmode = FB_VMODE_NONINTERLACED
  241. }
  242. }
  243. };
  244. size_t display_count = ARRAY_SIZE(displays);
  245. static int setup_display(void)
  246. {
  247. struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
  248. int reg;
  249. int timeout = 100000;
  250. enable_ipu_clock();
  251. imx_setup_hdmi();
  252. /* set video pll to 455MHz (24MHz * (37+11/12) / 2) */
  253. setbits_le32(&ccm->analog_pll_video, BM_ANADIG_PLL_VIDEO_POWERDOWN);
  254. reg = readl(&ccm->analog_pll_video);
  255. reg &= ~BM_ANADIG_PLL_VIDEO_DIV_SELECT;
  256. reg |= BF_ANADIG_PLL_VIDEO_DIV_SELECT(37);
  257. reg &= ~BM_ANADIG_PLL_VIDEO_POST_DIV_SELECT;
  258. reg |= BF_ANADIG_PLL_VIDEO_POST_DIV_SELECT(1);
  259. writel(reg, &ccm->analog_pll_video);
  260. writel(BF_ANADIG_PLL_VIDEO_NUM_A(11), &ccm->analog_pll_video_num);
  261. writel(BF_ANADIG_PLL_VIDEO_DENOM_B(12), &ccm->analog_pll_video_denom);
  262. reg &= ~BM_ANADIG_PLL_VIDEO_POWERDOWN;
  263. writel(reg, &ccm->analog_pll_video);
  264. while (timeout--)
  265. if (readl(&ccm->analog_pll_video) & BM_ANADIG_PLL_VIDEO_LOCK)
  266. break;
  267. if (timeout < 0) {
  268. printf("Warning: video pll lock timeout!\n");
  269. return -ETIMEDOUT;
  270. }
  271. reg = readl(&ccm->analog_pll_video);
  272. reg |= BM_ANADIG_PLL_VIDEO_ENABLE;
  273. reg &= ~BM_ANADIG_PLL_VIDEO_BYPASS;
  274. writel(reg, &ccm->analog_pll_video);
  275. /* gate ipu1_di0_clk */
  276. clrbits_le32(&ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK);
  277. /* select video_pll clock / 7 for ipu1_di0_clk -> 65MHz pixclock */
  278. reg = readl(&ccm->chsccdr);
  279. reg &= ~(MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK |
  280. MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK |
  281. MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK);
  282. reg |= (2 << MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET) |
  283. (6 << MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET) |
  284. (0 << MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET);
  285. writel(reg, &ccm->chsccdr);
  286. /* enable ipu1_di0_clk */
  287. setbits_le32(&ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK);
  288. return 0;
  289. }
  290. #endif /* CONFIG_VIDEO_IPUV3 */
  291. #ifdef CONFIG_USB_EHCI_MX6
  292. static void setup_usb(void)
  293. {
  294. SETUP_IOMUX_PADS(usb_pads);
  295. }
  296. int board_ehci_hcd_init(int port)
  297. {
  298. if (port == 1)
  299. gpio_direction_output(USB_H1_VBUS, 1);
  300. return 0;
  301. }
  302. #endif
  303. int board_early_init_f(void)
  304. {
  305. setup_iomux_uart();
  306. #ifdef CONFIG_CMD_SATA
  307. setup_sata();
  308. #endif
  309. #ifdef CONFIG_USB_EHCI_MX6
  310. setup_usb();
  311. #endif
  312. return 0;
  313. }
  314. int board_init(void)
  315. {
  316. int ret = 0;
  317. /* address of boot parameters */
  318. gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
  319. #ifdef CONFIG_VIDEO_IPUV3
  320. ret = setup_display();
  321. #endif
  322. return ret;
  323. }
  324. static enum board_type board_type(void)
  325. {
  326. int val1, val2, val3;
  327. SETUP_IOMUX_PADS(board_detect);
  328. /*
  329. * Machine selection -
  330. * Machine val1, val2, val3
  331. * ----------------------------
  332. * HB2 x x 0
  333. * HB rev 3.x x 0 x
  334. * CBi 0 1 x
  335. * HB 1 1 x
  336. */
  337. gpio_direction_input(IMX_GPIO_NR(2, 8));
  338. val3 = gpio_get_value(IMX_GPIO_NR(2, 8));
  339. if (val3 == 0)
  340. return HUMMINGBOARD2;
  341. gpio_direction_input(IMX_GPIO_NR(3, 4));
  342. val2 = gpio_get_value(IMX_GPIO_NR(3, 4));
  343. if (val2 == 0)
  344. return HUMMINGBOARD;
  345. gpio_direction_input(IMX_GPIO_NR(4, 9));
  346. val1 = gpio_get_value(IMX_GPIO_NR(4, 9));
  347. if (val1 == 0) {
  348. return CUBOXI;
  349. } else {
  350. return HUMMINGBOARD;
  351. }
  352. }
  353. static bool is_rev_15_som(void)
  354. {
  355. int val1, val2;
  356. SETUP_IOMUX_PADS(som_rev_detect);
  357. val1 = gpio_get_value(IMX_GPIO_NR(6, 0));
  358. val2 = gpio_get_value(IMX_GPIO_NR(6, 4));
  359. if (val1 == 1 && val2 == 0)
  360. return true;
  361. return false;
  362. }
  363. int checkboard(void)
  364. {
  365. switch (board_type()) {
  366. case CUBOXI:
  367. puts("Board: MX6 Cubox-i");
  368. break;
  369. case HUMMINGBOARD:
  370. puts("Board: MX6 HummingBoard");
  371. break;
  372. case HUMMINGBOARD2:
  373. puts("Board: MX6 HummingBoard2");
  374. break;
  375. case UNKNOWN:
  376. default:
  377. puts("Board: Unknown\n");
  378. goto out;
  379. }
  380. if (is_rev_15_som())
  381. puts(" (som rev 1.5)\n");
  382. else
  383. puts("\n");
  384. out:
  385. return 0;
  386. }
  387. int board_late_init(void)
  388. {
  389. #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
  390. switch (board_type()) {
  391. case CUBOXI:
  392. env_set("board_name", "CUBOXI");
  393. break;
  394. case HUMMINGBOARD:
  395. env_set("board_name", "HUMMINGBOARD");
  396. break;
  397. case HUMMINGBOARD2:
  398. env_set("board_name", "HUMMINGBOARD2");
  399. break;
  400. case UNKNOWN:
  401. default:
  402. env_set("board_name", "CUBOXI");
  403. }
  404. if (is_mx6dq())
  405. env_set("board_rev", "MX6Q");
  406. else
  407. env_set("board_rev", "MX6DL");
  408. if (is_rev_15_som())
  409. env_set("som_rev", "V15");
  410. #endif
  411. return 0;
  412. }
  413. #ifdef CONFIG_SPL_BUILD
  414. #include <asm/arch/mx6-ddr.h>
  415. static const struct mx6dq_iomux_ddr_regs mx6q_ddr_ioregs = {
  416. .dram_sdclk_0 = 0x00020030,
  417. .dram_sdclk_1 = 0x00020030,
  418. .dram_cas = 0x00020030,
  419. .dram_ras = 0x00020030,
  420. .dram_reset = 0x000c0030,
  421. .dram_sdcke0 = 0x00003000,
  422. .dram_sdcke1 = 0x00003000,
  423. .dram_sdba2 = 0x00000000,
  424. .dram_sdodt0 = 0x00003030,
  425. .dram_sdodt1 = 0x00003030,
  426. .dram_sdqs0 = 0x00000030,
  427. .dram_sdqs1 = 0x00000030,
  428. .dram_sdqs2 = 0x00000030,
  429. .dram_sdqs3 = 0x00000030,
  430. .dram_sdqs4 = 0x00000030,
  431. .dram_sdqs5 = 0x00000030,
  432. .dram_sdqs6 = 0x00000030,
  433. .dram_sdqs7 = 0x00000030,
  434. .dram_dqm0 = 0x00020030,
  435. .dram_dqm1 = 0x00020030,
  436. .dram_dqm2 = 0x00020030,
  437. .dram_dqm3 = 0x00020030,
  438. .dram_dqm4 = 0x00020030,
  439. .dram_dqm5 = 0x00020030,
  440. .dram_dqm6 = 0x00020030,
  441. .dram_dqm7 = 0x00020030,
  442. };
  443. static const struct mx6sdl_iomux_ddr_regs mx6dl_ddr_ioregs = {
  444. .dram_sdclk_0 = 0x00000028,
  445. .dram_sdclk_1 = 0x00000028,
  446. .dram_cas = 0x00000028,
  447. .dram_ras = 0x00000028,
  448. .dram_reset = 0x000c0028,
  449. .dram_sdcke0 = 0x00003000,
  450. .dram_sdcke1 = 0x00003000,
  451. .dram_sdba2 = 0x00000000,
  452. .dram_sdodt0 = 0x00003030,
  453. .dram_sdodt1 = 0x00003030,
  454. .dram_sdqs0 = 0x00000028,
  455. .dram_sdqs1 = 0x00000028,
  456. .dram_sdqs2 = 0x00000028,
  457. .dram_sdqs3 = 0x00000028,
  458. .dram_sdqs4 = 0x00000028,
  459. .dram_sdqs5 = 0x00000028,
  460. .dram_sdqs6 = 0x00000028,
  461. .dram_sdqs7 = 0x00000028,
  462. .dram_dqm0 = 0x00000028,
  463. .dram_dqm1 = 0x00000028,
  464. .dram_dqm2 = 0x00000028,
  465. .dram_dqm3 = 0x00000028,
  466. .dram_dqm4 = 0x00000028,
  467. .dram_dqm5 = 0x00000028,
  468. .dram_dqm6 = 0x00000028,
  469. .dram_dqm7 = 0x00000028,
  470. };
  471. static const struct mx6dq_iomux_grp_regs mx6q_grp_ioregs = {
  472. .grp_ddr_type = 0x000C0000,
  473. .grp_ddrmode_ctl = 0x00020000,
  474. .grp_ddrpke = 0x00000000,
  475. .grp_addds = 0x00000030,
  476. .grp_ctlds = 0x00000030,
  477. .grp_ddrmode = 0x00020000,
  478. .grp_b0ds = 0x00000030,
  479. .grp_b1ds = 0x00000030,
  480. .grp_b2ds = 0x00000030,
  481. .grp_b3ds = 0x00000030,
  482. .grp_b4ds = 0x00000030,
  483. .grp_b5ds = 0x00000030,
  484. .grp_b6ds = 0x00000030,
  485. .grp_b7ds = 0x00000030,
  486. };
  487. static const struct mx6sdl_iomux_grp_regs mx6sdl_grp_ioregs = {
  488. .grp_ddr_type = 0x000c0000,
  489. .grp_ddrmode_ctl = 0x00020000,
  490. .grp_ddrpke = 0x00000000,
  491. .grp_addds = 0x00000028,
  492. .grp_ctlds = 0x00000028,
  493. .grp_ddrmode = 0x00020000,
  494. .grp_b0ds = 0x00000028,
  495. .grp_b1ds = 0x00000028,
  496. .grp_b2ds = 0x00000028,
  497. .grp_b3ds = 0x00000028,
  498. .grp_b4ds = 0x00000028,
  499. .grp_b5ds = 0x00000028,
  500. .grp_b6ds = 0x00000028,
  501. .grp_b7ds = 0x00000028,
  502. };
  503. /* microSOM with Dual processor and 1GB memory */
  504. static const struct mx6_mmdc_calibration mx6q_1g_mmcd_calib = {
  505. .p0_mpwldectrl0 = 0x00000000,
  506. .p0_mpwldectrl1 = 0x00000000,
  507. .p1_mpwldectrl0 = 0x00000000,
  508. .p1_mpwldectrl1 = 0x00000000,
  509. .p0_mpdgctrl0 = 0x0314031c,
  510. .p0_mpdgctrl1 = 0x023e0304,
  511. .p1_mpdgctrl0 = 0x03240330,
  512. .p1_mpdgctrl1 = 0x03180260,
  513. .p0_mprddlctl = 0x3630323c,
  514. .p1_mprddlctl = 0x3436283a,
  515. .p0_mpwrdlctl = 0x36344038,
  516. .p1_mpwrdlctl = 0x422a423c,
  517. };
  518. /* microSOM with Quad processor and 2GB memory */
  519. static const struct mx6_mmdc_calibration mx6q_2g_mmcd_calib = {
  520. .p0_mpwldectrl0 = 0x00000000,
  521. .p0_mpwldectrl1 = 0x00000000,
  522. .p1_mpwldectrl0 = 0x00000000,
  523. .p1_mpwldectrl1 = 0x00000000,
  524. .p0_mpdgctrl0 = 0x0314031c,
  525. .p0_mpdgctrl1 = 0x023e0304,
  526. .p1_mpdgctrl0 = 0x03240330,
  527. .p1_mpdgctrl1 = 0x03180260,
  528. .p0_mprddlctl = 0x3630323c,
  529. .p1_mprddlctl = 0x3436283a,
  530. .p0_mpwrdlctl = 0x36344038,
  531. .p1_mpwrdlctl = 0x422a423c,
  532. };
  533. /* microSOM with Solo processor and 512MB memory */
  534. static const struct mx6_mmdc_calibration mx6dl_512m_mmcd_calib = {
  535. .p0_mpwldectrl0 = 0x0045004D,
  536. .p0_mpwldectrl1 = 0x003A0047,
  537. .p0_mpdgctrl0 = 0x023C0224,
  538. .p0_mpdgctrl1 = 0x02000220,
  539. .p0_mprddlctl = 0x44444846,
  540. .p0_mpwrdlctl = 0x32343032,
  541. };
  542. /* microSOM with Dual lite processor and 1GB memory */
  543. static const struct mx6_mmdc_calibration mx6dl_1g_mmcd_calib = {
  544. .p0_mpwldectrl0 = 0x0045004D,
  545. .p0_mpwldectrl1 = 0x003A0047,
  546. .p1_mpwldectrl0 = 0x001F001F,
  547. .p1_mpwldectrl1 = 0x00210035,
  548. .p0_mpdgctrl0 = 0x023C0224,
  549. .p0_mpdgctrl1 = 0x02000220,
  550. .p1_mpdgctrl0 = 0x02200220,
  551. .p1_mpdgctrl1 = 0x02040208,
  552. .p0_mprddlctl = 0x44444846,
  553. .p1_mprddlctl = 0x4042463C,
  554. .p0_mpwrdlctl = 0x32343032,
  555. .p1_mpwrdlctl = 0x36363430,
  556. };
  557. static struct mx6_ddr3_cfg mem_ddr_2g = {
  558. .mem_speed = 1600,
  559. .density = 2,
  560. .width = 16,
  561. .banks = 8,
  562. .rowaddr = 14,
  563. .coladdr = 10,
  564. .pagesz = 2,
  565. .trcd = 1375,
  566. .trcmin = 4875,
  567. .trasmin = 3500,
  568. };
  569. static struct mx6_ddr3_cfg mem_ddr_4g = {
  570. .mem_speed = 1600,
  571. .density = 4,
  572. .width = 16,
  573. .banks = 8,
  574. .rowaddr = 16,
  575. .coladdr = 10,
  576. .pagesz = 2,
  577. .trcd = 1375,
  578. .trcmin = 4875,
  579. .trasmin = 3500,
  580. };
  581. static void ccgr_init(void)
  582. {
  583. struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
  584. writel(0x00C03F3F, &ccm->CCGR0);
  585. writel(0x0030FC03, &ccm->CCGR1);
  586. writel(0x0FFFC000, &ccm->CCGR2);
  587. writel(0x3FF00000, &ccm->CCGR3);
  588. writel(0x00FFF300, &ccm->CCGR4);
  589. writel(0x0F0000C3, &ccm->CCGR5);
  590. writel(0x000003FF, &ccm->CCGR6);
  591. }
  592. static void spl_dram_init(int width)
  593. {
  594. struct mx6_ddr_sysinfo sysinfo = {
  595. /* width of data bus: 0=16, 1=32, 2=64 */
  596. .dsize = width / 32,
  597. /* config for full 4GB range so that get_mem_size() works */
  598. .cs_density = 32, /* 32Gb per CS */
  599. .ncs = 1, /* single chip select */
  600. .cs1_mirror = 0,
  601. .rtt_wr = 1 /*DDR3_RTT_60_OHM*/, /* RTT_Wr = RZQ/4 */
  602. .rtt_nom = 1 /*DDR3_RTT_60_OHM*/, /* RTT_Nom = RZQ/4 */
  603. .walat = 1, /* Write additional latency */
  604. .ralat = 5, /* Read additional latency */
  605. .mif3_mode = 3, /* Command prediction working mode */
  606. .bi_on = 1, /* Bank interleaving enabled */
  607. .sde_to_rst = 0x10, /* 14 cycles, 200us (JEDEC default) */
  608. .rst_to_cke = 0x23, /* 33 cycles, 500us (JEDEC default) */
  609. .ddr_type = DDR_TYPE_DDR3,
  610. .refsel = 1, /* Refresh cycles at 32KHz */
  611. .refr = 7, /* 8 refresh commands per refresh cycle */
  612. };
  613. if (is_mx6dq())
  614. mx6dq_dram_iocfg(width, &mx6q_ddr_ioregs, &mx6q_grp_ioregs);
  615. else
  616. mx6sdl_dram_iocfg(width, &mx6dl_ddr_ioregs, &mx6sdl_grp_ioregs);
  617. if (is_cpu_type(MXC_CPU_MX6D))
  618. mx6_dram_cfg(&sysinfo, &mx6q_1g_mmcd_calib, &mem_ddr_2g);
  619. else if (is_cpu_type(MXC_CPU_MX6Q))
  620. mx6_dram_cfg(&sysinfo, &mx6q_2g_mmcd_calib, &mem_ddr_4g);
  621. else if (is_cpu_type(MXC_CPU_MX6DL))
  622. mx6_dram_cfg(&sysinfo, &mx6dl_1g_mmcd_calib, &mem_ddr_2g);
  623. else if (is_cpu_type(MXC_CPU_MX6SOLO))
  624. mx6_dram_cfg(&sysinfo, &mx6dl_512m_mmcd_calib, &mem_ddr_2g);
  625. }
  626. void board_init_f(ulong dummy)
  627. {
  628. /* setup AIPS and disable watchdog */
  629. arch_cpu_init();
  630. ccgr_init();
  631. gpr_init();
  632. /* iomux and setup of i2c */
  633. board_early_init_f();
  634. /* setup GP timer */
  635. timer_init();
  636. /* UART clocks enabled and gd valid - init serial console */
  637. preloader_console_init();
  638. /* DDR initialization */
  639. if (is_cpu_type(MXC_CPU_MX6SOLO))
  640. spl_dram_init(32);
  641. else
  642. spl_dram_init(64);
  643. /* Clear the BSS. */
  644. memset(__bss_start, 0, __bss_end - __bss_start);
  645. /* load/boot image from boot device */
  646. board_init_r(NULL, 0);
  647. }
  648. #endif