blob: 4f4cf2480ca4f23c16d20e9909e70ee1c1ef457d [file] [log] [blame]
/*
* Process information shared by bootloader/EROM through bootinfo structure.
*
* Copyright (c) 2014 Google, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/moduleparam.h>
#include <linux/reboot.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <asm/io.h>
#include <asm/setup.h>
#include <asm/system_info.h>
/* Location used by EROM to copy bootinfo */
#define BOOTINFO_ADDRESS 0x01010000
#define BOOTINFO_SIZE 0x10000
/* EROM copies non-secure fields from OTP to a well defined memory
* location during boot process. Following structure defines the
* contents of this memory. Structure defined in berlin_bootinfo.h
* in bootloader.
*/
struct cdp_bootinfo {
u32 otp_rkek_id[2]; /* rkek id from OTP */
u32 otp_version; /* otp version */
u32 otp_market_id; /* otp market id */
u32 otp_ult[2]; /* otp ULT info */
u32 chip_version; /* bg2cdp chip version*/
u32 speed_tag; /* 0 - slow, 1 - full */
u32 leakage_current;/* leakage current info */
u32 temp_id; /* Temp ID in deg C */
u32 erom_id; /* erom id*/
u32 feature_bits; /* Feature flags */
};
static __init struct cdp_bootinfo *get_bootinfo(void)
{
void* bootinfo_v = NULL;
bootinfo_v = ioremap(BOOTINFO_ADDRESS, BOOTINFO_SIZE);
if (!bootinfo_v)
early_print(KERN_ERR "Failed to map BOOTINFO\n");
return (struct cdp_bootinfo *)bootinfo_v;
}
static __init void unmap_bootinfo(struct cdp_bootinfo *bootinfo_v)
{
iounmap(bootinfo_v);
}
/* Get SOC revision information */
static __init unsigned char get_soc_rev(struct cdp_bootinfo *pinfo)
{
return pinfo->chip_version & 0xFF;
}
static __init u64 get_rkek_id(struct cdp_bootinfo *pinfo)
{
u64 rkek_id = pinfo->otp_rkek_id[1];
rkek_id = (rkek_id << 32) | pinfo->otp_rkek_id[0];
return rkek_id;
}
static __init u32 get_otp_ver(struct cdp_bootinfo *pinfo)
{
return pinfo->otp_version;
}
static __init u32 get_otp_mktid(struct cdp_bootinfo *pinfo)
{
return pinfo->otp_market_id;
}
static __init u32 get_speed_tag(struct cdp_bootinfo *pinfo)
{
return pinfo->speed_tag;
}
static __init u32 get_otp_feature_bits(struct cdp_bootinfo *pinfo)
{
return pinfo->feature_bits;
}
static __init u64 get_otp_ult(struct cdp_bootinfo *pinfo)
{
u64 otp_ult = pinfo->otp_ult[1];
otp_ult = (otp_ult << 32) | pinfo->otp_ult[0];
return otp_ult;
}
void __init mv88de3006_proc_bootinfo(int board_rev)
{
u64 rkek_id, ult;
u32 chip_rev, ult_l, ult_h;
struct cdp_bootinfo *pinfo = get_bootinfo();
if (!pinfo)
return;
rkek_id = get_rkek_id(pinfo);
chip_rev = get_soc_rev(pinfo);
ult = get_otp_ult(pinfo);
ult_l = ult & 0xFFFFFFFF;
ult_h = ult >> 32;
/* Since bootloader is not capable of generating DTB and device
* tree does not support setting of system_rev and serial, parse
* bootinfo to get and set this.
*/
system_rev = (board_rev << 8) | chip_rev;
system_serial_low = __builtin_bswap32(rkek_id & 0xFFFFFFFF);
system_serial_high = __builtin_bswap32(rkek_id >> 32);
early_print(KERN_INFO "speed_tag: %d otp_ver: %d mkt_id: %d "
" otp_ult: 0x%08X%08X feature_bits:0x%08X\n",
get_speed_tag(pinfo),
get_otp_ver(pinfo), get_otp_mktid(pinfo),
ult_h, ult_l, get_otp_feature_bits(pinfo));
unmap_bootinfo(pinfo);
return;
}