[U-Boot] [PATCH v1 0/4] MIPS: optimise cache initialization

Do some minor cleanups. Improve the code for changing the k0 CCA. Make the index base address for cache initialisation configurable.
Some changes are insprired by the book "MD0901 Boot-MIPS" [1].
Also this is partly a preparation for the upcoming support for Mediatek MT76xx platform.
[1] https://training.mips.com/cps_mips/Examples/MD00901_Boot-MIPS_Example_Boot_C...
Daniel Schwierzeck (4): MIPS: cache: reimplement dcache_[status,enable,disable] MIPS: cache: optimise changing of k0 CCA mode MIPS: cache: make index base address configurable MIPS: cache: remove config option CONFIG_SYS_MIPS_CACHE_MODE
README | 14 ---- arch/mips/Kconfig | 12 ++++ arch/mips/lib/cache.c | 20 ++++++ arch/mips/lib/cache_init.S | 118 ++++++++++--------------------- include/configs/imgtec_xilfpga.h | 3 - include/configs/pic32mzdask.h | 3 - scripts/config_whitelist.txt | 1 - 7 files changed, 70 insertions(+), 101 deletions(-)

Those functions are not needed during cache init and can be implemented in C. Only support the safe disabling of caches when this is required for booting an OS. Reenabling caches is much harder to implement if an optional coherency manager must be supported. As there is no real use-case anyway, dcache_enable is implemented with an error message.
Signed-off-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com ---
arch/mips/lib/cache.c | 20 +++++++++++++++++ arch/mips/lib/cache_init.S | 46 -------------------------------------- 2 files changed, 20 insertions(+), 46 deletions(-)
diff --git a/arch/mips/lib/cache.c b/arch/mips/lib/cache.c index 1d14fc487e..d56fd1e0f4 100644 --- a/arch/mips/lib/cache.c +++ b/arch/mips/lib/cache.c @@ -175,3 +175,23 @@ void invalidate_dcache_range(ulong start_addr, ulong stop) /* ensure cache ops complete before any further memory accesses */ sync(); } + +int dcache_status(void) +{ + unsigned int cca = read_c0_config() & CONF_CM_CMASK; + return cca != CONF_CM_UNCACHED; +} + +void dcache_enable(void) +{ + puts("Not supported!\n"); +} + +void dcache_disable(void) +{ + /* change CCA to uncached */ + change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); + + /* ensure the pipeline doesn't contain now-invalid instructions */ + instruction_hazard_barrier(); +} diff --git a/arch/mips/lib/cache_init.S b/arch/mips/lib/cache_init.S index b209f23f0a..395bfffdb8 100644 --- a/arch/mips/lib/cache_init.S +++ b/arch/mips/lib/cache_init.S @@ -423,49 +423,3 @@ return: sync jr ra END(mips_cache_reset) - -/* - * dcache_status - get cache status - * - * RETURNS: 0 - cache disabled; 1 - cache enabled - * - */ -LEAF(dcache_status) - mfc0 t0, CP0_CONFIG - li t1, CONF_CM_UNCACHED - andi t0, t0, CONF_CM_CMASK - move v0, zero - beq t0, t1, 2f - li v0, 1 -2: jr ra - END(dcache_status) - -/* - * dcache_disable - disable cache - * - * RETURNS: N/A - * - */ -LEAF(dcache_disable) - mfc0 t0, CP0_CONFIG - li t1, -8 - and t0, t0, t1 - ori t0, t0, CONF_CM_UNCACHED - mtc0 t0, CP0_CONFIG - jr ra - END(dcache_disable) - -/* - * dcache_enable - enable cache - * - * RETURNS: N/A - * - */ -LEAF(dcache_enable) - mfc0 t0, CP0_CONFIG - ori t0, CONF_CM_CMASK - xori t0, CONF_CM_CMASK - ori t0, CONFIG_SYS_MIPS_CACHE_MODE - mtc0 t0, CP0_CONFIG - jr ra - END(dcache_enable)

