2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright 2003-2011 Netlogic Microsystems (Netlogic). All rights
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
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
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.
34 #ifndef __NLM_HAL_MMIO_H__
35 #define __NLM_HAL_MMIO_H__
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
44 * For o32 compilation, we have to disable interrupts and enable KX bit to
45 * access 64 bit addresses or data.
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.
51 static inline uint32_t nlm_save_flags_kx(void)
53 uint32_t sr = mips_rd_status();
55 mips_wr_status((sr & ~MIPS_SR_INT_IE) | MIPS_SR_KX);
59 static inline uint32_t nlm_save_flags_cop2(void)
61 uint32_t sr = mips_rd_status();
63 mips_wr_status((sr & ~MIPS_SR_INT_IE) | MIPS_SR_COP_2_BIT);
67 static inline void nlm_restore_flags(uint32_t sr)
72 static inline uint32_t
73 nlm_load_word(uint64_t addr)
75 volatile uint32_t *p = (volatile uint32_t *)(long)addr;
81 nlm_store_word(uint64_t addr, uint32_t val)
83 volatile uint32_t *p = (volatile uint32_t *)(long)addr;
88 #if defined(__mips_n64) || defined(__mips_n32)
89 static inline uint64_t
90 nlm_load_dword(volatile uint64_t addr)
92 volatile uint64_t *p = (volatile uint64_t *)(long)addr;
98 nlm_store_dword(volatile uint64_t addr, uint64_t val)
100 volatile uint64_t *p = (volatile uint64_t *)(long)addr;
106 static inline uint64_t
107 nlm_load_dword(uint64_t addr)
109 volatile uint64_t *p = (volatile uint64_t *)(long)addr;
110 uint32_t valhi, vallo, sr;
112 sr = nlm_save_flags_kx();
113 __asm__ __volatile__(
117 "dsra32 %0, $8, 0\n\t"
120 : "=r"(valhi), "=r"(vallo)
123 nlm_restore_flags(sr);
125 return ((uint64_t)valhi << 32) | vallo;
129 nlm_store_dword(uint64_t addr, uint64_t val)
131 volatile uint64_t *p = (volatile uint64_t *)(long)addr;
132 uint32_t valhi, vallo, sr;
135 vallo = val & 0xffffffff;
137 sr = nlm_save_flags_kx();
138 __asm__ __volatile__(
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 */
147 : : "r"(p), "r"(valhi), "r"(vallo)
148 : "$8", "$9", "memory");
149 nlm_restore_flags(sr);
153 #if defined(__mips_n64)
154 static inline uint64_t
155 nlm_load_word_daddr(uint64_t addr)
157 volatile uint32_t *p = (volatile uint32_t *)(long)addr;
163 nlm_store_word_daddr(uint64_t addr, uint32_t val)
165 volatile uint32_t *p = (volatile uint32_t *)(long)addr;
170 static inline uint64_t
171 nlm_load_dword_daddr(uint64_t addr)
173 volatile uint64_t *p = (volatile uint64_t *)(long)addr;
179 nlm_store_dword_daddr(uint64_t addr, uint64_t val)
181 volatile uint64_t *p = (volatile uint64_t *)(long)addr;
186 #elif defined(__mips_n32)
188 static inline uint64_t
189 nlm_load_word_daddr(uint64_t addr)
193 __asm__ __volatile__(
205 nlm_store_word_daddr(uint64_t addr, uint32_t val)
207 __asm__ __volatile__(
212 : : "r"(val), "r"(addr)
216 static inline uint64_t
217 nlm_load_dword_daddr(uint64_t addr)
221 __asm__ __volatile__(
232 nlm_store_dword_daddr(uint64_t addr, uint64_t val)
234 __asm__ __volatile__(
239 : : "r"(val), "r"(addr)
244 static inline uint64_t
245 nlm_load_word_daddr(uint64_t addr)
247 uint32_t val, addrhi, addrlo, sr;
250 addrlo = addr & 0xffffffff;
252 sr = nlm_save_flags_kx();
253 __asm__ __volatile__(
256 "dsll32 $8, %1, 0\n\t"
257 "dsll32 $9, %2, 0\n\t"
258 "dsrl32 $9, $9, 0\n\t"
263 : "r"(addrhi), "r"(addrlo)
265 nlm_restore_flags(sr);
272 nlm_store_word_daddr(uint64_t addr, uint32_t val)
274 uint32_t addrhi, addrlo, sr;
277 addrlo = addr & 0xffffffff;
279 sr = nlm_save_flags_kx();
280 __asm__ __volatile__(
283 "dsll32 $8, %1, 0\n\t"
284 "dsll32 $9, %2, 0\n\t"
285 "dsrl32 $9, $9, 0\n\t"
289 : : "r"(val), "r"(addrhi), "r"(addrlo)
290 : "$8", "$9", "memory");
291 nlm_restore_flags(sr);
294 static inline uint64_t
295 nlm_load_dword_daddr(uint64_t addr)
297 uint32_t addrh, addrl, sr;
301 addrl = addr & 0xffffffff;
303 sr = nlm_save_flags_kx();
304 __asm__ __volatile__(
307 "dsll32 $8, %2, 0\n\t"
308 "dsll32 $9, %3, 0\n\t"
309 "dsrl32 $9, $9, 0\n\t"
312 "dsra32 %0, $8, 0\n\t"
315 : "=r"(valh), "=r"(vall)
316 : "r"(addrh), "r"(addrl)
318 nlm_restore_flags(sr);
320 return ((uint64_t)valh << 32) | vall;
324 nlm_store_dword_daddr(uint64_t addr, uint64_t val)
326 uint32_t addrh, addrl, sr;
330 addrl = addr & 0xffffffff;
332 vall = val & 0xffffffff;
334 sr = nlm_save_flags_kx();
335 __asm__ __volatile__(
338 "dsll32 $8, %2, 0\n\t"
339 "dsll32 $9, %3, 0\n\t"
340 "dsrl32 $9, $9, 0\n\t"
342 "dsll32 $8, %0, 0\n\t"
343 "dsll32 $10, %1, 0\n\t"
344 "dsrl32 $10, $10, 0\n\t"
348 : : "r"(valh), "r"(vall), "r"(addrh), "r"(addrl)
349 : "$8", "$9", "memory");
350 nlm_restore_flags(sr);
352 #endif /* __mips_n64 */
354 static inline uint32_t
355 nlm_read_reg(uint64_t base, uint32_t reg)
357 volatile uint32_t *addr = (volatile uint32_t *)(long)base + reg;
363 nlm_write_reg(uint64_t base, uint32_t reg, uint32_t val)
365 volatile uint32_t *addr = (volatile uint32_t *)(long)base + reg;
370 static inline uint64_t
371 nlm_read_reg64(uint64_t base, uint32_t reg)
373 uint64_t addr = base + (reg >> 1) * sizeof(uint64_t);
375 return nlm_load_dword(addr);
379 nlm_write_reg64(uint64_t base, uint32_t reg, uint64_t val)
381 uint64_t addr = base + (reg >> 1) * sizeof(uint64_t);
383 return nlm_store_dword(addr, val);
387 * Routines to store 32/64 bit values to 64 bit addresses,
388 * used when going thru XKPHYS to access registers
390 static inline uint32_t
391 nlm_read_reg_xkphys(uint64_t base, uint32_t reg)
393 uint64_t addr = base + reg * sizeof(uint32_t);
395 return nlm_load_word_daddr(addr);
399 nlm_write_reg_xkphys(uint64_t base, uint32_t reg, uint32_t val)
401 uint64_t addr = base + reg * sizeof(uint32_t);
402 return nlm_store_word_daddr(addr, val);
405 static inline uint64_t
406 nlm_read_reg64_xkphys(uint64_t base, uint32_t reg)
408 uint64_t addr = base + (reg >> 1) * sizeof(uint64_t);
410 return nlm_load_dword_daddr(addr);
414 nlm_write_reg64_xkphys(uint64_t base, uint32_t reg, uint64_t val)
416 uint64_t addr = base + (reg >> 1) * sizeof(uint64_t);
418 return nlm_store_dword_daddr(addr, val);
421 /* Location where IO base is mapped */
422 extern uint64_t xlp_io_base;
424 static inline uint64_t
425 nlm_pcicfg_base(uint32_t devoffset)
427 return xlp_io_base + devoffset;
430 static inline uint64_t
431 nlm_xkphys_map_pcibar0(uint64_t pcibase)
435 paddr = nlm_read_reg(pcibase, 0x4) & ~0xfu;
436 return (uint64_t)0x9000000000000000 | paddr;