[U-Boot] [PATCH] IXP425: Fixing PCI access Part 1/1

Stefan Althoefer stefan.althoefer at web.de
Thu Dec 4 22:09:49 CET 2008


[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 <stefan.althoefer at web.de>
----

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


More information about the U-Boot mailing list