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