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