cl-som-imx7.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * U-Boot board functions for CompuLab CL-SOM-iMX7 module
  4. *
  5. * (C) Copyright 2017 CompuLab, Ltd. http://www.compulab.com
  6. *
  7. * Author: Uri Mashiach <uri.mashiach@compulab.co.il>
  8. */
  9. #include <common.h>
  10. #include <env.h>
  11. #include <init.h>
  12. #include <mmc.h>
  13. #include <phy.h>
  14. #include <netdev.h>
  15. #include <fsl_esdhc_imx.h>
  16. #include <power/pmic.h>
  17. #include <power/pfuze3000_pmic.h>
  18. #include <asm/mach-imx/mxc_i2c.h>
  19. #include <asm/mach-imx/iomux-v3.h>
  20. #include <asm/arch-mx7/mx7-pins.h>
  21. #include <asm/arch-mx7/sys_proto.h>
  22. #include <asm/arch-mx7/clock.h>
  23. #include "../common/eeprom.h"
  24. #include "common.h"
  25. DECLARE_GLOBAL_DATA_PTR;
  26. #ifdef CONFIG_SYS_I2C_MXC
  27. #define I2C_PAD_CTRL (PAD_CTL_DSE_3P3V_32OHM | PAD_CTL_SRE_SLOW | \
  28. PAD_CTL_HYS)
  29. #define CL_SOM_IMX7_GPIO_I2C2_SCL IMX_GPIO_NR(1, 6)
  30. #define CL_SOM_IMX7_GPIO_I2C2_SDA IMX_GPIO_NR(1, 7)
  31. static struct i2c_pads_info cl_som_imx7_i2c_pad_info2 = {
  32. .scl = {
  33. .i2c_mode = MX7D_PAD_GPIO1_IO06__I2C2_SCL |
  34. MUX_PAD_CTRL(I2C_PAD_CTRL),
  35. .gpio_mode = MX7D_PAD_GPIO1_IO06__GPIO1_IO6 |
  36. MUX_PAD_CTRL(I2C_PAD_CTRL),
  37. .gp = CL_SOM_IMX7_GPIO_I2C2_SCL,
  38. },
  39. .sda = {
  40. .i2c_mode = MX7D_PAD_GPIO1_IO07__I2C2_SDA |
  41. MUX_PAD_CTRL(I2C_PAD_CTRL),
  42. .gpio_mode = MX7D_PAD_GPIO1_IO07__GPIO1_IO7 |
  43. MUX_PAD_CTRL(I2C_PAD_CTRL),
  44. .gp = CL_SOM_IMX7_GPIO_I2C2_SDA,
  45. },
  46. };
  47. /*
  48. * cl_som_imx7_setup_i2c() - I2C pinmux configuration.
  49. */
  50. static void cl_som_imx7_setup_i2c(void)
  51. {
  52. setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &cl_som_imx7_i2c_pad_info2);
  53. }
  54. #else /* !CONFIG_SYS_I2C_MXC */
  55. static void cl_som_imx7_setup_i2c(void) {}
  56. #endif /* CONFIG_SYS_I2C_MXC */
  57. int dram_init(void)
  58. {
  59. gd->ram_size = imx_ddr_size();
  60. return 0;
  61. }
  62. #ifdef CONFIG_FSL_ESDHC_IMX
  63. #define CL_SOM_IMX7_GPIO_USDHC3_PWR IMX_GPIO_NR(6, 11)
  64. static struct fsl_esdhc_cfg cl_som_imx7_usdhc_cfg[3] = {
  65. {USDHC1_BASE_ADDR, 0, 4},
  66. {USDHC3_BASE_ADDR},
  67. };
  68. int board_mmc_init(bd_t *bis)
  69. {
  70. int i, ret;
  71. /*
  72. * According to the board_mmc_init() the following map is done:
  73. * (U-boot device node) (Physical Port)
  74. * mmc0 USDHC1
  75. * mmc2 USDHC3 (eMMC)
  76. */
  77. for (i = 0; i < CONFIG_SYS_FSL_USDHC_NUM; i++) {
  78. switch (i) {
  79. case 0:
  80. cl_som_imx7_usdhc1_pads_set();
  81. gpio_request(CL_SOM_IMX7_GPIO_USDHC1_CD, "usdhc1_cd");
  82. cl_som_imx7_usdhc_cfg[0].sdhc_clk =
  83. mxc_get_clock(MXC_ESDHC_CLK);
  84. break;
  85. case 1:
  86. cl_som_imx7_usdhc3_emmc_pads_set();
  87. gpio_request(CL_SOM_IMX7_GPIO_USDHC3_PWR, "usdhc3_pwr");
  88. gpio_direction_output(CL_SOM_IMX7_GPIO_USDHC3_PWR, 0);
  89. udelay(500);
  90. gpio_direction_output(CL_SOM_IMX7_GPIO_USDHC3_PWR, 1);
  91. cl_som_imx7_usdhc_cfg[1].sdhc_clk =
  92. mxc_get_clock(MXC_ESDHC3_CLK);
  93. break;
  94. default:
  95. printf("Warning: you configured more USDHC controllers "
  96. "(%d) than supported by the board\n", i + 1);
  97. return -EINVAL;
  98. }
  99. ret = fsl_esdhc_initialize(bis, &cl_som_imx7_usdhc_cfg[i]);
  100. if (ret)
  101. return ret;
  102. }
  103. return 0;
  104. }
  105. #endif /* CONFIG_FSL_ESDHC_IMX */
  106. #ifdef CONFIG_FEC_MXC
  107. #define CL_SOM_IMX7_ETH1_PHY_NRST IMX_GPIO_NR(1, 4)
  108. /*
  109. * cl_som_imx7_rgmii_rework() - Ethernet PHY configuration.
  110. */
  111. static void cl_som_imx7_rgmii_rework(struct phy_device *phydev)
  112. {
  113. unsigned short val;
  114. /* Ar8031 phy SmartEEE feature cause link status generates glitch,
  115. * which cause ethernet link down/up issue, so disable SmartEEE
  116. */
  117. phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x3);
  118. phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x805d);
  119. phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4003);
  120. val = phy_read(phydev, MDIO_DEVAD_NONE, 0xe);
  121. val &= ~(0x1 << 8);
  122. phy_write(phydev, MDIO_DEVAD_NONE, 0xe, val);
  123. /* To enable AR8031 ouput a 125MHz clk from CLK_25M */
  124. phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x7);
  125. phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x8016);
  126. phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4007);
  127. val = phy_read(phydev, MDIO_DEVAD_NONE, 0xe);
  128. val &= 0xffe3;
  129. val |= 0x18;
  130. phy_write(phydev, MDIO_DEVAD_NONE, 0xe, val);
  131. /* introduce tx clock delay */
  132. phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x5);
  133. val = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e);
  134. val |= 0x0100;
  135. phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, val);
  136. }
  137. int board_phy_config(struct phy_device *phydev)
  138. {
  139. cl_som_imx7_rgmii_rework(phydev);
  140. if (phydev->drv->config)
  141. phydev->drv->config(phydev);
  142. return 0;
  143. }
  144. /*
  145. * cl_som_imx7_handle_mac_address() - set Ethernet MAC address environment.
  146. *
  147. * @env_var: MAC address environment variable
  148. * @eeprom_bus: I2C bus of the environment EEPROM
  149. *
  150. * @return: 0 on success, < 0 on failure
  151. */
  152. static int cl_som_imx7_handle_mac_address(char *env_var, uint eeprom_bus)
  153. {
  154. int ret;
  155. unsigned char enetaddr[6];
  156. ret = eth_env_get_enetaddr(env_var, enetaddr);
  157. if (ret)
  158. return 0;
  159. ret = cl_eeprom_read_mac_addr(enetaddr, eeprom_bus);
  160. if (ret)
  161. return ret;
  162. ret = is_valid_ethaddr(enetaddr);
  163. if (!ret)
  164. return -1;
  165. return eth_env_set_enetaddr(env_var, enetaddr);
  166. }
  167. #define CL_SOM_IMX7_FEC_DEV_ID_PRI 0
  168. int board_eth_init(bd_t *bis)
  169. {
  170. /* set Ethernet MAC address environment */
  171. cl_som_imx7_handle_mac_address("ethaddr", CONFIG_SYS_I2C_EEPROM_BUS);
  172. /* Ethernet interface pinmux configuration */
  173. cl_som_imx7_phy1_rst_pads_set();
  174. cl_som_imx7_fec1_pads_set();
  175. /* PHY reset */
  176. gpio_request(CL_SOM_IMX7_ETH1_PHY_NRST, "eth1_phy_nrst");
  177. gpio_direction_output(CL_SOM_IMX7_ETH1_PHY_NRST, 0);
  178. mdelay(10);
  179. gpio_set_value(CL_SOM_IMX7_ETH1_PHY_NRST, 1);
  180. /* MAC initialization */
  181. return fecmxc_initialize_multi(bis, CL_SOM_IMX7_FEC_DEV_ID_PRI,
  182. CONFIG_FEC_MXC_PHYADDR, IMX_FEC_BASE);
  183. }
  184. /*
  185. * cl_som_imx7_setup_fec() - Ethernet MAC 1 clock configuration.
  186. * - ENET1 reference clock mode select.
  187. * - ENET1_TX_CLK output driver is disabled when configured for ALT1.
  188. */
  189. static void cl_som_imx7_setup_fec(void)
  190. {
  191. struct iomuxc_gpr_base_regs *const iomuxc_gpr_regs
  192. = (struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR;
  193. /* Use 125M anatop REF_CLK1 for ENET1, clear gpr1[13], gpr1[17]*/
  194. clrsetbits_le32(&iomuxc_gpr_regs->gpr[1],
  195. (IOMUXC_GPR_GPR1_GPR_ENET1_TX_CLK_SEL_MASK |
  196. IOMUXC_GPR_GPR1_GPR_ENET1_CLK_DIR_MASK), 0);
  197. set_clk_enet(ENET_125MHZ);
  198. }
  199. #else /* !CONFIG_FEC_MXC */
  200. static void cl_som_imx7_setup_fec(void) {}
  201. #endif /* CONFIG_FEC_MXC */
  202. #ifdef CONFIG_SPI
  203. static void cl_som_imx7_spi_init(void)
  204. {
  205. cl_som_imx7_espi1_pads_set();
  206. }
  207. #else /* !CONFIG_SPI */
  208. static void cl_som_imx7_spi_init(void) {}
  209. #endif /* CONFIG_SPI */
  210. int board_early_init_f(void)
  211. {
  212. cl_som_imx7_uart1_pads_set();
  213. cl_som_imx7_usb_otg1_pads_set();
  214. return 0;
  215. }
  216. int board_init(void)
  217. {
  218. /* address of boot parameters */
  219. gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
  220. cl_som_imx7_setup_i2c();
  221. cl_som_imx7_setup_fec();
  222. cl_som_imx7_spi_init();
  223. return 0;
  224. }
  225. #ifdef CONFIG_POWER
  226. #define I2C_PMIC 0
  227. int power_init_board(void)
  228. {
  229. struct pmic *p;
  230. int ret;
  231. unsigned int reg, rev_id;
  232. ret = power_pfuze3000_init(I2C_PMIC);
  233. if (ret)
  234. return ret;
  235. p = pmic_get("PFUZE3000");
  236. ret = pmic_probe(p);
  237. if (ret)
  238. return ret;
  239. pmic_reg_read(p, PFUZE3000_DEVICEID, &reg);
  240. pmic_reg_read(p, PFUZE3000_REVID, &rev_id);
  241. printf("PMIC: PFUZE3000 DEV_ID=0x%x REV_ID=0x%x\n", reg, rev_id);
  242. /* disable Low Power Mode during standby mode */
  243. pmic_reg_write(p, PFUZE3000_LDOGCTL, 0x1);
  244. return 0;
  245. }
  246. #endif /* CONFIG_POWER */
  247. /*
  248. * cl_som_imx7_setup_wdog() - watchdog configuration.
  249. * - Output WDOG_B signal to reset external pmic.
  250. * - Suspend the watchdog timer during low-power modes.
  251. */
  252. void cl_som_imx7_setup_wdog(void)
  253. {
  254. struct wdog_regs *wdog = (struct wdog_regs *)WDOG1_BASE_ADDR;
  255. cl_som_imx7_wdog_pads_set();
  256. set_wdog_reset(wdog);
  257. /*
  258. * Do not assert internal WDOG_RESET_B_DEB(controlled by bit 4),
  259. * since we use PMIC_PWRON to reset the board.
  260. */
  261. clrsetbits_le16(&wdog->wcr, 0, 0x10);
  262. }
  263. int board_late_init(void)
  264. {
  265. env_set("board_name", "CL-SOM-iMX7");
  266. cl_som_imx7_setup_wdog();
  267. return 0;
  268. }
  269. int checkboard(void)
  270. {
  271. char *mode;
  272. if (IS_ENABLED(CONFIG_ARMV7_BOOT_SEC_DEFAULT))
  273. mode = "secure";
  274. else
  275. mode = "non-secure";
  276. printf("Board: CL-SOM-iMX7 in %s mode\n", mode);
  277. return 0;
  278. }