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