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