Hi Daniel,
On 07.09.2018 19:02, Daniel Schwierzeck wrote:
Those functions are not needed during cache init and can be implemented in C. Only support the safe disabling of caches when this is required for booting an OS. Reenabling caches is much harder to implement if an optional coherency manager must be supported. As there is no real use-case anyway, dcache_enable is implemented with an error message.
Signed-off-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com
Many thanks for working on this. I'll be doing some more test later this week using this series. One comment though directly:
A few weeks ago I wanted to enable the "cache" cmd (CMD_CACHE) on my MT7688 MIPS platform. Unfortunately some I-Cache functions are missing for this:
building ... cmd/built-in.o: In function `do_icache': cmd/cache.c:(.text.do_icache+0x48): undefined reference to `icache_disable' cmd/cache.c:(.text.do_icache+0x68): undefined reference to `icache_enable' cmd/cache.c:(.text.do_icache+0x88): undefined reference to `icache_status' Makefile:1350: recipe for target 'u-boot' failed
Would it be possible to add those functions as well to this series (or some follow-up patch)? Using the cache cmd can be quite helpful while testing / debugging.
Thanks, Stefan

Am Mo., 10. Sep. 2018 um 07:34 Uhr schrieb Stefan Roese sr@denx.de:
Hi Daniel,
On 07.09.2018 19:02, Daniel Schwierzeck wrote:
Those functions are not needed during cache init and can be implemented in C. Only support the safe disabling of caches when this is required for booting an OS. Reenabling caches is much harder to implement if an optional coherency manager must be supported. As there is no real use-case anyway, dcache_enable is implemented with an error message.
Signed-off-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com
Many thanks for working on this. I'll be doing some more test later this week using this series. One comment though directly:
A few weeks ago I wanted to enable the "cache" cmd (CMD_CACHE) on my MT7688 MIPS platform. Unfortunately some I-Cache functions are missing for this:
building ... cmd/built-in.o: In function `do_icache': cmd/cache.c:(.text.do_icache+0x48): undefined reference to `icache_disable' cmd/cache.c:(.text.do_icache+0x68): undefined reference to `icache_enable' cmd/cache.c:(.text.do_icache+0x88): undefined reference to `icache_status' Makefile:1350: recipe for target 'u-boot' failed
Would it be possible to add those functions as well to this series (or some follow-up patch)? Using the cache cmd can be quite helpful while testing / debugging.
The problem is that you can't independently disable I-Cache and D-Cache on MIPS. I could add them as dummy functions or with the same implementation as dcache_*

On 11.09.2018 16:12, Daniel Schwierzeck wrote:
Am Mo., 10. Sep. 2018 um 07:34 Uhr schrieb Stefan Roese sr@denx.de:
Hi Daniel,
On 07.09.2018 19:02, Daniel Schwierzeck wrote:
Those functions are not needed during cache init and can be implemented in C. Only support the safe disabling of caches when this is required for booting an OS. Reenabling caches is much harder to implement if an optional coherency manager must be supported. As there is no real use-case anyway, dcache_enable is implemented with an error message.
Signed-off-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com
Many thanks for working on this. I'll be doing some more test later this week using this series. One comment though directly:
A few weeks ago I wanted to enable the "cache" cmd (CMD_CACHE) on my MT7688 MIPS platform. Unfortunately some I-Cache functions are missing for this:
building ... cmd/built-in.o: In function `do_icache': cmd/cache.c:(.text.do_icache+0x48): undefined reference to `icache_disable' cmd/cache.c:(.text.do_icache+0x68): undefined reference to `icache_enable' cmd/cache.c:(.text.do_icache+0x88): undefined reference to `icache_status' Makefile:1350: recipe for target 'u-boot' failed
Would it be possible to add those functions as well to this series (or some follow-up patch)? Using the cache cmd can be quite helpful while testing / debugging.
The problem is that you can't independently disable I-Cache and D-Cache on MIPS.
Why is this the case? Can't the I-Cache be disabled at all? Or is it just not possible (or complex) while running with I-Cache enabled?
I could add them as dummy functions or with the same implementation as dcache_*
That's perhaps a pragmatic work-around - if the I-Cache can't be disabled at all.
Thanks, Stefan

Am Di., 11. Sep. 2018 um 16:30 Uhr schrieb Stefan Roese sr@denx.de:
On 11.09.2018 16:12, Daniel Schwierzeck wrote:
Am Mo., 10. Sep. 2018 um 07:34 Uhr schrieb Stefan Roese sr@denx.de:
Hi Daniel,
On 07.09.2018 19:02, Daniel Schwierzeck wrote:
Those functions are not needed during cache init and can be implemented in C. Only support the safe disabling of caches when this is required for booting an OS. Reenabling caches is much harder to implement if an optional coherency manager must be supported. As there is no real use-case anyway, dcache_enable is implemented with an error message.
Signed-off-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com
Many thanks for working on this. I'll be doing some more test later this week using this series. One comment though directly:
A few weeks ago I wanted to enable the "cache" cmd (CMD_CACHE) on my MT7688 MIPS platform. Unfortunately some I-Cache functions are missing for this:
building ... cmd/built-in.o: In function `do_icache': cmd/cache.c:(.text.do_icache+0x48): undefined reference to `icache_disable' cmd/cache.c:(.text.do_icache+0x68): undefined reference to `icache_enable' cmd/cache.c:(.text.do_icache+0x88): undefined reference to `icache_status' Makefile:1350: recipe for target 'u-boot' failed
Would it be possible to add those functions as well to this series (or some follow-up patch)? Using the cache cmd can be quite helpful while testing / debugging.
The problem is that you can't independently disable I-Cache and D-Cache on MIPS.
Why is this the case? Can't the I-Cache be disabled at all? Or is it just not possible (or complex) while running with I-Cache enabled?
you can only configure the "Cache Coherency Algorithm" in Coprocessor 0 Config register. This setting affects I-Cache and D-Cache at once.
Maybe a workaround for icache_[en|dis]able could be to shift the instruction pointer from KSEG0 to KSEG1. This is the same principle you had with ddr_calibrate() in your first iteration of MT76xx patch series.
I could add them as dummy functions or with the same implementation as dcache_*
That's perhaps a pragmatic work-around - if the I-Cache can't be disabled at all.
Thanks, Stefan
-- - Daniel

