Commit 2f766895 authored by Paul Mackerras's avatar Paul Mackerras

PPC32: Convert the various PCI config space accessors to the new API.

parent bd039e05
......@@ -60,7 +60,7 @@ obj-$(CONFIG_ADIR) += i8259.o indirect_pci.o pci_auto.o \
todc_time.o
obj-$(CONFIG_EV64260) += gt64260_common.o gt64260_pic.o \
indirect_pci.o todc_time.o pci_auto.o
obj-$(CONFIG_GEMINI) += open_pic.o i8259.o
obj-$(CONFIG_GEMINI) += open_pic.o i8259.o indirect_pci.o
obj-$(CONFIG_K2) += i8259.o indirect_pci.o todc_time.o \
pci_auto.o
obj-$(CONFIG_LOPEC) += mpc10x_common.o indirect_pci.o pci_auto.o \
......
......@@ -24,48 +24,88 @@
#include <asm/pci-bridge.h>
#include <asm/machdep.h>
#define cfg_read(val, addr, type, op) *val = op((type)(addr))
#define cfg_write(val, addr, type, op) op((type *)(addr), (val))
static int
indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
int len, u32 *val)
{
struct pci_controller *hose = bus->sysdata;
volatile unsigned char *cfg_data;
if (ppc_md.pci_exclude_device)
if (ppc_md.pci_exclude_device(bus->number, devfn))
return PCIBIOS_DEVICE_NOT_FOUND;
#define INDIRECT_PCI_OP(rw, size, type, op, mask) \
static int \
indirect_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \
{ \
struct pci_controller *hose = dev->sysdata; \
\
if (ppc_md.pci_exclude_device) \
if (ppc_md.pci_exclude_device(dev->bus->number, dev->devfn)) \
return PCIBIOS_DEVICE_NOT_FOUND; \
\
out_be32(hose->cfg_addr, \
((offset & 0xfc) << 24) | (dev->devfn << 16) \
| ((dev->bus->number - hose->bus_offset) << 8) | 0x80); \
cfg_##rw(val, hose->cfg_data + (offset & mask), type, op); \
return PCIBIOS_SUCCESSFUL; \
out_be32(hose->cfg_addr,
((offset & 0xfc) << 24) | (devfn << 16)
| ((bus->number - hose->bus_offset) << 8) | 0x80);
/*
* Note: the caller has already checked that offset is
* suitably aligned and that len is 1, 2 or 4.
*/
cfg_data = hose->cfg_data + (offset & 3);
switch (len) {
case 1:
*val = in_8((u8 *)cfg_data);
break;
case 2:
*val = in_le16((u16 *)cfg_data);
break;
default:
*val = in_le32((u32 *)cfg_data);
break;
}
return PCIBIOS_SUCCESSFUL;
}
INDIRECT_PCI_OP(read, byte, u8 *, in_8, 3)
INDIRECT_PCI_OP(read, word, u16 *, in_le16, 2)
INDIRECT_PCI_OP(read, dword, u32 *, in_le32, 0)
INDIRECT_PCI_OP(write, byte, u8, out_8, 3)
INDIRECT_PCI_OP(write, word, u16, out_le16, 2)
INDIRECT_PCI_OP(write, dword, u32, out_le32, 0)
static int
indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
int len, u32 val)
{
struct pci_controller *hose = bus->sysdata;
volatile unsigned char *cfg_data;
if (ppc_md.pci_exclude_device)
if (ppc_md.pci_exclude_device(bus->number, devfn))
return PCIBIOS_DEVICE_NOT_FOUND;
out_be32(hose->cfg_addr,
((offset & 0xfc) << 24) | (devfn << 16)
| ((bus->number - hose->bus_offset) << 8) | 0x80);
/*
* Note: the caller has already checked that offset is
* suitably aligned and that len is 1, 2 or 4.
*/
cfg_data = hose->cfg_data + (offset & 3);
switch (len) {
case 1:
out_8((u8 *)cfg_data, val);
break;
case 2:
out_le16((u16 *)cfg_data, val);
break;
default:
out_le32((u32 *)cfg_data, val);
break;
}
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops indirect_pci_ops =
{
indirect_read_config_byte,
indirect_read_config_word,
indirect_read_config_dword,
indirect_write_config_byte,
indirect_write_config_word,
indirect_write_config_dword
indirect_read_config,
indirect_write_config
};
void __init
setup_indirect_pci(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
{
unsigned long base = cfg_addr & PAGE_MASK;
char *mbase;
mbase = ioremap(base, PAGE_SIZE);
hose->cfg_addr = (unsigned int *)(mbase + (cfg_addr & ~PAGE_MASK));
if ((cfg_data & PAGE_MASK) != base)
mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE);
hose->cfg_data = (unsigned char *)(mbase + (cfg_data & ~PAGE_MASK));
hose->ops = &indirect_pci_ops;
hose->cfg_addr = (unsigned int *) ioremap(cfg_addr, 4);
hose->cfg_data = (unsigned char *) ioremap(cfg_data, 4);
}
......@@ -816,19 +816,19 @@ scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn)
/*
* Scans the OF tree for a device node matching a PCI device
*/
struct device_node*
pci_device_to_OF_node(struct pci_dev *dev)
struct device_node *
pci_busdev_to_OF_node(struct pci_bus *bus, int devfn)
{
struct pci_controller *hose;
struct device_node *node;
int bus;
int busnr;
if (!have_of)
return NULL;
/* Lookup the hose */
bus = dev->bus->number;
hose = pci_bus_to_hose(bus);
busnr = bus->number;
hose = pci_bus_to_hose(busnr);
if (!hose)
return NULL;
......@@ -839,12 +839,18 @@ pci_device_to_OF_node(struct pci_dev *dev)
/* Fixup bus number according to what OF think it is. */
if (pci_to_OF_bus_map)
bus = pci_to_OF_bus_map[bus];
if (bus == 0xff)
busnr = pci_to_OF_bus_map[busnr];
if (busnr == 0xff)
return NULL;
/* Now, lookup childs of the hose */
return scan_OF_childs_for_device(node->child, bus, dev->devfn);
return scan_OF_childs_for_device(node->child, busnr, devfn);
}
struct device_node*
pci_device_to_OF_node(struct pci_dev *dev)
{
return pci_busdev_to_OF_node(dev->bus, dev->devfn);
}
/* This routine is meant to be used early during boot, when the
......@@ -1512,31 +1518,33 @@ null_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \
return PCIBIOS_DEVICE_NOT_FOUND; \
}
NULL_PCI_OP(read, byte, u8 *)
NULL_PCI_OP(read, word, u16 *)
NULL_PCI_OP(read, dword, u32 *)
NULL_PCI_OP(write, byte, u8)
NULL_PCI_OP(write, word, u16)
NULL_PCI_OP(write, dword, u32)
static int
null_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
int len, u32 *val)
{
return PCIBIOS_DEVICE_NOT_FOUND;
}
static int
null_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
int len, u32 val)
{
return PCIBIOS_DEVICE_NOT_FOUND;
}
static struct pci_ops null_pci_ops =
{
null_read_config_byte,
null_read_config_word,
null_read_config_dword,
null_write_config_byte,
null_write_config_word,
null_write_config_dword
null_read_config,
null_write_config
};
/*
* These functions are used early on before PCI scanning is done
* and all of the pci_dev and pci_bus structures have been created.
*/
static struct pci_dev *
fake_pci_dev(struct pci_controller *hose, int busnr, int devfn)
static struct pci_bus *
fake_pci_bus(struct pci_controller *hose, int busnr)
{
static struct pci_dev dev;
static struct pci_bus bus;
if (hose == 0) {
......@@ -1544,20 +1552,17 @@ fake_pci_dev(struct pci_controller *hose, int busnr, int devfn)
if (hose == 0)
printk(KERN_ERR "Can't find hose for PCI bus %d!\n", busnr);
}
dev.bus = &bus;
dev.sysdata = hose;
dev.devfn = devfn;
bus.number = busnr;
bus.ops = hose? hose->ops: &null_pci_ops;
return &dev;
return &bus;
}
#define EARLY_PCI_OP(rw, size, type) \
int early_##rw##_config_##size(struct pci_controller *hose, int bus, \
int devfn, int offset, type value) \
{ \
return pci_##rw##_config_##size(fake_pci_dev(hose, bus, devfn), \
offset, value); \
return pci_bus_##rw##_config_##size(fake_pci_bus(hose, bus), \
devfn, offset, value); \
}
EARLY_PCI_OP(read, byte, u8 *)
......
......@@ -250,6 +250,7 @@ EXPORT_SYMBOL(find_all_nodes);
EXPORT_SYMBOL(get_property);
EXPORT_SYMBOL(request_OF_resource);
EXPORT_SYMBOL(release_OF_resource);
EXPORT_SYMBOL(pci_busdev_to_OF_node);
EXPORT_SYMBOL(pci_device_to_OF_node);
EXPORT_SYMBOL(pci_device_from_OF_node);
EXPORT_SYMBOL(pmac_newworld);
......
......@@ -61,49 +61,72 @@ void *pci_io_base(unsigned int bus)
}
#define cfg_read(val, addr, type, op) *val = op((type)(addr))
#define cfg_write(val, addr, type, op) op((val), (type *)(addr)); DEFW()
#define cfg_read_bad *val = ~0;
#define cfg_write_bad ;
#define cfg_read_val(val) *val
#define cfg_write_val(val) val
#define APUS_PCI_OP(rw, size, type, op, mask) \
int \
apus_pcibios_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \
{ \
int fnno = FNNO(dev->devfn); \
int devno = DEVNO(dev->devfn); \
\
if (dev->bus->number > 0 || devno != 1) { \
cfg_##rw##_bad; \
return PCIBIOS_DEVICE_NOT_FOUND; \
} \
/* base address + function offset + offset ^ endianness conversion */ \
cfg_##rw(val, apus_hose->cfg_data + (fnno<<5) + (offset ^ mask), \
type, op); \
\
DPRINTK(#op " b: 0x%x, d: 0x%x, f: 0x%x, o: 0x%x, v: 0x%x\n", \
dev->bus->number, dev->devfn>>3, dev->devfn&7, \
offset, cfg_##rw##_val(val)); \
return PCIBIOS_SUCCESSFUL; \
int
apus_pcibios_read_config(struct pci_bus *bus, int devfn, int offset,
int len, u32 *val)
{
int fnno = FNNO(devfn);
int devno = DEVNO(devfn);
volatile unsigned char *cfg_data;
if (bus->number > 0 || devno != 1) {
*val = ~0;
return PCIBIOS_DEVICE_NOT_FOUND;
}
/* base address + function offset + offset ^ endianness conversion */
/* XXX the fnno<<5 bit seems wacky -- paulus */
cfg_data = apus_hose->cfg_data + (fnno<<5) + (offset ^ (len - 1));
switch (len) {
case 1:
*val = readb(cfg_data);
break;
case 2:
*val = readw(cfg_data);
break;
default:
*val = readl(cfg_data);
break;
}
DPRINTK("read b: 0x%x, d: 0x%x, f: 0x%x, o: 0x%x, l: %d, v: 0x%x\n",
bus->number, devfn>>3, devfn&7, offset, len, *val);
return PCIBIOS_SUCCESSFUL;
}
APUS_PCI_OP(read, byte, u8 *, readb, 3)
APUS_PCI_OP(read, word, u16 *, readw, 2)
APUS_PCI_OP(read, dword, u32 *, readl, 0)
APUS_PCI_OP(write, byte, u8, writeb, 3)
APUS_PCI_OP(write, word, u16, writew, 2)
APUS_PCI_OP(write, dword, u32, writel, 0)
int
apus_pcibios_write_config(struct pci_bus *bus, int devfn, int offset,
int len, u32 *val)
{
int fnno = FNNO(devfn);
int devno = DEVNO(devfn);
volatile unsigned char *cfg_data;
if (bus->number > 0 || devno != 1) {
return PCIBIOS_DEVICE_NOT_FOUND;
}
/* base address + function offset + offset ^ endianness conversion */
/* XXX the fnno<<5 bit seems wacky -- paulus */
cfg_data = apus_hose->cfg_data + (fnno<<5) + (offset ^ (len - 1));
switch (len) {
case 1:
writeb(val, cfg_data); DEFW();
break;
case 2:
writew(val, cfg_data); DEFW();
break;
default:
writel(val, cfg_data); DEFW();
break;
}
DPRINTK("write b: 0x%x, d: 0x%x, f: 0x%x, o: 0x%x, l: %d, v: 0x%x\n",
bus->number, devfn>>3, devfn&7, offset, len, val);
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops apus_pci_ops = {
apus_pcibios_read_config_byte,
apus_pcibios_read_config_word,
apus_pcibios_read_config_dword,
apus_pcibios_write_config_byte,
apus_pcibios_write_config_word,
apus_pcibios_write_config_dword
apus_pcibios_read_config,
apus_pcibios_write_config
};
static struct resource pci_mem = { "B/CVisionPPC PCI mem", CVPPC_FB_APERTURE_ONE, CVPPC_PCI_CONFIG, IORESOURCE_MEM };
......
......@@ -28,136 +28,108 @@
/* LongTrail */
unsigned long gg2_pci_config_base;
#define pci_config_addr(dev, offset) \
(gg2_pci_config_base | ((dev->bus->number)<<16) | ((dev->devfn)<<8) | (offset))
volatile struct Hydra *Hydra = NULL;
/*
* The VLSI Golden Gate II has only 512K of PCI configuration space, so we
* limit the bus number to 3 bits
*/
#define cfg_read(val, addr, type, op) *val = op((type)(addr))
#define cfg_write(val, addr, type, op) op((type *)(addr), (val))
#define cfg_read_bad(val, size) *val = bad_##size;
#define cfg_write_bad(val, size)
#define bad_byte 0xff
#define bad_word 0xffff
#define bad_dword 0xffffffffU
int __chrp gg2_read_config(struct pci_bus *bus, unsigned int devfn, int off,
int len, u32 *val)
{
volatile unsigned char *cfg_data;
struct pci_controller *hose = bus->sysdata;
#define GG2_PCI_OP(rw, size, type, op) \
int __chrp gg2_##rw##_config_##size(struct pci_dev *dev, int off, type val) \
{ \
if (dev->bus->number > 7) { \
cfg_##rw##_bad(val, size) \
return PCIBIOS_DEVICE_NOT_FOUND; \
} \
cfg_##rw(val, pci_config_addr(dev, off), type, op); \
return PCIBIOS_SUCCESSFUL; \
if (bus->number > 7)
return PCIBIOS_DEVICE_NOT_FOUND;
/*
* Note: the caller has already checked that off is
* suitably aligned and that len is 1, 2 or 4.
*/
cfg_data = hose->cfg_data + ((bus->number<<16) | (devfn<<8) | off);
switch (len) {
case 1:
*val = in_8((u8 *)cfg_data);
break;
case 2:
*val = in_le16((u16 *)cfg_data);
break;
default:
*val = in_le32((u32 *)cfg_data);
break;
}
return PCIBIOS_SUCCESSFUL;
}
GG2_PCI_OP(read, byte, u8 *, in_8)
GG2_PCI_OP(read, word, u16 *, in_le16)
GG2_PCI_OP(read, dword, u32 *, in_le32)
GG2_PCI_OP(write, byte, u8, out_8)
GG2_PCI_OP(write, word, u16, out_le16)
GG2_PCI_OP(write, dword, u32, out_le32)
static struct pci_ops gg2_pci_ops =
int __chrp gg2_write_config(struct pci_bus *bus, unsigned int devfn, int off,
int len, u32 val)
{
gg2_read_config_byte,
gg2_read_config_word,
gg2_read_config_dword,
gg2_write_config_byte,
gg2_write_config_word,
gg2_write_config_dword
};
volatile unsigned char *cfg_data;
struct pci_controller *hose = bus->sysdata;
/*
* Access functions for PCI config space on IBM "python" host bridges.
if (bus->number > 7)
return PCIBIOS_DEVICE_NOT_FOUND;
/*
* Note: the caller has already checked that off is
* suitably aligned and that len is 1, 2 or 4.
*/
#define PYTHON_CFA(b, d, o) (0x80 | ((b) << 8) | ((d) << 16) \
| (((o) & ~3) << 24))
#define PYTHON_PCI_OP(rw, size, type, op, mask) \
int __chrp \
python_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \
{ \
struct pci_controller *hose = dev->sysdata; \
\
out_be32(hose->cfg_addr, \
PYTHON_CFA(dev->bus->number, dev->devfn, offset)); \
cfg_##rw(val, hose->cfg_data + (offset & mask), type, op); \
return PCIBIOS_SUCCESSFUL; \
cfg_data = hose->cfg_data + ((bus->number<<16) | (devfn<<8) | off);
switch (len) {
case 1:
out_8((u8 *)cfg_data, val);
break;
case 2:
out_le16((u16 *)cfg_data, val);
break;
default:
out_le32((u32 *)cfg_data, val);
break;
}
return PCIBIOS_SUCCESSFUL;
}
PYTHON_PCI_OP(read, byte, u8 *, in_8, 3)
PYTHON_PCI_OP(read, word, u16 *, in_le16, 2)
PYTHON_PCI_OP(read, dword, u32 *, in_le32, 0)
PYTHON_PCI_OP(write, byte, u8, out_8, 3)
PYTHON_PCI_OP(write, word, u16, out_le16, 2)
PYTHON_PCI_OP(write, dword, u32, out_le32, 0)
static struct pci_ops python_pci_ops =
static struct pci_ops gg2_pci_ops =
{
python_read_config_byte,
python_read_config_word,
python_read_config_dword,
python_write_config_byte,
python_write_config_word,
python_write_config_dword
gg2_read_config,
gg2_write_config
};
/*
* Access functions for PCI config space using RTAS calls.
*/
#define RTAS_PCI_READ_OP(size, type, nbytes) \
int __chrp \
rtas_read_config_##size(struct pci_dev *dev, int offset, type val) \
{ \
unsigned long addr = (offset & 0xff) | ((dev->devfn & 0xff) << 8) \
| ((dev->bus->number & 0xff) << 16); \
unsigned long ret = ~0UL; \
int rval; \
\
rval = call_rtas("read-pci-config", 2, 2, &ret, addr, nbytes); \
*val = ret; \
return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL; \
int __chrp
rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
int len, u32 *val)
{
unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
| ((bus->number & 0xff) << 16);
unsigned long ret = ~0UL;
int rval;
rval = call_rtas("read-pci-config", 2, 2, &ret, addr, len);
*val = ret;
return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;
}
#define RTAS_PCI_WRITE_OP(size, type, nbytes) \
int __chrp \
rtas_write_config_##size(struct pci_dev *dev, int offset, type val) \
{ \
unsigned long addr = (offset & 0xff) | ((dev->devfn & 0xff) << 8) \
| ((dev->bus->number & 0xff) << 16); \
int rval; \
\
rval = call_rtas("write-pci-config", 3, 1, NULL, \
addr, nbytes, (ulong)val); \
return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL; \
}
int __chrp
rtas_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
int len, u32 val)
{
unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
| ((bus->number & 0xff) << 16);
int rval;
RTAS_PCI_READ_OP(byte, u8 *, 1)
RTAS_PCI_READ_OP(word, u16 *, 2)
RTAS_PCI_READ_OP(dword, u32 *, 4)
RTAS_PCI_WRITE_OP(byte, u8, 1)
RTAS_PCI_WRITE_OP(word, u16, 2)
RTAS_PCI_WRITE_OP(dword, u32, 4)
rval = call_rtas("write-pci-config", 3, 1, NULL, addr, len, val);
return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;
}
static struct pci_ops rtas_pci_ops =
{
rtas_read_config_byte,
rtas_read_config_word,
rtas_read_config_dword,
rtas_write_config_byte,
rtas_write_config_word,
rtas_write_config_dword
rtas_read_config,
rtas_write_config
};
volatile struct Hydra *Hydra = NULL;
int __init
hydra_init(void)
{
......@@ -203,12 +175,9 @@ static void __init
setup_python(struct pci_controller *hose, struct device_node *dev)
{
u32 *reg, val;
volatile unsigned char *cfg;
unsigned long addr = dev->addrs[0].address;
hose->ops = &python_pci_ops;
cfg = ioremap(dev->addrs[0].address + 0xf8000, 0x20);
hose->cfg_addr = (volatile unsigned int *) cfg;
hose->cfg_data = cfg + 0x10;
setup_indirect_pci(hose, addr + 0xf8000, addr + 0xf8010);
/* Clear the magic go-slow bit */
reg = (u32 *) ioremap(dev->addrs[0].address + 0xf6000, 0x40);
......@@ -288,8 +257,9 @@ chrp_find_bridges(void)
setup_grackle(hose);
} else if (is_longtrail) {
hose->ops = &gg2_pci_ops;
gg2_pci_config_base = (unsigned long)
hose->cfg_data = (unsigned char *)
ioremap(GG2_PCI_CONFIG_BASE, 0x80000);
gg2_pci_config_base = (unsigned long) hose->cfg_data;
} else {
printk("No methods for %s (model %s), using RTAS\n",
dev->full_name, model);
......
......@@ -13,84 +13,6 @@
#include <asm/uaccess.h>
#include <asm/pci-bridge.h>
#define pci_config_addr(bus,dev,offset) \
(0x80000000 | (bus<<16) | (dev<<8) | offset)
int
gemini_pcibios_read_config_byte(struct pci_dev *dev, int offset, u8 *val)
{
unsigned long reg;
reg = grackle_read(pci_config_addr(dev->bus->number, dev->devfn,
(offset & ~(0x3))));
*val = ((reg >> ((offset & 0x3) << 3)) & 0xff);
return PCIBIOS_SUCCESSFUL;
}
int
gemini_pcibios_read_config_word(struct pci_dev *dev, int offset, u16 *val)
{
unsigned long reg;
reg = grackle_read(pci_config_addr(dev->bus->number, dev->devfn,
(offset & ~(0x3))));
*val = ((reg >> ((offset & 0x3) << 3)) & 0xffff);
return PCIBIOS_SUCCESSFUL;
}
int
gemini_pcibios_read_config_dword(struct pci_dev *dev, int offset, u32 *val)
{
*val = grackle_read(pci_config_addr(dev->bus->number, dev->devfn,
(offset & ~(0x3))));
return PCIBIOS_SUCCESSFUL;
}
int
gemini_pcibios_write_config_byte(struct pci_dev *dev, int offset, u8 val)
{
unsigned long reg;
int shifts = offset & 0x3;
unsigned int addr = pci_config_addr(dev->bus->number, dev->devfn,
(offset & ~(0x3)));
reg = grackle_read(addr);
reg = (reg & ~(0xff << (shifts << 3))) | (val << (shifts << 3));
grackle_write(addr, reg );
return PCIBIOS_SUCCESSFUL;
}
int
gemini_pcibios_write_config_word(struct pci_dev *dev, int offset, u16 val)
{
unsigned long reg;
int shifts = offset & 0x3;
unsigned int addr = pci_config_addr(dev->bus->number, dev->devfn,
(offset & ~(0x3)));
reg = grackle_read(addr);
reg = (reg & ~(0xffff << (shifts << 3))) | (val << (shifts << 3));
grackle_write(addr, reg );
return PCIBIOS_SUCCESSFUL;
}
int
gemini_pcibios_write_config_dword(struct pci_dev *dev, int offset, u32 val)
{
grackle_write(pci_config_addr(dev->bus->number, dev->devfn,
(offset & ~(0x3))), val);
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops gemini_pci_ops =
{
gemini_pcibios_read_config_byte,
gemini_pcibios_read_config_word,
gemini_pcibios_read_config_dword,
gemini_pcibios_write_config_byte,
gemini_pcibios_write_config_word,
gemini_pcibios_write_config_dword
};
void __init gemini_pcibios_fixup(void)
{
int i;
......@@ -118,5 +40,5 @@ void __init gemini_find_bridges(void)
hose = pcibios_alloc_controller();
if (!hose)
return;
hose->ops = &gemini_pci_ops;
setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
}
......@@ -137,101 +137,118 @@ macrisc_cfg_access(struct pci_controller* hose, u8 bus, u8 dev_fn, u8 offset)
/* Uninorth will return garbage if we don't read back the value ! */
do {
out_le32(hose->cfg_addr, caddr);
} while(in_le32(hose->cfg_addr) != caddr);
} while (in_le32(hose->cfg_addr) != caddr);
offset &= has_uninorth ? 0x07 : 0x03;
return (unsigned int)(hose->cfg_data) + (unsigned int)offset;
}
#define cfg_read(val, addr, type, op, op2) \
*val = op((type)(addr))
#define cfg_write(val, addr, type, op, op2) \
op((type *)(addr), (val)); (void) op2((type *)(addr))
#define cfg_read_bad(val, size) *val = bad_##size;
#define cfg_write_bad(val, size)
#define bad_byte 0xff
#define bad_word 0xffff
#define bad_dword 0xffffffffU
#define MACRISC_PCI_OP(rw, size, type, op, op2) \
static int __pmac \
macrisc_##rw##_config_##size(struct pci_dev *dev, int off, type val) \
{ \
struct pci_controller *hose = dev->sysdata; \
unsigned int addr; \
\
addr = macrisc_cfg_access(hose, dev->bus->number, dev->devfn, off); \
if (!addr) { \
cfg_##rw##_bad(val, size) \
return PCIBIOS_DEVICE_NOT_FOUND; \
} \
cfg_##rw(val, addr, type, op, op2); \
return PCIBIOS_SUCCESSFUL; \
static int __pmac
macrisc_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
int len, u32 *val)
{
struct pci_controller *hose = bus->sysdata;
unsigned int addr;
addr = macrisc_cfg_access(hose, bus->number, devfn, offset);
if (!addr)
return PCIBIOS_DEVICE_NOT_FOUND;
/*
* Note: the caller has already checked that offset is
* suitably aligned and that len is 1, 2 or 4.
*/
switch (len) {
case 1:
*val = in_8((u8 *)addr);
break;
case 2:
*val = in_le16((u16 *)addr);
break;
default:
*val = in_le32((u32 *)addr);
break;
}
return PCIBIOS_SUCCESSFUL;
}
MACRISC_PCI_OP(read, byte, u8 *, in_8, x)
MACRISC_PCI_OP(read, word, u16 *, in_le16, x)
MACRISC_PCI_OP(read, dword, u32 *, in_le32, x)
MACRISC_PCI_OP(write, byte, u8, out_8, in_8)
MACRISC_PCI_OP(write, word, u16, out_le16, in_le16)
MACRISC_PCI_OP(write, dword, u32, out_le32, in_le32)
static int __pmac
macrisc_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
int len, u32 val)
{
struct pci_controller *hose = bus->sysdata;
unsigned int addr;
addr = macrisc_cfg_access(hose, bus->number, devfn, offset);
if (!addr)
return PCIBIOS_DEVICE_NOT_FOUND;
/*
* Note: the caller has already checked that offset is
* suitably aligned and that len is 1, 2 or 4.
*/
switch (len) {
case 1:
out_8((u8 *)addr, val);
(void) in_8((u8 *)addr);
break;
case 2:
out_le16((u16 *)addr, val);
(void) in_le16((u16 *)addr);
break;
default:
out_le32((u32 *)addr, val);
(void) in_le32((u32 *)addr);
break;
}
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops macrisc_pci_ops =
{
macrisc_read_config_byte,
macrisc_read_config_word,
macrisc_read_config_dword,
macrisc_write_config_byte,
macrisc_write_config_word,
macrisc_write_config_dword
macrisc_read_config,
macrisc_write_config
};
/*
* Verifiy that a specific (bus, dev_fn) exists on chaos
*/
static int __pmac
chaos_validate_dev(struct pci_dev *dev, int offset)
chaos_validate_dev(struct pci_bus *bus, int devfn, int offset)
{
if(pci_device_to_OF_node(dev) == 0)
if (pci_busdev_to_OF_node(bus, devfn) == 0)
return PCIBIOS_DEVICE_NOT_FOUND;
if((dev->vendor == 0x106b) && (dev->device == 3) && (offset >= 0x10) &&
(offset != 0x14) && (offset != 0x18) && (offset <= 0x24)) {
if (/*(dev->vendor == 0x106b) && (dev->device == 3) &&*/ (offset >= 0x10)
&& (offset != 0x14) && (offset != 0x18) && (offset <= 0x24)) {
return PCIBIOS_BAD_REGISTER_NUMBER;
}
return PCIBIOS_SUCCESSFUL;
}
#define CHAOS_PCI_OP(rw, size, type) \
static int __pmac \
chaos_##rw##_config_##size(struct pci_dev *dev, int off, type val) \
{ \
int result = chaos_validate_dev(dev, off); \
if(result == PCIBIOS_BAD_REGISTER_NUMBER) { \
cfg_##rw##_bad(val, size) \
return PCIBIOS_BAD_REGISTER_NUMBER; \
} \
if(result == PCIBIOS_SUCCESSFUL) \
return macrisc_##rw##_config_##size(dev, off, val); \
return result; \
static int __pmac
chaos_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
int len, u32 *val)
{
int result = chaos_validate_dev(bus, devfn, offset);
if (result == PCIBIOS_BAD_REGISTER_NUMBER)
*val = ~0U;
if (result != PCIBIOS_SUCCESSFUL)
return result;
return macrisc_read_config(bus, devfn, offset, len, val);
}
CHAOS_PCI_OP(read, byte, u8 *)
CHAOS_PCI_OP(read, word, u16 *)
CHAOS_PCI_OP(read, dword, u32 *)
CHAOS_PCI_OP(write, byte, u8)
CHAOS_PCI_OP(write, word, u16)
CHAOS_PCI_OP(write, dword, u32)
static int __pmac
chaos_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
int len, u32 val)
{
int result = chaos_validate_dev(bus, devfn, offset);
if (result != PCIBIOS_SUCCESSFUL)
return result;
return macrisc_write_config(bus, devfn, offset, len, val);
}
static struct pci_ops chaos_pci_ops =
{
chaos_read_config_byte,
chaos_read_config_word,
chaos_read_config_dword,
chaos_write_config_byte,
chaos_write_config_word,
chaos_write_config_dword
chaos_read_config,
chaos_write_config
};
......@@ -489,7 +506,8 @@ pcibios_fixup_OF_interrupts(void)
* obtained from the OF device-tree
*/
pci_for_each_dev(dev) {
struct device_node* node = pci_device_to_OF_node(dev);
struct device_node *node;
node = pci_device_to_OF_node(dev);
/* this is the node, see if it has interrupts */
if (node && node->n_intrs > 0)
dev->irq = node->intrs[0].line;
......
......@@ -31,6 +31,7 @@ extern void pci_init_resource(struct resource *res, unsigned long start,
*/
extern int pci_device_from_OF_node(struct device_node *node,
u8* bus, u8* devfn);
extern struct device_node* pci_busdev_to_OF_node(struct pci_bus *, int);
extern struct device_node* pci_device_to_OF_node(struct pci_dev *);
extern void pci_create_OF_bus_map(void);
......
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