IXP42x PCI rewrite

clean up IXP PCI handling: get rid of IXP-private bus scan, BAR assign etc.
code and use u-boot's PCI infrastructure instead.  Move board-specific PCI
setup code (clock/reset) to board directory.

Signed-off-by: Michael Schwingen <michael@schwingen.org>
This commit is contained in:
Michael Schwingen 2011-05-23 00:00:12 +02:00 committed by Albert ARIBAUD
parent 904ec57b33
commit 29161f47d0
4 changed files with 216 additions and 555 deletions

View file

@ -22,88 +22,21 @@
* MA 02111-1307 USA * MA 02111-1307 USA
*/ */
#ifndef _IXP425PCI_H_ #ifndef _IXP425PCI_H
#define _IXP425PCI_H_ #define _IXP425PCI_H
#define TRUE 1
#define FALSE 0
#define OK 0 #define OK 0
#define ERROR -1 #define ERROR -1
#define BOOL int
#define IXP425_PCI_MAX_BAR_PER_FUNC 6 struct pci_controller;
#define IXP425_PCI_MAX_BAR (IXP425_PCI_MAX_BAR_PER_FUNC * \ extern void pci_ixp_init(struct pci_controller *hose);
IXP425_PCI_MAX_FUNC_ON_BUS)
enum PciBarId
{
CSR_BAR=0,
IO_BAR,
SD_BAR,
NO_BAR
};
/*Base address register descriptor*/
typedef struct
{
unsigned int size;
unsigned int address;
} PciBar;
typedef struct
{
unsigned int bus;
unsigned int device;
unsigned int func;
unsigned int irq;
BOOL error;
unsigned short vendor_id;
unsigned short device_id;
/*We need an extra entry in this array for dummy placeholder*/
PciBar bar[IXP425_PCI_MAX_BAR_PER_FUNC + 1];
} PciDevice;
/* Mask definitions*/ /* Mask definitions*/
#define IXP425_PCI_TOP_WORD_OF_LONG_MASK 0xffff0000
#define IXP425_PCI_TOP_BYTE_OF_LONG_MASK 0xff000000
#define IXP425_PCI_BOTTOM_WORD_OF_LONG_MASK 0x0000ffff
#define IXP425_PCI_BOTTOM_TRIBYTES_OF_LONG_MASK 0x00ffffff
#define IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK 0x0000000f #define IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK 0x0000000f
#define IXP425_PCI_MAX_UINT32 0xffffffff
#define IXP425_PCI_BAR_QUERY 0xffffffff
#define IXP425_PCI_BAR_MEM_BASE 0x100000
#define IXP425_PCI_BAR_IO_BASE 0x000000
/*define the maximum number of bus segments - we support a single segment*/
#define IXP425_PCI_MAX_BUS 1
/*define the maximum number of cards per bus segment*/
#define IXP425_PCI_MAX_DEV 4
/*define the maximum number of functions per device*/
#define IXP425_PCI_MAX_FUNC 8
/* define the maximum number of separate functions that we can
potentially have on the bus*/
#define IXP425_PCI_MAX_FUNC_ON_BUS (1+ IXP425_PCI_MAX_FUNC * \
IXP425_PCI_MAX_DEV * \
IXP425_PCI_MAX_BUS)
/*define the maximum number of BARs per function*/
#define IXP425_PCI_MAX_BAR_PER_FUNC 6
#define IXP425_PCI_MAX_BAR (IXP425_PCI_MAX_BAR_PER_FUNC * \
IXP425_PCI_MAX_FUNC_ON_BUS)
#define PCI_NP_CBE_BESL (4) #define PCI_NP_CBE_BESL (4)
#define PCI_NP_AD_FUNCSL (8) #define PCI_NP_AD_FUNCSL (8)
#define REG_WRITE(b,o,v) (*(volatile unsigned int*)((b+o))=(v))
#define REG_READ(b,o,v) ((v)=(*(volatile unsigned int*)((b+o))))
#define PCI_DELAY 500
#define USEC_LOOP_COUNT 533
#define PCI_SETTLE_USEC 200
#define PCI_MIN_RESET_ASSERT_USEC 2000
/*Register addressing definitions for PCI controller configuration /*Register addressing definitions for PCI controller configuration
and status registers*/ and status registers*/
@ -150,28 +83,6 @@ typedef struct
#define NP_CMD_CONFIGWRITE (0xb) #define NP_CMD_CONFIGWRITE (0xb)
*/ */
/*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 the default settings for the controller's BARs*/
#ifdef IXP425_PCI_SIMPLE_MAPPING
#define IXP425_PCI_BAR_0_DEFAULT 0x00000000
#define IXP425_PCI_BAR_1_DEFAULT 0x01000000
#define IXP425_PCI_BAR_2_DEFAULT 0x02000000
#define IXP425_PCI_BAR_3_DEFAULT 0x03000000
#define IXP425_PCI_BAR_4_DEFAULT 0x00000000
#define IXP425_PCI_BAR_5_DEFAULT 0x00000000
#else
#define IXP425_PCI_BAR_0_DEFAULT 0x40000000
#define IXP425_PCI_BAR_1_DEFAULT 0x41000000
#define IXP425_PCI_BAR_2_DEFAULT 0x42000000
#define IXP425_PCI_BAR_3_DEFAULT 0x43000000
#define IXP425_PCI_BAR_4_DEFAULT 0x00000000
#define IXP425_PCI_BAR_5_DEFAULT 0x00000000
#endif
/*Configuration Port register bit definitions*/ /*Configuration Port register bit definitions*/
#define PCI_CRP_WRITE BIT(16) #define PCI_CRP_WRITE BIT(16)
@ -228,17 +139,6 @@ typedef struct
#define PCI_CFG_SPECIAL_USE 0x41 #define PCI_CFG_SPECIAL_USE 0x41
#define PCI_CFG_MODE 0x43 #define PCI_CFG_MODE 0x43
/*Specify the initial command we send to PCI devices*/
#define INITIAL_PCI_CMD (PCI_CMD_IO_ENABLE \
| PCI_CMD_MEM_ENABLE \
| PCI_CMD_MASTER_ENABLE \
| PCI_CMD_WI_ENABLE)
/*define the sub vendor and subsystem to be used */
#define IXP425_PCI_SUB_VENDOR_SYSTEM 0x00000000
#define PCI_IRQ_LINES 4
#define PCI_CMD_IO_ENABLE 0x0001 /* IO access enable */ #define PCI_CMD_IO_ENABLE 0x0001 /* IO access enable */
#define PCI_CMD_MEM_ENABLE 0x0002 /* memory access enable */ #define PCI_CMD_MEM_ENABLE 0x0002 /* memory access enable */
#define PCI_CMD_MASTER_ENABLE 0x0004 /* bus master enable */ #define PCI_CMD_MASTER_ENABLE 0x0004 /* bus master enable */
@ -287,26 +187,4 @@ typedef struct
#define PCI_DMACTRL_PADC1 BIT(14) #define PCI_DMACTRL_PADC1 BIT(14)
#define PCI_DMACTRL_PADE1 BIT(15) #define PCI_DMACTRL_PADE1 BIT(15)
/* GPIO related register */
#undef IXP425_GPIO_GPOUTR
#undef IXP425_GPIO_GPOER
#undef IXP425_GPIO_GPINR
#undef IXP425_GPIO_GPISR
#undef IXP425_GPIO_GPIT1R
#undef IXP425_GPIO_GPIT2R
#undef IXP425_GPIO_GPCLKR
#define IXP425_GPIO_GPOUTR 0xC8004000
#define IXP425_GPIO_GPOER 0xC8004004
#define IXP425_GPIO_GPINR 0xC8004008
#define IXP425_GPIO_GPISR 0xC800400C
#define IXP425_GPIO_GPIT1R 0xC8004010
#define IXP425_GPIO_GPIT2R 0xC8004014
#define IXP425_GPIO_GPCLKR 0xC8004018
#define READ_GPIO_REG(addr,val) \
(val) = *((volatile int *)(addr));
#define WRITE_GPIO_REG(addr,val) \
*((volatile int *)(addr)) = (val);
#endif #endif