Changing the Cache Coherency Algorithm (CCA) for kernel mode requires executing from KSEG1. Thus do a jump from KSEG0 to KSEG1 before changing the CCA mode. Jump back to KSEG0 afterwards.
Signed-off-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com ---
arch/mips/lib/cache_init.S | 54 ++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 22 deletions(-)
diff --git a/arch/mips/lib/cache_init.S b/arch/mips/lib/cache_init.S index 395bfffdb8..4e956031b3 100644 --- a/arch/mips/lib/cache_init.S +++ b/arch/mips/lib/cache_init.S @@ -84,6 +84,7 @@ 10: .set pop .endm + /* * mips_cache_reset - low level initialisation of the primary caches * @@ -319,19 +320,21 @@ l1_init: PTR_LI t0, INDEX_BASE cache_loop t0, t1, R_IC_LINE, INDEX_STORE_TAG_I #endif - - /* Enable use of the I-cache by setting Config.K0 */ sync - mfc0 t0, CP0_CONFIG - li t1, CONFIG_SYS_MIPS_CACHE_MODE -#if __mips_isa_rev >= 2 - ins t0, t1, 0, 3 -#else - ori t0, t0, CONF_CM_CMASK - xori t0, t0, CONF_CM_CMASK + + /* + * Enable use of the I-cache by setting Config.K0. The code for this + * must be executed from KSEG1. Jump from KSEG0 to KSEG1 to do this. + * Jump back to KSEG0 after caches are enabled and insert an + * instruction hazard barrier. + */ + PTR_LA t0, change_k0_cca + li t1, CPHYSADDR(~0) + and t0, t0, t1 + PTR_LI t1, CKSEG1 or t0, t0, t1 -#endif - mtc0 t0, CP0_CONFIG + li a0, CONFIG_SYS_MIPS_CACHE_MODE + jalr.hb t0
/* * then initialize D-cache. @@ -391,16 +394,9 @@ l2_unbypass: beqz t0, 2f
/* Change Config.K0 to a coherent CCA */ - mfc0 t0, CP0_CONFIG - li t1, CONF_CM_CACHABLE_COW -#if __mips_isa_rev >= 2 - ins t0, t1, 0, 3 -#else - ori t0, t0, CONF_CM_CMASK - xori t0, t0, CONF_CM_CMASK - or t0, t0, t1 -#endif - mtc0 t0, CP0_CONFIG + PTR_LA t0, change_k0_cca + li a0, CONF_CM_CACHABLE_COW + jalr t0
/* * Join the coherent domain such that the caches of this core are kept @@ -421,5 +417,19 @@ l2_unbypass: return: /* Ensure all cache operations complete before returning */ sync - jr ra + jr R_RETURN END(mips_cache_reset) + +LEAF(change_k0_cca) + mfc0 t0, CP0_CONFIG +#if __mips_isa_rev >= 2 + ins t0, a0, 0, 3 +#else + xor a0, a0, t0 + andi a0, a0, CONF_CM_CMASK + xor a0, a0, t0 +#endif + mtc0 a0, CP0_CONFIG + + jr.hb ra + END(change_k0_cca)

