mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-22 20:58:22 +00:00
arm: mvebu: turris_omnia: Implement getting board information from MCU
Implement reading board serial number, first MAC address and board version from MCU. MCU supports board information if the FEAT_BOARD_INFO feature bit is set in MCU features. Prefer getting board information from MCU if supported, fallback to Atmel SHA chip. Signed-off-by: Marek Behún <kabel@kernel.org> Reviewed-by: Stefan Roese <sr@denx.de>
This commit is contained in:
parent
ed8d3bd11a
commit
2f1b88affa
5 changed files with 145 additions and 30 deletions
|
@ -11,6 +11,7 @@
|
||||||
#include <atsha204a-i2c.h>
|
#include <atsha204a-i2c.h>
|
||||||
|
|
||||||
#include "turris_atsha_otp.h"
|
#include "turris_atsha_otp.h"
|
||||||
|
#include "turris_common.h"
|
||||||
|
|
||||||
#define TURRIS_ATSHA_OTP_VERSION 0
|
#define TURRIS_ATSHA_OTP_VERSION 0
|
||||||
#define TURRIS_ATSHA_OTP_SERIAL 1
|
#define TURRIS_ATSHA_OTP_SERIAL 1
|
||||||
|
@ -32,26 +33,6 @@ static struct udevice *get_atsha204a_dev(void)
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void increment_mac(u8 *mac)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 5; i >= 3; i--) {
|
|
||||||
mac[i] += 1;
|
|
||||||
if (mac[i])
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_mac_if_invalid(int i, u8 *mac)
|
|
||||||
{
|
|
||||||
u8 oldmac[6];
|
|
||||||
|
|
||||||
if (is_valid_ethaddr(mac) &&
|
|
||||||
!eth_env_get_enetaddr_by_index("eth", i, oldmac))
|
|
||||||
eth_env_set_enetaddr_by_index("eth", i, mac);
|
|
||||||
}
|
|
||||||
|
|
||||||
int turris_atsha_otp_init_mac_addresses(int first_idx)
|
int turris_atsha_otp_init_mac_addresses(int first_idx)
|
||||||
{
|
{
|
||||||
struct udevice *dev = get_atsha204a_dev();
|
struct udevice *dev = get_atsha204a_dev();
|
||||||
|
@ -84,11 +65,7 @@ int turris_atsha_otp_init_mac_addresses(int first_idx)
|
||||||
mac[4] = mac1[2];
|
mac[4] = mac1[2];
|
||||||
mac[5] = mac1[3];
|
mac[5] = mac1[3];
|
||||||
|
|
||||||
set_mac_if_invalid((first_idx + 0) % 3, mac);
|
turris_init_mac_addresses(first_idx, mac);
|
||||||
increment_mac(mac);
|
|
||||||
set_mac_if_invalid((first_idx + 1) % 3, mac);
|
|
||||||
increment_mac(mac);
|
|
||||||
set_mac_if_invalid((first_idx + 2) % 3, mac);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
42
board/CZ.NIC/turris_common.c
Normal file
42
board/CZ.NIC/turris_common.c
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2017 Marek Behún <kabel@kernel.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <env.h>
|
||||||
|
#include <net.h>
|
||||||
|
|
||||||
|
#include "turris_common.h"
|
||||||
|
|
||||||
|
static void increment_mac(u8 *mac)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 5; i >= 3; i--) {
|
||||||
|
mac[i] += 1;
|
||||||
|
if (mac[i])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_mac_if_invalid(int i, u8 *mac)
|
||||||
|
{
|
||||||
|
u8 oldmac[6];
|
||||||
|
|
||||||
|
if (is_valid_ethaddr(mac) &&
|
||||||
|
!eth_env_get_enetaddr_by_index("eth", i, oldmac))
|
||||||
|
eth_env_set_enetaddr_by_index("eth", i, mac);
|
||||||
|
}
|
||||||
|
|
||||||
|
void turris_init_mac_addresses(int first_idx, const u8 *first_mac)
|
||||||
|
{
|
||||||
|
u8 mac[6];
|
||||||
|
|
||||||
|
memcpy(mac, first_mac, sizeof(mac));
|
||||||
|
|
||||||
|
set_mac_if_invalid((first_idx + 0) % 3, mac);
|
||||||
|
increment_mac(mac);
|
||||||
|
set_mac_if_invalid((first_idx + 1) % 3, mac);
|
||||||
|
increment_mac(mac);
|
||||||
|
set_mac_if_invalid((first_idx + 2) % 3, mac);
|
||||||
|
}
|
10
board/CZ.NIC/turris_common.h
Normal file
10
board/CZ.NIC/turris_common.h
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
|
||||||
|
#ifndef TURRIS_COMMON_H
|
||||||
|
#define TURRIS_COMMON_H
|
||||||
|
|
||||||
|
#include <asm/types.h>
|
||||||
|
|
||||||
|
void turris_init_mac_addresses(int first_idx, const u8 *first_mac);
|
||||||
|
|
||||||
|
#endif
|
|
@ -2,4 +2,4 @@
|
||||||
#
|
#
|
||||||
# Copyright (C) 2017 Marek Behún <kabel@kernel.org>
|
# Copyright (C) 2017 Marek Behún <kabel@kernel.org>
|
||||||
|
|
||||||
obj-y := turris_omnia.o ../turris_atsha_otp.o
|
obj-y := turris_omnia.o ../turris_atsha_otp.o ../turris_common.o
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/arch/cpu.h>
|
#include <asm/arch/cpu.h>
|
||||||
#include <asm/arch/soc.h>
|
#include <asm/arch/soc.h>
|
||||||
|
#include <asm/unaligned.h>
|
||||||
#include <dm/uclass.h>
|
#include <dm/uclass.h>
|
||||||
#include <dt-bindings/gpio/gpio.h>
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
#include <fdt_support.h>
|
#include <fdt_support.h>
|
||||||
|
@ -25,12 +26,14 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <turris-omnia-mcu-interface.h>
|
#include <turris-omnia-mcu-interface.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
|
#include <linux/bitrev.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <u-boot/crc.h>
|
#include <u-boot/crc.h>
|
||||||
|
|
||||||
#include "../drivers/ddr/marvell/a38x/ddr3_init.h"
|
#include "../drivers/ddr/marvell/a38x/ddr3_init.h"
|
||||||
#include <../serdes/a38x/high_speed_env_spec.h>
|
#include <../serdes/a38x/high_speed_env_spec.h>
|
||||||
#include "../turris_atsha_otp.h"
|
#include "../turris_atsha_otp.h"
|
||||||
|
#include "../turris_common.h"
|
||||||
|
|
||||||
DECLARE_GLOBAL_DATA_PTR;
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
|
@ -186,6 +189,70 @@ static bool omnia_mcu_has_feature(u32 feature)
|
||||||
return feature & features;
|
return feature & features;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u32 omnia_mcu_crc32(const void *p, size_t len)
|
||||||
|
{
|
||||||
|
u32 val, crc = 0;
|
||||||
|
|
||||||
|
compiletime_assert(!(len % 4), "length has to be a multiple of 4");
|
||||||
|
|
||||||
|
while (len) {
|
||||||
|
val = bitrev32(get_unaligned_le32(p));
|
||||||
|
crc = crc32(crc, (void *)&val, 4);
|
||||||
|
p += 4;
|
||||||
|
len -= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ~bitrev32(crc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Can only be called after relocation, since it needs cleared BSS */
|
||||||
|
static int omnia_mcu_board_info(char *serial, u8 *mac, char *version)
|
||||||
|
{
|
||||||
|
static u8 reply[17];
|
||||||
|
static bool cached;
|
||||||
|
|
||||||
|
if (!cached) {
|
||||||
|
u8 csum;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = omnia_mcu_read(CMD_BOARD_INFO_GET, reply, sizeof(reply));
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (reply[0] != 16)
|
||||||
|
return -EBADMSG;
|
||||||
|
|
||||||
|
csum = reply[16];
|
||||||
|
reply[16] = 0;
|
||||||
|
|
||||||
|
if ((omnia_mcu_crc32(&reply[1], 16) & 0xff) != csum)
|
||||||
|
return -EBADMSG;
|
||||||
|
|
||||||
|
cached = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serial) {
|
||||||
|
const char *serial_env;
|
||||||
|
|
||||||
|
serial_env = env_get("serial#");
|
||||||
|
if (serial_env && strlen(serial_env) == 16) {
|
||||||
|
strcpy(serial, serial_env);
|
||||||
|
} else {
|
||||||
|
sprintf(serial, "%016llX",
|
||||||
|
get_unaligned_le64(&reply[1]));
|
||||||
|
env_set("serial#", serial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mac)
|
||||||
|
memcpy(mac, &reply[9], ETH_ALEN);
|
||||||
|
|
||||||
|
if (version)
|
||||||
|
sprintf(version, "%u", reply[15]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void enable_a385_watchdog(unsigned int timeout_minutes)
|
static void enable_a385_watchdog(unsigned int timeout_minutes)
|
||||||
{
|
{
|
||||||
struct sar_freq_modes sar_freq;
|
struct sar_freq_modes sar_freq;
|
||||||
|
@ -965,13 +1032,23 @@ int board_late_init(void)
|
||||||
|
|
||||||
int checkboard(void)
|
int checkboard(void)
|
||||||
{
|
{
|
||||||
char serial[17];
|
char serial[17], version[4];
|
||||||
|
bool has_version;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = turris_atsha_otp_get_serial_number(serial);
|
|
||||||
printf(" MCU type: %s\n", omnia_get_mcu_type());
|
printf(" MCU type: %s\n", omnia_get_mcu_type());
|
||||||
printf(" MCU version: %s\n", omnia_get_mcu_version());
|
printf(" MCU version: %s\n", omnia_get_mcu_version());
|
||||||
printf(" RAM size: %i MiB\n", omnia_get_ram_size_gb() * 1024);
|
printf(" RAM size: %i MiB\n", omnia_get_ram_size_gb() * 1024);
|
||||||
|
|
||||||
|
if (omnia_mcu_has_feature(FEAT_BOARD_INFO)) {
|
||||||
|
err = omnia_mcu_board_info(serial, NULL, version);
|
||||||
|
has_version = !err;
|
||||||
|
} else {
|
||||||
|
err = turris_atsha_otp_get_serial_number(serial);
|
||||||
|
has_version = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" Board version: %s\n", has_version ? version : "unknown");
|
||||||
printf(" Serial Number: %s\n", !err ? serial : "unknown");
|
printf(" Serial Number: %s\n", !err ? serial : "unknown");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -979,8 +1056,17 @@ int checkboard(void)
|
||||||
|
|
||||||
int misc_init_r(void)
|
int misc_init_r(void)
|
||||||
{
|
{
|
||||||
turris_atsha_otp_init_mac_addresses(1);
|
if (omnia_mcu_has_feature(FEAT_BOARD_INFO)) {
|
||||||
turris_atsha_otp_init_serial_number();
|
char serial[17];
|
||||||
|
u8 first_mac[6];
|
||||||
|
|
||||||
|
if (!omnia_mcu_board_info(serial, first_mac, NULL))
|
||||||
|
turris_init_mac_addresses(1, first_mac);
|
||||||
|
} else {
|
||||||
|
turris_atsha_otp_init_mac_addresses(1);
|
||||||
|
turris_atsha_otp_init_serial_number();
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue