2 /***********************license start***************
3 * Author: Cavium Networks
5 * Contact: support@caviumnetworks.com
6 * This file is part of the OCTEON SDK
8 * Copyright (c) 2003-2008 Cavium Networks
10 * This file is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License, Version 2, as
12 * published by the Free Software Foundation.
14 * This file is distributed in the hope that it will be useful, but
15 * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
16 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
17 * NONINFRINGEMENT. See the GNU General Public License for more
20 * You should have received a copy of the GNU General Public License
21 * along with this file; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 * or visit http://www.gnu.org/licenses/.
25 * This file may also be available under a different license from Cavium.
26 * Contact Cavium Networks for more information
27 ***********************license end**************************************/
31 * Helper utilities for qlm_jtag.
35 #include <asm/octeon/octeon.h>
36 #include <asm/octeon/cvmx-helper-jtag.h>
40 * Initialize the internal QLM JTAG logic to allow programming
41 * of the JTAG chain by the cvmx_helper_qlm_jtag_*() functions.
42 * These functions should only be used at the direction of Cavium
43 * Networks. Programming incorrect values into the JTAG chain
44 * can cause chip damage.
46 void cvmx_helper_qlm_jtag_init(void)
48 union cvmx_ciu_qlm_jtgc jtgc
;
49 uint32_t clock_div
= 0;
50 uint32_t divisor
= cvmx_sysinfo_get()->cpu_clock_hz
/ (25 * 1000000);
51 divisor
= (divisor
- 1) >> 2;
52 /* Convert the divisor into a power of 2 shift */
55 divisor
= divisor
>> 1;
59 * Clock divider for QLM JTAG operations. eclk is divided by
63 jtgc
.s
.clk_div
= clock_div
;
65 if (OCTEON_IS_MODEL(OCTEON_CN52XX
))
69 cvmx_write_csr(CVMX_CIU_QLM_JTGC
, jtgc
.u64
);
70 cvmx_read_csr(CVMX_CIU_QLM_JTGC
);
74 * Write up to 32bits into the QLM jtag chain. Bits are shifted
75 * into the MSB and out the LSB, so you should shift in the low
76 * order bits followed by the high order bits. The JTAG chain is
77 * 4 * 268 bits long, or 1072.
79 * @qlm: QLM to shift value into
80 * @bits: Number of bits to shift in (1-32).
81 * @data: Data to shift in. Bit 0 enters the chain first, followed by
84 * Returns The low order bits of the JTAG chain that shifted out of the
87 uint32_t cvmx_helper_qlm_jtag_shift(int qlm
, int bits
, uint32_t data
)
89 union cvmx_ciu_qlm_jtgd jtgd
;
92 jtgd
.s
.shft_cnt
= bits
- 1;
93 jtgd
.s
.shft_reg
= data
;
94 if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X
))
95 jtgd
.s
.select
= 1 << qlm
;
96 cvmx_write_csr(CVMX_CIU_QLM_JTGD
, jtgd
.u64
);
98 jtgd
.u64
= cvmx_read_csr(CVMX_CIU_QLM_JTGD
);
99 } while (jtgd
.s
.shift
);
100 return jtgd
.s
.shft_reg
>> (32 - bits
);
104 * Shift long sequences of zeros into the QLM JTAG chain. It is
105 * common to need to shift more than 32 bits of zeros into the
106 * chain. This function is a convience wrapper around
107 * cvmx_helper_qlm_jtag_shift() to shift more than 32 bits of
110 * @qlm: QLM to shift zeros into
113 void cvmx_helper_qlm_jtag_shift_zeros(int qlm
, int bits
)
119 cvmx_helper_qlm_jtag_shift(qlm
, n
, 0);
125 * Program the QLM JTAG chain into all lanes of the QLM. You must
126 * have already shifted in 268*4, or 1072 bits into the JTAG
127 * chain. Updating invalid values can possibly cause chip damage.
129 * @qlm: QLM to program
131 void cvmx_helper_qlm_jtag_update(int qlm
)
133 union cvmx_ciu_qlm_jtgd jtgd
;
135 /* Update the new data */
138 if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X
))
139 jtgd
.s
.select
= 1 << qlm
;
140 cvmx_write_csr(CVMX_CIU_QLM_JTGD
, jtgd
.u64
);
142 jtgd
.u64
= cvmx_read_csr(CVMX_CIU_QLM_JTGD
);
143 } while (jtgd
.s
.update
);