[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