|
| 1 | +/* SPDX-License-Identifier: MIT */ |
| 2 | + |
| 3 | +#include "adt.h" |
| 4 | +#include "pmgr.h" |
| 5 | +#include "utils.h" |
| 6 | + |
| 7 | +/* ISP DART has some quirks we must work around */ |
| 8 | + |
| 9 | +#define DART_T8020_ENABLED_STREAMS 0xfc |
| 10 | +#define DART_T8020_STREAM_COMMAND 0x20 |
| 11 | +#define DART_T8020_STREAM_SELECT 0x34 |
| 12 | +#define DART_T8020_TCR_OFF 0x100 |
| 13 | +#define DART_T8020_TTBR 0x200 |
| 14 | + |
| 15 | +#define DART_T8020_TCR_TRANSLATE_ENABLE BIT(7) |
| 16 | +#define DART_T8020_STREAM_COMMAND_INVALIDATE BIT(20) |
| 17 | + |
| 18 | +struct dart_tunables { |
| 19 | + u64 offset; |
| 20 | + u64 clear; |
| 21 | + u64 set; |
| 22 | +}; |
| 23 | + |
| 24 | +int isp_init(void) |
| 25 | +{ |
| 26 | + int err = 0; |
| 27 | + const char *path = "/arm-io/isp"; |
| 28 | + const char *dart_path = "/arm-io/dart-isp"; |
| 29 | + |
| 30 | + if (pmgr_adt_power_enable(path) < 0) |
| 31 | + return -1; |
| 32 | + |
| 33 | + int adt_path[8]; |
| 34 | + int node = adt_path_offset_trace(adt, dart_path, adt_path); |
| 35 | + if (node < 0) { |
| 36 | + printf("isp: Error getting node %s\n", dart_path); |
| 37 | + return -1; |
| 38 | + } |
| 39 | + |
| 40 | + int dart_domain_count = 3; // TODO get from dt |
| 41 | + for (int index = 0; index < dart_domain_count; index++) { |
| 42 | + u64 base; |
| 43 | + err = adt_get_reg(adt, adt_path, "reg", index, &base, NULL); |
| 44 | + if (err < 0) |
| 45 | + goto out; |
| 46 | + |
| 47 | + u32 length; |
| 48 | + char prop[32] = "dart-tunables-instance"; |
| 49 | + snprintf(prop, sizeof(prop), "dart-tunables-instance-%u", index); |
| 50 | + const struct dart_tunables *config = adt_getprop(adt, node, prop, &length); |
| 51 | + if (!config || !length) { |
| 52 | + printf("isp: Error getting ADT node %s property %s.\n", path, prop); |
| 53 | + err = -1; |
| 54 | + goto out; |
| 55 | + } |
| 56 | + |
| 57 | + err = adt_get_reg(adt, adt_path, "reg", index, &base, NULL); |
| 58 | + if (err < 0) |
| 59 | + goto out; |
| 60 | + |
| 61 | + /* DART error handler gets stuck w/o these */ |
| 62 | + write32(base + DART_T8020_ENABLED_STREAMS, 0x1); |
| 63 | + write32(base + 0x2f0, 0x0); |
| 64 | + write32(base + DART_T8020_STREAM_SELECT, 0xffffffff); |
| 65 | + write32(base + DART_T8020_STREAM_COMMAND, DART_T8020_STREAM_COMMAND_INVALIDATE); |
| 66 | + |
| 67 | + /* I think these lock CTRR? Coproc __TEXT read-only region? */ |
| 68 | + int count = length / sizeof(*config); |
| 69 | + for (int i = 0; i < count; i++) { |
| 70 | + u64 offset = config->offset & 0xffff; |
| 71 | + u32 set = config->set & 0xffffffff; |
| 72 | + mask32(base + offset, read32(base + offset), set); |
| 73 | + config++; |
| 74 | + } |
| 75 | + |
| 76 | + write32(base + DART_T8020_TCR_OFF, DART_T8020_TCR_TRANSLATE_ENABLE); |
| 77 | + write32(base + 0x13c, 0x20000); |
| 78 | + } |
| 79 | + |
| 80 | +out: |
| 81 | + pmgr_adt_power_disable(path); |
| 82 | + return err; |
| 83 | +} |
0 commit comments