xref: /netbsd-src/sys/arch/mips/cavium/octeonvar.h (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: octeonvar.h,v 1.6 2018/04/19 21:50:06 christos 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  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #ifndef _MIPS_OCTEON_OCTEONVAR_H_
33 #define _MIPS_OCTEON_OCTEONVAR_H_
34 
35 #include <sys/bus.h>
36 #include <sys/evcnt.h>
37 #include <sys/kcpuset.h>
38 #include <mips/locore.h>
39 #include <dev/pci/pcivar.h>
40 
41 /* XXX elsewhere */
42 #define	_ASM_PROLOGUE \
43 		"	.set push			\n" \
44 		"	.set noreorder			\n"
45 #define	_ASM_PROLOGUE_MIPS64 \
46 		_ASM_PROLOGUE				\
47 		"	.set mips64			\n"
48 #define	_ASM_PROLOGUE_OCTEON \
49 		_ASM_PROLOGUE				\
50 		"	.set arch=octeon		\n"
51 #define	_ASM_EPILOGUE \
52 		"	.set pop			\n"
53 /*
54  * subbits = __BITS64_GET(XXX, bits);
55  * bits = __BITS64_SET(XXX, subbits);
56  */
57 #ifndef	__BITS64_GET
58 #define	__BITS64_GET(name, bits)	\
59 	    (((uint64_t)(bits) & name) >> name##_SHIFT)
60 #endif
61 #ifndef	__BITS64_SET
62 #define	__BITS64_SET(name, subbits)	\
63 	    (((uint64_t)(subbits) << name##_SHIFT) & name)
64 #endif
65 
66 struct octeon_config {
67 	struct mips_bus_space mc_iobus_bust;
68 	struct mips_bus_space mc_bootbus_bust;
69 	struct mips_pci_chipset mc_pc;
70 
71 	struct mips_bus_dma_tag mc_iobus_dmat;
72 	struct mips_bus_dma_tag mc_bootbus_dmat;
73 	struct mips_bus_dma_tag mc_core1_dmat;
74 	struct mips_bus_dma_tag mc_fpa_dmat;
75 
76 	struct extent *mc_io_ex;
77 	struct extent *mc_mem_ex;
78 
79 	int	mc_mallocsafe;
80 };
81 
82 #define NIRQS	64
83 
84 struct cpu_softc {
85 	struct cpu_info *cpu_ci;
86 
87 	uint64_t cpu_int0_sum0;
88 	uint64_t cpu_int1_sum0;
89 	uint64_t cpu_int2_sum0;
90 
91 	uint64_t cpu_int0_en0;
92 	uint64_t cpu_int1_en0;
93 	uint64_t cpu_int2_en0;
94 
95 	uint64_t cpu_int0_en1;
96 	uint64_t cpu_int1_en1;
97 	uint64_t cpu_int2_en1;
98 
99 	uint64_t cpu_int32_en;
100 
101 	struct evcnt cpu_intr_evs[NIRQS];
102 
103 	uint64_t cpu_int0_enable0;
104 	uint64_t cpu_int1_enable0;
105 	uint64_t cpu_int2_enable0;
106 
107 	void *cpu_wdog_sih;		// wdog softint handler
108 	uint64_t cpu_wdog;
109 	uint64_t cpu_pp_poke;
110 
111 #ifdef MULTIPROCESSOR
112 	uint64_t cpu_mbox_set;
113 	uint64_t cpu_mbox_clr;
114 #endif
115 };
116 
117 /*
118  * FPA map
119  */
120 
121 #define	OCTEON_POOL_NO_PKT	0
122 #define	OCTEON_POOL_NO_WQE	1
123 #define	OCTEON_POOL_NO_CMD	2
124 #define	OCTEON_POOL_NO_SG	3
125 #define	OCTEON_POOL_NO_XXX_4	4
126 #define	OCTEON_POOL_NO_XXX_5	5
127 #define	OCTEON_POOL_NO_XXX_6	6
128 #define	OCTEON_POOL_NO_DUMP	7	/* FPA debug dump */
129 
130 #define	OCTEON_POOL_SIZE_PKT	2048	/* 128 x 16 */
131 #define	OCTEON_POOL_SIZE_WQE	128	/* 128 x 1 */
132 #define	OCTEON_POOL_SIZE_CMD	1024	/* 128 x 8 */
133 #define	OCTEON_POOL_SIZE_SG	512	/* 128 x 4 */
134 #define	OCTEON_POOL_SIZE_XXX_4	0
135 #define	OCTEON_POOL_SIZE_XXX_5	0
136 #define	OCTEON_POOL_SIZE_XXX_6	0
137 #define	OCTEON_POOL_SIZE_XXX_7	0
138 
139 #define	OCTEON_POOL_NELEMS_PKT		4096
140 #define	OCTEON_POOL_NELEMS_WQE		4096
141 #define	OCTEON_POOL_NELEMS_CMD		32
142 #define	OCTEON_POOL_NELEMS_SG		1024
143 #define	OCTEON_POOL_NELEMS_XXX_4	0
144 #define	OCTEON_POOL_NELEMS_XXX_5	0
145 #define	OCTEON_POOL_NELEMS_XXX_6	0
146 #define	OCTEON_POOL_NELEMS_XXX_7	0
147 
148 /*
149  * CVMSEG (``scratch'') memory map
150  */
151 struct octeon_cvmseg_map {
152 	/* 0-3 */
153 	uint64_t		csm_xxx_0;
154 	uint64_t		csm_xxx_1;
155 	uint64_t		csm_xxx_2;
156 	uint64_t		csm_pow_intr;
157 
158 	/* 4-19 */
159 	struct octeon_cvmseg_ether_map {
160 		uint64_t	csm_ether_fau_req;
161 		uint64_t	csm_ether_fau_done;
162 		uint64_t	csm_ether_fau_cmdptr;
163 		uint64_t	csm_ether_xxx_3;
164 	} csm_ether[4/* XXX */];
165 
166 	/* 20-32 */
167 	uint64_t	xxx_20_32[32 - 20];
168 } __packed;
169 #define	OCTEON_CVMSEG_OFFSET(entry) \
170 	offsetof(struct octeon_cvmseg_map, entry)
171 #define	OCTEON_CVMSEG_ETHER_OFFSET(n, entry) \
172 	(offsetof(struct octeon_cvmseg_map, csm_ether) + \
173 	 sizeof(struct octeon_cvmseg_ether_map) * (n) + \
174 	 offsetof(struct octeon_cvmseg_ether_map, entry))
175 
176 /*
177  * FAU register map
178  *
179  * => FAU registers exist in FAU unit
180  * => devices (PKO) can access these registers
181  * => CPU can read those values after loading them into CVMSEG
182  */
183 struct octeon_fau_map {
184 	struct {
185 		/* PKO command index */
186 		uint64_t	_fau_map_port_pkocmdidx;
187 		/* send requested */
188 		uint64_t	_fau_map_port_txreq;
189 		/* send completed */
190 		uint64_t	_fau_map_port_txdone;
191 		/* XXX */
192 		uint64_t	_fau_map_port_pad;
193 	} __packed _fau_map_port[3];
194 };
195 
196 /*
197  * POW qos/group map
198  */
199 
200 #define	OCTEON_POW_QOS_PIP		0
201 #define	OCTEON_POW_QOS_CORE1		1
202 #define	OCTEON_POW_QOS_XXX_2		2
203 #define	OCTEON_POW_QOS_XXX_3		3
204 #define	OCTEON_POW_QOS_XXX_4		4
205 #define	OCTEON_POW_QOS_XXX_5		5
206 #define	OCTEON_POW_QOS_XXX_6		6
207 #define	OCTEON_POW_QOS_XXX_7		7
208 
209 #define	OCTEON_POW_GROUP_PIP		0
210 #define	OCTEON_POW_GROUP_XXX_1		1
211 #define	OCTEON_POW_GROUP_XXX_2		2
212 #define	OCTEON_POW_GROUP_XXX_3		3
213 #define	OCTEON_POW_GROUP_XXX_4		4
214 #define	OCTEON_POW_GROUP_XXX_5		5
215 #define	OCTEON_POW_GROUP_XXX_6		6
216 #define	OCTEON_POW_GROUP_CORE1_SEND	7
217 #define	OCTEON_POW_GROUP_CORE1_TASK_0	8
218 #define	OCTEON_POW_GROUP_CORE1_TASK_1	9
219 #define	OCTEON_POW_GROUP_CORE1_TASK_2	10
220 #define	OCTEON_POW_GROUP_CORE1_TASK_3	11
221 #define	OCTEON_POW_GROUP_CORE1_TASK_4	12
222 #define	OCTEON_POW_GROUP_CORE1_TASK_5	13
223 #define	OCTEON_POW_GROUP_CORE1_TASK_6	14
224 #define	OCTEON_POW_GROUP_CORE1_TASK_7	15
225 
226 #ifdef _KERNEL
227 extern struct octeon_config	octeon_configuration;
228 #ifdef MULTIPROCESSOR
229 extern kcpuset_t *cpus_booted;
230 extern struct cpu_softc		octeon_cpu1_softc;
231 #endif
232 
233 void	octeon_bus_io_init(bus_space_tag_t, void *);
234 void	octeon_bus_mem_init(bus_space_tag_t, void *);
235 void	octeon_cal_timer(int);
236 void	octeon_dma_init(struct octeon_config *);
237 void	octeon_intr_init(struct cpu_info *);
238 void	octeon_iointr(int, vaddr_t, uint32_t);
239 void	octeon_pci_init(pci_chipset_tag_t, struct octeon_config *);
240 void	*octeon_intr_establish(int, int, int (*)(void *), void *);
241 void	octeon_intr_disestablish(void *cookie);
242 
243 void	octeon_reset_vector(void);
244 uint64_t mips_cp0_cvmctl_read(void);
245 void	 mips_cp0_cvmctl_write(uint64_t);
246 
247 #endif /* _KERNEL */
248 
249 #if defined(__mips_n32)
250 #define ffs64	__builtin_ffsll
251 #elif defined(_LP64)
252 #define ffs64	__builtin_ffsl
253 #else
254 #error unknown ABI
255 #endif
256 
257 /*
258  * Prefetch
259  *
260  *	OCTEON_PREF		normal (L1 and L2)
261  *	OCTEON_PREF_L1		L1 only
262  *	OCTEON_PREF_L2		L2 only
263  *	OCTEON_PREF_DWB		don't write back
264  *	OCTEON_PREF_PFS		prepare for store
265  */
266 #define __OCTEON_PREF_N(n, base, offset)			\
267 	__asm __volatile (					\
268 		"	.set	push				\
269 		"	.set	arch=octeon			\n" \
270 		"	pref	"#n", "#offset"(%[base])	\n" \
271 		"	.set	pop				\
272 		: : [base] "d" (base)				\
273 	)
274 #define __OCTEON_PREF_0(base, offset)	__OCTEON_PREF_N(0, base, offset)
275 #define __OCTEON_PREF_4(base, offset)	__OCTEON_PREF_N(4, base, offset)
276 #define __OCTEON_PREF_28(base, offset)	__OCTEON_PREF_N(28, base, offset)
277 #define __OCTEON_PREF_29(base, offset)	__OCTEON_PREF_N(29, base, offset)
278 #define __OCTEON_PREF_30(base, offset)	__OCTEON_PREF_N(30, base, offset)
279 #define OCTEON_PREF(base, offset)	__OCTEON_PREF_0(base, offset)
280 #define OCTEON_PREF_L1(base, offset)	__OCTEON_PREF_4(base, offset)
281 #define OCTEON_PREF_L2(base, offset)	__OCTEON_PREF_28(base, offset)
282 #define OCTEON_PREF_DWB(base, offset)	__OCTEON_PREF_29(base, offset)
283 #define OCTEON_PREF_PFS(base, offset)	__OCTEON_PREF_30(base, offset)
284 
285 /*
286  * Sync
287  */
288 #define OCTEON_SYNCCOMMON(name) \
289 	__asm __volatile ( \
290 		_ASM_PROLOGUE_OCTEON			\
291 		"	"#name"				\n" \
292 		_ASM_EPILOGUE				\
293 		::: "memory")
294 #define OCTEON_SYNCIOBDMA	OCTEON_SYNCCOMMON(synciobdma)
295 #define OCTEON_SYNCW		OCTEON_SYNCCOMMON(syncw)
296 #define OCTEON_SYNC		OCTEON_SYNCCOMMON(sync)
297 #define OCTEON_SYNCWS		OCTEON_SYNCCOMMON(syncws)
298 #define OCTEON_SYNCS		OCTEON_SYNCCOMMON(syncs)
299 /* XXX backward compatibility */
300 #if 1
301 #define	OCT_SYNCIOBDMA		OCTEON_SYNCIOBDMA
302 #define	OCT_SYNCW		OCTEON_SYNCW
303 #define	OCT_SYNC		OCTEON_SYNC
304 #define	OCT_SYNCWS		OCTEON_SYNCWS
305 #define	OCT_SYNCS		OCTEON_SYNCS
306 #endif
307 
308 /* octeon core does not use cca to determine cacheability */
309 #define OCTEON_CCA_NONE UINT64_C(0)
310 
311 static __inline uint64_t
312 octeon_xkphys_read_8(paddr_t address)
313 {
314 	return mips3_ld(MIPS_PHYS_TO_XKPHYS(OCTEON_CCA_NONE, address));
315 }
316 
317 static __inline void
318 octeon_xkphys_write_8(paddr_t address, uint64_t value)
319 {
320 	mips3_sd(MIPS_PHYS_TO_XKPHYS(OCTEON_CCA_NONE, address), value);
321 }
322 
323 /* XXX backward compatibility */
324 #if 1
325 #define octeon_read_csr(address) \
326 	octeon_xkphys_read_8(address)
327 #define octeon_write_csr(address, value) \
328 	octeon_xkphys_write_8(address, value)
329 #endif
330 
331 static __inline void
332 octeon_iobdma_write_8(uint64_t value)
333 {
334 	uint64_t addr = UINT64_C(0xffffffffffffa200);
335 
336 	octeon_xkphys_write_8(addr, value);
337 }
338 
339 static __inline uint64_t
340 octeon_cvmseg_read_8(size_t offset)
341 {
342 	return octeon_xkphys_read_8(UINT64_C(0xffffffffffff8000) + offset);
343 }
344 
345 static __inline void
346 octeon_cvmseg_write_8(size_t offset, uint64_t value)
347 {
348 	octeon_xkphys_write_8(UINT64_C(0xffffffffffff8000) + offset, value);
349 }
350 
351 /* XXX */
352 static __inline uint32_t
353 octeon_disable_interrupt(uint32_t *new)
354 {
355 	uint32_t s, tmp;
356 
357 	__asm __volatile (
358 		_ASM_PROLOGUE
359 		"	mfc0	%[s], $12		\n"
360 		"	and	%[tmp], %[s], ~1	\n"
361 		"	mtc0	%[tmp], $12		\n"
362 		_ASM_EPILOGUE
363 		: [s]"=&r"(s), [tmp]"=&r"(tmp));
364 	if (new)
365 		*new = tmp;
366 	return s;
367 }
368 
369 /* XXX */
370 static __inline void
371 octeon_restore_status(uint32_t s)
372 {
373 	__asm __volatile (
374 		_ASM_PROLOGUE
375 		"	mtc0	%[s], $12		\n"
376 		_ASM_EPILOGUE
377 		:: [s]"r"(s));
378 }
379 
380 static __inline uint64_t
381 octeon_get_cycles(void)
382 {
383 #if defined(__mips_o32)
384 	uint32_t s, lo, hi;
385 
386 	s = octeon_disable_interrupt((void *)0);
387 	__asm __volatile (
388 		_ASM_PROLOGUE_MIPS64
389 		"	dmfc0	%[lo], $9, 6		\n"
390 		"	add	%[hi], %[lo], $0	\n"
391 		"	srl	%[hi], 32		\n"
392 		"	sll	%[lo], 32		\n"
393 		"	srl	%[lo], 32		\n"
394 		_ASM_EPILOGUE
395 		: [lo]"=&r"(lo), [hi]"=&r"(hi));
396 	octeon_restore_status(s);
397 	return ((uint64_t)hi << 32) + (uint64_t)lo;
398 #else
399 	uint64_t tmp;
400 
401 	__asm __volatile (
402 		_ASM_PROLOGUE_MIPS64
403 		"	dmfc0	%[tmp], $9, 6		\n"
404 		_ASM_EPILOGUE
405 		: [tmp]"=&r"(tmp));
406 	return tmp;
407 #endif
408 }
409 
410 /* -------------------------------------------------------------------------- */
411 
412 /* ---- event counter */
413 
414 #if defined(OCTEON_ETH_DEBUG)
415 #define	OCTEON_EVCNT_INC(sc, name) \
416 	do { (sc)->sc_ev_##name.ev_count++; } while (0)
417 #define	OCTEON_EVCNT_ADD(sc, name, n) \
418 	do { (sc)->sc_ev_##name.ev_count += (n); } while (0)
419 #define	OCTEON_EVCNT_ATTACH_EVCNTS(sc, entries, devname) \
420 do {								\
421 	int i;							\
422 	const struct octeon_evcnt_entry *ee;			\
423 								\
424 	for (i = 0; i < (int)__arraycount(entries); i++) {	\
425 		ee = &(entries)[i];				\
426 		evcnt_attach_dynamic(				\
427 		    (struct evcnt *)((uintptr_t)(sc) + ee->ee_offset), \
428 		    ee->ee_type, ee->ee_parent, devname,	\
429 		    ee->ee_name);				\
430 	}							\
431 } while (0)
432 #else
433 #define	OCTEON_EVCNT_INC(sc, name)
434 #define	OCTEON_EVCNT_ADD(sc, name, n)
435 #define	OCTEON_EVCNT_ATTACH_EVCNTS(sc, entries, devname)
436 #endif
437 
438 struct octeon_evcnt_entry {
439 	size_t		ee_offset;
440 	int		ee_type;
441 	struct evcnt	*ee_parent;
442 	const char	*ee_name;
443 };
444 
445 #define	OCTEON_EVCNT_ENTRY(_sc_type, _var, _ev_type, _parent, _name) \
446 	{							\
447 		.ee_offset = offsetof(_sc_type, sc_ev_##_var),	\
448 		.ee_type = EVCNT_TYPE_##_ev_type,		\
449 		.ee_parent = _parent,				\
450 		.ee_name = _name				\
451 	}
452 
453 #endif	/* _MIPS_OCTEON_OCTEONVAR_H_ */
454