1 /* $NetBSD: maltavar.h,v 1.3 2002/03/18 10:10:16 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 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #ifndef _MIPS_OCTEON_OCTEONVAR_H_ 40 #define _MIPS_OCTEON_OCTEONVAR_H_ 41 42 #include <machine/bus.h> 43 44 /* XXX elsewhere */ 45 #define _ASM_PROLOGUE \ 46 " .set push \n" \ 47 " .set noreorder \n" 48 #define _ASM_PROLOGUE_MIPS64 \ 49 _ASM_PROLOGUE \ 50 " .set mips64 \n" 51 #define _ASM_PROLOGUE_OCTEON \ 52 _ASM_PROLOGUE \ 53 " .set arch=octeon \n" 54 #define _ASM_EPILOGUE \ 55 " .set pop \n" 56 /* 57 * subbits = __BITS64_GET(XXX, bits); 58 * bits = __BITS64_SET(XXX, subbits); 59 */ 60 #ifndef __BITS64_GET 61 #define __BITS64_GET(name, bits) \ 62 (((uint64_t)(bits) & name) >> name##_SHIFT) 63 #endif 64 #ifndef __BITS64_SET 65 #define __BITS64_SET(name, subbits) \ 66 (((uint64_t)(subbits) << name##_SHIFT) & name) 67 #endif 68 69 struct octeon_config { 70 bus_space_tag_t mc_iobus_bust; 71 bus_space_tag_t mc_bootbus_bust; 72 73 bus_dma_tag_t mc_iobus_dmat; 74 bus_dma_tag_t mc_bootbus_dmat; 75 /* 76 struct mips_bus_dma_tag mc_core1_dmat; 77 78 struct extent *mc_io_ex; 79 struct extent *mc_mem_ex; 80 81 int mc_mallocsafe; 82 */ 83 }; 84 85 /* 86 * FPA map 87 */ 88 89 #define OCTEON_POOL_NO_PKT 0 90 #define OCTEON_POOL_NO_WQE 1 91 #define OCTEON_POOL_NO_CMD 2 92 #define OCTEON_POOL_NO_SG 3 93 #define OCTEON_POOL_NO_XXX_4 4 94 #define OCTEON_POOL_NO_XXX_5 5 95 #define OCTEON_POOL_NO_XXX_6 6 96 #define OCTEON_POOL_NO_DUMP 7 /* FPA debug dump */ 97 98 #define OCTEON_POOL_SIZE_PKT 2048 /* 128 x 16 */ 99 #define OCTEON_POOL_SIZE_WQE 128 /* 128 x 1 */ 100 #define OCTEON_POOL_SIZE_CMD 1024 /* 128 x 8 */ 101 #define OCTEON_POOL_SIZE_SG 512 /* 128 x 4 */ 102 #define OCTEON_POOL_SIZE_XXX_4 0 103 #define OCTEON_POOL_SIZE_XXX_5 0 104 #define OCTEON_POOL_SIZE_XXX_6 0 105 #define OCTEON_POOL_SIZE_XXX_7 0 106 107 #define OCTEON_POOL_NELEMS_PKT 4096 108 #define OCTEON_POOL_NELEMS_WQE 4096 109 #define OCTEON_POOL_NELEMS_CMD 32 110 #define OCTEON_POOL_NELEMS_SG 1024 111 #define OCTEON_POOL_NELEMS_XXX_4 0 112 #define OCTEON_POOL_NELEMS_XXX_5 0 113 #define OCTEON_POOL_NELEMS_XXX_6 0 114 #define OCTEON_POOL_NELEMS_XXX_7 0 115 116 /* 117 * CVMSEG (``scratch'') memory map 118 */ 119 struct octeon_cvmseg_map { 120 /* 0-3 */ 121 uint64_t csm_xxx_0; 122 uint64_t csm_xxx_1; 123 uint64_t csm_xxx_2; 124 uint64_t csm_pow_intr; 125 126 /* 4-19 */ 127 struct octeon_cvmseg_ether_map { 128 uint64_t csm_ether_fau_req; 129 uint64_t csm_ether_fau_done; 130 uint64_t csm_ether_fau_cmdptr; 131 uint64_t csm_ether_xxx_3; 132 } csm_ether[4/* XXX */]; 133 134 /* 20-32 */ 135 uint64_t xxx_20_32[32 - 20]; 136 } __packed; 137 #define OCTEON_CVMSEG_OFFSET(entry) \ 138 offsetof(struct octeon_cvmseg_map, entry) 139 #define OCTEON_CVMSEG_ETHER_OFFSET(n, entry) \ 140 (offsetof(struct octeon_cvmseg_map, csm_ether) + \ 141 sizeof(struct octeon_cvmseg_ether_map) * (n) + \ 142 offsetof(struct octeon_cvmseg_ether_map, entry)) 143 144 /* 145 * FAU register map 146 * 147 * => FAU registers exist in FAU unit 148 * => devices (PKO) can access these registers 149 * => CPU can read those values after loading them into CVMSEG 150 */ 151 struct octeon_fau_map { 152 struct { 153 /* PKO command index */ 154 uint64_t _fau_map_port_pkocmdidx; 155 /* send requested */ 156 uint64_t _fau_map_port_txreq; 157 /* send completed */ 158 uint64_t _fau_map_port_txdone; 159 /* XXX */ 160 uint64_t _fau_map_port_pad; 161 } __packed _fau_map_port[3]; 162 }; 163 164 /* 165 * POW qos/group map 166 */ 167 168 #define OCTEON_POW_QOS_PIP 0 169 #define OCTEON_POW_QOS_CORE1 1 170 #define OCTEON_POW_QOS_XXX_2 2 171 #define OCTEON_POW_QOS_XXX_3 3 172 #define OCTEON_POW_QOS_XXX_4 4 173 #define OCTEON_POW_QOS_XXX_5 5 174 #define OCTEON_POW_QOS_XXX_6 6 175 #define OCTEON_POW_QOS_XXX_7 7 176 177 #define OCTEON_POW_GROUP_PIP 0 178 #define OCTEON_POW_GROUP_XXX_1 1 179 #define OCTEON_POW_GROUP_XXX_2 2 180 #define OCTEON_POW_GROUP_XXX_3 3 181 #define OCTEON_POW_GROUP_XXX_4 4 182 #define OCTEON_POW_GROUP_XXX_5 5 183 #define OCTEON_POW_GROUP_XXX_6 6 184 #define OCTEON_POW_GROUP_CORE1_SEND 7 185 #define OCTEON_POW_GROUP_CORE1_TASK_0 8 186 #define OCTEON_POW_GROUP_CORE1_TASK_1 9 187 #define OCTEON_POW_GROUP_CORE1_TASK_2 10 188 #define OCTEON_POW_GROUP_CORE1_TASK_3 11 189 #define OCTEON_POW_GROUP_CORE1_TASK_4 12 190 #define OCTEON_POW_GROUP_CORE1_TASK_5 13 191 #define OCTEON_POW_GROUP_CORE1_TASK_6 14 192 #define OCTEON_POW_GROUP_CORE1_TASK_7 15 193 194 #ifdef _KERNEL 195 extern struct octeon_config octeon_configuration; 196 197 void octeon_bus_io_init(bus_space_tag_t, void *); 198 void octeon_bus_mem_init(bus_space_tag_t, void *); 199 void octeon_cal_timer(int); 200 void octeon_dma_init(struct octeon_config *); 201 void octeon_intr_init(void); 202 int octeon_get_ethaddr(int, u_int8_t *); 203 #endif /* _KERNEL */ 204 205 static inline int 206 ffs64(uint64_t val) 207 { 208 int ret; 209 210 __asm __volatile ( \ 211 _ASM_PROLOGUE_MIPS64 212 " dclz %0, %1 \n" 213 _ASM_EPILOGUE 214 : "=r"(ret) : "r"(val)); 215 return 64 - ret; 216 } 217 218 /* 219 * Prefetch 220 * 221 * OCTEON_PREF normal (L1 and L2) 222 * OCTEON_PREF_L1 L1 only 223 * OCTEON_PREF_L2 L2 only 224 * OCTEON_PREF_DWB don't write back 225 * OCTEON_PREF_PFS prepare for store 226 */ 227 #define __OCTEON_PREF_N(n, base, offset) \ 228 __asm __volatile ( \ 229 " .set push \ 230 " .set arch=octeon \n" \ 231 " pref "#n", "#offset"(%[base]) \n" \ 232 " .set pop \ 233 : : [base] "d" (base) \ 234 ) 235 #define __OCTEON_PREF_0(base, offset) __OCTEON_PREF_N(0, base, offset) 236 #define __OCTEON_PREF_4(base, offset) __OCTEON_PREF_N(4, base, offset) 237 #define __OCTEON_PREF_28(base, offset) __OCTEON_PREF_N(28, base, offset) 238 #define __OCTEON_PREF_29(base, offset) __OCTEON_PREF_N(29, base, offset) 239 #define __OCTEON_PREF_30(base, offset) __OCTEON_PREF_N(30, base, offset) 240 #define OCTEON_PREF(base, offset) __OCTEON_PREF_0(base, offset) 241 #define OCTEON_PREF_L1(base, offset) __OCTEON_PREF_4(base, offset) 242 #define OCTEON_PREF_L2(base, offset) __OCTEON_PREF_28(base, offset) 243 #define OCTEON_PREF_DWB(base, offset) __OCTEON_PREF_29(base, offset) 244 #define OCTEON_PREF_PFS(base, offset) __OCTEON_PREF_30(base, offset) 245 246 /* 247 * Sync 248 */ 249 #define OCTEON_SYNCCOMMON(name) \ 250 __asm __volatile ( \ 251 _ASM_PROLOGUE_OCTEON \ 252 " "#name" \n" \ 253 _ASM_EPILOGUE \ 254 ::: "memory") 255 #define OCTEON_SYNCIOBDMA __asm __volatile (".word 0x8f" : : :"memory") 256 #define OCTEON_SYNCW __asm __volatile (".word 0x10f" : : ) 257 #define OCTEON_SYNC OCTEON_SYNCCOMMON(sync) 258 #define OCTEON_SYNCWS __asm __volatile (".word 0x14f" : : ) 259 /* XXX backward compatibility */ 260 #if 1 261 #define OCT_SYNCIOBDMA OCTEON_SYNCIOBDMA 262 #define OCT_SYNCW OCTEON_SYNCW 263 #define OCT_SYNC OCTEON_SYNC 264 #define OCT_SYNCWS OCTEON_SYNCWS 265 #endif 266 267 static inline uint64_t 268 octeon_xkphys_read_8(paddr_t address) 269 { 270 volatile uint64_t *p = 271 (volatile uint64_t *)(PHYS_TO_XKPHYS(address, CCA_NC)); 272 return (*p); 273 } 274 275 static inline void 276 octeon_xkphys_write_8(paddr_t address, uint64_t value) 277 { 278 *(volatile uint64_t *)(PHYS_TO_XKPHYS(address, CCA_NC)) = value; 279 } 280 281 /* XXX backward compatibility */ 282 #if 1 283 #define octeon_read_csr(address) \ 284 octeon_xkphys_read_8(address) 285 #define octeon_write_csr(address, value) \ 286 octeon_xkphys_write_8(address, value) 287 #endif 288 289 static inline void 290 octeon_iobdma_write_8(uint64_t value) 291 { 292 uint64_t addr = 0xffffffffffffa200ULL; 293 294 *(volatile uint64_t *)addr = value; 295 } 296 297 static inline uint64_t 298 octeon_cvmseg_read_8(size_t offset) 299 { 300 return octeon_xkphys_read_8(0xffffffffffff8000ULL + offset); 301 } 302 303 static inline void 304 octeon_cvmseg_write_8(size_t offset, uint64_t value) 305 { 306 octeon_xkphys_write_8(0xffffffffffff8000ULL + offset, value); 307 } 308 309 /* XXX */ 310 static inline uint32_t 311 octeon_disable_interrupt(uint32_t *new) 312 { 313 uint32_t s, tmp; 314 315 __asm __volatile ( 316 _ASM_PROLOGUE 317 " mfc0 %[s], $12 \n" 318 " and %[tmp], %[s], ~1 \n" 319 " mtc0 %[tmp], $12 \n" 320 _ASM_EPILOGUE 321 : [s]"=&r"(s), [tmp]"=&r"(tmp)); 322 if (new) 323 *new = tmp; 324 return s; 325 } 326 327 /* XXX */ 328 static inline void 329 octeon_restore_status(uint32_t s) 330 { 331 __asm __volatile ( 332 _ASM_PROLOGUE 333 " mtc0 %[s], $12 \n" 334 _ASM_EPILOGUE 335 :: [s]"r"(s)); 336 } 337 338 static inline uint64_t 339 octeon_get_cycles(void) 340 { 341 #if defined(__mips_o32) 342 uint32_t s, lo, hi; 343 344 s = octeon_disable_interrupt((void *)0); 345 __asm __volatile ( 346 _ASM_PROLOGUE_MIPS64 347 " dmfc0 %[lo], $9, 6 \n" 348 " add %[hi], %[lo], $0 \n" 349 " srl %[hi], 32 \n" 350 " sll %[lo], 32 \n" 351 " srl %[lo], 32 \n" 352 _ASM_EPILOGUE 353 : [lo]"=&r"(lo), [hi]"=&r"(hi)); 354 octeon_restore_status(s); 355 return ((uint64_t)hi << 32) + (uint64_t)lo; 356 #else 357 uint64_t tmp; 358 359 __asm __volatile ( 360 _ASM_PROLOGUE_MIPS64 361 " dmfc0 %[tmp], $9, 6 \n" 362 _ASM_EPILOGUE 363 : [tmp]"=&r"(tmp)); 364 return tmp; 365 #endif 366 } 367 368 /* -------------------------------------------------------------------------- */ 369 370 /* ---- event counter */ 371 372 #if defined(OCTEON_ETH_DEBUG) 373 #define OCTEON_EVCNT_INC(sc, name) \ 374 do { (sc)->sc_ev_##name.ev_count++; } while (0) 375 #define OCTEON_EVCNT_ADD(sc, name, n) \ 376 do { (sc)->sc_ev_##name.ev_count += (n); } while (0) 377 #define OCTEON_EVCNT_ATTACH_EVCNTS(sc, entries, devname) \ 378 do { \ 379 int i; \ 380 const struct octeon_evcnt_entry *ee; \ 381 \ 382 for (i = 0; i < (int)nitems(entries); i++) { \ 383 ee = &(entries)[i]; \ 384 evcnt_attach_dynamic( \ 385 (struct evcnt *)((uintptr_t)(sc) + ee->ee_offset), \ 386 ee->ee_type, ee->ee_parent, devname, \ 387 ee->ee_name); \ 388 } \ 389 } while (0) 390 #else 391 #define OCTEON_EVCNT_INC(sc, name) 392 #define OCTEON_EVCNT_ADD(sc, name, n) 393 #define OCTEON_EVCNT_ATTACH_EVCNTS(sc, entries, devname) 394 #endif 395 396 struct octeon_evcnt_entry { 397 size_t ee_offset; 398 int ee_type; 399 struct evcnt *ee_parent; 400 const char *ee_name; 401 }; 402 403 #define OCTEON_EVCNT_ENTRY(_sc_type, _var, _ev_type, _parent, _name) \ 404 { \ 405 .ee_offset = offsetof(_sc_type, sc_ev_##_var), \ 406 .ee_type = EVCNT_TYPE_##_ev_type, \ 407 .ee_parent = _parent, \ 408 .ee_name = _name \ 409 } 410 411 #endif /* _MIPS_OCTEON_OCTEONVAR_H_ */ 412