/* * (C) Copyright 2007 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * Author: Igor Lisitsin * * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include #include #include #include #if CONFIG_POST & CONFIG_SYS_POST_CACHE .text /* * All 44x variants deal with cache management differently * because they have the address translation always enabled. * The 40x ppc's don't use address translation in U-Boot at all, * so we have to distinguish here between 40x and 44x. */ #ifdef CONFIG_440 /* void cache_post_disable (int tlb) */ cache_post_disable: tlbre r0, r3, 0x0002 ori r0, r0, TLB_WORD2_I_ENABLE@l tlbwe r0, r3, 0x0002 sync isync blr /* void cache_post_wt (int tlb) */ cache_post_wt: tlbre r0, r3, 0x0002 ori r0, r0, TLB_WORD2_W_ENABLE@l andi. r0, r0, ~TLB_WORD2_I_ENABLE@l tlbwe r0, r3, 0x0002 sync isync blr /* void cache_post_wb (int tlb) */ cache_post_wb: tlbre r0, r3, 0x0002 andi. r0, r0, ~TLB_WORD2_W_ENABLE@l andi. r0, r0, ~TLB_WORD2_I_ENABLE@l tlbwe r0, r3, 0x0002 sync isync blr #else /* void cache_post_disable (int tlb) */ cache_post_disable: lis r0, 0x0000 ori r0, r0, 0x0000 mtdccr r0 sync isync blr /* void cache_post_wt (int tlb) */ cache_post_wt: lis r0, 0x8000 ori r0, r0, 0x0000 mtdccr r0 lis r0, 0x8000 ori r0, r0, 0x0000 mtdcwr r0 sync isync blr /* void cache_post_wb (int tlb) */ cache_post_wb: lis r0, 0x8000 ori r0, r0, 0x0000 mtdccr r0 lis r0, 0x0000 ori r0, r0, 0x0000 mtdcwr r0 sync isync blr #endif /* void cache_post_dinvalidate (void *p, int size) */ cache_post_dinvalidate: dcbi r0, r3 addi r3, r3, CONFIG_SYS_CACHELINE_SIZE subic. r4, r4, CONFIG_SYS_CACHELINE_SIZE bgt cache_post_dinvalidate sync blr /* void cache_post_dstore (void *p, int size) */ cache_post_dstore: dcbst r0, r3 addi r3, r3, CONFIG_SYS_CACHELINE_SIZE subic. r4, r4, CONFIG_SYS_CACHELINE_SIZE bgt cache_post_dstore sync blr /* void cache_post_dtouch (void *p, int size) */ cache_post_dtouch: dcbt r0, r3 addi r3, r3, CONFIG_SYS_CACHELINE_SIZE subic. r4, r4, CONFIG_SYS_CACHELINE_SIZE bgt cache_post_dtouch sync blr /* void cache_post_iinvalidate (void) */ cache_post_iinvalidate: iccci r0, r0 sync blr /* void cache_post_memset (void *p, int val, int size) */ cache_post_memset: mtctr r5 1: stb r4, 0(r3) addi r3, r3, 1 bdnz 1b blr /* int cache_post_check (void *p, int size) */ cache_post_check: mtctr r4 1: lbz r0, 0(r3) addi r3, r3, 1 cmpwi r0, 0xff bne 2f bdnz 1b li r3, 0 blr 2: li r3, -1 blr #define CACHE_POST_DISABLE() \ mr r3, r10; \ bl cache_post_disable #define CACHE_POST_WT() \ mr r3, r10; \ bl cache_post_wt #define CACHE_POST_WB() \ mr r3, r10; \ bl cache_post_wb #define CACHE_POST_DINVALIDATE() \ mr r3, r11; \ mr r4, r12; \ bl cache_post_dinvalidate #define CACHE_POST_DFLUSH() \ mr r3, r11; \ mr r4, r12; \ bl cache_post_dflush #define CACHE_POST_DSTORE() \ mr r3, r11; \ mr r4, r12; \ bl cache_post_dstore #define CACHE_POST_DTOUCH() \ mr r3, r11; \ mr r4, r12; \ bl cache_post_dtouch #define CACHE_POST_IINVALIDATE() \ bl cache_post_iinvalidate #define CACHE_POST_MEMSET(val) \ mr r3, r11; \ li r4, val; \ mr r5, r12; \ bl cache_post_memset #define CACHE_POST_CHECK() \ mr r3, r11; \ mr r4, r12; \ bl cache_post_check; \ mr r13, r3 /* * Write and read 0xff pattern with caching enabled. */ .global cache_post_test1 cache_post_test1: mflr r9 mr r10, r3 /* tlb */ mr r11, r4 /* p */ mr r12, r5 /* size */ CACHE_POST_WB() CACHE_POST_DINVALIDATE() /* Write the negative pattern to the test area */ CACHE_POST_MEMSET(0xff) /* Read the test area */ CACHE_POST_CHECK() CACHE_POST_DINVALIDATE() CACHE_POST_DISABLE() mr r3, r13 mtlr r9 blr /* * Write zeroes with caching enabled. * Write 0xff pattern with caching disabled. * Read 0xff pattern with caching enabled. */ .global cache_post_test2 cache_post_test2: mflr r9 mr r10, r3 /* tlb */ mr r11, r4 /* p */ mr r12, r5 /* size */ CACHE_POST_WB() CACHE_POST_DINVALIDATE() /* Write the zero pattern to the test area */ CACHE_POST_MEMSET(0) CACHE_POST_DINVALIDATE() CACHE_POST_DISABLE() /* Write the negative pattern to the test area */ CACHE_POST_MEMSET(0xff) CACHE_POST_WB() /* Read the test area */ CACHE_POST_CHECK() CACHE_POST_DINVALIDATE() CACHE_POST_DISABLE() mr r3, r13 mtlr r9 blr /* * Write-through mode test. * Write zeroes, store the cache, write 0xff pattern. * Invalidate the cache. * Check that 0xff pattern is read. */ .global cache_post_test3 cache_post_test3: mflr r9 mr r10, r3 /* tlb */ mr r11, r4 /* p */ mr r12, r5 /* size */ CACHE_POST_WT() CACHE_POST_DINVALIDATE() /* Cache the test area */ CACHE_POST_DTOUCH() /* Write the zero pattern to the test area */ CACHE_POST_MEMSET(0) CACHE_POST_DSTORE() /* Write the negative pattern to the test area */ CACHE_POST_MEMSET(0xff) CACHE_POST_DINVALIDATE() CACHE_POST_DISABLE() /* Read the test area */ CACHE_POST_CHECK() mr r3, r13 mtlr r9 blr /* * Write-back mode test. * Write 0xff pattern, store the cache, write zeroes. * Invalidate the cache. * Check that 0xff pattern is read. */ .global cache_post_test4 cache_post_test4: mflr r9 mr r10, r3 /* tlb */ mr r11, r4 /* p */ mr r12, r5 /* size */ CACHE_POST_WB() CACHE_POST_DINVALIDATE() /* Cache the test area */ CACHE_POST_DTOUCH() /* Write the negative pattern to the test area */ CACHE_POST_MEMSET(0xff) CACHE_POST_DSTORE() /* Write the zero pattern to the test area */ CACHE_POST_MEMSET(0) CACHE_POST_DINVALIDATE() CACHE_POST_DISABLE() /* Read the test area */ CACHE_POST_CHECK() mr r3, r13 mtlr r9 blr /* * Load the test instructions into the instruction cache. * Replace the test instructions. * Check that the original instructions are executed. */ .global cache_post_test5 cache_post_test5: mflr r9 mr r10, r3 /* tlb */ mr r11, r4 /* p */ mr r12, r5 /* size */ CACHE_POST_WT() CACHE_POST_IINVALIDATE() /* Compute r13 = cache_post_test_inst */ bl cache_post_test5_reloc cache_post_test5_reloc: mflr r13 lis r0, (cache_post_test_inst - cache_post_test5_reloc)@h ori r0, r0, (cache_post_test_inst - cache_post_test5_reloc)@l add r13, r13, r0 /* Copy the test instructions to the test area */ lwz r0, 0(r13) stw r0, 0(r11) lwz r0, 8(r13) stw r0, 4(r11) sync /* Invalidate the cache line */ icbi r0, r11 sync isync /* Execute the test instructions */ mtlr r11 blrl /* Replace the test instruction */ lwz r0, 4(r13) stw r0, 0(r11) sync /* Do not invalidate the cache line */ isync /* Execute the test instructions */ mtlr r11 blrl mr r13, r3 CACHE_POST_IINVALIDATE() CACHE_POST_DINVALIDATE() CACHE_POST_DISABLE() mr r3, r13 mtlr r9 blr /* * Load the test instructions into the instruction cache. * Replace the test instructions and invalidate the cache. * Check that the replaced instructions are executed. */ .global cache_post_test6 cache_post_test6: mflr r9 mr r10, r3 /* tlb */ mr r11, r4 /* p */ mr r12, r5 /* size */ CACHE_POST_WT() CACHE_POST_IINVALIDATE() /* Compute r13 = cache_post_test_inst */ bl cache_post_test6_reloc cache_post_test6_reloc: mflr r13 lis r0, (cache_post_test_inst - cache_post_test6_reloc)@h ori r0, r0, (cache_post_test_inst - cache_post_test6_reloc)@l add r13, r13, r0 /* Copy the test instructions to the test area */ lwz r0, 4(r13) stw r0, 0(r11) lwz r0, 8(r13) stw r0, 4(r11) sync /* Invalidate the cache line */ icbi r0, r11 sync isync /* Execute the test instructions */ mtlr r11 blrl /* Replace the test instruction */ lwz r0, 0(r13) stw r0, 0(r11) sync /* Invalidate the cache line */ icbi r0, r11 sync isync /* Execute the test instructions */ mtlr r11 blrl mr r13, r3 CACHE_POST_IINVALIDATE() CACHE_POST_DINVALIDATE() CACHE_POST_DISABLE() mr r3, r13 mtlr r9 blr /* Test instructions. */ cache_post_test_inst: li r3, 0 li r3, -1 blr #endif /* CONFIG_POST & CONFIG_SYS_POST_CACHE */