board.c revision 211946
1/*********************************************************************
2 *
3 * Copyright 2003-2006 Raza Microelectronics, Inc. (RMI). All rights
4 * reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY Raza Microelectronics, Inc. ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RMI OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES, LOSS OF USE, DATA, OR PROFITS, OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27 * THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * *****************************RMI_2**********************************/
30#include <sys/cdefs.h>		/* RCS ID & Copyright macro defns */
31__FBSDID("$FreeBSD: head/sys/mips/rmi/board.c 211946 2010-08-28 19:02:51Z jchandra $");
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/bus.h>
35#include <sys/kernel.h>
36#include <sys/lock.h>
37#include <sys/mutex.h>
38
39#include <machine/cpufunc.h>
40#include <mips/rmi/msgring.h>
41#include <mips/rmi/board.h>
42#include <mips/rmi/pic.h>
43#include <mips/rmi/shared_structs.h>
44
45static int xlr_rxstn_to_txstn_map[128] = {
46	[0 ... 7] = TX_STN_CPU_0,
47	[8 ... 15] = TX_STN_CPU_1,
48	[16 ... 23] = TX_STN_CPU_2,
49	[24 ... 31] = TX_STN_CPU_3,
50	[32 ... 39] = TX_STN_CPU_4,
51	[40 ... 47] = TX_STN_CPU_5,
52	[48 ... 55] = TX_STN_CPU_6,
53	[56 ... 63] = TX_STN_CPU_7,
54	[64 ... 95] = TX_STN_INVALID,
55	[96 ... 103] = TX_STN_GMAC,
56	[104 ... 107] = TX_STN_DMA,
57	[108 ... 111] = TX_STN_INVALID,
58	[112 ... 113] = TX_STN_XGS_0,
59	[114 ... 115] = TX_STN_XGS_1,
60	[116 ... 119] = TX_STN_INVALID,
61	[120 ... 127] = TX_STN_SAE
62};
63
64static int xls_rxstn_to_txstn_map[128] = {
65	[0 ... 7] = TX_STN_CPU_0,
66	[8 ... 15] = TX_STN_CPU_1,
67	[16 ... 23] = TX_STN_CPU_2,
68	[24 ... 31] = TX_STN_CPU_3,
69	[32 ... 63] = TX_STN_INVALID,
70	[64 ... 71] = TX_STN_PCIE,
71	[72 ... 79] = TX_STN_INVALID,
72	[80 ... 87] = TX_STN_GMAC1,
73	[88 ... 95] = TX_STN_INVALID,
74	[96 ... 103] = TX_STN_GMAC0,
75	[104 ... 107] = TX_STN_DMA,
76	[108 ... 111] = TX_STN_CDE,
77	[112 ... 119] = TX_STN_INVALID,
78	[120 ... 127] = TX_STN_SAE
79};
80
81struct stn_cc *xlr_core_cc_configs[] = { &cc_table_cpu_0, &cc_table_cpu_1,
82    &cc_table_cpu_2, &cc_table_cpu_3, &cc_table_cpu_4, &cc_table_cpu_5,
83    &cc_table_cpu_6, &cc_table_cpu_7};
84
85struct stn_cc *xls_core_cc_configs[] = { &xls_cc_table_cpu_0, &xls_cc_table_cpu_1,
86   &xls_cc_table_cpu_2, &xls_cc_table_cpu_3 };
87
88struct xlr_board_info xlr_board_info;
89
90static int
91xlr_pcmcia_present(void)
92{
93	xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_GPIO_OFFSET);
94	uint32_t resetconf;
95
96	resetconf = xlr_read_reg(mmio, 21);
97	return ((resetconf & 0x4000) != 0);
98}
99
100static void
101xlr_board_specific_overrides(struct xlr_board_info* board)
102{
103	struct xlr_gmac_block_t *blk1, *blk2;
104
105	blk1 = &board->gmac_block[1];
106	blk2 = &board->gmac_block[2];
107
108	switch (xlr_boot1_info.board_major_version) {
109	case RMI_XLR_BOARD_ARIZONA_I:
110		/* ATX-I has SPI-4, not XGMAC */
111		blk1->type = XLR_SPI4;
112		blk1->enabled = 0;     /* nlge does not
113							 support SPI-4 */
114		blk2->type = XLR_SPI4;
115		blk2->enabled = 0;
116		break;
117
118	case RMI_XLR_BOARD_ARIZONA_II:
119		/* XGMII_A --> VSC7281, XGMII_B --> VSC7281 */
120		blk1->enabled = 1;
121		blk1->num_ports = 1;
122		blk1->gmac_port[0].valid = 1;
123
124		blk2->enabled = 1;
125		blk2->num_ports = 1;
126		blk2->gmac_port[0].valid = 1;
127	default:
128		break;
129	}
130}
131
132static int
133quad0_xaui(void)
134{
135	xlr_reg_t *gpio_mmio =
136	    (unsigned int *)(DEFAULT_XLR_IO_BASE + XLR_IO_GPIO_OFFSET);
137	uint32_t bit24;
138
139	bit24 = (xlr_read_reg(gpio_mmio, 0x15) >> 24) & 0x1;
140	return (bit24);
141}
142
143static int
144quad1_xaui(void)
145{
146	xlr_reg_t *gpio_mmio =
147	    (unsigned int *)(DEFAULT_XLR_IO_BASE + XLR_IO_GPIO_OFFSET);
148	uint32_t bit25;
149
150	bit25 = (xlr_read_reg(gpio_mmio, 0x15) >> 25) & 0x1;
151	return (bit25);
152}
153
154static void
155xls_board_specific_overrides(struct xlr_board_info* board)
156{
157	struct xlr_gmac_block_t *blk0, *blk1;
158	int i;
159
160	blk0 = &board->gmac_block[0];
161	blk1 = &board->gmac_block[1];
162
163	switch (xlr_boot1_info.board_major_version) {
164	case RMI_XLR_BOARD_ARIZONA_VI:
165		blk0->mode = XLR_PORT0_RGMII;
166		blk0->gmac_port[0].type = XLR_RGMII;
167		blk0->gmac_port[0].phy_addr = 0;
168		blk0->gmac_port[0].mii_addr = XLR_IO_GMAC_4_OFFSET;
169		/* Because of the Octal PHY, SGMII Quad1 is MII is also bound
170		 * to the PHY attached to SGMII0_MDC/MDIO/MDINT. */
171		for (i = 0; i < 4; i++) {
172			blk1->gmac_port[i].mii_addr = XLR_IO_GMAC_0_OFFSET;
173			blk1->gmac_port[i].serdes_addr = XLR_IO_GMAC_0_OFFSET;
174		}
175		blk1->gmac_port[1].mii_addr = XLR_IO_GMAC_0_OFFSET;
176		blk1->gmac_port[2].mii_addr = XLR_IO_GMAC_0_OFFSET;
177		blk1->gmac_port[3].mii_addr = XLR_IO_GMAC_0_OFFSET;
178
179		blk1->gmac_port[1].serdes_addr = XLR_IO_GMAC_0_OFFSET;
180		blk1->gmac_port[2].serdes_addr = XLR_IO_GMAC_0_OFFSET;
181		blk1->gmac_port[3].serdes_addr = XLR_IO_GMAC_0_OFFSET;
182
183		/* RGMII MDIO interrupt is thru NA1 and SGMII MDIO
184		 * interrupts for ports in blk1 are from NA0 */
185		blk0->gmac_port[0].mdint_id = 1;
186
187		blk1->gmac_port[0].mdint_id = 0;
188		blk1->gmac_port[1].mdint_id = 0;
189		blk1->gmac_port[2].mdint_id = 0;
190		blk1->gmac_port[3].mdint_id = 0;
191		break;
192
193	case RMI_XLR_BOARD_ARIZONA_VIII:
194		/* There is just one Octal PHY on the board and it is
195		 * connected to the MII interface for NA Quad 0. */
196		blk1->gmac_port[0].mii_addr = XLR_IO_GMAC_0_OFFSET;
197		blk1->gmac_port[1].mii_addr = XLR_IO_GMAC_0_OFFSET;
198		blk1->gmac_port[2].mii_addr = XLR_IO_GMAC_0_OFFSET;
199		blk1->gmac_port[3].mii_addr = XLR_IO_GMAC_0_OFFSET;
200
201		/* Board 8.3 (Lite) has XLS108 */
202		if (xlr_boot1_info.board_minor_version == 3) {
203			/* NA0 has 3 ports */
204			blk0->gmac_port[3].valid = 1;
205			blk0->num_ports--;
206			/* NA1 is completely disabled */
207			blk1->enabled = 0;
208		}
209
210		break;
211
212	case RMI_XLR_BOARD_ARIZONA_XI:
213	case RMI_XLR_BOARD_ARIZONA_XII:
214		if (quad0_xaui()) { /* GMAC ports 0-3 are set to XAUI */
215			/* only GMAC0 is active i.e, the 0-th port on this quad.
216			 * Disable all the other 7 possible ports. */
217			for (i = 1; i < MAX_NA_PORTS; i++) {
218				memset(&blk0->gmac_port[i], 0,
219				    sizeof(blk0->gmac_port[i]));
220			}
221			/* Setup for XAUI on N/w Acc0: gmac0 */
222			blk0->type 		= XLR_XGMAC;
223			blk0->mode 		= XLR_XAUI;
224			blk0->num_ports 	= 1;
225			blk0->gmac_port[0].type = XLR_XAUI;
226			blk1->gmac_port[0].phy_addr = 16;
227			blk0->gmac_port[0].tx_bucket_id = blk0->station_txbase;
228			/* Other addresses etc need not be modified as XAUI_0
229			 * shares its addresses with SGMII GMAC_0, which was
230			 * set in the caller. */
231		}
232		else {
233			blk0->num_ports 	= 1;  /* only 1 RGMII port */
234			blk0->mode = XLR_PORT0_RGMII;
235			blk0->gmac_port[0].type = XLR_RGMII;
236			blk0->gmac_port[0].phy_addr = 0;
237			blk0->gmac_port[0].mii_addr = XLR_IO_GMAC_0_OFFSET;
238		}
239
240		if (quad1_xaui()) { /* GMAC ports 4-7 are used for XAUI */
241			/* only GMAC4 is active i.e, the 0-th port on this quad.
242			 * Disable all the other 7 possible ports. */
243			for (i = 1; i < MAX_NA_PORTS; i++) {
244				memset(&blk1->gmac_port[i], 0,
245				    sizeof(blk1->gmac_port[i]));
246			}
247			/* Setup for XAUI on N/w Acc1: gmac4 */
248			blk1->type 		= XLR_XGMAC;
249			blk1->mode 		= XLR_XAUI;
250			blk1->num_ports 	= 1;
251			/* XAUI and SGMII ports share FMN buckets on N/w Acc 1;
252			   so, station_txbase, station_rfr need not be
253			   patched up. */
254			blk1->gmac_port[0].type = XLR_XAUI;
255			blk1->gmac_port[0].phy_addr = 16;
256			blk1->gmac_port[0].tx_bucket_id = blk1->station_txbase;
257			/* Other addresses etc need not be modified as XAUI_1
258			 * shares its addresses with SGMII GMAC_4, which was
259			 * set in the caller. */
260		}
261		break;
262
263	default:
264		break;
265	}
266}
267
268/*
269 * All our knowledge of chip and board that cannot be detected by probing
270 * at run-time goes here
271 */
272int
273xlr_board_info_setup()
274{
275	struct xlr_gmac_block_t *blk0, *blk1, *blk2;
276	int i;
277
278	/* This setup code is long'ish because the same base driver
279	 * (if_nlge.c) is used for different:
280	 *    - CPUs (XLR/XLS)
281	 *    - boards (for each CPU, multiple board configs are possible
282	 *	        and available).
283	 *
284	 * At the time of writing, there are atleast 12 boards, 4 with XLR
285	 * and 8 with XLS. This means that the base driver needs to work with
286	 * 12 different configurations, with varying levels of differences.
287	 * To accomodate the different configs, the xlr_board_info struct
288	 * has various attributes for paramters that could be different.
289	 * These attributes are setup here and can be used directly in the
290	 * base driver.
291	 * It was seen that the setup code is not entirely trivial and
292	 * it is possible to organize it in different ways. In the following,
293	 * we choose an approach that sacrifices code-compactness/speed for
294	 * readability. This is because configuration code executes once
295	 * per reboot and hence has a minimal performance impact.
296	 * On the other hand, driver debugging/enhancements require
297	 * that different engineers can quickly comprehend the setup
298	 * sequence. Hence, readability is seen as the key requirement for
299	 * this code. It is for the reader to decide how much of this
300	 * requirement is met with the current code organization !!
301	 *
302	 * The initialization is organized thus:
303	 *
304	 * if (CPU is XLS) {
305	 *    // initialize per XLS architecture
306	 *       // default inits (per chip spec)
307	 *       // board-specific overrides
308	 * } else if (CPU is XLR) {
309	 *    // initialize per XLR architecture
310	 *       // default inits (per chip spec)
311	 *       // board-specific overrides
312	 * }
313	 *
314	 * Within each CPU-specific initialization, all the default
315	 * initializations are done first. This is followed up with
316	 * board specific overrides.
317	 */
318
319	/* start with a clean slate */
320	memset(&xlr_board_info, 0, sizeof(xlr_board_info));
321	xlr_board_info.ata =  xlr_pcmcia_present();
322
323	blk0 = &xlr_board_info.gmac_block[0];
324	blk1 = &xlr_board_info.gmac_block[1];
325	blk2 = &xlr_board_info.gmac_block[2];
326
327	if (xlr_is_xls()) {
328		xlr_board_info.is_xls = 1;
329		xlr_board_info.nr_cpus = 8;
330		xlr_board_info.usb = 1;
331		/* Board version 8 has NAND flash */
332		xlr_board_info.cfi =
333		    (xlr_boot1_info.board_major_version != RMI_XLR_BOARD_ARIZONA_VIII);
334		xlr_board_info.pci_irq = 0;
335		xlr_board_info.credit_configs = xls_core_cc_configs;
336		xlr_board_info.bucket_sizes   = &xls_bucket_sizes;
337		xlr_board_info.msgmap         = xls_rxstn_to_txstn_map;
338		xlr_board_info.gmacports      = MAX_NA_PORTS;
339
340		/* ---------------- Network Acc 0 ---------------- */
341
342		blk0->type 		= XLR_GMAC;
343		blk0->enabled 		= 0xf;
344		blk0->credit_config 	= &xls_cc_table_gmac0;
345		blk0->station_id 	= TX_STN_GMAC0;
346		blk0->station_txbase 	= MSGRNG_STNID_GMACTX0;
347		blk0->station_rfr 	= MSGRNG_STNID_GMACRFR_0;
348		blk0->mode 		= XLR_SGMII;
349		blk0->baseaddr 		= XLR_IO_GMAC_0_OFFSET;
350		blk0->baseirq 		= PIC_GMAC_0_IRQ;
351		blk0->baseinst 		= 0;
352
353		/* By default, assume SGMII is setup. But this can change based
354		   on board-specific or setting-specific info. */
355		for (i = 0; i < 4; i++) {
356			blk0->gmac_port[i].valid = 1;
357			blk0->gmac_port[i].instance = i + blk0->baseinst;
358			blk0->gmac_port[i].type = XLR_SGMII;
359			blk0->gmac_port[i].phy_addr = i + 16;
360			blk0->gmac_port[i].tx_bucket_id =
361			    blk0->station_txbase + i;
362			blk0->gmac_port[i].mdint_id = 0;
363			blk0->num_ports++;
364			blk0->gmac_port[i].base_addr = XLR_IO_GMAC_0_OFFSET + i * 0x1000;
365			blk0->gmac_port[i].mii_addr = XLR_IO_GMAC_0_OFFSET;
366			blk0->gmac_port[i].pcs_addr = XLR_IO_GMAC_0_OFFSET;
367			blk0->gmac_port[i].serdes_addr = XLR_IO_GMAC_0_OFFSET;
368		}
369
370		/* ---------------- Network Acc 1 ---------------- */
371		blk1->type 		= XLR_GMAC;
372		blk1->enabled 		= 0xf;
373		blk1->credit_config 	= &xls_cc_table_gmac1;
374		blk1->station_id 	= TX_STN_GMAC1;
375		blk1->station_txbase 	= MSGRNG_STNID_GMAC1_TX0;
376		blk1->station_rfr 	= MSGRNG_STNID_GMAC1_FR_0;
377		blk1->mode 		= XLR_SGMII;
378		blk1->baseaddr 		= XLR_IO_GMAC_4_OFFSET;
379		blk1->baseirq 		= PIC_XGS_0_IRQ;
380		blk1->baseinst 		= 4;
381
382		for (i = 0; i < 4; i++) {
383			blk1->gmac_port[i].valid = 1;
384			blk1->gmac_port[i].instance = i + blk1->baseinst;
385			blk1->gmac_port[i].type = XLR_SGMII;
386			blk1->gmac_port[i].phy_addr = i + 20;
387			blk1->gmac_port[i].tx_bucket_id =
388			    blk1->station_txbase + i;
389			blk1->gmac_port[i].mdint_id = 1;
390			blk1->num_ports++;
391			blk1->gmac_port[i].base_addr = XLR_IO_GMAC_4_OFFSET +  i * 0x1000;
392			blk1->gmac_port[i].mii_addr = XLR_IO_GMAC_4_OFFSET;
393			blk1->gmac_port[i].pcs_addr = XLR_IO_GMAC_4_OFFSET;
394			blk1->gmac_port[i].serdes_addr = XLR_IO_GMAC_0_OFFSET;
395		}
396
397		/* ---------------- Network Acc 2 ---------------- */
398		xlr_board_info.gmac_block[2].enabled = 0;  /* disabled on XLS */
399
400		xls_board_specific_overrides(&xlr_board_info);
401
402	} else {	/* XLR */
403		xlr_board_info.is_xls = 0;
404		xlr_board_info.nr_cpus = 32;
405		xlr_board_info.usb = 0;
406		xlr_board_info.cfi = 1;
407		xlr_board_info.pci_irq = 0;
408		xlr_board_info.credit_configs = xlr_core_cc_configs;
409		xlr_board_info.bucket_sizes   = &bucket_sizes;
410		xlr_board_info.msgmap         =  xlr_rxstn_to_txstn_map;
411		xlr_board_info.gmacports         = 4;
412
413		/* ---------------- GMAC0 ---------------- */
414		blk0->type 		= XLR_GMAC;
415		blk0->enabled 		= 0xf;
416		blk0->credit_config 	= &cc_table_gmac;
417		blk0->station_id 	= TX_STN_GMAC;
418		blk0->station_txbase 	= MSGRNG_STNID_GMACTX0;
419		blk0->station_rfr 	= MSGRNG_STNID_GMACRFR_0;
420		blk0->mode 		= XLR_RGMII;
421		blk0->baseaddr 		= XLR_IO_GMAC_0_OFFSET;
422		blk0->baseirq 		= PIC_GMAC_0_IRQ;
423		blk0->baseinst 		= 0;
424
425		/* first, do the common/easy stuff for all the ports */
426		for (i = 0; i < 4; i++) {
427			blk0->gmac_port[i].valid = 1;
428			blk0->gmac_port[i].instance = i + blk0->baseinst;
429			blk0->gmac_port[i].type = XLR_RGMII;
430			blk0->gmac_port[i].phy_addr = i;
431			blk0->gmac_port[i].tx_bucket_id =
432			    blk0->station_txbase + i;
433			blk0->gmac_port[i].mdint_id = 0;
434			blk0->gmac_port[i].base_addr = XLR_IO_GMAC_0_OFFSET + i * 0x1000;
435			blk0->gmac_port[i].mii_addr = XLR_IO_GMAC_0_OFFSET;
436			/* RGMII ports, no PCS/SERDES */
437			blk0->num_ports++;
438		}
439
440		/* ---------------- XGMAC0 ---------------- */
441		blk1->type 		= XLR_XGMAC;
442		blk1->mode 		= XLR_XGMII;
443		blk1->enabled 		= 0;
444		blk1->credit_config 	= &cc_table_xgs_0;
445		blk1->station_txbase 	= MSGRNG_STNID_XGS0_TX;
446		blk1->station_rfr 	= MSGRNG_STNID_XMAC0RFR;
447		blk1->station_id 	= TX_STN_XGS_0;	/* TBD: is this correct ? */
448		blk1->baseaddr 		= XLR_IO_XGMAC_0_OFFSET;
449		blk1->baseirq 		= PIC_XGS_0_IRQ;
450		blk1->baseinst 		= 4;
451
452		blk1->gmac_port[0].type 	= XLR_XGMII;
453		blk1->gmac_port[0].instance 	= 0;
454		blk1->gmac_port[0].phy_addr 	= 0;
455		blk1->gmac_port[0].base_addr 	= XLR_IO_XGMAC_0_OFFSET;
456		blk1->gmac_port[0].mii_addr 	= XLR_IO_XGMAC_0_OFFSET;
457		blk1->gmac_port[0].tx_bucket_id = blk1->station_txbase;
458		blk1->gmac_port[0].mdint_id 	= 1;
459
460		/* ---------------- XGMAC1 ---------------- */
461		blk2->type 		= XLR_XGMAC;
462		blk2->mode 		= XLR_XGMII;
463		blk2->enabled 		= 0;
464		blk2->credit_config 	= &cc_table_xgs_1;
465		blk2->station_txbase 	= MSGRNG_STNID_XGS1_TX;
466		blk2->station_rfr 	= MSGRNG_STNID_XMAC1RFR;
467		blk2->station_id 	= TX_STN_XGS_1;	/* TBD: is this correct ? */
468		blk2->baseaddr 		= XLR_IO_XGMAC_1_OFFSET;
469		blk2->baseirq 		= PIC_XGS_1_IRQ;
470		blk2->baseinst 		= 5;
471
472		blk2->gmac_port[0].type 	= XLR_XGMII;
473		blk2->gmac_port[0].instance 	= 0;
474		blk2->gmac_port[0].phy_addr 	= 0;
475		blk2->gmac_port[0].base_addr 	= XLR_IO_XGMAC_1_OFFSET;
476		blk2->gmac_port[0].mii_addr 	= XLR_IO_XGMAC_1_OFFSET;
477		blk2->gmac_port[0].tx_bucket_id = blk2->station_txbase;
478		blk2->gmac_port[0].mdint_id 	= 2;
479
480		/* Done with default setup. Now do board-specific tweaks. */
481		xlr_board_specific_overrides(&xlr_board_info);
482  	}
483  	return 0;
484}
485