u-boot-brain/board/theobroma-systems/puma_rk3399/puma-rk3399.c
Philipp Tomsich 9415b9a7d8 rockchip: board: puma_rk3399: add support for serial# and cpuid# via efuses
With our efuse driver for the RK3399 ready, we can add the
board-specific code that consumes the cpuid from the efuse block and
postprocesses it into the system serial (using the same CRC32 based
derivation as in Linux).

We expose the cpuid via two distinct environment variables:
   serial# - the serial number, as derived in Linux
   cpuid#  - the raw 16 byte CPU id field from the fuse block

Signed-off-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
Acked-by: Simon Glass <sjg@chromium.org>
2017-06-07 07:29:18 -06:00

176 lines
3.7 KiB
C

/*
* (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <dm.h>
#include <misc.h>
#include <ram.h>
#include <dm/pinctrl.h>
#include <dm/uclass-internal.h>
#include <misc.h>
#include <asm/setup.h>
#include <asm/arch/periph.h>
#include <power/regulator.h>
#include <u-boot/sha256.h>
#define RK3399_CPUID_OFF 0x7
#define RK3399_CPUID_LEN 0x10
DECLARE_GLOBAL_DATA_PTR;
#define RK3399_CPUID_OFF 0x7
#define RK3399_CPUID_LEN 0x10
DECLARE_GLOBAL_DATA_PTR;
int board_init(void)
{
struct udevice *pinctrl, *regulator;
int ret;
/*
* The PWM does not have decicated interrupt number in dts and can
* not get periph_id by pinctrl framework, so let's init them here.
* The PWM2 and PWM3 are for pwm regulators.
*/
ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
if (ret) {
debug("%s: Cannot find pinctrl device\n", __func__);
goto out;
}
ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_PWM2);
if (ret) {
debug("%s PWM2 pinctrl init fail!\n", __func__);
goto out;
}
/* rk3399 need to init vdd_center to get the correct output voltage */
ret = regulator_get_by_platname("vdd_center", &regulator);
if (ret)
debug("%s: Cannot get vdd_center regulator\n", __func__);
ret = regulator_get_by_platname("vcc5v0_host", &regulator);
if (ret) {
debug("%s vcc5v0_host init fail! ret %d\n", __func__, ret);
goto out;
}
ret = regulator_set_enable(regulator, true);
if (ret) {
debug("%s vcc5v0-host-en set fail!\n", __func__);
goto out;
}
out:
return 0;
}
static void setup_serial(void)
{
#if CONFIG_IS_ENABLED(ROCKCHIP_EFUSE)
struct udevice *dev;
int ret, i;
u8 cpuid[RK3399_CPUID_LEN];
u8 low[RK3399_CPUID_LEN/2], high[RK3399_CPUID_LEN/2];
char cpuid_str[RK3399_CPUID_LEN * 2 + 1];
u64 serialno;
char serialno_str[16];
/* the first misc device will be used */
ret = uclass_get_device(UCLASS_MISC, 0, &dev);
if (ret) {
debug("%s: could not find efuse device\n", __func__);
return;
}
/* read the cpu_id range from the efuses */
ret = misc_read(dev, RK3399_CPUID_OFF, &cpuid, sizeof(cpuid));
if (ret) {
debug("%s: reading cpuid from the efuses failed\n",
__func__);
return;
}
memset(cpuid_str, 0, sizeof(cpuid_str));
for (i = 0; i < 16; i++)
sprintf(&cpuid_str[i * 2], "%02x", cpuid[i]);
debug("cpuid: %s\n", cpuid_str);
/*
* Mix the cpuid bytes using the same rules as in
* ${linux}/drivers/soc/rockchip/rockchip-cpuinfo.c
*/
for (i = 0; i < 8; i++) {
low[i] = cpuid[1 + (i << 1)];
high[i] = cpuid[i << 1];
}
serialno = crc32_no_comp(0, low, 8);
serialno |= (u64)crc32_no_comp(serialno, high, 8) << 32;
snprintf(serialno_str, sizeof(serialno_str), "%llx", serialno);
setenv("cpuid#", cpuid_str);
setenv("serial#", serialno_str);
#endif
return;
}
int misc_init_r(void)
{
setup_serial();
return 0;
}
#ifdef CONFIG_SERIAL_TAG
void get_board_serial(struct tag_serialnr *serialnr)
{
char *serial_string;
u64 serial = 0;
serial_string = getenv("serial#");
if (serial_string)
serial = simple_strtoull(serial_string, NULL, 16);
serialnr->high = (u32)(serial >> 32);
serialnr->low = (u32)(serial & 0xffffffff);
}
#endif
int dram_init(void)
{
struct ram_info ram;
struct udevice *dev;
int ret;
ret = uclass_get_device(UCLASS_RAM, 0, &dev);
if (ret) {
debug("DRAM init failed: %d\n", ret);
return ret;
}
ret = ram_get_info(dev, &ram);
if (ret) {
debug("Cannot get DRAM size: %d\n", ret);
return ret;
}
debug("SDRAM base=%llx, size=%x\n", ram.base, (unsigned int)ram.size);
gd->ram_size = ram.size;
return 0;
}
int dram_init_banksize(void)
{
/* Reserve 0x200000 for ATF bl31 */
gd->bd->bi_dram[0].start = 0x200000;
gd->bd->bi_dram[0].size = 0x7e000000;
return 0;
}