soc/cavium: Apply additional devicetree fixups
Depends on Change-Id: I0f27b92a5e074966f893399eb401eb97d784850d Apply additional devicetree fixes: * Update SCLK from boot fuses * Updated REFCLKUAA from UART ref clock divider settings * Remove disabled PEM entries * Remove phandle to disabled PEM entries Fixes: * Linux console wrong baud rate once the PL011 driver is started. * thunderx-pem kernel module crash on disable PCIe ports. Tested on Cavium SoC. Change-Id: I7e8eefd913915a879dad28dfb7801a2018ed2985 Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> Reviewed-on: https://review.coreboot.org/25382 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: David Hendricks <david.hendricks@gmail.com>
This commit is contained in:
parent
367956d58e
commit
de4410c51f
|
@ -94,6 +94,8 @@
|
||||||
(0x87E090000000ULL + ((x) << 24)) : 0)
|
(0x87E090000000ULL + ((x) << 24)) : 0)
|
||||||
|
|
||||||
/* PEM */
|
/* PEM */
|
||||||
|
#define PEM_PEMX_PF_BAR0(x) (0x87e0c0000000ULL + 0x1000000ULL * (x))
|
||||||
|
|
||||||
/* SATA */
|
/* SATA */
|
||||||
/* USB */
|
/* USB */
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,264 @@
|
||||||
#include <symbols.h>
|
#include <symbols.h>
|
||||||
#include <libbdk-boot/bdk-boot.h>
|
#include <libbdk-boot/bdk-boot.h>
|
||||||
#include <soc/ecam0.h>
|
#include <soc/ecam0.h>
|
||||||
|
#include <console/uart.h>
|
||||||
|
#include <libbdk-hal/bdk-pcie.h>
|
||||||
|
#include <soc/ecam0.h>
|
||||||
|
#include <device/pci.h>
|
||||||
|
#include <libbdk-hal/bdk-qlm.h>
|
||||||
|
#include <libbdk-hal/bdk-config.h>
|
||||||
|
#include <libbdk-arch/bdk-csrs-bgx.h>
|
||||||
|
|
||||||
|
#include <fit.h>
|
||||||
|
|
||||||
|
static const char *QLM_BGX_MODE_MAP[BDK_QLM_MODE_LAST] = {
|
||||||
|
[BDK_QLM_MODE_SGMII_4X1] = "sgmii",
|
||||||
|
[BDK_QLM_MODE_SGMII_2X1] = "sgmii",
|
||||||
|
[BDK_QLM_MODE_SGMII_1X1] = "sgmii",
|
||||||
|
[BDK_QLM_MODE_XAUI_1X4] = "xaui",
|
||||||
|
[BDK_QLM_MODE_RXAUI_2X2] = "rxaui",
|
||||||
|
[BDK_QLM_MODE_RXAUI_1X2] = "rxaui",
|
||||||
|
[BDK_QLM_MODE_XFI_4X1] = "xfi",
|
||||||
|
[BDK_QLM_MODE_XFI_2X1] = "xfi",
|
||||||
|
[BDK_QLM_MODE_XFI_1X1] = "xfi",
|
||||||
|
[BDK_QLM_MODE_XLAUI_1X4] = "xlaui",
|
||||||
|
[BDK_QLM_MODE_10G_KR_4X1] = "xfi-10g-kr",
|
||||||
|
[BDK_QLM_MODE_10G_KR_2X1] = "xfi-10g-kr",
|
||||||
|
[BDK_QLM_MODE_10G_KR_1X1] = "xfi-10g-kr",
|
||||||
|
[BDK_QLM_MODE_40G_KR4_1X4] = "xlaui-40g-kr",
|
||||||
|
[BDK_QLM_MODE_QSGMII_4X1] = "qsgmii",
|
||||||
|
};
|
||||||
|
|
||||||
|
static void dt_platform_fixup_phy(struct device_tree_node *node, char *path,
|
||||||
|
int64_t phy_address, bdk_qlm_modes_t qlm_mode)
|
||||||
|
{
|
||||||
|
char *data = NULL;
|
||||||
|
size_t size = 0;
|
||||||
|
dt_find_bin_prop(node, "qlm-mode", (void **)&data, &size);
|
||||||
|
|
||||||
|
if (!data || strncmp(data, path, 6) != 0)
|
||||||
|
return; /* No key prefix match. */
|
||||||
|
printk(BIOS_INFO, "%s: Node %s = %s\n", __func__, node->name, data);
|
||||||
|
|
||||||
|
if (strlen(path) == strlen(data) && strcmp(data, path) == 0) {
|
||||||
|
/* Keep node, remove "qlm-mode" property */
|
||||||
|
dt_delete_prop(node, "qlm-mode");
|
||||||
|
printk(BIOS_INFO, "%s: Removing qlm-mode on "
|
||||||
|
"node %s\n", __func__, node->name);
|
||||||
|
/* Linux only access the Phy via MDIO.
|
||||||
|
Remove 'phy-handle' if this option is not available */
|
||||||
|
switch (qlm_mode) {
|
||||||
|
case BDK_QLM_MODE_SGMII_4X1:
|
||||||
|
case BDK_QLM_MODE_SGMII_2X1:
|
||||||
|
case BDK_QLM_MODE_SGMII_1X1:
|
||||||
|
case BDK_QLM_MODE_QSGMII_4X1:
|
||||||
|
if ((phy_address & BDK_IF_PHY_TYPE_MASK) !=
|
||||||
|
BDK_IF_PHY_MDIO) {
|
||||||
|
dt_delete_prop(node, "phy-handle");
|
||||||
|
printk(BIOS_INFO, "%s: Removing phy-handle on "
|
||||||
|
"node %s\n", __func__, node->name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printk(BIOS_INFO, "%s: Removing node %s\n", __func__,
|
||||||
|
node->name);
|
||||||
|
/* No match, remove node */
|
||||||
|
list_remove(&node->list_node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dt_iterate_phy(struct device_tree_node *parent,
|
||||||
|
const char *name,
|
||||||
|
char *path,
|
||||||
|
int64_t phy_address,
|
||||||
|
bdk_qlm_modes_t qlm_mode)
|
||||||
|
{
|
||||||
|
struct device_tree_property *prop;
|
||||||
|
|
||||||
|
/* Check if parent itself has the required property value. */
|
||||||
|
list_for_each(prop, parent->properties, list_node) {
|
||||||
|
if (!strcmp(name, prop->prop.name)) {
|
||||||
|
dt_platform_fixup_phy(parent, path, phy_address,
|
||||||
|
qlm_mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct device_tree_node *child;
|
||||||
|
list_for_each(child, parent->children, list_node) {
|
||||||
|
dt_iterate_phy(child, name, path, phy_address, qlm_mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dt_platform_fixup_mac(struct device_tree_node *node)
|
||||||
|
{
|
||||||
|
const char *name = "local-mac-address";
|
||||||
|
u64 *localmac = NULL;
|
||||||
|
size_t size = 0;
|
||||||
|
|
||||||
|
dt_find_bin_prop(node, name, (void **)&localmac, &size);
|
||||||
|
|
||||||
|
if (!localmac)
|
||||||
|
return;
|
||||||
|
static size_t used_mac;
|
||||||
|
|
||||||
|
/* Extract our MAC address info so we can assign them */
|
||||||
|
size_t next_free_mac_address =
|
||||||
|
bdk_config_get_int(BDK_CONFIG_MAC_ADDRESS);
|
||||||
|
size_t num_free_mac_addresses =
|
||||||
|
bdk_config_get_int(BDK_CONFIG_MAC_ADDRESS_NUM);
|
||||||
|
size_t num_free_override =
|
||||||
|
bdk_config_get_int(BDK_CONFIG_MAC_ADDRESS_NUM_OVERRIDE);
|
||||||
|
if (num_free_override != -1)
|
||||||
|
num_free_mac_addresses = num_free_override;
|
||||||
|
|
||||||
|
if (size == 6) {
|
||||||
|
if (*localmac)
|
||||||
|
return;
|
||||||
|
if (used_mac < num_free_mac_addresses) {
|
||||||
|
*localmac = next_free_mac_address + used_mac;
|
||||||
|
dt_add_bin_prop(node, name, (void *)&localmac, 6);
|
||||||
|
used_mac++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printk(BIOS_INFO, "%s: Removing node %s\n", __func__, node->name);
|
||||||
|
list_remove(&node->list_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dt_iterate_mac(struct device_tree_node *parent)
|
||||||
|
{
|
||||||
|
struct device_tree_property *prop;
|
||||||
|
const char *name = "local-mac-address";
|
||||||
|
|
||||||
|
/* Check if parent itself has the required property value. */
|
||||||
|
list_for_each(prop, parent->properties, list_node) {
|
||||||
|
if (!strcmp(name, prop->prop.name))
|
||||||
|
dt_platform_fixup_mac(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct device_tree_node *child;
|
||||||
|
list_for_each(child, parent->children, list_node) {
|
||||||
|
dt_iterate_mac(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do additional device_tree modifications. */
|
||||||
|
static int dt_platform_fixup(struct device_tree_fixup *fixup,
|
||||||
|
struct device_tree *tree)
|
||||||
|
{
|
||||||
|
struct device_tree_node *dt_node;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
/* Set the sclk clock rate. */
|
||||||
|
dt_node = dt_find_node_by_path(tree->root, "soc@0/sclk", NULL, NULL, 0);
|
||||||
|
if (dt_node) {
|
||||||
|
const u32 freq = thunderx_get_io_clock();
|
||||||
|
printk(BIOS_INFO, "%s: Set SCLK to %u Hz\n", __func__, freq);
|
||||||
|
dt_add_u32_prop(dt_node, "clock-frequency", freq);
|
||||||
|
} else
|
||||||
|
printk(BIOS_ERR, "%s: Node not found. OS might miss-behave !\n",
|
||||||
|
__func__);
|
||||||
|
|
||||||
|
/* Set refclkuaa clock rate. */
|
||||||
|
dt_node = dt_find_node_by_path(tree->root, "soc@0/refclkuaa", NULL,
|
||||||
|
NULL, 0);
|
||||||
|
if (dt_node) {
|
||||||
|
const u32 freq = uart_platform_refclk();
|
||||||
|
printk(BIOS_INFO, "%s: Set REFCLKUAA to %u Hz\n", __func__,
|
||||||
|
freq);
|
||||||
|
dt_add_u32_prop(dt_node, "clock-frequency", freq);
|
||||||
|
} else
|
||||||
|
printk(BIOS_ERR, "%s: Node not found. OS might miss-behave !\n",
|
||||||
|
__func__);
|
||||||
|
|
||||||
|
/* Remove unused PEM entries */
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
char path[32];
|
||||||
|
u32 phandle = 0;
|
||||||
|
const uint64_t addr = PEM_PEMX_PF_BAR0(i);
|
||||||
|
/* Remove the node */
|
||||||
|
snprintf(path, sizeof(path), "soc@0/pci@%llx", addr);
|
||||||
|
dt_node = dt_find_node_by_path(tree->root, path, NULL, NULL, 0);
|
||||||
|
if (!dt_node || bdk_pcie_is_running(0, i)) {
|
||||||
|
printk(BIOS_INFO, "%s: ignoring %s\n", __func__, path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Store the phandle */
|
||||||
|
phandle = dt_get_phandle(dt_node);
|
||||||
|
printk(BIOS_INFO, "%s: Removing node %s\n", __func__, path);
|
||||||
|
list_remove(&dt_node->list_node);
|
||||||
|
|
||||||
|
/* Remove phandle to non existing nodes */
|
||||||
|
snprintf(path, sizeof(path), "soc@0/smmu0@%llx", SMMU_PF_BAR0);
|
||||||
|
dt_node = dt_find_node_by_path(tree->root, path, NULL, NULL, 0);
|
||||||
|
if (!dt_node) {
|
||||||
|
printk(BIOS_ERR, "%s: SMMU entry not found\n",
|
||||||
|
__func__);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
u32 *data = NULL;
|
||||||
|
size_t size = 0;
|
||||||
|
dt_find_bin_prop(dt_node, "mmu-masters", (void **)&data, &size);
|
||||||
|
if (!size) {
|
||||||
|
printk(BIOS_ERR, "%s: mmu-masters entry not found\n",
|
||||||
|
__func__);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (size_t j = 0; j < size / (sizeof(u32) * 2); j++)
|
||||||
|
if (be32_to_cpu(data[j * 2]) == phandle) {
|
||||||
|
data[j * 2] = 0;
|
||||||
|
data[j * 2 + 1] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove QLM mode entries */
|
||||||
|
size_t bgx_index, bgx_iface;
|
||||||
|
for (bgx_iface = 0; bgx_iface < 4; bgx_iface++) {
|
||||||
|
for (bgx_index = 0; bgx_index < 4; bgx_index++) {
|
||||||
|
char path[32];
|
||||||
|
int qlm = bdk_qlm_get_qlm_num(0, BDK_IF_BGX,
|
||||||
|
bgx_iface, bgx_index);
|
||||||
|
bdk_qlm_modes_t qlm_mode = (qlm == -1) ?
|
||||||
|
BDK_QLM_MODE_DISABLED :
|
||||||
|
bdk_qlm_get_mode(0, qlm);
|
||||||
|
|
||||||
|
/* BGXX_CMRX_RX_DMAC_CTL is used to mark ports as
|
||||||
|
* disabled that would otherwise be enabled */
|
||||||
|
if (qlm_mode != BDK_QLM_MODE_DISABLED) {
|
||||||
|
BDK_CSR_INIT(rx_dmac_ctl, 0,
|
||||||
|
BDK_BGXX_CMRX_RX_DMAC_CTL(bgx_iface,
|
||||||
|
bgx_index));
|
||||||
|
if (rx_dmac_ctl.u == 0)
|
||||||
|
qlm_mode = BDK_QLM_MODE_DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qlm_mode == BDK_QLM_MODE_DISABLED)
|
||||||
|
snprintf(path, sizeof(path), "0x0%x%x,disabled",
|
||||||
|
bgx_iface, bgx_index);
|
||||||
|
else
|
||||||
|
snprintf(path, sizeof(path), "0x0%x%x,%s",
|
||||||
|
bgx_iface, bgx_index,
|
||||||
|
QLM_BGX_MODE_MAP[qlm_mode]);
|
||||||
|
|
||||||
|
int64_t phy_address =
|
||||||
|
bdk_config_get_int(BDK_CONFIG_PHY_ADDRESS, 0,
|
||||||
|
bgx_iface, bgx_index);
|
||||||
|
|
||||||
|
dt_iterate_phy(tree->root, "qlm-mode", path,
|
||||||
|
phy_address, qlm_mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set local MAC address */
|
||||||
|
dt_iterate_mac(tree->root);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void soc_read_resources(device_t dev)
|
static void soc_read_resources(device_t dev)
|
||||||
{
|
{
|
||||||
|
@ -42,6 +300,17 @@ static void soc_init(device_t dev)
|
||||||
bdk_boot();
|
bdk_boot();
|
||||||
|
|
||||||
/* TODO: additional trustzone init */
|
/* TODO: additional trustzone init */
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_PAYLOAD_FIT_SUPPORT)) {
|
||||||
|
struct device_tree_fixup *dt_fixup;
|
||||||
|
|
||||||
|
dt_fixup = malloc(sizeof(*dt_fixup));
|
||||||
|
if (dt_fixup) {
|
||||||
|
dt_fixup->fixup = dt_platform_fixup;
|
||||||
|
list_insert_after(&dt_fixup->list_node,
|
||||||
|
&device_tree_fixups);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void soc_final(device_t dev)
|
static void soc_final(device_t dev)
|
||||||
|
|
Loading…
Reference in New Issue