add oleg's fix for ethtool
[openwrt.git] / package / linux / kernel-source / arch / mips / brcm-boards / bcm947xx / sbpci.c
1 /*
2 * Low-Level PCI and SB support for BCM47xx
3 *
4 * Copyright 2004, Broadcom Corporation
5 * All Rights Reserved.
6 *
7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
11 *
12 * $Id$
13 */
14
15 #include <typedefs.h>
16 #include <pcicfg.h>
17 #include <bcmdevs.h>
18 #include <sbconfig.h>
19 #include <sbpci.h>
20 #include <osl.h>
21 #include <bcmendian.h>
22 #include <bcmutils.h>
23 #include <sbutils.h>
24 #include <bcmnvram.h>
25 #include <hndmips.h>
26
27 /* Can free sbpci_init() memory after boot */
28 #ifndef linux
29 #define __init
30 #endif
31
32 /* Emulated configuration space */
33 static pci_config_regs sb_config_regs[SB_MAXCORES];
34
35 /* Banned cores */
36 static uint16 pci_ban[32] = { 0 };
37 static uint pci_banned = 0;
38
39 /* CardBus mode */
40 static bool cardbus = FALSE;
41
42 /* Disable PCI host core */
43 static bool pci_disabled = FALSE;
44
45 /*
46 * Functions for accessing external PCI configuration space
47 */
48
49 /* Assume one-hot slot wiring */
50 #define PCI_SLOT_MAX 16
51
52 static uint32
53 config_cmd(void *sbh, uint bus, uint dev, uint func, uint off)
54 {
55 uint coreidx;
56 sbpciregs_t *regs;
57 uint32 addr = 0;
58
59 /* CardBusMode supports only one device */
60 if (cardbus && dev > 1)
61 return 0;
62
63 coreidx = sb_coreidx(sbh);
64 regs = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0);
65
66 /* Type 0 transaction */
67 if (bus == 1) {
68 /* Skip unwired slots */
69 if (dev < PCI_SLOT_MAX) {
70 /* Slide the PCI window to the appropriate slot */
71 W_REG(&regs->sbtopci1, SBTOPCI_CFG0 | ((1 << (dev + 16)) & SBTOPCI1_MASK));
72 addr = SB_PCI_CFG | ((1 << (dev + 16)) & ~SBTOPCI1_MASK) |
73 (func << 8) | (off & ~3);
74 }
75 }
76
77 /* Type 1 transaction */
78 else {
79 W_REG(&regs->sbtopci1, SBTOPCI_CFG1);
80 addr = SB_PCI_CFG | (bus << 16) | (dev << 11) | (func << 8) | (off & ~3);
81 }
82
83 sb_setcoreidx(sbh, coreidx);
84
85 return addr;
86 }
87
88 static int
89 extpci_read_config(void *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
90 {
91 uint32 addr, *reg = NULL, val;
92 int ret = 0;
93
94 if (pci_disabled ||
95 !(addr = config_cmd(sbh, bus, dev, func, off)) ||
96 !(reg = (uint32 *) REG_MAP(addr, len)) ||
97 BUSPROBE(val, reg))
98 val = 0xffffffff;
99
100 val >>= 8 * (off & 3);
101 if (len == 4)
102 *((uint32 *) buf) = val;
103 else if (len == 2)
104 *((uint16 *) buf) = (uint16) val;
105 else if (len == 1)
106 *((uint8 *) buf) = (uint8) val;
107 else
108 ret = -1;
109
110 if (reg)
111 REG_UNMAP(reg);
112
113 return ret;
114 }
115
116 static int
117 extpci_write_config(void *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
118 {
119 uint32 addr, *reg = NULL, val;
120 int ret = 0;
121
122 if (pci_disabled ||
123 !(addr = config_cmd(sbh, bus, dev, func, off)) ||
124 !(reg = (uint32 *) REG_MAP(addr, len)) ||
125 BUSPROBE(val, reg))
126 goto done;
127
128 if (len == 4)
129 val = *((uint32 *) buf);
130 else if (len == 2) {
131 val &= ~(0xffff << (8 * (off & 3)));
132 val |= *((uint16 *) buf) << (8 * (off & 3));
133 } else if (len == 1) {
134 val &= ~(0xff << (8 * (off & 3)));
135 val |= *((uint8 *) buf) << (8 * (off & 3));
136 } else
137 ret = -1;
138
139 W_REG(reg, val);
140
141 done:
142 if (reg)
143 REG_UNMAP(reg);
144
145 return ret;
146 }
147
148 /*
149 * Functions for accessing translated SB configuration space
150 */
151
152 static int
153 sb_read_config(void *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
154 {
155 pci_config_regs *cfg;
156
157 if (dev >= SB_MAXCORES || (off + len) > sizeof(pci_config_regs))
158 return -1;
159 cfg = &sb_config_regs[dev];
160
161 ASSERT(ISALIGNED(off, len));
162 ASSERT(ISALIGNED(buf, len));
163
164 if (len == 4)
165 *((uint32 *) buf) = ltoh32(*((uint32 *)((ulong) cfg + off)));
166 else if (len == 2)
167 *((uint16 *) buf) = ltoh16(*((uint16 *)((ulong) cfg + off)));
168 else if (len == 1)
169 *((uint8 *) buf) = *((uint8 *)((ulong) cfg + off));
170 else
171 return -1;
172
173 return 0;
174 }
175
176 static int
177 sb_write_config(void *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
178 {
179 uint coreidx, n;
180 void *regs;
181 sbconfig_t *sb;
182 pci_config_regs *cfg;
183
184 if (dev >= SB_MAXCORES || (off + len) > sizeof(pci_config_regs))
185 return -1;
186 cfg = &sb_config_regs[dev];
187
188 ASSERT(ISALIGNED(off, len));
189 ASSERT(ISALIGNED(buf, len));
190
191 /* Emulate BAR sizing */
192 if (off >= OFFSETOF(pci_config_regs, base[0]) && off <= OFFSETOF(pci_config_regs, base[3]) &&
193 len == 4 && *((uint32 *) buf) == ~0) {
194 coreidx = sb_coreidx(sbh);
195 if ((regs = sb_setcoreidx(sbh, dev))) {
196 sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
197 /* Highest numbered address match register */
198 n = (R_REG(&sb->sbidlow) & SBIDL_AR_MASK) >> SBIDL_AR_SHIFT;
199 if (off == OFFSETOF(pci_config_regs, base[0]))
200 cfg->base[0] = ~(sb_size(R_REG(&sb->sbadmatch0)) - 1);
201 else if (off == OFFSETOF(pci_config_regs, base[1]) && n >= 1)
202 cfg->base[1] = ~(sb_size(R_REG(&sb->sbadmatch1)) - 1);
203 else if (off == OFFSETOF(pci_config_regs, base[2]) && n >= 2)
204 cfg->base[2] = ~(sb_size(R_REG(&sb->sbadmatch2)) - 1);
205 else if (off == OFFSETOF(pci_config_regs, base[3]) && n >= 3)
206 cfg->base[3] = ~(sb_size(R_REG(&sb->sbadmatch3)) - 1);
207 }
208 sb_setcoreidx(sbh, coreidx);
209 return 0;
210 }
211
212 if (len == 4)
213 *((uint32 *)((ulong) cfg + off)) = htol32(*((uint32 *) buf));
214 else if (len == 2)
215 *((uint16 *)((ulong) cfg + off)) = htol16(*((uint16 *) buf));
216 else if (len == 1)
217 *((uint8 *)((ulong) cfg + off)) = *((uint8 *) buf);
218 else
219 return -1;
220
221 return 0;
222 }
223
224 int
225 sbpci_read_config(void *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
226 {
227 if (bus == 0)
228 return sb_read_config(sbh, bus, dev, func, off, buf, len);
229 else
230 return extpci_read_config(sbh, bus, dev, func, off, buf, len);
231 }
232
233 int
234 sbpci_write_config(void *sbh, uint bus, uint dev, uint func, uint off, void *buf, int len)
235 {
236 if (bus == 0)
237 return sb_write_config(sbh, bus, dev, func, off, buf, len);
238 else
239 return extpci_write_config(sbh, bus, dev, func, off, buf, len);
240 }
241
242 void
243 sbpci_ban(uint16 core)
244 {
245 if (pci_banned < ARRAYSIZE(pci_ban))
246 pci_ban[pci_banned++] = core;
247 }
248
249 int __init
250 sbpci_init(void *sbh)
251 {
252 uint chip, chiprev, chippkg, coreidx, host, i;
253 uint32 boardflags;
254 sbpciregs_t *pci;
255 sbconfig_t *sb;
256 pci_config_regs *cfg;
257 void *regs;
258 char varname[8];
259 uint wlidx = 0;
260 uint16 vendor, core;
261 uint8 class, subclass, progif;
262 uint32 val;
263 uint32 sbips_int_mask[] = { 0, SBIPS_INT1_MASK, SBIPS_INT2_MASK, SBIPS_INT3_MASK, SBIPS_INT4_MASK };
264 uint32 sbips_int_shift[] = { 0, 0, SBIPS_INT2_SHIFT, SBIPS_INT3_SHIFT, SBIPS_INT4_SHIFT };
265
266 chip = sb_chip(sbh);
267 chiprev = sb_chiprev(sbh);
268 chippkg = sb_chippkg(sbh);
269 coreidx = sb_coreidx(sbh);
270
271 if (!(pci = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0)))
272 return -1;
273 sb_core_reset(sbh, 0);
274
275 boardflags = (uint32) getintvar(NULL, "boardflags");
276
277 if ((chip == BCM4310_DEVICE_ID) && (chiprev == 0))
278 pci_disabled = TRUE;
279
280 /*
281 * The 200-pin BCM4712 package does not bond out PCI. Even when
282 * PCI is bonded out, some boards may leave the pins
283 * floating.
284 */
285 if (((chip == BCM4712_DEVICE_ID) && (chippkg == BCM4712SMALL_PKG_ID)) ||
286 (boardflags & BFL_NOPCI))
287 pci_disabled = TRUE;
288
289 /*
290 * If the PCI core should not be touched (disabled, not bonded
291 * out, or pins floating), do not even attempt to access core
292 * registers. Otherwise, try to determine if it is in host
293 * mode.
294 */
295 if (pci_disabled)
296 host = 0;
297 else
298 host = !BUSPROBE(val, &pci->control);
299
300 if (!host) {
301 /* Disable PCI interrupts in client mode */
302 sb = (sbconfig_t *)((ulong) pci + SBCONFIGOFF);
303 W_REG(&sb->sbintvec, 0);
304
305 /* Disable the PCI bridge in client mode */
306 sbpci_ban(SB_PCI);
307 printf("PCI: Disabled\n");
308 } else {
309 /* Reset the external PCI bus and enable the clock */
310 W_REG(&pci->control, 0x5); /* enable the tristate drivers */
311 W_REG(&pci->control, 0xd); /* enable the PCI clock */
312 OSL_DELAY(150); /* delay > 100 us */
313 W_REG(&pci->control, 0xf); /* deassert PCI reset */
314 W_REG(&pci->arbcontrol, PCI_INT_ARB); /* use internal arbiter */
315 OSL_DELAY(1); /* delay 1 us */
316
317 /* Enable CardBusMode */
318 cardbus = nvram_match("cardbus", "1");
319 if (cardbus) {
320 printf("PCI: Enabling CardBus\n");
321 /* GPIO 1 resets the CardBus device on bcm94710ap */
322 sb_gpioout(sbh, 1, 1);
323 sb_gpioouten(sbh, 1, 1);
324 W_REG(&pci->sprom[0], R_REG(&pci->sprom[0]) | 0x400);
325 }
326
327 /* 64 MB I/O access window */
328 W_REG(&pci->sbtopci0, SBTOPCI_IO);
329 /* 64 MB configuration access window */
330 W_REG(&pci->sbtopci1, SBTOPCI_CFG0);
331 /* 1 GB memory access window */
332 W_REG(&pci->sbtopci2, SBTOPCI_MEM | SB_PCI_DMA);
333
334 /* Enable PCI bridge BAR0 prefetch and burst */
335 val = 6;
336 sbpci_write_config(sbh, 1, 0, 0, PCI_CFG_CMD, &val, sizeof(val));
337
338 /* Enable PCI interrupts */
339 W_REG(&pci->intmask, PCI_INTA);
340 }
341
342 /* Scan the SB bus */
343 bzero(sb_config_regs, sizeof(sb_config_regs));
344 for (cfg = sb_config_regs; cfg < &sb_config_regs[SB_MAXCORES]; cfg++) {
345 cfg->vendor = 0xffff;
346 if (!(regs = sb_setcoreidx(sbh, cfg - sb_config_regs)))
347 continue;
348 sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
349
350 /* Read ID register and parse vendor and core */
351 val = R_REG(&sb->sbidhigh);
352 vendor = (val & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT;
353 core = (val & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT;
354 progif = 0;
355
356 /* Check if this core is banned */
357 for (i = 0; i < pci_banned; i++)
358 if (core == pci_ban[i])
359 break;
360 if (i < pci_banned)
361 continue;
362
363 /* Known vendor translations */
364 switch (vendor) {
365 case SB_VEND_BCM:
366 vendor = VENDOR_BROADCOM;
367 break;
368 }
369
370 /* Determine class based on known core codes */
371 switch (core) {
372 case SB_ILINE20:
373 class = PCI_CLASS_NET;
374 subclass = PCI_NET_ETHER;
375 core = BCM47XX_ILINE_ID;
376 break;
377 case SB_ILINE100:
378 class = PCI_CLASS_NET;
379 subclass = PCI_NET_ETHER;
380 core = BCM4610_ILINE_ID;
381 break;
382 case SB_ENET:
383 class = PCI_CLASS_NET;
384 subclass = PCI_NET_ETHER;
385 core = BCM47XX_ENET_ID;
386 break;
387 case SB_SDRAM:
388 case SB_MEMC:
389 class = PCI_CLASS_MEMORY;
390 subclass = PCI_MEMORY_RAM;
391 break;
392 case SB_PCI:
393 class = PCI_CLASS_BRIDGE;
394 subclass = PCI_BRIDGE_PCI;
395 break;
396 case SB_MIPS:
397 case SB_MIPS33:
398 class = PCI_CLASS_CPU;
399 subclass = PCI_CPU_MIPS;
400 break;
401 case SB_CODEC:
402 class = PCI_CLASS_COMM;
403 subclass = PCI_COMM_MODEM;
404 core = BCM47XX_V90_ID;
405 break;
406 case SB_USB:
407 class = PCI_CLASS_SERIAL;
408 subclass = PCI_SERIAL_USB;
409 progif = 0x10; /* OHCI */
410 core = BCM47XX_USB_ID;
411 break;
412 case SB_USB11H:
413 class = PCI_CLASS_SERIAL;
414 subclass = PCI_SERIAL_USB;
415 progif = 0x10; /* OHCI */
416 core = BCM47XX_USBH_ID;
417 break;
418 case SB_USB11D:
419 class = PCI_CLASS_SERIAL;
420 subclass = PCI_SERIAL_USB;
421 core = BCM47XX_USBD_ID;
422 break;
423 case SB_IPSEC:
424 class = PCI_CLASS_CRYPT;
425 subclass = PCI_CRYPT_NETWORK;
426 core = BCM47XX_IPSEC_ID;
427 break;
428 case SB_EXTIF:
429 case SB_CC:
430 class = PCI_CLASS_MEMORY;
431 subclass = PCI_MEMORY_FLASH;
432 break;
433 case SB_D11:
434 class = PCI_CLASS_NET;
435 subclass = PCI_NET_OTHER;
436 /* Let an nvram variable override this */
437 sprintf(varname, "wl%did", wlidx);
438 wlidx++;
439 if ((core = getintvar(NULL, varname)) == 0) {
440 if (chip == BCM4712_DEVICE_ID) {
441 if (chippkg == BCM4712SMALL_PKG_ID)
442 core = BCM4306_D11G_ID;
443 else
444 core = BCM4306_D11DUAL_ID;
445 } else {
446 /* 4310 */
447 core = BCM4310_D11B_ID;
448 }
449 }
450 break;
451
452 default:
453 class = subclass = progif = 0xff;
454 break;
455 }
456
457 /* Supported translations */
458 cfg->vendor = htol16(vendor);
459 cfg->device = htol16(core);
460 cfg->rev_id = chiprev;
461 cfg->prog_if = progif;
462 cfg->sub_class = subclass;
463 cfg->base_class = class;
464 cfg->base[0] = htol32(sb_base(R_REG(&sb->sbadmatch0)));
465 cfg->base[1] = htol32(sb_base(R_REG(&sb->sbadmatch1)));
466 cfg->base[2] = htol32(sb_base(R_REG(&sb->sbadmatch2)));
467 cfg->base[3] = htol32(sb_base(R_REG(&sb->sbadmatch3)));
468 cfg->base[4] = 0;
469 cfg->base[5] = 0;
470 if (class == PCI_CLASS_BRIDGE && subclass == PCI_BRIDGE_PCI)
471 cfg->header_type = PCI_HEADER_BRIDGE;
472 else
473 cfg->header_type = PCI_HEADER_NORMAL;
474 /* Save core interrupt flag */
475 cfg->int_pin = R_REG(&sb->sbtpsflag) & SBTPS_NUM0_MASK;
476 /* Default to MIPS shared interrupt 0 */
477 cfg->int_line = 0;
478 /* MIPS sbipsflag maps core interrupt flags to interrupts 1 through 4 */
479 if ((regs = sb_setcore(sbh, SB_MIPS, 0)) ||
480 (regs = sb_setcore(sbh, SB_MIPS33, 0))) {
481 sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
482 val = R_REG(&sb->sbipsflag);
483 for (cfg->int_line = 1; cfg->int_line <= 4; cfg->int_line++) {
484 if (((val & sbips_int_mask[cfg->int_line]) >> sbips_int_shift[cfg->int_line]) == cfg->int_pin)
485 break;
486 }
487 if (cfg->int_line > 4)
488 cfg->int_line = 0;
489 }
490 /* Emulated core */
491 *((uint32 *) &cfg->sprom_control) = 0xffffffff;
492 }
493
494 sb_setcoreidx(sbh, coreidx);
495 return 0;
496 }
497
498 void
499 sbpci_check(void *sbh)
500 {
501 uint coreidx;
502 sbpciregs_t *pci;
503 uint32 sbtopci1;
504 uint32 buf[64], *ptr, i;
505 ulong pa;
506 volatile uint j;
507
508 coreidx = sb_coreidx(sbh);
509 pci = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0);
510
511 /* Clear the test array */
512 pa = (ulong) DMA_MAP(NULL, buf, sizeof(buf), DMA_RX, NULL);
513 ptr = (uint32 *) OSL_UNCACHED(&buf[0]);
514 memset(ptr, 0, sizeof(buf));
515
516 /* Point PCI window 1 to memory */
517 sbtopci1 = R_REG(&pci->sbtopci1);
518 W_REG(&pci->sbtopci1, SBTOPCI_MEM | (pa & SBTOPCI1_MASK));
519
520 /* Fill the test array via PCI window 1 */
521 ptr = (uint32 *) REG_MAP(SB_PCI_CFG + (pa & ~SBTOPCI1_MASK), sizeof(buf));
522 for (i = 0; i < ARRAYSIZE(buf); i++) {
523 for (j = 0; j < 2; j++);
524 W_REG(&ptr[i], i);
525 }
526 REG_UNMAP(ptr);
527
528 /* Restore PCI window 1 */
529 W_REG(&pci->sbtopci1, sbtopci1);
530
531 /* Check the test array */
532 DMA_UNMAP(NULL, pa, sizeof(buf), DMA_RX, NULL);
533 ptr = (uint32 *) OSL_UNCACHED(&buf[0]);
534 for (i = 0; i < ARRAYSIZE(buf); i++) {
535 if (ptr[i] != i)
536 break;
537 }
538
539 /* Change the clock if the test fails */
540 if (i < ARRAYSIZE(buf)) {
541 uint32 req, cur;
542
543 cur = sb_clock(sbh);
544 printf("PCI: Test failed at %d MHz\n", (cur + 500000) / 1000000);
545 for (req = 104000000; req < 176000000; req += 4000000) {
546 printf("PCI: Resetting to %d MHz\n", (req + 500000) / 1000000);
547 /* This will only reset if the clocks are valid and have changed */
548 sb_mips_setclock(sbh, req, 0, 0);
549 }
550 /* Should not reach here */
551 ASSERT(0);
552 }
553
554 sb_setcoreidx(sbh, coreidx);
555 }
This page took 0.092668 seconds and 5 git commands to generate.