allow nvram access to kernel modules on brcm-2.6
[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-19 01:36:54.000000000 +0100
3 +++ linux.dev/arch/mips/Kconfig 2005-12-28 16:37:32.810257250 +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-19 01:36:54.000000000 +0100
24 +++ linux.dev/arch/mips/Makefile 2005-12-28 16:37:32.814257500 +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-28 16:37:32.814257500 +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-28 16:37:32.814257500 +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-28 16:37:32.814257500 +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-28 16:37:32.814257500 +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-28 16:37:32.818257750 +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-28 16:37:32.834258750 +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-28 19:30:54.804469750 +0100
1251 @@ -0,0 +1,192 @@
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(char *nv_buf, const 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 early_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 +
1418 +char *nvram_get(const char *name)
1419 +{
1420 + char *var, *value, *end, *eq;
1421 +
1422 + if (!name)
1423 + return NULL;
1424 +
1425 + if (!nvram_buf[0])
1426 + return NULL;
1427 +
1428 + /* Look for name=value and return value */
1429 + var = &nvram_buf[sizeof(struct nvram_header)];
1430 + end = nvram_buf + sizeof(nvram_buf) - 2;
1431 + end[0] = end[1] = '\0';
1432 + for (; *var; var = value + strlen(value) + 1) {
1433 + if (!(eq = strchr(var, '=')))
1434 + break;
1435 + value = eq + 1;
1436 + if ((eq - var) == strlen(name) && strncmp(var, name, (eq - var)) == 0)
1437 + return value;
1438 + }
1439 +
1440 + return NULL;
1441 +}
1442 +
1443 +EXPORT_SYMBOL(nvram_get);
1444 diff -urN linux.old/arch/mips/bcm947xx/broadcom/sbmips.c linux.dev/arch/mips/bcm947xx/broadcom/sbmips.c
1445 --- linux.old/arch/mips/bcm947xx/broadcom/sbmips.c 1970-01-01 01:00:00.000000000 +0100
1446 +++ linux.dev/arch/mips/bcm947xx/broadcom/sbmips.c 2005-12-28 19:19:50.570957750 +0100
1447 @@ -0,0 +1,1038 @@
1448 +/*
1449 + * BCM47XX Sonics SiliconBackplane MIPS core routines
1450 + *
1451 + * Copyright 2005, Broadcom Corporation
1452 + * All Rights Reserved.
1453 + *
1454 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
1455 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
1456 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
1457 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
1458 + *
1459 + * $Id$
1460 + */
1461 +
1462 +#include <typedefs.h>
1463 +#include <osl.h>
1464 +#include <sbutils.h>
1465 +#include <bcmdevs.h>
1466 +#include <bcmnvram.h>
1467 +#include <bcmutils.h>
1468 +#include <hndmips.h>
1469 +#include <sbconfig.h>
1470 +#include <sbextif.h>
1471 +#include <sbchipc.h>
1472 +#include <sbmemc.h>
1473 +#include <mipsinc.h>
1474 +#include <sbutils.h>
1475 +
1476 +/*
1477 + * Returns TRUE if an external UART exists at the given base
1478 + * register.
1479 + */
1480 +static bool
1481 +BCMINITFN(serial_exists)(uint8 *regs)
1482 +{
1483 + uint8 save_mcr, status1;
1484 +
1485 + save_mcr = R_REG(&regs[UART_MCR]);
1486 + W_REG(&regs[UART_MCR], UART_MCR_LOOP | 0x0a);
1487 + status1 = R_REG(&regs[UART_MSR]) & 0xf0;
1488 + W_REG(&regs[UART_MCR], save_mcr);
1489 +
1490 + return (status1 == 0x90);
1491 +}
1492 +
1493 +/*
1494 + * Initializes UART access. The callback function will be called once
1495 + * per found UART.
1496 + */
1497 +void
1498 +BCMINITFN(sb_serial_init)(sb_t *sbh, void (*add)(void *regs, uint irq, uint baud_base, uint reg_shift))
1499 +{
1500 + void *regs;
1501 + ulong base;
1502 + uint irq;
1503 + int i, n;
1504 +
1505 + if ((regs = sb_setcore(sbh, SB_EXTIF, 0))) {
1506 + extifregs_t *eir = (extifregs_t *) regs;
1507 + sbconfig_t *sb;
1508 +
1509 + /* Determine external UART register base */
1510 + sb = (sbconfig_t *)((ulong) eir + SBCONFIGOFF);
1511 + base = EXTIF_CFGIF_BASE(sb_base(R_REG(&sb->sbadmatch1)));
1512 +
1513 + /* Determine IRQ */
1514 + irq = sb_irq(sbh);
1515 +
1516 + /* Disable GPIO interrupt initially */
1517 + W_REG(&eir->gpiointpolarity, 0);
1518 + W_REG(&eir->gpiointmask, 0);
1519 +
1520 + /* Search for external UARTs */
1521 + n = 2;
1522 + for (i = 0; i < 2; i++) {
1523 + regs = (void *) REG_MAP(base + (i * 8), 8);
1524 + if (BCMINIT(serial_exists)(regs)) {
1525 + /* Set GPIO 1 to be the external UART IRQ */
1526 + W_REG(&eir->gpiointmask, 2);
1527 + if (add)
1528 + add(regs, irq, 13500000, 0);
1529 + }
1530 + }
1531 +
1532 + /* Add internal UART if enabled */
1533 + if (R_REG(&eir->corecontrol) & CC_UE)
1534 + if (add)
1535 + add((void *) &eir->uartdata, irq, sb_clock(sbh), 2);
1536 + } else if ((regs = sb_setcore(sbh, SB_CC, 0))) {
1537 + chipcregs_t *cc = (chipcregs_t *) regs;
1538 + uint32 rev, cap, pll, baud_base, div;
1539 +
1540 + /* Determine core revision and capabilities */
1541 + rev = sb_corerev(sbh);
1542 + cap = R_REG(&cc->capabilities);
1543 + pll = cap & CAP_PLL_MASK;
1544 +
1545 + /* Determine IRQ */
1546 + irq = sb_irq(sbh);
1547 +
1548 + if (pll == PLL_TYPE1) {
1549 + /* PLL clock */
1550 + baud_base = sb_clock_rate(pll,
1551 + R_REG(&cc->clockcontrol_n),
1552 + R_REG(&cc->clockcontrol_m2));
1553 + div = 1;
1554 + } else {
1555 + if (rev >= 11) {
1556 + /* Fixed ALP clock */
1557 + baud_base = 20000000;
1558 + div = 1;
1559 + /* Set the override bit so we don't divide it */
1560 + W_REG(&cc->corecontrol, CC_UARTCLKO);
1561 + } else if (rev >= 3) {
1562 + /* Internal backplane clock */
1563 + baud_base = sb_clock(sbh);
1564 + div = 2; /* Minimum divisor */
1565 + W_REG(&cc->clkdiv,
1566 + ((R_REG(&cc->clkdiv) & ~CLKD_UART) | div));
1567 + } else {
1568 + /* Fixed internal backplane clock */
1569 + baud_base = 88000000;
1570 + div = 48;
1571 + }
1572 +
1573 + /* Clock source depends on strapping if UartClkOverride is unset */
1574 + if ((rev > 0) &&
1575 + ((R_REG(&cc->corecontrol) & CC_UARTCLKO) == 0)) {
1576 + if ((cap & CAP_UCLKSEL) == CAP_UINTCLK) {
1577 + /* Internal divided backplane clock */
1578 + baud_base /= div;
1579 + } else {
1580 + /* Assume external clock of 1.8432 MHz */
1581 + baud_base = 1843200;
1582 + }
1583 + }
1584 + }
1585 +
1586 + /* Add internal UARTs */
1587 + n = cap & CAP_UARTS_MASK;
1588 + for (i = 0; i < n; i++) {
1589 + /* Register offset changed after revision 0 */
1590 + if (rev)
1591 + regs = (void *)((ulong) &cc->uart0data + (i * 256));
1592 + else
1593 + regs = (void *)((ulong) &cc->uart0data + (i * 8));
1594 +
1595 + if (add)
1596 + add(regs, irq, baud_base, 0);
1597 + }
1598 + }
1599 +}
1600 +
1601 +/*
1602 + * Initialize jtag master and return handle for
1603 + * jtag_rwreg. Returns NULL on failure.
1604 + */
1605 +void *
1606 +sb_jtagm_init(sb_t *sbh, uint clkd, bool exttap)
1607 +{
1608 + void *regs;
1609 +
1610 + if ((regs = sb_setcore(sbh, SB_CC, 0)) != NULL) {
1611 + chipcregs_t *cc = (chipcregs_t *) regs;
1612 + uint32 tmp;
1613 +
1614 + /*
1615 + * Determine jtagm availability from
1616 + * core revision and capabilities.
1617 + */
1618 + tmp = sb_corerev(sbh);
1619 + /*
1620 + * Corerev 10 has jtagm, but the only chip
1621 + * with it does not have a mips, and
1622 + * the layout of the jtagcmd register is
1623 + * different. We'll only accept >= 11.
1624 + */
1625 + if (tmp < 11)
1626 + return (NULL);
1627 +
1628 + tmp = R_REG(&cc->capabilities);
1629 + if ((tmp & CAP_JTAGP) == 0)
1630 + return (NULL);
1631 +
1632 + /* Set clock divider if requested */
1633 + if (clkd != 0) {
1634 + tmp = R_REG(&cc->clkdiv);
1635 + tmp = (tmp & ~CLKD_JTAG) |
1636 + ((clkd << CLKD_JTAG_SHIFT) & CLKD_JTAG);
1637 + W_REG(&cc->clkdiv, tmp);
1638 + }
1639 +
1640 + /* Enable jtagm */
1641 + tmp = JCTRL_EN | (exttap ? JCTRL_EXT_EN : 0);
1642 + W_REG(&cc->jtagctrl, tmp);
1643 + }
1644 +
1645 + return (regs);
1646 +}
1647 +
1648 +void
1649 +sb_jtagm_disable(void *h)
1650 +{
1651 + chipcregs_t *cc = (chipcregs_t *)h;
1652 +
1653 + W_REG(&cc->jtagctrl, R_REG(&cc->jtagctrl) & ~JCTRL_EN);
1654 +}
1655 +
1656 +/*
1657 + * Read/write a jtag register. Assumes a target with
1658 + * 8 bit IR and 32 bit DR.
1659 + */
1660 +#define IRWIDTH 8
1661 +#define DRWIDTH 32
1662 +uint32
1663 +jtag_rwreg(void *h, uint32 ir, uint32 dr)
1664 +{
1665 + chipcregs_t *cc = (chipcregs_t *) h;
1666 + uint32 tmp;
1667 +
1668 + W_REG(&cc->jtagir, ir);
1669 + W_REG(&cc->jtagdr, dr);
1670 + tmp = JCMD_START | JCMD_ACC_IRDR |
1671 + ((IRWIDTH - 1) << JCMD_IRW_SHIFT) |
1672 + (DRWIDTH - 1);
1673 + W_REG(&cc->jtagcmd, tmp);
1674 + while (((tmp = R_REG(&cc->jtagcmd)) & JCMD_BUSY) == JCMD_BUSY) {
1675 + /* OSL_DELAY(1); */
1676 + }
1677 +
1678 + tmp = R_REG(&cc->jtagdr);
1679 + return (tmp);
1680 +}
1681 +
1682 +/* Returns the SB interrupt flag of the current core. */
1683 +uint32
1684 +sb_flag(sb_t *sbh)
1685 +{
1686 + void *regs;
1687 + sbconfig_t *sb;
1688 +
1689 + regs = sb_coreregs(sbh);
1690 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
1691 +
1692 + return (R_REG(&sb->sbtpsflag) & SBTPS_NUM0_MASK);
1693 +}
1694 +
1695 +static const uint32 sbips_int_mask[] = {
1696 + 0,
1697 + SBIPS_INT1_MASK,
1698 + SBIPS_INT2_MASK,
1699 + SBIPS_INT3_MASK,
1700 + SBIPS_INT4_MASK
1701 +};
1702 +
1703 +static const uint32 sbips_int_shift[] = {
1704 + 0,
1705 + 0,
1706 + SBIPS_INT2_SHIFT,
1707 + SBIPS_INT3_SHIFT,
1708 + SBIPS_INT4_SHIFT
1709 +};
1710 +
1711 +/*
1712 + * Returns the MIPS IRQ assignment of the current core. If unassigned,
1713 + * 0 is returned.
1714 + */
1715 +uint
1716 +sb_irq(sb_t *sbh)
1717 +{
1718 + uint idx;
1719 + void *regs;
1720 + sbconfig_t *sb;
1721 + uint32 flag, sbipsflag;
1722 + uint irq = 0;
1723 +
1724 + flag = sb_flag(sbh);
1725 +
1726 + idx = sb_coreidx(sbh);
1727 +
1728 + if ((regs = sb_setcore(sbh, SB_MIPS, 0)) ||
1729 + (regs = sb_setcore(sbh, SB_MIPS33, 0))) {
1730 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
1731 +
1732 + /* sbipsflag specifies which core is routed to interrupts 1 to 4 */
1733 + sbipsflag = R_REG(&sb->sbipsflag);
1734 + for (irq = 1; irq <= 4; irq++) {
1735 + if (((sbipsflag & sbips_int_mask[irq]) >> sbips_int_shift[irq]) == flag)
1736 + break;
1737 + }
1738 + if (irq == 5)
1739 + irq = 0;
1740 + }
1741 +
1742 + sb_setcoreidx(sbh, idx);
1743 +
1744 + return irq;
1745 +}
1746 +
1747 +/* Clears the specified MIPS IRQ. */
1748 +static void
1749 +BCMINITFN(sb_clearirq)(sb_t *sbh, uint irq)
1750 +{
1751 + void *regs;
1752 + sbconfig_t *sb;
1753 +
1754 + if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) &&
1755 + !(regs = sb_setcore(sbh, SB_MIPS33, 0)))
1756 + ASSERT(regs);
1757 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
1758 +
1759 + if (irq == 0)
1760 + W_REG(&sb->sbintvec, 0);
1761 + else
1762 + OR_REG(&sb->sbipsflag, sbips_int_mask[irq]);
1763 +}
1764 +
1765 +/*
1766 + * Assigns the specified MIPS IRQ to the specified core. Shared MIPS
1767 + * IRQ 0 may be assigned more than once.
1768 + */
1769 +static void
1770 +BCMINITFN(sb_setirq)(sb_t *sbh, uint irq, uint coreid, uint coreunit)
1771 +{
1772 + void *regs;
1773 + sbconfig_t *sb;
1774 + uint32 flag;
1775 +
1776 + regs = sb_setcore(sbh, coreid, coreunit);
1777 + ASSERT(regs);
1778 + flag = sb_flag(sbh);
1779 +
1780 + if (!(regs = sb_setcore(sbh, SB_MIPS, 0)) &&
1781 + !(regs = sb_setcore(sbh, SB_MIPS33, 0)))
1782 + ASSERT(regs);
1783 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
1784 +
1785 + if (irq == 0)
1786 + OR_REG(&sb->sbintvec, 1 << flag);
1787 + else {
1788 + flag <<= sbips_int_shift[irq];
1789 + ASSERT(!(flag & ~sbips_int_mask[irq]));
1790 + flag |= R_REG(&sb->sbipsflag) & ~sbips_int_mask[irq];
1791 + W_REG(&sb->sbipsflag, flag);
1792 + }
1793 +}
1794 +
1795 +/*
1796 + * Initializes clocks and interrupts. SB and NVRAM access must be
1797 + * initialized prior to calling.
1798 + */
1799 +void
1800 +BCMINITFN(sb_mips_init)(sb_t *sbh)
1801 +{
1802 + ulong hz, ns, tmp;
1803 + extifregs_t *eir;
1804 + chipcregs_t *cc;
1805 + char *value;
1806 + uint irq;
1807 +
1808 + /* Figure out current SB clock speed */
1809 + if ((hz = sb_clock(sbh)) == 0)
1810 + hz = 100000000;
1811 + ns = 1000000000 / hz;
1812 +
1813 + /* Setup external interface timing */
1814 + if ((eir = sb_setcore(sbh, SB_EXTIF, 0))) {
1815 + /* Initialize extif so we can get to the LEDs and external UART */
1816 + W_REG(&eir->prog_config, CF_EN);
1817 +
1818 + /* Set timing for the flash */
1819 + tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
1820 + tmp = tmp | (CEIL(40, ns) << FW_W1_SHIFT); /* W1 = 40nS */
1821 + tmp = tmp | CEIL(120, ns); /* W0 = 120nS */
1822 + W_REG(&eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */
1823 +
1824 + /* Set programmable interface timing for external uart */
1825 + tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
1826 + tmp = tmp | (CEIL(20, ns) << FW_W2_SHIFT); /* W2 = 20nS */
1827 + tmp = tmp | (CEIL(100, ns) << FW_W1_SHIFT); /* W1 = 100nS */
1828 + tmp = tmp | CEIL(120, ns); /* W0 = 120nS */
1829 + W_REG(&eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */
1830 + } else if ((cc = sb_setcore(sbh, SB_CC, 0))) {
1831 + /* Set timing for the flash */
1832 + tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
1833 + tmp |= CEIL(10, ns) << FW_W1_SHIFT; /* W1 = 10nS */
1834 + tmp |= CEIL(120, ns); /* W0 = 120nS */
1835 +
1836 + // Added by Chen-I for 5365
1837 + if (BCMINIT(sb_chip)(sbh) == BCM5365_DEVICE_ID)
1838 + {
1839 + W_REG(&cc->flash_waitcount, tmp);
1840 + W_REG(&cc->pcmcia_memwait, tmp);
1841 + }
1842 + else
1843 + {
1844 + if (sb_corerev(sbh) < 9)
1845 + W_REG(&cc->flash_waitcount, tmp);
1846 +
1847 + if ((sb_corerev(sbh) < 9) ||
1848 + ((BCMINIT(sb_chip)(sbh) == BCM5350_DEVICE_ID) && BCMINIT(sb_chiprev)(sbh) == 0)) {
1849 + W_REG(&cc->pcmcia_memwait, tmp);
1850 + }
1851 + }
1852 + }
1853 +
1854 + /* Chip specific initialization */
1855 + switch (BCMINIT(sb_chip)(sbh)) {
1856 + case BCM4710_DEVICE_ID:
1857 + /* Clear interrupt map */
1858 + for (irq = 0; irq <= 4; irq++)
1859 + BCMINIT(sb_clearirq)(sbh, irq);
1860 + BCMINIT(sb_setirq)(sbh, 0, SB_CODEC, 0);
1861 + BCMINIT(sb_setirq)(sbh, 0, SB_EXTIF, 0);
1862 + BCMINIT(sb_setirq)(sbh, 2, SB_ENET, 1);
1863 + BCMINIT(sb_setirq)(sbh, 3, SB_ILINE20, 0);
1864 + BCMINIT(sb_setirq)(sbh, 4, SB_PCI, 0);
1865 + ASSERT(eir);
1866 + value = BCMINIT(early_nvram_get)("et0phyaddr");
1867 + if (value && !strcmp(value, "31")) {
1868 + /* Enable internal UART */
1869 + W_REG(&eir->corecontrol, CC_UE);
1870 + /* Give USB its own interrupt */
1871 + BCMINIT(sb_setirq)(sbh, 1, SB_USB, 0);
1872 + } else {
1873 + /* Disable internal UART */
1874 + W_REG(&eir->corecontrol, 0);
1875 + /* Give Ethernet its own interrupt */
1876 + BCMINIT(sb_setirq)(sbh, 1, SB_ENET, 0);
1877 + BCMINIT(sb_setirq)(sbh, 0, SB_USB, 0);
1878 + }
1879 + break;
1880 + case BCM5350_DEVICE_ID:
1881 + /* Clear interrupt map */
1882 + for (irq = 0; irq <= 4; irq++)
1883 + BCMINIT(sb_clearirq)(sbh, irq);
1884 + BCMINIT(sb_setirq)(sbh, 0, SB_CC, 0);
1885 + BCMINIT(sb_setirq)(sbh, 1, SB_D11, 0);
1886 + BCMINIT(sb_setirq)(sbh, 2, SB_ENET, 0);
1887 + BCMINIT(sb_setirq)(sbh, 3, SB_PCI, 0);
1888 + BCMINIT(sb_setirq)(sbh, 4, SB_USB, 0);
1889 + break;
1890 + }
1891 +}
1892 +
1893 +uint32
1894 +BCMINITFN(sb_mips_clock)(sb_t *sbh)
1895 +{
1896 + extifregs_t *eir;
1897 + chipcregs_t *cc;
1898 + uint32 n, m;
1899 + uint idx;
1900 + uint32 pll_type, rate = 0;
1901 +
1902 + /* get index of the current core */
1903 + idx = sb_coreidx(sbh);
1904 + pll_type = PLL_TYPE1;
1905 +
1906 + /* switch to extif or chipc core */
1907 + if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) {
1908 + n = R_REG(&eir->clockcontrol_n);
1909 + m = R_REG(&eir->clockcontrol_sb);
1910 + } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) {
1911 + pll_type = R_REG(&cc->capabilities) & CAP_PLL_MASK;
1912 + n = R_REG(&cc->clockcontrol_n);
1913 + if ((pll_type == PLL_TYPE2) ||
1914 + (pll_type == PLL_TYPE4) ||
1915 + (pll_type == PLL_TYPE6) ||
1916 + (pll_type == PLL_TYPE7))
1917 + m = R_REG(&cc->clockcontrol_mips);
1918 + else if (pll_type == PLL_TYPE5) {
1919 + rate = 200000000;
1920 + goto out;
1921 + }
1922 + else if (pll_type == PLL_TYPE3) {
1923 + if (BCMINIT(sb_chip)(sbh) == BCM5365_DEVICE_ID) { /* 5365 is also type3 */
1924 + rate = 200000000;
1925 + goto out;
1926 + } else
1927 + m = R_REG(&cc->clockcontrol_m2); /* 5350 uses m2 to control mips */
1928 + } else
1929 + m = R_REG(&cc->clockcontrol_sb);
1930 + } else
1931 + goto out;
1932 +
1933 + // Added by Chen-I for 5365
1934 + if (BCMINIT(sb_chip)(sbh) == BCM5365_DEVICE_ID)
1935 + rate = 100000000;
1936 + else
1937 + /* calculate rate */
1938 + rate = sb_clock_rate(pll_type, n, m);
1939 +
1940 + if (pll_type == PLL_TYPE6)
1941 + rate = SB2MIPS_T6(rate);
1942 +
1943 +out:
1944 + /* switch back to previous core */
1945 + sb_setcoreidx(sbh, idx);
1946 +
1947 + return rate;
1948 +}
1949 +
1950 +#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
1951 +
1952 +static void
1953 +BCMINITFN(handler)(void)
1954 +{
1955 + /* Step 11 */
1956 + __asm__ (
1957 + ".set\tmips32\n\t"
1958 + "ssnop\n\t"
1959 + "ssnop\n\t"
1960 + /* Disable interrupts */
1961 + /* MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~(ALLINTS | STO_IE)); */
1962 + "mfc0 $15, $12\n\t"
1963 + /* Just a Hack to not to use reg 'at' which was causing problems on 4704 A2 */
1964 + "li $14, -31746\n\t"
1965 + "and $15, $15, $14\n\t"
1966 + "mtc0 $15, $12\n\t"
1967 + "eret\n\t"
1968 + "nop\n\t"
1969 + "nop\n\t"
1970 + ".set\tmips0"
1971 + );
1972 +}
1973 +
1974 +/* The following MUST come right after handler() */
1975 +static void
1976 +BCMINITFN(afterhandler)(void)
1977 +{
1978 +}
1979 +
1980 +/*
1981 + * Set the MIPS, backplane and PCI clocks as closely as possible.
1982 + */
1983 +bool
1984 +BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 pciclock)
1985 +{
1986 + extifregs_t *eir = NULL;
1987 + chipcregs_t *cc = NULL;
1988 + mipsregs_t *mipsr = NULL;
1989 + volatile uint32 *clockcontrol_n, *clockcontrol_sb, *clockcontrol_pci, *clockcontrol_m2;
1990 + uint32 orig_n, orig_sb, orig_pci, orig_m2, orig_mips, orig_ratio_parm, orig_ratio_cfg;
1991 + uint32 pll_type, sync_mode;
1992 + uint ic_size, ic_lsize;
1993 + uint idx, i;
1994 + typedef struct {
1995 + uint32 mipsclock;
1996 + uint16 n;
1997 + uint32 sb;
1998 + uint32 pci33;
1999 + uint32 pci25;
2000 + } n3m_table_t;
2001 + static n3m_table_t BCMINITDATA(type1_table)[] = {
2002 + { 96000000, 0x0303, 0x04020011, 0x11030011, 0x11050011 }, /* 96.000 32.000 24.000 */
2003 + { 100000000, 0x0009, 0x04020011, 0x11030011, 0x11050011 }, /* 100.000 33.333 25.000 */
2004 + { 104000000, 0x0802, 0x04020011, 0x11050009, 0x11090009 }, /* 104.000 31.200 24.960 */
2005 + { 108000000, 0x0403, 0x04020011, 0x11050009, 0x02000802 }, /* 108.000 32.400 24.923 */
2006 + { 112000000, 0x0205, 0x04020011, 0x11030021, 0x02000403 }, /* 112.000 32.000 24.889 */
2007 + { 115200000, 0x0303, 0x04020009, 0x11030011, 0x11050011 }, /* 115.200 32.000 24.000 */
2008 + { 120000000, 0x0011, 0x04020011, 0x11050011, 0x11090011 }, /* 120.000 30.000 24.000 */
2009 + { 124800000, 0x0802, 0x04020009, 0x11050009, 0x11090009 }, /* 124.800 31.200 24.960 */
2010 + { 128000000, 0x0305, 0x04020011, 0x11050011, 0x02000305 }, /* 128.000 32.000 24.000 */
2011 + { 132000000, 0x0603, 0x04020011, 0x11050011, 0x02000305 }, /* 132.000 33.000 24.750 */
2012 + { 136000000, 0x0c02, 0x04020011, 0x11090009, 0x02000603 }, /* 136.000 32.640 24.727 */
2013 + { 140000000, 0x0021, 0x04020011, 0x11050021, 0x02000c02 }, /* 140.000 30.000 24.706 */
2014 + { 144000000, 0x0405, 0x04020011, 0x01020202, 0x11090021 }, /* 144.000 30.857 24.686 */
2015 + { 150857142, 0x0605, 0x04020021, 0x02000305, 0x02000605 }, /* 150.857 33.000 24.000 */
2016 + { 152000000, 0x0e02, 0x04020011, 0x11050021, 0x02000e02 }, /* 152.000 32.571 24.000 */
2017 + { 156000000, 0x0802, 0x04020005, 0x11050009, 0x11090009 }, /* 156.000 31.200 24.960 */
2018 + { 160000000, 0x0309, 0x04020011, 0x11090011, 0x02000309 }, /* 160.000 32.000 24.000 */
2019 + { 163200000, 0x0c02, 0x04020009, 0x11090009, 0x02000603 }, /* 163.200 32.640 24.727 */
2020 + { 168000000, 0x0205, 0x04020005, 0x11030021, 0x02000403 }, /* 168.000 32.000 24.889 */
2021 + { 176000000, 0x0602, 0x04020003, 0x11050005, 0x02000602 }, /* 176.000 33.000 24.000 */
2022 + };
2023 + typedef struct {
2024 + uint32 mipsclock;
2025 + uint16 n;
2026 + uint32 m2; /* that is the clockcontrol_m2 */
2027 + } type3_table_t;
2028 + static type3_table_t type3_table[] = { /* for 5350, mips clock is always double sb clock */
2029 + { 150000000, 0x311, 0x4020005 },
2030 + { 200000000, 0x311, 0x4020003 },
2031 + };
2032 + typedef struct {
2033 + uint32 mipsclock;
2034 + uint32 sbclock;
2035 + uint16 n;
2036 + uint32 sb;
2037 + uint32 pci33;
2038 + uint32 m2;
2039 + uint32 m3;
2040 + uint32 ratio_cfg;
2041 + uint32 ratio_parm;
2042 + } n4m_table_t;
2043 +
2044 + static n4m_table_t BCMINITDATA(type2_table)[] = {
2045 + { 180000000, 80000000, 0x0403, 0x01010000, 0x01020300, 0x01020600, 0x05000100, 8, 0x012a00a9 },
2046 + { 180000000, 90000000, 0x0403, 0x01000100, 0x01020300, 0x01000100, 0x05000100, 11, 0x0aaa0555 },
2047 + { 200000000, 100000000, 0x0303, 0x02010000, 0x02040001, 0x02010000, 0x06000001, 11, 0x0aaa0555 },
2048 + { 211200000, 105600000, 0x0902, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
2049 + { 220800000, 110400000, 0x1500, 0x01000200, 0x01030400, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
2050 + { 230400000, 115200000, 0x0604, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
2051 + { 234000000, 104000000, 0x0b01, 0x01010000, 0x01010700, 0x01020600, 0x05000100, 8, 0x012a00a9 },
2052 + { 240000000, 120000000, 0x0803, 0x01000200, 0x01020600, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
2053 + { 252000000, 126000000, 0x0504, 0x01000100, 0x01020500, 0x01000100, 0x05000100, 11, 0x0aaa0555 },
2054 + { 264000000, 132000000, 0x0903, 0x01000200, 0x01020700, 0x01000200, 0x05000200, 11, 0x0aaa0555 },
2055 + { 270000000, 120000000, 0x0703, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9 },
2056 + { 276000000, 122666666, 0x1500, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9 },
2057 + { 280000000, 140000000, 0x0503, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 11, 0x0aaa0555 },
2058 + { 288000000, 128000000, 0x0604, 0x01010000, 0x01030400, 0x01020600, 0x05000100, 8, 0x012a00a9 },
2059 + { 288000000, 144000000, 0x0404, 0x01000000, 0x01010600, 0x01000000, 0x05000000, 11, 0x0aaa0555 },
2060 + { 300000000, 133333333, 0x0803, 0x01010000, 0x01020600, 0x01020600, 0x05000100, 8, 0x012a00a9 },
2061 + { 300000000, 150000000, 0x0803, 0x01000100, 0x01020600, 0x01000100, 0x05000100, 11, 0x0aaa0555 }
2062 + };
2063 +
2064 + static n4m_table_t BCMINITDATA(type4_table)[] = {
2065 + { 192000000, 96000000, 0x0702, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, 0x0aaa0555 },
2066 + { 198000000, 99000000, 0x0603, 0x11020005, 0x11030011, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2067 + { 200000000, 100000000, 0x0009, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 11, 0x0aaa0555 },
2068 + { 204000000, 102000000, 0x0c02, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2069 + { 208000000, 104000000, 0x0802, 0x11030002, 0x11090005, 0x11030002, 0x04000003, 11, 0x0aaa0555 },
2070 + { 210000000, 105000000, 0x0209, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2071 + { 216000000, 108000000, 0x0111, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2072 + { 224000000, 112000000, 0x0205, 0x11030002, 0x02002103, 0x11030002, 0x04000003, 11, 0x0aaa0555 },
2073 + { 228000000, 101333333, 0x0e02, 0x11030003, 0x11210005, 0x01030305, 0x04000005, 8, 0x012a00a9 },
2074 + { 228000000, 114000000, 0x0e02, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2075 + { 240000000, 102857143, 0x0109, 0x04000021, 0x01050203, 0x11030021, 0x04000003, 13, 0x254a14a9 },
2076 + { 240000000, 120000000, 0x0109, 0x11030002, 0x01050203, 0x11030002, 0x04000003, 11, 0x0aaa0555 },
2077 + { 252000000, 100800000, 0x0203, 0x04000009, 0x11050005, 0x02000209, 0x04000002, 9, 0x02520129 },
2078 + { 252000000, 126000000, 0x0203, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 11, 0x0aaa0555 },
2079 + { 264000000, 132000000, 0x0602, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 11, 0x0aaa0555 },
2080 + { 272000000, 116571428, 0x0c02, 0x04000021, 0x02000909, 0x02000221, 0x04000003, 13, 0x254a14a9 },
2081 + { 280000000, 120000000, 0x0209, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 13, 0x254a14a9 },
2082 + { 288000000, 123428571, 0x0111, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 13, 0x254a14a9 },
2083 + { 300000000, 120000000, 0x0009, 0x04000009, 0x01030203, 0x02000902, 0x04000002, 9, 0x02520129 },
2084 + { 300000000, 150000000, 0x0009, 0x04000005, 0x01030203, 0x04000005, 0x04000002, 11, 0x0aaa0555 }
2085 + };
2086 +
2087 + static n4m_table_t BCMINITDATA(type7_table)[] = {
2088 + { 183333333, 91666666, 0x0605, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, 0x0aaa0555 },
2089 + { 187500000, 93750000, 0x0a03, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 11, 0x0aaa0555 },
2090 + { 196875000, 98437500, 0x1003, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2091 + { 200000000, 100000000, 0x0311, 0x04000011, 0x11030011, 0x04000009, 0x04000003, 11, 0x0aaa0555 },
2092 + { 200000000, 100000000, 0x0311, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 11, 0x0aaa0555 },
2093 + { 206250000, 103125000, 0x1103, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2094 + { 212500000, 106250000, 0x0c05, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2095 + { 215625000, 107812500, 0x1203, 0x11090009, 0x11050005, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2096 + { 216666666, 108333333, 0x0805, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, 0x0aaa0555 },
2097 + { 225000000, 112500000, 0x0d03, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, 0x0aaa0555 },
2098 + { 233333333, 116666666, 0x0905, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 11, 0x0aaa0555 },
2099 + { 237500000, 118750000, 0x0e05, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 11, 0x0aaa0555 },
2100 + { 240000000, 120000000, 0x0b11, 0x11020009, 0x11210009, 0x11020009, 0x04000009, 11, 0x0aaa0555 },
2101 + { 250000000, 125000000, 0x0f03, 0x11020003, 0x11210003, 0x11020003, 0x04000003, 11, 0x0aaa0555 }
2102 + };
2103 +
2104 + ulong start, end, dst;
2105 + bool ret = FALSE;
2106 +
2107 + /* get index of the current core */
2108 + idx = sb_coreidx(sbh);
2109 + clockcontrol_m2 = NULL;
2110 +
2111 + /* switch to extif or chipc core */
2112 + if ((eir = (extifregs_t *) sb_setcore(sbh, SB_EXTIF, 0))) {
2113 + pll_type = PLL_TYPE1;
2114 + clockcontrol_n = &eir->clockcontrol_n;
2115 + clockcontrol_sb = &eir->clockcontrol_sb;
2116 + clockcontrol_pci = &eir->clockcontrol_pci;
2117 + clockcontrol_m2 = &cc->clockcontrol_m2;
2118 + } else if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) {
2119 + pll_type = R_REG(&cc->capabilities) & CAP_PLL_MASK;
2120 + if (pll_type == PLL_TYPE6) {
2121 + clockcontrol_n = NULL;
2122 + clockcontrol_sb = NULL;
2123 + clockcontrol_pci = NULL;
2124 + } else {
2125 + clockcontrol_n = &cc->clockcontrol_n;
2126 + clockcontrol_sb = &cc->clockcontrol_sb;
2127 + clockcontrol_pci = &cc->clockcontrol_pci;
2128 + clockcontrol_m2 = &cc->clockcontrol_m2;
2129 + }
2130 + } else
2131 + goto done;
2132 +
2133 + if (pll_type == PLL_TYPE6) {
2134 + /* Silence compilers */
2135 + orig_n = orig_sb = orig_pci = 0;
2136 + } else {
2137 + /* Store the current clock register values */
2138 + orig_n = R_REG(clockcontrol_n);
2139 + orig_sb = R_REG(clockcontrol_sb);
2140 + orig_pci = R_REG(clockcontrol_pci);
2141 + }
2142 +
2143 + if (pll_type == PLL_TYPE1) {
2144 + /* Keep the current PCI clock if not specified */
2145 + if (pciclock == 0) {
2146 + pciclock = sb_clock_rate(pll_type, R_REG(clockcontrol_n), R_REG(clockcontrol_pci));
2147 + pciclock = (pciclock <= 25000000) ? 25000000 : 33000000;
2148 + }
2149 +
2150 + /* Search for the closest MIPS clock less than or equal to a preferred value */
2151 + for (i = 0; i < ARRAYSIZE(BCMINIT(type1_table)); i++) {
2152 + ASSERT(BCMINIT(type1_table)[i].mipsclock ==
2153 + sb_clock_rate(pll_type, BCMINIT(type1_table)[i].n, BCMINIT(type1_table)[i].sb));
2154 + if (BCMINIT(type1_table)[i].mipsclock > mipsclock)
2155 + break;
2156 + }
2157 + if (i == 0) {
2158 + ret = FALSE;
2159 + goto done;
2160 + } else {
2161 + ret = TRUE;
2162 + i--;
2163 + }
2164 + ASSERT(BCMINIT(type1_table)[i].mipsclock <= mipsclock);
2165 +
2166 + /* No PLL change */
2167 + if ((orig_n == BCMINIT(type1_table)[i].n) &&
2168 + (orig_sb == BCMINIT(type1_table)[i].sb) &&
2169 + (orig_pci == BCMINIT(type1_table)[i].pci33))
2170 + goto done;
2171 +
2172 + /* Set the PLL controls */
2173 + W_REG(clockcontrol_n, BCMINIT(type1_table)[i].n);
2174 + W_REG(clockcontrol_sb, BCMINIT(type1_table)[i].sb);
2175 + if (pciclock == 25000000)
2176 + W_REG(clockcontrol_pci, BCMINIT(type1_table)[i].pci25);
2177 + else
2178 + W_REG(clockcontrol_pci, BCMINIT(type1_table)[i].pci33);
2179 +
2180 + /* Reset */
2181 + sb_watchdog(sbh, 1);
2182 +
2183 + while (1);
2184 + } else if ((pll_type == PLL_TYPE3) &&
2185 + (BCMINIT(sb_chip)(sbh) != BCM5365_DEVICE_ID)) {
2186 + /* 5350 */
2187 + /* Search for the closest MIPS clock less than or equal to a preferred value */
2188 +
2189 + for (i = 0; i < ARRAYSIZE(type3_table); i++) {
2190 + if (type3_table[i].mipsclock > mipsclock)
2191 + break;
2192 + }
2193 + if (i == 0) {
2194 + ret = FALSE;
2195 + goto done;
2196 + } else {
2197 + ret = TRUE;
2198 + i--;
2199 + }
2200 + ASSERT(type3_table[i].mipsclock <= mipsclock);
2201 +
2202 + /* No PLL change */
2203 + orig_m2 = R_REG(&cc->clockcontrol_m2);
2204 + if ((orig_n == type3_table[i].n) &&
2205 + (orig_m2 == type3_table[i].m2)) {
2206 + goto done;
2207 + }
2208 +
2209 + /* Set the PLL controls */
2210 + W_REG(clockcontrol_n, type3_table[i].n);
2211 + W_REG(clockcontrol_m2, type3_table[i].m2);
2212 +
2213 + /* Reset */
2214 + sb_watchdog(sbh, 1);
2215 + while (1);
2216 + } else if ((pll_type == PLL_TYPE2) ||
2217 + (pll_type == PLL_TYPE4) ||
2218 + (pll_type == PLL_TYPE6) ||
2219 + (pll_type == PLL_TYPE7)) {
2220 + n4m_table_t *table = NULL, *te;
2221 + uint tabsz = 0;
2222 +
2223 + ASSERT(cc);
2224 +
2225 + orig_mips = R_REG(&cc->clockcontrol_mips);
2226 +
2227 + if (pll_type == PLL_TYPE6) {
2228 + uint32 new_mips = 0;
2229 +
2230 + ret = TRUE;
2231 + if (mipsclock <= SB2MIPS_T6(CC_T6_M1))
2232 + new_mips = CC_T6_MMASK;
2233 +
2234 + if (orig_mips == new_mips)
2235 + goto done;
2236 +
2237 + W_REG(&cc->clockcontrol_mips, new_mips);
2238 + goto end_fill;
2239 + }
2240 +
2241 + if (pll_type == PLL_TYPE2) {
2242 + table = BCMINIT(type2_table);
2243 + tabsz = ARRAYSIZE(BCMINIT(type2_table));
2244 + } else if (pll_type == PLL_TYPE4) {
2245 + table = BCMINIT(type4_table);
2246 + tabsz = ARRAYSIZE(BCMINIT(type4_table));
2247 + } else if (pll_type == PLL_TYPE7) {
2248 + table = BCMINIT(type7_table);
2249 + tabsz = ARRAYSIZE(BCMINIT(type7_table));
2250 + } else
2251 + ASSERT("No table for plltype" == NULL);
2252 +
2253 + /* Store the current clock register values */
2254 + orig_m2 = R_REG(&cc->clockcontrol_m2);
2255 + orig_ratio_parm = 0;
2256 + orig_ratio_cfg = 0;
2257 +
2258 + /* Look up current ratio */
2259 + for (i = 0; i < tabsz; i++) {
2260 + if ((orig_n == table[i].n) &&
2261 + (orig_sb == table[i].sb) &&
2262 + (orig_pci == table[i].pci33) &&
2263 + (orig_m2 == table[i].m2) &&
2264 + (orig_mips == table[i].m3)) {
2265 + orig_ratio_parm = table[i].ratio_parm;
2266 + orig_ratio_cfg = table[i].ratio_cfg;
2267 + break;
2268 + }
2269 + }
2270 +
2271 + /* Search for the closest MIPS clock greater or equal to a preferred value */
2272 + for (i = 0; i < tabsz; i++) {
2273 + ASSERT(table[i].mipsclock ==
2274 + sb_clock_rate(pll_type, table[i].n, table[i].m3));
2275 + if ((mipsclock <= table[i].mipsclock) &&
2276 + ((sbclock == 0) || (sbclock <= table[i].sbclock)))
2277 + break;
2278 + }
2279 + if (i == tabsz) {
2280 + ret = FALSE;
2281 + goto done;
2282 + } else {
2283 + te = &table[i];
2284 + ret = TRUE;
2285 + }
2286 +
2287 + /* No PLL change */
2288 + if ((orig_n == te->n) &&
2289 + (orig_sb == te->sb) &&
2290 + (orig_pci == te->pci33) &&
2291 + (orig_m2 == te->m2) &&
2292 + (orig_mips == te->m3))
2293 + goto done;
2294 +
2295 + /* Set the PLL controls */
2296 + W_REG(clockcontrol_n, te->n);
2297 + W_REG(clockcontrol_sb, te->sb);
2298 + W_REG(clockcontrol_pci, te->pci33);
2299 + W_REG(&cc->clockcontrol_m2, te->m2);
2300 + W_REG(&cc->clockcontrol_mips, te->m3);
2301 +
2302 + /* Set the chipcontrol bit to change mipsref to the backplane divider if needed */
2303 + if ((pll_type == PLL_TYPE7) &&
2304 + (te->sb != te->m2) &&
2305 + (sb_clock_rate(pll_type, te->n, te->m2) == 120000000))
2306 + W_REG(&cc->chipcontrol, R_REG(&cc->chipcontrol) | 0x100);
2307 +
2308 + /* No ratio change */
2309 + if (orig_ratio_parm == te->ratio_parm)
2310 + goto end_fill;
2311 +
2312 + icache_probe(MFC0(C0_CONFIG, 1), &ic_size, &ic_lsize);
2313 +
2314 + /* Preload the code into the cache */
2315 + start = ((ulong) &&start_fill) & ~(ic_lsize - 1);
2316 + end = ((ulong) &&end_fill + (ic_lsize - 1)) & ~(ic_lsize - 1);
2317 + while (start < end) {
2318 + cache_op(start, Fill_I);
2319 + start += ic_lsize;
2320 + }
2321 +
2322 + /* Copy the handler */
2323 + start = (ulong) &BCMINIT(handler);
2324 + end = (ulong) &BCMINIT(afterhandler);
2325 + dst = KSEG1ADDR(0x180);
2326 + for (i = 0; i < (end - start); i += 4)
2327 + *((ulong *)(dst + i)) = *((ulong *)(start + i));
2328 +
2329 + /* Preload handler into the cache one line at a time */
2330 + for (i = 0; i < (end - start); i += 4)
2331 + cache_op(dst + i, Fill_I);
2332 +
2333 + /* Clear BEV bit */
2334 + MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~ST0_BEV);
2335 +
2336 + /* Enable interrupts */
2337 + MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) | (ALLINTS | ST0_IE));
2338 +
2339 + /* Enable MIPS timer interrupt */
2340 + if (!(mipsr = sb_setcore(sbh, SB_MIPS, 0)) &&
2341 + !(mipsr = sb_setcore(sbh, SB_MIPS33, 0)))
2342 + ASSERT(mipsr);
2343 + W_REG(&mipsr->intmask, 1);
2344 +
2345 + start_fill:
2346 + /* step 1, set clock ratios */
2347 + MTC0(C0_BROADCOM, 3, te->ratio_parm);
2348 + MTC0(C0_BROADCOM, 1, te->ratio_cfg);
2349 +
2350 + /* step 2: program timer intr */
2351 + W_REG(&mipsr->timer, 100);
2352 + (void) R_REG(&mipsr->timer);
2353 +
2354 + /* step 3, switch to async */
2355 + sync_mode = MFC0(C0_BROADCOM, 4);
2356 + MTC0(C0_BROADCOM, 4, 1 << 22);
2357 +
2358 + /* step 4, set cfg active */
2359 + MTC0(C0_BROADCOM, 2, 0x9);
2360 +
2361 +
2362 + /* steps 5 & 6 */
2363 + __asm__ __volatile__ (
2364 + ".set\tmips3\n\t"
2365 + "wait\n\t"
2366 + ".set\tmips0"
2367 + );
2368 +
2369 + /* step 7, clear cfg_active */
2370 + MTC0(C0_BROADCOM, 2, 0);
2371 +
2372 + /* Additional Step: set back to orig sync mode */
2373 + MTC0(C0_BROADCOM, 4, sync_mode);
2374 +
2375 + /* step 8, fake soft reset */
2376 + MTC0(C0_BROADCOM, 5, MFC0(C0_BROADCOM, 5) | 4);
2377 +
2378 + end_fill:
2379 + /* step 9 set watchdog timer */
2380 + sb_watchdog(sbh, 20);
2381 + (void) R_REG(&cc->chipid);
2382 +
2383 + /* step 11 */
2384 + __asm__ __volatile__ (
2385 + ".set\tmips3\n\t"
2386 + "sync\n\t"
2387 + "wait\n\t"
2388 + ".set\tmips0"
2389 + );
2390 + while (1);
2391 + }
2392 +
2393 +done:
2394 + /* switch back to previous core */
2395 + sb_setcoreidx(sbh, idx);
2396 +
2397 + return ret;
2398 +}
2399 +
2400 +/*
2401 + * This also must be run from the cache on 47xx
2402 + * so there are no mips core BIU ops in progress
2403 + * when the PFC is enabled.
2404 + */
2405 +
2406 +static void
2407 +BCMINITFN(_enable_pfc)(uint32 mode)
2408 +{
2409 + /* write range */
2410 + *(volatile uint32 *)PFC_CR1 = 0xffff0000;
2411 +
2412 + /* enable */
2413 + *(volatile uint32 *)PFC_CR0 = mode;
2414 +}
2415 +
2416 +void
2417 +BCMINITFN(enable_pfc)(uint32 mode)
2418 +{
2419 + ulong start, end;
2420 + int i;
2421 +
2422 + /* If auto then choose the correct mode for this
2423 + platform, currently we only ever select one mode */
2424 + if (mode == PFC_AUTO)
2425 + mode = PFC_INST;
2426 +
2427 + /* enable prefetch cache if available */
2428 + if (MFC0(C0_BROADCOM, 0) & BRCM_PFC_AVAIL) {
2429 + start = (ulong) &BCMINIT(_enable_pfc);
2430 + end = (ulong) &BCMINIT(enable_pfc);
2431 +
2432 + /* Preload handler into the cache one line at a time */
2433 + for (i = 0; i < (end - start); i += 4)
2434 + cache_op(start + i, Fill_I);
2435 +
2436 + BCMINIT(_enable_pfc)(mode);
2437 + }
2438 +}
2439 +
2440 +/* returns the ncdl value to be programmed into sdram_ncdl for calibration */
2441 +uint32
2442 +BCMINITFN(sb_memc_get_ncdl)(sb_t *sbh)
2443 +{
2444 + sbmemcregs_t *memc;
2445 + uint32 ret = 0;
2446 + uint32 config, rd, wr, misc, dqsg, cd, sm, sd;
2447 + uint idx, rev;
2448 +
2449 + idx = sb_coreidx(sbh);
2450 +
2451 + memc = (sbmemcregs_t *)sb_setcore(sbh, SB_MEMC, 0);
2452 + if (memc == 0)
2453 + goto out;
2454 +
2455 + rev = sb_corerev(sbh);
2456 +
2457 + config = R_REG(&memc->config);
2458 + wr = R_REG(&memc->wrncdlcor);
2459 + rd = R_REG(&memc->rdncdlcor);
2460 + misc = R_REG(&memc->miscdlyctl);
2461 + dqsg = R_REG(&memc->dqsgatencdl);
2462 +
2463 + rd &= MEMC_RDNCDLCOR_RD_MASK;
2464 + wr &= MEMC_WRNCDLCOR_WR_MASK;
2465 + dqsg &= MEMC_DQSGATENCDL_G_MASK;
2466 +
2467 + if (config & MEMC_CONFIG_DDR) {
2468 + ret = (wr << 16) | (rd << 8) | dqsg;
2469 + } else {
2470 + if (rev > 0)
2471 + cd = rd;
2472 + else
2473 + cd = (rd == MEMC_CD_THRESHOLD) ? rd : (wr + MEMC_CD_THRESHOLD);
2474 + sm = (misc & MEMC_MISC_SM_MASK) >> MEMC_MISC_SM_SHIFT;
2475 + sd = (misc & MEMC_MISC_SD_MASK) >> MEMC_MISC_SD_SHIFT;
2476 + ret = (sm << 16) | (sd << 8) | cd;
2477 + }
2478 +
2479 +out:
2480 + /* switch back to previous core */
2481 + sb_setcoreidx(sbh, idx);
2482 +
2483 + return ret;
2484 +}
2485 +
2486 diff -urN linux.old/arch/mips/bcm947xx/broadcom/sbpci.c linux.dev/arch/mips/bcm947xx/broadcom/sbpci.c
2487 --- linux.old/arch/mips/bcm947xx/broadcom/sbpci.c 1970-01-01 01:00:00.000000000 +0100
2488 +++ linux.dev/arch/mips/bcm947xx/broadcom/sbpci.c 2005-12-28 16:37:32.854260000 +0100
2489 @@ -0,0 +1,533 @@
2490 +/*
2491 + * Low-Level PCI and SB support for BCM47xx
2492 + *
2493 + * Copyright 2005, Broadcom Corporation
2494 + * All Rights Reserved.
2495 + *
2496 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
2497 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
2498 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
2499 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
2500 + *
2501 + * $Id$
2502 + */
2503 +
2504 +#include <typedefs.h>
2505 +#include <pcicfg.h>
2506 +#include <bcmdevs.h>
2507 +#include <sbconfig.h>
2508 +#include <osl.h>
2509 +#include <sbutils.h>
2510 +#include <sbpci.h>
2511 +#include <bcmendian.h>
2512 +#include <bcmutils.h>
2513 +#include <bcmnvram.h>
2514 +#include <hndmips.h>
2515 +
2516 +/* Can free sbpci_init() memory after boot */
2517 +#ifndef linux
2518 +#define __init
2519 +#endif
2520 +
2521 +/* Emulated configuration space */
2522 +static pci_config_regs sb_config_regs[SB_MAXCORES];
2523 +
2524 +/* Banned cores */
2525 +static uint16 pci_ban[32] = { 0 };
2526 +static uint pci_banned = 0;
2527 +
2528 +/* CardBus mode */
2529 +static bool cardbus = FALSE;
2530 +
2531 +/* Disable PCI host core */
2532 +static bool pci_disabled = FALSE;
2533 +
2534 +/*
2535 + * Functions for accessing external PCI configuration space
2536 + */
2537 +
2538 +/* Assume one-hot slot wiring */
2539 +#define PCI_SLOT_MAX 16
2540 +
2541 +static uint32
2542 +config_cmd(sb_t *sbh, uint bus, uint dev, uint func, uint off)
2543 +{
2544 + uint coreidx;
2545 + sbpciregs_t *regs;
2546 + uint32 addr = 0;
2547 +
2548 + /* CardBusMode supports only one device */
2549 + if (cardbus && dev > 1)
2550 + return 0;
2551 +
2552 + coreidx = sb_coreidx(sbh);
2553 + regs = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0);
2554 +
2555 + /* Type 0 transaction */
2556 + if (bus == 1) {
2557 + /* Skip unwired slots */
2558 + if (dev < PCI_SLOT_MAX) {
2559 + /* Slide the PCI window to the appropriate slot */
2560 + W_REG(&regs->sbtopci1, SBTOPCI_CFG0 | ((1 << (dev + 16)) & SBTOPCI1_MASK));
2561 + addr = SB_PCI_CFG | ((1 << (dev + 16)) & ~SBTOPCI1_MASK) |
2562 + (func << 8) | (off & ~3);
2563 + }
2564 + }
2565 +
2566 + /* Type 1 transaction */
2567 + else {
2568 + W_REG(&regs->sbtopci1, SBTOPCI_CFG1);
2569 + addr = SB_PCI_CFG | (bus << 16) | (dev << 11) | (func << 8) | (off & ~3);
2570 + }
2571 +
2572 + sb_setcoreidx(sbh, coreidx);
2573 +
2574 + return addr;
2575 +}
2576 +
2577 +static int
2578 +extpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
2579 +{
2580 + uint32 addr, *reg = NULL, val;
2581 + int ret = 0;
2582 +
2583 + if (pci_disabled ||
2584 + !(addr = config_cmd(sbh, bus, dev, func, off)) ||
2585 + !(reg = (uint32 *) REG_MAP(addr, len)) ||
2586 + BUSPROBE(val, reg))
2587 + val = 0xffffffff;
2588 +
2589 + val >>= 8 * (off & 3);
2590 + if (len == 4)
2591 + *((uint32 *) buf) = val;
2592 + else if (len == 2)
2593 + *((uint16 *) buf) = (uint16) val;
2594 + else if (len == 1)
2595 + *((uint8 *) buf) = (uint8) val;
2596 + else
2597 + ret = -1;
2598 +
2599 + if (reg)
2600 + REG_UNMAP(reg);
2601 +
2602 + return ret;
2603 +}
2604 +
2605 +static int
2606 +extpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
2607 +{
2608 + uint32 addr, *reg = NULL, val;
2609 + int ret = 0;
2610 +
2611 + if (pci_disabled ||
2612 + !(addr = config_cmd(sbh, bus, dev, func, off)) ||
2613 + !(reg = (uint32 *) REG_MAP(addr, len)) ||
2614 + BUSPROBE(val, reg))
2615 + goto done;
2616 +
2617 + if (len == 4)
2618 + val = *((uint32 *) buf);
2619 + else if (len == 2) {
2620 + val &= ~(0xffff << (8 * (off & 3)));
2621 + val |= *((uint16 *) buf) << (8 * (off & 3));
2622 + } else if (len == 1) {
2623 + val &= ~(0xff << (8 * (off & 3)));
2624 + val |= *((uint8 *) buf) << (8 * (off & 3));
2625 + } else
2626 + ret = -1;
2627 +
2628 + W_REG(reg, val);
2629 +
2630 + done:
2631 + if (reg)
2632 + REG_UNMAP(reg);
2633 +
2634 + return ret;
2635 +}
2636 +
2637 +/*
2638 + * Functions for accessing translated SB configuration space
2639 + */
2640 +
2641 +static int
2642 +sb_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
2643 +{
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 + if (len == 4)
2654 + *((uint32 *) buf) = ltoh32(*((uint32 *)((ulong) cfg + off)));
2655 + else if (len == 2)
2656 + *((uint16 *) buf) = ltoh16(*((uint16 *)((ulong) cfg + off)));
2657 + else if (len == 1)
2658 + *((uint8 *) buf) = *((uint8 *)((ulong) cfg + off));
2659 + else
2660 + return -1;
2661 +
2662 + return 0;
2663 +}
2664 +
2665 +static int
2666 +sb_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
2667 +{
2668 + uint coreidx, n;
2669 + void *regs;
2670 + sbconfig_t *sb;
2671 + pci_config_regs *cfg;
2672 +
2673 + if (dev >= SB_MAXCORES || (off + len) > sizeof(pci_config_regs))
2674 + return -1;
2675 + cfg = &sb_config_regs[dev];
2676 +
2677 + ASSERT(ISALIGNED(off, len));
2678 + ASSERT(ISALIGNED((uintptr)buf, len));
2679 +
2680 + /* Emulate BAR sizing */
2681 + if (off >= OFFSETOF(pci_config_regs, base[0]) && off <= OFFSETOF(pci_config_regs, base[3]) &&
2682 + len == 4 && *((uint32 *) buf) == ~0) {
2683 + coreidx = sb_coreidx(sbh);
2684 + if ((regs = sb_setcoreidx(sbh, dev))) {
2685 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
2686 + /* Highest numbered address match register */
2687 + n = (R_REG(&sb->sbidlow) & SBIDL_AR_MASK) >> SBIDL_AR_SHIFT;
2688 + if (off == OFFSETOF(pci_config_regs, base[0]))
2689 + cfg->base[0] = ~(sb_size(R_REG(&sb->sbadmatch0)) - 1);
2690 +#if 0
2691 + else if (off == OFFSETOF(pci_config_regs, base[1]) && n >= 1)
2692 + cfg->base[1] = ~(sb_size(R_REG(&sb->sbadmatch1)) - 1);
2693 + else if (off == OFFSETOF(pci_config_regs, base[2]) && n >= 2)
2694 + cfg->base[2] = ~(sb_size(R_REG(&sb->sbadmatch2)) - 1);
2695 + else if (off == OFFSETOF(pci_config_regs, base[3]) && n >= 3)
2696 + cfg->base[3] = ~(sb_size(R_REG(&sb->sbadmatch3)) - 1);
2697 +#endif
2698 + }
2699 + sb_setcoreidx(sbh, coreidx);
2700 + return 0;
2701 + }
2702 +
2703 + if (len == 4)
2704 + *((uint32 *)((ulong) cfg + off)) = htol32(*((uint32 *) buf));
2705 + else if (len == 2)
2706 + *((uint16 *)((ulong) cfg + off)) = htol16(*((uint16 *) buf));
2707 + else if (len == 1)
2708 + *((uint8 *)((ulong) cfg + off)) = *((uint8 *) buf);
2709 + else
2710 + return -1;
2711 +
2712 + return 0;
2713 +}
2714 +
2715 +int
2716 +sbpci_read_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
2717 +{
2718 + if (bus == 0)
2719 + return sb_read_config(sbh, bus, dev, func, off, buf, len);
2720 + else
2721 + return extpci_read_config(sbh, bus, dev, func, off, buf, len);
2722 +}
2723 +
2724 +int
2725 +sbpci_write_config(sb_t *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
2726 +{
2727 + if (bus == 0)
2728 + return sb_write_config(sbh, bus, dev, func, off, buf, len);
2729 + else
2730 + return extpci_write_config(sbh, bus, dev, func, off, buf, len);
2731 +}
2732 +
2733 +void
2734 +sbpci_ban(uint16 core)
2735 +{
2736 + if (pci_banned < ARRAYSIZE(pci_ban))
2737 + pci_ban[pci_banned++] = core;
2738 +}
2739 +
2740 +static int
2741 +sbpci_init_pci(sb_t *sbh)
2742 +{
2743 + uint chip, chiprev, chippkg, host;
2744 + uint32 boardflags;
2745 + sbpciregs_t *pci;
2746 + sbconfig_t *sb;
2747 + uint32 val;
2748 +
2749 + chip = sb_chip(sbh);
2750 + chiprev = sb_chiprev(sbh);
2751 + chippkg = sb_chippkg(sbh);
2752 +
2753 + if (!(pci = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0))) {
2754 + printf("PCI: no core\n");
2755 + pci_disabled = TRUE;
2756 + return -1;
2757 + }
2758 + sb_core_reset(sbh, 0);
2759 +
2760 + boardflags = (uint32) getintvar(NULL, "boardflags");
2761 +
2762 + if ((chip == BCM4310_DEVICE_ID) && (chiprev == 0))
2763 + pci_disabled = TRUE;
2764 +
2765 + /*
2766 + * The 200-pin BCM4712 package does not bond out PCI. Even when
2767 + * PCI is bonded out, some boards may leave the pins
2768 + * floating.
2769 + */
2770 + if (((chip == BCM4712_DEVICE_ID) &&
2771 + ((chippkg == BCM4712SMALL_PKG_ID) ||
2772 + (chippkg == BCM4712MID_PKG_ID))) ||
2773 + (boardflags & BFL_NOPCI))
2774 + pci_disabled = TRUE;
2775 +
2776 + /*
2777 + * If the PCI core should not be touched (disabled, not bonded
2778 + * out, or pins floating), do not even attempt to access core
2779 + * registers. Otherwise, try to determine if it is in host
2780 + * mode.
2781 + */
2782 + if (pci_disabled)
2783 + host = 0;
2784 + else
2785 + host = !BUSPROBE(val, &pci->control);
2786 +
2787 + if (!host) {
2788 + /* Disable PCI interrupts in client mode */
2789 + sb = (sbconfig_t *)((ulong) pci + SBCONFIGOFF);
2790 + W_REG(&sb->sbintvec, 0);
2791 +
2792 + /* Disable the PCI bridge in client mode */
2793 + sbpci_ban(SB_PCI);
2794 + printf("PCI: Disabled\n");
2795 + } else {
2796 + /* Reset the external PCI bus and enable the clock */
2797 + W_REG(&pci->control, 0x5); /* enable the tristate drivers */
2798 + W_REG(&pci->control, 0xd); /* enable the PCI clock */
2799 + OSL_DELAY(150); /* delay > 100 us */
2800 + W_REG(&pci->control, 0xf); /* deassert PCI reset */
2801 + W_REG(&pci->arbcontrol, PCI_INT_ARB); /* use internal arbiter */
2802 + OSL_DELAY(1); /* delay 1 us */
2803 +
2804 + /* Enable CardBusMode */
2805 + cardbus = nvram_match("cardbus", "1");
2806 + if (cardbus) {
2807 + printf("PCI: Enabling CardBus\n");
2808 + /* GPIO 1 resets the CardBus device on bcm94710ap */
2809 + sb_gpioout(sbh, 1, 1, GPIO_DRV_PRIORITY);
2810 + sb_gpioouten(sbh, 1, 1, GPIO_DRV_PRIORITY);
2811 + W_REG(&pci->sprom[0], R_REG(&pci->sprom[0]) | 0x400);
2812 + }
2813 +
2814 + /* 64 MB I/O access window */
2815 + W_REG(&pci->sbtopci0, SBTOPCI_IO);
2816 + /* 64 MB configuration access window */
2817 + W_REG(&pci->sbtopci1, SBTOPCI_CFG0);
2818 + /* 1 GB memory access window */
2819 + W_REG(&pci->sbtopci2, SBTOPCI_MEM | SB_PCI_DMA);
2820 +
2821 + /* Enable PCI bridge BAR0 prefetch and burst */
2822 + val = 6;
2823 + sbpci_write_config(sbh, 1, 0, 0, PCI_CFG_CMD, &val, sizeof(val));
2824 +
2825 + /* Enable PCI interrupts */
2826 + W_REG(&pci->intmask, PCI_INTA);
2827 + }
2828 +
2829 + return 0;
2830 +}
2831 +
2832 +static int
2833 +sbpci_init_cores(sb_t *sbh)
2834 +{
2835 + uint chip, chiprev, chippkg, coreidx, i;
2836 + sbconfig_t *sb;
2837 + pci_config_regs *cfg;
2838 + void *regs;
2839 + char varname[8];
2840 + uint wlidx = 0;
2841 + uint16 vendor, core;
2842 + uint8 class, subclass, progif;
2843 + uint32 val;
2844 + uint32 sbips_int_mask[] = { 0, SBIPS_INT1_MASK, SBIPS_INT2_MASK, SBIPS_INT3_MASK, SBIPS_INT4_MASK };
2845 + uint32 sbips_int_shift[] = { 0, 0, SBIPS_INT2_SHIFT, SBIPS_INT3_SHIFT, SBIPS_INT4_SHIFT };
2846 +
2847 + chip = sb_chip(sbh);
2848 + chiprev = sb_chiprev(sbh);
2849 + chippkg = sb_chippkg(sbh);
2850 + coreidx = sb_coreidx(sbh);
2851 +
2852 + /* Scan the SB bus */
2853 + bzero(sb_config_regs, sizeof(sb_config_regs));
2854 + for (cfg = sb_config_regs; cfg < &sb_config_regs[SB_MAXCORES]; cfg++) {
2855 + cfg->vendor = 0xffff;
2856 + if (!(regs = sb_setcoreidx(sbh, cfg - sb_config_regs)))
2857 + continue;
2858 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
2859 +
2860 + /* Read ID register and parse vendor and core */
2861 + val = R_REG(&sb->sbidhigh);
2862 + vendor = (val & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT;
2863 + core = (val & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT;
2864 + progif = 0;
2865 +
2866 + /* Check if this core is banned */
2867 + for (i = 0; i < pci_banned; i++)
2868 + if (core == pci_ban[i])
2869 + break;
2870 + if (i < pci_banned)
2871 + continue;
2872 +
2873 + /* Known vendor translations */
2874 + switch (vendor) {
2875 + case SB_VEND_BCM:
2876 + vendor = VENDOR_BROADCOM;
2877 + break;
2878 + }
2879 +
2880 + /* Determine class based on known core codes */
2881 + switch (core) {
2882 + case SB_ILINE20:
2883 + class = PCI_CLASS_NET;
2884 + subclass = PCI_NET_ETHER;
2885 + core = BCM47XX_ILINE_ID;
2886 + break;
2887 + case SB_ILINE100:
2888 + class = PCI_CLASS_NET;
2889 + subclass = PCI_NET_ETHER;
2890 + core = BCM4610_ILINE_ID;
2891 + break;
2892 + case SB_ENET:
2893 + class = PCI_CLASS_NET;
2894 + subclass = PCI_NET_ETHER;
2895 + core = BCM47XX_ENET_ID;
2896 + break;
2897 + case SB_SDRAM:
2898 + case SB_MEMC:
2899 + class = PCI_CLASS_MEMORY;
2900 + subclass = PCI_MEMORY_RAM;
2901 + break;
2902 + case SB_PCI:
2903 +#if 0
2904 + class = PCI_CLASS_BRIDGE;
2905 + subclass = PCI_BRIDGE_PCI;
2906 + break;
2907 +#endif
2908 + case SB_MIPS:
2909 + case SB_MIPS33:
2910 + class = PCI_CLASS_CPU;
2911 + subclass = PCI_CPU_MIPS;
2912 + break;
2913 + case SB_CODEC:
2914 + class = PCI_CLASS_COMM;
2915 + subclass = PCI_COMM_MODEM;
2916 + core = BCM47XX_V90_ID;
2917 + break;
2918 + case SB_USB:
2919 + class = PCI_CLASS_SERIAL;
2920 + subclass = PCI_SERIAL_USB;
2921 + progif = 0x10; /* OHCI */
2922 + core = BCM47XX_USB_ID;
2923 + break;
2924 + case SB_USB11H:
2925 + class = PCI_CLASS_SERIAL;
2926 + subclass = PCI_SERIAL_USB;
2927 + progif = 0x10; /* OHCI */
2928 + core = BCM47XX_USBH_ID;
2929 + break;
2930 + case SB_USB11D:
2931 + class = PCI_CLASS_SERIAL;
2932 + subclass = PCI_SERIAL_USB;
2933 + core = BCM47XX_USBD_ID;
2934 + break;
2935 + case SB_IPSEC:
2936 + class = PCI_CLASS_CRYPT;
2937 + subclass = PCI_CRYPT_NETWORK;
2938 + core = BCM47XX_IPSEC_ID;
2939 + break;
2940 + case SB_ROBO:
2941 + class = PCI_CLASS_NET;
2942 + subclass = PCI_NET_OTHER;
2943 + core = BCM47XX_ROBO_ID;
2944 + break;
2945 + case SB_EXTIF:
2946 + case SB_CC:
2947 + class = PCI_CLASS_MEMORY;
2948 + subclass = PCI_MEMORY_FLASH;
2949 + break;
2950 + case SB_D11:
2951 + class = PCI_CLASS_NET;
2952 + subclass = PCI_NET_OTHER;
2953 + /* Let an nvram variable override this */
2954 + sprintf(varname, "wl%did", wlidx);
2955 + wlidx++;
2956 + if ((core = getintvar(NULL, varname)) == 0) {
2957 + if (chip == BCM4712_DEVICE_ID) {
2958 + if (chippkg == BCM4712SMALL_PKG_ID)
2959 + core = BCM4306_D11G_ID;
2960 + else
2961 + core = BCM4306_D11DUAL_ID;
2962 + } else {
2963 + /* 4310 */
2964 + core = BCM4310_D11B_ID;
2965 + }
2966 + }
2967 + break;
2968 +
2969 + default:
2970 + class = subclass = progif = 0xff;
2971 + break;
2972 + }
2973 +
2974 + /* Supported translations */
2975 + cfg->vendor = htol16(vendor);
2976 + cfg->device = htol16(core);
2977 + cfg->rev_id = chiprev;
2978 + cfg->prog_if = progif;
2979 + cfg->sub_class = subclass;
2980 + cfg->base_class = class;
2981 + cfg->base[0] = htol32(sb_base(R_REG(&sb->sbadmatch0)));
2982 + cfg->base[1] = 0;//htol32(sb_base(R_REG(&sb->sbadmatch1)));
2983 + cfg->base[2] = 0;//htol32(sb_base(R_REG(&sb->sbadmatch2)));
2984 + cfg->base[3] = 0;//htol32(sb_base(R_REG(&sb->sbadmatch3)));
2985 + cfg->base[4] = 0;
2986 + cfg->base[5] = 0;
2987 + if (class == PCI_CLASS_BRIDGE && subclass == PCI_BRIDGE_PCI)
2988 + cfg->header_type = PCI_HEADER_BRIDGE;
2989 + else
2990 + cfg->header_type = PCI_HEADER_NORMAL;
2991 + /* Save core interrupt flag */
2992 + cfg->int_pin = R_REG(&sb->sbtpsflag) & SBTPS_NUM0_MASK;
2993 + /* Default to MIPS shared interrupt 0 */
2994 + cfg->int_line = 0;
2995 + /* MIPS sbipsflag maps core interrupt flags to interrupts 1 through 4 */
2996 + if ((regs = sb_setcore(sbh, SB_MIPS, 0)) ||
2997 + (regs = sb_setcore(sbh, SB_MIPS33, 0))) {
2998 + sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
2999 + val = R_REG(&sb->sbipsflag);
3000 + for (cfg->int_line = 1; cfg->int_line <= 4; cfg->int_line++) {
3001 + if (((val & sbips_int_mask[cfg->int_line]) >> sbips_int_shift[cfg->int_line]) == cfg->int_pin)
3002 + break;
3003 + }
3004 + if (cfg->int_line > 4)
3005 + cfg->int_line = 0;
3006 + }
3007 + /* Emulated core */
3008 + *((uint32 *) &cfg->sprom_control) = 0xffffffff;
3009 + }
3010 +
3011 + sb_setcoreidx(sbh, coreidx);
3012 + return 0;
3013 +}
3014 +
3015 +int __init
3016 +sbpci_init(sb_t *sbh)
3017 +{
3018 + sbpci_init_pci(sbh);
3019 + sbpci_init_cores(sbh);
3020 + return 0;
3021 +}
3022 +
3023 diff -urN linux.old/arch/mips/bcm947xx/broadcom/sbutils.c linux.dev/arch/mips/bcm947xx/broadcom/sbutils.c
3024 --- linux.old/arch/mips/bcm947xx/broadcom/sbutils.c 1970-01-01 01:00:00.000000000 +0100
3025 +++ linux.dev/arch/mips/bcm947xx/broadcom/sbutils.c 2005-12-28 16:37:32.858260250 +0100
3026 @@ -0,0 +1,2370 @@
3027 +/*
3028 + * Misc utility routines for accessing chip-specific features
3029 + * of the SiliconBackplane-based Broadcom chips.
3030 + *
3031 + * Copyright 2005, Broadcom Corporation
3032 + * All Rights Reserved.
3033 + *
3034 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
3035 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
3036 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
3037 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
3038 + * $Id$
3039 + */
3040 +
3041 +#include <typedefs.h>
3042 +#include <osl.h>
3043 +#include <sbutils.h>
3044 +#include <bcmutils.h>
3045 +#include <bcmdevs.h>
3046 +#include <sbconfig.h>
3047 +#include <sbchipc.h>
3048 +#include <sbpci.h>
3049 +#include <pcicfg.h>
3050 +#include <sbextif.h>
3051 +#include <bcmsrom.h>
3052 +
3053 +/* debug/trace */
3054 +#define SB_ERROR(args)
3055 +
3056 +
3057 +typedef uint32 (*sb_intrsoff_t)(void *intr_arg);
3058 +typedef void (*sb_intrsrestore_t)(void *intr_arg, uint32 arg);
3059 +typedef bool (*sb_intrsenabled_t)(void *intr_arg);
3060 +
3061 +/* misc sb info needed by some of the routines */
3062 +typedef struct sb_info {
3063 +
3064 + struct sb_pub sb; /* back plane public state(must be first field of sb_info */
3065 +
3066 + void *osh; /* osl os handle */
3067 + void *sdh; /* bcmsdh handle */
3068 +
3069 + void *curmap; /* current regs va */
3070 + void *regs[SB_MAXCORES]; /* other regs va */
3071 +
3072 + uint curidx; /* current core index */
3073 + uint dev_coreid; /* the core provides driver functions */
3074 +
3075 + uint gpioidx; /* gpio control core index */
3076 + uint gpioid; /* gpio control coretype */
3077 +
3078 + uint numcores; /* # discovered cores */
3079 + uint coreid[SB_MAXCORES]; /* id of each core */
3080 +
3081 + void *intr_arg; /* interrupt callback function arg */
3082 + sb_intrsoff_t intrsoff_fn; /* function turns chip interrupts off */
3083 + sb_intrsrestore_t intrsrestore_fn; /* function restore chip interrupts */
3084 + sb_intrsenabled_t intrsenabled_fn; /* function to check if chip interrupts are enabled */
3085 +
3086 +} sb_info_t;
3087 +
3088 +/* local prototypes */
3089 +static sb_info_t * BCMINIT(sb_doattach)(sb_info_t *si, uint devid, osl_t *osh, void *regs,
3090 + uint bustype, void *sdh, char **vars, int *varsz);
3091 +static void BCMINIT(sb_scan)(sb_info_t *si);
3092 +static uint sb_corereg(sb_info_t *si, uint coreidx, uint regoff, uint mask, uint val);
3093 +static uint _sb_coreidx(sb_info_t *si);
3094 +static uint sb_findcoreidx(sb_info_t *si, uint coreid, uint coreunit);
3095 +static uint BCMINIT(sb_pcidev2chip)(uint pcidev);
3096 +static uint BCMINIT(sb_chip2numcores)(uint chip);
3097 +static int sb_pci_fixcfg(sb_info_t *si);
3098 +
3099 +/* delay needed between the mdio control/ mdiodata register data access */
3100 +#define PR28829_DELAY() OSL_DELAY(10)
3101 +
3102 +
3103 +/* global variable to indicate reservation/release of gpio's*/
3104 +static uint32 sb_gpioreservation = 0;
3105 +
3106 +#define SB_INFO(sbh) (sb_info_t*)sbh
3107 +#define SET_SBREG(sbh, r, mask, val) W_SBREG((sbh), (r), ((R_SBREG((sbh), (r)) & ~(mask)) | (val)))
3108 +#define GOODCOREADDR(x) (((x) >= SB_ENUM_BASE) && ((x) <= SB_ENUM_LIM) && ISALIGNED((x), SB_CORE_SIZE))
3109 +#define GOODREGS(regs) ((regs) && ISALIGNED((uintptr)(regs), SB_CORE_SIZE))
3110 +#define REGS2SB(va) (sbconfig_t*) ((int8*)(va) + SBCONFIGOFF)
3111 +#define GOODIDX(idx) (((uint)idx) < SB_MAXCORES)
3112 +#define BADIDX (SB_MAXCORES+1)
3113 +#define NOREV -1
3114 +
3115 +#define PCI(si) ((BUSTYPE(si->sb.bustype) == PCI_BUS) && (si->sb.buscoretype == SB_PCI))
3116 +
3117 +/* sonicsrev */
3118 +#define SONICS_2_2 (SBIDL_RV_2_2 >> SBIDL_RV_SHIFT)
3119 +#define SONICS_2_3 (SBIDL_RV_2_3 >> SBIDL_RV_SHIFT)
3120 +
3121 +#define R_SBREG(sbh, sbr) sb_read_sbreg((sbh), (sbr))
3122 +#define W_SBREG(sbh, sbr, v) sb_write_sbreg((sbh), (sbr), (v))
3123 +#define AND_SBREG(sbh, sbr, v) W_SBREG((sbh), (sbr), (R_SBREG((sbh), (sbr)) & (v)))
3124 +#define OR_SBREG(sbh, sbr, v) W_SBREG((sbh), (sbr), (R_SBREG((sbh), (sbr)) | (v)))
3125 +
3126 +/*
3127 + * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts before/
3128 + * after core switching to avoid invalid register accesss inside ISR.
3129 + */
3130 +#define INTR_OFF(si, intr_val) \
3131 + if ((si)->intrsoff_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \
3132 + intr_val = (*(si)->intrsoff_fn)((si)->intr_arg); }
3133 +#define INTR_RESTORE(si, intr_val) \
3134 + if ((si)->intrsrestore_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \
3135 + (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val); }
3136 +
3137 +/* dynamic clock control defines */
3138 +#define LPOMINFREQ 25000 /* low power oscillator min */
3139 +#define LPOMAXFREQ 43000 /* low power oscillator max */
3140 +#define XTALMINFREQ 19800000 /* 20 MHz - 1% */
3141 +#define XTALMAXFREQ 20200000 /* 20 MHz + 1% */
3142 +#define PCIMINFREQ 25000000 /* 25 MHz */
3143 +#define PCIMAXFREQ 34000000 /* 33 MHz + fudge */
3144 +
3145 +#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */
3146 +#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */
3147 +
3148 +#define MIN_DUMPBUFLEN 32 /* debug */
3149 +
3150 +/* GPIO Based LED powersave defines */
3151 +#define DEFAULT_GPIO_ONTIME 10
3152 +#define DEFAULT_GPIO_OFFTIME 90
3153 +
3154 +#define DEFAULT_GPIOTIMERVAL ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME)
3155 +
3156 +static uint32
3157 +sb_read_sbreg(sb_info_t *si, volatile uint32 *sbr)
3158 +{
3159 + uint32 val = R_REG(sbr);
3160 +
3161 + return (val);
3162 +}
3163 +
3164 +static void
3165 +sb_write_sbreg(sb_info_t *si, volatile uint32 *sbr, uint32 v)
3166 +{
3167 + W_REG(sbr, v);
3168 +}
3169 +
3170 +/* Using sb_kattach depends on SB_BUS support, either implicit */
3171 +/* no limiting BCMBUSTYPE value) or explicit (value is SB_BUS). */
3172 +#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SB_BUS)
3173 +
3174 +/* global kernel resource */
3175 +static sb_info_t ksi;
3176 +
3177 +/* generic kernel variant of sb_attach() */
3178 +sb_t *
3179 +BCMINITFN(sb_kattach)()
3180 +{
3181 + uint32 *regs;
3182 +
3183 + if (ksi.curmap == NULL) {
3184 + uint32 cid;
3185 +
3186 + regs = (uint32 *)REG_MAP(SB_ENUM_BASE, SB_CORE_SIZE);
3187 + cid = R_REG((uint32 *)regs);
3188 + if (((cid & CID_ID_MASK) == BCM4712_DEVICE_ID) &&
3189 + ((cid & CID_PKG_MASK) != BCM4712LARGE_PKG_ID) &&
3190 + ((cid & CID_REV_MASK) <= (3 << CID_REV_SHIFT))) {
3191 + uint32 *scc, val;
3192 +
3193 + scc = (uint32 *)((uchar*)regs + OFFSETOF(chipcregs_t, slow_clk_ctl));
3194 + val = R_REG(scc);
3195 + SB_ERROR((" initial scc = 0x%x\n", val));
3196 + val |= SCC_SS_XTAL;
3197 + W_REG(scc, val);
3198 + }
3199 +
3200 + if (BCMINIT(sb_doattach)(&ksi, BCM4710_DEVICE_ID, NULL, (void*)regs,
3201 + SB_BUS, NULL, NULL, NULL) == NULL) {
3202 + return NULL;
3203 + }
3204 + }
3205 +
3206 + return (sb_t *)&ksi;
3207 +}
3208 +#endif
3209 +
3210 +static sb_info_t *
3211 +BCMINITFN(sb_doattach)(sb_info_t *si, uint devid, osl_t *osh, void *regs,
3212 + uint bustype, void *sdh, char **vars, int *varsz)
3213 +{
3214 + uint origidx;
3215 + chipcregs_t *cc;
3216 + sbconfig_t *sb;
3217 + uint32 w;
3218 +
3219 + ASSERT(GOODREGS(regs));
3220 +
3221 + bzero((uchar*)si, sizeof (sb_info_t));
3222 +
3223 + si->sb.buscoreidx = si->gpioidx = BADIDX;
3224 +
3225 + si->osh = osh;
3226 + si->curmap = regs;
3227 + si->sdh = sdh;
3228 +
3229 + /* check to see if we are a sb core mimic'ing a pci core */
3230 + if (bustype == PCI_BUS) {
3231 + if (OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof (uint32)) == 0xffffffff)
3232 + bustype = SB_BUS;
3233 + else
3234 + bustype = PCI_BUS;
3235 + }
3236 +
3237 + si->sb.bustype = bustype;
3238 + if (si->sb.bustype != BUSTYPE(si->sb.bustype)) {
3239 + SB_ERROR(("sb_doattach: bus type %d does not match configured bus type %d\n",
3240 + si->sb.bustype, BUSTYPE(si->sb.bustype)));
3241 + return NULL;
3242 + }
3243 +
3244 + /* kludge to enable the clock on the 4306 which lacks a slowclock */
3245 + if (BUSTYPE(si->sb.bustype) == PCI_BUS)
3246 + sb_clkctl_xtal(&si->sb, XTAL|PLL, ON);
3247 +
3248 + if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
3249 + w = OSL_PCI_READ_CONFIG(osh, PCI_BAR0_WIN, sizeof (uint32));
3250 + if (!GOODCOREADDR(w))
3251 + OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN, sizeof (uint32), SB_ENUM_BASE);
3252 + }
3253 +
3254 + /* initialize current core index value */
3255 + si->curidx = _sb_coreidx(si);
3256 +
3257 + if (si->curidx == BADIDX) {
3258 + SB_ERROR(("sb_doattach: bad core index\n"));
3259 + return NULL;
3260 + }
3261 +
3262 + /* get sonics backplane revision */
3263 + sb = REGS2SB(si->curmap);
3264 + si->sb.sonicsrev = (R_SBREG(si, &(sb)->sbidlow) & SBIDL_RV_MASK) >> SBIDL_RV_SHIFT;
3265 +
3266 + /* keep and reuse the initial register mapping */
3267 + origidx = si->curidx;
3268 + if (BUSTYPE(si->sb.bustype) == SB_BUS)
3269 + si->regs[origidx] = regs;
3270 +
3271 + /* is core-0 a chipcommon core? */
3272 + si->numcores = 1;
3273 + cc = (chipcregs_t*) sb_setcoreidx(&si->sb, 0);
3274 + if (sb_coreid(&si->sb) != SB_CC)
3275 + cc = NULL;
3276 +
3277 + /* determine chip id and rev */
3278 + if (cc) {
3279 + /* chip common core found! */
3280 + si->sb.chip = R_REG(&cc->chipid) & CID_ID_MASK;
3281 + si->sb.chiprev = (R_REG(&cc->chipid) & CID_REV_MASK) >> CID_REV_SHIFT;
3282 + si->sb.chippkg = (R_REG(&cc->chipid) & CID_PKG_MASK) >> CID_PKG_SHIFT;
3283 + } else {
3284 + /* no chip common core -- must convert device id to chip id */
3285 + if ((si->sb.chip = BCMINIT(sb_pcidev2chip)(devid)) == 0) {
3286 + SB_ERROR(("sb_doattach: unrecognized device id 0x%04x\n", devid));
3287 + sb_setcoreidx(&si->sb, origidx);
3288 + return NULL;
3289 + }
3290 + }
3291 +
3292 + /* get chipcommon rev */
3293 + si->sb.ccrev = cc ? (int)sb_corerev(&si->sb) : NOREV;
3294 +
3295 + /* determine numcores */
3296 + if (cc && ((si->sb.ccrev == 4) || (si->sb.ccrev >= 6)))
3297 + si->numcores = (R_REG(&cc->chipid) & CID_CC_MASK) >> CID_CC_SHIFT;
3298 + else
3299 + si->numcores = BCMINIT(sb_chip2numcores)(si->sb.chip);
3300 +
3301 + /* return to original core */
3302 + sb_setcoreidx(&si->sb, origidx);
3303 +
3304 + /* sanity checks */
3305 + ASSERT(si->sb.chip);
3306 +
3307 + /* scan for cores */
3308 + BCMINIT(sb_scan)(si);
3309 +
3310 + /* fixup necessary chip/core configurations */
3311 + if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
3312 + if (sb_pci_fixcfg(si)) {
3313 + SB_ERROR(("sb_doattach: sb_pci_fixcfg failed\n"));
3314 + return NULL;
3315 + }
3316 + }
3317 +
3318 + /* srom_var_init() depends on sb_scan() info */
3319 + if (srom_var_init(si, si->sb.bustype, si->curmap, osh, vars, varsz)) {
3320 + SB_ERROR(("sb_doattach: srom_var_init failed: bad srom\n"));
3321 + return (NULL);
3322 + }
3323 +
3324 + if (cc == NULL) {
3325 + /*
3326 + * The chip revision number is hardwired into all
3327 + * of the pci function config rev fields and is
3328 + * independent from the individual core revision numbers.
3329 + * For example, the "A0" silicon of each chip is chip rev 0.
3330 + */
3331 + if (BUSTYPE(si->sb.bustype) == PCI_BUS) {
3332 + w = OSL_PCI_READ_CONFIG(osh, PCI_CFG_REV, sizeof (uint32));
3333 + si->sb.chiprev = w & 0xff;
3334 + } else
3335 + si->sb.chiprev = 0;
3336 + }
3337 +
3338 + /* gpio control core is required */
3339 + if (!GOODIDX(si->gpioidx)) {
3340 + SB_ERROR(("sb_doattach: gpio control core not found\n"));
3341 + return NULL;
3342 + }
3343 +
3344 + /* get boardtype and boardrev */
3345 + switch (BUSTYPE(si->sb.bustype)) {
3346 + case PCI_BUS:
3347 + /* do a pci config read to get subsystem id and subvendor id */
3348 + w = OSL_PCI_READ_CONFIG(osh, PCI_CFG_SVID, sizeof (uint32));
3349 + si->sb.boardvendor = w & 0xffff;
3350 + si->sb.boardtype = (w >> 16) & 0xffff;
3351 + break;
3352 +
3353 + case SB_BUS:
3354 + case JTAG_BUS:
3355 + si->sb.boardvendor = VENDOR_BROADCOM;
3356 + if ((si->sb.boardtype = getintvar(NULL, "boardtype")) == 0)
3357 + si->sb.boardtype = 0xffff;
3358 + break;
3359 + }
3360 +
3361 + if (si->sb.boardtype == 0) {
3362 + SB_ERROR(("sb_doattach: unknown board type\n"));
3363 + ASSERT(si->sb.boardtype);
3364 + }
3365 +
3366 + /* setup the GPIO based LED powersave register */
3367 + if (si->sb.ccrev >= 16) {
3368 + w = getintvar(*vars, "gpiotimerval");
3369 + if (!w)
3370 + w = DEFAULT_GPIOTIMERVAL;
3371 + sb_corereg(si, 0, OFFSETOF(chipcregs_t, gpiotimerval), ~0, w);
3372 + }
3373 +
3374 +
3375 + return (si);
3376 +}
3377 +
3378 +uint
3379 +sb_coreid(sb_t *sbh)
3380 +{
3381 + sb_info_t *si;
3382 + sbconfig_t *sb;
3383 +
3384 + si = SB_INFO(sbh);
3385 + sb = REGS2SB(si->curmap);
3386 +
3387 + return ((R_SBREG(si, &(sb)->sbidhigh) & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT);
3388 +}
3389 +
3390 +uint
3391 +sb_coreidx(sb_t *sbh)
3392 +{
3393 + sb_info_t *si;
3394 +
3395 + si = SB_INFO(sbh);
3396 + return (si->curidx);
3397 +}
3398 +
3399 +/* return current index of core */
3400 +static uint
3401 +_sb_coreidx(sb_info_t *si)
3402 +{
3403 + sbconfig_t *sb;
3404 + uint32 sbaddr = 0;
3405 +
3406 + ASSERT(si);
3407 +
3408 + switch (BUSTYPE(si->sb.bustype)) {
3409 + case SB_BUS:
3410 + sb = REGS2SB(si->curmap);
3411 + sbaddr = sb_base(R_SBREG(si, &sb->sbadmatch0));
3412 + break;
3413 +
3414 + case PCI_BUS:
3415 + sbaddr = OSL_PCI_READ_CONFIG(si->osh, PCI_BAR0_WIN, sizeof (uint32));
3416 + break;
3417 +
3418 +#ifdef BCMJTAG
3419 + case JTAG_BUS:
3420 + sbaddr = (uint32)si->curmap;
3421 + break;
3422 +#endif /* BCMJTAG */