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