octeonvar.h revision 1.7 1 /* $NetBSD: octeonvar.h,v 1.7 2020/05/13 21:09:02 riastradh 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-31 */
167 uint64_t xxx_20_32[32 - 20];
168
169 /* 32-63 */
170 uint64_t csm_rnm[32];
171 } __packed;
172 #define OCTEON_CVMSEG_OFFSET(entry) \
173 offsetof(struct octeon_cvmseg_map, entry)
174 #define OCTEON_CVMSEG_ETHER_OFFSET(n, entry) \
175 (offsetof(struct octeon_cvmseg_map, csm_ether) + \
176 sizeof(struct octeon_cvmseg_ether_map) * (n) + \
177 offsetof(struct octeon_cvmseg_ether_map, entry))
178
179 /*
180 * FAU register map
181 *
182 * => FAU registers exist in FAU unit
183 * => devices (PKO) can access these registers
184 * => CPU can read those values after loading them into CVMSEG
185 */
186 struct octeon_fau_map {
187 struct {
188 /* PKO command index */
189 uint64_t _fau_map_port_pkocmdidx;
190 /* send requested */
191 uint64_t _fau_map_port_txreq;
192 /* send completed */
193 uint64_t _fau_map_port_txdone;
194 /* XXX */
195 uint64_t _fau_map_port_pad;
196 } __packed _fau_map_port[3];
197 };
198
199 /*
200 * POW qos/group map
201 */
202
203 #define OCTEON_POW_QOS_PIP 0
204 #define OCTEON_POW_QOS_CORE1 1
205 #define OCTEON_POW_QOS_XXX_2 2
206 #define OCTEON_POW_QOS_XXX_3 3
207 #define OCTEON_POW_QOS_XXX_4 4
208 #define OCTEON_POW_QOS_XXX_5 5
209 #define OCTEON_POW_QOS_XXX_6 6
210 #define OCTEON_POW_QOS_XXX_7 7
211
212 #define OCTEON_POW_GROUP_PIP 0
213 #define OCTEON_POW_GROUP_XXX_1 1
214 #define OCTEON_POW_GROUP_XXX_2 2
215 #define OCTEON_POW_GROUP_XXX_3 3
216 #define OCTEON_POW_GROUP_XXX_4 4
217 #define OCTEON_POW_GROUP_XXX_5 5
218 #define OCTEON_POW_GROUP_XXX_6 6
219 #define OCTEON_POW_GROUP_CORE1_SEND 7
220 #define OCTEON_POW_GROUP_CORE1_TASK_0 8
221 #define OCTEON_POW_GROUP_CORE1_TASK_1 9
222 #define OCTEON_POW_GROUP_CORE1_TASK_2 10
223 #define OCTEON_POW_GROUP_CORE1_TASK_3 11
224 #define OCTEON_POW_GROUP_CORE1_TASK_4 12
225 #define OCTEON_POW_GROUP_CORE1_TASK_5 13
226 #define OCTEON_POW_GROUP_CORE1_TASK_6 14
227 #define OCTEON_POW_GROUP_CORE1_TASK_7 15
228
229 #ifdef _KERNEL
230 extern struct octeon_config octeon_configuration;
231 #ifdef MULTIPROCESSOR
232 extern kcpuset_t *cpus_booted;
233 extern struct cpu_softc octeon_cpu1_softc;
234 #endif
235
236 void octeon_bus_io_init(bus_space_tag_t, void *);
237 void octeon_bus_mem_init(bus_space_tag_t, void *);
238 void octeon_cal_timer(int);
239 void octeon_dma_init(struct octeon_config *);
240 void octeon_intr_init(struct cpu_info *);
241 void octeon_iointr(int, vaddr_t, uint32_t);
242 void octeon_pci_init(pci_chipset_tag_t, struct octeon_config *);
243 void *octeon_intr_establish(int, int, int (*)(void *), void *);
244 void octeon_intr_disestablish(void *cookie);
245
246 void octeon_reset_vector(void);
247 uint64_t mips_cp0_cvmctl_read(void);
248 void mips_cp0_cvmctl_write(uint64_t);
249
250 #endif /* _KERNEL */
251
252 #if defined(__mips_n32)
253 #define ffs64 __builtin_ffsll
254 #elif defined(_LP64)
255 #define ffs64 __builtin_ffsl
256 #else
257 #error unknown ABI
258 #endif
259
260 /*
261 * Prefetch
262 *
263 * OCTEON_PREF normal (L1 and L2)
264 * OCTEON_PREF_L1 L1 only
265 * OCTEON_PREF_L2 L2 only
266 * OCTEON_PREF_DWB don't write back
267 * OCTEON_PREF_PFS prepare for store
268 */
269 #define __OCTEON_PREF_N(n, base, offset) \
270 __asm __volatile ( \
271 " .set push \
272 " .set arch=octeon \n" \
273 " pref "#n", "#offset"(%[base]) \n" \
274 " .set pop \
275 : : [base] "d" (base) \
276 )
277 #define __OCTEON_PREF_0(base, offset) __OCTEON_PREF_N(0, base, offset)
278 #define __OCTEON_PREF_4(base, offset) __OCTEON_PREF_N(4, base, offset)
279 #define __OCTEON_PREF_28(base, offset) __OCTEON_PREF_N(28, base, offset)
280 #define __OCTEON_PREF_29(base, offset) __OCTEON_PREF_N(29, base, offset)
281 #define __OCTEON_PREF_30(base, offset) __OCTEON_PREF_N(30, base, offset)
282 #define OCTEON_PREF(base, offset) __OCTEON_PREF_0(base, offset)
283 #define OCTEON_PREF_L1(base, offset) __OCTEON_PREF_4(base, offset)
284 #define OCTEON_PREF_L2(base, offset) __OCTEON_PREF_28(base, offset)
285 #define OCTEON_PREF_DWB(base, offset) __OCTEON_PREF_29(base, offset)
286 #define OCTEON_PREF_PFS(base, offset) __OCTEON_PREF_30(base, offset)
287
288 /*
289 * Sync
290 */
291 #define OCTEON_SYNCCOMMON(name) \
292 __asm __volatile ( \
293 _ASM_PROLOGUE_OCTEON \
294 " "#name" \n" \
295 _ASM_EPILOGUE \
296 ::: "memory")
297 #define OCTEON_SYNCIOBDMA OCTEON_SYNCCOMMON(synciobdma)
298 #define OCTEON_SYNCW OCTEON_SYNCCOMMON(syncw)
299 #define OCTEON_SYNC OCTEON_SYNCCOMMON(sync)
300 #define OCTEON_SYNCWS OCTEON_SYNCCOMMON(syncws)
301 #define OCTEON_SYNCS OCTEON_SYNCCOMMON(syncs)
302 /* XXX backward compatibility */
303 #if 1
304 #define OCT_SYNCIOBDMA OCTEON_SYNCIOBDMA
305 #define OCT_SYNCW OCTEON_SYNCW
306 #define OCT_SYNC OCTEON_SYNC
307 #define OCT_SYNCWS OCTEON_SYNCWS
308 #define OCT_SYNCS OCTEON_SYNCS
309 #endif
310
311 /* octeon core does not use cca to determine cacheability */
312 #define OCTEON_CCA_NONE UINT64_C(0)
313
314 static __inline uint64_t
315 octeon_xkphys_read_8(paddr_t address)
316 {
317 return mips3_ld(MIPS_PHYS_TO_XKPHYS(OCTEON_CCA_NONE, address));
318 }
319
320 static __inline void
321 octeon_xkphys_write_8(paddr_t address, uint64_t value)
322 {
323 mips3_sd(MIPS_PHYS_TO_XKPHYS(OCTEON_CCA_NONE, address), value);
324 }
325
326 /* XXX backward compatibility */
327 #if 1
328 #define octeon_read_csr(address) \
329 octeon_xkphys_read_8(address)
330 #define octeon_write_csr(address, value) \
331 octeon_xkphys_write_8(address, value)
332 #endif
333
334 static __inline void
335 octeon_iobdma_write_8(uint64_t value)
336 {
337 uint64_t addr = UINT64_C(0xffffffffffffa200);
338
339 octeon_xkphys_write_8(addr, value);
340 }
341
342 static __inline uint64_t
343 octeon_cvmseg_read_8(size_t offset)
344 {
345 return octeon_xkphys_read_8(UINT64_C(0xffffffffffff8000) + offset);
346 }
347
348 static __inline void
349 octeon_cvmseg_write_8(size_t offset, uint64_t value)
350 {
351 octeon_xkphys_write_8(UINT64_C(0xffffffffffff8000) + offset, value);
352 }
353
354 /* XXX */
355 static __inline uint32_t
356 octeon_disable_interrupt(uint32_t *new)
357 {
358 uint32_t s, tmp;
359
360 __asm __volatile (
361 _ASM_PROLOGUE
362 " mfc0 %[s], $12 \n"
363 " and %[tmp], %[s], ~1 \n"
364 " mtc0 %[tmp], $12 \n"
365 _ASM_EPILOGUE
366 : [s]"=&r"(s), [tmp]"=&r"(tmp));
367 if (new)
368 *new = tmp;
369 return s;
370 }
371
372 /* XXX */
373 static __inline void
374 octeon_restore_status(uint32_t s)
375 {
376 __asm __volatile (
377 _ASM_PROLOGUE
378 " mtc0 %[s], $12 \n"
379 _ASM_EPILOGUE
380 :: [s]"r"(s));
381 }
382
383 static __inline uint64_t
384 octeon_get_cycles(void)
385 {
386 #if defined(__mips_o32)
387 uint32_t s, lo, hi;
388
389 s = octeon_disable_interrupt((void *)0);
390 __asm __volatile (
391 _ASM_PROLOGUE_MIPS64
392 " dmfc0 %[lo], $9, 6 \n"
393 " add %[hi], %[lo], $0 \n"
394 " srl %[hi], 32 \n"
395 " sll %[lo], 32 \n"
396 " srl %[lo], 32 \n"
397 _ASM_EPILOGUE
398 : [lo]"=&r"(lo), [hi]"=&r"(hi));
399 octeon_restore_status(s);
400 return ((uint64_t)hi << 32) + (uint64_t)lo;
401 #else
402 uint64_t tmp;
403
404 __asm __volatile (
405 _ASM_PROLOGUE_MIPS64
406 " dmfc0 %[tmp], $9, 6 \n"
407 _ASM_EPILOGUE
408 : [tmp]"=&r"(tmp));
409 return tmp;
410 #endif
411 }
412
413 /* -------------------------------------------------------------------------- */
414
415 /* ---- event counter */
416
417 #if defined(OCTEON_ETH_DEBUG)
418 #define OCTEON_EVCNT_INC(sc, name) \
419 do { (sc)->sc_ev_##name.ev_count++; } while (0)
420 #define OCTEON_EVCNT_ADD(sc, name, n) \
421 do { (sc)->sc_ev_##name.ev_count += (n); } while (0)
422 #define OCTEON_EVCNT_ATTACH_EVCNTS(sc, entries, devname) \
423 do { \
424 int i; \
425 const struct octeon_evcnt_entry *ee; \
426 \
427 for (i = 0; i < (int)__arraycount(entries); i++) { \
428 ee = &(entries)[i]; \
429 evcnt_attach_dynamic( \
430 (struct evcnt *)((uintptr_t)(sc) + ee->ee_offset), \
431 ee->ee_type, ee->ee_parent, devname, \
432 ee->ee_name); \
433 } \
434 } while (0)
435 #else
436 #define OCTEON_EVCNT_INC(sc, name)
437 #define OCTEON_EVCNT_ADD(sc, name, n)
438 #define OCTEON_EVCNT_ATTACH_EVCNTS(sc, entries, devname)
439 #endif
440
441 struct octeon_evcnt_entry {
442 size_t ee_offset;
443 int ee_type;
444 struct evcnt *ee_parent;
445 const char *ee_name;
446 };
447
448 #define OCTEON_EVCNT_ENTRY(_sc_type, _var, _ev_type, _parent, _name) \
449 { \
450 .ee_offset = offsetof(_sc_type, sc_ev_##_var), \
451 .ee_type = EVCNT_TYPE_##_ev_type, \
452 .ee_parent = _parent, \
453 .ee_name = _name \
454 }
455
456 #endif /* _MIPS_OCTEON_OCTEONVAR_H_ */
457