1 /* 2 * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <dm.h> 9 #include <misc.h> 10 #include <dm/pinctrl.h> 11 #include <dm/uclass-internal.h> 12 #include <asm/setup.h> 13 #include <asm/arch/periph.h> 14 #include <power/regulator.h> 15 #include <spl.h> 16 #include <u-boot/sha256.h> 17 18 DECLARE_GLOBAL_DATA_PTR; 19 20 int board_init(void) 21 { 22 int ret; 23 24 /* 25 * We need to call into regulators_enable_boot_on() again, as the call 26 * during SPL may have not included all regulators. 27 */ 28 ret = regulators_enable_boot_on(false); 29 if (ret) 30 debug("%s: Cannot enable boot on regulator\n", __func__); 31 32 return 0; 33 } 34 35 void spl_board_init(void) 36 { 37 int ret; 38 39 /* 40 * Turning the eMMC and SPI back on (if disabled via the Qseven 41 * BIOS_ENABLE) signal is done through a always-on regulator). 42 */ 43 ret = regulators_enable_boot_on(false); 44 if (ret) 45 debug("%s: Cannot enable boot on regulator\n", __func__); 46 47 preloader_console_init(); 48 } 49 50 static void setup_macaddr(void) 51 { 52 #if CONFIG_IS_ENABLED(CMD_NET) 53 int ret; 54 const char *cpuid = env_get("cpuid#"); 55 u8 hash[SHA256_SUM_LEN]; 56 int size = sizeof(hash); 57 u8 mac_addr[6]; 58 59 /* Only generate a MAC address, if none is set in the environment */ 60 if (env_get("ethaddr")) 61 return; 62 63 if (!cpuid) { 64 debug("%s: could not retrieve 'cpuid#'\n", __func__); 65 return; 66 } 67 68 ret = hash_block("sha256", (void *)cpuid, strlen(cpuid), hash, &size); 69 if (ret) { 70 debug("%s: failed to calculate SHA256\n", __func__); 71 return; 72 } 73 74 /* Copy 6 bytes of the hash to base the MAC address on */ 75 memcpy(mac_addr, hash, 6); 76 77 /* Make this a valid MAC address and set it */ 78 mac_addr[0] &= 0xfe; /* clear multicast bit */ 79 mac_addr[0] |= 0x02; /* set local assignment bit (IEEE802) */ 80 eth_env_set_enetaddr("ethaddr", mac_addr); 81 #endif 82 } 83 84 static void setup_serial(void) 85 { 86 #if CONFIG_IS_ENABLED(ROCKCHIP_EFUSE) 87 const u32 cpuid_offset = 0x7; 88 const u32 cpuid_length = 0x10; 89 90 struct udevice *dev; 91 int ret, i; 92 u8 cpuid[cpuid_length]; 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]; 97 98 /* retrieve the device */ 99 ret = uclass_get_device_by_driver(UCLASS_MISC, 100 DM_GET_DRIVER(rockchip_efuse), &dev); 101 if (ret) { 102 debug("%s: could not find efuse device\n", __func__); 103 return; 104 } 105 106 /* read the cpu_id range from the efuses */ 107 ret = misc_read(dev, cpuid_offset, &cpuid, sizeof(cpuid)); 108 if (ret) { 109 debug("%s: reading cpuid from the efuses failed\n", 110 __func__); 111 return; 112 } 113 114 memset(cpuid_str, 0, sizeof(cpuid_str)); 115 for (i = 0; i < 16; i++) 116 sprintf(&cpuid_str[i * 2], "%02x", cpuid[i]); 117 118 debug("cpuid: %s\n", cpuid_str); 119 120 /* 121 * Mix the cpuid bytes using the same rules as in 122 * ${linux}/drivers/soc/rockchip/rockchip-cpuinfo.c 123 */ 124 for (i = 0; i < 8; i++) { 125 low[i] = cpuid[1 + (i << 1)]; 126 high[i] = cpuid[i << 1]; 127 } 128 129 serialno = crc32_no_comp(0, low, 8); 130 serialno |= (u64)crc32_no_comp(serialno, high, 8) << 32; 131 snprintf(serialno_str, sizeof(serialno_str), "%llx", serialno); 132 133 env_set("cpuid#", cpuid_str); 134 env_set("serial#", serialno_str); 135 #endif 136 } 137 138 int misc_init_r(void) 139 { 140 setup_serial(); 141 setup_macaddr(); 142 143 return 0; 144 } 145 146 #ifdef CONFIG_SERIAL_TAG 147 void get_board_serial(struct tag_serialnr *serialnr) 148 { 149 char *serial_string; 150 u64 serial = 0; 151 152 serial_string = env_get("serial#"); 153 154 if (serial_string) 155 serial = simple_strtoull(serial_string, NULL, 16); 156 157 serialnr->high = (u32)(serial >> 32); 158 serialnr->low = (u32)(serial & 0xffffffff); 159 } 160 #endif 161