diff --git a/platform/generic/include/mips/p8700.h b/platform/generic/include/mips/p8700.h index 5facd38a..ad7353f8 100644 --- a/platform/generic/include/mips/p8700.h +++ b/platform/generic/include/mips/p8700.h @@ -58,6 +58,14 @@ extern const struct p8700_cm_info *p8700_cm_info; #define CSR_MIPSCONFIG10 0x7da #define CSR_MIPSCONFIG11 0x7db +#define MIPSCONFIG1_L2C BIT(31) +#define MIPSCONFIG1_IS GENMASK(24,22) +#define MIPSCONFIG1_IL GENMASK(21,19) +#define MIPSCONFIG1_IA GENMASK(18,16) +#define MIPSCONFIG1_DS GENMASK(15,13) +#define MIPSCONFIG1_DL GENMASK(12,10) +#define MIPSCONFIG1_DA GENMASK(9,7) + #define MIPSCONFIG5_MTW 4 #define GEN_MASK(h, l) (((1ul << ((h) + 1 - (l))) - 1) << (l)) @@ -113,6 +121,43 @@ extern const struct p8700_cm_info *p8700_cm_info; #define L2_PFT_CONTROL_OFFSET 0x0300 #define L2_PFT_CONTROL_B_OFFSET 0x0308 +#define GCR_L2_CONFIG 0x0130 +#define GCR_L2_ASSOC GENMASK(7, 0) +#define GCR_L2_LINE_SIZE GENMASK(11, 8) +#define GCR_L2_SET_SIZE GENMASK(15, 12) +#define GCR_L2_BYPASS BIT(20) +#define GCR_L2_COP_DATA_ECC_WE BIT(24) +#define GCR_L2_COP_TAG_ECC_WE BIT(25) +#define GCR_L2_COP_LRU_WE BIT(26) +#define GCR_L2_REG_EXISTS BIT(31) + +#define GCR_L2_TAG_ADDR 0x0600 +#define GCR_L2_TAG_STATE 0x0608 +#define GCR_L2_DATA 0x0610 +#define GCR_L2_ECC 0x0618 + +#define GCR_L2SM_COP 0x0620 +#define GCR_L2SM_COP_CMD GENMASK(1, 0) +#define L2SM_COP_CMD_NOP 0 +#define L2SM_COP_CMD_START 1 +#define L2SM_COP_CMD_ABORT 3 +#define GCR_L2SM_COP_TYPE GENMASK(4, 2) +#define L2SM_COP_TYPE_IDX_WBINV 0 +#define L2SM_COP_TYPE_IDX_STORETAG 1 +#define L2SM_COP_TYPE_IDX_STORETAGDATA 2 +#define L2SM_COP_TYPE_HIT_INV 4 +#define L2SM_COP_TYPE_HIT_WBINV 5 +#define L2SM_COP_TYPE_HIT_WB 6 +#define L2SM_COP_TYPE_FETCHLOCK 7 +#define GCR_L2SM_COP_RUNNING BIT(5) +#define GCR_L2SM_COP_RESULT GENMASK(8, 6) +#define L2SM_COP_RESULT_DONTCARE 0 +#define L2SM_COP_RESULT_DONE_OK 1 +#define L2SM_COP_RESULT_DONE_ERROR 2 +#define L2SM_COP_RESULT_ABORT_OK 3 +#define L2SM_COP_RESULT_ABORT_ERROR 4 +#define GCR_L2SM_COP_PRESENT BIT(31) + /* CPC Block offsets */ #define CPC_PWRUP_CTL 0x0030 #define CPC_CM_STAT_CONF 0x1008 @@ -138,6 +183,15 @@ void mips_p8700_pmp_set(unsigned int n, unsigned long flags, void mips_p8700_power_up_other_cluster(u32 hartid); int mips_p8700_hart_start(u32 hartid, ulong saddr); int mips_p8700_hart_stop(void); + +struct p8700_cache_info { + u32 line; + u32 assoc_ways; + u32 sets; +}; + +void mips_p8700_cache_info(struct p8700_cache_info *l1d, struct p8700_cache_info *l1i, + struct p8700_cache_info *l2); struct fdt_match; int mips_p8700_platform_init(const void *fdt, int nodeoff, const struct fdt_match *match); diff --git a/platform/generic/mips/eyeq7h.c b/platform/generic/mips/eyeq7h.c index 5c74bc5e..816ac6f5 100644 --- a/platform/generic/mips/eyeq7h.c +++ b/platform/generic/mips/eyeq7h.c @@ -171,6 +171,32 @@ static struct fdt_general_fixup eyeq7h_acc_clusters_fixup = { .do_fixup = eyeq7h_acc_clusters_do_fixup, }; +static void eyeq7h_cache_do_fixup(struct fdt_general_fixup *f, void *fdt) +{ + struct p8700_cache_info l1d, l1i, l2; + mips_p8700_cache_info(&l1d, &l1i, &l2); + + sbi_dprintf("Cache geometry:\n" + " D: %4d Kbytes line %3d bytes %2d ways %5d sets\n" + " I: %4d Kbytes line %3d bytes %2d ways %5d sets\n", + l1d.assoc_ways * l1d.line * l1d.sets / 1024, + l1d.line, l1d.assoc_ways, l1d.sets, + l1i.assoc_ways * l1i.line * l1i.sets / 1024, + l1i.line, l1i.assoc_ways, l1i.sets); + if (l2.line) { + sbi_dprintf(" L2: %4d Kbytes line %3d bytes %2d ways %5d sets\n", + l2.assoc_ways * l2.line * l2.sets / 1024, + l2.line, l2.assoc_ways, l2.sets); + } else { + sbi_dprintf(" L2: not present\n"); + } +} + +static struct fdt_general_fixup eyeq7h_cache_fixup = { + .name = "cache-fixup", + .do_fixup = eyeq7h_cache_do_fixup, +}; + static int eyeq7h_final_init(bool cold_boot) { if (!cold_boot) @@ -178,6 +204,7 @@ static int eyeq7h_final_init(bool cold_boot) sbi_hsm_set_device(&eyeq7h_hsm); fdt_register_general_fixup(&eyeq7h_acc_clusters_fixup); + fdt_register_general_fixup(&eyeq7h_cache_fixup); return generic_final_init(cold_boot); } diff --git a/platform/generic/mips/p8700.c b/platform/generic/mips/p8700.c index c1f2ac7f..4e693bc0 100644 --- a/platform/generic/mips/p8700.c +++ b/platform/generic/mips/p8700.c @@ -123,6 +123,51 @@ int mips_p8700_hart_stop() return 0; } +void mips_p8700_cache_info(struct p8700_cache_info *l1d, struct p8700_cache_info *l1i, + struct p8700_cache_info *l2) +{ + u32 mipsconfig1 = csr_read(CSR_MIPSCONFIG1); + + if (l1d) { + u32 da = EXTRACT_FIELD(mipsconfig1, MIPSCONFIG1_DA); + u32 dl = EXTRACT_FIELD(mipsconfig1, MIPSCONFIG1_DL); + u32 ds = EXTRACT_FIELD(mipsconfig1, MIPSCONFIG1_DS); + + l1d->line = dl ? 1 << (dl + 1) : 0; + l1d->assoc_ways = da +1; + l1d->sets = ds == 7 ? 32 : 1 << (ds + 6); + } + if (l1i) { + u32 ia = EXTRACT_FIELD(mipsconfig1, MIPSCONFIG1_IA); + u32 il = EXTRACT_FIELD(mipsconfig1, MIPSCONFIG1_IL); + u32 is = EXTRACT_FIELD(mipsconfig1, MIPSCONFIG1_IS); + + l1i->line = il ? 1 << (il + 1) : 0; + l1i->assoc_ways = ia +1; + l1i->sets = is == 7 ? 32 : 1 << (is + 6); + } + if (l2) { + if (mipsconfig1 & MIPSCONFIG1_L2C) { + void *cm_base = (void *)p8700_cm_info->gcr_base[0]; + u32 l2_config = readl(cm_base + GCR_L2_CONFIG); + + if (l2_config & GCR_L2_REG_EXISTS) { + u32 l2a = EXTRACT_FIELD(l2_config, GCR_L2_ASSOC); + u32 l2l = EXTRACT_FIELD(l2_config, GCR_L2_LINE_SIZE); + u32 l2s = EXTRACT_FIELD(l2_config, GCR_L2_SET_SIZE); + + l2->assoc_ways = l2a + 1; + l2->line = 1 << (l2l + 1); + l2->sets = 1 << (l2s + 6); + return; + } + } + l2->line = 0; + l2->assoc_ways = 0; + l2->sets = 0; + } +} + int mips_p8700_platform_init(const void *fdt, int nodeoff, const struct fdt_match *match) { const struct p8700_cm_info *data = match->data;