Commit 1a6407d9 authored by Russell King's avatar Russell King

[ARM] Update PCI host bridge drivers for GregKH PCI cleanups.

parent 5097d470
...@@ -34,9 +34,9 @@ ...@@ -34,9 +34,9 @@
#define PLX_SET_CONFIG \ #define PLX_SET_CONFIG \
{ unsigned long flags; \ { unsigned long flags; \
local_irq_save(flags); \ local_irq_save(flags); \
__raw_writel((1<<31 | (dev->bus->number << 16) \ __raw_writel((1<<31 | (bus->number << 16) \
| (dev->devfn << 8) | (where & ~3) \ | (devfn << 8) | (where & ~3) \
| ((dev->bus->number == 0)?0:1)), PLX_BASE + 0xac); \ | ((bus->number == 0)?0:1)), PLX_BASE + 0xac); \
#define PLX_CONFIG_WRITE(size) \ #define PLX_CONFIG_WRITE(size) \
PLX_SET_CONFIG \ PLX_SET_CONFIG \
...@@ -58,47 +58,47 @@ ...@@ -58,47 +58,47 @@
/* Configuration space access routines */ /* Configuration space access routines */
static int
plx90x0_read_config_byte (struct pci_dev *dev,
int where, u8 *value)
{
PLX_CONFIG_READ(b)
}
static int
plx90x0_read_config_word (struct pci_dev *dev,
int where, u16 *value)
{
PLX_CONFIG_READ(w)
}
static int static int
plx90x0_read_config_dword (struct pci_dev *dev, plx90x0_read_config (struct pci_bus *bus, unsigned int devfn, int where,
int where, u32 *value) int where, int size, u32 *value)
{ {
PLX_CONFIG_READ(l) switch (size) {
} case 1:
PLX_CONFIG_READ(b)
static int break;
plx90x0_write_config_byte (struct pci_dev *dev, case 2:
int where, u8 value) PLX_CONFIG_READ(w)
{ break;
PLX_CONFIG_WRITE(b) case 4:
PLX_CONFIG_READ(l)
break;
}
return PCIBIOS_SUCCESSFUL;
} }
static int static int
plx90x0_write_config_word (struct pci_dev *dev, plx90x0_write_config (struct pci_bus *bus, unsigned int devfn, int where,
int where, u16 value) int where, int size, u32 value)
{ {
PLX_CONFIG_WRITE(w) switch (size) {
case 1:
PLX_CONFIG_WRITE(b)
break;
case 2:
PLX_CONFIG_WRITE(w)
break;
case 4:
PLX_CONFIG_WRITE(l)
break;
}
return PCIBIOS_SUCCESSFUL;
} }
static int static struct pci_ops plx90x0_ops =
plx90x0_write_config_dword (struct pci_dev *dev,
int where, u32 value)
{ {
PLX_CONFIG_WRITE(l) .read = plx90x0_read_config,
} .write = plx90x0_write_config,
};
static void static void
plx_syserr_handler(int irq, void *handle, struct pt_regs *regs) plx_syserr_handler(int irq, void *handle, struct pt_regs *regs)
...@@ -108,17 +108,6 @@ plx_syserr_handler(int irq, void *handle, struct pt_regs *regs) ...@@ -108,17 +108,6 @@ plx_syserr_handler(int irq, void *handle, struct pt_regs *regs)
__raw_writew(0xf000, PLX_BASE + 6); __raw_writew(0xf000, PLX_BASE + 6);
} }
static struct pci_ops
plx90x0_ops =
{
plx90x0_read_config_byte,
plx90x0_read_config_word,
plx90x0_read_config_dword,
plx90x0_write_config_byte,
plx90x0_write_config_word,
plx90x0_write_config_dword,
};
/* /*
* Initialise the PCI system. * Initialise the PCI system.
*/ */
......
...@@ -15,63 +15,49 @@ ...@@ -15,63 +15,49 @@
#define MAX_SLOTS 7 #define MAX_SLOTS 7
#define CONFIG_CMD(dev, where) (0x80000000 | (dev->bus->number << 16) | (dev->devfn << 8) | (where & ~3)) #define CONFIG_CMD(bus, devfn, where) (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
static int static int
via82c505_read_config_byte(struct pci_dev *dev, int where, u8 *value) via82c505_read_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 *value)
{ {
outl(CONFIG_CMD(dev,where),0xCF8); outl(CONFIG_CMD(dev,where),0xCF8);
*value=inb(0xCFC + (where&3)); switch (size) {
return PCIBIOS_SUCCESSFUL; case 1:
} *value=inb(0xCFC + (where&3));
break;
static int case 2:
via82c505_read_config_word(struct pci_dev *dev, int where, u16 *value) *value=inw(0xCFC + (where&2));
{ break;
outl(CONFIG_CMD(dev,where),0xCF8); case 4:
*value=inw(0xCFC + (where&2)); *value=inl(0xCFC);
return PCIBIOS_SUCCESSFUL; break;
} }
static int
via82c505_read_config_dword(struct pci_dev *dev, int where, u32 *value)
{
outl(CONFIG_CMD(dev,where),0xCF8);
*value=inl(0xCFC);
return PCIBIOS_SUCCESSFUL;
}
static int
via82c505_write_config_byte(struct pci_dev *dev, int where, u8 value)
{
outl(CONFIG_CMD(dev,where),0xCF8);
outb(value, 0xCFC + (where&3));
return PCIBIOS_SUCCESSFUL;
}
static int
via82c505_write_config_word(struct pci_dev *dev, int where, u16 value)
{
outl(CONFIG_CMD(dev,where),0xCF8);
outw(value, 0xCFC + (where&2));
return PCIBIOS_SUCCESSFUL; return PCIBIOS_SUCCESSFUL;
} }
static int static int
via82c505_write_config_dword(struct pci_dev *dev, int where, u32 value) via82c505_write_config(struct pci_bus *bus, unsigned int devfn, int where
int size, u32 value)
{ {
outl(CONFIG_CMD(dev,where),0xCF8); outl(CONFIG_CMD(bus,devfn,where),0xCF8);
outl(value, 0xCFC); switch (size) {
case 1:
outb(value, 0xCFC + (where&3));
break;
case 2:
outw(value, 0xCFC + (where&2));
break;
case 4:
outl(value, 0xCFC);
break;
}
return PCIBIOS_SUCCESSFUL; return PCIBIOS_SUCCESSFUL;
} }
static struct pci_ops via82c505_ops = { static struct pci_ops via82c505_ops = {
via82c505_read_config_byte, .read = via82c505_read_config,
via82c505_read_config_word, .write = via82c505_write_config,
via82c505_read_config_dword,
via82c505_write_config_byte,
via82c505_write_config_word,
via82c505_write_config_dword,
}; };
void __init via82c505_preinit(void *sysdata) void __init via82c505_preinit(void *sysdata)
......
...@@ -36,12 +36,11 @@ extern void pcibios_report_status(u_int status_mask, int warn); ...@@ -36,12 +36,11 @@ extern void pcibios_report_status(u_int status_mask, int warn);
extern void register_isa_ports(unsigned int, unsigned int, unsigned int); extern void register_isa_ports(unsigned int, unsigned int, unsigned int);
static unsigned long static unsigned long
dc21285_base_address(struct pci_dev *dev) dc21285_base_address(struct pci_bus *bus, unsigned int devfn)
{ {
unsigned long addr = 0; unsigned long addr = 0;
unsigned int devfn = dev->devfn;
if (dev->bus->number == 0) { if (bus->number == 0) {
if (PCI_SLOT(devfn) == 0) if (PCI_SLOT(devfn) == 0)
/* /*
* For devfn 0, point at the 21285 * For devfn 0, point at the 21285
...@@ -54,54 +53,33 @@ dc21285_base_address(struct pci_dev *dev) ...@@ -54,54 +53,33 @@ dc21285_base_address(struct pci_dev *dev)
addr = PCICFG0_BASE | 0xc00000 | (devfn << 8); addr = PCICFG0_BASE | 0xc00000 | (devfn << 8);
} }
} else } else
addr = PCICFG1_BASE | (dev->bus->number << 16) | (devfn << 8); addr = PCICFG1_BASE | (bus->number << 16) | (devfn << 8);
return addr; return addr;
} }
static int static int
dc21285_read_config_byte(struct pci_dev *dev, int where, u8 *value) dc21285_read_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 *value)
{ {
unsigned long addr = dc21285_base_address(dev); unsigned long addr = dc21285_base_address(bus, devfn);
u8 v;
if (addr)
asm("ldr%?b %0, [%1, %2]"
: "=r" (v) : "r" (addr), "r" (where));
else
v = 0xff;
*value = v;
return PCIBIOS_SUCCESSFUL;
}
static int
dc21285_read_config_word(struct pci_dev *dev, int where, u16 *value)
{
unsigned long addr = dc21285_base_address(dev);
u16 v;
if (addr)
asm("ldr%?h %0, [%1, %2]"
: "=r" (v) : "r" (addr), "r" (where));
else
v = 0xffff;
*value = v;
return PCIBIOS_SUCCESSFUL;
}
static int
dc21285_read_config_dword(struct pci_dev *dev, int where, u32 *value)
{
unsigned long addr = dc21285_base_address(dev);
u32 v; u32 v;
if (addr) if (addr)
asm("ldr%? %0, [%1, %2]" switch (size) {
: "=r" (v) : "r" (addr), "r" (where)); case 1:
asm("ldr%?b %0, [%1, %2]"
: "=r" (v) : "r" (addr), "r" (where));
break;
case 2:
asm("ldr%?h %0, [%1, %2]"
: "=r" (v) : "r" (addr), "r" (where));
break;
case 4:
asm("ldr%? %0, [%1, %2]"
: "=r" (v) : "r" (addr), "r" (where));
break;
}
else else
v = 0xffffffff; v = 0xffffffff;
...@@ -111,48 +89,33 @@ dc21285_read_config_dword(struct pci_dev *dev, int where, u32 *value) ...@@ -111,48 +89,33 @@ dc21285_read_config_dword(struct pci_dev *dev, int where, u32 *value)
} }
static int static int
dc21285_write_config_byte(struct pci_dev *dev, int where, u8 value) dc21285_write_config(struct pci_bus *bus, unsigned int devfn, int where,
{ int size, u32 value)
unsigned long addr = dc21285_base_address(dev);
if (addr)
asm("str%?b %0, [%1, %2]"
: : "r" (value), "r" (addr), "r" (where));
return PCIBIOS_SUCCESSFUL;
}
static int
dc21285_write_config_word(struct pci_dev *dev, int where, u16 value)
{
unsigned long addr = dc21285_base_address(dev);
if (addr)
asm("str%?h %0, [%1, %2]"
: : "r" (value), "r" (addr), "r" (where));
return PCIBIOS_SUCCESSFUL;
}
static int
dc21285_write_config_dword(struct pci_dev *dev, int where, u32 value)
{ {
unsigned long addr = dc21285_base_address(dev); unsigned long addr = dc21285_base_address(bus, devfn);
if (addr) if (addr)
asm("str%? %0, [%1, %2]" switch (size) {
: : "r" (value), "r" (addr), "r" (where)); case 1:
asm("str%?b %0, [%1, %2]"
: : "r" (value), "r" (addr), "r" (where));
break;
case 2:
asm("str%?h %0, [%1, %2]"
: : "r" (value), "r" (addr), "r" (where));
break;
case 4:
asm("str%? %0, [%1, %2]"
: : "r" (value), "r" (addr), "r" (where));
break;
}
return PCIBIOS_SUCCESSFUL; return PCIBIOS_SUCCESSFUL;
} }
static struct pci_ops dc21285_ops = { static struct pci_ops dc21285_ops = {
dc21285_read_config_byte, .read = dc21285_read_config,
dc21285_read_config_word, .write = dc21285_write_config,
dc21285_read_config_dword,
dc21285_write_config_byte,
dc21285_write_config_word,
dc21285_write_config_dword,
}; };
static struct timer_list serr_timer; static struct timer_list serr_timer;
......
...@@ -181,11 +181,12 @@ static spinlock_t v3_lock = SPIN_LOCK_UNLOCKED; ...@@ -181,11 +181,12 @@ static spinlock_t v3_lock = SPIN_LOCK_UNLOCKED;
#undef V3_LB_BASE_PREFETCH #undef V3_LB_BASE_PREFETCH
#define V3_LB_BASE_PREFETCH 0 #define V3_LB_BASE_PREFETCH 0
static unsigned long v3_open_config_window(struct pci_dev *dev, int offset) static unsigned long v3_open_config_window(struct pci_bus *bus,
unsigned int devfn, int offset)
{ {
unsigned int address, mapaddress, busnr; unsigned int address, mapaddress, busnr;
busnr = dev->bus->number; busnr = bus->number;
/* /*
* Trap out illegal values * Trap out illegal values
...@@ -194,11 +195,11 @@ static unsigned long v3_open_config_window(struct pci_dev *dev, int offset) ...@@ -194,11 +195,11 @@ static unsigned long v3_open_config_window(struct pci_dev *dev, int offset)
BUG(); BUG();
if (busnr > 255) if (busnr > 255)
BUG(); BUG();
if (dev->devfn > 255) if (devfn > 255)
BUG(); BUG();
if (busnr == 0) { if (busnr == 0) {
int slot = PCI_SLOT(dev->devfn); int slot = PCI_SLOT(devfn);
/* /*
* local bus segment so need a type 0 config cycle * local bus segment so need a type 0 config cycle
...@@ -210,7 +211,7 @@ static unsigned long v3_open_config_window(struct pci_dev *dev, int offset) ...@@ -210,7 +211,7 @@ static unsigned long v3_open_config_window(struct pci_dev *dev, int offset)
* 3:1 = config cycle (101) * 3:1 = config cycle (101)
* 0 = PCI A1 & A0 are 0 (0) * 0 = PCI A1 & A0 are 0 (0)
*/ */
address = PCI_FUNC(dev->devfn) << 8; address = PCI_FUNC(devfn) << 8;
mapaddress = V3_LB_MAP_TYPE_CONFIG; mapaddress = V3_LB_MAP_TYPE_CONFIG;
if (slot > 12) if (slot > 12)
...@@ -237,7 +238,7 @@ static unsigned long v3_open_config_window(struct pci_dev *dev, int offset) ...@@ -237,7 +238,7 @@ static unsigned long v3_open_config_window(struct pci_dev *dev, int offset)
* 0 = PCI A1 & A0 from host bus (1) * 0 = PCI A1 & A0 from host bus (1)
*/ */
mapaddress = V3_LB_MAP_TYPE_CONFIG | V3_LB_MAP_AD_LOW_EN; mapaddress = V3_LB_MAP_TYPE_CONFIG | V3_LB_MAP_AD_LOW_EN;
address = (busnr << 16) | (dev->devfn << 8); address = (busnr << 16) | (devfn << 8);
} }
/* /*
...@@ -276,104 +277,62 @@ static void v3_close_config_window(void) ...@@ -276,104 +277,62 @@ static void v3_close_config_window(void)
V3_LB_BASE_ADR_SIZE_256MB | V3_LB_BASE_ENABLE); V3_LB_BASE_ADR_SIZE_256MB | V3_LB_BASE_ENABLE);
} }
static int v3_read_config_byte(struct pci_dev *dev, int where, u8 *val) static int v3_read_config(struct pci_bus *bus, unsigned int devfn, int where,
{ int size, u32 *val)
unsigned long addr;
unsigned long flags;
u8 v;
spin_lock_irqsave(&v3_lock, flags);
addr = v3_open_config_window(dev, where);
v = __raw_readb(addr);
v3_close_config_window();
spin_unlock_irqrestore(&v3_lock, flags);
*val = v;
return PCIBIOS_SUCCESSFUL;
}
static int v3_read_config_word(struct pci_dev *dev, int where, u16 *val)
{
unsigned long addr;
unsigned long flags;
u16 v;
spin_lock_irqsave(&v3_lock, flags);
addr = v3_open_config_window(dev, where);
v = __raw_readw(addr);
v3_close_config_window();
spin_unlock_irqrestore(&v3_lock, flags);
*val = v;
return PCIBIOS_SUCCESSFUL;
}
static int v3_read_config_dword(struct pci_dev *dev, int where, u32 *val)
{ {
unsigned long addr; unsigned long addr;
unsigned long flags; unsigned long flags;
u32 v; u32 v;
spin_lock_irqsave(&v3_lock, flags); spin_lock_irqsave(&v3_lock, flags);
addr = v3_open_config_window(dev, where); addr = v3_open_config_window(bus, devfn, where);
v = __raw_readl(addr); switch (size) {
case 1:
v = __raw_readb(addr);
break;
v3_close_config_window(); case 2:
spin_unlock_irqrestore(&v3_lock, flags); v = __raw_readw(addr);
break;
*val = v;
return PCIBIOS_SUCCESSFUL;
}
static int v3_write_config_byte(struct pci_dev *dev, int where, u8 val)
{
unsigned long addr;
unsigned long flags;
spin_lock_irqsave(&v3_lock, flags);
addr = v3_open_config_window(dev, where);
__raw_writeb(val, addr);
__raw_readb(addr);
v3_close_config_window();
spin_unlock_irqrestore(&v3_lock, flags);
return PCIBIOS_SUCCESSFUL;
}
static int v3_write_config_word(struct pci_dev *dev, int where, u16 val)
{
unsigned long addr;
unsigned long flags;
spin_lock_irqsave(&v3_lock, flags);
addr = v3_open_config_window(dev, where);
__raw_writew(val, addr); case 4:
__raw_readw(addr); v = __raw_readl(addr);
break;
}
v3_close_config_window(); v3_close_config_window();
spin_unlock_irqrestore(&v3_lock, flags); spin_unlock_irqrestore(&v3_lock, flags);
*val = v;
return PCIBIOS_SUCCESSFUL; return PCIBIOS_SUCCESSFUL;
} }
static int v3_write_config_dword(struct pci_dev *dev, int where, u32 val) static int v3_write_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 val)
{ {
unsigned long addr; unsigned long addr;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&v3_lock, flags); spin_lock_irqsave(&v3_lock, flags);
addr = v3_open_config_window(dev, where); addr = v3_open_config_window(bus, devfn, where);
__raw_writel(val, addr); switch (size) {
__raw_readl(addr); case 1:
__raw_writeb((u8)val, addr);
__raw_readb(addr);
break;
case 2:
__raw_writew((u16)val, addr);
__raw_readw(addr);
break;
case 4:
__raw_writel(val, addr);
__raw_readl(addr);
break;
}
v3_close_config_window(); v3_close_config_window();
spin_unlock_irqrestore(&v3_lock, flags); spin_unlock_irqrestore(&v3_lock, flags);
...@@ -382,12 +341,8 @@ static int v3_write_config_dword(struct pci_dev *dev, int where, u32 val) ...@@ -382,12 +341,8 @@ static int v3_write_config_dword(struct pci_dev *dev, int where, u32 val)
} }
static struct pci_ops pci_v3_ops = { static struct pci_ops pci_v3_ops = {
.read_byte = v3_read_config_byte, .read = v3_read_config,
.read_word = v3_read_config_word, .write = v3_write_config,
.read_dword = v3_read_config_dword,
.write_byte = v3_write_config_byte,
.write_word = v3_write_config_word,
.write_dword = v3_write_config_dword,
}; };
static struct resource non_mem = { static struct resource non_mem = {
......
...@@ -55,22 +55,23 @@ ...@@ -55,22 +55,23 @@
#define DBG(x...) do { } while (0) #define DBG(x...) do { } while (0)
#endif #endif
extern int (*external_fault)(unsigned long, struct pt_regs *); /*
* Calculate the address, etc from the bus, devfn and register
static u32 iop310_cfg_address(struct pci_dev *dev, int where) * offset. Note that we have two root buses, so we need some
* method to determine whether we need config type 0 or 1 cycles.
* We use a root bus number in our bus->sysdata structure for this.
*/
static u32 iop310_cfg_address(struct pci_bus *bus, int devfn, int where)
{ {
struct pci_sys_data *sys = dev->sysdata; struct pci_sys_data *sys = bus->sysdata;
u32 addr; u32 addr;
where &= ~3; if (sys->busnr == bus->number)
addr = 1 << (PCI_SLOT(devfn) + 16);
if (sys->busnr == dev->bus->number)
addr = 1 << (PCI_SLOT(dev->devfn) + 16);
else else
addr = dev->bus->number << 16 | addr = bus->number << 16 | PCI_SLOT(devfn) << 11 | 1;
PCI_SLOT(dev->devfn) << 11 | 1;
addr |= PCI_FUNC(dev->devfn) << 8 | where; addr |= PCI_FUNC(devfn) << 8 | (where & ~3);
return addr; return addr;
} }
...@@ -106,9 +107,13 @@ static int iop310_pri_pci_status(void) ...@@ -106,9 +107,13 @@ static int iop310_pri_pci_status(void)
return ret; return ret;
} }
static inline u32 iop310_pri_read(struct pci_dev *dev, int where) /*
* Simply write the address register and read the configuration
* data. Note that the 4 nop's ensure that we are able to handle
* a delayed abort (in theory.)
*/
static inline u32 iop310_pri_read(unsigned long addr)
{ {
unsigned long addr = iop310_cfg_address(dev, where);
u32 val; u32 val;
__asm__ __volatile__( __asm__ __volatile__(
...@@ -125,111 +130,59 @@ static inline u32 iop310_pri_read(struct pci_dev *dev, int where) ...@@ -125,111 +130,59 @@ static inline u32 iop310_pri_read(struct pci_dev *dev, int where)
} }
static int static int
iop310_pri_rd_cfg_byte(struct pci_dev *dev, int where, u8 *p) iop310_pri_read_config(struct pci_bus *bus, unsigned int devfn, int where,
{ int size, u32 *value)
u8 val;
val = iop310_pri_read(dev, where) >> ((where & 3) * 8);
if (iop310_pri_pci_status())
val = 0xff;
*p = val;
return PCIBIOS_SUCCESSFUL;
}
static int
iop310_pri_rd_cfg_word(struct pci_dev *dev, int where, u16 *p)
{
u16 val;
val = iop310_pri_read(dev, where) >> ((where & 3) * 8);
if (iop310_pri_pci_status())
val = 0xffff;
*p = val;
return PCIBIOS_SUCCESSFUL;
}
static int
iop310_pri_rd_cfg_dword(struct pci_dev *dev, int where, u32 *p)
{ {
u32 val; unsigned long addr = iop310_cfg_address(bus, devfn, where);
u32 val = iop310_pri_read(addr) >> ((where & 3) * 8);
val = iop310_pri_read(dev, where);
if (iop310_pri_pci_status()) if (iop310_pri_pci_status())
val = 0xffffffff; val = 0xffffffff;
*p = val; *value = val;
return PCIBIOS_SUCCESSFUL; return PCIBIOS_SUCCESSFUL;
} }
static int static int
iop310_pri_wr_cfg_byte(struct pci_dev *dev, int where, u8 v) iop310_pri_write_config(struct pci_bus *bus, unsigned int devfn, int where
int size, u32 value)
{ {
unsigned long addr = iop310_cfg_address(bus, devfn, where);
u32 val; u32 val;
val = iop310_pri_read(dev, where); if (size != 4) {
val = iop310_pri_read(addr);
if (!iop310_pri_pci_status() == 0)
return PCIBIOS_SUCCESSFUL;
if (iop310_pri_pci_status() == 0) {
where = (where & 3) * 8; where = (where & 3) * 8;
val &= ~(0xff << where);
val |= v << where;
*IOP310_POCCDR = val;
}
return PCIBIOS_SUCCESSFUL;
}
static int if (size == 1)
iop310_pri_wr_cfg_word(struct pci_dev *dev, int where, u16 v) val &= ~(0xff << where);
{ else
u32 val; val &= ~(0xffff << where);
val = iop310_pri_read(dev, where); *IOP310_POCCDR = val | v << where;
} else {
if (iop310_pri_pci_status() == 0) { asm volatile(
where = (where & 2) * 8; "str %1, [%2]\n\t"
val &= ~(0xffff << where); "str %0, [%3]\n\t"
val |= v << where; "nop\n\t"
*IOP310_POCCDR = val; "nop\n\t"
"nop\n\t"
"nop\n\t"
:
: "r" (val), "r" (addr),
"r" (IOP310_POCCAR), "r" (IOP310_POCCDR));
} }
return PCIBIOS_SUCCESSFUL; return PCIBIOS_SUCCESSFUL;
} }
static int
iop310_pri_wr_cfg_dword(struct pci_dev *dev, int where, u32 val)
{
unsigned long addr;
addr = iop310_cfg_address(dev, where);
__asm__ __volatile__(
"str %1, [%2]\n\t"
"str %0, [%3]\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
:
: "r" (val), "r" (addr), "r" (IOP310_POCCAR), "r" (IOP310_POCCDR));
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops iop310_primary_ops = { static struct pci_ops iop310_primary_ops = {
iop310_pri_rd_cfg_byte, .read = iop310_pri_read_config,
iop310_pri_rd_cfg_word, .write = iop310_pri_write_config,
iop310_pri_rd_cfg_dword,
iop310_pri_wr_cfg_byte,
iop310_pri_wr_cfg_word,
iop310_pri_wr_cfg_dword,
}; };
/* /*
...@@ -255,9 +208,13 @@ static int iop310_sec_pci_status(void) ...@@ -255,9 +208,13 @@ static int iop310_sec_pci_status(void)
return ret; return ret;
} }
static inline u32 iop310_sec_read(struct pci_dev *dev, int where) /*
* Simply write the address register and read the configuration
* data. Note that the 4 nop's ensure that we are able to handle
* a delayed abort (in theory.)
*/
static inline u32 iop310_sec_read(unsigned long addr)
{ {
unsigned long addr = iop310_cfg_address(dev, where);
u32 val; u32 val;
__asm__ __volatile__( __asm__ __volatile__(
...@@ -274,111 +231,60 @@ static inline u32 iop310_sec_read(struct pci_dev *dev, int where) ...@@ -274,111 +231,60 @@ static inline u32 iop310_sec_read(struct pci_dev *dev, int where)
} }
static int static int
iop310_sec_rd_cfg_byte(struct pci_dev *dev, int where, u8 *p) iop310_sec_read_config(struct pci_bus *bus, unsigned int devfn, int where,
{ int size, u32 *value)
u8 val;
val = iop310_sec_read(dev, where) >> ((where & 3) * 8);
if (iop310_sec_pci_status())
val = 0xff;
*p = val;
return PCIBIOS_SUCCESSFUL;
}
static int
iop310_sec_rd_cfg_word(struct pci_dev *dev, int where, u16 *p)
{ {
u16 val; unsigned long addr = iop310_cfg_address(bus, devfn, where);
u32 val = iop310_sec_read(addr) >> ((where & 3) * 8);
val = iop310_sec_read(dev, where) >> ((where & 3) * 8);
if (iop310_sec_pci_status())
val = 0xffff;
*p = val;
return PCIBIOS_SUCCESSFUL;
}
static int
iop310_sec_rd_cfg_dword(struct pci_dev *dev, int where, u32 *p)
{
u32 val;
val = iop310_sec_read(dev, where);
if (iop310_sec_pci_status()) if (iop310_sec_pci_status())
val = 0xffffffff; val = 0xffffffff;
*p = val; *value = val;
return PCIBIOS_SUCCESSFUL; return PCIBIOS_SUCCESSFUL;
} }
static int static int
iop310_sec_wr_cfg_byte(struct pci_dev *dev, int where, u8 v) iop310_sec_write_config(struct pci_bus *bus, unsigned int devfn, int where
int size, u32 value)
{ {
unsigned long addr = iop310_cfg_address(bus, devfn, where);
u32 val; u32 val;
val = iop310_sec_read(dev, where); if (size != 4) {
val = iop310_sec_read(addr);
if (iop310_sec_pci_status() == 0) { if (!iop310_sec_pci_status() == 0)
where = (where & 3) * 8; return PCIBIOS_SUCCESSFUL;
val &= ~(0xff << where);
val |= v << where;
*IOP310_SOCCDR = val;
}
return PCIBIOS_SUCCESSFUL;
}
static int
iop310_sec_wr_cfg_word(struct pci_dev *dev, int where, u16 v)
{
u32 val;
val = iop310_sec_read(dev, where); where = (where & 3) * 8;
if (iop310_sec_pci_status() == 0) { if (size == 1)
where = (where & 2) * 8; val &= ~(0xff << where);
val &= ~(0xffff << where); else
val |= v << where; val &= ~(0xffff << where);
*IOP310_SOCCDR = val;
*IOP310_SOCCDR = val | v << where;
} else {
asm volatile(
"str %1, [%2]\n\t"
"str %0, [%3]\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
:
: "r" (val), "r" (addr),
"r" (IOP310_SOCCAR), "r" (IOP310_SOCCDR));
} }
return PCIBIOS_SUCCESSFUL; return PCIBIOS_SUCCESSFUL;
} }
static int
iop310_sec_wr_cfg_dword(struct pci_dev *dev, int where, u32 val)
{
unsigned long addr;
addr = iop310_cfg_address(dev, where);
__asm__ __volatile__(
"str %1, [%2]\n\t"
"str %0, [%3]\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
:
: "r" (val), "r" (addr), "r" (IOP310_SOCCAR), "r" (IOP310_SOCCDR));
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops iop310_secondary_ops = { static struct pci_ops iop310_secondary_ops = {
iop310_sec_rd_cfg_byte, .read = iop310_sec_read_config,
iop310_sec_rd_cfg_word, .write = iop310_sec_write_config,
iop310_sec_rd_cfg_dword,
iop310_sec_wr_cfg_byte,
iop310_sec_wr_cfg_word,
iop310_sec_wr_cfg_dword,
}; };
/* /*
...@@ -524,5 +430,5 @@ void iop310_init(void) ...@@ -524,5 +430,5 @@ void iop310_init(void)
*/ */
*IOP310_PCR &= 0xfff8; *IOP310_PCR &= 0xfff8;
hook_fault_code(6, iop310_pci_abort, SIGBUS, "imprecise external abort"); hook_fault_code(16+6, iop310_pci_abort, SIGBUS, "imprecise external abort");
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment