Root/usbboot/xburst_stage2/cache.c

1/*
2 * Handle operation of Jz CPU's cache
3 *
4 * Copyright (C) 2006 Ingenic Semiconductor Inc.
5 * Author: Seeger Chin <seeger.chin@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 */
12#define u32 unsigned int
13
14#define Index_Invalidate_I 0x00
15#define Index_Writeback_Inv_D 0x01
16#define Index_Load_Tag_I 0x04
17#define Index_Load_Tag_D 0x05
18#define Index_Store_Tag_I 0x08
19#define Index_Store_Tag_D 0x09
20#define Hit_Invalidate_I 0x10
21#define Hit_Invalidate_D 0x11
22#define Hit_Writeback_Inv_D 0x15
23#define Hit_Writeback_I 0x18
24#define Hit_Writeback_D 0x19
25
26#define CACHE_SIZE 16*1024
27#define CACHE_LINE_SIZE 32
28#define KSEG0 0x80000000
29
30#define K0_TO_K1() \
31do { \
32    unsigned long __k0_addr; \
33                        \
34    __asm__ __volatile__( \
35    "la %0, 1f\n\t" \
36    "or %0, %0, %1\n\t" \
37    "jr %0\n\t" \
38    "nop\n\t" \
39    "1: nop\n" \
40    : "=&r"(__k0_addr) \
41    : "r" (0x20000000) ); \
42} while(0)
43
44#define K1_TO_K0() \
45do { \
46    unsigned long __k0_addr; \
47    __asm__ __volatile__( \
48    "nop;nop;nop;nop;nop;nop;nop\n\t" \
49    "la %0, 1f\n\t" \
50    "jr %0\n\t" \
51    "nop\n\t" \
52    "1: nop\n" \
53    : "=&r" (__k0_addr)); \
54} while (0)
55
56#define INVALIDATE_BTB() \
57do { \
58    unsigned long tmp; \
59    __asm__ __volatile__( \
60    ".set mips32\n\t" \
61    "mfc0 %0, $16, 7\n\t" \
62    "nop\n\t" \
63    "ori %0, 2\n\t" \
64    "mtc0 %0, $16, 7\n\t" \
65    "nop\n\t" \
66    ".set mips2\n\t" \
67    : "=&r" (tmp)); \
68} while (0)
69
70#define SYNC_WB() __asm__ __volatile__ ("sync")
71
72#define cache_op(op,addr) \
73    __asm__ __volatile__( \
74    " .set noreorder \n" \
75    " .set mips32\n\t \n" \
76    " cache %0, %1 \n" \
77    " .set mips0 \n" \
78    " .set reorder" \
79    : \
80    : "i" (op), "m" (*(unsigned char *)(addr)))
81
82void __flush_dcache_line(unsigned long addr)
83{
84    cache_op(Hit_Writeback_Inv_D, addr);
85    SYNC_WB();
86}
87
88void __icache_invalidate_all(void)
89{
90    u32 i;
91
92    K0_TO_K1();
93
94    asm volatile (".set noreorder\n"
95              ".set mips32\n\t"
96              "mtc0\t$0,$28\n\t"
97              "mtc0\t$0,$29\n"
98              ".set mips0\n"
99              ".set reorder\n");
100    for (i=KSEG0;i<KSEG0+CACHE_SIZE;i+=CACHE_LINE_SIZE)
101        cache_op(Index_Store_Tag_I, i);
102
103    K1_TO_K0();
104
105    INVALIDATE_BTB();
106}
107
108void __dcache_invalidate_all(void)
109{
110    u32 i;
111
112    asm volatile (".set noreorder\n"
113              ".set mips32\n\t"
114              "mtc0\t$0,$28\n\t"
115              "mtc0\t$0,$29\n"
116              ".set mips0\n"
117              ".set reorder\n");
118    for (i=KSEG0;i<KSEG0+CACHE_SIZE;i+=CACHE_LINE_SIZE)
119        cache_op(Index_Store_Tag_D, i);
120}
121
122void __dcache_writeback_all(void)
123{
124    u32 i;
125    for (i=KSEG0;i<KSEG0+CACHE_SIZE;i+=CACHE_LINE_SIZE)
126        cache_op(Index_Writeback_Inv_D, i);
127    SYNC_WB();
128}
129
130void dma_cache_wback_inv(unsigned long addr, unsigned long size)
131{
132    unsigned long end, a;
133
134    if (size >= CACHE_SIZE) {
135        __dcache_writeback_all();
136    }
137    else {
138        unsigned long dc_lsize = CACHE_LINE_SIZE;
139
140        a = addr & ~(dc_lsize - 1);
141        end = (addr + size - 1) & ~(dc_lsize - 1);
142        while (1) {
143            __flush_dcache_line(a); /* Hit_Writeback_Inv_D */
144            if (a == end)
145                break;
146            a += dc_lsize;
147        }
148    }
149}
150

Archive Download this file



interactive