b3469134ebee7df6927cdf8cf79442e23e69ef14
[oweals/openwrt.git] / openwrt / 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 //#define CT4712_WR         1   /* Workaround for 4712 */
249
250 int __init
251 sbpci_init(void *sbh)
252 {
253         uint chip, chiprev, chippkg, coreidx, host, i;
254         uint32 boardflags;
255         sbpciregs_t *pci;
256         sbconfig_t *sb;
257         pci_config_regs *cfg;
258         void *regs;
259         char varname[8];
260         int CT4712_WR;
261         uint wlidx = 0;
262         uint16 vendor, core;
263         uint8 class, subclass, progif;
264         uint32 val;
265         uint32 sbips_int_mask[] = { 0, SBIPS_INT1_MASK, SBIPS_INT2_MASK, SBIPS_INT3_MASK, SBIPS_INT4_MASK };
266         uint32 sbips_int_shift[] = { 0, 0, SBIPS_INT2_SHIFT, SBIPS_INT3_SHIFT, SBIPS_INT4_SHIFT };
267
268         chip = sb_chip(sbh);
269         chiprev = sb_chiprev(sbh);
270         chippkg = sb_chippkg(sbh);
271         coreidx = sb_coreidx(sbh);
272
273         if (!(pci = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0)))
274                 return -1;
275         sb_core_reset(sbh, 0);
276
277         /* In some board, */ 
278         if(nvram_match("boardtype", "bcm94710dev"))
279                 CT4712_WR = 0;
280         else
281                 CT4712_WR = 1;
282
283         boardflags = (uint32) getintvar(NULL, "boardflags");
284
285         if ((chip == BCM4310_DEVICE_ID) && (chiprev == 0))
286                 pci_disabled = TRUE;
287
288         /*
289          * The 200-pin BCM4712 package does not bond out PCI. Even when
290          * PCI is bonded out, some boards may leave the pins
291          * floating.
292          */
293         if (((chip == BCM4712_DEVICE_ID) && (chippkg == BCM4712SMALL_PKG_ID)) ||
294             (boardflags & BFL_NOPCI) || CT4712_WR)
295                 pci_disabled = TRUE;
296
297         /*
298          * If the PCI core should not be touched (disabled, not bonded
299          * out, or pins floating), do not even attempt to access core
300          * registers. Otherwise, try to determine if it is in host
301          * mode.
302          */
303         if (pci_disabled)
304                 host = 0;
305         else
306                 host = !BUSPROBE(val, &pci->control);
307
308         if (!host) {
309                 /* Disable PCI interrupts in client mode */
310                 sb = (sbconfig_t *)((ulong) pci + SBCONFIGOFF);
311                 W_REG(&sb->sbintvec, 0);
312
313                 /* Disable the PCI bridge in client mode */
314                 sbpci_ban(SB_PCI);
315                 printf("PCI: Disabled\n");
316         } else {
317                 /* Reset the external PCI bus and enable the clock */
318                 W_REG(&pci->control, 0x5);              /* enable the tristate drivers */
319                 W_REG(&pci->control, 0xd);              /* enable the PCI clock */
320                 OSL_DELAY(150);                         /* delay > 100 us */
321                 W_REG(&pci->control, 0xf);              /* deassert PCI reset */
322                 W_REG(&pci->arbcontrol, PCI_INT_ARB);   /* use internal arbiter */
323                 OSL_DELAY(1);                           /* delay 1 us */
324
325                 /* Enable CardBusMode */
326                 cardbus = nvram_match("cardbus", "1");
327                 if (cardbus) {
328                         printf("PCI: Enabling CardBus\n");
329                         /* GPIO 1 resets the CardBus device on bcm94710ap */
330                         sb_gpioout(sbh, 1, 1);
331                         sb_gpioouten(sbh, 1, 1);
332                         W_REG(&pci->sprom[0], R_REG(&pci->sprom[0]) | 0x400);
333                 }
334
335                 /* 64 MB I/O access window */
336                 W_REG(&pci->sbtopci0, SBTOPCI_IO);
337                 /* 64 MB configuration access window */
338                 W_REG(&pci->sbtopci1, SBTOPCI_CFG0);
339                 /* 1 GB memory access window */
340                 W_REG(&pci->sbtopci2, SBTOPCI_MEM | SB_PCI_DMA);
341
342                 /* Enable PCI bridge BAR0 prefetch and burst */
343                 val = 6;
344                 sbpci_write_config(sbh, 1, 0, 0, PCI_CFG_CMD, &val, sizeof(val));
345
346                 /* Enable PCI interrupts */
347                 W_REG(&pci->intmask, PCI_INTA);
348         }
349
350         /* Scan the SB bus */
351         bzero(sb_config_regs, sizeof(sb_config_regs));
352         for (cfg = sb_config_regs; cfg < &sb_config_regs[SB_MAXCORES]; cfg++) {
353                 cfg->vendor = 0xffff;
354                 if (!(regs = sb_setcoreidx(sbh, cfg - sb_config_regs)))
355                         continue;
356                 sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
357
358                 /* Read ID register and parse vendor and core */
359                 val = R_REG(&sb->sbidhigh);
360                 vendor = (val & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT;
361                 core = (val & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT;
362                 progif = 0;
363
364                 /* Check if this core is banned */
365                 for (i = 0; i < pci_banned; i++)
366                         if (core == pci_ban[i])
367                                 break;
368                 if (i < pci_banned)
369                         continue;
370
371                 /* Known vendor translations */
372                 switch (vendor) {
373                 case SB_VEND_BCM:
374                         vendor = VENDOR_BROADCOM;
375                         break;
376                 }
377
378                 /* Determine class based on known core codes */
379                 switch (core) {
380                 case SB_ILINE20:
381                         class = PCI_CLASS_NET;
382                         subclass = PCI_NET_ETHER;
383                         core = BCM47XX_ILINE_ID;
384                         break;
385                 case SB_ILINE100:
386                         class = PCI_CLASS_NET;
387                         subclass = PCI_NET_ETHER;
388                         core = BCM4610_ILINE_ID;
389                         break;
390                 case SB_ENET:
391                         class = PCI_CLASS_NET;
392                         subclass = PCI_NET_ETHER;
393                         core = BCM47XX_ENET_ID;
394                         break;
395                 case SB_SDRAM:
396                 case SB_MEMC:
397                         class = PCI_CLASS_MEMORY;
398                         subclass = PCI_MEMORY_RAM;
399                         break;
400                 case SB_PCI:
401                         class = PCI_CLASS_BRIDGE;
402                         subclass = PCI_BRIDGE_PCI;
403                         break;
404                 case SB_MIPS:
405                 case SB_MIPS33:
406                         class = PCI_CLASS_CPU;
407                         subclass = PCI_CPU_MIPS;
408                         break;
409                 case SB_CODEC:
410                         class = PCI_CLASS_COMM;
411                         subclass = PCI_COMM_MODEM;
412                         core = BCM47XX_V90_ID;
413                         break;
414                 case SB_USB:
415                         class = PCI_CLASS_SERIAL;
416                         subclass = PCI_SERIAL_USB;
417                         progif = 0x10; /* OHCI */
418                         core = BCM47XX_USB_ID;
419                         break;
420                 case SB_USB11H:
421                         class = PCI_CLASS_SERIAL;
422                         subclass = PCI_SERIAL_USB;
423                         progif = 0x10; /* OHCI */
424                         core = BCM47XX_USBH_ID;
425                         break;
426                 case SB_USB11D:
427                         class = PCI_CLASS_SERIAL;
428                         subclass = PCI_SERIAL_USB;
429                         core = BCM47XX_USBD_ID;
430                         break;
431                 case SB_IPSEC:
432                         class = PCI_CLASS_CRYPT;
433                         subclass = PCI_CRYPT_NETWORK;
434                         core = BCM47XX_IPSEC_ID;
435                         break;
436                 case SB_EXTIF:
437                 case SB_CC:
438                         class = PCI_CLASS_MEMORY;
439                         subclass = PCI_MEMORY_FLASH;
440                         break;
441                 case SB_D11:
442                         class = PCI_CLASS_NET;
443                         subclass = PCI_NET_OTHER;
444                         /* Let an nvram variable override this */
445                         sprintf(varname, "wl%did", wlidx);
446                         wlidx++;
447                         if ((core = getintvar(NULL, varname)) == 0) {
448                                 if (chip == BCM4712_DEVICE_ID) {
449                                         if (chippkg == BCM4712SMALL_PKG_ID)
450                                                 core = BCM4306_D11G_ID;
451                                         else
452                                                 core = BCM4306_D11DUAL_ID;
453                                 } else {
454                                         /* 4310 */
455                                         core = BCM4310_D11B_ID;
456                                 }
457                         }
458                         break;
459
460                 default:
461                         class = subclass = progif = 0xff;
462                         break;
463                 }
464
465                 /* Supported translations */
466                 cfg->vendor = htol16(vendor);
467                 cfg->device = htol16(core);
468                 cfg->rev_id = chiprev;
469                 cfg->prog_if = progif;
470                 cfg->sub_class = subclass;
471                 cfg->base_class = class;
472                 cfg->base[0] = htol32(sb_base(R_REG(&sb->sbadmatch0)));
473                 cfg->base[1] = htol32(sb_base(R_REG(&sb->sbadmatch1)));
474                 cfg->base[2] = htol32(sb_base(R_REG(&sb->sbadmatch2)));
475                 cfg->base[3] = htol32(sb_base(R_REG(&sb->sbadmatch3)));
476                 cfg->base[4] = 0;
477                 cfg->base[5] = 0;
478                 if (class == PCI_CLASS_BRIDGE && subclass == PCI_BRIDGE_PCI)
479                         cfg->header_type = PCI_HEADER_BRIDGE;
480                 else
481                         cfg->header_type = PCI_HEADER_NORMAL;
482                 /* Save core interrupt flag */
483                 cfg->int_pin = R_REG(&sb->sbtpsflag) & SBTPS_NUM0_MASK;
484                 /* Default to MIPS shared interrupt 0 */
485                 cfg->int_line = 0;
486                 /* MIPS sbipsflag maps core interrupt flags to interrupts 1 through 4 */
487                 if ((regs = sb_setcore(sbh, SB_MIPS, 0)) ||
488                     (regs = sb_setcore(sbh, SB_MIPS33, 0))) {
489                         sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF);
490                         val = R_REG(&sb->sbipsflag);
491                         for (cfg->int_line = 1; cfg->int_line <= 4; cfg->int_line++) {
492                                 if (((val & sbips_int_mask[cfg->int_line]) >> sbips_int_shift[cfg->int_line]) == cfg->int_pin)
493                                         break;
494                         }
495                         if (cfg->int_line > 4)
496                                 cfg->int_line = 0;
497                 }
498                 /* Emulated core */
499                 *((uint32 *) &cfg->sprom_control) = 0xffffffff;
500         }
501
502         sb_setcoreidx(sbh, coreidx);
503         return 0;
504 }
505
506 void
507 sbpci_check(void *sbh)
508 {
509         uint coreidx;
510         sbpciregs_t *pci;
511         uint32 sbtopci1;
512         uint32 buf[64], *ptr, i;
513         ulong pa;
514         volatile uint j;
515
516         coreidx = sb_coreidx(sbh);
517         pci = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0);
518
519         /* Clear the test array */
520         pa = (ulong) DMA_MAP(NULL, buf, sizeof(buf), DMA_RX, NULL);
521         ptr = (uint32 *) OSL_UNCACHED(&buf[0]);
522         memset(ptr, 0, sizeof(buf));
523
524         /* Point PCI window 1 to memory */
525         sbtopci1 = R_REG(&pci->sbtopci1);
526         W_REG(&pci->sbtopci1, SBTOPCI_MEM | (pa & SBTOPCI1_MASK));
527
528         /* Fill the test array via PCI window 1 */
529         ptr = (uint32 *) REG_MAP(SB_PCI_CFG + (pa & ~SBTOPCI1_MASK), sizeof(buf));
530         for (i = 0; i < ARRAYSIZE(buf); i++) {
531                 for (j = 0; j < 2; j++);
532                 W_REG(&ptr[i], i);
533         }
534         REG_UNMAP(ptr);
535
536         /* Restore PCI window 1 */
537         W_REG(&pci->sbtopci1, sbtopci1);
538
539         /* Check the test array */
540         DMA_UNMAP(NULL, pa, sizeof(buf), DMA_RX, NULL);
541         ptr = (uint32 *) OSL_UNCACHED(&buf[0]);
542         for (i = 0; i < ARRAYSIZE(buf); i++) {
543                 if (ptr[i] != i)
544                         break;
545         }
546
547         /* Change the clock if the test fails */
548         if (i < ARRAYSIZE(buf)) {
549                 uint32 req, cur;
550
551                 cur = sb_clock(sbh);
552                 printf("PCI: Test failed at %d MHz\n", (cur + 500000) / 1000000);
553                 for (req = 104000000; req < 176000000; req += 4000000) {
554                         printf("PCI: Resetting to %d MHz\n", (req + 500000) / 1000000);
555                         /* This will only reset if the clocks are valid and have changed */
556                         sb_mips_setclock(sbh, req, 0, 0);
557                 }
558                 /* Should not reach here */
559                 ASSERT(0);
560         }
561
562         sb_setcoreidx(sbh, coreidx);
563 }