1 2/***********************license start*************** 3 * Copyright (c) 2003-2010 Cavium Networks (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 Networks 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 NETWORKS 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 = cvmx_clock_get_rate(CVMX_CLOCK_SCLK) / (25 * 1000000); 76 divisor = (divisor-1)>>2; 77 /* Convert the divisor into a power of 2 shift */ 78 while (divisor) 79 { 80 clock_div++; 81 divisor>>=1; 82 } 83 84 /* Clock divider for QLM JTAG operations. sclk is divided by 2^(CLK_DIV + 2) */ 85 jtgc.u64 = 0; 86 jtgc.s.clk_div = clock_div; 87 jtgc.s.mux_sel = 0; 88 if (OCTEON_IS_MODEL(OCTEON_CN52XX)) 89 jtgc.s.bypass = 0x3; 90 else if (OCTEON_IS_MODEL(OCTEON_CN63XX)) 91 jtgc.s.bypass = 0x7; 92 else 93 jtgc.s.bypass = 0xf; 94 cvmx_write_csr(CVMX_CIU_QLM_JTGC, jtgc.u64); 95 cvmx_read_csr(CVMX_CIU_QLM_JTGC); 96} 97 98 99/** 100 * Write up to 32bits into the QLM jtag chain. Bits are shifted 101 * into the MSB and out the LSB, so you should shift in the low 102 * order bits followed by the high order bits. The JTAG chain for 103 * CN52XX and CN56XX is 4 * 268 bits long, or 1072. The JTAG chain 104 * for CN63XX is 4 * 300 bits long, or 1200. 105 * 106 * @param qlm QLM to shift value into 107 * @param bits Number of bits to shift in (1-32). 108 * @param data Data to shift in. Bit 0 enters the chain first, followed by 109 * bit 1, etc. 110 * 111 * @return The low order bits of the JTAG chain that shifted out of the 112 * circle. 113 */ 114uint32_t cvmx_helper_qlm_jtag_shift(int qlm, int bits, uint32_t data) 115{ 116 cvmx_ciu_qlm_jtgc_t jtgc; 117 cvmx_ciu_qlm_jtgd_t jtgd; 118 119 jtgc.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGC); 120 jtgc.s.mux_sel = qlm; 121 if (!OCTEON_IS_MODEL(OCTEON_CN63XX)) 122 jtgc.s.bypass = 1<<qlm; 123 cvmx_write_csr(CVMX_CIU_QLM_JTGC, jtgc.u64); 124 cvmx_read_csr(CVMX_CIU_QLM_JTGC); 125 126 jtgd.u64 = 0; 127 jtgd.s.shift = 1; 128 jtgd.s.shft_cnt = bits-1; 129 jtgd.s.shft_reg = data; 130 if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)) 131 jtgd.s.select = 1 << qlm; 132 cvmx_write_csr(CVMX_CIU_QLM_JTGD, jtgd.u64); 133 do 134 { 135 jtgd.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGD); 136 } while (jtgd.s.shift); 137 return jtgd.s.shft_reg >> (32-bits); 138} 139 140 141/** 142 * Shift long sequences of zeros into the QLM JTAG chain. It is 143 * common to need to shift more than 32 bits of zeros into the 144 * chain. This function is a convience wrapper around 145 * cvmx_helper_qlm_jtag_shift() to shift more than 32 bits of 146 * zeros at a time. 147 * 148 * @param qlm QLM to shift zeros into 149 * @param bits 150 */ 151void cvmx_helper_qlm_jtag_shift_zeros(int qlm, int bits) 152{ 153 while (bits > 0) 154 { 155 int n = bits; 156 if (n > 32) 157 n = 32; 158 cvmx_helper_qlm_jtag_shift(qlm, n, 0); 159 bits -= n; 160 } 161} 162 163 164/** 165 * Program the QLM JTAG chain into all lanes of the QLM. You must 166 * have already shifted in the proper number of bits into the 167 * JTAG chain. Updating invalid values can possibly cause chip damage. 168 * 169 * @param qlm QLM to program 170 */ 171void cvmx_helper_qlm_jtag_update(int qlm) 172{ 173 cvmx_ciu_qlm_jtgc_t jtgc; 174 cvmx_ciu_qlm_jtgd_t jtgd; 175 176 jtgc.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGC); 177 jtgc.s.mux_sel = qlm; 178 if (!OCTEON_IS_MODEL(OCTEON_CN63XX)) 179 jtgc.s.bypass = 1<<qlm; 180 181 cvmx_write_csr(CVMX_CIU_QLM_JTGC, jtgc.u64); 182 cvmx_read_csr(CVMX_CIU_QLM_JTGC); 183 184 /* Update the new data */ 185 jtgd.u64 = 0; 186 jtgd.s.update = 1; 187 if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)) 188 jtgd.s.select = 1 << qlm; 189 cvmx_write_csr(CVMX_CIU_QLM_JTGD, jtgd.u64); 190 do 191 { 192 jtgd.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGD); 193 } while (jtgd.s.update); 194} 195 196 197/** 198 * Load the QLM JTAG chain with data from all lanes of the QLM. 199 * 200 * @param qlm QLM to program 201 */ 202void cvmx_helper_qlm_jtag_capture(int qlm) 203{ 204 cvmx_ciu_qlm_jtgc_t jtgc; 205 cvmx_ciu_qlm_jtgd_t jtgd; 206 207 jtgc.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGC); 208 jtgc.s.mux_sel = qlm; 209 if (!OCTEON_IS_MODEL(OCTEON_CN63XX)) 210 jtgc.s.bypass = 1<<qlm; 211 212 cvmx_write_csr(CVMX_CIU_QLM_JTGC, jtgc.u64); 213 cvmx_read_csr(CVMX_CIU_QLM_JTGC); 214 215 jtgd.u64 = 0; 216 jtgd.s.capture = 1; 217 if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)) 218 jtgd.s.select = 1 << qlm; 219 cvmx_write_csr(CVMX_CIU_QLM_JTGD, jtgd.u64); 220 do 221 { 222 jtgd.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGD); 223 } while (jtgd.s.capture); 224} 225 226