1233294Sstas 2102644Snectar/***********************license start*************** 355682Smarkm * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights 4142403Snectar * reserved. 5233294Sstas * 6233294Sstas * 755682Smarkm * Redistribution and use in source and binary forms, with or without 855682Smarkm * modification, are permitted provided that the following conditions are 955682Smarkm * met: 1055682Smarkm * 1155682Smarkm * * Redistributions of source code must retain the above copyright 1255682Smarkm * notice, this list of conditions and the following disclaimer. 1355682Smarkm * 1455682Smarkm * * Redistributions in binary form must reproduce the above 1555682Smarkm * copyright notice, this list of conditions and the following 1690926Snectar * disclaimer in the documentation and/or other materials provided 1790926Snectar * with the distribution. 18233294Sstas 1990926Snectar * * Neither the name of Cavium Inc. nor the names of 20233294Sstas * its contributors may be used to endorse or promote products 2190926Snectar * derived from this software without specific prior written 22233294Sstas * permission. 2355682Smarkm 24142403Snectar * This Software, including technical data, may be subject to U.S. export control 25142403Snectar * laws, including the U.S. Export Administration Act and its associated 2655682Smarkm * regulations, and may be subject to export or import regulations in other 2755682Smarkm * countries. 28233294Sstas 2955682Smarkm * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 30233294Sstas * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 31102644Snectar * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 32102644Snectar * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 33102644Snectar * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 34127808Snectar * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 3590926Snectar * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 36127808Snectar * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 3755682Smarkm * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 3855682Smarkm * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 3955682Smarkm ***********************license end**************************************/ 4055682Smarkm 4155682Smarkm 4255682Smarkm/** 43178825Sdfr * @file 4455682Smarkm * 45178825Sdfr * Helper utilities for qlm_jtag. 46178825Sdfr * 47178825Sdfr * <hr>$Revision: 42480 $<hr> 48142403Snectar */ 49178825Sdfr#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 50178825Sdfr#include <asm/octeon/cvmx.h> 51178825Sdfr#include <asm/octeon/cvmx-clock.h> 52233294Sstas#include <asm/octeon/cvmx-helper-jtag.h> 53178825Sdfr#else 54178825Sdfr#if !defined(__FreeBSD__) || !defined(_KERNEL) 55142403Snectar#include "executive-config.h" 56142403Snectar#include "cvmx-config.h" 57142403Snectar#endif 58233294Sstas#include "cvmx.h" 59142403Snectar#if defined(__FreeBSD__) && defined(_KERNEL) 60142403Snectar#include "cvmx-helper-jtag.h" 61142403Snectar#endif 62142403Snectar#endif 63142403Snectar 64142403Snectar/** 65142403Snectar * Initialize the internal QLM JTAG logic to allow programming 66142403Snectar * of the JTAG chain by the cvmx_helper_qlm_jtag_*() functions. 67142403Snectar * These functions should only be used at the direction of Cavium 68142403Snectar * Networks. Programming incorrect values into the JTAG chain 69142403Snectar * can cause chip damage. 70142403Snectar */ 71142403Snectarvoid cvmx_helper_qlm_jtag_init(void) 72142403Snectar{ 73233294Sstas cvmx_ciu_qlm_jtgc_t jtgc; 74142403Snectar int clock_div = 0; 75142403Snectar int divisor; 76142403Snectar 77142403Snectar divisor = cvmx_clock_get_rate(CVMX_CLOCK_SCLK) / (1000000 * 78178825Sdfr (OCTEON_IS_MODEL(OCTEON_CN68XX) ? 10 : 25)); 79142403Snectar 80142403Snectar divisor = (divisor-1)>>2; 81142403Snectar /* Convert the divisor into a power of 2 shift */ 82142403Snectar while (divisor) 83142403Snectar { 84142403Snectar clock_div++; 85142403Snectar divisor>>=1; 86142403Snectar } 87233294Sstas 88233294Sstas /* Clock divider for QLM JTAG operations. sclk is divided by 2^(CLK_DIV + 2) */ 89233294Sstas jtgc.u64 = 0; 90233294Sstas jtgc.s.clk_div = clock_div; 91233294Sstas jtgc.s.mux_sel = 0; 92233294Sstas if (OCTEON_IS_MODEL(OCTEON_CN52XX)) 93178825Sdfr jtgc.s.bypass = 0x3; 94178825Sdfr else if (OCTEON_IS_MODEL(OCTEON_CN63XX) || OCTEON_IS_MODEL(OCTEON_CN66XX)) 95178825Sdfr jtgc.s.bypass = 0x7; 96178825Sdfr else 97178825Sdfr jtgc.s.bypass = 0xf; 98178825Sdfr if (OCTEON_IS_MODEL(OCTEON_CN68XX)) 99178825Sdfr jtgc.s.bypass_ext = 1; 100233294Sstas cvmx_write_csr(CVMX_CIU_QLM_JTGC, jtgc.u64); 101142403Snectar cvmx_read_csr(CVMX_CIU_QLM_JTGC); 102142403Snectar} 103178825Sdfr 104142403Snectar 105142403Snectar/** 106233294Sstas * Write up to 32bits into the QLM jtag chain. Bits are shifted 107178825Sdfr * into the MSB and out the LSB, so you should shift in the low 108178825Sdfr * order bits followed by the high order bits. The JTAG chain for 109178825Sdfr * CN52XX and CN56XX is 4 * 268 bits long, or 1072. The JTAG chain 110178825Sdfr * for CN63XX is 4 * 300 bits long, or 1200. 111178825Sdfr * 112233294Sstas * @param qlm QLM to shift value into 113233294Sstas * @param bits Number of bits to shift in (1-32). 114233294Sstas * @param data Data to shift in. Bit 0 enters the chain first, followed by 115233294Sstas * bit 1, etc. 116233294Sstas * 117233294Sstas * @return The low order bits of the JTAG chain that shifted out of the 118233294Sstas * circle. 119233294Sstas */ 120233294Sstasuint32_t cvmx_helper_qlm_jtag_shift(int qlm, int bits, uint32_t data) 121233294Sstas{ 122233294Sstas cvmx_ciu_qlm_jtgc_t jtgc; 123233294Sstas cvmx_ciu_qlm_jtgd_t jtgd; 124233294Sstas 125233294Sstas jtgc.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGC); 126233294Sstas jtgc.s.mux_sel = qlm; 127233294Sstas if (!OCTEON_IS_MODEL(OCTEON_CN6XXX) && !OCTEON_IS_MODEL(OCTEON_CNF7XXX)) 128178825Sdfr jtgc.s.bypass = 1<<qlm; 129178825Sdfr cvmx_write_csr(CVMX_CIU_QLM_JTGC, jtgc.u64); 130178825Sdfr cvmx_read_csr(CVMX_CIU_QLM_JTGC); 131178825Sdfr 132142403Snectar jtgd.u64 = 0; 133142403Snectar jtgd.s.shift = 1; 134178825Sdfr jtgd.s.shft_cnt = bits-1; 135178825Sdfr jtgd.s.shft_reg = data; 136178825Sdfr if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)) 137233294Sstas jtgd.s.select = 1 << qlm; 138233294Sstas cvmx_write_csr(CVMX_CIU_QLM_JTGD, jtgd.u64); 139233294Sstas do 140233294Sstas { 141178825Sdfr jtgd.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGD); 142178825Sdfr } while (jtgd.s.shift); 143178825Sdfr return jtgd.s.shft_reg >> (32-bits); 144178825Sdfr} 145178825Sdfr 146178825Sdfr 147178825Sdfr/** 148178825Sdfr * Shift long sequences of zeros into the QLM JTAG chain. It is 149178825Sdfr * common to need to shift more than 32 bits of zeros into the 150233294Sstas * chain. This function is a convience wrapper around 151178825Sdfr * cvmx_helper_qlm_jtag_shift() to shift more than 32 bits of 152178825Sdfr * zeros at a time. 153233294Sstas * 154233294Sstas * @param qlm QLM to shift zeros into 155233294Sstas * @param bits 156233294Sstas */ 157233294Sstasvoid cvmx_helper_qlm_jtag_shift_zeros(int qlm, int bits) 158233294Sstas{ 159233294Sstas while (bits > 0) 160233294Sstas { 161233294Sstas int n = bits; 162233294Sstas if (n > 32) 163233294Sstas n = 32; 164233294Sstas cvmx_helper_qlm_jtag_shift(qlm, n, 0); 165233294Sstas bits -= n; 166233294Sstas } 167233294Sstas} 168233294Sstas 169233294Sstas 170178825Sdfr/** 171178825Sdfr * Program the QLM JTAG chain into all lanes of the QLM. You must 172233294Sstas * have already shifted in the proper number of bits into the 173178825Sdfr * JTAG chain. Updating invalid values can possibly cause chip damage. 174233294Sstas * 175233294Sstas * @param qlm QLM to program 176233294Sstas */ 177233294Sstasvoid cvmx_helper_qlm_jtag_update(int qlm) 178178825Sdfr{ 179233294Sstas cvmx_ciu_qlm_jtgc_t jtgc; 180178825Sdfr cvmx_ciu_qlm_jtgd_t jtgd; 181233294Sstas 182233294Sstas jtgc.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGC); 183233294Sstas jtgc.s.mux_sel = qlm; 184233294Sstas if (!OCTEON_IS_MODEL(OCTEON_CN6XXX) && !OCTEON_IS_MODEL(OCTEON_CNF7XXX)) 185233294Sstas jtgc.s.bypass = 1<<qlm; 186233294Sstas 187233294Sstas cvmx_write_csr(CVMX_CIU_QLM_JTGC, jtgc.u64); 188233294Sstas cvmx_read_csr(CVMX_CIU_QLM_JTGC); 189233294Sstas 190233294Sstas /* Update the new data */ 191233294Sstas jtgd.u64 = 0; 192233294Sstas jtgd.s.update = 1; 193178825Sdfr if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)) 194178825Sdfr jtgd.s.select = 1 << qlm; 195178825Sdfr cvmx_write_csr(CVMX_CIU_QLM_JTGD, jtgd.u64); 196178825Sdfr do 197178825Sdfr { 198233294Sstas jtgd.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGD); 199233294Sstas } while (jtgd.s.update); 200178825Sdfr} 201178825Sdfr 202178825Sdfr 203178825Sdfr/** 204178825Sdfr * Load the QLM JTAG chain with data from all lanes of the QLM. 205233294Sstas * 206233294Sstas * @param qlm QLM to program 207233294Sstas */ 208178825Sdfrvoid cvmx_helper_qlm_jtag_capture(int qlm) 209233294Sstas{ 210178825Sdfr cvmx_ciu_qlm_jtgc_t jtgc; 211178825Sdfr cvmx_ciu_qlm_jtgd_t jtgd; 212178825Sdfr 213178825Sdfr jtgc.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGC); 214178825Sdfr jtgc.s.mux_sel = qlm; 215178825Sdfr if (!OCTEON_IS_MODEL(OCTEON_CN6XXX) && !OCTEON_IS_MODEL(OCTEON_CNF7XXX)) 216178825Sdfr jtgc.s.bypass = 1<<qlm; 217178825Sdfr 218178825Sdfr cvmx_write_csr(CVMX_CIU_QLM_JTGC, jtgc.u64); 219178825Sdfr cvmx_read_csr(CVMX_CIU_QLM_JTGC); 220178825Sdfr 221178825Sdfr jtgd.u64 = 0; 222178825Sdfr jtgd.s.capture = 1; 223178825Sdfr if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)) 224178825Sdfr jtgd.s.select = 1 << qlm; 225178825Sdfr cvmx_write_csr(CVMX_CIU_QLM_JTGD, jtgd.u64); 226178825Sdfr do 227178825Sdfr { 228178825Sdfr jtgd.u64 = cvmx_read_csr(CVMX_CIU_QLM_JTGD); 229178825Sdfr } while (jtgd.s.capture); 230233294Sstas} 231233294Sstas