]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/mips/cpu/mips32/cpu.c
Merge branch 'u-boot-imx/master' into 'u-boot-arm/master'
[karo-tx-uboot.git] / arch / mips / cpu / mips32 / cpu.c
1 /*
2  * (C) Copyright 2003
3  * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <common.h>
9 #include <command.h>
10 #include <netdev.h>
11 #include <asm/mipsregs.h>
12 #include <asm/cacheops.h>
13 #include <asm/reboot.h>
14
15 #define cache_op(op,addr)                                               \
16         __asm__ __volatile__(                                           \
17         "       .set    push                                    \n"     \
18         "       .set    noreorder                               \n"     \
19         "       .set    mips3\n\t                               \n"     \
20         "       cache   %0, %1                                  \n"     \
21         "       .set    pop                                     \n"     \
22         :                                                               \
23         : "i" (op), "R" (*(unsigned char *)(addr)))
24
25 void __attribute__((weak)) _machine_restart(void)
26 {
27 }
28
29 int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
30 {
31         _machine_restart();
32
33         fprintf(stderr, "*** reset failed ***\n");
34         return 0;
35 }
36
37 #ifdef CONFIG_SYS_CACHELINE_SIZE
38
39 static inline unsigned long icache_line_size(void)
40 {
41         return CONFIG_SYS_CACHELINE_SIZE;
42 }
43
44 static inline unsigned long dcache_line_size(void)
45 {
46         return CONFIG_SYS_CACHELINE_SIZE;
47 }
48
49 #else /* !CONFIG_SYS_CACHELINE_SIZE */
50
51 static inline unsigned long icache_line_size(void)
52 {
53         unsigned long conf1, il;
54         conf1 = read_c0_config1();
55         il = (conf1 & MIPS_CONF1_IL) >> MIPS_CONF1_IL_SHIFT;
56         if (!il)
57                 return 0;
58         return 2 << il;
59 }
60
61 static inline unsigned long dcache_line_size(void)
62 {
63         unsigned long conf1, dl;
64         conf1 = read_c0_config1();
65         dl = (conf1 & MIPS_CONF1_DL) >> MIPS_CONF1_DL_SHIFT;
66         if (!dl)
67                 return 0;
68         return 2 << dl;
69 }
70
71 #endif /* !CONFIG_SYS_CACHELINE_SIZE */
72
73 void flush_cache(ulong start_addr, ulong size)
74 {
75         unsigned long ilsize = icache_line_size();
76         unsigned long dlsize = dcache_line_size();
77         unsigned long addr, aend;
78
79         /* aend will be miscalculated when size is zero, so we return here */
80         if (size == 0)
81                 return;
82
83         addr = start_addr & ~(dlsize - 1);
84         aend = (start_addr + size - 1) & ~(dlsize - 1);
85
86         if (ilsize == dlsize) {
87                 /* flush I-cache & D-cache simultaneously */
88                 while (1) {
89                         cache_op(HIT_WRITEBACK_INV_D, addr);
90                         cache_op(HIT_INVALIDATE_I, addr);
91                         if (addr == aend)
92                                 break;
93                         addr += dlsize;
94                 }
95                 return;
96         }
97
98         /* flush D-cache */
99         while (1) {
100                 cache_op(HIT_WRITEBACK_INV_D, addr);
101                 if (addr == aend)
102                         break;
103                 addr += dlsize;
104         }
105
106         /* flush I-cache */
107         addr = start_addr & ~(ilsize - 1);
108         aend = (start_addr + size - 1) & ~(ilsize - 1);
109         while (1) {
110                 cache_op(HIT_INVALIDATE_I, addr);
111                 if (addr == aend)
112                         break;
113                 addr += ilsize;
114         }
115 }
116
117 void flush_dcache_range(ulong start_addr, ulong stop)
118 {
119         unsigned long lsize = dcache_line_size();
120         unsigned long addr = start_addr & ~(lsize - 1);
121         unsigned long aend = (stop - 1) & ~(lsize - 1);
122
123         while (1) {
124                 cache_op(HIT_WRITEBACK_INV_D, addr);
125                 if (addr == aend)
126                         break;
127                 addr += lsize;
128         }
129 }
130
131 void invalidate_dcache_range(ulong start_addr, ulong stop)
132 {
133         unsigned long lsize = dcache_line_size();
134         unsigned long addr = start_addr & ~(lsize - 1);
135         unsigned long aend = (stop - 1) & ~(lsize - 1);
136
137         while (1) {
138                 cache_op(HIT_INVALIDATE_D, addr);
139                 if (addr == aend)
140                         break;
141                 addr += lsize;
142         }
143 }
144
145 void write_one_tlb(int index, u32 pagemask, u32 hi, u32 low0, u32 low1)
146 {
147         write_c0_entrylo0(low0);
148         write_c0_pagemask(pagemask);
149         write_c0_entrylo1(low1);
150         write_c0_entryhi(hi);
151         write_c0_index(index);
152         tlb_write_indexed();
153 }
154
155 int cpu_eth_init(bd_t *bis)
156 {
157 #ifdef CONFIG_SOC_AU1X00
158         au1x00_enet_initialize(bis);
159 #endif
160         return 0;
161 }