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