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