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