1 2/***********************license start*************** 3 * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights 4 * reserved. 5 * 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are 9 * met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * * Redistributions in binary form must reproduce the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer in the documentation and/or other materials provided 17 * with the distribution. 18 19 * * Neither the name of Cavium Inc. nor the names of 20 * its contributors may be used to endorse or promote products 21 * derived from this software without specific prior written 22 * permission. 23 24 * This Software, including technical data, may be subject to U.S. export control 25 * laws, including the U.S. Export Administration Act and its associated 26 * regulations, and may be subject to export or import regulations in other 27 * countries. 28 29 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 30 * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 31 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 32 * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 33 * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 34 * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 35 * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 36 * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 37 * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 38 * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 39 ***********************license end**************************************/ 40 41 42/** 43 * @file 44 * 45 * Helper utilities for qlm_jtag. 46 * 47 * <hr>$Revision: 42480 $<hr> 48 */ 49#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 50#include <asm/octeon/cvmx.h> 51#include <asm/octeon/cvmx-clock.h> 52#include <asm/octeon/cvmx-helper-jtag.h> 53#else 54#if !defined(__FreeBSD__) || !defined(_KERNEL) 55#include "executive-config.h" 56#include "cvmx-config.h" 57#endif 58#include "cvmx.h" 59#if defined(__FreeBSD__) && defined(_KERNEL) 60#include "cvmx-helper-jtag.h" 61#endif 62#endif 63 64/** 65 * Initialize the internal QLM JTAG logic to allow programming 66 * of the JTAG chain by the cvmx_helper_qlm_jtag_*() functions. 67 * These functions should only be used at the direction of Cavium 68 * Networks. Programming incorrect values into the JTAG chain 69 * can cause chip damage. 70 */ 71void cvmx_helper_qlm_jtag_init(void) 72{ 73 cvmx_ciu_qlm_jtgc_t jtgc; 74 int clock_div = 0; 75 int divisor; 76 77 divisor = cvmx_clock_get_rate(CVMX_CLOCK_SCLK) / (1000000 * 78 (OCTEON_IS_MODEL(OCTEON_CN68XX) ? 10 : 25)); 79 80 divisor = (divisor-1)>>2; 81 /* Convert the divisor into a power of 2 shift */ 82 while (divisor) 83 { 84 clock_div++; 85 divisor>>=1; 86 } 87 88 /* Clock divider for QLM JTAG operations. sclk is divided by 2^(CLK_DIV + 2) */ 89 jtgc.u64 = 0; 90 jtgc.s.clk_div = clock_div; 91 jtgc.s.mux_sel = 0; 92 if (OCTEON_IS_MODEL(OCTEON_CN52XX)) 93 jtgc.s.bypass = 0x3; 94 else if (OCTEON_IS_MODEL(OCTEON_CN63XX) || OCTEON_IS_MODEL(OCTEON_CN66XX)) 95 jtgc.s.bypass = 0x7; 96 else 97 jtgc.s.bypass = 0xf; 98 if (OCTEON_IS_MODEL(OCTEON_CN68XX)) 99 jtgc.s.bypass_ext = 1; 100 cvmx_write_csr(CVMX_CIU_QLM_JTGC, jtgc.u64); 101 cvmx_read_csr(CVMX_CIU_QLM_JTGC); 102} 103 104 105/** 106 * Write up to 32bits into the QLM jtag chain. Bits are shifted 107 * into the MSB and out the LSB, so you should shift in the low 108 * order bits followed by the high order bits. The JTAG chain for 109 * CN52XX and CN56XX is 4 * 268 bits long, or 1072. The JTAG chain 110 * for CN63XX is 4 * 300 bits long, or 1200. 111 * 112 * @param qlm QLM to shift value into 113 * @param bits Number of bits to shift in (1-32). 114 * @param data Data to shift in. Bit 0 enters the chain first, followed by 115 * bit 1, etc. 116 * 117 * @return The low order bits of the JTAG chain that shifted out of the 118 * circle. 119 */ 120uint32_t cvmx_helper_qlm_jtag_shift(int qlm, int bits, uint32_t data) 121{ 122 cvmx_ciu_qlm_jtgc_t jtgc; 123 cvmx_ciu_qlm_jtgd_t jtgd; 124 125 jtgc.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGC); 126 jtgc.s.mux_sel = qlm; 127 if (!OCTEON_IS_MODEL(OCTEON_CN6XXX) && !OCTEON_IS_MODEL(OCTEON_CNF7XXX)) 128 jtgc.s.bypass = 1<<qlm; 129 cvmx_write_csr(CVMX_CIU_QLM_JTGC, jtgc.u64); 130 cvmx_read_csr(CVMX_CIU_QLM_JTGC); 131 132 jtgd.u64 = 0; 133 jtgd.s.shift = 1; 134 jtgd.s.shft_cnt = bits-1; 135 jtgd.s.shft_reg = data; 136 if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)) 137 jtgd.s.select = 1 << qlm; 138 cvmx_write_csr(CVMX_CIU_QLM_JTGD, jtgd.u64); 139 do 140 { 141 jtgd.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGD); 142 } while (jtgd.s.shift); 143 return jtgd.s.shft_reg >> (32-bits); 144} 145 146 147/** 148 * Shift long sequences of zeros into the QLM JTAG chain. It is 149 * common to need to shift more than 32 bits of zeros into the 150 * chain. This function is a convience wrapper around 151 * cvmx_helper_qlm_jtag_shift() to shift more than 32 bits of 152 * zeros at a time. 153 * 154 * @param qlm QLM to shift zeros into 155 * @param bits 156 */ 157void cvmx_helper_qlm_jtag_shift_zeros(int qlm, int bits) 158{ 159 while (bits > 0) 160 { 161 int n = bits; 162 if (n > 32) 163 n = 32; 164 cvmx_helper_qlm_jtag_shift(qlm, n, 0); 165 bits -= n; 166 } 167} 168 169 170/** 171 * Program the QLM JTAG chain into all lanes of the QLM. You must 172 * have already shifted in the proper number of bits into the 173 * JTAG chain. Updating invalid values can possibly cause chip damage. 174 * 175 * @param qlm QLM to program 176 */ 177void cvmx_helper_qlm_jtag_update(int qlm) 178{ 179 cvmx_ciu_qlm_jtgc_t jtgc; 180 cvmx_ciu_qlm_jtgd_t jtgd; 181 182 jtgc.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGC); 183 jtgc.s.mux_sel = qlm; 184 if (!OCTEON_IS_MODEL(OCTEON_CN6XXX) && !OCTEON_IS_MODEL(OCTEON_CNF7XXX)) 185 jtgc.s.bypass = 1<<qlm; 186 187 cvmx_write_csr(CVMX_CIU_QLM_JTGC, jtgc.u64); 188 cvmx_read_csr(CVMX_CIU_QLM_JTGC); 189 190 /* Update the new data */ 191 jtgd.u64 = 0; 192 jtgd.s.update = 1; 193 if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)) 194 jtgd.s.select = 1 << qlm; 195 cvmx_write_csr(CVMX_CIU_QLM_JTGD, jtgd.u64); 196 do 197 { 198 jtgd.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGD); 199 } while (jtgd.s.update); 200} 201 202 203/** 204 * Load the QLM JTAG chain with data from all lanes of the QLM. 205 * 206 * @param qlm QLM to program 207 */ 208void cvmx_helper_qlm_jtag_capture(int qlm) 209{ 210 cvmx_ciu_qlm_jtgc_t jtgc; 211 cvmx_ciu_qlm_jtgd_t jtgd; 212 213 jtgc.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGC); 214 jtgc.s.mux_sel = qlm; 215 if (!OCTEON_IS_MODEL(OCTEON_CN6XXX) && !OCTEON_IS_MODEL(OCTEON_CNF7XXX)) 216 jtgc.s.bypass = 1<<qlm; 217 218 cvmx_write_csr(CVMX_CIU_QLM_JTGC, jtgc.u64); 219 cvmx_read_csr(CVMX_CIU_QLM_JTGC); 220 221 jtgd.u64 = 0; 222 jtgd.s.capture = 1; 223 if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)) 224 jtgd.s.select = 1 << qlm; 225 cvmx_write_csr(CVMX_CIU_QLM_JTGD, jtgd.u64); 226 do 227 { 228 jtgd.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGD); 229 } while (jtgd.s.capture); 230} 231