1a13110a9SKlaus Goger /* 2a13110a9SKlaus Goger * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH 3a13110a9SKlaus Goger * 4a13110a9SKlaus Goger * SPDX-License-Identifier: GPL-2.0+ 5a13110a9SKlaus Goger */ 6*fb740646SPhilipp Tomsich 7a13110a9SKlaus Goger #include <common.h> 8a13110a9SKlaus Goger #include <dm.h> 9e92e5803SPhilipp Tomsich #include <misc.h> 10a13110a9SKlaus Goger #include <dm/pinctrl.h> 11a13110a9SKlaus Goger #include <dm/uclass-internal.h> 129415b9a7SPhilipp Tomsich #include <asm/setup.h> 13a13110a9SKlaus Goger #include <asm/arch/periph.h> 14a13110a9SKlaus Goger #include <power/regulator.h> 15*fb740646SPhilipp Tomsich #include <spl.h> 16e92e5803SPhilipp Tomsich #include <u-boot/sha256.h> 17e92e5803SPhilipp Tomsich 18a13110a9SKlaus Goger DECLARE_GLOBAL_DATA_PTR; 19a13110a9SKlaus Goger 20a13110a9SKlaus Goger int board_init(void) 21a13110a9SKlaus Goger { 22a13110a9SKlaus Goger struct udevice *pinctrl, *regulator; 23a13110a9SKlaus Goger int ret; 24a13110a9SKlaus Goger 25a13110a9SKlaus Goger /* 26a13110a9SKlaus Goger * The PWM does not have decicated interrupt number in dts and can 27a13110a9SKlaus Goger * not get periph_id by pinctrl framework, so let's init them here. 28a13110a9SKlaus Goger * The PWM2 and PWM3 are for pwm regulators. 29a13110a9SKlaus Goger */ 30a13110a9SKlaus Goger ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); 31a13110a9SKlaus Goger if (ret) { 32a13110a9SKlaus Goger debug("%s: Cannot find pinctrl device\n", __func__); 33a13110a9SKlaus Goger goto out; 34a13110a9SKlaus Goger } 35a13110a9SKlaus Goger 36a13110a9SKlaus Goger ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_PWM2); 37a13110a9SKlaus Goger if (ret) { 38a13110a9SKlaus Goger debug("%s PWM2 pinctrl init fail!\n", __func__); 39a13110a9SKlaus Goger goto out; 40a13110a9SKlaus Goger } 41a13110a9SKlaus Goger 42a13110a9SKlaus Goger /* rk3399 need to init vdd_center to get the correct output voltage */ 43a13110a9SKlaus Goger ret = regulator_get_by_platname("vdd_center", ®ulator); 44a13110a9SKlaus Goger if (ret) 45a13110a9SKlaus Goger debug("%s: Cannot get vdd_center regulator\n", __func__); 46a13110a9SKlaus Goger 47a13110a9SKlaus Goger ret = regulator_get_by_platname("vcc5v0_host", ®ulator); 48a13110a9SKlaus Goger if (ret) { 49a13110a9SKlaus Goger debug("%s vcc5v0_host init fail! ret %d\n", __func__, ret); 50a13110a9SKlaus Goger goto out; 51a13110a9SKlaus Goger } 52a13110a9SKlaus Goger 53a13110a9SKlaus Goger ret = regulator_set_enable(regulator, true); 54a13110a9SKlaus Goger if (ret) { 55a13110a9SKlaus Goger debug("%s vcc5v0-host-en set fail!\n", __func__); 56a13110a9SKlaus Goger goto out; 57a13110a9SKlaus Goger } 58a13110a9SKlaus Goger 59a13110a9SKlaus Goger out: 60a13110a9SKlaus Goger return 0; 61a13110a9SKlaus Goger } 62a13110a9SKlaus Goger 63*fb740646SPhilipp Tomsich void spl_board_init(void) 64*fb740646SPhilipp Tomsich { 65*fb740646SPhilipp Tomsich preloader_console_init(); 66*fb740646SPhilipp Tomsich } 67*fb740646SPhilipp Tomsich 688adc9d18SKlaus Goger static void setup_macaddr(void) 698adc9d18SKlaus Goger { 708adc9d18SKlaus Goger #if CONFIG_IS_ENABLED(CMD_NET) 718adc9d18SKlaus Goger int ret; 7200caae6dSSimon Glass const char *cpuid = env_get("cpuid#"); 738adc9d18SKlaus Goger u8 hash[SHA256_SUM_LEN]; 748adc9d18SKlaus Goger int size = sizeof(hash); 758adc9d18SKlaus Goger u8 mac_addr[6]; 768adc9d18SKlaus Goger 778adc9d18SKlaus Goger /* Only generate a MAC address, if none is set in the environment */ 7800caae6dSSimon Glass if (env_get("ethaddr")) 798adc9d18SKlaus Goger return; 808adc9d18SKlaus Goger 818adc9d18SKlaus Goger if (!cpuid) { 828adc9d18SKlaus Goger debug("%s: could not retrieve 'cpuid#'\n", __func__); 838adc9d18SKlaus Goger return; 848adc9d18SKlaus Goger } 858adc9d18SKlaus Goger 868adc9d18SKlaus Goger ret = hash_block("sha256", (void *)cpuid, strlen(cpuid), hash, &size); 878adc9d18SKlaus Goger if (ret) { 888adc9d18SKlaus Goger debug("%s: failed to calculate SHA256\n", __func__); 898adc9d18SKlaus Goger return; 908adc9d18SKlaus Goger } 918adc9d18SKlaus Goger 928adc9d18SKlaus Goger /* Copy 6 bytes of the hash to base the MAC address on */ 938adc9d18SKlaus Goger memcpy(mac_addr, hash, 6); 948adc9d18SKlaus Goger 958adc9d18SKlaus Goger /* Make this a valid MAC address and set it */ 968adc9d18SKlaus Goger mac_addr[0] &= 0xfe; /* clear multicast bit */ 978adc9d18SKlaus Goger mac_addr[0] |= 0x02; /* set local assignment bit (IEEE802) */ 98fd1e959eSSimon Glass eth_env_set_enetaddr("ethaddr", mac_addr); 998adc9d18SKlaus Goger #endif 1008adc9d18SKlaus Goger } 1018adc9d18SKlaus Goger 1029415b9a7SPhilipp Tomsich static void setup_serial(void) 1039415b9a7SPhilipp Tomsich { 1049415b9a7SPhilipp Tomsich #if CONFIG_IS_ENABLED(ROCKCHIP_EFUSE) 10526722335SKever Yang const u32 cpuid_offset = 0x7; 10626722335SKever Yang const u32 cpuid_length = 0x10; 10726722335SKever Yang 1089415b9a7SPhilipp Tomsich struct udevice *dev; 1099415b9a7SPhilipp Tomsich int ret, i; 11026722335SKever Yang u8 cpuid[cpuid_length]; 11126722335SKever Yang u8 low[cpuid_length/2], high[cpuid_length/2]; 11226722335SKever Yang char cpuid_str[cpuid_length * 2 + 1]; 1139415b9a7SPhilipp Tomsich u64 serialno; 11460d7c509SKlaus Goger char serialno_str[17]; 1159415b9a7SPhilipp Tomsich 1168adc9d18SKlaus Goger /* retrieve the device */ 1178adc9d18SKlaus Goger ret = uclass_get_device_by_driver(UCLASS_MISC, 1188adc9d18SKlaus Goger DM_GET_DRIVER(rockchip_efuse), &dev); 1199415b9a7SPhilipp Tomsich if (ret) { 1209415b9a7SPhilipp Tomsich debug("%s: could not find efuse device\n", __func__); 1219415b9a7SPhilipp Tomsich return; 1229415b9a7SPhilipp Tomsich } 1239415b9a7SPhilipp Tomsich 1249415b9a7SPhilipp Tomsich /* read the cpu_id range from the efuses */ 12526722335SKever Yang ret = misc_read(dev, cpuid_offset, &cpuid, sizeof(cpuid)); 1269415b9a7SPhilipp Tomsich if (ret) { 1279415b9a7SPhilipp Tomsich debug("%s: reading cpuid from the efuses failed\n", 1289415b9a7SPhilipp Tomsich __func__); 1299415b9a7SPhilipp Tomsich return; 1309415b9a7SPhilipp Tomsich } 1319415b9a7SPhilipp Tomsich 1329415b9a7SPhilipp Tomsich memset(cpuid_str, 0, sizeof(cpuid_str)); 1339415b9a7SPhilipp Tomsich for (i = 0; i < 16; i++) 1349415b9a7SPhilipp Tomsich sprintf(&cpuid_str[i * 2], "%02x", cpuid[i]); 1359415b9a7SPhilipp Tomsich 1369415b9a7SPhilipp Tomsich debug("cpuid: %s\n", cpuid_str); 1379415b9a7SPhilipp Tomsich 1389415b9a7SPhilipp Tomsich /* 1399415b9a7SPhilipp Tomsich * Mix the cpuid bytes using the same rules as in 1409415b9a7SPhilipp Tomsich * ${linux}/drivers/soc/rockchip/rockchip-cpuinfo.c 1419415b9a7SPhilipp Tomsich */ 1429415b9a7SPhilipp Tomsich for (i = 0; i < 8; i++) { 1439415b9a7SPhilipp Tomsich low[i] = cpuid[1 + (i << 1)]; 1449415b9a7SPhilipp Tomsich high[i] = cpuid[i << 1]; 1459415b9a7SPhilipp Tomsich } 1469415b9a7SPhilipp Tomsich 1479415b9a7SPhilipp Tomsich serialno = crc32_no_comp(0, low, 8); 1489415b9a7SPhilipp Tomsich serialno |= (u64)crc32_no_comp(serialno, high, 8) << 32; 1499415b9a7SPhilipp Tomsich snprintf(serialno_str, sizeof(serialno_str), "%llx", serialno); 1509415b9a7SPhilipp Tomsich 151382bee57SSimon Glass env_set("cpuid#", cpuid_str); 152382bee57SSimon Glass env_set("serial#", serialno_str); 1539415b9a7SPhilipp Tomsich #endif 1549415b9a7SPhilipp Tomsich } 1559415b9a7SPhilipp Tomsich 1569415b9a7SPhilipp Tomsich int misc_init_r(void) 1579415b9a7SPhilipp Tomsich { 1589415b9a7SPhilipp Tomsich setup_serial(); 1598adc9d18SKlaus Goger setup_macaddr(); 1609415b9a7SPhilipp Tomsich 1619415b9a7SPhilipp Tomsich return 0; 1629415b9a7SPhilipp Tomsich } 1639415b9a7SPhilipp Tomsich 1649415b9a7SPhilipp Tomsich #ifdef CONFIG_SERIAL_TAG 1659415b9a7SPhilipp Tomsich void get_board_serial(struct tag_serialnr *serialnr) 1669415b9a7SPhilipp Tomsich { 1679415b9a7SPhilipp Tomsich char *serial_string; 1689415b9a7SPhilipp Tomsich u64 serial = 0; 1699415b9a7SPhilipp Tomsich 17000caae6dSSimon Glass serial_string = env_get("serial#"); 1719415b9a7SPhilipp Tomsich 1729415b9a7SPhilipp Tomsich if (serial_string) 1739415b9a7SPhilipp Tomsich serial = simple_strtoull(serial_string, NULL, 16); 1749415b9a7SPhilipp Tomsich 1759415b9a7SPhilipp Tomsich serialnr->high = (u32)(serial >> 32); 1769415b9a7SPhilipp Tomsich serialnr->low = (u32)(serial & 0xffffffff); 1779415b9a7SPhilipp Tomsich } 1789415b9a7SPhilipp Tomsich #endif 179