Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

MIPS: Add Cavium OCTEON processor support files to arch/mips/cavium-octeon/executive and asm/octeon.

These files are used to coordinate resource sharing between all of
the programs running on the OCTEON SOC. The OCTEON processor has many
CPU cores (current parts have up to 16, but more are possible). It
also has a variety of on-chip hardware blocks for things like network
acceleration, encryption and RAID.

One typical configuration is to run Linux on several of the CPU cores,
and other dedicated applications on the other cores.

Resource allocation between the various programs running on the system
(Linux kernel and other dedicated applications) needs to be
coordinated. The code we use to do this we call the 'executive'. All
of this resource allocation and sharing code is gathered together in
the executive directory.

Included in the patch set are the following files:

cvmx-bootmem.c and cvmx-sysinfo.c -- Coordinate memory allocation.
All memory used by the Linux kernel is obtained here at boot time.

cvmx-l2c.c -- Coordinates operations on the shared level 2 cache.

octeon-model.c -- Probes chip capabilities and version.

The corresponding headers are in asm/octeon.

Signed-off-by: Tomaso Paoletti <tpaoletti@caviumnetworks.com>
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

create mode 100644 arch/mips/cavium-octeon/executive/Makefile
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-bootmem.c
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-l2c.c
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-sysinfo.c
create mode 100644 arch/mips/cavium-octeon/executive/octeon-model.c
create mode 100644 arch/mips/include/asm/octeon/cvmx-asm.h
create mode 100644 arch/mips/include/asm/octeon/cvmx-bootinfo.h
create mode 100644 arch/mips/include/asm/octeon/cvmx-bootmem.h
create mode 100644 arch/mips/include/asm/octeon/cvmx-l2c.h
create mode 100644 arch/mips/include/asm/octeon/cvmx-packet.h
create mode 100644 arch/mips/include/asm/octeon/cvmx-spinlock.h
create mode 100644 arch/mips/include/asm/octeon/cvmx-sysinfo.h
create mode 100644 arch/mips/include/asm/octeon/cvmx.h
create mode 100644 arch/mips/include/asm/octeon/octeon-feature.h
create mode 100644 arch/mips/include/asm/octeon/octeon-model.h

authored by

David Daney and committed by
Ralf Baechle
58f07778 54293ec3

