1232809Sjmallett/***********************license start***************
2232809Sjmallett * Copyright (c) 2003-2010  Cavium Inc. (support@cavium.com). All rights
3232809Sjmallett * reserved.
4232809Sjmallett *
5232809Sjmallett *
6232809Sjmallett * Redistribution and use in source and binary forms, with or without
7232809Sjmallett * modification, are permitted provided that the following conditions are
8232809Sjmallett * met:
9232809Sjmallett *
10232809Sjmallett *   * Redistributions of source code must retain the above copyright
11232809Sjmallett *     notice, this list of conditions and the following disclaimer.
12232809Sjmallett *
13232809Sjmallett *   * Redistributions in binary form must reproduce the above
14232809Sjmallett *     copyright notice, this list of conditions and the following
15232809Sjmallett *     disclaimer in the documentation and/or other materials provided
16232809Sjmallett *     with the distribution.
17232809Sjmallett
18232809Sjmallett *   * Neither the name of Cavium Inc. nor the names of
19232809Sjmallett *     its contributors may be used to endorse or promote products
20232809Sjmallett *     derived from this software without specific prior written
21232809Sjmallett *     permission.
22232809Sjmallett
23232809Sjmallett * This Software, including technical data, may be subject to U.S. export  control
24232809Sjmallett * laws, including the U.S. Export Administration Act and its  associated
25232809Sjmallett * regulations, and may be subject to export or import  regulations in other
26232809Sjmallett * countries.
27232809Sjmallett
28232809Sjmallett * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29232809Sjmallett * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
30232809Sjmallett * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
31232809Sjmallett * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
32232809Sjmallett * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
33232809Sjmallett * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
34232809Sjmallett * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
35232809Sjmallett * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
36232809Sjmallett * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE  RISK ARISING OUT OF USE OR
37232809Sjmallett * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38232809Sjmallett ***********************license end**************************************/
39232809Sjmallett
40232809Sjmallett/**
41232809Sjmallett * @file
42232809Sjmallett *
43232809Sjmallett * Support library for the ILK
44232809Sjmallett *
45232809Sjmallett * <hr>$Revision: 49448 $<hr>
46232809Sjmallett */
47232809Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL
48232809Sjmallett#include <linux/module.h>
49232809Sjmallett#include <asm/octeon/cvmx.h>
50232809Sjmallett#include <asm/octeon/cvmx-config.h>
51232809Sjmallett#include <asm/octeon/cvmx-sysinfo.h>
52232809Sjmallett#include <asm/octeon/cvmx-pko.h>
53232809Sjmallett#include <asm/octeon/cvmx-ilk.h>
54232809Sjmallett#include <asm/octeon/cvmx-ilk-defs.h>
55232809Sjmallett#include <asm/octeon/cvmx-helper-util.h>
56232809Sjmallett#include <asm/octeon/cvmx-helper-ilk.h>
57232809Sjmallett#else
58232809Sjmallett#include "cvmx.h"
59232812Sjmallett#if !defined(__FreeBSD__) || !defined(_KERNEL)
60232809Sjmallett#include "cvmx-config.h"
61232812Sjmallett#endif
62232809Sjmallett#include "cvmx-sysinfo.h"
63232809Sjmallett#include "cvmx-pko.h"
64232809Sjmallett#include "cvmx-ilk.h"
65232809Sjmallett#include "cvmx-helper-util.h"
66232809Sjmallett#include "cvmx-helper-ilk.h"
67232809Sjmallett#endif
68232809Sjmallett
69232809Sjmallett#ifdef CVMX_ENABLE_HELPER_FUNCTIONS
70232809Sjmallett
71232809Sjmallett/*
72232809Sjmallett * global configurations. to disable the 2nd ILK, set
73232809Sjmallett * cvmx_ilk_lane_mask[CVMX_NUM_ILK_INTF] = {0xff, 0x0} and
74232809Sjmallett * cvmx_ilk_chans[CVMX_NUM_ILK_INTF] = {8, 0}
75232809Sjmallett */
76232809Sjmallettunsigned char cvmx_ilk_lane_mask[CVMX_NUM_ILK_INTF] = {0xf, 0xf0};
77232809Sjmallett//#define SINGLE_PORT_SIM_ILK
78232809Sjmallett#ifdef SINGLE_PORT_SIM_ILK
79232809Sjmallettunsigned char cvmx_ilk_chans[CVMX_NUM_ILK_INTF] = {1, 1};
80232809Sjmallettunsigned char cvmx_ilk_chan_map[CVMX_NUM_ILK_INTF][CVMX_MAX_ILK_CHANS] =
81232809Sjmallett{{0},
82232809Sjmallett {0}};
83232809Sjmallett#else /* sample case */
84232809Sjmallettunsigned char cvmx_ilk_chans[CVMX_NUM_ILK_INTF] = {8, 8};
85232809Sjmallettunsigned char cvmx_ilk_chan_map[CVMX_NUM_ILK_INTF][CVMX_MAX_ILK_CHANS] =
86232809Sjmallett{{0, 1, 2, 3, 4, 5, 6, 7},
87232809Sjmallett {0, 1, 2, 3, 4, 5, 6, 7}};
88232809Sjmallett#endif
89232809Sjmallett
90232809Sjmallett/* Default callbacks, can be overridden
91232809Sjmallett *  using cvmx_ilk_get_callbacks/cvmx_ilk_set_callbacks
92232809Sjmallett */
93232809Sjmallettstatic cvmx_ilk_callbacks_t cvmx_ilk_callbacks = {
94232809Sjmallett  .calendar_setup_rx   = cvmx_ilk_cal_setup_rx,
95232809Sjmallett};
96232809Sjmallett
97232809Sjmallettstatic cvmx_ilk_intf_t cvmx_ilk_intf_cfg[CVMX_NUM_ILK_INTF];
98232809Sjmallett
99232809Sjmallett/**
100232809Sjmallett * Get current ILK initialization callbacks
101232809Sjmallett *
102232809Sjmallett * @param callbacks  Pointer to the callbacks structure.to fill
103232809Sjmallett *
104232809Sjmallett * @return Pointer to cvmx_ilk_callbacks_t structure.
105232809Sjmallett */
106232809Sjmallettvoid cvmx_ilk_get_callbacks(cvmx_ilk_callbacks_t * callbacks)
107232809Sjmallett{
108232809Sjmallett    memcpy(callbacks, &cvmx_ilk_callbacks, sizeof(cvmx_ilk_callbacks));
109232809Sjmallett}
110232809Sjmallett
111232809Sjmallett/**
112232809Sjmallett * Set new ILK initialization callbacks
113232809Sjmallett *
114232809Sjmallett * @param new_callbacks  Pointer to an updated callbacks structure.
115232809Sjmallett */
116232809Sjmallettvoid cvmx_ilk_set_callbacks(cvmx_ilk_callbacks_t * new_callbacks)
117232809Sjmallett{
118232809Sjmallett    memcpy(&cvmx_ilk_callbacks, new_callbacks, sizeof(cvmx_ilk_callbacks));
119232809Sjmallett}
120232809Sjmallett
121232809Sjmallett/**
122232809Sjmallett * Initialize and start the ILK interface.
123232809Sjmallett *
124232809Sjmallett * @param interface The identifier of the packet interface to configure and
125232809Sjmallett *                  use as a ILK interface. cn68xx has 2 interfaces: ilk0 and
126232809Sjmallett *                  ilk1.
127232809Sjmallett *
128232809Sjmallett * @param lane_mask the lane group for this interface
129232809Sjmallett *
130232809Sjmallett * @return Zero on success, negative of failure.
131232809Sjmallett */
132232809Sjmallettint cvmx_ilk_start_interface (int interface, unsigned char lane_mask)
133232809Sjmallett{
134232809Sjmallett    int res = -1;
135232809Sjmallett    int other_intf, this_qlm, other_qlm;
136232809Sjmallett    unsigned char uni_mask;
137232809Sjmallett    cvmx_mio_qlmx_cfg_t mio_qlmx_cfg, other_mio_qlmx_cfg;
138232809Sjmallett    cvmx_ilk_txx_cfg0_t ilk_txx_cfg0;
139232809Sjmallett    cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0;
140232809Sjmallett    cvmx_ilk_ser_cfg_t ilk_ser_cfg;
141232809Sjmallett
142232809Sjmallett    if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
143232809Sjmallett        return res;
144232809Sjmallett
145232809Sjmallett    if (interface >= CVMX_NUM_ILK_INTF)
146232809Sjmallett        return res;
147232809Sjmallett
148232809Sjmallett    if (lane_mask == 0)
149232809Sjmallett        return res;
150232809Sjmallett
151232809Sjmallett    /* check conflicts between 2 ilk interfaces. 1 lane can be assigned to 1
152232809Sjmallett     * interface only */
153232809Sjmallett    other_intf = !interface;
154232809Sjmallett    this_qlm = interface + CVMX_ILK_QLM_BASE;
155232809Sjmallett    other_qlm = other_intf + CVMX_ILK_QLM_BASE;
156232809Sjmallett    if (cvmx_ilk_intf_cfg[other_intf].lane_en_mask & lane_mask)
157232809Sjmallett    {
158232809Sjmallett        cvmx_dprintf ("ILK%d: %s: lane assignment conflict\n", interface,
159232809Sjmallett                      __FUNCTION__);
160232809Sjmallett        return res;
161232809Sjmallett    }
162232809Sjmallett
163232809Sjmallett    /* check the legality of the lane mask. interface 0 can have 8 lanes,
164232809Sjmallett     * while interface 1 can have 4 lanes at most */
165232809Sjmallett    uni_mask = lane_mask >> (interface * 4);
166232809Sjmallett    if ((uni_mask != 0x1 && uni_mask != 0x3 && uni_mask != 0xf &&
167232809Sjmallett         uni_mask != 0xff) || (interface == 1 && lane_mask > 0xf0))
168232809Sjmallett    {
169232809Sjmallett#if CVMX_ENABLE_DEBUG_PRINTS
170232809Sjmallett        cvmx_dprintf ("ILK%d: %s: incorrect lane mask: 0x%x \n", interface,
171232809Sjmallett                      __FUNCTION__, uni_mask);
172232809Sjmallett#endif
173232809Sjmallett        return res;
174232809Sjmallett    }
175232809Sjmallett
176232809Sjmallett    /* check the availability of qlms. qlm_cfg = 001 means the chip is fused
177232809Sjmallett     * to give this qlm to ilk */
178232809Sjmallett    mio_qlmx_cfg.u64 = cvmx_read_csr (CVMX_MIO_QLMX_CFG(this_qlm));
179232809Sjmallett    other_mio_qlmx_cfg.u64 = cvmx_read_csr (CVMX_MIO_QLMX_CFG(other_qlm));
180232809Sjmallett    if (mio_qlmx_cfg.s.qlm_cfg != 1 ||
181232809Sjmallett        (uni_mask == 0xff && other_mio_qlmx_cfg.s.qlm_cfg != 1))
182232809Sjmallett    {
183232809Sjmallett#if CVMX_ENABLE_DEBUG_PRINTS
184232809Sjmallett        cvmx_dprintf ("ILK%d: %s: qlm unavailable\n", interface, __FUNCTION__);
185232809Sjmallett#endif
186232809Sjmallett        return res;
187232809Sjmallett    }
188232809Sjmallett
189232809Sjmallett    /* power up the serdes */
190232809Sjmallett    ilk_ser_cfg.u64 = cvmx_read_csr (CVMX_ILK_SER_CFG);
191232809Sjmallett    if (ilk_ser_cfg.s.ser_pwrup == 0)
192232809Sjmallett    {
193232809Sjmallett        ilk_ser_cfg.s.ser_rxpol_auto = 1;
194232809Sjmallett        ilk_ser_cfg.s.ser_rxpol = 0;
195232809Sjmallett        ilk_ser_cfg.s.ser_txpol = 0;
196232809Sjmallett        ilk_ser_cfg.s.ser_reset_n = 0xff;
197232809Sjmallett        ilk_ser_cfg.s.ser_haul = 0;
198232809Sjmallett    }
199232809Sjmallett    ilk_ser_cfg.s.ser_pwrup |= ((interface ==0) && (lane_mask > 0xf)) ?
200232809Sjmallett                               0x3 : (1 << interface);
201232809Sjmallett    cvmx_write_csr (CVMX_ILK_SER_CFG, ilk_ser_cfg.u64);
202232809Sjmallett
203232809Sjmallett    /* configure the lane enable of the interface */
204232809Sjmallett    ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface));
205232809Sjmallett    ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface));
206232809Sjmallett    ilk_txx_cfg0.s.lane_ena = ilk_rxx_cfg0.s.lane_ena = lane_mask;
207232809Sjmallett    cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64);
208232809Sjmallett    cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64);
209232809Sjmallett
210232809Sjmallett    /* write to local cache. for lane speed, if interface 0 has 8 lanes,
211232809Sjmallett     * assume both qlms have the same speed */
212232809Sjmallett    cvmx_ilk_intf_cfg[interface].intf_en = 1;
213232809Sjmallett    cvmx_ilk_intf_cfg[interface].lane_en_mask = lane_mask;
214232809Sjmallett    res = 0;
215232809Sjmallett
216232809Sjmallett    return res;
217232809Sjmallett}
218232809Sjmallett
219232809Sjmallett/**
220232809Sjmallett * set pipe group base and length for the interface
221232809Sjmallett *
222232809Sjmallett * @param interface The identifier of the packet interface to configure and
223232809Sjmallett *                  use as a ILK interface. cn68xx has 2 interfaces: ilk0 and
224232809Sjmallett *                  ilk1.
225232809Sjmallett *
226232809Sjmallett * @param pipe_base the base of the pipe group
227232809Sjmallett * @param pipe_len  the length of the pipe group
228232809Sjmallett *
229232809Sjmallett * @return Zero on success, negative of failure.
230232809Sjmallett */
231232809Sjmallettint cvmx_ilk_set_pipe (int interface, int pipe_base, unsigned int pipe_len)
232232809Sjmallett{
233232809Sjmallett    int res = -1;
234232809Sjmallett    cvmx_ilk_txx_pipe_t ilk_txx_pipe;
235232809Sjmallett
236232809Sjmallett    if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
237232809Sjmallett        return res;
238232809Sjmallett
239232809Sjmallett    if (interface >= CVMX_NUM_ILK_INTF)
240232809Sjmallett        return res;
241232809Sjmallett
242232809Sjmallett    /* base should be between 0 and 127. base + length should be <127 */
243232809Sjmallett    if (!(pipe_base >= 0 && pipe_base <= 127) || (pipe_base + pipe_len > 127))
244232809Sjmallett    {
245232809Sjmallett#if CVMX_ENABLE_DEBUG_PRINTS
246232809Sjmallett        cvmx_dprintf ("ILK%d: %s: pipe base/length out of bounds\n", interface,
247232809Sjmallett                      __FUNCTION__);
248232809Sjmallett#endif
249232809Sjmallett        return res;
250232809Sjmallett    }
251232809Sjmallett
252232809Sjmallett    /* set them in ilk tx section */
253232809Sjmallett    ilk_txx_pipe.u64 = cvmx_read_csr (CVMX_ILK_TXX_PIPE(interface));
254232809Sjmallett    ilk_txx_pipe.s.base = pipe_base;
255232809Sjmallett    ilk_txx_pipe.s.nump = pipe_len;
256232809Sjmallett    cvmx_write_csr (CVMX_ILK_TXX_PIPE(interface), ilk_txx_pipe.u64);
257232809Sjmallett    res = 0;
258232809Sjmallett
259232809Sjmallett    return res;
260232809Sjmallett}
261232809Sjmallett
262232809Sjmallett/**
263232809Sjmallett * set logical channels for tx
264232809Sjmallett *
265232809Sjmallett * @param interface The identifier of the packet interface to configure and
266232809Sjmallett *                  use as a ILK interface. cn68xx has 2 interfaces: ilk0 and
267232809Sjmallett *                  ilk1.
268232809Sjmallett *
269232809Sjmallett * @param pch     pointer to an array of pipe-channel pair
270232809Sjmallett * @param num_chs the number of entries in the pipe-channel array
271232809Sjmallett *
272232809Sjmallett * @return Zero on success, negative of failure.
273232809Sjmallett */
274232809Sjmallettint cvmx_ilk_tx_set_channel (int interface, cvmx_ilk_pipe_chan_t *pch,
275232809Sjmallett                             unsigned int num_chs)
276232809Sjmallett{
277232809Sjmallett    int res = -1;
278232809Sjmallett    cvmx_ilk_txx_idx_pmap_t ilk_txx_idx_pmap;
279232809Sjmallett    unsigned int i;
280232809Sjmallett
281232809Sjmallett    if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
282232809Sjmallett        return res;
283232809Sjmallett
284232809Sjmallett    if (interface >= CVMX_NUM_ILK_INTF)
285232809Sjmallett        return res;
286232809Sjmallett
287232809Sjmallett    if (pch == NULL || num_chs > CVMX_MAX_ILK_PIPES)
288232809Sjmallett        return res;
289232809Sjmallett
290232809Sjmallett    /* write the pair to ilk tx */
291232809Sjmallett    for (i = 0; i < num_chs; i++)
292232809Sjmallett    {
293232809Sjmallett        ilk_txx_idx_pmap.u64 = 0;
294232809Sjmallett        ilk_txx_idx_pmap.s.index = pch->pipe;
295232809Sjmallett        cvmx_write_csr(CVMX_ILK_TXX_IDX_PMAP(interface), ilk_txx_idx_pmap.u64);
296232809Sjmallett        cvmx_write_csr(CVMX_ILK_TXX_MEM_PMAP(interface), pch->chan);
297232809Sjmallett        pch++;
298232809Sjmallett    }
299232809Sjmallett    res = 0;
300232809Sjmallett
301232809Sjmallett    return res;
302232809Sjmallett}
303232809Sjmallett
304232809Sjmallett/**
305232809Sjmallett * set pkind for rx
306232809Sjmallett *
307232809Sjmallett * @param interface The identifier of the packet interface to configure and
308232809Sjmallett *                  use as a ILK interface. cn68xx has 2 interfaces: ilk0 and
309232809Sjmallett *                  ilk1.
310232809Sjmallett *
311232809Sjmallett * @param chpknd    pointer to an array of channel-pkind pair
312232809Sjmallett * @param num_pknd the number of entries in the channel-pkind array
313232809Sjmallett *
314232809Sjmallett * @return Zero on success, negative of failure.
315232809Sjmallett */
316232809Sjmallettint cvmx_ilk_rx_set_pknd (int interface, cvmx_ilk_chan_pknd_t *chpknd,
317232809Sjmallett                          unsigned int num_pknd)
318232809Sjmallett{
319232809Sjmallett    int res = -1;
320232809Sjmallett    cvmx_ilk_rxf_idx_pmap_t ilk_rxf_idx_pmap;
321232809Sjmallett    unsigned int i;
322232809Sjmallett
323232809Sjmallett    if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
324232809Sjmallett        return res;
325232809Sjmallett
326232809Sjmallett    if (interface >= CVMX_NUM_ILK_INTF)
327232809Sjmallett        return res;
328232809Sjmallett
329232809Sjmallett    if (chpknd == NULL || num_pknd > CVMX_MAX_ILK_PKNDS)
330232809Sjmallett        return res;
331232809Sjmallett
332232809Sjmallett    /* write the pair to ilk rx. note the channels for different interfaces
333232809Sjmallett     * are given in *chpknd and interface is not used as a param */
334232809Sjmallett    for (i = 0; i < num_pknd; i++)
335232809Sjmallett    {
336232809Sjmallett        ilk_rxf_idx_pmap.u64 = 0;
337232809Sjmallett        ilk_rxf_idx_pmap.s.index = interface * 256 + chpknd->chan;
338232809Sjmallett        cvmx_write_csr (CVMX_ILK_RXF_IDX_PMAP, ilk_rxf_idx_pmap.u64);
339232809Sjmallett        cvmx_write_csr (CVMX_ILK_RXF_MEM_PMAP, chpknd->pknd);
340232809Sjmallett        chpknd++;
341232809Sjmallett    }
342232809Sjmallett    res = 0;
343232809Sjmallett
344232809Sjmallett    return res;
345232809Sjmallett}
346232809Sjmallett
347232809Sjmallett/**
348232809Sjmallett * configure calendar for rx
349232809Sjmallett *
350232809Sjmallett * @param interface The identifier of the packet interface to configure and
351232809Sjmallett *                  use as a ILK interface. cn68xx has 2 interfaces: ilk0 and
352232809Sjmallett *                  ilk1.
353232809Sjmallett *
354232809Sjmallett * @param cal_depth the number of calendar entries
355232809Sjmallett * @param pent      pointer to calendar entries
356232809Sjmallett *
357232809Sjmallett * @return Zero on success, negative of failure.
358232809Sjmallett */
359232812Sjmallettstatic int cvmx_ilk_rx_cal_conf (int interface, int cal_depth,
360232809Sjmallett                          cvmx_ilk_cal_entry_t *pent)
361232809Sjmallett{
362232809Sjmallett    int res = -1, num_grp, num_rest, i, j;
363232809Sjmallett    cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0;
364232809Sjmallett    cvmx_ilk_rxx_idx_cal_t ilk_rxx_idx_cal;
365232809Sjmallett    cvmx_ilk_rxx_mem_cal0_t ilk_rxx_mem_cal0;
366232809Sjmallett    cvmx_ilk_rxx_mem_cal1_t ilk_rxx_mem_cal1;
367232809Sjmallett    unsigned long int tmp;
368232809Sjmallett
369232809Sjmallett    if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
370232809Sjmallett        return res;
371232809Sjmallett
372232809Sjmallett    if (interface >= CVMX_NUM_ILK_INTF)
373232809Sjmallett        return res;
374232809Sjmallett
375232809Sjmallett    if (cal_depth < CVMX_ILK_RX_MIN_CAL || cal_depth > CVMX_ILK_MAX_CAL
376232809Sjmallett        || pent == NULL)
377232809Sjmallett        return res;
378232809Sjmallett
379232809Sjmallett    /* mandatory link-level fc as workarounds for ILK-15397 and ILK-15479 */
380232809Sjmallett    /* TODO: test effectiveness */
381232809Sjmallett#if 0
382232809Sjmallett    if (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_0) && pent->ent_ctrl == PIPE_BPID)
383232809Sjmallett        for (i = 0; i < cal_depth; i++)
384232809Sjmallett            pent->ent_ctrl = LINK;
385232809Sjmallett#endif
386232809Sjmallett
387232809Sjmallett    /* set the depth */
388232809Sjmallett    ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface));
389232809Sjmallett    ilk_rxx_cfg0.s.cal_depth = cal_depth;
390232809Sjmallett    cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64);
391232809Sjmallett
392232809Sjmallett    /* set the calendar index */
393232809Sjmallett    num_grp = cal_depth / CVMX_ILK_CAL_GRP_SZ;
394232809Sjmallett    num_rest = cal_depth % CVMX_ILK_CAL_GRP_SZ;
395232809Sjmallett    ilk_rxx_idx_cal.u64 = 0;
396232809Sjmallett    ilk_rxx_idx_cal.s.inc = 1;
397232809Sjmallett    cvmx_write_csr (CVMX_ILK_RXX_IDX_CAL(interface), ilk_rxx_idx_cal.u64);
398232809Sjmallett
399232809Sjmallett    /* set the calendar entries. each group has both cal0 and cal1 registers */
400232809Sjmallett    for (i = 0; i < num_grp; i++)
401232809Sjmallett    {
402232809Sjmallett        ilk_rxx_mem_cal0.u64 = 0;
403232809Sjmallett        for (j = 0; j < CVMX_ILK_CAL_GRP_SZ/2; j++)
404232809Sjmallett        {
405232809Sjmallett            tmp = 0;
406232809Sjmallett            tmp = pent->pipe_bpid & ~(~tmp << CVMX_ILK_PIPE_BPID_SZ);
407232809Sjmallett            tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j;
408232809Sjmallett            ilk_rxx_mem_cal0.u64 |= tmp;
409232809Sjmallett
410232809Sjmallett            tmp = 0;
411232809Sjmallett            tmp = pent->ent_ctrl & ~(~tmp << CVMX_ILK_ENT_CTRL_SZ);
412232809Sjmallett            tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j +
413232809Sjmallett                    CVMX_ILK_PIPE_BPID_SZ;
414232809Sjmallett            ilk_rxx_mem_cal0.u64 |= tmp;
415232809Sjmallett            pent++;
416232809Sjmallett        }
417232809Sjmallett        cvmx_write_csr(CVMX_ILK_RXX_MEM_CAL0(interface), ilk_rxx_mem_cal0.u64);
418232809Sjmallett
419232809Sjmallett        ilk_rxx_mem_cal1.u64 = 0;
420232809Sjmallett        for (j = 0; j < CVMX_ILK_CAL_GRP_SZ/2; j++)
421232809Sjmallett        {
422232809Sjmallett            tmp = 0;
423232809Sjmallett            tmp = pent->pipe_bpid & ~(~tmp << CVMX_ILK_PIPE_BPID_SZ);
424232809Sjmallett            tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j;
425232809Sjmallett            ilk_rxx_mem_cal1.u64 |= tmp;
426232809Sjmallett
427232809Sjmallett            tmp = 0;
428232809Sjmallett            tmp = pent->ent_ctrl & ~(~tmp << CVMX_ILK_ENT_CTRL_SZ);
429232809Sjmallett            tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j +
430232809Sjmallett                    CVMX_ILK_PIPE_BPID_SZ;
431232809Sjmallett            ilk_rxx_mem_cal1.u64 |= tmp;
432232809Sjmallett            pent++;
433232809Sjmallett        }
434232809Sjmallett        cvmx_write_csr(CVMX_ILK_RXX_MEM_CAL1(interface), ilk_rxx_mem_cal1.u64);
435232809Sjmallett    }
436232809Sjmallett
437232809Sjmallett    /* set the calendar entries, the fraction of a group. but both cal0 and
438232809Sjmallett     * cal1 must be written */
439232809Sjmallett    ilk_rxx_mem_cal0.u64 = 0;
440232809Sjmallett    ilk_rxx_mem_cal1.u64 = 0;
441232809Sjmallett    for (i = 0; i < num_rest; i++)
442232809Sjmallett    {
443232809Sjmallett        if (i < CVMX_ILK_CAL_GRP_SZ/2)
444232809Sjmallett        {
445232809Sjmallett            tmp = 0;
446232809Sjmallett            tmp = pent->pipe_bpid & ~(~tmp << CVMX_ILK_PIPE_BPID_SZ);
447232809Sjmallett            tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * i;
448232809Sjmallett            ilk_rxx_mem_cal0.u64 |= tmp;
449232809Sjmallett
450232809Sjmallett            tmp = 0;
451232809Sjmallett            tmp = pent->ent_ctrl & ~(~tmp << CVMX_ILK_ENT_CTRL_SZ);
452232809Sjmallett            tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * i +
453232809Sjmallett                    CVMX_ILK_PIPE_BPID_SZ;
454232809Sjmallett            ilk_rxx_mem_cal0.u64 |= tmp;
455232809Sjmallett            pent++;
456232809Sjmallett        }
457232809Sjmallett
458232809Sjmallett        if (i >= CVMX_ILK_CAL_GRP_SZ/2)
459232809Sjmallett        {
460232809Sjmallett            tmp = 0;
461232809Sjmallett            tmp = pent->pipe_bpid & ~(~tmp << CVMX_ILK_PIPE_BPID_SZ);
462232809Sjmallett            tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) *
463232809Sjmallett                    (i - CVMX_ILK_CAL_GRP_SZ/2);
464232809Sjmallett            ilk_rxx_mem_cal1.u64 |= tmp;
465232809Sjmallett
466232809Sjmallett            tmp = 0;
467232809Sjmallett            tmp = pent->ent_ctrl & ~(~tmp << CVMX_ILK_ENT_CTRL_SZ);
468232809Sjmallett            tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) *
469232809Sjmallett                    (i - CVMX_ILK_CAL_GRP_SZ/2) + CVMX_ILK_PIPE_BPID_SZ;
470232809Sjmallett            ilk_rxx_mem_cal1.u64 |= tmp;
471232809Sjmallett            pent++;
472232809Sjmallett        }
473232809Sjmallett    }
474232809Sjmallett    cvmx_write_csr(CVMX_ILK_RXX_MEM_CAL0(interface), ilk_rxx_mem_cal0.u64);
475232809Sjmallett    cvmx_write_csr(CVMX_ILK_RXX_MEM_CAL1(interface), ilk_rxx_mem_cal1.u64);
476232809Sjmallett    cvmx_read_csr (CVMX_ILK_RXX_MEM_CAL1(interface));
477232809Sjmallett
478232809Sjmallett    return 0;
479232809Sjmallett}
480232809Sjmallett
481232809Sjmallett/**
482232809Sjmallett * set high water mark for rx
483232809Sjmallett *
484232809Sjmallett * @param interface The identifier of the packet interface to configure and
485232809Sjmallett *                  use as a ILK interface. cn68xx has 2 interfaces: ilk0 and
486232809Sjmallett *                  ilk1.
487232809Sjmallett *
488232809Sjmallett * @param hi_wm     high water mark for this interface
489232809Sjmallett *
490232809Sjmallett * @return Zero on success, negative of failure.
491232809Sjmallett */
492232812Sjmallettstatic int cvmx_ilk_rx_set_hwm (int interface, int hi_wm)
493232809Sjmallett{
494232809Sjmallett    int res = -1;
495232809Sjmallett    cvmx_ilk_rxx_cfg1_t ilk_rxx_cfg1;
496232809Sjmallett
497232809Sjmallett    if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
498232809Sjmallett        return res;
499232809Sjmallett
500232809Sjmallett    if (interface >= CVMX_NUM_ILK_INTF)
501232809Sjmallett        return res;
502232809Sjmallett
503232809Sjmallett    if (hi_wm <= 0)
504232809Sjmallett        return res;
505232809Sjmallett
506232809Sjmallett    /* set the hwm */
507232809Sjmallett    ilk_rxx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG1(interface));
508232809Sjmallett    ilk_rxx_cfg1.s.rx_fifo_hwm = hi_wm;
509232809Sjmallett    cvmx_write_csr (CVMX_ILK_RXX_CFG1(interface), ilk_rxx_cfg1.u64);
510232809Sjmallett    res = 0;
511232809Sjmallett
512232809Sjmallett    return res;
513232809Sjmallett}
514232809Sjmallett
515232809Sjmallett/**
516232809Sjmallett * enable calendar for rx
517232809Sjmallett *
518232809Sjmallett * @param interface The identifier of the packet interface to configure and
519232809Sjmallett *                  use as a ILK interface. cn68xx has 2 interfaces: ilk0 and
520232809Sjmallett *                  ilk1.
521232809Sjmallett *
522232809Sjmallett * @param cal_ena   enable or disable calendar
523232809Sjmallett *
524232809Sjmallett * @return Zero on success, negative of failure.
525232809Sjmallett */
526232812Sjmallettstatic int cvmx_ilk_rx_cal_ena (int interface, unsigned char cal_ena)
527232809Sjmallett{
528232809Sjmallett    int res = -1;
529232809Sjmallett    cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0;
530232809Sjmallett
531232809Sjmallett    if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
532232809Sjmallett        return res;
533232809Sjmallett
534232809Sjmallett    if (interface >= CVMX_NUM_ILK_INTF)
535232809Sjmallett        return res;
536232809Sjmallett
537232809Sjmallett    /* set the enable */
538232809Sjmallett    ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface));
539232809Sjmallett    ilk_rxx_cfg0.s.cal_ena = cal_ena;
540232809Sjmallett    cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64);
541232809Sjmallett    cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface));
542232809Sjmallett    res = 0;
543232809Sjmallett
544232809Sjmallett    return res;
545232809Sjmallett}
546232809Sjmallett
547232809Sjmallett/**
548232809Sjmallett * set up calendar for rx
549232809Sjmallett *
550232809Sjmallett * @param interface The identifier of the packet interface to configure and
551232809Sjmallett *                  use as a ILK interface. cn68xx has 2 interfaces: ilk0 and
552232809Sjmallett *                  ilk1.
553232809Sjmallett *
554232809Sjmallett * @param cal_depth the number of calendar entries
555232809Sjmallett * @param pent      pointer to calendar entries
556232809Sjmallett * @param hi_wm     high water mark for this interface
557232809Sjmallett * @param cal_ena   enable or disable calendar
558232809Sjmallett *
559232809Sjmallett * @return Zero on success, negative of failure.
560232809Sjmallett */
561232809Sjmallettint cvmx_ilk_cal_setup_rx (int interface, int cal_depth,
562232809Sjmallett                           cvmx_ilk_cal_entry_t *pent, int hi_wm,
563232809Sjmallett                           unsigned char cal_ena)
564232809Sjmallett{
565232809Sjmallett    int res = -1;
566232809Sjmallett
567232809Sjmallett    if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
568232809Sjmallett        return res;
569232809Sjmallett
570232809Sjmallett    if (interface >= CVMX_NUM_ILK_INTF)
571232809Sjmallett        return res;
572232809Sjmallett
573232809Sjmallett    res = cvmx_ilk_rx_cal_conf (interface, cal_depth, pent);
574232809Sjmallett    if (res < 0)
575232809Sjmallett        return res;
576232809Sjmallett
577232809Sjmallett    res = cvmx_ilk_rx_set_hwm (interface, hi_wm);
578232809Sjmallett    if (res < 0)
579232809Sjmallett        return res;
580232809Sjmallett
581232809Sjmallett    res = cvmx_ilk_rx_cal_ena (interface, cal_ena);
582232809Sjmallett    return res;
583232809Sjmallett}
584232809Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL
585232809SjmallettEXPORT_SYMBOL(cvmx_ilk_cal_setup_rx);
586232809Sjmallett#endif
587232809Sjmallett
588232809Sjmallett/**
589232809Sjmallett * configure calendar for tx
590232809Sjmallett *
591232809Sjmallett * @param interface The identifier of the packet interface to configure and
592232809Sjmallett *                  use as a ILK interface. cn68xx has 2 interfaces: ilk0 and
593232809Sjmallett *                  ilk1.
594232809Sjmallett *
595232809Sjmallett * @param cal_depth the number of calendar entries
596232809Sjmallett * @param pent      pointer to calendar entries
597232809Sjmallett *
598232809Sjmallett * @return Zero on success, negative of failure.
599232809Sjmallett */
600232812Sjmallettstatic int cvmx_ilk_tx_cal_conf (int interface, int cal_depth,
601232809Sjmallett                          cvmx_ilk_cal_entry_t *pent)
602232809Sjmallett{
603232809Sjmallett    int res = -1, num_grp, num_rest, i, j;
604232809Sjmallett    cvmx_ilk_txx_cfg0_t ilk_txx_cfg0;
605232809Sjmallett    cvmx_ilk_txx_idx_cal_t ilk_txx_idx_cal;
606232809Sjmallett    cvmx_ilk_txx_mem_cal0_t ilk_txx_mem_cal0;
607232809Sjmallett    cvmx_ilk_txx_mem_cal1_t ilk_txx_mem_cal1;
608232809Sjmallett    unsigned long int tmp;
609232809Sjmallett    cvmx_ilk_cal_entry_t *ent_tmp;
610232809Sjmallett
611232809Sjmallett    if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
612232809Sjmallett        return res;
613232809Sjmallett
614232809Sjmallett    if (interface >= CVMX_NUM_ILK_INTF)
615232809Sjmallett        return res;
616232809Sjmallett
617232809Sjmallett    if (cal_depth < CVMX_ILK_TX_MIN_CAL || cal_depth > CVMX_ILK_MAX_CAL
618232809Sjmallett        || pent == NULL)
619232809Sjmallett        return res;
620232809Sjmallett
621232809Sjmallett    /* mandatory link-level fc as workarounds for ILK-15397 and ILK-15479 */
622232809Sjmallett    /* TODO: test effectiveness */
623232809Sjmallett#if 0
624232809Sjmallett    if (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_0) && pent->ent_ctrl == PIPE_BPID)
625232809Sjmallett        for (i = 0; i < cal_depth; i++)
626232809Sjmallett            pent->ent_ctrl = LINK;
627232809Sjmallett#endif
628232809Sjmallett
629232809Sjmallett    /* tx calendar depth must be a multiple of 8 */
630232809Sjmallett    num_grp = (cal_depth - 1) / CVMX_ILK_CAL_GRP_SZ + 1;
631232809Sjmallett    num_rest = cal_depth % CVMX_ILK_CAL_GRP_SZ;
632232809Sjmallett    if (num_rest != 0)
633232809Sjmallett    {
634232809Sjmallett        ent_tmp = pent + cal_depth;
635232809Sjmallett        for (i = num_rest; i < 8; i++, ent_tmp++)
636232809Sjmallett        {
637232809Sjmallett            ent_tmp->pipe_bpid = 0;
638232809Sjmallett            ent_tmp->ent_ctrl = XOFF;
639232809Sjmallett        }
640232809Sjmallett    }
641232809Sjmallett    cal_depth = num_grp * 8;
642232809Sjmallett
643232809Sjmallett    /* set the depth */
644232809Sjmallett    ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface));
645232809Sjmallett    ilk_txx_cfg0.s.cal_depth = cal_depth;
646232809Sjmallett    cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64);
647232809Sjmallett
648232809Sjmallett    /* set the calendar index */
649232809Sjmallett    ilk_txx_idx_cal.u64 = 0;
650232809Sjmallett    ilk_txx_idx_cal.s.inc = 1;
651232809Sjmallett    cvmx_write_csr (CVMX_ILK_TXX_IDX_CAL(interface), ilk_txx_idx_cal.u64);
652232809Sjmallett
653232809Sjmallett    /* set the calendar entries. each group has both cal0 and cal1 registers */
654232809Sjmallett    for (i = 0; i < num_grp; i++)
655232809Sjmallett    {
656232809Sjmallett        ilk_txx_mem_cal0.u64 = 0;
657232809Sjmallett        for (j = 0; j < CVMX_ILK_CAL_GRP_SZ/2; j++)
658232809Sjmallett        {
659232809Sjmallett            tmp = 0;
660232809Sjmallett            tmp = pent->pipe_bpid & ~(~tmp << CVMX_ILK_PIPE_BPID_SZ);
661232809Sjmallett            tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j;
662232809Sjmallett            ilk_txx_mem_cal0.u64 |= tmp;
663232809Sjmallett
664232809Sjmallett            tmp = 0;
665232809Sjmallett            tmp = pent->ent_ctrl & ~(~tmp << CVMX_ILK_ENT_CTRL_SZ);
666232809Sjmallett            tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j +
667232809Sjmallett                    CVMX_ILK_PIPE_BPID_SZ;
668232809Sjmallett            ilk_txx_mem_cal0.u64 |= tmp;
669232809Sjmallett            pent++;
670232809Sjmallett        }
671232809Sjmallett        cvmx_write_csr(CVMX_ILK_TXX_MEM_CAL0(interface), ilk_txx_mem_cal0.u64);
672232809Sjmallett
673232809Sjmallett        ilk_txx_mem_cal1.u64 = 0;
674232809Sjmallett        for (j = 0; j < CVMX_ILK_CAL_GRP_SZ/2; j++)
675232809Sjmallett        {
676232809Sjmallett            tmp = 0;
677232809Sjmallett            tmp = pent->pipe_bpid & ~(~tmp << CVMX_ILK_PIPE_BPID_SZ);
678232809Sjmallett            tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j;
679232809Sjmallett            ilk_txx_mem_cal1.u64 |= tmp;
680232809Sjmallett
681232809Sjmallett            tmp = 0;
682232809Sjmallett            tmp = pent->ent_ctrl & ~(~tmp << CVMX_ILK_ENT_CTRL_SZ);
683232809Sjmallett            tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j +
684232809Sjmallett                    CVMX_ILK_PIPE_BPID_SZ;
685232809Sjmallett            ilk_txx_mem_cal1.u64 |= tmp;
686232809Sjmallett            pent++;
687232809Sjmallett        }
688232809Sjmallett        cvmx_write_csr(CVMX_ILK_TXX_MEM_CAL1(interface), ilk_txx_mem_cal1.u64);
689232809Sjmallett    }
690232809Sjmallett    cvmx_read_csr (CVMX_ILK_TXX_MEM_CAL1(interface));
691232809Sjmallett
692232809Sjmallett    return 0;
693232809Sjmallett}
694232809Sjmallett
695232812Sjmallett#ifdef CVMX_ILK_BP_CONF_ENA
696232809Sjmallett/**
697232809Sjmallett * configure backpressure for tx
698232809Sjmallett *
699232809Sjmallett * @param interface The identifier of the packet interface to configure and
700232809Sjmallett *                  use as a ILK interface. cn68xx has 2 interfaces: ilk0 and
701232809Sjmallett *                  ilk1.
702232809Sjmallett *
703232809Sjmallett * @param cal_depth the number of calendar entries
704232809Sjmallett * @param pent      pointer to calendar entries
705232809Sjmallett *
706232809Sjmallett * @return Zero on success, negative of failure.
707232809Sjmallett */
708232812Sjmallettstatic int cvmx_ilk_bp_conf (int interface, int cal_depth, cvmx_ilk_cal_entry_t *pent)
709232809Sjmallett{
710232809Sjmallett    int res = -1, i;
711232809Sjmallett    cvmx_ipd_ctl_status_t ipd_ctl_status;
712232809Sjmallett    cvmx_ilk_cal_entry_t *tmp;
713232809Sjmallett    unsigned char bpid;
714232809Sjmallett    cvmx_ipd_bpidx_mbuf_th_t ipd_bpidx_mbuf_th;
715232809Sjmallett
716232809Sjmallett    /* enable bp for the interface */
717232809Sjmallett    ipd_ctl_status.u64 = cvmx_read_csr (CVMX_IPD_CTL_STATUS);
718232809Sjmallett    ipd_ctl_status.s.pbp_en = 1;
719232809Sjmallett    cvmx_write_csr (CVMX_IPD_CTL_STATUS, ipd_ctl_status.u64);
720232809Sjmallett
721232809Sjmallett    /* enable bp for each id */
722232809Sjmallett    for (i = 0, tmp = pent; i < cal_depth; i++, tmp++)
723232809Sjmallett    {
724232809Sjmallett        bpid = tmp->pipe_bpid;
725232809Sjmallett        ipd_bpidx_mbuf_th.u64 =
726232809Sjmallett            cvmx_read_csr (CVMX_IPD_BPIDX_MBUF_TH(bpid));
727232809Sjmallett        ipd_bpidx_mbuf_th.s.page_cnt = 1; /* 256 buffers */
728232809Sjmallett        ipd_bpidx_mbuf_th.s.bp_enb = 1;
729232809Sjmallett        cvmx_write_csr (CVMX_IPD_BPIDX_MBUF_TH(bpid), ipd_bpidx_mbuf_th.u64);
730232809Sjmallett    }
731232809Sjmallett    res = 0;
732232809Sjmallett
733232809Sjmallett    return res;
734232809Sjmallett}
735232812Sjmallett#endif
736232809Sjmallett
737232809Sjmallett/**
738232809Sjmallett * enable calendar for tx
739232809Sjmallett *
740232809Sjmallett * @param interface The identifier of the packet interface to configure and
741232809Sjmallett *                  use as a ILK interface. cn68xx has 2 interfaces: ilk0 and
742232809Sjmallett *                  ilk1.
743232809Sjmallett *
744232809Sjmallett * @param cal_ena   enable or disable calendar
745232809Sjmallett *
746232809Sjmallett * @return Zero on success, negative of failure.
747232809Sjmallett */
748232812Sjmallettstatic int cvmx_ilk_tx_cal_ena (int interface, unsigned char cal_ena)
749232809Sjmallett{
750232809Sjmallett    int res = -1;
751232809Sjmallett    cvmx_ilk_txx_cfg0_t ilk_txx_cfg0;
752232809Sjmallett
753232809Sjmallett    if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
754232809Sjmallett        return res;
755232809Sjmallett
756232809Sjmallett    if (interface >= CVMX_NUM_ILK_INTF)
757232809Sjmallett        return res;
758232809Sjmallett
759232809Sjmallett    /* set the enable */
760232809Sjmallett    ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface));
761232809Sjmallett    ilk_txx_cfg0.s.cal_ena = cal_ena;
762232809Sjmallett    cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64);
763232809Sjmallett    cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface));
764232809Sjmallett    res = 0;
765232809Sjmallett
766232809Sjmallett    return res;
767232809Sjmallett}
768232809Sjmallett
769232809Sjmallett/**
770232809Sjmallett * set up calendar for tx
771232809Sjmallett *
772232809Sjmallett * @param interface The identifier of the packet interface to configure and
773232809Sjmallett *                  use as a ILK interface. cn68xx has 2 interfaces: ilk0 and
774232809Sjmallett *                  ilk1.
775232809Sjmallett *
776232809Sjmallett * @param cal_depth the number of calendar entries
777232809Sjmallett * @param pent      pointer to calendar entries
778232809Sjmallett * @param cal_ena   enable or disable calendar
779232809Sjmallett *
780232809Sjmallett * @return Zero on success, negative of failure.
781232809Sjmallett */
782232809Sjmallettint cvmx_ilk_cal_setup_tx (int interface, int cal_depth,
783232809Sjmallett                           cvmx_ilk_cal_entry_t *pent, unsigned char cal_ena)
784232809Sjmallett{
785232809Sjmallett    int res = -1;
786232809Sjmallett
787232809Sjmallett    if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
788232809Sjmallett        return res;
789232809Sjmallett
790232809Sjmallett    if (interface >= CVMX_NUM_ILK_INTF)
791232809Sjmallett        return res;
792232809Sjmallett
793232809Sjmallett    res = cvmx_ilk_tx_cal_conf (interface, cal_depth, pent);
794232809Sjmallett    if (res < 0)
795232809Sjmallett        return res;
796232809Sjmallett
797232809Sjmallett#ifdef CVMX_ILK_BP_CONF_ENA
798232809Sjmallett    res = cvmx_ilk_bp_conf (interface, cal_depth, pent);
799232809Sjmallett    if (res < 0)
800232809Sjmallett        return res;
801232809Sjmallett#endif
802232809Sjmallett
803232809Sjmallett    res = cvmx_ilk_tx_cal_ena (interface, cal_ena);
804232809Sjmallett    return res;
805232809Sjmallett}
806232809Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL
807232809SjmallettEXPORT_SYMBOL(cvmx_ilk_cal_setup_tx);
808232809Sjmallett#endif
809232809Sjmallett
810232809Sjmallett#ifdef CVMX_ILK_STATS_ENA
811232809Sjmallettstatic void cvmx_ilk_reg_dump_rx (int interface)
812232809Sjmallett{
813232809Sjmallett    int i;
814232809Sjmallett    cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0;
815232809Sjmallett    cvmx_ilk_rxx_cfg1_t ilk_rxx_cfg1;
816232809Sjmallett    cvmx_ilk_rxx_int_t ilk_rxx_int;
817232809Sjmallett    cvmx_ilk_rxx_jabber_t ilk_rxx_jabber;
818232809Sjmallett    cvmx_ilk_rx_lnex_cfg_t ilk_rx_lnex_cfg;
819232809Sjmallett    cvmx_ilk_rx_lnex_int_t ilk_rx_lnex_int;
820232809Sjmallett    cvmx_ilk_gbl_cfg_t ilk_gbl_cfg;
821232809Sjmallett    cvmx_ilk_ser_cfg_t ilk_ser_cfg;
822232809Sjmallett    cvmx_ilk_rxf_idx_pmap_t ilk_rxf_idx_pmap;
823232809Sjmallett    cvmx_ilk_rxf_mem_pmap_t ilk_rxf_mem_pmap;
824232809Sjmallett    cvmx_ilk_rxx_idx_cal_t ilk_rxx_idx_cal;
825232809Sjmallett    cvmx_ilk_rxx_mem_cal0_t ilk_rxx_mem_cal0;
826232809Sjmallett    cvmx_ilk_rxx_mem_cal1_t ilk_rxx_mem_cal1;
827232809Sjmallett
828232809Sjmallett    ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface));
829232809Sjmallett    cvmx_dprintf ("ilk rxx cfg0: 0x%16lx\n", ilk_rxx_cfg0.u64);
830232809Sjmallett
831232809Sjmallett    ilk_rxx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG1(interface));
832232809Sjmallett    cvmx_dprintf ("ilk rxx cfg1: 0x%16lx\n", ilk_rxx_cfg1.u64);
833232809Sjmallett
834232809Sjmallett    ilk_rxx_int.u64 = cvmx_read_csr (CVMX_ILK_RXX_INT(interface));
835232809Sjmallett    cvmx_dprintf ("ilk rxx int: 0x%16lx\n", ilk_rxx_int.u64);
836232809Sjmallett    cvmx_write_csr (CVMX_ILK_RXX_INT(interface), ilk_rxx_int.u64);
837232809Sjmallett
838232809Sjmallett    ilk_rxx_jabber.u64 = cvmx_read_csr (CVMX_ILK_RXX_JABBER(interface));
839232809Sjmallett    cvmx_dprintf ("ilk rxx jabber: 0x%16lx\n", ilk_rxx_jabber.u64);
840232809Sjmallett
841232809Sjmallett#define LNE_NUM_DBG 4
842232809Sjmallett    for (i = 0; i < LNE_NUM_DBG; i++)
843232809Sjmallett    {
844232809Sjmallett        ilk_rx_lnex_cfg.u64 = cvmx_read_csr (CVMX_ILK_RX_LNEX_CFG(i));
845232809Sjmallett        cvmx_dprintf ("ilk rx lnex cfg lane: %d  0x%16lx\n", i,
846232809Sjmallett                      ilk_rx_lnex_cfg.u64);
847232809Sjmallett    }
848232809Sjmallett
849232809Sjmallett    for (i = 0; i < LNE_NUM_DBG; i++)
850232809Sjmallett    {
851232809Sjmallett        ilk_rx_lnex_int.u64 = cvmx_read_csr (CVMX_ILK_RX_LNEX_INT(i));
852232809Sjmallett        cvmx_dprintf ("ilk rx lnex int lane: %d  0x%16lx\n", i,
853232809Sjmallett                      ilk_rx_lnex_int.u64);
854232809Sjmallett        cvmx_write_csr (CVMX_ILK_RX_LNEX_INT(i), ilk_rx_lnex_int.u64);
855232809Sjmallett    }
856232809Sjmallett
857232809Sjmallett    ilk_gbl_cfg.u64 = cvmx_read_csr (CVMX_ILK_GBL_CFG);
858232809Sjmallett    cvmx_dprintf ("ilk gbl cfg: 0x%16lx\n", ilk_gbl_cfg.u64);
859232809Sjmallett
860232809Sjmallett    ilk_ser_cfg.u64 = cvmx_read_csr (CVMX_ILK_SER_CFG);
861232809Sjmallett    cvmx_dprintf ("ilk ser cfg: 0x%16lx\n", ilk_ser_cfg.u64);
862232809Sjmallett
863232809Sjmallett#define CHAN_NUM_DBG 8
864232809Sjmallett    ilk_rxf_idx_pmap.u64 = 0;
865232809Sjmallett    ilk_rxf_idx_pmap.s.index = interface * 256;
866232809Sjmallett    ilk_rxf_idx_pmap.s.inc = 1;
867232809Sjmallett    cvmx_write_csr (CVMX_ILK_RXF_IDX_PMAP, ilk_rxf_idx_pmap.u64);
868232809Sjmallett    for (i = 0; i < CHAN_NUM_DBG; i++)
869232809Sjmallett    {
870232809Sjmallett        ilk_rxf_mem_pmap.u64 = cvmx_read_csr (CVMX_ILK_RXF_MEM_PMAP);
871232809Sjmallett        cvmx_dprintf ("ilk rxf mem pmap chan: %3d  0x%16lx\n", i,
872232809Sjmallett                      ilk_rxf_mem_pmap.u64);
873232809Sjmallett    }
874232809Sjmallett
875232809Sjmallett#define CAL_NUM_DBG 2
876232809Sjmallett    ilk_rxx_idx_cal.u64 = 0;
877232809Sjmallett    ilk_rxx_idx_cal.s.inc = 1;
878232809Sjmallett    cvmx_write_csr (CVMX_ILK_RXX_IDX_CAL(interface), ilk_rxx_idx_cal.u64);
879232809Sjmallett    for (i = 0; i < CAL_NUM_DBG; i++)
880232809Sjmallett    {
881232809Sjmallett        ilk_rxx_idx_cal.u64 = cvmx_read_csr(CVMX_ILK_RXX_IDX_CAL(interface));
882232809Sjmallett        cvmx_dprintf ("ilk rxx idx cal: 0x%16lx\n", ilk_rxx_idx_cal.u64);
883232809Sjmallett
884232809Sjmallett        ilk_rxx_mem_cal0.u64 = cvmx_read_csr(CVMX_ILK_RXX_MEM_CAL0(interface));
885232809Sjmallett        cvmx_dprintf ("ilk rxx mem cal0: 0x%16lx\n", ilk_rxx_mem_cal0.u64);
886232809Sjmallett        ilk_rxx_mem_cal1.u64 = cvmx_read_csr(CVMX_ILK_RXX_MEM_CAL1(interface));
887232809Sjmallett        cvmx_dprintf ("ilk rxx mem cal1: 0x%16lx\n", ilk_rxx_mem_cal1.u64);
888232809Sjmallett    }
889232809Sjmallett}
890232809Sjmallett
891232809Sjmallettstatic void cvmx_ilk_reg_dump_tx (int interface)
892232809Sjmallett{
893232809Sjmallett    int i;
894232809Sjmallett    cvmx_ilk_txx_cfg0_t ilk_txx_cfg0;
895232809Sjmallett    cvmx_ilk_txx_cfg1_t ilk_txx_cfg1;
896232809Sjmallett    cvmx_ilk_txx_idx_pmap_t ilk_txx_idx_pmap;
897232809Sjmallett    cvmx_ilk_txx_mem_pmap_t ilk_txx_mem_pmap;
898232809Sjmallett    cvmx_ilk_txx_int_t ilk_txx_int;
899232809Sjmallett    cvmx_ilk_txx_pipe_t ilk_txx_pipe;
900232809Sjmallett    cvmx_ilk_txx_idx_cal_t ilk_txx_idx_cal;
901232809Sjmallett    cvmx_ilk_txx_mem_cal0_t ilk_txx_mem_cal0;
902232809Sjmallett    cvmx_ilk_txx_mem_cal1_t ilk_txx_mem_cal1;
903232809Sjmallett
904232809Sjmallett    ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface));
905232809Sjmallett    cvmx_dprintf ("ilk txx cfg0: 0x%16lx\n", ilk_txx_cfg0.u64);
906232809Sjmallett
907232809Sjmallett    ilk_txx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG1(interface));
908232809Sjmallett    cvmx_dprintf ("ilk txx cfg1: 0x%16lx\n", ilk_txx_cfg1.u64);
909232809Sjmallett
910232809Sjmallett    ilk_txx_pipe.u64 = cvmx_read_csr (CVMX_ILK_TXX_PIPE(interface));
911232809Sjmallett    cvmx_dprintf ("ilk txx pipe: 0x%16lx\n", ilk_txx_pipe.u64);
912232809Sjmallett
913232809Sjmallett    ilk_txx_idx_pmap.u64 = 0;
914232809Sjmallett    ilk_txx_idx_pmap.s.index = ilk_txx_pipe.s.base;
915232809Sjmallett    ilk_txx_idx_pmap.s.inc = 1;
916232809Sjmallett    cvmx_write_csr (CVMX_ILK_TXX_IDX_PMAP(interface), ilk_txx_idx_pmap.u64);
917232809Sjmallett    for (i = 0; i < CHAN_NUM_DBG; i++)
918232809Sjmallett    {
919232809Sjmallett        ilk_txx_mem_pmap.u64 = cvmx_read_csr (CVMX_ILK_TXX_MEM_PMAP(interface));
920232809Sjmallett        cvmx_dprintf ("ilk txx mem pmap pipe: %3d  0x%16lx\n",
921232809Sjmallett                      ilk_txx_pipe.s.base + i, ilk_txx_mem_pmap.u64);
922232809Sjmallett    }
923232809Sjmallett
924232809Sjmallett    ilk_txx_int.u64 = cvmx_read_csr (CVMX_ILK_TXX_INT(interface));
925232809Sjmallett    cvmx_dprintf ("ilk txx int: 0x%16lx\n", ilk_txx_int.u64);
926232809Sjmallett
927232809Sjmallett    ilk_txx_idx_cal.u64 = 0;
928232809Sjmallett    ilk_txx_idx_cal.s.inc = 1;
929232809Sjmallett    cvmx_write_csr (CVMX_ILK_TXX_IDX_CAL(interface), ilk_txx_idx_cal.u64);
930232809Sjmallett    for (i = 0; i < CAL_NUM_DBG; i++)
931232809Sjmallett    {
932232809Sjmallett        ilk_txx_idx_cal.u64 = cvmx_read_csr(CVMX_ILK_TXX_IDX_CAL(interface));
933232809Sjmallett        cvmx_dprintf ("ilk txx idx cal: 0x%16lx\n", ilk_txx_idx_cal.u64);
934232809Sjmallett
935232809Sjmallett        ilk_txx_mem_cal0.u64 = cvmx_read_csr(CVMX_ILK_TXX_MEM_CAL0(interface));
936232809Sjmallett        cvmx_dprintf ("ilk txx mem cal0: 0x%16lx\n", ilk_txx_mem_cal0.u64);
937232809Sjmallett        ilk_txx_mem_cal1.u64 = cvmx_read_csr(CVMX_ILK_TXX_MEM_CAL1(interface));
938232809Sjmallett        cvmx_dprintf ("ilk txx mem cal1: 0x%16lx\n", ilk_txx_mem_cal1.u64);
939232809Sjmallett    }
940232809Sjmallett}
941232809Sjmallett#endif
942232809Sjmallett
943232809Sjmallett/**
944232809Sjmallett * show run time status
945232809Sjmallett *
946232809Sjmallett * @param interface The identifier of the packet interface to enable. cn68xx
947232809Sjmallett *                  has 2 interfaces: ilk0 and ilk1.
948232809Sjmallett *
949232809Sjmallett * @return nothing
950232809Sjmallett */
951232809Sjmallett#ifdef CVMX_ILK_RUNTIME_DBG
952232809Sjmallettvoid cvmx_ilk_runtime_status (int interface)
953232809Sjmallett{
954232809Sjmallett    cvmx_ilk_txx_cfg1_t ilk_txx_cfg1;
955232809Sjmallett    cvmx_ilk_txx_flow_ctl0_t ilk_txx_flow_ctl0;
956232809Sjmallett    cvmx_ilk_rxx_cfg1_t ilk_rxx_cfg1;
957232809Sjmallett    cvmx_ilk_rxx_int_t ilk_rxx_int;
958232809Sjmallett    cvmx_ilk_rxx_flow_ctl0_t ilk_rxx_flow_ctl0;
959232809Sjmallett    cvmx_ilk_rxx_flow_ctl1_t ilk_rxx_flow_ctl1;
960232809Sjmallett    cvmx_ilk_gbl_int_t ilk_gbl_int;
961232809Sjmallett
962232809Sjmallett    cvmx_dprintf ("\nilk run-time status: interface: %d\n", interface);
963232809Sjmallett
964232809Sjmallett    ilk_txx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG1(interface));
965232809Sjmallett    cvmx_dprintf ("\nilk txx cfg1: 0x%16lx\n", ilk_txx_cfg1.u64);
966232809Sjmallett    if (ilk_txx_cfg1.s.rx_link_fc)
967232809Sjmallett        cvmx_dprintf ("link flow control received\n");
968232809Sjmallett    if (ilk_txx_cfg1.s.tx_link_fc)
969232809Sjmallett        cvmx_dprintf ("link flow control sent\n");
970232809Sjmallett
971232809Sjmallett    ilk_txx_flow_ctl0.u64 = cvmx_read_csr (CVMX_ILK_TXX_FLOW_CTL0(interface));
972232809Sjmallett    cvmx_dprintf ("\nilk txx flow ctl0: 0x%16lx\n", ilk_txx_flow_ctl0.u64);
973232809Sjmallett
974232809Sjmallett    ilk_rxx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG1(interface));
975232809Sjmallett    cvmx_dprintf ("\nilk rxx cfg1: 0x%16lx\n", ilk_rxx_cfg1.u64);
976232809Sjmallett    cvmx_dprintf ("rx fifo count: %d\n", ilk_rxx_cfg1.s.rx_fifo_cnt);
977232809Sjmallett
978232809Sjmallett    ilk_rxx_int.u64 = cvmx_read_csr (CVMX_ILK_RXX_INT(interface));
979232809Sjmallett    cvmx_dprintf ("\nilk rxx int: 0x%16lx\n", ilk_rxx_int.u64);
980232809Sjmallett    if (ilk_rxx_int.s.pkt_drop_rxf)
981232809Sjmallett        cvmx_dprintf ("rx fifo packet drop\n");
982232809Sjmallett    if (ilk_rxx_int.u64)
983232809Sjmallett        cvmx_write_csr (CVMX_ILK_RXX_INT(interface), ilk_rxx_int.u64);
984232809Sjmallett
985232809Sjmallett    ilk_rxx_flow_ctl0.u64 = cvmx_read_csr (CVMX_ILK_RXX_FLOW_CTL0(interface));
986232809Sjmallett    cvmx_dprintf ("\nilk rxx flow ctl0: 0x%16lx\n", ilk_rxx_flow_ctl0.u64);
987232809Sjmallett
988232809Sjmallett    ilk_rxx_flow_ctl1.u64 = cvmx_read_csr (CVMX_ILK_RXX_FLOW_CTL1(interface));
989232809Sjmallett    cvmx_dprintf ("\nilk rxx flow ctl1: 0x%16lx\n", ilk_rxx_flow_ctl1.u64);
990232809Sjmallett
991232809Sjmallett    ilk_gbl_int.u64 = cvmx_read_csr (CVMX_ILK_GBL_INT);
992232809Sjmallett    cvmx_dprintf ("\nilk gbl int: 0x%16lx\n", ilk_gbl_int.u64);
993232809Sjmallett    if (ilk_gbl_int.s.rxf_push_full)
994232809Sjmallett        cvmx_dprintf ("rx fifo overflow\n");
995232809Sjmallett    if (ilk_gbl_int.u64)
996232809Sjmallett        cvmx_write_csr (CVMX_ILK_GBL_INT, ilk_gbl_int.u64);
997232809Sjmallett}
998232809Sjmallett#endif
999232809Sjmallett
1000232809Sjmallett/**
1001232809Sjmallett * enable interface
1002232809Sjmallett *
1003232809Sjmallett * @param interface The identifier of the packet interface to enable. cn68xx
1004232809Sjmallett *                  has 2 interfaces: ilk0 and ilk1.
1005232809Sjmallett *
1006232809Sjmallett * @return Zero on success, negative of failure.
1007232809Sjmallett */
1008232809Sjmallett//#define CVMX_ILK_STATS_ENA 1
1009232809Sjmallettint cvmx_ilk_enable (int interface)
1010232809Sjmallett{
1011232809Sjmallett    int res = -1;
1012232809Sjmallett    int retry_count = 0;
1013232809Sjmallett    cvmx_helper_link_info_t result;
1014232809Sjmallett    cvmx_ilk_txx_cfg1_t ilk_txx_cfg1;
1015232809Sjmallett    cvmx_ilk_rxx_cfg1_t ilk_rxx_cfg1;
1016232809Sjmallett#ifdef CVMX_ILK_STATS_ENA
1017232809Sjmallett    cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0;
1018232809Sjmallett    cvmx_ilk_txx_cfg0_t ilk_txx_cfg0;
1019232809Sjmallett#endif
1020232809Sjmallett
1021232809Sjmallett    if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
1022232809Sjmallett        return res;
1023232809Sjmallett
1024232809Sjmallett    if (interface >= CVMX_NUM_ILK_INTF)
1025232809Sjmallett        return res;
1026232809Sjmallett
1027232809Sjmallett    result.u64 = 0;
1028232809Sjmallett
1029232809Sjmallett#ifdef CVMX_ILK_STATS_ENA
1030232809Sjmallett    cvmx_dprintf ("\n");
1031232809Sjmallett    cvmx_dprintf ("<<<< ILK%d: Before enabling ilk\n", interface);
1032232809Sjmallett    cvmx_ilk_reg_dump_rx (interface);
1033232809Sjmallett    cvmx_ilk_reg_dump_tx (interface);
1034232809Sjmallett#endif
1035232809Sjmallett
1036232809Sjmallett    /* RX packet will be enabled only if link is up */
1037232809Sjmallett
1038232809Sjmallett    /* TX side */
1039232809Sjmallett    ilk_txx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG1(interface));
1040232809Sjmallett    ilk_txx_cfg1.s.pkt_ena = 1;
1041232809Sjmallett    ilk_txx_cfg1.s.rx_link_fc_ign = 1; /* cannot use link fc workaround */
1042232809Sjmallett    cvmx_write_csr (CVMX_ILK_TXX_CFG1(interface), ilk_txx_cfg1.u64);
1043232809Sjmallett    cvmx_read_csr (CVMX_ILK_TXX_CFG1(interface));
1044232809Sjmallett
1045232809Sjmallett#ifdef CVMX_ILK_STATS_ENA
1046232809Sjmallett    /* RX side stats */
1047232809Sjmallett    ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface));
1048232809Sjmallett    ilk_rxx_cfg0.s.lnk_stats_ena = 1;
1049232809Sjmallett    cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64);
1050232809Sjmallett
1051232809Sjmallett    /* TX side stats */
1052232809Sjmallett    ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface));
1053232809Sjmallett    ilk_txx_cfg0.s.lnk_stats_ena = 1;
1054232809Sjmallett    cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64);
1055232809Sjmallett#endif
1056232809Sjmallett
1057232809Sjmallettretry:
1058232809Sjmallett    retry_count++;
1059232809Sjmallett    if (retry_count > 10)
1060232809Sjmallett       goto out;
1061232809Sjmallett
1062232809Sjmallett    /* Make sure the link is up, so that packets can be sent. */
1063232809Sjmallett    result = __cvmx_helper_ilk_link_get(cvmx_helper_get_ipd_port(interface + CVMX_ILK_GBL_BASE, 0));
1064232809Sjmallett
1065232809Sjmallett    /* Small delay before another retry. */
1066232809Sjmallett    cvmx_wait_usec(100);
1067232809Sjmallett
1068232809Sjmallett    ilk_rxx_cfg1.u64 = cvmx_read_csr(CVMX_ILK_RXX_CFG1(interface));
1069232809Sjmallett    if (ilk_rxx_cfg1.s.pkt_ena == 0)
1070232809Sjmallett       goto retry;
1071232809Sjmallett
1072232809Sjmallettout:
1073232809Sjmallett
1074232809Sjmallett#ifdef CVMX_ILK_STATS_ENA
1075232809Sjmallett    cvmx_dprintf (">>>> ILK%d: After ILK is enabled\n", interface);
1076232809Sjmallett    cvmx_ilk_reg_dump_rx (interface);
1077232809Sjmallett    cvmx_ilk_reg_dump_tx (interface);
1078232809Sjmallett#endif
1079232809Sjmallett
1080232809Sjmallett    if (result.s.link_up)
1081232809Sjmallett        return 0;
1082232809Sjmallett
1083232809Sjmallett    return -1;
1084232809Sjmallett}
1085232809Sjmallett
1086232809Sjmallett/**
1087232809Sjmallett * Disable interface
1088232809Sjmallett *
1089232809Sjmallett * @param interface The identifier of the packet interface to disable. cn68xx
1090232809Sjmallett *                  has 2 interfaces: ilk0 and ilk1.
1091232809Sjmallett *
1092232809Sjmallett * @return Zero on success, negative of failure.
1093232809Sjmallett */
1094232809Sjmallettint cvmx_ilk_disable (int interface)
1095232809Sjmallett{
1096232809Sjmallett    int res = -1;
1097232809Sjmallett    cvmx_ilk_txx_cfg1_t ilk_txx_cfg1;
1098232809Sjmallett    cvmx_ilk_rxx_cfg1_t ilk_rxx_cfg1;
1099232809Sjmallett#ifdef CVMX_ILK_STATS_ENA
1100232809Sjmallett    cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0;
1101232809Sjmallett    cvmx_ilk_txx_cfg0_t ilk_txx_cfg0;
1102232809Sjmallett#endif
1103232809Sjmallett
1104232809Sjmallett    if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
1105232809Sjmallett        return res;
1106232809Sjmallett
1107232809Sjmallett    if (interface >= CVMX_NUM_ILK_INTF)
1108232809Sjmallett        return res;
1109232809Sjmallett
1110232809Sjmallett    /* TX side */
1111232809Sjmallett    ilk_txx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG1(interface));
1112232809Sjmallett    ilk_txx_cfg1.s.pkt_ena = 0;
1113232809Sjmallett    cvmx_write_csr (CVMX_ILK_TXX_CFG1(interface), ilk_txx_cfg1.u64);
1114232809Sjmallett
1115232809Sjmallett    /* RX side */
1116232809Sjmallett    ilk_rxx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG1(interface));
1117232809Sjmallett    ilk_rxx_cfg1.s.pkt_ena = 0;
1118232809Sjmallett    cvmx_write_csr (CVMX_ILK_RXX_CFG1(interface), ilk_rxx_cfg1.u64);
1119232809Sjmallett
1120232809Sjmallett#ifdef CVMX_ILK_STATS_ENA
1121232809Sjmallett    /* RX side stats */
1122232809Sjmallett    ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface));
1123232809Sjmallett    ilk_rxx_cfg0.s.lnk_stats_ena = 0;
1124232809Sjmallett    cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64);
1125232809Sjmallett
1126232809Sjmallett    /* RX side stats */
1127232809Sjmallett    ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface));
1128232809Sjmallett    ilk_txx_cfg0.s.lnk_stats_ena = 0;
1129232809Sjmallett    cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64);
1130232809Sjmallett#endif
1131232809Sjmallett
1132232809Sjmallett    return 0;
1133232809Sjmallett}
1134232809Sjmallett
1135232809Sjmallett/**
1136232809Sjmallett * Provide interface enable status
1137232809Sjmallett *
1138232809Sjmallett * @param interface The identifier of the packet interface to disable. cn68xx
1139232809Sjmallett *                  has 2 interfaces: ilk0 and ilk1.
1140232809Sjmallett *
1141232809Sjmallett * @return Zero, not enabled; One, enabled.
1142232809Sjmallett */
1143232809Sjmallettint cvmx_ilk_get_intf_ena (int interface)
1144232809Sjmallett{
1145232809Sjmallett    return cvmx_ilk_intf_cfg[interface].intf_en;
1146232809Sjmallett}
1147232809Sjmallett
1148232809Sjmallett/**
1149232809Sjmallett * bit counter
1150232809Sjmallett *
1151232809Sjmallett * @param uc the byte to be counted
1152232809Sjmallett *
1153232809Sjmallett * @return number of bits set
1154232809Sjmallett */
1155232809Sjmallettunsigned char cvmx_ilk_bit_count (unsigned char uc)
1156232809Sjmallett{
1157232809Sjmallett    unsigned char count;
1158232809Sjmallett
1159232809Sjmallett    for (count = 0; uc > 0; uc &= uc-1)
1160232809Sjmallett        count++;
1161232809Sjmallett
1162232809Sjmallett    return count;
1163232809Sjmallett}
1164232809Sjmallett
1165232809Sjmallett/**
1166232809Sjmallett * Provide interface lane mask
1167232809Sjmallett *
1168232809Sjmallett * @param interface The identifier of the packet interface to disable. cn68xx
1169232809Sjmallett *                  has 2 interfaces: ilk0 and ilk1.
1170232809Sjmallett *
1171232809Sjmallett * @return lane mask
1172232809Sjmallett */
1173232809Sjmallettunsigned char cvmx_ilk_get_intf_ln_msk (int interface)
1174232809Sjmallett{
1175232809Sjmallett    return cvmx_ilk_intf_cfg[interface].lane_en_mask;
1176232809Sjmallett}
1177232809Sjmallett
1178232809Sjmallett/**
1179232809Sjmallett * Provide channel info
1180232809Sjmallett *
1181232809Sjmallett * @param interface The identifier of the packet interface to disable. cn68xx
1182232809Sjmallett *                  has 2 interfaces: ilk0 and ilk1.
1183232809Sjmallett * @param chans    A pointer to a channel array
1184232809Sjmallett * @param num_chan A pointer to the number of channels
1185232809Sjmallett *
1186232809Sjmallett * @return Zero on success, negative of failure.
1187232809Sjmallett */
1188232809Sjmallettint cvmx_ilk_get_chan_info (int interface, unsigned char **chans,
1189232809Sjmallett                            unsigned char *num_chan)
1190232809Sjmallett{
1191232809Sjmallett    *chans = cvmx_ilk_chan_map[interface];
1192232809Sjmallett    *num_chan = cvmx_ilk_chans[interface];
1193232809Sjmallett
1194232809Sjmallett    return 0;
1195232809Sjmallett}
1196232809Sjmallett
1197232809Sjmallett/**
1198232809Sjmallett * Show channel statistics
1199232809Sjmallett *
1200232809Sjmallett * @param interface The identifier of the packet interface to disable. cn68xx
1201232809Sjmallett *                  has 2 interfaces: ilk0 and ilk1.
1202232809Sjmallett * @param pstats A pointer to cvmx_ilk_stats_ctrl_t that specifies which
1203232809Sjmallett *               logical channels to access
1204232809Sjmallett *
1205232809Sjmallett * @return nothing
1206232809Sjmallett */
1207232809Sjmallettvoid cvmx_ilk_show_stats (int interface, cvmx_ilk_stats_ctrl_t *pstats)
1208232809Sjmallett{
1209232809Sjmallett    unsigned int i;
1210232809Sjmallett    cvmx_ilk_rxx_idx_stat0_t ilk_rxx_idx_stat0;
1211232809Sjmallett    cvmx_ilk_rxx_idx_stat1_t ilk_rxx_idx_stat1;
1212232809Sjmallett    cvmx_ilk_rxx_mem_stat0_t ilk_rxx_mem_stat0;
1213232809Sjmallett    cvmx_ilk_rxx_mem_stat1_t ilk_rxx_mem_stat1;
1214232809Sjmallett
1215232809Sjmallett    cvmx_ilk_txx_idx_stat0_t ilk_txx_idx_stat0;
1216232809Sjmallett    cvmx_ilk_txx_idx_stat1_t ilk_txx_idx_stat1;
1217232809Sjmallett    cvmx_ilk_txx_mem_stat0_t ilk_txx_mem_stat0;
1218232809Sjmallett    cvmx_ilk_txx_mem_stat1_t ilk_txx_mem_stat1;
1219232809Sjmallett
1220232809Sjmallett    if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
1221232809Sjmallett        return;
1222232809Sjmallett
1223232809Sjmallett    if (interface >= CVMX_NUM_ILK_INTF)
1224232809Sjmallett        return;
1225232809Sjmallett
1226232809Sjmallett    if (pstats == NULL)
1227232809Sjmallett        return;
1228232809Sjmallett
1229232809Sjmallett    /* discrete channels */
1230232809Sjmallett    if (pstats->chan_list != NULL)
1231232809Sjmallett    {
1232232809Sjmallett        for (i = 0; i < pstats->num_chans; i++)
1233232809Sjmallett        {
1234232809Sjmallett
1235232809Sjmallett            /* get the number of rx packets */
1236232809Sjmallett            ilk_rxx_idx_stat0.u64 = 0;
1237232809Sjmallett            ilk_rxx_idx_stat0.s.index = *pstats->chan_list;
1238232809Sjmallett            ilk_rxx_idx_stat0.s.clr = pstats->clr_on_rd;
1239232809Sjmallett            cvmx_write_csr (CVMX_ILK_RXX_IDX_STAT0(interface),
1240232809Sjmallett                            ilk_rxx_idx_stat0.u64);
1241232809Sjmallett            ilk_rxx_mem_stat0.u64 = cvmx_read_csr
1242232809Sjmallett                                    (CVMX_ILK_RXX_MEM_STAT0(interface));
1243232809Sjmallett
1244232809Sjmallett            /* get the number of rx bytes */
1245232809Sjmallett            ilk_rxx_idx_stat1.u64 = 0;
1246232809Sjmallett            ilk_rxx_idx_stat1.s.index = *pstats->chan_list;
1247232809Sjmallett            ilk_rxx_idx_stat1.s.clr = pstats->clr_on_rd;
1248232809Sjmallett            cvmx_write_csr (CVMX_ILK_RXX_IDX_STAT1(interface),
1249232809Sjmallett                            ilk_rxx_idx_stat1.u64);
1250232809Sjmallett            ilk_rxx_mem_stat1.u64 = cvmx_read_csr
1251232809Sjmallett                                    (CVMX_ILK_RXX_MEM_STAT1(interface));
1252232809Sjmallett
1253232809Sjmallett            cvmx_dprintf ("ILK%d Channel%d Rx: %d packets %d bytes\n", interface,
1254232809Sjmallett                    *pstats->chan_list, ilk_rxx_mem_stat0.s.rx_pkt,
1255232809Sjmallett                    (unsigned int) ilk_rxx_mem_stat1.s.rx_bytes);
1256232809Sjmallett
1257232809Sjmallett            /* get the number of tx packets */
1258232809Sjmallett            ilk_txx_idx_stat0.u64 = 0;
1259232809Sjmallett            ilk_txx_idx_stat0.s.index = *pstats->chan_list;
1260232809Sjmallett            ilk_txx_idx_stat0.s.clr = pstats->clr_on_rd;
1261232809Sjmallett            cvmx_write_csr (CVMX_ILK_TXX_IDX_STAT0(interface),
1262232809Sjmallett                            ilk_txx_idx_stat0.u64);
1263232809Sjmallett            ilk_txx_mem_stat0.u64 = cvmx_read_csr
1264232809Sjmallett                                    (CVMX_ILK_TXX_MEM_STAT0(interface));
1265232809Sjmallett
1266232809Sjmallett            /* get the number of tx bytes */
1267232809Sjmallett            ilk_txx_idx_stat1.u64 = 0;
1268232809Sjmallett            ilk_txx_idx_stat1.s.index = *pstats->chan_list;
1269232809Sjmallett            ilk_txx_idx_stat1.s.clr = pstats->clr_on_rd;
1270232809Sjmallett            cvmx_write_csr (CVMX_ILK_TXX_IDX_STAT1(interface),
1271232809Sjmallett                            ilk_txx_idx_stat1.u64);
1272232809Sjmallett            ilk_txx_mem_stat1.u64 = cvmx_read_csr
1273232809Sjmallett                                    (CVMX_ILK_TXX_MEM_STAT1(interface));
1274232809Sjmallett
1275232809Sjmallett            cvmx_dprintf ("ILK%d Channel%d Tx: %d packets %d bytes\n", interface,
1276232809Sjmallett                    *pstats->chan_list, ilk_txx_mem_stat0.s.tx_pkt,
1277232809Sjmallett                    (unsigned int) ilk_txx_mem_stat1.s.tx_bytes);
1278232809Sjmallett
1279232809Sjmallett            pstats++;
1280232809Sjmallett        }
1281232809Sjmallett        return;
1282232809Sjmallett    }
1283232809Sjmallett
1284232809Sjmallett    /* continuous channels */
1285232809Sjmallett    ilk_rxx_idx_stat0.u64 = 0;
1286232809Sjmallett    ilk_rxx_idx_stat0.s.index = pstats->chan_start;
1287232809Sjmallett    ilk_rxx_idx_stat0.s.inc = pstats->chan_step;
1288232809Sjmallett    ilk_rxx_idx_stat0.s.clr = pstats->clr_on_rd;
1289232809Sjmallett    cvmx_write_csr (CVMX_ILK_RXX_IDX_STAT0(interface), ilk_rxx_idx_stat0.u64);
1290232809Sjmallett
1291232809Sjmallett    ilk_rxx_idx_stat1.u64 = 0;
1292232809Sjmallett    ilk_rxx_idx_stat1.s.index = pstats->chan_start;
1293232809Sjmallett    ilk_rxx_idx_stat1.s.inc = pstats->chan_step;
1294232809Sjmallett    ilk_rxx_idx_stat1.s.clr = pstats->clr_on_rd;
1295232809Sjmallett    cvmx_write_csr (CVMX_ILK_RXX_IDX_STAT1(interface), ilk_rxx_idx_stat1.u64);
1296232809Sjmallett
1297232809Sjmallett    ilk_txx_idx_stat0.u64 = 0;
1298232809Sjmallett    ilk_txx_idx_stat0.s.index = pstats->chan_start;
1299232809Sjmallett    ilk_txx_idx_stat0.s.inc = pstats->chan_step;
1300232809Sjmallett    ilk_txx_idx_stat0.s.clr = pstats->clr_on_rd;
1301232809Sjmallett    cvmx_write_csr (CVMX_ILK_TXX_IDX_STAT0(interface), ilk_txx_idx_stat0.u64);
1302232809Sjmallett
1303232809Sjmallett    ilk_txx_idx_stat1.u64 = 0;
1304232809Sjmallett    ilk_txx_idx_stat1.s.index = pstats->chan_start;
1305232809Sjmallett    ilk_txx_idx_stat1.s.inc = pstats->chan_step;
1306232809Sjmallett    ilk_txx_idx_stat1.s.clr = pstats->clr_on_rd;
1307232809Sjmallett    cvmx_write_csr (CVMX_ILK_TXX_IDX_STAT1(interface), ilk_txx_idx_stat1.u64);
1308232809Sjmallett
1309232809Sjmallett    for (i = pstats->chan_start; i <= pstats->chan_end; i += pstats->chan_step)
1310232809Sjmallett    {
1311232809Sjmallett        ilk_rxx_mem_stat0.u64 = cvmx_read_csr
1312232809Sjmallett                                (CVMX_ILK_RXX_MEM_STAT0(interface));
1313232809Sjmallett        ilk_rxx_mem_stat1.u64 = cvmx_read_csr
1314232809Sjmallett                                (CVMX_ILK_RXX_MEM_STAT1(interface));
1315232809Sjmallett        cvmx_dprintf ("ILK%d Channel%d Rx: %d packets %d bytes\n", interface, i,
1316232809Sjmallett                ilk_rxx_mem_stat0.s.rx_pkt,
1317232809Sjmallett                (unsigned int) ilk_rxx_mem_stat1.s.rx_bytes);
1318232809Sjmallett
1319232809Sjmallett        ilk_txx_mem_stat0.u64 = cvmx_read_csr
1320232809Sjmallett                                (CVMX_ILK_TXX_MEM_STAT0(interface));
1321232809Sjmallett        ilk_txx_mem_stat1.u64 = cvmx_read_csr
1322232809Sjmallett                                (CVMX_ILK_TXX_MEM_STAT1(interface));
1323232809Sjmallett        cvmx_dprintf ("ILK%d Channel%d Tx: %d packets %d bytes\n", interface, i,
1324232809Sjmallett                ilk_rxx_mem_stat0.s.rx_pkt,
1325232809Sjmallett                (unsigned int) ilk_rxx_mem_stat1.s.rx_bytes);
1326232809Sjmallett    }
1327232809Sjmallett
1328232809Sjmallett    return;
1329232809Sjmallett}
1330232809Sjmallett
1331232809Sjmallett/**
1332232809Sjmallett * enable or disable loopbacks
1333232809Sjmallett *
1334232809Sjmallett * @param interface The identifier of the packet interface to disable. cn68xx
1335232809Sjmallett *                  has 2 interfaces: ilk0 and ilk1.
1336232809Sjmallett * @param enable    Enable or disable loopback
1337232809Sjmallett * @param mode      Internal or external loopback
1338232809Sjmallett *
1339232809Sjmallett * @return Zero on success, negative of failure.
1340232809Sjmallett */
1341232809Sjmallettint cvmx_ilk_lpbk (int interface, cvmx_ilk_lpbk_ena_t enable,
1342232809Sjmallett                   cvmx_ilk_lpbk_mode_t mode)
1343232809Sjmallett{
1344232809Sjmallett    int res = -1;
1345232809Sjmallett    cvmx_ilk_txx_cfg0_t ilk_txx_cfg0;
1346232809Sjmallett    cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0;
1347232809Sjmallett
1348232809Sjmallett    if (!(OCTEON_IS_MODEL(OCTEON_CN68XX)))
1349232809Sjmallett        return res;
1350232809Sjmallett
1351232809Sjmallett    if (interface >= CVMX_NUM_ILK_INTF)
1352232809Sjmallett        return res;
1353232809Sjmallett
1354232809Sjmallett    /* internal loopback. only 1 type of loopback can be on at 1 time */
1355232809Sjmallett    if (mode == CVMX_ILK_LPBK_INT)
1356232809Sjmallett    {
1357232809Sjmallett        if (enable == CVMX_ILK_LPBK_ENA)
1358232809Sjmallett        {
1359232809Sjmallett            ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface));
1360232809Sjmallett            ilk_txx_cfg0.s.ext_lpbk = CVMX_ILK_LPBK_DISA;
1361232809Sjmallett            ilk_txx_cfg0.s.ext_lpbk_fc = CVMX_ILK_LPBK_DISA;
1362232809Sjmallett            cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64);
1363232809Sjmallett
1364232809Sjmallett            ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface));
1365232809Sjmallett            ilk_rxx_cfg0.s.ext_lpbk = CVMX_ILK_LPBK_DISA;
1366232809Sjmallett            ilk_rxx_cfg0.s.ext_lpbk_fc = CVMX_ILK_LPBK_DISA;
1367232809Sjmallett            cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64);
1368232809Sjmallett        }
1369232809Sjmallett
1370232809Sjmallett        ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface));
1371232809Sjmallett        ilk_txx_cfg0.s.int_lpbk = enable;
1372232809Sjmallett        cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64);
1373232809Sjmallett
1374232809Sjmallett        res = 0;
1375232809Sjmallett        return res;
1376232809Sjmallett    }
1377232809Sjmallett
1378232809Sjmallett    /* external loopback. only 1 type of loopback can be on at 1 time */
1379232809Sjmallett    if (enable == CVMX_ILK_LPBK_ENA)
1380232809Sjmallett    {
1381232809Sjmallett        ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface));
1382232809Sjmallett        ilk_txx_cfg0.s.int_lpbk = CVMX_ILK_LPBK_DISA;
1383232809Sjmallett        cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64);
1384232809Sjmallett    }
1385232809Sjmallett
1386232809Sjmallett    ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface));
1387232809Sjmallett    ilk_txx_cfg0.s.ext_lpbk = enable;
1388232809Sjmallett    ilk_txx_cfg0.s.ext_lpbk_fc = enable;
1389232809Sjmallett    cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64);
1390232809Sjmallett
1391232809Sjmallett    ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface));
1392232809Sjmallett    ilk_rxx_cfg0.s.ext_lpbk = enable;
1393232809Sjmallett    ilk_rxx_cfg0.s.ext_lpbk_fc = enable;
1394232809Sjmallett    cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64);
1395232809Sjmallett
1396232809Sjmallett    res = 0;
1397232809Sjmallett    return res;
1398232809Sjmallett}
1399232809Sjmallett
1400232809Sjmallett#endif /* CVMX_ENABLE_HELPER_FUNCTIONS */
1401