vining_2000.c 12 KB

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