1 /* $OpenBSD: octeonvar.h,v 1.54 2022/08/29 02:01:18 jsg 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 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #ifndef _MIPS_OCTEON_OCTEONVAR_H_ 34 #define _MIPS_OCTEON_OCTEONVAR_H_ 35 36 #include <machine/bus.h> 37 38 /* XXX elsewhere */ 39 #define _ASM_PROLOGUE \ 40 " .set push \n" \ 41 " .set noreorder \n" 42 #define _ASM_PROLOGUE_MIPS64 \ 43 _ASM_PROLOGUE \ 44 " .set mips64 \n" 45 #define _ASM_PROLOGUE_OCTEON \ 46 _ASM_PROLOGUE \ 47 " .set arch=octeon \n" 48 #define _ASM_EPILOGUE \ 49 " .set pop \n" 50 /* 51 * subbits = __BITS64_GET(XXX, bits); 52 * bits = __BITS64_SET(XXX, subbits); 53 */ 54 #ifndef __BITS64_GET 55 #define __BITS64_GET(name, bits) \ 56 (((uint64_t)(bits) & name) >> name##_SHIFT) 57 #endif 58 #ifndef __BITS64_SET 59 #define __BITS64_SET(name, subbits) \ 60 (((uint64_t)(subbits) << name##_SHIFT) & name) 61 #endif 62 63 struct octeon_config { 64 bus_space_tag_t mc_iobus_bust; 65 bus_space_tag_t mc_bootbus_bust; 66 67 bus_dma_tag_t mc_iobus_dmat; 68 bus_dma_tag_t mc_bootbus_dmat; 69 }; 70 71 #define GPIO_CONFIG_MD_OUTPUT_SEL_MASK (GPIO_CONFIG_MD0 | GPIO_CONFIG_MD1) 72 #define GPIO_CONFIG_MD_USB0_VBUS_CTRL GPIO_CONFIG_MD0 73 #define GPIO_CONFIG_MD_USB1_VBUS_CTRL GPIO_CONFIG_MD1 74 75 /* 76 * FPA map 77 */ 78 79 #define OCTEON_POOL_NO_PKT 0 80 #define OCTEON_POOL_NO_WQE 1 81 #define OCTEON_POOL_NO_CMD 2 82 #define OCTEON_POOL_NO_SG 3 83 #define OCTEON_POOL_NO_XXX_4 4 84 #define OCTEON_POOL_NO_XXX_5 5 85 #define OCTEON_POOL_NO_XXX_6 6 86 #define OCTEON_POOL_NO_DUMP 7 /* FPA debug dump */ 87 88 #define OCTEON_POOL_SIZE_PKT 1920 /* 128 x 15 */ 89 #define OCTEON_POOL_SIZE_WQE 128 /* 128 x 1 */ 90 #define OCTEON_POOL_SIZE_CMD 1024 /* 128 x 8 */ 91 #define OCTEON_POOL_SIZE_SG 128 /* 128 x 1 */ 92 #define OCTEON_POOL_SIZE_XXX_4 0 93 #define OCTEON_POOL_SIZE_XXX_5 0 94 #define OCTEON_POOL_SIZE_XXX_6 0 95 #define OCTEON_POOL_SIZE_XXX_7 0 96 97 #define OCTEON_POOL_NELEMS_PKT 4096 98 #define OCTEON_POOL_NELEMS_WQE 4096 99 #define OCTEON_POOL_NELEMS_CMD 32 100 #define OCTEON_POOL_NELEMS_SG 4096 101 #define OCTEON_POOL_NELEMS_XXX_4 0 102 #define OCTEON_POOL_NELEMS_XXX_5 0 103 #define OCTEON_POOL_NELEMS_XXX_6 0 104 #define OCTEON_POOL_NELEMS_XXX_7 0 105 106 /* 107 * CVMSEG (``scratch'') memory map 108 */ 109 struct octeon_cvmseg_map { 110 uint64_t csm_pow_intr; 111 112 struct octeon_cvmseg_ether_map { 113 uint64_t csm_ether_fau_done; 114 } csm_ether[12/* XXX */]; 115 } __packed; 116 #define OCTEON_CVMSEG_OFFSET(entry) \ 117 offsetof(struct octeon_cvmseg_map, entry) 118 #define OCTEON_CVMSEG_ETHER_OFFSET(n, entry) \ 119 (offsetof(struct octeon_cvmseg_map, csm_ether) + \ 120 sizeof(struct octeon_cvmseg_ether_map) * (n) + \ 121 offsetof(struct octeon_cvmseg_ether_map, entry)) 122 123 /* 124 * FAU register map 125 * 126 * => FAU registers exist in FAU unit 127 * => devices (PKO) can access these registers 128 * => CPU can read those values after loading them into CVMSEG 129 */ 130 struct octeon_fau_map { 131 struct { 132 /* PKO command index */ 133 uint64_t _fau_map_port_pkocmdidx; 134 /* send requested */ 135 uint64_t _fau_map_port_txreq; 136 /* send completed */ 137 uint64_t _fau_map_port_txdone; 138 /* XXX */ 139 uint64_t _fau_map_port_pad; 140 } __packed _fau_map_port[3]; 141 }; 142 143 /* 144 * POW qos/group map 145 */ 146 147 #define OCTEON_POW_QOS_PIP 0 148 #define OCTEON_POW_QOS_CORE1 1 149 #define OCTEON_POW_QOS_XXX_2 2 150 #define OCTEON_POW_QOS_XXX_3 3 151 #define OCTEON_POW_QOS_XXX_4 4 152 #define OCTEON_POW_QOS_XXX_5 5 153 #define OCTEON_POW_QOS_XXX_6 6 154 #define OCTEON_POW_QOS_XXX_7 7 155 156 #define OCTEON_POW_GROUP_MAX 16 157 158 enum cnmac_stat { 159 cnmac_stat_rx_toto_gmx, 160 cnmac_stat_rx_totp_gmx, 161 cnmac_stat_rx_toto_pip, 162 cnmac_stat_rx_totp_pip, 163 cnmac_stat_rx_h64, 164 cnmac_stat_rx_h127, 165 cnmac_stat_rx_h255, 166 cnmac_stat_rx_h511, 167 cnmac_stat_rx_h1023, 168 cnmac_stat_rx_h1518, 169 cnmac_stat_rx_hmax, 170 cnmac_stat_rx_bcast, 171 cnmac_stat_rx_mcast, 172 cnmac_stat_rx_qdpo, 173 cnmac_stat_rx_qdpp, 174 cnmac_stat_rx_fcs, 175 cnmac_stat_rx_frag, 176 cnmac_stat_rx_undersz, 177 cnmac_stat_rx_jabber, 178 cnmac_stat_rx_oversz, 179 cnmac_stat_rx_raw, 180 cnmac_stat_rx_bad, 181 cnmac_stat_rx_drop, 182 cnmac_stat_rx_ctl, 183 cnmac_stat_rx_dmac, 184 cnmac_stat_tx_toto, 185 cnmac_stat_tx_totp, 186 cnmac_stat_tx_hmin, 187 cnmac_stat_tx_h64, 188 cnmac_stat_tx_h127, 189 cnmac_stat_tx_h255, 190 cnmac_stat_tx_h511, 191 cnmac_stat_tx_h1023, 192 cnmac_stat_tx_h1518, 193 cnmac_stat_tx_hmax, 194 cnmac_stat_tx_bcast, 195 cnmac_stat_tx_mcast, 196 cnmac_stat_tx_coll, 197 cnmac_stat_tx_defer, 198 cnmac_stat_tx_scol, 199 cnmac_stat_tx_mcol, 200 cnmac_stat_tx_ctl, 201 cnmac_stat_tx_uflow, 202 cnmac_stat_count 203 }; 204 205 #if defined(_KERNEL) || defined(_STANDALONE) 206 #define OCTEON_ARGV_MAX 64 207 208 /* 209 * OCTEON board types recognized by OpenBSD/octeon. 210 * 211 * It is fine to use BOARD_UNKNOWN when the board does not need 212 * special treatment. 213 */ 214 enum octeon_board { 215 BOARD_UNKNOWN, 216 BOARD_CHECKPOINT_N100, 217 BOARD_CN3010_EVB_HS5, 218 BOARD_DLINK_DSR_500, 219 BOARD_NETGEAR_UTM25, 220 BOARD_RHINOLABS_UTM8, 221 BOARD_UBIQUITI_E100, 222 BOARD_UBIQUITI_E120, 223 BOARD_UBIQUITI_E200, 224 BOARD_UBIQUITI_E220, 225 BOARD_UBIQUITI_E300, 226 BOARD_UBIQUITI_E1000, 227 }; 228 229 struct boot_desc { 230 uint32_t desc_ver; 231 uint32_t desc_size; 232 uint64_t stack_top; 233 uint64_t heap_start; 234 uint64_t heap_end; 235 uint64_t __unused17; 236 uint64_t __unused16; 237 uint32_t __unused18; 238 uint32_t __unused15; 239 uint32_t __unused14; 240 uint32_t argc; 241 uint32_t argv[OCTEON_ARGV_MAX]; 242 uint32_t flags; 243 uint32_t core_mask; 244 uint32_t dram_size; 245 uint32_t phy_mem_desc_addr; 246 uint32_t debugger_flag_addr; 247 uint32_t eclock; 248 uint32_t __unused10; 249 uint32_t __unused9; 250 uint16_t __unused8; 251 uint8_t __unused7; 252 uint8_t __unused6; 253 uint16_t __unused5; 254 uint8_t __unused4; 255 uint8_t __unused3; 256 uint8_t __unused2[20]; 257 uint8_t __unused1[6]; 258 uint8_t __unused0; 259 uint64_t boot_info_addr; 260 }; 261 262 struct boot_info { 263 uint32_t ver_major; 264 uint32_t ver_minor; 265 uint64_t stack_top; 266 uint64_t heap_start; 267 uint64_t heap_end; 268 uint64_t boot_desc_addr; 269 uint32_t exception_base_addr; 270 uint32_t stack_size; 271 uint32_t flags; 272 uint32_t core_mask; 273 uint32_t dram_size; 274 uint32_t phys_mem_desc_addr; 275 uint32_t debugger_flags_addr; 276 uint32_t eclock; 277 uint32_t dclock; 278 uint32_t __unused0; 279 uint16_t board_type; 280 uint8_t board_rev_major; 281 uint8_t board_rev_minor; 282 uint16_t __unused1; 283 uint8_t __unused2; 284 uint8_t __unused3; 285 char board_serial[20]; 286 uint8_t mac_addr_base[6]; 287 uint8_t mac_addr_count; 288 uint64_t cf_common_addr; 289 uint64_t cf_attr_addr; 290 uint64_t led_display_addr; 291 uint32_t dfaclock; 292 uint32_t config_flags; 293 /* The fields below are available when ver_minor >= 3. */ 294 uint64_t fdt_addr; 295 }; 296 297 struct octeon_bootmem_desc { 298 uint32_t lock; 299 uint32_t flags; 300 uint64_t head_addr; 301 uint32_t major_version; 302 uint32_t minor_version; 303 uint64_t app_data_addr; 304 uint64_t app_data_size; 305 uint32_t named_block_num_blocks; 306 uint32_t named_block_name_len; 307 uint64_t named_block_array_addr; 308 }; 309 310 struct octeon_bootmem_block { 311 uint64_t next; 312 uint64_t size; 313 }; 314 315 extern enum octeon_board octeon_board; 316 extern struct boot_desc *octeon_boot_desc; 317 extern struct boot_info *octeon_boot_info; 318 319 #ifdef _KERNEL 320 /* Device capabilities advertised in boot_info->config_flags */ 321 #define BOOTINFO_CFG_FLAG_PCI_HOST (1ull << 0) 322 #define BOOTINFO_CFG_FLAG_PCI_TARGET (1ull << 1) 323 #define BOOTINFO_CFG_FLAG_DEBUG (1ull << 2) 324 #define BOOTINFO_CFG_FLAG_NO_MAGIC (1ull << 3) 325 326 #define BOOTMEM_BLOCK_ALIGN 16 327 #define BOOTMEM_BLOCK_MASK (BOOTMEM_BLOCK_ALIGN - 1) 328 #define BOOTMEM_BLOCK_MIN_SIZE 16 329 330 int bootmem_alloc_region(paddr_t, size_t); 331 void bootmem_free(paddr_t, size_t); 332 333 int octeon_ioclock_speed(void); 334 335 #endif /* _KERNEL */ 336 #endif /* _KERNEL || _STANDALONE */ 337 338 static inline int 339 ffs64(uint64_t val) 340 { 341 int ret; 342 343 __asm volatile ( \ 344 _ASM_PROLOGUE_MIPS64 345 " dclz %0, %1 \n" 346 _ASM_EPILOGUE 347 : "=r"(ret) : "r"(val)); 348 return 64 - ret; 349 } 350 351 static inline int 352 ffs32(uint32_t val) 353 { 354 int ret; 355 356 __asm volatile ( \ 357 _ASM_PROLOGUE_MIPS64 358 " clz %0, %1 \n" 359 _ASM_EPILOGUE 360 : "=r"(ret) : "r"(val)); 361 return 32 - ret; 362 } 363 364 static inline uint64_t 365 octeon_xkphys_read_8(paddr_t address) 366 { 367 volatile uint64_t *p = 368 (volatile uint64_t *)(PHYS_TO_XKPHYS(address, CCA_NC)); 369 return (*p); 370 } 371 372 #define MIO_BOOT_BIST_STAT 0x00011800000000f8ULL 373 static inline void 374 octeon_xkphys_write_8(paddr_t address, uint64_t value) 375 { 376 *(volatile uint64_t *)(PHYS_TO_XKPHYS(address, CCA_NC)) = value; 377 378 /* 379 * It seems an immediate read is necessary when doing a write to an RSL 380 * register in order to complete the write. 381 * We use MIO_BOOT_BIST_STAT because it's apparently the fastest 382 * write. 383 */ 384 385 /* 386 * XXX 387 * This if would be better written as: 388 * if ((address & 0xffffff0000000000ULL) == OCTEON_MIO_BOOT_BASE) { 389 * but octeonreg.h can't be included here and we want this inlined 390 * 391 * Note that the SDK masks with 0x7ffff but that doesn't make sense. 392 * This is a physical address. 393 */ 394 if (((address >> 40) & 0xfffff) == (0x118)) { 395 value = *(volatile uint64_t *) 396 (PHYS_TO_XKPHYS(MIO_BOOT_BIST_STAT, CCA_NC)); 397 } 398 } 399 400 static inline void 401 octeon_iobdma_write_8(uint64_t value) 402 { 403 uint64_t addr = 0xffffffffffffa200ULL; 404 405 *(volatile uint64_t *)addr = value; 406 } 407 408 static inline void 409 octeon_lmtdma_write_8(off_t offset, uint64_t value) 410 { 411 *(volatile uint64_t *)(0xffffffffffffa400ULL + offset) = value; 412 } 413 414 static inline uint64_t 415 octeon_cvmseg_read_8(size_t offset) 416 { 417 return *(volatile uint64_t *)(0xffffffffffff8000ULL + offset); 418 } 419 420 static inline void 421 octeon_cvmseg_write_8(size_t offset, uint64_t value) 422 { 423 *(volatile uint64_t *)(0xffffffffffff8000ULL + offset) = value; 424 } 425 426 static inline uint32_t 427 octeon_get_coreid(void) 428 { 429 uint32_t coreid; 430 431 __asm volatile ( 432 _ASM_PROLOGUE_OCTEON 433 " rdhwr %0, $0\n" 434 _ASM_EPILOGUE 435 : "=r" (coreid)); 436 return coreid; 437 } 438 439 static inline uint64_t 440 octeon_get_cycles(void) 441 { 442 uint64_t tmp; 443 444 __asm volatile ( 445 _ASM_PROLOGUE_MIPS64 446 " dmfc0 %[tmp], $9, 6 \n" 447 _ASM_EPILOGUE 448 : [tmp]"=&r"(tmp)); 449 return tmp; 450 } 451 452 static inline uint64_t 453 octeon_get_cvmctl(void) 454 { 455 uint64_t tmp; 456 457 __asm volatile ( 458 _ASM_PROLOGUE_OCTEON 459 " dmfc0 %[tmp], $9, 7 \n" 460 _ASM_EPILOGUE 461 : [tmp]"=r"(tmp)); 462 return tmp; 463 } 464 465 static inline uint64_t 466 octeon_get_cvmmemctl(void) 467 { 468 uint64_t tmp; 469 470 __asm volatile ( 471 _ASM_PROLOGUE_OCTEON 472 " dmfc0 %[tmp], $11, 7 \n" 473 _ASM_EPILOGUE 474 : [tmp]"=r"(tmp)); 475 return tmp; 476 } 477 478 static inline void 479 octeon_set_cvmmemctl(uint64_t val) 480 { 481 __asm volatile ( 482 _ASM_PROLOGUE_OCTEON 483 " dmtc0 %[tmp], $11, 7 \n" 484 _ASM_EPILOGUE 485 : : [tmp]"r"(val) : "memory"); 486 } 487 488 static inline void 489 octeon_synciobdma(void) 490 { 491 __asm volatile ( 492 _ASM_PROLOGUE_OCTEON 493 " synciobdma\n" 494 _ASM_EPILOGUE 495 : : : "memory"); 496 } 497 498 #endif /* _MIPS_OCTEON_OCTEONVAR_H_ */ 499