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