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