The index base address used for the cache initialisation is currently hard-coded to CKSEG0. Make this value configurable if a MIPS system needs to have a different address (e.g. in SRAM or ScratchPad RAM).
Signed-off-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com ---
arch/mips/Kconfig | 12 ++++++++++++ arch/mips/lib/cache_init.S | 18 ++++++++---------- 2 files changed, 20 insertions(+), 10 deletions(-)
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 6e5e0ffe65..095d81689f 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -218,6 +218,18 @@ config MIPS_CM_BASE the GCRs occupy a region of the physical address space which is otherwise unused, or at minimum that software doesn't need to access.
+config MIPS_CACHE_INDEX_BASE + hex "Index base address for cache initialisation" + default 0x80000000 if CPU_MIPS32 + default 0xffffffff80000000 if CPU_MIPS64 + help + This is the base address for a memory block, which is used for + initialising the cache lines. This is also the base address of a memory + block which is used for loading and filling cache lines when + SYS_MIPS_CACHE_INIT_RAM_LOAD is selected. + Normally this is CKSEG0. If the MIPS system needs to move this block + to some SRAM or ScratchPad RAM, adapt this option accordingly. + endmenu
menu "OS boot interface" diff --git a/arch/mips/lib/cache_init.S b/arch/mips/lib/cache_init.S index 4e956031b3..5616ee6dfd 100644 --- a/arch/mips/lib/cache_init.S +++ b/arch/mips/lib/cache_init.S @@ -18,8 +18,6 @@ #define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT #endif
-#define INDEX_BASE CKSEG0 - .macro f_fill64 dst, offset, val LONG_S \val, (\offset + 0 * LONGSIZE)(\dst) LONG_S \val, (\offset + 1 * LONGSIZE)(\dst) @@ -256,7 +254,7 @@ l2_probe_done: /* * Now clear that much memory starting from zero. */ - PTR_LI a0, CKSEG1 + PTR_LI a0, CKSEG1ADDR(CONFIG_MIPS_CACHE_INDEX_BASE) PTR_ADDU a1, a0, v0 2: PTR_ADDIU a0, 64 f_fill64 a0, -64, zero @@ -272,7 +270,7 @@ l2_probe_done: bnez R_L2_BYPASSED, l1_init
l2_init: - PTR_LI t0, INDEX_BASE + PTR_LI t0, CKSEG0ADDR(CONFIG_MIPS_CACHE_INDEX_BASE) PTR_ADDU t1, t0, R_L2_SIZE 1: cache INDEX_STORE_TAG_SD, 0(t0) PTR_ADDU t0, t0, R_L2_LINE @@ -308,16 +306,16 @@ l1_init: * Initialize the I-cache first, */ blez R_IC_SIZE, 1f - PTR_LI t0, INDEX_BASE + PTR_LI t0, CKSEG0ADDR(CONFIG_MIPS_CACHE_INDEX_BASE) PTR_ADDU t1, t0, R_IC_SIZE /* clear tag to invalidate */ cache_loop t0, t1, R_IC_LINE, INDEX_STORE_TAG_I #ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD /* fill once, so data field parity is correct */ - PTR_LI t0, INDEX_BASE + PTR_LI t0, CKSEG0ADDR(CONFIG_MIPS_CACHE_INDEX_BASE) cache_loop t0, t1, R_IC_LINE, FILL /* invalidate again - prudent but not strictly neccessary */ - PTR_LI t0, INDEX_BASE + PTR_LI t0, CKSEG0ADDR(CONFIG_MIPS_CACHE_INDEX_BASE) cache_loop t0, t1, R_IC_LINE, INDEX_STORE_TAG_I #endif sync @@ -340,18 +338,18 @@ l1_init: * then initialize D-cache. */ 1: blez R_DC_SIZE, 3f - PTR_LI t0, INDEX_BASE + PTR_LI t0, CKSEG0ADDR(CONFIG_MIPS_CACHE_INDEX_BASE) PTR_ADDU t1, t0, R_DC_SIZE /* clear all tags */ cache_loop t0, t1, R_DC_LINE, INDEX_STORE_TAG_D #ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD /* load from each line (in cached space) */ - PTR_LI t0, INDEX_BASE + PTR_LI t0, CKSEG0ADDR(CONFIG_MIPS_CACHE_INDEX_BASE) 2: LONG_L zero, 0(t0) PTR_ADDU t0, R_DC_LINE bne t0, t1, 2b /* clear all tags */ - PTR_LI t0, INDEX_BASE + PTR_LI t0, CKSEG0ADDR(CONFIG_MIPS_CACHE_INDEX_BASE) cache_loop t0, t1, R_DC_LINE, INDEX_STORE_TAG_D #endif 3:

