Merge tag 'u-boot-imx-20190628' of https://gitlab.denx.de/u-boot/custodians/u-boot-imx
[platform/kernel/u-boot.git] / board / theobroma-systems / puma_rk3399 / puma-rk3399.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
4  */
5
6 #include <common.h>
7 #include <dm.h>
8 #include <environment.h>
9 #include <misc.h>
10 #include <spl.h>
11 #include <syscon.h>
12 #include <usb.h>
13 #include <dm/pinctrl.h>
14 #include <dm/uclass-internal.h>
15 #include <asm/io.h>
16 #include <asm/setup.h>
17 #include <asm/arch-rockchip/clock.h>
18 #include <asm/arch-rockchip/hardware.h>
19 #include <asm/arch-rockchip/grf_rk3399.h>
20 #include <asm/arch-rockchip/periph.h>
21 #include <power/regulator.h>
22 #include <u-boot/sha256.h>
23
24 int board_init(void)
25 {
26         int ret;
27
28         /*
29          * We need to call into regulators_enable_boot_on() again, as the call
30          * during SPL may have not included all regulators.
31          */
32         ret = regulators_enable_boot_on(false);
33         if (ret)
34                 debug("%s: Cannot enable boot on regulator\n", __func__);
35
36         return 0;
37 }
38
39 static void setup_macaddr(void)
40 {
41 #if CONFIG_IS_ENABLED(CMD_NET)
42         int ret;
43         const char *cpuid = env_get("cpuid#");
44         u8 hash[SHA256_SUM_LEN];
45         int size = sizeof(hash);
46         u8 mac_addr[6];
47
48         /* Only generate a MAC address, if none is set in the environment */
49         if (env_get("ethaddr"))
50                 return;
51
52         if (!cpuid) {
53                 debug("%s: could not retrieve 'cpuid#'\n", __func__);
54                 return;
55         }
56
57         ret = hash_block("sha256", (void *)cpuid, strlen(cpuid), hash, &size);
58         if (ret) {
59                 debug("%s: failed to calculate SHA256\n", __func__);
60                 return;
61         }
62
63         /* Copy 6 bytes of the hash to base the MAC address on */
64         memcpy(mac_addr, hash, 6);
65
66         /* Make this a valid MAC address and set it */
67         mac_addr[0] &= 0xfe;  /* clear multicast bit */
68         mac_addr[0] |= 0x02;  /* set local assignment bit (IEEE802) */
69         eth_env_set_enetaddr("ethaddr", mac_addr);
70 #endif
71 }
72
73 static void setup_serial(void)
74 {
75 #if CONFIG_IS_ENABLED(ROCKCHIP_EFUSE)
76         const u32 cpuid_offset = 0x7;
77         const u32 cpuid_length = 0x10;
78
79         struct udevice *dev;
80         int ret, i;
81         u8 cpuid[cpuid_length];
82         u8 low[cpuid_length/2], high[cpuid_length/2];
83         char cpuid_str[cpuid_length * 2 + 1];
84         u64 serialno;
85         char serialno_str[17];
86
87         /* retrieve the device */
88         ret = uclass_get_device_by_driver(UCLASS_MISC,
89                                           DM_GET_DRIVER(rockchip_efuse), &dev);
90         if (ret) {
91                 debug("%s: could not find efuse device\n", __func__);
92                 return;
93         }
94
95         /* read the cpu_id range from the efuses */
96         ret = misc_read(dev, cpuid_offset, &cpuid, sizeof(cpuid));
97         if (ret) {
98                 debug("%s: reading cpuid from the efuses failed\n",
99                       __func__);
100                 return;
101         }
102
103         memset(cpuid_str, 0, sizeof(cpuid_str));
104         for (i = 0; i < 16; i++)
105                 sprintf(&cpuid_str[i * 2], "%02x", cpuid[i]);
106
107         debug("cpuid: %s\n", cpuid_str);
108
109         /*
110          * Mix the cpuid bytes using the same rules as in
111          *   ${linux}/drivers/soc/rockchip/rockchip-cpuinfo.c
112          */
113         for (i = 0; i < 8; i++) {
114                 low[i] = cpuid[1 + (i << 1)];
115                 high[i] = cpuid[i << 1];
116         }
117
118         serialno = crc32_no_comp(0, low, 8);
119         serialno |= (u64)crc32_no_comp(serialno, high, 8) << 32;
120         snprintf(serialno_str, sizeof(serialno_str), "%016llx", serialno);
121
122         env_set("cpuid#", cpuid_str);
123         env_set("serial#", serialno_str);
124 #endif
125 }
126
127 static void setup_iodomain(void)
128 {
129         const u32 GRF_IO_VSEL_GPIO4CD_SHIFT = 3;
130         struct rk3399_grf_regs *grf =
131             syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
132
133         /*
134          * Set bit 3 in GRF_IO_VSEL so PCIE_RST# works (pin GPIO4_C6).
135          * Linux assumes that PCIE_RST# works out of the box as it probes
136          * PCIe before loading the iodomain driver.
137          */
138         rk_setreg(&grf->io_vsel, 1 << GRF_IO_VSEL_GPIO4CD_SHIFT);
139 }
140
141 /*
142  * Swap mmc0 and mmc1 in boot_targets if booted from SD-Card.
143  *
144  * If bootsource is uSD-card we can assume that we want to use the
145  * SD-Card instead of the eMMC as first boot_target for distroboot.
146  * We only want to swap the defaults and not any custom environment a
147  * user has set. We exit early if a changed boot_targets environment
148  * is detected.
149  */
150 static int setup_boottargets(void)
151 {
152         const char *boot_device =
153                 ofnode_get_chosen_prop("u-boot,spl-boot-device");
154         char *env_default, *env;
155
156         if (!boot_device) {
157                 debug("%s: /chosen/u-boot,spl-boot-device not set\n",
158                       __func__);
159                 return -1;
160         }
161         debug("%s: booted from %s\n", __func__, boot_device);
162
163         env_default = env_get_default("boot_targets");
164         env = env_get("boot_targets");
165         if (!env) {
166                 debug("%s: boot_targets does not exist\n", __func__);
167                 return -1;
168         }
169         debug("%s: boot_targets current: %s - default: %s\n",
170               __func__, env, env_default);
171
172         if (strcmp(env_default, env) != 0) {
173                 debug("%s: boot_targets not default, don't change it\n",
174                       __func__);
175                 return 0;
176         }
177
178         /*
179          * Only run, if booting from mmc1 (i.e. /dwmmc@fe320000) and
180          * only consider cases where the default boot-order first
181          * tries to boot from mmc0 (eMMC) and then from mmc1
182          * (i.e. external SD).
183          *
184          * In other words: the SD card will be moved to earlier in the
185          * order, if U-Boot was also loaded from the SD-card.
186          */
187         if (!strcmp(boot_device, "/dwmmc@fe320000")) {
188                 char *mmc0, *mmc1;
189
190                 debug("%s: booted from SD-Card\n", __func__);
191                 mmc0 = strstr(env, "mmc0");
192                 mmc1 = strstr(env, "mmc1");
193
194                 if (!mmc0 || !mmc1) {
195                         debug("%s: only one mmc boot_target found\n", __func__);
196                         return -1;
197                 }
198
199                 /*
200                  * If mmc0 comes first in the boot order, we need to change
201                  * the strings to make mmc1 first.
202                  */
203                 if (mmc0 < mmc1) {
204                         mmc0[3] = '1';
205                         mmc1[3] = '0';
206                         debug("%s: set boot_targets to: %s\n", __func__, env);
207                         env_set("boot_targets", env);
208                 }
209         }
210
211         return 0;
212 }
213
214 int misc_init_r(void)
215 {
216         setup_serial();
217         setup_macaddr();
218         setup_iodomain();
219         setup_boottargets();
220
221         return 0;
222 }
223
224 #ifdef CONFIG_SERIAL_TAG
225 void get_board_serial(struct tag_serialnr *serialnr)
226 {
227         char *serial_string;
228         u64 serial = 0;
229
230         serial_string = env_get("serial#");
231
232         if (serial_string)
233                 serial = simple_strtoull(serial_string, NULL, 16);
234
235         serialnr->high = (u32)(serial >> 32);
236         serialnr->low = (u32)(serial & 0xffffffff);
237 }
238 #endif
239
240 /**
241  * Switch power at an external regulator (for our root hub).
242  *
243  * @param ctrl pointer to the xHCI controller
244  * @param port port number as in the control message (one-based)
245  * @param enable boolean indicating whether to enable or disable power
246  * @return returns 0 on success, an error-code on failure
247  */
248 static int board_usb_port_power_set(struct udevice *dev, int port,
249                                     bool enable)
250 {
251 #if CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(DM_REGULATOR)
252         /* We start counting ports at 0, while USB counts from 1. */
253         int index = port - 1;
254         const char *regname = NULL;
255         struct udevice *regulator;
256         const char *prop = "tsd,usb-port-power";
257         int ret;
258
259         debug("%s: ctrl '%s' port %d enable %s\n", __func__,
260               dev_read_name(dev), port, enable ? "true" : "false");
261
262         ret = dev_read_string_index(dev, prop, index, &regname);
263         if (ret < 0) {
264                 debug("%s: ctrl '%s' port %d: no entry in '%s'\n",
265                       __func__, dev_read_name(dev), port, prop);
266                 return ret;
267         }
268
269         ret = regulator_get_by_platname(regname, &regulator);
270         if (ret) {
271                 debug("%s: ctrl '%s' port %d: could not get regulator '%s'\n",
272                       __func__, dev_read_name(dev), port, regname);
273                 return ret;
274         }
275
276         regulator_set_enable(regulator, enable);
277         return 0;
278 #else
279         return -ENOTSUPP;
280 #endif
281 }
282
283 void usb_hub_reset_devices(struct usb_hub_device *hub, int port)
284 {
285         struct udevice *dev = hub->pusb_dev->dev;
286         struct udevice *ctrl;
287
288         /* We are only interested in our root-hubs */
289         if (usb_hub_is_root_hub(dev) == false)
290                 return;
291
292         ctrl = usb_get_bus(dev);
293         if (!ctrl) {
294                 debug("%s: could not retrieve ctrl for hub\n", __func__);
295                 return;
296         }
297
298         /*
299          * To work around an incompatibility between the single-threaded
300          * USB stack in U-Boot and (a strange low-power mode of) the USB
301          * hub we have on-module, we need to delay powering on the hub
302          * until the first time the port is probed.
303          */
304         board_usb_port_power_set(ctrl, port, true);
305 }