Merge tag 'efi-2020-07-rc6' of https://gitlab.denx.de/u-boot/custodians/u-boot-efi
[oweals/u-boot.git] / board / dhelectronics / dh_imx6 / dh_imx6.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * DHCOM DH-iMX6 PDK board support
4  *
5  * Copyright (C) 2017 Marek Vasut <marex@denx.de>
6  */
7
8 #include <common.h>
9 #include <dm.h>
10 #include <eeprom.h>
11 #include <image.h>
12 #include <init.h>
13 #include <net.h>
14 #include <dm/device-internal.h>
15 #include <asm/arch/clock.h>
16 #include <asm/arch/crm_regs.h>
17 #include <asm/arch/imx-regs.h>
18 #include <asm/arch/iomux.h>
19 #include <asm/arch/mx6-pins.h>
20 #include <asm/arch/sys_proto.h>
21 #include <asm/gpio.h>
22 #include <asm/io.h>
23 #include <asm/mach-imx/boot_mode.h>
24 #include <asm/mach-imx/iomux-v3.h>
25 #include <asm/mach-imx/sata.h>
26 #include <ahci.h>
27 #include <dwc_ahsata.h>
28 #include <env.h>
29 #include <errno.h>
30 #include <fsl_esdhc_imx.h>
31 #include <fuse.h>
32 #include <i2c_eeprom.h>
33 #include <mmc.h>
34 #include <usb.h>
35 #include <linux/delay.h>
36 #include <usb/ehci-ci.h>
37
38 DECLARE_GLOBAL_DATA_PTR;
39
40 int dram_init(void)
41 {
42         gd->ram_size = imx_ddr_size();
43         return 0;
44 }
45
46 /*
47  * Do not overwrite the console
48  * Use always serial for U-Boot console
49  */
50 int overwrite_console(void)
51 {
52         return 1;
53 }
54
55 static int setup_fec_clock(void)
56 {
57         struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
58
59         /* set gpr1[21] to select anatop clock */
60         clrsetbits_le32(&iomuxc_regs->gpr[1], 0x1 << 21, 0x1 << 21);
61
62         return enable_fec_anatop_clock(0, ENET_50MHZ);
63 }
64
65 #ifdef CONFIG_USB_EHCI_MX6
66 static void setup_usb(void)
67 {
68         /*
69          * Set daisy chain for otg_pin_id on MX6Q.
70          * For MX6DL, this bit is reserved.
71          */
72         imx_iomux_set_gpr_register(1, 13, 1, 0);
73 }
74
75 int board_usb_phy_mode(int port)
76 {
77         if (port == 1)
78                 return USB_INIT_HOST;
79         else
80                 return USB_INIT_DEVICE;
81 }
82 #endif
83
84 static int setup_dhcom_mac_from_fuse(void)
85 {
86         struct udevice *dev;
87         ofnode eeprom;
88         unsigned char enetaddr[6];
89         int ret;
90
91         ret = eth_env_get_enetaddr("ethaddr", enetaddr);
92         if (ret)        /* ethaddr is already set */
93                 return 0;
94
95         imx_get_mac_from_fuse(0, enetaddr);
96
97         if (is_valid_ethaddr(enetaddr)) {
98                 eth_env_set_enetaddr("ethaddr", enetaddr);
99                 return 0;
100         }
101
102         eeprom = ofnode_path("/soc/aips-bus@2100000/i2c@21a8000/eeprom@50");
103         if (!ofnode_valid(eeprom)) {
104                 printf("Invalid hardware path to EEPROM!\n");
105                 return -ENODEV;
106         }
107
108         ret = uclass_get_device_by_ofnode(UCLASS_I2C_EEPROM, eeprom, &dev);
109         if (ret) {
110                 printf("Cannot find EEPROM!\n");
111                 return ret;
112         }
113
114         ret = i2c_eeprom_read(dev, 0xfa, enetaddr, 0x6);
115         if (ret) {
116                 printf("Error reading configuration EEPROM!\n");
117                 return ret;
118         }
119
120         if (is_valid_ethaddr(enetaddr))
121                 eth_env_set_enetaddr("ethaddr", enetaddr);
122
123         return 0;
124 }
125
126 int board_early_init_f(void)
127 {
128 #ifdef CONFIG_USB_EHCI_MX6
129         setup_usb();
130 #endif
131
132         return 0;
133 }
134
135 int board_init(void)
136 {
137         struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
138
139         /* address of boot parameters */
140         gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
141
142         /* Enable eim_slow clocks */
143         setbits_le32(&mxc_ccm->CCGR6, 0x1 << MXC_CCM_CCGR6_EMI_SLOW_OFFSET);
144
145         setup_fec_clock();
146
147         return 0;
148 }
149
150 #ifdef CONFIG_CMD_BMODE
151 static const struct boot_mode board_boot_modes[] = {
152         /* 4 bit bus width */
153         {"sd2",  MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)},
154         {"sd3",  MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)},
155         /* 8 bit bus width */
156         {"emmc", MAKE_CFGVAL(0x60, 0x58, 0x00, 0x00)},
157         {NULL,   0},
158 };
159 #endif
160
161 #define HW_CODE_BIT_0   IMX_GPIO_NR(2, 19)
162 #define HW_CODE_BIT_1   IMX_GPIO_NR(6, 6)
163 #define HW_CODE_BIT_2   IMX_GPIO_NR(2, 16)
164
165 static int board_get_hwcode(void)
166 {
167         int hw_code;
168
169         gpio_request(HW_CODE_BIT_0, "HW-code-bit-0");
170         gpio_request(HW_CODE_BIT_1, "HW-code-bit-1");
171         gpio_request(HW_CODE_BIT_2, "HW-code-bit-2");
172
173         gpio_direction_input(HW_CODE_BIT_0);
174         gpio_direction_input(HW_CODE_BIT_1);
175         gpio_direction_input(HW_CODE_BIT_2);
176
177         /* HW 100 + HW 200 = 00b; HW 300 = 01b */
178         hw_code = ((gpio_get_value(HW_CODE_BIT_2) << 2) |
179                    (gpio_get_value(HW_CODE_BIT_1) << 1) |
180                     gpio_get_value(HW_CODE_BIT_0)) + 2;
181
182         return hw_code;
183 }
184
185 int board_late_init(void)
186 {
187         u32 hw_code;
188         char buf[16];
189
190         setup_dhcom_mac_from_fuse();
191
192         hw_code = board_get_hwcode();
193
194         switch (get_cpu_type()) {
195         case MXC_CPU_MX6SOLO:
196                 snprintf(buf, sizeof(buf), "imx6s-dhcom%1d", hw_code);
197                 break;
198         case MXC_CPU_MX6DL:
199                 snprintf(buf, sizeof(buf), "imx6dl-dhcom%1d", hw_code);
200                 break;
201         case MXC_CPU_MX6D:
202                 snprintf(buf, sizeof(buf), "imx6d-dhcom%1d", hw_code);
203                 break;
204         case MXC_CPU_MX6Q:
205                 snprintf(buf, sizeof(buf), "imx6q-dhcom%1d", hw_code);
206                 break;
207         default:
208                 snprintf(buf, sizeof(buf), "UNKNOWN%1d", hw_code);
209                 break;
210         }
211
212         env_set("dhcom", buf);
213
214 #ifdef CONFIG_CMD_BMODE
215         add_board_boot_modes(board_boot_modes);
216 #endif
217         return 0;
218 }
219
220 int checkboard(void)
221 {
222         puts("Board: DHCOM i.MX6\n");
223         return 0;
224 }
225
226 #ifdef CONFIG_MULTI_DTB_FIT
227 int board_fit_config_name_match(const char *name)
228 {
229         if (is_mx6dq()) {
230                 if (!strcmp(name, "imx6q-dhcom-pdk2"))
231                         return 0;
232         } else if (is_mx6sdl()) {
233                 if (!strcmp(name, "imx6dl-dhcom-pdk2"))
234                         return 0;
235         }
236
237         return -1;
238 }
239 #endif