| #include <linux/linkage.h> |
| #include <init.h> |
| |
| #define CACHE_DLINESIZE 32 |
| |
| ENTRY(__mmu_cache_on) |
| mov r12, lr |
| #ifdef CONFIG_MMU |
| mov r0, #0 |
| mcr p15, 0, r0, c7, c10, 4 @ drain write buffer |
| mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs |
| mrc p15, 0, r0, c1, c0, 0 @ read control reg |
| orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement |
| orr r0, r0, #0x0030 |
| #ifdef CONFIG_CPU_ENDIAN_BE8 |
| orr r0, r0, #1 << 25 @ big-endian page tables |
| #endif |
| bl __common_mmu_cache_on |
| mov r0, #0 |
| mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs |
| #endif |
| mov pc, r12 |
| ENDPROC(__mmu_cache_on) |
| |
| __common_mmu_cache_on: |
| orr r0, r0, #0x000d @ Write buffer, mmu |
| b 1f |
| .align 5 @ cache line aligned |
| 1: mcr p15, 0, r0, c1, c0, 0 @ load control register |
| mrc p15, 0, r0, c1, c0, 0 @ and read it back to |
| sub pc, lr, r0, lsr #32 @ properly flush pipeline |
| |
| ENTRY(__mmu_cache_off) |
| #ifdef CONFIG_MMU |
| mrc p15, 0, r0, c1, c0 |
| bic r0, r0, #0x000d |
| mcr p15, 0, r0, c1, c0 @ turn MMU and cache off |
| mov r0, #0 |
| mcr p15, 0, r0, c7, c7 @ invalidate whole cache v4 |
| mcr p15, 0, r0, c8, c7 @ invalidate whole TLB v4 |
| #endif |
| mov pc, lr |
| ENDPROC(__mmu_cache_off) |
| |
| __BARE_INIT |
| ENTRY(__mmu_cache_flush) |
| mrc p15, 0, r6, c0, c0 @ get processor ID |
| mov r2, #64*1024 @ default: 32K dcache size (*2) |
| mov r11, #32 @ default: 32 byte line size |
| mrc p15, 0, r3, c0, c0, 1 @ read cache type |
| teq r3, r6 @ cache ID register present? |
| beq no_cache_id |
| mov r1, r3, lsr #18 |
| and r1, r1, #7 |
| mov r2, #1024 |
| mov r2, r2, lsl r1 @ base dcache size *2 |
| tst r3, #1 << 14 @ test M bit |
| addne r2, r2, r2, lsr #1 @ +1/2 size if M == 1 |
| mov r3, r3, lsr #12 |
| and r3, r3, #3 |
| mov r11, #8 |
| mov r11, r11, lsl r3 @ cache line size in bytes |
| no_cache_id: |
| mov r1, pc |
| bic r1, r1, #63 @ align to longest cache line |
| add r2, r1, r2 |
| 1: |
| ldr r3, [r1], r11 @ s/w flush D cache |
| teq r1, r2 |
| bne 1b |
| |
| mcr p15, 0, r1, c7, c5, 0 @ flush I cache |
| mcr p15, 0, r1, c7, c6, 0 @ flush D cache |
| mcr p15, 0, r1, c7, c10, 4 @ drain WB |
| mov pc, lr |
| ENDPROC(__mmu_cache_flush) |
| |
| .section ".text.text" |
| /* |
| * dma_inv_range(start, end) |
| * |
| * Invalidate (discard) the specified virtual address range. |
| * May not write back any entries. If 'start' or 'end' |
| * are not cache line aligned, those lines must be written |
| * back. |
| * |
| * - start - virtual start address |
| * - end - virtual end address |
| * |
| * (same as v4wb) |
| */ |
| ENTRY(__dma_inv_range) |
| tst r0, #CACHE_DLINESIZE - 1 |
| bic r0, r0, #CACHE_DLINESIZE - 1 |
| mcrne p15, 0, r0, c7, c10, 1 @ clean D entry |
| tst r1, #CACHE_DLINESIZE - 1 |
| mcrne p15, 0, r1, c7, c10, 1 @ clean D entry |
| 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry |
| add r0, r0, #CACHE_DLINESIZE |
| cmp r0, r1 |
| blo 1b |
| mcr p15, 0, r0, c7, c10, 4 @ drain WB |
| mov pc, lr |
| |
| /* |
| * dma_clean_range(start, end) |
| * |
| * Clean the specified virtual address range. |
| * |
| * - start - virtual start address |
| * - end - virtual end address |
| * |
| * (same as v4wb) |
| */ |
| ENTRY(__dma_clean_range) |
| bic r0, r0, #CACHE_DLINESIZE - 1 |
| 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry |
| add r0, r0, #CACHE_DLINESIZE |
| cmp r0, r1 |
| blo 1b |
| mcr p15, 0, r0, c7, c10, 4 @ drain WB |
| mov pc, lr |
| |
| /* |
| * dma_flush_range(start, end) |
| * |
| * Clean and invalidate the specified virtual address range. |
| * |
| * - start - virtual start address |
| * - end - virtual end address |
| */ |
| ENTRY(__dma_flush_range) |
| bic r0, r0, #CACHE_DLINESIZE - 1 |
| 1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry |
| add r0, r0, #CACHE_DLINESIZE |
| cmp r0, r1 |
| blo 1b |
| mcr p15, 0, r0, c7, c10, 4 @ drain WB |
| mov pc, lr |
| |