1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright 2003-2011 Netlogic Microsystems (Netlogic). All rights
5 * reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY Netlogic Microsystems ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * NETLOGIC_BSD
31 * $FreeBSD$
32 */
33
34 #ifndef __NLM_HAL_MMIO_H__
35 #define __NLM_HAL_MMIO_H__
36
37 /*
38 * This file contains platform specific memory mapped IO implementation
39 * and will provide a way to read 32/64 bit memory mapped registers in
40 * all ABIs
41 */
42
43 /*
44 * For o32 compilation, we have to disable interrupts and enable KX bit to
45 * access 64 bit addresses or data.
46 *
47 * We need to disable interrupts because we save just the lower 32 bits of
48 * registers in interrupt handling. So if we get hit by an interrupt while
49 * using the upper 32 bits of a register, we lose.
50 */
51 static inline uint32_t nlm_save_flags_kx(void)
52 {
53 uint32_t sr = mips_rd_status();
54
55 mips_wr_status((sr & ~MIPS_SR_INT_IE) | MIPS_SR_KX);
56 return (sr);
57 }
58
59 static inline uint32_t nlm_save_flags_cop2(void)
60 {
61 uint32_t sr = mips_rd_status();
62
63 mips_wr_status((sr & ~MIPS_SR_INT_IE) | MIPS_SR_COP_2_BIT);
64 return (sr);
65 }
66
67 static inline void nlm_restore_flags(uint32_t sr)
68 {
69 mips_wr_status(sr);
70 }
71
72 static inline uint32_t
73 nlm_load_word(uint64_t addr)
74 {
75 volatile uint32_t *p = (volatile uint32_t *)(long)addr;
76
77 return *p;
78 }
79
80 static inline void
81 nlm_store_word(uint64_t addr, uint32_t val)
82 {
83 volatile uint32_t *p = (volatile uint32_t *)(long)addr;
84
85 *p = val;
86 }
87
88 #if defined(__mips_n64) || defined(__mips_n32)
89 static inline uint64_t
90 nlm_load_dword(volatile uint64_t addr)
91 {
92 volatile uint64_t *p = (volatile uint64_t *)(long)addr;
93
94 return *p;
95 }
96
97 static inline void
98 nlm_store_dword(volatile uint64_t addr, uint64_t val)
99 {
100 volatile uint64_t *p = (volatile uint64_t *)(long)addr;
101
102 *p = val;
103 }
104
105 #else /* o32 */
106 static inline uint64_t
107 nlm_load_dword(uint64_t addr)
108 {
109 volatile uint64_t *p = (volatile uint64_t *)(long)addr;
110 uint32_t valhi, vallo, sr;
111
112 sr = nlm_save_flags_kx();
113 __asm__ __volatile__(
114 ".set push\n\t"
115 ".set mips64\n\t"
116 "ld $8, 0(%2)\n\t"
117 "dsra32 %0, $8, 0\n\t"
118 "sll %1, $8, 0\n\t"
119 ".set pop\n"
120 : "=r"(valhi), "=r"(vallo)
121 : "r"(p)
122 : "$8");
123 nlm_restore_flags(sr);
124
125 return ((uint64_t)valhi << 32) | vallo;
126 }
127
128 static inline void
129 nlm_store_dword(uint64_t addr, uint64_t val)
130 {
131 volatile uint64_t *p = (volatile uint64_t *)(long)addr;
132 uint32_t valhi, vallo, sr;
133
134 valhi = val >> 32;
135 vallo = val & 0xffffffff;
136
137 sr = nlm_save_flags_kx();
138 __asm__ __volatile__(
139 ".set push\n\t"
140 ".set mips64\n\t"
141 "dsll32 $8, %1, 0\n\t"
142 "dsll32 $9, %2, 0\n\t" /* get rid of the */
143 "dsrl32 $9, $9, 0\n\t" /* sign extend */
144 "or $9, $9, $8\n\t"
145 "sd $9, 0(%0)\n\t"
146 ".set pop\n"
147 : : "r"(p), "r"(valhi), "r"(vallo)
148 : "$8", "$9", "memory");
149 nlm_restore_flags(sr);
150 }
151 #endif
152
153 #if defined(__mips_n64)
154 static inline uint64_t
155 nlm_load_word_daddr(uint64_t addr)
156 {
157 volatile uint32_t *p = (volatile uint32_t *)(long)addr;
158
159 return *p;
160 }
161
162 static inline void
163 nlm_store_word_daddr(uint64_t addr, uint32_t val)
164 {
165 volatile uint32_t *p = (volatile uint32_t *)(long)addr;
166
167 *p = val;
168 }
169
170 static inline uint64_t
171 nlm_load_dword_daddr(uint64_t addr)
172 {
173 volatile uint64_t *p = (volatile uint64_t *)(long)addr;
174
175 return *p;
176 }
177
178 static inline void
179 nlm_store_dword_daddr(uint64_t addr, uint64_t val)
180 {
181 volatile uint64_t *p = (volatile uint64_t *)(long)addr;
182
183 *p = val;
184 }
185
186 #elif defined(__mips_n32)
187
188 static inline uint64_t
189 nlm_load_word_daddr(uint64_t addr)
190 {
191 uint32_t val;
192
193 __asm__ __volatile__(
194 ".set push\n\t"
195 ".set mips64\n\t"
196 "lw %0, 0(%1)\n\t"
197 ".set pop\n"
198 : "=r"(val)
199 : "r"(addr));
200
201 return val;
202 }
203
204 static inline void
205 nlm_store_word_daddr(uint64_t addr, uint32_t val)
206 {
207 __asm__ __volatile__(
208 ".set push\n\t"
209 ".set mips64\n\t"
210 "sw %0, 0(%1)\n\t"
211 ".set pop\n"
212 : : "r"(val), "r"(addr)
213 : "memory");
214 }
215
216 static inline uint64_t
217 nlm_load_dword_daddr(uint64_t addr)
218 {
219 uint64_t val;
220
221 __asm__ __volatile__(
222 ".set push\n\t"
223 ".set mips64\n\t"
224 "ld %0, 0(%1)\n\t"
225 ".set pop\n"
226 : "=r"(val)
227 : "r"(addr));
228 return val;
229 }
230
231 static inline void
232 nlm_store_dword_daddr(uint64_t addr, uint64_t val)
233 {
234 __asm__ __volatile__(
235 ".set push\n\t"
236 ".set mips64\n\t"
237 "sd %0, 0(%1)\n\t"
238 ".set pop\n"
239 : : "r"(val), "r"(addr)
240 : "memory");
241 }
242
243 #else /* o32 */
244 static inline uint64_t
245 nlm_load_word_daddr(uint64_t addr)
246 {
247 uint32_t val, addrhi, addrlo, sr;
248
249 addrhi = addr >> 32;
250 addrlo = addr & 0xffffffff;
251
252 sr = nlm_save_flags_kx();
253 __asm__ __volatile__(
254 ".set push\n\t"
255 ".set mips64\n\t"
256 "dsll32 $8, %1, 0\n\t"
257 "dsll32 $9, %2, 0\n\t"
258 "dsrl32 $9, $9, 0\n\t"
259 "or $9, $9, $8\n\t"
260 "lw %0, 0($9)\n\t"
261 ".set pop\n"
262 : "=r"(val)
263 : "r"(addrhi), "r"(addrlo)
264 : "$8", "$9");
265 nlm_restore_flags(sr);
266
267 return val;
268
269 }
270
271 static inline void
272 nlm_store_word_daddr(uint64_t addr, uint32_t val)
273 {
274 uint32_t addrhi, addrlo, sr;
275
276 addrhi = addr >> 32;
277 addrlo = addr & 0xffffffff;
278
279 sr = nlm_save_flags_kx();
280 __asm__ __volatile__(
281 ".set push\n\t"
282 ".set mips64\n\t"
283 "dsll32 $8, %1, 0\n\t"
284 "dsll32 $9, %2, 0\n\t"
285 "dsrl32 $9, $9, 0\n\t"
286 "or $9, $9, $8\n\t"
287 "sw %0, 0($9)\n\t"
288 ".set pop\n"
289 : : "r"(val), "r"(addrhi), "r"(addrlo)
290 : "$8", "$9", "memory");
291 nlm_restore_flags(sr);
292 }
293
294 static inline uint64_t
295 nlm_load_dword_daddr(uint64_t addr)
296 {
297 uint32_t addrh, addrl, sr;
298 uint32_t valh, vall;
299
300 addrh = addr >> 32;
301 addrl = addr & 0xffffffff;
302
303 sr = nlm_save_flags_kx();
304 __asm__ __volatile__(
305 ".set push\n\t"
306 ".set mips64\n\t"
307 "dsll32 $8, %2, 0\n\t"
308 "dsll32 $9, %3, 0\n\t"
309 "dsrl32 $9, $9, 0\n\t"
310 "or $9, $9, $8\n\t"
311 "ld $8, 0($9)\n\t"
312 "dsra32 %0, $8, 0\n\t"
313 "sll %1, $8, 0\n\t"
314 ".set pop\n"
315 : "=r"(valh), "=r"(vall)
316 : "r"(addrh), "r"(addrl)
317 : "$8", "$9");
318 nlm_restore_flags(sr);
319
320 return ((uint64_t)valh << 32) | vall;
321 }
322
323 static inline void
324 nlm_store_dword_daddr(uint64_t addr, uint64_t val)
325 {
326 uint32_t addrh, addrl, sr;
327 uint32_t valh, vall;
328
329 addrh = addr >> 32;
330 addrl = addr & 0xffffffff;
331 valh = val >> 32;
332 vall = val & 0xffffffff;
333
334 sr = nlm_save_flags_kx();
335 __asm__ __volatile__(
336 ".set push\n\t"
337 ".set mips64\n\t"
338 "dsll32 $8, %2, 0\n\t"
339 "dsll32 $9, %3, 0\n\t"
340 "dsrl32 $9, $9, 0\n\t"
341 "or $9, $9, $8\n\t"
342 "dsll32 $8, %0, 0\n\t"
343 "dsll32 $10, %1, 0\n\t"
344 "dsrl32 $10, $10, 0\n\t"
345 "or $8, $8, $10\n\t"
346 "sd $8, 0($9)\n\t"
347 ".set pop\n"
348 : : "r"(valh), "r"(vall), "r"(addrh), "r"(addrl)
349 : "$8", "$9", "memory");
350 nlm_restore_flags(sr);
351 }
352 #endif /* __mips_n64 */
353
354 static inline uint32_t
355 nlm_read_reg(uint64_t base, uint32_t reg)
356 {
357 volatile uint32_t *addr = (volatile uint32_t *)(long)base + reg;
358
359 return *addr;
360 }
361
362 static inline void
363 nlm_write_reg(uint64_t base, uint32_t reg, uint32_t val)
364 {
365 volatile uint32_t *addr = (volatile uint32_t *)(long)base + reg;
366
367 *addr = val;
368 }
369
370 static inline uint64_t
371 nlm_read_reg64(uint64_t base, uint32_t reg)
372 {
373 uint64_t addr = base + (reg >> 1) * sizeof(uint64_t);
374
375 return nlm_load_dword(addr);
376 }
377
378 static inline void
379 nlm_write_reg64(uint64_t base, uint32_t reg, uint64_t val)
380 {
381 uint64_t addr = base + (reg >> 1) * sizeof(uint64_t);
382
383 return nlm_store_dword(addr, val);
384 }
385
386 /*
387 * Routines to store 32/64 bit values to 64 bit addresses,
388 * used when going thru XKPHYS to access registers
389 */
390 static inline uint32_t
391 nlm_read_reg_xkphys(uint64_t base, uint32_t reg)
392 {
393 uint64_t addr = base + reg * sizeof(uint32_t);
394
395 return nlm_load_word_daddr(addr);
396 }
397
398 static inline void
399 nlm_write_reg_xkphys(uint64_t base, uint32_t reg, uint32_t val)
400 {
401 uint64_t addr = base + reg * sizeof(uint32_t);
402 return nlm_store_word_daddr(addr, val);
403 }
404
405 static inline uint64_t
406 nlm_read_reg64_xkphys(uint64_t base, uint32_t reg)
407 {
408 uint64_t addr = base + (reg >> 1) * sizeof(uint64_t);
409
410 return nlm_load_dword_daddr(addr);
411 }
412
413 static inline void
414 nlm_write_reg64_xkphys(uint64_t base, uint32_t reg, uint64_t val)
415 {
416 uint64_t addr = base + (reg >> 1) * sizeof(uint64_t);
417
418 return nlm_store_dword_daddr(addr, val);
419 }
420
421 /* Location where IO base is mapped */
422 extern uint64_t xlp_io_base;
423
424 static inline uint64_t
425 nlm_pcicfg_base(uint32_t devoffset)
426 {
427 return xlp_io_base + devoffset;
428 }
429
430 static inline uint64_t
431 nlm_xkphys_map_pcibar0(uint64_t pcibase)
432 {
433 uint64_t paddr;
434
435 paddr = nlm_read_reg(pcibase, 0x4) & ~0xfu;
436 return (uint64_t)0x9000000000000000 | paddr;
437 }
438
439 #endif
Cache object: 4a282b466afd598d557544c90a138bd8
|