nbhw18: dynamically enable devices in dts according to current serdes config

BugzID: 52859
This commit is contained in:
Marcel Reichmuth 2018-08-31 08:56:27 +02:00
parent b43929b7e4
commit f9ad35b73a
2 changed files with 156 additions and 3 deletions

View File

@ -51,6 +51,7 @@ DECLARE_GLOBAL_DATA_PTR;
#define BD_ADDRESS (0x0000) /* Board descriptor at beginning of EEPROM */
#define PD_ADDRESS (0x0200) /* Product descriptor */
#define PARTITION_ADDRESS (0x0600) /* Partition Table */
#define SERDES_CONFIG_ADDRESS (0x0800) /* SERDES config address */
#define DEV_CS0_BASE 0xfd000000
@ -95,9 +96,57 @@ static int _bd_init(void)
return 0;
}
typedef struct EEPROM_SERDES_CONFIG {
uint8_t magic[2];
uint8_t version;
uint8_t spare_0;
uint8_t serdes_cfg[6];
uint8_t spare1[2];
uint32_t crc32;
} EEPROM_SERDES_CONFIG;
static struct EEPROM_SERDES_CONFIG eeprom_serdes_config;
static void read_eeprom_serdes_config(void)
{
uint32_t crc;
if (i2c_read(BD_EEPROM_ADDR, SERDES_CONFIG_ADDRESS, 2, (uint8_t *)&eeprom_serdes_config, sizeof(eeprom_serdes_config))) {
goto fail;
}
crc = crc32(0, (uint8_t *)&eeprom_serdes_config, sizeof(eeprom_serdes_config)-4);
if ((eeprom_serdes_config.magic[0] != 0x83) ||
(eeprom_serdes_config.magic[1] != 0xfb) ||
(eeprom_serdes_config.version != 0x01) ||
(eeprom_serdes_config.crc32 != crc))
{
goto fail;
}
printf("Valid user serdes config found\n");
return;
fail:
memset(&eeprom_serdes_config, 0xff, sizeof(eeprom_serdes_config));
printf("No user serdes config found\n");
return;
}
static uint8_t get_eeprom_serdes_config(int serdes_index)
{
if ((serdes_index<0) || (serdes_index>=sizeof(eeprom_serdes_config.serdes_cfg))) return 0xff;
return eeprom_serdes_config.serdes_cfg[serdes_index];
}
static inline int __maybe_unused read_eeprom(void)
{
return _bd_init();
int res = _bd_init();
read_eeprom_serdes_config();
return res;
}
/* TODO: Create DA9063 Accessor Module */
@ -261,7 +310,17 @@ int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count)
board_serdes_map[5].serdes_type = SGMII2;
} else {
for (i = 0; i < ARRAY_SIZE(board_serdes_map); i++) {
enum serdes_type type = bd_get_serdes_type(i);
enum serdes_type type;
uint8_t user_config = get_eeprom_serdes_config(i);
if (user_config != 0xff) {
/* if we have a user config we use that one */
type = (enum serdes_type)user_config;
} else {
/* otherwise we use the config from the bd */
type = bd_get_serdes_type(i);
}
/* Do not touch serdes */
if (type < LAST_SERDES_TYPE) {
if ((type >= SGMII0) && (type <= SGMII2)) {
@ -633,7 +692,7 @@ static void set_devicetree_name(void)
/* add hardware versions to environment */
if (bd_get_devicetree(devicetreename, sizeof(devicetreename)) != 0) {
printf("Devicetree name not found, use legacy name\n");
strcpy(devicetreename, "am335x-nbhw16.dtb");
strcpy(devicetreename, "armada-385-nbhw18-prod1.dtb");
}
env_set("fdt_image", devicetreename);
@ -768,3 +827,95 @@ int pcie_lane_by_slot(int slot)
return -1;
}
}
static void ft_enable_node(void* blob, const char* name)
{
int node_ofs = -1;
node_ofs = fdt_path_offset(blob, name);
if (node_ofs >= 0) {
fdt_setprop_string(blob, node_ofs, "status", "okay");
}
}
static void ft_eth1_sgmii0(void *blob)
{
printf("FT: enable eth phy on sgmii0\n");
ft_enable_node(blob, "/soc/internal-regs/ethernet_phy@70000");
}
static void ft_dsa_sgmii0(void *blob)
{
printf("FT: enable dsa on sgmii0\n");
ft_enable_node(blob, "/soc/internal-regs/ethernet_dsa@70000");
ft_enable_node(blob, "/dsa_eth0@0");
}
static void ft_dsa_sgmii1(void *blob)
{
printf("FT: enable dsa on sgmii1\n");
ft_enable_node(blob, "/soc/internal-regs/ethernet_dsa@30000");
ft_enable_node(blob, "/dsa_eth1@0");
}
static void ft_sfp_sgmii1(void *blob)
{
/* Depending if the second ethernet port is in use
or not the sfp has a different interface name.
So enable the proper one. */
if (board_serdes_map[0].serdes_type==SGMII0) {
printf("FT: enable sfp for cfg1\n");
ft_enable_node(blob, "/soc/internal-regs/ethernet_sfp_cfg1@30000");
} else {
printf("FT: enable sfp for cfg0\n");
ft_enable_node(blob, "/soc/internal-regs/ethernet_sfp_cfg0@30000");
}
}
int ft_board_setup(void *blob, bd_t *bd)
{
struct serdes_map* sm;
u8 sm_count;
/* Enabled all components in dts depending on
current serdes configuration */
/* Determine SERDES configuration */
hws_board_topology_load(&sm, &sm_count);
/* Second ethernet port (SERDES0) can only be
connected to SGMII0. SO check, if we need to enable it. */
switch (board_serdes_map[0].serdes_type) {
case SGMII0 :
ft_eth1_sgmii0(blob);
break;
default :
break;
}
/* The PoE switch (SERDES1) can be connected either to
SGMII0 or SGMII1. So check, if we need to enable one of those. */
switch (board_serdes_map[1].serdes_type) {
case SGMII0 :
ft_dsa_sgmii0(blob);
break;
case SGMII1 :
ft_dsa_sgmii1(blob);
break;
default :
break;
}
/* SFP (SERDES2) can only be connected to SGMII1. So check,
if we need to enable it. */
switch (board_serdes_map[2].serdes_type) {
case SGMII1 :
ft_sfp_sgmii1(blob);
break;
default :
break;
}
return 0;
}

View File

@ -84,6 +84,8 @@
#define CONFIG_WATCHDOG
#endif
#define CONFIG_OF_BOARD_SETUP
#define CONFIG_SYS_ALT_MEMTEST
#ifndef CONFIG_SPL_BUILD