From 9ef073a271a8cb126098d09cdf2a233c5ff67fde Mon Sep 17 00:00:00 2001 From: Eileen Yoon Date: Tue, 15 Aug 2023 02:16:19 +0900 Subject: [PATCH 01/15] dapf: Support reg indexing + add ISP Also enable power if domain exists. Signed-off-by: Eileen Yoon --- src/dapf.c | 39 +++++++++++++++++++++++++++++++-------- src/dapf.h | 2 +- src/proxy.c | 2 +- 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/dapf.c b/src/dapf.c index cbeb576f2..332a1805b 100644 --- a/src/dapf.c +++ b/src/dapf.c @@ -5,6 +5,7 @@ #include "assert.h" #include "malloc.h" #include "memory.h" +#include "pmgr.h" #include "string.h" #include "utils.h" @@ -83,7 +84,7 @@ static int dapf_init_t8110(const char *path, u64 base, int node) return 0; } -int dapf_init(const char *path) +int dapf_init(const char *path, int index) { int ret; int dart_path[8]; @@ -93,8 +94,14 @@ int dapf_init(const char *path) return -1; } + u32 pwr; + if (!adt_getprop(adt, node, "clock-gates", &pwr)) + pwr = 0; + if (pwr && (pmgr_adt_power_enable(path) < 0)) + return -1; + u64 base; - if (adt_get_reg(adt, dart_path, "reg", 1, &base, NULL) < 0) { + if (adt_get_reg(adt, dart_path, "reg", index, &base, NULL) < 0) { printf("dapf: Error getting DAPF %s base address.\n", path); return -1; } @@ -110,28 +117,44 @@ int dapf_init(const char *path) return -1; } + if (pwr) + pmgr_adt_power_disable(path); + if (!ret) printf("dapf: Initialized %s\n", path); return ret; } -const char *dapf_paths[] = {"/arm-io/dart-aop", "/arm-io/dart-mtp", "/arm-io/dart-pmp", NULL}; +struct entry { + const char *path; + int index; +}; + +struct entry dapf_entries[] = { + {"/arm-io/dart-aop", 1}, + {"/arm-io/dart-mtp", 1}, + {"/arm-io/dart-pmp", 1}, + {"/arm-io/dart-isp", 5}, + {NULL, -1}, +}; int dapf_init_all(void) { int ret = 0; int count = 0; - for (const char **path = dapf_paths; *path; path++) { - if (adt_path_offset(adt, *path) < 0) + struct entry *entry = dapf_entries; + while (entry->path != NULL) { + if (adt_path_offset(adt, entry->path) < 0) { + entry++; continue; - - if (dapf_init(*path) < 0) { + } + if (dapf_init(entry->path, entry->index) < 0) { ret = -1; } + entry++; count += 1; } - return ret ? ret : count; } diff --git a/src/dapf.h b/src/dapf.h index 2a7e1bf12..0d36d5625 100644 --- a/src/dapf.h +++ b/src/dapf.h @@ -4,6 +4,6 @@ #define DAPF_H int dapf_init_all(void); -int dapf_init(const char *path); +int dapf_init(const char *path, int index); #endif diff --git a/src/proxy.c b/src/proxy.c index fca53ca38..05dcd7006 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -586,7 +586,7 @@ int proxy_process(ProxyRequest *request, ProxyReply *reply) reply->retval = dapf_init_all(); break; case P_DAPF_INIT: - reply->retval = dapf_init((const char *)request->args[0]); + reply->retval = dapf_init((const char *)request->args[0], 1); break; case P_CPUFREQ_INIT: From 336dfb0aa7abb373b0f7cb82193a6fb1d4c5e64e Mon Sep 17 00:00:00 2001 From: Eileen Yoon Date: Sat, 19 Aug 2023 03:54:54 +0900 Subject: [PATCH 02/15] kboot: Reserve ISP firmware Signed-off-by: Eileen Yoon --- src/kboot.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/kboot.c b/src/kboot.c index e37499d07..20a3d5bad 100644 --- a/src/kboot.c +++ b/src/kboot.c @@ -1791,6 +1791,68 @@ static int dt_set_sio_fwdata(void) return 0; } +struct isp_segment_ranges { + u64 phys; + u64 iova; + u64 remap; + u32 size; + u32 unk; +} PACKED; + +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); + return 0; + } + + u32 segments_len; + struct isp_segment_ranges *segments; + segments = + (struct isp_segment_ranges *)adt_getprop(adt, adt_node, "segment-ranges", &segments_len); + if (!segments || !segments_len) + bail("ADT: invalid ISP segment-ranges\n"); + + int count = segments_len / sizeof(*segments); + for (int i = 0; i < count; i++) + segments[i].remap = segments[i].iova; // match sio segment-ranges + + u64 ctrr_size; + switch (os_firmware.version) { + case V12_1: // haven't checked, probably right + case V12_2: // " + case V12_3: + case V12_3_1: + case V12_4: + case V12_5: + ctrr_size = 0x1800000; + break; + case V13_5: + ctrr_size = 0x1000000; + break; + default: + bail("FDT: couldn't get ISP CTRR size (%d)\n", os_firmware.version); + } + + u64 heap_base = segments[count - 1].iova + segments[count - 1].size; + u64 heap_size = ctrr_size - heap_base; + + int fdt_node = fdt_path_offset(dt, path); + if (fdt_node < 0) + bail("FDT: '%s' node not found\n", path); + + if (fdt_appendprop_u64(dt, fdt_node, "apple,isp-heap-base", heap_base)) + bail("FDT: couldn't set apple,isp-heap-base\n"); + if (fdt_appendprop_u64(dt, fdt_node, "apple,isp-heap-size", heap_size)) + bail("FDT: couldn't set apple,isp-heap-size\n"); + + return 0; +} + static int dt_disable_missing_devs(const char *adt_prefix, const char *dt_prefix, int max_devs) { int ret = -1; @@ -2101,6 +2163,10 @@ int kboot_prepare_dt(void *fdt) return -1; if (dt_set_sio_fwdata()) return -1; + if (dt_set_isp_fwdata()) + return -1; + if (dt_reserve_asc_firmware("/arm-io/isp", "isp")) + return -1; #ifndef RELEASE if (dt_transfer_virtios()) return 1; From 0098f4a3ff12260486e85b10cd1b0ff50eca047e Mon Sep 17 00:00:00 2001 From: Eileen Yoon Date: Wed, 23 Aug 2023 04:02:24 +0900 Subject: [PATCH 03/15] isp: tmp - Add t8020 ISP DART workaround Signed-off-by: Eileen Yoon --- Makefile | 1 + src/isp.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/isp.h | 10 +++++++ src/kboot.c | 2 ++ 4 files changed, 96 insertions(+) create mode 100644 src/isp.c create mode 100644 src/isp.h diff --git a/Makefile b/Makefile index 5ada7a245..c54150ed8 100644 --- a/Makefile +++ b/Makefile @@ -103,6 +103,7 @@ OBJECTS := \ i2c.o \ iodev.o \ iova.o \ + isp.o \ kboot.o \ main.o \ mcc.o \ diff --git a/src/isp.c b/src/isp.c new file mode 100644 index 000000000..716402ca2 --- /dev/null +++ b/src/isp.c @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: MIT */ + +#include "adt.h" +#include "pmgr.h" +#include "utils.h" + +/* ISP DART has some quirks we must work around */ + +#define DART_T8020_ENABLED_STREAMS 0xfc +#define DART_T8020_STREAM_COMMAND 0x20 +#define DART_T8020_STREAM_SELECT 0x34 +#define DART_T8020_TCR_OFF 0x100 +#define DART_T8020_TTBR 0x200 + +#define DART_T8020_TCR_TRANSLATE_ENABLE BIT(7) +#define DART_T8020_STREAM_COMMAND_INVALIDATE BIT(20) + +struct dart_tunables { + u64 offset; + u64 clear; + u64 set; +}; + +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; + + 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); + return -1; + } + + int dart_domain_count = 3; // TODO get from dt + for (int index = 0; index < dart_domain_count; index++) { + u64 base; + err = adt_get_reg(adt, adt_path, "reg", index, &base, NULL); + if (err < 0) + goto out; + + u32 length; + char prop[32] = "dart-tunables-instance"; + 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); + err = -1; + goto out; + } + + err = adt_get_reg(adt, adt_path, "reg", index, &base, NULL); + 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++; + } + + write32(base + DART_T8020_TCR_OFF, DART_T8020_TCR_TRANSLATE_ENABLE); + write32(base + 0x13c, 0x20000); + } + +out: + pmgr_adt_power_disable(path); + return err; +} diff --git a/src/isp.h b/src/isp.h new file mode 100644 index 000000000..af83b3446 --- /dev/null +++ b/src/isp.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: MIT */ + +#ifndef ISP_H +#define ISP_H + +#include "types.h" + +int isp_init(void); + +#endif diff --git a/src/kboot.c b/src/kboot.c index 20a3d5bad..137be7b9b 100644 --- a/src/kboot.c +++ b/src/kboot.c @@ -10,6 +10,7 @@ #include "devicetree.h" #include "exception.h" #include "firmware.h" +#include "isp.h" #include "malloc.h" #include "memory.h" #include "pcie.h" @@ -2196,6 +2197,7 @@ int kboot_boot(void *kernel) usb_init(); pcie_init(); dapf_init_all(); + isp_init(); printf("Setting SMP mode to WFE...\n"); smp_set_wfe_mode(true); From d8ceccad33a05b49565a2e8e558a139d68b9af51 Mon Sep 17 00:00:00 2001 From: Eileen Yoon Date: Sat, 2 Sep 2023 11:03:33 +0900 Subject: [PATCH 04/15] isp/kboot: Prelim T6000 support Handle /arm-io/isp0 and diff CTRR writes. Signed-off-by: Eileen Yoon --- src/isp.c | 102 ++++++++++++++++++++++++++++++++++++++++------------ src/kboot.c | 9 +++-- 2 files changed, 83 insertions(+), 28 deletions(-) diff --git a/src/isp.c b/src/isp.c index 716402ca2..233fdcad9 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 137be7b9b..96aaf9ee2 100644 --- a/src/kboot.c +++ b/src/kboot.c @@ -1803,13 +1803,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; From caa40210fafbb54ccb9e1b5abbc1485096e2c152 Mon Sep 17 00:00:00 2001 From: Eileen Yoon Date: Sat, 2 Sep 2023 22:44:49 +0900 Subject: [PATCH 05/15] isp: t6000 13c index 0 flag Signed-off-by: Eileen Yoon --- src/isp.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/isp.c b/src/isp.c index 233fdcad9..2e6dac81b 100644 --- a/src/isp.c +++ b/src/isp.c @@ -43,7 +43,7 @@ static void isp_ctrr_init_t8020(u64 base, const struct dart_tunables *config, u3 write32(base + 0x13c, 0x20000); } -static void isp_ctrr_init_t6000(u64 base, const struct dart_tunables *config, u32 length) +static void isp_ctrr_init_t6000(u64 base, const struct dart_tunables *config, u32 length, int index) { write32(base + DART_T8020_ENABLED_STREAMS, 0x1); write32(base + 0x2f0, 0x0); @@ -59,7 +59,10 @@ static void isp_ctrr_init_t6000(u64 base, const struct dart_tunables *config, u3 } write32(base + DART_T8020_TCR_OFF, DART_T8020_TCR_TRANSLATE_ENABLE); - write32(base + 0x13c, 0x20000); + u32 val = 0x20000; + if (!index) + val |= 0x100; + write32(base + 0x13c, val); } int isp_init(void) @@ -124,7 +127,7 @@ int isp_init(void) isp_ctrr_init_t8020(base, config, length); break; case DART_T6000: - isp_ctrr_init_t6000(base, config, length); + isp_ctrr_init_t6000(base, config, length, index); break; case DART_T8110: printf("isp: warning: dart type %s not tested yet!\n", type_s); From f81b2c3678c30472d8492fd0a3ff4f24ca1768fe Mon Sep 17 00:00:00 2001 From: Eileen Yoon Date: Sat, 2 Sep 2023 23:06:18 +0900 Subject: [PATCH 06/15] isp: t6000 stream select mask Signed-off-by: Eileen Yoon --- src/isp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/isp.c b/src/isp.c index 2e6dac81b..0eb710c24 100644 --- a/src/isp.c +++ b/src/isp.c @@ -47,7 +47,8 @@ static void isp_ctrr_init_t6000(u64 base, const struct dart_tunables *config, u3 { write32(base + DART_T8020_ENABLED_STREAMS, 0x1); write32(base + 0x2f0, 0x0); - write32(base + DART_T8020_STREAM_SELECT, 0xffff); // diff from t8020 + mask32(base + DART_T8020_STREAM_SELECT, read32(base + DART_T8020_STREAM_SELECT), 0xffff); + // write32(base + DART_T8020_STREAM_SELECT, 0xffff); // diff from t8020 write32(base + DART_T8020_STREAM_COMMAND, 0x0); int count = length / sizeof(*config); From a3cb742f7be39a9947766240993ec1dd398e515c Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Fri, 8 Sep 2023 00:02:55 +0900 Subject: [PATCH 07/15] kboot: Use adt_segment_ranges struct instead of open-coding Signed-off-by: Hector Martin --- src/adt.h | 9 +++++++++ src/kboot.c | 19 +++++++++---------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/adt.h b/src/adt.h index 6373c8682..5f717978b 100644 --- a/src/adt.h +++ b/src/adt.h @@ -106,4 +106,13 @@ bool adt_is_compatible(const void *adt, int nodeoffset, const char *compat); for (const struct adt_property *prop = ADT_PROP(adt, _poff); _prop_count--; \ prop = ADT_PROP(adt, _poff = adt_next_property_offset(adt, _poff))) +/* Common ADT properties */ +struct adt_segment_ranges { + u64 phys; + u64 iova; + u64 remap; + u32 size; + u32 unk; +} PACKED; + #endif diff --git a/src/kboot.c b/src/kboot.c index 96aaf9ee2..a3d6a91ff 100644 --- a/src/kboot.c +++ b/src/kboot.c @@ -1540,33 +1540,32 @@ static int dt_reserve_asc_firmware(const char *adt_path, const char *fdt_path) bail("FDT: couldn't set '%s.phandle' property: %d\n", fdt_path, ret); } - const uint64_t *segments; + const struct adt_segment_ranges *seg; u32 segments_len; - segments = adt_getprop(adt, node, "segment-ranges", &segments_len); - unsigned int num_maps = segments_len / 32; + seg = adt_getprop(adt, node, "segment-ranges", &segments_len); + unsigned int num_maps = segments_len / sizeof(*seg); for (unsigned i = 0; i < num_maps; i++) { - u64 paddr = segments[0]; - u64 iova = segments[2]; - u32 size = segments[3]; - segments += 4; + u64 iova = seg->iova; char node_name[64]; - snprintf(node_name, sizeof(node_name), "asc-firmware@%lx", paddr); + snprintf(node_name, sizeof(node_name), "asc-firmware@%lx", seg->phys); - int mem_node = dt_get_or_add_reserved_mem(node_name, "apple,asc-mem", paddr, size); + int mem_node = dt_get_or_add_reserved_mem(node_name, "apple,asc-mem", seg->phys, seg->size); if (mem_node < 0) return ret; uint32_t mem_phandle = fdt_get_phandle(dt, mem_node); - ret = dt_device_set_reserved_mem(mem_node, node_name, dev_phandle, iova, size); + ret = dt_device_set_reserved_mem(mem_node, node_name, dev_phandle, iova, seg->size); if (ret < 0) return ret; ret = dt_device_add_mem_region(fdt_path, mem_phandle, NULL); if (ret < 0) return ret; + + seg++; } return 0; From e709f9a859c006f010832f21b4223f3638553f73 Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Fri, 8 Sep 2023 00:03:55 +0900 Subject: [PATCH 08/15] kboot: Handle ISP/SIO reserved firmware differences The iova field is different, handle it with a flag. Signed-off-by: Hector Martin --- src/kboot.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/kboot.c b/src/kboot.c index a3d6a91ff..cc413e472 100644 --- a/src/kboot.c +++ b/src/kboot.c @@ -1517,7 +1517,7 @@ static int dt_vram_reserved_region(const char *dcp_alias, const char *disp_alias disp_reserved_regions_vram, ®ion, 1); } -static int dt_reserve_asc_firmware(const char *adt_path, const char *fdt_path) +static int dt_reserve_asc_firmware(const char *adt_path, const char *fdt_path, bool remap) { int ret = 0; @@ -1547,7 +1547,7 @@ static int dt_reserve_asc_firmware(const char *adt_path, const char *fdt_path) unsigned int num_maps = segments_len / sizeof(*seg); for (unsigned i = 0; i < num_maps; i++) { - u64 iova = seg->iova; + u64 iova = remap ? seg->remap : seg->iova; char node_name[64]; snprintf(node_name, sizeof(node_name), "asc-firmware@%lx", seg->phys); @@ -2158,13 +2158,13 @@ int kboot_prepare_dt(void *fdt) return -1; if (dt_disable_missing_devs("i2c", "i2c@", 8)) return -1; - if (dt_reserve_asc_firmware("/arm-io/sio", "sio")) + if (dt_reserve_asc_firmware("/arm-io/sio", "sio", true)) return -1; if (dt_set_sio_fwdata()) return -1; - if (dt_set_isp_fwdata()) + if (dt_reserve_asc_firmware("/arm-io/isp", "isp", false)) return -1; - if (dt_reserve_asc_firmware("/arm-io/isp", "isp")) + if (dt_set_isp_fwdata()) return -1; #ifndef RELEASE if (dt_transfer_virtios()) From ca3ca11a41612cb0f08adda9452f068df47a2a5c Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Fri, 8 Sep 2023 00:04:29 +0900 Subject: [PATCH 09/15] pmgr: Expose pmgr_set_mode For ISP stuff which is not declared in the ADT Signed-off-by: Hector Martin --- src/pmgr.c | 6 +----- src/pmgr.h | 6 ++++++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/pmgr.c b/src/pmgr.c index 0b766d06a..930a4396f 100644 --- a/src/pmgr.c +++ b/src/pmgr.c @@ -16,10 +16,6 @@ #define PMGR_PS_ACTUAL GENMASK(7, 4) #define PMGR_PS_TARGET GENMASK(3, 0) -#define PMGR_PS_ACTIVE 0xf -#define PMGR_PS_CLKGATE 0x4 -#define PMGR_PS_PWRGATE 0x0 - #define PMGR_POLL_TIMEOUT 10000 #define PMGR_FLAG_VIRTUAL 0x10 @@ -67,7 +63,7 @@ static uintptr_t pmgr_get_psreg(u8 idx) return pmgr_reg + reg_offset; } -static int pmgr_set_mode(uintptr_t addr, u8 target_mode) +int pmgr_set_mode(uintptr_t addr, u8 target_mode) { mask32(addr, PMGR_PS_TARGET, FIELD_PREP(PMGR_PS_TARGET, target_mode)); if (poll32(addr, PMGR_PS_ACTUAL, FIELD_PREP(PMGR_PS_ACTUAL, target_mode), PMGR_POLL_TIMEOUT) < diff --git a/src/pmgr.h b/src/pmgr.h index c96f4b0fb..3b61a57af 100644 --- a/src/pmgr.h +++ b/src/pmgr.h @@ -10,6 +10,10 @@ #define PMGR_DEVICE_ID GENMASK(15, 0) #define PMGR_DIE_ID GENMASK(31, 28) +#define PMGR_PS_ACTIVE 0xf +#define PMGR_PS_CLKGATE 0x4 +#define PMGR_PS_PWRGATE 0x0 + int pmgr_init(void); int pmgr_power_enable(u32 id); @@ -23,6 +27,8 @@ int pmgr_adt_reset(const char *path); int pmgr_reset(int die, const char *name); +int pmgr_set_mode(uintptr_t addr, u8 target_mode); + u32 pmgr_get_feature(const char *name); #endif From 3b549bd0978fb9ea6b3c428c3b5d69ecd401416d Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Fri, 8 Sep 2023 00:06:07 +0900 Subject: [PATCH 10/15] isp: Allocate heap carveout Allocating this in m1n1 means we can treat it as a reserved-memory node and deal with knowing the size in m1n1, instead of the kernel. It also means we can deal with the firmware version dependency mess here. Signed-off-by: Hector Martin --- src/isp.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++++- src/isp.h | 1 + 2 files changed, 129 insertions(+), 2 deletions(-) diff --git a/src/isp.c b/src/isp.c index 0eb710c24..1b4f29fb2 100644 --- a/src/isp.c +++ b/src/isp.c @@ -2,9 +2,23 @@ #include "adt.h" #include "dart.h" +#include "firmware.h" #include "pmgr.h" +#include "soc.h" #include "utils.h" +#define ISP_ASC_VERSION 0x1800000 + +#define ISP_VER_T8103 0xb0090 +#define ISP_VER_T6000 0xb3091 +#define ISP_VER_T8112 0xc1090 +#define ISP_VER_T6020 0xc3091 + +// PMGR offset to enable to get the version info to work +#define ISP_PMGR_T8103 0x4018 +#define ISP_PMGR_T6000 0x8 +#define ISP_PMGR_T6020 0x4008 + /* ISP DART has some quirks we must work around */ #define DART_T8020_ENABLED_STREAMS 0xfc @@ -66,6 +80,20 @@ static void isp_ctrr_init_t6000(u64 base, const struct dart_tunables *config, u3 write32(base + 0x13c, val); } +static bool isp_initialized = false; +static u64 heap_phys, heap_iova, heap_size, heap_top; + +int isp_get_heap(u64 *phys, u64 *iova, u64 *size) +{ + if (!isp_initialized) + return -1; + + *phys = heap_phys; + *iova = heap_iova; + *size = heap_size; + return 0; +} + int isp_init(void) { int err = 0; @@ -73,11 +101,13 @@ int isp_init(void) const char *isp_path = "/arm-io/isp"; const char *dart_path = "/arm-io/dart-isp"; - int adt_path[8]; + int adt_path[8], adt_isp_path[8]; + int isp_node = adt_path_offset_trace(adt, isp_path, adt_isp_path); int node = adt_path_offset_trace(adt, dart_path, adt_path); - if (node < 0) { + if (node < 0 || isp_node < 0) { isp_path = "/arm-io/isp0"; dart_path = "/arm-io/dart-isp0"; + isp_node = adt_path_offset_trace(adt, isp_path, adt_isp_path); node = adt_path_offset_trace(adt, dart_path, adt_path); } if (node < 0) @@ -86,6 +116,100 @@ int isp_init(void) if (pmgr_adt_power_enable(isp_path) < 0) return -1; + u64 isp_base; + u64 pmgr_base; + err = adt_get_reg(adt, adt_isp_path, "reg", 0, &isp_base, NULL); + if (err) + return err; + + err = adt_get_reg(adt, adt_isp_path, "reg", 1, &pmgr_base, NULL); + if (err) + return err; + + u32 pmgr_off; + switch (chip_id) { + case T8103: + case T8112: + pmgr_off = ISP_PMGR_T8103; + break; + case T6000 ... T6002: + pmgr_off = ISP_PMGR_T6000; + break; + case T6020 ... T6022: + pmgr_off = ISP_PMGR_T6020; + break; + default: + printf("isp: Unsupported SoC\n"); + return -1; + } + + err = pmgr_set_mode(pmgr_base + pmgr_off, PMGR_PS_ACTIVE); + if (err) { + printf("isp: Failed to power on\n"); + return err; + } + + u32 ver_rev = read32(isp_base + ISP_ASC_VERSION); + printf("isp: Version 0x%x\n", ver_rev); + + pmgr_set_mode(pmgr_base + pmgr_off, PMGR_PS_PWRGATE); + + /* TODO: confirm versions */ + switch (ver_rev) { + case ISP_VER_T8103: + case ISP_VER_T8112: + switch (os_firmware.version) { + case V12_3 ... V12_4: + heap_top = 0x1800000; + break; + case V13_5: + heap_top = 0x1000000; + break; + default: + printf("isp: unsupported firmware\n"); + return -1; + } + break; + case ISP_VER_T6000: + switch (os_firmware.version) { + case V12_3: + heap_top = 0xe00000; + break; + case V13_5: + heap_top = 0xf00000; + break; + default: + printf("isp: unsupported firmware\n"); + return -1; + } + break; + case ISP_VER_T6020: + switch (os_firmware.version) { + case V13_5: + heap_top = 0xf00000; + break; + default: + printf("isp: unsupported firmware\n"); + return -1; + } + break; + default: + printf("isp: unknown revision 0x%x\n", ver_rev); + return -1; + } + + const struct adt_segment_ranges *seg; + u32 segments_len; + + seg = adt_getprop(adt, isp_node, "segment-ranges", &segments_len); + unsigned int count = segments_len / sizeof(*seg); + + heap_iova = seg[count - 1].iova + seg[count - 1].size; + heap_size = heap_top - heap_iova; + heap_phys = top_of_memory_alloc(heap_size); + + printf("isp: Heap: 0x%lx..0x%lx (0x%lx @ 0x%lx)\n", heap_iova, heap_top, heap_size, heap_phys); + enum dart_type_t type; const char *type_s; if (adt_is_compatible(adt, node, "dart,t8020")) { @@ -137,6 +261,8 @@ int isp_init(void) } } + isp_initialized = true; + out: pmgr_adt_power_disable(isp_path); return err; diff --git a/src/isp.h b/src/isp.h index af83b3446..08e0e7f34 100644 --- a/src/isp.h +++ b/src/isp.h @@ -6,5 +6,6 @@ #include "types.h" int isp_init(void); +int isp_get_heap(u64 *phys, u64 *iova, u64 *size); #endif From bb2d532008d2f76da7c5b0d2ecf30a6dcb0c5522 Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Fri, 8 Sep 2023 00:06:53 +0900 Subject: [PATCH 11/15] kboot: Handle ISP heap carveout Signed-off-by: Hector Martin --- src/kboot.c | 76 ++++++++++++++++++++++++++--------------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/src/kboot.c b/src/kboot.c index cc413e472..f689ed250 100644 --- a/src/kboot.c +++ b/src/kboot.c @@ -1801,7 +1801,28 @@ struct isp_segment_ranges { static int dt_set_isp_fwdata(void) { - const char *path = "isp"; + const char *fdt_path = "isp"; + int ret = 0; + + u64 phys, iova, size; + + int fdt_node = fdt_path_offset(dt, fdt_path); + if (fdt_node < 0) { + printf("FDT: '%s' not found\n", fdt_path); + return 0; + } + + if (isp_get_heap(&phys, &iova, &size)) { + const char *status = fdt_getprop(dt, fdt_node, "status", NULL); + + if (!status || strcmp(status, "disabled")) { + printf("FDT: ISP enabled but not initialized, disabling\n"); + if (fdt_setprop_string(dt, fdt_node, "status", "disabled") < 0) + bail("FDT: failed to set status property of ISP\n"); + } + + return 0; + } int adt_node = adt_path_offset(adt, "/arm-io/isp"); if (adt_node < 0) @@ -1809,45 +1830,22 @@ static int dt_set_isp_fwdata(void) if (adt_node < 0) return 0; - u32 segments_len; - struct isp_segment_ranges *segments; - segments = - (struct isp_segment_ranges *)adt_getprop(adt, adt_node, "segment-ranges", &segments_len); - if (!segments || !segments_len) - bail("ADT: invalid ISP segment-ranges\n"); - - int count = segments_len / sizeof(*segments); - for (int i = 0; i < count; i++) - segments[i].remap = segments[i].iova; // match sio segment-ranges - - u64 ctrr_size; - switch (os_firmware.version) { - case V12_1: // haven't checked, probably right - case V12_2: // " - case V12_3: - case V12_3_1: - case V12_4: - case V12_5: - ctrr_size = 0x1800000; - break; - case V13_5: - ctrr_size = 0x1000000; - break; - default: - bail("FDT: couldn't get ISP CTRR size (%d)\n", os_firmware.version); + uint32_t dev_phandle = fdt_get_phandle(dt, fdt_node); + if (!dev_phandle) { + ret = fdt_generate_phandle(dt, &dev_phandle); + if (!ret) + ret = fdt_setprop_u32(dt, fdt_node, "phandle", dev_phandle); + if (ret != 0) + bail("FDT: couldn't set '%s.phandle' property: %d\n", fdt_path, ret); } - u64 heap_base = segments[count - 1].iova + segments[count - 1].size; - u64 heap_size = ctrr_size - heap_base; - - int fdt_node = fdt_path_offset(dt, path); - if (fdt_node < 0) - bail("FDT: '%s' node not found\n", path); + int mem_node = dt_get_or_add_reserved_mem("isp-heap", "apple,asc-mem", phys, size); + if (mem_node < 0) + return ret; - if (fdt_appendprop_u64(dt, fdt_node, "apple,isp-heap-base", heap_base)) - bail("FDT: couldn't set apple,isp-heap-base\n"); - if (fdt_appendprop_u64(dt, fdt_node, "apple,isp-heap-size", heap_size)) - bail("FDT: couldn't set apple,isp-heap-size\n"); + ret = dt_device_set_reserved_mem(mem_node, "isp-heap", dev_phandle, iova, size); + if (ret < 0) + return ret; return 0; } @@ -2113,6 +2111,9 @@ int kboot_prepare_dt(void *fdt) dt = NULL; } + /* Need to init ISP early to carve out heap */ + isp_init(); + dt_bufsize = fdt_totalsize(fdt); assert(dt_bufsize); @@ -2195,7 +2196,6 @@ int kboot_boot(void *kernel) usb_init(); pcie_init(); dapf_init_all(); - isp_init(); printf("Setting SMP mode to WFE...\n"); smp_set_wfe_mode(true); From 067f61b8043c0dfcded7ceeba51ba1cc5fca2e36 Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Fri, 8 Sep 2023 00:39:16 +0900 Subject: [PATCH 12/15] kboot: Make dt_get_or_add_reserved_mem mutate existing nodes This means we can use it with pre-created nodes in the DT. Signed-off-by: Hector Martin --- src/kboot.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/kboot.c b/src/kboot.c index f689ed250..9594a2c1e 100644 --- a/src/kboot.c +++ b/src/kboot.c @@ -1208,21 +1208,20 @@ static int dt_get_or_add_reserved_mem(const char *node_name, const char *compat, bail("FDT: '/reserved-memory' not found\n"); int node = fdt_subnode_offset(dt, resv_node, node_name); - if (node >= 0) - return node; - - node = fdt_add_subnode(dt, resv_node, node_name); - if (node < 0) - bail("FDT: failed to add node '%s' to '/reserved-memory'\n", node_name); + if (node < 0) { + node = fdt_add_subnode(dt, resv_node, node_name); + if (node < 0) + bail("FDT: failed to add node '%s' to '/reserved-memory'\n", node_name); - uint32_t phandle; - ret = fdt_generate_phandle(dt, &phandle); - if (ret) - bail("FDT: failed to generate phandle: %d\n", ret); + uint32_t phandle; + ret = fdt_generate_phandle(dt, &phandle); + if (ret) + bail("FDT: failed to generate phandle: %d\n", ret); - ret = fdt_setprop_u32(dt, node, "phandle", phandle); - if (ret != 0) - bail("FDT: couldn't set '%s.phandle' property: %d\n", node_name, ret); + ret = fdt_setprop_u32(dt, node, "phandle", phandle); + if (ret != 0) + bail("FDT: couldn't set '%s.phandle' property: %d\n", node_name, ret); + } u64 reg[2] = {cpu_to_fdt64(paddr), cpu_to_fdt64(size)}; ret = fdt_setprop(dt, node, "reg", reg, sizeof(reg)); From bf07bd057a80c7311564718c3abe4c45f8bb97bd Mon Sep 17 00:00:00 2001 From: Eileen Yoon Date: Sun, 10 Sep 2023 19:38:28 +0900 Subject: [PATCH 13/15] kboot: Add isp-heap mem region to phandle So of_iommu can detect it. Signed-off-by: Eileen Yoon --- src/kboot.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/kboot.c b/src/kboot.c index 9594a2c1e..665a19b8b 100644 --- a/src/kboot.c +++ b/src/kboot.c @@ -1841,10 +1841,15 @@ static int dt_set_isp_fwdata(void) int mem_node = dt_get_or_add_reserved_mem("isp-heap", "apple,asc-mem", phys, size); if (mem_node < 0) return ret; + uint32_t mem_phandle = fdt_get_phandle(dt, mem_node); ret = dt_device_set_reserved_mem(mem_node, "isp-heap", dev_phandle, iova, size); if (ret < 0) - return ret; + bail("FDT: couldn't set 'isp-heap' reserved mem: %d\n", ret); + + ret = dt_device_add_mem_region(fdt_path, mem_phandle, NULL); + if (ret < 0) + bail("FDT: couldn't add 'isp-heap' reserved mem: %d\n", ret); return 0; } From 451189901648477d602520b671995a02a4315607 Mon Sep 17 00:00:00 2001 From: Eileen Yoon Date: Sun, 10 Sep 2023 19:39:19 +0900 Subject: [PATCH 14/15] kboot: Remove old ISP segment-ranges struct Signed-off-by: Eileen Yoon --- src/kboot.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/kboot.c b/src/kboot.c index 665a19b8b..b3a66d322 100644 --- a/src/kboot.c +++ b/src/kboot.c @@ -1790,14 +1790,6 @@ static int dt_set_sio_fwdata(void) return 0; } -struct isp_segment_ranges { - u64 phys; - u64 iova; - u64 remap; - u32 size; - u32 unk; -} PACKED; - static int dt_set_isp_fwdata(void) { const char *fdt_path = "isp"; From b5c2fcbebde6c426a61728b7b8a7419ce525b47a Mon Sep 17 00:00:00 2001 From: Eileen Yoon Date: Sun, 10 Sep 2023 19:44:23 +0900 Subject: [PATCH 15/15] kboot/isp: Pass ctrr_size to FDT Still needed to fill out the fw bootargs. Signed-off-by: Eileen Yoon --- src/isp.c | 3 ++- src/isp.h | 2 +- src/kboot.c | 10 ++++++++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/isp.c b/src/isp.c index 1b4f29fb2..f0bbc8aac 100644 --- a/src/isp.c +++ b/src/isp.c @@ -83,7 +83,7 @@ static void isp_ctrr_init_t6000(u64 base, const struct dart_tunables *config, u3 static bool isp_initialized = false; static u64 heap_phys, heap_iova, heap_size, heap_top; -int isp_get_heap(u64 *phys, u64 *iova, u64 *size) +int isp_get_heap(u64 *phys, u64 *iova, u64 *size, u64 *top) { if (!isp_initialized) return -1; @@ -91,6 +91,7 @@ int isp_get_heap(u64 *phys, u64 *iova, u64 *size) *phys = heap_phys; *iova = heap_iova; *size = heap_size; + *top = heap_top; return 0; } diff --git a/src/isp.h b/src/isp.h index 08e0e7f34..f556de63a 100644 --- a/src/isp.h +++ b/src/isp.h @@ -6,6 +6,6 @@ #include "types.h" int isp_init(void); -int isp_get_heap(u64 *phys, u64 *iova, u64 *size); +int isp_get_heap(u64 *phys, u64 *iova, u64 *size, u64 *top); #endif diff --git a/src/kboot.c b/src/kboot.c index b3a66d322..264068690 100644 --- a/src/kboot.c +++ b/src/kboot.c @@ -1795,7 +1795,7 @@ static int dt_set_isp_fwdata(void) const char *fdt_path = "isp"; int ret = 0; - u64 phys, iova, size; + u64 phys, iova, size, top; int fdt_node = fdt_path_offset(dt, fdt_path); if (fdt_node < 0) { @@ -1803,7 +1803,7 @@ static int dt_set_isp_fwdata(void) return 0; } - if (isp_get_heap(&phys, &iova, &size)) { + if (isp_get_heap(&phys, &iova, &size, &top)) { const char *status = fdt_getprop(dt, fdt_node, "status", NULL); if (!status || strcmp(status, "disabled")) { @@ -1843,6 +1843,12 @@ static int dt_set_isp_fwdata(void) if (ret < 0) bail("FDT: couldn't add 'isp-heap' reserved mem: %d\n", ret); + fdt_node = fdt_path_offset(dt, fdt_path); + if (fdt_node < 0) + return fdt_node; + if (fdt_appendprop_u64(dt, fdt_node, "apple,isp-ctrr-size", top)) + bail("FDT: couldn't append to 'apple,isp-ctrr-size'\n"); + return 0; }