[PATCH] IXP425: Fixing PCI access

This patch fixes the PCI handling routines of the IXP port.
It seems that this hasn't been touch for quite a while and
u-boot PCI handling has changed since then (but nobody
update IXP). Not even access to configuration space
did work.

It was tested with Janz emPC-A400.


The patch is against "latest" u-boot git-repository

Please (still) be patient if style of submission or patches are
offending.

Signed-off-by: Stefan Althoefer <[EMAIL PROTECTED]>
----

diff -uprN u-boot-orig//cpu/ixp/pci.c u-boot/cpu/ixp/pci.c
--- u-boot-orig//cpu/ixp/pci.c  2008-12-02 17:25:31.000000000 +0100
+++ u-boot/cpu/ixp/pci.c        2008-12-02 22:00:59.000000000 +0100
@@ -33,16 +33,15 @@
 #include <asm/arch/ixp425.h>
 #include <asm/arch/ixp425pci.h>
 
-static void non_prefetch_read (unsigned int addr, unsigned int cmd,
+static int non_prefetch_read (unsigned int addr, unsigned int cmd,
                               unsigned int *data);
-static void non_prefetch_write (unsigned int addr, unsigned int cmd,
+static int non_prefetch_write (unsigned int addr, unsigned int cmd,
                                unsigned int data);
 static void configure_pins (void);
 static void sys_pci_gpio_clock_config (void);
-static void pci_bus_scan (void);
-static int pci_device_exists (unsigned int deviceNo);
-static void sys_pci_bar_info_get (unsigned int devnum, unsigned int bus,
-                                 unsigned int dev, unsigned int func);
+void pci_bus_scan (void);
+static int pci_device_exists (pci_dev_t dev);
+static void sys_pci_bar_info_get (unsigned int devnum, pci_dev_t dev);
 static void sys_pci_device_bars_write (void);
 static void calc_bars (PciBar * Bars[], unsigned int nBars,
                       unsigned int startAddr);
@@ -68,6 +67,23 @@ PciBar *memBars[IXP425_PCI_MAX_BAR];
 PciBar *ioBars[IXP425_PCI_MAX_BAR];
 PciDevice devices[IXP425_PCI_MAX_FUNC_ON_BUS];
 
+extern int pciTranslateIrq(pci_dev_t dev, int intPin);
+
+static u32 ixp4xx_config_addr(u8 bus_num, pci_dev_t devfn, int where)
+{
+       u32 addr;
+       if (!bus_num) {
+               /* type 0 */
+               addr = BIT(32-PCI_DEV(devfn)) | ((PCI_FUNC(devfn)) << 8) |
+                   (where & ~3);
+       } else {
+               /* type 1 */
+               addr = (bus_num << 16) | ((PCI_DEV(devfn)) << 11) |
+                       ((PCI_FUNC(devfn)) << 8) | (where & ~3) | 1;
+       }
+       return addr;
+}
+
 int pci_read_config_dword (pci_dev_t dev, int where, unsigned int *val)
 {
        unsigned int retval;
@@ -75,8 +91,11 @@ int pci_read_config_dword (pci_dev_t dev
 
        /*address bits 31:28 specify the device 10:8 specify the function */
        /*Set the address to be read */
-       addr = BIT ((31 - dev)) | (where & ~3);
-       non_prefetch_read (addr, NP_CMD_CONFIGREAD, &retval);
+       //addr = BIT ((31 - dev)) | (where & ~3);
+       addr = ixp4xx_config_addr(PCI_BUS(dev),dev, where & ~3);
+       if( non_prefetch_read (addr, NP_CMD_CONFIGREAD, &retval) != OK ){
+               return ERROR;
+       }
 
        *val = retval;
 
@@ -99,8 +118,11 @@ int pci_read_config_word (pci_dev_t dev,
        byteEnables = byteEnables << PCI_NP_CBE_BESL;
        /*address bits 31:28 specify the device 10:8 specify the function */
        /*Set the address to be read */
-       addr = BIT ((31 - dev)) | (where & ~3);
-       non_prefetch_read (addr, byteEnables | NP_CMD_CONFIGREAD, &retval);
+       //addr = BIT ((31 - dev)) | (where & ~3);
+       addr = ixp4xx_config_addr(PCI_BUS(dev),dev, where & ~3);
+       if( non_prefetch_read (addr, byteEnables | NP_CMD_CONFIGREAD, &retval) 
!= OK ){
+               return ERROR;
+       }
 
        /*Pick out the word we are interested in */
        *val = (retval >> (8 * n));
@@ -123,8 +145,11 @@ int pci_read_config_byte (pci_dev_t dev,
 
        /*address bits 31:28 specify the device, 10:8 specify the function */
        /*Set the address to be read */
-       addr = BIT ((31 - dev)) | (where & ~3);
-       non_prefetch_read (addr, byteEnables | NP_CMD_CONFIGREAD, &retval);
+       //addr = BIT ((31 - dev)) | (where & ~3);
+       addr = ixp4xx_config_addr(PCI_BUS(dev),dev, where & ~3);
+       if( non_prefetch_read (addr, byteEnables | NP_CMD_CONFIGREAD, &retval) 
!= OK ){
+               return ERROR;
+       }
        /*Pick out the byte we are interested in */
        *val = (retval >> (8 * n));
 
@@ -146,8 +171,11 @@ int pci_write_config_byte (pci_dev_t dev
        ldata = val << (8 * n);
        /*address bits 31:28 specify the device 10:8 specify the function */
        /*Set the address to be written */
-       addr = BIT ((31 - dev)) | (where & ~3);
-       non_prefetch_write (addr, byteEnables | NP_CMD_CONFIGWRITE, ldata);
+       //addr = BIT ((31 - dev)) | (where & ~3);
+       addr = ixp4xx_config_addr(PCI_BUS(dev),dev, where & ~3);
+       if( non_prefetch_write (addr, byteEnables | NP_CMD_CONFIGWRITE, ldata) 
!= OK ){
+               return ERROR;
+       }
 
        return (OK);
 }
@@ -169,8 +197,11 @@ int pci_write_config_word (pci_dev_t dev
        ldata = val << (8 * n);
        /*address bits 31:28 specify the device 10:8 specify the function */
        /*Set the address to be written */
-       addr = BIT (31 - dev) | (where & ~3);
-       non_prefetch_write (addr, byteEnables | NP_CMD_CONFIGWRITE, ldata);
+       //addr = BIT (31 - dev) | (where & ~3);
+       addr = ixp4xx_config_addr(PCI_BUS(dev),dev, where & ~3);
+       if( non_prefetch_write (addr, byteEnables | NP_CMD_CONFIGWRITE, ldata) 
!= OK ){
+               return ERROR;
+       }
 
        return (OK);
 }
@@ -181,29 +212,41 @@ int pci_write_config_dword (pci_dev_t de
 
        /*address bits 31:28 specify the device 10:8 specify the function */
        /*Set the address to be written */
-       addr = BIT (31 - dev) | (where & ~3);
-       non_prefetch_write (addr, NP_CMD_CONFIGWRITE, val);
+       //addr = BIT (31 - dev) | (where & ~3);
+       addr = ixp4xx_config_addr(PCI_BUS(dev),dev, where & ~3);
+       if( non_prefetch_write (addr, NP_CMD_CONFIGWRITE, val) != OK ){
+               return ERROR;
+       }
 
        return (OK);
 }
 
-void non_prefetch_read (unsigned int addr,
+int non_prefetch_read (unsigned int addr,
                        unsigned int cmd, unsigned int *data)
 {
-       REG_WRITE (PCI_CSR_BASE, PCI_NP_AD_OFFSET, addr);
+       unsigned int   isr;
 
+       REG_WRITE (PCI_CSR_BASE, PCI_NP_AD_OFFSET, addr);
        /*set up and execute the read */
        REG_WRITE (PCI_CSR_BASE, PCI_NP_CBE_OFFSET, cmd);
-
        /*The result of the read is now in np_rdata */
        REG_READ (PCI_CSR_BASE, PCI_NP_RDATA_OFFSET, *data);
 
-       return;
+       /* Check for abort */
+       REG_READ (PCI_CSR_BASE, PCI_ISR_OFFSET, isr);
+       if( isr & PCI_ISR_PFE ){
+               /* clear the bit */
+               REG_WRITE (PCI_CSR_BASE, PCI_ISR_OFFSET, PCI_ISR_PFE);
+               return ERROR;
+       }
+
+       return OK;
 }
 
-void non_prefetch_write (unsigned int addr,
+int non_prefetch_write (unsigned int addr,
                         unsigned int cmd, unsigned int data)
 {
+       unsigned int   isr;
 
        REG_WRITE (PCI_CSR_BASE, PCI_NP_AD_OFFSET, addr);
        /*set up the write */
@@ -211,7 +254,15 @@ void non_prefetch_write (unsigned int ad
        /*Execute the write by writing to NP_WDATA */
        REG_WRITE (PCI_CSR_BASE, PCI_NP_WDATA_OFFSET, data);
 
-       return;
+       /* Check for abort */
+       REG_READ (PCI_CSR_BASE, PCI_ISR_OFFSET, isr);
+       if( isr & PCI_ISR_PFE ){
+               /* clear the bit */
+               REG_WRITE (PCI_CSR_BASE, PCI_ISR_OFFSET, PCI_ISR_PFE);
+               return ERROR;
+       }
+
+       return OK;
 }
 
 /*
@@ -259,7 +310,7 @@ void pci_ixp_init (struct pci_controller
 
 /*
  ==========================================================
-               Init IXP PCI
+               Init IXP PCI
  ==========================================================
 */
        REG_READ (PCI_CSR_BASE, PCI_CSR_OFFSET, regval);
@@ -304,9 +355,7 @@ void pci_ixp_init (struct pci_controller
        pci_write_config_word (0, PCI_CFG_COMMAND, INITIAL_PCI_CMD);
        REG_WRITE (PCI_CSR_BASE, PCI_ISR_OFFSET, PCI_ISR_PSE
                   | PCI_ISR_PFE | PCI_ISR_PPE | PCI_ISR_AHBE);
-#ifdef CONFIG_PCI_SCAN_SHOW
-       printf ("Device  bus  dev  func  deviceID  vendorID \n");
-#endif
+
        pci_bus_scan ();
 }
 
@@ -349,15 +398,17 @@ void sys_pci_gpio_clock_config (void)
 
 void pci_bus_scan (void)
 {
-       unsigned int bus = 0, dev, func = 0;
+        int       busno, devno, funcno;
+       pci_dev_t dev;
        unsigned short data16;
        unsigned int data32;
        unsigned char intPin;
 
+       unsigned int vendorId;
+       unsigned char HeaderType;
+
        /* Assign first device to ourselves */
-       devices[0].bus = 0;
-       devices[0].device = 0;
-       devices[0].func = 0;
+       devices[0].device = PCI_BDF(0,0,0);
 
        crp_read (PCI_CFG_VENDOR_ID, &data32);
 
@@ -371,22 +422,30 @@ void pci_bus_scan (void)
        nMBars = 0;
        nIOBars = 0;
 
-       for (dev = 0; dev < IXP425_PCI_MAX_DEV; dev++) {
-
-               /*Check whether a device is present */
-               if (pci_device_exists (dev) != TRUE) {
+       for(busno=0; busno<2; busno++){
+         for(devno=0; devno<PCI_MAX_PCI_DEVICES; devno++){
+           for(funcno=0; funcno<PCI_MAX_PCI_FUNCTIONS; funcno++) {
+               dev = PCI_BDF(busno,devno,funcno);
+
+               if( pci_read_config_dword (dev, PCI_CFG_VENDOR_ID, &vendorId) 
== ERROR ){
+                   funcno=PCI_MAX_PCI_FUNCTIONS;
+                   continue;
+               }
 
-                       /*Clear error bits in ISR, write 1 to clear */
-                       REG_WRITE (PCI_CSR_BASE, PCI_ISR_OFFSET, PCI_ISR_PSE
-                                  | PCI_ISR_PFE | PCI_ISR_PPE |
-                                  PCI_ISR_AHBE);
-                       continue;
+               if ( vendorId == 0x0 ) {
+                   funcno=PCI_MAX_PCI_FUNCTIONS;
+                   continue;
+               }
+               
+               if( funcno == 0 ){
+                   pci_read_config_byte(dev, PCI_HEADER_TYPE, &HeaderType);
+                   if ( !(HeaderType & 0x80) ){
+                       funcno=PCI_MAX_PCI_FUNCTIONS;
+                   }
                }
 
                /*A device is present, add an entry to the array */
-               devices[nDevices].bus = bus;
                devices[nDevices].device = dev;
-               devices[nDevices].func = func;
 
                pci_read_config_word (dev, PCI_CFG_VENDOR_ID, &data16);
 
@@ -399,24 +458,22 @@ void pci_bus_scan (void)
                devices[nDevices].error = FALSE;
 
                /*Figure out what BARs are on this device */
-               sys_pci_bar_info_get (nDevices, bus, dev, func);
+               sys_pci_bar_info_get (nDevices, dev);
                /*Figure out what INTX# line the card uses */
-               pci_read_config_byte (dev, PCI_CFG_DEV_INT_PIN, &intPin);
+       pci_read_config_byte (dev, PCI_CFG_DEV_INT_PIN, &intPin);
 
                /*assign the appropriate irq line */
                if (intPin > PCI_IRQ_LINES) {
                        devices[nDevices].error = TRUE;
                } else if (intPin != 0) {
                        /*This device uses an interrupt line */
-                       /*devices[nDevices].irq = 
ixp425PciIntTranslate[dev][intPin-1]; */
-                       devices[nDevices].irq = intPin;
+                       //devices[nDevices].irq = 
ixp425PciIntTranslate[devno][intPin-1];
+                       devices[nDevices].irq = pciTranslateIrq(dev,intPin);
+                       //devices[nDevices].irq = intPin;
                }
-#ifdef CONFIG_PCI_SCAN_SHOW
-               printf ("%06d    %03d %03d %04d  %08d      %08x\n", nDevices,
-                       devices[nDevices].vendor_id);
-#endif
                nDevices++;
-
+           }
+         }
        }
 
        calc_bars (memBars, nMBars, IXP425_PCI_BAR_MEM_BASE);
@@ -426,44 +483,43 @@ void pci_bus_scan (void)
                   | PCI_ISR_PFE | PCI_ISR_PPE | PCI_ISR_AHBE);
 }
 
-void sys_pci_bar_info_get (unsigned int devnum,
-                          unsigned int bus,
-                          unsigned int dev, unsigned int func)
+void sys_pci_bar_info_get (unsigned int devnum, pci_dev_t dev)
 {
        unsigned int data32;
        unsigned int tmp;
        unsigned int size;
+       int          bar;
 
-       pci_write_config_dword (devnum,
-                               PCI_CFG_BASE_ADDRESS_0, IXP425_PCI_BAR_QUERY);
-       pci_read_config_dword (devnum, PCI_CFG_BASE_ADDRESS_0, &data32);
-
-       devices[devnum].bar[0].address = (data32 & 1);
-
-       if (data32 & 1) {
+       for(bar=0; bar<=5; bar++){
+           pci_write_config_dword (dev,
+                                   PCI_CFG_BASE_ADDRESS_0+(4*bar), 
IXP425_PCI_BAR_QUERY);
+           pci_read_config_dword (dev, PCI_CFG_BASE_ADDRESS_0+(4*bar), 
&data32);
+           
+           devices[devnum].bar[dev].address = (data32 & 1);
+           
+           if (data32 & 1) {
                /* IO space */
                tmp = data32 & ~0x3;
                size = ~(tmp - 1);
-               devices[devnum].bar[0].size = size;
-
+               devices[devnum].bar[bar].size = size;
+               
                if (nIOBars < IXP425_PCI_MAX_BAR) {
-                       ioBars[nIOBars++] = &devices[devnum].bar[0];
+                   ioBars[nIOBars++] = &devices[devnum].bar[bar];
                }
-       } else {
+           } else {
                /* Mem space */
                tmp = data32 & ~IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK;
                size = ~(tmp - 1);
-               devices[devnum].bar[0].size = size;
-
+               devices[devnum].bar[bar].size = size;
+               
                if (nMBars < IXP425_PCI_MAX_BAR) {
-                       memBars[nMBars++] = &devices[devnum].bar[0];
+                       memBars[nMBars++] = &devices[devnum].bar[bar];
                } else {
                        devices[devnum].error = TRUE;
                }
-
+               
+           }
        }
-
-       devices[devnum].bar[1].size = 0;
 }
 
 void sortBars (PciBar * Bars[], unsigned int nBars)
@@ -497,28 +553,33 @@ void calc_bars (PciBar * Bars[], unsigne
        }
 
        for (i = 0; i < nBars; i++) {
+           if( Bars[i]->size > 0 ){
+               if( startAddr & ((Bars[i]->size)-1) ){
+                   startAddr |= ((Bars[i]->size)-1);
+                   startAddr += 1;
+               }
                Bars[i]->address |= startAddr;
                startAddr += Bars[i]->size;
+           }
        }
 }
 
 void sys_pci_device_bars_write (void)
 {
-       unsigned int i;
-       int addr;
+       unsigned int i, bar;
 
        for (i = 1; i < nDevices; i++) {
                if (devices[i].error) {
                        continue;
                }
 
-               pci_write_config_dword (devices[i].device,
-                                       PCI_CFG_BASE_ADDRESS_0,
-                                       devices[i].bar[0].address);
-               addr = BIT (31 - devices[i].device) |
-                       (0 << PCI_NP_AD_FUNCSL) |
-                       (PCI_CFG_BASE_ADDRESS_0 & ~3);
-               pci_write_config_dword (devices[i].device,
+               for(bar=0; bar<5; bar++){
+                   pci_write_config_dword (devices[i].device,
+                                           PCI_CFG_BASE_ADDRESS_0+(4*bar),
+                                           devices[i].bar[bar].address);
+               }
+
+               pci_write_config_byte (devices[i].device,
                                        PCI_CFG_DEV_INT_LINE, devices[i].irq);
 
                pci_write_config_word (devices[i].device,
@@ -528,24 +589,18 @@ void sys_pci_device_bars_write (void)
 }
 
 
-int pci_device_exists (unsigned int deviceNo)
+int pci_device_exists (pci_dev_t dev)
 {
        unsigned int vendorId;
-       unsigned int regval;
 
-       pci_read_config_dword (deviceNo, PCI_CFG_VENDOR_ID, &vendorId);
+       if( pci_read_config_dword (dev, PCI_CFG_VENDOR_ID, &vendorId) == ERROR 
){
+           return FALSE;
+       }
 
-       /* There are two ways to find out an empty device.
-        *   1. check Master Abort bit after the access.
-        *   2. check whether the vendor id read back is 0x0.
-        */
-       REG_READ (PCI_CSR_BASE, PCI_ISR_OFFSET, regval);
-       if ((vendorId != 0x0) && ((regval & PCI_ISR_PFE) == 0)) {
+       if ( vendorId != 0x0 ) {
                return TRUE;
        }
-       /*no device present, make sure that the master abort bit is reset */
 
-       REG_WRITE (PCI_CSR_BASE, PCI_ISR_OFFSET, PCI_ISR_PFE);
        return FALSE;
 }
 
diff -uprN u-boot-orig//board/ixdp425/ixdp425.c u-boot/board/ixdp425/ixdp425.c
--- u-boot-orig//board/ixdp425/ixdp425.c        2008-12-02 17:25:31.000000000 
+0100
+++ u-boot/board/ixdp425/ixdp425.c      2008-12-03 14:13:36.000000000 +0100
@@ -118,9 +118,18 @@ void pci_init_board(void)
 
        pci_ixp_init(&hose);
 }
+
+#include <pci.h>
+int pciTranslateIrq(pci_dev_t dev, int intPin)
+{
+       /* FIXME: This needs to be implemented by someone
+          who onws an IXDP425 board */
+       return 0;
+}
 #endif
 
 int board_eth_init(bd_t *bis)
 {
        return pci_eth_init(bis);
 }
+
diff -uprN u-boot-orig//drivers/pci/pci_indirect.c 
u-boot/drivers/pci/pci_indirect.c
--- u-boot-orig//drivers/pci/pci_indirect.c     2008-12-02 17:25:31.000000000 
+0100
+++ u-boot/drivers/pci/pci_indirect.c   2008-12-02 23:03:09.000000000 +0100
@@ -11,7 +11,7 @@
 
 #include <common.h>
 
-#if (!defined(__I386__) && !defined(CONFIG_IXDP425))
+#if (!defined(__I386__) && !defined(CONFIG_IXP425))
 
 #include <asm/processor.h>
 #include <asm/io.h>
@@ -133,4 +133,4 @@ void pci_setup_indirect(struct pci_contr
        hose->cfg_data = (unsigned char *) cfg_data;
 }
 
-#endif /* !__I386__ && !CONFIG_IXDP425 */
+#endif /* !__I386__ && !CONFIG_IXP425 */
Dateien u-boot-orig//.git/index und u-boot/.git/index sind verschieden.
diff -uprN u-boot-orig//include/asm-arm/arch-ixp/ixp425pci.h 
u-boot/include/asm-arm/arch-ixp/ixp425pci.h
--- u-boot-orig//include/asm-arm/arch-ixp/ixp425pci.h   2008-12-02 
17:25:32.000000000 +0100
+++ u-boot/include/asm-arm/arch-ixp/ixp425pci.h 2008-12-02 22:04:57.000000000 
+0100
@@ -52,9 +52,7 @@ typedef struct
 
 typedef struct
 {
-       unsigned int bus;
-       unsigned int device;
-       unsigned int func;
+       pci_dev_t    device;
        unsigned int irq;
        BOOL error;
        unsigned short vendor_id;
@@ -74,13 +72,13 @@ typedef struct
 
 #define IXP425_PCI_BAR_QUERY                   0xffffffff
 
-#define IXP425_PCI_BAR_MEM_BASE 0x100000
-#define IXP425_PCI_BAR_IO_BASE 0x000000
+#define IXP425_PCI_BAR_MEM_BASE 0x48000000
+#define IXP425_PCI_BAR_IO_BASE 0x00000000    /* not supported */
 
 /*define the maximum number of bus segments - we support a single segment*/
-#define IXP425_PCI_MAX_BUS  1
+#define IXP425_PCI_MAX_BUS  4
 /*define the maximum number of cards per bus segment*/
-#define IXP425_PCI_MAX_DEV  4
+#define IXP425_PCI_MAX_DEV  8
 /*define the maximum number of functions per device*/
 #define IXP425_PCI_MAX_FUNC 8
 /* define the maximum number of separate functions that we can
@@ -153,7 +151,7 @@ typedef struct
 /*define the default setting of the AHB memory base reg*/
 #define IXP425_PCI_AHBMEMBASE_DEFAULT 0x00010203
 #define IXP425_PCI_AHBIOBASE_DEFAULT  0x0
-#define IXP425_PCI_PCIMEMBASE_DEFAULT 0x0
+#define IXP425_PCI_PCIMEMBASE_DEFAULT 0x48494a4b
 
 /*define the default settings for the controller's BARs*/
 #ifdef IXP425_PCI_SIMPLE_MAPPING
_______________________________________________
U-Boot mailing list
[email protected]
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to