View file

@ -50,7 +50,6 @@ PCI_HOSE_OP(write, byte, u8)
PCI_HOSE_OP(write, word, u16) PCI_HOSE_OP(write, word, u16)
PCI_HOSE_OP(write, dword, u32) PCI_HOSE_OP(write, dword, u32)
#ifndef CONFIG_IXP425
#define PCI_OP(rw, size, type, error_code) \ #define PCI_OP(rw, size, type, error_code) \
int pci_##rw##_config_##size(pci_dev_t dev, int offset, type value) \ int pci_##rw##_config_##size(pci_dev_t dev, int offset, type value) \
{ \ { \
@ -71,7 +70,6 @@ PCI_OP(read, dword, u32 *, *value = 0xffffffff)
PCI_OP(write, byte, u8, ) PCI_OP(write, byte, u8, )
PCI_OP(write, word, u16, ) PCI_OP(write, word, u16, )
PCI_OP(write, dword, u32, ) PCI_OP(write, dword, u32, )
#endif /* CONFIG_IXP425 */
#define PCI_READ_VIA_DWORD_OP(size, type, off_mask) \ #define PCI_READ_VIA_DWORD_OP(size, type, off_mask) \
int pci_hose_read_config_##size##_via_dword(struct pci_controller *hose,\ int pci_hose_read_config_##size##_via_dword(struct pci_controller *hose,\
@ -190,7 +188,6 @@ int pci_last_busno(void)
return hose->last_busno; return hose->last_busno;
} }
#ifndef CONFIG_IXP425
pci_dev_t pci_find_devices(struct pci_device_id *ids, int index) pci_dev_t pci_find_devices(struct pci_device_id *ids, int index)
{ {
struct pci_controller * hose; struct pci_controller * hose;
@ -246,7 +243,6 @@ pci_dev_t pci_find_devices(struct pci_device_id *ids, int index)
return (-1); return (-1);
} }
#endif /* CONFIG_IXP425 */
pci_dev_t pci_find_device(unsigned int vendor, unsigned int device, int index) pci_dev_t pci_find_device(unsigned int vendor, unsigned int device, int index)
{ {

View file

@ -11,7 +11,7 @@
#include <common.h> #include <common.h>
#if (!defined(__I386__) && !defined(CONFIG_IXDP425)) #if !defined(__I386__)
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/io.h> #include <asm/io.h>
@ -20,15 +20,6 @@
#define cfg_read(val, addr, type, op) *val = op((type)(addr)) #define cfg_read(val, addr, type, op) *val = op((type)(addr))
#define cfg_write(val, addr, type, op) op((type *)(addr), (val)) #define cfg_write(val, addr, type, op) op((type *)(addr), (val))
#ifdef CONFIG_IXP425
extern unsigned char in_8 (volatile unsigned *addr);
extern unsigned short in_le16 (volatile unsigned *addr);
extern unsigned in_le32 (volatile unsigned *addr);
extern void out_8 (volatile unsigned *addr, char val);
extern void out_le16 (volatile unsigned *addr, unsigned short val);
extern void out_le32 (volatile unsigned *addr, unsigned int val);
#endif /* CONFIG_IXP425 */
#if defined(CONFIG_MPC8260) #if defined(CONFIG_MPC8260)
#define INDIRECT_PCI_OP(rw, size, type, op, mask) \ #define INDIRECT_PCI_OP(rw, size, type, op, mask) \
static int \ static int \
@ -134,4 +125,4 @@ void pci_setup_indirect(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
hose->cfg_data = (unsigned char *) cfg_data; hose->cfg_data = (unsigned char *) cfg_data;
} }
#endif /* !__I386__ && !CONFIG_IXDP425 */ #endif /* !__I386__ */

View file

@ -1,5 +1,8 @@
/* /*
* IXP PCI Init * IXP PCI Init
*
* (C) Copyright 2011
* Michael Schwingen, michael@schwingen.org
* (C) Copyright 2004 eslab.whut.edu.cn * (C) Copyright 2004 eslab.whut.edu.cn
* Yue Hu(huyue_whut@yahoo.com.cn), Ligong Xue(lgxue@hotmail.com) * Yue Hu(huyue_whut@yahoo.com.cn), Ligong Xue(lgxue@hotmail.com)
* *
@ -22,7 +25,6 @@
* MA 02111-1307 USA * MA 02111-1307 USA
*/ */
#include <common.h> #include <common.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/io.h> #include <asm/io.h>
@ -30,542 +32,336 @@
#include <asm/arch/ixp425.h> #include <asm/arch/ixp425.h>
#include <asm/arch/ixp425pci.h> #include <asm/arch/ixp425pci.h>
static void non_prefetch_read (unsigned int addr, unsigned int cmd, DECLARE_GLOBAL_DATA_PTR;
static void non_prefetch_read(unsigned int addr, unsigned int cmd,
unsigned int *data); unsigned int *data);
static void non_prefetch_write (unsigned int addr, unsigned int cmd, static void non_prefetch_write(unsigned int addr, unsigned int cmd,
unsigned int data); unsigned int data);
static void configure_pins (void);
static void sys_pci_gpio_clock_config (void); /*define the sub vendor and subsystem to be used */
static void pci_bus_scan (void); #define IXP425_PCI_SUB_VENDOR_SYSTEM 0x00000000
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);
static void sys_pci_device_bars_write (void);
static void calc_bars (PciBar * Bars[], unsigned int nBars,
unsigned int startAddr);
#define PCI_MEMORY_BUS 0x00000000 #define PCI_MEMORY_BUS 0x00000000
#define PCI_MEMORY_PHY 0x48000000 #define PCI_MEMORY_PHY 0x00000000
#define PCI_MEMORY_SIZE 0x04000000 #define PCI_MEMORY_SIZE 0x04000000
#define PCI_MEM_BUS 0x40000000 #define PCI_MEM_BUS 0x48000000
#define PCI_MEM_PHY 0x00000000 #define PCI_MEM_PHY 0x00000000
#define PCI_MEM_SIZE 0x04000000 #define PCI_MEM_SIZE 0x04000000
#define PCI_IO_BUS 0x40000000 #define PCI_IO_BUS 0x00000000
#define PCI_IO_PHY 0x50000000 #define PCI_IO_PHY 0x00000000
#define PCI_IO_SIZE 0x10000000 #define PCI_IO_SIZE 0x00010000
struct pci_controller hose; /* build address value for config sycle */
static unsigned int pci_config_addr(pci_dev_t bdf, unsigned int reg)
unsigned int nDevices;
unsigned int nMBars;
unsigned int nIOBars;
PciBar *memBars[IXP425_PCI_MAX_BAR];
PciBar *ioBars[IXP425_PCI_MAX_BAR];
PciDevice devices[IXP425_PCI_MAX_FUNC_ON_BUS];
int pci_read_config_dword (pci_dev_t dev, int where, unsigned int *val)
{ {
unsigned int retval; unsigned int bus = PCI_BUS(bdf);
unsigned int dev = PCI_DEV(bdf);
unsigned int func = PCI_FUNC(bdf);
unsigned int addr; unsigned int addr;
/*address bits 31:28 specify the device 10:8 specify the function */ if (bus) { /* secondary bus, use type 1 config cycle */
/*Set the address to be read */ addr = bdf | (reg & ~3) | 1;
addr = BIT ((31 - dev)) | (where & ~3); } else {
non_prefetch_read (addr, NP_CMD_CONFIGREAD, &retval); /*
primary bus, type 0 config cycle. address bits 31:28
*val = retval; specify the device 10:8 specify the function
return (OK);
}
int pci_read_config_word (pci_dev_t dev, int where, unsigned short *val)
{
unsigned int n;
unsigned int retval;
unsigned int addr;
unsigned int byteEnables;
n = where % 4;
/*byte enables are 4 bits active low, the position of each
bit maps to the byte that it enables */
byteEnables =
(~(BIT (n) | BIT ((n + 1)))) &
IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK;
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);
/*Pick out the word we are interested in */
*val = (retval >> (8 * n));
return (OK);
}
int pci_read_config_byte (pci_dev_t dev, int where, unsigned char *val)
{
unsigned int retval;
unsigned int n;
unsigned int byteEnables;
unsigned int addr;
n = where % 4;
/*byte enables are 4 bits, active low, the position of each
bit maps to the byte that it enables */
byteEnables = (~BIT (n)) & IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK;
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);
/*Pick out the byte we are interested in */
*val = (retval >> (8 * n));
return (OK);
}
int pci_write_config_byte (pci_dev_t dev, int where, unsigned char val)
{
unsigned int addr;
unsigned int byteEnables;
unsigned int n;
unsigned int ldata;
n = where % 4;
/*byte enables are 4 bits active low, the position of each
bit maps to the byte that it enables */
byteEnables = (~BIT (n)) & IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK;
byteEnables = byteEnables << PCI_NP_CBE_BESL;
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);
return (OK);
}
int pci_write_config_word (pci_dev_t dev, int where, unsigned short val)
{
unsigned int addr;
unsigned int byteEnables;
unsigned int n;
unsigned int ldata;
n = where % 4;
/*byte enables are 4 bits active low, the position of each
bit maps to the byte that it enables */
byteEnables =
(~(BIT (n) | BIT ((n + 1)))) &
IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK;
byteEnables = byteEnables << PCI_NP_CBE_BESL;
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);
return (OK);
}
int pci_write_config_dword (pci_dev_t dev, int where, unsigned int val)
{
unsigned int addr;
/*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);
return (OK);
}
void non_prefetch_read (unsigned int addr,
unsigned int cmd, unsigned int *data)
{
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;
}
void non_prefetch_write (unsigned int addr,
unsigned int cmd, unsigned int data)
{
REG_WRITE (PCI_CSR_BASE, PCI_NP_AD_OFFSET, addr);
/*set up the write */
REG_WRITE (PCI_CSR_BASE, PCI_NP_CBE_OFFSET, cmd);
/*Execute the write by writing to NP_WDATA */
REG_WRITE (PCI_CSR_BASE, PCI_NP_WDATA_OFFSET, data);
return;
}
/*
* PCI controller config registers are accessed through these functions
* i.e. these allow us to set up our own BARs etc.
*/ */
void crp_read (unsigned int offset, unsigned int *data) addr = BIT((31 - dev)) | (func << 8) | (reg & ~3);
{ }
REG_WRITE (PCI_CSR_BASE, PCI_CRP_AD_CBE_OFFSET, offset);
REG_READ (PCI_CSR_BASE, PCI_CRP_RDATA_OFFSET, *data); return addr;
} }
void crp_write (unsigned int offset, unsigned int data) static int pci_config_status(void)
{
/*The CRP address register bit 16 indicates that we want to do a write */
REG_WRITE (PCI_CSR_BASE, PCI_CRP_AD_CBE_OFFSET,
PCI_CRP_WRITE | offset);
REG_WRITE (PCI_CSR_BASE, PCI_CRP_WDATA_OFFSET, data);
}
/*struct pci_controller *hose*/
void pci_ixp_init (struct pci_controller *hose)
{ {
unsigned int regval; unsigned int regval;
regval = readl(PCI_CSR_BASE + PCI_ISR_OFFSET);
if ((regval & PCI_ISR_PFE) == 0)
return OK;
/* no device present, make sure that the master abort bit is reset */
writel(PCI_ISR_PFE, PCI_CSR_BASE + PCI_ISR_OFFSET);
return ERROR;
}
static int pci_ixp_hose_read_config_dword(struct pci_controller *hose,
pci_dev_t bdf, int where, unsigned int *val)
{
unsigned int retval;
unsigned int addr;
int stat;
debug("pci_ixp_hose_read_config_dword: bdf %x, reg %x", bdf, where);
/*Set the address to be read */
addr = pci_config_addr(bdf, where);
non_prefetch_read(addr, NP_CMD_CONFIGREAD, &retval);
*val = retval;
stat = pci_config_status();
if (stat < 0)
*val = -1;
debug("-> val %x, status %x\n", *val, stat);
return stat;
}
static int pci_ixp_hose_read_config_word(struct pci_controller *hose,
pci_dev_t bdf, int where, unsigned short *val)
{
unsigned int n;
unsigned int retval;
unsigned int addr;
unsigned int byteEnables;
int stat;
debug("pci_ixp_hose_read_config_word: bdf %x, reg %x", bdf, where);
n = where % 4;
/*byte enables are 4 bits active low, the position of each
bit maps to the byte that it enables */
byteEnables =
(~(BIT(n) | BIT((n + 1)))) &
IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK;
byteEnables = byteEnables << PCI_NP_CBE_BESL;
/*Set the address to be read */
addr = pci_config_addr(bdf, where);
non_prefetch_read(addr, byteEnables | NP_CMD_CONFIGREAD, &retval);
/*Pick out the word we are interested in */
*val = retval >> (8 * n);
stat = pci_config_status();
if (stat < 0)
*val = -1;
debug("-> val %x, status %x\n", *val, stat);
return stat;
}
static int pci_ixp_hose_read_config_byte(struct pci_controller *hose,
pci_dev_t bdf, int where, unsigned char *val)
{
unsigned int retval;
unsigned int n;
unsigned int byteEnables;
unsigned int addr;
int stat;
debug("pci_ixp_hose_read_config_byte: bdf %x, reg %x", bdf, where);
n = where % 4;
/*byte enables are 4 bits, active low, the position of each
bit maps to the byte that it enables */
byteEnables = (~BIT(n)) & IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK;
byteEnables = byteEnables << PCI_NP_CBE_BESL;
/*Set the address to be read */
addr = pci_config_addr(bdf, where);
non_prefetch_read(addr, byteEnables | NP_CMD_CONFIGREAD, &retval);
/*Pick out the byte we are interested in */
*val = retval >> (8 * n);
stat = pci_config_status();
if (stat < 0)
*val = -1;
debug("-> val %x, status %x\n", *val, stat);
return stat;
}
static int pci_ixp_hose_write_config_byte(struct pci_controller *hose,
pci_dev_t bdf, int where, unsigned char val)
{
unsigned int addr;
unsigned int byteEnables;
unsigned int n;
unsigned int ldata;
int stat;
debug("pci_ixp_hose_write_config_byte: bdf %x, reg %x, val %x",
bdf, where, val);
n = where % 4;
/*byte enables are 4 bits active low, the position of each
bit maps to the byte that it enables */
byteEnables = (~BIT(n)) & IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK;
byteEnables = byteEnables << PCI_NP_CBE_BESL;
ldata = val << (8 * n);
/*Set the address to be written */
addr = pci_config_addr(bdf, where);
non_prefetch_write(addr, byteEnables | NP_CMD_CONFIGWRITE, ldata);
stat = pci_config_status();
debug("-> status %x\n", stat);
return stat;
}
static int pci_ixp_hose_write_config_word(struct pci_controller *hose,
pci_dev_t bdf, int where, unsigned short val)
{
unsigned int addr;
unsigned int byteEnables;
unsigned int n;
unsigned int ldata;
int stat;
debug("pci_ixp_hose_write_config_word: bdf %x, reg %x, val %x",
bdf, where, val);
n = where % 4;
/*byte enables are 4 bits active low, the position of each
bit maps to the byte that it enables */
byteEnables =
(~(BIT(n) | BIT((n + 1)))) &
IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK;
byteEnables = byteEnables << PCI_NP_CBE_BESL;
ldata = val << (8 * n);
/*Set the address to be written */
addr = pci_config_addr(bdf, where);
non_prefetch_write(addr, byteEnables | NP_CMD_CONFIGWRITE, ldata);
stat = pci_config_status();
debug("-> status %x\n", stat);
return stat;
}
static int pci_ixp_hose_write_config_dword(struct pci_controller *hose,
pci_dev_t bdf, int where, unsigned int val)
{
unsigned int addr;
int stat;
debug("pci_ixp_hose_write_config_dword: bdf %x, reg %x, val %x",
bdf, where, val);
/*Set the address to be written */
addr = pci_config_addr(bdf, where);
non_prefetch_write(addr, NP_CMD_CONFIGWRITE, val);
stat = pci_config_status();
debug("-> status %x\n", stat);
return stat;
}
static void non_prefetch_read(unsigned int addr,
unsigned int cmd, unsigned int *data)
{
writel(addr, PCI_CSR_BASE + PCI_NP_AD_OFFSET);
/*set up and execute the read */
writel(cmd, PCI_CSR_BASE + PCI_NP_CBE_OFFSET);
/*The result of the read is now in np_rdata */
*data = readl(PCI_CSR_BASE + PCI_NP_RDATA_OFFSET);
return;
}
static void non_prefetch_write(unsigned int addr,
unsigned int cmd, unsigned int data)
{
writel(addr, PCI_CSR_BASE + PCI_NP_AD_OFFSET);
/*set up the write */
writel(cmd, PCI_CSR_BASE + PCI_NP_CBE_OFFSET);
/*Execute the write by writing to NP_WDATA */
writel(data, PCI_CSR_BASE + PCI_NP_WDATA_OFFSET);
return;
}
static void crp_write(unsigned int offset, unsigned int data)
{
/*
* The CRP address register bit 16 indicates that we want to do a
* write
*/
writel(PCI_CRP_WRITE | offset, PCI_CSR_BASE + PCI_CRP_AD_CBE_OFFSET);
writel(data, PCI_CSR_BASE + PCI_CRP_WDATA_OFFSET);
}
void pci_ixp_init(struct pci_controller *hose)
{
unsigned int csr;
/*
* Specify that the AHB bus is operating in big endian mode. Set up
* byte lane swapping between little-endian PCI and the big-endian
* AHB bus
*/
#ifdef __ARMEB__
csr = PCI_CSR_ABE | PCI_CSR_PDS | PCI_CSR_ADS;
#else
csr = PCI_CSR_ABE;
#endif
writel(csr, PCI_CSR_BASE + PCI_CSR_OFFSET);
writel(0, PCI_CSR_BASE + PCI_INTEN_OFFSET);
/*
* We configure the PCI inbound memory windows to be
* 1:1 mapped to SDRAM
*/
crp_write(PCI_CFG_BASE_ADDRESS_0, 0x00000000);
crp_write(PCI_CFG_BASE_ADDRESS_1, 0x01000000);
crp_write(PCI_CFG_BASE_ADDRESS_2, 0x02000000);
crp_write(PCI_CFG_BASE_ADDRESS_3, 0x03000000);
/*
* Enable CSR window at 64 MiB to allow PCI masters
* to continue prefetching past 64 MiB boundary.
*/
crp_write(PCI_CFG_BASE_ADDRESS_4, 0x04000000);
/*
* Enable the IO window to be way up high, at 0xfffffc00
*/
crp_write(PCI_CFG_BASE_ADDRESS_5, 0xfffffc01);
/*Setup PCI-AHB and AHB-PCI address mappings */
writel(0x00010203, PCI_CSR_BASE + PCI_AHBMEMBASE_OFFSET);
writel(0x00000000, PCI_CSR_BASE + PCI_AHBIOBASE_OFFSET);
writel(0x48494a4b, PCI_CSR_BASE + PCI_PCIMEMBASE_OFFSET);
crp_write(PCI_CFG_SUB_VENDOR_ID, IXP425_PCI_SUB_VENDOR_SYSTEM);
crp_write(PCI_CFG_COMMAND, PCI_CFG_CMD_MAE | PCI_CFG_CMD_BME);
udelay(1000);
/* clear error bits in status register */
writel(PCI_ISR_PSE | PCI_ISR_PFE | PCI_ISR_PPE | PCI_ISR_AHBE,
PCI_CSR_BASE + PCI_ISR_OFFSET);
/*
* Set Initialize Complete in PCI Control Register: allow IXP4XX to
* respond to PCI configuration cycles.
*/
csr |= PCI_CSR_IC;
writel(csr, PCI_CSR_BASE + PCI_CSR_OFFSET);
hose->first_busno = 0; hose->first_busno = 0;
hose->last_busno = 0x00; hose->last_busno = 0;
/* System memory space */ /* System memory space */
pci_set_region (hose->regions + 0, pci_set_region(hose->regions + 0,
PCI_MEMORY_BUS, PCI_MEMORY_BUS,
PCI_MEMORY_PHY, PCI_MEMORY_SIZE, PCI_REGION_SYS_MEMORY); PCI_MEMORY_PHY, PCI_MEMORY_SIZE, PCI_REGION_SYS_MEMORY);
/* PCI memory space */ /* PCI memory space */
pci_set_region (hose->regions + 1, pci_set_region(hose->regions + 1,
PCI_MEM_BUS, PCI_MEM_BUS,
PCI_MEM_PHY, PCI_MEM_SIZE, PCI_REGION_MEM); PCI_MEM_PHY, PCI_MEM_SIZE, PCI_REGION_MEM);
/* PCI I/O space */ /* PCI I/O space */
pci_set_region (hose->regions + 2, pci_set_region(hose->regions + 2,
PCI_IO_BUS, PCI_IO_PHY, PCI_IO_SIZE, PCI_REGION_IO); PCI_IO_BUS, PCI_IO_PHY, PCI_IO_SIZE, PCI_REGION_IO);
hose->region_count = 3; hose->region_count = 3;
pci_register_hose (hose); pci_set_ops(hose,
pci_ixp_hose_read_config_byte,
pci_ixp_hose_read_config_word,
pci_ixp_hose_read_config_dword,
pci_ixp_hose_write_config_byte,
pci_ixp_hose_write_config_word,
pci_ixp_hose_write_config_dword);
/* pci_register_hose(hose);
========================================================== hose->last_busno = pci_hose_scan(hose);
Init IXP PCI
==========================================================
*/
REG_READ (PCI_CSR_BASE, PCI_CSR_OFFSET, regval);
regval |= 1 << 2;
REG_WRITE (PCI_CSR_BASE, PCI_CSR_OFFSET, regval);
configure_pins ();
READ_GPIO_REG (IXP425_GPIO_GPOUTR, regval);
WRITE_GPIO_REG (IXP425_GPIO_GPOUTR, regval & (~(1 << 13)));
udelay (533);
sys_pci_gpio_clock_config ();
REG_WRITE (PCI_CSR_BASE, PCI_INTEN_OFFSET, 0);
udelay (100);
READ_GPIO_REG (IXP425_GPIO_GPOUTR, regval);
WRITE_GPIO_REG (IXP425_GPIO_GPOUTR, regval | (1 << 13));
udelay (533);
crp_write (PCI_CFG_BASE_ADDRESS_0, IXP425_PCI_BAR_0_DEFAULT);
crp_write (PCI_CFG_BASE_ADDRESS_1, IXP425_PCI_BAR_1_DEFAULT);
crp_write (PCI_CFG_BASE_ADDRESS_2, IXP425_PCI_BAR_2_DEFAULT);
crp_write (PCI_CFG_BASE_ADDRESS_3, IXP425_PCI_BAR_3_DEFAULT);
crp_write (PCI_CFG_BASE_ADDRESS_4, IXP425_PCI_BAR_4_DEFAULT);
crp_write (PCI_CFG_BASE_ADDRESS_5, IXP425_PCI_BAR_5_DEFAULT);
/*Setup PCI-AHB and AHB-PCI address mappings */
REG_WRITE (PCI_CSR_BASE, PCI_AHBMEMBASE_OFFSET,
IXP425_PCI_AHBMEMBASE_DEFAULT);
REG_WRITE (PCI_CSR_BASE, PCI_AHBIOBASE_OFFSET,
IXP425_PCI_AHBIOBASE_DEFAULT);
REG_WRITE (PCI_CSR_BASE, PCI_PCIMEMBASE_OFFSET,
IXP425_PCI_PCIMEMBASE_DEFAULT);
crp_write (PCI_CFG_SUB_VENDOR_ID, IXP425_PCI_SUB_VENDOR_SYSTEM);
REG_READ (PCI_CSR_BASE, PCI_CSR_OFFSET, regval);
regval |= PCI_CSR_IC | PCI_CSR_ABE | PCI_CSR_PDS;
REG_WRITE (PCI_CSR_BASE, PCI_CSR_OFFSET, regval);
crp_write (PCI_CFG_COMMAND, PCI_CFG_CMD_MAE | PCI_CFG_CMD_BME);
udelay (1000);
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 ();
}
void configure_pins (void)
{
unsigned int regval;
/* Disable clock on GPIO PIN 14 */
READ_GPIO_REG (IXP425_GPIO_GPCLKR, regval);
WRITE_GPIO_REG (IXP425_GPIO_GPCLKR, regval & (~(1 << 8)));
READ_GPIO_REG (IXP425_GPIO_GPCLKR, regval);
READ_GPIO_REG (IXP425_GPIO_GPOER, regval);
WRITE_GPIO_REG (IXP425_GPIO_GPOER,
(((~(3 << 13)) & regval) | (0xf << 8)));
READ_GPIO_REG (IXP425_GPIO_GPOER, regval);
READ_GPIO_REG (IXP425_GPIO_GPIT2R, regval);
WRITE_GPIO_REG (IXP425_GPIO_GPIT2R,
(regval &
((0x1 << 9) | (0x1 << 6) | (0x1 << 3) | 0x1)));
READ_GPIO_REG (IXP425_GPIO_GPIT2R, regval);
READ_GPIO_REG (IXP425_GPIO_GPISR, regval);
WRITE_GPIO_REG (IXP425_GPIO_GPISR, (regval | (0xf << 8)));
READ_GPIO_REG (IXP425_GPIO_GPISR, regval);
}
void sys_pci_gpio_clock_config (void)
{
unsigned int regval;
READ_GPIO_REG (IXP425_GPIO_GPCLKR, regval);
regval |= 0x1 << 4;
WRITE_GPIO_REG (IXP425_GPIO_GPCLKR, regval);
READ_GPIO_REG (IXP425_GPIO_GPCLKR, regval);
regval |= 0x1 << 8;
WRITE_GPIO_REG (IXP425_GPIO_GPCLKR, regval);
}
void pci_bus_scan (void)
{
unsigned int bus = 0, dev, func = 0;
unsigned short data16;
unsigned int data32;
unsigned char intPin;
/* Assign first device to ourselves */
devices[0].bus = 0;
devices[0].device = 0;
devices[0].func = 0;
crp_read (PCI_CFG_VENDOR_ID, &data32);
devices[0].vendor_id = data32 & IXP425_PCI_BOTTOM_WORD_OF_LONG_MASK;
devices[0].device_id = data32 >> 16;
devices[0].error = FALSE;
devices[0].bar[NO_BAR].size = 0; /*dummy - required */
nDevices = 1;
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) {
/*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;
}
/*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);
devices[nDevices].vendor_id = data16;
pci_read_config_word (dev, PCI_CFG_DEVICE_ID, &data16);
devices[nDevices].device_id = data16;
/*The device is functioning correctly, set error to FALSE */
devices[nDevices].error = FALSE;
/*Figure out what BARs are on this device */
sys_pci_bar_info_get (nDevices, bus, dev, func);
/*Figure out what INTX# line the card uses */
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;
}
#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);
sys_pci_device_bars_write ();
REG_WRITE (PCI_CSR_BASE, PCI_ISR_OFFSET, PCI_ISR_PSE
| 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)
{
unsigned int data32;
unsigned int tmp;
unsigned int size;
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) {
/* IO space */
tmp = data32 & ~0x3;
size = ~(tmp - 1);
devices[devnum].bar[0].size = size;
if (nIOBars < IXP425_PCI_MAX_BAR) {
ioBars[nIOBars++] = &devices[devnum].bar[0];
}
} else {
/* Mem space */
tmp = data32 & ~IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK;
size = ~(tmp - 1);
devices[devnum].bar[0].size = size;
if (nMBars < IXP425_PCI_MAX_BAR) {
memBars[nMBars++] = &devices[devnum].bar[0];
} else {
devices[devnum].error = TRUE;
}
}
devices[devnum].bar[1].size = 0;
}
void sortBars (PciBar * Bars[], unsigned int nBars)
{
unsigned int i, j;
PciBar *tmp;
if (nBars == 0) {
return;
}
/* Sort biggest to smallest */
for (i = 0; i < nBars - 1; i++) {
for (j = i + 1; j < nBars; j++) {
if (Bars[j]->size > Bars[i]->size) {
/* swap them */
tmp = Bars[i];
Bars[i] = Bars[j];
Bars[j] = tmp;
}
}
}
}
void calc_bars (PciBar * Bars[], unsigned int nBars, unsigned int startAddr)
{
unsigned int i;
if (nBars == 0) {
return;
}
for (i = 0; i < nBars; i++) {
Bars[i]->address |= startAddr;
startAddr += Bars[i]->size;
}
}
void sys_pci_device_bars_write (void)
{
unsigned int i;
int addr;
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,
PCI_CFG_DEV_INT_LINE, devices[i].irq);
pci_write_config_word (devices[i].device,
PCI_CFG_COMMAND, INITIAL_PCI_CMD);
}
}
int pci_device_exists (unsigned int deviceNo)
{
unsigned int vendorId;
unsigned int regval;
pci_read_config_dword (deviceNo, PCI_CFG_VENDOR_ID, &vendorId);
/* 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)) {
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;
}
pci_dev_t pci_find_devices (struct pci_device_id * ids, int devNo)
{
unsigned int i;
unsigned int devdidvid;
unsigned int didvid;
unsigned int vendorId, deviceId;
vendorId = ids->vendor;
deviceId = ids->device;
didvid = ((deviceId << 16) & IXP425_PCI_TOP_WORD_OF_LONG_MASK) |
(vendorId & IXP425_PCI_BOTTOM_WORD_OF_LONG_MASK);
for (i = devNo + 1; i < nDevices; i++) {
pci_read_config_dword (devices[i].device, PCI_CFG_VENDOR_ID,
&devdidvid);
if (devdidvid == didvid) {
return devices[i].device;
}
}
return -1;
} }