1 /***********************license start***************
2 * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * * Neither the name of Cavium Inc. nor the names of
19 * its contributors may be used to endorse or promote products
20 * derived from this software without specific prior written
23 * This Software, including technical data, may be subject to U.S. export control
24 * laws, including the U.S. Export Administration Act and its associated
25 * regulations, and may be subject to export or import regulations in other
28 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29 * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
30 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
31 * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
32 * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
33 * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
34 * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
35 * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
36 * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
37 * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38 ***********************license end**************************************/
43 * Support library for the ILK
45 * <hr>$Revision: 49448 $<hr>
47 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
48 #include <linux/module.h>
49 #include <asm/octeon/cvmx.h>
50 #include <asm/octeon/cvmx-config.h>
51 #include <asm/octeon/cvmx-sysinfo.h>
52 #include <asm/octeon/cvmx-pko.h>
53 #include <asm/octeon/cvmx-ilk.h>
54 #include <asm/octeon/cvmx-ilk-defs.h>
55 #include <asm/octeon/cvmx-helper-util.h>
56 #include <asm/octeon/cvmx-helper-ilk.h>
59 #if !defined(__FreeBSD__) || !defined(_KERNEL)
60 #include "cvmx-config.h"
62 #include "cvmx-sysinfo.h"
65 #include "cvmx-helper-util.h"
66 #include "cvmx-helper-ilk.h"
69 #ifdef CVMX_ENABLE_HELPER_FUNCTIONS
72 * global configurations. to disable the 2nd ILK, set
73 * cvmx_ilk_lane_mask[CVMX_NUM_ILK_INTF] = {0xff, 0x0} and
74 * cvmx_ilk_chans[CVMX_NUM_ILK_INTF] = {8, 0}
76 unsigned char cvmx_ilk_lane_mask[CVMX_NUM_ILK_INTF] = {0xf, 0xf0};
77 //#define SINGLE_PORT_SIM_ILK
78 #ifdef SINGLE_PORT_SIM_ILK
79 unsigned char cvmx_ilk_chans[CVMX_NUM_ILK_INTF] = {1, 1};
80 unsigned char cvmx_ilk_chan_map[CVMX_NUM_ILK_INTF][CVMX_MAX_ILK_CHANS] =
83 #else /* sample case */
84 unsigned char cvmx_ilk_chans[CVMX_NUM_ILK_INTF] = {8, 8};
85 unsigned char cvmx_ilk_chan_map[CVMX_NUM_ILK_INTF][CVMX_MAX_ILK_CHANS] =
86 {{0, 1, 2, 3, 4, 5, 6, 7},
87 {0, 1, 2, 3, 4, 5, 6, 7}};
90 /* Default callbacks, can be overridden
91 * using cvmx_ilk_get_callbacks/cvmx_ilk_set_callbacks
93 static cvmx_ilk_callbacks_t cvmx_ilk_callbacks = {
94 .calendar_setup_rx = cvmx_ilk_cal_setup_rx,
97 static cvmx_ilk_intf_t cvmx_ilk_intf_cfg[CVMX_NUM_ILK_INTF];
100 * Get current ILK initialization callbacks
102 * @param callbacks Pointer to the callbacks structure.to fill
104 * @return Pointer to cvmx_ilk_callbacks_t structure.
106 void cvmx_ilk_get_callbacks(cvmx_ilk_callbacks_t * callbacks)
108 memcpy(callbacks, &cvmx_ilk_callbacks, sizeof(cvmx_ilk_callbacks));
112 * Set new ILK initialization callbacks
114 * @param new_callbacks Pointer to an updated callbacks structure.
116 void cvmx_ilk_set_callbacks(cvmx_ilk_callbacks_t * new_callbacks)
118 memcpy(&cvmx_ilk_callbacks, new_callbacks, sizeof(cvmx_ilk_callbacks));
122 * Initialize and start the ILK interface.
124 * @param interface The identifier of the packet interface to configure and
125 * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and
128 * @param lane_mask the lane group for this interface
130 * @return Zero on success, negative of failure.
132 int cvmx_ilk_start_interface (int interface, unsigned char lane_mask)
135 int other_intf, this_qlm, other_qlm;
136 unsigned char uni_mask;
137 cvmx_mio_qlmx_cfg_t mio_qlmx_cfg, other_mio_qlmx_cfg;
138 cvmx_ilk_txx_cfg0_t ilk_txx_cfg0;
139 cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0;
140 cvmx_ilk_ser_cfg_t ilk_ser_cfg;
142 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
145 if (interface >= CVMX_NUM_ILK_INTF)
151 /* check conflicts between 2 ilk interfaces. 1 lane can be assigned to 1
153 other_intf = !interface;
154 this_qlm = interface + CVMX_ILK_QLM_BASE;
155 other_qlm = other_intf + CVMX_ILK_QLM_BASE;
156 if (cvmx_ilk_intf_cfg[other_intf].lane_en_mask & lane_mask)
158 cvmx_dprintf ("ILK%d: %s: lane assignment conflict\n", interface,
163 /* check the legality of the lane mask. interface 0 can have 8 lanes,
164 * while interface 1 can have 4 lanes at most */
165 uni_mask = lane_mask >> (interface * 4);
166 if ((uni_mask != 0x1 && uni_mask != 0x3 && uni_mask != 0xf &&
167 uni_mask != 0xff) || (interface == 1 && lane_mask > 0xf0))
169 #if CVMX_ENABLE_DEBUG_PRINTS
170 cvmx_dprintf ("ILK%d: %s: incorrect lane mask: 0x%x \n", interface,
171 __FUNCTION__, uni_mask);
176 /* check the availability of qlms. qlm_cfg = 001 means the chip is fused
177 * to give this qlm to ilk */
178 mio_qlmx_cfg.u64 = cvmx_read_csr (CVMX_MIO_QLMX_CFG(this_qlm));
179 other_mio_qlmx_cfg.u64 = cvmx_read_csr (CVMX_MIO_QLMX_CFG(other_qlm));
180 if (mio_qlmx_cfg.s.qlm_cfg != 1 ||
181 (uni_mask == 0xff && other_mio_qlmx_cfg.s.qlm_cfg != 1))
183 #if CVMX_ENABLE_DEBUG_PRINTS
184 cvmx_dprintf ("ILK%d: %s: qlm unavailable\n", interface, __FUNCTION__);
189 /* power up the serdes */
190 ilk_ser_cfg.u64 = cvmx_read_csr (CVMX_ILK_SER_CFG);
191 if (ilk_ser_cfg.s.ser_pwrup == 0)
193 ilk_ser_cfg.s.ser_rxpol_auto = 1;
194 ilk_ser_cfg.s.ser_rxpol = 0;
195 ilk_ser_cfg.s.ser_txpol = 0;
196 ilk_ser_cfg.s.ser_reset_n = 0xff;
197 ilk_ser_cfg.s.ser_haul = 0;
199 ilk_ser_cfg.s.ser_pwrup |= ((interface ==0) && (lane_mask > 0xf)) ?
200 0x3 : (1 << interface);
201 cvmx_write_csr (CVMX_ILK_SER_CFG, ilk_ser_cfg.u64);
203 /* configure the lane enable of the interface */
204 ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface));
205 ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface));
206 ilk_txx_cfg0.s.lane_ena = ilk_rxx_cfg0.s.lane_ena = lane_mask;
207 cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64);
208 cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64);
210 /* write to local cache. for lane speed, if interface 0 has 8 lanes,
211 * assume both qlms have the same speed */
212 cvmx_ilk_intf_cfg[interface].intf_en = 1;
213 cvmx_ilk_intf_cfg[interface].lane_en_mask = lane_mask;
220 * set pipe group base and length for the interface
222 * @param interface The identifier of the packet interface to configure and
223 * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and
226 * @param pipe_base the base of the pipe group
227 * @param pipe_len the length of the pipe group
229 * @return Zero on success, negative of failure.
231 int cvmx_ilk_set_pipe (int interface, int pipe_base, unsigned int pipe_len)
234 cvmx_ilk_txx_pipe_t ilk_txx_pipe;
236 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
239 if (interface >= CVMX_NUM_ILK_INTF)
242 /* base should be between 0 and 127. base + length should be <127 */
243 if (!(pipe_base >= 0 && pipe_base <= 127) || (pipe_base + pipe_len > 127))
245 #if CVMX_ENABLE_DEBUG_PRINTS
246 cvmx_dprintf ("ILK%d: %s: pipe base/length out of bounds\n", interface,
252 /* set them in ilk tx section */
253 ilk_txx_pipe.u64 = cvmx_read_csr (CVMX_ILK_TXX_PIPE(interface));
254 ilk_txx_pipe.s.base = pipe_base;
255 ilk_txx_pipe.s.nump = pipe_len;
256 cvmx_write_csr (CVMX_ILK_TXX_PIPE(interface), ilk_txx_pipe.u64);
263 * set logical channels for tx
265 * @param interface The identifier of the packet interface to configure and
266 * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and
269 * @param pch pointer to an array of pipe-channel pair
270 * @param num_chs the number of entries in the pipe-channel array
272 * @return Zero on success, negative of failure.
274 int cvmx_ilk_tx_set_channel (int interface, cvmx_ilk_pipe_chan_t *pch,
275 unsigned int num_chs)
278 cvmx_ilk_txx_idx_pmap_t ilk_txx_idx_pmap;
281 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
284 if (interface >= CVMX_NUM_ILK_INTF)
287 if (pch == NULL || num_chs > CVMX_MAX_ILK_PIPES)
290 /* write the pair to ilk tx */
291 for (i = 0; i < num_chs; i++)
293 ilk_txx_idx_pmap.u64 = 0;
294 ilk_txx_idx_pmap.s.index = pch->pipe;
295 cvmx_write_csr(CVMX_ILK_TXX_IDX_PMAP(interface), ilk_txx_idx_pmap.u64);
296 cvmx_write_csr(CVMX_ILK_TXX_MEM_PMAP(interface), pch->chan);
307 * @param interface The identifier of the packet interface to configure and
308 * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and
311 * @param chpknd pointer to an array of channel-pkind pair
312 * @param num_pknd the number of entries in the channel-pkind array
314 * @return Zero on success, negative of failure.
316 int cvmx_ilk_rx_set_pknd (int interface, cvmx_ilk_chan_pknd_t *chpknd,
317 unsigned int num_pknd)
320 cvmx_ilk_rxf_idx_pmap_t ilk_rxf_idx_pmap;
323 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
326 if (interface >= CVMX_NUM_ILK_INTF)
329 if (chpknd == NULL || num_pknd > CVMX_MAX_ILK_PKNDS)
332 /* write the pair to ilk rx. note the channels for different interfaces
333 * are given in *chpknd and interface is not used as a param */
334 for (i = 0; i < num_pknd; i++)
336 ilk_rxf_idx_pmap.u64 = 0;
337 ilk_rxf_idx_pmap.s.index = interface * 256 + chpknd->chan;
338 cvmx_write_csr (CVMX_ILK_RXF_IDX_PMAP, ilk_rxf_idx_pmap.u64);
339 cvmx_write_csr (CVMX_ILK_RXF_MEM_PMAP, chpknd->pknd);
348 * configure calendar for rx
350 * @param interface The identifier of the packet interface to configure and
351 * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and
354 * @param cal_depth the number of calendar entries
355 * @param pent pointer to calendar entries
357 * @return Zero on success, negative of failure.
359 static int cvmx_ilk_rx_cal_conf (int interface, int cal_depth,
360 cvmx_ilk_cal_entry_t *pent)
362 int res = -1, num_grp, num_rest, i, j;
363 cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0;
364 cvmx_ilk_rxx_idx_cal_t ilk_rxx_idx_cal;
365 cvmx_ilk_rxx_mem_cal0_t ilk_rxx_mem_cal0;
366 cvmx_ilk_rxx_mem_cal1_t ilk_rxx_mem_cal1;
367 unsigned long int tmp;
369 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
372 if (interface >= CVMX_NUM_ILK_INTF)
375 if (cal_depth < CVMX_ILK_RX_MIN_CAL || cal_depth > CVMX_ILK_MAX_CAL
379 /* mandatory link-level fc as workarounds for ILK-15397 and ILK-15479 */
380 /* TODO: test effectiveness */
382 if (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_0) && pent->ent_ctrl == PIPE_BPID)
383 for (i = 0; i < cal_depth; i++)
384 pent->ent_ctrl = LINK;
388 ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface));
389 ilk_rxx_cfg0.s.cal_depth = cal_depth;
390 cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64);
392 /* set the calendar index */
393 num_grp = cal_depth / CVMX_ILK_CAL_GRP_SZ;
394 num_rest = cal_depth % CVMX_ILK_CAL_GRP_SZ;
395 ilk_rxx_idx_cal.u64 = 0;
396 ilk_rxx_idx_cal.s.inc = 1;
397 cvmx_write_csr (CVMX_ILK_RXX_IDX_CAL(interface), ilk_rxx_idx_cal.u64);
399 /* set the calendar entries. each group has both cal0 and cal1 registers */
400 for (i = 0; i < num_grp; i++)
402 ilk_rxx_mem_cal0.u64 = 0;
403 for (j = 0; j < CVMX_ILK_CAL_GRP_SZ/2; j++)
406 tmp = pent->pipe_bpid & ~(~tmp << CVMX_ILK_PIPE_BPID_SZ);
407 tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j;
408 ilk_rxx_mem_cal0.u64 |= tmp;
411 tmp = pent->ent_ctrl & ~(~tmp << CVMX_ILK_ENT_CTRL_SZ);
412 tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j +
413 CVMX_ILK_PIPE_BPID_SZ;
414 ilk_rxx_mem_cal0.u64 |= tmp;
417 cvmx_write_csr(CVMX_ILK_RXX_MEM_CAL0(interface), ilk_rxx_mem_cal0.u64);
419 ilk_rxx_mem_cal1.u64 = 0;
420 for (j = 0; j < CVMX_ILK_CAL_GRP_SZ/2; j++)
423 tmp = pent->pipe_bpid & ~(~tmp << CVMX_ILK_PIPE_BPID_SZ);
424 tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j;
425 ilk_rxx_mem_cal1.u64 |= tmp;
428 tmp = pent->ent_ctrl & ~(~tmp << CVMX_ILK_ENT_CTRL_SZ);
429 tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j +
430 CVMX_ILK_PIPE_BPID_SZ;
431 ilk_rxx_mem_cal1.u64 |= tmp;
434 cvmx_write_csr(CVMX_ILK_RXX_MEM_CAL1(interface), ilk_rxx_mem_cal1.u64);
437 /* set the calendar entries, the fraction of a group. but both cal0 and
438 * cal1 must be written */
439 ilk_rxx_mem_cal0.u64 = 0;
440 ilk_rxx_mem_cal1.u64 = 0;
441 for (i = 0; i < num_rest; i++)
443 if (i < CVMX_ILK_CAL_GRP_SZ/2)
446 tmp = pent->pipe_bpid & ~(~tmp << CVMX_ILK_PIPE_BPID_SZ);
447 tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * i;
448 ilk_rxx_mem_cal0.u64 |= tmp;
451 tmp = pent->ent_ctrl & ~(~tmp << CVMX_ILK_ENT_CTRL_SZ);
452 tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * i +
453 CVMX_ILK_PIPE_BPID_SZ;
454 ilk_rxx_mem_cal0.u64 |= tmp;
458 if (i >= CVMX_ILK_CAL_GRP_SZ/2)
461 tmp = pent->pipe_bpid & ~(~tmp << CVMX_ILK_PIPE_BPID_SZ);
462 tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) *
463 (i - CVMX_ILK_CAL_GRP_SZ/2);
464 ilk_rxx_mem_cal1.u64 |= tmp;
467 tmp = pent->ent_ctrl & ~(~tmp << CVMX_ILK_ENT_CTRL_SZ);
468 tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) *
469 (i - CVMX_ILK_CAL_GRP_SZ/2) + CVMX_ILK_PIPE_BPID_SZ;
470 ilk_rxx_mem_cal1.u64 |= tmp;
474 cvmx_write_csr(CVMX_ILK_RXX_MEM_CAL0(interface), ilk_rxx_mem_cal0.u64);
475 cvmx_write_csr(CVMX_ILK_RXX_MEM_CAL1(interface), ilk_rxx_mem_cal1.u64);
476 cvmx_read_csr (CVMX_ILK_RXX_MEM_CAL1(interface));
482 * set high water mark for rx
484 * @param interface The identifier of the packet interface to configure and
485 * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and
488 * @param hi_wm high water mark for this interface
490 * @return Zero on success, negative of failure.
492 static int cvmx_ilk_rx_set_hwm (int interface, int hi_wm)
495 cvmx_ilk_rxx_cfg1_t ilk_rxx_cfg1;
497 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
500 if (interface >= CVMX_NUM_ILK_INTF)
507 ilk_rxx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG1(interface));
508 ilk_rxx_cfg1.s.rx_fifo_hwm = hi_wm;
509 cvmx_write_csr (CVMX_ILK_RXX_CFG1(interface), ilk_rxx_cfg1.u64);
516 * enable calendar for rx
518 * @param interface The identifier of the packet interface to configure and
519 * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and
522 * @param cal_ena enable or disable calendar
524 * @return Zero on success, negative of failure.
526 static int cvmx_ilk_rx_cal_ena (int interface, unsigned char cal_ena)
529 cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0;
531 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
534 if (interface >= CVMX_NUM_ILK_INTF)
538 ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface));
539 ilk_rxx_cfg0.s.cal_ena = cal_ena;
540 cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64);
541 cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface));
548 * set up calendar for rx
550 * @param interface The identifier of the packet interface to configure and
551 * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and
554 * @param cal_depth the number of calendar entries
555 * @param pent pointer to calendar entries
556 * @param hi_wm high water mark for this interface
557 * @param cal_ena enable or disable calendar
559 * @return Zero on success, negative of failure.
561 int cvmx_ilk_cal_setup_rx (int interface, int cal_depth,
562 cvmx_ilk_cal_entry_t *pent, int hi_wm,
563 unsigned char cal_ena)
567 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
570 if (interface >= CVMX_NUM_ILK_INTF)
573 res = cvmx_ilk_rx_cal_conf (interface, cal_depth, pent);
577 res = cvmx_ilk_rx_set_hwm (interface, hi_wm);
581 res = cvmx_ilk_rx_cal_ena (interface, cal_ena);
584 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
585 EXPORT_SYMBOL(cvmx_ilk_cal_setup_rx);
589 * configure calendar for tx
591 * @param interface The identifier of the packet interface to configure and
592 * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and
595 * @param cal_depth the number of calendar entries
596 * @param pent pointer to calendar entries
598 * @return Zero on success, negative of failure.
600 static int cvmx_ilk_tx_cal_conf (int interface, int cal_depth,
601 cvmx_ilk_cal_entry_t *pent)
603 int res = -1, num_grp, num_rest, i, j;
604 cvmx_ilk_txx_cfg0_t ilk_txx_cfg0;
605 cvmx_ilk_txx_idx_cal_t ilk_txx_idx_cal;
606 cvmx_ilk_txx_mem_cal0_t ilk_txx_mem_cal0;
607 cvmx_ilk_txx_mem_cal1_t ilk_txx_mem_cal1;
608 unsigned long int tmp;
609 cvmx_ilk_cal_entry_t *ent_tmp;
611 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
614 if (interface >= CVMX_NUM_ILK_INTF)
617 if (cal_depth < CVMX_ILK_TX_MIN_CAL || cal_depth > CVMX_ILK_MAX_CAL
621 /* mandatory link-level fc as workarounds for ILK-15397 and ILK-15479 */
622 /* TODO: test effectiveness */
624 if (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_0) && pent->ent_ctrl == PIPE_BPID)
625 for (i = 0; i < cal_depth; i++)
626 pent->ent_ctrl = LINK;
629 /* tx calendar depth must be a multiple of 8 */
630 num_grp = (cal_depth - 1) / CVMX_ILK_CAL_GRP_SZ + 1;
631 num_rest = cal_depth % CVMX_ILK_CAL_GRP_SZ;
634 ent_tmp = pent + cal_depth;
635 for (i = num_rest; i < 8; i++, ent_tmp++)
637 ent_tmp->pipe_bpid = 0;
638 ent_tmp->ent_ctrl = XOFF;
641 cal_depth = num_grp * 8;
644 ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface));
645 ilk_txx_cfg0.s.cal_depth = cal_depth;
646 cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64);
648 /* set the calendar index */
649 ilk_txx_idx_cal.u64 = 0;
650 ilk_txx_idx_cal.s.inc = 1;
651 cvmx_write_csr (CVMX_ILK_TXX_IDX_CAL(interface), ilk_txx_idx_cal.u64);
653 /* set the calendar entries. each group has both cal0 and cal1 registers */
654 for (i = 0; i < num_grp; i++)
656 ilk_txx_mem_cal0.u64 = 0;
657 for (j = 0; j < CVMX_ILK_CAL_GRP_SZ/2; j++)
660 tmp = pent->pipe_bpid & ~(~tmp << CVMX_ILK_PIPE_BPID_SZ);
661 tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j;
662 ilk_txx_mem_cal0.u64 |= tmp;
665 tmp = pent->ent_ctrl & ~(~tmp << CVMX_ILK_ENT_CTRL_SZ);
666 tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j +
667 CVMX_ILK_PIPE_BPID_SZ;
668 ilk_txx_mem_cal0.u64 |= tmp;
671 cvmx_write_csr(CVMX_ILK_TXX_MEM_CAL0(interface), ilk_txx_mem_cal0.u64);
673 ilk_txx_mem_cal1.u64 = 0;
674 for (j = 0; j < CVMX_ILK_CAL_GRP_SZ/2; j++)
677 tmp = pent->pipe_bpid & ~(~tmp << CVMX_ILK_PIPE_BPID_SZ);
678 tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j;
679 ilk_txx_mem_cal1.u64 |= tmp;
682 tmp = pent->ent_ctrl & ~(~tmp << CVMX_ILK_ENT_CTRL_SZ);
683 tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j +
684 CVMX_ILK_PIPE_BPID_SZ;
685 ilk_txx_mem_cal1.u64 |= tmp;
688 cvmx_write_csr(CVMX_ILK_TXX_MEM_CAL1(interface), ilk_txx_mem_cal1.u64);
690 cvmx_read_csr (CVMX_ILK_TXX_MEM_CAL1(interface));
695 #ifdef CVMX_ILK_BP_CONF_ENA
697 * configure backpressure for tx
699 * @param interface The identifier of the packet interface to configure and
700 * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and
703 * @param cal_depth the number of calendar entries
704 * @param pent pointer to calendar entries
706 * @return Zero on success, negative of failure.
708 static int cvmx_ilk_bp_conf (int interface, int cal_depth, cvmx_ilk_cal_entry_t *pent)
711 cvmx_ipd_ctl_status_t ipd_ctl_status;
712 cvmx_ilk_cal_entry_t *tmp;
714 cvmx_ipd_bpidx_mbuf_th_t ipd_bpidx_mbuf_th;
716 /* enable bp for the interface */
717 ipd_ctl_status.u64 = cvmx_read_csr (CVMX_IPD_CTL_STATUS);
718 ipd_ctl_status.s.pbp_en = 1;
719 cvmx_write_csr (CVMX_IPD_CTL_STATUS, ipd_ctl_status.u64);
721 /* enable bp for each id */
722 for (i = 0, tmp = pent; i < cal_depth; i++, tmp++)
724 bpid = tmp->pipe_bpid;
725 ipd_bpidx_mbuf_th.u64 =
726 cvmx_read_csr (CVMX_IPD_BPIDX_MBUF_TH(bpid));
727 ipd_bpidx_mbuf_th.s.page_cnt = 1; /* 256 buffers */
728 ipd_bpidx_mbuf_th.s.bp_enb = 1;
729 cvmx_write_csr (CVMX_IPD_BPIDX_MBUF_TH(bpid), ipd_bpidx_mbuf_th.u64);
738 * enable calendar for tx
740 * @param interface The identifier of the packet interface to configure and
741 * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and
744 * @param cal_ena enable or disable calendar
746 * @return Zero on success, negative of failure.
748 static int cvmx_ilk_tx_cal_ena (int interface, unsigned char cal_ena)
751 cvmx_ilk_txx_cfg0_t ilk_txx_cfg0;
753 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
756 if (interface >= CVMX_NUM_ILK_INTF)
760 ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface));
761 ilk_txx_cfg0.s.cal_ena = cal_ena;
762 cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64);
763 cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface));
770 * set up calendar for tx
772 * @param interface The identifier of the packet interface to configure and
773 * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and
776 * @param cal_depth the number of calendar entries
777 * @param pent pointer to calendar entries
778 * @param cal_ena enable or disable calendar
780 * @return Zero on success, negative of failure.
782 int cvmx_ilk_cal_setup_tx (int interface, int cal_depth,
783 cvmx_ilk_cal_entry_t *pent, unsigned char cal_ena)
787 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
790 if (interface >= CVMX_NUM_ILK_INTF)
793 res = cvmx_ilk_tx_cal_conf (interface, cal_depth, pent);
797 #ifdef CVMX_ILK_BP_CONF_ENA
798 res = cvmx_ilk_bp_conf (interface, cal_depth, pent);
803 res = cvmx_ilk_tx_cal_ena (interface, cal_ena);
806 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
807 EXPORT_SYMBOL(cvmx_ilk_cal_setup_tx);
810 #ifdef CVMX_ILK_STATS_ENA
811 static void cvmx_ilk_reg_dump_rx (int interface)
814 cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0;
815 cvmx_ilk_rxx_cfg1_t ilk_rxx_cfg1;
816 cvmx_ilk_rxx_int_t ilk_rxx_int;
817 cvmx_ilk_rxx_jabber_t ilk_rxx_jabber;
818 cvmx_ilk_rx_lnex_cfg_t ilk_rx_lnex_cfg;
819 cvmx_ilk_rx_lnex_int_t ilk_rx_lnex_int;
820 cvmx_ilk_gbl_cfg_t ilk_gbl_cfg;
821 cvmx_ilk_ser_cfg_t ilk_ser_cfg;
822 cvmx_ilk_rxf_idx_pmap_t ilk_rxf_idx_pmap;
823 cvmx_ilk_rxf_mem_pmap_t ilk_rxf_mem_pmap;
824 cvmx_ilk_rxx_idx_cal_t ilk_rxx_idx_cal;
825 cvmx_ilk_rxx_mem_cal0_t ilk_rxx_mem_cal0;
826 cvmx_ilk_rxx_mem_cal1_t ilk_rxx_mem_cal1;
828 ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface));
829 cvmx_dprintf ("ilk rxx cfg0: 0x%16lx\n", ilk_rxx_cfg0.u64);
831 ilk_rxx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG1(interface));
832 cvmx_dprintf ("ilk rxx cfg1: 0x%16lx\n", ilk_rxx_cfg1.u64);
834 ilk_rxx_int.u64 = cvmx_read_csr (CVMX_ILK_RXX_INT(interface));
835 cvmx_dprintf ("ilk rxx int: 0x%16lx\n", ilk_rxx_int.u64);
836 cvmx_write_csr (CVMX_ILK_RXX_INT(interface), ilk_rxx_int.u64);
838 ilk_rxx_jabber.u64 = cvmx_read_csr (CVMX_ILK_RXX_JABBER(interface));
839 cvmx_dprintf ("ilk rxx jabber: 0x%16lx\n", ilk_rxx_jabber.u64);
841 #define LNE_NUM_DBG 4
842 for (i = 0; i < LNE_NUM_DBG; i++)
844 ilk_rx_lnex_cfg.u64 = cvmx_read_csr (CVMX_ILK_RX_LNEX_CFG(i));
845 cvmx_dprintf ("ilk rx lnex cfg lane: %d 0x%16lx\n", i,
846 ilk_rx_lnex_cfg.u64);
849 for (i = 0; i < LNE_NUM_DBG; i++)
851 ilk_rx_lnex_int.u64 = cvmx_read_csr (CVMX_ILK_RX_LNEX_INT(i));
852 cvmx_dprintf ("ilk rx lnex int lane: %d 0x%16lx\n", i,
853 ilk_rx_lnex_int.u64);
854 cvmx_write_csr (CVMX_ILK_RX_LNEX_INT(i), ilk_rx_lnex_int.u64);
857 ilk_gbl_cfg.u64 = cvmx_read_csr (CVMX_ILK_GBL_CFG);
858 cvmx_dprintf ("ilk gbl cfg: 0x%16lx\n", ilk_gbl_cfg.u64);
860 ilk_ser_cfg.u64 = cvmx_read_csr (CVMX_ILK_SER_CFG);
861 cvmx_dprintf ("ilk ser cfg: 0x%16lx\n", ilk_ser_cfg.u64);
863 #define CHAN_NUM_DBG 8
864 ilk_rxf_idx_pmap.u64 = 0;
865 ilk_rxf_idx_pmap.s.index = interface * 256;
866 ilk_rxf_idx_pmap.s.inc = 1;
867 cvmx_write_csr (CVMX_ILK_RXF_IDX_PMAP, ilk_rxf_idx_pmap.u64);
868 for (i = 0; i < CHAN_NUM_DBG; i++)
870 ilk_rxf_mem_pmap.u64 = cvmx_read_csr (CVMX_ILK_RXF_MEM_PMAP);
871 cvmx_dprintf ("ilk rxf mem pmap chan: %3d 0x%16lx\n", i,
872 ilk_rxf_mem_pmap.u64);
875 #define CAL_NUM_DBG 2
876 ilk_rxx_idx_cal.u64 = 0;
877 ilk_rxx_idx_cal.s.inc = 1;
878 cvmx_write_csr (CVMX_ILK_RXX_IDX_CAL(interface), ilk_rxx_idx_cal.u64);
879 for (i = 0; i < CAL_NUM_DBG; i++)
881 ilk_rxx_idx_cal.u64 = cvmx_read_csr(CVMX_ILK_RXX_IDX_CAL(interface));
882 cvmx_dprintf ("ilk rxx idx cal: 0x%16lx\n", ilk_rxx_idx_cal.u64);
884 ilk_rxx_mem_cal0.u64 = cvmx_read_csr(CVMX_ILK_RXX_MEM_CAL0(interface));
885 cvmx_dprintf ("ilk rxx mem cal0: 0x%16lx\n", ilk_rxx_mem_cal0.u64);
886 ilk_rxx_mem_cal1.u64 = cvmx_read_csr(CVMX_ILK_RXX_MEM_CAL1(interface));
887 cvmx_dprintf ("ilk rxx mem cal1: 0x%16lx\n", ilk_rxx_mem_cal1.u64);
891 static void cvmx_ilk_reg_dump_tx (int interface)
894 cvmx_ilk_txx_cfg0_t ilk_txx_cfg0;
895 cvmx_ilk_txx_cfg1_t ilk_txx_cfg1;
896 cvmx_ilk_txx_idx_pmap_t ilk_txx_idx_pmap;
897 cvmx_ilk_txx_mem_pmap_t ilk_txx_mem_pmap;
898 cvmx_ilk_txx_int_t ilk_txx_int;
899 cvmx_ilk_txx_pipe_t ilk_txx_pipe;
900 cvmx_ilk_txx_idx_cal_t ilk_txx_idx_cal;
901 cvmx_ilk_txx_mem_cal0_t ilk_txx_mem_cal0;
902 cvmx_ilk_txx_mem_cal1_t ilk_txx_mem_cal1;
904 ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface));
905 cvmx_dprintf ("ilk txx cfg0: 0x%16lx\n", ilk_txx_cfg0.u64);
907 ilk_txx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG1(interface));
908 cvmx_dprintf ("ilk txx cfg1: 0x%16lx\n", ilk_txx_cfg1.u64);
910 ilk_txx_pipe.u64 = cvmx_read_csr (CVMX_ILK_TXX_PIPE(interface));
911 cvmx_dprintf ("ilk txx pipe: 0x%16lx\n", ilk_txx_pipe.u64);
913 ilk_txx_idx_pmap.u64 = 0;
914 ilk_txx_idx_pmap.s.index = ilk_txx_pipe.s.base;
915 ilk_txx_idx_pmap.s.inc = 1;
916 cvmx_write_csr (CVMX_ILK_TXX_IDX_PMAP(interface), ilk_txx_idx_pmap.u64);
917 for (i = 0; i < CHAN_NUM_DBG; i++)
919 ilk_txx_mem_pmap.u64 = cvmx_read_csr (CVMX_ILK_TXX_MEM_PMAP(interface));
920 cvmx_dprintf ("ilk txx mem pmap pipe: %3d 0x%16lx\n",
921 ilk_txx_pipe.s.base + i, ilk_txx_mem_pmap.u64);
924 ilk_txx_int.u64 = cvmx_read_csr (CVMX_ILK_TXX_INT(interface));
925 cvmx_dprintf ("ilk txx int: 0x%16lx\n", ilk_txx_int.u64);
927 ilk_txx_idx_cal.u64 = 0;
928 ilk_txx_idx_cal.s.inc = 1;
929 cvmx_write_csr (CVMX_ILK_TXX_IDX_CAL(interface), ilk_txx_idx_cal.u64);
930 for (i = 0; i < CAL_NUM_DBG; i++)
932 ilk_txx_idx_cal.u64 = cvmx_read_csr(CVMX_ILK_TXX_IDX_CAL(interface));
933 cvmx_dprintf ("ilk txx idx cal: 0x%16lx\n", ilk_txx_idx_cal.u64);
935 ilk_txx_mem_cal0.u64 = cvmx_read_csr(CVMX_ILK_TXX_MEM_CAL0(interface));
936 cvmx_dprintf ("ilk txx mem cal0: 0x%16lx\n", ilk_txx_mem_cal0.u64);
937 ilk_txx_mem_cal1.u64 = cvmx_read_csr(CVMX_ILK_TXX_MEM_CAL1(interface));
938 cvmx_dprintf ("ilk txx mem cal1: 0x%16lx\n", ilk_txx_mem_cal1.u64);
944 * show run time status
946 * @param interface The identifier of the packet interface to enable. cn68xx
947 * has 2 interfaces: ilk0 and ilk1.
951 #ifdef CVMX_ILK_RUNTIME_DBG
952 void cvmx_ilk_runtime_status (int interface)
954 cvmx_ilk_txx_cfg1_t ilk_txx_cfg1;
955 cvmx_ilk_txx_flow_ctl0_t ilk_txx_flow_ctl0;
956 cvmx_ilk_rxx_cfg1_t ilk_rxx_cfg1;
957 cvmx_ilk_rxx_int_t ilk_rxx_int;
958 cvmx_ilk_rxx_flow_ctl0_t ilk_rxx_flow_ctl0;
959 cvmx_ilk_rxx_flow_ctl1_t ilk_rxx_flow_ctl1;
960 cvmx_ilk_gbl_int_t ilk_gbl_int;
962 cvmx_dprintf ("\nilk run-time status: interface: %d\n", interface);
964 ilk_txx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG1(interface));
965 cvmx_dprintf ("\nilk txx cfg1: 0x%16lx\n", ilk_txx_cfg1.u64);
966 if (ilk_txx_cfg1.s.rx_link_fc)
967 cvmx_dprintf ("link flow control received\n");
968 if (ilk_txx_cfg1.s.tx_link_fc)
969 cvmx_dprintf ("link flow control sent\n");
971 ilk_txx_flow_ctl0.u64 = cvmx_read_csr (CVMX_ILK_TXX_FLOW_CTL0(interface));
972 cvmx_dprintf ("\nilk txx flow ctl0: 0x%16lx\n", ilk_txx_flow_ctl0.u64);
974 ilk_rxx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG1(interface));
975 cvmx_dprintf ("\nilk rxx cfg1: 0x%16lx\n", ilk_rxx_cfg1.u64);
976 cvmx_dprintf ("rx fifo count: %d\n", ilk_rxx_cfg1.s.rx_fifo_cnt);
978 ilk_rxx_int.u64 = cvmx_read_csr (CVMX_ILK_RXX_INT(interface));
979 cvmx_dprintf ("\nilk rxx int: 0x%16lx\n", ilk_rxx_int.u64);
980 if (ilk_rxx_int.s.pkt_drop_rxf)
981 cvmx_dprintf ("rx fifo packet drop\n");
983 cvmx_write_csr (CVMX_ILK_RXX_INT(interface), ilk_rxx_int.u64);
985 ilk_rxx_flow_ctl0.u64 = cvmx_read_csr (CVMX_ILK_RXX_FLOW_CTL0(interface));
986 cvmx_dprintf ("\nilk rxx flow ctl0: 0x%16lx\n", ilk_rxx_flow_ctl0.u64);
988 ilk_rxx_flow_ctl1.u64 = cvmx_read_csr (CVMX_ILK_RXX_FLOW_CTL1(interface));
989 cvmx_dprintf ("\nilk rxx flow ctl1: 0x%16lx\n", ilk_rxx_flow_ctl1.u64);
991 ilk_gbl_int.u64 = cvmx_read_csr (CVMX_ILK_GBL_INT);
992 cvmx_dprintf ("\nilk gbl int: 0x%16lx\n", ilk_gbl_int.u64);
993 if (ilk_gbl_int.s.rxf_push_full)
994 cvmx_dprintf ("rx fifo overflow\n");
996 cvmx_write_csr (CVMX_ILK_GBL_INT, ilk_gbl_int.u64);
1003 * @param interface The identifier of the packet interface to enable. cn68xx
1004 * has 2 interfaces: ilk0 and ilk1.
1006 * @return Zero on success, negative of failure.
1008 //#define CVMX_ILK_STATS_ENA 1
1009 int cvmx_ilk_enable (int interface)
1012 int retry_count = 0;
1013 cvmx_helper_link_info_t result;
1014 cvmx_ilk_txx_cfg1_t ilk_txx_cfg1;
1015 cvmx_ilk_rxx_cfg1_t ilk_rxx_cfg1;
1016 #ifdef CVMX_ILK_STATS_ENA
1017 cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0;
1018 cvmx_ilk_txx_cfg0_t ilk_txx_cfg0;
1021 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
1024 if (interface >= CVMX_NUM_ILK_INTF)
1029 #ifdef CVMX_ILK_STATS_ENA
1030 cvmx_dprintf ("\n");
1031 cvmx_dprintf ("<<<< ILK%d: Before enabling ilk\n", interface);
1032 cvmx_ilk_reg_dump_rx (interface);
1033 cvmx_ilk_reg_dump_tx (interface);
1036 /* RX packet will be enabled only if link is up */
1039 ilk_txx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG1(interface));
1040 ilk_txx_cfg1.s.pkt_ena = 1;
1041 ilk_txx_cfg1.s.rx_link_fc_ign = 1; /* cannot use link fc workaround */
1042 cvmx_write_csr (CVMX_ILK_TXX_CFG1(interface), ilk_txx_cfg1.u64);
1043 cvmx_read_csr (CVMX_ILK_TXX_CFG1(interface));
1045 #ifdef CVMX_ILK_STATS_ENA
1047 ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface));
1048 ilk_rxx_cfg0.s.lnk_stats_ena = 1;
1049 cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64);
1052 ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface));
1053 ilk_txx_cfg0.s.lnk_stats_ena = 1;
1054 cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64);
1059 if (retry_count > 10)
1062 /* Make sure the link is up, so that packets can be sent. */
1063 result = __cvmx_helper_ilk_link_get(cvmx_helper_get_ipd_port(interface + CVMX_ILK_GBL_BASE, 0));
1065 /* Small delay before another retry. */
1066 cvmx_wait_usec(100);
1068 ilk_rxx_cfg1.u64 = cvmx_read_csr(CVMX_ILK_RXX_CFG1(interface));
1069 if (ilk_rxx_cfg1.s.pkt_ena == 0)
1074 #ifdef CVMX_ILK_STATS_ENA
1075 cvmx_dprintf (">>>> ILK%d: After ILK is enabled\n", interface);
1076 cvmx_ilk_reg_dump_rx (interface);
1077 cvmx_ilk_reg_dump_tx (interface);
1080 if (result.s.link_up)
1089 * @param interface The identifier of the packet interface to disable. cn68xx
1090 * has 2 interfaces: ilk0 and ilk1.
1092 * @return Zero on success, negative of failure.
1094 int cvmx_ilk_disable (int interface)
1097 cvmx_ilk_txx_cfg1_t ilk_txx_cfg1;
1098 cvmx_ilk_rxx_cfg1_t ilk_rxx_cfg1;
1099 #ifdef CVMX_ILK_STATS_ENA
1100 cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0;
1101 cvmx_ilk_txx_cfg0_t ilk_txx_cfg0;
1104 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
1107 if (interface >= CVMX_NUM_ILK_INTF)
1111 ilk_txx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG1(interface));
1112 ilk_txx_cfg1.s.pkt_ena = 0;
1113 cvmx_write_csr (CVMX_ILK_TXX_CFG1(interface), ilk_txx_cfg1.u64);
1116 ilk_rxx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG1(interface));
1117 ilk_rxx_cfg1.s.pkt_ena = 0;
1118 cvmx_write_csr (CVMX_ILK_RXX_CFG1(interface), ilk_rxx_cfg1.u64);
1120 #ifdef CVMX_ILK_STATS_ENA
1122 ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface));
1123 ilk_rxx_cfg0.s.lnk_stats_ena = 0;
1124 cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64);
1127 ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface));
1128 ilk_txx_cfg0.s.lnk_stats_ena = 0;
1129 cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64);
1136 * Provide interface enable status
1138 * @param interface The identifier of the packet interface to disable. cn68xx
1139 * has 2 interfaces: ilk0 and ilk1.
1141 * @return Zero, not enabled; One, enabled.
1143 int cvmx_ilk_get_intf_ena (int interface)
1145 return cvmx_ilk_intf_cfg[interface].intf_en;
1151 * @param uc the byte to be counted
1153 * @return number of bits set
1155 unsigned char cvmx_ilk_bit_count (unsigned char uc)
1157 unsigned char count;
1159 for (count = 0; uc > 0; uc &= uc-1)
1166 * Provide interface lane mask
1168 * @param interface The identifier of the packet interface to disable. cn68xx
1169 * has 2 interfaces: ilk0 and ilk1.
1173 unsigned char cvmx_ilk_get_intf_ln_msk (int interface)
1175 return cvmx_ilk_intf_cfg[interface].lane_en_mask;
1179 * Provide channel info
1181 * @param interface The identifier of the packet interface to disable. cn68xx
1182 * has 2 interfaces: ilk0 and ilk1.
1183 * @param chans A pointer to a channel array
1184 * @param num_chan A pointer to the number of channels
1186 * @return Zero on success, negative of failure.
1188 int cvmx_ilk_get_chan_info (int interface, unsigned char **chans,
1189 unsigned char *num_chan)
1191 *chans = cvmx_ilk_chan_map[interface];
1192 *num_chan = cvmx_ilk_chans[interface];
1198 * Show channel statistics
1200 * @param interface The identifier of the packet interface to disable. cn68xx
1201 * has 2 interfaces: ilk0 and ilk1.
1202 * @param pstats A pointer to cvmx_ilk_stats_ctrl_t that specifies which
1203 * logical channels to access
1207 void cvmx_ilk_show_stats (int interface, cvmx_ilk_stats_ctrl_t *pstats)
1210 cvmx_ilk_rxx_idx_stat0_t ilk_rxx_idx_stat0;
1211 cvmx_ilk_rxx_idx_stat1_t ilk_rxx_idx_stat1;
1212 cvmx_ilk_rxx_mem_stat0_t ilk_rxx_mem_stat0;
1213 cvmx_ilk_rxx_mem_stat1_t ilk_rxx_mem_stat1;
1215 cvmx_ilk_txx_idx_stat0_t ilk_txx_idx_stat0;
1216 cvmx_ilk_txx_idx_stat1_t ilk_txx_idx_stat1;
1217 cvmx_ilk_txx_mem_stat0_t ilk_txx_mem_stat0;
1218 cvmx_ilk_txx_mem_stat1_t ilk_txx_mem_stat1;
1220 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
1223 if (interface >= CVMX_NUM_ILK_INTF)
1229 /* discrete channels */
1230 if (pstats->chan_list != NULL)
1232 for (i = 0; i < pstats->num_chans; i++)
1235 /* get the number of rx packets */
1236 ilk_rxx_idx_stat0.u64 = 0;
1237 ilk_rxx_idx_stat0.s.index = *pstats->chan_list;
1238 ilk_rxx_idx_stat0.s.clr = pstats->clr_on_rd;
1239 cvmx_write_csr (CVMX_ILK_RXX_IDX_STAT0(interface),
1240 ilk_rxx_idx_stat0.u64);
1241 ilk_rxx_mem_stat0.u64 = cvmx_read_csr
1242 (CVMX_ILK_RXX_MEM_STAT0(interface));
1244 /* get the number of rx bytes */
1245 ilk_rxx_idx_stat1.u64 = 0;
1246 ilk_rxx_idx_stat1.s.index = *pstats->chan_list;
1247 ilk_rxx_idx_stat1.s.clr = pstats->clr_on_rd;
1248 cvmx_write_csr (CVMX_ILK_RXX_IDX_STAT1(interface),
1249 ilk_rxx_idx_stat1.u64);
1250 ilk_rxx_mem_stat1.u64 = cvmx_read_csr
1251 (CVMX_ILK_RXX_MEM_STAT1(interface));
1253 cvmx_dprintf ("ILK%d Channel%d Rx: %d packets %d bytes\n", interface,
1254 *pstats->chan_list, ilk_rxx_mem_stat0.s.rx_pkt,
1255 (unsigned int) ilk_rxx_mem_stat1.s.rx_bytes);
1257 /* get the number of tx packets */
1258 ilk_txx_idx_stat0.u64 = 0;
1259 ilk_txx_idx_stat0.s.index = *pstats->chan_list;
1260 ilk_txx_idx_stat0.s.clr = pstats->clr_on_rd;
1261 cvmx_write_csr (CVMX_ILK_TXX_IDX_STAT0(interface),
1262 ilk_txx_idx_stat0.u64);
1263 ilk_txx_mem_stat0.u64 = cvmx_read_csr
1264 (CVMX_ILK_TXX_MEM_STAT0(interface));
1266 /* get the number of tx bytes */
1267 ilk_txx_idx_stat1.u64 = 0;
1268 ilk_txx_idx_stat1.s.index = *pstats->chan_list;
1269 ilk_txx_idx_stat1.s.clr = pstats->clr_on_rd;
1270 cvmx_write_csr (CVMX_ILK_TXX_IDX_STAT1(interface),
1271 ilk_txx_idx_stat1.u64);
1272 ilk_txx_mem_stat1.u64 = cvmx_read_csr
1273 (CVMX_ILK_TXX_MEM_STAT1(interface));
1275 cvmx_dprintf ("ILK%d Channel%d Tx: %d packets %d bytes\n", interface,
1276 *pstats->chan_list, ilk_txx_mem_stat0.s.tx_pkt,
1277 (unsigned int) ilk_txx_mem_stat1.s.tx_bytes);
1284 /* continuous channels */
1285 ilk_rxx_idx_stat0.u64 = 0;
1286 ilk_rxx_idx_stat0.s.index = pstats->chan_start;
1287 ilk_rxx_idx_stat0.s.inc = pstats->chan_step;
1288 ilk_rxx_idx_stat0.s.clr = pstats->clr_on_rd;
1289 cvmx_write_csr (CVMX_ILK_RXX_IDX_STAT0(interface), ilk_rxx_idx_stat0.u64);
1291 ilk_rxx_idx_stat1.u64 = 0;
1292 ilk_rxx_idx_stat1.s.index = pstats->chan_start;
1293 ilk_rxx_idx_stat1.s.inc = pstats->chan_step;
1294 ilk_rxx_idx_stat1.s.clr = pstats->clr_on_rd;
1295 cvmx_write_csr (CVMX_ILK_RXX_IDX_STAT1(interface), ilk_rxx_idx_stat1.u64);
1297 ilk_txx_idx_stat0.u64 = 0;
1298 ilk_txx_idx_stat0.s.index = pstats->chan_start;
1299 ilk_txx_idx_stat0.s.inc = pstats->chan_step;
1300 ilk_txx_idx_stat0.s.clr = pstats->clr_on_rd;
1301 cvmx_write_csr (CVMX_ILK_TXX_IDX_STAT0(interface), ilk_txx_idx_stat0.u64);
1303 ilk_txx_idx_stat1.u64 = 0;
1304 ilk_txx_idx_stat1.s.index = pstats->chan_start;
1305 ilk_txx_idx_stat1.s.inc = pstats->chan_step;
1306 ilk_txx_idx_stat1.s.clr = pstats->clr_on_rd;
1307 cvmx_write_csr (CVMX_ILK_TXX_IDX_STAT1(interface), ilk_txx_idx_stat1.u64);
1309 for (i = pstats->chan_start; i <= pstats->chan_end; i += pstats->chan_step)
1311 ilk_rxx_mem_stat0.u64 = cvmx_read_csr
1312 (CVMX_ILK_RXX_MEM_STAT0(interface));
1313 ilk_rxx_mem_stat1.u64 = cvmx_read_csr
1314 (CVMX_ILK_RXX_MEM_STAT1(interface));
1315 cvmx_dprintf ("ILK%d Channel%d Rx: %d packets %d bytes\n", interface, i,
1316 ilk_rxx_mem_stat0.s.rx_pkt,
1317 (unsigned int) ilk_rxx_mem_stat1.s.rx_bytes);
1319 ilk_txx_mem_stat0.u64 = cvmx_read_csr
1320 (CVMX_ILK_TXX_MEM_STAT0(interface));
1321 ilk_txx_mem_stat1.u64 = cvmx_read_csr
1322 (CVMX_ILK_TXX_MEM_STAT1(interface));
1323 cvmx_dprintf ("ILK%d Channel%d Tx: %d packets %d bytes\n", interface, i,
1324 ilk_rxx_mem_stat0.s.rx_pkt,
1325 (unsigned int) ilk_rxx_mem_stat1.s.rx_bytes);
1332 * enable or disable loopbacks
1334 * @param interface The identifier of the packet interface to disable. cn68xx
1335 * has 2 interfaces: ilk0 and ilk1.
1336 * @param enable Enable or disable loopback
1337 * @param mode Internal or external loopback
1339 * @return Zero on success, negative of failure.
1341 int cvmx_ilk_lpbk (int interface, cvmx_ilk_lpbk_ena_t enable,
1342 cvmx_ilk_lpbk_mode_t mode)
1345 cvmx_ilk_txx_cfg0_t ilk_txx_cfg0;
1346 cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0;
1348 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
1351 if (interface >= CVMX_NUM_ILK_INTF)
1354 /* internal loopback. only 1 type of loopback can be on at 1 time */
1355 if (mode == CVMX_ILK_LPBK_INT)
1357 if (enable == CVMX_ILK_LPBK_ENA)
1359 ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface));
1360 ilk_txx_cfg0.s.ext_lpbk = CVMX_ILK_LPBK_DISA;
1361 ilk_txx_cfg0.s.ext_lpbk_fc = CVMX_ILK_LPBK_DISA;
1362 cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64);
1364 ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface));
1365 ilk_rxx_cfg0.s.ext_lpbk = CVMX_ILK_LPBK_DISA;
1366 ilk_rxx_cfg0.s.ext_lpbk_fc = CVMX_ILK_LPBK_DISA;
1367 cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64);
1370 ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface));
1371 ilk_txx_cfg0.s.int_lpbk = enable;
1372 cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64);
1378 /* external loopback. only 1 type of loopback can be on at 1 time */
1379 if (enable == CVMX_ILK_LPBK_ENA)
1381 ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface));
1382 ilk_txx_cfg0.s.int_lpbk = CVMX_ILK_LPBK_DISA;
1383 cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64);
1386 ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface));
1387 ilk_txx_cfg0.s.ext_lpbk = enable;
1388 ilk_txx_cfg0.s.ext_lpbk_fc = enable;
1389 cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64);
1391 ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface));
1392 ilk_rxx_cfg0.s.ext_lpbk = enable;
1393 ilk_rxx_cfg0.s.ext_lpbk_fc = enable;
1394 cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64);
1400 #endif /* CVMX_ENABLE_HELPER_FUNCTIONS */