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