]>
Commit | Line | Data |
---|---|---|
a13110a9 KG |
1 | /* |
2 | * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH | |
3 | * | |
4 | * SPDX-License-Identifier: GPL-2.0+ | |
5 | */ | |
6 | #include <common.h> | |
7 | #include <dm.h> | |
e92e5803 PT |
8 | #include <misc.h> |
9 | #include <ram.h> | |
a13110a9 KG |
10 | #include <dm/pinctrl.h> |
11 | #include <dm/uclass-internal.h> | |
9415b9a7 PT |
12 | #include <misc.h> |
13 | #include <asm/setup.h> | |
a13110a9 KG |
14 | #include <asm/arch/periph.h> |
15 | #include <power/regulator.h> | |
e92e5803 PT |
16 | #include <u-boot/sha256.h> |
17 | ||
9415b9a7 PT |
18 | #define RK3399_CPUID_OFF 0x7 |
19 | #define RK3399_CPUID_LEN 0x10 | |
20 | ||
e92e5803 PT |
21 | DECLARE_GLOBAL_DATA_PTR; |
22 | ||
23 | #define RK3399_CPUID_OFF 0x7 | |
24 | #define RK3399_CPUID_LEN 0x10 | |
a13110a9 KG |
25 | |
26 | DECLARE_GLOBAL_DATA_PTR; | |
27 | ||
28 | int board_init(void) | |
29 | { | |
30 | struct udevice *pinctrl, *regulator; | |
31 | int ret; | |
32 | ||
33 | /* | |
34 | * The PWM does not have decicated interrupt number in dts and can | |
35 | * not get periph_id by pinctrl framework, so let's init them here. | |
36 | * The PWM2 and PWM3 are for pwm regulators. | |
37 | */ | |
38 | ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); | |
39 | if (ret) { | |
40 | debug("%s: Cannot find pinctrl device\n", __func__); | |
41 | goto out; | |
42 | } | |
43 | ||
44 | ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_PWM2); | |
45 | if (ret) { | |
46 | debug("%s PWM2 pinctrl init fail!\n", __func__); | |
47 | goto out; | |
48 | } | |
49 | ||
50 | /* rk3399 need to init vdd_center to get the correct output voltage */ | |
51 | ret = regulator_get_by_platname("vdd_center", ®ulator); | |
52 | if (ret) | |
53 | debug("%s: Cannot get vdd_center regulator\n", __func__); | |
54 | ||
55 | ret = regulator_get_by_platname("vcc5v0_host", ®ulator); | |
56 | if (ret) { | |
57 | debug("%s vcc5v0_host init fail! ret %d\n", __func__, ret); | |
58 | goto out; | |
59 | } | |
60 | ||
61 | ret = regulator_set_enable(regulator, true); | |
62 | if (ret) { | |
63 | debug("%s vcc5v0-host-en set fail!\n", __func__); | |
64 | goto out; | |
65 | } | |
66 | ||
67 | out: | |
68 | return 0; | |
69 | } | |
70 | ||
8adc9d18 KG |
71 | static void setup_macaddr(void) |
72 | { | |
73 | #if CONFIG_IS_ENABLED(CMD_NET) | |
74 | int ret; | |
75 | const char *cpuid = getenv("cpuid#"); | |
76 | u8 hash[SHA256_SUM_LEN]; | |
77 | int size = sizeof(hash); | |
78 | u8 mac_addr[6]; | |
79 | ||
80 | /* Only generate a MAC address, if none is set in the environment */ | |
81 | if (getenv("ethaddr")) | |
82 | return; | |
83 | ||
84 | if (!cpuid) { | |
85 | debug("%s: could not retrieve 'cpuid#'\n", __func__); | |
86 | return; | |
87 | } | |
88 | ||
89 | ret = hash_block("sha256", (void *)cpuid, strlen(cpuid), hash, &size); | |
90 | if (ret) { | |
91 | debug("%s: failed to calculate SHA256\n", __func__); | |
92 | return; | |
93 | } | |
94 | ||
95 | /* Copy 6 bytes of the hash to base the MAC address on */ | |
96 | memcpy(mac_addr, hash, 6); | |
97 | ||
98 | /* Make this a valid MAC address and set it */ | |
99 | mac_addr[0] &= 0xfe; /* clear multicast bit */ | |
100 | mac_addr[0] |= 0x02; /* set local assignment bit (IEEE802) */ | |
101 | eth_setenv_enetaddr("ethaddr", mac_addr); | |
102 | #endif | |
103 | ||
104 | return; | |
105 | } | |
106 | ||
9415b9a7 PT |
107 | static void setup_serial(void) |
108 | { | |
109 | #if CONFIG_IS_ENABLED(ROCKCHIP_EFUSE) | |
110 | struct udevice *dev; | |
111 | int ret, i; | |
112 | u8 cpuid[RK3399_CPUID_LEN]; | |
113 | u8 low[RK3399_CPUID_LEN/2], high[RK3399_CPUID_LEN/2]; | |
114 | char cpuid_str[RK3399_CPUID_LEN * 2 + 1]; | |
115 | u64 serialno; | |
116 | char serialno_str[16]; | |
117 | ||
8adc9d18 KG |
118 | /* retrieve the device */ |
119 | ret = uclass_get_device_by_driver(UCLASS_MISC, | |
120 | DM_GET_DRIVER(rockchip_efuse), &dev); | |
9415b9a7 PT |
121 | if (ret) { |
122 | debug("%s: could not find efuse device\n", __func__); | |
123 | return; | |
124 | } | |
125 | ||
126 | /* read the cpu_id range from the efuses */ | |
127 | ret = misc_read(dev, RK3399_CPUID_OFF, &cpuid, sizeof(cpuid)); | |
128 | if (ret) { | |
129 | debug("%s: reading cpuid from the efuses failed\n", | |
130 | __func__); | |
131 | return; | |
132 | } | |
133 | ||
134 | memset(cpuid_str, 0, sizeof(cpuid_str)); | |
135 | for (i = 0; i < 16; i++) | |
136 | sprintf(&cpuid_str[i * 2], "%02x", cpuid[i]); | |
137 | ||
138 | debug("cpuid: %s\n", cpuid_str); | |
139 | ||
140 | /* | |
141 | * Mix the cpuid bytes using the same rules as in | |
142 | * ${linux}/drivers/soc/rockchip/rockchip-cpuinfo.c | |
143 | */ | |
144 | for (i = 0; i < 8; i++) { | |
145 | low[i] = cpuid[1 + (i << 1)]; | |
146 | high[i] = cpuid[i << 1]; | |
147 | } | |
148 | ||
149 | serialno = crc32_no_comp(0, low, 8); | |
150 | serialno |= (u64)crc32_no_comp(serialno, high, 8) << 32; | |
151 | snprintf(serialno_str, sizeof(serialno_str), "%llx", serialno); | |
152 | ||
153 | setenv("cpuid#", cpuid_str); | |
154 | setenv("serial#", serialno_str); | |
155 | #endif | |
156 | ||
157 | return; | |
158 | } | |
159 | ||
160 | int misc_init_r(void) | |
161 | { | |
162 | setup_serial(); | |
8adc9d18 | 163 | setup_macaddr(); |
9415b9a7 PT |
164 | |
165 | return 0; | |
166 | } | |
167 | ||
168 | #ifdef CONFIG_SERIAL_TAG | |
169 | void get_board_serial(struct tag_serialnr *serialnr) | |
170 | { | |
171 | char *serial_string; | |
172 | u64 serial = 0; | |
173 | ||
174 | serial_string = getenv("serial#"); | |
175 | ||
176 | if (serial_string) | |
177 | serial = simple_strtoull(serial_string, NULL, 16); | |
178 | ||
179 | serialnr->high = (u32)(serial >> 32); | |
180 | serialnr->low = (u32)(serial & 0xffffffff); | |
181 | } | |
182 | #endif | |
183 | ||
a13110a9 KG |
184 | int dram_init_banksize(void) |
185 | { | |
186 | /* Reserve 0x200000 for ATF bl31 */ | |
187 | gd->bd->bi_dram[0].start = 0x200000; | |
188 | gd->bd->bi_dram[0].size = 0x7e000000; | |
189 | ||
190 | return 0; | |
191 | } |