Caches should be configured to mode CONF_CM_CACHABLE_NONCOHERENT (or CONF_CM_CACHABLE_COW when a CM is available). There is no need to make this configurable.
Signed-off-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com
---
README | 14 -------------- arch/mips/lib/cache_init.S | 6 +----- include/configs/imgtec_xilfpga.h | 3 --- include/configs/pic32mzdask.h | 3 --- scripts/config_whitelist.txt | 1 - 5 files changed, 1 insertion(+), 26 deletions(-)
diff --git a/README b/README index a91af2a189..c280b7a95f 100644 --- a/README +++ b/README @@ -528,20 +528,6 @@ The following options need to be configured: pointer. This is needed for the temporary stack before relocation.
- CONFIG_SYS_MIPS_CACHE_MODE - - Cache operation mode for the MIPS CPU. - See also arch/mips/include/asm/mipsregs.h. - Possible values are: - CONF_CM_CACHABLE_NO_WA - CONF_CM_CACHABLE_WA - CONF_CM_UNCACHED - CONF_CM_CACHABLE_NONCOHERENT - CONF_CM_CACHABLE_CE - CONF_CM_CACHABLE_COW - CONF_CM_CACHABLE_CUW - CONF_CM_CACHABLE_ACCELERATED - CONFIG_SYS_XWAY_EBU_BOOTCFG
Special option for Lantiq XWAY SoCs for booting from NOR flash. diff --git a/arch/mips/lib/cache_init.S b/arch/mips/lib/cache_init.S index 5616ee6dfd..cfad1d9c8a 100644 --- a/arch/mips/lib/cache_init.S +++ b/arch/mips/lib/cache_init.S @@ -14,10 +14,6 @@ #include <asm/cacheops.h> #include <asm/cm.h>
-#ifndef CONFIG_SYS_MIPS_CACHE_MODE -#define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT -#endif - .macro f_fill64 dst, offset, val LONG_S \val, (\offset + 0 * LONGSIZE)(\dst) LONG_S \val, (\offset + 1 * LONGSIZE)(\dst) @@ -331,7 +327,7 @@ l1_init: and t0, t0, t1 PTR_LI t1, CKSEG1 or t0, t0, t1 - li a0, CONFIG_SYS_MIPS_CACHE_MODE + li a0, CONF_CM_CACHABLE_NONCOHERENT jalr.hb t0
/* diff --git a/include/configs/imgtec_xilfpga.h b/include/configs/imgtec_xilfpga.h index 29b23fa40e..8e2d72323d 100644 --- a/include/configs/imgtec_xilfpga.h +++ b/include/configs/imgtec_xilfpga.h @@ -19,9 +19,6 @@ /* CPU Timer rate */ #define CONFIG_SYS_MIPS_TIMER_FREQ 50000000
-/* Cache Configuration */ -#define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT - /*---------------------------------------------------------------------- * Memory Layout */ diff --git a/include/configs/pic32mzdask.h b/include/configs/pic32mzdask.h index d3775023d0..ec2e7743d9 100644 --- a/include/configs/pic32mzdask.h +++ b/include/configs/pic32mzdask.h @@ -16,9 +16,6 @@ /* CPU Timer rate */ #define CONFIG_SYS_MIPS_TIMER_FREQ 100000000
-/* Cache Configuration */ -#define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT - /*---------------------------------------------------------------------- * Memory Layout */ diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index 1a5606d123..b3cba57843 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -3435,7 +3435,6 @@ CONFIG_SYS_MEM_TOP_HIDE CONFIG_SYS_MFD CONFIG_SYS_MHZ CONFIG_SYS_MII_MODE -CONFIG_SYS_MIPS_CACHE_MODE CONFIG_SYS_MIPS_TIMER_FREQ CONFIG_SYS_MMCSD_FS_BOOT_PARTITION CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR
participants (2)
-
Daniel Schwierzeck
-
Stefan Roese