1 /* $OpenBSD: octeonvar.h,v 1.48 2020/06/27 01:01:36 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 /* 159 * Octeon board types known to work with OpenBSD/octeon. 160 * NB: BOARD_TYPE_UBIQUITI_E100 is also used by other vendors, but we don't run 161 * on those boards yet. 162 */ 163 #define BOARD_TYPE_CN3010_EVB_HS5 11 164 #define BOARD_TYPE_UBIQUITI_E100 20002 165 #define BOARD_TYPE_UBIQUITI_E200 20003 166 #define BOARD_TYPE_UBIQUITI_E120 20004 167 #define BOARD_TYPE_UBIQUITI_E220 20005 168 #define BOARD_TYPE_UBIQUITI_E1000 20010 169 #define BOARD_TYPE_RHINOLABS_SHASTA 20012 170 #define BOARD_TYPE_DSR_500 20015 171 #define BOARD_TYPE_UBIQUITI_E300 20300 172 173 #if defined(_KERNEL) || defined(_STANDALONE) 174 #define OCTEON_ARGV_MAX 64 175 176 struct boot_desc { 177 uint32_t desc_ver; 178 uint32_t desc_size; 179 uint64_t stack_top; 180 uint64_t heap_start; 181 uint64_t heap_end; 182 uint64_t __unused17; 183 uint64_t __unused16; 184 uint32_t __unused18; 185 uint32_t __unused15; 186 uint32_t __unused14; 187 uint32_t argc; 188 uint32_t argv[OCTEON_ARGV_MAX]; 189 uint32_t flags; 190 uint32_t core_mask; 191 uint32_t dram_size; 192 uint32_t phy_mem_desc_addr; 193 uint32_t debugger_flag_addr; 194 uint32_t eclock; 195 uint32_t __unused10; 196 uint32_t __unused9; 197 uint16_t __unused8; 198 uint8_t __unused7; 199 uint8_t __unused6; 200 uint16_t __unused5; 201 uint8_t __unused4; 202 uint8_t __unused3; 203 uint8_t __unused2[20]; 204 uint8_t __unused1[6]; 205 uint8_t __unused0; 206 uint64_t boot_info_addr; 207 }; 208 209 struct boot_info { 210 uint32_t ver_major; 211 uint32_t ver_minor; 212 uint64_t stack_top; 213 uint64_t heap_start; 214 uint64_t heap_end; 215 uint64_t boot_desc_addr; 216 uint32_t exception_base_addr; 217 uint32_t stack_size; 218 uint32_t flags; 219 uint32_t core_mask; 220 uint32_t dram_size; 221 uint32_t phys_mem_desc_addr; 222 uint32_t debugger_flags_addr; 223 uint32_t eclock; 224 uint32_t dclock; 225 uint32_t __unused0; 226 uint16_t board_type; 227 uint8_t board_rev_major; 228 uint8_t board_rev_minor; 229 uint16_t __unused1; 230 uint8_t __unused2; 231 uint8_t __unused3; 232 char board_serial[20]; 233 uint8_t mac_addr_base[6]; 234 uint8_t mac_addr_count; 235 uint64_t cf_common_addr; 236 uint64_t cf_attr_addr; 237 uint64_t led_display_addr; 238 uint32_t dfaclock; 239 uint32_t config_flags; 240 /* The fields below are available when ver_minor >= 3. */ 241 uint64_t fdt_addr; 242 }; 243 244 struct octeon_bootmem_desc { 245 uint32_t lock; 246 uint32_t flags; 247 uint64_t head_addr; 248 uint32_t major_version; 249 uint32_t minor_version; 250 uint64_t app_data_addr; 251 uint64_t app_data_size; 252 uint32_t named_block_num_blocks; 253 uint32_t named_block_name_len; 254 uint64_t named_block_array_addr; 255 }; 256 257 struct octeon_bootmem_block { 258 uint64_t next; 259 uint64_t size; 260 }; 261 262 extern struct boot_desc *octeon_boot_desc; 263 extern struct boot_info *octeon_boot_info; 264 265 #ifdef _KERNEL 266 /* Device capabilities advertised in boot_info->config_flags */ 267 #define BOOTINFO_CFG_FLAG_PCI_HOST (1ull << 0) 268 #define BOOTINFO_CFG_FLAG_PCI_TARGET (1ull << 1) 269 #define BOOTINFO_CFG_FLAG_DEBUG (1ull << 2) 270 #define BOOTINFO_CFG_FLAG_NO_MAGIC (1ull << 3) 271 272 #define BOOTMEM_BLOCK_ALIGN 16 273 #define BOOTMEM_BLOCK_MASK (BOOTMEM_BLOCK_ALIGN - 1) 274 #define BOOTMEM_BLOCK_MIN_SIZE 16 275 276 int bootmem_alloc_region(paddr_t, size_t); 277 void bootmem_free(paddr_t, size_t); 278 279 int octeon_ioclock_speed(void); 280 281 #endif /* _KERNEL */ 282 #endif /* _KERNEL || _STANDALONE */ 283 284 static inline int 285 ffs64(uint64_t val) 286 { 287 int ret; 288 289 __asm volatile ( \ 290 _ASM_PROLOGUE_MIPS64 291 " dclz %0, %1 \n" 292 _ASM_EPILOGUE 293 : "=r"(ret) : "r"(val)); 294 return 64 - ret; 295 } 296 297 static inline int 298 ffs32(uint32_t val) 299 { 300 int ret; 301 302 __asm __volatile ( \ 303 _ASM_PROLOGUE_MIPS64 304 " clz %0, %1 \n" 305 _ASM_EPILOGUE 306 : "=r"(ret) : "r"(val)); 307 return 32 - ret; 308 } 309 310 static inline uint64_t 311 octeon_xkphys_read_8(paddr_t address) 312 { 313 volatile uint64_t *p = 314 (volatile uint64_t *)(PHYS_TO_XKPHYS(address, CCA_NC)); 315 return (*p); 316 } 317 318 #define MIO_BOOT_BIST_STAT 0x00011800000000f8ULL 319 static inline void 320 octeon_xkphys_write_8(paddr_t address, uint64_t value) 321 { 322 *(volatile uint64_t *)(PHYS_TO_XKPHYS(address, CCA_NC)) = value; 323 324 /* 325 * It seems an immediate read is necessary when doing a write to an RSL 326 * register in order to complete the write. 327 * We use MIO_BOOT_BIST_STAT because it's apparently the fastest 328 * write. 329 */ 330 331 /* 332 * XXX 333 * This if would be better writen as: 334 * if ((address & 0xffffff0000000000ULL) == OCTEON_MIO_BOOT_BASE) { 335 * but octeonreg.h can't be included here and we want this inlined 336 * 337 * Note that the SDK masks with 0x7ffff but that doesn't make sense. 338 * This is a physical address. 339 */ 340 if (((address >> 40) & 0xfffff) == (0x118)) { 341 value = *(volatile uint64_t *) 342 (PHYS_TO_XKPHYS(MIO_BOOT_BIST_STAT, CCA_NC)); 343 } 344 } 345 346 static inline void 347 octeon_iobdma_write_8(uint64_t value) 348 { 349 uint64_t addr = 0xffffffffffffa200ULL; 350 351 *(volatile uint64_t *)addr = value; 352 } 353 354 static inline void 355 octeon_lmtdma_write_8(off_t offset, uint64_t value) 356 { 357 *(volatile uint64_t *)(0xffffffffffffa400ULL + offset) = value; 358 } 359 360 static inline uint64_t 361 octeon_cvmseg_read_8(size_t offset) 362 { 363 return *(volatile uint64_t *)(0xffffffffffff8000ULL + offset); 364 } 365 366 static inline void 367 octeon_cvmseg_write_8(size_t offset, uint64_t value) 368 { 369 *(volatile uint64_t *)(0xffffffffffff8000ULL + offset) = value; 370 } 371 372 static inline uint32_t 373 octeon_get_coreid(void) 374 { 375 uint32_t coreid; 376 377 __asm volatile ( 378 _ASM_PROLOGUE_OCTEON 379 " rdhwr %0, $0\n" 380 _ASM_EPILOGUE 381 : "=r" (coreid)); 382 return coreid; 383 } 384 385 static inline uint64_t 386 octeon_get_cycles(void) 387 { 388 uint64_t tmp; 389 390 __asm volatile ( 391 _ASM_PROLOGUE_MIPS64 392 " dmfc0 %[tmp], $9, 6 \n" 393 _ASM_EPILOGUE 394 : [tmp]"=&r"(tmp)); 395 return tmp; 396 } 397 398 static inline uint64_t 399 octeon_get_cvmctl(void) 400 { 401 uint64_t tmp; 402 403 __asm volatile ( 404 _ASM_PROLOGUE_OCTEON 405 " dmfc0 %[tmp], $9, 7 \n" 406 _ASM_EPILOGUE 407 : [tmp]"=r"(tmp)); 408 return tmp; 409 } 410 411 static inline uint64_t 412 octeon_get_cvmmemctl(void) 413 { 414 uint64_t tmp; 415 416 __asm volatile ( 417 _ASM_PROLOGUE_OCTEON 418 " dmfc0 %[tmp], $11, 7 \n" 419 _ASM_EPILOGUE 420 : [tmp]"=r"(tmp)); 421 return tmp; 422 } 423 424 static inline void 425 octeon_set_cvmmemctl(uint64_t val) 426 { 427 __asm volatile ( 428 _ASM_PROLOGUE_OCTEON 429 " dmtc0 %[tmp], $11, 7 \n" 430 _ASM_EPILOGUE 431 : : [tmp]"r"(val) : "memory"); 432 } 433 434 static inline void 435 octeon_synciobdma(void) 436 { 437 __asm volatile ( 438 _ASM_PROLOGUE_OCTEON 439 " synciobdma\n" 440 _ASM_EPILOGUE 441 : : : "memory"); 442 } 443 444 #endif /* _MIPS_OCTEON_OCTEONVAR_H_ */ 445