1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (c) 2003-2012 Broadcom Corporation
3*4882a593Smuzhiyun * All Rights Reserved
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * This software is available to you under a choice of one of two
6*4882a593Smuzhiyun * licenses. You may choose to be licensed under the terms of the GNU
7*4882a593Smuzhiyun * General Public License (GPL) Version 2, available from the file
8*4882a593Smuzhiyun * COPYING in the main directory of this source tree, or the Broadcom
9*4882a593Smuzhiyun * license below:
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * Redistribution and use in source and binary forms, with or without
12*4882a593Smuzhiyun * modification, are permitted provided that the following conditions
13*4882a593Smuzhiyun * are met:
14*4882a593Smuzhiyun *
15*4882a593Smuzhiyun * 1. Redistributions of source code must retain the above copyright
16*4882a593Smuzhiyun * notice, this list of conditions and the following disclaimer.
17*4882a593Smuzhiyun * 2. Redistributions in binary form must reproduce the above copyright
18*4882a593Smuzhiyun * notice, this list of conditions and the following disclaimer in
19*4882a593Smuzhiyun * the documentation and/or other materials provided with the
20*4882a593Smuzhiyun * distribution.
21*4882a593Smuzhiyun *
22*4882a593Smuzhiyun * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
23*4882a593Smuzhiyun * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24*4882a593Smuzhiyun * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25*4882a593Smuzhiyun * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
26*4882a593Smuzhiyun * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27*4882a593Smuzhiyun * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28*4882a593Smuzhiyun * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29*4882a593Smuzhiyun * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30*4882a593Smuzhiyun * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
31*4882a593Smuzhiyun * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
32*4882a593Smuzhiyun * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33*4882a593Smuzhiyun */
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun #include <asm/cpu-info.h>
36*4882a593Smuzhiyun #include <linux/irq.h>
37*4882a593Smuzhiyun #include <linux/interrupt.h>
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun #include <asm/cpu.h>
40*4882a593Smuzhiyun #include <asm/mipsregs.h>
41*4882a593Smuzhiyun #include <asm/netlogic/xlr/fmn.h>
42*4882a593Smuzhiyun #include <asm/netlogic/xlr/xlr.h>
43*4882a593Smuzhiyun #include <asm/netlogic/common.h>
44*4882a593Smuzhiyun #include <asm/netlogic/haldefs.h>
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun struct xlr_board_fmn_config xlr_board_fmn_config;
47*4882a593Smuzhiyun
print_credit_config(struct xlr_fmn_info * fmn_info)48*4882a593Smuzhiyun static void __maybe_unused print_credit_config(struct xlr_fmn_info *fmn_info)
49*4882a593Smuzhiyun {
50*4882a593Smuzhiyun int bkt;
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun pr_info("Bucket size :\n");
53*4882a593Smuzhiyun pr_info("Station\t: Size\n");
54*4882a593Smuzhiyun for (bkt = 0; bkt < 16; bkt++)
55*4882a593Smuzhiyun pr_info(" %d %d %d %d %d %d %d %d\n",
56*4882a593Smuzhiyun xlr_board_fmn_config.bucket_size[(bkt * 8) + 0],
57*4882a593Smuzhiyun xlr_board_fmn_config.bucket_size[(bkt * 8) + 1],
58*4882a593Smuzhiyun xlr_board_fmn_config.bucket_size[(bkt * 8) + 2],
59*4882a593Smuzhiyun xlr_board_fmn_config.bucket_size[(bkt * 8) + 3],
60*4882a593Smuzhiyun xlr_board_fmn_config.bucket_size[(bkt * 8) + 4],
61*4882a593Smuzhiyun xlr_board_fmn_config.bucket_size[(bkt * 8) + 5],
62*4882a593Smuzhiyun xlr_board_fmn_config.bucket_size[(bkt * 8) + 6],
63*4882a593Smuzhiyun xlr_board_fmn_config.bucket_size[(bkt * 8) + 7]);
64*4882a593Smuzhiyun pr_info("\n");
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun pr_info("Credits distribution :\n");
67*4882a593Smuzhiyun pr_info("Station\t: Size\n");
68*4882a593Smuzhiyun for (bkt = 0; bkt < 16; bkt++)
69*4882a593Smuzhiyun pr_info(" %d %d %d %d %d %d %d %d\n",
70*4882a593Smuzhiyun fmn_info->credit_config[(bkt * 8) + 0],
71*4882a593Smuzhiyun fmn_info->credit_config[(bkt * 8) + 1],
72*4882a593Smuzhiyun fmn_info->credit_config[(bkt * 8) + 2],
73*4882a593Smuzhiyun fmn_info->credit_config[(bkt * 8) + 3],
74*4882a593Smuzhiyun fmn_info->credit_config[(bkt * 8) + 4],
75*4882a593Smuzhiyun fmn_info->credit_config[(bkt * 8) + 5],
76*4882a593Smuzhiyun fmn_info->credit_config[(bkt * 8) + 6],
77*4882a593Smuzhiyun fmn_info->credit_config[(bkt * 8) + 7]);
78*4882a593Smuzhiyun pr_info("\n");
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun
check_credit_distribution(void)81*4882a593Smuzhiyun static void check_credit_distribution(void)
82*4882a593Smuzhiyun {
83*4882a593Smuzhiyun struct xlr_board_fmn_config *cfg = &xlr_board_fmn_config;
84*4882a593Smuzhiyun int bkt, n, total_credits, ncores;
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun ncores = hweight32(nlm_current_node()->coremask);
87*4882a593Smuzhiyun for (bkt = 0; bkt < 128; bkt++) {
88*4882a593Smuzhiyun total_credits = 0;
89*4882a593Smuzhiyun for (n = 0; n < ncores; n++)
90*4882a593Smuzhiyun total_credits += cfg->cpu[n].credit_config[bkt];
91*4882a593Smuzhiyun total_credits += cfg->gmac[0].credit_config[bkt];
92*4882a593Smuzhiyun total_credits += cfg->gmac[1].credit_config[bkt];
93*4882a593Smuzhiyun total_credits += cfg->dma.credit_config[bkt];
94*4882a593Smuzhiyun total_credits += cfg->cmp.credit_config[bkt];
95*4882a593Smuzhiyun total_credits += cfg->sae.credit_config[bkt];
96*4882a593Smuzhiyun total_credits += cfg->xgmac[0].credit_config[bkt];
97*4882a593Smuzhiyun total_credits += cfg->xgmac[1].credit_config[bkt];
98*4882a593Smuzhiyun if (total_credits > cfg->bucket_size[bkt])
99*4882a593Smuzhiyun pr_err("ERROR: Bucket %d: credits (%d) > size (%d)\n",
100*4882a593Smuzhiyun bkt, total_credits, cfg->bucket_size[bkt]);
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun pr_info("Credit distribution complete.\n");
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun /**
106*4882a593Smuzhiyun * Configure bucket size and credits for a device. 'size' is the size of
107*4882a593Smuzhiyun * the buckets for the device. This size is distributed among all the CPUs
108*4882a593Smuzhiyun * so that all of them can send messages to the device.
109*4882a593Smuzhiyun *
110*4882a593Smuzhiyun * The device is also given 'cpu_credits' to send messages to the CPUs
111*4882a593Smuzhiyun *
112*4882a593Smuzhiyun * @dev_info: FMN information structure for each devices
113*4882a593Smuzhiyun * @start_stn_id: Starting station id of dev_info
114*4882a593Smuzhiyun * @end_stn_id: End station id of dev_info
115*4882a593Smuzhiyun * @num_buckets: Total number of buckets for den_info
116*4882a593Smuzhiyun * @cpu_credits: Allowed credits to cpu for each devices pointing by dev_info
117*4882a593Smuzhiyun * @size: Size of the each buckets in the device station
118*4882a593Smuzhiyun */
setup_fmn_cc(struct xlr_fmn_info * dev_info,int start_stn_id,int end_stn_id,int num_buckets,int cpu_credits,int size)119*4882a593Smuzhiyun static void setup_fmn_cc(struct xlr_fmn_info *dev_info, int start_stn_id,
120*4882a593Smuzhiyun int end_stn_id, int num_buckets, int cpu_credits, int size)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun int i, j, num_core, n, credits_per_cpu;
123*4882a593Smuzhiyun struct xlr_fmn_info *cpu = xlr_board_fmn_config.cpu;
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun num_core = hweight32(nlm_current_node()->coremask);
126*4882a593Smuzhiyun dev_info->num_buckets = num_buckets;
127*4882a593Smuzhiyun dev_info->start_stn_id = start_stn_id;
128*4882a593Smuzhiyun dev_info->end_stn_id = end_stn_id;
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun n = num_core;
131*4882a593Smuzhiyun if (num_core == 3)
132*4882a593Smuzhiyun n = 4;
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun for (i = start_stn_id; i <= end_stn_id; i++) {
135*4882a593Smuzhiyun xlr_board_fmn_config.bucket_size[i] = size;
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun /* Dividing device credits equally to cpus */
138*4882a593Smuzhiyun credits_per_cpu = size / n;
139*4882a593Smuzhiyun for (j = 0; j < num_core; j++)
140*4882a593Smuzhiyun cpu[j].credit_config[i] = credits_per_cpu;
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun /* credits left to distribute */
143*4882a593Smuzhiyun credits_per_cpu = size - (credits_per_cpu * num_core);
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun /* distribute the remaining credits (if any), among cores */
146*4882a593Smuzhiyun for (j = 0; (j < num_core) && (credits_per_cpu >= 4); j++) {
147*4882a593Smuzhiyun cpu[j].credit_config[i] += 4;
148*4882a593Smuzhiyun credits_per_cpu -= 4;
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun /* Distributing cpu per bucket credits to devices */
153*4882a593Smuzhiyun for (i = 0; i < num_core; i++) {
154*4882a593Smuzhiyun for (j = 0; j < FMN_CORE_NBUCKETS; j++)
155*4882a593Smuzhiyun dev_info->credit_config[(i * 8) + j] = cpu_credits;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun /*
160*4882a593Smuzhiyun * Each core has 256 slots and 8 buckets,
161*4882a593Smuzhiyun * Configure the 8 buckets each with 32 slots
162*4882a593Smuzhiyun */
setup_cpu_fmninfo(struct xlr_fmn_info * cpu,int num_core)163*4882a593Smuzhiyun static void setup_cpu_fmninfo(struct xlr_fmn_info *cpu, int num_core)
164*4882a593Smuzhiyun {
165*4882a593Smuzhiyun int i, j;
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun for (i = 0; i < num_core; i++) {
168*4882a593Smuzhiyun cpu[i].start_stn_id = (8 * i);
169*4882a593Smuzhiyun cpu[i].end_stn_id = (8 * i + 8);
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun for (j = cpu[i].start_stn_id; j < cpu[i].end_stn_id; j++)
172*4882a593Smuzhiyun xlr_board_fmn_config.bucket_size[j] = 32;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun /**
177*4882a593Smuzhiyun * Setup the FMN details for each devices according to the device available
178*4882a593Smuzhiyun * in each variant of XLR/XLS processor
179*4882a593Smuzhiyun */
xlr_board_info_setup(void)180*4882a593Smuzhiyun void xlr_board_info_setup(void)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun struct xlr_fmn_info *cpu = xlr_board_fmn_config.cpu;
183*4882a593Smuzhiyun struct xlr_fmn_info *gmac = xlr_board_fmn_config.gmac;
184*4882a593Smuzhiyun struct xlr_fmn_info *xgmac = xlr_board_fmn_config.xgmac;
185*4882a593Smuzhiyun struct xlr_fmn_info *dma = &xlr_board_fmn_config.dma;
186*4882a593Smuzhiyun struct xlr_fmn_info *cmp = &xlr_board_fmn_config.cmp;
187*4882a593Smuzhiyun struct xlr_fmn_info *sae = &xlr_board_fmn_config.sae;
188*4882a593Smuzhiyun int processor_id, num_core;
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun num_core = hweight32(nlm_current_node()->coremask);
191*4882a593Smuzhiyun processor_id = read_c0_prid() & PRID_IMP_MASK;
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun setup_cpu_fmninfo(cpu, num_core);
194*4882a593Smuzhiyun switch (processor_id) {
195*4882a593Smuzhiyun case PRID_IMP_NETLOGIC_XLS104:
196*4882a593Smuzhiyun case PRID_IMP_NETLOGIC_XLS108:
197*4882a593Smuzhiyun setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
198*4882a593Smuzhiyun FMN_STNID_GMAC0_TX3, 8, 16, 32);
199*4882a593Smuzhiyun setup_fmn_cc(dma, FMN_STNID_DMA_0,
200*4882a593Smuzhiyun FMN_STNID_DMA_3, 4, 8, 64);
201*4882a593Smuzhiyun setup_fmn_cc(sae, FMN_STNID_SEC0,
202*4882a593Smuzhiyun FMN_STNID_SEC1, 2, 8, 128);
203*4882a593Smuzhiyun break;
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun case PRID_IMP_NETLOGIC_XLS204:
206*4882a593Smuzhiyun case PRID_IMP_NETLOGIC_XLS208:
207*4882a593Smuzhiyun setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
208*4882a593Smuzhiyun FMN_STNID_GMAC0_TX3, 8, 16, 32);
209*4882a593Smuzhiyun setup_fmn_cc(dma, FMN_STNID_DMA_0,
210*4882a593Smuzhiyun FMN_STNID_DMA_3, 4, 8, 64);
211*4882a593Smuzhiyun setup_fmn_cc(sae, FMN_STNID_SEC0,
212*4882a593Smuzhiyun FMN_STNID_SEC1, 2, 8, 128);
213*4882a593Smuzhiyun break;
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun case PRID_IMP_NETLOGIC_XLS404:
216*4882a593Smuzhiyun case PRID_IMP_NETLOGIC_XLS408:
217*4882a593Smuzhiyun case PRID_IMP_NETLOGIC_XLS404B:
218*4882a593Smuzhiyun case PRID_IMP_NETLOGIC_XLS408B:
219*4882a593Smuzhiyun case PRID_IMP_NETLOGIC_XLS416B:
220*4882a593Smuzhiyun case PRID_IMP_NETLOGIC_XLS608B:
221*4882a593Smuzhiyun case PRID_IMP_NETLOGIC_XLS616B:
222*4882a593Smuzhiyun setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
223*4882a593Smuzhiyun FMN_STNID_GMAC0_TX3, 8, 8, 32);
224*4882a593Smuzhiyun setup_fmn_cc(&gmac[1], FMN_STNID_GMAC1_FR_0,
225*4882a593Smuzhiyun FMN_STNID_GMAC1_TX3, 8, 8, 32);
226*4882a593Smuzhiyun setup_fmn_cc(dma, FMN_STNID_DMA_0,
227*4882a593Smuzhiyun FMN_STNID_DMA_3, 4, 4, 64);
228*4882a593Smuzhiyun setup_fmn_cc(cmp, FMN_STNID_CMP_0,
229*4882a593Smuzhiyun FMN_STNID_CMP_3, 4, 4, 64);
230*4882a593Smuzhiyun setup_fmn_cc(sae, FMN_STNID_SEC0,
231*4882a593Smuzhiyun FMN_STNID_SEC1, 2, 8, 128);
232*4882a593Smuzhiyun break;
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun case PRID_IMP_NETLOGIC_XLS412B:
235*4882a593Smuzhiyun setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
236*4882a593Smuzhiyun FMN_STNID_GMAC0_TX3, 8, 8, 32);
237*4882a593Smuzhiyun setup_fmn_cc(&gmac[1], FMN_STNID_GMAC1_FR_0,
238*4882a593Smuzhiyun FMN_STNID_GMAC1_TX3, 8, 8, 32);
239*4882a593Smuzhiyun setup_fmn_cc(dma, FMN_STNID_DMA_0,
240*4882a593Smuzhiyun FMN_STNID_DMA_3, 4, 4, 64);
241*4882a593Smuzhiyun setup_fmn_cc(cmp, FMN_STNID_CMP_0,
242*4882a593Smuzhiyun FMN_STNID_CMP_3, 4, 4, 64);
243*4882a593Smuzhiyun setup_fmn_cc(sae, FMN_STNID_SEC0,
244*4882a593Smuzhiyun FMN_STNID_SEC1, 2, 8, 128);
245*4882a593Smuzhiyun break;
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun case PRID_IMP_NETLOGIC_XLR308:
248*4882a593Smuzhiyun case PRID_IMP_NETLOGIC_XLR308C:
249*4882a593Smuzhiyun setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
250*4882a593Smuzhiyun FMN_STNID_GMAC0_TX3, 8, 16, 32);
251*4882a593Smuzhiyun setup_fmn_cc(dma, FMN_STNID_DMA_0,
252*4882a593Smuzhiyun FMN_STNID_DMA_3, 4, 8, 64);
253*4882a593Smuzhiyun setup_fmn_cc(sae, FMN_STNID_SEC0,
254*4882a593Smuzhiyun FMN_STNID_SEC1, 2, 4, 128);
255*4882a593Smuzhiyun break;
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun case PRID_IMP_NETLOGIC_XLR532:
258*4882a593Smuzhiyun case PRID_IMP_NETLOGIC_XLR532C:
259*4882a593Smuzhiyun case PRID_IMP_NETLOGIC_XLR516C:
260*4882a593Smuzhiyun case PRID_IMP_NETLOGIC_XLR508C:
261*4882a593Smuzhiyun setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
262*4882a593Smuzhiyun FMN_STNID_GMAC0_TX3, 8, 16, 32);
263*4882a593Smuzhiyun setup_fmn_cc(dma, FMN_STNID_DMA_0,
264*4882a593Smuzhiyun FMN_STNID_DMA_3, 4, 8, 64);
265*4882a593Smuzhiyun setup_fmn_cc(sae, FMN_STNID_SEC0,
266*4882a593Smuzhiyun FMN_STNID_SEC1, 2, 4, 128);
267*4882a593Smuzhiyun break;
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun case PRID_IMP_NETLOGIC_XLR732:
270*4882a593Smuzhiyun case PRID_IMP_NETLOGIC_XLR716:
271*4882a593Smuzhiyun setup_fmn_cc(&xgmac[0], FMN_STNID_XMAC0_00_TX,
272*4882a593Smuzhiyun FMN_STNID_XMAC0_15_TX, 8, 0, 32);
273*4882a593Smuzhiyun setup_fmn_cc(&xgmac[1], FMN_STNID_XMAC1_00_TX,
274*4882a593Smuzhiyun FMN_STNID_XMAC1_15_TX, 8, 0, 32);
275*4882a593Smuzhiyun setup_fmn_cc(&gmac[0], FMN_STNID_GMAC0,
276*4882a593Smuzhiyun FMN_STNID_GMAC0_TX3, 8, 24, 32);
277*4882a593Smuzhiyun setup_fmn_cc(dma, FMN_STNID_DMA_0,
278*4882a593Smuzhiyun FMN_STNID_DMA_3, 4, 4, 64);
279*4882a593Smuzhiyun setup_fmn_cc(sae, FMN_STNID_SEC0,
280*4882a593Smuzhiyun FMN_STNID_SEC1, 2, 4, 128);
281*4882a593Smuzhiyun break;
282*4882a593Smuzhiyun default:
283*4882a593Smuzhiyun pr_err("Unknown CPU with processor ID [%d]\n", processor_id);
284*4882a593Smuzhiyun pr_err("Error: Cannot initialize FMN credits.\n");
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun check_credit_distribution();
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun #if 0 /* debug */
290*4882a593Smuzhiyun print_credit_config(&cpu[0]);
291*4882a593Smuzhiyun print_credit_config(&gmac[0]);
292*4882a593Smuzhiyun #endif
293*4882a593Smuzhiyun }
294