blob: 36e9cd7f842a7caf422844d7e3f15de3429f500c [file] [log] [blame]
Klaus Gogera13110a2017-04-07 19:13:38 +02001/*
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>
Philipp Tomsiche92e5802017-04-28 17:31:44 +02008#include <misc.h>
9#include <ram.h>
Klaus Gogera13110a2017-04-07 19:13:38 +020010#include <dm/pinctrl.h>
11#include <dm/uclass-internal.h>
Philipp Tomsich9415b9a2017-05-05 19:21:39 +020012#include <misc.h>
13#include <asm/setup.h>
Klaus Gogera13110a2017-04-07 19:13:38 +020014#include <asm/arch/periph.h>
15#include <power/regulator.h>
Philipp Tomsiche92e5802017-04-28 17:31:44 +020016#include <u-boot/sha256.h>
17
Philipp Tomsich9415b9a2017-05-05 19:21:39 +020018#define RK3399_CPUID_OFF 0x7
19#define RK3399_CPUID_LEN 0x10
20
Philipp Tomsiche92e5802017-04-28 17:31:44 +020021DECLARE_GLOBAL_DATA_PTR;
22
23#define RK3399_CPUID_OFF 0x7
24#define RK3399_CPUID_LEN 0x10
Klaus Gogera13110a2017-04-07 19:13:38 +020025
26DECLARE_GLOBAL_DATA_PTR;
27
28int 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", &regulator);
52 if (ret)
53 debug("%s: Cannot get vdd_center regulator\n", __func__);
54
55 ret = regulator_get_by_platname("vcc5v0_host", &regulator);
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
67out:
68 return 0;
69}
70
Klaus Goger8adc9d12017-05-05 19:21:40 +020071static 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
Philipp Tomsich9415b9a2017-05-05 19:21:39 +0200107static 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
Klaus Goger8adc9d12017-05-05 19:21:40 +0200118 /* retrieve the device */
119 ret = uclass_get_device_by_driver(UCLASS_MISC,
120 DM_GET_DRIVER(rockchip_efuse), &dev);
Philipp Tomsich9415b9a2017-05-05 19:21:39 +0200121 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
160int misc_init_r(void)
161{
162 setup_serial();
Klaus Goger8adc9d12017-05-05 19:21:40 +0200163 setup_macaddr();
Philipp Tomsich9415b9a2017-05-05 19:21:39 +0200164
165 return 0;
166}
167
168#ifdef CONFIG_SERIAL_TAG
169void 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