patch-2.4.19 linux-2.4.19/arch/mips/mips-boards/generic/pci.c
Next file: linux-2.4.19/arch/mips/mips-boards/generic/printf.c
Previous file: linux-2.4.19/arch/mips/mips-boards/generic/mipsIRQ.S
Back to the patch index
Back to the overall index
- Lines: 312
- Date:
Fri Aug 2 17:39:43 2002
- Orig file:
linux-2.4.18/arch/mips/mips-boards/generic/pci.c
- Orig date:
Sun Sep 9 10:43:02 2001
diff -urN linux-2.4.18/arch/mips/mips-boards/generic/pci.c linux-2.4.19/arch/mips/mips-boards/generic/pci.c
@@ -29,66 +29,229 @@
#include <asm/mips-boards/generic.h>
#include <asm/gt64120.h>
+#include <asm/mips-boards/bonito64.h>
#ifdef CONFIG_MIPS_MALTA
#include <asm/mips-boards/malta.h>
#endif
+#include <asm/mips-boards/msc01_pci.h>
#define PCI_ACCESS_READ 0
#define PCI_ACCESS_WRITE 1
+/*
+ * PCI configuration cycle AD bus definition
+ */
+/* Type 0 */
+#define PCI_CFG_TYPE0_REG_SHF 0
+#define PCI_CFG_TYPE0_FUNC_SHF 8
+
+/* Type 1 */
+#define PCI_CFG_TYPE1_REG_SHF 0
+#define PCI_CFG_TYPE1_FUNC_SHF 8
+#define PCI_CFG_TYPE1_DEV_SHF 11
+#define PCI_CFG_TYPE1_BUS_SHF 16
+
static int
mips_pcibios_config_access(unsigned char access_type, struct pci_dev *dev,
unsigned char where, u32 *data)
{
unsigned char bus = dev->bus->number;
unsigned char dev_fn = dev->devfn;
- u32 intr;
+ unsigned char type;
+ u32 intr, dummy;
+ u64 pci_addr;
+
+ switch(mips_revision_corid) {
+ case MIPS_REVISION_CORID_QED_RM5261:
+ case MIPS_REVISION_CORID_CORE_LV:
+ case MIPS_REVISION_CORID_CORE_FPGA:
+ /* Galileo GT64120 system controller. */
+
+ if ((bus == 0) && (dev_fn >= PCI_DEVFN(31,0)))
+ return -1; /* Because of a bug in the galileo (for slot 31). */
+
+ /* Clear cause register bits */
+ GT_READ(GT_INTRCAUSE_OFS, intr);
+ GT_WRITE(GT_INTRCAUSE_OFS, intr &
+ ~(GT_INTRCAUSE_MASABORT0_BIT |
+ GT_INTRCAUSE_TARABORT0_BIT));
+
+ /* Setup address */
+ GT_WRITE(GT_PCI0_CFGADDR_OFS,
+ (bus << GT_PCI0_CFGADDR_BUSNUM_SHF) |
+ (dev_fn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
+ ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
+ GT_PCI0_CFGADDR_CONFIGEN_BIT);
+
+ if (access_type == PCI_ACCESS_WRITE) {
+ if (bus == 0 && dev_fn == 0) {
+ /*
+ * The Galileo system controller is acting
+ * differently than other devices.
+ */
+ GT_WRITE(GT_PCI0_CFGDATA_OFS, *data);
+ } else {
+ GT_PCI_WRITE(GT_PCI0_CFGDATA_OFS, *data);
+ }
+ } else {
+ if (bus == 0 && dev_fn == 0) {
+ /*
+ * The Galileo system controller is acting
+ * differently than other devices.
+ */
+ GT_READ(GT_PCI0_CFGDATA_OFS, *data);
+ } else {
+ GT_PCI_READ(GT_PCI0_CFGDATA_OFS, *data);
+ }
+ }
+
+ /* Check for master or target abort */
+ GT_READ(GT_INTRCAUSE_OFS, intr);
+
+ if (intr & (GT_INTRCAUSE_MASABORT0_BIT |
+ GT_INTRCAUSE_TARABORT0_BIT))
+ {
+ /* Error occured */
+
+ /* Clear bits */
+ GT_READ(GT_INTRCAUSE_OFS, intr);
+ GT_WRITE(GT_INTRCAUSE_OFS, intr &
+ ~(GT_INTRCAUSE_MASABORT0_BIT |
+ GT_INTRCAUSE_TARABORT0_BIT));
- if ((bus == 0) && (dev_fn >= PCI_DEVFN(31,0)))
- return -1; /* Because of a bug in the galileo (for slot 31). */
+ return -1;
+ }
+
+ break;
- /* Clear cause register bits */
- GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
- GT_INTRCAUSE_TARABORT0_BIT));
-
- /* Setup address */
- GT_WRITE(GT_PCI0_CFGADDR_OFS,
- (bus << GT_PCI0_CFGADDR_BUSNUM_SHF) |
- (dev_fn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
- ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
- GT_PCI0_CFGADDR_CONFIGEN_BIT);
-
- if (access_type == PCI_ACCESS_WRITE) {
- if (bus == 0 && dev_fn == 0) {
- /*
- * Galileo is acting differently than other devices.
- */
- GT_WRITE(GT_PCI0_CFGDATA_OFS, *data);
+ case MIPS_REVISION_CORID_BONITO64:
+ case MIPS_REVISION_CORID_CORE_20K:
+ /* Algorithmics Bonito64 system controller. */
+
+ if ((bus == 0) && (PCI_SLOT(dev_fn) == 0)) {
+ return -1;
+ }
+
+ /* Clear cause register bits */
+ BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR |
+ BONITO_PCICMD_MTABORT_CLR);
+
+ /*
+ * Setup pattern to be used as PCI "address" for
+ * Type 0 cycle
+ */
+ if (bus == 0) {
+ /* IDSEL */
+ pci_addr = (u64)1 << (PCI_SLOT(dev_fn) + 10);
} else {
- GT_PCI_WRITE(GT_PCI0_CFGDATA_OFS, *data);
+ /* Bus number */
+ pci_addr = bus << PCI_CFG_TYPE1_BUS_SHF;
+
+ /* Device number */
+ pci_addr |= PCI_SLOT(dev_fn) << PCI_CFG_TYPE1_DEV_SHF;
}
- } else {
- if (bus == 0 && dev_fn == 0) {
- /*
- * Galileo is acting differently than other devices.
- */
- GT_READ(GT_PCI0_CFGDATA_OFS, *data);
+
+ /* Function (same for Type 0/1) */
+ pci_addr |= PCI_FUNC(dev_fn) << PCI_CFG_TYPE0_FUNC_SHF;
+
+ /* Register number (same for Type 0/1) */
+ pci_addr |= (where & ~0x3) << PCI_CFG_TYPE0_REG_SHF;
+
+ if (bus == 0) {
+ /* Type 0 */
+ BONITO_PCIMAP_CFG = pci_addr >> 16;
} else {
- GT_PCI_READ(GT_PCI0_CFGDATA_OFS, *data);
+ /* Type 1 */
+ BONITO_PCIMAP_CFG = (pci_addr >> 16) | 0x10000;
+ }
+
+ /* Flush Bonito register block */
+ dummy = BONITO_PCIMAP_CFG;
+ __asm__ __volatile__(
+ ".set\tnoreorder\n\t"
+ ".set\tnoat\n\t"
+ "sync\n\t"
+ ".set\tat\n\t"
+ ".set\treorder");
+
+ /* Perform access */
+ if (access_type == PCI_ACCESS_WRITE) {
+ *(volatile u32 *)(KSEG1ADDR(BONITO_PCICFG_BASE +
+ (pci_addr & 0xffff))) = *(u32 *)data;
+
+ /* Wait till done */
+ while (BONITO_PCIMSTAT & 0xF)
+ ;
+ } else {
+ *(u32 *)data =
+ *(volatile u32 *)(KSEG1ADDR(BONITO_PCICFG_BASE +
+ (pci_addr & 0xffff)));
}
- }
- /* Check for master or target abort */
- GT_READ(GT_INTRCAUSE_OFS, intr);
+ /* Detect Master/Target abort */
+ if (BONITO_PCICMD & (BONITO_PCICMD_MABORT_CLR |
+ BONITO_PCICMD_MTABORT_CLR) )
+ {
+ /* Error occurred */
+
+ /* Clear bits */
+ BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR |
+ BONITO_PCICMD_MTABORT_CLR);
+
+ return -1;
+ }
+ break;
- if (intr & (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT))
- {
- /* Error occured */
-
- /* Clear bits */
- GT_WRITE( GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
- GT_INTRCAUSE_TARABORT0_BIT) );
+ case MIPS_REVISION_CORID_CORE_MSC:
+ /* MIPS system controller. */
+ if ((bus == 0) && (PCI_SLOT(dev_fn) == 0)) {
+ return -1;
+ }
+
+ /* Clear status register bits. */
+ MSC_WRITE(MSC01_PCI_INTSTAT,
+ (MSC01_PCI_INTCFG_MA_BIT |
+ MSC01_PCI_INTCFG_TA_BIT));
+
+ /* Setup address */
+ if (bus == 0)
+ type = 0; /* Type 0 */
+ else
+ type = 1; /* Type 1 */
+
+ MSC_WRITE(MSC01_PCI_CFGADDR,
+ ((bus << MSC01_PCI_CFGADDR_BNUM_SHF) |
+ (PCI_SLOT(dev_fn) << MSC01_PCI_CFGADDR_DNUM_SHF) |
+ (PCI_FUNC(dev_fn) << MSC01_PCI_CFGADDR_FNUM_SHF) |
+ ((where /4 ) << MSC01_PCI_CFGADDR_RNUM_SHF) |
+ (type)));
+
+ /* Perform access */
+ if (access_type == PCI_ACCESS_WRITE) {
+ MSC_WRITE(MSC01_PCI_CFGDATA, *data);
+ } else {
+ MSC_READ(MSC01_PCI_CFGDATA, *data);
+ }
+
+ /* Detect Master/Target abort */
+ MSC_READ(MSC01_PCI_INTSTAT, intr);
+ if (intr & (MSC01_PCI_INTCFG_MA_BIT |
+ MSC01_PCI_INTCFG_TA_BIT))
+ {
+ /* Error occurred */
+
+ /* Clear bits */
+ MSC_READ(MSC01_PCI_INTSTAT, intr);
+ MSC_WRITE(MSC01_PCI_INTSTAT,
+ (MSC01_PCI_INTCFG_MA_BIT |
+ MSC01_PCI_INTCFG_TA_BIT));
+
+ return -1;
+ }
+ break;
+ default:
+ printk("Unknown Core card, don't know the system controller.\n");
return -1;
}
@@ -216,21 +379,28 @@
printk("PCI: Probing PCI hardware on host bus 0.\n");
pci_scan_bus(0, &mips_pci_ops, NULL);
- /*
- * Due to a bug in the Galileo system controller, we need to setup
- * the PCI BAR for the Galileo internal registers.
- * This should be done in the bios/bootprom and will be fixed in
- * a later revision of YAMON (the MIPS boards boot prom).
- */
- GT_WRITE(GT_PCI0_CFGADDR_OFS,
- (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | /* Local bus */
- (0 << GT_PCI0_CFGADDR_DEVNUM_SHF) | /* GT64120 device */
- (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | /* Function 0 */
- ((0x20/4) << GT_PCI0_CFGADDR_REGNUM_SHF) | /* BAR 4 */
- GT_PCI0_CFGADDR_CONFIGEN_BIT );
-
- /* Perform the write */
- GT_WRITE( GT_PCI0_CFGDATA_OFS, PHYSADDR(MIPS_GT_BASE));
+ switch(mips_revision_corid) {
+ case MIPS_REVISION_CORID_QED_RM5261:
+ case MIPS_REVISION_CORID_CORE_LV:
+ case MIPS_REVISION_CORID_CORE_FPGA:
+ /*
+ * Due to a bug in the Galileo system controller, we need
+ * to setup the PCI BAR for the Galileo internal registers.
+ * This should be done in the bios/bootprom and will be
+ * fixed in a later revision of YAMON (the MIPS boards
+ * boot prom).
+ */
+ GT_WRITE(GT_PCI0_CFGADDR_OFS,
+ (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | /* Local bus */
+ (0 << GT_PCI0_CFGADDR_DEVNUM_SHF) | /* GT64120 dev */
+ (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | /* Function 0*/
+ ((0x20/4) << GT_PCI0_CFGADDR_REGNUM_SHF) | /* BAR 4*/
+ GT_PCI0_CFGADDR_CONFIGEN_BIT );
+
+ /* Perform the write */
+ GT_WRITE( GT_PCI0_CFGDATA_OFS, PHYSADDR(MIPS_GT_BASE));
+ break;
+ }
#ifdef CONFIG_MIPS_MALTA
pci_for_each_dev(pdev) {
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)