cvmx-qlm.c revision 256281
1/***********************license start*************** 2 * Copyright (c) 2011 Cavium Inc. (support@cavium.com). All rights 3 * reserved. 4 * 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * * Redistributions in binary form must reproduce the above 14 * copyright notice, this list of conditions and the following 15 * disclaimer in the documentation and/or other materials provided 16 * with the distribution. 17 18 * * Neither the name of Cavium Inc. nor the names of 19 * its contributors may be used to endorse or promote products 20 * derived from this software without specific prior written 21 * permission. 22 23 * This Software, including technical data, may be subject to U.S. export control 24 * laws, including the U.S. Export Administration Act and its associated 25 * regulations, and may be subject to export or import regulations in other 26 * countries. 27 28 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29 * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 30 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31 * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32 * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33 * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34 * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35 * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36 * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37 * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38 ***********************license end**************************************/ 39 40 41/** 42 * @file 43 * 44 * Helper utilities for qlm. 45 * 46 * <hr>$Revision: 70129 $<hr> 47 */ 48#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 49#include <asm/octeon/cvmx.h> 50#include <asm/octeon/cvmx-bootmem.h> 51#include <asm/octeon/cvmx-helper-jtag.h> 52#include <asm/octeon/cvmx-qlm.h> 53#include <asm/octeon/cvmx-gmxx-defs.h> 54#include <asm/octeon/cvmx-sriox-defs.h> 55#include <asm/octeon/cvmx-sriomaintx-defs.h> 56#include <asm/octeon/cvmx-pciercx-defs.h> 57#else 58#if !defined(__FreeBSD__) || !defined(_KERNEL) 59#include "executive-config.h" 60#include "cvmx-config.h" 61#include "cvmx.h" 62#include "cvmx-bootmem.h" 63#include "cvmx-helper-jtag.h" 64#include "cvmx-qlm.h" 65#else 66#include "cvmx.h" 67#include "cvmx-bootmem.h" 68#include "cvmx-helper-jtag.h" 69#include "cvmx-qlm.h" 70#endif 71 72#endif 73 74/** 75 * The JTAG chain for CN52XX and CN56XX is 4 * 268 bits long, or 1072. 76 * CN5XXX full chain shift is: 77 * new data => lane 3 => lane 2 => lane 1 => lane 0 => data out 78 * The JTAG chain for CN63XX is 4 * 300 bits long, or 1200. 79 * The JTAG chain for CN68XX is 4 * 304 bits long, or 1216. 80 * The JTAG chain for CN66XX/CN61XX/CNF71XX is 4 * 304 bits long, or 1216. 81 * CN6XXX full chain shift is: 82 * new data => lane 0 => lane 1 => lane 2 => lane 3 => data out 83 * Shift LSB first, get LSB out 84 */ 85extern const __cvmx_qlm_jtag_field_t __cvmx_qlm_jtag_field_cn52xx[]; 86extern const __cvmx_qlm_jtag_field_t __cvmx_qlm_jtag_field_cn56xx[]; 87extern const __cvmx_qlm_jtag_field_t __cvmx_qlm_jtag_field_cn63xx[]; 88extern const __cvmx_qlm_jtag_field_t __cvmx_qlm_jtag_field_cn66xx[]; 89extern const __cvmx_qlm_jtag_field_t __cvmx_qlm_jtag_field_cn68xx[]; 90 91#define CVMX_QLM_JTAG_UINT32 40 92#ifdef CVMX_BUILD_FOR_LINUX_HOST 93extern void octeon_remote_read_mem(void *buffer, uint64_t physical_address, int length); 94extern void octeon_remote_write_mem(uint64_t physical_address, const void *buffer, int length); 95uint32_t __cvmx_qlm_jtag_xor_ref[5][CVMX_QLM_JTAG_UINT32]; 96#else 97typedef uint32_t qlm_jtag_uint32_t[CVMX_QLM_JTAG_UINT32]; 98CVMX_SHARED qlm_jtag_uint32_t *__cvmx_qlm_jtag_xor_ref; 99#endif 100 101 102/** 103 * Return the number of QLMs supported by the chip 104 * 105 * @return Number of QLMs 106 */ 107int cvmx_qlm_get_num(void) 108{ 109 if (OCTEON_IS_MODEL(OCTEON_CN68XX)) 110 return 5; 111 else if (OCTEON_IS_MODEL(OCTEON_CN66XX)) 112 return 3; 113 else if (OCTEON_IS_MODEL(OCTEON_CN63XX)) 114 return 3; 115 else if (OCTEON_IS_MODEL(OCTEON_CN61XX)) 116 return 3; 117 else if (OCTEON_IS_MODEL(OCTEON_CN56XX)) 118 return 4; 119 else if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CNF71XX)) 120 return 2; 121 122 //cvmx_dprintf("Warning: cvmx_qlm_get_num: This chip does not have QLMs\n"); 123 return 0; 124} 125 126/** 127 * Return the qlm number based on the interface 128 * 129 * @param interface Interface to look up 130 */ 131int cvmx_qlm_interface(int interface) 132{ 133 if (OCTEON_IS_MODEL(OCTEON_CN61XX)) { 134 return (interface == 0) ? 2 : 0; 135 } else if (OCTEON_IS_MODEL(OCTEON_CN63XX) || OCTEON_IS_MODEL(OCTEON_CN66XX)) { 136 return 2 - interface; 137 } else { 138 /* Must be cn68XX */ 139 switch(interface) { 140 case 1: 141 return 0; 142 default: 143 return interface; 144 } 145 } 146} 147 148/** 149 * Return number of lanes for a given qlm 150 * 151 * @return Number of lanes 152 */ 153int cvmx_qlm_get_lanes(int qlm) 154{ 155 if (OCTEON_IS_MODEL(OCTEON_CN61XX) && qlm == 1) 156 return 2; 157 else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) 158 return 2; 159 160 return 4; 161} 162 163/** 164 * Get the QLM JTAG fields based on Octeon model on the supported chips. 165 * 166 * @return qlm_jtag_field_t structure 167 */ 168const __cvmx_qlm_jtag_field_t *cvmx_qlm_jtag_get_field(void) 169{ 170 /* Figure out which JTAG chain description we're using */ 171 if (OCTEON_IS_MODEL(OCTEON_CN68XX)) 172 return __cvmx_qlm_jtag_field_cn68xx; 173 else if (OCTEON_IS_MODEL(OCTEON_CN66XX) 174 || OCTEON_IS_MODEL(OCTEON_CN61XX) 175 || OCTEON_IS_MODEL(OCTEON_CNF71XX)) 176 return __cvmx_qlm_jtag_field_cn66xx; 177 else if (OCTEON_IS_MODEL(OCTEON_CN63XX)) 178 return __cvmx_qlm_jtag_field_cn63xx; 179 else if (OCTEON_IS_MODEL(OCTEON_CN56XX)) 180 return __cvmx_qlm_jtag_field_cn56xx; 181 else if (OCTEON_IS_MODEL(OCTEON_CN52XX)) 182 return __cvmx_qlm_jtag_field_cn52xx; 183 else 184 { 185 //cvmx_dprintf("cvmx_qlm_jtag_get_field: Needs update for this chip\n"); 186 return NULL; 187 } 188} 189 190/** 191 * Get the QLM JTAG length by going through qlm_jtag_field for each 192 * Octeon model that is supported 193 * 194 * @return return the length. 195 */ 196int cvmx_qlm_jtag_get_length(void) 197{ 198 const __cvmx_qlm_jtag_field_t *qlm_ptr = cvmx_qlm_jtag_get_field(); 199 int length = 0; 200 201 /* Figure out how many bits are in the JTAG chain */ 202 while (qlm_ptr != NULL && qlm_ptr->name) 203 { 204 if (qlm_ptr->stop_bit > length) 205 length = qlm_ptr->stop_bit + 1; 206 qlm_ptr++; 207 } 208 return length; 209} 210 211/** 212 * Initialize the QLM layer 213 */ 214void cvmx_qlm_init(void) 215{ 216 int qlm; 217 int qlm_jtag_length; 218 char *qlm_jtag_name = "cvmx_qlm_jtag"; 219 int qlm_jtag_size = CVMX_QLM_JTAG_UINT32 * 8 * 4; 220 static uint64_t qlm_base = 0; 221 const cvmx_bootmem_named_block_desc_t *desc; 222 223#ifndef CVMX_BUILD_FOR_LINUX_HOST 224 /* Skip actual JTAG accesses on simulator */ 225 if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM) 226 return; 227#endif 228 229 qlm_jtag_length = cvmx_qlm_jtag_get_length(); 230 231 if (4 * qlm_jtag_length > (int)sizeof(__cvmx_qlm_jtag_xor_ref[0]) * 8) 232 { 233 cvmx_dprintf("ERROR: cvmx_qlm_init: JTAG chain larger than XOR ref size\n"); 234 return; 235 } 236 237 /* No need to initialize the initial JTAG state if cvmx_qlm_jtag 238 named block is already created. */ 239 if ((desc = cvmx_bootmem_find_named_block(qlm_jtag_name)) != NULL) 240 { 241#ifdef CVMX_BUILD_FOR_LINUX_HOST 242 char buffer[qlm_jtag_size]; 243 244 octeon_remote_read_mem(buffer, desc->base_addr, qlm_jtag_size); 245 memcpy(__cvmx_qlm_jtag_xor_ref, buffer, qlm_jtag_size); 246#else 247 __cvmx_qlm_jtag_xor_ref = cvmx_phys_to_ptr(desc->base_addr); 248#endif 249 /* Initialize the internal JTAG */ 250 cvmx_helper_qlm_jtag_init(); 251 return; 252 } 253 254 /* Create named block to store the initial JTAG state. */ 255 qlm_base = cvmx_bootmem_phy_named_block_alloc(qlm_jtag_size, 0, 0, 128, qlm_jtag_name, CVMX_BOOTMEM_FLAG_END_ALLOC); 256 257 if (qlm_base == -1ull) 258 { 259 cvmx_dprintf("ERROR: cvmx_qlm_init: Error in creating %s named block\n", qlm_jtag_name); 260 return; 261 } 262 263#ifndef CVMX_BUILD_FOR_LINUX_HOST 264 __cvmx_qlm_jtag_xor_ref = cvmx_phys_to_ptr(qlm_base); 265#endif 266 memset(__cvmx_qlm_jtag_xor_ref, 0, qlm_jtag_size); 267 268 /* Initialize the internal JTAG */ 269 cvmx_helper_qlm_jtag_init(); 270 271 /* Read the XOR defaults for the JTAG chain */ 272 for (qlm=0; qlm<cvmx_qlm_get_num(); qlm++) 273 { 274 int i; 275 /* Capture the reset defaults */ 276 cvmx_helper_qlm_jtag_capture(qlm); 277 /* Save the reset defaults. This will shift out too much data, but 278 the extra zeros don't hurt anything */ 279 for (i=0; i<CVMX_QLM_JTAG_UINT32; i++) 280 __cvmx_qlm_jtag_xor_ref[qlm][i] = cvmx_helper_qlm_jtag_shift(qlm, 32, 0); 281 } 282 283#ifdef CVMX_BUILD_FOR_LINUX_HOST 284 /* Update the initial state for oct-remote utils. */ 285 { 286 char buffer[qlm_jtag_size]; 287 288 memcpy(buffer, &__cvmx_qlm_jtag_xor_ref, qlm_jtag_size); 289 octeon_remote_write_mem(qlm_base, buffer, qlm_jtag_size); 290 } 291#endif 292 293 /* Apply speed tweak as a workaround for errata G-16094. */ 294 __cvmx_qlm_speed_tweak(); 295 __cvmx_qlm_pcie_idle_dac_tweak(); 296} 297 298/** 299 * Lookup the bit information for a JTAG field name 300 * 301 * @param name Name to lookup 302 * 303 * @return Field info, or NULL on failure 304 */ 305static const __cvmx_qlm_jtag_field_t *__cvmx_qlm_lookup_field(const char *name) 306{ 307 const __cvmx_qlm_jtag_field_t *ptr = cvmx_qlm_jtag_get_field(); 308 while (ptr->name) 309 { 310 if (strcmp(name, ptr->name) == 0) 311 return ptr; 312 ptr++; 313 } 314 cvmx_dprintf("__cvmx_qlm_lookup_field: Illegal field name %s\n", name); 315 return NULL; 316} 317 318/** 319 * Get a field in a QLM JTAG chain 320 * 321 * @param qlm QLM to get 322 * @param lane Lane in QLM to get 323 * @param name String name of field 324 * 325 * @return JTAG field value 326 */ 327uint64_t cvmx_qlm_jtag_get(int qlm, int lane, const char *name) 328{ 329 const __cvmx_qlm_jtag_field_t *field = __cvmx_qlm_lookup_field(name); 330 int qlm_jtag_length = cvmx_qlm_jtag_get_length(); 331 int num_lanes = cvmx_qlm_get_lanes(qlm); 332 333 if (!field) 334 return 0; 335 336 /* Capture the current settings */ 337 cvmx_helper_qlm_jtag_capture(qlm); 338 /* Shift past lanes we don't care about. CN6XXX shifts lane 3 first */ 339 cvmx_helper_qlm_jtag_shift_zeros(qlm, qlm_jtag_length * (num_lanes-1-lane)); /* Shift to the start of the field */ 340 cvmx_helper_qlm_jtag_shift_zeros(qlm, field->start_bit); 341 /* Shift out the value and return it */ 342 return cvmx_helper_qlm_jtag_shift(qlm, field->stop_bit - field->start_bit + 1, 0); 343} 344 345/** 346 * Set a field in a QLM JTAG chain 347 * 348 * @param qlm QLM to set 349 * @param lane Lane in QLM to set, or -1 for all lanes 350 * @param name String name of field 351 * @param value Value of the field 352 */ 353void cvmx_qlm_jtag_set(int qlm, int lane, const char *name, uint64_t value) 354{ 355 int i, l; 356 uint32_t shift_values[CVMX_QLM_JTAG_UINT32]; 357 int num_lanes = cvmx_qlm_get_lanes(qlm); 358 const __cvmx_qlm_jtag_field_t *field = __cvmx_qlm_lookup_field(name); 359 int qlm_jtag_length = cvmx_qlm_jtag_get_length(); 360 int total_length = qlm_jtag_length * num_lanes; 361 int bits = 0; 362 363 if (!field) 364 return; 365 366 /* Get the current state */ 367 cvmx_helper_qlm_jtag_capture(qlm); 368 for (i=0; i<CVMX_QLM_JTAG_UINT32; i++) 369 shift_values[i] = cvmx_helper_qlm_jtag_shift(qlm, 32, 0); 370 371 /* Put new data in our local array */ 372 for (l=0; l<num_lanes; l++) 373 { 374 uint64_t new_value = value; 375 int bits; 376 if ((l != lane) && (lane != -1)) 377 continue; 378 for (bits = field->start_bit + (num_lanes-1-l)*qlm_jtag_length; 379 bits <= field->stop_bit + (num_lanes-1-l)*qlm_jtag_length; 380 bits++) 381 { 382 if (new_value & 1) 383 shift_values[bits/32] |= 1<<(bits&31); 384 else 385 shift_values[bits/32] &= ~(1<<(bits&31)); 386 new_value>>=1; 387 } 388 } 389 390 /* Shift out data and xor with reference */ 391 while (bits < total_length) 392 { 393 uint32_t shift = shift_values[bits/32] ^ __cvmx_qlm_jtag_xor_ref[qlm][bits/32]; 394 int width = total_length - bits; 395 if (width > 32) 396 width = 32; 397 cvmx_helper_qlm_jtag_shift(qlm, width, shift); 398 bits += 32; 399 } 400 401 /* Update the new data */ 402 cvmx_helper_qlm_jtag_update(qlm); 403 /* Always give the QLM 1ms to settle after every update. This may not 404 always be needed, but some of the options make significant 405 electrical changes */ 406 cvmx_wait_usec(1000); 407} 408 409/** 410 * Errata G-16094: QLM Gen2 Equalizer Default Setting Change. 411 * CN68XX pass 1.x and CN66XX pass 1.x QLM tweak. This function tweaks the 412 * JTAG setting for a QLMs to run better at 5 and 6.25Ghz. 413 */ 414void __cvmx_qlm_speed_tweak(void) 415{ 416 cvmx_mio_qlmx_cfg_t qlm_cfg; 417 int num_qlms = 0; 418 int qlm; 419 420 if (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_X)) 421 num_qlms = 5; 422 else if (OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_X)) 423 num_qlms = 3; 424 else 425 return; 426 427 /* Loop through the QLMs */ 428 for (qlm = 0; qlm < num_qlms; qlm++) 429 { 430 /* Read the QLM speed */ 431 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm)); 432 433 /* If the QLM is at 6.25Ghz or 5Ghz then program JTAG */ 434 if ((qlm_cfg.s.qlm_spd == 5) || (qlm_cfg.s.qlm_spd == 12) || 435 (qlm_cfg.s.qlm_spd == 0) || (qlm_cfg.s.qlm_spd == 6) || 436 (qlm_cfg.s.qlm_spd == 11)) 437 { 438 cvmx_qlm_jtag_set(qlm, -1, "rx_cap_gen2", 0x1); 439 cvmx_qlm_jtag_set(qlm, -1, "rx_eq_gen2", 0x8); 440 } 441 } 442} 443 444/** 445 * Errata G-16174: QLM Gen2 PCIe IDLE DAC change. 446 * CN68XX pass 1.x, CN66XX pass 1.x and CN63XX pass 1.0-2.2 QLM tweak. 447 * This function tweaks the JTAG setting for a QLMs for PCIe to run better. 448 */ 449void __cvmx_qlm_pcie_idle_dac_tweak(void) 450{ 451 int num_qlms = 0; 452 int qlm; 453 454 if (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_X)) 455 num_qlms = 5; 456 else if (OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_X)) 457 num_qlms = 3; 458 else if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X) || 459 OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_X)) 460 num_qlms = 3; 461 else 462 return; 463 464 /* Loop through the QLMs */ 465 for (qlm = 0; qlm < num_qlms; qlm++) 466 cvmx_qlm_jtag_set(qlm, -1, "idle_dac", 0x2); 467} 468 469#ifndef CVMX_BUILD_FOR_LINUX_HOST 470/** 471 * Get the speed (Gbaud) of the QLM in Mhz. 472 * 473 * @param qlm QLM to examine 474 * 475 * @return Speed in Mhz 476 */ 477int cvmx_qlm_get_gbaud_mhz(int qlm) 478{ 479 if (OCTEON_IS_MODEL(OCTEON_CN63XX)) 480 { 481 if (qlm == 2) 482 { 483 cvmx_gmxx_inf_mode_t inf_mode; 484 inf_mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(0)); 485 switch (inf_mode.s.speed) 486 { 487 case 0: return 5000; /* 5 Gbaud */ 488 case 1: return 2500; /* 2.5 Gbaud */ 489 case 2: return 2500; /* 2.5 Gbaud */ 490 case 3: return 1250; /* 1.25 Gbaud */ 491 case 4: return 1250; /* 1.25 Gbaud */ 492 case 5: return 6250; /* 6.25 Gbaud */ 493 case 6: return 5000; /* 5 Gbaud */ 494 case 7: return 2500; /* 2.5 Gbaud */ 495 case 8: return 3125; /* 3.125 Gbaud */ 496 case 9: return 2500; /* 2.5 Gbaud */ 497 case 10: return 1250; /* 1.25 Gbaud */ 498 case 11: return 5000; /* 5 Gbaud */ 499 case 12: return 6250; /* 6.25 Gbaud */ 500 case 13: return 3750; /* 3.75 Gbaud */ 501 case 14: return 3125; /* 3.125 Gbaud */ 502 default: return 0; /* Disabled */ 503 } 504 } 505 else 506 { 507 cvmx_sriox_status_reg_t status_reg; 508 status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(qlm)); 509 if (status_reg.s.srio) 510 { 511 cvmx_sriomaintx_port_0_ctl2_t sriomaintx_port_0_ctl2; 512 sriomaintx_port_0_ctl2.u32 = cvmx_read_csr(CVMX_SRIOMAINTX_PORT_0_CTL2(qlm)); 513 switch (sriomaintx_port_0_ctl2.s.sel_baud) 514 { 515 case 1: return 1250; /* 1.25 Gbaud */ 516 case 2: return 2500; /* 2.5 Gbaud */ 517 case 3: return 3125; /* 3.125 Gbaud */ 518 case 4: return 5000; /* 5 Gbaud */ 519 case 5: return 6250; /* 6.250 Gbaud */ 520 default: return 0; /* Disabled */ 521 } 522 } 523 else 524 { 525 cvmx_pciercx_cfg032_t pciercx_cfg032; 526 pciercx_cfg032.u32 = cvmx_read_csr(CVMX_PCIERCX_CFG032(qlm)); 527 switch (pciercx_cfg032.s.ls) 528 { 529 case 1: 530 return 2500; 531 case 2: 532 return 5000; 533 case 4: 534 return 8000; 535 default: 536 { 537 cvmx_mio_rst_boot_t mio_rst_boot; 538 mio_rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT); 539 if ((qlm == 0) && mio_rst_boot.s.qlm0_spd == 0xf) 540 return 0; 541 if ((qlm == 1) && mio_rst_boot.s.qlm1_spd == 0xf) 542 return 0; 543 return 5000; /* Best guess I can make */ 544 } 545 } 546 } 547 } 548 } 549 else if (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF71XX)) 550 { 551 cvmx_mio_qlmx_cfg_t qlm_cfg; 552 553 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm)); 554 switch (qlm_cfg.s.qlm_spd) 555 { 556 case 0: return 5000; /* 5 Gbaud */ 557 case 1: return 2500; /* 2.5 Gbaud */ 558 case 2: return 2500; /* 2.5 Gbaud */ 559 case 3: return 1250; /* 1.25 Gbaud */ 560 case 4: return 1250; /* 1.25 Gbaud */ 561 case 5: return 6250; /* 6.25 Gbaud */ 562 case 6: return 5000; /* 5 Gbaud */ 563 case 7: return 2500; /* 2.5 Gbaud */ 564 case 8: return 3125; /* 3.125 Gbaud */ 565 case 9: return 2500; /* 2.5 Gbaud */ 566 case 10: return 1250; /* 1.25 Gbaud */ 567 case 11: return 5000; /* 5 Gbaud */ 568 case 12: return 6250; /* 6.25 Gbaud */ 569 case 13: return 3750; /* 3.75 Gbaud */ 570 case 14: return 3125; /* 3.125 Gbaud */ 571 default: return 0; /* Disabled */ 572 } 573 } 574 return 0; 575} 576#endif 577 578/* 579 * Read QLM and return status based on CN66XX. 580 * @return Return 1 if QLM is SGMII 581 * 2 if QLM is XAUI 582 * 3 if QLM is PCIe gen2 / gen1 583 * 4 if QLM is SRIO 1x4 short / long 584 * 5 if QLM is SRIO 2x2 short / long 585 * 6 if QLM is SRIO 4x1 short / long 586 * 7 if QLM is PCIe 1x2 gen2 / gen1 587 * 8 if QLM is PCIe 2x1 gen2 / gen1 588 * 9 if QLM is ILK 589 * 10 if QLM is RXAUI 590 * -1 otherwise 591 */ 592int cvmx_qlm_get_status(int qlm) 593{ 594 cvmx_mio_qlmx_cfg_t qlmx_cfg; 595 596 if (OCTEON_IS_MODEL(OCTEON_CN68XX)) 597 { 598 qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm)); 599 /* QLM is disabled when QLM SPD is 15. */ 600 if (qlmx_cfg.s.qlm_spd == 15) 601 return -1; 602 603 switch (qlmx_cfg.s.qlm_cfg) 604 { 605 case 0: /* PCIE */ 606 return 3; 607 case 1: /* ILK */ 608 return 9; 609 case 2: /* SGMII */ 610 return 1; 611 case 3: /* XAUI */ 612 return 2; 613 case 7: /* RXAUI */ 614 return 10; 615 default: return -1; 616 } 617 } 618 else if (OCTEON_IS_MODEL(OCTEON_CN66XX)) 619 { 620 qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm)); 621 /* QLM is disabled when QLM SPD is 15. */ 622 if (qlmx_cfg.s.qlm_spd == 15) 623 return -1; 624 625 switch (qlmx_cfg.s.qlm_cfg) 626 { 627 case 0x9: /* SGMII */ 628 return 1; 629 case 0xb: /* XAUI */ 630 return 2; 631 case 0x0: /* PCIE gen2 */ 632 case 0x8: /* PCIE gen2 (alias) */ 633 case 0x2: /* PCIE gen1 */ 634 case 0xa: /* PCIE gen1 (alias) */ 635 return 3; 636 case 0x1: /* SRIO 1x4 short */ 637 case 0x3: /* SRIO 1x4 long */ 638 return 4; 639 case 0x4: /* SRIO 2x2 short */ 640 case 0x6: /* SRIO 2x2 long */ 641 return 5; 642 case 0x5: /* SRIO 4x1 short */ 643 case 0x7: /* SRIO 4x1 long */ 644 if (!OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_0)) 645 return 6; 646 default: 647 return -1; 648 } 649 } 650 else if (OCTEON_IS_MODEL(OCTEON_CN63XX)) 651 { 652 cvmx_sriox_status_reg_t status_reg; 653 /* For now skip qlm2 */ 654 if (qlm == 2) 655 { 656 cvmx_gmxx_inf_mode_t inf_mode; 657 inf_mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(0)); 658 if (inf_mode.s.speed == 15) 659 return -1; 660 else if(inf_mode.s.mode == 0) 661 return 1; 662 else 663 return 2; 664 } 665 status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(qlm)); 666 if (status_reg.s.srio) 667 return 4; 668 else 669 return 3; 670 } 671 else if (OCTEON_IS_MODEL(OCTEON_CN61XX)) 672 { 673 qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm)); 674 /* QLM is disabled when QLM SPD is 15. */ 675 if (qlmx_cfg.s.qlm_spd == 15) 676 return -1; 677 678 switch(qlm) 679 { 680 case 0: 681 switch (qlmx_cfg.s.qlm_cfg) 682 { 683 case 0: /* PCIe 1x4 gen2 / gen1 */ 684 return 3; 685 case 2: /* SGMII */ 686 return 1; 687 case 3: /* XAUI */ 688 return 2; 689 default: return -1; 690 } 691 break; 692 case 1: 693 switch (qlmx_cfg.s.qlm_cfg) 694 { 695 case 0: /* PCIe 1x2 gen2 / gen1 */ 696 return 7; 697 case 1: /* PCIe 2x1 gen2 / gen1 */ 698 return 8; 699 default: return -1; 700 } 701 break; 702 case 2: 703 switch (qlmx_cfg.s.qlm_cfg) 704 { 705 case 2: /* SGMII */ 706 return 1; 707 case 3: /* XAUI */ 708 return 2; 709 default: return -1; 710 } 711 break; 712 } 713 } 714 else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) 715 { 716 qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm)); 717 /* QLM is disabled when QLM SPD is 15. */ 718 if (qlmx_cfg.s.qlm_spd == 15) 719 return -1; 720 721 switch(qlm) 722 { 723 case 0: 724 if (qlmx_cfg.s.qlm_cfg == 2) /* SGMII */ 725 return 1; 726 break; 727 case 1: 728 switch (qlmx_cfg.s.qlm_cfg) 729 { 730 case 0: /* PCIe 1x2 gen2 / gen1 */ 731 return 7; 732 case 1: /* PCIe 2x1 gen2 / gen1 */ 733 return 8; 734 default: return -1; 735 } 736 break; 737 } 738 } 739 return -1; 740} 741