blob: 2d0f78da118f512a2f6296cb4ed240ae4f45d297 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Marek Vasut00671d92017-10-09 21:51:10 +02002/*
3 * DHCOM DH-iMX6 PDK board support
4 *
5 * Copyright (C) 2017 Marek Vasut <marex@denx.de>
Marek Vasut00671d92017-10-09 21:51:10 +02006 */
7
8#include <common.h>
Marek Vasut7937aba2019-05-17 16:58:51 +02009#include <dm.h>
10#include <dm/device-internal.h>
Marek Vasut00671d92017-10-09 21:51:10 +020011#include <asm/arch/clock.h>
12#include <asm/arch/crm_regs.h>
13#include <asm/arch/imx-regs.h>
14#include <asm/arch/iomux.h>
15#include <asm/arch/mx6-pins.h>
16#include <asm/arch/sys_proto.h>
17#include <asm/gpio.h>
18#include <asm/io.h>
19#include <asm/mach-imx/boot_mode.h>
20#include <asm/mach-imx/iomux-v3.h>
Marek Vasut00671d92017-10-09 21:51:10 +020021#include <asm/mach-imx/sata.h>
Marek Vasut6bd9bba2019-05-17 16:58:52 +020022#include <ahci.h>
23#include <dwc_ahsata.h>
Simon Glass5e6201b2019-08-01 09:46:51 -060024#include <env.h>
Marek Vasut00671d92017-10-09 21:51:10 +020025#include <errno.h>
Yangbo Lu73340382019-06-21 11:42:28 +080026#include <fsl_esdhc_imx.h>
Marek Vasut00671d92017-10-09 21:51:10 +020027#include <fuse.h>
Ludwig Zenz7217dae2019-07-08 15:04:58 +020028#include <i2c_eeprom.h>
Marek Vasut00671d92017-10-09 21:51:10 +020029#include <miiphy.h>
30#include <mmc.h>
31#include <net.h>
32#include <netdev.h>
33#include <usb.h>
34#include <usb/ehci-ci.h>
35
36DECLARE_GLOBAL_DATA_PTR;
37
Marek Vasut00671d92017-10-09 21:51:10 +020038int dram_init(void)
39{
40 gd->ram_size = imx_ddr_size();
41 return 0;
42}
43
44/*
45 * Do not overwrite the console
46 * Use always serial for U-Boot console
47 */
48int overwrite_console(void)
49{
50 return 1;
51}
52
53#ifdef CONFIG_FEC_MXC
54static void eth_phy_reset(void)
55{
56 /* Reset PHY */
57 gpio_direction_output(IMX_GPIO_NR(5, 0) , 0);
58 udelay(500);
59 gpio_set_value(IMX_GPIO_NR(5, 0), 1);
60
61 /* Enable VIO */
62 gpio_direction_output(IMX_GPIO_NR(1, 7) , 0);
63
64 /*
65 * KSZ9021 PHY needs at least 10 mSec after PHY reset
66 * is released to stabilize
67 */
68 mdelay(10);
69}
70
71static int setup_fec_clock(void)
72{
73 struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
74
75 /* set gpr1[21] to select anatop clock */
76 clrsetbits_le32(&iomuxc_regs->gpr[1], 0x1 << 21, 0x1 << 21);
77
78 return enable_fec_anatop_clock(0, ENET_50MHZ);
79}
80
81int board_eth_init(bd_t *bis)
82{
83 uint32_t base = IMX_FEC_BASE;
84 struct mii_dev *bus = NULL;
85 struct phy_device *phydev = NULL;
86
Marek Vasut7bc33632019-05-17 16:58:50 +020087 gpio_request(IMX_GPIO_NR(5, 0), "PHY-reset");
88 gpio_request(IMX_GPIO_NR(1, 7), "VIO");
89
Marek Vasut00671d92017-10-09 21:51:10 +020090 setup_fec_clock();
91
92 eth_phy_reset();
93
94 bus = fec_get_miibus(base, -1);
95 if (!bus)
96 return -EINVAL;
97
98 /* Scan PHY 0 */
99 phydev = phy_find_by_mask(bus, 0xf, PHY_INTERFACE_MODE_RGMII);
100 if (!phydev) {
101 printf("Ethernet PHY not found!\n");
102 return -EINVAL;
103 }
104
105 return fec_probe(bis, -1, base, bus, phydev);
106}
107#endif
108
Marek Vasut00671d92017-10-09 21:51:10 +0200109#ifdef CONFIG_USB_EHCI_MX6
110static void setup_usb(void)
111{
112 /*
113 * Set daisy chain for otg_pin_id on MX6Q.
114 * For MX6DL, this bit is reserved.
115 */
116 imx_iomux_set_gpr_register(1, 13, 1, 0);
117}
118
119int board_usb_phy_mode(int port)
120{
Marek Vasut00671d92017-10-09 21:51:10 +0200121 if (port == 1)
Marek Vasut861b6892017-10-22 10:22:40 +0200122 return USB_INIT_HOST;
Marek Vasut00671d92017-10-09 21:51:10 +0200123 else
Marek Vasut861b6892017-10-22 10:22:40 +0200124 return USB_INIT_DEVICE;
Marek Vasut00671d92017-10-09 21:51:10 +0200125}
Marek Vasut00671d92017-10-09 21:51:10 +0200126#endif
127
128static int setup_dhcom_mac_from_fuse(void)
129{
Ludwig Zenz7217dae2019-07-08 15:04:58 +0200130 struct udevice *dev;
131 ofnode eeprom;
Marek Vasut00671d92017-10-09 21:51:10 +0200132 unsigned char enetaddr[6];
133 int ret;
134
135 ret = eth_env_get_enetaddr("ethaddr", enetaddr);
136 if (ret) /* ethaddr is already set */
137 return 0;
138
139 imx_get_mac_from_fuse(0, enetaddr);
140
141 if (is_valid_ethaddr(enetaddr)) {
142 eth_env_set_enetaddr("ethaddr", enetaddr);
143 return 0;
144 }
145
Ludwig Zenz7217dae2019-07-08 15:04:58 +0200146 eeprom = ofnode_path("/soc/aips-bus@2100000/i2c@21a8000/eeprom@50");
147 if (!ofnode_valid(eeprom)) {
148 printf("Invalid hardware path to EEPROM!\n");
149 return -ENODEV;
150 }
151
152 ret = uclass_get_device_by_ofnode(UCLASS_I2C_EEPROM, eeprom, &dev);
Marek Vasut00671d92017-10-09 21:51:10 +0200153 if (ret) {
Ludwig Zenz7217dae2019-07-08 15:04:58 +0200154 printf("Cannot find EEPROM!\n");
Marek Vasut00671d92017-10-09 21:51:10 +0200155 return ret;
156 }
157
Ludwig Zenz7217dae2019-07-08 15:04:58 +0200158 ret = i2c_eeprom_read(dev, 0xfa, enetaddr, 0x6);
Marek Vasut00671d92017-10-09 21:51:10 +0200159 if (ret) {
160 printf("Error reading configuration EEPROM!\n");
161 return ret;
162 }
163
164 if (is_valid_ethaddr(enetaddr))
165 eth_env_set_enetaddr("ethaddr", enetaddr);
166
167 return 0;
168}
169
170int board_early_init_f(void)
171{
172#ifdef CONFIG_USB_EHCI_MX6
173 setup_usb();
174#endif
175
176 return 0;
177}
178
Marek Vasut00671d92017-10-09 21:51:10 +0200179int board_init(void)
180{
181 struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
182
183 /* address of boot parameters */
184 gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
185
186 /* Enable eim_slow clocks */
187 setbits_le32(&mxc_ccm->CCGR6, 0x1 << MXC_CCM_CCGR6_EMI_SLOW_OFFSET);
188
Marek Vasut00671d92017-10-09 21:51:10 +0200189 setup_dhcom_mac_from_fuse();
190
191 return 0;
192}
193
194#ifdef CONFIG_CMD_BMODE
195static const struct boot_mode board_boot_modes[] = {
196 /* 4 bit bus width */
197 {"sd2", MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)},
198 {"sd3", MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)},
199 /* 8 bit bus width */
200 {"emmc", MAKE_CFGVAL(0x40, 0x38, 0x00, 0x00)},
201 {NULL, 0},
202};
203#endif
204
205#define HW_CODE_BIT_0 IMX_GPIO_NR(2, 19)
206#define HW_CODE_BIT_1 IMX_GPIO_NR(6, 6)
207#define HW_CODE_BIT_2 IMX_GPIO_NR(2, 16)
208
209static int board_get_hwcode(void)
210{
211 int hw_code;
212
Marek Vasut7bc33632019-05-17 16:58:50 +0200213 gpio_request(HW_CODE_BIT_0, "HW-code-bit-0");
214 gpio_request(HW_CODE_BIT_1, "HW-code-bit-1");
215 gpio_request(HW_CODE_BIT_2, "HW-code-bit-2");
216
Marek Vasut00671d92017-10-09 21:51:10 +0200217 gpio_direction_input(HW_CODE_BIT_0);
218 gpio_direction_input(HW_CODE_BIT_1);
219 gpio_direction_input(HW_CODE_BIT_2);
220
221 /* HW 100 + HW 200 = 00b; HW 300 = 01b */
222 hw_code = ((gpio_get_value(HW_CODE_BIT_2) << 2) |
223 (gpio_get_value(HW_CODE_BIT_1) << 1) |
224 gpio_get_value(HW_CODE_BIT_0)) + 2;
225
226 return hw_code;
227}
228
229int board_late_init(void)
230{
231 u32 hw_code;
232 char buf[16];
233
234 hw_code = board_get_hwcode();
235
236 switch (get_cpu_type()) {
237 case MXC_CPU_MX6SOLO:
238 snprintf(buf, sizeof(buf), "imx6s-dhcom%1d", hw_code);
239 break;
240 case MXC_CPU_MX6DL:
241 snprintf(buf, sizeof(buf), "imx6dl-dhcom%1d", hw_code);
242 break;
243 case MXC_CPU_MX6D:
244 snprintf(buf, sizeof(buf), "imx6d-dhcom%1d", hw_code);
245 break;
246 case MXC_CPU_MX6Q:
247 snprintf(buf, sizeof(buf), "imx6q-dhcom%1d", hw_code);
248 break;
249 default:
250 snprintf(buf, sizeof(buf), "UNKNOWN%1d", hw_code);
251 break;
252 }
253
254 env_set("dhcom", buf);
255
256#ifdef CONFIG_CMD_BMODE
257 add_board_boot_modes(board_boot_modes);
258#endif
259 return 0;
260}
261
262int checkboard(void)
263{
264 puts("Board: DHCOM i.MX6\n");
265 return 0;
266}
Ludwig Zenz9ea1ba92019-07-02 14:49:49 +0200267
268#ifdef CONFIG_MULTI_DTB_FIT
269int board_fit_config_name_match(const char *name)
270{
271 if (is_mx6dq()) {
272 if (!strcmp(name, "imx6q-dhcom-pdk2"))
273 return 0;
274 } else if (is_mx6sdl()) {
275 if (!strcmp(name, "imx6dl-dhcom-pdk2"))
276 return 0;
277 }
278
279 return -1;
280}
281#endif