diff --git a/src/isp.c b/src/isp.c index 716402ca..233fdcad 100644 --- a/src/isp.c +++ b/src/isp.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: MIT */ #include "adt.h" +#include "dart.h" #include "pmgr.h" #include "utils.h" @@ -21,19 +22,79 @@ struct dart_tunables { u64 set; }; +static void isp_ctrr_init_t8020(u64 base, const struct dart_tunables *config, u32 length) +{ + /* DART error handler gets stuck w/o these */ + write32(base + DART_T8020_ENABLED_STREAMS, 0x1); + write32(base + 0x2f0, 0x0); + write32(base + DART_T8020_STREAM_SELECT, 0xffffffff); + write32(base + DART_T8020_STREAM_COMMAND, DART_T8020_STREAM_COMMAND_INVALIDATE); + + /* I think these lock CTRR? Configurable __TEXT read-only region? */ + int count = length / sizeof(*config); + for (int i = 0; i < count; i++) { + u64 offset = config->offset & 0xffff; + u32 set = config->set & 0xffffffff; + mask32(base + offset, read32(base + offset), set); + config++; + } + + write32(base + DART_T8020_TCR_OFF, DART_T8020_TCR_TRANSLATE_ENABLE); + write32(base + 0x13c, 0x20000); +} + +static void isp_ctrr_init_t6000(u64 base, const struct dart_tunables *config, u32 length) +{ + write32(base + DART_T8020_ENABLED_STREAMS, 0x1); + write32(base + 0x2f0, 0x0); + write32(base + DART_T8020_STREAM_SELECT, 0xffff); // diff from t8020 + write32(base + DART_T8020_STREAM_COMMAND, 0x0); + + int count = length / sizeof(*config); + for (int i = 0; i < count; i++) { + u64 offset = config->offset & 0xffff; + u32 set = config->set & 0xffffffff; + mask32(base + offset, read32(base + offset), set); + config++; + } + + write32(base + DART_T8020_TCR_OFF, DART_T8020_TCR_TRANSLATE_ENABLE); + write32(base + 0x13c, 0x20000); +} + int isp_init(void) { int err = 0; - const char *path = "/arm-io/isp"; - const char *dart_path = "/arm-io/dart-isp"; - if (pmgr_adt_power_enable(path) < 0) - return -1; + const char *isp_path = "/arm-io/isp"; + const char *dart_path = "/arm-io/dart-isp"; int adt_path[8]; int node = adt_path_offset_trace(adt, dart_path, adt_path); if (node < 0) { - printf("isp: Error getting node %s\n", dart_path); + isp_path = "/arm-io/isp0"; + dart_path = "/arm-io/dart-isp0"; + node = adt_path_offset_trace(adt, dart_path, adt_path); + } + if (node < 0) + return 0; + + if (pmgr_adt_power_enable(isp_path) < 0) + return -1; + + enum dart_type_t type; + const char *type_s; + if (adt_is_compatible(adt, node, "dart,t8020")) { + type = DART_T8020; + type_s = "t8020"; + } else if (adt_is_compatible(adt, node, "dart,t6000")) { + type = DART_T6000; + type_s = "t6000"; + } else if (adt_is_compatible(adt, node, "dart,t8110")) { + type = DART_T8110; + type_s = "t8110"; + } else { + printf("isp: dart %s is of an unknown type\n", dart_path); return -1; } @@ -49,7 +110,7 @@ int isp_init(void) snprintf(prop, sizeof(prop), "dart-tunables-instance-%u", index); const struct dart_tunables *config = adt_getprop(adt, node, prop, &length); if (!config || !length) { - printf("isp: Error getting ADT node %s property %s.\n", path, prop); + printf("isp: Error getting ADT node %s property %s.\n", isp_path, prop); err = -1; goto out; } @@ -58,26 +119,21 @@ int isp_init(void) if (err < 0) goto out; - /* DART error handler gets stuck w/o these */ - write32(base + DART_T8020_ENABLED_STREAMS, 0x1); - write32(base + 0x2f0, 0x0); - write32(base + DART_T8020_STREAM_SELECT, 0xffffffff); - write32(base + DART_T8020_STREAM_COMMAND, DART_T8020_STREAM_COMMAND_INVALIDATE); - - /* I think these lock CTRR? Coproc __TEXT read-only region? */ - int count = length / sizeof(*config); - for (int i = 0; i < count; i++) { - u64 offset = config->offset & 0xffff; - u32 set = config->set & 0xffffffff; - mask32(base + offset, read32(base + offset), set); - config++; + switch (type) { + case DART_T8020: + isp_ctrr_init_t8020(base, config, length); + break; + case DART_T6000: + isp_ctrr_init_t6000(base, config, length); + break; + case DART_T8110: + printf("isp: warning: dart type %s not tested yet!\n", type_s); + isp_ctrr_init_t8020(base, config, length); + break; } - - write32(base + DART_T8020_TCR_OFF, DART_T8020_TCR_TRANSLATE_ENABLE); - write32(base + 0x13c, 0x20000); } out: - pmgr_adt_power_disable(path); + pmgr_adt_power_disable(isp_path); return err; } diff --git a/src/kboot.c b/src/kboot.c index 18438d07..74524b08 100644 --- a/src/kboot.c +++ b/src/kboot.c @@ -1804,13 +1804,12 @@ struct isp_segment_ranges { static int dt_set_isp_fwdata(void) { const char *path = "isp"; - const char *adt_path = "/arm-io/isp"; - int adt_node = adt_path_offset(adt, adt_path); - if (adt_node < 0) { - printf("ADT: '%s' node not found\n", adt_path); + int adt_node = adt_path_offset(adt, "/arm-io/isp"); + if (adt_node < 0) + adt_node = adt_path_offset(adt, "/arm-io/isp0"); + if (adt_node < 0) return 0; - } u32 segments_len; struct isp_segment_ranges *segments;