1232809Sjmallett/***********************license start*************** 2232809Sjmallett * Copyright (c) 2011 Cavium Inc. (support@cavium.com). All rights 3232809Sjmallett * reserved. 4232809Sjmallett * 5232809Sjmallett * 6232809Sjmallett * Redistribution and use in source and binary forms, with or without 7232809Sjmallett * modification, are permitted provided that the following conditions are 8232809Sjmallett * met: 9232809Sjmallett * 10232809Sjmallett * * Redistributions of source code must retain the above copyright 11232809Sjmallett * notice, this list of conditions and the following disclaimer. 12232809Sjmallett * 13232809Sjmallett * * Redistributions in binary form must reproduce the above 14232809Sjmallett * copyright notice, this list of conditions and the following 15232809Sjmallett * disclaimer in the documentation and/or other materials provided 16232809Sjmallett * with the distribution. 17232809Sjmallett 18232809Sjmallett * * Neither the name of Cavium Inc. nor the names of 19232809Sjmallett * its contributors may be used to endorse or promote products 20232809Sjmallett * derived from this software without specific prior written 21232809Sjmallett * permission. 22232809Sjmallett 23232809Sjmallett * This Software, including technical data, may be subject to U.S. export control 24232809Sjmallett * laws, including the U.S. Export Administration Act and its associated 25232809Sjmallett * regulations, and may be subject to export or import regulations in other 26232809Sjmallett * countries. 27232809Sjmallett 28232809Sjmallett * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29232809Sjmallett * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 30232809Sjmallett * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31232809Sjmallett * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32232809Sjmallett * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33232809Sjmallett * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34232809Sjmallett * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35232809Sjmallett * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36232809Sjmallett * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37232809Sjmallett * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38232809Sjmallett ***********************license end**************************************/ 39232809Sjmallett 40232809Sjmallett 41232809Sjmallett/** 42232809Sjmallett * @file 43232809Sjmallett * 44232809Sjmallett * Helper utilities for qlm. 45232809Sjmallett * 46232809Sjmallett * <hr>$Revision: 70129 $<hr> 47232809Sjmallett */ 48232809Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 49232809Sjmallett#include <asm/octeon/cvmx.h> 50232809Sjmallett#include <asm/octeon/cvmx-bootmem.h> 51232809Sjmallett#include <asm/octeon/cvmx-helper-jtag.h> 52232809Sjmallett#include <asm/octeon/cvmx-qlm.h> 53232809Sjmallett#include <asm/octeon/cvmx-gmxx-defs.h> 54232809Sjmallett#include <asm/octeon/cvmx-sriox-defs.h> 55232809Sjmallett#include <asm/octeon/cvmx-sriomaintx-defs.h> 56232809Sjmallett#include <asm/octeon/cvmx-pciercx-defs.h> 57232809Sjmallett#else 58232812Sjmallett#if !defined(__FreeBSD__) || !defined(_KERNEL) 59232809Sjmallett#include "executive-config.h" 60232809Sjmallett#include "cvmx-config.h" 61232809Sjmallett#include "cvmx.h" 62232809Sjmallett#include "cvmx-bootmem.h" 63232809Sjmallett#include "cvmx-helper-jtag.h" 64232809Sjmallett#include "cvmx-qlm.h" 65232812Sjmallett#else 66232812Sjmallett#include "cvmx.h" 67232812Sjmallett#include "cvmx-bootmem.h" 68232812Sjmallett#include "cvmx-helper-jtag.h" 69232812Sjmallett#include "cvmx-qlm.h" 70232809Sjmallett#endif 71232809Sjmallett 72232812Sjmallett#endif 73232812Sjmallett 74232809Sjmallett/** 75232809Sjmallett * The JTAG chain for CN52XX and CN56XX is 4 * 268 bits long, or 1072. 76232809Sjmallett * CN5XXX full chain shift is: 77232809Sjmallett * new data => lane 3 => lane 2 => lane 1 => lane 0 => data out 78232809Sjmallett * The JTAG chain for CN63XX is 4 * 300 bits long, or 1200. 79232809Sjmallett * The JTAG chain for CN68XX is 4 * 304 bits long, or 1216. 80232809Sjmallett * The JTAG chain for CN66XX/CN61XX/CNF71XX is 4 * 304 bits long, or 1216. 81232809Sjmallett * CN6XXX full chain shift is: 82232809Sjmallett * new data => lane 0 => lane 1 => lane 2 => lane 3 => data out 83232809Sjmallett * Shift LSB first, get LSB out 84232809Sjmallett */ 85232809Sjmallettextern const __cvmx_qlm_jtag_field_t __cvmx_qlm_jtag_field_cn52xx[]; 86232809Sjmallettextern const __cvmx_qlm_jtag_field_t __cvmx_qlm_jtag_field_cn56xx[]; 87232809Sjmallettextern const __cvmx_qlm_jtag_field_t __cvmx_qlm_jtag_field_cn63xx[]; 88232809Sjmallettextern const __cvmx_qlm_jtag_field_t __cvmx_qlm_jtag_field_cn66xx[]; 89232809Sjmallettextern const __cvmx_qlm_jtag_field_t __cvmx_qlm_jtag_field_cn68xx[]; 90232809Sjmallett 91232809Sjmallett#define CVMX_QLM_JTAG_UINT32 40 92232809Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_HOST 93232809Sjmallettextern void octeon_remote_read_mem(void *buffer, uint64_t physical_address, int length); 94232809Sjmallettextern void octeon_remote_write_mem(uint64_t physical_address, const void *buffer, int length); 95232809Sjmallettuint32_t __cvmx_qlm_jtag_xor_ref[5][CVMX_QLM_JTAG_UINT32]; 96232809Sjmallett#else 97232809Sjmalletttypedef uint32_t qlm_jtag_uint32_t[CVMX_QLM_JTAG_UINT32]; 98232809SjmallettCVMX_SHARED qlm_jtag_uint32_t *__cvmx_qlm_jtag_xor_ref; 99232809Sjmallett#endif 100232809Sjmallett 101232809Sjmallett 102232809Sjmallett/** 103232809Sjmallett * Return the number of QLMs supported by the chip 104232809Sjmallett * 105232809Sjmallett * @return Number of QLMs 106232809Sjmallett */ 107232809Sjmallettint cvmx_qlm_get_num(void) 108232809Sjmallett{ 109232809Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN68XX)) 110232809Sjmallett return 5; 111232809Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CN66XX)) 112232809Sjmallett return 3; 113232809Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CN63XX)) 114232809Sjmallett return 3; 115232809Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CN61XX)) 116232809Sjmallett return 3; 117232809Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CN56XX)) 118232809Sjmallett return 4; 119232809Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CNF71XX)) 120232809Sjmallett return 2; 121232809Sjmallett 122232809Sjmallett //cvmx_dprintf("Warning: cvmx_qlm_get_num: This chip does not have QLMs\n"); 123232809Sjmallett return 0; 124232809Sjmallett} 125232809Sjmallett 126232809Sjmallett/** 127232809Sjmallett * Return the qlm number based on the interface 128232809Sjmallett * 129232809Sjmallett * @param interface Interface to look up 130232809Sjmallett */ 131232809Sjmallettint cvmx_qlm_interface(int interface) 132232809Sjmallett{ 133232809Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN61XX)) { 134232809Sjmallett return (interface == 0) ? 2 : 0; 135232809Sjmallett } else if (OCTEON_IS_MODEL(OCTEON_CN63XX) || OCTEON_IS_MODEL(OCTEON_CN66XX)) { 136232809Sjmallett return 2 - interface; 137232809Sjmallett } else { 138232809Sjmallett /* Must be cn68XX */ 139232809Sjmallett switch(interface) { 140232809Sjmallett case 1: 141232809Sjmallett return 0; 142232809Sjmallett default: 143232809Sjmallett return interface; 144232809Sjmallett } 145232809Sjmallett } 146232809Sjmallett} 147232809Sjmallett 148232809Sjmallett/** 149232809Sjmallett * Return number of lanes for a given qlm 150232809Sjmallett * 151232809Sjmallett * @return Number of lanes 152232809Sjmallett */ 153232809Sjmallettint cvmx_qlm_get_lanes(int qlm) 154232809Sjmallett{ 155232809Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN61XX) && qlm == 1) 156232809Sjmallett return 2; 157232809Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) 158232809Sjmallett return 2; 159232809Sjmallett 160232809Sjmallett return 4; 161232809Sjmallett} 162232809Sjmallett 163232809Sjmallett/** 164232809Sjmallett * Get the QLM JTAG fields based on Octeon model on the supported chips. 165232809Sjmallett * 166232809Sjmallett * @return qlm_jtag_field_t structure 167232809Sjmallett */ 168232809Sjmallettconst __cvmx_qlm_jtag_field_t *cvmx_qlm_jtag_get_field(void) 169232809Sjmallett{ 170232809Sjmallett /* Figure out which JTAG chain description we're using */ 171232809Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN68XX)) 172232809Sjmallett return __cvmx_qlm_jtag_field_cn68xx; 173232809Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CN66XX) 174232809Sjmallett || OCTEON_IS_MODEL(OCTEON_CN61XX) 175232809Sjmallett || OCTEON_IS_MODEL(OCTEON_CNF71XX)) 176232809Sjmallett return __cvmx_qlm_jtag_field_cn66xx; 177232809Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CN63XX)) 178232809Sjmallett return __cvmx_qlm_jtag_field_cn63xx; 179232809Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CN56XX)) 180232809Sjmallett return __cvmx_qlm_jtag_field_cn56xx; 181232809Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CN52XX)) 182232809Sjmallett return __cvmx_qlm_jtag_field_cn52xx; 183232809Sjmallett else 184232809Sjmallett { 185232809Sjmallett //cvmx_dprintf("cvmx_qlm_jtag_get_field: Needs update for this chip\n"); 186232809Sjmallett return NULL; 187232809Sjmallett } 188232809Sjmallett} 189232809Sjmallett 190232809Sjmallett/** 191232809Sjmallett * Get the QLM JTAG length by going through qlm_jtag_field for each 192232809Sjmallett * Octeon model that is supported 193232809Sjmallett * 194232809Sjmallett * @return return the length. 195232809Sjmallett */ 196232809Sjmallettint cvmx_qlm_jtag_get_length(void) 197232809Sjmallett{ 198232809Sjmallett const __cvmx_qlm_jtag_field_t *qlm_ptr = cvmx_qlm_jtag_get_field(); 199232809Sjmallett int length = 0; 200232809Sjmallett 201232809Sjmallett /* Figure out how many bits are in the JTAG chain */ 202232809Sjmallett while (qlm_ptr != NULL && qlm_ptr->name) 203232809Sjmallett { 204232809Sjmallett if (qlm_ptr->stop_bit > length) 205232809Sjmallett length = qlm_ptr->stop_bit + 1; 206232809Sjmallett qlm_ptr++; 207232809Sjmallett } 208232809Sjmallett return length; 209232809Sjmallett} 210232809Sjmallett 211232809Sjmallett/** 212232809Sjmallett * Initialize the QLM layer 213232809Sjmallett */ 214232809Sjmallettvoid cvmx_qlm_init(void) 215232809Sjmallett{ 216232809Sjmallett int qlm; 217232809Sjmallett int qlm_jtag_length; 218232809Sjmallett char *qlm_jtag_name = "cvmx_qlm_jtag"; 219232809Sjmallett int qlm_jtag_size = CVMX_QLM_JTAG_UINT32 * 8 * 4; 220232809Sjmallett static uint64_t qlm_base = 0; 221232809Sjmallett const cvmx_bootmem_named_block_desc_t *desc; 222232809Sjmallett 223232809Sjmallett#ifndef CVMX_BUILD_FOR_LINUX_HOST 224232809Sjmallett /* Skip actual JTAG accesses on simulator */ 225232809Sjmallett if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM) 226232809Sjmallett return; 227232809Sjmallett#endif 228232809Sjmallett 229232809Sjmallett qlm_jtag_length = cvmx_qlm_jtag_get_length(); 230232809Sjmallett 231232809Sjmallett if (4 * qlm_jtag_length > (int)sizeof(__cvmx_qlm_jtag_xor_ref[0]) * 8) 232232809Sjmallett { 233232809Sjmallett cvmx_dprintf("ERROR: cvmx_qlm_init: JTAG chain larger than XOR ref size\n"); 234232809Sjmallett return; 235232809Sjmallett } 236232809Sjmallett 237232809Sjmallett /* No need to initialize the initial JTAG state if cvmx_qlm_jtag 238232809Sjmallett named block is already created. */ 239232809Sjmallett if ((desc = cvmx_bootmem_find_named_block(qlm_jtag_name)) != NULL) 240232809Sjmallett { 241232809Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_HOST 242232809Sjmallett char buffer[qlm_jtag_size]; 243232809Sjmallett 244232809Sjmallett octeon_remote_read_mem(buffer, desc->base_addr, qlm_jtag_size); 245232809Sjmallett memcpy(__cvmx_qlm_jtag_xor_ref, buffer, qlm_jtag_size); 246232809Sjmallett#else 247232809Sjmallett __cvmx_qlm_jtag_xor_ref = cvmx_phys_to_ptr(desc->base_addr); 248232809Sjmallett#endif 249232809Sjmallett /* Initialize the internal JTAG */ 250232809Sjmallett cvmx_helper_qlm_jtag_init(); 251232809Sjmallett return; 252232809Sjmallett } 253232809Sjmallett 254232809Sjmallett /* Create named block to store the initial JTAG state. */ 255232809Sjmallett qlm_base = cvmx_bootmem_phy_named_block_alloc(qlm_jtag_size, 0, 0, 128, qlm_jtag_name, CVMX_BOOTMEM_FLAG_END_ALLOC); 256232809Sjmallett 257232809Sjmallett if (qlm_base == -1ull) 258232809Sjmallett { 259232809Sjmallett cvmx_dprintf("ERROR: cvmx_qlm_init: Error in creating %s named block\n", qlm_jtag_name); 260232809Sjmallett return; 261232809Sjmallett } 262232809Sjmallett 263232809Sjmallett#ifndef CVMX_BUILD_FOR_LINUX_HOST 264232809Sjmallett __cvmx_qlm_jtag_xor_ref = cvmx_phys_to_ptr(qlm_base); 265232809Sjmallett#endif 266232809Sjmallett memset(__cvmx_qlm_jtag_xor_ref, 0, qlm_jtag_size); 267232809Sjmallett 268232809Sjmallett /* Initialize the internal JTAG */ 269232809Sjmallett cvmx_helper_qlm_jtag_init(); 270232809Sjmallett 271232809Sjmallett /* Read the XOR defaults for the JTAG chain */ 272232809Sjmallett for (qlm=0; qlm<cvmx_qlm_get_num(); qlm++) 273232809Sjmallett { 274232809Sjmallett int i; 275232809Sjmallett /* Capture the reset defaults */ 276232809Sjmallett cvmx_helper_qlm_jtag_capture(qlm); 277232809Sjmallett /* Save the reset defaults. This will shift out too much data, but 278232809Sjmallett the extra zeros don't hurt anything */ 279232809Sjmallett for (i=0; i<CVMX_QLM_JTAG_UINT32; i++) 280232809Sjmallett __cvmx_qlm_jtag_xor_ref[qlm][i] = cvmx_helper_qlm_jtag_shift(qlm, 32, 0); 281232809Sjmallett } 282232809Sjmallett 283232809Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_HOST 284232809Sjmallett /* Update the initial state for oct-remote utils. */ 285232809Sjmallett { 286232809Sjmallett char buffer[qlm_jtag_size]; 287232809Sjmallett 288232809Sjmallett memcpy(buffer, &__cvmx_qlm_jtag_xor_ref, qlm_jtag_size); 289232809Sjmallett octeon_remote_write_mem(qlm_base, buffer, qlm_jtag_size); 290232809Sjmallett } 291232809Sjmallett#endif 292232809Sjmallett 293232809Sjmallett /* Apply speed tweak as a workaround for errata G-16094. */ 294232809Sjmallett __cvmx_qlm_speed_tweak(); 295232809Sjmallett __cvmx_qlm_pcie_idle_dac_tweak(); 296232809Sjmallett} 297232809Sjmallett 298232809Sjmallett/** 299232809Sjmallett * Lookup the bit information for a JTAG field name 300232809Sjmallett * 301232809Sjmallett * @param name Name to lookup 302232809Sjmallett * 303232809Sjmallett * @return Field info, or NULL on failure 304232809Sjmallett */ 305232809Sjmallettstatic const __cvmx_qlm_jtag_field_t *__cvmx_qlm_lookup_field(const char *name) 306232809Sjmallett{ 307232809Sjmallett const __cvmx_qlm_jtag_field_t *ptr = cvmx_qlm_jtag_get_field(); 308232809Sjmallett while (ptr->name) 309232809Sjmallett { 310232809Sjmallett if (strcmp(name, ptr->name) == 0) 311232809Sjmallett return ptr; 312232809Sjmallett ptr++; 313232809Sjmallett } 314232809Sjmallett cvmx_dprintf("__cvmx_qlm_lookup_field: Illegal field name %s\n", name); 315232809Sjmallett return NULL; 316232809Sjmallett} 317232809Sjmallett 318232809Sjmallett/** 319232809Sjmallett * Get a field in a QLM JTAG chain 320232809Sjmallett * 321232809Sjmallett * @param qlm QLM to get 322232809Sjmallett * @param lane Lane in QLM to get 323232809Sjmallett * @param name String name of field 324232809Sjmallett * 325232809Sjmallett * @return JTAG field value 326232809Sjmallett */ 327232809Sjmallettuint64_t cvmx_qlm_jtag_get(int qlm, int lane, const char *name) 328232809Sjmallett{ 329232809Sjmallett const __cvmx_qlm_jtag_field_t *field = __cvmx_qlm_lookup_field(name); 330232809Sjmallett int qlm_jtag_length = cvmx_qlm_jtag_get_length(); 331232809Sjmallett int num_lanes = cvmx_qlm_get_lanes(qlm); 332232809Sjmallett 333232809Sjmallett if (!field) 334232809Sjmallett return 0; 335232809Sjmallett 336232809Sjmallett /* Capture the current settings */ 337232809Sjmallett cvmx_helper_qlm_jtag_capture(qlm); 338232809Sjmallett /* Shift past lanes we don't care about. CN6XXX shifts lane 3 first */ 339232809Sjmallett cvmx_helper_qlm_jtag_shift_zeros(qlm, qlm_jtag_length * (num_lanes-1-lane)); /* Shift to the start of the field */ 340232809Sjmallett cvmx_helper_qlm_jtag_shift_zeros(qlm, field->start_bit); 341232809Sjmallett /* Shift out the value and return it */ 342232809Sjmallett return cvmx_helper_qlm_jtag_shift(qlm, field->stop_bit - field->start_bit + 1, 0); 343232809Sjmallett} 344232809Sjmallett 345232809Sjmallett/** 346232809Sjmallett * Set a field in a QLM JTAG chain 347232809Sjmallett * 348232809Sjmallett * @param qlm QLM to set 349232809Sjmallett * @param lane Lane in QLM to set, or -1 for all lanes 350232809Sjmallett * @param name String name of field 351232809Sjmallett * @param value Value of the field 352232809Sjmallett */ 353232809Sjmallettvoid cvmx_qlm_jtag_set(int qlm, int lane, const char *name, uint64_t value) 354232809Sjmallett{ 355232809Sjmallett int i, l; 356232809Sjmallett uint32_t shift_values[CVMX_QLM_JTAG_UINT32]; 357232809Sjmallett int num_lanes = cvmx_qlm_get_lanes(qlm); 358232809Sjmallett const __cvmx_qlm_jtag_field_t *field = __cvmx_qlm_lookup_field(name); 359232809Sjmallett int qlm_jtag_length = cvmx_qlm_jtag_get_length(); 360232809Sjmallett int total_length = qlm_jtag_length * num_lanes; 361232809Sjmallett int bits = 0; 362232809Sjmallett 363232809Sjmallett if (!field) 364232809Sjmallett return; 365232809Sjmallett 366232809Sjmallett /* Get the current state */ 367232809Sjmallett cvmx_helper_qlm_jtag_capture(qlm); 368232809Sjmallett for (i=0; i<CVMX_QLM_JTAG_UINT32; i++) 369232809Sjmallett shift_values[i] = cvmx_helper_qlm_jtag_shift(qlm, 32, 0); 370232809Sjmallett 371232809Sjmallett /* Put new data in our local array */ 372232809Sjmallett for (l=0; l<num_lanes; l++) 373232809Sjmallett { 374232809Sjmallett uint64_t new_value = value; 375232809Sjmallett int bits; 376232809Sjmallett if ((l != lane) && (lane != -1)) 377232809Sjmallett continue; 378232809Sjmallett for (bits = field->start_bit + (num_lanes-1-l)*qlm_jtag_length; 379232809Sjmallett bits <= field->stop_bit + (num_lanes-1-l)*qlm_jtag_length; 380232809Sjmallett bits++) 381232809Sjmallett { 382232809Sjmallett if (new_value & 1) 383232809Sjmallett shift_values[bits/32] |= 1<<(bits&31); 384232809Sjmallett else 385232809Sjmallett shift_values[bits/32] &= ~(1<<(bits&31)); 386232809Sjmallett new_value>>=1; 387232809Sjmallett } 388232809Sjmallett } 389232809Sjmallett 390232809Sjmallett /* Shift out data and xor with reference */ 391232809Sjmallett while (bits < total_length) 392232809Sjmallett { 393232809Sjmallett uint32_t shift = shift_values[bits/32] ^ __cvmx_qlm_jtag_xor_ref[qlm][bits/32]; 394232809Sjmallett int width = total_length - bits; 395232809Sjmallett if (width > 32) 396232809Sjmallett width = 32; 397232809Sjmallett cvmx_helper_qlm_jtag_shift(qlm, width, shift); 398232809Sjmallett bits += 32; 399232809Sjmallett } 400232809Sjmallett 401232809Sjmallett /* Update the new data */ 402232809Sjmallett cvmx_helper_qlm_jtag_update(qlm); 403232809Sjmallett /* Always give the QLM 1ms to settle after every update. This may not 404232809Sjmallett always be needed, but some of the options make significant 405232809Sjmallett electrical changes */ 406232809Sjmallett cvmx_wait_usec(1000); 407232809Sjmallett} 408232809Sjmallett 409232809Sjmallett/** 410232809Sjmallett * Errata G-16094: QLM Gen2 Equalizer Default Setting Change. 411232809Sjmallett * CN68XX pass 1.x and CN66XX pass 1.x QLM tweak. This function tweaks the 412232809Sjmallett * JTAG setting for a QLMs to run better at 5 and 6.25Ghz. 413232809Sjmallett */ 414232809Sjmallettvoid __cvmx_qlm_speed_tweak(void) 415232809Sjmallett{ 416232809Sjmallett cvmx_mio_qlmx_cfg_t qlm_cfg; 417232809Sjmallett int num_qlms = 0; 418232809Sjmallett int qlm; 419232809Sjmallett 420232809Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_X)) 421232809Sjmallett num_qlms = 5; 422232809Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_X)) 423232809Sjmallett num_qlms = 3; 424232809Sjmallett else 425232809Sjmallett return; 426232809Sjmallett 427232809Sjmallett /* Loop through the QLMs */ 428232809Sjmallett for (qlm = 0; qlm < num_qlms; qlm++) 429232809Sjmallett { 430232809Sjmallett /* Read the QLM speed */ 431232809Sjmallett qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm)); 432232809Sjmallett 433232809Sjmallett /* If the QLM is at 6.25Ghz or 5Ghz then program JTAG */ 434232809Sjmallett if ((qlm_cfg.s.qlm_spd == 5) || (qlm_cfg.s.qlm_spd == 12) || 435232809Sjmallett (qlm_cfg.s.qlm_spd == 0) || (qlm_cfg.s.qlm_spd == 6) || 436232809Sjmallett (qlm_cfg.s.qlm_spd == 11)) 437232809Sjmallett { 438232809Sjmallett cvmx_qlm_jtag_set(qlm, -1, "rx_cap_gen2", 0x1); 439232809Sjmallett cvmx_qlm_jtag_set(qlm, -1, "rx_eq_gen2", 0x8); 440232809Sjmallett } 441232809Sjmallett } 442232809Sjmallett} 443232809Sjmallett 444232809Sjmallett/** 445232809Sjmallett * Errata G-16174: QLM Gen2 PCIe IDLE DAC change. 446232809Sjmallett * CN68XX pass 1.x, CN66XX pass 1.x and CN63XX pass 1.0-2.2 QLM tweak. 447232809Sjmallett * This function tweaks the JTAG setting for a QLMs for PCIe to run better. 448232809Sjmallett */ 449232809Sjmallettvoid __cvmx_qlm_pcie_idle_dac_tweak(void) 450232809Sjmallett{ 451232809Sjmallett int num_qlms = 0; 452232809Sjmallett int qlm; 453232809Sjmallett 454232809Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_X)) 455232809Sjmallett num_qlms = 5; 456232809Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_X)) 457232809Sjmallett num_qlms = 3; 458232809Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X) || 459232809Sjmallett OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_X)) 460232809Sjmallett num_qlms = 3; 461232809Sjmallett else 462232809Sjmallett return; 463232809Sjmallett 464232809Sjmallett /* Loop through the QLMs */ 465232809Sjmallett for (qlm = 0; qlm < num_qlms; qlm++) 466232809Sjmallett cvmx_qlm_jtag_set(qlm, -1, "idle_dac", 0x2); 467232809Sjmallett} 468232809Sjmallett 469232809Sjmallett#ifndef CVMX_BUILD_FOR_LINUX_HOST 470232809Sjmallett/** 471232809Sjmallett * Get the speed (Gbaud) of the QLM in Mhz. 472232809Sjmallett * 473232809Sjmallett * @param qlm QLM to examine 474232809Sjmallett * 475232809Sjmallett * @return Speed in Mhz 476232809Sjmallett */ 477232809Sjmallettint cvmx_qlm_get_gbaud_mhz(int qlm) 478232809Sjmallett{ 479232809Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN63XX)) 480232809Sjmallett { 481232809Sjmallett if (qlm == 2) 482232809Sjmallett { 483232809Sjmallett cvmx_gmxx_inf_mode_t inf_mode; 484232809Sjmallett inf_mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(0)); 485232809Sjmallett switch (inf_mode.s.speed) 486232809Sjmallett { 487232809Sjmallett case 0: return 5000; /* 5 Gbaud */ 488232809Sjmallett case 1: return 2500; /* 2.5 Gbaud */ 489232809Sjmallett case 2: return 2500; /* 2.5 Gbaud */ 490232809Sjmallett case 3: return 1250; /* 1.25 Gbaud */ 491232809Sjmallett case 4: return 1250; /* 1.25 Gbaud */ 492232809Sjmallett case 5: return 6250; /* 6.25 Gbaud */ 493232809Sjmallett case 6: return 5000; /* 5 Gbaud */ 494232809Sjmallett case 7: return 2500; /* 2.5 Gbaud */ 495232809Sjmallett case 8: return 3125; /* 3.125 Gbaud */ 496232809Sjmallett case 9: return 2500; /* 2.5 Gbaud */ 497232809Sjmallett case 10: return 1250; /* 1.25 Gbaud */ 498232809Sjmallett case 11: return 5000; /* 5 Gbaud */ 499232809Sjmallett case 12: return 6250; /* 6.25 Gbaud */ 500232809Sjmallett case 13: return 3750; /* 3.75 Gbaud */ 501232809Sjmallett case 14: return 3125; /* 3.125 Gbaud */ 502232809Sjmallett default: return 0; /* Disabled */ 503232809Sjmallett } 504232809Sjmallett } 505232809Sjmallett else 506232809Sjmallett { 507232809Sjmallett cvmx_sriox_status_reg_t status_reg; 508232809Sjmallett status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(qlm)); 509232809Sjmallett if (status_reg.s.srio) 510232809Sjmallett { 511232809Sjmallett cvmx_sriomaintx_port_0_ctl2_t sriomaintx_port_0_ctl2; 512232809Sjmallett sriomaintx_port_0_ctl2.u32 = cvmx_read_csr(CVMX_SRIOMAINTX_PORT_0_CTL2(qlm)); 513232809Sjmallett switch (sriomaintx_port_0_ctl2.s.sel_baud) 514232809Sjmallett { 515232809Sjmallett case 1: return 1250; /* 1.25 Gbaud */ 516232809Sjmallett case 2: return 2500; /* 2.5 Gbaud */ 517232809Sjmallett case 3: return 3125; /* 3.125 Gbaud */ 518232809Sjmallett case 4: return 5000; /* 5 Gbaud */ 519232809Sjmallett case 5: return 6250; /* 6.250 Gbaud */ 520232809Sjmallett default: return 0; /* Disabled */ 521232809Sjmallett } 522232809Sjmallett } 523232809Sjmallett else 524232809Sjmallett { 525232809Sjmallett cvmx_pciercx_cfg032_t pciercx_cfg032; 526232809Sjmallett pciercx_cfg032.u32 = cvmx_read_csr(CVMX_PCIERCX_CFG032(qlm)); 527232809Sjmallett switch (pciercx_cfg032.s.ls) 528232809Sjmallett { 529232809Sjmallett case 1: 530232809Sjmallett return 2500; 531232809Sjmallett case 2: 532232809Sjmallett return 5000; 533232809Sjmallett case 4: 534232809Sjmallett return 8000; 535232809Sjmallett default: 536232809Sjmallett { 537232809Sjmallett cvmx_mio_rst_boot_t mio_rst_boot; 538232809Sjmallett mio_rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT); 539232809Sjmallett if ((qlm == 0) && mio_rst_boot.s.qlm0_spd == 0xf) 540232809Sjmallett return 0; 541232809Sjmallett if ((qlm == 1) && mio_rst_boot.s.qlm1_spd == 0xf) 542232809Sjmallett return 0; 543232809Sjmallett return 5000; /* Best guess I can make */ 544232809Sjmallett } 545232809Sjmallett } 546232809Sjmallett } 547232809Sjmallett } 548232809Sjmallett } 549232809Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF71XX)) 550232809Sjmallett { 551232809Sjmallett cvmx_mio_qlmx_cfg_t qlm_cfg; 552232809Sjmallett 553232809Sjmallett qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm)); 554232809Sjmallett switch (qlm_cfg.s.qlm_spd) 555232809Sjmallett { 556232809Sjmallett case 0: return 5000; /* 5 Gbaud */ 557232809Sjmallett case 1: return 2500; /* 2.5 Gbaud */ 558232809Sjmallett case 2: return 2500; /* 2.5 Gbaud */ 559232809Sjmallett case 3: return 1250; /* 1.25 Gbaud */ 560232809Sjmallett case 4: return 1250; /* 1.25 Gbaud */ 561232809Sjmallett case 5: return 6250; /* 6.25 Gbaud */ 562232809Sjmallett case 6: return 5000; /* 5 Gbaud */ 563232809Sjmallett case 7: return 2500; /* 2.5 Gbaud */ 564232809Sjmallett case 8: return 3125; /* 3.125 Gbaud */ 565232809Sjmallett case 9: return 2500; /* 2.5 Gbaud */ 566232809Sjmallett case 10: return 1250; /* 1.25 Gbaud */ 567232809Sjmallett case 11: return 5000; /* 5 Gbaud */ 568232809Sjmallett case 12: return 6250; /* 6.25 Gbaud */ 569232809Sjmallett case 13: return 3750; /* 3.75 Gbaud */ 570232809Sjmallett case 14: return 3125; /* 3.125 Gbaud */ 571232809Sjmallett default: return 0; /* Disabled */ 572232809Sjmallett } 573232809Sjmallett } 574232809Sjmallett return 0; 575232809Sjmallett} 576232809Sjmallett#endif 577232809Sjmallett 578232809Sjmallett/* 579232809Sjmallett * Read QLM and return status based on CN66XX. 580232809Sjmallett * @return Return 1 if QLM is SGMII 581232809Sjmallett * 2 if QLM is XAUI 582232809Sjmallett * 3 if QLM is PCIe gen2 / gen1 583232809Sjmallett * 4 if QLM is SRIO 1x4 short / long 584232809Sjmallett * 5 if QLM is SRIO 2x2 short / long 585232809Sjmallett * 6 if QLM is SRIO 4x1 short / long 586232809Sjmallett * 7 if QLM is PCIe 1x2 gen2 / gen1 587232809Sjmallett * 8 if QLM is PCIe 2x1 gen2 / gen1 588232809Sjmallett * 9 if QLM is ILK 589232809Sjmallett * 10 if QLM is RXAUI 590232809Sjmallett * -1 otherwise 591232809Sjmallett */ 592232809Sjmallettint cvmx_qlm_get_status(int qlm) 593232809Sjmallett{ 594232809Sjmallett cvmx_mio_qlmx_cfg_t qlmx_cfg; 595232809Sjmallett 596232809Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN68XX)) 597232809Sjmallett { 598232809Sjmallett qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm)); 599232809Sjmallett /* QLM is disabled when QLM SPD is 15. */ 600232809Sjmallett if (qlmx_cfg.s.qlm_spd == 15) 601232809Sjmallett return -1; 602232809Sjmallett 603232809Sjmallett switch (qlmx_cfg.s.qlm_cfg) 604232809Sjmallett { 605232809Sjmallett case 0: /* PCIE */ 606232809Sjmallett return 3; 607232809Sjmallett case 1: /* ILK */ 608232809Sjmallett return 9; 609232809Sjmallett case 2: /* SGMII */ 610232809Sjmallett return 1; 611232809Sjmallett case 3: /* XAUI */ 612232809Sjmallett return 2; 613232809Sjmallett case 7: /* RXAUI */ 614232809Sjmallett return 10; 615232809Sjmallett default: return -1; 616232809Sjmallett } 617232809Sjmallett } 618232809Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CN66XX)) 619232809Sjmallett { 620232809Sjmallett qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm)); 621232809Sjmallett /* QLM is disabled when QLM SPD is 15. */ 622232809Sjmallett if (qlmx_cfg.s.qlm_spd == 15) 623232809Sjmallett return -1; 624232809Sjmallett 625232809Sjmallett switch (qlmx_cfg.s.qlm_cfg) 626232809Sjmallett { 627232809Sjmallett case 0x9: /* SGMII */ 628232809Sjmallett return 1; 629232809Sjmallett case 0xb: /* XAUI */ 630232809Sjmallett return 2; 631232809Sjmallett case 0x0: /* PCIE gen2 */ 632232809Sjmallett case 0x8: /* PCIE gen2 (alias) */ 633232809Sjmallett case 0x2: /* PCIE gen1 */ 634232809Sjmallett case 0xa: /* PCIE gen1 (alias) */ 635232809Sjmallett return 3; 636232809Sjmallett case 0x1: /* SRIO 1x4 short */ 637232809Sjmallett case 0x3: /* SRIO 1x4 long */ 638232809Sjmallett return 4; 639232809Sjmallett case 0x4: /* SRIO 2x2 short */ 640232809Sjmallett case 0x6: /* SRIO 2x2 long */ 641232809Sjmallett return 5; 642232809Sjmallett case 0x5: /* SRIO 4x1 short */ 643232809Sjmallett case 0x7: /* SRIO 4x1 long */ 644232809Sjmallett if (!OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_0)) 645232809Sjmallett return 6; 646232809Sjmallett default: 647232809Sjmallett return -1; 648232809Sjmallett } 649232809Sjmallett } 650232809Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CN63XX)) 651232809Sjmallett { 652232809Sjmallett cvmx_sriox_status_reg_t status_reg; 653232809Sjmallett /* For now skip qlm2 */ 654232809Sjmallett if (qlm == 2) 655232809Sjmallett { 656232809Sjmallett cvmx_gmxx_inf_mode_t inf_mode; 657232809Sjmallett inf_mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(0)); 658232809Sjmallett if (inf_mode.s.speed == 15) 659232809Sjmallett return -1; 660232809Sjmallett else if(inf_mode.s.mode == 0) 661232809Sjmallett return 1; 662232809Sjmallett else 663232809Sjmallett return 2; 664232809Sjmallett } 665232809Sjmallett status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(qlm)); 666232809Sjmallett if (status_reg.s.srio) 667232809Sjmallett return 4; 668232809Sjmallett else 669232809Sjmallett return 3; 670232809Sjmallett } 671232809Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CN61XX)) 672232809Sjmallett { 673232809Sjmallett qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm)); 674232809Sjmallett /* QLM is disabled when QLM SPD is 15. */ 675232809Sjmallett if (qlmx_cfg.s.qlm_spd == 15) 676232809Sjmallett return -1; 677232809Sjmallett 678232809Sjmallett switch(qlm) 679232809Sjmallett { 680232809Sjmallett case 0: 681232809Sjmallett switch (qlmx_cfg.s.qlm_cfg) 682232809Sjmallett { 683232809Sjmallett case 0: /* PCIe 1x4 gen2 / gen1 */ 684232809Sjmallett return 3; 685232809Sjmallett case 2: /* SGMII */ 686232809Sjmallett return 1; 687232809Sjmallett case 3: /* XAUI */ 688232809Sjmallett return 2; 689232809Sjmallett default: return -1; 690232809Sjmallett } 691232809Sjmallett break; 692232809Sjmallett case 1: 693232809Sjmallett switch (qlmx_cfg.s.qlm_cfg) 694232809Sjmallett { 695232809Sjmallett case 0: /* PCIe 1x2 gen2 / gen1 */ 696232809Sjmallett return 7; 697232809Sjmallett case 1: /* PCIe 2x1 gen2 / gen1 */ 698232809Sjmallett return 8; 699232809Sjmallett default: return -1; 700232809Sjmallett } 701232809Sjmallett break; 702232809Sjmallett case 2: 703232809Sjmallett switch (qlmx_cfg.s.qlm_cfg) 704232809Sjmallett { 705232809Sjmallett case 2: /* SGMII */ 706232809Sjmallett return 1; 707232809Sjmallett case 3: /* XAUI */ 708232809Sjmallett return 2; 709232809Sjmallett default: return -1; 710232809Sjmallett } 711232809Sjmallett break; 712232809Sjmallett } 713232809Sjmallett } 714232809Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) 715232809Sjmallett { 716232809Sjmallett qlmx_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm)); 717232809Sjmallett /* QLM is disabled when QLM SPD is 15. */ 718232809Sjmallett if (qlmx_cfg.s.qlm_spd == 15) 719232809Sjmallett return -1; 720232809Sjmallett 721232809Sjmallett switch(qlm) 722232809Sjmallett { 723232809Sjmallett case 0: 724232809Sjmallett if (qlmx_cfg.s.qlm_cfg == 2) /* SGMII */ 725232809Sjmallett return 1; 726232809Sjmallett break; 727232809Sjmallett case 1: 728232809Sjmallett switch (qlmx_cfg.s.qlm_cfg) 729232809Sjmallett { 730232809Sjmallett case 0: /* PCIe 1x2 gen2 / gen1 */ 731232809Sjmallett return 7; 732232809Sjmallett case 1: /* PCIe 2x1 gen2 / gen1 */ 733232809Sjmallett return 8; 734232809Sjmallett default: return -1; 735232809Sjmallett } 736232809Sjmallett break; 737232809Sjmallett } 738232809Sjmallett } 739232809Sjmallett return -1; 740232809Sjmallett} 741