vining_2000.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  1. /*
  2. * Copyright (C) 2016 samtec automotive software & electronics gmbh
  3. *
  4. * Author: Christoph Fritz <chf.fritz@googlemail.com>
  5. *
  6. * SPDX-License-Identifier: GPL-2.0+
  7. */
  8. #include <asm/arch/clock.h>
  9. #include <asm/arch/crm_regs.h>
  10. #include <asm/arch/iomux.h>
  11. #include <asm/arch/imx-regs.h>
  12. #include <asm/arch/mx6-pins.h>
  13. #include <asm/arch/sys_proto.h>
  14. #include <asm/gpio.h>
  15. #include <asm/mach-imx/iomux-v3.h>
  16. #include <asm/io.h>
  17. #include <asm/mach-imx/mxc_i2c.h>
  18. #include <linux/sizes.h>
  19. #include <common.h>
  20. #include <fsl_esdhc.h>
  21. #include <mmc.h>
  22. #include <i2c.h>
  23. #include <miiphy.h>
  24. #include <netdev.h>
  25. #include <power/pmic.h>
  26. #include <power/pfuze100_pmic.h>
  27. #include <usb.h>
  28. #include <usb/ehci-ci.h>
  29. #include <pwm.h>
  30. #include <wait_bit.h>
  31. DECLARE_GLOBAL_DATA_PTR;
  32. #define UART_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PUS_100K_UP | \
  33. PAD_CTL_PKE | PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \
  34. PAD_CTL_SRE_FAST)
  35. #define ENET_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_PKE | \
  36. PAD_CTL_SPEED_HIGH | PAD_CTL_DSE_48ohm | \
  37. PAD_CTL_SRE_FAST)
  38. #define ENET_CLK_PAD_CTRL PAD_CTL_DSE_34ohm
  39. #define ENET_RX_PAD_CTRL (PAD_CTL_PKE | \
  40. PAD_CTL_PUS_100K_DOWN | PAD_CTL_SPEED_HIGH | \
  41. PAD_CTL_SRE_FAST)
  42. #define I2C_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PUS_100K_UP | \
  43. PAD_CTL_PKE | PAD_CTL_ODE | PAD_CTL_SPEED_MED | \
  44. PAD_CTL_DSE_40ohm)
  45. #define USDHC_CLK_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_SPEED_MED | \
  46. PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST)
  47. #define USDHC_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PUS_47K_UP | \
  48. PAD_CTL_PKE | PAD_CTL_SPEED_MED | PAD_CTL_DSE_80ohm | \
  49. PAD_CTL_SRE_FAST)
  50. #define GPIO_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PUS_100K_UP | \
  51. PAD_CTL_PKE)
  52. int dram_init(void)
  53. {
  54. gd->ram_size = imx_ddr_size();
  55. return 0;
  56. }
  57. static iomux_v3_cfg_t const uart1_pads[] = {
  58. MX6_PAD_GPIO1_IO04__UART1_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
  59. MX6_PAD_GPIO1_IO05__UART1_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
  60. };
  61. static iomux_v3_cfg_t const usdhc2_pads[] = {
  62. MX6_PAD_SD2_CLK__USDHC2_CLK | MUX_PAD_CTRL(USDHC_CLK_PAD_CTRL),
  63. MX6_PAD_SD2_CMD__USDHC2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  64. MX6_PAD_SD2_DATA0__USDHC2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  65. MX6_PAD_SD2_DATA1__USDHC2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  66. MX6_PAD_SD2_DATA2__USDHC2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  67. MX6_PAD_SD2_DATA3__USDHC2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  68. MX6_PAD_LCD1_VSYNC__GPIO3_IO_28 | MUX_PAD_CTRL(GPIO_PAD_CTRL),
  69. };
  70. static iomux_v3_cfg_t const usdhc4_pads[] = {
  71. MX6_PAD_SD4_CLK__USDHC4_CLK | MUX_PAD_CTRL(USDHC_CLK_PAD_CTRL),
  72. MX6_PAD_SD4_CMD__USDHC4_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  73. MX6_PAD_SD4_DATA0__USDHC4_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  74. MX6_PAD_SD4_DATA1__USDHC4_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  75. MX6_PAD_SD4_DATA2__USDHC4_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  76. MX6_PAD_SD4_DATA3__USDHC4_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  77. MX6_PAD_SD4_DATA4__USDHC4_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  78. MX6_PAD_SD4_DATA5__USDHC4_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  79. MX6_PAD_SD4_DATA6__USDHC4_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  80. MX6_PAD_SD4_DATA7__USDHC4_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  81. };
  82. static iomux_v3_cfg_t const fec1_pads[] = {
  83. MX6_PAD_ENET1_MDC__ENET1_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
  84. MX6_PAD_ENET1_MDIO__ENET1_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL),
  85. MX6_PAD_RGMII1_RD0__ENET1_RX_DATA_0 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
  86. MX6_PAD_RGMII1_RD1__ENET1_RX_DATA_1 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
  87. MX6_PAD_RGMII1_TD0__ENET1_TX_DATA_0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  88. MX6_PAD_RGMII1_TD1__ENET1_TX_DATA_1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  89. MX6_PAD_RGMII1_RX_CTL__ENET1_RX_EN | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
  90. MX6_PAD_RGMII1_TX_CTL__ENET1_TX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
  91. MX6_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 | MUX_PAD_CTRL(ENET_CLK_PAD_CTRL) |
  92. MUX_MODE_SION,
  93. /* LAN8720 PHY Reset */
  94. MX6_PAD_RGMII1_TD3__GPIO5_IO_9 | MUX_PAD_CTRL(NO_PAD_CTRL),
  95. };
  96. static iomux_v3_cfg_t const pwm_led_pads[] = {
  97. MX6_PAD_RGMII2_RD2__PWM2_OUT | MUX_PAD_CTRL(NO_PAD_CTRL), /* green */
  98. MX6_PAD_RGMII2_TD2__PWM6_OUT | MUX_PAD_CTRL(NO_PAD_CTRL), /* red */
  99. MX6_PAD_RGMII2_RD3__PWM1_OUT | MUX_PAD_CTRL(NO_PAD_CTRL), /* blue */
  100. };
  101. static void setup_iomux_uart(void)
  102. {
  103. imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
  104. }
  105. #define PHY_RESET IMX_GPIO_NR(5, 9)
  106. int board_eth_init(bd_t *bis)
  107. {
  108. struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
  109. int ret;
  110. unsigned char eth1addr[6];
  111. /* just to get secound mac address */
  112. imx_get_mac_from_fuse(1, eth1addr);
  113. if (!getenv("eth1addr") && is_valid_ethaddr(eth1addr))
  114. eth_env_set_enetaddr("eth1addr", eth1addr);
  115. imx_iomux_v3_setup_multiple_pads(fec1_pads, ARRAY_SIZE(fec1_pads));
  116. /*
  117. * Generate phy reference clock via pin IOMUX ENET_REF_CLK1/2 by erasing
  118. * ENET1/2_TX_CLK_DIR gpr1[14:13], so that reference clock is driven by
  119. * ref_enetpll0/1 and enable ENET1/2_TX_CLK output driver.
  120. */
  121. clrsetbits_le32(&iomuxc_regs->gpr[1],
  122. IOMUX_GPR1_FEC1_CLOCK_MUX2_SEL_MASK |
  123. IOMUX_GPR1_FEC2_CLOCK_MUX2_SEL_MASK,
  124. IOMUX_GPR1_FEC1_CLOCK_MUX1_SEL_MASK |
  125. IOMUX_GPR1_FEC2_CLOCK_MUX1_SEL_MASK);
  126. ret = enable_fec_anatop_clock(0, ENET_50MHZ);
  127. if (ret)
  128. goto eth_fail;
  129. /* reset phy */
  130. gpio_direction_output(PHY_RESET, 0);
  131. mdelay(16);
  132. gpio_set_value(PHY_RESET, 1);
  133. mdelay(1);
  134. ret = fecmxc_initialize_multi(bis, 0, CONFIG_FEC_MXC_PHYADDR,
  135. IMX_FEC_BASE);
  136. if (ret)
  137. goto eth_fail;
  138. return ret;
  139. eth_fail:
  140. printf("FEC MXC: %s:failed (%i)\n", __func__, ret);
  141. gpio_set_value(PHY_RESET, 0);
  142. return ret;
  143. }
  144. #define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
  145. /* I2C1 for PMIC */
  146. static struct i2c_pads_info i2c_pad_info1 = {
  147. .scl = {
  148. .i2c_mode = MX6_PAD_GPIO1_IO00__I2C1_SCL | PC,
  149. .gpio_mode = MX6_PAD_GPIO1_IO00__GPIO1_IO_0 | PC,
  150. .gp = IMX_GPIO_NR(1, 0),
  151. },
  152. .sda = {
  153. .i2c_mode = MX6_PAD_GPIO1_IO01__I2C1_SDA | PC,
  154. .gpio_mode = MX6_PAD_GPIO1_IO01__GPIO1_IO_1 | PC,
  155. .gp = IMX_GPIO_NR(1, 1),
  156. },
  157. };
  158. static struct pmic *pfuze_init(unsigned char i2cbus)
  159. {
  160. struct pmic *p;
  161. int ret;
  162. u32 reg;
  163. ret = power_pfuze100_init(i2cbus);
  164. if (ret)
  165. return NULL;
  166. p = pmic_get("PFUZE100");
  167. ret = pmic_probe(p);
  168. if (ret)
  169. return NULL;
  170. pmic_reg_read(p, PFUZE100_DEVICEID, &reg);
  171. printf("PMIC: PFUZE100 ID=0x%02x\n", reg);
  172. /* Set SW1AB stanby volage to 0.975V */
  173. pmic_reg_read(p, PFUZE100_SW1ABSTBY, &reg);
  174. reg &= ~SW1x_STBY_MASK;
  175. reg |= SW1x_0_975V;
  176. pmic_reg_write(p, PFUZE100_SW1ABSTBY, reg);
  177. /* Set SW1AB/VDDARM step ramp up time from 16us to 4us/25mV */
  178. pmic_reg_read(p, PFUZE100_SW1ABCONF, &reg);
  179. reg &= ~SW1xCONF_DVSSPEED_MASK;
  180. reg |= SW1xCONF_DVSSPEED_4US;
  181. pmic_reg_write(p, PFUZE100_SW1ABCONF, reg);
  182. /* Set SW1C standby voltage to 0.975V */
  183. pmic_reg_read(p, PFUZE100_SW1CSTBY, &reg);
  184. reg &= ~SW1x_STBY_MASK;
  185. reg |= SW1x_0_975V;
  186. pmic_reg_write(p, PFUZE100_SW1CSTBY, reg);
  187. /* Set SW1C/VDDSOC step ramp up time from 16us to 4us/25mV */
  188. pmic_reg_read(p, PFUZE100_SW1CCONF, &reg);
  189. reg &= ~SW1xCONF_DVSSPEED_MASK;
  190. reg |= SW1xCONF_DVSSPEED_4US;
  191. pmic_reg_write(p, PFUZE100_SW1CCONF, reg);
  192. return p;
  193. }
  194. static int pfuze_mode_init(struct pmic *p, u32 mode)
  195. {
  196. unsigned char offset, i, switch_num;
  197. u32 id;
  198. int ret;
  199. pmic_reg_read(p, PFUZE100_DEVICEID, &id);
  200. id = id & 0xf;
  201. if (id == 0) {
  202. switch_num = 6;
  203. offset = PFUZE100_SW1CMODE;
  204. } else if (id == 1) {
  205. switch_num = 4;
  206. offset = PFUZE100_SW2MODE;
  207. } else {
  208. printf("Not supported, id=%d\n", id);
  209. return -EINVAL;
  210. }
  211. ret = pmic_reg_write(p, PFUZE100_SW1ABMODE, mode);
  212. if (ret < 0) {
  213. printf("Set SW1AB mode error!\n");
  214. return ret;
  215. }
  216. for (i = 0; i < switch_num - 1; i++) {
  217. ret = pmic_reg_write(p, offset + i * SWITCH_SIZE, mode);
  218. if (ret < 0) {
  219. printf("Set switch 0x%x mode error!\n",
  220. offset + i * SWITCH_SIZE);
  221. return ret;
  222. }
  223. }
  224. return ret;
  225. }
  226. int power_init_board(void)
  227. {
  228. struct pmic *p;
  229. int ret;
  230. p = pfuze_init(I2C_PMIC);
  231. if (!p)
  232. return -ENODEV;
  233. ret = pfuze_mode_init(p, APS_PFM);
  234. if (ret < 0)
  235. return ret;
  236. return 0;
  237. }
  238. #ifdef CONFIG_USB_EHCI_MX6
  239. static iomux_v3_cfg_t const usb_otg_pads[] = {
  240. /* OGT1 */
  241. MX6_PAD_GPIO1_IO09__USB_OTG1_PWR | MUX_PAD_CTRL(NO_PAD_CTRL),
  242. MX6_PAD_GPIO1_IO10__ANATOP_OTG1_ID | MUX_PAD_CTRL(NO_PAD_CTRL),
  243. /* OTG2 */
  244. MX6_PAD_GPIO1_IO12__USB_OTG2_PWR | MUX_PAD_CTRL(NO_PAD_CTRL)
  245. };
  246. static void setup_iomux_usb(void)
  247. {
  248. imx_iomux_v3_setup_multiple_pads(usb_otg_pads,
  249. ARRAY_SIZE(usb_otg_pads));
  250. }
  251. int board_usb_phy_mode(int port)
  252. {
  253. if (port == 1)
  254. return USB_INIT_HOST;
  255. else
  256. return usb_phy_mode(port);
  257. }
  258. #endif
  259. #ifdef CONFIG_PWM_IMX
  260. static int set_pwm_leds(void)
  261. {
  262. int ret;
  263. imx_iomux_v3_setup_multiple_pads(pwm_led_pads,
  264. ARRAY_SIZE(pwm_led_pads));
  265. /* enable backlight PWM 2, green LED */
  266. ret = pwm_init(1, 0, 0);
  267. if (ret)
  268. goto error;
  269. /* duty cycle 200ns, period: 8000ns */
  270. ret = pwm_config(1, 200, 8000);
  271. if (ret)
  272. goto error;
  273. ret = pwm_enable(1);
  274. if (ret)
  275. goto error;
  276. /* enable backlight PWM 1, blue LED */
  277. ret = pwm_init(0, 0, 0);
  278. if (ret)
  279. goto error;
  280. /* duty cycle 200ns, period: 8000ns */
  281. ret = pwm_config(0, 200, 8000);
  282. if (ret)
  283. goto error;
  284. ret = pwm_enable(0);
  285. if (ret)
  286. goto error;
  287. /* enable backlight PWM 6, red LED */
  288. ret = pwm_init(5, 0, 0);
  289. if (ret)
  290. goto error;
  291. /* duty cycle 200ns, period: 8000ns */
  292. ret = pwm_config(5, 200, 8000);
  293. if (ret)
  294. goto error;
  295. ret = pwm_enable(5);
  296. error:
  297. return ret;
  298. }
  299. #else
  300. static int set_pwm_leds(void)
  301. {
  302. return 0;
  303. }
  304. #endif
  305. #define ADCx_HC0 0x00
  306. #define ADCx_HS 0x08
  307. #define ADCx_HS_C0 BIT(0)
  308. #define ADCx_R0 0x0c
  309. #define ADCx_CFG 0x14
  310. #define ADCx_CFG_SWMODE 0x308
  311. #define ADCx_GC 0x18
  312. #define ADCx_GC_CAL BIT(7)
  313. static int read_adc(u32 *val)
  314. {
  315. int ret;
  316. void __iomem *b = map_physmem(ADC1_BASE_ADDR, 0x100, MAP_NOCACHE);
  317. /* use software mode */
  318. writel(ADCx_CFG_SWMODE, b + ADCx_CFG);
  319. /* start auto calibration */
  320. setbits_le32(b + ADCx_GC, ADCx_GC_CAL);
  321. ret = wait_for_bit("ADC", b + ADCx_GC, ADCx_GC_CAL, ADCx_GC_CAL, 10, 0);
  322. if (ret)
  323. goto adc_exit;
  324. /* start conversion */
  325. writel(0, b + ADCx_HC0);
  326. /* wait for conversion */
  327. ret = wait_for_bit("ADC", b + ADCx_HS, ADCx_HS_C0, ADCx_HS_C0, 10, 0);
  328. if (ret)
  329. goto adc_exit;
  330. /* read result */
  331. *val = readl(b + ADCx_R0);
  332. adc_exit:
  333. if (ret)
  334. printf("ADC failure (ret=%i)\n", ret);
  335. unmap_physmem(b, MAP_NOCACHE);
  336. return ret;
  337. }
  338. #define VAL_UPPER 2498
  339. #define VAL_LOWER 1550
  340. static int set_pin_state(void)
  341. {
  342. u32 val;
  343. int ret;
  344. ret = read_adc(&val);
  345. if (ret)
  346. return ret;
  347. if (val >= VAL_UPPER)
  348. env_set("pin_state", "connected");
  349. else if (val < VAL_UPPER && val > VAL_LOWER)
  350. env_set("pin_state", "open");
  351. else
  352. env_set("pin_state", "button");
  353. return ret;
  354. }
  355. int board_late_init(void)
  356. {
  357. int ret;
  358. ret = set_pwm_leds();
  359. if (ret)
  360. return ret;
  361. ret = set_pin_state();
  362. return ret;
  363. }
  364. int board_early_init_f(void)
  365. {
  366. setup_iomux_uart();
  367. setup_iomux_usb();
  368. return 0;
  369. }
  370. static struct fsl_esdhc_cfg usdhc_cfg[2] = {
  371. {USDHC4_BASE_ADDR, 0, 8},
  372. {USDHC2_BASE_ADDR, 0, 4},
  373. };
  374. #define USDHC2_CD_GPIO IMX_GPIO_NR(3, 28)
  375. int board_mmc_getcd(struct mmc *mmc)
  376. {
  377. struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
  378. if (cfg->esdhc_base == USDHC4_BASE_ADDR)
  379. return 1;
  380. if (cfg->esdhc_base == USDHC2_BASE_ADDR)
  381. return !gpio_get_value(USDHC2_CD_GPIO);
  382. return -EINVAL;
  383. }
  384. int board_mmc_init(bd_t *bis)
  385. {
  386. int ret;
  387. /*
  388. * According to the board_mmc_init() the following map is done:
  389. * (U-Boot device node) (Physical Port)
  390. * mmc0 USDHC4
  391. * mmc1 USDHC2
  392. */
  393. imx_iomux_v3_setup_multiple_pads(
  394. usdhc4_pads, ARRAY_SIZE(usdhc4_pads));
  395. usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
  396. imx_iomux_v3_setup_multiple_pads(
  397. usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
  398. gpio_direction_input(USDHC2_CD_GPIO);
  399. usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
  400. ret = fsl_esdhc_initialize(bis, &usdhc_cfg[0]);
  401. if (ret) {
  402. printf("Warning: failed to initialize USDHC4\n");
  403. return ret;
  404. }
  405. ret = fsl_esdhc_initialize(bis, &usdhc_cfg[1]);
  406. if (ret) {
  407. printf("Warning: failed to initialize USDHC2\n");
  408. return ret;
  409. }
  410. return 0;
  411. }
  412. int board_init(void)
  413. {
  414. /* Address of boot parameters */
  415. gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
  416. #ifdef CONFIG_SYS_I2C_MXC
  417. setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
  418. #endif
  419. return 0;
  420. }
  421. int checkboard(void)
  422. {
  423. puts("Board: VIN|ING 2000\n");
  424. return 0;
  425. }