vining_2000.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2016 samtec automotive software & electronics gmbh
  4. * Copyright (C) 2017-2019 softing automotive electronics gmbH
  5. *
  6. * Author: Christoph Fritz <chf.fritz@googlemail.com>
  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 <env.h>
  19. #include <linux/sizes.h>
  20. #include <common.h>
  21. #include <fsl_esdhc_imx.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 USDHC_RESET_CTRL (PAD_CTL_HYS | PAD_CTL_PUS_47K_UP | \
  52. PAD_CTL_PKE | PAD_CTL_SPEED_MED | PAD_CTL_DSE_80ohm)
  53. #define GPIO_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PUS_100K_UP | \
  54. PAD_CTL_PKE)
  55. int dram_init(void)
  56. {
  57. gd->ram_size = imx_ddr_size();
  58. return 0;
  59. }
  60. static iomux_v3_cfg_t const fec1_pads[] = {
  61. MX6_PAD_ENET1_MDC__ENET1_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
  62. MX6_PAD_ENET1_MDIO__ENET1_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL),
  63. MX6_PAD_RGMII1_RD0__ENET1_RX_DATA_0 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
  64. MX6_PAD_RGMII1_RD1__ENET1_RX_DATA_1 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
  65. MX6_PAD_RGMII1_TD0__ENET1_TX_DATA_0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  66. MX6_PAD_RGMII1_TD1__ENET1_TX_DATA_1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  67. MX6_PAD_RGMII1_RX_CTL__ENET1_RX_EN | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
  68. MX6_PAD_RGMII1_TX_CTL__ENET1_TX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
  69. MX6_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 | MUX_PAD_CTRL(ENET_CLK_PAD_CTRL) |
  70. MUX_MODE_SION,
  71. /* LAN8720 PHY Reset */
  72. MX6_PAD_RGMII1_TD3__GPIO5_IO_9 | MUX_PAD_CTRL(NO_PAD_CTRL),
  73. };
  74. static iomux_v3_cfg_t const pwm_led_pads[] = {
  75. MX6_PAD_RGMII2_RD2__PWM2_OUT | MUX_PAD_CTRL(NO_PAD_CTRL), /* green */
  76. MX6_PAD_RGMII2_TD2__PWM6_OUT | MUX_PAD_CTRL(NO_PAD_CTRL), /* red */
  77. MX6_PAD_RGMII2_RD3__PWM1_OUT | MUX_PAD_CTRL(NO_PAD_CTRL), /* blue */
  78. };
  79. #define PHY_RESET IMX_GPIO_NR(5, 9)
  80. int board_eth_init(bd_t *bis)
  81. {
  82. struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
  83. int ret;
  84. unsigned char eth1addr[6];
  85. /* just to get secound mac address */
  86. imx_get_mac_from_fuse(1, eth1addr);
  87. if (!env_get("eth1addr") && is_valid_ethaddr(eth1addr))
  88. eth_env_set_enetaddr("eth1addr", eth1addr);
  89. imx_iomux_v3_setup_multiple_pads(fec1_pads, ARRAY_SIZE(fec1_pads));
  90. /*
  91. * Generate phy reference clock via pin IOMUX ENET_REF_CLK1/2 by erasing
  92. * ENET1/2_TX_CLK_DIR gpr1[14:13], so that reference clock is driven by
  93. * ref_enetpll0/1 and enable ENET1/2_TX_CLK output driver.
  94. */
  95. clrsetbits_le32(&iomuxc_regs->gpr[1],
  96. IOMUX_GPR1_FEC1_CLOCK_MUX2_SEL_MASK |
  97. IOMUX_GPR1_FEC2_CLOCK_MUX2_SEL_MASK,
  98. IOMUX_GPR1_FEC1_CLOCK_MUX1_SEL_MASK |
  99. IOMUX_GPR1_FEC2_CLOCK_MUX1_SEL_MASK);
  100. ret = enable_fec_anatop_clock(0, ENET_50MHZ);
  101. if (ret)
  102. goto eth_fail;
  103. /* reset phy */
  104. gpio_request(PHY_RESET, "PHY-reset");
  105. gpio_direction_output(PHY_RESET, 0);
  106. mdelay(16);
  107. gpio_set_value(PHY_RESET, 1);
  108. mdelay(1);
  109. ret = fecmxc_initialize_multi(bis, 0, CONFIG_FEC_MXC_PHYADDR,
  110. IMX_FEC_BASE);
  111. if (ret)
  112. goto eth_fail;
  113. return ret;
  114. eth_fail:
  115. printf("FEC MXC: %s:failed (%i)\n", __func__, ret);
  116. gpio_set_value(PHY_RESET, 0);
  117. return ret;
  118. }
  119. #define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
  120. /* I2C1 for PMIC */
  121. static struct i2c_pads_info i2c_pad_info1 = {
  122. .scl = {
  123. .i2c_mode = MX6_PAD_GPIO1_IO00__I2C1_SCL | PC,
  124. .gpio_mode = MX6_PAD_GPIO1_IO00__GPIO1_IO_0 | PC,
  125. .gp = IMX_GPIO_NR(1, 0),
  126. },
  127. .sda = {
  128. .i2c_mode = MX6_PAD_GPIO1_IO01__I2C1_SDA | PC,
  129. .gpio_mode = MX6_PAD_GPIO1_IO01__GPIO1_IO_1 | PC,
  130. .gp = IMX_GPIO_NR(1, 1),
  131. },
  132. };
  133. static struct pmic *pfuze_init(unsigned char i2cbus)
  134. {
  135. struct pmic *p;
  136. int ret;
  137. u32 reg;
  138. ret = power_pfuze100_init(i2cbus);
  139. if (ret)
  140. return NULL;
  141. p = pmic_get("PFUZE100");
  142. ret = pmic_probe(p);
  143. if (ret)
  144. return NULL;
  145. pmic_reg_read(p, PFUZE100_DEVICEID, &reg);
  146. printf("PMIC: PFUZE100 ID=0x%02x\n", reg);
  147. /* Set SW1AB stanby volage to 0.975V */
  148. pmic_reg_read(p, PFUZE100_SW1ABSTBY, &reg);
  149. reg &= ~SW1x_STBY_MASK;
  150. reg |= SW1x_0_975V;
  151. pmic_reg_write(p, PFUZE100_SW1ABSTBY, reg);
  152. /* Set SW1AB/VDDARM step ramp up time from 16us to 4us/25mV */
  153. pmic_reg_read(p, PFUZE100_SW1ABCONF, &reg);
  154. reg &= ~SW1xCONF_DVSSPEED_MASK;
  155. reg |= SW1xCONF_DVSSPEED_4US;
  156. pmic_reg_write(p, PFUZE100_SW1ABCONF, reg);
  157. /* Set SW1C standby voltage to 0.975V */
  158. pmic_reg_read(p, PFUZE100_SW1CSTBY, &reg);
  159. reg &= ~SW1x_STBY_MASK;
  160. reg |= SW1x_0_975V;
  161. pmic_reg_write(p, PFUZE100_SW1CSTBY, reg);
  162. /* Set SW1C/VDDSOC step ramp up time from 16us to 4us/25mV */
  163. pmic_reg_read(p, PFUZE100_SW1CCONF, &reg);
  164. reg &= ~SW1xCONF_DVSSPEED_MASK;
  165. reg |= SW1xCONF_DVSSPEED_4US;
  166. pmic_reg_write(p, PFUZE100_SW1CCONF, reg);
  167. return p;
  168. }
  169. static int pfuze_mode_init(struct pmic *p, u32 mode)
  170. {
  171. unsigned char offset, i, switch_num;
  172. u32 id;
  173. int ret;
  174. pmic_reg_read(p, PFUZE100_DEVICEID, &id);
  175. id = id & 0xf;
  176. if (id == 0) {
  177. switch_num = 6;
  178. offset = PFUZE100_SW1CMODE;
  179. } else if (id == 1) {
  180. switch_num = 4;
  181. offset = PFUZE100_SW2MODE;
  182. } else {
  183. printf("Not supported, id=%d\n", id);
  184. return -EINVAL;
  185. }
  186. ret = pmic_reg_write(p, PFUZE100_SW1ABMODE, mode);
  187. if (ret < 0) {
  188. printf("Set SW1AB mode error!\n");
  189. return ret;
  190. }
  191. for (i = 0; i < switch_num - 1; i++) {
  192. ret = pmic_reg_write(p, offset + i * SWITCH_SIZE, mode);
  193. if (ret < 0) {
  194. printf("Set switch 0x%x mode error!\n",
  195. offset + i * SWITCH_SIZE);
  196. return ret;
  197. }
  198. }
  199. return ret;
  200. }
  201. int power_init_board(void)
  202. {
  203. struct pmic *p;
  204. int ret;
  205. p = pfuze_init(I2C_PMIC);
  206. if (!p)
  207. return -ENODEV;
  208. ret = pfuze_mode_init(p, APS_PFM);
  209. if (ret < 0)
  210. return ret;
  211. return 0;
  212. }
  213. #ifdef CONFIG_USB_EHCI_MX6
  214. static iomux_v3_cfg_t const usb_otg_pads[] = {
  215. /* OGT1 */
  216. MX6_PAD_GPIO1_IO09__USB_OTG1_PWR | MUX_PAD_CTRL(NO_PAD_CTRL),
  217. MX6_PAD_GPIO1_IO10__ANATOP_OTG1_ID | MUX_PAD_CTRL(NO_PAD_CTRL),
  218. /* OTG2 */
  219. MX6_PAD_GPIO1_IO12__USB_OTG2_PWR | MUX_PAD_CTRL(NO_PAD_CTRL)
  220. };
  221. static void setup_iomux_usb(void)
  222. {
  223. imx_iomux_v3_setup_multiple_pads(usb_otg_pads,
  224. ARRAY_SIZE(usb_otg_pads));
  225. }
  226. int board_usb_phy_mode(int port)
  227. {
  228. if (port == 1)
  229. return USB_INIT_HOST;
  230. else
  231. return usb_phy_mode(port);
  232. }
  233. #endif
  234. #ifdef CONFIG_PWM_IMX
  235. static int set_pwm_leds(void)
  236. {
  237. int ret;
  238. imx_iomux_v3_setup_multiple_pads(pwm_led_pads,
  239. ARRAY_SIZE(pwm_led_pads));
  240. /* enable backlight PWM 2, green LED */
  241. ret = pwm_init(1, 0, 0);
  242. if (ret)
  243. goto error;
  244. /* duty cycle 200ns, period: 8000ns */
  245. ret = pwm_config(1, 200, 8000);
  246. if (ret)
  247. goto error;
  248. ret = pwm_enable(1);
  249. if (ret)
  250. goto error;
  251. /* enable backlight PWM 1, blue LED */
  252. ret = pwm_init(0, 0, 0);
  253. if (ret)
  254. goto error;
  255. /* duty cycle 200ns, period: 8000ns */
  256. ret = pwm_config(0, 200, 8000);
  257. if (ret)
  258. goto error;
  259. ret = pwm_enable(0);
  260. if (ret)
  261. goto error;
  262. /* enable backlight PWM 6, red LED */
  263. ret = pwm_init(5, 0, 0);
  264. if (ret)
  265. goto error;
  266. /* duty cycle 200ns, period: 8000ns */
  267. ret = pwm_config(5, 200, 8000);
  268. if (ret)
  269. goto error;
  270. ret = pwm_enable(5);
  271. error:
  272. return ret;
  273. }
  274. #else
  275. static int set_pwm_leds(void)
  276. {
  277. return 0;
  278. }
  279. #endif
  280. #define ADCx_HC0 0x00
  281. #define ADCx_HS 0x08
  282. #define ADCx_HS_C0 BIT(0)
  283. #define ADCx_R0 0x0c
  284. #define ADCx_CFG 0x14
  285. #define ADCx_CFG_SWMODE 0x308
  286. #define ADCx_GC 0x18
  287. #define ADCx_GC_CAL BIT(7)
  288. static int read_adc(u32 *val)
  289. {
  290. int ret;
  291. void __iomem *b = map_physmem(ADC1_BASE_ADDR, 0x100, MAP_NOCACHE);
  292. /* use software mode */
  293. writel(ADCx_CFG_SWMODE, b + ADCx_CFG);
  294. /* start auto calibration */
  295. setbits_le32(b + ADCx_GC, ADCx_GC_CAL);
  296. ret = wait_for_bit_le32(b + ADCx_GC, ADCx_GC_CAL, ADCx_GC_CAL, 10, 0);
  297. if (ret)
  298. goto adc_exit;
  299. /* start conversion */
  300. writel(0, b + ADCx_HC0);
  301. /* wait for conversion */
  302. ret = wait_for_bit_le32(b + ADCx_HS, ADCx_HS_C0, ADCx_HS_C0, 10, 0);
  303. if (ret)
  304. goto adc_exit;
  305. /* read result */
  306. *val = readl(b + ADCx_R0);
  307. adc_exit:
  308. if (ret)
  309. printf("ADC failure (ret=%i)\n", ret);
  310. unmap_physmem(b, MAP_NOCACHE);
  311. return ret;
  312. }
  313. #define VAL_UPPER 2498
  314. #define VAL_LOWER 1550
  315. static int set_pin_state(void)
  316. {
  317. u32 val;
  318. int ret;
  319. ret = read_adc(&val);
  320. if (ret)
  321. return ret;
  322. if (val >= VAL_UPPER)
  323. env_set("pin_state", "connected");
  324. else if (val < VAL_UPPER && val > VAL_LOWER)
  325. env_set("pin_state", "open");
  326. else
  327. env_set("pin_state", "button");
  328. return ret;
  329. }
  330. int board_late_init(void)
  331. {
  332. int ret;
  333. ret = set_pwm_leds();
  334. if (ret)
  335. return ret;
  336. ret = set_pin_state();
  337. return ret;
  338. }
  339. int board_early_init_f(void)
  340. {
  341. setup_iomux_usb();
  342. return 0;
  343. }
  344. int board_init(void)
  345. {
  346. /* Address of boot parameters */
  347. gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
  348. #ifdef CONFIG_SYS_I2C_MXC
  349. setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
  350. #endif
  351. return 0;
  352. }
  353. int checkboard(void)
  354. {
  355. puts("Board: VIN|ING 2000\n");
  356. return 0;
  357. }