xref: /openbsd-src/sys/arch/octeon/include/octeonvar.h (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*	$NetBSD: maltavar.h,v 1.3 2002/03/18 10:10:16 simonb Exp $	*/
2 
3 /*-
4  * Copyright (c) 2001 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Jason R. Thorpe.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the NetBSD
21  *	Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #ifndef _MIPS_OCTEON_OCTEONVAR_H_
40 #define _MIPS_OCTEON_OCTEONVAR_H_
41 
42 #include <machine/bus.h>
43 
44 /* XXX elsewhere */
45 #define	_ASM_PROLOGUE \
46 		"	.set push			\n" \
47 		"	.set noreorder			\n"
48 #define	_ASM_PROLOGUE_MIPS64 \
49 		_ASM_PROLOGUE				\
50 		"	.set mips64			\n"
51 #define	_ASM_PROLOGUE_OCTEON \
52 		_ASM_PROLOGUE				\
53 		"	.set arch=octeon		\n"
54 #define	_ASM_EPILOGUE \
55 		"	.set pop			\n"
56 /*
57  * subbits = __BITS64_GET(XXX, bits);
58  * bits = __BITS64_SET(XXX, subbits);
59  */
60 #ifndef	__BITS64_GET
61 #define	__BITS64_GET(name, bits)	\
62 	    (((uint64_t)(bits) & name) >> name##_SHIFT)
63 #endif
64 #ifndef	__BITS64_SET
65 #define	__BITS64_SET(name, subbits)	\
66 	    (((uint64_t)(subbits) << name##_SHIFT) & name)
67 #endif
68 
69 struct octeon_config {
70 	bus_space_tag_t mc_iobus_bust;
71 	bus_space_tag_t mc_bootbus_bust;
72 
73 	bus_dma_tag_t mc_iobus_dmat;
74 	bus_dma_tag_t mc_bootbus_dmat;
75 /*
76 	struct mips_bus_dma_tag mc_core1_dmat;
77 
78 	struct extent *mc_io_ex;
79 	struct extent *mc_mem_ex;
80 
81 	int	mc_mallocsafe;
82 */
83 };
84 
85 /*
86  * FPA map
87  */
88 
89 #define	OCTEON_POOL_NO_PKT	0
90 #define	OCTEON_POOL_NO_WQE	1
91 #define	OCTEON_POOL_NO_CMD	2
92 #define	OCTEON_POOL_NO_SG	3
93 #define	OCTEON_POOL_NO_XXX_4	4
94 #define	OCTEON_POOL_NO_XXX_5	5
95 #define	OCTEON_POOL_NO_XXX_6	6
96 #define	OCTEON_POOL_NO_DUMP	7	/* FPA debug dump */
97 
98 #define	OCTEON_POOL_SIZE_PKT	2048	/* 128 x 16 */
99 #define	OCTEON_POOL_SIZE_WQE	128	/* 128 x 1 */
100 #define	OCTEON_POOL_SIZE_CMD	1024	/* 128 x 8 */
101 #define	OCTEON_POOL_SIZE_SG	512	/* 128 x 4 */
102 #define	OCTEON_POOL_SIZE_XXX_4	0
103 #define	OCTEON_POOL_SIZE_XXX_5	0
104 #define	OCTEON_POOL_SIZE_XXX_6	0
105 #define	OCTEON_POOL_SIZE_XXX_7	0
106 
107 #define	OCTEON_POOL_NELEMS_PKT		4096
108 #define	OCTEON_POOL_NELEMS_WQE		4096
109 #define	OCTEON_POOL_NELEMS_CMD		32
110 #define	OCTEON_POOL_NELEMS_SG		1024
111 #define	OCTEON_POOL_NELEMS_XXX_4	0
112 #define	OCTEON_POOL_NELEMS_XXX_5	0
113 #define	OCTEON_POOL_NELEMS_XXX_6	0
114 #define	OCTEON_POOL_NELEMS_XXX_7	0
115 
116 /*
117  * CVMSEG (``scratch'') memory map
118  */
119 struct octeon_cvmseg_map {
120 	/* 0-3 */
121 	uint64_t		csm_xxx_0;
122 	uint64_t		csm_xxx_1;
123 	uint64_t		csm_xxx_2;
124 	uint64_t		csm_pow_intr;
125 
126 	/* 4-19 */
127 	struct octeon_cvmseg_ether_map {
128 		uint64_t	csm_ether_fau_req;
129 		uint64_t	csm_ether_fau_done;
130 		uint64_t	csm_ether_fau_cmdptr;
131 		uint64_t	csm_ether_xxx_3;
132 	} csm_ether[4/* XXX */];
133 
134 	/* 20-32 */
135 	uint64_t	xxx_20_32[32 - 20];
136 } __packed;
137 #define	OCTEON_CVMSEG_OFFSET(entry) \
138 	offsetof(struct octeon_cvmseg_map, entry)
139 #define	OCTEON_CVMSEG_ETHER_OFFSET(n, entry) \
140 	(offsetof(struct octeon_cvmseg_map, csm_ether) + \
141 	 sizeof(struct octeon_cvmseg_ether_map) * (n) + \
142 	 offsetof(struct octeon_cvmseg_ether_map, entry))
143 
144 /*
145  * FAU register map
146  *
147  * => FAU registers exist in FAU unit
148  * => devices (PKO) can access these registers
149  * => CPU can read those values after loading them into CVMSEG
150  */
151 struct octeon_fau_map {
152 	struct {
153 		/* PKO command index */
154 		uint64_t	_fau_map_port_pkocmdidx;
155 		/* send requested */
156 		uint64_t	_fau_map_port_txreq;
157 		/* send completed */
158 		uint64_t	_fau_map_port_txdone;
159 		/* XXX */
160 		uint64_t	_fau_map_port_pad;
161 	} __packed _fau_map_port[3];
162 };
163 
164 /*
165  * POW qos/group map
166  */
167 
168 #define	OCTEON_POW_QOS_PIP		0
169 #define	OCTEON_POW_QOS_CORE1		1
170 #define	OCTEON_POW_QOS_XXX_2		2
171 #define	OCTEON_POW_QOS_XXX_3		3
172 #define	OCTEON_POW_QOS_XXX_4		4
173 #define	OCTEON_POW_QOS_XXX_5		5
174 #define	OCTEON_POW_QOS_XXX_6		6
175 #define	OCTEON_POW_QOS_XXX_7		7
176 
177 #define	OCTEON_POW_GROUP_PIP		0
178 #define	OCTEON_POW_GROUP_XXX_1		1
179 #define	OCTEON_POW_GROUP_XXX_2		2
180 #define	OCTEON_POW_GROUP_XXX_3		3
181 #define	OCTEON_POW_GROUP_XXX_4		4
182 #define	OCTEON_POW_GROUP_XXX_5		5
183 #define	OCTEON_POW_GROUP_XXX_6		6
184 #define	OCTEON_POW_GROUP_CORE1_SEND	7
185 #define	OCTEON_POW_GROUP_CORE1_TASK_0	8
186 #define	OCTEON_POW_GROUP_CORE1_TASK_1	9
187 #define	OCTEON_POW_GROUP_CORE1_TASK_2	10
188 #define	OCTEON_POW_GROUP_CORE1_TASK_3	11
189 #define	OCTEON_POW_GROUP_CORE1_TASK_4	12
190 #define	OCTEON_POW_GROUP_CORE1_TASK_5	13
191 #define	OCTEON_POW_GROUP_CORE1_TASK_6	14
192 #define	OCTEON_POW_GROUP_CORE1_TASK_7	15
193 
194 #ifdef _KERNEL
195 extern struct octeon_config	octeon_configuration;
196 
197 void	octeon_bus_io_init(bus_space_tag_t, void *);
198 void	octeon_bus_mem_init(bus_space_tag_t, void *);
199 void	octeon_cal_timer(int);
200 void	octeon_dma_init(struct octeon_config *);
201 void	octeon_intr_init(void);
202 int	octeon_get_ethaddr(int, u_int8_t *);
203 #endif /* _KERNEL */
204 
205 static inline int
206 ffs64(uint64_t val)
207 {
208 	int ret;
209 
210 	__asm __volatile ( \
211 		_ASM_PROLOGUE_MIPS64
212 		"	dclz	%0, %1			\n"
213 		_ASM_EPILOGUE
214 		: "=r"(ret) : "r"(val));
215 	return 64 - ret;
216 }
217 
218 /*
219  * Prefetch
220  *
221  *	OCTEON_PREF		normal (L1 and L2)
222  *	OCTEON_PREF_L1		L1 only
223  *	OCTEON_PREF_L2		L2 only
224  *	OCTEON_PREF_DWB		don't write back
225  *	OCTEON_PREF_PFS		prepare for store
226  */
227 #define __OCTEON_PREF_N(n, base, offset)			\
228 	__asm __volatile (					\
229 		"	.set	push				\
230 		"	.set	arch=octeon			\n" \
231 		"	pref	"#n", "#offset"(%[base])	\n" \
232 		"	.set	pop				\
233 		: : [base] "d" (base)				\
234 	)
235 #define __OCTEON_PREF_0(base, offset)	__OCTEON_PREF_N(0, base, offset)
236 #define __OCTEON_PREF_4(base, offset)	__OCTEON_PREF_N(4, base, offset)
237 #define __OCTEON_PREF_28(base, offset)	__OCTEON_PREF_N(28, base, offset)
238 #define __OCTEON_PREF_29(base, offset)	__OCTEON_PREF_N(29, base, offset)
239 #define __OCTEON_PREF_30(base, offset)	__OCTEON_PREF_N(30, base, offset)
240 #define OCTEON_PREF(base, offset)	__OCTEON_PREF_0(base, offset)
241 #define OCTEON_PREF_L1(base, offset)	__OCTEON_PREF_4(base, offset)
242 #define OCTEON_PREF_L2(base, offset)	__OCTEON_PREF_28(base, offset)
243 #define OCTEON_PREF_DWB(base, offset)	__OCTEON_PREF_29(base, offset)
244 #define OCTEON_PREF_PFS(base, offset)	__OCTEON_PREF_30(base, offset)
245 
246 /*
247  * Sync
248  */
249 #define OCTEON_SYNCCOMMON(name) \
250 	__asm __volatile ( \
251 		_ASM_PROLOGUE_OCTEON			\
252 		"	"#name"				\n" \
253 		_ASM_EPILOGUE				\
254 		::: "memory")
255 #define OCTEON_SYNCIOBDMA	__asm __volatile (".word 0x8f" : : :"memory")
256 #define OCTEON_SYNCW		__asm __volatile (".word  0x10f" : : )
257 #define OCTEON_SYNC		OCTEON_SYNCCOMMON(sync)
258 #define OCTEON_SYNCWS		__asm __volatile (".word  0x14f" : : )
259 /* XXX backward compatibility */
260 #if 1
261 #define	OCT_SYNCIOBDMA		OCTEON_SYNCIOBDMA
262 #define	OCT_SYNCW		OCTEON_SYNCW
263 #define	OCT_SYNC		OCTEON_SYNC
264 #define	OCT_SYNCWS		OCTEON_SYNCWS
265 #endif
266 
267 static inline uint64_t
268 octeon_xkphys_read_8(paddr_t address)
269 {
270 	volatile uint64_t *p =
271 	    (volatile uint64_t *)(PHYS_TO_XKPHYS(address, CCA_NC));
272 	return (*p);
273 }
274 
275 static inline void
276 octeon_xkphys_write_8(paddr_t address, uint64_t value)
277 {
278 	*(volatile uint64_t *)(PHYS_TO_XKPHYS(address, CCA_NC)) = value;
279 }
280 
281 /* XXX backward compatibility */
282 #if 1
283 #define octeon_read_csr(address) \
284 	octeon_xkphys_read_8(address)
285 #define octeon_write_csr(address, value) \
286 	octeon_xkphys_write_8(address, value)
287 #endif
288 
289 static inline void
290 octeon_iobdma_write_8(uint64_t value)
291 {
292 	uint64_t addr = 0xffffffffffffa200ULL;
293 
294 	*(volatile uint64_t *)addr = value;
295 }
296 
297 static inline uint64_t
298 octeon_cvmseg_read_8(size_t offset)
299 {
300 	return octeon_xkphys_read_8(0xffffffffffff8000ULL + offset);
301 }
302 
303 static inline void
304 octeon_cvmseg_write_8(size_t offset, uint64_t value)
305 {
306 	octeon_xkphys_write_8(0xffffffffffff8000ULL + offset, value);
307 }
308 
309 /* XXX */
310 static inline uint32_t
311 octeon_disable_interrupt(uint32_t *new)
312 {
313 	uint32_t s, tmp;
314 
315 	__asm __volatile (
316 		_ASM_PROLOGUE
317 		"	mfc0	%[s], $12		\n"
318 		"	and	%[tmp], %[s], ~1	\n"
319 		"	mtc0	%[tmp], $12		\n"
320 		_ASM_EPILOGUE
321 		: [s]"=&r"(s), [tmp]"=&r"(tmp));
322 	if (new)
323 		*new = tmp;
324 	return s;
325 }
326 
327 /* XXX */
328 static inline void
329 octeon_restore_status(uint32_t s)
330 {
331 	__asm __volatile (
332 		_ASM_PROLOGUE
333 		"	mtc0	%[s], $12		\n"
334 		_ASM_EPILOGUE
335 		:: [s]"r"(s));
336 }
337 
338 static inline uint64_t
339 octeon_get_cycles(void)
340 {
341 #if defined(__mips_o32)
342 	uint32_t s, lo, hi;
343 
344 	s = octeon_disable_interrupt((void *)0);
345 	__asm __volatile (
346 		_ASM_PROLOGUE_MIPS64
347 		"	dmfc0	%[lo], $9, 6		\n"
348 		"	add	%[hi], %[lo], $0	\n"
349 		"	srl	%[hi], 32		\n"
350 		"	sll	%[lo], 32		\n"
351 		"	srl	%[lo], 32		\n"
352 		_ASM_EPILOGUE
353 		: [lo]"=&r"(lo), [hi]"=&r"(hi));
354 	octeon_restore_status(s);
355 	return ((uint64_t)hi << 32) + (uint64_t)lo;
356 #else
357 	uint64_t tmp;
358 
359 	__asm __volatile (
360 		_ASM_PROLOGUE_MIPS64
361 		"	dmfc0	%[tmp], $9, 6		\n"
362 		_ASM_EPILOGUE
363 		: [tmp]"=&r"(tmp));
364 	return tmp;
365 #endif
366 }
367 
368 /* -------------------------------------------------------------------------- */
369 
370 /* ---- event counter */
371 
372 #if defined(OCTEON_ETH_DEBUG)
373 #define	OCTEON_EVCNT_INC(sc, name) \
374 	do { (sc)->sc_ev_##name.ev_count++; } while (0)
375 #define	OCTEON_EVCNT_ADD(sc, name, n) \
376 	do { (sc)->sc_ev_##name.ev_count += (n); } while (0)
377 #define	OCTEON_EVCNT_ATTACH_EVCNTS(sc, entries, devname) \
378 do {								\
379 	int i;							\
380 	const struct octeon_evcnt_entry *ee;			\
381 								\
382 	for (i = 0; i < (int)nitems(entries); i++) {	\
383 		ee = &(entries)[i];				\
384 		evcnt_attach_dynamic(				\
385 		    (struct evcnt *)((uintptr_t)(sc) + ee->ee_offset), \
386 		    ee->ee_type, ee->ee_parent, devname,	\
387 		    ee->ee_name);				\
388 	}							\
389 } while (0)
390 #else
391 #define	OCTEON_EVCNT_INC(sc, name)
392 #define	OCTEON_EVCNT_ADD(sc, name, n)
393 #define	OCTEON_EVCNT_ATTACH_EVCNTS(sc, entries, devname)
394 #endif
395 
396 struct octeon_evcnt_entry {
397 	size_t		ee_offset;
398 	int		ee_type;
399 	struct evcnt	*ee_parent;
400 	const char	*ee_name;
401 };
402 
403 #define	OCTEON_EVCNT_ENTRY(_sc_type, _var, _ev_type, _parent, _name) \
404 	{							\
405 		.ee_offset = offsetof(_sc_type, sc_ev_##_var),	\
406 		.ee_type = EVCNT_TYPE_##_ev_type,		\
407 		.ee_parent = _parent,				\
408 		.ee_name = _name				\
409 	}
410 
411 #endif	/* _MIPS_OCTEON_OCTEONVAR_H_ */
412