summaryrefslogtreecommitdiff
path: root/libcpu/mips/gs232/cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'libcpu/mips/gs232/cache.c')
-rw-r--r--libcpu/mips/gs232/cache.c231
1 files changed, 231 insertions, 0 deletions
diff --git a/libcpu/mips/gs232/cache.c b/libcpu/mips/gs232/cache.c
new file mode 100644
index 0000000000..484d3816f4
--- /dev/null
+++ b/libcpu/mips/gs232/cache.c
@@ -0,0 +1,231 @@
+/*
+ * Cache Ops For Loongson GS232
+ *
+ * Copyright (c) 2006-2019, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2010-07-09 Bernard first version
+ * 2011-08-08 lgnq modified for LS1B
+ * 2015-07-08 chinesebear modified for loongson 1c
+ */
+
+#include <rtthread.h>
+#include <mips.h>
+
+#define K0BASE 0x80000000
+#define PRID_LS1C 0x4220
+
+extern void Clear_TagLo (void);
+extern void Invalidate_Icache_Ls1c(unsigned int);
+extern void Invalidate_Dcache_ClearTag_Ls1c(unsigned int);
+extern void Invalidate_Dcache_Fill_Ls1c(unsigned int);
+extern void Writeback_Invalidate_Dcache(unsigned int);
+extern void enable_cpu_cache(void);
+
+typedef struct cacheinfo_t
+{
+ unsigned int icache_size;
+ unsigned int dcache_size;
+ unsigned int icacheline_size;
+ unsigned int dcacheline_size;
+} cacheinfo_t ;
+
+typedef struct cacheop_t
+{
+ void (*Clear_TagLo) (void);
+ void (*Invalidate_Icache) (unsigned int);
+ void (*Invalidate_Dcache_Fill) (unsigned int);
+ void (*Invalidate_Dcache_ClearTag) (unsigned int);
+ void (*Init_Cache)(void);
+} cacheop_t ;
+
+static cacheop_t cacheop, *pcacheop;
+static cacheinfo_t cacheinfo, *pcacheinfo;
+
+int identify_cpu(void)
+{
+ unsigned int cpu_id;
+
+ pcacheop = &cacheop;
+ pcacheinfo = &cacheinfo;
+
+ rt_kprintf("CPU configure: 0x%08x\n", read_c0_config());
+ cpu_id = read_c0_prid();
+ switch (cpu_id)
+ {
+ case PRID_LS1C:
+ rt_kprintf("CPU:Loongson 1C\n");
+ pcacheop->Clear_TagLo = Clear_TagLo;
+ pcacheop->Invalidate_Icache = Invalidate_Icache_Ls1c;
+ pcacheop->Invalidate_Dcache_Fill = Invalidate_Dcache_Fill_Ls1c;
+ pcacheop->Invalidate_Dcache_ClearTag = Invalidate_Dcache_ClearTag_Ls1c;
+ break;
+ default:
+ rt_kprintf("Unknown CPU type, system halted!\n");
+ while (1)
+ {
+ ;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+void probe_cache(void)
+{
+ unsigned int config1 = read_c0_config1();
+ unsigned int icache_size, icache_line_size, icache_sets, icache_ways;
+ unsigned int dcache_size, dcache_line_size, dcache_sets, dcache_ways;
+
+ if ((icache_line_size = ((config1 >> 19) & 7)))
+ icache_line_size = 2 << icache_line_size;
+ else
+ icache_line_size = icache_line_size;
+ icache_sets = 64 << ((config1 >> 22) & 7);
+ icache_ways = 1 + ((config1 >> 16) & 7);
+ icache_size = icache_sets * icache_ways * icache_line_size;
+
+ if ((dcache_line_size = ((config1 >> 10) & 7)))
+ dcache_line_size = 2 << dcache_line_size;
+ else
+ dcache_line_size = dcache_line_size;
+ dcache_sets = 64 << ((config1 >> 13) & 7);
+ dcache_ways = 1 + ((config1 >> 7) & 7);
+ dcache_size = dcache_sets * dcache_ways * dcache_line_size;
+
+ rt_kprintf("DCache %2dkb, linesize %d bytes.\n", dcache_size >> 10, dcache_line_size);
+ rt_kprintf("ICache %2dkb, linesize %d bytes.\n", icache_size >> 10, icache_line_size);
+
+ pcacheinfo->icache_size = icache_size;
+ pcacheinfo->dcache_size = dcache_size;
+ pcacheinfo->icacheline_size = icache_line_size;
+ pcacheinfo->dcacheline_size = dcache_line_size;
+
+ return ;
+}
+
+void invalidate_writeback_dcache_all(void)
+{
+ unsigned int start = K0BASE;
+ unsigned int end = (start + pcacheinfo->dcache_size);
+
+ while (start < end)
+ {
+ Writeback_Invalidate_Dcache(start); //hit writeback invalidate
+ start += pcacheinfo->dcacheline_size;
+ }
+}
+
+void invalidate_writeback_dcache(unsigned long addr, int size)
+{
+ unsigned long start, end;
+
+ start = (addr +pcacheinfo->dcacheline_size -1) & (- pcacheinfo->dcacheline_size);
+ end = (end + size + pcacheinfo->dcacheline_size -1) & ( -pcacheinfo->dcacheline_size);
+
+ while (start <end)
+ {
+ Writeback_Invalidate_Dcache(start);
+ start += pcacheinfo->dcacheline_size;
+ }
+}
+
+void invalidate_icache_all(void)
+{
+ unsigned int start = K0BASE;
+ unsigned int end = (start + pcacheinfo->icache_size);
+
+ while (start < end)
+ {
+ pcacheop->Invalidate_Icache(start);
+ start += pcacheinfo->icacheline_size;
+ }
+}
+
+void invalidate_dcache_all(void)
+{
+ unsigned int start = K0BASE;
+ unsigned int end = (start + pcacheinfo->dcache_size);
+ while (start <end)
+ {
+ Invalidate_Dcache_Fill_Ls1c(start);
+ start += pcacheinfo->icacheline_size;
+ }
+}
+
+//with cache disabled
+void init_dcache(void)
+{
+ unsigned int start = K0BASE;
+ unsigned int end = (start + pcacheinfo->dcache_size);
+
+ while (start < end)
+ {
+ pcacheop->Invalidate_Dcache_ClearTag(start);
+ start += pcacheinfo->dcacheline_size;
+ }
+
+}
+
+void rt_hw_cache_init(void)
+{
+ unsigned int start, end;
+
+ /* 1. identify cpu and probe cache */
+ identify_cpu();
+ probe_cache();
+
+ start = K0BASE;
+ end = (start + pcacheinfo->icache_size);
+
+ /*
+ * 2. clear CP0 taglo/taghi register;
+ */
+ pcacheop->Clear_TagLo();
+
+ /*
+ * 3. invalidate instruction cache;
+ */
+ while (start < end)
+ {
+ pcacheop->Invalidate_Icache(start); //index invalidate icache
+ start += pcacheinfo->icacheline_size;
+ }
+
+ /*
+ * 4. invalidate data cache;
+ */
+ start = K0BASE;
+ end = (start + pcacheinfo->dcache_size);
+ while(start < end)
+ {
+ pcacheop->Invalidate_Dcache_ClearTag(start);
+ start += pcacheinfo->dcacheline_size;
+ }
+
+ start = K0BASE;
+ while(start < end)
+ {
+ pcacheop->Invalidate_Dcache_Fill(start); //index invalidate dcache
+ start += pcacheinfo->dcacheline_size;
+ }
+
+ start = K0BASE;
+ while(start < end)
+ {
+ pcacheop->Invalidate_Dcache_ClearTag(start);
+ start += pcacheinfo->dcacheline_size;
+ }
+
+ /* enable cache */
+ enable_cpu_cache();
+ rt_kprintf("enable cpu cache done\n");
+
+ return ;
+}
+
+