1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include <linux/config.h>
27#include <linux/sched.h>
28#include <linux/smp.h>
29
30#include <asm/io.h>
31#include <asm/sibyte/sb1250.h>
32#include <asm/sibyte/sb1250_regs.h>
33#include <asm/sibyte/sb1250_dma.h>
34#include <asm/sibyte/64bit.h>
35
36#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
37#define SB1_PREF_LOAD_STREAMED_HINT "0"
38#define SB1_PREF_STORE_STREAMED_HINT "1"
39#else
40#define SB1_PREF_LOAD_STREAMED_HINT "4"
41#define SB1_PREF_STORE_STREAMED_HINT "5"
42#endif
43
44#ifdef CONFIG_SIBYTE_DMA_PAGEOPS
45static inline void clear_page_cpu(void *page)
46#else
47void clear_page(void *page)
48#endif
49{
50
51
52
53
54
55
56
57
58
59 __asm__ __volatile__(
60 ".set push \n"
61 ".set noreorder \n"
62 ".set noat \n"
63 ".set mips4 \n"
64 " addiu $1, %0, %2 \n"
65#ifdef CONFIG_CPU_HAS_PREFETCH
66 " pref " SB1_PREF_STORE_STREAMED_HINT ", 0(%0) \n"
67 " pref " SB1_PREF_STORE_STREAMED_HINT ", 32(%0) \n"
68 " pref " SB1_PREF_STORE_STREAMED_HINT ", 64(%0) \n"
69 " pref " SB1_PREF_STORE_STREAMED_HINT ", 96(%0) \n"
70#endif
71 "1: sd $0, 0(%0) \n"
72 " sd $0, 8(%0) \n"
73 " sd $0, 16(%0) \n"
74 " sd $0, 24(%0) \n"
75#ifdef CONFIG_CPU_HAS_PREFETCH
76 " pref " SB1_PREF_STORE_STREAMED_HINT ",128(%0) \n"
77#endif
78 " bne $1, %0, 1b \n"
79 " addiu %0, %0, 32 \n"
80 ".set pop \n"
81 : "=r" (page)
82 : "0" (page), "I" (PAGE_SIZE-32)
83 : "memory");
84
85}
86
87#ifdef CONFIG_SIBYTE_DMA_PAGEOPS
88static inline void copy_page_cpu(void *to, void *from)
89#else
90void copy_page(void *to, void *from)
91#endif
92{
93
94
95
96
97
98
99
100
101
102
103
104
105 __asm__ __volatile__(
106 ".set push \n"
107 ".set noreorder \n"
108 ".set noat \n"
109 ".set mips4 \n"
110 " addiu $1, %0, %4 \n"
111#ifdef CONFIG_CPU_HAS_PREFETCH
112 " pref " SB1_PREF_LOAD_STREAMED_HINT ", 0(%0) \n"
113 " pref " SB1_PREF_STORE_STREAMED_HINT ", 0(%1) \n"
114 " pref " SB1_PREF_LOAD_STREAMED_HINT ", 32(%0) \n"
115 " pref " SB1_PREF_STORE_STREAMED_HINT ", 32(%1) \n"
116 " pref " SB1_PREF_LOAD_STREAMED_HINT ", 64(%0) \n"
117 " pref " SB1_PREF_STORE_STREAMED_HINT ", 64(%1) \n"
118#endif
119 "1: lw $2, 0(%0) \n"
120 " lw $3, 4(%0) \n"
121 " lw $4, 8(%0) \n"
122 " lw $5, 12(%0) \n"
123 " lw $6, 16(%0) \n"
124 " lw $7, 20(%0) \n"
125 " lw $8, 24(%0) \n"
126 " lw $9, 28(%0) \n"
127#ifdef CONFIG_CPU_HAS_PREFETCH
128 " pref " SB1_PREF_LOAD_STREAMED_HINT ", 96(%0) \n"
129 " pref " SB1_PREF_STORE_STREAMED_HINT ", 96(%1) \n"
130#endif
131 " sw $2, 0(%1) \n"
132 " sw $3, 4(%1) \n"
133 " sw $4, 8(%1) \n"
134 " sw $5, 12(%1) \n"
135 " sw $6, 16(%1) \n"
136 " sw $7, 20(%1) \n"
137 " sw $8, 24(%1) \n"
138 " sw $9, 28(%1) \n"
139 " addiu %1, %1, 32 \n"
140 " nop \n"
141 " nop \n"
142 " bne $1, %0, 1b \n"
143 " addiu %0, %0, 32 \n"
144 ".set pop \n"
145 : "=r" (to), "=r" (from)
146 : "0" (from), "1" (to), "I" (PAGE_SIZE-32)
147 : "$2","$3","$4","$5","$6","$7","$8","$9","memory");
148}
149
150
151#ifdef CONFIG_SIBYTE_DMA_PAGEOPS
152
153
154
155
156
157typedef struct dmadscr_s {
158 uint64_t dscr_a;
159 uint64_t dscr_b;
160 uint64_t pad_a;
161 uint64_t pad_b;
162} dmadscr_t;
163
164static dmadscr_t page_descr[NR_CPUS] __attribute__((aligned(SMP_CACHE_BYTES)));
165
166void sb1_dma_init(void)
167{
168 int cpu = smp_processor_id();
169 uint64_t base_val = PHYSADDR(&page_descr[cpu]) | V_DM_DSCR_BASE_RINGSZ(1);
170
171 out64(base_val,
172 IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_BASE));
173 out64(base_val | M_DM_DSCR_BASE_RESET,
174 IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_BASE));
175 out64(base_val | M_DM_DSCR_BASE_ENABL,
176 IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_BASE));
177}
178
179void clear_page(void *page)
180{
181 int cpu = smp_processor_id();
182
183
184 if (KSEGX(page) != K0BASE)
185 return clear_page_cpu(page);
186
187 page_descr[cpu].dscr_a = PHYSADDR(page) | M_DM_DSCRA_ZERO_MEM | M_DM_DSCRA_L2C_DEST | M_DM_DSCRA_INTERRUPT;
188 page_descr[cpu].dscr_b = V_DM_DSCRB_SRC_LENGTH(PAGE_SIZE);
189 out64(1, IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_COUNT));
190
191
192
193
194
195 while (!(in64(IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_BASE_DEBUG)) & M_DM_DSCR_BASE_INTERRUPT))
196 ;
197 in64(IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_BASE));
198}
199
200void copy_page(void *to, void *from)
201{
202 unsigned long from_phys = PHYSADDR(from);
203 unsigned long to_phys = PHYSADDR(to);
204 int cpu = smp_processor_id();
205
206
207 if ((KSEGX(to) != K0BASE) || (KSEGX(from) != K0BASE))
208 return copy_page_cpu(to, from);
209
210 page_descr[cpu].dscr_a = PHYSADDR(to_phys) | M_DM_DSCRA_L2C_DEST | M_DM_DSCRA_INTERRUPT;
211 page_descr[cpu].dscr_b = PHYSADDR(from_phys) | V_DM_DSCRB_SRC_LENGTH(PAGE_SIZE);
212 out64(1, IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_COUNT));
213
214
215
216
217
218 while (!(in64(IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_BASE_DEBUG)) & M_DM_DSCR_BASE_INTERRUPT))
219 ;
220 in64(IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_BASE));
221}
222
223#endif
224