]>
Commit | Line | Data |
---|---|---|
04825384 RG |
1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
2 | /* | |
3 | * RK3399: Architecture common definitions | |
4 | * | |
5 | * Copyright (C) 2019 Collabora Inc - https://www.collabora.com/ | |
6 | * Rohan Garg <[email protected]> | |
7 | * | |
8 | * Based on puma-rk3399.c: | |
9 | * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH | |
10 | */ | |
11 | ||
12 | #include <common.h> | |
13 | #include <env.h> | |
14 | #include <dm.h> | |
4d72caa5 | 15 | #include <hash.h> |
f7ae49fc | 16 | #include <log.h> |
04825384 RG |
17 | #include <dm/uclass-internal.h> |
18 | #include <misc.h> | |
3db71108 | 19 | #include <u-boot/crc.h> |
04825384 RG |
20 | #include <u-boot/sha256.h> |
21 | ||
22 | #include <asm/arch-rockchip/misc.h> | |
23 | ||
24 | int rockchip_setup_macaddr(void) | |
25 | { | |
26 | #if CONFIG_IS_ENABLED(CMD_NET) | |
27 | int ret; | |
28 | const char *cpuid = env_get("cpuid#"); | |
29 | u8 hash[SHA256_SUM_LEN]; | |
30 | int size = sizeof(hash); | |
31 | u8 mac_addr[6]; | |
32 | ||
33 | /* Only generate a MAC address, if none is set in the environment */ | |
34 | if (env_get("ethaddr")) | |
d490fadc | 35 | return 0; |
04825384 RG |
36 | |
37 | if (!cpuid) { | |
38 | debug("%s: could not retrieve 'cpuid#'\n", __func__); | |
39 | return -1; | |
40 | } | |
41 | ||
42 | ret = hash_block("sha256", (void *)cpuid, strlen(cpuid), hash, &size); | |
43 | if (ret) { | |
44 | debug("%s: failed to calculate SHA256\n", __func__); | |
45 | return -1; | |
46 | } | |
47 | ||
48 | /* Copy 6 bytes of the hash to base the MAC address on */ | |
49 | memcpy(mac_addr, hash, 6); | |
50 | ||
51 | /* Make this a valid MAC address and set it */ | |
52 | mac_addr[0] &= 0xfe; /* clear multicast bit */ | |
53 | mac_addr[0] |= 0x02; /* set local assignment bit (IEEE802) */ | |
54 | eth_env_set_enetaddr("ethaddr", mac_addr); | |
55 | #endif | |
56 | return 0; | |
57 | } | |
58 | ||
59 | int rockchip_cpuid_from_efuse(const u32 cpuid_offset, | |
60 | const u32 cpuid_length, | |
61 | u8 *cpuid) | |
62 | { | |
e61350a5 | 63 | #if CONFIG_IS_ENABLED(ROCKCHIP_EFUSE) || CONFIG_IS_ENABLED(ROCKCHIP_OTP) |
04825384 RG |
64 | struct udevice *dev; |
65 | int ret; | |
66 | ||
67 | /* retrieve the device */ | |
e61350a5 | 68 | #if CONFIG_IS_ENABLED(ROCKCHIP_EFUSE) |
04825384 | 69 | ret = uclass_get_device_by_driver(UCLASS_MISC, |
65e25bea | 70 | DM_DRIVER_GET(rockchip_efuse), &dev); |
e61350a5 HS |
71 | #elif CONFIG_IS_ENABLED(ROCKCHIP_OTP) |
72 | ret = uclass_get_device_by_driver(UCLASS_MISC, | |
65e25bea | 73 | DM_DRIVER_GET(rockchip_otp), &dev); |
e61350a5 | 74 | #endif |
04825384 RG |
75 | if (ret) { |
76 | debug("%s: could not find efuse device\n", __func__); | |
77 | return -1; | |
78 | } | |
79 | ||
80 | /* read the cpu_id range from the efuses */ | |
03f98b75 | 81 | ret = misc_read(dev, cpuid_offset, cpuid, cpuid_length); |
04825384 RG |
82 | if (ret) { |
83 | debug("%s: reading cpuid from the efuses failed\n", | |
84 | __func__); | |
85 | return -1; | |
86 | } | |
87 | #endif | |
88 | return 0; | |
89 | } | |
90 | ||
91 | int rockchip_cpuid_set(const u8 *cpuid, const u32 cpuid_length) | |
92 | { | |
93 | u8 low[cpuid_length / 2], high[cpuid_length / 2]; | |
94 | char cpuid_str[cpuid_length * 2 + 1]; | |
95 | u64 serialno; | |
96 | char serialno_str[17]; | |
fd3a7ae8 | 97 | const char *oldid; |
04825384 RG |
98 | int i; |
99 | ||
100 | memset(cpuid_str, 0, sizeof(cpuid_str)); | |
101 | for (i = 0; i < 16; i++) | |
102 | sprintf(&cpuid_str[i * 2], "%02x", cpuid[i]); | |
103 | ||
104 | debug("cpuid: %s\n", cpuid_str); | |
105 | ||
106 | /* | |
107 | * Mix the cpuid bytes using the same rules as in | |
108 | * ${linux}/drivers/soc/rockchip/rockchip-cpuinfo.c | |
109 | */ | |
110 | for (i = 0; i < 8; i++) { | |
111 | low[i] = cpuid[1 + (i << 1)]; | |
112 | high[i] = cpuid[i << 1]; | |
113 | } | |
114 | ||
115 | serialno = crc32_no_comp(0, low, 8); | |
116 | serialno |= (u64)crc32_no_comp(serialno, high, 8) << 32; | |
117 | snprintf(serialno_str, sizeof(serialno_str), "%016llx", serialno); | |
118 | ||
fd3a7ae8 HS |
119 | oldid = env_get("cpuid#"); |
120 | if (oldid && strcmp(oldid, cpuid_str) != 0) | |
121 | printf("cpuid: value %s present in env does not match hardware %s\n", | |
122 | oldid, cpuid_str); | |
123 | ||
04825384 | 124 | env_set("cpuid#", cpuid_str); |
fd3a7ae8 HS |
125 | |
126 | /* Only generate serial# when none is set yet */ | |
127 | if (!env_get("serial#")) | |
128 | env_set("serial#", serialno_str); | |
04825384 RG |
129 | |
130 | return 0; | |
131 | } |