+4200
+13
arch/mips/cavium-octeon/executive/Makefile
··· 1 + # 2 + # Makefile for the Cavium Octeon specific kernel interface routines 3 + # under Linux. 4 + # 5 + # This file is subject to the terms and conditions of the GNU General Public 6 + # License. See the file "COPYING" in the main directory of this archive 7 + # for more details. 8 + # 9 + # Copyright (C) 2005-2008 Cavium Networks 10 + # 11 + 12 + obj-y += cvmx-bootmem.o cvmx-l2c.o cvmx-sysinfo.o octeon-model.o 13 +
+586
arch/mips/cavium-octeon/executive/cvmx-bootmem.c
··· 1 + /***********************license start*************** 2 + * Author: Cavium Networks 3 + * 4 + * Contact: support@caviumnetworks.com 5 + * This file is part of the OCTEON SDK 6 + * 7 + * Copyright (c) 2003-2008 Cavium Networks 8 + * 9 + * This file is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License, Version 2, as 11 + * published by the Free Software Foundation. 12 + * 13 + * This file is distributed in the hope that it will be useful, but 14 + * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 15 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 16 + * NONINFRINGEMENT. See the GNU General Public License for more 17 + * details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with this file; if not, write to the Free Software 21 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 + * or visit http://www.gnu.org/licenses/. 23 + * 24 + * This file may also be available under a different license from Cavium. 25 + * Contact Cavium Networks for more information 26 + ***********************license end**************************************/ 27 + 28 + /* 29 + * Simple allocate only memory allocator. Used to allocate memory at 30 + * application start time. 31 + */ 32 + 33 + #include <linux/kernel.h> 34 + 35 + #include <asm/octeon/cvmx.h> 36 + #include <asm/octeon/cvmx-spinlock.h> 37 + #include <asm/octeon/cvmx-bootmem.h> 38 + 39 + /*#define DEBUG */ 40 + 41 + 42 + static struct cvmx_bootmem_desc *cvmx_bootmem_desc; 43 + 44 + /* See header file for descriptions of functions */ 45 + 46 + /* 47 + * Wrapper functions are provided for reading/writing the size and 48 + * next block values as these may not be directly addressible (in 32 49 + * bit applications, for instance.) Offsets of data elements in 50 + * bootmem list, must match cvmx_bootmem_block_header_t. 51 + */ 52 + #define NEXT_OFFSET 0 53 + #define SIZE_OFFSET 8 54 + 55 + static void cvmx_bootmem_phy_set_size(uint64_t addr, uint64_t size) 56 + { 57 + cvmx_write64_uint64((addr + SIZE_OFFSET) | (1ull << 63), size); 58 + } 59 + 60 + static void cvmx_bootmem_phy_set_next(uint64_t addr, uint64_t next) 61 + { 62 + cvmx_write64_uint64((addr + NEXT_OFFSET) | (1ull << 63), next); 63 + } 64 + 65 + static uint64_t cvmx_bootmem_phy_get_size(uint64_t addr) 66 + { 67 + return cvmx_read64_uint64((addr + SIZE_OFFSET) | (1ull << 63)); 68 + } 69 + 70 + static uint64_t cvmx_bootmem_phy_get_next(uint64_t addr) 71 + { 72 + return cvmx_read64_uint64((addr + NEXT_OFFSET) | (1ull << 63)); 73 + } 74 + 75 + void *cvmx_bootmem_alloc_range(uint64_t size, uint64_t alignment, 76 + uint64_t min_addr, uint64_t max_addr) 77 + { 78 + int64_t address; 79 + address = 80 + cvmx_bootmem_phy_alloc(size, min_addr, max_addr, alignment, 0); 81 + 82 + if (address > 0) 83 + return cvmx_phys_to_ptr(address); 84 + else 85 + return NULL; 86 + } 87 + 88 + void *cvmx_bootmem_alloc_address(uint64_t size, uint64_t address, 89 + uint64_t alignment) 90 + { 91 + return cvmx_bootmem_alloc_range(size, alignment, address, 92 + address + size); 93 + } 94 + 95 + void *cvmx_bootmem_alloc(uint64_t size, uint64_t alignment) 96 + { 97 + return cvmx_bootmem_alloc_range(size, alignment, 0, 0); 98 + } 99 + 100 + int cvmx_bootmem_free_named(char *name) 101 + { 102 + return cvmx_bootmem_phy_named_block_free(name, 0); 103 + } 104 + 105 + struct cvmx_bootmem_named_block_desc *cvmx_bootmem_find_named_block(char *name) 106 + { 107 + return cvmx_bootmem_phy_named_block_find(name, 0); 108 + } 109 + 110 + void cvmx_bootmem_lock(void) 111 + { 112 + cvmx_spinlock_lock((cvmx_spinlock_t *) &(cvmx_bootmem_desc->lock)); 113 + } 114 + 115 + void cvmx_bootmem_unlock(void) 116 + { 117 + cvmx_spinlock_unlock((cvmx_spinlock_t *) &(cvmx_bootmem_desc->lock)); 118 + } 119 + 120 + int cvmx_bootmem_init(void *mem_desc_ptr) 121 + { 122 + /* Here we set the global pointer to the bootmem descriptor 123 + * block. This pointer will be used directly, so we will set 124 + * it up to be directly usable by the application. It is set 125 + * up as follows for the various runtime/ABI combinations: 126 + * 127 + * Linux 64 bit: Set XKPHYS bit 128 + * Linux 32 bit: use mmap to create mapping, use virtual address 129 + * CVMX 64 bit: use physical address directly 130 + * CVMX 32 bit: use physical address directly 131 + * 132 + * Note that the CVMX environment assumes the use of 1-1 TLB 133 + * mappings so that the physical addresses can be used 134 + * directly 135 + */ 136 + if (!cvmx_bootmem_desc) { 137 + #if defined(CVMX_ABI_64) 138 + /* Set XKPHYS bit */ 139 + cvmx_bootmem_desc = cvmx_phys_to_ptr(CAST64(mem_desc_ptr)); 140 + #else 141 + cvmx_bootmem_desc = (struct cvmx_bootmem_desc *) mem_desc_ptr; 142 + #endif 143 + } 144 + 145 + return 0; 146 + } 147 + 148 + /* 149 + * The cvmx_bootmem_phy* functions below return 64 bit physical 150 + * addresses, and expose more features that the cvmx_bootmem_functions 151 + * above. These are required for full memory space access in 32 bit 152 + * applications, as well as for using some advance features. Most 153 + * applications should not need to use these. 154 + */ 155 + 156 + int64_t cvmx_bootmem_phy_alloc(uint64_t req_size, uint64_t address_min, 157 + uint64_t address_max, uint64_t alignment, 158 + uint32_t flags) 159 + { 160 + 161 + uint64_t head_addr; 162 + uint64_t ent_addr; 163 + /* points to previous list entry, NULL current entry is head of list */ 164 + uint64_t prev_addr = 0; 165 + uint64_t new_ent_addr = 0; 166 + uint64_t desired_min_addr; 167 + 168 + #ifdef DEBUG 169 + cvmx_dprintf("cvmx_bootmem_phy_alloc: req_size: 0x%llx, " 170 + "min_addr: 0x%llx, max_addr: 0x%llx, align: 0x%llx\n", 171 + (unsigned long long)req_size, 172 + (unsigned long long)address_min, 173 + (unsigned long long)address_max, 174 + (unsigned long long)alignment); 175 + #endif 176 + 177 + if (cvmx_bootmem_desc->major_version > 3) { 178 + cvmx_dprintf("ERROR: Incompatible bootmem descriptor " 179 + "version: %d.%d at addr: %p\n", 180 + (int)cvmx_bootmem_desc->major_version, 181 + (int)cvmx_bootmem_desc->minor_version, 182 + cvmx_bootmem_desc); 183 + goto error_out; 184 + } 185 + 186 + /* 187 + * Do a variety of checks to validate the arguments. The 188 + * allocator code will later assume that these checks have 189 + * been made. We validate that the requested constraints are 190 + * not self-contradictory before we look through the list of 191 + * available memory. 192 + */ 193 + 194 + /* 0 is not a valid req_size for this allocator */ 195 + if (!req_size) 196 + goto error_out; 197 + 198 + /* Round req_size up to mult of minimum alignment bytes */ 199 + req_size = (req_size + (CVMX_BOOTMEM_ALIGNMENT_SIZE - 1)) & 200 + ~(CVMX_BOOTMEM_ALIGNMENT_SIZE - 1); 201 + 202 + /* 203 + * Convert !0 address_min and 0 address_max to special case of 204 + * range that specifies an exact memory block to allocate. Do 205 + * this before other checks and adjustments so that this 206 + * tranformation will be validated. 207 + */ 208 + if (address_min && !address_max) 209 + address_max = address_min + req_size; 210 + else if (!address_min && !address_max) 211 + address_max = ~0ull; /* If no limits given, use max limits */ 212 + 213 + 214 + /* 215 + * Enforce minimum alignment (this also keeps the minimum free block 216 + * req_size the same as the alignment req_size. 217 + */ 218 + if (alignment < CVMX_BOOTMEM_ALIGNMENT_SIZE) 219 + alignment = CVMX_BOOTMEM_ALIGNMENT_SIZE; 220 + 221 + /* 222 + * Adjust address minimum based on requested alignment (round 223 + * up to meet alignment). Do this here so we can reject 224 + * impossible requests up front. (NOP for address_min == 0) 225 + */ 226 + if (alignment) 227 + address_min = __ALIGN_MASK(address_min, (alignment - 1)); 228 + 229 + /* 230 + * Reject inconsistent args. We have adjusted these, so this 231 + * may fail due to our internal changes even if this check 232 + * would pass for the values the user supplied. 233 + */ 234 + if (req_size > address_max - address_min) 235 + goto error_out; 236 + 237 + /* Walk through the list entries - first fit found is returned */ 238 + 239 + if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING)) 240 + cvmx_bootmem_lock(); 241 + head_addr = cvmx_bootmem_desc->head_addr; 242 + ent_addr = head_addr; 243 + for (; ent_addr; 244 + prev_addr = ent_addr, 245 + ent_addr = cvmx_bootmem_phy_get_next(ent_addr)) { 246 + uint64_t usable_base, usable_max; 247 + uint64_t ent_size = cvmx_bootmem_phy_get_size(ent_addr); 248 + 249 + if (cvmx_bootmem_phy_get_next(ent_addr) 250 + && ent_addr > cvmx_bootmem_phy_get_next(ent_addr)) { 251 + cvmx_dprintf("Internal bootmem_alloc() error: ent: " 252 + "0x%llx, next: 0x%llx\n", 253 + (unsigned long long)ent_addr, 254 + (unsigned long long) 255 + cvmx_bootmem_phy_get_next(ent_addr)); 256 + goto error_out; 257 + } 258 + 259 + /* 260 + * Determine if this is an entry that can satisify the 261 + * request Check to make sure entry is large enough to 262 + * satisfy request. 263 + */ 264 + usable_base = 265 + __ALIGN_MASK(max(address_min, ent_addr), alignment - 1); 266 + usable_max = min(address_max, ent_addr + ent_size); 267 + /* 268 + * We should be able to allocate block at address 269 + * usable_base. 270 + */ 271 + 272 + desired_min_addr = usable_base; 273 + /* 274 + * Determine if request can be satisfied from the 275 + * current entry. 276 + */ 277 + if (!((ent_addr + ent_size) > usable_base 278 + && ent_addr < address_max 279 + && req_size <= usable_max - usable_base)) 280 + continue; 281 + /* 282 + * We have found an entry that has room to satisfy the 283 + * request, so allocate it from this entry. If end 284 + * CVMX_BOOTMEM_FLAG_END_ALLOC set, then allocate from 285 + * the end of this block rather than the beginning. 286 + */ 287 + if (flags & CVMX_BOOTMEM_FLAG_END_ALLOC) { 288 + desired_min_addr = usable_max - req_size; 289 + /* 290 + * Align desired address down to required 291 + * alignment. 292 + */ 293 + desired_min_addr &= ~(alignment - 1); 294 + } 295 + 296 + /* Match at start of entry */ 297 + if (desired_min_addr == ent_addr) { 298 + if (req_size < ent_size) { 299 + /* 300 + * big enough to create a new block 301 + * from top portion of block. 302 + */ 303 + new_ent_addr = ent_addr + req_size; 304 + cvmx_bootmem_phy_set_next(new_ent_addr, 305 + cvmx_bootmem_phy_get_next(ent_addr)); 306 + cvmx_bootmem_phy_set_size(new_ent_addr, 307 + ent_size - 308 + req_size); 309 + 310 + /* 311 + * Adjust next pointer as following 312 + * code uses this. 313 + */ 314 + cvmx_bootmem_phy_set_next(ent_addr, 315 + new_ent_addr); 316 + } 317 + 318 + /* 319 + * adjust prev ptr or head to remove this 320 + * entry from list. 321 + */ 322 + if (prev_addr) 323 + cvmx_bootmem_phy_set_next(prev_addr, 324 + cvmx_bootmem_phy_get_next(ent_addr)); 325 + else 326 + /* 327 + * head of list being returned, so 328 + * update head ptr. 329 + */ 330 + cvmx_bootmem_desc->head_addr = 331 + cvmx_bootmem_phy_get_next(ent_addr); 332 + 333 + if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING)) 334 + cvmx_bootmem_unlock(); 335 + return desired_min_addr; 336 + } 337 + /* 338 + * block returned doesn't start at beginning of entry, 339 + * so we know that we will be splitting a block off 340 + * the front of this one. Create a new block from the 341 + * beginning, add to list, and go to top of loop 342 + * again. 343 + * 344 + * create new block from high portion of 345 + * block, so that top block starts at desired 346 + * addr. 347 + */ 348 + new_ent_addr = desired_min_addr; 349 + cvmx_bootmem_phy_set_next(new_ent_addr, 350 + cvmx_bootmem_phy_get_next 351 + (ent_addr)); 352 + cvmx_bootmem_phy_set_size(new_ent_addr, 353 + cvmx_bootmem_phy_get_size 354 + (ent_addr) - 355 + (desired_min_addr - 356 + ent_addr)); 357 + cvmx_bootmem_phy_set_size(ent_addr, 358 + desired_min_addr - ent_addr); 359 + cvmx_bootmem_phy_set_next(ent_addr, new_ent_addr); 360 + /* Loop again to handle actual alloc from new block */ 361 + } 362 + error_out: 363 + /* We didn't find anything, so return error */ 364 + if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING)) 365 + cvmx_bootmem_unlock(); 366 + return -1; 367 + } 368 + 369 + int __cvmx_bootmem_phy_free(uint64_t phy_addr, uint64_t size, uint32_t flags) 370 + { 371 + uint64_t cur_addr; 372 + uint64_t prev_addr = 0; /* zero is invalid */ 373 + int retval = 0; 374 + 375 + #ifdef DEBUG 376 + cvmx_dprintf("__cvmx_bootmem_phy_free addr: 0x%llx, size: 0x%llx\n", 377 + (unsigned long long)phy_addr, (unsigned long long)size); 378 + #endif 379 + if (cvmx_bootmem_desc->major_version > 3) { 380 + cvmx_dprintf("ERROR: Incompatible bootmem descriptor " 381 + "version: %d.%d at addr: %p\n", 382 + (int)cvmx_bootmem_desc->major_version, 383 + (int)cvmx_bootmem_desc->minor_version, 384 + cvmx_bootmem_desc); 385 + return 0; 386 + } 387 + 388 + /* 0 is not a valid size for this allocator */ 389 + if (!size) 390 + return 0; 391 + 392 + if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING)) 393 + cvmx_bootmem_lock(); 394 + cur_addr = cvmx_bootmem_desc->head_addr; 395 + if (cur_addr == 0 || phy_addr < cur_addr) { 396 + /* add at front of list - special case with changing head ptr */ 397 + if (cur_addr && phy_addr + size > cur_addr) 398 + goto bootmem_free_done; /* error, overlapping section */ 399 + else if (phy_addr + size == cur_addr) { 400 + /* Add to front of existing first block */ 401 + cvmx_bootmem_phy_set_next(phy_addr, 402 + cvmx_bootmem_phy_get_next 403 + (cur_addr)); 404 + cvmx_bootmem_phy_set_size(phy_addr, 405 + cvmx_bootmem_phy_get_size 406 + (cur_addr) + size); 407 + cvmx_bootmem_desc->head_addr = phy_addr; 408 + 409 + } else { 410 + /* New block before first block. OK if cur_addr is 0 */ 411 + cvmx_bootmem_phy_set_next(phy_addr, cur_addr); 412 + cvmx_bootmem_phy_set_size(phy_addr, size); 413 + cvmx_bootmem_desc->head_addr = phy_addr; 414 + } 415 + retval = 1; 416 + goto bootmem_free_done; 417 + } 418 + 419 + /* Find place in list to add block */ 420 + while (cur_addr && phy_addr > cur_addr) { 421 + prev_addr = cur_addr; 422 + cur_addr = cvmx_bootmem_phy_get_next(cur_addr); 423 + } 424 + 425 + if (!cur_addr) { 426 + /* 427 + * We have reached the end of the list, add on to end, 428 + * checking to see if we need to combine with last 429 + * block 430 + */ 431 + if (prev_addr + cvmx_bootmem_phy_get_size(prev_addr) == 432 + phy_addr) { 433 + cvmx_bootmem_phy_set_size(prev_addr, 434 + cvmx_bootmem_phy_get_size 435 + (prev_addr) + size); 436 + } else { 437 + cvmx_bootmem_phy_set_next(prev_addr, phy_addr); 438 + cvmx_bootmem_phy_set_size(phy_addr, size); 439 + cvmx_bootmem_phy_set_next(phy_addr, 0); 440 + } 441 + retval = 1; 442 + goto bootmem_free_done; 443 + } else { 444 + /* 445 + * insert between prev and cur nodes, checking for 446 + * merge with either/both. 447 + */ 448 + if (prev_addr + cvmx_bootmem_phy_get_size(prev_addr) == 449 + phy_addr) { 450 + /* Merge with previous */ 451 + cvmx_bootmem_phy_set_size(prev_addr, 452 + cvmx_bootmem_phy_get_size 453 + (prev_addr) + size); 454 + if (phy_addr + size == cur_addr) { 455 + /* Also merge with current */ 456 + cvmx_bootmem_phy_set_size(prev_addr, 457 + cvmx_bootmem_phy_get_size(cur_addr) + 458 + cvmx_bootmem_phy_get_size(prev_addr)); 459 + cvmx_bootmem_phy_set_next(prev_addr, 460 + cvmx_bootmem_phy_get_next(cur_addr)); 461 + } 462 + retval = 1; 463 + goto bootmem_free_done; 464 + } else if (phy_addr + size == cur_addr) { 465 + /* Merge with current */ 466 + cvmx_bootmem_phy_set_size(phy_addr, 467 + cvmx_bootmem_phy_get_size 468 + (cur_addr) + size); 469 + cvmx_bootmem_phy_set_next(phy_addr, 470 + cvmx_bootmem_phy_get_next 471 + (cur_addr)); 472 + cvmx_bootmem_phy_set_next(prev_addr, phy_addr); 473 + retval = 1; 474 + goto bootmem_free_done; 475 + } 476 + 477 + /* It is a standalone block, add in between prev and cur */ 478 + cvmx_bootmem_phy_set_size(phy_addr, size); 479 + cvmx_bootmem_phy_set_next(phy_addr, cur_addr); 480 + cvmx_bootmem_phy_set_next(prev_addr, phy_addr); 481 + 482 + } 483 + retval = 1; 484 + 485 + bootmem_free_done: 486 + if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING)) 487 + cvmx_bootmem_unlock(); 488 + return retval; 489 + 490 + } 491 + 492 + struct cvmx_bootmem_named_block_desc * 493 + cvmx_bootmem_phy_named_block_find(char *name, uint32_t flags) 494 + { 495 + unsigned int i; 496 + struct cvmx_bootmem_named_block_desc *named_block_array_ptr; 497 + 498 + #ifdef DEBUG 499 + cvmx_dprintf("cvmx_bootmem_phy_named_block_find: %s\n", name); 500 + #endif 501 + /* 502 + * Lock the structure to make sure that it is not being 503 + * changed while we are examining it. 504 + */ 505 + if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING)) 506 + cvmx_bootmem_lock(); 507 + 508 + /* Use XKPHYS for 64 bit linux */ 509 + named_block_array_ptr = (struct cvmx_bootmem_named_block_desc *) 510 + cvmx_phys_to_ptr(cvmx_bootmem_desc->named_block_array_addr); 511 + 512 + #ifdef DEBUG 513 + cvmx_dprintf 514 + ("cvmx_bootmem_phy_named_block_find: named_block_array_ptr: %p\n", 515 + named_block_array_ptr); 516 + #endif 517 + if (cvmx_bootmem_desc->major_version == 3) { 518 + for (i = 0; 519 + i < cvmx_bootmem_desc->named_block_num_blocks; i++) { 520 + if ((name && named_block_array_ptr[i].size 521 + && !strncmp(name, named_block_array_ptr[i].name, 522 + cvmx_bootmem_desc->named_block_name_len 523 + - 1)) 524 + || (!name && !named_block_array_ptr[i].size)) { 525 + if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING)) 526 + cvmx_bootmem_unlock(); 527 + 528 + return &(named_block_array_ptr[i]); 529 + } 530 + } 531 + } else { 532 + cvmx_dprintf("ERROR: Incompatible bootmem descriptor " 533 + "version: %d.%d at addr: %p\n", 534 + (int)cvmx_bootmem_desc->major_version, 535 + (int)cvmx_bootmem_desc->minor_version, 536 + cvmx_bootmem_desc); 537 + } 538 + if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING)) 539 + cvmx_bootmem_unlock(); 540 + 541 + return NULL; 542 + } 543 + 544 + int cvmx_bootmem_phy_named_block_free(char *name, uint32_t flags) 545 + { 546 + struct cvmx_bootmem_named_block_desc *named_block_ptr; 547 + 548 + if (cvmx_bootmem_desc->major_version != 3) { 549 + cvmx_dprintf("ERROR: Incompatible bootmem descriptor version: " 550 + "%d.%d at addr: %p\n", 551 + (int)cvmx_bootmem_desc->major_version, 552 + (int)cvmx_bootmem_desc->minor_version, 553 + cvmx_bootmem_desc); 554 + return 0; 555 + } 556 + #ifdef DEBUG 557 + cvmx_dprintf("cvmx_bootmem_phy_named_block_free: %s\n", name); 558 + #endif 559 + 560 + /* 561 + * Take lock here, as name lookup/block free/name free need to 562 + * be atomic. 563 + */ 564 + cvmx_bootmem_lock(); 565 + 566 + named_block_ptr = 567 + cvmx_bootmem_phy_named_block_find(name, 568 + CVMX_BOOTMEM_FLAG_NO_LOCKING); 569 + if (named_block_ptr) { 570 + #ifdef DEBUG 571 + cvmx_dprintf("cvmx_bootmem_phy_named_block_free: " 572 + "%s, base: 0x%llx, size: 0x%llx\n", 573 + name, 574 + (unsigned long long)named_block_ptr->base_addr, 575 + (unsigned long long)named_block_ptr->size); 576 + #endif 577 + __cvmx_bootmem_phy_free(named_block_ptr->base_addr, 578 + named_block_ptr->size, 579 + CVMX_BOOTMEM_FLAG_NO_LOCKING); 580 + named_block_ptr->size = 0; 581 + /* Set size to zero to indicate block not used. */ 582 + } 583 + 584 + cvmx_bootmem_unlock(); 585 + return named_block_ptr != NULL; /* 0 on failure, 1 on success */ 586 + }
+734
arch/mips/cavium-octeon/executive/cvmx-l2c.c
··· 1 + /***********************license start*************** 2 + * Author: Cavium Networks 3 + * 4 + * Contact: support@caviumnetworks.com 5 + * This file is part of the OCTEON SDK 6 + * 7 + * Copyright (c) 2003-2008 Cavium Networks 8 + * 9 + * This file is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License, Version 2, as 11 + * published by the Free Software Foundation. 12 + * 13 + * This file is distributed in the hope that it will be useful, but 14 + * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 15 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 16 + * NONINFRINGEMENT. See the GNU General Public License for more 17 + * details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with this file; if not, write to the Free Software 21 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 + * or visit http://www.gnu.org/licenses/. 23 + * 24 + * This file may also be available under a different license from Cavium. 25 + * Contact Cavium Networks for more information 26 + ***********************license end**************************************/ 27 + 28 + /* 29 + * Implementation of the Level 2 Cache (L2C) control, measurement, and 30 + * debugging facilities. 31 + */ 32 + 33 + #include <asm/octeon/cvmx.h> 34 + #include <asm/octeon/cvmx-l2c.h> 35 + #include <asm/octeon/cvmx-spinlock.h> 36 + 37 + /* 38 + * This spinlock is used internally to ensure that only one core is 39 + * performing certain L2 operations at a time. 40 + * 41 + * NOTE: This only protects calls from within a single application - 42 + * if multiple applications or operating systems are running, then it 43 + * is up to the user program to coordinate between them. 44 + */ 45 + static cvmx_spinlock_t cvmx_l2c_spinlock; 46 + 47 + static inline int l2_size_half(void) 48 + { 49 + uint64_t val = cvmx_read_csr(CVMX_L2D_FUS3); 50 + return !!(val & (1ull << 34)); 51 + } 52 + 53 + int cvmx_l2c_get_core_way_partition(uint32_t core) 54 + { 55 + uint32_t field; 56 + 57 + /* Validate the core number */ 58 + if (core >= cvmx_octeon_num_cores()) 59 + return -1; 60 + 61 + /* 62 + * Use the lower two bits of the coreNumber to determine the 63 + * bit offset of the UMSK[] field in the L2C_SPAR register. 64 + */ 65 + field = (core & 0x3) * 8; 66 + 67 + /* 68 + * Return the UMSK[] field from the appropriate L2C_SPAR 69 + * register based on the coreNumber. 70 + */ 71 + 72 + switch (core & 0xC) { 73 + case 0x0: 74 + return (cvmx_read_csr(CVMX_L2C_SPAR0) & (0xFF << field)) >> 75 + field; 76 + case 0x4: 77 + return (cvmx_read_csr(CVMX_L2C_SPAR1) & (0xFF << field)) >> 78 + field; 79 + case 0x8: 80 + return (cvmx_read_csr(CVMX_L2C_SPAR2) & (0xFF << field)) >> 81 + field; 82 + case 0xC: 83 + return (cvmx_read_csr(CVMX_L2C_SPAR3) & (0xFF << field)) >> 84 + field; 85 + } 86 + return 0; 87 + } 88 + 89 + int cvmx_l2c_set_core_way_partition(uint32_t core, uint32_t mask) 90 + { 91 + uint32_t field; 92 + uint32_t valid_mask; 93 + 94 + valid_mask = (0x1 << cvmx_l2c_get_num_assoc()) - 1; 95 + 96 + mask &= valid_mask; 97 + 98 + /* A UMSK setting which blocks all L2C Ways is an error. */ 99 + if (mask == valid_mask) 100 + return -1; 101 + 102 + /* Validate the core number */ 103 + if (core >= cvmx_octeon_num_cores()) 104 + return -1; 105 + 106 + /* Check to make sure current mask & new mask don't block all ways */ 107 + if (((mask | cvmx_l2c_get_core_way_partition(core)) & valid_mask) == 108 + valid_mask) 109 + return -1; 110 + 111 + /* Use the lower two bits of core to determine the bit offset of the 112 + * UMSK[] field in the L2C_SPAR register. 113 + */ 114 + field = (core & 0x3) * 8; 115 + 116 + /* Assign the new mask setting to the UMSK[] field in the appropriate 117 + * L2C_SPAR register based on the core_num. 118 + * 119 + */ 120 + switch (core & 0xC) { 121 + case 0x0: 122 + cvmx_write_csr(CVMX_L2C_SPAR0, 123 + (cvmx_read_csr(CVMX_L2C_SPAR0) & 124 + ~(0xFF << field)) | mask << field); 125 + break; 126 + case 0x4: 127 + cvmx_write_csr(CVMX_L2C_SPAR1, 128 + (cvmx_read_csr(CVMX_L2C_SPAR1) & 129 + ~(0xFF << field)) | mask << field); 130 + break; 131 + case 0x8: 132 + cvmx_write_csr(CVMX_L2C_SPAR2, 133 + (cvmx_read_csr(CVMX_L2C_SPAR2) & 134 + ~(0xFF << field)) | mask << field); 135 + break; 136 + case 0xC: 137 + cvmx_write_csr(CVMX_L2C_SPAR3, 138 + (cvmx_read_csr(CVMX_L2C_SPAR3) & 139 + ~(0xFF << field)) | mask << field); 140 + break; 141 + } 142 + return 0; 143 + } 144 + 145 + int cvmx_l2c_set_hw_way_partition(uint32_t mask) 146 + { 147 + uint32_t valid_mask; 148 + 149 + valid_mask = 0xff; 150 + 151 + if (OCTEON_IS_MODEL(OCTEON_CN58XX) || OCTEON_IS_MODEL(OCTEON_CN38XX)) { 152 + if (l2_size_half()) 153 + valid_mask = 0xf; 154 + } else if (l2_size_half()) 155 + valid_mask = 0x3; 156 + 157 + mask &= valid_mask; 158 + 159 + /* A UMSK setting which blocks all L2C Ways is an error. */ 160 + if (mask == valid_mask) 161 + return -1; 162 + /* Check to make sure current mask & new mask don't block all ways */ 163 + if (((mask | cvmx_l2c_get_hw_way_partition()) & valid_mask) == 164 + valid_mask) 165 + return -1; 166 + 167 + cvmx_write_csr(CVMX_L2C_SPAR4, 168 + (cvmx_read_csr(CVMX_L2C_SPAR4) & ~0xFF) | mask); 169 + return 0; 170 + } 171 + 172 + int cvmx_l2c_get_hw_way_partition(void) 173 + { 174 + return cvmx_read_csr(CVMX_L2C_SPAR4) & (0xFF); 175 + } 176 + 177 + void cvmx_l2c_config_perf(uint32_t counter, enum cvmx_l2c_event event, 178 + uint32_t clear_on_read) 179 + { 180 + union cvmx_l2c_pfctl pfctl; 181 + 182 + pfctl.u64 = cvmx_read_csr(CVMX_L2C_PFCTL); 183 + 184 + switch (counter) { 185 + case 0: 186 + pfctl.s.cnt0sel = event; 187 + pfctl.s.cnt0ena = 1; 188 + if (!cvmx_octeon_is_pass1()) 189 + pfctl.s.cnt0rdclr = clear_on_read; 190 + break; 191 + case 1: 192 + pfctl.s.cnt1sel = event; 193 + pfctl.s.cnt1ena = 1; 194 + if (!cvmx_octeon_is_pass1()) 195 + pfctl.s.cnt1rdclr = clear_on_read; 196 + break; 197 + case 2: 198 + pfctl.s.cnt2sel = event; 199 + pfctl.s.cnt2ena = 1; 200 + if (!cvmx_octeon_is_pass1()) 201 + pfctl.s.cnt2rdclr = clear_on_read; 202 + break; 203 + case 3: 204 + default: 205 + pfctl.s.cnt3sel = event; 206 + pfctl.s.cnt3ena = 1; 207 + if (!cvmx_octeon_is_pass1()) 208 + pfctl.s.cnt3rdclr = clear_on_read; 209 + break; 210 + } 211 + 212 + cvmx_write_csr(CVMX_L2C_PFCTL, pfctl.u64); 213 + } 214 + 215 + uint64_t cvmx_l2c_read_perf(uint32_t counter) 216 + { 217 + switch (counter) { 218 + case 0: 219 + return cvmx_read_csr(CVMX_L2C_PFC0); 220 + case 1: 221 + return cvmx_read_csr(CVMX_L2C_PFC1); 222 + case 2: 223 + return cvmx_read_csr(CVMX_L2C_PFC2); 224 + case 3: 225 + default: 226 + return cvmx_read_csr(CVMX_L2C_PFC3); 227 + } 228 + } 229 + 230 + /** 231 + * @INTERNAL 232 + * Helper function use to fault in cache lines for L2 cache locking 233 + * 234 + * @addr: Address of base of memory region to read into L2 cache 235 + * @len: Length (in bytes) of region to fault in 236 + */ 237 + static void fault_in(uint64_t addr, int len) 238 + { 239 + volatile char *ptr; 240 + volatile char dummy; 241 + /* 242 + * Adjust addr and length so we get all cache lines even for 243 + * small ranges spanning two cache lines 244 + */ 245 + len += addr & CVMX_CACHE_LINE_MASK; 246 + addr &= ~CVMX_CACHE_LINE_MASK; 247 + ptr = (volatile char *)cvmx_phys_to_ptr(addr); 248 + /* 249 + * Invalidate L1 cache to make sure all loads result in data 250 + * being in L2. 251 + */ 252 + CVMX_DCACHE_INVALIDATE; 253 + while (len > 0) { 254 + dummy += *ptr; 255 + len -= CVMX_CACHE_LINE_SIZE; 256 + ptr += CVMX_CACHE_LINE_SIZE; 257 + } 258 + } 259 + 260 + int cvmx_l2c_lock_line(uint64_t addr) 261 + { 262 + int retval = 0; 263 + union cvmx_l2c_dbg l2cdbg; 264 + union cvmx_l2c_lckbase lckbase; 265 + union cvmx_l2c_lckoff lckoff; 266 + union cvmx_l2t_err l2t_err; 267 + l2cdbg.u64 = 0; 268 + lckbase.u64 = 0; 269 + lckoff.u64 = 0; 270 + 271 + cvmx_spinlock_lock(&cvmx_l2c_spinlock); 272 + 273 + /* Clear l2t error bits if set */ 274 + l2t_err.u64 = cvmx_read_csr(CVMX_L2T_ERR); 275 + l2t_err.s.lckerr = 1; 276 + l2t_err.s.lckerr2 = 1; 277 + cvmx_write_csr(CVMX_L2T_ERR, l2t_err.u64); 278 + 279 + addr &= ~CVMX_CACHE_LINE_MASK; 280 + 281 + /* Set this core as debug core */ 282 + l2cdbg.s.ppnum = cvmx_get_core_num(); 283 + CVMX_SYNC; 284 + cvmx_write_csr(CVMX_L2C_DBG, l2cdbg.u64); 285 + cvmx_read_csr(CVMX_L2C_DBG); 286 + 287 + lckoff.s.lck_offset = 0; /* Only lock 1 line at a time */ 288 + cvmx_write_csr(CVMX_L2C_LCKOFF, lckoff.u64); 289 + cvmx_read_csr(CVMX_L2C_LCKOFF); 290 + 291 + if (((union cvmx_l2c_cfg) (cvmx_read_csr(CVMX_L2C_CFG))).s.idxalias) { 292 + int alias_shift = 293 + CVMX_L2C_IDX_ADDR_SHIFT + 2 * CVMX_L2_SET_BITS - 1; 294 + uint64_t addr_tmp = 295 + addr ^ (addr & ((1 << alias_shift) - 1)) >> 296 + CVMX_L2_SET_BITS; 297 + lckbase.s.lck_base = addr_tmp >> 7; 298 + } else { 299 + lckbase.s.lck_base = addr >> 7; 300 + } 301 + 302 + lckbase.s.lck_ena = 1; 303 + cvmx_write_csr(CVMX_L2C_LCKBASE, lckbase.u64); 304 + cvmx_read_csr(CVMX_L2C_LCKBASE); /* Make sure it gets there */ 305 + 306 + fault_in(addr, CVMX_CACHE_LINE_SIZE); 307 + 308 + lckbase.s.lck_ena = 0; 309 + cvmx_write_csr(CVMX_L2C_LCKBASE, lckbase.u64); 310 + cvmx_read_csr(CVMX_L2C_LCKBASE); /* Make sure it gets there */ 311 + 312 + /* Stop being debug core */ 313 + cvmx_write_csr(CVMX_L2C_DBG, 0); 314 + cvmx_read_csr(CVMX_L2C_DBG); 315 + 316 + l2t_err.u64 = cvmx_read_csr(CVMX_L2T_ERR); 317 + if (l2t_err.s.lckerr || l2t_err.s.lckerr2) 318 + retval = 1; /* We were unable to lock the line */ 319 + 320 + cvmx_spinlock_unlock(&cvmx_l2c_spinlock); 321 + 322 + return retval; 323 + } 324 + 325 + int cvmx_l2c_lock_mem_region(uint64_t start, uint64_t len) 326 + { 327 + int retval = 0; 328 + 329 + /* Round start/end to cache line boundaries */ 330 + len += start & CVMX_CACHE_LINE_MASK; 331 + start &= ~CVMX_CACHE_LINE_MASK; 332 + len = (len + CVMX_CACHE_LINE_MASK) & ~CVMX_CACHE_LINE_MASK; 333 + 334 + while (len) { 335 + retval += cvmx_l2c_lock_line(start); 336 + start += CVMX_CACHE_LINE_SIZE; 337 + len -= CVMX_CACHE_LINE_SIZE; 338 + } 339 + 340 + return retval; 341 + } 342 + 343 + void cvmx_l2c_flush(void) 344 + { 345 + uint64_t assoc, set; 346 + uint64_t n_assoc, n_set; 347 + union cvmx_l2c_dbg l2cdbg; 348 + 349 + cvmx_spinlock_lock(&cvmx_l2c_spinlock); 350 + 351 + l2cdbg.u64 = 0; 352 + if (!OCTEON_IS_MODEL(OCTEON_CN30XX)) 353 + l2cdbg.s.ppnum = cvmx_get_core_num(); 354 + l2cdbg.s.finv = 1; 355 + n_set = CVMX_L2_SETS; 356 + n_assoc = l2_size_half() ? (CVMX_L2_ASSOC / 2) : CVMX_L2_ASSOC; 357 + for (set = 0; set < n_set; set++) { 358 + for (assoc = 0; assoc < n_assoc; assoc++) { 359 + l2cdbg.s.set = assoc; 360 + /* Enter debug mode, and make sure all other 361 + ** writes complete before we enter debug 362 + ** mode */ 363 + CVMX_SYNCW; 364 + cvmx_write_csr(CVMX_L2C_DBG, l2cdbg.u64); 365 + cvmx_read_csr(CVMX_L2C_DBG); 366 + 367 + CVMX_PREPARE_FOR_STORE(CVMX_ADD_SEG 368 + (CVMX_MIPS_SPACE_XKPHYS, 369 + set * CVMX_CACHE_LINE_SIZE), 0); 370 + CVMX_SYNCW; /* Push STF out to L2 */ 371 + /* Exit debug mode */ 372 + CVMX_SYNC; 373 + cvmx_write_csr(CVMX_L2C_DBG, 0); 374 + cvmx_read_csr(CVMX_L2C_DBG); 375 + } 376 + } 377 + 378 + cvmx_spinlock_unlock(&cvmx_l2c_spinlock); 379 + } 380 + 381 + int cvmx_l2c_unlock_line(uint64_t address) 382 + { 383 + int assoc; 384 + union cvmx_l2c_tag tag; 385 + union cvmx_l2c_dbg l2cdbg; 386 + uint32_t tag_addr; 387 + 388 + uint32_t index = cvmx_l2c_address_to_index(address); 389 + 390 + cvmx_spinlock_lock(&cvmx_l2c_spinlock); 391 + /* Compute portion of address that is stored in tag */ 392 + tag_addr = 393 + ((address >> CVMX_L2C_TAG_ADDR_ALIAS_SHIFT) & 394 + ((1 << CVMX_L2C_TAG_ADDR_ALIAS_SHIFT) - 1)); 395 + for (assoc = 0; assoc < CVMX_L2_ASSOC; assoc++) { 396 + tag = cvmx_get_l2c_tag(assoc, index); 397 + 398 + if (tag.s.V && (tag.s.addr == tag_addr)) { 399 + l2cdbg.u64 = 0; 400 + l2cdbg.s.ppnum = cvmx_get_core_num(); 401 + l2cdbg.s.set = assoc; 402 + l2cdbg.s.finv = 1; 403 + 404 + CVMX_SYNC; 405 + /* Enter debug mode */ 406 + cvmx_write_csr(CVMX_L2C_DBG, l2cdbg.u64); 407 + cvmx_read_csr(CVMX_L2C_DBG); 408 + 409 + CVMX_PREPARE_FOR_STORE(CVMX_ADD_SEG 410 + (CVMX_MIPS_SPACE_XKPHYS, 411 + address), 0); 412 + CVMX_SYNC; 413 + /* Exit debug mode */ 414 + cvmx_write_csr(CVMX_L2C_DBG, 0); 415 + cvmx_read_csr(CVMX_L2C_DBG); 416 + cvmx_spinlock_unlock(&cvmx_l2c_spinlock); 417 + return tag.s.L; 418 + } 419 + } 420 + cvmx_spinlock_unlock(&cvmx_l2c_spinlock); 421 + return 0; 422 + } 423 + 424 + int cvmx_l2c_unlock_mem_region(uint64_t start, uint64_t len) 425 + { 426 + int num_unlocked = 0; 427 + /* Round start/end to cache line boundaries */ 428 + len += start & CVMX_CACHE_LINE_MASK; 429 + start &= ~CVMX_CACHE_LINE_MASK; 430 + len = (len + CVMX_CACHE_LINE_MASK) & ~CVMX_CACHE_LINE_MASK; 431 + while (len > 0) { 432 + num_unlocked += cvmx_l2c_unlock_line(start); 433 + start += CVMX_CACHE_LINE_SIZE; 434 + len -= CVMX_CACHE_LINE_SIZE; 435 + } 436 + 437 + return num_unlocked; 438 + } 439 + 440 + /* 441 + * Internal l2c tag types. These are converted to a generic structure 442 + * that can be used on all chips. 443 + */ 444 + union __cvmx_l2c_tag { 445 + uint64_t u64; 446 + struct cvmx_l2c_tag_cn50xx { 447 + uint64_t reserved:40; 448 + uint64_t V:1; /* Line valid */ 449 + uint64_t D:1; /* Line dirty */ 450 + uint64_t L:1; /* Line locked */ 451 + uint64_t U:1; /* Use, LRU eviction */ 452 + uint64_t addr:20; /* Phys mem addr (33..14) */ 453 + } cn50xx; 454 + struct cvmx_l2c_tag_cn30xx { 455 + uint64_t reserved:41; 456 + uint64_t V:1; /* Line valid */ 457 + uint64_t D:1; /* Line dirty */ 458 + uint64_t L:1; /* Line locked */ 459 + uint64_t U:1; /* Use, LRU eviction */ 460 + uint64_t addr:19; /* Phys mem addr (33..15) */ 461 + } cn30xx; 462 + struct cvmx_l2c_tag_cn31xx { 463 + uint64_t reserved:42; 464 + uint64_t V:1; /* Line valid */ 465 + uint64_t D:1; /* Line dirty */ 466 + uint64_t L:1; /* Line locked */ 467 + uint64_t U:1; /* Use, LRU eviction */ 468 + uint64_t addr:18; /* Phys mem addr (33..16) */ 469 + } cn31xx; 470 + struct cvmx_l2c_tag_cn38xx { 471 + uint64_t reserved:43; 472 + uint64_t V:1; /* Line valid */ 473 + uint64_t D:1; /* Line dirty */ 474 + uint64_t L:1; /* Line locked */ 475 + uint64_t U:1; /* Use, LRU eviction */ 476 + uint64_t addr:17; /* Phys mem addr (33..17) */ 477 + } cn38xx; 478 + struct cvmx_l2c_tag_cn58xx { 479 + uint64_t reserved:44; 480 + uint64_t V:1; /* Line valid */ 481 + uint64_t D:1; /* Line dirty */ 482 + uint64_t L:1; /* Line locked */ 483 + uint64_t U:1; /* Use, LRU eviction */ 484 + uint64_t addr:16; /* Phys mem addr (33..18) */ 485 + } cn58xx; 486 + struct cvmx_l2c_tag_cn58xx cn56xx; /* 2048 sets */ 487 + struct cvmx_l2c_tag_cn31xx cn52xx; /* 512 sets */ 488 + }; 489 + 490 + /** 491 + * @INTERNAL 492 + * Function to read a L2C tag. This code make the current core 493 + * the 'debug core' for the L2. This code must only be executed by 494 + * 1 core at a time. 495 + * 496 + * @assoc: Association (way) of the tag to dump 497 + * @index: Index of the cacheline 498 + * 499 + * Returns The Octeon model specific tag structure. This is 500 + * translated by a wrapper function to a generic form that is 501 + * easier for applications to use. 502 + */ 503 + static union __cvmx_l2c_tag __read_l2_tag(uint64_t assoc, uint64_t index) 504 + { 505 + 506 + uint64_t debug_tag_addr = (((1ULL << 63) | (index << 7)) + 96); 507 + uint64_t core = cvmx_get_core_num(); 508 + union __cvmx_l2c_tag tag_val; 509 + uint64_t dbg_addr = CVMX_L2C_DBG; 510 + unsigned long flags; 511 + 512 + union cvmx_l2c_dbg debug_val; 513 + debug_val.u64 = 0; 514 + /* 515 + * For low core count parts, the core number is always small enough 516 + * to stay in the correct field and not set any reserved bits. 517 + */ 518 + debug_val.s.ppnum = core; 519 + debug_val.s.l2t = 1; 520 + debug_val.s.set = assoc; 521 + /* 522 + * Make sure core is quiet (no prefetches, etc.) before 523 + * entering debug mode. 524 + */ 525 + CVMX_SYNC; 526 + /* Flush L1 to make sure debug load misses L1 */ 527 + CVMX_DCACHE_INVALIDATE; 528 + 529 + local_irq_save(flags); 530 + 531 + /* 532 + * The following must be done in assembly as when in debug 533 + * mode all data loads from L2 return special debug data, not 534 + * normal memory contents. Also, interrupts must be 535 + * disabled, since if an interrupt occurs while in debug mode 536 + * the ISR will get debug data from all its memory reads 537 + * instead of the contents of memory 538 + */ 539 + 540 + asm volatile (".set push \n" 541 + " .set mips64 \n" 542 + " .set noreorder \n" 543 + /* Enter debug mode, wait for store */ 544 + " sd %[dbg_val], 0(%[dbg_addr]) \n" 545 + " ld $0, 0(%[dbg_addr]) \n" 546 + /* Read L2C tag data */ 547 + " ld %[tag_val], 0(%[tag_addr]) \n" 548 + /* Exit debug mode, wait for store */ 549 + " sd $0, 0(%[dbg_addr]) \n" 550 + " ld $0, 0(%[dbg_addr]) \n" 551 + /* Invalidate dcache to discard debug data */ 552 + " cache 9, 0($0) \n" 553 + " .set pop" : 554 + [tag_val] "=r"(tag_val.u64) : [dbg_addr] "r"(dbg_addr), 555 + [dbg_val] "r"(debug_val.u64), 556 + [tag_addr] "r"(debug_tag_addr) : "memory"); 557 + 558 + local_irq_restore(flags); 559 + return tag_val; 560 + 561 + } 562 + 563 + union cvmx_l2c_tag cvmx_l2c_get_tag(uint32_t association, uint32_t index) 564 + { 565 + union __cvmx_l2c_tag tmp_tag; 566 + union cvmx_l2c_tag tag; 567 + tag.u64 = 0; 568 + 569 + if ((int)association >= cvmx_l2c_get_num_assoc()) { 570 + cvmx_dprintf 571 + ("ERROR: cvmx_get_l2c_tag association out of range\n"); 572 + return tag; 573 + } 574 + if ((int)index >= cvmx_l2c_get_num_sets()) { 575 + cvmx_dprintf("ERROR: cvmx_get_l2c_tag " 576 + "index out of range (arg: %d, max: %d\n", 577 + index, cvmx_l2c_get_num_sets()); 578 + return tag; 579 + } 580 + /* __read_l2_tag is intended for internal use only */ 581 + tmp_tag = __read_l2_tag(association, index); 582 + 583 + /* 584 + * Convert all tag structure types to generic version, as it 585 + * can represent all models. 586 + */ 587 + if (OCTEON_IS_MODEL(OCTEON_CN58XX) || OCTEON_IS_MODEL(OCTEON_CN56XX)) { 588 + tag.s.V = tmp_tag.cn58xx.V; 589 + tag.s.D = tmp_tag.cn58xx.D; 590 + tag.s.L = tmp_tag.cn58xx.L; 591 + tag.s.U = tmp_tag.cn58xx.U; 592 + tag.s.addr = tmp_tag.cn58xx.addr; 593 + } else if (OCTEON_IS_MODEL(OCTEON_CN38XX)) { 594 + tag.s.V = tmp_tag.cn38xx.V; 595 + tag.s.D = tmp_tag.cn38xx.D; 596 + tag.s.L = tmp_tag.cn38xx.L; 597 + tag.s.U = tmp_tag.cn38xx.U; 598 + tag.s.addr = tmp_tag.cn38xx.addr; 599 + } else if (OCTEON_IS_MODEL(OCTEON_CN31XX) 600 + || OCTEON_IS_MODEL(OCTEON_CN52XX)) { 601 + tag.s.V = tmp_tag.cn31xx.V; 602 + tag.s.D = tmp_tag.cn31xx.D; 603 + tag.s.L = tmp_tag.cn31xx.L; 604 + tag.s.U = tmp_tag.cn31xx.U; 605 + tag.s.addr = tmp_tag.cn31xx.addr; 606 + } else if (OCTEON_IS_MODEL(OCTEON_CN30XX)) { 607 + tag.s.V = tmp_tag.cn30xx.V; 608 + tag.s.D = tmp_tag.cn30xx.D; 609 + tag.s.L = tmp_tag.cn30xx.L; 610 + tag.s.U = tmp_tag.cn30xx.U; 611 + tag.s.addr = tmp_tag.cn30xx.addr; 612 + } else if (OCTEON_IS_MODEL(OCTEON_CN50XX)) { 613 + tag.s.V = tmp_tag.cn50xx.V; 614 + tag.s.D = tmp_tag.cn50xx.D; 615 + tag.s.L = tmp_tag.cn50xx.L; 616 + tag.s.U = tmp_tag.cn50xx.U; 617 + tag.s.addr = tmp_tag.cn50xx.addr; 618 + } else { 619 + cvmx_dprintf("Unsupported OCTEON Model in %s\n", __func__); 620 + } 621 + 622 + return tag; 623 + } 624 + 625 + uint32_t cvmx_l2c_address_to_index(uint64_t addr) 626 + { 627 + uint64_t idx = addr >> CVMX_L2C_IDX_ADDR_SHIFT; 628 + union cvmx_l2c_cfg l2c_cfg; 629 + l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG); 630 + 631 + if (l2c_cfg.s.idxalias) { 632 + idx ^= 633 + ((addr & CVMX_L2C_ALIAS_MASK) >> 634 + CVMX_L2C_TAG_ADDR_ALIAS_SHIFT); 635 + } 636 + idx &= CVMX_L2C_IDX_MASK; 637 + return idx; 638 + } 639 + 640 + int cvmx_l2c_get_cache_size_bytes(void) 641 + { 642 + return cvmx_l2c_get_num_sets() * cvmx_l2c_get_num_assoc() * 643 + CVMX_CACHE_LINE_SIZE; 644 + } 645 + 646 + /** 647 + * Return log base 2 of the number of sets in the L2 cache 648 + * Returns 649 + */ 650 + int cvmx_l2c_get_set_bits(void) 651 + { 652 + int l2_set_bits; 653 + if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN58XX)) 654 + l2_set_bits = 11; /* 2048 sets */ 655 + else if (OCTEON_IS_MODEL(OCTEON_CN38XX)) 656 + l2_set_bits = 10; /* 1024 sets */ 657 + else if (OCTEON_IS_MODEL(OCTEON_CN31XX) 658 + || OCTEON_IS_MODEL(OCTEON_CN52XX)) 659 + l2_set_bits = 9; /* 512 sets */ 660 + else if (OCTEON_IS_MODEL(OCTEON_CN30XX)) 661 + l2_set_bits = 8; /* 256 sets */ 662 + else if (OCTEON_IS_MODEL(OCTEON_CN50XX)) 663 + l2_set_bits = 7; /* 128 sets */ 664 + else { 665 + cvmx_dprintf("Unsupported OCTEON Model in %s\n", __func__); 666 + l2_set_bits = 11; /* 2048 sets */ 667 + } 668 + return l2_set_bits; 669 + 670 + } 671 + 672 + /* Return the number of sets in the L2 Cache */ 673 + int cvmx_l2c_get_num_sets(void) 674 + { 675 + return 1 << cvmx_l2c_get_set_bits(); 676 + } 677 + 678 + /* Return the number of associations in the L2 Cache */ 679 + int cvmx_l2c_get_num_assoc(void) 680 + { 681 + int l2_assoc; 682 + if (OCTEON_IS_MODEL(OCTEON_CN56XX) || 683 + OCTEON_IS_MODEL(OCTEON_CN52XX) || 684 + OCTEON_IS_MODEL(OCTEON_CN58XX) || 685 + OCTEON_IS_MODEL(OCTEON_CN50XX) || OCTEON_IS_MODEL(OCTEON_CN38XX)) 686 + l2_assoc = 8; 687 + else if (OCTEON_IS_MODEL(OCTEON_CN31XX) || 688 + OCTEON_IS_MODEL(OCTEON_CN30XX)) 689 + l2_assoc = 4; 690 + else { 691 + cvmx_dprintf("Unsupported OCTEON Model in %s\n", __func__); 692 + l2_assoc = 8; 693 + } 694 + 695 + /* Check to see if part of the cache is disabled */ 696 + if (cvmx_fuse_read(265)) 697 + l2_assoc = l2_assoc >> 2; 698 + else if (cvmx_fuse_read(264)) 699 + l2_assoc = l2_assoc >> 1; 700 + 701 + return l2_assoc; 702 + } 703 + 704 + /** 705 + * Flush a line from the L2 cache 706 + * This should only be called from one core at a time, as this routine 707 + * sets the core to the 'debug' core in order to flush the line. 708 + * 709 + * @assoc: Association (or way) to flush 710 + * @index: Index to flush 711 + */ 712 + void cvmx_l2c_flush_line(uint32_t assoc, uint32_t index) 713 + { 714 + union cvmx_l2c_dbg l2cdbg; 715 + 716 + l2cdbg.u64 = 0; 717 + l2cdbg.s.ppnum = cvmx_get_core_num(); 718 + l2cdbg.s.finv = 1; 719 + 720 + l2cdbg.s.set = assoc; 721 + /* 722 + * Enter debug mode, and make sure all other writes complete 723 + * before we enter debug mode. 724 + */ 725 + asm volatile ("sync" : : : "memory"); 726 + cvmx_write_csr(CVMX_L2C_DBG, l2cdbg.u64); 727 + cvmx_read_csr(CVMX_L2C_DBG); 728 + 729 + CVMX_PREPARE_FOR_STORE(((1ULL << 63) + (index) * 128), 0); 730 + /* Exit debug mode */ 731 + asm volatile ("sync" : : : "memory"); 732 + cvmx_write_csr(CVMX_L2C_DBG, 0); 733 + cvmx_read_csr(CVMX_L2C_DBG); 734 + }
+116
arch/mips/cavium-octeon/executive/cvmx-sysinfo.c
··· 1 + /***********************license start*************** 2 + * Author: Cavium Networks 3 + * 4 + * Contact: support@caviumnetworks.com 5 + * This file is part of the OCTEON SDK 6 + * 7 + * Copyright (c) 2003-2008 Cavium Networks 8 + * 9 + * This file is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License, Version 2, as 11 + * published by the Free Software Foundation. 12 + * 13 + * This file is distributed in the hope that it will be useful, but 14 + * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 15 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 16 + * NONINFRINGEMENT. See the GNU General Public License for more 17 + * details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with this file; if not, write to the Free Software 21 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 + * or visit http://www.gnu.org/licenses/. 23 + * 24 + * This file may also be available under a different license from Cavium. 25 + * Contact Cavium Networks for more information 26 + ***********************license end**************************************/ 27 + 28 + /* 29 + * This module provides system/board/application information obtained 30 + * by the bootloader. 31 + */ 32 + 33 + #include <asm/octeon/cvmx.h> 34 + #include <asm/octeon/cvmx-spinlock.h> 35 + #include <asm/octeon/cvmx-sysinfo.h> 36 + 37 + /** 38 + * This structure defines the private state maintained by sysinfo module. 39 + * 40 + */ 41 + static struct { 42 + struct cvmx_sysinfo sysinfo; /* system information */ 43 + cvmx_spinlock_t lock; /* mutex spinlock */ 44 + 45 + } state = { 46 + .lock = CVMX_SPINLOCK_UNLOCKED_INITIALIZER 47 + }; 48 + 49 + 50 + /* 51 + * Global variables that define the min/max of the memory region set 52 + * up for 32 bit userspace access. 53 + */ 54 + uint64_t linux_mem32_min; 55 + uint64_t linux_mem32_max; 56 + uint64_t linux_mem32_wired; 57 + uint64_t linux_mem32_offset; 58 + 59 + /** 60 + * This function returns the application information as obtained 61 + * by the bootloader. This provides the core mask of the cores 62 + * running the same application image, as well as the physical 63 + * memory regions available to the core. 64 + * 65 + * Returns Pointer to the boot information structure 66 + * 67 + */ 68 + struct cvmx_sysinfo *cvmx_sysinfo_get(void) 69 + { 70 + return &(state.sysinfo); 71 + } 72 + 73 + /** 74 + * This function is used in non-simple executive environments (such as 75 + * Linux kernel, u-boot, etc.) to configure the minimal fields that 76 + * are required to use simple executive files directly. 77 + * 78 + * Locking (if required) must be handled outside of this 79 + * function 80 + * 81 + * @phy_mem_desc_ptr: 82 + * Pointer to global physical memory descriptor 83 + * (bootmem descriptor) @board_type: Octeon board 84 + * type enumeration 85 + * 86 + * @board_rev_major: 87 + * Board major revision 88 + * @board_rev_minor: 89 + * Board minor revision 90 + * @cpu_clock_hz: 91 + * CPU clock freqency in hertz 92 + * 93 + * Returns 0: Failure 94 + * 1: success 95 + */ 96 + int cvmx_sysinfo_minimal_initialize(void *phy_mem_desc_ptr, 97 + uint16_t board_type, 98 + uint8_t board_rev_major, 99 + uint8_t board_rev_minor, 100 + uint32_t cpu_clock_hz) 101 + { 102 + 103 + /* The sysinfo structure was already initialized */ 104 + if (state.sysinfo.board_type) 105 + return 0; 106 + 107 + memset(&(state.sysinfo), 0x0, sizeof(state.sysinfo)); 108 + state.sysinfo.phy_mem_desc_ptr = phy_mem_desc_ptr; 109 + state.sysinfo.board_type = board_type; 110 + state.sysinfo.board_rev_major = board_rev_major; 111 + state.sysinfo.board_rev_minor = board_rev_minor; 112 + state.sysinfo.cpu_clock_hz = cpu_clock_hz; 113 + 114 + return 1; 115 + } 116 +
+358
arch/mips/cavium-octeon/executive/octeon-model.c
··· 1 + /***********************license start*************** 2 + * Author: Cavium Networks 3 + * 4 + * Contact: support@caviumnetworks.com 5 + * This file is part of the OCTEON SDK 6 + * 7 + * Copyright (c) 2003-2008 Cavium Networks 8 + * 9 + * This file is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License, Version 2, as 11 + * published by the Free Software Foundation. 12 + * 13 + * This file is distributed in the hope that it will be useful, but 14 + * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 15 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 16 + * NONINFRINGEMENT. See the GNU General Public License for more 17 + * details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with this file; if not, write to the Free Software 21 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 + * or visit http://www.gnu.org/licenses/. 23 + * 24 + * This file may also be available under a different license from Cavium. 25 + * Contact Cavium Networks for more information 26 + ***********************license end**************************************/ 27 + 28 + /* 29 + * File defining functions for working with different Octeon 30 + * models. 31 + */ 32 + #include <asm/octeon/octeon.h> 33 + 34 + /** 35 + * Given the chip processor ID from COP0, this function returns a 36 + * string representing the chip model number. The string is of the 37 + * form CNXXXXpX.X-FREQ-SUFFIX. 38 + * - XXXX = The chip model number 39 + * - X.X = Chip pass number 40 + * - FREQ = Current frequency in Mhz 41 + * - SUFFIX = NSP, EXP, SCP, SSP, or CP 42 + * 43 + * @chip_id: Chip ID 44 + * 45 + * Returns Model string 46 + */ 47 + const char *octeon_model_get_string(uint32_t chip_id) 48 + { 49 + static char buffer[32]; 50 + return octeon_model_get_string_buffer(chip_id, buffer); 51 + } 52 + 53 + /* 54 + * Version of octeon_model_get_string() that takes buffer as argument, 55 + * as running early in u-boot static/global variables don't work when 56 + * running from flash. 57 + */ 58 + const char *octeon_model_get_string_buffer(uint32_t chip_id, char *buffer) 59 + { 60 + const char *family; 61 + const char *core_model; 62 + char pass[4]; 63 + int clock_mhz; 64 + const char *suffix; 65 + union cvmx_l2d_fus3 fus3; 66 + int num_cores; 67 + union cvmx_mio_fus_dat2 fus_dat2; 68 + union cvmx_mio_fus_dat3 fus_dat3; 69 + char fuse_model[10]; 70 + uint32_t fuse_data = 0; 71 + 72 + fus3.u64 = cvmx_read_csr(CVMX_L2D_FUS3); 73 + fus_dat2.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT2); 74 + fus_dat3.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT3); 75 + 76 + num_cores = cvmx_octeon_num_cores(); 77 + 78 + /* Make sure the non existant devices look disabled */ 79 + switch ((chip_id >> 8) & 0xff) { 80 + case 6: /* CN50XX */ 81 + case 2: /* CN30XX */ 82 + fus_dat3.s.nodfa_dte = 1; 83 + fus_dat3.s.nozip = 1; 84 + break; 85 + case 4: /* CN57XX or CN56XX */ 86 + fus_dat3.s.nodfa_dte = 1; 87 + break; 88 + default: 89 + break; 90 + } 91 + 92 + /* Make a guess at the suffix */ 93 + /* NSP = everything */ 94 + /* EXP = No crypto */ 95 + /* SCP = No DFA, No zip */ 96 + /* CP = No DFA, No crypto, No zip */ 97 + if (fus_dat3.s.nodfa_dte) { 98 + if (fus_dat2.s.nocrypto) 99 + suffix = "CP"; 100 + else 101 + suffix = "SCP"; 102 + } else if (fus_dat2.s.nocrypto) 103 + suffix = "EXP"; 104 + else 105 + suffix = "NSP"; 106 + 107 + /* 108 + * Assume pass number is encoded using <5:3><2:0>. Exceptions 109 + * will be fixed later. 110 + */ 111 + sprintf(pass, "%u.%u", ((chip_id >> 3) & 7) + 1, chip_id & 7); 112 + 113 + /* 114 + * Use the number of cores to determine the last 2 digits of 115 + * the model number. There are some exceptions that are fixed 116 + * later. 117 + */ 118 + switch (num_cores) { 119 + case 16: 120 + core_model = "60"; 121 + break; 122 + case 15: 123 + core_model = "58"; 124 + break; 125 + case 14: 126 + core_model = "55"; 127 + break; 128 + case 13: 129 + core_model = "52"; 130 + break; 131 + case 12: 132 + core_model = "50"; 133 + break; 134 + case 11: 135 + core_model = "48"; 136 + break; 137 + case 10: 138 + core_model = "45"; 139 + break; 140 + case 9: 141 + core_model = "42"; 142 + break; 143 + case 8: 144 + core_model = "40"; 145 + break; 146 + case 7: 147 + core_model = "38"; 148 + break; 149 + case 6: 150 + core_model = "34"; 151 + break; 152 + case 5: 153 + core_model = "32"; 154 + break; 155 + case 4: 156 + core_model = "30"; 157 + break; 158 + case 3: 159 + core_model = "25"; 160 + break; 161 + case 2: 162 + core_model = "20"; 163 + break; 164 + case 1: 165 + core_model = "10"; 166 + break; 167 + default: 168 + core_model = "XX"; 169 + break; 170 + } 171 + 172 + /* Now figure out the family, the first two digits */ 173 + switch ((chip_id >> 8) & 0xff) { 174 + case 0: /* CN38XX, CN37XX or CN36XX */ 175 + if (fus3.cn38xx.crip_512k) { 176 + /* 177 + * For some unknown reason, the 16 core one is 178 + * called 37 instead of 36. 179 + */ 180 + if (num_cores >= 16) 181 + family = "37"; 182 + else 183 + family = "36"; 184 + } else 185 + family = "38"; 186 + /* 187 + * This series of chips didn't follow the standard 188 + * pass numbering. 189 + */ 190 + switch (chip_id & 0xf) { 191 + case 0: 192 + strcpy(pass, "1.X"); 193 + break; 194 + case 1: 195 + strcpy(pass, "2.X"); 196 + break; 197 + case 3: 198 + strcpy(pass, "3.X"); 199 + break; 200 + default: 201 + strcpy(pass, "X.X"); 202 + break; 203 + } 204 + break; 205 + case 1: /* CN31XX or CN3020 */ 206 + if ((chip_id & 0x10) || fus3.cn31xx.crip_128k) 207 + family = "30"; 208 + else 209 + family = "31"; 210 + /* 211 + * This series of chips didn't follow the standard 212 + * pass numbering. 213 + */ 214 + switch (chip_id & 0xf) { 215 + case 0: 216 + strcpy(pass, "1.0"); 217 + break; 218 + case 2: 219 + strcpy(pass, "1.1"); 220 + break; 221 + default: 222 + strcpy(pass, "X.X"); 223 + break; 224 + } 225 + break; 226 + case 2: /* CN3010 or CN3005 */ 227 + family = "30"; 228 + /* A chip with half cache is an 05 */ 229 + if (fus3.cn30xx.crip_64k) 230 + core_model = "05"; 231 + /* 232 + * This series of chips didn't follow the standard 233 + * pass numbering. 234 + */ 235 + switch (chip_id & 0xf) { 236 + case 0: 237 + strcpy(pass, "1.0"); 238 + break; 239 + case 2: 240 + strcpy(pass, "1.1"); 241 + break; 242 + default: 243 + strcpy(pass, "X.X"); 244 + break; 245 + } 246 + break; 247 + case 3: /* CN58XX */ 248 + family = "58"; 249 + /* Special case. 4 core, no crypto */ 250 + if ((num_cores == 4) && fus_dat2.cn38xx.nocrypto) 251 + core_model = "29"; 252 + 253 + /* Pass 1 uses different encodings for pass numbers */ 254 + if ((chip_id & 0xFF) < 0x8) { 255 + switch (chip_id & 0x3) { 256 + case 0: 257 + strcpy(pass, "1.0"); 258 + break; 259 + case 1: 260 + strcpy(pass, "1.1"); 261 + break; 262 + case 3: 263 + strcpy(pass, "1.2"); 264 + break; 265 + default: 266 + strcpy(pass, "1.X"); 267 + break; 268 + } 269 + } 270 + break; 271 + case 4: /* CN57XX, CN56XX, CN55XX, CN54XX */ 272 + if (fus_dat2.cn56xx.raid_en) { 273 + if (fus3.cn56xx.crip_1024k) 274 + family = "55"; 275 + else 276 + family = "57"; 277 + if (fus_dat2.cn56xx.nocrypto) 278 + suffix = "SP"; 279 + else 280 + suffix = "SSP"; 281 + } else { 282 + if (fus_dat2.cn56xx.nocrypto) 283 + suffix = "CP"; 284 + else { 285 + suffix = "NSP"; 286 + if (fus_dat3.s.nozip) 287 + suffix = "SCP"; 288 + } 289 + if (fus3.cn56xx.crip_1024k) 290 + family = "54"; 291 + else 292 + family = "56"; 293 + } 294 + break; 295 + case 6: /* CN50XX */ 296 + family = "50"; 297 + break; 298 + case 7: /* CN52XX */ 299 + if (fus3.cn52xx.crip_256k) 300 + family = "51"; 301 + else 302 + family = "52"; 303 + break; 304 + default: 305 + family = "XX"; 306 + core_model = "XX"; 307 + strcpy(pass, "X.X"); 308 + suffix = "XXX"; 309 + break; 310 + } 311 + 312 + clock_mhz = octeon_get_clock_rate() / 1000000; 313 + 314 + if (family[0] != '3') { 315 + /* Check for model in fuses, overrides normal decode */ 316 + /* This is _not_ valid for Octeon CN3XXX models */ 317 + fuse_data |= cvmx_fuse_read_byte(51); 318 + fuse_data = fuse_data << 8; 319 + fuse_data |= cvmx_fuse_read_byte(50); 320 + fuse_data = fuse_data << 8; 321 + fuse_data |= cvmx_fuse_read_byte(49); 322 + fuse_data = fuse_data << 8; 323 + fuse_data |= cvmx_fuse_read_byte(48); 324 + if (fuse_data & 0x7ffff) { 325 + int model = fuse_data & 0x3fff; 326 + int suffix = (fuse_data >> 14) & 0x1f; 327 + if (suffix && model) { 328 + /* 329 + * Have both number and suffix in 330 + * fuses, so both 331 + */ 332 + sprintf(fuse_model, "%d%c", 333 + model, 'A' + suffix - 1); 334 + core_model = ""; 335 + family = fuse_model; 336 + } else if (suffix && !model) { 337 + /* 338 + * Only have suffix, so add suffix to 339 + * 'normal' model number. 340 + */ 341 + sprintf(fuse_model, "%s%c", core_model, 342 + 'A' + suffix - 1); 343 + core_model = fuse_model; 344 + } else { 345 + /* 346 + * Don't have suffix, so just use 347 + * model from fuses. 348 + */ 349 + sprintf(fuse_model, "%d", model); 350 + core_model = ""; 351 + family = fuse_model; 352 + } 353 + } 354 + } 355 + sprintf(buffer, "CN%s%sp%s-%d-%s", 356 + family, core_model, pass, clock_mhz, suffix); 357 + return buffer; 358 + }
+128
arch/mips/include/asm/octeon/cvmx-asm.h
··· 1 + /***********************license start*************** 2 + * Author: Cavium Networks 3 + * 4 + * Contact: support@caviumnetworks.com 5 + * This file is part of the OCTEON SDK 6 + * 7 + * Copyright (c) 2003-2008 Cavium Networks 8 + * 9 + * This file is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License, Version 2, as 11 + * published by the Free Software Foundation. 12 + * 13 + * This file is distributed in the hope that it will be useful, but 14 + * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 15 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 16 + * NONINFRINGEMENT. See the GNU General Public License for more 17 + * details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with this file; if not, write to the Free Software 21 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 + * or visit http://www.gnu.org/licenses/. 23 + * 24 + * This file may also be available under a different license from Cavium. 25 + * Contact Cavium Networks for more information 26 + ***********************license end**************************************/ 27 + 28 + /* 29 + * 30 + * This is file defines ASM primitives for the executive. 31 + */ 32 + #ifndef __CVMX_ASM_H__ 33 + #define __CVMX_ASM_H__ 34 + 35 + #include "octeon-model.h" 36 + 37 + /* other useful stuff */ 38 + #define CVMX_SYNC asm volatile ("sync" : : : "memory") 39 + /* String version of SYNCW macro for using in inline asm constructs */ 40 + #define CVMX_SYNCW_STR "syncw\nsyncw\n" 41 + #ifdef __OCTEON__ 42 + 43 + /* Deprecated, will be removed in future release */ 44 + #define CVMX_SYNCIO asm volatile ("nop") 45 + 46 + #define CVMX_SYNCIOBDMA asm volatile ("synciobdma" : : : "memory") 47 + 48 + /* Deprecated, will be removed in future release */ 49 + #define CVMX_SYNCIOALL asm volatile ("nop") 50 + 51 + /* 52 + * We actually use two syncw instructions in a row when we need a write 53 + * memory barrier. This is because the CN3XXX series of Octeons have 54 + * errata Core-401. This can cause a single syncw to not enforce 55 + * ordering under very rare conditions. Even if it is rare, better safe 56 + * than sorry. 57 + */ 58 + #define CVMX_SYNCW asm volatile ("syncw\n\tsyncw" : : : "memory") 59 + 60 + /* 61 + * Define new sync instructions to be normal SYNC instructions for 62 + * operating systems that use threads. 63 + */ 64 + #define CVMX_SYNCWS CVMX_SYNCW 65 + #define CVMX_SYNCS CVMX_SYNC 66 + #define CVMX_SYNCWS_STR CVMX_SYNCW_STR 67 + #else 68 + /* 69 + * Not using a Cavium compiler, always use the slower sync so the 70 + * assembler stays happy. 71 + */ 72 + /* Deprecated, will be removed in future release */ 73 + #define CVMX_SYNCIO asm volatile ("nop") 74 + 75 + #define CVMX_SYNCIOBDMA asm volatile ("sync" : : : "memory") 76 + 77 + /* Deprecated, will be removed in future release */ 78 + #define CVMX_SYNCIOALL asm volatile ("nop") 79 + 80 + #define CVMX_SYNCW asm volatile ("sync" : : : "memory") 81 + #define CVMX_SYNCWS CVMX_SYNCW 82 + #define CVMX_SYNCS CVMX_SYNC 83 + #define CVMX_SYNCWS_STR CVMX_SYNCW_STR 84 + #endif 85 + 86 + /* 87 + * CVMX_PREPARE_FOR_STORE makes each byte of the block unpredictable 88 + * (actually old value or zero) until that byte is stored to (by this or 89 + * another processor. Note that the value of each byte is not only 90 + * unpredictable, but may also change again - up until the point when one 91 + * of the cores stores to the byte. 92 + */ 93 + #define CVMX_PREPARE_FOR_STORE(address, offset) \ 94 + asm volatile ("pref 30, " CVMX_TMP_STR(offset) "(%[rbase])" : : \ 95 + [rbase] "d" (address)) 96 + /* 97 + * This is a command headed to the L2 controller to tell it to clear 98 + * its dirty bit for a block. Basically, SW is telling HW that the 99 + * current version of the block will not be used. 100 + */ 101 + #define CVMX_DONT_WRITE_BACK(address, offset) \ 102 + asm volatile ("pref 29, " CVMX_TMP_STR(offset) "(%[rbase])" : : \ 103 + [rbase] "d" (address)) 104 + 105 + /* flush stores, invalidate entire icache */ 106 + #define CVMX_ICACHE_INVALIDATE \ 107 + { CVMX_SYNC; asm volatile ("synci 0($0)" : : ); } 108 + 109 + /* flush stores, invalidate entire icache */ 110 + #define CVMX_ICACHE_INVALIDATE2 \ 111 + { CVMX_SYNC; asm volatile ("cache 0, 0($0)" : : ); } 112 + 113 + /* complete prefetches, invalidate entire dcache */ 114 + #define CVMX_DCACHE_INVALIDATE \ 115 + { CVMX_SYNC; asm volatile ("cache 9, 0($0)" : : ); } 116 + 117 + 118 + #define CVMX_POP(result, input) \ 119 + asm ("pop %[rd],%[rs]" : [rd] "=d" (result) : [rs] "d" (input)) 120 + #define CVMX_DPOP(result, input) \ 121 + asm ("dpop %[rd],%[rs]" : [rd] "=d" (result) : [rs] "d" (input)) 122 + 123 + /* some new cop0-like stuff */ 124 + #define CVMX_RDHWR(result, regstr) \ 125 + asm volatile ("rdhwr %[rt],$" CVMX_TMP_STR(regstr) : [rt] "=d" (result)) 126 + #define CVMX_RDHWRNV(result, regstr) \ 127 + asm ("rdhwr %[rt],$" CVMX_TMP_STR(regstr) : [rt] "=d" (result)) 128 + #endif /* __CVMX_ASM_H__ */
+262
arch/mips/include/asm/octeon/cvmx-bootinfo.h
··· 1 + /***********************license start*************** 2 + * Author: Cavium Networks 3 + * 4 + * Contact: support@caviumnetworks.com 5 + * This file is part of the OCTEON SDK 6 + * 7 + * Copyright (c) 2003-2008 Cavium Networks 8 + * 9 + * This file is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License, Version 2, as 11 + * published by the Free Software Foundation. 12 + * 13 + * This file is distributed in the hope that it will be useful, but 14 + * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 15 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 16 + * NONINFRINGEMENT. See the GNU General Public License for more 17 + * details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with this file; if not, write to the Free Software 21 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 + * or visit http://www.gnu.org/licenses/. 23 + * 24 + * This file may also be available under a different license from Cavium. 25 + * Contact Cavium Networks for more information 26 + ***********************license end**************************************/ 27 + 28 + /* 29 + * Header file containing the ABI with the bootloader. 30 + */ 31 + 32 + #ifndef __CVMX_BOOTINFO_H__ 33 + #define __CVMX_BOOTINFO_H__ 34 + 35 + /* 36 + * Current major and minor versions of the CVMX bootinfo block that is 37 + * passed from the bootloader to the application. This is versioned 38 + * so that applications can properly handle multiple bootloader 39 + * versions. 40 + */ 41 + #define CVMX_BOOTINFO_MAJ_VER 1 42 + #define CVMX_BOOTINFO_MIN_VER 2 43 + 44 + #if (CVMX_BOOTINFO_MAJ_VER == 1) 45 + #define CVMX_BOOTINFO_OCTEON_SERIAL_LEN 20 46 + /* 47 + * This structure is populated by the bootloader. For binary 48 + * compatibility the only changes that should be made are 49 + * adding members to the end of the structure, and the minor 50 + * version should be incremented at that time. 51 + * If an incompatible change is made, the major version 52 + * must be incremented, and the minor version should be reset 53 + * to 0. 54 + */ 55 + struct cvmx_bootinfo { 56 + uint32_t major_version; 57 + uint32_t minor_version; 58 + 59 + uint64_t stack_top; 60 + uint64_t heap_base; 61 + uint64_t heap_end; 62 + uint64_t desc_vaddr; 63 + 64 + uint32_t exception_base_addr; 65 + uint32_t stack_size; 66 + uint32_t flags; 67 + uint32_t core_mask; 68 + /* DRAM size in megabytes */ 69 + uint32_t dram_size; 70 + /* physical address of free memory descriptor block*/ 71 + uint32_t phy_mem_desc_addr; 72 + /* used to pass flags from app to debugger */ 73 + uint32_t debugger_flags_base_addr; 74 + 75 + /* CPU clock speed, in hz */ 76 + uint32_t eclock_hz; 77 + 78 + /* DRAM clock speed, in hz */ 79 + uint32_t dclock_hz; 80 + 81 + uint32_t reserved0; 82 + uint16_t board_type; 83 + uint8_t board_rev_major; 84 + uint8_t board_rev_minor; 85 + uint16_t reserved1; 86 + uint8_t reserved2; 87 + uint8_t reserved3; 88 + char board_serial_number[CVMX_BOOTINFO_OCTEON_SERIAL_LEN]; 89 + uint8_t mac_addr_base[6]; 90 + uint8_t mac_addr_count; 91 + #if (CVMX_BOOTINFO_MIN_VER >= 1) 92 + /* 93 + * Several boards support compact flash on the Octeon boot 94 + * bus. The CF memory spaces may be mapped to different 95 + * addresses on different boards. These are the physical 96 + * addresses, so care must be taken to use the correct 97 + * XKPHYS/KSEG0 addressing depending on the application's 98 + * ABI. These values will be 0 if CF is not present. 99 + */ 100 + uint64_t compact_flash_common_base_addr; 101 + uint64_t compact_flash_attribute_base_addr; 102 + /* 103 + * Base address of the LED display (as on EBT3000 board) 104 + * This will be 0 if LED display not present. 105 + */ 106 + uint64_t led_display_base_addr; 107 + #endif 108 + #if (CVMX_BOOTINFO_MIN_VER >= 2) 109 + /* DFA reference clock in hz (if applicable)*/ 110 + uint32_t dfa_ref_clock_hz; 111 + 112 + /* 113 + * flags indicating various configuration options. These 114 + * flags supercede the 'flags' variable and should be used 115 + * instead if available. 116 + */ 117 + uint32_t config_flags; 118 + #endif 119 + 120 + }; 121 + 122 + #define CVMX_BOOTINFO_CFG_FLAG_PCI_HOST (1ull << 0) 123 + #define CVMX_BOOTINFO_CFG_FLAG_PCI_TARGET (1ull << 1) 124 + #define CVMX_BOOTINFO_CFG_FLAG_DEBUG (1ull << 2) 125 + #define CVMX_BOOTINFO_CFG_FLAG_NO_MAGIC (1ull << 3) 126 + /* This flag is set if the TLB mappings are not contained in the 127 + * 0x10000000 - 0x20000000 boot bus region. */ 128 + #define CVMX_BOOTINFO_CFG_FLAG_OVERSIZE_TLB_MAPPING (1ull << 4) 129 + #define CVMX_BOOTINFO_CFG_FLAG_BREAK (1ull << 5) 130 + 131 + #endif /* (CVMX_BOOTINFO_MAJ_VER == 1) */ 132 + 133 + /* Type defines for board and chip types */ 134 + enum cvmx_board_types_enum { 135 + CVMX_BOARD_TYPE_NULL = 0, 136 + CVMX_BOARD_TYPE_SIM = 1, 137 + CVMX_BOARD_TYPE_EBT3000 = 2, 138 + CVMX_BOARD_TYPE_KODAMA = 3, 139 + CVMX_BOARD_TYPE_NIAGARA = 4, 140 + CVMX_BOARD_TYPE_NAC38 = 5, /* formerly NAO38 */ 141 + CVMX_BOARD_TYPE_THUNDER = 6, 142 + CVMX_BOARD_TYPE_TRANTOR = 7, 143 + CVMX_BOARD_TYPE_EBH3000 = 8, 144 + CVMX_BOARD_TYPE_EBH3100 = 9, 145 + CVMX_BOARD_TYPE_HIKARI = 10, 146 + CVMX_BOARD_TYPE_CN3010_EVB_HS5 = 11, 147 + CVMX_BOARD_TYPE_CN3005_EVB_HS5 = 12, 148 + CVMX_BOARD_TYPE_KBP = 13, 149 + /* Deprecated, CVMX_BOARD_TYPE_CN3010_EVB_HS5 supports the CN3020 */ 150 + CVMX_BOARD_TYPE_CN3020_EVB_HS5 = 14, 151 + CVMX_BOARD_TYPE_EBT5800 = 15, 152 + CVMX_BOARD_TYPE_NICPRO2 = 16, 153 + CVMX_BOARD_TYPE_EBH5600 = 17, 154 + CVMX_BOARD_TYPE_EBH5601 = 18, 155 + CVMX_BOARD_TYPE_EBH5200 = 19, 156 + CVMX_BOARD_TYPE_BBGW_REF = 20, 157 + CVMX_BOARD_TYPE_NIC_XLE_4G = 21, 158 + CVMX_BOARD_TYPE_EBT5600 = 22, 159 + CVMX_BOARD_TYPE_EBH5201 = 23, 160 + CVMX_BOARD_TYPE_MAX, 161 + 162 + /* 163 + * The range from CVMX_BOARD_TYPE_MAX to 164 + * CVMX_BOARD_TYPE_CUST_DEFINED_MIN is reserved for future 165 + * SDK use. 166 + */ 167 + 168 + /* 169 + * Set aside a range for customer boards. These numbers are managed 170 + * by Cavium. 171 + */ 172 + CVMX_BOARD_TYPE_CUST_DEFINED_MIN = 10000, 173 + CVMX_BOARD_TYPE_CUST_WSX16 = 10001, 174 + CVMX_BOARD_TYPE_CUST_NS0216 = 10002, 175 + CVMX_BOARD_TYPE_CUST_NB5 = 10003, 176 + CVMX_BOARD_TYPE_CUST_WMR500 = 10004, 177 + CVMX_BOARD_TYPE_CUST_DEFINED_MAX = 20000, 178 + 179 + /* 180 + * Set aside a range for customer private use. The SDK won't 181 + * use any numbers in this range. 182 + */ 183 + CVMX_BOARD_TYPE_CUST_PRIVATE_MIN = 20001, 184 + CVMX_BOARD_TYPE_CUST_PRIVATE_MAX = 30000, 185 + 186 + /* The remaining range is reserved for future use. */ 187 + }; 188 + 189 + enum cvmx_chip_types_enum { 190 + CVMX_CHIP_TYPE_NULL = 0, 191 + CVMX_CHIP_SIM_TYPE_DEPRECATED = 1, 192 + CVMX_CHIP_TYPE_OCTEON_SAMPLE = 2, 193 + CVMX_CHIP_TYPE_MAX, 194 + }; 195 + 196 + /* Compatability alias for NAC38 name change, planned to be removed 197 + * from SDK 1.7 */ 198 + #define CVMX_BOARD_TYPE_NAO38 CVMX_BOARD_TYPE_NAC38 199 + 200 + /* Functions to return string based on type */ 201 + #define ENUM_BRD_TYPE_CASE(x) \ 202 + case x: return(#x + 16); /* Skip CVMX_BOARD_TYPE_ */ 203 + static inline const char *cvmx_board_type_to_string(enum 204 + cvmx_board_types_enum type) 205 + { 206 + switch (type) { 207 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NULL) 208 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_SIM) 209 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT3000) 210 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_KODAMA) 211 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIAGARA) 212 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NAC38) 213 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_THUNDER) 214 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_TRANTOR) 215 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH3000) 216 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH3100) 217 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_HIKARI) 218 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CN3010_EVB_HS5) 219 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CN3005_EVB_HS5) 220 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_KBP) 221 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CN3020_EVB_HS5) 222 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT5800) 223 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NICPRO2) 224 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5600) 225 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5601) 226 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5200) 227 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_BBGW_REF) 228 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIC_XLE_4G) 229 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT5600) 230 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5201) 231 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_MAX) 232 + 233 + /* Customer boards listed here */ 234 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_DEFINED_MIN) 235 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_WSX16) 236 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_NS0216) 237 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_NB5) 238 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_WMR500) 239 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_DEFINED_MAX) 240 + 241 + /* Customer private range */ 242 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MIN) 243 + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MAX) 244 + } 245 + return "Unsupported Board"; 246 + } 247 + 248 + #define ENUM_CHIP_TYPE_CASE(x) \ 249 + case x: return(#x + 15); /* Skip CVMX_CHIP_TYPE */ 250 + static inline const char *cvmx_chip_type_to_string(enum 251 + cvmx_chip_types_enum type) 252 + { 253 + switch (type) { 254 + ENUM_CHIP_TYPE_CASE(CVMX_CHIP_TYPE_NULL) 255 + ENUM_CHIP_TYPE_CASE(CVMX_CHIP_SIM_TYPE_DEPRECATED) 256 + ENUM_CHIP_TYPE_CASE(CVMX_CHIP_TYPE_OCTEON_SAMPLE) 257 + ENUM_CHIP_TYPE_CASE(CVMX_CHIP_TYPE_MAX) 258 + } 259 + return "Unsupported Chip"; 260 + } 261 + 262 + #endif /* __CVMX_BOOTINFO_H__ */
+288
arch/mips/include/asm/octeon/cvmx-bootmem.h
··· 1 + /***********************license start*************** 2 + * Author: Cavium Networks 3 + * 4 + * Contact: support@caviumnetworks.com 5 + * This file is part of the OCTEON SDK 6 + * 7 + * Copyright (c) 2003-2008 Cavium Networks 8 + * 9 + * This file is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License, Version 2, as 11 + * published by the Free Software Foundation. 12 + * 13 + * This file is distributed in the hope that it will be useful, but 14 + * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 15 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 16 + * NONINFRINGEMENT. See the GNU General Public License for more 17 + * details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with this file; if not, write to the Free Software 21 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 + * or visit http://www.gnu.org/licenses/. 23 + * 24 + * This file may also be available under a different license from Cavium. 25 + * Contact Cavium Networks for more information 26 + ***********************license end**************************************/ 27 + 28 + /* 29 + * Simple allocate only memory allocator. Used to allocate memory at 30 + * application start time. 31 + */ 32 + 33 + #ifndef __CVMX_BOOTMEM_H__ 34 + #define __CVMX_BOOTMEM_H__ 35 + /* Must be multiple of 8, changing breaks ABI */ 36 + #define CVMX_BOOTMEM_NAME_LEN 128 37 + 38 + /* Can change without breaking ABI */ 39 + #define CVMX_BOOTMEM_NUM_NAMED_BLOCKS 64 40 + 41 + /* minimum alignment of bootmem alloced blocks */ 42 + #define CVMX_BOOTMEM_ALIGNMENT_SIZE (16ull) 43 + 44 + /* Flags for cvmx_bootmem_phy_mem* functions */ 45 + /* Allocate from end of block instead of beginning */ 46 + #define CVMX_BOOTMEM_FLAG_END_ALLOC (1 << 0) 47 + 48 + /* Don't do any locking. */ 49 + #define CVMX_BOOTMEM_FLAG_NO_LOCKING (1 << 1) 50 + 51 + /* First bytes of each free physical block of memory contain this structure, 52 + * which is used to maintain the free memory list. Since the bootloader is 53 + * only 32 bits, there is a union providing 64 and 32 bit versions. The 54 + * application init code converts addresses to 64 bit addresses before the 55 + * application starts. 56 + */ 57 + struct cvmx_bootmem_block_header { 58 + /* 59 + * Note: these are referenced from assembly routines in the 60 + * bootloader, so this structure should not be changed 61 + * without changing those routines as well. 62 + */ 63 + uint64_t next_block_addr; 64 + uint64_t size; 65 + 66 + }; 67 + 68 + /* 69 + * Structure for named memory blocks. Number of descriptors available 70 + * can be changed without affecting compatiblity, but name length 71 + * changes require a bump in the bootmem descriptor version Note: This 72 + * structure must be naturally 64 bit aligned, as a single memory 73 + * image will be used by both 32 and 64 bit programs. 74 + */ 75 + struct cvmx_bootmem_named_block_desc { 76 + /* Base address of named block */ 77 + uint64_t base_addr; 78 + /* 79 + * Size actually allocated for named block (may differ from 80 + * requested). 81 + */ 82 + uint64_t size; 83 + /* name of named block */ 84 + char name[CVMX_BOOTMEM_NAME_LEN]; 85 + }; 86 + 87 + /* Current descriptor versions */ 88 + /* CVMX bootmem descriptor major version */ 89 + #define CVMX_BOOTMEM_DESC_MAJ_VER 3 90 + 91 + /* CVMX bootmem descriptor minor version */ 92 + #define CVMX_BOOTMEM_DESC_MIN_VER 0 93 + 94 + /* First three members of cvmx_bootmem_desc_t are left in original 95 + * positions for backwards compatibility. 96 + */ 97 + struct cvmx_bootmem_desc { 98 + /* spinlock to control access to list */ 99 + uint32_t lock; 100 + /* flags for indicating various conditions */ 101 + uint32_t flags; 102 + uint64_t head_addr; 103 + 104 + /* Incremented when incompatible changes made */ 105 + uint32_t major_version; 106 + 107 + /* 108 + * Incremented changed when compatible changes made, reset to 109 + * zero when major incremented. 110 + */ 111 + uint32_t minor_version; 112 + 113 + uint64_t app_data_addr; 114 + uint64_t app_data_size; 115 + 116 + /* number of elements in named blocks array */ 117 + uint32_t named_block_num_blocks; 118 + 119 + /* length of name array in bootmem blocks */ 120 + uint32_t named_block_name_len; 121 + /* address of named memory block descriptors */ 122 + uint64_t named_block_array_addr; 123 + 124 + }; 125 + 126 + /** 127 + * Initialize the boot alloc memory structures. This is 128 + * normally called inside of cvmx_user_app_init() 129 + * 130 + * @mem_desc_ptr: Address of the free memory list 131 + */ 132 + extern int cvmx_bootmem_init(void *mem_desc_ptr); 133 + 134 + /** 135 + * Allocate a block of memory from the free list that was passed 136 + * to the application by the bootloader. 137 + * This is an allocate-only algorithm, so freeing memory is not possible. 138 + * 139 + * @size: Size in bytes of block to allocate 140 + * @alignment: Alignment required - must be power of 2 141 + * 142 + * Returns pointer to block of memory, NULL on error 143 + */ 144 + extern void *cvmx_bootmem_alloc(uint64_t size, uint64_t alignment); 145 + 146 + /** 147 + * Allocate a block of memory from the free list that was 148 + * passed to the application by the bootloader at a specific 149 + * address. This is an allocate-only algorithm, so 150 + * freeing memory is not possible. Allocation will fail if 151 + * memory cannot be allocated at the specified address. 152 + * 153 + * @size: Size in bytes of block to allocate 154 + * @address: Physical address to allocate memory at. If this memory is not 155 + * available, the allocation fails. 156 + * @alignment: Alignment required - must be power of 2 157 + * Returns pointer to block of memory, NULL on error 158 + */ 159 + extern void *cvmx_bootmem_alloc_address(uint64_t size, uint64_t address, 160 + uint64_t alignment); 161 + 162 + /** 163 + * Allocate a block of memory from the free list that was 164 + * passed to the application by the bootloader within a specified 165 + * address range. This is an allocate-only algorithm, so 166 + * freeing memory is not possible. Allocation will fail if 167 + * memory cannot be allocated in the requested range. 168 + * 169 + * @size: Size in bytes of block to allocate 170 + * @min_addr: defines the minimum address of the range 171 + * @max_addr: defines the maximum address of the range 172 + * @alignment: Alignment required - must be power of 2 173 + * Returns pointer to block of memory, NULL on error 174 + */ 175 + extern void *cvmx_bootmem_alloc_range(uint64_t size, uint64_t alignment, 176 + uint64_t min_addr, uint64_t max_addr); 177 + 178 + /** 179 + * Frees a previously allocated named bootmem block. 180 + * 181 + * @name: name of block to free 182 + * 183 + * Returns 0 on failure, 184 + * !0 on success 185 + */ 186 + extern int cvmx_bootmem_free_named(char *name); 187 + 188 + /** 189 + * Finds a named bootmem block by name. 190 + * 191 + * @name: name of block to free 192 + * 193 + * Returns pointer to named block descriptor on success 194 + * 0 on failure 195 + */ 196 + struct cvmx_bootmem_named_block_desc *cvmx_bootmem_find_named_block(char *name); 197 + 198 + /** 199 + * Allocates a block of physical memory from the free list, at 200 + * (optional) requested address and alignment. 201 + * 202 + * @req_size: size of region to allocate. All requests are rounded up 203 + * to be a multiple CVMX_BOOTMEM_ALIGNMENT_SIZE bytes size 204 + * 205 + * @address_min: Minimum address that block can occupy. 206 + * 207 + * @address_max: Specifies the maximum address_min (inclusive) that 208 + * the allocation can use. 209 + * 210 + * @alignment: Requested alignment of the block. If this alignment 211 + * cannot be met, the allocation fails. This must be a 212 + * power of 2. (Note: Alignment of 213 + * CVMX_BOOTMEM_ALIGNMENT_SIZE bytes is required, and 214 + * internally enforced. Requested alignments of less than 215 + * CVMX_BOOTMEM_ALIGNMENT_SIZE are set to 216 + * CVMX_BOOTMEM_ALIGNMENT_SIZE.) 217 + * 218 + * @flags: Flags to control options for the allocation. 219 + * 220 + * Returns physical address of block allocated, or -1 on failure 221 + */ 222 + int64_t cvmx_bootmem_phy_alloc(uint64_t req_size, uint64_t address_min, 223 + uint64_t address_max, uint64_t alignment, 224 + uint32_t flags); 225 + 226 + /** 227 + * Finds a named memory block by name. 228 + * Also used for finding an unused entry in the named block table. 229 + * 230 + * @name: Name of memory block to find. If NULL pointer given, then 231 + * finds unused descriptor, if available. 232 + * 233 + * @flags: Flags to control options for the allocation. 234 + * 235 + * Returns Pointer to memory block descriptor, NULL if not found. 236 + * If NULL returned when name parameter is NULL, then no memory 237 + * block descriptors are available. 238 + */ 239 + struct cvmx_bootmem_named_block_desc * 240 + cvmx_bootmem_phy_named_block_find(char *name, uint32_t flags); 241 + 242 + /** 243 + * Frees a named block. 244 + * 245 + * @name: name of block to free 246 + * @flags: flags for passing options 247 + * 248 + * Returns 0 on failure 249 + * 1 on success 250 + */ 251 + int cvmx_bootmem_phy_named_block_free(char *name, uint32_t flags); 252 + 253 + /** 254 + * Frees a block to the bootmem allocator list. This must 255 + * be used with care, as the size provided must match the size 256 + * of the block that was allocated, or the list will become 257 + * corrupted. 258 + * 259 + * IMPORTANT: This is only intended to be used as part of named block 260 + * frees and initial population of the free memory list. 261 + * * 262 + * 263 + * @phy_addr: physical address of block 264 + * @size: size of block in bytes. 265 + * @flags: flags for passing options 266 + * 267 + * Returns 1 on success, 268 + * 0 on failure 269 + */ 270 + int __cvmx_bootmem_phy_free(uint64_t phy_addr, uint64_t size, uint32_t flags); 271 + 272 + /** 273 + * Locks the bootmem allocator. This is useful in certain situations 274 + * where multiple allocations must be made without being interrupted. 275 + * This should be used with the CVMX_BOOTMEM_FLAG_NO_LOCKING flag. 276 + * 277 + */ 278 + void cvmx_bootmem_lock(void); 279 + 280 + /** 281 + * Unlocks the bootmem allocator. This is useful in certain situations 282 + * where multiple allocations must be made without being interrupted. 283 + * This should be used with the CVMX_BOOTMEM_FLAG_NO_LOCKING flag. 284 + * 285 + */ 286 + void cvmx_bootmem_unlock(void); 287 + 288 + #endif /* __CVMX_BOOTMEM_H__ */
+325
arch/mips/include/asm/octeon/cvmx-l2c.h
··· 1 + /***********************license start*************** 2 + * Author: Cavium Networks 3 + * 4 + * Contact: support@caviumnetworks.com 5 + * This file is part of the OCTEON SDK 6 + * 7 + * Copyright (c) 2003-2008 Cavium Networks 8 + * 9 + * This file is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License, Version 2, as 11 + * published by the Free Software Foundation. 12 + * 13 + * This file is distributed in the hope that it will be useful, but 14 + * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 15 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 16 + * NONINFRINGEMENT. See the GNU General Public License for more 17 + * details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with this file; if not, write to the Free Software 21 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 + * or visit http://www.gnu.org/licenses/. 23 + * 24 + * This file may also be available under a different license from Cavium. 25 + * Contact Cavium Networks for more information 26 + ***********************license end**************************************/ 27 + 28 + /* 29 + * 30 + * Interface to the Level 2 Cache (L2C) control, measurement, and debugging 31 + * facilities. 32 + */ 33 + 34 + #ifndef __CVMX_L2C_H__ 35 + #define __CVMX_L2C_H__ 36 + 37 + /* Deprecated macro, use function */ 38 + #define CVMX_L2_ASSOC cvmx_l2c_get_num_assoc() 39 + 40 + /* Deprecated macro, use function */ 41 + #define CVMX_L2_SET_BITS cvmx_l2c_get_set_bits() 42 + 43 + /* Deprecated macro, use function */ 44 + #define CVMX_L2_SETS cvmx_l2c_get_num_sets() 45 + 46 + #define CVMX_L2C_IDX_ADDR_SHIFT 7 /* based on 128 byte cache line size */ 47 + #define CVMX_L2C_IDX_MASK (cvmx_l2c_get_num_sets() - 1) 48 + 49 + /* Defines for index aliasing computations */ 50 + #define CVMX_L2C_TAG_ADDR_ALIAS_SHIFT \ 51 + (CVMX_L2C_IDX_ADDR_SHIFT + cvmx_l2c_get_set_bits()) 52 + 53 + #define CVMX_L2C_ALIAS_MASK \ 54 + (CVMX_L2C_IDX_MASK << CVMX_L2C_TAG_ADDR_ALIAS_SHIFT) 55 + 56 + union cvmx_l2c_tag { 57 + uint64_t u64; 58 + struct { 59 + uint64_t reserved:28; 60 + uint64_t V:1; /* Line valid */ 61 + uint64_t D:1; /* Line dirty */ 62 + uint64_t L:1; /* Line locked */ 63 + uint64_t U:1; /* Use, LRU eviction */ 64 + uint64_t addr:32; /* Phys mem (not all bits valid) */ 65 + } s; 66 + }; 67 + 68 + /* L2C Performance Counter events. */ 69 + enum cvmx_l2c_event { 70 + CVMX_L2C_EVENT_CYCLES = 0, 71 + CVMX_L2C_EVENT_INSTRUCTION_MISS = 1, 72 + CVMX_L2C_EVENT_INSTRUCTION_HIT = 2, 73 + CVMX_L2C_EVENT_DATA_MISS = 3, 74 + CVMX_L2C_EVENT_DATA_HIT = 4, 75 + CVMX_L2C_EVENT_MISS = 5, 76 + CVMX_L2C_EVENT_HIT = 6, 77 + CVMX_L2C_EVENT_VICTIM_HIT = 7, 78 + CVMX_L2C_EVENT_INDEX_CONFLICT = 8, 79 + CVMX_L2C_EVENT_TAG_PROBE = 9, 80 + CVMX_L2C_EVENT_TAG_UPDATE = 10, 81 + CVMX_L2C_EVENT_TAG_COMPLETE = 11, 82 + CVMX_L2C_EVENT_TAG_DIRTY = 12, 83 + CVMX_L2C_EVENT_DATA_STORE_NOP = 13, 84 + CVMX_L2C_EVENT_DATA_STORE_READ = 14, 85 + CVMX_L2C_EVENT_DATA_STORE_WRITE = 15, 86 + CVMX_L2C_EVENT_FILL_DATA_VALID = 16, 87 + CVMX_L2C_EVENT_WRITE_REQUEST = 17, 88 + CVMX_L2C_EVENT_READ_REQUEST = 18, 89 + CVMX_L2C_EVENT_WRITE_DATA_VALID = 19, 90 + CVMX_L2C_EVENT_XMC_NOP = 20, 91 + CVMX_L2C_EVENT_XMC_LDT = 21, 92 + CVMX_L2C_EVENT_XMC_LDI = 22, 93 + CVMX_L2C_EVENT_XMC_LDD = 23, 94 + CVMX_L2C_EVENT_XMC_STF = 24, 95 + CVMX_L2C_EVENT_XMC_STT = 25, 96 + CVMX_L2C_EVENT_XMC_STP = 26, 97 + CVMX_L2C_EVENT_XMC_STC = 27, 98 + CVMX_L2C_EVENT_XMC_DWB = 28, 99 + CVMX_L2C_EVENT_XMC_PL2 = 29, 100 + CVMX_L2C_EVENT_XMC_PSL1 = 30, 101 + CVMX_L2C_EVENT_XMC_IOBLD = 31, 102 + CVMX_L2C_EVENT_XMC_IOBST = 32, 103 + CVMX_L2C_EVENT_XMC_IOBDMA = 33, 104 + CVMX_L2C_EVENT_XMC_IOBRSP = 34, 105 + CVMX_L2C_EVENT_XMC_BUS_VALID = 35, 106 + CVMX_L2C_EVENT_XMC_MEM_DATA = 36, 107 + CVMX_L2C_EVENT_XMC_REFL_DATA = 37, 108 + CVMX_L2C_EVENT_XMC_IOBRSP_DATA = 38, 109 + CVMX_L2C_EVENT_RSC_NOP = 39, 110 + CVMX_L2C_EVENT_RSC_STDN = 40, 111 + CVMX_L2C_EVENT_RSC_FILL = 41, 112 + CVMX_L2C_EVENT_RSC_REFL = 42, 113 + CVMX_L2C_EVENT_RSC_STIN = 43, 114 + CVMX_L2C_EVENT_RSC_SCIN = 44, 115 + CVMX_L2C_EVENT_RSC_SCFL = 45, 116 + CVMX_L2C_EVENT_RSC_SCDN = 46, 117 + CVMX_L2C_EVENT_RSC_DATA_VALID = 47, 118 + CVMX_L2C_EVENT_RSC_VALID_FILL = 48, 119 + CVMX_L2C_EVENT_RSC_VALID_STRSP = 49, 120 + CVMX_L2C_EVENT_RSC_VALID_REFL = 50, 121 + CVMX_L2C_EVENT_LRF_REQ = 51, 122 + CVMX_L2C_EVENT_DT_RD_ALLOC = 52, 123 + CVMX_L2C_EVENT_DT_WR_INVAL = 53 124 + }; 125 + 126 + /** 127 + * Configure one of the four L2 Cache performance counters to capture event 128 + * occurences. 129 + * 130 + * @counter: The counter to configure. Range 0..3. 131 + * @event: The type of L2 Cache event occurrence to count. 132 + * @clear_on_read: When asserted, any read of the performance counter 133 + * clears the counter. 134 + * 135 + * The routine does not clear the counter. 136 + */ 137 + void cvmx_l2c_config_perf(uint32_t counter, 138 + enum cvmx_l2c_event event, uint32_t clear_on_read); 139 + /** 140 + * Read the given L2 Cache performance counter. The counter must be configured 141 + * before reading, but this routine does not enforce this requirement. 142 + * 143 + * @counter: The counter to configure. Range 0..3. 144 + * 145 + * Returns The current counter value. 146 + */ 147 + uint64_t cvmx_l2c_read_perf(uint32_t counter); 148 + 149 + /** 150 + * Return the L2 Cache way partitioning for a given core. 151 + * 152 + * @core: The core processor of interest. 153 + * 154 + * Returns The mask specifying the partitioning. 0 bits in mask indicates 155 + * the cache 'ways' that a core can evict from. 156 + * -1 on error 157 + */ 158 + int cvmx_l2c_get_core_way_partition(uint32_t core); 159 + 160 + /** 161 + * Partitions the L2 cache for a core 162 + * 163 + * @core: The core that the partitioning applies to. 164 + * 165 + * @mask: The partitioning of the ways expressed as a binary mask. A 0 166 + * bit allows the core to evict cache lines from a way, while a 167 + * 1 bit blocks the core from evicting any lines from that 168 + * way. There must be at least one allowed way (0 bit) in the 169 + * mask. 170 + * 171 + * If any ways are blocked for all cores and the HW blocks, then those 172 + * ways will never have any cache lines evicted from them. All cores 173 + * and the hardware blocks are free to read from all ways regardless 174 + * of the partitioning. 175 + */ 176 + int cvmx_l2c_set_core_way_partition(uint32_t core, uint32_t mask); 177 + 178 + /** 179 + * Return the L2 Cache way partitioning for the hw blocks. 180 + * 181 + * Returns The mask specifying the reserved way. 0 bits in mask indicates 182 + * the cache 'ways' that a core can evict from. 183 + * -1 on error 184 + */ 185 + int cvmx_l2c_get_hw_way_partition(void); 186 + 187 + /** 188 + * Partitions the L2 cache for the hardware blocks. 189 + * 190 + * @mask: The partitioning of the ways expressed as a binary mask. A 0 191 + * bit allows the core to evict cache lines from a way, while a 192 + * 1 bit blocks the core from evicting any lines from that 193 + * way. There must be at least one allowed way (0 bit) in the 194 + * mask. 195 + * 196 + * If any ways are blocked for all cores and the HW blocks, then those 197 + * ways will never have any cache lines evicted from them. All cores 198 + * and the hardware blocks are free to read from all ways regardless 199 + * of the partitioning. 200 + */ 201 + int cvmx_l2c_set_hw_way_partition(uint32_t mask); 202 + 203 + /** 204 + * Locks a line in the L2 cache at the specified physical address 205 + * 206 + * @addr: physical address of line to lock 207 + * 208 + * Returns 0 on success, 209 + * 1 if line not locked. 210 + */ 211 + int cvmx_l2c_lock_line(uint64_t addr); 212 + 213 + /** 214 + * Locks a specified memory region in the L2 cache. 215 + * 216 + * Note that if not all lines can be locked, that means that all 217 + * but one of the ways (associations) available to the locking 218 + * core are locked. Having only 1 association available for 219 + * normal caching may have a significant adverse affect on performance. 220 + * Care should be taken to ensure that enough of the L2 cache is left 221 + * unlocked to allow for normal caching of DRAM. 222 + * 223 + * @start: Physical address of the start of the region to lock 224 + * @len: Length (in bytes) of region to lock 225 + * 226 + * Returns Number of requested lines that where not locked. 227 + * 0 on success (all locked) 228 + */ 229 + int cvmx_l2c_lock_mem_region(uint64_t start, uint64_t len); 230 + 231 + /** 232 + * Unlock and flush a cache line from the L2 cache. 233 + * IMPORTANT: Must only be run by one core at a time due to use 234 + * of L2C debug features. 235 + * Note that this function will flush a matching but unlocked cache line. 236 + * (If address is not in L2, no lines are flushed.) 237 + * 238 + * @address: Physical address to unlock 239 + * 240 + * Returns 0: line not unlocked 241 + * 1: line unlocked 242 + */ 243 + int cvmx_l2c_unlock_line(uint64_t address); 244 + 245 + /** 246 + * Unlocks a region of memory that is locked in the L2 cache 247 + * 248 + * @start: start physical address 249 + * @len: length (in bytes) to unlock 250 + * 251 + * Returns Number of locked lines that the call unlocked 252 + */ 253 + int cvmx_l2c_unlock_mem_region(uint64_t start, uint64_t len); 254 + 255 + /** 256 + * Read the L2 controller tag for a given location in L2 257 + * 258 + * @association: 259 + * Which association to read line from 260 + * @index: Which way to read from. 261 + * 262 + * Returns l2c tag structure for line requested. 263 + */ 264 + union cvmx_l2c_tag cvmx_l2c_get_tag(uint32_t association, uint32_t index); 265 + 266 + /* Wrapper around deprecated old function name */ 267 + static inline union cvmx_l2c_tag cvmx_get_l2c_tag(uint32_t association, 268 + uint32_t index) 269 + { 270 + return cvmx_l2c_get_tag(association, index); 271 + } 272 + 273 + /** 274 + * Returns the cache index for a given physical address 275 + * 276 + * @addr: physical address 277 + * 278 + * Returns L2 cache index 279 + */ 280 + uint32_t cvmx_l2c_address_to_index(uint64_t addr); 281 + 282 + /** 283 + * Flushes (and unlocks) the entire L2 cache. 284 + * IMPORTANT: Must only be run by one core at a time due to use 285 + * of L2C debug features. 286 + */ 287 + void cvmx_l2c_flush(void); 288 + 289 + /** 290 + * 291 + * Returns Returns the size of the L2 cache in bytes, 292 + * -1 on error (unrecognized model) 293 + */ 294 + int cvmx_l2c_get_cache_size_bytes(void); 295 + 296 + /** 297 + * Return the number of sets in the L2 Cache 298 + * 299 + * Returns 300 + */ 301 + int cvmx_l2c_get_num_sets(void); 302 + 303 + /** 304 + * Return log base 2 of the number of sets in the L2 cache 305 + * Returns 306 + */ 307 + int cvmx_l2c_get_set_bits(void); 308 + /** 309 + * Return the number of associations in the L2 Cache 310 + * 311 + * Returns 312 + */ 313 + int cvmx_l2c_get_num_assoc(void); 314 + 315 + /** 316 + * Flush a line from the L2 cache 317 + * This should only be called from one core at a time, as this routine 318 + * sets the core to the 'debug' core in order to flush the line. 319 + * 320 + * @assoc: Association (or way) to flush 321 + * @index: Index to flush 322 + */ 323 + void cvmx_l2c_flush_line(uint32_t assoc, uint32_t index); 324 + 325 + #endif /* __CVMX_L2C_H__ */
+61
arch/mips/include/asm/octeon/cvmx-packet.h
··· 1 + /***********************license start*************** 2 + * Author: Cavium Networks 3 + * 4 + * Contact: support@caviumnetworks.com 5 + * This file is part of the OCTEON SDK 6 + * 7 + * Copyright (c) 2003-2008 Cavium Networks 8 + * 9 + * This file is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License, Version 2, as 11 + * published by the Free Software Foundation. 12 + * 13 + * This file is distributed in the hope that it will be useful, but 14 + * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 15 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 16 + * NONINFRINGEMENT. See the GNU General Public License for more 17 + * details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with this file; if not, write to the Free Software 21 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 + * or visit http://www.gnu.org/licenses/. 23 + * 24 + * This file may also be available under a different license from Cavium. 25 + * Contact Cavium Networks for more information 26 + ***********************license end**************************************/ 27 + 28 + /* 29 + * Packet buffer defines. 30 + */ 31 + 32 + #ifndef __CVMX_PACKET_H__ 33 + #define __CVMX_PACKET_H__ 34 + 35 + /** 36 + * This structure defines a buffer pointer on Octeon 37 + */ 38 + union cvmx_buf_ptr { 39 + void *ptr; 40 + uint64_t u64; 41 + struct { 42 + /* if set, invert the "free" pick of the overall 43 + * packet. HW always sets this bit to 0 on inbound 44 + * packet */ 45 + uint64_t i:1; 46 + 47 + /* Indicates the amount to back up to get to the 48 + * buffer start in cache lines. In most cases this is 49 + * less than one complete cache line, so the value is 50 + * zero */ 51 + uint64_t back:4; 52 + /* The pool that the buffer came from / goes to */ 53 + uint64_t pool:3; 54 + /* The size of the segment pointed to by addr (in bytes) */ 55 + uint64_t size:16; 56 + /* Pointer to the first byte of the data, NOT buffer */ 57 + uint64_t addr:40; 58 + } s; 59 + }; 60 + 61 + #endif /* __CVMX_PACKET_H__ */
+232
arch/mips/include/asm/octeon/cvmx-spinlock.h
··· 1 + /***********************license start*************** 2 + * Author: Cavium Networks 3 + * 4 + * Contact: support@caviumnetworks.com 5 + * This file is part of the OCTEON SDK 6 + * 7 + * Copyright (c) 2003-2008 Cavium Networks 8 + * 9 + * This file is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License, Version 2, as 11 + * published by the Free Software Foundation. 12 + * 13 + * This file is distributed in the hope that it will be useful, but 14 + * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 15 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 16 + * NONINFRINGEMENT. See the GNU General Public License for more 17 + * details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with this file; if not, write to the Free Software 21 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 + * or visit http://www.gnu.org/licenses/. 23 + * 24 + * This file may also be available under a different license from Cavium. 25 + * Contact Cavium Networks for more information 26 + ***********************license end**************************************/ 27 + 28 + /** 29 + * Implementation of spinlocks for Octeon CVMX. Although similar in 30 + * function to Linux kernel spinlocks, they are not compatible. 31 + * Octeon CVMX spinlocks are only used to synchronize with the boot 32 + * monitor and other non-Linux programs running in the system. 33 + */ 34 + 35 + #ifndef __CVMX_SPINLOCK_H__ 36 + #define __CVMX_SPINLOCK_H__ 37 + 38 + #include "cvmx-asm.h" 39 + 40 + /* Spinlocks for Octeon */ 41 + 42 + /* define these to enable recursive spinlock debugging */ 43 + /*#define CVMX_SPINLOCK_DEBUG */ 44 + 45 + /** 46 + * Spinlocks for Octeon CVMX 47 + */ 48 + typedef struct { 49 + volatile uint32_t value; 50 + } cvmx_spinlock_t; 51 + 52 + /* note - macros not expanded in inline ASM, so values hardcoded */ 53 + #define CVMX_SPINLOCK_UNLOCKED_VAL 0 54 + #define CVMX_SPINLOCK_LOCKED_VAL 1 55 + 56 + #define CVMX_SPINLOCK_UNLOCKED_INITIALIZER {CVMX_SPINLOCK_UNLOCKED_VAL} 57 + 58 + /** 59 + * Initialize a spinlock 60 + * 61 + * @lock: Lock to initialize 62 + */ 63 + static inline void cvmx_spinlock_init(cvmx_spinlock_t *lock) 64 + { 65 + lock->value = CVMX_SPINLOCK_UNLOCKED_VAL; 66 + } 67 + 68 + /** 69 + * Return non-zero if the spinlock is currently locked 70 + * 71 + * @lock: Lock to check 72 + * Returns Non-zero if locked 73 + */ 74 + static inline int cvmx_spinlock_locked(cvmx_spinlock_t *lock) 75 + { 76 + return lock->value != CVMX_SPINLOCK_UNLOCKED_VAL; 77 + } 78 + 79 + /** 80 + * Releases lock 81 + * 82 + * @lock: pointer to lock structure 83 + */ 84 + static inline void cvmx_spinlock_unlock(cvmx_spinlock_t *lock) 85 + { 86 + CVMX_SYNCWS; 87 + lock->value = 0; 88 + CVMX_SYNCWS; 89 + } 90 + 91 + /** 92 + * Attempts to take the lock, but does not spin if lock is not available. 93 + * May take some time to acquire the lock even if it is available 94 + * due to the ll/sc not succeeding. 95 + * 96 + * @lock: pointer to lock structure 97 + * 98 + * Returns 0: lock successfully taken 99 + * 1: lock not taken, held by someone else 100 + * These return values match the Linux semantics. 101 + */ 102 + 103 + static inline unsigned int cvmx_spinlock_trylock(cvmx_spinlock_t *lock) 104 + { 105 + unsigned int tmp; 106 + 107 + __asm__ __volatile__(".set noreorder \n" 108 + "1: ll %[tmp], %[val] \n" 109 + /* if lock held, fail immediately */ 110 + " bnez %[tmp], 2f \n" 111 + " li %[tmp], 1 \n" 112 + " sc %[tmp], %[val] \n" 113 + " beqz %[tmp], 1b \n" 114 + " li %[tmp], 0 \n" 115 + "2: \n" 116 + ".set reorder \n" : 117 + [val] "+m"(lock->value), [tmp] "=&r"(tmp) 118 + : : "memory"); 119 + 120 + return tmp != 0; /* normalize to 0 or 1 */ 121 + } 122 + 123 + /** 124 + * Gets lock, spins until lock is taken 125 + * 126 + * @lock: pointer to lock structure 127 + */ 128 + static inline void cvmx_spinlock_lock(cvmx_spinlock_t *lock) 129 + { 130 + unsigned int tmp; 131 + 132 + __asm__ __volatile__(".set noreorder \n" 133 + "1: ll %[tmp], %[val] \n" 134 + " bnez %[tmp], 1b \n" 135 + " li %[tmp], 1 \n" 136 + " sc %[tmp], %[val] \n" 137 + " beqz %[tmp], 1b \n" 138 + " nop \n" 139 + ".set reorder \n" : 140 + [val] "+m"(lock->value), [tmp] "=&r"(tmp) 141 + : : "memory"); 142 + 143 + } 144 + 145 + /** ******************************************************************** 146 + * Bit spinlocks 147 + * These spinlocks use a single bit (bit 31) of a 32 bit word for locking. 148 + * The rest of the bits in the word are left undisturbed. This enables more 149 + * compact data structures as only 1 bit is consumed for the lock. 150 + * 151 + */ 152 + 153 + /** 154 + * Gets lock, spins until lock is taken 155 + * Preserves the low 31 bits of the 32 bit 156 + * word used for the lock. 157 + * 158 + * 159 + * @word: word to lock bit 31 of 160 + */ 161 + static inline void cvmx_spinlock_bit_lock(uint32_t *word) 162 + { 163 + unsigned int tmp; 164 + unsigned int sav; 165 + 166 + __asm__ __volatile__(".set noreorder \n" 167 + ".set noat \n" 168 + "1: ll %[tmp], %[val] \n" 169 + " bbit1 %[tmp], 31, 1b \n" 170 + " li $at, 1 \n" 171 + " ins %[tmp], $at, 31, 1 \n" 172 + " sc %[tmp], %[val] \n" 173 + " beqz %[tmp], 1b \n" 174 + " nop \n" 175 + ".set at \n" 176 + ".set reorder \n" : 177 + [val] "+m"(*word), [tmp] "=&r"(tmp), [sav] "=&r"(sav) 178 + : : "memory"); 179 + 180 + } 181 + 182 + /** 183 + * Attempts to get lock, returns immediately with success/failure 184 + * Preserves the low 31 bits of the 32 bit 185 + * word used for the lock. 186 + * 187 + * 188 + * @word: word to lock bit 31 of 189 + * Returns 0: lock successfully taken 190 + * 1: lock not taken, held by someone else 191 + * These return values match the Linux semantics. 192 + */ 193 + static inline unsigned int cvmx_spinlock_bit_trylock(uint32_t *word) 194 + { 195 + unsigned int tmp; 196 + 197 + __asm__ __volatile__(".set noreorder\n\t" 198 + ".set noat\n" 199 + "1: ll %[tmp], %[val] \n" 200 + /* if lock held, fail immediately */ 201 + " bbit1 %[tmp], 31, 2f \n" 202 + " li $at, 1 \n" 203 + " ins %[tmp], $at, 31, 1 \n" 204 + " sc %[tmp], %[val] \n" 205 + " beqz %[tmp], 1b \n" 206 + " li %[tmp], 0 \n" 207 + "2: \n" 208 + ".set at \n" 209 + ".set reorder \n" : 210 + [val] "+m"(*word), [tmp] "=&r"(tmp) 211 + : : "memory"); 212 + 213 + return tmp != 0; /* normalize to 0 or 1 */ 214 + } 215 + 216 + /** 217 + * Releases bit lock 218 + * 219 + * Unconditionally clears bit 31 of the lock word. Note that this is 220 + * done non-atomically, as this implementation assumes that the rest 221 + * of the bits in the word are protected by the lock. 222 + * 223 + * @word: word to unlock bit 31 in 224 + */ 225 + static inline void cvmx_spinlock_bit_unlock(uint32_t *word) 226 + { 227 + CVMX_SYNCWS; 228 + *word &= ~(1UL << 31); 229 + CVMX_SYNCWS; 230 + } 231 + 232 + #endif /* __CVMX_SPINLOCK_H__ */
+152
arch/mips/include/asm/octeon/cvmx-sysinfo.h
··· 1 + /***********************license start*************** 2 + * Author: Cavium Networks 3 + * 4 + * Contact: support@caviumnetworks.com 5 + * This file is part of the OCTEON SDK 6 + * 7 + * Copyright (c) 2003-2008 Cavium Networks 8 + * 9 + * This file is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License, Version 2, as 11 + * published by the Free Software Foundation. 12 + * 13 + * This file is distributed in the hope that it will be useful, but 14 + * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 15 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 16 + * NONINFRINGEMENT. See the GNU General Public License for more 17 + * details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with this file; if not, write to the Free Software 21 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 + * or visit http://www.gnu.org/licenses/. 23 + * 24 + * This file may also be available under a different license from Cavium. 25 + * Contact Cavium Networks for more information 26 + ***********************license end**************************************/ 27 + 28 + /* 29 + * This module provides system/board information obtained by the bootloader. 30 + */ 31 + 32 + #ifndef __CVMX_SYSINFO_H__ 33 + #define __CVMX_SYSINFO_H__ 34 + 35 + #define OCTEON_SERIAL_LEN 20 36 + /** 37 + * Structure describing application specific information. 38 + * __cvmx_app_init() populates this from the cvmx boot descriptor. 39 + * This structure is private to simple executive applications, so 40 + * no versioning is required. 41 + * 42 + * This structure must be provided with some fields set in order to 43 + * use simple executive functions in other applications (Linux kernel, 44 + * u-boot, etc.) The cvmx_sysinfo_minimal_initialize() function is 45 + * provided to set the required values in these cases. 46 + */ 47 + struct cvmx_sysinfo { 48 + /* System wide variables */ 49 + /* installed DRAM in system, in bytes */ 50 + uint64_t system_dram_size; 51 + 52 + /* ptr to memory descriptor block */ 53 + void *phy_mem_desc_ptr; 54 + 55 + 56 + /* Application image specific variables */ 57 + /* stack top address (virtual) */ 58 + uint64_t stack_top; 59 + /* heap base address (virtual) */ 60 + uint64_t heap_base; 61 + /* stack size in bytes */ 62 + uint32_t stack_size; 63 + /* heap size in bytes */ 64 + uint32_t heap_size; 65 + /* coremask defining cores running application */ 66 + uint32_t core_mask; 67 + /* Deprecated, use cvmx_coremask_first_core() to select init core */ 68 + uint32_t init_core; 69 + 70 + /* exception base address, as set by bootloader */ 71 + uint64_t exception_base_addr; 72 + 73 + /* cpu clock speed in hz */ 74 + uint32_t cpu_clock_hz; 75 + 76 + /* dram data rate in hz (data rate = 2 * clock rate */ 77 + uint32_t dram_data_rate_hz; 78 + 79 + 80 + uint16_t board_type; 81 + uint8_t board_rev_major; 82 + uint8_t board_rev_minor; 83 + uint8_t mac_addr_base[6]; 84 + uint8_t mac_addr_count; 85 + char board_serial_number[OCTEON_SERIAL_LEN]; 86 + /* 87 + * Several boards support compact flash on the Octeon boot 88 + * bus. The CF memory spaces may be mapped to different 89 + * addresses on different boards. These values will be 0 if 90 + * CF is not present. Note that these addresses are physical 91 + * addresses, and it is up to the application to use the 92 + * proper addressing mode (XKPHYS, KSEG0, etc.) 93 + */ 94 + uint64_t compact_flash_common_base_addr; 95 + uint64_t compact_flash_attribute_base_addr; 96 + /* 97 + * Base address of the LED display (as on EBT3000 board) This 98 + * will be 0 if LED display not present. Note that this 99 + * address is a physical address, and it is up to the 100 + * application to use the proper addressing mode (XKPHYS, 101 + * KSEG0, etc.) 102 + */ 103 + uint64_t led_display_base_addr; 104 + /* DFA reference clock in hz (if applicable)*/ 105 + uint32_t dfa_ref_clock_hz; 106 + /* configuration flags from bootloader */ 107 + uint32_t bootloader_config_flags; 108 + 109 + /* Uart number used for console */ 110 + uint8_t console_uart_num; 111 + }; 112 + 113 + /** 114 + * This function returns the system/board information as obtained 115 + * by the bootloader. 116 + * 117 + * 118 + * Returns Pointer to the boot information structure 119 + * 120 + */ 121 + 122 + extern struct cvmx_sysinfo *cvmx_sysinfo_get(void); 123 + 124 + /** 125 + * This function is used in non-simple executive environments (such as 126 + * Linux kernel, u-boot, etc.) to configure the minimal fields that 127 + * are required to use simple executive files directly. 128 + * 129 + * Locking (if required) must be handled outside of this 130 + * function 131 + * 132 + * @phy_mem_desc_ptr: Pointer to global physical memory descriptor 133 + * (bootmem descriptor) @board_type: Octeon board 134 + * type enumeration 135 + * 136 + * @board_rev_major: 137 + * Board major revision 138 + * @board_rev_minor: 139 + * Board minor revision 140 + * @cpu_clock_hz: 141 + * CPU clock freqency in hertz 142 + * 143 + * Returns 0: Failure 144 + * 1: success 145 + */ 146 + extern int cvmx_sysinfo_minimal_initialize(void *phy_mem_desc_ptr, 147 + uint16_t board_type, 148 + uint8_t board_rev_major, 149 + uint8_t board_rev_minor, 150 + uint32_t cpu_clock_hz); 151 + 152 + #endif /* __CVMX_SYSINFO_H__ */
+505
arch/mips/include/asm/octeon/cvmx.h
··· 1 + /***********************license start*************** 2 + * Author: Cavium Networks 3 + * 4 + * Contact: support@caviumnetworks.com 5 + * This file is part of the OCTEON SDK 6 + * 7 + * Copyright (c) 2003-2008 Cavium Networks 8 + * 9 + * This file is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License, Version 2, as 11 + * published by the Free Software Foundation. 12 + * 13 + * This file is distributed in the hope that it will be useful, but 14 + * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 15 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 16 + * NONINFRINGEMENT. See the GNU General Public License for more 17 + * details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with this file; if not, write to the Free Software 21 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 + * or visit http://www.gnu.org/licenses/. 23 + * 24 + * This file may also be available under a different license from Cavium. 25 + * Contact Cavium Networks for more information 26 + ***********************license end**************************************/ 27 + 28 + #ifndef __CVMX_H__ 29 + #define __CVMX_H__ 30 + 31 + #include <linux/kernel.h> 32 + #include <linux/string.h> 33 + 34 + #include "cvmx-asm.h" 35 + #include "cvmx-packet.h" 36 + #include "cvmx-sysinfo.h" 37 + 38 + #include "cvmx-ciu-defs.h" 39 + #include "cvmx-gpio-defs.h" 40 + #include "cvmx-iob-defs.h" 41 + #include "cvmx-ipd-defs.h" 42 + #include "cvmx-l2c-defs.h" 43 + #include "cvmx-l2d-defs.h" 44 + #include "cvmx-l2t-defs.h" 45 + #include "cvmx-led-defs.h" 46 + #include "cvmx-mio-defs.h" 47 + #include "cvmx-pow-defs.h" 48 + 49 + #include "cvmx-bootinfo.h" 50 + #include "cvmx-bootmem.h" 51 + #include "cvmx-l2c.h" 52 + 53 + #ifndef CVMX_ENABLE_DEBUG_PRINTS 54 + #define CVMX_ENABLE_DEBUG_PRINTS 1 55 + #endif 56 + 57 + #if CVMX_ENABLE_DEBUG_PRINTS 58 + #define cvmx_dprintf printk 59 + #else 60 + #define cvmx_dprintf(...) {} 61 + #endif 62 + 63 + #define CVMX_MAX_CORES (16) 64 + #define CVMX_CACHE_LINE_SIZE (128) /* In bytes */ 65 + #define CVMX_CACHE_LINE_MASK (CVMX_CACHE_LINE_SIZE - 1) /* In bytes */ 66 + #define CVMX_CACHE_LINE_ALIGNED __attribute__ ((aligned(CVMX_CACHE_LINE_SIZE))) 67 + #define CAST64(v) ((long long)(long)(v)) 68 + #define CASTPTR(type, v) ((type *)(long)(v)) 69 + 70 + /* 71 + * Returns processor ID, different Linux and simple exec versions 72 + * provided in the cvmx-app-init*.c files. 73 + */ 74 + static inline uint32_t cvmx_get_proc_id(void) __attribute__ ((pure)); 75 + static inline uint32_t cvmx_get_proc_id(void) 76 + { 77 + uint32_t id; 78 + asm("mfc0 %0, $15,0" : "=r"(id)); 79 + return id; 80 + } 81 + 82 + /* turn the variable name into a string */ 83 + #define CVMX_TMP_STR(x) CVMX_TMP_STR2(x) 84 + #define CVMX_TMP_STR2(x) #x 85 + 86 + /** 87 + * Builds a bit mask given the required size in bits. 88 + * 89 + * @bits: Number of bits in the mask 90 + * Returns The mask 91 + */ static inline uint64_t cvmx_build_mask(uint64_t bits) 92 + { 93 + return ~((~0x0ull) << bits); 94 + } 95 + 96 + /** 97 + * Builds a memory address for I/O based on the Major and Sub DID. 98 + * 99 + * @major_did: 5 bit major did 100 + * @sub_did: 3 bit sub did 101 + * Returns I/O base address 102 + */ 103 + static inline uint64_t cvmx_build_io_address(uint64_t major_did, 104 + uint64_t sub_did) 105 + { 106 + return (0x1ull << 48) | (major_did << 43) | (sub_did << 40); 107 + } 108 + 109 + /** 110 + * Perform mask and shift to place the supplied value into 111 + * the supplied bit rage. 112 + * 113 + * Example: cvmx_build_bits(39,24,value) 114 + * <pre> 115 + * 6 5 4 3 3 2 1 116 + * 3 5 7 9 1 3 5 7 0 117 + * +-------+-------+-------+-------+-------+-------+-------+------+ 118 + * 000000000000000000000000___________value000000000000000000000000 119 + * </pre> 120 + * 121 + * @high_bit: Highest bit value can occupy (inclusive) 0-63 122 + * @low_bit: Lowest bit value can occupy inclusive 0-high_bit 123 + * @value: Value to use 124 + * Returns Value masked and shifted 125 + */ 126 + static inline uint64_t cvmx_build_bits(uint64_t high_bit, 127 + uint64_t low_bit, uint64_t value) 128 + { 129 + return (value & cvmx_build_mask(high_bit - low_bit + 1)) << low_bit; 130 + } 131 + 132 + enum cvmx_mips_space { 133 + CVMX_MIPS_SPACE_XKSEG = 3LL, 134 + CVMX_MIPS_SPACE_XKPHYS = 2LL, 135 + CVMX_MIPS_SPACE_XSSEG = 1LL, 136 + CVMX_MIPS_SPACE_XUSEG = 0LL 137 + }; 138 + 139 + /* These macros for use when using 32 bit pointers. */ 140 + #define CVMX_MIPS32_SPACE_KSEG0 1l 141 + #define CVMX_ADD_SEG32(segment, add) \ 142 + (((int32_t)segment << 31) | (int32_t)(add)) 143 + 144 + #define CVMX_IO_SEG CVMX_MIPS_SPACE_XKPHYS 145 + 146 + /* These macros simplify the process of creating common IO addresses */ 147 + #define CVMX_ADD_SEG(segment, add) \ 148 + ((((uint64_t)segment) << 62) | (add)) 149 + #ifndef CVMX_ADD_IO_SEG 150 + #define CVMX_ADD_IO_SEG(add) CVMX_ADD_SEG(CVMX_IO_SEG, (add)) 151 + #endif 152 + 153 + /** 154 + * Convert a memory pointer (void*) into a hardware compatable 155 + * memory address (uint64_t). Octeon hardware widgets don't 156 + * understand logical addresses. 157 + * 158 + * @ptr: C style memory pointer 159 + * Returns Hardware physical address 160 + */ 161 + static inline uint64_t cvmx_ptr_to_phys(void *ptr) 162 + { 163 + if (sizeof(void *) == 8) { 164 + /* 165 + * We're running in 64 bit mode. Normally this means 166 + * that we can use 40 bits of address space (the 167 + * hardware limit). Unfortunately there is one case 168 + * were we need to limit this to 30 bits, sign 169 + * extended 32 bit. Although these are 64 bits wide, 170 + * only 30 bits can be used. 171 + */ 172 + if ((CAST64(ptr) >> 62) == 3) 173 + return CAST64(ptr) & cvmx_build_mask(30); 174 + else 175 + return CAST64(ptr) & cvmx_build_mask(40); 176 + } else { 177 + return (long)(ptr) & 0x1fffffff; 178 + } 179 + } 180 + 181 + /** 182 + * Convert a hardware physical address (uint64_t) into a 183 + * memory pointer (void *). 184 + * 185 + * @physical_address: 186 + * Hardware physical address to memory 187 + * Returns Pointer to memory 188 + */ 189 + static inline void *cvmx_phys_to_ptr(uint64_t physical_address) 190 + { 191 + if (sizeof(void *) == 8) { 192 + /* Just set the top bit, avoiding any TLB uglyness */ 193 + return CASTPTR(void, 194 + CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, 195 + physical_address)); 196 + } else { 197 + return CASTPTR(void, 198 + CVMX_ADD_SEG32(CVMX_MIPS32_SPACE_KSEG0, 199 + physical_address)); 200 + } 201 + } 202 + 203 + /* The following #if controls the definition of the macro 204 + CVMX_BUILD_WRITE64. This macro is used to build a store operation to 205 + a full 64bit address. With a 64bit ABI, this can be done with a simple 206 + pointer access. 32bit ABIs require more complicated assembly */ 207 + 208 + /* We have a full 64bit ABI. Writing to a 64bit address can be done with 209 + a simple volatile pointer */ 210 + #define CVMX_BUILD_WRITE64(TYPE, ST) \ 211 + static inline void cvmx_write64_##TYPE(uint64_t addr, TYPE##_t val) \ 212 + { \ 213 + *CASTPTR(volatile TYPE##_t, addr) = val; \ 214 + } 215 + 216 + 217 + /* The following #if controls the definition of the macro 218 + CVMX_BUILD_READ64. This macro is used to build a load operation from 219 + a full 64bit address. With a 64bit ABI, this can be done with a simple 220 + pointer access. 32bit ABIs require more complicated assembly */ 221 + 222 + /* We have a full 64bit ABI. Writing to a 64bit address can be done with 223 + a simple volatile pointer */ 224 + #define CVMX_BUILD_READ64(TYPE, LT) \ 225 + static inline TYPE##_t cvmx_read64_##TYPE(uint64_t addr) \ 226 + { \ 227 + return *CASTPTR(volatile TYPE##_t, addr); \ 228 + } 229 + 230 + 231 + /* The following defines 8 functions for writing to a 64bit address. Each 232 + takes two arguments, the address and the value to write. 233 + cvmx_write64_int64 cvmx_write64_uint64 234 + cvmx_write64_int32 cvmx_write64_uint32 235 + cvmx_write64_int16 cvmx_write64_uint16 236 + cvmx_write64_int8 cvmx_write64_uint8 */ 237 + CVMX_BUILD_WRITE64(int64, "sd"); 238 + CVMX_BUILD_WRITE64(int32, "sw"); 239 + CVMX_BUILD_WRITE64(int16, "sh"); 240 + CVMX_BUILD_WRITE64(int8, "sb"); 241 + CVMX_BUILD_WRITE64(uint64, "sd"); 242 + CVMX_BUILD_WRITE64(uint32, "sw"); 243 + CVMX_BUILD_WRITE64(uint16, "sh"); 244 + CVMX_BUILD_WRITE64(uint8, "sb"); 245 + #define cvmx_write64 cvmx_write64_uint64 246 + 247 + /* The following defines 8 functions for reading from a 64bit address. Each 248 + takes the address as the only argument 249 + cvmx_read64_int64 cvmx_read64_uint64 250 + cvmx_read64_int32 cvmx_read64_uint32 251 + cvmx_read64_int16 cvmx_read64_uint16 252 + cvmx_read64_int8 cvmx_read64_uint8 */ 253 + CVMX_BUILD_READ64(int64, "ld"); 254 + CVMX_BUILD_READ64(int32, "lw"); 255 + CVMX_BUILD_READ64(int16, "lh"); 256 + CVMX_BUILD_READ64(int8, "lb"); 257 + CVMX_BUILD_READ64(uint64, "ld"); 258 + CVMX_BUILD_READ64(uint32, "lw"); 259 + CVMX_BUILD_READ64(uint16, "lhu"); 260 + CVMX_BUILD_READ64(uint8, "lbu"); 261 + #define cvmx_read64 cvmx_read64_uint64 262 + 263 + 264 + static inline void cvmx_write_csr(uint64_t csr_addr, uint64_t val) 265 + { 266 + cvmx_write64(csr_addr, val); 267 + 268 + /* 269 + * Perform an immediate read after every write to an RSL 270 + * register to force the write to complete. It doesn't matter 271 + * what RSL read we do, so we choose CVMX_MIO_BOOT_BIST_STAT 272 + * because it is fast and harmless. 273 + */ 274 + if ((csr_addr >> 40) == (0x800118)) 275 + cvmx_read64(CVMX_MIO_BOOT_BIST_STAT); 276 + } 277 + 278 + static inline void cvmx_write_io(uint64_t io_addr, uint64_t val) 279 + { 280 + cvmx_write64(io_addr, val); 281 + 282 + } 283 + 284 + static inline uint64_t cvmx_read_csr(uint64_t csr_addr) 285 + { 286 + uint64_t val = cvmx_read64(csr_addr); 287 + return val; 288 + } 289 + 290 + 291 + static inline void cvmx_send_single(uint64_t data) 292 + { 293 + const uint64_t CVMX_IOBDMA_SENDSINGLE = 0xffffffffffffa200ull; 294 + cvmx_write64(CVMX_IOBDMA_SENDSINGLE, data); 295 + } 296 + 297 + static inline void cvmx_read_csr_async(uint64_t scraddr, uint64_t csr_addr) 298 + { 299 + union { 300 + uint64_t u64; 301 + struct { 302 + uint64_t scraddr:8; 303 + uint64_t len:8; 304 + uint64_t addr:48; 305 + } s; 306 + } addr; 307 + addr.u64 = csr_addr; 308 + addr.s.scraddr = scraddr >> 3; 309 + addr.s.len = 1; 310 + cvmx_send_single(addr.u64); 311 + } 312 + 313 + /* Return true if Octeon is CN38XX pass 1 */ 314 + static inline int cvmx_octeon_is_pass1(void) 315 + { 316 + #if OCTEON_IS_COMMON_BINARY() 317 + return 0; /* Pass 1 isn't supported for common binaries */ 318 + #else 319 + /* Now that we know we're built for a specific model, only check CN38XX */ 320 + #if OCTEON_IS_MODEL(OCTEON_CN38XX) 321 + return cvmx_get_proc_id() == OCTEON_CN38XX_PASS1; 322 + #else 323 + return 0; /* Built for non CN38XX chip, we're not CN38XX pass1 */ 324 + #endif 325 + #endif 326 + } 327 + 328 + static inline unsigned int cvmx_get_core_num(void) 329 + { 330 + unsigned int core_num; 331 + CVMX_RDHWRNV(core_num, 0); 332 + return core_num; 333 + } 334 + 335 + /** 336 + * Returns the number of bits set in the provided value. 337 + * Simple wrapper for POP instruction. 338 + * 339 + * @val: 32 bit value to count set bits in 340 + * 341 + * Returns Number of bits set 342 + */ 343 + static inline uint32_t cvmx_pop(uint32_t val) 344 + { 345 + uint32_t pop; 346 + CVMX_POP(pop, val); 347 + return pop; 348 + } 349 + 350 + /** 351 + * Returns the number of bits set in the provided value. 352 + * Simple wrapper for DPOP instruction. 353 + * 354 + * @val: 64 bit value to count set bits in 355 + * 356 + * Returns Number of bits set 357 + */ 358 + static inline int cvmx_dpop(uint64_t val) 359 + { 360 + int pop; 361 + CVMX_DPOP(pop, val); 362 + return pop; 363 + } 364 + 365 + /** 366 + * Provide current cycle counter as a return value 367 + * 368 + * Returns current cycle counter 369 + */ 370 + 371 + static inline uint64_t cvmx_get_cycle(void) 372 + { 373 + uint64_t cycle; 374 + CVMX_RDHWR(cycle, 31); 375 + return cycle; 376 + } 377 + 378 + /** 379 + * Reads a chip global cycle counter. This counts CPU cycles since 380 + * chip reset. The counter is 64 bit. 381 + * This register does not exist on CN38XX pass 1 silicion 382 + * 383 + * Returns Global chip cycle count since chip reset. 384 + */ 385 + static inline uint64_t cvmx_get_cycle_global(void) 386 + { 387 + if (cvmx_octeon_is_pass1()) 388 + return 0; 389 + else 390 + return cvmx_read64(CVMX_IPD_CLK_COUNT); 391 + } 392 + 393 + /** 394 + * This macro spins on a field waiting for it to reach a value. It 395 + * is common in code to need to wait for a specific field in a CSR 396 + * to match a specific value. Conceptually this macro expands to: 397 + * 398 + * 1) read csr at "address" with a csr typedef of "type" 399 + * 2) Check if ("type".s."field" "op" "value") 400 + * 3) If #2 isn't true loop to #1 unless too much time has passed. 401 + */ 402 + #define CVMX_WAIT_FOR_FIELD64(address, type, field, op, value, timeout_usec)\ 403 + ( \ 404 + { \ 405 + int result; \ 406 + do { \ 407 + uint64_t done = cvmx_get_cycle() + (uint64_t)timeout_usec * \ 408 + cvmx_sysinfo_get()->cpu_clock_hz / 1000000; \ 409 + type c; \ 410 + while (1) { \ 411 + c.u64 = cvmx_read_csr(address); \ 412 + if ((c.s.field) op(value)) { \ 413 + result = 0; \ 414 + break; \ 415 + } else if (cvmx_get_cycle() > done) { \ 416 + result = -1; \ 417 + break; \ 418 + } else \ 419 + cvmx_wait(100); \ 420 + } \ 421 + } while (0); \ 422 + result; \ 423 + }) 424 + 425 + /***************************************************************************/ 426 + 427 + static inline void cvmx_reset_octeon(void) 428 + { 429 + union cvmx_ciu_soft_rst ciu_soft_rst; 430 + ciu_soft_rst.u64 = 0; 431 + ciu_soft_rst.s.soft_rst = 1; 432 + cvmx_write_csr(CVMX_CIU_SOFT_RST, ciu_soft_rst.u64); 433 + } 434 + 435 + /* Return the number of cores available in the chip */ 436 + static inline uint32_t cvmx_octeon_num_cores(void) 437 + { 438 + uint32_t ciu_fuse = (uint32_t) cvmx_read_csr(CVMX_CIU_FUSE) & 0xffff; 439 + return cvmx_pop(ciu_fuse); 440 + } 441 + 442 + /** 443 + * Read a byte of fuse data 444 + * @byte_addr: address to read 445 + * 446 + * Returns fuse value: 0 or 1 447 + */ 448 + static uint8_t cvmx_fuse_read_byte(int byte_addr) 449 + { 450 + union cvmx_mio_fus_rcmd read_cmd; 451 + 452 + read_cmd.u64 = 0; 453 + read_cmd.s.addr = byte_addr; 454 + read_cmd.s.pend = 1; 455 + cvmx_write_csr(CVMX_MIO_FUS_RCMD, read_cmd.u64); 456 + while ((read_cmd.u64 = cvmx_read_csr(CVMX_MIO_FUS_RCMD)) 457 + && read_cmd.s.pend) 458 + ; 459 + return read_cmd.s.dat; 460 + } 461 + 462 + /** 463 + * Read a single fuse bit 464 + * 465 + * @fuse: Fuse number (0-1024) 466 + * 467 + * Returns fuse value: 0 or 1 468 + */ 469 + static inline int cvmx_fuse_read(int fuse) 470 + { 471 + return (cvmx_fuse_read_byte(fuse >> 3) >> (fuse & 0x7)) & 1; 472 + } 473 + 474 + static inline int cvmx_octeon_model_CN36XX(void) 475 + { 476 + return OCTEON_IS_MODEL(OCTEON_CN38XX) 477 + && !cvmx_octeon_is_pass1() 478 + && cvmx_fuse_read(264); 479 + } 480 + 481 + static inline int cvmx_octeon_zip_present(void) 482 + { 483 + return octeon_has_feature(OCTEON_FEATURE_ZIP); 484 + } 485 + 486 + static inline int cvmx_octeon_dfa_present(void) 487 + { 488 + if (!OCTEON_IS_MODEL(OCTEON_CN38XX) 489 + && !OCTEON_IS_MODEL(OCTEON_CN31XX) 490 + && !OCTEON_IS_MODEL(OCTEON_CN58XX)) 491 + return 0; 492 + else if (OCTEON_IS_MODEL(OCTEON_CN3020)) 493 + return 0; 494 + else if (cvmx_octeon_is_pass1()) 495 + return 1; 496 + else 497 + return !cvmx_fuse_read(120); 498 + } 499 + 500 + static inline int cvmx_octeon_crypto_present(void) 501 + { 502 + return octeon_has_feature(OCTEON_FEATURE_CRYPTO); 503 + } 504 + 505 + #endif /* __CVMX_H__ */
+119
arch/mips/include/asm/octeon/octeon-feature.h
··· 1 + /***********************license start*************** 2 + * Author: Cavium Networks 3 + * 4 + * Contact: support@caviumnetworks.com 5 + * This file is part of the OCTEON SDK 6 + * 7 + * Copyright (c) 2003-2008 Cavium Networks 8 + * 9 + * This file is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License, Version 2, as 11 + * published by the Free Software Foundation. 12 + * 13 + * This file is distributed in the hope that it will be useful, but 14 + * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 15 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 16 + * NONINFRINGEMENT. See the GNU General Public License for more 17 + * details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with this file; if not, write to the Free Software 21 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 + * or visit http://www.gnu.org/licenses/. 23 + * 24 + * This file may also be available under a different license from Cavium. 25 + * Contact Cavium Networks for more information 26 + ***********************license end**************************************/ 27 + 28 + /* 29 + * File defining checks for different Octeon features. 30 + */ 31 + 32 + #ifndef __OCTEON_FEATURE_H__ 33 + #define __OCTEON_FEATURE_H__ 34 + 35 + enum octeon_feature { 36 + /* 37 + * Octeon models in the CN5XXX family and higher support 38 + * atomic add instructions to memory (saa/saad). 39 + */ 40 + OCTEON_FEATURE_SAAD, 41 + /* Does this Octeon support the ZIP offload engine? */ 42 + OCTEON_FEATURE_ZIP, 43 + /* Does this Octeon support crypto acceleration using COP2? */ 44 + OCTEON_FEATURE_CRYPTO, 45 + /* Does this Octeon support PCI express? */ 46 + OCTEON_FEATURE_PCIE, 47 + /* Some Octeon models support internal memory for storing 48 + * cryptographic keys */ 49 + OCTEON_FEATURE_KEY_MEMORY, 50 + /* Octeon has a LED controller for banks of external LEDs */ 51 + OCTEON_FEATURE_LED_CONTROLLER, 52 + /* Octeon has a trace buffer */ 53 + OCTEON_FEATURE_TRA, 54 + /* Octeon has a management port */ 55 + OCTEON_FEATURE_MGMT_PORT, 56 + /* Octeon has a raid unit */ 57 + OCTEON_FEATURE_RAID, 58 + /* Octeon has a builtin USB */ 59 + OCTEON_FEATURE_USB, 60 + }; 61 + 62 + static inline int cvmx_fuse_read(int fuse); 63 + 64 + /** 65 + * Determine if the current Octeon supports a specific feature. These 66 + * checks have been optimized to be fairly quick, but they should still 67 + * be kept out of fast path code. 68 + * 69 + * @feature: Feature to check for. This should always be a constant so the 70 + * compiler can remove the switch statement through optimization. 71 + * 72 + * Returns Non zero if the feature exists. Zero if the feature does not 73 + * exist. 74 + */ 75 + static inline int octeon_has_feature(enum octeon_feature feature) 76 + { 77 + switch (feature) { 78 + case OCTEON_FEATURE_SAAD: 79 + return !OCTEON_IS_MODEL(OCTEON_CN3XXX); 80 + 81 + case OCTEON_FEATURE_ZIP: 82 + if (OCTEON_IS_MODEL(OCTEON_CN30XX) 83 + || OCTEON_IS_MODEL(OCTEON_CN50XX) 84 + || OCTEON_IS_MODEL(OCTEON_CN52XX)) 85 + return 0; 86 + else if (OCTEON_IS_MODEL(OCTEON_CN38XX_PASS1)) 87 + return 1; 88 + else 89 + return !cvmx_fuse_read(121); 90 + 91 + case OCTEON_FEATURE_CRYPTO: 92 + return !cvmx_fuse_read(90); 93 + 94 + case OCTEON_FEATURE_PCIE: 95 + return OCTEON_IS_MODEL(OCTEON_CN56XX) 96 + || OCTEON_IS_MODEL(OCTEON_CN52XX); 97 + 98 + case OCTEON_FEATURE_KEY_MEMORY: 99 + case OCTEON_FEATURE_LED_CONTROLLER: 100 + return OCTEON_IS_MODEL(OCTEON_CN38XX) 101 + || OCTEON_IS_MODEL(OCTEON_CN58XX) 102 + || OCTEON_IS_MODEL(OCTEON_CN56XX); 103 + case OCTEON_FEATURE_TRA: 104 + return !(OCTEON_IS_MODEL(OCTEON_CN30XX) 105 + || OCTEON_IS_MODEL(OCTEON_CN50XX)); 106 + case OCTEON_FEATURE_MGMT_PORT: 107 + return OCTEON_IS_MODEL(OCTEON_CN56XX) 108 + || OCTEON_IS_MODEL(OCTEON_CN52XX); 109 + case OCTEON_FEATURE_RAID: 110 + return OCTEON_IS_MODEL(OCTEON_CN56XX) 111 + || OCTEON_IS_MODEL(OCTEON_CN52XX); 112 + case OCTEON_FEATURE_USB: 113 + return !(OCTEON_IS_MODEL(OCTEON_CN38XX) 114 + || OCTEON_IS_MODEL(OCTEON_CN58XX)); 115 + } 116 + return 0; 117 + } 118 + 119 + #endif /* __OCTEON_FEATURE_H__ */
+321
arch/mips/include/asm/octeon/octeon-model.h
··· 1 + /***********************license start*************** 2 + * Author: Cavium Networks 3 + * 4 + * Contact: support@caviumnetworks.com 5 + * This file is part of the OCTEON SDK 6 + * 7 + * Copyright (c) 2003-2008 Cavium Networks 8 + * 9 + * This file is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License, Version 2, as 11 + * published by the Free Software Foundation. 12 + * 13 + * This file is distributed in the hope that it will be useful, but 14 + * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 15 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 16 + * NONINFRINGEMENT. See the GNU General Public License for more 17 + * details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with this file; if not, write to the Free Software 21 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 + * or visit http://www.gnu.org/licenses/. 23 + * 24 + * This file may also be available under a different license from Cavium. 25 + * Contact Cavium Networks for more information 26 + ***********************license end**************************************/ 27 + 28 + /* 29 + * 30 + * File defining different Octeon model IDs and macros to 31 + * compare them. 32 + * 33 + */ 34 + 35 + #ifndef __OCTEON_MODEL_H__ 36 + #define __OCTEON_MODEL_H__ 37 + 38 + /* NOTE: These must match what is checked in common-config.mk */ 39 + /* Defines to represent the different versions of Octeon. */ 40 + 41 + /* 42 + * IMPORTANT: When the default pass is updated for an Octeon Model, 43 + * the corresponding change must also be made in the oct-sim script. 44 + */ 45 + 46 + /* 47 + * The defines below should be used with the OCTEON_IS_MODEL() macro 48 + * to determine what model of chip the software is running on. Models 49 + * ending in 'XX' match multiple models (families), while specific 50 + * models match only that model. If a pass (revision) is specified, 51 + * then only that revision will be matched. Care should be taken when 52 + * checking for both specific models and families that the specific 53 + * models are checked for first. While these defines are similar to 54 + * the processor ID, they are not intended to be used by anything 55 + * other that the OCTEON_IS_MODEL framework, and the values are 56 + * subject to change at anytime without notice. 57 + * 58 + * NOTE: only the OCTEON_IS_MODEL() macro/function and the OCTEON_CN* 59 + * macros should be used outside of this file. All other macros are 60 + * for internal use only, and may change without notice. 61 + */ 62 + 63 + /* Flag bits in top byte */ 64 + /* Ignores revision in model checks */ 65 + #define OM_IGNORE_REVISION 0x01000000 66 + /* Check submodels */ 67 + #define OM_CHECK_SUBMODEL 0x02000000 68 + /* Match all models previous than the one specified */ 69 + #define OM_MATCH_PREVIOUS_MODELS 0x04000000 70 + /* Ignores the minor revison on newer parts */ 71 + #define OM_IGNORE_MINOR_REVISION 0x08000000 72 + #define OM_FLAG_MASK 0xff000000 73 + 74 + /* 75 + * CN5XXX models with new revision encoding 76 + */ 77 + #define OCTEON_CN58XX_PASS1_0 0x000d0300 78 + #define OCTEON_CN58XX_PASS1_1 0x000d0301 79 + #define OCTEON_CN58XX_PASS1_2 0x000d0303 80 + #define OCTEON_CN58XX_PASS2_0 0x000d0308 81 + #define OCTEON_CN58XX_PASS2_1 0x000d0309 82 + #define OCTEON_CN58XX_PASS2_2 0x000d030a 83 + #define OCTEON_CN58XX_PASS2_3 0x000d030b 84 + 85 + #define OCTEON_CN58XX (OCTEON_CN58XX_PASS1_0 | OM_IGNORE_REVISION) 86 + #define OCTEON_CN58XX_PASS1_X (OCTEON_CN58XX_PASS1_0 \ 87 + | OM_IGNORE_MINOR_REVISION) 88 + #define OCTEON_CN58XX_PASS2_X (OCTEON_CN58XX_PASS2_0 \ 89 + | OM_IGNORE_MINOR_REVISION) 90 + #define OCTEON_CN58XX_PASS1 OCTEON_CN58XX_PASS1_X 91 + #define OCTEON_CN58XX_PASS2 OCTEON_CN58XX_PASS2_X 92 + 93 + #define OCTEON_CN56XX_PASS1_0 0x000d0400 94 + #define OCTEON_CN56XX_PASS1_1 0x000d0401 95 + #define OCTEON_CN56XX_PASS2_0 0x000d0408 96 + #define OCTEON_CN56XX_PASS2_1 0x000d0409 97 + 98 + #define OCTEON_CN56XX (OCTEON_CN56XX_PASS2_0 | OM_IGNORE_REVISION) 99 + #define OCTEON_CN56XX_PASS1_X (OCTEON_CN56XX_PASS1_0 \ 100 + | OM_IGNORE_MINOR_REVISION) 101 + #define OCTEON_CN56XX_PASS2_X (OCTEON_CN56XX_PASS2_0 \ 102 + | OM_IGNORE_MINOR_REVISION) 103 + #define OCTEON_CN56XX_PASS1 OCTEON_CN56XX_PASS1_X 104 + #define OCTEON_CN56XX_PASS2 OCTEON_CN56XX_PASS2_X 105 + 106 + #define OCTEON_CN57XX OCTEON_CN56XX 107 + #define OCTEON_CN57XX_PASS1 OCTEON_CN56XX_PASS1 108 + #define OCTEON_CN57XX_PASS2 OCTEON_CN56XX_PASS2 109 + 110 + #define OCTEON_CN55XX OCTEON_CN56XX 111 + #define OCTEON_CN55XX_PASS1 OCTEON_CN56XX_PASS1 112 + #define OCTEON_CN55XX_PASS2 OCTEON_CN56XX_PASS2 113 + 114 + #define OCTEON_CN54XX OCTEON_CN56XX 115 + #define OCTEON_CN54XX_PASS1 OCTEON_CN56XX_PASS1 116 + #define OCTEON_CN54XX_PASS2 OCTEON_CN56XX_PASS2 117 + 118 + #define OCTEON_CN50XX_PASS1_0 0x000d0600 119 + 120 + #define OCTEON_CN50XX (OCTEON_CN50XX_PASS1_0 | OM_IGNORE_REVISION) 121 + #define OCTEON_CN50XX_PASS1_X (OCTEON_CN50XX_PASS1_0 \ 122 + | OM_IGNORE_MINOR_REVISION) 123 + #define OCTEON_CN50XX_PASS1 OCTEON_CN50XX_PASS1_X 124 + 125 + /* 126 + * NOTE: Octeon CN5000F model is not identifiable using the 127 + * OCTEON_IS_MODEL() functions, but are treated as CN50XX. 128 + */ 129 + 130 + #define OCTEON_CN52XX_PASS1_0 0x000d0700 131 + #define OCTEON_CN52XX_PASS2_0 0x000d0708 132 + 133 + #define OCTEON_CN52XX (OCTEON_CN52XX_PASS2_0 | OM_IGNORE_REVISION) 134 + #define OCTEON_CN52XX_PASS1_X (OCTEON_CN52XX_PASS1_0 \ 135 + | OM_IGNORE_MINOR_REVISION) 136 + #define OCTEON_CN52XX_PASS2_X (OCTEON_CN52XX_PASS2_0 \ 137 + | OM_IGNORE_MINOR_REVISION) 138 + #define OCTEON_CN52XX_PASS1 OCTEON_CN52XX_PASS1_X 139 + #define OCTEON_CN52XX_PASS2 OCTEON_CN52XX_PASS2_X 140 + 141 + /* 142 + * CN3XXX models with old revision enconding 143 + */ 144 + #define OCTEON_CN38XX_PASS1 0x000d0000 145 + #define OCTEON_CN38XX_PASS2 0x000d0001 146 + #define OCTEON_CN38XX_PASS3 0x000d0003 147 + #define OCTEON_CN38XX (OCTEON_CN38XX_PASS3 | OM_IGNORE_REVISION) 148 + 149 + #define OCTEON_CN36XX OCTEON_CN38XX 150 + #define OCTEON_CN36XX_PASS2 OCTEON_CN38XX_PASS2 151 + #define OCTEON_CN36XX_PASS3 OCTEON_CN38XX_PASS3 152 + 153 + /* The OCTEON_CN31XX matches CN31XX models and the CN3020 */ 154 + #define OCTEON_CN31XX_PASS1 0x000d0100 155 + #define OCTEON_CN31XX_PASS1_1 0x000d0102 156 + #define OCTEON_CN31XX (OCTEON_CN31XX_PASS1 | OM_IGNORE_REVISION) 157 + 158 + /* 159 + * This model is only used for internal checks, it is not a valid 160 + * model for the OCTEON_MODEL environment variable. This matches the 161 + * CN3010 and CN3005 but NOT the CN3020. 162 + */ 163 + #define OCTEON_CN30XX_PASS1 0x000d0200 164 + #define OCTEON_CN30XX_PASS1_1 0x000d0202 165 + #define OCTEON_CN30XX (OCTEON_CN30XX_PASS1 | OM_IGNORE_REVISION) 166 + 167 + #define OCTEON_CN3005_PASS1 (0x000d0210 | OM_CHECK_SUBMODEL) 168 + #define OCTEON_CN3005_PASS1_0 (0x000d0210 | OM_CHECK_SUBMODEL) 169 + #define OCTEON_CN3005_PASS1_1 (0x000d0212 | OM_CHECK_SUBMODEL) 170 + #define OCTEON_CN3005 (OCTEON_CN3005_PASS1 | OM_IGNORE_REVISION \ 171 + | OM_CHECK_SUBMODEL) 172 + 173 + #define OCTEON_CN3010_PASS1 (0x000d0200 | OM_CHECK_SUBMODEL) 174 + #define OCTEON_CN3010_PASS1_0 (0x000d0200 | OM_CHECK_SUBMODEL) 175 + #define OCTEON_CN3010_PASS1_1 (0x000d0202 | OM_CHECK_SUBMODEL) 176 + #define OCTEON_CN3010 (OCTEON_CN3010_PASS1 | OM_IGNORE_REVISION \ 177 + | OM_CHECK_SUBMODEL) 178 + 179 + #define OCTEON_CN3020_PASS1 (0x000d0110 | OM_CHECK_SUBMODEL) 180 + #define OCTEON_CN3020_PASS1_0 (0x000d0110 | OM_CHECK_SUBMODEL) 181 + #define OCTEON_CN3020_PASS1_1 (0x000d0112 | OM_CHECK_SUBMODEL) 182 + #define OCTEON_CN3020 (OCTEON_CN3020_PASS1 | OM_IGNORE_REVISION \ 183 + | OM_CHECK_SUBMODEL) 184 + 185 + 186 + 187 + /* This matches the complete family of CN3xxx CPUs, and not subsequent models */ 188 + #define OCTEON_CN3XXX (OCTEON_CN58XX_PASS1_0 \ 189 + | OM_MATCH_PREVIOUS_MODELS \ 190 + | OM_IGNORE_REVISION) 191 + 192 + /* The revision byte (low byte) has two different encodings. 193 + * CN3XXX: 194 + * 195 + * bits 196 + * <7:5>: reserved (0) 197 + * <4>: alternate package 198 + * <3:0>: revision 199 + * 200 + * CN5XXX: 201 + * 202 + * bits 203 + * <7>: reserved (0) 204 + * <6>: alternate package 205 + * <5:3>: major revision 206 + * <2:0>: minor revision 207 + * 208 + */ 209 + 210 + /* Masks used for the various types of model/family/revision matching */ 211 + #define OCTEON_38XX_FAMILY_MASK 0x00ffff00 212 + #define OCTEON_38XX_FAMILY_REV_MASK 0x00ffff0f 213 + #define OCTEON_38XX_MODEL_MASK 0x00ffff10 214 + #define OCTEON_38XX_MODEL_REV_MASK (OCTEON_38XX_FAMILY_REV_MASK \ 215 + | OCTEON_38XX_MODEL_MASK) 216 + 217 + /* CN5XXX and later use different layout of bits in the revision ID field */ 218 + #define OCTEON_58XX_FAMILY_MASK OCTEON_38XX_FAMILY_MASK 219 + #define OCTEON_58XX_FAMILY_REV_MASK 0x00ffff3f 220 + #define OCTEON_58XX_MODEL_MASK 0x00ffffc0 221 + #define OCTEON_58XX_MODEL_REV_MASK (OCTEON_58XX_FAMILY_REV_MASK \ 222 + | OCTEON_58XX_MODEL_MASK) 223 + #define OCTEON_58XX_MODEL_MINOR_REV_MASK (OCTEON_58XX_MODEL_REV_MASK \ 224 + & 0x00fffff8) 225 + 226 + #define __OCTEON_MATCH_MASK__(x, y, z) (((x) & (z)) == ((y) & (z))) 227 + 228 + /* NOTE: This is for internal (to this file) use only. */ 229 + static inline int __OCTEON_IS_MODEL_COMPILE__(uint32_t arg_model, 230 + uint32_t chip_model) 231 + { 232 + uint32_t rev_and_sub = OM_IGNORE_REVISION | OM_CHECK_SUBMODEL; 233 + 234 + if ((arg_model & OCTEON_38XX_FAMILY_MASK) < OCTEON_CN58XX_PASS1_0) { 235 + if (((arg_model & OM_FLAG_MASK) == rev_and_sub) && 236 + __OCTEON_MATCH_MASK__(chip_model, arg_model, 237 + OCTEON_38XX_MODEL_MASK)) 238 + return 1; 239 + if (((arg_model & OM_FLAG_MASK) == 0) && 240 + __OCTEON_MATCH_MASK__(chip_model, arg_model, 241 + OCTEON_38XX_FAMILY_REV_MASK)) 242 + return 1; 243 + if (((arg_model & OM_FLAG_MASK) == OM_IGNORE_REVISION) && 244 + __OCTEON_MATCH_MASK__(chip_model, arg_model, 245 + OCTEON_38XX_FAMILY_MASK)) 246 + return 1; 247 + if (((arg_model & OM_FLAG_MASK) == OM_CHECK_SUBMODEL) && 248 + __OCTEON_MATCH_MASK__((chip_model), (arg_model), 249 + OCTEON_38XX_MODEL_REV_MASK)) 250 + return 1; 251 + if ((arg_model & OM_MATCH_PREVIOUS_MODELS) && 252 + ((chip_model & OCTEON_38XX_MODEL_MASK) < 253 + (arg_model & OCTEON_38XX_MODEL_MASK))) 254 + return 1; 255 + } else { 256 + if (((arg_model & OM_FLAG_MASK) == rev_and_sub) && 257 + __OCTEON_MATCH_MASK__((chip_model), (arg_model), 258 + OCTEON_58XX_MODEL_MASK)) 259 + return 1; 260 + if (((arg_model & OM_FLAG_MASK) == 0) && 261 + __OCTEON_MATCH_MASK__((chip_model), (arg_model), 262 + OCTEON_58XX_FAMILY_REV_MASK)) 263 + return 1; 264 + if (((arg_model & OM_FLAG_MASK) == OM_IGNORE_MINOR_REVISION) && 265 + __OCTEON_MATCH_MASK__((chip_model), (arg_model), 266 + OCTEON_58XX_MODEL_MINOR_REV_MASK)) 267 + return 1; 268 + if (((arg_model & OM_FLAG_MASK) == OM_IGNORE_REVISION) && 269 + __OCTEON_MATCH_MASK__((chip_model), (arg_model), 270 + OCTEON_58XX_FAMILY_MASK)) 271 + return 1; 272 + if (((arg_model & OM_FLAG_MASK) == OM_CHECK_SUBMODEL) && 273 + __OCTEON_MATCH_MASK__((chip_model), (arg_model), 274 + OCTEON_58XX_MODEL_REV_MASK)) 275 + return 1; 276 + if ((arg_model & OM_MATCH_PREVIOUS_MODELS) && 277 + ((chip_model & OCTEON_58XX_MODEL_MASK) < 278 + (arg_model & OCTEON_58XX_MODEL_MASK))) 279 + return 1; 280 + } 281 + return 0; 282 + } 283 + 284 + /* forward declarations */ 285 + static inline uint32_t cvmx_get_proc_id(void) __attribute__ ((pure)); 286 + static inline uint64_t cvmx_read_csr(uint64_t csr_addr); 287 + 288 + /* NOTE: This for internal use only!!!!! */ 289 + static inline int __octeon_is_model_runtime__(uint32_t model) 290 + { 291 + uint32_t cpuid = cvmx_get_proc_id(); 292 + 293 + /* 294 + * Check for special case of mismarked 3005 samples. We only 295 + * need to check if the sub model isn't being ignored. 296 + */ 297 + if ((model & OM_CHECK_SUBMODEL) == OM_CHECK_SUBMODEL) { 298 + if (cpuid == OCTEON_CN3010_PASS1 \ 299 + && (cvmx_read_csr(0x80011800800007B8ull) & (1ull << 34))) 300 + cpuid |= 0x10; 301 + } 302 + return __OCTEON_IS_MODEL_COMPILE__(model, cpuid); 303 + } 304 + 305 + /* 306 + * The OCTEON_IS_MODEL macro should be used for all Octeon model 307 + * checking done in a program. This should be kept runtime if at all 308 + * possible. Any compile time (#if OCTEON_IS_MODEL) usage must be 309 + * condtionalized with OCTEON_IS_COMMON_BINARY() if runtime checking 310 + * support is required. 311 + */ 312 + #define OCTEON_IS_MODEL(x) __octeon_is_model_runtime__(x) 313 + #define OCTEON_IS_COMMON_BINARY() 1 314 + #undef OCTEON_MODEL 315 + 316 + const char *octeon_model_get_string(uint32_t chip_id); 317 + const char *octeon_model_get_string_buffer(uint32_t chip_id, char *buffer); 318 + 319 + #include "octeon-feature.h" 320 + 321 + #endif /* __OCTEON_MODEL_H__ */