1/* $OpenBSD: octeonvar.h,v 1.55 2025/12/30 22:55:07 jsg 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 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#ifndef _MIPS_OCTEON_OCTEONVAR_H_
34#define _MIPS_OCTEON_OCTEONVAR_H_
35
36#include <machine/bus.h>
37
38/* XXX elsewhere */
39#define _ASM_PROLOGUE \
40 " .set push \n" \
41 " .set noreorder \n"
42#define _ASM_PROLOGUE_MIPS64 \
43 _ASM_PROLOGUE \
44 " .set mips64 \n"
45#define _ASM_PROLOGUE_OCTEON \
46 _ASM_PROLOGUE \
47 " .set arch=octeon \n"
48#define _ASM_EPILOGUE \
49 " .set pop \n"
50/*
51 * subbits = __BITS64_GET(XXX, bits);
52 * bits = __BITS64_SET(XXX, subbits);
53 */
54#ifndef __BITS64_GET
55#define __BITS64_GET(name, bits) \
56 (((uint64_t)(bits) & name) >> name##_SHIFT)
57#endif
58#ifndef __BITS64_SET
59#define __BITS64_SET(name, subbits) \
60 (((uint64_t)(subbits) << name##_SHIFT) & name)
61#endif
62
63struct octeon_config {
64 bus_space_tag_t mc_iobus_bust;
65 bus_space_tag_t mc_bootbus_bust;
66
67 bus_dma_tag_t mc_iobus_dmat;
68 bus_dma_tag_t mc_bootbus_dmat;
69};
70
71#define GPIO_CONFIG_MD_OUTPUT_SEL_MASK (GPIO_CONFIG_MD0 | GPIO_CONFIG_MD1)
72#define GPIO_CONFIG_MD_USB0_VBUS_CTRL GPIO_CONFIG_MD0
73#define GPIO_CONFIG_MD_USB1_VBUS_CTRL GPIO_CONFIG_MD1
74
75/*
76 * FPA map
77 */
78
79#define OCTEON_POOL_NO_PKT 0
80#define OCTEON_POOL_NO_WQE 1
81#define OCTEON_POOL_NO_CMD 2
82#define OCTEON_POOL_NO_SG 3
83#define OCTEON_POOL_NO_XXX_4 4
84#define OCTEON_POOL_NO_XXX_5 5
85#define OCTEON_POOL_NO_XXX_6 6
86#define OCTEON_POOL_NO_DUMP 7 /* FPA debug dump */
87
88#define OCTEON_POOL_SIZE_PKT 1920 /* 128 x 15 */
89#define OCTEON_POOL_SIZE_WQE 128 /* 128 x 1 */
90#define OCTEON_POOL_SIZE_CMD 1024 /* 128 x 8 */
91#define OCTEON_POOL_SIZE_SG 128 /* 128 x 1 */
92#define OCTEON_POOL_SIZE_XXX_4 0
93#define OCTEON_POOL_SIZE_XXX_5 0
94#define OCTEON_POOL_SIZE_XXX_6 0
95#define OCTEON_POOL_SIZE_XXX_7 0
96
97#define OCTEON_POOL_NELEMS_PKT 4096
98#define OCTEON_POOL_NELEMS_WQE 4096
99#define OCTEON_POOL_NELEMS_CMD 32
100#define OCTEON_POOL_NELEMS_SG 4096
101#define OCTEON_POOL_NELEMS_XXX_4 0
102#define OCTEON_POOL_NELEMS_XXX_5 0
103#define OCTEON_POOL_NELEMS_XXX_6 0
104#define OCTEON_POOL_NELEMS_XXX_7 0
105
106/*
107 * CVMSEG (``scratch'') memory map
108 */
109struct octeon_cvmseg_map {
110 uint64_t csm_pow_intr;
111
112 struct octeon_cvmseg_ether_map {
113 uint64_t csm_ether_fau_done;
114 } csm_ether[12/* XXX */];
115} __packed;
116#define OCTEON_CVMSEG_OFFSET(entry) \
117 offsetof(struct octeon_cvmseg_map, entry)
118#define OCTEON_CVMSEG_ETHER_OFFSET(n, entry) \
119 (offsetof(struct octeon_cvmseg_map, csm_ether) + \
120 sizeof(struct octeon_cvmseg_ether_map) * (n) + \
121 offsetof(struct octeon_cvmseg_ether_map, entry))
122
123/*
124 * FAU register map
125 *
126 * => FAU registers exist in FAU unit
127 * => devices (PKO) can access these registers
128 * => CPU can read those values after loading them into CVMSEG
129 */
130struct octeon_fau_map {
131 struct {
132 /* PKO command index */
133 uint64_t _fau_map_port_pkocmdidx;
134 /* send requested */
135 uint64_t _fau_map_port_txreq;
136 /* send completed */
137 uint64_t _fau_map_port_txdone;
138 /* XXX */
139 uint64_t _fau_map_port_pad;
140 } __packed _fau_map_port[3];
141};
142
143/*
144 * POW qos/group map
145 */
146
147#define OCTEON_POW_QOS_PIP 0
148#define OCTEON_POW_QOS_CORE1 1
149#define OCTEON_POW_QOS_XXX_2 2
150#define OCTEON_POW_QOS_XXX_3 3
151#define OCTEON_POW_QOS_XXX_4 4
152#define OCTEON_POW_QOS_XXX_5 5
153#define OCTEON_POW_QOS_XXX_6 6
154#define OCTEON_POW_QOS_XXX_7 7
155
156#define OCTEON_POW_GROUP_MAX 16
157
158enum cnmac_stat {
159 cnmac_stat_rx_toto_gmx,
160 cnmac_stat_rx_totp_gmx,
161 cnmac_stat_rx_toto_pip,
162 cnmac_stat_rx_totp_pip,
163 cnmac_stat_rx_h64,
164 cnmac_stat_rx_h127,
165 cnmac_stat_rx_h255,
166 cnmac_stat_rx_h511,
167 cnmac_stat_rx_h1023,
168 cnmac_stat_rx_h1518,
169 cnmac_stat_rx_hmax,
170 cnmac_stat_rx_bcast,
171 cnmac_stat_rx_mcast,
172 cnmac_stat_rx_qdpo,
173 cnmac_stat_rx_qdpp,
174 cnmac_stat_rx_fcs,
175 cnmac_stat_rx_frag,
176 cnmac_stat_rx_undersz,
177 cnmac_stat_rx_jabber,
178 cnmac_stat_rx_oversz,
179 cnmac_stat_rx_raw,
180 cnmac_stat_rx_bad,
181 cnmac_stat_rx_drop,
182 cnmac_stat_rx_ctl,
183 cnmac_stat_rx_dmac,
184 cnmac_stat_tx_toto,
185 cnmac_stat_tx_totp,
186 cnmac_stat_tx_hmin,
187 cnmac_stat_tx_h64,
188 cnmac_stat_tx_h127,
189 cnmac_stat_tx_h255,
190 cnmac_stat_tx_h511,
191 cnmac_stat_tx_h1023,
192 cnmac_stat_tx_h1518,
193 cnmac_stat_tx_hmax,
194 cnmac_stat_tx_bcast,
195 cnmac_stat_tx_mcast,
196 cnmac_stat_tx_coll,
197 cnmac_stat_tx_defer,
198 cnmac_stat_tx_scol,
199 cnmac_stat_tx_mcol,
200 cnmac_stat_tx_ctl,
201 cnmac_stat_tx_uflow,
202 cnmac_stat_count
203};
204
205#if defined(_KERNEL) || defined(_STANDALONE)
206#define OCTEON_ARGV_MAX 64
207
208/*
209 * OCTEON board types recognized by OpenBSD/octeon.
210 *
211 * It is fine to use BOARD_UNKNOWN when the board does not need
212 * special treatment.
213 */
214enum octeon_board {
215 BOARD_UNKNOWN,
216 BOARD_CHECKPOINT_N100,
217 BOARD_CN3010_EVB_HS5,
218 BOARD_DLINK_DSR_500,
219 BOARD_NETGEAR_UTM25,
220 BOARD_RHINOLABS_UTM8,
221 BOARD_UBIQUITI_E100,
222 BOARD_UBIQUITI_E120,
223 BOARD_UBIQUITI_E200,
224 BOARD_UBIQUITI_E220,
225 BOARD_UBIQUITI_E300,
226 BOARD_UBIQUITI_E1000,
227};
228
229struct boot_desc {
230 uint32_t desc_ver;
231 uint32_t desc_size;
232 uint64_t stack_top;
233 uint64_t heap_start;
234 uint64_t heap_end;
235 uint64_t __unused17;
236 uint64_t __unused16;
237 uint32_t __unused18;
238 uint32_t __unused15;
239 uint32_t __unused14;
240 uint32_t argc;
241 uint32_t argv[OCTEON_ARGV_MAX];
242 uint32_t flags;
243 uint32_t core_mask;
244 uint32_t dram_size;
245 uint32_t phy_mem_desc_addr;
246 uint32_t debugger_flag_addr;
247 uint32_t eclock;
248 uint32_t __unused10;
249 uint32_t __unused9;
250 uint16_t __unused8;
251 uint8_t __unused7;
252 uint8_t __unused6;
253 uint16_t __unused5;
254 uint8_t __unused4;
255 uint8_t __unused3;
256 uint8_t __unused2[20];
257 uint8_t __unused1[6];
258 uint8_t __unused0;
259 uint64_t boot_info_addr;
260};
261
262struct boot_info {
263 uint32_t ver_major;
264 uint32_t ver_minor;
265 uint64_t stack_top;
266 uint64_t heap_start;
267 uint64_t heap_end;
268 uint64_t boot_desc_addr;
269 uint32_t exception_base_addr;
270 uint32_t stack_size;
271 uint32_t flags;
272 uint32_t core_mask;
273 uint32_t dram_size;
274 uint32_t phys_mem_desc_addr;
275 uint32_t debugger_flags_addr;
276 uint32_t eclock;
277 uint32_t dclock;
278 uint32_t __unused0;
279 uint16_t board_type;
280 uint8_t board_rev_major;
281 uint8_t board_rev_minor;
282 uint16_t __unused1;
283 uint8_t __unused2;
284 uint8_t __unused3;
285 char board_serial[20];
286 uint8_t mac_addr_base[6];
287 uint8_t mac_addr_count;
288 uint64_t cf_common_addr;
289 uint64_t cf_attr_addr;
290 uint64_t led_display_addr;
291 uint32_t dfaclock;
292 uint32_t config_flags;
293 /* The fields below are available when ver_minor >= 3. */
294 uint64_t fdt_addr;
295};
296
297struct octeon_bootmem_desc {
298 uint32_t lock;
299 uint32_t flags;
300 uint64_t head_addr;
301 uint32_t major_version;
302 uint32_t minor_version;
303 uint64_t app_data_addr;
304 uint64_t app_data_size;
305 uint32_t named_block_num_blocks;
306 uint32_t named_block_name_len;
307 uint64_t named_block_array_addr;
308};
309
310struct octeon_bootmem_block {
311 uint64_t next;
312 uint64_t size;
313};
314
315extern enum octeon_board octeon_board;
316extern struct boot_desc *octeon_boot_desc;
317extern struct boot_info *octeon_boot_info;
318
319#ifdef _KERNEL
320/* Device capabilities advertised in boot_info->config_flags */
321#define BOOTINFO_CFG_FLAG_PCI_HOST (1ull << 0)
322#define BOOTINFO_CFG_FLAG_PCI_TARGET (1ull << 1)
323#define BOOTINFO_CFG_FLAG_DEBUG (1ull << 2)
324#define BOOTINFO_CFG_FLAG_NO_MAGIC (1ull << 3)
325
326#define BOOTMEM_BLOCK_ALIGN 16
327#define BOOTMEM_BLOCK_MASK (BOOTMEM_BLOCK_ALIGN - 1)
328#define BOOTMEM_BLOCK_MIN_SIZE 16
329
330int bootmem_alloc_region(paddr_t, size_t);
331void bootmem_free(paddr_t, size_t);
332
333int octeon_ioclock_speed(void);
334
335#endif /* _KERNEL */
336#endif /* _KERNEL || _STANDALONE */
337
338static inline uint64_t
339octeon_xkphys_read_8(paddr_t address)
340{
341 volatile uint64_t *p =
342 (volatile uint64_t *)(PHYS_TO_XKPHYS(address, CCA_NC));
343 return (*p);
344}
345
346#define MIO_BOOT_BIST_STAT 0x00011800000000f8ULL
347static inline void
348octeon_xkphys_write_8(paddr_t address, uint64_t value)
349{
350 *(volatile uint64_t *)(PHYS_TO_XKPHYS(address, CCA_NC)) = value;
351
352 /*
353 * It seems an immediate read is necessary when doing a write to an RSL
354 * register in order to complete the write.
355 * We use MIO_BOOT_BIST_STAT because it's apparently the fastest
356 * write.
357 */
358
359 /*
360 * XXX
361 * This if would be better written as:
362 * if ((address & 0xffffff0000000000ULL) == OCTEON_MIO_BOOT_BASE) {
363 * but octeonreg.h can't be included here and we want this inlined
364 *
365 * Note that the SDK masks with 0x7ffff but that doesn't make sense.
366 * This is a physical address.
367 */
368 if (((address >> 40) & 0xfffff) == (0x118)) {
369 value = *(volatile uint64_t *)
370 (PHYS_TO_XKPHYS(MIO_BOOT_BIST_STAT, CCA_NC));
371 }
372}
373
374static inline void
375octeon_iobdma_write_8(uint64_t value)
376{
377 uint64_t addr = 0xffffffffffffa200ULL;
378
379 *(volatile uint64_t *)addr = value;
380}
381
382static inline void
383octeon_lmtdma_write_8(off_t offset, uint64_t value)
384{
385 *(volatile uint64_t *)(0xffffffffffffa400ULL + offset) = value;
386}
387
388static inline uint64_t
389octeon_cvmseg_read_8(size_t offset)
390{
391 return *(volatile uint64_t *)(0xffffffffffff8000ULL + offset);
392}
393
394static inline void
395octeon_cvmseg_write_8(size_t offset, uint64_t value)
396{
397 *(volatile uint64_t *)(0xffffffffffff8000ULL + offset) = value;
398}
399
400static inline uint32_t
401octeon_get_coreid(void)
402{
403 uint32_t coreid;
404
405 __asm volatile (
406 _ASM_PROLOGUE_OCTEON
407 " rdhwr %0, $0\n"
408 _ASM_EPILOGUE
409 : "=r" (coreid));
410 return coreid;
411}
412
413static inline uint64_t
414octeon_get_cycles(void)
415{
416 uint64_t tmp;
417
418 __asm volatile (
419 _ASM_PROLOGUE_MIPS64
420 " dmfc0 %[tmp], $9, 6 \n"
421 _ASM_EPILOGUE
422 : [tmp]"=&r"(tmp));
423 return tmp;
424}
425
426static inline uint64_t
427octeon_get_cvmctl(void)
428{
429 uint64_t tmp;
430
431 __asm volatile (
432 _ASM_PROLOGUE_OCTEON
433 " dmfc0 %[tmp], $9, 7 \n"
434 _ASM_EPILOGUE
435 : [tmp]"=r"(tmp));
436 return tmp;
437}
438
439static inline uint64_t
440octeon_get_cvmmemctl(void)
441{
442 uint64_t tmp;
443
444 __asm volatile (
445 _ASM_PROLOGUE_OCTEON
446 " dmfc0 %[tmp], $11, 7 \n"
447 _ASM_EPILOGUE
448 : [tmp]"=r"(tmp));
449 return tmp;
450}
451
452static inline void
453octeon_set_cvmmemctl(uint64_t val)
454{
455 __asm volatile (
456 _ASM_PROLOGUE_OCTEON
457 " dmtc0 %[tmp], $11, 7 \n"
458 _ASM_EPILOGUE
459 : : [tmp]"r"(val) : "memory");
460}
461
462static inline void
463octeon_synciobdma(void)
464{
465 __asm volatile (
466 _ASM_PROLOGUE_OCTEON
467 " synciobdma\n"
468 _ASM_EPILOGUE
469 : : : "memory");
470}
471
472#endif /* _MIPS_OCTEON_OCTEONVAR_H_ */