xref: /openbsd-src/sys/arch/octeon/include/octeonvar.h (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1 /*	$OpenBSD: octeonvar.h,v 1.20 2014/07/14 10:23:58 jasper Exp $	*/
2 /*	$NetBSD: maltavar.h,v 1.3 2002/03/18 10:10:16 simonb Exp $	*/
3 
4 /*-
5  * Copyright (c) 2001 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Jason R. Thorpe.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *	This product includes software developed by the NetBSD
22  *	Foundation, Inc. and its contributors.
23  * 4. Neither the name of The NetBSD Foundation nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 #ifndef _MIPS_OCTEON_OCTEONVAR_H_
41 #define _MIPS_OCTEON_OCTEONVAR_H_
42 
43 #include <machine/bus.h>
44 
45 /* XXX elsewhere */
46 #define	_ASM_PROLOGUE \
47 		"	.set push			\n" \
48 		"	.set noreorder			\n"
49 #define	_ASM_PROLOGUE_MIPS64 \
50 		_ASM_PROLOGUE				\
51 		"	.set mips64			\n"
52 #define	_ASM_PROLOGUE_OCTEON \
53 		_ASM_PROLOGUE				\
54 		"	.set arch=octeon		\n"
55 #define	_ASM_EPILOGUE \
56 		"	.set pop			\n"
57 /*
58  * subbits = __BITS64_GET(XXX, bits);
59  * bits = __BITS64_SET(XXX, subbits);
60  */
61 #ifndef	__BITS64_GET
62 #define	__BITS64_GET(name, bits)	\
63 	    (((uint64_t)(bits) & name) >> name##_SHIFT)
64 #endif
65 #ifndef	__BITS64_SET
66 #define	__BITS64_SET(name, subbits)	\
67 	    (((uint64_t)(subbits) << name##_SHIFT) & name)
68 #endif
69 
70 struct octeon_config {
71 	bus_space_tag_t mc_iobus_bust;
72 	bus_space_tag_t mc_bootbus_bust;
73 
74 	bus_dma_tag_t mc_iobus_dmat;
75 	bus_dma_tag_t mc_bootbus_dmat;
76 /*
77 	struct mips_bus_dma_tag mc_core1_dmat;
78 
79 	struct extent *mc_io_ex;
80 	struct extent *mc_mem_ex;
81 
82 	int	mc_mallocsafe;
83 */
84 };
85 
86 /*
87  * FPA map
88  */
89 
90 #define	OCTEON_POOL_NO_PKT	0
91 #define	OCTEON_POOL_NO_WQE	1
92 #define	OCTEON_POOL_NO_CMD	2
93 #define	OCTEON_POOL_NO_SG	3
94 #define	OCTEON_POOL_NO_XXX_4	4
95 #define	OCTEON_POOL_NO_XXX_5	5
96 #define	OCTEON_POOL_NO_XXX_6	6
97 #define	OCTEON_POOL_NO_DUMP	7	/* FPA debug dump */
98 
99 #define	OCTEON_POOL_SIZE_PKT	2048	/* 128 x 16 */
100 #define	OCTEON_POOL_SIZE_WQE	128	/* 128 x 1 */
101 #define	OCTEON_POOL_SIZE_CMD	1024	/* 128 x 8 */
102 #define	OCTEON_POOL_SIZE_SG	512	/* 128 x 4 */
103 #define	OCTEON_POOL_SIZE_XXX_4	0
104 #define	OCTEON_POOL_SIZE_XXX_5	0
105 #define	OCTEON_POOL_SIZE_XXX_6	0
106 #define	OCTEON_POOL_SIZE_XXX_7	0
107 
108 #define	OCTEON_POOL_NELEMS_PKT		4096
109 #define	OCTEON_POOL_NELEMS_WQE		4096
110 #define	OCTEON_POOL_NELEMS_CMD		32
111 #define	OCTEON_POOL_NELEMS_SG		1024
112 #define	OCTEON_POOL_NELEMS_XXX_4	0
113 #define	OCTEON_POOL_NELEMS_XXX_5	0
114 #define	OCTEON_POOL_NELEMS_XXX_6	0
115 #define	OCTEON_POOL_NELEMS_XXX_7	0
116 
117 /*
118  * CVMSEG (``scratch'') memory map
119  */
120 struct octeon_cvmseg_map {
121 	/* 0-3 */
122 	uint64_t		csm_xxx_0;
123 	uint64_t		csm_xxx_1;
124 	uint64_t		csm_xxx_2;
125 	uint64_t		csm_pow_intr;
126 
127 	/* 4-19 */
128 	struct octeon_cvmseg_ether_map {
129 		uint64_t	csm_ether_fau_req;
130 		uint64_t	csm_ether_fau_done;
131 		uint64_t	csm_ether_fau_cmdptr;
132 		uint64_t	csm_ether_xxx_3;
133 	} csm_ether[4/* XXX */];
134 
135 	/* 20-32 */
136 	uint64_t	xxx_20_32[32 - 20];
137 } __packed;
138 #define	OCTEON_CVMSEG_OFFSET(entry) \
139 	offsetof(struct octeon_cvmseg_map, entry)
140 #define	OCTEON_CVMSEG_ETHER_OFFSET(n, entry) \
141 	(offsetof(struct octeon_cvmseg_map, csm_ether) + \
142 	 sizeof(struct octeon_cvmseg_ether_map) * (n) + \
143 	 offsetof(struct octeon_cvmseg_ether_map, entry))
144 
145 /*
146  * FAU register map
147  *
148  * => FAU registers exist in FAU unit
149  * => devices (PKO) can access these registers
150  * => CPU can read those values after loading them into CVMSEG
151  */
152 struct octeon_fau_map {
153 	struct {
154 		/* PKO command index */
155 		uint64_t	_fau_map_port_pkocmdidx;
156 		/* send requested */
157 		uint64_t	_fau_map_port_txreq;
158 		/* send completed */
159 		uint64_t	_fau_map_port_txdone;
160 		/* XXX */
161 		uint64_t	_fau_map_port_pad;
162 	} __packed _fau_map_port[3];
163 };
164 
165 /*
166  * POW qos/group map
167  */
168 
169 #define	OCTEON_POW_QOS_PIP		0
170 #define	OCTEON_POW_QOS_CORE1		1
171 #define	OCTEON_POW_QOS_XXX_2		2
172 #define	OCTEON_POW_QOS_XXX_3		3
173 #define	OCTEON_POW_QOS_XXX_4		4
174 #define	OCTEON_POW_QOS_XXX_5		5
175 #define	OCTEON_POW_QOS_XXX_6		6
176 #define	OCTEON_POW_QOS_XXX_7		7
177 
178 #define	OCTEON_POW_GROUP_PIP		0
179 #define	OCTEON_POW_GROUP_XXX_1		1
180 #define	OCTEON_POW_GROUP_XXX_2		2
181 #define	OCTEON_POW_GROUP_XXX_3		3
182 #define	OCTEON_POW_GROUP_XXX_4		4
183 #define	OCTEON_POW_GROUP_XXX_5		5
184 #define	OCTEON_POW_GROUP_XXX_6		6
185 #define	OCTEON_POW_GROUP_CORE1_SEND	7
186 #define	OCTEON_POW_GROUP_CORE1_TASK_0	8
187 #define	OCTEON_POW_GROUP_CORE1_TASK_1	9
188 #define	OCTEON_POW_GROUP_CORE1_TASK_2	10
189 #define	OCTEON_POW_GROUP_CORE1_TASK_3	11
190 #define	OCTEON_POW_GROUP_CORE1_TASK_4	12
191 #define	OCTEON_POW_GROUP_CORE1_TASK_5	13
192 #define	OCTEON_POW_GROUP_CORE1_TASK_6	14
193 #define	OCTEON_POW_GROUP_CORE1_TASK_7	15
194 
195 /*
196  * Octeon board types known to work with OpenBSD/octeon.
197  * One of the main reasons for keeping this list is to be able to tell which
198  * boards do and do not have octcf(4). Currently the only board not to have octcf(4)
199  * is BOARD_TYPE_UBIQUITI_E100. Sadly, this number is also used by other vendors, but
200  * we don't run on those boards yet. When that time comes, iobus needs extra care for
201  * not blindly attaching octcf(4) on every board.
202  */
203 #define	BOARD_TYPE_SIM			1
204 #define	BOARD_TYPE_UBIQUITI_E100	20002
205 
206 #if defined(_KERNEL) || defined(_STANDALONE)
207 #define OCTEON_ARGV_MAX 64
208 
209 /* Maximum number of cores on <= CN52XX */
210 #define OCTEON_MAXCPUS	4
211 
212 struct boot_desc {
213 	uint32_t	desc_ver;
214 	uint32_t	desc_size;
215 	uint64_t	stack_top;
216 	uint64_t 	heap_start;
217 	uint64_t	heap_end;
218 	uint64_t      	__unused17;
219 	uint64_t     	__unused16;
220 	uint32_t      	__unused18;
221 	uint32_t      	__unused15;
222 	uint32_t      	__unused14;
223 	uint32_t	argc;
224 	uint32_t	argv[OCTEON_ARGV_MAX];
225 	uint32_t	flags;
226 	uint32_t	core_mask;
227 	uint32_t	dram_size;
228 	uint32_t	phy_mem_desc_addr;
229 	uint32_t	debugger_flag_addr;
230 	uint32_t	eclock;
231 	uint32_t      	__unused10;
232 	uint32_t      	__unused9;
233 	uint16_t      	__unused8;
234 	uint8_t 	__unused7;
235 	uint8_t 	__unused6;
236 	uint16_t 	__unused5;
237 	uint8_t 	__unused4;
238 	uint8_t 	__unused3;
239 	uint8_t 	__unused2[20];
240 	uint8_t 	__unused1[6];
241 	uint8_t 	__unused0;
242 	uint64_t 	boot_info_addr;
243 };
244 
245 struct boot_info {
246 	uint32_t ver_major;
247 	uint32_t ver_minor;
248 	uint64_t stack_top;
249 	uint64_t heap_start;
250 	uint64_t heap_end;
251 	uint64_t boot_desc_addr;
252 	uint32_t exception_base_addr;
253 	uint32_t stack_size;
254 	uint32_t flags;
255 	uint32_t core_mask;
256 	uint32_t dram_size;
257 	uint32_t phys_mem_desc_addr;
258 	uint32_t debugger_flags_addr;
259 	uint32_t eclock;
260 	uint32_t dclock;
261 	uint32_t __unused0;
262 	uint16_t board_type;
263 	uint8_t board_rev_major;
264 	uint8_t board_rev_minor;
265 	uint16_t __unused1;
266 	uint8_t __unused2;
267 	uint8_t __unused3;
268 	char board_serial[20];
269 	uint8_t mac_addr_base[6];
270 	uint8_t mac_addr_count;
271 	uint64_t cf_common_addr;
272 	uint64_t cf_attr_addr;
273 	uint64_t led_display_addr;
274 	uint32_t dfaclock;
275 	uint32_t config_flags;
276 };
277 
278 extern struct boot_desc *octeon_boot_desc;
279 extern struct boot_info *octeon_boot_info;
280 
281 #ifdef _KERNEL
282 /* Device capabilities advertised in boot_info->config_flags */
283 #define BOOTINFO_CFG_FLAG_PCI_HOST	(1ull << 0)
284 #define BOOTINFO_CFG_FLAG_PCI_TARGET	(1ull << 1)
285 #define BOOTINFO_CFG_FLAG_DEBUG		(1ull << 2)
286 #define BOOTINFO_CFG_FLAG_NO_MAGIC	(1ull << 3)
287 
288 void	octeon_bus_io_init(bus_space_tag_t, void *);
289 void	octeon_bus_mem_init(bus_space_tag_t, void *);
290 void	octeon_cal_timer(int);
291 void	octeon_dma_init(struct octeon_config *);
292 void	octeon_intr_init(void);
293 int	octeon_get_ethaddr(int, u_int8_t *);
294 
295 int	octeon_ioclock_speed(void);
296 
297 #endif /* _KERNEL */
298 #endif /* _KERNEL || _STANDALONE */
299 
300 static inline int
301 ffs64(uint64_t val)
302 {
303 	int ret;
304 
305 	__asm volatile ( \
306 		_ASM_PROLOGUE_MIPS64
307 		"	dclz	%0, %1			\n"
308 		_ASM_EPILOGUE
309 		: "=r"(ret) : "r"(val));
310 	return 64 - ret;
311 }
312 
313 static inline int
314 ffs32(uint32_t val)
315 {
316 	int ret;
317 
318 	__asm __volatile ( \
319 		_ASM_PROLOGUE_MIPS64
320 		"	clz	%0, %1			\n"
321 		_ASM_EPILOGUE
322 		: "=r"(ret) : "r"(val));
323 	return 32 - ret;
324 }
325 
326 static inline uint64_t
327 octeon_xkphys_read_8(paddr_t address)
328 {
329 	volatile uint64_t *p =
330 	    (volatile uint64_t *)(PHYS_TO_XKPHYS(address, CCA_NC));
331 	return (*p);
332 }
333 
334 #define	MIO_BOOT_BIST_STAT			0x00011800000000f8ULL
335 static inline void
336 octeon_xkphys_write_8(paddr_t address, uint64_t value)
337 {
338 	*(volatile uint64_t *)(PHYS_TO_XKPHYS(address, CCA_NC)) = value;
339 
340 	/*
341 	 * It seems an immediate read is necessary when doing a write to an RSL
342 	 * register in order to complete the write.
343 	 * We use MIO_BOOT_BIST_STAT because it's apparently the fastest
344 	 * write.
345 	 */
346 
347 	/*
348 	 * XXX
349 	 * This if would be better writen as:
350 	 * if ((address & 0xffffff0000000000ULL) == OCTEON_MIO_BOOT_BASE) {
351 	 * but octeonreg.h can't be included here and we want this inlined
352 	 *
353 	 * Note that the SDK masks with 0x7ffff but that doesn't make sense.
354 	 * This is a physical address.
355 	 */
356 	if (((address >> 40) & 0xfffff) == (0x118)) {
357 		value = *(volatile uint64_t *)
358 		    (PHYS_TO_XKPHYS(MIO_BOOT_BIST_STAT, CCA_NC));
359 	}
360 }
361 
362 static inline void
363 octeon_iobdma_write_8(uint64_t value)
364 {
365 	uint64_t addr = 0xffffffffffffa200ULL;
366 
367 	*(volatile uint64_t *)addr = value;
368 }
369 
370 static inline uint64_t
371 octeon_cvmseg_read_8(size_t offset)
372 {
373 	return octeon_xkphys_read_8(0xffffffffffff8000ULL + offset);
374 }
375 
376 static inline void
377 octeon_cvmseg_write_8(size_t offset, uint64_t value)
378 {
379 	octeon_xkphys_write_8(0xffffffffffff8000ULL + offset, value);
380 }
381 
382 /* XXX */
383 static inline uint32_t
384 octeon_disable_interrupt(uint32_t *new)
385 {
386 	uint32_t s, tmp;
387 
388 	__asm volatile (
389 		_ASM_PROLOGUE
390 		"	mfc0	%[s], $12		\n"
391 		"	and	%[tmp], %[s], ~1	\n"
392 		"	mtc0	%[tmp], $12		\n"
393 		_ASM_EPILOGUE
394 		: [s]"=&r"(s), [tmp]"=&r"(tmp));
395 	if (new)
396 		*new = tmp;
397 	return s;
398 }
399 
400 /* XXX */
401 static inline void
402 octeon_restore_status(uint32_t s)
403 {
404 	__asm volatile (
405 		_ASM_PROLOGUE
406 		"	mtc0	%[s], $12		\n"
407 		_ASM_EPILOGUE
408 		:: [s]"r"(s));
409 }
410 
411 static inline uint64_t
412 octeon_get_cycles(void)
413 {
414 	uint64_t tmp;
415 
416 	__asm volatile (
417 		_ASM_PROLOGUE_MIPS64
418 		"	dmfc0	%[tmp], $9, 6		\n"
419 		_ASM_EPILOGUE
420 		: [tmp]"=&r"(tmp));
421 	return tmp;
422 }
423 
424 /* -------------------------------------------------------------------------- */
425 
426 /* ---- event counter */
427 
428 #if defined(OCTEON_ETH_DEBUG)
429 #define	OCTEON_EVCNT_INC(sc, name) \
430 	do { (sc)->sc_ev_##name.ev_count++; } while (0)
431 #define	OCTEON_EVCNT_ADD(sc, name, n) \
432 	do { (sc)->sc_ev_##name.ev_count += (n); } while (0)
433 #define	OCTEON_EVCNT_ATTACH_EVCNTS(sc, entries, devname) \
434 do {								\
435 	int i;							\
436 	const struct octeon_evcnt_entry *ee;			\
437 								\
438 	for (i = 0; i < (int)nitems(entries); i++) {	\
439 		ee = &(entries)[i];				\
440 		evcnt_attach_dynamic(				\
441 		    (struct evcnt *)((uintptr_t)(sc) + ee->ee_offset), \
442 		    ee->ee_type, ee->ee_parent, devname,	\
443 		    ee->ee_name);				\
444 	}							\
445 } while (0)
446 #else
447 #define	OCTEON_EVCNT_INC(sc, name)
448 #define	OCTEON_EVCNT_ADD(sc, name, n)
449 #define	OCTEON_EVCNT_ATTACH_EVCNTS(sc, entries, devname)
450 #endif
451 
452 struct octeon_evcnt_entry {
453 	size_t		ee_offset;
454 	int		ee_type;
455 	struct evcnt	*ee_parent;
456 	const char	*ee_name;
457 };
458 
459 #define	OCTEON_EVCNT_ENTRY(_sc_type, _var, _ev_type, _parent, _name) \
460 	{							\
461 		.ee_offset = offsetof(_sc_type, sc_ev_##_var),	\
462 		.ee_type = EVCNT_TYPE_##_ev_type,		\
463 		.ee_parent = _parent,				\
464 		.ee_name = _name				\
465 	}
466 
467 #endif	/* _MIPS_OCTEON_OCTEONVAR_H_ */
468