mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-12-03 11:39:08 +00:00
kboot: propagate ATC tunables to the FDT
Signed-off-by: Sven Peter <sven@svenpeter.dev>
This commit is contained in:
parent
3b68165900
commit
28103d9003
1 changed files with 163 additions and 0 deletions
163
src/kboot.c
163
src/kboot.c
|
@ -18,6 +18,8 @@
|
||||||
|
|
||||||
#define MAX_CHOSEN_PARAMS 16
|
#define MAX_CHOSEN_PARAMS 16
|
||||||
|
|
||||||
|
#define MAX_ATC_DEVS 8
|
||||||
|
|
||||||
static void *dt = NULL;
|
static void *dt = NULL;
|
||||||
static int dt_bufsize = 0;
|
static int dt_bufsize = 0;
|
||||||
static void *initrd_start = NULL;
|
static void *initrd_start = NULL;
|
||||||
|
@ -621,6 +623,165 @@ static int dt_set_uboot(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct atc_tunable {
|
||||||
|
u32 offset : 24;
|
||||||
|
u32 size : 8;
|
||||||
|
u32 mask;
|
||||||
|
u32 value;
|
||||||
|
} PACKED;
|
||||||
|
static_assert(sizeof(struct atc_tunable) == 12, "Invalid atc_tunable size");
|
||||||
|
|
||||||
|
struct atc_tunable_info {
|
||||||
|
const char *adt_name;
|
||||||
|
const char *fdt_name;
|
||||||
|
size_t reg_offset;
|
||||||
|
size_t reg_size;
|
||||||
|
bool required;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct atc_tunable_info atc_tunables[] = {
|
||||||
|
/* global tunables applied after power on or reset */
|
||||||
|
{"tunable_ATC0AXI2AF", "apple,tunable-axi2af", 0x0, 0x4000, true},
|
||||||
|
{"tunable_ATC_FABRIC", "apple,tunable-common", 0x45000, 0x4000, true},
|
||||||
|
{"tunable_AUS_CMN_TOP", "apple,tunable-common", 0x800, 0x4000, true},
|
||||||
|
{"tunable_AUS_CMN_SHM", "apple,tunable-common", 0xa00, 0x4000, true},
|
||||||
|
{"tunable_AUSPLL_CORE", "apple,tunable-common", 0x2200, 0x4000, true},
|
||||||
|
{"tunable_AUSPLL_TOP", "apple,tunable-common", 0x2000, 0x4000, true},
|
||||||
|
{"tunable_CIO3PLL_CORE", "apple,tunable-common", 0x2a00, 0x4000, true},
|
||||||
|
{"tunable_CIO3PLL_TOP", "apple,tunable-common", 0x2800, 0x4000, true},
|
||||||
|
{"tunable_CIO_CIO3PLL_TOP", "apple,tunable-common", 0x2800, 0x4000, false},
|
||||||
|
{"tunable_USB_ACIOPHY_TOP", "apple,tunable-common", 0x0, 0x4000, true},
|
||||||
|
/* lane-specific tunables applied after a cable is connected */
|
||||||
|
{"tunable_DP_LN0_AUSPMA_TX_TOP", "apple,tunable-lane0-dp", 0xc000, 0x1000, true},
|
||||||
|
{"tunable_DP_LN1_AUSPMA_TX_TOP", "apple,tunable-lane1-dp", 0x13000, 0x1000, true},
|
||||||
|
{"tunable_USB_LN0_AUSPMA_RX_TOP", "apple,tunable-lane0-usb", 0x9000, 0x1000, true},
|
||||||
|
{"tunable_USB_LN0_AUSPMA_RX_EQ", "apple,tunable-lane0-usb", 0xa000, 0x1000, true},
|
||||||
|
{"tunable_USB_LN0_AUSPMA_RX_SHM", "apple,tunable-lane0-usb", 0xb000, 0x1000, true},
|
||||||
|
{"tunable_USB_LN0_AUSPMA_TX_TOP", "apple,tunable-lane0-usb", 0xc000, 0x1000, true},
|
||||||
|
{"tunable_USB_LN1_AUSPMA_RX_TOP", "apple,tunable-lane1-usb", 0x10000, 0x1000, true},
|
||||||
|
{"tunable_USB_LN1_AUSPMA_RX_EQ", "apple,tunable-lane1-usb", 0x11000, 0x1000, true},
|
||||||
|
{"tunable_USB_LN1_AUSPMA_RX_SHM", "apple,tunable-lane1-usb", 0x12000, 0x1000, true},
|
||||||
|
{"tunable_USB_LN1_AUSPMA_TX_TOP", "apple,tunable-lane1-usb", 0x13000, 0x1000, true},
|
||||||
|
{"tunable_CIO_LN0_AUSPMA_RX_TOP", "apple,tunable-lane0-cio", 0x9000, 0x1000, true},
|
||||||
|
{"tunable_CIO_LN0_AUSPMA_RX_EQ", "apple,tunable-lane0-cio", 0xa000, 0x1000, true},
|
||||||
|
{"tunable_CIO_LN0_AUSPMA_RX_SHM", "apple,tunable-lane0-cio", 0xb000, 0x1000, true},
|
||||||
|
{"tunable_CIO_LN0_AUSPMA_TX_TOP", "apple,tunable-lane0-cio", 0xc000, 0x1000, true},
|
||||||
|
{"tunable_CIO_LN1_AUSPMA_RX_TOP", "apple,tunable-lane1-cio", 0x10000, 0x1000, true},
|
||||||
|
{"tunable_CIO_LN1_AUSPMA_RX_EQ", "apple,tunable-lane1-cio", 0x11000, 0x1000, true},
|
||||||
|
{"tunable_CIO_LN1_AUSPMA_RX_SHM", "apple,tunable-lane1-cio", 0x12000, 0x1000, true},
|
||||||
|
{"tunable_CIO_LN1_AUSPMA_TX_TOP", "apple,tunable-lane1-cio", 0x13000, 0x1000, true},
|
||||||
|
};
|
||||||
|
|
||||||
|
static int dt_append_atc_tunable(int adt_node, int fdt_node,
|
||||||
|
const struct atc_tunable_info *tunable_info)
|
||||||
|
{
|
||||||
|
u32 tunables_len;
|
||||||
|
const struct atc_tunable *tunable_adt =
|
||||||
|
adt_getprop(adt, adt_node, tunable_info->adt_name, &tunables_len);
|
||||||
|
|
||||||
|
if (!tunable_adt) {
|
||||||
|
printf("ADT: tunable %s not found\n", tunable_info->adt_name);
|
||||||
|
|
||||||
|
if (tunable_info->required)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tunables_len % sizeof(*tunable_adt)) {
|
||||||
|
printf("ADT: tunable %s with invalid length %d\n", tunable_info->adt_name, tunables_len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 n_tunables = tunables_len / sizeof(*tunable_adt);
|
||||||
|
for (size_t j = 0; j < n_tunables; j++) {
|
||||||
|
const struct atc_tunable *tunable = &tunable_adt[j];
|
||||||
|
|
||||||
|
if (tunable->size != 32) {
|
||||||
|
printf("kboot: ATC tunable has invalid size %d\n", tunable->size);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tunable->offset % (tunable->size / 8)) {
|
||||||
|
printf("kboot: ATC tunable has unaligned offset %x\n", tunable->offset);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tunable->offset + (tunable->size / 8) > tunable_info->reg_size) {
|
||||||
|
printf("kboot: ATC tunable has invalid offset %x\n", tunable->offset);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fdt_appendprop_u32(dt, fdt_node, tunable_info->fdt_name,
|
||||||
|
tunable->offset + tunable_info->reg_offset) < 0)
|
||||||
|
return -1;
|
||||||
|
if (fdt_appendprop_u32(dt, fdt_node, tunable_info->fdt_name, tunable->mask) < 0)
|
||||||
|
return -1;
|
||||||
|
if (fdt_appendprop_u32(dt, fdt_node, tunable_info->fdt_name, tunable->value) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dt_copy_atc_tunables(const char *adt_path, const char *dt_alias)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
int adt_node = adt_path_offset(adt, adt_path);
|
||||||
|
if (adt_node < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const char *fdt_path = fdt_get_alias(dt, dt_alias);
|
||||||
|
if (fdt_path == NULL) {
|
||||||
|
printf("FDT: Unable to find alias %s\n", dt_alias);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fdt_node = fdt_path_offset(dt, fdt_path);
|
||||||
|
if (fdt_node < 0) {
|
||||||
|
printf("FDT: Unable to find path %s for alias %s\n", fdt_path, dt_alias);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sizeof(atc_tunables) / sizeof(*atc_tunables); ++i) {
|
||||||
|
ret = dt_append_atc_tunable(adt_node, fdt_node, &atc_tunables[i]);
|
||||||
|
if (ret)
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
/*
|
||||||
|
* USB3 and Thunderbolt won't work if something went wrong. Clean up to make
|
||||||
|
* sure we don't leave half-filled properties around so that we can at least
|
||||||
|
* try to boot with USB2 support only.
|
||||||
|
*/
|
||||||
|
for (size_t i = 0; i < sizeof(atc_tunables) / sizeof(*atc_tunables); ++i)
|
||||||
|
fdt_delprop(dt, fdt_node, atc_tunables[i].fdt_name);
|
||||||
|
|
||||||
|
printf("FDT: Unable to setup ATC tunables for %s - USB3/Thunderbolt will not work\n", adt_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dt_set_atc_tunables(void)
|
||||||
|
{
|
||||||
|
char adt_path[32];
|
||||||
|
char fdt_alias[32];
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_ATC_DEVS; ++i) {
|
||||||
|
memset(adt_path, 0, sizeof(adt_path));
|
||||||
|
snprintf(adt_path, sizeof(adt_path), "/arm-io/atc-phy%d", i);
|
||||||
|
|
||||||
|
memset(fdt_alias, 0, sizeof(adt_path));
|
||||||
|
snprintf(fdt_alias, sizeof(fdt_alias), "atcphy%d", i);
|
||||||
|
|
||||||
|
dt_copy_atc_tunables(adt_path, fdt_alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int dt_disable_missing_devs(const char *adt_prefix, const char *dt_prefix, int max_devs)
|
static int dt_disable_missing_devs(const char *adt_prefix, const char *dt_prefix, int max_devs)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
@ -801,6 +962,8 @@ int kboot_prepare_dt(void *fdt)
|
||||||
return -1;
|
return -1;
|
||||||
if (dt_set_uboot())
|
if (dt_set_uboot())
|
||||||
return -1;
|
return -1;
|
||||||
|
if (dt_set_atc_tunables())
|
||||||
|
return -1;
|
||||||
if (dt_disable_missing_devs("usb-drd", "usb@", 8))
|
if (dt_disable_missing_devs("usb-drd", "usb@", 8))
|
||||||
return -1;
|
return -1;
|
||||||
if (dt_disable_missing_devs("i2c", "i2c@", 8))
|
if (dt_disable_missing_devs("i2c", "i2c@", 8))
|
||||||
|
|
Loading…
Reference in a new issue