538ef69a113c918d624e2659928904535abb243f
[openwrt/svn-archive/archive.git] / openwrt / target / linux / linux-2.6 / patches / brcm / 001-bcm947xx.patch
1 diff -urN linux.old/arch/mips/Kconfig linux.dev/arch/mips/Kconfig
2 --- linux.old/arch/mips/Kconfig 2005-12-15 13:26:49.758027500 +0100
3 +++ linux.dev/arch/mips/Kconfig 2005-12-15 12:57:27.889182500 +0100
4 @@ -244,6 +244,17 @@
5 Members include the Acer PICA, MIPS Magnum 4000, MIPS Millenium and
6 Olivetti M700-10 workstations.
7
8 +config BCM947XX
9 + bool "Support for BCM947xx based boards"
10 + select DMA_NONCOHERENT
11 + select HW_HAS_PCI
12 + select IRQ_CPU
13 + select SYS_HAS_CPU_MIPS32_R1
14 + select SYS_SUPPORTS_32BIT_KERNEL
15 + select SYS_SUPPORTS_LITTLE_ENDIAN
16 + help
17 + Support for BCM947xx based boards
18 +
19 config LASAT
20 bool "Support for LASAT Networks platforms"
21 select DMA_NONCOHERENT
22 diff -urN linux.old/arch/mips/Makefile linux.dev/arch/mips/Makefile
23 --- linux.old/arch/mips/Makefile 2005-12-15 13:26:49.766024000 +0100
24 +++ linux.dev/arch/mips/Makefile 2005-12-15 12:57:27.921168500 +0100
25 @@ -689,6 +689,13 @@
26 load-$(CONFIG_SIBYTE_BIGSUR) := 0xffffffff80100000
27
28 #
29 +# Broadcom BCM47XX boards
30 +#
31 +core-$(CONFIG_BCM947XX) += arch/mips/bcm947xx/ arch/mips/bcm947xx/broadcom/
32 +cflags-$(CONFIG_BCM947XX) += -Iarch/mips/bcm947xx/include
33 +load-$(CONFIG_BCM947XX) := 0xffffffff80001000
34 +
35 +#
36 # SNI RM200 PCI
37 #
38 core-$(CONFIG_SNI_RM200_PCI) += arch/mips/sni/
39 diff -urN linux.old/arch/mips/bcm947xx/Makefile linux.dev/arch/mips/bcm947xx/Makefile
40 --- linux.old/arch/mips/bcm947xx/Makefile 1970-01-01 01:00:00.000000000 +0100
41 +++ linux.dev/arch/mips/bcm947xx/Makefile 2005-12-15 14:32:03.580639500 +0100
42 @@ -0,0 +1,6 @@
43 +#
44 +# Makefile for the BCM47xx specific kernel interface routines
45 +# under Linux.
46 +#
47 +
48 +obj-y := irq.o int-handler.o prom.o setup.o time.o pci.o
49 diff -urN linux.old/arch/mips/bcm947xx/broadcom/Makefile linux.dev/arch/mips/bcm947xx/broadcom/Makefile
50 --- linux.old/arch/mips/bcm947xx/broadcom/Makefile 1970-01-01 01:00:00.000000000 +0100
51 +++ linux.dev/arch/mips/bcm947xx/broadcom/Makefile 2005-12-17 20:51:17.749271000 +0100
52 @@ -0,0 +1,6 @@
53 +#
54 +# Makefile for the BCM47xx specific kernel interface routines
55 +# under Linux.
56 +#
57 +
58 +obj-y := sbutils.o linux_osl.o bcmsrom.o bcmutils.o sbmips.o sbpci.o sflash.o nvram.o cfe_env.o
59 diff -urN linux.old/arch/mips/bcm947xx/broadcom/bcmsrom.c linux.dev/arch/mips/bcm947xx/broadcom/bcmsrom.c
60 --- linux.old/arch/mips/bcm947xx/broadcom/bcmsrom.c 1970-01-01 01:00:00.000000000 +0100
61 +++ linux.dev/arch/mips/bcm947xx/broadcom/bcmsrom.c 2005-12-17 01:21:23.007883000 +0100
62 @@ -0,0 +1,481 @@
63 +/*
64 + * Misc useful routines to access NIC SROM/OTP .
65 + *
66 + * Copyright 2005, Broadcom Corporation
67 + * All Rights Reserved.
68 + *
69 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
70 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
71 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
72 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
73 + * $Id$
74 + */
75 +
76 +#include <typedefs.h>
77 +#include <osl.h>
78 +#include <bcmutils.h>
79 +#include <bcmsrom.h>
80 +#include <bcmdevs.h>
81 +#include <bcmendian.h>
82 +#include <pcicfg.h>
83 +#include <sbutils.h>
84 +
85 +#include <proto/ethernet.h> /* for sprom content groking */
86 +
87 +#define VARS_MAX 4096 /* should be reduced */
88 +
89 +#define WRITE_ENABLE_DELAY 500 /* 500 ms after write enable/disable toggle */
90 +#define WRITE_WORD_DELAY 20 /* 20 ms between each word write */
91 +
92 +static int initvars_srom_pci(void *sbh, void *curmap, char **vars, int *count);
93 +static int sprom_read_pci(uint16 *sprom, uint wordoff, uint16 *buf, uint nwords, bool check_crc);
94 +
95 +static int initvars_table(osl_t *osh, char *start, char *end, char **vars, uint *count);
96 +
97 +/*
98 + * Initialize local vars from the right source for this platform.
99 + * Return 0 on success, nonzero on error.
100 + */
101 +int
102 +srom_var_init(void *sbh, uint bustype, void *curmap, osl_t *osh, char **vars, int *count)
103 +{
104 + ASSERT(bustype == BUSTYPE(bustype));
105 + if (vars == NULL || count == NULL)
106 + return (0);
107 +
108 + switch (BUSTYPE(bustype)) {
109 +
110 + case PCI_BUS:
111 + ASSERT(curmap); /* can not be NULL */
112 + return initvars_srom_pci(sbh, curmap, vars, count);
113 +
114 + default:
115 + return 0;
116 + }
117 + return (-1);
118 +}
119 +
120 +/* support only 16-bit word read from srom */
121 +int
122 +srom_read(uint bustype, void *curmap, osl_t *osh, uint byteoff, uint nbytes, uint16 *buf)
123 +{
124 + void *srom;
125 + uint off, nw;
126 +
127 + ASSERT(bustype == BUSTYPE(bustype));
128 +
129 + /* check input - 16-bit access only */
130 + if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > (SPROM_SIZE * 2))
131 + return 1;
132 +
133 + off = byteoff / 2;
134 + nw = nbytes / 2;
135 +
136 + if (BUSTYPE(bustype) == PCI_BUS) {
137 + if (!curmap)
138 + return 1;
139 + srom = (uchar*)curmap + PCI_BAR0_SPROM_OFFSET;
140 + if (sprom_read_pci(srom, off, buf, nw, FALSE))
141 + return 1;
142 + } else {
143 + return 1;
144 + }
145 +
146 + return 0;
147 +}
148 +
149 +/* support only 16-bit word write into srom */
150 +int
151 +srom_write(uint bustype, void *curmap, osl_t *osh, uint byteoff, uint nbytes, uint16 *buf)
152 +{
153 + uint16 *srom;
154 + uint i, off, nw, crc_range;
155 + uint16 image[SPROM_SIZE], *p;
156 + uint8 crc;
157 + volatile uint32 val32;
158 +
159 + ASSERT(bustype == BUSTYPE(bustype));
160 +
161 + /* check input - 16-bit access only */
162 + if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > (SPROM_SIZE * 2))
163 + return 1;
164 +
165 + crc_range = (((BUSTYPE(bustype) == SDIO_BUS)) ? SPROM_SIZE : SPROM_CRC_RANGE) * 2;
166 +
167 + /* if changes made inside crc cover range */
168 + if (byteoff < crc_range) {
169 + nw = (((byteoff + nbytes) > crc_range) ? byteoff + nbytes : crc_range) / 2;
170 + /* read data including entire first 64 words from srom */
171 + if (srom_read(bustype, curmap, osh, 0, nw * 2, image))
172 + return 1;
173 + /* make changes */
174 + bcopy((void*)buf, (void*)&image[byteoff / 2], nbytes);
175 + /* calculate crc */
176 + htol16_buf(image, crc_range);
177 + crc = ~hndcrc8((uint8 *)image, crc_range - 1, CRC8_INIT_VALUE);
178 + ltoh16_buf(image, crc_range);
179 + image[(crc_range / 2) - 1] = (crc << 8) | (image[(crc_range / 2) - 1] & 0xff);
180 + p = image;
181 + off = 0;
182 + } else {
183 + p = buf;
184 + off = byteoff / 2;
185 + nw = nbytes / 2;
186 + }
187 +
188 + if (BUSTYPE(bustype) == PCI_BUS) {
189 + srom = (uint16*)((uchar*)curmap + PCI_BAR0_SPROM_OFFSET);
190 + /* enable writes to the SPROM */
191 + val32 = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32));
192 + val32 |= SPROM_WRITEEN;
193 + OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32);
194 + bcm_mdelay(WRITE_ENABLE_DELAY);
195 + /* write srom */
196 + for (i = 0; i < nw; i++) {
197 + W_REG(&srom[off + i], p[i]);
198 + bcm_mdelay(WRITE_WORD_DELAY);
199 + }
200 + /* disable writes to the SPROM */
201 + OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32 & ~SPROM_WRITEEN);
202 + } else {
203 + return 1;
204 + }
205 +
206 + bcm_mdelay(WRITE_ENABLE_DELAY);
207 + return 0;
208 +}
209 +
210 +
211 +/*
212 + * Read in and validate sprom.
213 + * Return 0 on success, nonzero on error.
214 + */
215 +static int
216 +sprom_read_pci(uint16 *sprom, uint wordoff, uint16 *buf, uint nwords, bool check_crc)
217 +{
218 + int err = 0;
219 + uint i;
220 +
221 + /* read the sprom */
222 + for (i = 0; i < nwords; i++)
223 + buf[i] = R_REG(&sprom[wordoff + i]);
224 +
225 + if (check_crc) {
226 + /* fixup the endianness so crc8 will pass */
227 + htol16_buf(buf, nwords * 2);
228 + if (hndcrc8((uint8*)buf, nwords * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE)
229 + err = 1;
230 + /* now correct the endianness of the byte array */
231 + ltoh16_buf(buf, nwords * 2);
232 + }
233 +
234 + return err;
235 +}
236 +
237 +/*
238 +* Create variable table from memory.
239 +* Return 0 on success, nonzero on error.
240 +*/
241 +static int
242 +initvars_table(osl_t *osh, char *start, char *end, char **vars, uint *count)
243 +{
244 + int c = (int)(end - start);
245 +
246 + /* do it only when there is more than just the null string */
247 + if (c > 1) {
248 + char *vp = MALLOC(osh, c);
249 + ASSERT(vp);
250 + if (!vp)
251 + return BCME_NOMEM;
252 + bcopy(start, vp, c);
253 + *vars = vp;
254 + *count = c;
255 + }
256 + else {
257 + *vars = NULL;
258 + *count = 0;
259 + }
260 +
261 + return 0;
262 +}
263 +
264 +/*
265 + * Initialize nonvolatile variable table from sprom.
266 + * Return 0 on success, nonzero on error.
267 + */
268 +static int
269 +initvars_srom_pci(void *sbh, void *curmap, char **vars, int *count)
270 +{
271 + uint16 w, b[64];
272 + uint8 sromrev;
273 + struct ether_addr ea;
274 + char eabuf[32];
275 + uint32 w32;
276 + int woff, i;
277 + char *vp, *base;
278 + osl_t *osh = sb_osh(sbh);
279 + int err;
280 +
281 + /*
282 + * Apply CRC over SROM content regardless SROM is present or not,
283 + * and use variable <devpath>sromrev's existance in flash to decide
284 + * if we should return an error when CRC fails or read SROM variables
285 + * from flash.
286 + */
287 + sprom_read_pci((void*)((int8*)curmap + PCI_BAR0_SPROM_OFFSET), 0, b, sizeof(b)/sizeof(b[0]), TRUE);
288 +
289 + /* top word of sprom contains version and crc8 */
290 + sromrev = b[63] & 0xff;
291 + /* bcm4401 sroms misprogrammed */
292 + if (sromrev == 0x10)
293 + sromrev = 1;
294 +
295 + /* srom version check */
296 + if (sromrev > 3)
297 + return (-2);
298 +
299 + ASSERT(vars);
300 + ASSERT(count);
301 +
302 + base = vp = MALLOC(osh, VARS_MAX);
303 + ASSERT(vp);
304 + if (!vp)
305 + return -2;
306 +
307 + vp += sprintf(vp, "sromrev=%d", sromrev);
308 + vp++;
309 +
310 + if (sromrev >= 3) {
311 + /* New section takes over the 3th hardware function space */
312 +
313 + /* Words 22+23 are 11a (mid) ofdm power offsets */
314 + w32 = ((uint32)b[23] << 16) | b[22];
315 + vp += sprintf(vp, "ofdmapo=%d", w32);
316 + vp++;
317 +
318 + /* Words 24+25 are 11a (low) ofdm power offsets */
319 + w32 = ((uint32)b[25] << 16) | b[24];
320 + vp += sprintf(vp, "ofdmalpo=%d", w32);
321 + vp++;
322 +
323 + /* Words 26+27 are 11a (high) ofdm power offsets */
324 + w32 = ((uint32)b[27] << 16) | b[26];
325 + vp += sprintf(vp, "ofdmahpo=%d", w32);
326 + vp++;
327 +
328 + /*GPIO LED Powersave duty cycle (oncount >> 24) (offcount >> 8)*/
329 + w32 = ((uint32)b[43] << 24) | ((uint32)b[42] << 8);
330 + vp += sprintf(vp, "gpiotimerval=%d", w32);
331 +
332 + /*GPIO LED Powersave duty cycle (oncount >> 24) (offcount >> 8)*/
333 + w32 = ((uint32)((unsigned char)(b[21] >> 8) & 0xFF) << 24) | /* oncount*/
334 + ((uint32)((unsigned char)(b[21] & 0xFF)) << 8); /* offcount */
335 + vp += sprintf(vp, "gpiotimerval=%d", w32);
336 +
337 + vp++;
338 + }
339 +
340 + if (sromrev >= 2) {
341 + /* New section takes over the 4th hardware function space */
342 +
343 + /* Word 29 is max power 11a high/low */
344 + w = b[29];
345 + vp += sprintf(vp, "pa1himaxpwr=%d", w & 0xff);
346 + vp++;
347 + vp += sprintf(vp, "pa1lomaxpwr=%d", (w >> 8) & 0xff);
348 + vp++;
349 +
350 + /* Words 30-32 set the 11alow pa settings,
351 + * 33-35 are the 11ahigh ones.
352 + */
353 + for (i = 0; i < 3; i++) {
354 + vp += sprintf(vp, "pa1lob%d=%d", i, b[30 + i]);
355 + vp++;
356 + vp += sprintf(vp, "pa1hib%d=%d", i, b[33 + i]);
357 + vp++;
358 + }
359 + w = b[59];
360 + if (w == 0)
361 + vp += sprintf(vp, "ccode=");
362 + else
363 + vp += sprintf(vp, "ccode=%c%c", (w >> 8), (w & 0xff));
364 + vp++;
365 +
366 + }
367 +
368 + /* parameter section of sprom starts at byte offset 72 */
369 + woff = 72/2;
370 +
371 + /* first 6 bytes are il0macaddr */
372 + ea.octet[0] = (b[woff] >> 8) & 0xff;
373 + ea.octet[1] = b[woff] & 0xff;
374 + ea.octet[2] = (b[woff+1] >> 8) & 0xff;
375 + ea.octet[3] = b[woff+1] & 0xff;
376 + ea.octet[4] = (b[woff+2] >> 8) & 0xff;
377 + ea.octet[5] = b[woff+2] & 0xff;
378 + woff += ETHER_ADDR_LEN/2 ;
379 + bcm_ether_ntoa((uchar*)&ea, eabuf);
380 + vp += sprintf(vp, "il0macaddr=%s", eabuf);
381 + vp++;
382 +
383 + /* next 6 bytes are et0macaddr */
384 + ea.octet[0] = (b[woff] >> 8) & 0xff;
385 + ea.octet[1] = b[woff] & 0xff;
386 + ea.octet[2] = (b[woff+1] >> 8) & 0xff;
387 + ea.octet[3] = b[woff+1] & 0xff;
388 + ea.octet[4] = (b[woff+2] >> 8) & 0xff;
389 + ea.octet[5] = b[woff+2] & 0xff;
390 + woff += ETHER_ADDR_LEN/2 ;
391 + bcm_ether_ntoa((uchar*)&ea, eabuf);
392 + vp += sprintf(vp, "et0macaddr=%s", eabuf);
393 + vp++;
394 +
395 + /* next 6 bytes are et1macaddr */
396 + ea.octet[0] = (b[woff] >> 8) & 0xff;
397 + ea.octet[1] = b[woff] & 0xff;
398 + ea.octet[2] = (b[woff+1] >> 8) & 0xff;
399 + ea.octet[3] = b[woff+1] & 0xff;
400 + ea.octet[4] = (b[woff+2] >> 8) & 0xff;
401 + ea.octet[5] = b[woff+2] & 0xff;
402 + woff += ETHER_ADDR_LEN/2 ;
403 + bcm_ether_ntoa((uchar*)&ea, eabuf);
404 + vp += sprintf(vp, "et1macaddr=%s", eabuf);
405 + vp++;
406 +
407 + /*
408 + * Enet phy settings one or two singles or a dual
409 + * Bits 4-0 : MII address for enet0 (0x1f for not there)
410 + * Bits 9-5 : MII address for enet1 (0x1f for not there)
411 + * Bit 14 : Mdio for enet0
412 + * Bit 15 : Mdio for enet1
413 + */
414 + w = b[woff];
415 + vp += sprintf(vp, "et0phyaddr=%d", (w & 0x1f));
416 + vp++;
417 + vp += sprintf(vp, "et1phyaddr=%d", ((w >> 5) & 0x1f));
418 + vp++;
419 + vp += sprintf(vp, "et0mdcport=%d", ((w >> 14) & 0x1));
420 + vp++;
421 + vp += sprintf(vp, "et1mdcport=%d", ((w >> 15) & 0x1));
422 + vp++;
423 +
424 + /* Word 46 has board rev, antennas 0/1 & Country code/control */
425 + w = b[46];
426 + vp += sprintf(vp, "boardrev=%d", w & 0xff);
427 + vp++;
428 +
429 + if (sromrev > 1)
430 + vp += sprintf(vp, "cctl=%d", (w >> 8) & 0xf);
431 + else
432 + vp += sprintf(vp, "cc=%d", (w >> 8) & 0xf);
433 + vp++;
434 +
435 + vp += sprintf(vp, "aa0=%d", (w >> 12) & 0x3);
436 + vp++;
437 +
438 + vp += sprintf(vp, "aa1=%d", (w >> 14) & 0x3);
439 + vp++;
440 +
441 + /* Words 47-49 set the (wl) pa settings */
442 + woff = 47;
443 +
444 + for (i = 0; i < 3; i++) {
445 + vp += sprintf(vp, "pa0b%d=%d", i, b[woff+i]);
446 + vp++;
447 + vp += sprintf(vp, "pa1b%d=%d", i, b[woff+i+6]);
448 + vp++;
449 + }
450 +
451 + /*
452 + * Words 50-51 set the customer-configured wl led behavior.
453 + * 8 bits/gpio pin. High bit: activehi=0, activelo=1;
454 + * LED behavior values defined in wlioctl.h .
455 + */
456 + w = b[50];
457 + if ((w != 0) && (w != 0xffff)) {
458 + /* gpio0 */
459 + vp += sprintf(vp, "wl0gpio0=%d", (w & 0xff));
460 + vp++;
461 +
462 + /* gpio1 */
463 + vp += sprintf(vp, "wl0gpio1=%d", (w >> 8) & 0xff);
464 + vp++;
465 + }
466 + w = b[51];
467 + if ((w != 0) && (w != 0xffff)) {
468 + /* gpio2 */
469 + vp += sprintf(vp, "wl0gpio2=%d", w & 0xff);
470 + vp++;
471 +
472 + /* gpio3 */
473 + vp += sprintf(vp, "wl0gpio3=%d", (w >> 8) & 0xff);
474 + vp++;
475 + }
476 +
477 + /* Word 52 is max power 0/1 */
478 + w = b[52];
479 + vp += sprintf(vp, "pa0maxpwr=%d", w & 0xff);
480 + vp++;
481 + vp += sprintf(vp, "pa1maxpwr=%d", (w >> 8) & 0xff);
482 + vp++;
483 +
484 + /* Word 56 is idle tssi target 0/1 */
485 + w = b[56];
486 + vp += sprintf(vp, "pa0itssit=%d", w & 0xff);
487 + vp++;
488 + vp += sprintf(vp, "pa1itssit=%d", (w >> 8) & 0xff);
489 + vp++;
490 +
491 + /* Word 57 is boardflags, if not programmed make it zero */
492 + w32 = (uint32)b[57];
493 + if (w32 == 0xffff) w32 = 0;
494 + if (sromrev > 1) {
495 + /* Word 28 is the high bits of boardflags */
496 + w32 |= (uint32)b[28] << 16;
497 + }
498 + vp += sprintf(vp, "boardflags=%d", w32);
499 + vp++;
500 +
501 + /* Word 58 is antenna gain 0/1 */
502 + w = b[58];
503 + vp += sprintf(vp, "ag0=%d", w & 0xff);
504 + vp++;
505 +
506 + vp += sprintf(vp, "ag1=%d", (w >> 8) & 0xff);
507 + vp++;
508 +
509 + if (sromrev == 1) {
510 + /* set the oem string */
511 + vp += sprintf(vp, "oem=%02x%02x%02x%02x%02x%02x%02x%02x",
512 + ((b[59] >> 8) & 0xff), (b[59] & 0xff),
513 + ((b[60] >> 8) & 0xff), (b[60] & 0xff),
514 + ((b[61] >> 8) & 0xff), (b[61] & 0xff),
515 + ((b[62] >> 8) & 0xff), (b[62] & 0xff));
516 + vp++;
517 + } else if (sromrev == 2) {
518 + /* Word 60 OFDM tx power offset from CCK level */
519 + /* OFDM Power Offset - opo */
520 + vp += sprintf(vp, "opo=%d", b[60] & 0xff);
521 + vp++;
522 + } else {
523 + /* Word 60: cck power offsets */
524 + vp += sprintf(vp, "cckpo=%d", b[60]);
525 + vp++;
526 +
527 + /* Words 61+62: 11g ofdm power offsets */
528 + w32 = ((uint32)b[62] << 16) | b[61];
529 + vp += sprintf(vp, "ofdmgpo=%d", w32);
530 + vp++;
531 + }
532 +
533 + /* final nullbyte terminator */
534 + *vp++ = '\0';
535 +
536 + ASSERT((vp - base) <= VARS_MAX);
537 +
538 + err = initvars_table(osh, base, vp, vars, count);
539 +
540 + MFREE(osh, base, VARS_MAX);
541 + return err;
542 +}
543 +
544 diff -urN linux.old/arch/mips/bcm947xx/broadcom/bcmutils.c linux.dev/arch/mips/bcm947xx/broadcom/bcmutils.c
545 --- linux.old/arch/mips/bcm947xx/broadcom/bcmutils.c 1970-01-01 01:00:00.000000000 +0100
546 +++ linux.dev/arch/mips/bcm947xx/broadcom/bcmutils.c 2005-12-17 17:53:52.387365000 +0100
547 @@ -0,0 +1,356 @@
548 +/*
549 + * Misc useful OS-independent routines.
550 + *
551 + * Copyright 2005, Broadcom Corporation
552 + * All Rights Reserved.
553 + *
554 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
555 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
556 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
557 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
558 + * $Id$
559 + */
560 +
561 +#include <typedefs.h>
562 +#include <osl.h>
563 +#include <sbutils.h>
564 +#include <bcmnvram.h>
565 +#include <bcmutils.h>
566 +#include <bcmendian.h>
567 +#include <bcmdevs.h>
568 +
569 +unsigned char bcm_ctype[] = {
570 + _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 0-7 */
571 + _BCM_C,_BCM_C|_BCM_S,_BCM_C|_BCM_S,_BCM_C|_BCM_S,_BCM_C|_BCM_S,_BCM_C|_BCM_S,_BCM_C,_BCM_C, /* 8-15 */
572 + _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 16-23 */
573 + _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 24-31 */
574 + _BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 32-39 */
575 + _BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 40-47 */
576 + _BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D, /* 48-55 */
577 + _BCM_D,_BCM_D,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 56-63 */
578 + _BCM_P,_BCM_U|_BCM_X,_BCM_U|_BCM_X,_BCM_U|_BCM_X,_BCM_U|_BCM_X,_BCM_U|_BCM_X,_BCM_U|_BCM_X,_BCM_U, /* 64-71 */
579 + _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 72-79 */
580 + _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 80-87 */
581 + _BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 88-95 */
582 + _BCM_P,_BCM_L|_BCM_X,_BCM_L|_BCM_X,_BCM_L|_BCM_X,_BCM_L|_BCM_X,_BCM_L|_BCM_X,_BCM_L|_BCM_X,_BCM_L, /* 96-103 */
583 + _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 104-111 */
584 + _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 112-119 */
585 + _BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_C, /* 120-127 */
586 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
587 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
588 + _BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 160-175 */
589 + _BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 176-191 */
590 + _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 192-207 */
591 + _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_L, /* 208-223 */
592 + _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 224-239 */
593 + _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L /* 240-255 */
594 +};
595 +
596 +uchar
597 +bcm_toupper(uchar c)
598 +{
599 + if (bcm_islower(c))
600 + c -= 'a'-'A';
601 + return (c);
602 +}
603 +
604 +ulong
605 +bcm_strtoul(char *cp, char **endp, uint base)
606 +{
607 + ulong result, value;
608 + bool minus;
609 +
610 + minus = FALSE;
611 +
612 + while (bcm_isspace(*cp))
613 + cp++;
614 +
615 + if (cp[0] == '+')
616 + cp++;
617 + else if (cp[0] == '-') {
618 + minus = TRUE;
619 + cp++;
620 + }
621 +
622 + if (base == 0) {
623 + if (cp[0] == '0') {
624 + if ((cp[1] == 'x') || (cp[1] == 'X')) {
625 + base = 16;
626 + cp = &cp[2];
627 + } else {
628 + base = 8;
629 + cp = &cp[1];
630 + }
631 + } else
632 + base = 10;
633 + } else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) {
634 + cp = &cp[2];
635 + }
636 +
637 + result = 0;
638 +
639 + while (bcm_isxdigit(*cp) &&
640 + (value = bcm_isdigit(*cp) ? *cp-'0' : bcm_toupper(*cp)-'A'+10) < base) {
641 + result = result*base + value;
642 + cp++;
643 + }
644 +
645 + if (minus)
646 + result = (ulong)(result * -1);
647 +
648 + if (endp)
649 + *endp = (char *)cp;
650 +
651 + return (result);
652 +}
653 +
654 +uint
655 +bcm_atoi(char *s)
656 +{
657 + uint n;
658 +
659 + n = 0;
660 +
661 + while (bcm_isdigit(*s))
662 + n = (n * 10) + *s++ - '0';
663 + return (n);
664 +}
665 +
666 +/* return pointer to location of substring 'needle' in 'haystack' */
667 +char*
668 +bcmstrstr(char *haystack, char *needle)
669 +{
670 + int len, nlen;
671 + int i;
672 +
673 + if ((haystack == NULL) || (needle == NULL))
674 + return (haystack);
675 +
676 + nlen = strlen(needle);
677 + len = strlen(haystack) - nlen + 1;
678 +
679 + for (i = 0; i < len; i++)
680 + if (bcmp(needle, &haystack[i], nlen) == 0)
681 + return (&haystack[i]);
682 + return (NULL);
683 +}
684 +
685 +char*
686 +bcmstrcat(char *dest, const char *src)
687 +{
688 + strcpy(&dest[strlen(dest)], src);
689 + return (dest);
690 +}
691 +
692 +
693 +char*
694 +bcm_ether_ntoa(char *ea, char *buf)
695 +{
696 + sprintf(buf,"%02x:%02x:%02x:%02x:%02x:%02x",
697 + (uchar)ea[0]&0xff, (uchar)ea[1]&0xff, (uchar)ea[2]&0xff,
698 + (uchar)ea[3]&0xff, (uchar)ea[4]&0xff, (uchar)ea[5]&0xff);
699 + return (buf);
700 +}
701 +
702 +/* parse a xx:xx:xx:xx:xx:xx format ethernet address */
703 +int
704 +bcm_ether_atoe(char *p, char *ea)
705 +{
706 + int i = 0;
707 +
708 + for (;;) {
709 + ea[i++] = (char) bcm_strtoul(p, &p, 16);
710 + if (!*p++ || i == 6)
711 + break;
712 + }
713 +
714 + return (i == 6);
715 +}
716 +
717 +void
718 +bcm_mdelay(uint ms)
719 +{
720 + uint i;
721 +
722 + for (i = 0; i < ms; i++) {
723 + OSL_DELAY(1000);
724 + }
725 +}
726 +
727 +/*
728 + * Search the name=value vars for a specific one and return its value.
729 + * Returns NULL if not found.
730 + */
731 +char*
732 +getvar(char *vars, char *name)
733 +{
734 + char *s;
735 + int len;
736 +
737 + len = strlen(name);
738 +
739 + /* first look in vars[] */
740 + for (s = vars; s && *s; ) {
741 + if ((bcmp(s, name, len) == 0) && (s[len] == '='))
742 + return (&s[len+1]);
743 +
744 + while (*s++)
745 + ;
746 + }
747 +
748 + /* then query nvram */
749 + return (BCMINIT(nvram_get)(name));
750 +}
751 +
752 +/*
753 + * Search the vars for a specific one and return its value as
754 + * an integer. Returns 0 if not found.
755 + */
756 +int
757 +getintvar(char *vars, char *name)
758 +{
759 + char *val;
760 +
761 + if ((val = getvar(vars, name)) == NULL)
762 + return (0);
763 +
764 + return (bcm_strtoul(val, NULL, 0));
765 +}
766 +
767 +
768 +/* Search for token in comma separated token-string */
769 +static int
770 +findmatch(char *string, char *name)
771 +{
772 + uint len;
773 + char *c;
774 +
775 + len = strlen(name);
776 + while ((c = strchr(string, ',')) != NULL) {
777 + if (len == (uint)(c - string) && !strncmp(string, name, len))
778 + return 1;
779 + string = c + 1;
780 + }
781 +
782 + return (!strcmp(string, name));
783 +}
784 +
785 +/* Return gpio pin number assigned to the named pin */
786 +/*
787 +* Variable should be in format:
788 +*
789 +* gpio<N>=pin_name,pin_name
790 +*
791 +* This format allows multiple features to share the gpio with mutual
792 +* understanding.
793 +*
794 +* 'def_pin' is returned if a specific gpio is not defined for the requested functionality
795 +* and if def_pin is not used by others.
796 +*/
797 +uint
798 +getgpiopin(char *vars, char *pin_name, uint def_pin)
799 +{
800 + char name[] = "gpioXXXX";
801 + char *val;
802 + uint pin;
803 +
804 + /* Go thru all possibilities till a match in pin name */
805 + for (pin = 0; pin < GPIO_NUMPINS; pin ++) {
806 + sprintf(name, "gpio%d", pin);
807 + val = getvar(vars, name);
808 + if (val && findmatch(val, pin_name))
809 + return pin;
810 + }
811 +
812 + if (def_pin != GPIO_PIN_NOTDEFINED) {
813 + /* make sure the default pin is not used by someone else */
814 + sprintf(name, "gpio%d", def_pin);
815 + if (getvar(vars, name)) {
816 + def_pin = GPIO_PIN_NOTDEFINED;
817 + }
818 + }
819 +
820 + return def_pin;
821 +}
822 +
823 +
824 +/*******************************************************************************
825 + * crc8
826 + *
827 + * Computes a crc8 over the input data using the polynomial:
828 + *
829 + * x^8 + x^7 +x^6 + x^4 + x^2 + 1
830 + *
831 + * The caller provides the initial value (either CRC8_INIT_VALUE
832 + * or the previous returned value) to allow for processing of
833 + * discontiguous blocks of data. When generating the CRC the
834 + * caller is responsible for complementing the final return value
835 + * and inserting it into the byte stream. When checking, a final
836 + * return value of CRC8_GOOD_VALUE indicates a valid CRC.
837 + *
838 + * Reference: Dallas Semiconductor Application Note 27
839 + * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
840 + * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
841 + * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
842 + *
843 + ******************************************************************************/
844 +
845 +static uint8 crc8_table[256] = {
846 + 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
847 + 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
848 + 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
849 + 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
850 + 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
851 + 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
852 + 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
853 + 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
854 + 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
855 + 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
856 + 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
857 + 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
858 + 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
859 + 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
860 + 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
861 + 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
862 + 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
863 + 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
864 + 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
865 + 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
866 + 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
867 + 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
868 + 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
869 + 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
870 + 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
871 + 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
872 + 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
873 + 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
874 + 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
875 + 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
876 + 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
877 + 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F
878 +};
879 +
880 +#define CRC_INNER_LOOP(n, c, x) \
881 + (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff]
882 +
883 +uint8
884 +hndcrc8(
885 + uint8 *pdata, /* pointer to array of data to process */
886 + uint nbytes, /* number of input data bytes to process */
887 + uint8 crc /* either CRC8_INIT_VALUE or previous return value */
888 +)
889 +{
890 + /* hard code the crc loop instead of using CRC_INNER_LOOP macro
891 + * to avoid the undefined and unnecessary (uint8 >> 8) operation. */
892 + while (nbytes-- > 0)
893 + crc = crc8_table[(crc ^ *pdata++) & 0xff];
894 +
895 + return crc;
896 +}
897 +
898 +#ifdef notdef
899 +#define CLEN 1499
900 +#define CBUFSIZ (CLEN+4)
901 +#define CNBUFS 5
902 +
903 +#endif
904 diff -urN linux.old/arch/mips/bcm947xx/broadcom/cfe_env.c linux.dev/arch/mips/bcm947xx/broadcom/cfe_env.c
905 --- linux.old/arch/mips/bcm947xx/broadcom/cfe_env.c 1970-01-01 01:00:00.000000000 +0100
906 +++ linux.dev/arch/mips/bcm947xx/broadcom/cfe_env.c 2005-12-17 21:40:08.166726750 +0100
907 @@ -0,0 +1,234 @@
908 +/*
909 + * NVRAM variable manipulation (Linux kernel half)
910 + *
911 + * Copyright 2001-2003, Broadcom Corporation
912 + * All Rights Reserved.
913 + *
914 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
915 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
916 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
917 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
918 + *
919 + * $Id$
920 + */
921 +
922 +#include <linux/config.h>
923 +#include <linux/init.h>
924 +#include <linux/module.h>
925 +#include <linux/kernel.h>
926 +#include <linux/string.h>
927 +#include <asm/io.h>
928 +#include <asm/uaccess.h>
929 +
930 +#include <typedefs.h>
931 +#include <osl.h>
932 +#include <bcmendian.h>
933 +#include <bcmutils.h>
934 +
935 +#define NVRAM_SIZE (0x1ff0)
936 +static char _nvdata[NVRAM_SIZE] __initdata;
937 +static char _valuestr[256] __initdata;
938 +
939 +/*
940 + * TLV types. These codes are used in the "type-length-value"
941 + * encoding of the items stored in the NVRAM device (flash or EEPROM)
942 + *
943 + * The layout of the flash/nvram is as follows:
944 + *
945 + * <type> <length> <data ...> <type> <length> <data ...> <type_end>
946 + *
947 + * The type code of "ENV_TLV_TYPE_END" marks the end of the list.
948 + * The "length" field marks the length of the data section, not
949 + * including the type and length fields.
950 + *
951 + * Environment variables are stored as follows:
952 + *
953 + * <type_env> <length> <flags> <name> = <value>
954 + *
955 + * If bit 0 (low bit) is set, the length is an 8-bit value.
956 + * If bit 0 (low bit) is clear, the length is a 16-bit value
957 + *
958 + * Bit 7 set indicates "user" TLVs. In this case, bit 0 still
959 + * indicates the size of the length field.
960 + *
961 + * Flags are from the constants below:
962 + *
963 + */
964 +#define ENV_LENGTH_16BITS 0x00 /* for low bit */
965 +#define ENV_LENGTH_8BITS 0x01
966 +
967 +#define ENV_TYPE_USER 0x80
968 +
969 +#define ENV_CODE_SYS(n,l) (((n)<<1)|(l))
970 +#define ENV_CODE_USER(n,l) ((((n)<<1)|(l)) | ENV_TYPE_USER)
971 +
972 +/*
973 + * The actual TLV types we support
974 + */
975 +
976 +#define ENV_TLV_TYPE_END 0x00
977 +#define ENV_TLV_TYPE_ENV ENV_CODE_SYS(0,ENV_LENGTH_8BITS)
978 +
979 +/*
980 + * Environment variable flags
981 + */
982 +
983 +#define ENV_FLG_NORMAL 0x00 /* normal read/write */
984 +#define ENV_FLG_BUILTIN 0x01 /* builtin - not stored in flash */
985 +#define ENV_FLG_READONLY 0x02 /* read-only - cannot be changed */
986 +
987 +#define ENV_FLG_MASK 0xFF /* mask of attributes we keep */
988 +#define ENV_FLG_ADMIN 0x100 /* lets us internally override permissions */
989 +
990 +
991 +/* *********************************************************************
992 + * _nvram_read(buffer,offset,length)
993 + *
994 + * Read data from the NVRAM device
995 + *
996 + * Input parameters:
997 + * buffer - destination buffer
998 + * offset - offset of data to read
999 + * length - number of bytes to read
1000 + *
1001 + * Return value:
1002 + * number of bytes read, or <0 if error occured
1003 + ********************************************************************* */
1004 +static int
1005 +_nvram_read(unsigned char *nv_buf, unsigned char *buffer, int offset, int length)
1006 +{
1007 + int i;
1008 + if (offset > NVRAM_SIZE)
1009 + return -1;
1010 +
1011 + for ( i = 0; i < length; i++) {
1012 + buffer[i] = ((volatile unsigned char*)nv_buf)[offset + i];
1013 + }
1014 + return length;
1015 +}
1016 +
1017 +
1018 +static char*
1019 +_strnchr(const char *dest,int c,size_t cnt)
1020 +{
1021 + while (*dest && (cnt > 0)) {
1022 + if (*dest == c) return (char *) dest;
1023 + dest++;
1024 + cnt--;
1025 + }
1026 + return NULL;
1027 +}
1028 +
1029 +
1030 +
1031 +/*
1032 + * Core support API: Externally visible.
1033 + */
1034 +
1035 +/*
1036 + * Get the value of an NVRAM variable
1037 + * @param name name of variable to get
1038 + * @return value of variable or NULL if undefined
1039 + */
1040 +
1041 +char*
1042 +cfe_env_get(unsigned char *nv_buf, char* name)
1043 +{
1044 + int size;
1045 + unsigned char *buffer;
1046 + unsigned char *ptr;
1047 + unsigned char *envval;
1048 + unsigned int reclen;
1049 + unsigned int rectype;
1050 + int offset;
1051 + int flg;
1052 +
1053 + size = NVRAM_SIZE;
1054 + buffer = &_nvdata[0];
1055 +
1056 + ptr = buffer;
1057 + offset = 0;
1058 +
1059 + /* Read the record type and length */
1060 + if (_nvram_read(nv_buf, ptr,offset,1) != 1) {
1061 + goto error;
1062 + }
1063 +
1064 + while ((*ptr != ENV_TLV_TYPE_END) && (size > 1)) {
1065 +
1066 + /* Adjust pointer for TLV type */
1067 + rectype = *(ptr);
1068 + offset++;
1069 + size--;
1070 +
1071 + /*
1072 + * Read the length. It can be either 1 or 2 bytes
1073 + * depending on the code
1074 + */
1075 + if (rectype & ENV_LENGTH_8BITS) {
1076 + /* Read the record type and length - 8 bits */
1077 + if (_nvram_read(nv_buf, ptr,offset,1) != 1) {
1078 + goto error;
1079 + }
1080 + reclen = *(ptr);
1081 + size--;
1082 + offset++;
1083 + }
1084 + else {
1085 + /* Read the record type and length - 16 bits, MSB first */
1086 + if (_nvram_read(nv_buf, ptr,offset,2) != 2) {
1087 + goto error;
1088 + }
1089 + reclen = (((unsigned int) *(ptr)) << 8) + (unsigned int) *(ptr+1);
1090 + size -= 2;
1091 + offset += 2;
1092 + }
1093 +
1094 + if (reclen > size)
1095 + break; /* should not happen, bad NVRAM */
1096 +
1097 + switch (rectype) {
1098 + case ENV_TLV_TYPE_ENV:
1099 + /* Read the TLV data */
1100 + if (_nvram_read(nv_buf, ptr,offset,reclen) != reclen)
1101 + goto error;
1102 + flg = *ptr++;
1103 + envval = (unsigned char *) _strnchr(ptr,'=',(reclen-1));
1104 + if (envval) {
1105 + *envval++ = '\0';
1106 + memcpy(_valuestr,envval,(reclen-1)-(envval-ptr));
1107 + _valuestr[(reclen-1)-(envval-ptr)] = '\0';
1108 +#if 0
1109 + printk(KERN_INFO "NVRAM:%s=%s\n", ptr, _valuestr);
1110 +#endif
1111 + if(!strcmp(ptr, name)){
1112 + return _valuestr;
1113 + }
1114 + if((strlen(ptr) > 1) && !strcmp(&ptr[1], name))
1115 + return _valuestr;
1116 + }
1117 + break;
1118 +
1119 + default:
1120 + /* Unknown TLV type, skip it. */
1121 + break;
1122 + }
1123 +
1124 + /*
1125 + * Advance to next TLV
1126 + */
1127 +
1128 + size -= (int)reclen;
1129 + offset += reclen;
1130 +
1131 + /* Read the next record type */
1132 + ptr = buffer;
1133 + if (_nvram_read(nv_buf, ptr,offset,1) != 1)
1134 + goto error;
1135 + }
1136 +
1137 +error:
1138 + return NULL;
1139 +
1140 +}
1141 +
1142 diff -urN linux.old/arch/mips/bcm947xx/broadcom/linux_osl.c linux.dev/arch/mips/bcm947xx/broadcom/linux_osl.c
1143 --- linux.old/arch/mips/bcm947xx/broadcom/linux_osl.c 1970-01-01 01:00:00.000000000 +0100
1144 +++ linux.dev/arch/mips/bcm947xx/broadcom/linux_osl.c 2005-12-15 17:11:05.818041750 +0100
1145 @@ -0,0 +1,102 @@
1146 +/*
1147 + * Linux OS Independent Layer
1148 + *
1149 + * Copyright 2005, Broadcom Corporation
1150 + * All Rights Reserved.
1151 + *
1152 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
1153 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
1154 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
1155 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
1156 + *
1157 + * $Id$
1158 + */
1159 +
1160 +#define LINUX_OSL
1161 +
1162 +#include <typedefs.h>
1163 +#include <bcmendian.h>
1164 +#include <linux/module.h>
1165 +#include <linuxver.h>
1166 +#include <osl.h>
1167 +#include <bcmutils.h>
1168 +#include <linux/delay.h>
1169 +#ifdef mips
1170 +#include <asm/paccess.h>
1171 +#endif
1172 +#include <pcicfg.h>
1173 +
1174 +#define PCI_CFG_RETRY 10
1175 +
1176 +#define OS_HANDLE_MAGIC 0x1234abcd
1177 +#define BCM_MEM_FILENAME_LEN 24
1178 +
1179 +typedef struct bcm_mem_link {
1180 + struct bcm_mem_link *prev;
1181 + struct bcm_mem_link *next;
1182 + uint size;
1183 + int line;
1184 + char file[BCM_MEM_FILENAME_LEN];
1185 +} bcm_mem_link_t;
1186 +
1187 +struct os_handle {
1188 + uint magic;
1189 + void *pdev;
1190 + uint malloced;
1191 + uint failed;
1192 + bcm_mem_link_t *dbgmem_list;
1193 +};
1194 +
1195 +uint32
1196 +osl_pci_read_config(osl_t *osh, uint offset, uint size)
1197 +{
1198 + uint val;
1199 + uint retry=PCI_CFG_RETRY;
1200 +
1201 + ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
1202 +
1203 + /* only 4byte access supported */
1204 + ASSERT(size == 4);
1205 +
1206 + do {
1207 + pci_read_config_dword(osh->pdev, offset, &val);
1208 + if (val != 0xffffffff)
1209 + break;
1210 + } while (retry--);
1211 +
1212 +
1213 + return (val);
1214 +}
1215 +
1216 +void
1217 +osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val)
1218 +{
1219 + uint retry=PCI_CFG_RETRY;
1220 +
1221 + ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
1222 +
1223 + /* only 4byte access supported */
1224 + ASSERT(size == 4);
1225 +
1226 + do {
1227 + pci_write_config_dword(osh->pdev, offset, val);
1228 + if (offset!=PCI_BAR0_WIN)
1229 + break;
1230 + if (osl_pci_read_config(osh,offset,size) == val)
1231 + break;
1232 + } while (retry--);
1233 +
1234 +}
1235 +
1236 +void
1237 +osl_delay(uint usec)
1238 +{
1239 + uint d;
1240 +
1241 + while (usec > 0) {
1242 + d = MIN(usec, 1000);
1243 + udelay(d);
1244 + usec -= d;
1245 + }
1246 +}
1247 +
1248 diff -urN linux.old/arch/mips/bcm947xx/broadcom/nvram.c linux.dev/arch/mips/bcm947xx/broadcom/nvram.c
1249 --- linux.old/arch/mips/bcm947xx/broadcom/nvram.c 1970-01-01 01:00:00.000000000 +0100
1250 +++ linux.dev/arch/mips/bcm947xx/broadcom/nvram.c 2005-12-17 21:41:45.656819500 +0100
1251 @@ -0,0 +1,165 @@
1252 +/*
1253 + * NVRAM variable manipulation (Linux kernel half)
1254 + *
1255 + * Copyright 2005, Broadcom Corporation
1256 + * All Rights Reserved.
1257 + *
1258 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
1259 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
1260 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
1261 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
1262 + *
1263 + * $Id$
1264 + */
1265 +
1266 +#include <linux/config.h>
1267 +#include <linux/init.h>
1268 +#include <linux/module.h>
1269 +#include <linux/kernel.h>
1270 +#include <linux/string.h>
1271 +#include <linux/interrupt.h>
1272 +#include <linux/spinlock.h>
1273 +#include <linux/slab.h>
1274 +#include <asm/bootinfo.h>
1275 +#include <asm/addrspace.h>
1276 +#include <asm/io.h>
1277 +#include <asm/uaccess.h>
1278 +
1279 +#include <typedefs.h>
1280 +#include <bcmendian.h>
1281 +#include <bcmnvram.h>
1282 +#include <bcmutils.h>
1283 +#include <sbconfig.h>
1284 +#include <sbchipc.h>
1285 +#include <sbutils.h>
1286 +#include <sbmips.h>
1287 +#include <sflash.h>
1288 +
1289 +/* In BSS to minimize text size and page aligned so it can be mmap()-ed */
1290 +static char nvram_buf[NVRAM_SPACE] __attribute__((aligned(PAGE_SIZE)));
1291 +
1292 +/* Global SB handle */
1293 +extern void *sbh;
1294 +extern spinlock_t bcm947xx_sbh_lock;
1295 +static int cfe_env;
1296 +
1297 +extern char *cfe_env_get(unsigned char *nv_buf, char *name);
1298 +
1299 +
1300 +/* Convenience */
1301 +#define sbh_lock bcm947xx_sbh_lock
1302 +#define KB * 1024
1303 +#define MB * 1024 * 1024
1304 +
1305 +/* Probe for NVRAM header */
1306 +static void __init
1307 +early_nvram_init(void)
1308 +{
1309 + struct nvram_header *header;
1310 + chipcregs_t *cc;
1311 + struct sflash *info = NULL;
1312 + int i;
1313 + uint32 base, off, lim;
1314 + u32 *src, *dst;
1315 +
1316 + cfe_env = 0;
1317 + if ((cc = sb_setcore(sbh, SB_CC, 0)) != NULL) {
1318 + base = KSEG1ADDR(SB_FLASH2);
1319 + switch (readl(&cc->capabilities) & CAP_FLASH_MASK) {
1320 + case PFLASH:
1321 + lim = SB_FLASH2_SZ;
1322 + break;
1323 +
1324 + case SFLASH_ST:
1325 + case SFLASH_AT:
1326 + if ((info = sflash_init(cc)) == NULL)
1327 + return;
1328 + lim = info->size;
1329 + break;
1330 +
1331 + case FLASH_NONE:
1332 + default:
1333 + return;
1334 + }
1335 + } else {
1336 + /* extif assumed, Stop at 4 MB */
1337 + base = KSEG1ADDR(SB_FLASH1);
1338 + lim = SB_FLASH1_SZ;
1339 + }
1340 +
1341 + /* XXX: hack for supporting the CFE environment stuff on WGT634U */
1342 + src = (u32 *) KSEG1ADDR(base + 8 * 1024 * 1024 - 0x2000);
1343 + dst = (u32 *) nvram_buf;
1344 + if ((lim == 0x02000000) && ((*src & 0xff00ff) == 0x000001)) {
1345 + printk("early_nvram_init: WGT634U NVRAM found.\n");
1346 +
1347 + for (i = 0; i < 0x1ff0; i++) {
1348 + if (*src == 0xFFFFFFFF)
1349 + break;
1350 + *dst++ = *src++;
1351 + }
1352 + cfe_env = 1;
1353 + return;
1354 + }
1355 +
1356 + off = FLASH_MIN;
1357 + while (off <= lim) {
1358 + /* Windowed flash access */
1359 + header = (struct nvram_header *) KSEG1ADDR(base + off - NVRAM_SPACE);
1360 + if (header->magic == NVRAM_MAGIC)
1361 + goto found;
1362 + off <<= 1;
1363 + }
1364 +
1365 + /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
1366 + header = (struct nvram_header *) KSEG1ADDR(base + 4 KB);
1367 + if (header->magic == NVRAM_MAGIC)
1368 + goto found;
1369 +
1370 + header = (struct nvram_header *) KSEG1ADDR(base + 1 KB);
1371 + if (header->magic == NVRAM_MAGIC)
1372 + goto found;
1373 +
1374 + return;
1375 +
1376 +found:
1377 + src = (u32 *) header;
1378 + dst = (u32 *) nvram_buf;
1379 + for (i = 0; i < sizeof(struct nvram_header); i += 4)
1380 + *dst++ = *src++;
1381 + for (; i < header->len && i < NVRAM_SPACE; i += 4)
1382 + *dst++ = ltoh32(*src++);
1383 +}
1384 +
1385 +/* Early (before mm or mtd) read-only access to NVRAM */
1386 +char * __init nvram_get(const char *name)
1387 +{
1388 + char *var, *value, *end, *eq;
1389 +
1390 + if (!name)
1391 + return NULL;
1392 +
1393 + /* Too early? */
1394 + if (sbh == NULL)
1395 + return NULL;
1396 +
1397 + if (!nvram_buf[0])
1398 + early_nvram_init();
1399 +
1400 + if (cfe_env)
1401 + return cfe_env_get(nvram_buf, name);
1402 +
1403 + /* Look for name=value and return value */
1404 + var = &nvram_buf[sizeof(struct nvram_header)];
1405 + end = nvram_buf + sizeof(nvram_buf) - 2;
1406 + end[0] = end[1] = '\0';
1407 + for (; *var; var = value + strlen(value) + 1) {
1408 + if (!(eq = strchr(var, '=')))
1409 + break;
1410 + value = eq + 1;
1411 + if ((eq - var) == strlen(name) && strncmp(var, name, (eq - var)) == 0)
1412 + return value;
1413 + }
1414 +
1415 + return NULL;
1416 +}
1417 diff -urN linux.old/arch/mips/bcm947xx/broadcom/sbmips.c linux.dev/arch/mips/bcm947xx/broadcom/sbmips.c
1418 --- linux.old/arch/mips/bcm947xx/broadcom/sbmips.c 1970-01-01 01:00:00.000000000 +0100
1419 +++ linux.dev/arch/mips/bcm947xx/broadcom/sbmips.c 2005-12-15 16:46:31.122961250 +0100
1420 @@ -0,0 +1,1038 @@
1421 +/*
1422 + * BCM47XX Sonics SiliconBackplane MIPS core routines
1423 + *
1424 + * Copyright 2005, Broadcom Corporation
1425 + * All Rights Reserved.
1426 + *
1427 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
1428 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
1429 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
1430 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
1431 + *
1432 + * $Id$
1433 + */
1434 +
1435 +#include <typedefs.h>
1436 +#include <osl.h>
1437 +#include <sbutils.h>
1438 +#include <bcmdevs.h>
1439 +#include <bcmnvram.h>
1440 +#include <bcmutils.h>
1441 +#include <hndmips.h>
1442 +#include <sbconfig.h>
1443 +#include <sbextif.h>
1444 +#include <sbchipc.h>
1445 +#include <sbmemc.h>
1446 +#include <mipsinc.h>
1447 +#include <sbutils.h>
1448 +
1449 +/*
1450 + * Returns TRUE if an external UART exists at the given base
1451 + * register.
1452 + */
1453 +static bool
1454 +BCMINITFN(serial_exists)(uint8 *regs)
1455 +{
1456 + uint8 save_mcr, status1;
1457 +
1458 + save_mcr = R_REG(&regs[UART_MCR]);
1459 + W_REG(&regs[UART_MCR], UART_MCR_LOOP | 0x0a);
1460 + status1 = R_REG(&regs[UART_MSR]) & 0xf0;
1461 + W_REG(&regs[UART_MCR], save_mcr);
1462 +
1463 + return (status1 == 0x90);
1464 +}
1465 +
1466 +/*
1467 + * Initializes UART access. The callback function will be called once
1468 + * per found UART.
1469 + */
1470 +void
1471 +BCMINITFN(sb_serial_init)(sb_t *sbh, void (*add)(void *regs, uint irq, uint baud_base, uint reg_shift))
1472 +{
1473 + void *regs;
1474 + ulong base;
1475 + uint irq;
1476 + int i, n;
1477 +
1478 + if ((regs = sb_setcore(sbh, SB_EXTIF, 0))) {
1479 + extifregs_t *eir = (extifregs_t *) regs;
1480 + sbconfig_t *sb;
1481 +
1482 + /* Determine external UART register base */
1483 + sb = (sbconfig_t *)((ulong) eir + SBCONFIGOFF);
1484 + base = EXTIF_CFGIF_BASE(sb_base(R_REG(&sb->sbadmatch1)));
1485 +
1486 + /* Determine IRQ */
1487 + irq = sb_irq(sbh);
1488 +
1489 + /* Disable GPIO interrupt initially */
1490 + W_REG(&eir->gpiointpolarity, 0);
1491 + W_REG(&eir->gpiointmask, 0);
1492 +
1493 + /* Search for external UARTs */
1494 + n = 2;
1495 + for (i = 0; i < 2; i++) {
1496 + regs = (void *) REG_MAP(base + (i * 8), 8);
1497 + if (BCMINIT(serial_exists)(regs)) {
1498 + /* Set GPIO 1 to be the external UART IRQ */
1499 + W_REG(&eir->gpiointmask, 2);
1500 + if (add)
1501 + add(regs, irq, 13500000, 0);
1502 + }
1503 + }
1504 +
1505 + /* Add internal UART if enabled */
1506 + if (R_REG(&eir->corecontrol) & CC_UE)
1507 + if (add)
1508 + add((void *) &eir->uartdata, irq, sb_clock(sbh), 2);
1509 + } else if ((regs = sb_setcore(sbh, SB_CC, 0))) {
1510 + chipcregs_t *cc = (chipcregs_t *) regs;
1511 + uint32 rev, cap, pll, baud_base, div;
1512 +
1513 + /* Determine core revision and capabilities */
1514 + rev = sb_corerev(sbh);
1515 + cap = R_REG(&cc->capabilities);
1516 + pll = cap & CAP_PLL_MASK;
1517 +
1518 + /* Determine IRQ */
1519 + irq = sb_irq(sbh);
1520 +
1521 + if (pll == PLL_TYPE1) {
1522 + /* PLL clock */
1523 + baud_base = sb_clock_rate(pll,
1524 + R_REG(&cc->clockcontrol_n),
1525 + R_REG(&cc->clockcontrol_m2));
1526 + div = 1;
1527 + } else {
1528 + if (rev >= 11) {
1529 + /* Fixed ALP clock */
1530 + baud_base = 20000000;
1531 + div = 1;
1532 + /* Set the override bit so we don't divide it */
1533 + W_REG(&cc->corecontrol, CC_UARTCLKO);
1534 + } else if (rev >= 3) {
1535 + /* Internal backplane clock */
1536 + baud_base = sb_clock(sbh);
1537 + div = 2; /* Minimum divisor */
1538 + W_REG(&cc->clkdiv,
1539 + ((R_REG(&cc->clkdiv) & ~CLKD_UART) | div));
1540 + } else {
1541 + /* Fixed internal backplane clock */
1542 + baud_base = 88000000;
1543 + div = 48;
1544 + }
1545 +
1546 + /* Clock source depends on strapping if UartClkOverride is unset */
1547 + if ((rev > 0) &&
1548 + ((R_REG(&cc->corecontrol) & CC_UARTCLKO) == 0)) {
1549 + if ((cap & CAP_UCLKSEL) == CAP_UINTCLK) {
1550 + /* Internal divided backplane clock */
1551 + baud_base /= div;
1552 + } else {
1553 + /* Assume external clock of 1.8432 MHz */
1554 + baud_base = 1843200;
1555 + }
1556 + }
1557 + }
1558 +
1559 + /* Add internal UARTs */
1560 + n = cap & CAP_UARTS_MASK;
1561 + for (i = 0; i < n; i++) {
1562 + /* Register offset changed after revision 0 */
1563 + if (rev)
1564 + regs = (void *)((ulong) &cc->uart0data + (i * 256));
1565 + else
1566 + regs = (void *)((ulong) &cc->uart0data + (i * 8));
1567 +
1568 + if (add)
1569 + add(regs, irq, baud_base, 0);
1570 + }
1571 + }
1572 +}
1573 +
1574 +/*
1575 + * Initialize jtag master and return handle for
1576 + * jtag_rwreg. Returns NULL on failure.
1577 + */
1578 +void *
1579 +sb_jtagm_init(sb_t *sbh, uint clkd, bool exttap)
1580 +{
1581 + void *regs;
1582 +
1583 + if ((regs = sb_setcore(sbh, SB_CC, 0)) != NULL) {
1584 + chipcregs_t *cc = (chipcregs_t *) regs;
1585 + uint32 tmp;
1586 +
1587 + /*
1588 + * Determine jtagm availability from
1589 + * core revision and capabilities.
1590 + */
1591 + tmp = sb_corerev(sbh);
1592 + /*
1593 + * Corerev 10 has jtagm, but the only chip
1594 + * with it does not have a mips, and
1595 + * the layout of the jtagcmd register is
1596 + * different. We'll only accept >= 11.
1597 + */
1598 + if (tmp < 11)
1599 + return (NULL);
1600 +
1601 + tmp = R_REG(&cc->capabilities);
1602 + if ((tmp & CAP_JTAGP) == 0)
1603 + return (NULL);
1604 +
1605 + /* Set clock divider if requested */
1606 + if (clkd != 0) {
1607 + tmp = R_REG(&cc->clkdiv);
1608 + tmp = (tmp & ~CLKD_JTAG) |
1609 + ((clkd << CLKD_JTAG_SHIFT) & CLKD_JTAG);
1610 + W_REG(&cc->clkdiv, tmp);
1611 + }
1612 +
1613 + /* Enable jtagm */
1614 + tmp = JCTRL_EN | (exttap ? JCTRL_EXT_EN : 0);
1615 + W_REG(&cc->jtagctrl, tmp);
1616 + }
1617 +
1618 + return (regs);
1619 +}
1620 +
1621 +void
1622 +sb_jtagm_disable(void *h)
1623 +{
1624 + chipcregs_t *cc = (chipcregs_t *)h;
1625 +
1626 + W_REG(&cc->jtagctrl, R_REG(&cc->jtagctrl) & ~JCTRL_EN);
1627 +}
1628 +
1629 +/*
1630 + * Read/write a jtag register. Assumes a target with
1631 + * 8 bit IR and 32 bit DR.
1632 + */
1633 +#define IRWIDTH 8
1634 +#define DRWIDTH 32
1635 +uint32
1636 +jtag_rwreg(void *h, uint32 ir, uint32 dr)
1637 +{
1638 + chipcregs_t *cc = (chipcregs_t *) h;
1639 + uint32 tmp;
1640 +
1641 + W_REG(&cc->jtagir, ir);
1642 + W_REG(&cc->jtagdr, dr);
1643 + tmp = JCMD_START | JCMD_ACC_IRDR |
1644 + ((IRWIDTH - 1) << JCMD_IRW_SHIFT) |
1645 + (DRWIDTH - 1);
1646 + W_REG(&cc->jtagcmd, tmp);
1647 + while (((tmp = R_REG(&cc->jtagcmd)) & JCMD_BUSY) == JCMD_BUSY) {
1648 + /* OSL_DELAY(1); */
1649 + }
1650 +
1651 + tmp = R_REG(&cc->jtagdr);
1652 + return (tmp);
1653 +}
1654 +
1655 +/* Returns the SB interrupt flag of the current core. */
1656 +uint32
1657 +sb_flag(sb_t *sbh)
1658 +{
1659 + void *regs;
1660 + sbconfig_t *sb;
1661 +
1662 + regs = sb_coreregs(sbh);
1663 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
1664 +
1665 + return (R_REG(&sb->sbtpsflag) & SBTPS_NUM0_MASK);
1666 +}
1667 +
1668 +static const uint32 sbips_int_mask[] = {
1669 + 0,
1670 + SBIPS_INT1_MASK,
1671 + SBIPS_INT2_MASK,
1672 + SBIPS_INT3_MASK,
1673 + SBIPS_INT4_MASK
1674 +};
1675 +
1676 +static const uint32 sbips_int_shift[] = {
1677 + 0,
1678 + 0,
1679 + SBIPS_INT2_SHIFT,
1680 + SBIPS_INT3_SHIFT,
1681 + SBIPS_INT4_SHIFT
1682 +};
1683 +
1684 +/*
1685 + * Returns the MIPS IRQ assignment of the current core. If unassigned,
1686 + * 0 is returned.
1687 + */
1688 +uint
1689 +sb_irq(sb_t *sbh)
1690 +{
1691 + uint idx;
1692 + void *regs;
1693 + sbconfig_t *sb;
1694 + uint32 flag, sbipsflag;
1695 + uint irq = 0;
1696 +
1697 + flag = sb_flag(sbh);
1698 +
1699 + idx = sb_coreidx(sbh);
1700 +
1701 + if ((regs = sb_setcore(sbh, SB_MIPS, 0)) ||
1702 + (regs = sb_setcore(sbh, SB_MIPS33, 0))) {
1703 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
1704 +
1705 + /* sbipsflag specifies which core is routed to interrupts 1 to 4 */
1706 + sbipsflag = R_REG(&sb->sbipsflag);
1707 + for (irq = 1; irq <= 4; irq++) {
1708 + if (((sbipsflag & sbips_int_mask[irq]) >> sbips_int_shift[irq]) == flag)
1709 + break;
1710 + }
1711 + if (irq == 5)
1712 + irq = 0;
1713 + }
1714 +
1715 + sb_setcoreidx(sbh, idx);
1716 +
1717 + return irq;
1718 +}
1719 +
1720 +/* Clears the specified MIPS IRQ. */
1721 +static void
1722 +BCMINITFN(sb_clearirq)(sb_t *sbh, uint irq)
1723 +{
1724 + void *regs;
1725 + sbconfig_t *sb;
1726 +
1727 + if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) &&
1728 + !(regs = sb_setcore(sbh, SB_MIPS33, 0)))
1729 + ASSERT(regs);
1730 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
1731 +
1732 + if (irq == 0)
1733 + W_REG(&sb->sbintvec, 0);
1734 + else
1735 + OR_REG(&sb->sbipsflag, sbips_int_mask[irq]);
1736 +}
1737 +
1738 +/*
1739 + * Assigns the specified MIPS IRQ to the specified core. Shared MIPS
1740 + * IRQ 0 may be assigned more than once.
1741 + */
1742 +static void
1743 +BCMINITFN(sb_setirq)(sb_t *sbh, uint irq, uint coreid, uint coreunit)
1744 +{
1745 + void *regs;
1746 + sbconfig_t *sb;
1747 + uint32 flag;
1748 +
1749 + regs = sb_setcore(sbh, coreid, coreunit);
1750 + ASSERT(regs);
1751 + flag = sb_flag(sbh);
1752 +
1753 + if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) &&
1754 + !(regs = sb_setcore(sbh, SB_MIPS33, 0)))
1755 + ASSERT(regs);
1756 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
1757 +
1758 + if (irq == 0)
1759 + OR_REG(&sb->sbintvec, 1 << flag);
1760 + else {
1761 + flag <<= sbips_int_shift[irq];
1762 + ASSERT(!(flag & ~sbips_int_mask[irq]));
1763 + flag |= R_REG(&sb->sbipsflag) & ~sbips_int_mask[irq];
1764 + W_REG(&sb->sbipsflag, flag);
1765 + }
1766 +}
1767 +
1768 +/*
1769 + * Initializes clocks and interrupts. SB and NVRAM access must be
1770 + * initialized prior to calling.
1771 + */
1772 +void
1773 +BCMINITFN(sb_mips_init)(sb_t *sbh)
1774 +{
1775 + ulong hz, ns, tmp;
1776 + extifregs_t *eir;
1777 + chipcregs_t *cc;
1778 + char *value;
1779 + uint irq;
1780 +
1781 + /* Figure out current SB clock speed */
1782 + if ((hz = sb_clock(sbh)) == 0)
1783 + hz = 100000000;
1784 + ns = 1000000000 / hz;
1785 +
1786 + /* Setup external interface timing */
1787 + if ((eir = sb_setcore(sbh, SB_EXTIF, 0))) {
1788 + /* Initialize extif so we can get to the LEDs and external UART */
1789 + W_REG(&eir->prog_config, CF_EN);
1790 +
1791 + /* Set timing for the flash */
1792 + tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
1793 + tmp = tmp | (CEIL(40, ns) << FW_W1_SHIFT); /* W1 = 40nS */
1794 + tmp = tmp | CEIL(120, ns); /* W0 = 120nS */
1795 + W_REG(&eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */
1796 +
1797 + /* Set programmable interface timing for external uart */
1798 + tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
1799 + tmp = tmp | (CEIL(20, ns) << FW_W2_SHIFT); /* W2 = 20nS */
1800 + tmp = tmp | (CEIL(100, ns) << FW_W1_SHIFT); /* W1 = 100nS */
1801 + tmp = tmp | CEIL(120, ns); /* W0 = 120nS */
1802 + W_REG(&eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */
1803 + } else if ((cc = sb_setcore(sbh, SB_CC, 0))) {
1804 + /* Set timing for the flash */
1805 + tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
1806 + tmp |= CEIL(10, ns) << FW_W1_SHIFT; /* W1 = 10nS */
1807 + tmp |= CEIL(120, ns); /* W0 = 120nS */
1808 +
1809 + // Added by Chen-I for 5365
1810 + if (BCMINIT(sb_chip)(sbh) == BCM5365_DEVICE_ID)
1811 + {
1812 + W_REG(&cc->flash_waitcount, tmp);
1813 + W_REG(&cc->pcmcia_memwait, tmp);
1814 + }
1815 + else
1816 + {
1817 + if (sb_corerev(sbh) < 9)
1818 + W_REG(&cc->flash_waitcount, tmp);
1819 +
1820 + if ((sb_corerev(sbh) < 9) ||
1821 + ((BCMINIT(sb_chip)(sbh) == BCM5350_DEVICE_ID) && BCMINIT(sb_chiprev)(sbh) == 0)) {
1822 + W_REG(&cc->pcmcia_memwait, tmp);
1823 + }
1824 + }
1825 + }
1826 +
1827 + /* Chip specific initialization */
1828 + switch (BCMINIT(sb_chip)(sbh)) {
1829 + case BCM4710_DEVICE_ID:
1830 + /* Clear interrupt map */
1831 + for (irq = 0; irq <= 4; irq++)
1832 + BCMINIT(sb_clearirq)(sbh, irq);
1833 + BCMINIT(sb_setirq)(sbh, 0, SB_CODEC, 0);
1834 + BCMINIT(sb_setirq)(sbh, 0, SB_EXTIF, 0);
1835 + BCMINIT(sb_setirq)(sbh, 2, SB_ENET, 1);
1836 + BCMINIT(sb_setirq)(sbh, 3, SB_ILINE20, 0);
1837 + BCMINIT(sb_setirq)(sbh, 4, SB_PCI, 0);
1838 + ASSERT(eir);
1839 + value = BCMINIT(nvram_get)("et0phyaddr");
1840 + if (value && !strcmp(value, "31")) {
1841 + /* Enable internal UART */
1842 + W_REG(&eir->corecontrol, CC_UE);
1843 + /* Give USB its own interrupt */
1844 + BCMINIT(sb_setirq)(sbh, 1, SB_USB, 0);
1845 + } else {
1846 + /* Disable internal UART */
1847 + W_REG(&eir->corecontrol, 0);
1848 + /* Give Ethernet its own interrupt */
1849 + BCMINIT(sb_setirq)(sbh, 1, SB_ENET, 0);
1850 + BCMINIT(sb_setirq)(sbh, 0, SB_USB, 0);
1851 + }
1852 + break;
1853 + case BCM5350_DEVICE_ID:
1854 + /* Clear interrupt map */
1855 + for (irq = 0; irq <= 4; irq++)
1856 + BCMINIT(sb_clearirq)(sbh, irq);
1857 + BCMINIT(sb_setirq)(sbh, 0, SB_CC, 0);
1858 + BCMINIT(sb_setirq)(sbh, 1, SB_D11, 0);
1859 + BCMINIT(sb_setirq)(sbh, 2, SB_ENET, 0);
1860 + BCMINIT(sb_setirq)(sbh, 3, SB_PCI, 0);
1861 + BCMINIT(sb_setirq)(sbh, 4, SB_USB, 0);
1862 + break;
1863 + }
1864 +}
1865 +
1866 +uint32
1867 +BCMINITFN(sb_mips_clock)(sb_t *sbh)
1868 +{
1869 + extifregs_t *eir;
1870 + chipcregs_t *cc;
1871 + uint32 n, m;
1872 + uint idx;
1873 + uint32 pll_type, rate = 0;
1874 +
1875 + /* get index of the current core */
1876 + idx = sb_coreidx(sbh);
1877 + pll_type = PLL_TYPE1;
1878 +
1879 + /* switch to extif or chipc core */
1880 + if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) {
1881 + n = R_REG(&eir->clockcontrol_n);
1882 + m = R_REG(&eir->clockcontrol_sb);
1883 + } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) {
1884 + pll_type = R_REG(&cc->capabilities) & CAP_PLL_MASK;
1885 + n = R_REG(&cc->clockcontrol_n);
1886 + if ((pll_type == PLL_TYPE2) ||
1887 + (pll_type == PLL_TYPE4) ||
1888 + (pll_type == PLL_TYPE6) ||
1889 + (pll_type == PLL_TYPE7))
1890 + m = R_REG(&cc->clockcontrol_mips);
1891 + else if (pll_type == PLL_TYPE5) {
1892 + rate = 200000000;
1893 + goto out;
1894 + }
1895 + else if (pll_type == PLL_TYPE3) {
1896 + if (BCMINIT(sb_chip)(sbh) == BCM5365_DEVICE_ID) { /* 5365 is also type3 */
1897 + rate = 200000000;
1898 + goto out;
1899 + } else
1900 + m = R_REG(&cc->clockcontrol_m2); /* 5350 uses m2 to control mips */
1901 + } else
1902 + m = R_REG(&cc->clockcontrol_sb);
1903 + } else
1904 + goto out;
1905 +
1906 + // Added by Chen-I for 5365
1907 + if (BCMINIT(sb_chip)(sbh) == BCM5365_DEVICE_ID)
1908 + rate = 100000000;
1909 + else
1910 + /* calculate rate */
1911 + rate = sb_clock_rate(pll_type, n, m);
1912 +
1913 + if (pll_type == PLL_TYPE6)
1914 + rate = SB2MIPS_T6(rate);
1915 +
1916 +out:
1917 + /* switch back to previous core */
1918 + sb_setcoreidx(sbh, idx);
1919 +
1920 + return rate;
1921 +}
1922 +
1923 +#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
1924 +
1925 +static void
1926 +BCMINITFN(handler)(void)
1927 +{
1928 + /* Step 11 */
1929 + __asm__ (
1930 + ".set\tmips32\n\t"
1931 + "ssnop\n\t"
1932 + "ssnop\n\t"
1933 + /* Disable interrupts */
1934 + /* MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~(ALLINTS | STO_IE)); */
1935 + "mfc0 $15, $12\n\t"
1936 + /* Just a Hack to not to use reg 'at' which was causing problems on 4704 A2 */
1937 + "li $14, -31746\n\t"
1938 + "and $15, $15, $14\n\t"
1939 + "mtc0 $15, $12\n\t"
1940 + "eret\n\t"
1941 + "nop\n\t"
1942 + "nop\n\t"
1943 + ".set\tmips0"
1944 + );
1945 +}
1946 +
1947 +/* The following MUST come right after handler() */
1948 +static void
1949 +BCMINITFN(afterhandler)(void)
1950 +{
1951 +}
1952 +
1953 +/*
1954 + * Set the MIPS, backplane and PCI clocks as closely as possible.
1955 + */
1956 +bool
1957 +BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 pciclock)
1958 +{
1959 + extifregs_t *eir = NULL;
1960 + chipcregs_t *cc = NULL;
1961 + mipsregs_t *mipsr = NULL;
1962 + volatile uint32 *clockcontrol_n, *clockcontrol_sb, *clockcontrol_pci, *clockcontrol_m2;
1963 + uint32 orig_n, orig_sb, orig_pci, orig_m2, orig_mips, orig_ratio_parm, orig_ratio_cfg;
1964 + uint32 pll_type, sync_mode;
1965 + uint ic_size, ic_lsize;
1966 + uint idx, i;
1967 + typedef struct {
1968 + uint32 mipsclock;
1969 + uint16 n;
1970 + uint32 sb;
1971 + uint32 pci33;
1972 + uint32 pci25;
1973 + } n3m_table_t;
1974 + static n3m_table_t BCMINITDATA(type1_table)[] = {
1975 + { 96000000, 0x0303, 0x04020011, 0x11030011, 0x11050011 }, /* 96.000 32.000 24.000 */
1976 + { 100000000, 0x0009, 0x04020011, 0x11030011, 0x11050011 }, /* 100.000 33.333 25.000 */
1977 + { 104000000, 0x0802, 0x04020011, 0x11050009, 0x11090009 }, /* 104.000 31.200 24.960 */
1978 + { 108000000, 0x0403, 0x04020011, 0x11050009, 0x02000802 }, /* 108.000 32.400 24.923 */
1979 + { 112000000, 0x0205, 0x04020011, 0x11030021, 0x02000403 }, /* 112.000 32.000 24.889 */
1980 + { 115200000, 0x0303, 0x04020009, 0x11030011, 0x11050011 }, /* 115.200 32.000 24.000 */
1981 + { 120000000, 0x0011, 0x04020011, 0x11050011, 0x11090011 }, /* 120.000 30.000 24.000 */
1982 + { 124800000, 0x0802, 0x04020009, 0x11050009, 0x11090009 }, /* 124.800 31.200 24.960 */
1983 + { 128000000, 0x0305, 0x04020011, 0x11050011, 0x02000305 }, /* 128.000 32.000 24.000 */
1984 + { 132000000, 0x0603, 0x04020011, 0x11050011, 0x02000305 }, /* 132.000 33.000 24.750 */
1985 + { 136000000, 0x0c02, 0x04020011, 0x11090009, 0x02000603 }, /* 136.000 32.640 24.727 */
1986 + { 140000000, 0x0021, 0x04020011, 0x11050021, 0x02000c02 }, /* 140.000 30.000 24.706 */
1987 + { 144000000, 0x0405, 0x04020011, 0x01020202, 0x11090021 }, /* 144.000 30.857 24.686 */
1988 + { 150857142, 0x0605, 0x04020021, 0x02000305, 0x02000605 }, /* 150.857 33.000 24.000 */
1989 + { 152000000, 0x0e02, 0x04020011, 0x11050021, 0x02000e02 }, /* 152.000 32.571 24.000 */
1990 + { 156000000, 0x0802, 0x04020005, 0x11050009, 0x11090009 }, /* 156.000 31.200 24.960 */
1991 + { 160000000, 0x0309, 0x04020011, 0x11090011, 0x02000309 }, /* 160.000 32.000 24.000 */
1992 + { 163200000, 0x0c02, 0x04020009, 0x11090009, 0x02000603 }, /* 163.200 32.640 24.727 */
1993 + { 168000000, 0x0205, 0x04020005, 0x11030021, 0x02000403 }, /* 168.000 32.000 24.889 */
1994 + { 176000000, 0x0602, 0x04020003, 0x11050005, 0x02000602 }, /* 176.000 33.000 24.000 */
1995 + };
1996 + typedef struct {
1997 + uint32 mipsclock;
1998 + uint16 n;
1999 + uint32 m2; /* that is the clockcontrol_m2 */
2000 + } type3_table_t;
2001 + static type3_table_t type3_table[] = { /* for 5350, mips clock is always double sb clock */
2002 + { 150000000, 0x311, 0x4020005 },
2003 + { 200000000, 0x311, 0x4020003 },
2004 + };
2005 + typedef struct {
2006 + uint32 mipsclock;
2007 + uint32 sbclock;
2008 + uint16 n;
2009 + uint32 sb;
2010 + uint32 pci33;
2011 + uint32 m2;
2012 + uint32 m3;
2013 + uint32 ratio_cfg;
2014 + uint32 ratio_parm;
2015 + } n4m_table_t;
2016 +
2017 + static n4m_table_t BCMINITDATA(type2_table)[] = {
2018 + { 180000000, 80000000, 0x0403, 0x01010000, 0x01020300, 0x01020600, 0x05000100, 8, 0x012a00a9 },
2019 + { 180000000, 90000000, 0x0403, 0x01000100, 0x01020300, 0x01000100, 0x05000100, 11, 0x0aaa0555 },
2020 + { 200000000, 100000000, 0x0303, 0x02010000, 0x02040001, 0x02010000, 0x06000001, 11, 0x0aaa0555 },
2021 + { 211200000, 105600000, 0x0902, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
2022 + { 220800000, 110400000, 0x1500, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
2023 + { 230400000, 115200000, 0x0604, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
2024 + { 234000000, 104000000, 0x0b01, 0x01010000, 0x01010700, 0x01020600, 0x05000100, 8, 0x012a00a9 },
2025 + { 240000000, 120000000, 0x0803, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
2026 + { 252000000, 126000000, 0x0504, 0x01000100, 0x01020500, 0x01000100, 0x05000100, 11, 0x0aaa0555 },
2027 + { 264000000, 132000000, 0x0903, 0x01000200, 0x01020700, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
2028 + { 270000000, 120000000, 0x0703, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9 },
2029 + { 276000000, 122666666, 0x1500, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9 },
2030 + { 280000000, 140000000, 0x0503, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 11, 0x0aaa0555 },
2031 + { 288000000, 128000000, 0x0604, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9 },
2032 + { 288000000, 144000000, 0x0404, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 11, 0x0aaa0555 },
2033 + { 300000000, 133333333, 0x0803, 0x01010000, 0x01020600, 0x01020600, 0x05000100, 8, 0x012a00a9 },
2034 + { 300000000, 150000000, 0x0803, 0x01000100, 0x01020600, 0x01000100, 0x05000100, 11, 0x0aaa0555 }
2035 + };
2036 +
2037 + static n4m_table_t BCMINITDATA(type4_table)[] = {
2038 + { 192000000, 96000000, 0x0702, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, 0x0aaa0555 },
2039 + { 198000000, 99000000, 0x0603, 0x11020005, 0x11030011, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2040 + { 200000000, 100000000, 0x0009, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 11, 0x0aaa0555 },
2041 + { 204000000, 102000000, 0x0c02, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2042 + { 208000000, 104000000, 0x0802, 0x11030002, 0x11090005, 0x11030002, 0x04000003, 11, 0x0aaa0555 },
2043 + { 210000000, 105000000, 0x0209, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2044 + { 216000000, 108000000, 0x0111, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2045 + { 224000000, 112000000, 0x0205, 0x11030002, 0x02002103, 0x11030002, 0x04000003, 11, 0x0aaa0555 },
2046 + { 228000000, 101333333, 0x0e02, 0x11030003, 0x11210005, 0x01030305, 0x04000005, 8, 0x012a00a9 },
2047 + { 228000000, 114000000, 0x0e02, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2048 + { 240000000, 102857143, 0x0109, 0x04000021, 0x01050203, 0x11030021, 0x04000003, 13, 0x254a14a9 },
2049 + { 240000000, 120000000, 0x0109, 0x11030002, 0x01050203, 0x11030002, 0x04000003, 11, 0x0aaa0555 },
2050 + { 252000000, 100800000, 0x0203, 0x04000009, 0x11050005, 0x02000209, 0x04000002, 9, 0x02520129 },
2051 + { 252000000, 126000000, 0x0203, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 11, 0x0aaa0555 },
2052 + { 264000000, 132000000, 0x0602, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 11, 0x0aaa0555 },
2053 + { 272000000, 116571428, 0x0c02, 0x04000021, 0x02000909, 0x02000221, 0x04000003, 13, 0x254a14a9 },
2054 + { 280000000, 120000000, 0x0209, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 13, 0x254a14a9 },
2055 + { 288000000, 123428571, 0x0111, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 13, 0x254a14a9 },
2056 + { 300000000, 120000000, 0x0009, 0x04000009, 0x01030203, 0x02000902, 0x04000002, 9, 0x02520129 },
2057 + { 300000000, 150000000, 0x0009, 0x04000005, 0x01030203, 0x04000005, 0x04000002, 11, 0x0aaa0555 }
2058 + };
2059 +
2060 + static n4m_table_t BCMINITDATA(type7_table)[] = {
2061 + { 183333333, 91666666, 0x0605, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, 0x0aaa0555 },
2062 + { 187500000, 93750000, 0x0a03, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, 0x0aaa0555 },
2063 + { 196875000, 98437500, 0x1003, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2064 + { 200000000, 100000000, 0x0311, 0x04000011, 0x11030011, 0x04000009, 0x04000003, 11, 0x0aaa0555 },
2065 + { 200000000, 100000000, 0x0311, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 11, 0x0aaa0555 },
2066 + { 206250000, 103125000, 0x1103, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2067 + { 212500000, 106250000, 0x0c05, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2068 + { 215625000, 107812500, 0x1203, 0x11090009, 0x11050005, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2069 + { 216666666, 108333333, 0x0805, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, 0x0aaa0555 },
2070 + { 225000000, 112500000, 0x0d03, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, 0x0aaa0555 },
2071 + { 233333333, 116666666, 0x0905, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, 0x0aaa0555 },
2072 + { 237500000, 118750000, 0x0e05, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2073 + { 240000000, 120000000, 0x0b11, 0x11020009, 0x11210009, 0x11020009, 0x04000009, 11, 0x0aaa0555 },
2074 + { 250000000, 125000000, 0x0f03, 0x11020003, 0x11210003, 0x11020003, 0x04000003, 11, 0x0aaa0555 }
2075 + };
2076 +
2077 + ulong start, end, dst;
2078 + bool ret = FALSE;
2079 +
2080 + /* get index of the current core */
2081 + idx = sb_coreidx(sbh);
2082 + clockcontrol_m2 = NULL;
2083 +
2084 + /* switch to extif or chipc core */
2085 + if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) {
2086 + pll_type = PLL_TYPE1;
2087 + clockcontrol_n = &eir->clockcontrol_n;
2088 + clockcontrol_sb = &eir->clockcontrol_sb;
2089 + clockcontrol_pci = &eir->clockcontrol_pci;
2090 + clockcontrol_m2 = &cc->clockcontrol_m2;
2091 + } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) {
2092 + pll_type = R_REG(&cc->capabilities) & CAP_PLL_MASK;
2093 + if (pll_type == PLL_TYPE6) {
2094 + clockcontrol_n = NULL;
2095 + clockcontrol_sb = NULL;
2096 + clockcontrol_pci = NULL;
2097 + } else {
2098 + clockcontrol_n = &cc->clockcontrol_n;
2099 + clockcontrol_sb = &cc->clockcontrol_sb;
2100 + clockcontrol_pci = &cc->clockcontrol_pci;
2101 + clockcontrol_m2 = &cc->clockcontrol_m2;
2102 + }
2103 + } else
2104 + goto done;
2105 +
2106 + if (pll_type == PLL_TYPE6) {
2107 + /* Silence compilers */
2108 + orig_n = orig_sb = orig_pci = 0;
2109 + } else {
2110 + /* Store the current clock register values */
2111 + orig_n = R_REG(clockcontrol_n);
2112 + orig_sb = R_REG(clockcontrol_sb);
2113 + orig_pci = R_REG(clockcontrol_pci);
2114 + }
2115 +
2116 + if (pll_type == PLL_TYPE1) {
2117 + /* Keep the current PCI clock if not specified */
2118 + if (pciclock == 0) {
2119 + pciclock = sb_clock_rate(pll_type, R_REG(clockcontrol_n), R_REG(clockcontrol_pci));
2120 + pciclock = (pciclock <= 25000000) ? 25000000 : 33000000;
2121 + }
2122 +
2123 + /* Search for the closest MIPS clock less than or equal to a preferred value */
2124 + for (i = 0; i < ARRAYSIZE(BCMINIT(type1_table)); i++) {
2125 + ASSERT(BCMINIT(type1_table)[i].mipsclock ==
2126 + sb_clock_rate(pll_type, BCMINIT(type1_table)[i].n, BCMINIT(type1_table)[i].sb));
2127 + if (BCMINIT(type1_table)[i].mipsclock > mipsclock)
2128 + break;
2129 + }
2130 + if (i == 0) {
2131 + ret = FALSE;
2132 + goto done;
2133 + } else {
2134 + ret = TRUE;
2135 + i--;
2136 + }
2137 + ASSERT(BCMINIT(type1_table)[i].mipsclock <= mipsclock);
2138 +
2139 + /* No PLL change */
2140 + if ((orig_n == BCMINIT(type1_table)[i].n) &&
2141 + (orig_sb == BCMINIT(type1_table)[i].sb) &&
2142 + (orig_pci == BCMINIT(type1_table)[i].pci33))
2143 + goto done;
2144 +
2145 + /* Set the PLL controls */
2146 + W_REG(clockcontrol_n, BCMINIT(type1_table)[i].n);
2147 + W_REG(clockcontrol_sb, BCMINIT(type1_table)[i].sb);
2148 + if (pciclock == 25000000)
2149 + W_REG(clockcontrol_pci, BCMINIT(type1_table)[i].pci25);
2150 + else
2151 + W_REG(clockcontrol_pci, BCMINIT(type1_table)[i].pci33);
2152 +
2153 + /* Reset */
2154 + sb_watchdog(sbh, 1);
2155 +
2156 + while (1);
2157 + } else if ((pll_type == PLL_TYPE3) &&
2158 + (BCMINIT(sb_chip)(sbh) != BCM5365_DEVICE_ID)) {
2159 + /* 5350 */
2160 + /* Search for the closest MIPS clock less than or equal to a preferred value */
2161 +
2162 + for (i = 0; i < ARRAYSIZE(type3_table); i++) {
2163 + if (type3_table[i].mipsclock > mipsclock)
2164 + break;
2165 + }
2166 + if (i == 0) {
2167 + ret = FALSE;
2168 + goto done;
2169 + } else {
2170 + ret = TRUE;
2171 + i--;
2172 + }
2173 + ASSERT(type3_table[i].mipsclock <= mipsclock);
2174 +
2175 + /* No PLL change */
2176 + orig_m2 = R_REG(&cc->clockcontrol_m2);
2177 + if ((orig_n == type3_table[i].n) &&
2178 + (orig_m2 == type3_table[i].m2)) {
2179 + goto done;
2180 + }
2181 +
2182 + /* Set the PLL controls */
2183 + W_REG(clockcontrol_n, type3_table[i].n);
2184 + W_REG(clockcontrol_m2, type3_table[i].m2);
2185 +
2186 + /* Reset */
2187 + sb_watchdog(sbh, 1);
2188 + while (1);
2189 + } else if ((pll_type == PLL_TYPE2) ||
2190 + (pll_type == PLL_TYPE4) ||
2191 + (pll_type == PLL_TYPE6) ||
2192 + (pll_type == PLL_TYPE7)) {
2193 + n4m_table_t *table = NULL, *te;
2194 + uint tabsz = 0;
2195 +
2196 + ASSERT(cc);
2197 +
2198 + orig_mips = R_REG(&cc->clockcontrol_mips);
2199 +
2200 + if (pll_type == PLL_TYPE6) {
2201 + uint32 new_mips = 0;
2202 +
2203 + ret = TRUE;
2204 + if (mipsclock <= SB2MIPS_T6(CC_T6_M1))
2205 + new_mips = CC_T6_MMASK;
2206 +
2207 + if (orig_mips == new_mips)
2208 + goto done;
2209 +
2210 + W_REG(&cc->clockcontrol_mips, new_mips);
2211 + goto end_fill;
2212 + }
2213 +
2214 + if (pll_type == PLL_TYPE2) {
2215 + table = BCMINIT(type2_table);
2216 + tabsz = ARRAYSIZE(BCMINIT(type2_table));
2217 + } else if (pll_type == PLL_TYPE4) {
2218 + table = BCMINIT(type4_table);
2219 + tabsz = ARRAYSIZE(BCMINIT(type4_table));
2220 + } else if (pll_type == PLL_TYPE7) {
2221 + table = BCMINIT(type7_table);
2222 + tabsz = ARRAYSIZE(BCMINIT(type7_table));
2223 + } else
2224 + ASSERT("No table for plltype" == NULL);
2225 +
2226 + /* Store the current clock register values */
2227 + orig_m2 = R_REG(&cc->clockcontrol_m2);
2228 + orig_ratio_parm = 0;
2229 + orig_ratio_cfg = 0;
2230 +
2231 + /* Look up current ratio */
2232 + for (i = 0; i < tabsz; i++) {
2233 + if ((orig_n == table[i].n) &&
2234 + (orig_sb == table[i].sb) &&
2235 + (orig_pci == table[i].pci33) &&
2236 + (orig_m2 == table[i].m2) &&
2237 + (orig_mips == table[i].m3)) {
2238 + orig_ratio_parm = table[i].ratio_parm;
2239 + orig_ratio_cfg = table[i].ratio_cfg;
2240 + break;
2241 + }
2242 + }
2243 +
2244 + /* Search for the closest MIPS clock greater or equal to a preferred value */
2245 + for (i = 0; i < tabsz; i++) {
2246 + ASSERT(table[i].mipsclock ==
2247 + sb_clock_rate(pll_type, table[i].n, table[i].m3));
2248 + if ((mipsclock <= table[i].mipsclock) &&
2249 + ((sbclock == 0) || (sbclock <= table[i].sbclock)))
2250 + break;
2251 + }
2252 + if (i == tabsz) {
2253 + ret = FALSE;
2254 + goto done;
2255 + } else {
2256 + te = &table[i];
2257 + ret = TRUE;
2258 + }
2259 +
2260 + /* No PLL change */
2261 + if ((orig_n == te->n) &&
2262 + (orig_sb == te->sb) &&
2263 + (orig_pci == te->pci33) &&
2264 + (orig_m2 == te->m2) &&
2265 + (orig_mips == te->m3))
2266 + goto done;
2267 +
2268 + /* Set the PLL controls */
2269 + W_REG(clockcontrol_n, te->n);
2270 + W_REG(clockcontrol_sb, te->sb);
2271 + W_REG(clockcontrol_pci, te->pci33);
2272 + W_REG(&cc->clockcontrol_m2, te->m2);
2273 + W_REG(&cc->clockcontrol_mips, te->m3);
2274 +
2275 + /* Set the chipcontrol bit to change mipsref to the backplane divider if needed */
2276 + if ((pll_type == PLL_TYPE7) &&
2277 + (te->sb != te->m2) &&
2278 + (sb_clock_rate(pll_type, te->n, te->m2) == 120000000))
2279 + W_REG(&cc->chipcontrol, R_REG(&cc->chipcontrol) | 0x100);
2280 +
2281 + /* No ratio change */
2282 + if (orig_ratio_parm == te->ratio_parm)
2283 + goto end_fill;
2284 +
2285 + icache_probe(MFC0(C0_CONFIG, 1), &ic_size, &ic_lsize);
2286 +
2287 + /* Preload the code into the cache */
2288 + start = ((ulong) &&start_fill) & ~(ic_lsize - 1);
2289 + end = ((ulong) &&end_fill + (ic_lsize - 1)) & ~(ic_lsize - 1);
2290 + while (start < end) {
2291 + cache_op(start, Fill_I);
2292 + start += ic_lsize;
2293 + }
2294 +
2295 + /* Copy the handler */
2296 + start = (ulong) &BCMINIT(handler);
2297 + end = (ulong) &BCMINIT(afterhandler);
2298 + dst = KSEG1ADDR(0x180);
2299 + for (i = 0; i < (end - start); i += 4)
2300 + *((ulong *)(dst + i)) = *((ulong *)(start + i));
2301 +
2302 + /* Preload handler into the cache one line at a time */
2303 + for (i = 0; i < (end - start); i += 4)
2304 + cache_op(dst + i, Fill_I);
2305 +
2306 + /* Clear BEV bit */
2307 + MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~ST0_BEV);
2308 +
2309 + /* Enable interrupts */
2310 + MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) | (ALLINTS | ST0_IE));
2311 +
2312 + /* Enable MIPS timer interrupt */
2313 + if (!(mipsr = sb_setcore(sbh, SB_MIPS, 0)) &&
2314 + !(mipsr = sb_setcore(sbh, SB_MIPS33, 0)))
2315 + ASSERT(mipsr);
2316 + W_REG(&mipsr->intmask, 1);
2317 +
2318 + start_fill:
2319 + /* step 1, set clock ratios */
2320 + MTC0(C0_BROADCOM, 3, te->ratio_parm);
2321 + MTC0(C0_BROADCOM, 1, te->ratio_cfg);
2322 +
2323 + /* step 2: program timer intr */
2324 + W_REG(&mipsr->timer, 100);
2325 + (void) R_REG(&mipsr->timer);
2326 +
2327 + /* step 3, switch to async */
2328 + sync_mode = MFC0(C0_BROADCOM, 4);
2329 + MTC0(C0_BROADCOM, 4, 1 << 22);
2330 +
2331 + /* step 4, set cfg active */
2332 + MTC0(C0_BROADCOM, 2, 0x9);
2333 +
2334 +
2335 + /* steps 5 & 6 */
2336 + __asm__ __volatile__ (
2337 + ".set\tmips3\n\t"
2338 + "wait\n\t"
2339 + ".set\tmips0"
2340 + );
2341 +
2342 + /* step 7, clear cfg_active */
2343 + MTC0(C0_BROADCOM, 2, 0);
2344 +
2345 + /* Additional Step: set back to orig sync mode */
2346 + MTC0(C0_BROADCOM, 4, sync_mode);
2347 +
2348 + /* step 8, fake soft reset */
2349 + MTC0(C0_BROADCOM, 5, MFC0(C0_BROADCOM, 5) | 4);
2350 +
2351 + end_fill:
2352 + /* step 9 set watchdog timer */
2353 + sb_watchdog(sbh, 20);
2354 + (void) R_REG(&cc->chipid);
2355 +
2356 + /* step 11 */
2357 + __asm__ __volatile__ (
2358 + ".set\tmips3\n\t"
2359 + "sync\n\t"
2360 + "wait\n\t"
2361 + ".set\tmips0"
2362 + );
2363 + while (1);
2364 + }
2365 +
2366 +done:
2367 + /* switch back to previous core */
2368 + sb_setcoreidx(sbh, idx);
2369 +
2370 + return ret;
2371 +}
2372 +
2373 +/*
2374 + * This also must be run from the cache on 47xx
2375 + * so there are no mips core BIU ops in progress
2376 + * when the PFC is enabled.
2377 + */
2378 +
2379 +static void
2380 +BCMINITFN(_enable_pfc)(uint32 mode)
2381 +{
2382 + /* write range */
2383 + *(volatile uint32 *)PFC_CR1 = 0xffff0000;
2384 +
2385 + /* enable */
2386 + *(volatile uint32 *)PFC_CR0 = mode;
2387 +}
2388 +
2389 +void
2390 +BCMINITFN(enable_pfc)(uint32 mode)
2391 +{
2392 + ulong start, end;
2393 + int i;
2394 +
2395 + /* If auto then choose the correct mode for this
2396 + platform, currently we only ever select one mode */
2397 + if (mode == PFC_AUTO)
2398 + mode = PFC_INST;
2399 +
2400 + /* enable prefetch cache if available */
2401 + if (MFC0(C0_BROADCOM, 0) & BRCM_PFC_AVAIL) {
2402 + start = (ulong) &BCMINIT(_enable_pfc);
2403 + end = (ulong) &BCMINIT(enable_pfc);
2404 +
2405 + /* Preload handler into the cache one line at a time */
2406 + for (i = 0; i < (end - start); i += 4)
2407 + cache_op(start + i, Fill_I);
2408 +
2409 + BCMINIT(_enable_pfc)(mode);
2410 + }
2411 +}
2412 +
2413 +/* returns the ncdl value to be programmed into sdram_ncdl for calibration */
2414 +uint32
2415 +BCMINITFN(sb_memc_get_ncdl)(sb_t *sbh)
2416 +{
2417 + sbmemcregs_t *memc;
2418 + uint32 ret = 0;
2419 + uint32 config, rd, wr, misc, dqsg, cd, sm, sd;
2420 + uint idx, rev;
2421 +
2422 + idx = sb_coreidx(sbh);
2423 +
2424 + memc = (sbmemcregs_t *)sb_setcore(sbh, SB_MEMC, 0);
2425 + if (memc == 0)
2426 + goto out;
2427 +
2428 + rev = sb_corerev(sbh);
2429 +
2430 + config = R_REG(&memc->config);
2431 + wr = R_REG(&memc->wrncdlcor);
2432 + rd = R_REG(&memc->rdncdlcor);
2433 + misc = R_REG(&memc->miscdlyctl);
2434 + dqsg = R_REG(&memc->dqsgatencdl);
2435 +
2436 + rd &= MEMC_RDNCDLCOR_RD_MASK;
2437 + wr &= MEMC_WRNCDLCOR_WR_MASK;
2438 + dqsg &= MEMC_DQSGATENCDL_G_MASK;
2439 +
2440 + if (config & MEMC_CONFIG_DDR) {
2441 + ret = (wr << 16) | (rd << 8) | dqsg;
2442 + } else {
2443 + if (rev > 0)
2444 + cd = rd;
2445 + else
2446 + cd = (rd == MEMC_CD_THRESHOLD) ? rd : (wr + MEMC_CD_THRESHOLD);
2447 + sm = (misc & MEMC_MISC_SM_MASK) >> MEMC_MISC_SM_SHIFT;
2448 + sd = (misc & MEMC_MISC_SD_MASK) >> MEMC_MISC_SD_SHIFT;
2449 + ret = (sm << 16) | (sd << 8) | cd;
2450 + }
2451 +
2452 +out:
2453 + /* switch back to previous core */
2454 + sb_setcoreidx(sbh, idx);
2455 +
2456 + return ret;
2457 +}
2458 +
2459 diff -urN linux.old/arch/mips/bcm947xx/broadcom/sbpci.c linux.dev/arch/mips/bcm947xx/broadcom/sbpci.c
2460 --- linux.old/arch/mips/bcm947xx/broadcom/sbpci.c 1970-01-01 01:00:00.000000000 +0100
2461 +++ linux.dev/arch/mips/bcm947xx/broadcom/sbpci.c 2005-12-15 23:50:31.846688500 +0100
2462 @@ -0,0 +1,531 @@
2463 +/*
2464 + * Low-Level PCI and SB support for BCM47xx
2465 + *
2466 + * Copyright 2005, Broadcom Corporation
2467 + * All Rights Reserved.
2468 + *
2469 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
2470 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
2471 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
2472 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
2473 + *
2474 + * $Id$
2475 + */
2476 +
2477 +#include <typedefs.h>
2478 +#include <pcicfg.h>
2479 +#include <bcmdevs.h>
2480 +#include <sbconfig.h>
2481 +#include <osl.h>
2482 +#include <sbutils.h>
2483 +#include <sbpci.h>
2484 +#include <bcmendian.h>
2485 +#include <bcmutils.h>
2486 +#include <bcmnvram.h>
2487 +#include <hndmips.h>
2488 +
2489 +/* Can free sbpci_init() memory after boot */
2490 +#ifndef linux
2491 +#define __init
2492 +#endif
2493 +
2494 +/* Emulated configuration space */
2495 +static pci_config_regs sb_config_regs[SB_MAXCORES];
2496 +
2497 +/* Banned cores */
2498 +static uint16 pci_ban[32] = { 0 };
2499 +static uint pci_banned = 0;
2500 +
2501 +/* CardBus mode */
2502 +static bool cardbus = FALSE;
2503 +
2504 +/* Disable PCI host core */
2505 +static bool pci_disabled = FALSE;
2506 +
2507 +/*
2508 + * Functions for accessing external PCI configuration space
2509 + */
2510 +
2511 +/* Assume one-hot slot wiring */
2512 +#define PCI_SLOT_MAX 16
2513 +
2514 +static uint32
2515 +config_cmd(sb_t *sbh, uint bus, uint dev, uint func, uint off)
2516 +{
2517 + uint coreidx;
2518 + sbpciregs_t *regs;
2519 + uint32 addr = 0;
2520 +
2521 + /* CardBusMode supports only one device */
2522 + if (cardbus && dev > 1)
2523 + return 0;
2524 +
2525 + coreidx = sb_coreidx(sbh);
2526 + regs = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0);
2527 +
2528 + /* Type 0 transaction */
2529 + if (bus == 1) {
2530 + /* Skip unwired slots */
2531 + if (dev < PCI_SLOT_MAX) {
2532 + /* Slide the PCI window to the appropriate slot */
2533 + W_REG(&regs->sbtopci1, SBTOPCI_CFG0 | ((1 << (dev + 16)) & SBTOPCI1_MASK));
2534 + addr = SB_PCI_CFG | ((1 << (dev + 16)) & ~SBTOPCI1_MASK) |
2535 + (func << 8) | (off & ~3);
2536 + }
2537 + }
2538 +
2539 + /* Type 1 transaction */
2540 + else {
2541 + W_REG(&regs->sbtopci1, SBTOPCI_CFG1);
2542 + addr = SB_PCI_CFG | (bus << 16) | (dev << 11) | (func << 8) | (off & ~3);
2543 + }
2544 +
2545 + sb_setcoreidx(sbh, coreidx);
2546 +
2547 + return addr;
2548 +}
2549 +
2550 +static int
2551 +extpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
2552 +{
2553 + uint32 addr, *reg = NULL, val;
2554 + int ret = 0;
2555 +
2556 + if (pci_disabled ||
2557 + !(addr = config_cmd(sbh, bus, dev, func, off)) ||
2558 + !(reg = (uint32 *) REG_MAP(addr, len)) ||
2559 + BUSPROBE(val, reg))
2560 + val = 0xffffffff;
2561 +
2562 + val >>= 8 * (off & 3);
2563 + if (len == 4)
2564 + *((uint32 *) buf) = val;
2565 + else if (len == 2)
2566 + *((uint16 *) buf) = (uint16) val;
2567 + else if (len == 1)
2568 + *((uint8 *) buf) = (uint8) val;
2569 + else
2570 + ret = -1;
2571 +
2572 + if (reg)
2573 + REG_UNMAP(reg);
2574 +
2575 + return ret;
2576 +}
2577 +
2578 +static int
2579 +extpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
2580 +{
2581 + uint32 addr, *reg = NULL, val;
2582 + int ret = 0;
2583 +
2584 + if (pci_disabled ||
2585 + !(addr = config_cmd(sbh, bus, dev, func, off)) ||
2586 + !(reg = (uint32 *) REG_MAP(addr, len)) ||
2587 + BUSPROBE(val, reg))
2588 + goto done;
2589 +
2590 + if (len == 4)
2591 + val = *((uint32 *) buf);
2592 + else if (len == 2) {
2593 + val &= ~(0xffff << (8 * (off & 3)));
2594 + val |= *((uint16 *) buf) << (8 * (off & 3));
2595 + } else if (len == 1) {
2596 + val &= ~(0xff << (8 * (off & 3)));
2597 + val |= *((uint8 *) buf) << (8 * (off & 3));
2598 + } else
2599 + ret = -1;
2600 +
2601 + W_REG(reg, val);
2602 +
2603 + done:
2604 + if (reg)
2605 + REG_UNMAP(reg);
2606 +
2607 + return ret;
2608 +}
2609 +
2610 +/*
2611 + * Functions for accessing translated SB configuration space
2612 + */
2613 +
2614 +static int
2615 +sb_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
2616 +{
2617 + pci_config_regs *cfg;
2618 +
2619 + if (dev >= SB_MAXCORES || (off + len) > sizeof(pci_config_regs))
2620 + return -1;
2621 + cfg = &sb_config_regs[dev];
2622 +
2623 + ASSERT(ISALIGNED(off, len));
2624 + ASSERT(ISALIGNED((uintptr)buf, len));
2625 +
2626 + if (len == 4)
2627 + *((uint32 *) buf) = ltoh32(*((uint32 *)((ulong) cfg + off)));
2628 + else if (len == 2)
2629 + *((uint16 *) buf) = ltoh16(*((uint16 *)((ulong) cfg + off)));
2630 + else if (len == 1)
2631 + *((uint8 *) buf) = *((uint8 *)((ulong) cfg + off));
2632 + else
2633 + return -1;
2634 +
2635 + return 0;
2636 +}
2637 +
2638 +static int
2639 +sb_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
2640 +{
2641 + uint coreidx, n;
2642 + void *regs;
2643 + sbconfig_t *sb;
2644 + pci_config_regs *cfg;
2645 +
2646 + if (dev >= SB_MAXCORES || (off + len) > sizeof(pci_config_regs))
2647 + return -1;
2648 + cfg = &sb_config_regs[dev];
2649 +
2650 + ASSERT(ISALIGNED(off, len));
2651 + ASSERT(ISALIGNED((uintptr)buf, len));
2652 +
2653 + /* Emulate BAR sizing */
2654 + if (off >= OFFSETOF(pci_config_regs, base[0]) && off <= OFFSETOF(pci_config_regs, base[3]) &&
2655 + len == 4 && *((uint32 *) buf) == ~0) {
2656 + coreidx = sb_coreidx(sbh);
2657 + if ((regs = sb_setcoreidx(sbh, dev))) {
2658 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
2659 + /* Highest numbered address match register */
2660 + n = (R_REG(&sb->sbidlow) & SBIDL_AR_MASK) >> SBIDL_AR_SHIFT;
2661 + if (off == OFFSETOF(pci_config_regs, base[0]))
2662 + cfg->base[0] = ~(sb_size(R_REG(&sb->sbadmatch0)) - 1);
2663 +#if 0
2664 + else if (off == OFFSETOF(pci_config_regs, base[1]) && n >= 1)
2665 + cfg->base[1] = ~(sb_size(R_REG(&sb->sbadmatch1)) - 1);
2666 + else if (off == OFFSETOF(pci_config_regs, base[2]) && n >= 2)
2667 + cfg->base[2] = ~(sb_size(R_REG(&sb->sbadmatch2)) - 1);
2668 + else if (off == OFFSETOF(pci_config_regs, base[3]) && n >= 3)
2669 + cfg->base[3] = ~(sb_size(R_REG(&sb->sbadmatch3)) - 1);
2670 +#endif
2671 + }
2672 + sb_setcoreidx(sbh, coreidx);
2673 + return 0;
2674 + }
2675 +
2676 + if (len == 4)
2677 + *((uint32 *)((ulong) cfg + off)) = htol32(*((uint32 *) buf));
2678 + else if (len == 2)
2679 + *((uint16 *)((ulong) cfg + off)) = htol16(*((uint16 *) buf));
2680 + else if (len == 1)
2681 + *((uint8 *)((ulong) cfg + off)) = *((uint8 *) buf);
2682 + else
2683 + return -1;
2684 +
2685 + return 0;
2686 +}
2687 +
2688 +int
2689 +sbpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
2690 +{
2691 + if (bus == 0)
2692 + return sb_read_config(sbh, bus, dev, func, off, buf, len);
2693 + else
2694 + return extpci_read_config(sbh, bus, dev, func, off, buf, len);
2695 +}
2696 +
2697 +int
2698 +sbpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
2699 +{
2700 + if (bus == 0)
2701 + return sb_write_config(sbh, bus, dev, func, off, buf, len);
2702 + else
2703 + return extpci_write_config(sbh, bus, dev, func, off, buf, len);
2704 +}
2705 +
2706 +void
2707 +sbpci_ban(uint16 core)
2708 +{
2709 + if (pci_banned < ARRAYSIZE(pci_ban))
2710 + pci_ban[pci_banned++] = core;
2711 +}
2712 +
2713 +static int
2714 +sbpci_init_pci(sb_t *sbh)
2715 +{
2716 + uint chip, chiprev, chippkg, host;
2717 + uint32 boardflags;
2718 + sbpciregs_t *pci;
2719 + sbconfig_t *sb;
2720 + uint32 val;
2721 +
2722 + chip = sb_chip(sbh);
2723 + chiprev = sb_chiprev(sbh);
2724 + chippkg = sb_chippkg(sbh);
2725 +
2726 + if (!(pci = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0))) {
2727 + printf("PCI: no core\n");
2728 + pci_disabled = TRUE;
2729 + return -1;
2730 + }
2731 + sb_core_reset(sbh, 0);
2732 +
2733 + boardflags = (uint32) getintvar(NULL, "boardflags");
2734 +
2735 + if ((chip == BCM4310_DEVICE_ID) && (chiprev == 0))
2736 + pci_disabled = TRUE;
2737 +
2738 + /*
2739 + * The 200-pin BCM4712 package does not bond out PCI. Even when
2740 + * PCI is bonded out, some boards may leave the pins
2741 + * floating.
2742 + */
2743 + if (((chip == BCM4712_DEVICE_ID) &&
2744 + ((chippkg == BCM4712SMALL_PKG_ID) ||
2745 + (chippkg == BCM4712MID_PKG_ID))) ||
2746 + (boardflags & BFL_NOPCI))
2747 + pci_disabled = TRUE;
2748 +
2749 + /*
2750 + * If the PCI core should not be touched (disabled, not bonded
2751 + * out, or pins floating), do not even attempt to access core
2752 + * registers. Otherwise, try to determine if it is in host
2753 + * mode.
2754 + */
2755 + if (pci_disabled)
2756 + host = 0;
2757 + else
2758 + host = !BUSPROBE(val, &pci->control);
2759 +
2760 + if (!host) {
2761 + /* Disable PCI interrupts in client mode */
2762 + sb = (sbconfig_t *)((ulong) pci + SBCONFIGOFF);
2763 + W_REG(&sb->sbintvec, 0);
2764 +
2765 + /* Disable the PCI bridge in client mode */
2766 + sbpci_ban(SB_PCI);
2767 + printf("PCI: Disabled\n");
2768 + } else {
2769 + /* Reset the external PCI bus and enable the clock */
2770 + W_REG(&pci->control, 0x5); /* enable the tristate drivers */
2771 + W_REG(&pci->control, 0xd); /* enable the PCI clock */
2772 + OSL_DELAY(150); /* delay > 100 us */
2773 + W_REG(&pci->control, 0xf); /* deassert PCI reset */
2774 + W_REG(&pci->arbcontrol, PCI_INT_ARB); /* use internal arbiter */
2775 + OSL_DELAY(1); /* delay 1 us */
2776 +
2777 + /* Enable CardBusMode */
2778 + cardbus = nvram_match("cardbus", "1");
2779 + if (cardbus) {
2780 + printf("PCI: Enabling CardBus\n");
2781 + /* GPIO 1 resets the CardBus device on bcm94710ap */
2782 + sb_gpioout(sbh, 1, 1, GPIO_DRV_PRIORITY);
2783 + sb_gpioouten(sbh, 1, 1, GPIO_DRV_PRIORITY);
2784 + W_REG(&pci->sprom[0], R_REG(&pci->sprom[0]) | 0x400);
2785 + }
2786 +
2787 + /* 64 MB I/O access window */
2788 + W_REG(&pci->sbtopci0, SBTOPCI_IO);
2789 + /* 64 MB configuration access window */
2790 + W_REG(&pci->sbtopci1, SBTOPCI_CFG0);
2791 + /* 1 GB memory access window */
2792 + W_REG(&pci->sbtopci2, SBTOPCI_MEM | SB_PCI_DMA);
2793 +
2794 + /* Enable PCI bridge BAR0 prefetch and burst */
2795 + val = 6;
2796 + sbpci_write_config(sbh, 1, 0, 0, PCI_CFG_CMD, &val, sizeof(val));
2797 +
2798 + /* Enable PCI interrupts */
2799 + W_REG(&pci->intmask, PCI_INTA);
2800 + }
2801 +
2802 + return 0;
2803 +}
2804 +
2805 +static int
2806 +sbpci_init_cores(sb_t *sbh)
2807 +{
2808 + uint chip, chiprev, chippkg, coreidx, i;
2809 + sbconfig_t *sb;
2810 + pci_config_regs *cfg;
2811 + void *regs;
2812 + char varname[8];
2813 + uint wlidx = 0;
2814 + uint16 vendor, core;
2815 + uint8 class, subclass, progif;
2816 + uint32 val;
2817 + uint32 sbips_int_mask[] = { 0, SBIPS_INT1_MASK, SBIPS_INT2_MASK, SBIPS_INT3_MASK, SBIPS_INT4_MASK };
2818 + uint32 sbips_int_shift[] = { 0, 0, SBIPS_INT2_SHIFT, SBIPS_INT3_SHIFT, SBIPS_INT4_SHIFT };
2819 +
2820 + chip = sb_chip(sbh);
2821 + chiprev = sb_chiprev(sbh);
2822 + chippkg = sb_chippkg(sbh);
2823 + coreidx = sb_coreidx(sbh);
2824 +
2825 + /* Scan the SB bus */
2826 + bzero(sb_config_regs, sizeof(sb_config_regs));
2827 + for (cfg = sb_config_regs; cfg < &sb_config_regs[SB_MAXCORES]; cfg++) {
2828 + cfg->vendor = 0xffff;
2829 + if (!(regs = sb_setcoreidx(sbh, cfg - sb_config_regs)))
2830 + continue;
2831 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
2832 +
2833 + /* Read ID register and parse vendor and core */
2834 + val = R_REG(&sb->sbidhigh);
2835 + vendor = (val & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT;
2836 + core = (val & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT;
2837 + progif = 0;
2838 +
2839 + /* Check if this core is banned */
2840 + for (i = 0; i < pci_banned; i++)
2841 + if (core == pci_ban[i])
2842 + break;
2843 + if (i < pci_banned)
2844 + continue;
2845 +
2846 + /* Known vendor translations */
2847 + switch (vendor) {
2848 + case SB_VEND_BCM:
2849 + vendor = VENDOR_BROADCOM;
2850 + break;
2851 + }
2852 +
2853 + /* Determine class based on known core codes */
2854 + switch (core) {
2855 + case SB_ILINE20:
2856 + class = PCI_CLASS_NET;
2857 + subclass = PCI_NET_ETHER;
2858 + core = BCM47XX_ILINE_ID;
2859 + break;
2860 + case SB_ILINE100:
2861 + class = PCI_CLASS_NET;
2862 + subclass = PCI_NET_ETHER;
2863 + core = BCM4610_ILINE_ID;
2864 + break;
2865 + case SB_ENET:
2866 + class = PCI_CLASS_NET;
2867 + subclass = PCI_NET_ETHER;
2868 + core = BCM47XX_ENET_ID;
2869 + break;
2870 + case SB_SDRAM:
2871 + case SB_MEMC:
2872 + class = PCI_CLASS_MEMORY;
2873 + subclass = PCI_MEMORY_RAM;
2874 + break;
2875 + case SB_PCI:
2876 + class = PCI_CLASS_BRIDGE;
2877 + subclass = PCI_BRIDGE_PCI;
2878 + break;
2879 + case SB_MIPS:
2880 + case SB_MIPS33:
2881 + class = PCI_CLASS_CPU;
2882 + subclass = PCI_CPU_MIPS;
2883 + break;
2884 + case SB_CODEC:
2885 + class = PCI_CLASS_COMM;
2886 + subclass = PCI_COMM_MODEM;
2887 + core = BCM47XX_V90_ID;
2888 + break;
2889 + case SB_USB:
2890 + class = PCI_CLASS_SERIAL;
2891 + subclass = PCI_SERIAL_USB;
2892 + progif = 0x10; /* OHCI */
2893 + core = BCM47XX_USB_ID;
2894 + break;
2895 + case SB_USB11H:
2896 + class = PCI_CLASS_SERIAL;
2897 + subclass = PCI_SERIAL_USB;
2898 + progif = 0x10; /* OHCI */
2899 + core = BCM47XX_USBH_ID;
2900 + break;
2901 + case SB_USB11D:
2902 + class = PCI_CLASS_SERIAL;
2903 + subclass = PCI_SERIAL_USB;
2904 + core = BCM47XX_USBD_ID;
2905 + break;
2906 + case SB_IPSEC:
2907 + class = PCI_CLASS_CRYPT;
2908 + subclass = PCI_CRYPT_NETWORK;
2909 + core = BCM47XX_IPSEC_ID;
2910 + break;
2911 + case SB_ROBO:
2912 + class = PCI_CLASS_NET;
2913 + subclass = PCI_NET_OTHER;
2914 + core = BCM47XX_ROBO_ID;
2915 + break;
2916 + case SB_EXTIF:
2917 + case SB_CC:
2918 + class = PCI_CLASS_MEMORY;
2919 + subclass = PCI_MEMORY_FLASH;
2920 + break;
2921 + case SB_D11:
2922 + class = PCI_CLASS_NET;
2923 + subclass = PCI_NET_OTHER;
2924 + /* Let an nvram variable override this */
2925 + sprintf(varname, "wl%did", wlidx);
2926 + wlidx++;
2927 + if ((core = getintvar(NULL, varname)) == 0) {
2928 + if (chip == BCM4712_DEVICE_ID) {
2929 + if (chippkg == BCM4712SMALL_PKG_ID)
2930 + core = BCM4306_D11G_ID;
2931 + else
2932 + core = BCM4306_D11DUAL_ID;
2933 + } else {
2934 + /* 4310 */
2935 + core = BCM4310_D11B_ID;
2936 + }
2937 + }
2938 + break;
2939 +
2940 + default:
2941 + class = subclass = progif = 0xff;
2942 + break;
2943 + }
2944 +
2945 + /* Supported translations */
2946 + cfg->vendor = htol16(vendor);
2947 + cfg->device = htol16(core);
2948 + cfg->rev_id = chiprev;
2949 + cfg->prog_if = progif;
2950 + cfg->sub_class = subclass;
2951 + cfg->base_class = class;
2952 + cfg->base[0] = htol32(sb_base(R_REG(&sb->sbadmatch0)));
2953 + cfg->base[1] = 0;//htol32(sb_base(R_REG(&sb->sbadmatch1)));
2954 + cfg->base[2] = 0;//htol32(sb_base(R_REG(&sb->sbadmatch2)));
2955 + cfg->base[3] = 0;//htol32(sb_base(R_REG(&sb->sbadmatch3)));
2956 + cfg->base[4] = 0;
2957 + cfg->base[5] = 0;
2958 + if (class == PCI_CLASS_BRIDGE && subclass == PCI_BRIDGE_PCI)
2959 + cfg->header_type = PCI_HEADER_BRIDGE;
2960 + else
2961 + cfg->header_type = PCI_HEADER_NORMAL;
2962 + /* Save core interrupt flag */
2963 + cfg->int_pin = R_REG(&sb->sbtpsflag) & SBTPS_NUM0_MASK;
2964 + /* Default to MIPS shared interrupt 0 */
2965 + cfg->int_line = 0;
2966 + /* MIPS sbipsflag maps core interrupt flags to interrupts 1 through 4 */
2967 + if ((regs = sb_setcore(sbh, SB_MIPS, 0)) ||
2968 + (regs = sb_setcore(sbh, SB_MIPS33, 0))) {
2969 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
2970 + val = R_REG(&sb->sbipsflag);
2971 + for (cfg->int_line = 1; cfg->int_line <= 4; cfg->int_line++) {
2972 + if (((val & sbips_int_mask[cfg->int_line]) >> sbips_int_shift[cfg->int_line]) == cfg->int_pin)
2973 + break;
2974 + }
2975 + if (cfg->int_line > 4)
2976 + cfg->int_line = 0;
2977 + }
2978 + /* Emulated core */
2979 + *((uint32 *) &cfg->sprom_control) = 0xffffffff;
2980 + }
2981 +
2982 + sb_setcoreidx(sbh, coreidx);
2983 + return 0;
2984 +}
2985 +
2986 +int __init
2987 +sbpci_init(sb_t *sbh)
2988 +{
2989 + sbpci_init_pci(sbh);
2990 + sbpci_init_cores(sbh);
2991 + return 0;
2992 +}
2993 +
2994 diff -urN linux.old/arch/mips/bcm947xx/broadcom/sbutils.c linux.dev/arch/mips/bcm947xx/broadcom/sbutils.c
2995 --- linux.old/arch/mips/bcm947xx/broadcom/sbutils.c 1970-01-01 01:00:00.000000000 +0100
2996 +++ linux.dev/arch/mips/bcm947xx/broadcom/sbutils.c 2005-12-17 01:21:12.951254500 +0100
2997 @@ -0,0 +1,2370 @@
2998 +/*
2999 + * Misc utility routines for accessing chip-specific features
3000 + * of the SiliconBackplane-based Broadcom chips.
3001 + *
3002 + * Copyright 2005, Broadcom Corporation
3003 + * All Rights Reserved.
3004 + *
3005 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
3006 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
3007 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
3008 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
3009 + * $Id$
3010 + */
3011 +
3012 +#include <typedefs.h>
3013 +#include <osl.h>
3014 +#include <sbutils.h>
3015 +#include <bcmutils.h>
3016 +#include <bcmdevs.h>
3017 +#include <sbconfig.h>
3018 +#include <sbchipc.h>
3019 +#include <sbpci.h>
3020 +#include <pcicfg.h>
3021 +#include <sbextif.h>
3022 +#include <bcmsrom.h>
3023 +
3024 +/* debug/trace */
3025 +#define SB_ERROR(args)
3026 +
3027 +
3028 +typedef uint32 (*sb_intrsoff_t)(void *intr_arg);
3029 +typedef void (*sb_intrsrestore_t)(void *intr_arg, uint32 arg);
3030 +typedef bool (*sb_intrsenabled_t)(void *intr_arg);
3031 +
3032 +/* misc sb info needed by some of the routines */
3033 +typedef struct sb_info {
3034 +
3035 + struct sb_pub sb; /* back plane public state(must be first field of sb_info */
3036 +
3037 + void *osh; /* osl os handle */
3038 + void *sdh; /* bcmsdh handle */
3039 +
3040 + void *curmap; /* current regs va */
3041 + void *regs[SB_MAXCORES]; /* other regs va */
3042 +
3043 + uint curidx; /* current core index */
3044 + uint dev_coreid; /* the core provides driver functions */
3045 +
3046 + uint gpioidx; /* gpio control core index */
3047 + uint gpioid; /* gpio control coretype */
3048 +
3049 + uint numcores; /* # discovered cores */
3050 + uint coreid[SB_MAXCORES]; /* id of each core */
3051 +
3052 + void *intr_arg; /* interrupt callback function arg */
3053 + sb_intrsoff_t intrsoff_fn; /* function turns chip interrupts off */
3054 + sb_intrsrestore_t intrsrestore_fn; /* function restore chip interrupts */
3055 + sb_intrsenabled_t intrsenabled_fn; /* function to check if chip interrupts are enabled */
3056 +
3057 +} sb_info_t;
3058 +
3059 +/* local prototypes */
3060 +static sb_info_t * BCMINIT(sb_doattach)(sb_info_t *si, uint devid, osl_t *osh, void *regs,
3061 + uint bustype, void *sdh, char **vars, int *varsz);
3062 +static void BCMINIT(sb_scan)(sb_info_t *si);
3063 +static uint sb_corereg(sb_info_t *si, uint coreidx, uint regoff, uint mask, uint val);
3064 +static uint _sb_coreidx(sb_info_t *si);
3065 +static uint sb_findcoreidx(sb_info_t *si, uint coreid, uint coreunit);
3066 +static uint BCMINIT(sb_pcidev2chip)(uint pcidev);
3067 +static uint BCMINIT(sb_chip2numcores)(uint chip);
3068 +static int sb_pci_fixcfg(sb_info_t *si);
3069 +
3070 +/* delay needed between the mdio control/ mdiodata register data access */
3071 +#define PR28829_DELAY() OSL_DELAY(10)
3072 +
3073 +
3074 +/* global variable to indicate reservation/release of gpio's*/
3075 +static uint32 sb_gpioreservation = 0;
3076 +
3077 +#define SB_INFO(sbh) (sb_info_t*)sbh
3078 +#define SET_SBREG(sbh, r, mask, val) W_SBREG((sbh), (r), ((R_SBREG((sbh), (r)) & ~(mask)) | (val)))
3079 +#define GOODCOREADDR(x) (((x) >= SB_ENUM_BASE) && ((x) <= SB_ENUM_LIM) && ISALIGNED((x), SB_CORE_SIZE))
3080 +#define GOODREGS(regs) ((regs) && ISALIGNED((uintptr)(regs), SB_CORE_SIZE))
3081 +#define REGS2SB(va) (sbconfig_t*) ((int8*)(va) + SBCONFIGOFF)
3082 +#define GOODIDX(idx) (((uint)idx) < SB_MAXCORES)
3083 +#define BADIDX (SB_MAXCORES+1)
3084 +#define NOREV -1
3085 +
3086 +#define PCI(si) ((BUSTYPE(si->sb.bustype) == PCI_BUS) && (si->sb.buscoretype == SB_PCI))
3087 +
3088 +/* sonicsrev */
3089 +#define SONICS_2_2 (SBIDL_RV_2_2 >> SBIDL_RV_SHIFT)
3090 +#define SONICS_2_3 (SBIDL_RV_2_3 >> SBIDL_RV_SHIFT)
3091 +
3092 +#define R_SBREG(sbh, sbr) sb_read_sbreg((sbh), (sbr))
3093 +#define W_SBREG(sbh, sbr, v) sb_write_sbreg((sbh), (sbr), (v))
3094 +#define AND_SBREG(sbh, sbr, v) W_SBREG((sbh), (sbr), (R_SBREG((sbh), (sbr)) & (v)))
3095 +#define OR_SBREG(sbh, sbr, v) W_SBREG((sbh), (sbr), (R_SBREG((sbh), (sbr)) | (v)))
3096 +
3097 +/*
3098 + * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts before/
3099 + * after core switching to avoid invalid register accesss inside ISR.
3100 + */
3101 +#define INTR_OFF(si, intr_val) \
3102 + if ((si)->intrsoff_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \
3103 + intr_val = (*(si)->intrsoff_fn)((si)->intr_arg); }
3104 +#define INTR_RESTORE(si, intr_val) \
3105 + if ((si)->intrsrestore_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \
3106 + (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val); }
3107 +
3108 +/* dynamic clock control defines */
3109 +#define LPOMINFREQ 25000 /* low power oscillator min */
3110 +#define LPOMAXFREQ 43000 /* low power oscillator max */
3111 +#define XTALMINFREQ 19800000 /* 20 MHz - 1% */
3112 +#define XTALMAXFREQ 20200000 /* 20 MHz + 1% */
3113 +#define PCIMINFREQ 25000000 /* 25 MHz */
3114 +#define PCIMAXFREQ 34000000 /* 33 MHz + fudge */
3115 +
3116 +#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */
3117 +#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */
3118 +
3119 +#define MIN_DUMPBUFLEN 32 /* debug */
3120 +
3121 +/* GPIO Based LED powersave defines */
3122 +#define DEFAULT_GPIO_ONTIME 10
3123 +#define DEFAULT_GPIO_OFFTIME 90
3124 +
3125 +#define DEFAULT_GPIOTIMERVAL ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME)
3126 +
3127 +static uint32
3128 +sb_read_sbreg(sb_info_t *si, volatile uint32 *sbr)
3129 +{
3130 + uint32 val = R_REG(sbr);
3131 +
3132 + return (val);
3133 +}
3134 +
3135 +static void
3136 +sb_write_sbreg(sb_info_t *si, volatile uint32 *sbr, uint32 v)
3137 +{
3138 + W_REG(sbr, v);
3139 +}
3140 +
3141 +/* Using sb_kattach depends on SB_BUS support, either implicit */
3142 +/* no limiting BCMBUSTYPE value) or explicit (value is SB_BUS). */
3143 +#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SB_BUS)
3144 +
3145 +/* global kernel resource */
3146 +static sb_info_t ksi;
3147 +
3148 +/* generic kernel variant of sb_attach() */
3149 +sb_t *
3150 +BCMINITFN(sb_kattach)()
3151 +{
3152 + uint32 *regs;
3153 +
3154 + if (ksi.curmap == NULL) {
3155 + uint32 cid;
3156 +
3157 + regs = (uint32 *)REG_MAP(SB_ENUM_BASE, SB_CORE_SIZE);
3158 + cid = R_REG((uint32 *)regs);
3159 + if (((cid & CID_ID_MASK) == BCM4712_DEVICE_ID) &&
3160 + ((cid & CID_PKG_MASK) != BCM4712LARGE_PKG_ID) &&
3161 + ((cid & CID_REV_MASK) <= (3 << CID_REV_SHIFT))) {
3162 + uint32 *scc, val;
3163 +
3164 + scc = (uint32 *)((uchar*)regs + OFFSETOF(chipcregs_t, slow_clk_ctl));
3165 + val = R_REG(scc);
3166 + SB_ERROR((" initial scc = 0x%x\n", val));
3167 + val |= SCC_SS_XTAL;
3168 + W_REG(scc, val);
3169 + }
3170 +
3171 + if (BCMINIT(sb_doattach)(&ksi, BCM4710_DEVICE_ID, NULL, (void*)regs,
3172 + SB_BUS, NULL, NULL, NULL) == NULL) {
3173 + return NULL;
3174 + }
3175 + }
3176 +
3177 + return (sb_t *)&ksi;
3178 +}
3179 +#endif
3180 +
3181 +static sb_info_t *
3182 +BCMINITFN(sb_doattach)(sb_info_t *si, uint devid, osl_t *osh, void *regs,
3183 + uint bustype, void *sdh, char **vars, int *varsz)
3184 +{
3185 + uint origidx;
3186 + chipcregs_t *cc;
3187 + sbconfig_t *sb;
3188 + uint32 w;
3189 +
3190 + ASSERT(GOODREGS(regs));
3191 +
3192 + bzero((uchar*)si, sizeof (sb_info_t));
3193 +
3194 + si->sb.buscoreidx = si->gpioidx = BADIDX;
3195 +
3196 + si->osh = osh;
3197 + si->curmap = regs;
3198 + si->sdh = sdh;
3199 +
3200 + /* check to see if we are a sb core mimic'ing a pci core */
3201 + if (bustype == PCI_BUS) {
3202 + if (OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof (uint32)) == 0xffffffff)
3203 + bustype = SB_BUS;
3204 + else
3205 + bustype = PCI_BUS;
3206 + }
3207 +
3208 + si->sb.bustype = bustype;
3209 + if (si->sb.bustype != BUSTYPE(si->sb.bustype)) {
3210 + SB_ERROR(("sb_doattach: bus type %d does not match configured bus type %d\n",
3211 + si->sb.bustype, BUSTYPE(si->sb.bustype)));
3212 + return NULL;
3213 + }
3214 +
3215 + /* kludge to enable the clock on the 4306 which lacks a slowclock */
3216 + if (BUSTYPE(si->sb.bustype) == PCI_BUS)
3217 + sb_clkctl_xtal(&si->sb, XTAL|PLL, ON);
3218 +
3219 + if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
3220 + w = OSL_PCI_READ_CONFIG(osh, PCI_BAR0_WIN, sizeof (uint32));
3221 + if (!GOODCOREADDR(w))
3222 + OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN, sizeof (uint32), SB_ENUM_BASE);
3223 + }
3224 +
3225 + /* initialize current core index value */
3226 + si->curidx = _sb_coreidx(si);
3227 +
3228 + if (si->curidx == BADIDX) {
3229 + SB_ERROR(("sb_doattach: bad core index\n"));
3230 + return NULL;
3231 + }
3232 +
3233 + /* get sonics backplane revision */
3234 + sb = REGS2SB(si->curmap);
3235 + si->sb.sonicsrev = (R_SBREG(si, &(sb)->sbidlow) & SBIDL_RV_MASK) >> SBIDL_RV_SHIFT;
3236 +
3237 + /* keep and reuse the initial register mapping */
3238 + origidx = si->curidx;
3239 + if (BUSTYPE(si->sb.bustype) == SB_BUS)
3240 + si->regs[origidx] = regs;
3241 +
3242 + /* is core-0 a chipcommon core? */
3243 + si->numcores = 1;
3244 + cc = (chipcregs_t*) sb_setcoreidx(&si->sb, 0);
3245 + if (sb_coreid(&si->sb) != SB_CC)
3246 + cc = NULL;
3247 +
3248 + /* determine chip id and rev */
3249 + if (cc) {
3250 + /* chip common core found! */
3251 + si->sb.chip = R_REG(&cc->chipid) & CID_ID_MASK;
3252 + si->sb.chiprev = (R_REG(&cc->chipid) & CID_REV_MASK) >> CID_REV_SHIFT;
3253 + si->sb.chippkg = (R_REG(&cc->chipid) & CID_PKG_MASK) >> CID_PKG_SHIFT;
3254 + } else {
3255 + /* no chip common core -- must convert device id to chip id */
3256 + if ((si->sb.chip = BCMINIT(sb_pcidev2chip)(devid)) == 0) {
3257 + SB_ERROR(("sb_doattach: unrecognized device id 0x%04x\n", devid));
3258 + sb_setcoreidx(&si->sb, origidx);
3259 + return NULL;
3260 + }
3261 + }
3262 +
3263 + /* get chipcommon rev */
3264 + si->sb.ccrev = cc ? (int)sb_corerev(&si->sb) : NOREV;
3265 +
3266 + /* determine numcores */
3267 + if (cc && ((si->sb.ccrev == 4) || (si->sb.ccrev >= 6)))
3268 + si->numcores = (R_REG(&cc->chipid) & CID_CC_MASK) >> CID_CC_SHIFT;
3269 + else
3270 + si->numcores = BCMINIT(sb_chip2numcores)(si->sb.chip);
3271 +
3272 + /* return to original core */
3273 + sb_setcoreidx(&si->sb, origidx);
3274 +
3275 + /* sanity checks */
3276 + ASSERT(si->sb.chip);
3277 +
3278 + /* scan for cores */
3279 + BCMINIT(sb_scan)(si);
3280 +
3281 + /* fixup necessary chip/core configurations */
3282 + if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
3283 + if (sb_pci_fixcfg(si)) {
3284 + SB_ERROR(("sb_doattach: sb_pci_fixcfg failed\n"));
3285 + return NULL;
3286 + }
3287 + }
3288 +
3289 + /* srom_var_init() depends on sb_scan() info */
3290 + if (srom_var_init(si, si->sb.bustype, si->curmap, osh, vars, varsz)) {
3291 + SB_ERROR(("sb_doattach: srom_var_init failed: bad srom\n"));
3292 + return (NULL);
3293 + }
3294 +
3295 + if (cc == NULL) {
3296 + /*
3297 + * The chip revision number is hardwired into all
3298 + * of the pci function config rev fields and is
3299 + * independent from the individual core revision numbers.
3300 + * For example, the "A0" silicon of each chip is chip rev 0.
3301 + */
3302 + if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
3303 + w = OSL_PCI_READ_CONFIG(osh, PCI_CFG_REV, sizeof (uint32));
3304 + si->sb.chiprev = w & 0xff;
3305 + } else
3306 + si->sb.chiprev = 0;
3307 + }
3308 +
3309 + /* gpio control core is required */
3310 + if (!GOODIDX(si->gpioidx)) {
3311 + SB_ERROR(("sb_doattach: gpio control core not found\n"));
3312 + return NULL;
3313 + }
3314 +
3315 + /* get boardtype and boardrev */
3316 + switch (BUSTYPE(si->sb.bustype)) {
3317 + case PCI_BUS:
3318 + /* do a pci config read to get subsystem id and subvendor id */
3319 + w = OSL_PCI_READ_CONFIG(osh, PCI_CFG_SVID, sizeof (uint32));
3320 + si->sb.boardvendor = w & 0xffff;
3321 + si->sb.boardtype = (w >> 16) & 0xffff;
3322 + break;
3323 +
3324 + case SB_BUS:
3325 + case JTAG_BUS:
3326 + si->sb.boardvendor = VENDOR_BROADCOM;
3327 + if ((si->sb.boardtype = getintvar(NULL, "boardtype")) == 0)
3328 + si->sb.boardtype = 0xffff;
3329 + break;
3330 + }
3331 +
3332 + if (si->sb.boardtype == 0) {
3333 + SB_ERROR(("sb_doattach: unknown board type\n"));
3334 + ASSERT(si->sb.boardtype);
3335 + }
3336 +
3337 + /* setup the GPIO based LED powersave register */
3338 + if (si->sb.ccrev >= 16) {
3339 + w = getintvar(*vars, "gpiotimerval");
3340 + if (!w)
3341 + w = DEFAULT_GPIOTIMERVAL;
3342 + sb_corereg(si, 0, OFFSETOF(chipcregs_t, gpiotimerval), ~0, w);
3343 + }
3344 +
3345 +
3346 + return (si);
3347 +}
3348 +
3349 +uint
3350 +sb_coreid(sb_t *sbh)
3351 +{
3352 + sb_info_t *si;
3353 + sbconfig_t *sb;
3354 +
3355 + si = SB_INFO(sbh);
3356 + sb = REGS2SB(si->curmap);
3357 +
3358 + return ((R_SBREG(si, &(sb)->sbidhigh) & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT);
3359 +}
3360 +
3361 +uint
3362 +sb_coreidx(sb_t *sbh)
3363 +{
3364 + sb_info_t *si;
3365 +
3366 + si = SB_INFO(sbh);
3367 + return (si->curidx);
3368 +}
3369 +
3370 +/* return current index of core */
3371 +static uint
3372 +_sb_coreidx(sb_info_t *si)
3373 +{
3374 + sbconfig_t *sb;
3375 + uint32 sbaddr = 0;
3376 +
3377 + ASSERT(si);
3378 +
3379 + switch (BUSTYPE(si->sb.bustype)) {
3380 + case SB_BUS:
3381 + sb = REGS2SB(si->curmap);
3382 + sbaddr = sb_base(R_SBREG(si, &sb->sbadmatch0));
3383 + break;
3384 +
3385 + case PCI_BUS:
3386 + sbaddr = OSL_PCI_READ_CONFIG(si->osh, PCI_BAR0_WIN, sizeof (uint32));
3387 + break;
3388 +
3389 +#ifdef BCMJTAG
3390 + case JTAG_BUS:
3391 + sbaddr = (uint32)si->curmap;
3392 + break;
3393 +#endif /* BCMJTAG */
3394 +
3395 + default:
3396 + ASSERT(0);
3397 + }
3398 +
3399 + if (!GOODCOREADDR(sbaddr))
3400 + return BADIDX;
3401 +
3402 + return ((sbaddr - SB_ENUM_BASE) / SB_CORE_SIZE);
3403 +}
3404 +
3405 +uint
3406 +sb_corevendor(sb_t *sbh)
3407 +{
3408 + sb_info_t *si;
3409 + sbconfig_t *sb;
3410 +
3411 + si = SB_INFO(sbh);
3412 + sb = REGS2SB(si->curmap);
3413 +
3414 + return ((R_SBREG(si, &(sb)->sbidhigh) & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT);
3415 +}
3416 +
3417 +uint
3418 +sb_corerev(sb_t *sbh)
3419 +{
3420 + sb_info_t *si;
3421 + sbconfig_t *sb;
3422 + uint sbidh;
3423 +
3424 + si = SB_INFO(sbh);
3425 + sb = REGS2SB(si->curmap);
3426 + sbidh = R_SBREG(si, &(sb)->sbidhigh);
3427 +
3428 + return (SBCOREREV(sbidh));
3429 +}
3430 +
3431 +void *
3432 +sb_osh(sb_t *sbh)
3433 +{
3434 + sb_info_t *si;
3435 +
3436 + si = SB_INFO(sbh);
3437 + return si->osh;
3438 +}
3439 +
3440 +#define SBTML_ALLOW (SBTML_PE | SBTML_FGC | SBTML_FL_MASK)
3441 +
3442 +/* set/clear sbtmstatelow core-specific flags */
3443 +uint32
3444 +sb_coreflags(sb_t *sbh, uint32 mask, uint32 val)
3445 +{
3446 + sb_info_t *si;
3447 + sbconfig_t *sb;
3448 + uint32 w;
3449 +
3450 + si = SB_INFO(sbh);
3451 + sb = REGS2SB(si->curmap);
3452 +
3453 + ASSERT((val & ~mask) == 0);
3454 + ASSERT((mask & ~SBTML_ALLOW) == 0);
3455 +
3456 + /* mask and set */
3457 + if (mask || val) {
3458 + w = (R_SBREG(si, &sb->sbtmstatelow) & ~mask) | val;
3459 + W_SBREG(si, &sb->sbtmstatelow, w);
3460 + }
3461 +
3462 + /* return the new value */
3463 + return (R_SBREG(si, &sb->sbtmstatelow) & SBTML_ALLOW);
3464 +}
3465 +
3466 +/* set/clear sbtmstatehigh core-specific flags */
3467 +uint32
3468 +sb_coreflagshi(sb_t *sbh, uint32 mask, uint32 val)
3469 +{
3470 + sb_info_t *si;
3471 + sbconfig_t *sb;
3472 + uint32 w;
3473 +
3474 + si = SB_INFO(sbh);
3475 + sb = REGS2SB(si->curmap);
3476 +
3477 + ASSERT((val & ~mask) == 0);
3478 + ASSERT((mask & ~SBTMH_FL_MASK) == 0);
3479 +
3480 + /* mask and set */
3481 + if (mask || val) {
3482 + w = (R_SBREG(si, &sb->sbtmstatehigh) & ~mask) | val;
3483 + W_SBREG(si, &sb->sbtmstatehigh, w);
3484 + }
3485 +
3486 + /* return the new value */
3487 + return (R_SBREG(si, &sb->sbtmstatehigh) & SBTMH_FL_MASK);
3488 +}
3489 +
3490 +/* caller needs to take care of core-specific bist hazards */
3491 +int
3492 +sb_corebist(sb_t *sbh, uint coreid, uint coreunit)
3493 +{
3494 + uint32 sblo;
3495 + uint coreidx;
3496 + sb_info_t *si;
3497 + int result = 0;
3498 +
3499 + si = SB_INFO(sbh);
3500 +
3501 + coreidx = sb_findcoreidx(si, coreid, coreunit);
3502 + if (!GOODIDX(coreidx))
3503 + result = BCME_ERROR;
3504 + else {
3505 + sblo = sb_corereg(si, coreidx, SBCONFIGOFF + OFFSETOF(sbconfig_t, sbtmstatelow), 0, 0);
3506 + sb_corereg(si, coreidx, SBCONFIGOFF + OFFSETOF(sbconfig_t, sbtmstatelow), ~0, (sblo | SBTML_FGC | SBTML_BE));
3507 +
3508 + SPINWAIT(((sb_corereg(si, coreidx, SBCONFIGOFF + OFFSETOF(sbconfig_t, sbtmstatehigh), 0, 0) & SBTMH_BISTD) == 0), 100000);
3509 +
3510 + if (sb_corereg(si, coreidx, SBCONFIGOFF + OFFSETOF(sbconfig_t, sbtmstatehigh), 0, 0) & SBTMH_BISTF)
3511 + result = BCME_ERROR;
3512 +
3513 + sb_corereg(si, coreidx, SBCONFIGOFF + OFFSETOF(sbconfig_t, sbtmstatelow), ~0, sblo);
3514 + }
3515 +
3516 + return result;
3517 +}
3518 +
3519 +bool
3520 +sb_iscoreup(sb_t *sbh)
3521 +{
3522 + sb_info_t *si;
3523 + sbconfig_t *sb;
3524 +
3525 + si = SB_INFO(sbh);
3526 + sb = REGS2SB(si->curmap);
3527 +
3528 + return ((R_SBREG(si, &(sb)->sbtmstatelow) & (SBTML_RESET | SBTML_REJ_MASK | SBTML_CLK)) == SBTML_CLK);
3529 +}
3530 +
3531 +/*
3532 + * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation,
3533 + * switch back to the original core, and return the new value.
3534 + */
3535 +static uint
3536 +sb_corereg(sb_info_t *si, uint coreidx, uint regoff, uint mask, uint val)
3537 +{
3538 + uint origidx;
3539 + uint32 *r;
3540 + uint w;
3541 + uint intr_val = 0;
3542 +
3543 + ASSERT(GOODIDX(coreidx));
3544 + ASSERT(regoff < SB_CORE_SIZE);
3545 + ASSERT((val & ~mask) == 0);
3546 +
3547 + INTR_OFF(si, intr_val);
3548 +
3549 + /* save current core index */
3550 + origidx = sb_coreidx(&si->sb);
3551 +
3552 + /* switch core */
3553 + r = (uint32*) ((uchar*) sb_setcoreidx(&si->sb, coreidx) + regoff);
3554 +
3555 + /* mask and set */
3556 + if (mask || val) {
3557 + if (regoff >= SBCONFIGOFF) {
3558 + w = (R_SBREG(si, r) & ~mask) | val;
3559 + W_SBREG(si, r, w);
3560 + } else {
3561 + w = (R_REG(r) & ~mask) | val;
3562 + W_REG(r, w);
3563 + }
3564 + }
3565 +
3566 + /* readback */
3567 + if (regoff >= SBCONFIGOFF)
3568 + w = R_SBREG(si, r);
3569 + else
3570 + w = R_REG(r);
3571 +
3572 + /* restore core index */
3573 + if (origidx != coreidx)
3574 + sb_setcoreidx(&si->sb, origidx);
3575 +
3576 + INTR_RESTORE(si, intr_val);
3577 + return (w);
3578 +}
3579 +
3580 +#define DWORD_ALIGN(x) (x & ~(0x03))
3581 +#define BYTE_POS(x) (x & 0x3)
3582 +#define WORD_POS(x) (x & 0x1)
3583 +
3584 +#define BYTE_SHIFT(x) (8 * BYTE_POS(x))
3585 +#define WORD_SHIFT(x) (16 * WORD_POS(x))
3586 +
3587 +#define BYTE_VAL(a, x) ((a >> BYTE_SHIFT(x)) & 0xFF)
3588 +#define WORD_VAL(a, x) ((a >> WORD_SHIFT(x)) & 0xFFFF)
3589 +
3590 +#define read_pci_cfg_byte(a) \
3591 + (BYTE_VAL(OSL_PCI_READ_CONFIG(si->osh, DWORD_ALIGN(a), 4), a) & 0xff)
3592 +
3593 +#define read_pci_cfg_write(a) \
3594 + (WORD_VAL(OSL_PCI_READ_CONFIG(si->osh, DWORD_ALIGN(a), 4), a) & 0xffff)
3595 +
3596 +
3597 +/* scan the sb enumerated space to identify all cores */
3598 +static void
3599 +BCMINITFN(sb_scan)(sb_info_t *si)
3600 +{
3601 + uint origidx;
3602 + uint i;
3603 + bool pci;
3604 + uint pciidx;
3605 + uint pcirev;
3606 +
3607 +
3608 +
3609 + /* numcores should already be set */
3610 + ASSERT((si->numcores > 0) && (si->numcores <= SB_MAXCORES));
3611 +
3612 + /* save current core index */
3613 + origidx = sb_coreidx(&si->sb);
3614 +
3615 + si->sb.buscorerev = NOREV;
3616 + si->sb.buscoreidx = BADIDX;
3617 +
3618 + si->gpioidx = BADIDX;
3619 +
3620 + pci = FALSE;
3621 + pcirev = NOREV;
3622 + pciidx = BADIDX;
3623 +
3624 + for (i = 0; i < si->numcores; i++) {
3625 + sb_setcoreidx(&si->sb, i);
3626 + si->coreid[i] = sb_coreid(&si->sb);
3627 +
3628 + if (si->coreid[i] == SB_PCI) {
3629 + pciidx = i;
3630 + pcirev = sb_corerev(&si->sb);
3631 + pci = TRUE;
3632 + }
3633 + }
3634 + if (pci) {
3635 + si->sb.buscoretype = SB_PCI;
3636 + si->sb.buscorerev = pcirev;
3637 + si->sb.buscoreidx = pciidx;
3638 + }
3639 +
3640 + /*
3641 + * Find the gpio "controlling core" type and index.
3642 + * Precedence:
3643 + * - if there's a chip common core - use that
3644 + * - else if there's a pci core (rev >= 2) - use that
3645 + * - else there had better be an extif core (4710 only)
3646 + */
3647 + if (GOODIDX(sb_findcoreidx(si, SB_CC, 0))) {
3648 + si->gpioidx = sb_findcoreidx(si, SB_CC, 0);
3649 + si->gpioid = SB_CC;
3650 + } else if (PCI(si) && (si->sb.buscorerev >= 2)) {
3651 + si->gpioidx = si->sb.buscoreidx;
3652 + si->gpioid = SB_PCI;
3653 + } else if (sb_findcoreidx(si, SB_EXTIF, 0)) {
3654 + si->gpioidx = sb_findcoreidx(si, SB_EXTIF, 0);
3655 + si->gpioid = SB_EXTIF;
3656 + } else
3657 + ASSERT(si->gpioidx != BADIDX);
3658 +
3659 + /* return to original core index */
3660 + sb_setcoreidx(&si->sb, origidx);
3661 +}
3662 +
3663 +/* may be called with core in reset */
3664 +void
3665 +sb_detach(sb_t *sbh)
3666 +{
3667 + sb_info_t *si;
3668 + uint idx;
3669 +
3670 + si = SB_INFO(sbh);
3671 +
3672 + if (si == NULL)
3673 + return;
3674 +
3675 + if (BUSTYPE(si->sb.bustype) == SB_BUS)
3676 + for (idx = 0; idx < SB_MAXCORES; idx++)
3677 + if (si->regs[idx]) {
3678 + REG_UNMAP(si->regs[idx]);
3679 + si->regs[idx] = NULL;
3680 + }
3681 +
3682 + if (si != &ksi)
3683 + MFREE(si->osh, si, sizeof (sb_info_t));
3684 +}
3685 +
3686 +/* use pci dev id to determine chip id for chips not having a chipcommon core */
3687 +static uint
3688 +BCMINITFN(sb_pcidev2chip)(uint pcidev)
3689 +{
3690 + if ((pcidev >= BCM4710_DEVICE_ID) && (pcidev <= BCM47XX_USB_ID))
3691 + return (BCM4710_DEVICE_ID);
3692 + if ((pcidev >= BCM4402_DEVICE_ID) && (pcidev <= BCM4402_V90_ID))
3693 + return (BCM4402_DEVICE_ID);
3694 + if (pcidev == BCM4401_ENET_ID)
3695 + return (BCM4402_DEVICE_ID);
3696 + if ((pcidev >= BCM4307_V90_ID) && (pcidev <= BCM4307_D11B_ID))
3697 + return (BCM4307_DEVICE_ID);
3698 + if (pcidev == BCM4301_DEVICE_ID)
3699 + return (BCM4301_DEVICE_ID);
3700 +
3701 + return (0);
3702 +}
3703 +
3704 +/* convert chip number to number of i/o cores */
3705 +static uint
3706 +BCMINITFN(sb_chip2numcores)(uint chip)
3707 +{
3708 + if (chip == BCM4710_DEVICE_ID)
3709 + return (9);
3710 + if (chip == BCM4402_DEVICE_ID)
3711 + return (3);
3712 + if ((chip == BCM4301_DEVICE_ID) || (chip == BCM4307_DEVICE_ID))
3713 + return (5);
3714 + if (chip == BCM4306_DEVICE_ID) /* < 4306c0 */
3715 + return (6);
3716 + if (chip == BCM4704_DEVICE_ID)
3717 + return (9);
3718 + if (chip == BCM5365_DEVICE_ID)
3719 + return (7);
3720 +
3721 + SB_ERROR(("sb_chip2numcores: unsupported chip 0x%x\n", chip));
3722 + ASSERT(0);
3723 + return (1);
3724 +}
3725 +
3726 +/* return index of coreid or BADIDX if not found */
3727 +static uint
3728 +sb_findcoreidx( sb_info_t *si, uint coreid, uint coreunit)
3729 +{
3730 + uint found;
3731 + uint i;
3732 +
3733 + found = 0;
3734 +
3735 + for (i = 0; i < si->numcores; i++)
3736 + if (si->coreid[i] == coreid) {
3737 + if (found == coreunit)
3738 + return (i);
3739 + found++;
3740 + }
3741 +
3742 + return (BADIDX);
3743 +}
3744 +
3745 +/*
3746 + * this function changes logical "focus" to the indiciated core,
3747 + * must be called with interrupt off.
3748 + * Moreover, callers should keep interrupts off during switching out of and back to d11 core
3749 + */
3750 +void*
3751 +sb_setcoreidx(sb_t *sbh, uint coreidx)
3752 +{
3753 + sb_info_t *si;
3754 + uint32 sbaddr;
3755 +
3756 + si = SB_INFO(sbh);
3757 +
3758 + if (coreidx >= si->numcores)
3759 + return (NULL);
3760 +
3761 + /*
3762 + * If the user has provided an interrupt mask enabled function,
3763 + * then assert interrupts are disabled before switching the core.
3764 + */
3765 + ASSERT((si->intrsenabled_fn == NULL) || !(*(si)->intrsenabled_fn)((si)->intr_arg));
3766 +
3767 + sbaddr = SB_ENUM_BASE + (coreidx * SB_CORE_SIZE);
3768 +
3769 + switch (BUSTYPE(si->sb.bustype)) {
3770 + case SB_BUS:
3771 + /* map new one */
3772 + if (!si->regs[coreidx]) {
3773 + si->regs[coreidx] = (void*)REG_MAP(sbaddr, SB_CORE_SIZE);
3774 + ASSERT(GOODREGS(si->regs[coreidx]));
3775 + }
3776 + si->curmap = si->regs[coreidx];
3777 + break;
3778 +
3779 + case PCI_BUS:
3780 + /* point bar0 window */
3781 + OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN, 4, sbaddr);
3782 + break;
3783 +
3784 +#ifdef BCMJTAG
3785 + case JTAG_BUS:
3786 + /* map new one */
3787 + if (!si->regs[coreidx]) {
3788 + si->regs[coreidx] = (void *)sbaddr;
3789 + ASSERT(GOODREGS(si->regs[coreidx]));
3790 + }
3791 + si->curmap = si->regs[coreidx];
3792 + break;
3793 +#endif /* BCMJTAG */
3794 + }
3795 +
3796 + si->curidx = coreidx;
3797 +
3798 + return (si->curmap);
3799 +}
3800 +
3801 +/*
3802 + * this function changes logical "focus" to the indiciated core,
3803 + * must be called with interrupt off.
3804 + * Moreover, callers should keep interrupts off during switching out of and back to d11 core
3805 + */
3806 +void*
3807 +sb_setcore(sb_t *sbh, uint coreid, uint coreunit)
3808 +{
3809 + sb_info_t *si;
3810 + uint idx;
3811 +
3812 + si = SB_INFO(sbh);
3813 + idx = sb_findcoreidx(si, coreid, coreunit);
3814 + if (!GOODIDX(idx))
3815 + return (NULL);
3816 +
3817 + return (sb_setcoreidx(sbh, idx));
3818 +}
3819 +
3820 +/* return chip number */
3821 +uint
3822 +BCMINITFN(sb_chip)(sb_t *sbh)
3823 +{
3824 + sb_info_t *si;
3825 +
3826 + si = SB_INFO(sbh);
3827 + return (si->sb.chip);
3828 +}
3829 +
3830 +/* return chip revision number */
3831 +uint
3832 +BCMINITFN(sb_chiprev)(sb_t *sbh)
3833 +{
3834 + sb_info_t *si;
3835 +
3836 + si = SB_INFO(sbh);
3837 + return (si->sb.chiprev);
3838 +}
3839 +
3840 +/* return chip common revision number */
3841 +uint
3842 +BCMINITFN(sb_chipcrev)(sb_t *sbh)
3843 +{
3844 + sb_info_t *si;
3845 +
3846 + si = SB_INFO(sbh);
3847 + return (si->sb.ccrev);
3848 +}
3849 +
3850 +/* return chip package option */
3851 +uint
3852 +BCMINITFN(sb_chippkg)(sb_t *sbh)
3853 +{
3854 + sb_info_t *si;
3855 +
3856 + si = SB_INFO(sbh);
3857 + return (si->sb.chippkg);
3858 +}
3859 +
3860 +/* return PCI core rev. */
3861 +uint
3862 +BCMINITFN(sb_pcirev)(sb_t *sbh)
3863 +{
3864 + sb_info_t *si;
3865 +
3866 + si = SB_INFO(sbh);
3867 + return (si->sb.buscorerev);
3868 +}
3869 +
3870 +bool
3871 +BCMINITFN(sb_war16165)(sb_t *sbh)
3872 +{
3873 + sb_info_t *si;
3874 +
3875 + si = SB_INFO(sbh);
3876 +
3877 + return (PCI(si) && (si->sb.buscorerev <= 10));
3878 +}
3879 +
3880 +/* return board vendor id */
3881 +uint
3882 +BCMINITFN(sb_boardvendor)(sb_t *sbh)
3883 +{
3884 + sb_info_t *si;
3885 +
3886 + si = SB_INFO(sbh);
3887 + return (si->sb.boardvendor);
3888 +}
3889 +
3890 +/* return boardtype */
3891 +uint
3892 +BCMINITFN(sb_boardtype)(sb_t *sbh)
3893 +{
3894 + sb_info_t *si;
3895 + char *var;
3896 +
3897 + si = SB_INFO(sbh);
3898 +
3899 + if (BUSTYPE(si->sb.bustype) == SB_BUS && si->sb.boardtype == 0xffff) {
3900 + /* boardtype format is a hex string */
3901 + si->sb.boardtype = getintvar(NULL, "boardtype");
3902 +
3903 + /* backward compatibility for older boardtype string format */
3904 + if ((si->sb.boardtype == 0) && (var = getvar(NULL, "boardtype"))) {
3905 + if (!strcmp(var, "bcm94710dev"))
3906 + si->sb.boardtype = BCM94710D_BOARD;
3907 + else if (!strcmp(var, "bcm94710ap"))
3908 + si->sb.boardtype = BCM94710AP_BOARD;
3909 + else if (!strcmp(var, "bu4710"))
3910 + si->sb.boardtype = BU4710_BOARD;
3911 + else if (!strcmp(var, "bcm94702mn"))
3912 + si->sb.boardtype = BCM94702MN_BOARD;
3913 + else if (!strcmp(var, "bcm94710r1"))
3914 + si->sb.boardtype = BCM94710R1_BOARD;
3915 + else if (!strcmp(var, "bcm94710r4"))
3916 + si->sb.boardtype = BCM94710R4_BOARD;
3917 + else if (!strcmp(var, "bcm94702cpci"))
3918 + si->sb.boardtype = BCM94702CPCI_BOARD;
3919 + else if (!strcmp(var, "bcm95380_rr"))
3920 + si->sb.boardtype = BCM95380RR_BOARD;
3921 + }
3922 + }
3923 +
3924 + return (si->sb.boardtype);
3925 +}
3926 +
3927 +/* return bus type of sbh device */
3928 +uint
3929 +sb_bus(sb_t *sbh)
3930 +{
3931 + sb_info_t *si;
3932 +
3933 + si = SB_INFO(sbh);
3934 + return (si->sb.bustype);
3935 +}
3936 +
3937 +/* return bus core type */
3938 +uint
3939 +sb_buscoretype(sb_t *sbh)
3940 +{
3941 + sb_info_t *si;
3942 +
3943 + si = SB_INFO(sbh);
3944 +
3945 + return (si->sb.buscoretype);
3946 +}
3947 +
3948 +/* return bus core revision */
3949 +uint
3950 +sb_buscorerev(sb_t *sbh)
3951 +{
3952 + sb_info_t *si;
3953 + si = SB_INFO(sbh);
3954 +
3955 + return (si->sb.buscorerev);
3956 +}
3957 +
3958 +/* return list of found cores */
3959 +uint
3960 +sb_corelist(sb_t *sbh, uint coreid[])
3961 +{
3962 + sb_info_t *si;
3963 +
3964 + si = SB_INFO(sbh);
3965 +
3966 + bcopy((uchar*)si->coreid, (uchar*)coreid, (si->numcores * sizeof (uint)));
3967 + return (si->numcores);
3968 +}
3969 +
3970 +/* return current register mapping */
3971 +void *
3972 +sb_coreregs(sb_t *sbh)
3973 +{
3974 + sb_info_t *si;
3975 +
3976 + si = SB_INFO(sbh);
3977 + ASSERT(GOODREGS(si->curmap));
3978 +
3979 + return (si->curmap);
3980 +}
3981 +
3982 +
3983 +/* do buffered registers update */
3984 +void
3985 +sb_commit(sb_t *sbh)
3986 +{
3987 + sb_info_t *si;
3988 + uint origidx;
3989 + uint intr_val = 0;
3990 +
3991 + si = SB_INFO(sbh);
3992 +
3993 + origidx = si->curidx;
3994 + ASSERT(GOODIDX(origidx));
3995 +
3996 + INTR_OFF(si, intr_val);
3997 +
3998 + /* switch over to chipcommon core if there is one, else use pci */
3999 + if (si->sb.ccrev != NOREV) {
4000 + chipcregs_t *ccregs = (chipcregs_t *)sb_setcore(sbh, SB_CC, 0);
4001 +
4002 + /* do the buffer registers update */
4003 + W_REG(&ccregs->broadcastaddress, SB_COMMIT);
4004 + W_REG(&ccregs->broadcastdata, 0x0);
4005 + } else if (PCI(si)) {
4006 + sbpciregs_t *pciregs = (sbpciregs_t *)sb_setcore(sbh, SB_PCI, 0);
4007 +
4008 + /* do the buffer registers update */
4009 + W_REG(&pciregs->bcastaddr, SB_COMMIT);
4010 + W_REG(&pciregs->bcastdata, 0x0);
4011 + } else
4012 + ASSERT(0);
4013 +
4014 + /* restore core index */
4015 + sb_setcoreidx(sbh, origidx);
4016 + INTR_RESTORE(si, intr_val);
4017 +}
4018 +
4019 +/* reset and re-enable a core */
4020 +void
4021 +sb_core_reset(sb_t *sbh, uint32 bits)
4022 +{
4023 + sb_info_t *si;
4024 + sbconfig_t *sb;
4025 + volatile uint32 dummy;
4026 +