2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright 2003-2011 Netlogic Microsystems (Netlogic). All rights
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
18 * THIS SOFTWARE IS PROVIDED BY Netlogic Microsystems ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34 #include <sys/types.h>
35 #include <sys/systm.h>
37 #include <machine/cpufunc.h>
38 #include <mips/nlm/hal/mips-extns.h>
39 #include <mips/nlm/hal/haldefs.h>
40 #include <mips/nlm/hal/iomap.h>
41 #include <mips/nlm/hal/fmn.h>
43 /* XLP can take upto 16K of FMN messages per hardware queue, as spill.
44 * But, configuring all 16K causes the total spill memory to required
45 * to blow upto 192MB for single chip configuration, and 768MB in four
46 * chip configuration. Hence for now, we will setup the per queue spill
47 * as 1K FMN messages. With this, the total spill memory needed for 1024
48 * hardware queues (with 12bytes per single entry FMN message) becomes
49 * (1*1024)*12*1024queues = 12MB. For the four chip config, the memory
50 * needed = 12 * 4 = 48MB.
52 uint64_t nlm_cms_spill_total_messages = 1 * 1024;
54 /* On a XLP832, we have the following FMN stations:
67 * Total : 18 stations per chip
69 * For all 4 nodes, there are 18*4 = 72 FMN stations
71 uint32_t nlm_cms_total_stations = 18 * 4 /*xlp_num_nodes*/;
74 * Takes inputs as node, queue_size and maximum number of queues.
75 * Calculates the base, start & end and returns the same for a
78 * The output queues are maintained in the internal output buffer
79 * which is a on-chip SRAM structure. For the actial hardware
80 * internal implementation, It is a structure which consists
81 * of eight banks of 4096-entry x message-width SRAMs. The SRAM
82 * implementation is designed to run at 1GHz with a 1-cycle read/write
83 * access. A read/write transaction can be initiated for each bank
84 * every cycle for a total of eight accesses per cycle. Successive
85 * entries of the same output queue are placed in successive banks.
86 * This is done to spread different read & write accesses to same/different
87 * output queue over as many different banks as possible so that they
88 * can be scheduled concurrently. Spreading the accesses to as many banks
89 * as possible to maximize the concurrency internally is important for
90 * achieving the desired peak throughput. This is done by h/w implementation
93 * Output queues are allocated from this internal output buffer by
94 * software. The total capacity of the output buffer is 32K-entry.
95 * Each output queue can be sized from 32-entry to 1024-entry in
96 * increments of 32-entry. This is done by specifying a Start & a
97 * End pointer: pointers to the first & last 32-entry chunks allocated
98 * to the output queue.
100 * To optimize the storage required for 1024 OQ pointers, the upper 5-bits
101 * are shared by the Start & the End pointer. The side-effect of this
102 * optimization is that an OQ can't cross a 1024-entry boundary. Also, the
103 * lower 5-bits don't need to be specified in the Start & the End pointer
104 * as the allocation is in increments of 32-entries.
106 * Queue occupancy is tracked by a Head & a Tail pointer. Tail pointer
107 * indicates the location to which next entry will be written & Head
108 * pointer indicates the location from which next entry will be read. When
109 * these pointers reach the top of the allocated space (indicated by the
110 * End pointer), they are reset to the bottom of the allocated space
111 * (indicated by the Start pointer).
113 * Output queue pointer information:
114 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
126 * ------------------------------------
128 * ------------------------------------
129 * ------------------------------------
131 * ------------------------------------
133 * A total of 1024 segments can sit on one software-visible "bank"
134 * of internal SRAM. Each segment contains 32 entries. Also note
135 * that sw-visible "banks" are not the same as the actual internal
136 * 8-bank implementation of hardware. It is an optimization of
141 void nlm_cms_setup_credits(uint64_t base, int destid, int srcid, int credit)
145 val = (((uint64_t)credit << 24) | (destid << 12) | (srcid << 0));
146 nlm_write_cms_reg(base, CMS_OUTPUTQ_CREDIT_CFG, val);
151 * base - CMS module base address for this node.
152 * qid - is the output queue id otherwise called as vc id
153 * spill_base - is the 40-bit physical address of spill memory. Must be
155 * nsegs - No of segments where a "1" indicates 4KB. Spill size must be
158 int nlm_cms_alloc_spill_q(uint64_t base, int qid, uint64_t spill_base,
161 uint64_t queue_config;
162 uint32_t spill_start;
164 if (nsegs > CMS_MAX_SPILL_SEGMENTS_PER_QUEUE) {
168 queue_config = nlm_read_cms_reg(base,(CMS_OUTPUTQ_CONFIG(qid)));
170 spill_start = ((spill_base >> 12) & 0x3F);
171 /* Spill configuration */
172 queue_config = (((uint64_t)CMS_SPILL_ENA << 62) |
173 (((spill_base >> 18) & 0x3FFFFF) << 27) |
174 (spill_start + nsegs - 1) << 21 |
175 (spill_start << 15));
177 nlm_write_cms_reg(base,(CMS_OUTPUTQ_CONFIG(qid)),queue_config);
182 uint64_t nlm_cms_get_onchip_queue (uint64_t base, int qid)
184 return nlm_read_cms_reg(base, CMS_OUTPUTQ_CONFIG(qid));
187 void nlm_cms_set_onchip_queue (uint64_t base, int qid, uint64_t val)
191 rdval = nlm_read_cms_reg(base, CMS_OUTPUTQ_CONFIG(qid));
193 nlm_write_cms_reg(base, CMS_OUTPUTQ_CONFIG(qid), rdval);
196 void nlm_cms_per_queue_level_intr(uint64_t base, int qid, int sub_type,
201 val = nlm_read_cms_reg(base, CMS_OUTPUTQ_CONFIG(qid));
203 val &= ~((0x7ULL << 56) | (0x3ULL << 54));
205 val |= (((uint64_t)sub_type<<54) |
206 ((uint64_t)intr_val<<56));
208 nlm_write_cms_reg(base, CMS_OUTPUTQ_CONFIG(qid), val);
211 void nlm_cms_per_queue_timer_intr(uint64_t base, int qid, int sub_type,
216 val = nlm_read_cms_reg(base, CMS_OUTPUTQ_CONFIG(qid));
218 val &= ~((0x7ULL << 51) | (0x3ULL << 49));
220 val |= (((uint64_t)sub_type<<49) |
221 ((uint64_t)intr_val<<51));
223 nlm_write_cms_reg(base, CMS_OUTPUTQ_CONFIG(qid), val);
226 /* returns 1 if interrupt has been generated for this output queue */
227 int nlm_cms_outputq_intr_check(uint64_t base, int qid)
230 val = nlm_read_cms_reg(base, CMS_OUTPUTQ_CONFIG(qid));
232 return ((val >> 59) & 0x1);
235 void nlm_cms_outputq_clr_intr(uint64_t base, int qid)
238 val = nlm_read_cms_reg(base, CMS_OUTPUTQ_CONFIG(qid));
240 nlm_write_cms_reg(base, CMS_OUTPUTQ_CONFIG(qid), val);
243 void nlm_cms_illegal_dst_error_intr(uint64_t base, int en)
247 val = nlm_read_cms_reg(base, CMS_MSG_CONFIG);
249 nlm_write_cms_reg(base, CMS_MSG_CONFIG, val);
252 void nlm_cms_timeout_error_intr(uint64_t base, int en)
256 val = nlm_read_cms_reg(base, CMS_MSG_CONFIG);
258 nlm_write_cms_reg(base, CMS_MSG_CONFIG, val);
261 void nlm_cms_biu_error_resp_intr(uint64_t base, int en)
265 val = nlm_read_cms_reg(base, CMS_MSG_CONFIG);
267 nlm_write_cms_reg(base, CMS_MSG_CONFIG, val);
270 void nlm_cms_spill_uncorrectable_ecc_error_intr(uint64_t base, int en)
274 val = nlm_read_cms_reg(base, CMS_MSG_CONFIG);
275 val |= (en<<5) | (en<<3);
276 nlm_write_cms_reg(base, CMS_MSG_CONFIG, val);
279 void nlm_cms_spill_correctable_ecc_error_intr(uint64_t base, int en)
283 val = nlm_read_cms_reg(base, CMS_MSG_CONFIG);
284 val |= (en<<4) | (en<<2);
285 nlm_write_cms_reg(base, CMS_MSG_CONFIG, val);
288 void nlm_cms_outputq_uncorrectable_ecc_error_intr(uint64_t base, int en)
292 val = nlm_read_cms_reg(base, CMS_MSG_CONFIG);
294 nlm_write_cms_reg(base, CMS_MSG_CONFIG, val);
297 void nlm_cms_outputq_correctable_ecc_error_intr(uint64_t base, int en)
301 val = nlm_read_cms_reg(base, CMS_MSG_CONFIG);
303 nlm_write_cms_reg(base, CMS_MSG_CONFIG, val);
306 uint64_t nlm_cms_network_error_status(uint64_t base)
308 return nlm_read_cms_reg(base, CMS_MSG_ERR);
311 int nlm_cms_get_net_error_code(uint64_t err)
313 return ((err >> 12) & 0xf);
316 int nlm_cms_get_net_error_syndrome(uint64_t err)
318 return ((err >> 32) & 0x1ff);
321 int nlm_cms_get_net_error_ramindex(uint64_t err)
323 return ((err >> 44) & 0x7fff);
326 int nlm_cms_get_net_error_outputq(uint64_t err)
328 return ((err >> 16) & 0xfff);
331 /*========================= FMN Tracing related APIs ================*/
333 void nlm_cms_trace_setup(uint64_t base, int en, uint64_t trace_base,
334 uint64_t trace_limit, int match_dstid_en,
335 int dst_id, int match_srcid_en, int src_id,
340 nlm_write_cms_reg(base, CMS_TRACE_BASE_ADDR, trace_base);
341 nlm_write_cms_reg(base, CMS_TRACE_LIMIT_ADDR, trace_limit);
343 val = nlm_read_cms_reg(base, CMS_TRACE_CONFIG);
344 val |= (((uint64_t)match_dstid_en << 39) |
345 ((dst_id & 0xfff) << 24) |
346 (match_srcid_en << 23) |
347 ((src_id & 0xfff) << 8) |
350 nlm_write_cms_reg(base, CMS_MSG_CONFIG, val);
353 void nlm_cms_endian_byte_swap (uint64_t base, int en)
355 nlm_write_cms_reg(base, CMS_MSG_ENDIAN_SWAP, en);