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