1 /* $OpenBSD: octeonvar.h,v 1.20 2014/07/14 10:23:58 jasper Exp $ */ 2 /* $NetBSD: maltavar.h,v 1.3 2002/03/18 10:10:16 simonb Exp $ */ 3 4 /*- 5 * Copyright (c) 2001 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Jason R. Thorpe. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 #ifndef _MIPS_OCTEON_OCTEONVAR_H_ 41 #define _MIPS_OCTEON_OCTEONVAR_H_ 42 43 #include <machine/bus.h> 44 45 /* XXX elsewhere */ 46 #define _ASM_PROLOGUE \ 47 " .set push \n" \ 48 " .set noreorder \n" 49 #define _ASM_PROLOGUE_MIPS64 \ 50 _ASM_PROLOGUE \ 51 " .set mips64 \n" 52 #define _ASM_PROLOGUE_OCTEON \ 53 _ASM_PROLOGUE \ 54 " .set arch=octeon \n" 55 #define _ASM_EPILOGUE \ 56 " .set pop \n" 57 /* 58 * subbits = __BITS64_GET(XXX, bits); 59 * bits = __BITS64_SET(XXX, subbits); 60 */ 61 #ifndef __BITS64_GET 62 #define __BITS64_GET(name, bits) \ 63 (((uint64_t)(bits) & name) >> name##_SHIFT) 64 #endif 65 #ifndef __BITS64_SET 66 #define __BITS64_SET(name, subbits) \ 67 (((uint64_t)(subbits) << name##_SHIFT) & name) 68 #endif 69 70 struct octeon_config { 71 bus_space_tag_t mc_iobus_bust; 72 bus_space_tag_t mc_bootbus_bust; 73 74 bus_dma_tag_t mc_iobus_dmat; 75 bus_dma_tag_t mc_bootbus_dmat; 76 /* 77 struct mips_bus_dma_tag mc_core1_dmat; 78 79 struct extent *mc_io_ex; 80 struct extent *mc_mem_ex; 81 82 int mc_mallocsafe; 83 */ 84 }; 85 86 /* 87 * FPA map 88 */ 89 90 #define OCTEON_POOL_NO_PKT 0 91 #define OCTEON_POOL_NO_WQE 1 92 #define OCTEON_POOL_NO_CMD 2 93 #define OCTEON_POOL_NO_SG 3 94 #define OCTEON_POOL_NO_XXX_4 4 95 #define OCTEON_POOL_NO_XXX_5 5 96 #define OCTEON_POOL_NO_XXX_6 6 97 #define OCTEON_POOL_NO_DUMP 7 /* FPA debug dump */ 98 99 #define OCTEON_POOL_SIZE_PKT 2048 /* 128 x 16 */ 100 #define OCTEON_POOL_SIZE_WQE 128 /* 128 x 1 */ 101 #define OCTEON_POOL_SIZE_CMD 1024 /* 128 x 8 */ 102 #define OCTEON_POOL_SIZE_SG 512 /* 128 x 4 */ 103 #define OCTEON_POOL_SIZE_XXX_4 0 104 #define OCTEON_POOL_SIZE_XXX_5 0 105 #define OCTEON_POOL_SIZE_XXX_6 0 106 #define OCTEON_POOL_SIZE_XXX_7 0 107 108 #define OCTEON_POOL_NELEMS_PKT 4096 109 #define OCTEON_POOL_NELEMS_WQE 4096 110 #define OCTEON_POOL_NELEMS_CMD 32 111 #define OCTEON_POOL_NELEMS_SG 1024 112 #define OCTEON_POOL_NELEMS_XXX_4 0 113 #define OCTEON_POOL_NELEMS_XXX_5 0 114 #define OCTEON_POOL_NELEMS_XXX_6 0 115 #define OCTEON_POOL_NELEMS_XXX_7 0 116 117 /* 118 * CVMSEG (``scratch'') memory map 119 */ 120 struct octeon_cvmseg_map { 121 /* 0-3 */ 122 uint64_t csm_xxx_0; 123 uint64_t csm_xxx_1; 124 uint64_t csm_xxx_2; 125 uint64_t csm_pow_intr; 126 127 /* 4-19 */ 128 struct octeon_cvmseg_ether_map { 129 uint64_t csm_ether_fau_req; 130 uint64_t csm_ether_fau_done; 131 uint64_t csm_ether_fau_cmdptr; 132 uint64_t csm_ether_xxx_3; 133 } csm_ether[4/* XXX */]; 134 135 /* 20-32 */ 136 uint64_t xxx_20_32[32 - 20]; 137 } __packed; 138 #define OCTEON_CVMSEG_OFFSET(entry) \ 139 offsetof(struct octeon_cvmseg_map, entry) 140 #define OCTEON_CVMSEG_ETHER_OFFSET(n, entry) \ 141 (offsetof(struct octeon_cvmseg_map, csm_ether) + \ 142 sizeof(struct octeon_cvmseg_ether_map) * (n) + \ 143 offsetof(struct octeon_cvmseg_ether_map, entry)) 144 145 /* 146 * FAU register map 147 * 148 * => FAU registers exist in FAU unit 149 * => devices (PKO) can access these registers 150 * => CPU can read those values after loading them into CVMSEG 151 */ 152 struct octeon_fau_map { 153 struct { 154 /* PKO command index */ 155 uint64_t _fau_map_port_pkocmdidx; 156 /* send requested */ 157 uint64_t _fau_map_port_txreq; 158 /* send completed */ 159 uint64_t _fau_map_port_txdone; 160 /* XXX */ 161 uint64_t _fau_map_port_pad; 162 } __packed _fau_map_port[3]; 163 }; 164 165 /* 166 * POW qos/group map 167 */ 168 169 #define OCTEON_POW_QOS_PIP 0 170 #define OCTEON_POW_QOS_CORE1 1 171 #define OCTEON_POW_QOS_XXX_2 2 172 #define OCTEON_POW_QOS_XXX_3 3 173 #define OCTEON_POW_QOS_XXX_4 4 174 #define OCTEON_POW_QOS_XXX_5 5 175 #define OCTEON_POW_QOS_XXX_6 6 176 #define OCTEON_POW_QOS_XXX_7 7 177 178 #define OCTEON_POW_GROUP_PIP 0 179 #define OCTEON_POW_GROUP_XXX_1 1 180 #define OCTEON_POW_GROUP_XXX_2 2 181 #define OCTEON_POW_GROUP_XXX_3 3 182 #define OCTEON_POW_GROUP_XXX_4 4 183 #define OCTEON_POW_GROUP_XXX_5 5 184 #define OCTEON_POW_GROUP_XXX_6 6 185 #define OCTEON_POW_GROUP_CORE1_SEND 7 186 #define OCTEON_POW_GROUP_CORE1_TASK_0 8 187 #define OCTEON_POW_GROUP_CORE1_TASK_1 9 188 #define OCTEON_POW_GROUP_CORE1_TASK_2 10 189 #define OCTEON_POW_GROUP_CORE1_TASK_3 11 190 #define OCTEON_POW_GROUP_CORE1_TASK_4 12 191 #define OCTEON_POW_GROUP_CORE1_TASK_5 13 192 #define OCTEON_POW_GROUP_CORE1_TASK_6 14 193 #define OCTEON_POW_GROUP_CORE1_TASK_7 15 194 195 /* 196 * Octeon board types known to work with OpenBSD/octeon. 197 * One of the main reasons for keeping this list is to be able to tell which 198 * boards do and do not have octcf(4). Currently the only board not to have octcf(4) 199 * is BOARD_TYPE_UBIQUITI_E100. Sadly, this number is also used by other vendors, but 200 * we don't run on those boards yet. When that time comes, iobus needs extra care for 201 * not blindly attaching octcf(4) on every board. 202 */ 203 #define BOARD_TYPE_SIM 1 204 #define BOARD_TYPE_UBIQUITI_E100 20002 205 206 #if defined(_KERNEL) || defined(_STANDALONE) 207 #define OCTEON_ARGV_MAX 64 208 209 /* Maximum number of cores on <= CN52XX */ 210 #define OCTEON_MAXCPUS 4 211 212 struct boot_desc { 213 uint32_t desc_ver; 214 uint32_t desc_size; 215 uint64_t stack_top; 216 uint64_t heap_start; 217 uint64_t heap_end; 218 uint64_t __unused17; 219 uint64_t __unused16; 220 uint32_t __unused18; 221 uint32_t __unused15; 222 uint32_t __unused14; 223 uint32_t argc; 224 uint32_t argv[OCTEON_ARGV_MAX]; 225 uint32_t flags; 226 uint32_t core_mask; 227 uint32_t dram_size; 228 uint32_t phy_mem_desc_addr; 229 uint32_t debugger_flag_addr; 230 uint32_t eclock; 231 uint32_t __unused10; 232 uint32_t __unused9; 233 uint16_t __unused8; 234 uint8_t __unused7; 235 uint8_t __unused6; 236 uint16_t __unused5; 237 uint8_t __unused4; 238 uint8_t __unused3; 239 uint8_t __unused2[20]; 240 uint8_t __unused1[6]; 241 uint8_t __unused0; 242 uint64_t boot_info_addr; 243 }; 244 245 struct boot_info { 246 uint32_t ver_major; 247 uint32_t ver_minor; 248 uint64_t stack_top; 249 uint64_t heap_start; 250 uint64_t heap_end; 251 uint64_t boot_desc_addr; 252 uint32_t exception_base_addr; 253 uint32_t stack_size; 254 uint32_t flags; 255 uint32_t core_mask; 256 uint32_t dram_size; 257 uint32_t phys_mem_desc_addr; 258 uint32_t debugger_flags_addr; 259 uint32_t eclock; 260 uint32_t dclock; 261 uint32_t __unused0; 262 uint16_t board_type; 263 uint8_t board_rev_major; 264 uint8_t board_rev_minor; 265 uint16_t __unused1; 266 uint8_t __unused2; 267 uint8_t __unused3; 268 char board_serial[20]; 269 uint8_t mac_addr_base[6]; 270 uint8_t mac_addr_count; 271 uint64_t cf_common_addr; 272 uint64_t cf_attr_addr; 273 uint64_t led_display_addr; 274 uint32_t dfaclock; 275 uint32_t config_flags; 276 }; 277 278 extern struct boot_desc *octeon_boot_desc; 279 extern struct boot_info *octeon_boot_info; 280 281 #ifdef _KERNEL 282 /* Device capabilities advertised in boot_info->config_flags */ 283 #define BOOTINFO_CFG_FLAG_PCI_HOST (1ull << 0) 284 #define BOOTINFO_CFG_FLAG_PCI_TARGET (1ull << 1) 285 #define BOOTINFO_CFG_FLAG_DEBUG (1ull << 2) 286 #define BOOTINFO_CFG_FLAG_NO_MAGIC (1ull << 3) 287 288 void octeon_bus_io_init(bus_space_tag_t, void *); 289 void octeon_bus_mem_init(bus_space_tag_t, void *); 290 void octeon_cal_timer(int); 291 void octeon_dma_init(struct octeon_config *); 292 void octeon_intr_init(void); 293 int octeon_get_ethaddr(int, u_int8_t *); 294 295 int octeon_ioclock_speed(void); 296 297 #endif /* _KERNEL */ 298 #endif /* _KERNEL || _STANDALONE */ 299 300 static inline int 301 ffs64(uint64_t val) 302 { 303 int ret; 304 305 __asm volatile ( \ 306 _ASM_PROLOGUE_MIPS64 307 " dclz %0, %1 \n" 308 _ASM_EPILOGUE 309 : "=r"(ret) : "r"(val)); 310 return 64 - ret; 311 } 312 313 static inline int 314 ffs32(uint32_t val) 315 { 316 int ret; 317 318 __asm __volatile ( \ 319 _ASM_PROLOGUE_MIPS64 320 " clz %0, %1 \n" 321 _ASM_EPILOGUE 322 : "=r"(ret) : "r"(val)); 323 return 32 - ret; 324 } 325 326 static inline uint64_t 327 octeon_xkphys_read_8(paddr_t address) 328 { 329 volatile uint64_t *p = 330 (volatile uint64_t *)(PHYS_TO_XKPHYS(address, CCA_NC)); 331 return (*p); 332 } 333 334 #define MIO_BOOT_BIST_STAT 0x00011800000000f8ULL 335 static inline void 336 octeon_xkphys_write_8(paddr_t address, uint64_t value) 337 { 338 *(volatile uint64_t *)(PHYS_TO_XKPHYS(address, CCA_NC)) = value; 339 340 /* 341 * It seems an immediate read is necessary when doing a write to an RSL 342 * register in order to complete the write. 343 * We use MIO_BOOT_BIST_STAT because it's apparently the fastest 344 * write. 345 */ 346 347 /* 348 * XXX 349 * This if would be better writen as: 350 * if ((address & 0xffffff0000000000ULL) == OCTEON_MIO_BOOT_BASE) { 351 * but octeonreg.h can't be included here and we want this inlined 352 * 353 * Note that the SDK masks with 0x7ffff but that doesn't make sense. 354 * This is a physical address. 355 */ 356 if (((address >> 40) & 0xfffff) == (0x118)) { 357 value = *(volatile uint64_t *) 358 (PHYS_TO_XKPHYS(MIO_BOOT_BIST_STAT, CCA_NC)); 359 } 360 } 361 362 static inline void 363 octeon_iobdma_write_8(uint64_t value) 364 { 365 uint64_t addr = 0xffffffffffffa200ULL; 366 367 *(volatile uint64_t *)addr = value; 368 } 369 370 static inline uint64_t 371 octeon_cvmseg_read_8(size_t offset) 372 { 373 return octeon_xkphys_read_8(0xffffffffffff8000ULL + offset); 374 } 375 376 static inline void 377 octeon_cvmseg_write_8(size_t offset, uint64_t value) 378 { 379 octeon_xkphys_write_8(0xffffffffffff8000ULL + offset, value); 380 } 381 382 /* XXX */ 383 static inline uint32_t 384 octeon_disable_interrupt(uint32_t *new) 385 { 386 uint32_t s, tmp; 387 388 __asm volatile ( 389 _ASM_PROLOGUE 390 " mfc0 %[s], $12 \n" 391 " and %[tmp], %[s], ~1 \n" 392 " mtc0 %[tmp], $12 \n" 393 _ASM_EPILOGUE 394 : [s]"=&r"(s), [tmp]"=&r"(tmp)); 395 if (new) 396 *new = tmp; 397 return s; 398 } 399 400 /* XXX */ 401 static inline void 402 octeon_restore_status(uint32_t s) 403 { 404 __asm volatile ( 405 _ASM_PROLOGUE 406 " mtc0 %[s], $12 \n" 407 _ASM_EPILOGUE 408 :: [s]"r"(s)); 409 } 410 411 static inline uint64_t 412 octeon_get_cycles(void) 413 { 414 uint64_t tmp; 415 416 __asm volatile ( 417 _ASM_PROLOGUE_MIPS64 418 " dmfc0 %[tmp], $9, 6 \n" 419 _ASM_EPILOGUE 420 : [tmp]"=&r"(tmp)); 421 return tmp; 422 } 423 424 /* -------------------------------------------------------------------------- */ 425 426 /* ---- event counter */ 427 428 #if defined(OCTEON_ETH_DEBUG) 429 #define OCTEON_EVCNT_INC(sc, name) \ 430 do { (sc)->sc_ev_##name.ev_count++; } while (0) 431 #define OCTEON_EVCNT_ADD(sc, name, n) \ 432 do { (sc)->sc_ev_##name.ev_count += (n); } while (0) 433 #define OCTEON_EVCNT_ATTACH_EVCNTS(sc, entries, devname) \ 434 do { \ 435 int i; \ 436 const struct octeon_evcnt_entry *ee; \ 437 \ 438 for (i = 0; i < (int)nitems(entries); i++) { \ 439 ee = &(entries)[i]; \ 440 evcnt_attach_dynamic( \ 441 (struct evcnt *)((uintptr_t)(sc) + ee->ee_offset), \ 442 ee->ee_type, ee->ee_parent, devname, \ 443 ee->ee_name); \ 444 } \ 445 } while (0) 446 #else 447 #define OCTEON_EVCNT_INC(sc, name) 448 #define OCTEON_EVCNT_ADD(sc, name, n) 449 #define OCTEON_EVCNT_ATTACH_EVCNTS(sc, entries, devname) 450 #endif 451 452 struct octeon_evcnt_entry { 453 size_t ee_offset; 454 int ee_type; 455 struct evcnt *ee_parent; 456 const char *ee_name; 457 }; 458 459 #define OCTEON_EVCNT_ENTRY(_sc_type, _var, _ev_type, _parent, _name) \ 460 { \ 461 .ee_offset = offsetof(_sc_type, sc_ev_##_var), \ 462 .ee_type = EVCNT_TYPE_##_ev_type, \ 463 .ee_parent = _parent, \ 464 .ee_name = _name \ 465 } 466 467 #endif /* _MIPS_OCTEON_OCTEONVAR_H_ */ 468