xref: /f-stack/freebsd/mips/nlm/hal/haldefs.h (revision 22ce4aff)
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  */
nlm_save_flags_kx(void)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 
nlm_save_flags_cop2(void)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 
nlm_restore_flags(uint32_t sr)67 static inline void nlm_restore_flags(uint32_t sr)
68 {
69 	mips_wr_status(sr);
70 }
71 
72 static inline uint32_t
nlm_load_word(uint64_t addr)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
nlm_store_word(uint64_t addr,uint32_t val)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
nlm_load_dword(volatile uint64_t addr)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
nlm_store_dword(volatile uint64_t addr,uint64_t val)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
nlm_load_dword(uint64_t addr)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
nlm_store_dword(uint64_t addr,uint64_t val)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
nlm_load_word_daddr(uint64_t addr)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
nlm_store_word_daddr(uint64_t addr,uint32_t val)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
nlm_load_dword_daddr(uint64_t addr)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
nlm_store_dword_daddr(uint64_t addr,uint64_t val)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
nlm_load_word_daddr(uint64_t addr)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
nlm_store_word_daddr(uint64_t addr,uint32_t val)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
nlm_load_dword_daddr(uint64_t addr)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
nlm_store_dword_daddr(uint64_t addr,uint64_t val)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
nlm_load_word_daddr(uint64_t addr)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
nlm_store_word_daddr(uint64_t addr,uint32_t val)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
nlm_load_dword_daddr(uint64_t addr)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
nlm_store_dword_daddr(uint64_t addr,uint64_t val)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
nlm_read_reg(uint64_t base,uint32_t reg)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
nlm_write_reg(uint64_t base,uint32_t reg,uint32_t val)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
nlm_read_reg64(uint64_t base,uint32_t reg)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
nlm_write_reg64(uint64_t base,uint32_t reg,uint64_t val)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
nlm_read_reg_xkphys(uint64_t base,uint32_t reg)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
nlm_write_reg_xkphys(uint64_t base,uint32_t reg,uint32_t val)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
nlm_read_reg64_xkphys(uint64_t base,uint32_t reg)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
nlm_write_reg64_xkphys(uint64_t base,uint32_t reg,uint64_t val)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
nlm_pcicfg_base(uint32_t devoffset)425 nlm_pcicfg_base(uint32_t devoffset)
426 {
427 	return xlp_io_base + devoffset;
428 }
429 
430 static inline uint64_t
nlm_xkphys_map_pcibar0(uint64_t pcibase)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
440