1225394Sjchandra/*-
2225394Sjchandra * Copyright 2003-2011 Netlogic Microsystems (Netlogic). All rights
3225394Sjchandra * reserved.
4225394Sjchandra *
5225394Sjchandra * Redistribution and use in source and binary forms, with or without
6225394Sjchandra * modification, are permitted provided that the following conditions are
7225394Sjchandra * met:
8225394Sjchandra *
9225394Sjchandra * 1. Redistributions of source code must retain the above copyright
10225394Sjchandra *    notice, this list of conditions and the following disclaimer.
11225394Sjchandra * 2. Redistributions in binary form must reproduce the above copyright
12225394Sjchandra *    notice, this list of conditions and the following disclaimer in
13225394Sjchandra *    the documentation and/or other materials provided with the
14225394Sjchandra *    distribution.
15225394Sjchandra *
16225394Sjchandra * THIS SOFTWARE IS PROVIDED BY Netlogic Microsystems ``AS IS'' AND
17225394Sjchandra * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18225394Sjchandra * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19225394Sjchandra * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE
20225394Sjchandra * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21225394Sjchandra * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22225394Sjchandra * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23225394Sjchandra * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24225394Sjchandra * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25225394Sjchandra * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26225394Sjchandra * THE POSSIBILITY OF SUCH DAMAGE.
27225394Sjchandra *
28225394Sjchandra * NETLOGIC_BSD
29225394Sjchandra * $FreeBSD$
30225394Sjchandra */
31225394Sjchandra
32225394Sjchandra#ifndef __NLM_HAL_MMIO_H__
33225394Sjchandra#define __NLM_HAL_MMIO_H__
34225394Sjchandra
35225394Sjchandra/*
36225394Sjchandra * This file contains platform specific memory mapped IO implementation
37225394Sjchandra * and will provide a way to read 32/64 bit memory mapped registers in
38225394Sjchandra * all ABIs
39225394Sjchandra */
40225394Sjchandra
41225394Sjchandra/*
42225394Sjchandra * For o32 compilation, we have to disable interrupts and enable KX bit to
43225394Sjchandra * access 64 bit addresses or data.
44225394Sjchandra *
45225394Sjchandra * We need to disable interrupts because we save just the lower 32 bits of
46225394Sjchandra * registers in  interrupt handling. So if we get hit by an interrupt while
47225394Sjchandra * using the upper 32 bits of a register, we lose.
48225394Sjchandra */
49225394Sjchandrastatic inline uint32_t nlm_save_flags_kx(void)
50225394Sjchandra{
51225394Sjchandra	uint32_t sr = mips_rd_status();
52225394Sjchandra
53225394Sjchandra	mips_wr_status((sr & ~MIPS_SR_INT_IE) | MIPS_SR_KX);
54225394Sjchandra	return (sr);
55225394Sjchandra}
56225394Sjchandra
57225394Sjchandrastatic inline uint32_t nlm_save_flags_cop2(void)
58225394Sjchandra{
59225394Sjchandra	uint32_t sr = mips_rd_status();
60225394Sjchandra
61225394Sjchandra	mips_wr_status((sr & ~MIPS_SR_INT_IE) | MIPS_SR_COP_2_BIT);
62225394Sjchandra	return (sr);
63225394Sjchandra}
64225394Sjchandra
65225394Sjchandrastatic inline void nlm_restore_flags(uint32_t sr)
66225394Sjchandra{
67225394Sjchandra	mips_wr_status(sr);
68225394Sjchandra}
69225394Sjchandra
70225394Sjchandrastatic inline uint32_t
71225394Sjchandranlm_load_word(uint64_t addr)
72225394Sjchandra{
73225394Sjchandra	volatile uint32_t *p = (volatile uint32_t *)(long)addr;
74225394Sjchandra
75225394Sjchandra	return *p;
76225394Sjchandra}
77225394Sjchandra
78225394Sjchandrastatic inline void
79225394Sjchandranlm_store_word(uint64_t addr, uint32_t val)
80225394Sjchandra{
81225394Sjchandra	volatile uint32_t *p = (volatile uint32_t *)(long)addr;
82225394Sjchandra
83225394Sjchandra	*p = val;
84225394Sjchandra}
85225394Sjchandra
86225394Sjchandra#if defined(__mips_n64) || defined(__mips_n32)
87225394Sjchandrastatic inline uint64_t
88225394Sjchandranlm_load_dword(volatile uint64_t addr)
89225394Sjchandra{
90225394Sjchandra	volatile uint64_t *p = (volatile uint64_t *)(long)addr;
91225394Sjchandra
92225394Sjchandra	return *p;
93225394Sjchandra}
94225394Sjchandra
95225394Sjchandrastatic inline void
96225394Sjchandranlm_store_dword(volatile uint64_t addr, uint64_t val)
97225394Sjchandra{
98225394Sjchandra	volatile uint64_t *p = (volatile uint64_t *)(long)addr;
99225394Sjchandra
100225394Sjchandra	*p = val;
101225394Sjchandra}
102225394Sjchandra
103225394Sjchandra#else /* o32 */
104225394Sjchandrastatic inline uint64_t
105225394Sjchandranlm_load_dword(uint64_t addr)
106225394Sjchandra{
107225394Sjchandra	volatile uint64_t *p = (volatile uint64_t *)(long)addr;
108225394Sjchandra	uint32_t valhi, vallo, sr;
109225394Sjchandra
110225394Sjchandra	sr = nlm_save_flags_kx();
111225394Sjchandra	__asm__ __volatile__(
112225394Sjchandra		".set	push\n\t"
113225394Sjchandra		".set	mips64\n\t"
114225394Sjchandra		"ld	$8, 0(%2)\n\t"
115225394Sjchandra		"dsra32	%0, $8, 0\n\t"
116225394Sjchandra		"sll	%1, $8, 0\n\t"
117225394Sjchandra		".set	pop\n"
118225394Sjchandra		: "=r"(valhi), "=r"(vallo)
119225394Sjchandra		: "r"(p)
120225394Sjchandra		: "$8");
121225394Sjchandra	nlm_restore_flags(sr);
122225394Sjchandra
123225394Sjchandra	return ((uint64_t)valhi << 32) | vallo;
124225394Sjchandra}
125225394Sjchandra
126225394Sjchandrastatic inline void
127225394Sjchandranlm_store_dword(uint64_t addr, uint64_t val)
128225394Sjchandra{
129225394Sjchandra	volatile uint64_t *p = (volatile uint64_t *)(long)addr;
130225394Sjchandra	uint32_t valhi, vallo, sr;
131225394Sjchandra
132225394Sjchandra	valhi = val >> 32;
133225394Sjchandra	vallo = val & 0xffffffff;
134225394Sjchandra
135225394Sjchandra	sr = nlm_save_flags_kx();
136225394Sjchandra	__asm__ __volatile__(
137225394Sjchandra		".set	push\n\t"
138225394Sjchandra		".set	mips64\n\t"
139225394Sjchandra		"dsll32	$8, %1, 0\n\t"
140225394Sjchandra		"dsll32	$9, %2, 0\n\t"  /* get rid of the */
141225394Sjchandra		"dsrl32	$9, $9, 0\n\t"  /* sign extend */
142225394Sjchandra		"or	$9, $9, $8\n\t"
143225394Sjchandra		"sd	$9, 0(%0)\n\t"
144225394Sjchandra		".set	pop\n"
145225394Sjchandra		: : "r"(p), "r"(valhi), "r"(vallo)
146225394Sjchandra		: "$8", "$9", "memory");
147225394Sjchandra	nlm_restore_flags(sr);
148225394Sjchandra}
149225394Sjchandra#endif
150225394Sjchandra
151225394Sjchandra#if defined(__mips_n64)
152225394Sjchandrastatic inline uint64_t
153225394Sjchandranlm_load_word_daddr(uint64_t addr)
154225394Sjchandra{
155225394Sjchandra	volatile uint32_t *p = (volatile uint32_t *)(long)addr;
156225394Sjchandra
157225394Sjchandra	return *p;
158225394Sjchandra}
159225394Sjchandra
160225394Sjchandrastatic inline void
161225394Sjchandranlm_store_word_daddr(uint64_t addr, uint32_t val)
162225394Sjchandra{
163225394Sjchandra	volatile uint32_t *p = (volatile uint32_t *)(long)addr;
164225394Sjchandra
165225394Sjchandra	*p = val;
166225394Sjchandra}
167225394Sjchandra
168225394Sjchandrastatic inline uint64_t
169225394Sjchandranlm_load_dword_daddr(uint64_t addr)
170225394Sjchandra{
171225394Sjchandra	volatile uint64_t *p = (volatile uint64_t *)(long)addr;
172225394Sjchandra
173225394Sjchandra	return *p;
174225394Sjchandra}
175225394Sjchandra
176225394Sjchandrastatic inline void
177225394Sjchandranlm_store_dword_daddr(uint64_t addr, uint64_t val)
178225394Sjchandra{
179225394Sjchandra	volatile uint64_t *p = (volatile uint64_t *)(long)addr;
180225394Sjchandra
181225394Sjchandra	*p = val;
182225394Sjchandra}
183225394Sjchandra
184225394Sjchandra#elif defined(__mips_n32)
185225394Sjchandra
186225394Sjchandrastatic inline uint64_t
187225394Sjchandranlm_load_word_daddr(uint64_t addr)
188225394Sjchandra{
189225394Sjchandra	uint32_t val;
190225394Sjchandra
191225394Sjchandra	__asm__ __volatile__(
192225394Sjchandra		".set	push\n\t"
193225394Sjchandra		".set	mips64\n\t"
194225394Sjchandra		"lw		%0, 0(%1)\n\t"
195225394Sjchandra		".set	pop\n"
196225394Sjchandra		: "=r"(val)
197225394Sjchandra		: "r"(addr));
198225394Sjchandra
199225394Sjchandra	return val;
200225394Sjchandra}
201225394Sjchandra
202225394Sjchandrastatic inline void
203225394Sjchandranlm_store_word_daddr(uint64_t addr, uint32_t val)
204225394Sjchandra{
205225394Sjchandra	__asm__ __volatile__(
206225394Sjchandra		".set	push\n\t"
207225394Sjchandra		".set	mips64\n\t"
208225394Sjchandra		"sw		%0, 0(%1)\n\t"
209225394Sjchandra		".set	pop\n"
210225394Sjchandra		: : "r"(val), "r"(addr)
211225394Sjchandra		: "memory");
212225394Sjchandra}
213225394Sjchandra
214225394Sjchandrastatic inline uint64_t
215225394Sjchandranlm_load_dword_daddr(uint64_t addr)
216225394Sjchandra{
217225394Sjchandra	uint64_t val;
218225394Sjchandra
219225394Sjchandra	__asm__ __volatile__(
220225394Sjchandra		".set	push\n\t"
221225394Sjchandra		".set	mips64\n\t"
222225394Sjchandra		"ld		%0, 0(%1)\n\t"
223225394Sjchandra		".set	pop\n"
224225394Sjchandra		: "=r"(val)
225225394Sjchandra		: "r"(addr));
226225394Sjchandra	return val;
227225394Sjchandra}
228225394Sjchandra
229225394Sjchandrastatic inline void
230225394Sjchandranlm_store_dword_daddr(uint64_t addr, uint64_t val)
231225394Sjchandra{
232225394Sjchandra	__asm__ __volatile__(
233225394Sjchandra		".set	push\n\t"
234225394Sjchandra		".set	mips64\n\t"
235225394Sjchandra		"sd		%0, 0(%1)\n\t"
236225394Sjchandra		".set	pop\n"
237225394Sjchandra		: : "r"(val), "r"(addr)
238225394Sjchandra		: "memory");
239225394Sjchandra}
240225394Sjchandra
241225394Sjchandra#else /* o32 */
242225394Sjchandrastatic inline uint64_t
243225394Sjchandranlm_load_word_daddr(uint64_t addr)
244225394Sjchandra{
245225394Sjchandra	uint32_t val, addrhi, addrlo, sr;
246225394Sjchandra
247225394Sjchandra	addrhi = addr >> 32;
248225394Sjchandra	addrlo = addr & 0xffffffff;
249225394Sjchandra
250225394Sjchandra	sr = nlm_save_flags_kx();
251225394Sjchandra	__asm__ __volatile__(
252225394Sjchandra		".set	push\n\t"
253225394Sjchandra		".set	mips64\n\t"
254225394Sjchandra		"dsll32	$8, %1, 0\n\t"
255225394Sjchandra		"dsll32	$9, %2, 0\n\t"
256225394Sjchandra		"dsrl32	$9, $9, 0\n\t"
257225394Sjchandra		"or	$9, $9, $8\n\t"
258225394Sjchandra		"lw	%0, 0($9)\n\t"
259225394Sjchandra		".set	pop\n"
260225394Sjchandra		:	"=r"(val)
261225394Sjchandra		:	"r"(addrhi), "r"(addrlo)
262225394Sjchandra		:	"$8", "$9");
263225394Sjchandra	nlm_restore_flags(sr);
264225394Sjchandra
265225394Sjchandra	return val;
266225394Sjchandra
267225394Sjchandra}
268225394Sjchandra
269225394Sjchandrastatic inline void
270225394Sjchandranlm_store_word_daddr(uint64_t addr, uint32_t val)
271225394Sjchandra{
272225394Sjchandra	uint32_t addrhi, addrlo, sr;
273225394Sjchandra
274225394Sjchandra	addrhi = addr >> 32;
275225394Sjchandra	addrlo = addr & 0xffffffff;
276225394Sjchandra
277225394Sjchandra	sr = nlm_save_flags_kx();
278225394Sjchandra	__asm__ __volatile__(
279225394Sjchandra		".set	push\n\t"
280225394Sjchandra		".set	mips64\n\t"
281225394Sjchandra		"dsll32	$8, %1, 0\n\t"
282225394Sjchandra		"dsll32	$9, %2, 0\n\t"
283225394Sjchandra		"dsrl32	$9, $9, 0\n\t"
284225394Sjchandra		"or	$9, $9, $8\n\t"
285225394Sjchandra		"sw	%0, 0($9)\n\t"
286225394Sjchandra		".set	pop\n"
287225394Sjchandra		: : "r"(val), "r"(addrhi), "r"(addrlo)
288225394Sjchandra		:	"$8", "$9", "memory");
289225394Sjchandra	nlm_restore_flags(sr);
290225394Sjchandra}
291225394Sjchandra
292225394Sjchandrastatic inline uint64_t
293225394Sjchandranlm_load_dword_daddr(uint64_t addr)
294225394Sjchandra{
295225394Sjchandra	uint32_t addrh, addrl, sr;
296225394Sjchandra	uint32_t valh, vall;
297225394Sjchandra
298225394Sjchandra	addrh = addr >> 32;
299225394Sjchandra	addrl = addr & 0xffffffff;
300225394Sjchandra
301225394Sjchandra	sr = nlm_save_flags_kx();
302225394Sjchandra	__asm__ __volatile__(
303225394Sjchandra		".set	push\n\t"
304225394Sjchandra		".set	mips64\n\t"
305225394Sjchandra		"dsll32	$8, %2, 0\n\t"
306225394Sjchandra		"dsll32	$9, %3, 0\n\t"
307225394Sjchandra		"dsrl32	$9, $9, 0\n\t"
308225394Sjchandra		"or	$9, $9, $8\n\t"
309225394Sjchandra		"ld	$8, 0($9)\n\t"
310225394Sjchandra		"dsra32	%0, $8, 0\n\t"
311225394Sjchandra		"sll	%1, $8, 0\n\t"
312225394Sjchandra		".set	pop\n"
313225394Sjchandra		: "=r"(valh), "=r"(vall)
314225394Sjchandra		: "r"(addrh), "r"(addrl)
315225394Sjchandra		: "$8", "$9");
316225394Sjchandra	nlm_restore_flags(sr);
317225394Sjchandra
318225394Sjchandra	return ((uint64_t)valh << 32) | vall;
319225394Sjchandra}
320225394Sjchandra
321225394Sjchandrastatic inline void
322225394Sjchandranlm_store_dword_daddr(uint64_t addr, uint64_t val)
323225394Sjchandra{
324225394Sjchandra	uint32_t addrh, addrl, sr;
325225394Sjchandra	uint32_t valh, vall;
326225394Sjchandra
327225394Sjchandra	addrh = addr >> 32;
328225394Sjchandra	addrl = addr & 0xffffffff;
329225394Sjchandra	valh = val >> 32;
330225394Sjchandra	vall = val & 0xffffffff;
331225394Sjchandra
332225394Sjchandra	sr = nlm_save_flags_kx();
333225394Sjchandra	__asm__ __volatile__(
334225394Sjchandra		".set	push\n\t"
335225394Sjchandra		".set	mips64\n\t"
336225394Sjchandra		"dsll32	$8, %2, 0\n\t"
337225394Sjchandra		"dsll32	$9, %3, 0\n\t"
338225394Sjchandra		"dsrl32	$9, $9, 0\n\t"
339225394Sjchandra		"or	$9, $9, $8\n\t"
340225394Sjchandra		"dsll32	$8, %0, 0\n\t"
341225394Sjchandra		"dsll32	$10, %1, 0\n\t"
342225394Sjchandra		"dsrl32	$10, $10, 0\n\t"
343225394Sjchandra		"or	$8, $8, $10\n\t"
344225394Sjchandra		"sd	$8, 0($9)\n\t"
345225394Sjchandra		".set	pop\n"
346225394Sjchandra		: :	"r"(valh), "r"(vall), "r"(addrh), "r"(addrl)
347225394Sjchandra		:	"$8", "$9", "memory");
348225394Sjchandra	nlm_restore_flags(sr);
349225394Sjchandra}
350225394Sjchandra#endif /* __mips_n64 */
351225394Sjchandra
352225394Sjchandrastatic inline uint32_t
353225394Sjchandranlm_read_reg(uint64_t base, uint32_t reg)
354225394Sjchandra{
355225394Sjchandra	volatile uint32_t *addr = (volatile uint32_t *)(long)base + reg;
356225394Sjchandra
357225394Sjchandra	return *addr;
358225394Sjchandra}
359225394Sjchandra
360225394Sjchandrastatic inline void
361225394Sjchandranlm_write_reg(uint64_t base, uint32_t reg, uint32_t val)
362225394Sjchandra{
363225394Sjchandra	volatile uint32_t *addr = (volatile uint32_t *)(long)base + reg;
364225394Sjchandra
365225394Sjchandra	*addr = val;
366225394Sjchandra}
367225394Sjchandra
368225394Sjchandrastatic inline uint64_t
369225394Sjchandranlm_read_reg64(uint64_t base, uint32_t reg)
370225394Sjchandra{
371225394Sjchandra	uint64_t addr = base + (reg >> 1) * sizeof(uint64_t);
372225394Sjchandra
373225394Sjchandra	return nlm_load_dword(addr);
374225394Sjchandra}
375225394Sjchandra
376225394Sjchandrastatic inline void
377225394Sjchandranlm_write_reg64(uint64_t base, uint32_t reg, uint64_t val)
378225394Sjchandra{
379225394Sjchandra	uint64_t addr = base + (reg >> 1) * sizeof(uint64_t);
380225394Sjchandra
381225394Sjchandra	return nlm_store_dword(addr, val);
382225394Sjchandra}
383225394Sjchandra
384225394Sjchandra/*
385225394Sjchandra * Routines to store 32/64 bit values to 64 bit addresses,
386225394Sjchandra * used when going thru XKPHYS to access registers
387225394Sjchandra */
388225394Sjchandrastatic inline uint32_t
389225394Sjchandranlm_read_reg_xkphys(uint64_t base, uint32_t reg)
390225394Sjchandra{
391225394Sjchandra	uint64_t addr = base + reg * sizeof(uint32_t);
392225394Sjchandra
393225394Sjchandra	return nlm_load_word_daddr(addr);
394225394Sjchandra}
395225394Sjchandra
396225394Sjchandrastatic inline void
397225394Sjchandranlm_write_reg_xkphys(uint64_t base, uint32_t reg, uint32_t val)
398225394Sjchandra{
399225394Sjchandra	uint64_t addr = base + reg * sizeof(uint32_t);
400225394Sjchandra	return nlm_store_word_daddr(addr, val);
401225394Sjchandra}
402225394Sjchandra
403225394Sjchandrastatic inline uint64_t
404225394Sjchandranlm_read_reg64_xkphys(uint64_t base, uint32_t reg)
405225394Sjchandra{
406225394Sjchandra	uint64_t addr = base + (reg >> 1) * sizeof(uint64_t);
407225394Sjchandra
408225394Sjchandra	return nlm_load_dword_daddr(addr);
409225394Sjchandra}
410225394Sjchandra
411225394Sjchandrastatic inline void
412225394Sjchandranlm_write_reg64_xkphys(uint64_t base, uint32_t reg, uint64_t val)
413225394Sjchandra{
414225394Sjchandra	uint64_t addr = base + (reg >> 1) * sizeof(uint64_t);
415225394Sjchandra
416225394Sjchandra	return nlm_store_dword_daddr(addr, val);
417225394Sjchandra}
418225394Sjchandra
419225394Sjchandra/* Location where IO base is mapped */
420225394Sjchandraextern uint64_t xlp_io_base;
421225394Sjchandra
422225394Sjchandrastatic inline uint64_t
423225394Sjchandranlm_pcicfg_base(uint32_t devoffset)
424225394Sjchandra{
425225394Sjchandra	return xlp_io_base + devoffset;
426225394Sjchandra}
427225394Sjchandra
428225394Sjchandrastatic inline uint64_t
429225394Sjchandranlm_xkphys_map_pcibar0(uint64_t pcibase)
430225394Sjchandra{
431225394Sjchandra	uint64_t paddr;
432225394Sjchandra
433225394Sjchandra	paddr = nlm_read_reg(pcibase, 0x4) & ~0xfu;
434225394Sjchandra	return (uint64_t)0x9000000000000000 | paddr;
435225394Sjchandra}
436225394Sjchandra
437225394Sjchandra#endif
438