summaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
authorEric Biederman <ebiederm@xmission.com>2004-11-18 22:38:08 +0000
committerEric Biederman <ebiederm@xmission.com>2004-11-18 22:38:08 +0000
commita9e632c2ac29c60872e7e4f9314263b34ce5031d (patch)
tree2a76647833896d68306553c548a65743c87b417e /src/arch
parentbec8acedf18b4d35f95b4a4c254eb925bd4d53bd (diff)
- First stab at getting the ppc ports building and working.
- The sandpointx3+altimus has been consolidated into one directory for now. - Added support for having different versions of the pci access functions on a per bus basis if needed. Hopefully I have not broken something inadvertently. git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1786 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/i386/boot/linuxbios_table.c3
-rw-r--r--src/arch/i386/include/arch/pci_ops.h15
-rw-r--r--src/arch/i386/lib/Config.lb2
-rw-r--r--src/arch/i386/lib/exception.c2
-rw-r--r--src/arch/i386/lib/pci_ops.c60
-rw-r--r--src/arch/i386/lib/pci_ops_auto.c45
-rw-r--r--src/arch/i386/lib/pci_ops_conf1.c19
-rw-r--r--src/arch/i386/lib/pci_ops_conf2.c18
-rw-r--r--src/arch/ppc/include/arch/cpu.h57
-rw-r--r--src/arch/ppc/include/arch/pci_ops.h8
-rw-r--r--src/arch/ppc/lib/Config.lb4
-rw-r--r--src/arch/ppc/lib/c_start.S2
-rw-r--r--src/arch/ppc/lib/cpu.c29
-rw-r--r--src/arch/ppc/lib/div64.S58
-rw-r--r--src/arch/ppc/lib/pci_ops.c105
-rw-r--r--src/arch/ppc/lib/pci_ppc_conf1_ops.c46
16 files changed, 236 insertions, 237 deletions
diff --git a/src/arch/i386/boot/linuxbios_table.c b/src/arch/i386/boot/linuxbios_table.c
index 594b5e55a9..5b2b34ff8a 100644
--- a/src/arch/i386/boot/linuxbios_table.c
+++ b/src/arch/i386/boot/linuxbios_table.c
@@ -315,7 +315,6 @@ static void build_lb_mem_range(void *gp, struct device *dev, struct resource *re
static struct lb_memory *build_lb_mem(struct lb_header *head)
{
struct lb_memory *mem;
- struct device *dev;
/* Record where the lb memory ranges will live */
mem = lb_memory(head);
@@ -343,7 +342,7 @@ unsigned long write_linuxbios_table(
struct lb_record *rec_dest, *rec_src;
/* Write the option config table... */
rec_dest = lb_new_record(head);
- rec_src = (struct lb_record *)&option_table;
+ rec_src = (struct lb_record *)(void *)&option_table;
memcpy(rec_dest, rec_src, rec_src->size);
}
/* Record where RAM is located */
diff --git a/src/arch/i386/include/arch/pci_ops.h b/src/arch/i386/include/arch/pci_ops.h
index 51730c4692..72307a6211 100644
--- a/src/arch/i386/include/arch/pci_ops.h
+++ b/src/arch/i386/include/arch/pci_ops.h
@@ -1,18 +1,9 @@
#ifndef ARCH_I386_PCI_OPS_H
#define ARCH_I386_PCI_OPS_H
-struct pci_ops {
- uint8_t (*read8) (uint8_t bus, int devfn, int where);
- uint16_t (*read16) (uint8_t bus, int devfn, int where);
- uint32_t (*read32) (uint8_t bus, int devfn, int where);
- void (*write8) (uint8_t bus, int devfn, int where, uint8_t val);
- void (*write16) (uint8_t bus, int devfn, int where, uint16_t val);
- void (*write32) (uint8_t bus, int devfn, int where, uint32_t val);
-};
-extern const struct pci_ops *conf;
+const struct pci_bus_operations pci_cf8_conf1;
+const struct pci_bus_operations pci_cf8_conf2;
-void pci_set_method_conf1(void);
-void pci_set_method_conf2(void);
-void pci_set_method(void);
+void pci_set_method(device_t dev);
#endif /* ARCH_I386_PCI_OPS_H */
diff --git a/src/arch/i386/lib/Config.lb b/src/arch/i386/lib/Config.lb
index 6de19b65be..cdd3fd3891 100644
--- a/src/arch/i386/lib/Config.lb
+++ b/src/arch/i386/lib/Config.lb
@@ -6,7 +6,7 @@
#option CONFIG_PCIBIOS_IRQ=0
object c_start.S
object cpu.c
-object pci_ops.c
+#object pci_ops.c
object pci_ops_conf1.c
object pci_ops_conf2.c
object pci_ops_auto.c
diff --git a/src/arch/i386/lib/exception.c b/src/arch/i386/lib/exception.c
index 86edccbdd2..5f0c4e0563 100644
--- a/src/arch/i386/lib/exception.c
+++ b/src/arch/i386/lib/exception.c
@@ -420,7 +420,7 @@ void x86_exception(struct eregs *info)
if ( parse_ulong(&ptr, &addr) &&
(*ptr++ == ',') &&
parse_ulong(&ptr, &length)) {
- copy_to_hex(out_buffer, addr, length);
+ copy_to_hex(out_buffer, (void *)addr, length);
} else {
memcpy(out_buffer, "E01", 4);
}
diff --git a/src/arch/i386/lib/pci_ops.c b/src/arch/i386/lib/pci_ops.c
deleted file mode 100644
index ded7fd20a4..0000000000
--- a/src/arch/i386/lib/pci_ops.c
+++ /dev/null
@@ -1,60 +0,0 @@
-#include <console/console.h>
-#include <arch/io.h>
-#include <arch/pciconf.h>
-#include <device/pci.h>
-#include <device/pci_ids.h>
-#include <device/pci_ops.h>
-
-const struct pci_ops *conf = 0;
-
-/*
- * Direct access to PCI hardware...
- */
-
-uint8_t pci_read_config8(device_t dev, unsigned where)
-{
- uint8_t value;
- value = conf->read8(dev->bus->secondary, dev->path.u.pci.devfn, where);
- printk_spew("Read config 8 bus %d,devfn 0x%x,reg 0x%x,val 0x%x\n",
- dev->bus->secondary, dev->path.u.pci.devfn, where, value);
- return value;
-}
-
-uint16_t pci_read_config16(device_t dev, unsigned where)
-{
- uint16_t value;
- value = conf->read16(dev->bus->secondary, dev->path.u.pci.devfn, where);
- printk_spew( "Read config 16 bus %d,devfn 0x%x,reg 0x%x,val 0x%x\n",
- dev->bus->secondary, dev->path.u.pci.devfn, where, value);
- return value;
-}
-
-uint32_t pci_read_config32(device_t dev, unsigned where)
-{
- uint32_t value;
- value = conf->read32(dev->bus->secondary, dev->path.u.pci.devfn, where);
- printk_spew( "Read config 32 bus %d,devfn 0x%x,reg 0x%x,val 0x%x\n",
- dev->bus->secondary, dev->path.u.pci.devfn, where, value);
- return value;
-}
-
-void pci_write_config8(device_t dev, unsigned where, uint8_t val)
-{
- printk_spew( "Write config 8 bus %d, devfn 0x%x, reg 0x%x, val 0x%x\n",
- dev->bus->secondary, dev->path.u.pci.devfn, where, val);
- conf->write8(dev->bus->secondary, dev->path.u.pci.devfn, where, val);
-}
-
-void pci_write_config16(device_t dev, unsigned where, uint16_t val)
-{
- printk_spew( "Write config 16 bus %d, devfn 0x%x, reg 0x%x, val 0x%x\n",
- dev->bus->secondary, dev->path.u.pci.devfn, where, val);
- conf->write16(dev->bus->secondary, dev->path.u.pci.devfn, where, val);
-}
-
-void pci_write_config32(device_t dev, unsigned where, uint32_t val)
-{
- printk_spew( "Write config 32 bus %d, devfn 0x%x, reg 0x%x, val 0x%x\n",
- dev->bus->secondary, dev->path.u.pci.devfn, where, val);
- conf->write32(dev->bus->secondary, dev->path.u.pci.devfn, where, val);
-}
diff --git a/src/arch/i386/lib/pci_ops_auto.c b/src/arch/i386/lib/pci_ops_auto.c
index 5c45720888..b757e608fc 100644
--- a/src/arch/i386/lib/pci_ops_auto.c
+++ b/src/arch/i386/lib/pci_ops_auto.c
@@ -1,3 +1,4 @@
+#include <stddef.h>
#include <console/console.h>
#include <arch/io.h>
#include <arch/pciconf.h>
@@ -15,11 +16,12 @@
* This should be close to trivial, but it isn't, because there are buggy
* chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
*/
-static int pci_sanity_check(const struct pci_ops *o)
+static int pci_sanity_check(const struct pci_bus_operations *o)
{
uint16_t class, vendor;
- uint8_t bus;
+ unsigned bus;
int devfn;
+ struct bus pbus; /* Dummy device */
#define PCI_CLASS_BRIDGE_HOST 0x0600
#define PCI_CLASS_DISPLAY_VGA 0x0300
#define PCI_VENDOR_ID_COMPAQ 0x0e11
@@ -27,8 +29,8 @@ static int pci_sanity_check(const struct pci_ops *o)
#define PCI_VENDOR_ID_MOTOROLA 0x1057
for (bus = 0, devfn = 0; devfn < 0x100; devfn++) {
- class = o->read16(bus, devfn, PCI_CLASS_DEVICE);
- vendor = o->read16(bus, devfn, PCI_VENDOR_ID);
+ class = o->read16(&pbus, bus, devfn, PCI_CLASS_DEVICE);
+ vendor = o->read16(&pbus, bus, devfn, PCI_VENDOR_ID);
if (((class == PCI_CLASS_BRIDGE_HOST) || (class == PCI_CLASS_DISPLAY_VGA)) ||
((vendor == PCI_VENDOR_ID_INTEL) || (vendor == PCI_VENDOR_ID_COMPAQ) ||
(vendor == PCI_VENDOR_ID_MOTOROLA))) {
@@ -39,7 +41,7 @@ static int pci_sanity_check(const struct pci_ops *o)
return 0;
}
-static void pci_check_direct(void)
+const struct pci_bus_operations *pci_check_direct(void)
{
unsigned int tmp;
@@ -50,13 +52,12 @@ static void pci_check_direct(void)
outb(0x01, 0xCFB);
tmp = inl(0xCF8);
outl(0x80000000, 0xCF8);
- if (inl(0xCF8) == 0x80000000) {
- pci_set_method_conf1();
- if (pci_sanity_check(conf)) {
- outl(tmp, 0xCF8);
- printk_debug("PCI: Using configuration type 1\n");
- return;
- }
+ if ((inl(0xCF8) == 0x80000000) &&
+ pci_sanity_check(&pci_cf8_conf1))
+ {
+ outl(tmp, 0xCF8);
+ printk_debug("PCI: Using configuration type 1\n");
+ return &pci_cf8_conf1;
}
outl(tmp, 0xCF8);
}
@@ -68,25 +69,23 @@ static void pci_check_direct(void)
outb(0x00, 0xCFB);
outb(0x00, 0xCF8);
outb(0x00, 0xCFA);
- if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00) {
- pci_set_method_conf2();
- if (pci_sanity_check(conf)) {
- printk_debug("PCI: Using configuration type 2\n");
- }
+ if ((inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00) &&
+ pci_sanity_check(&pci_cf8_conf2))
+ {
+ printk_debug("PCI: Using configuration type 2\n");
+ return &pci_cf8_conf2;
}
}
- printk_debug("pci_check_direct failed\n");
- conf = 0;
-
- return;
+ die("pci_check_direct failed\n");
+ return NULL;
}
/** Set the method to be used for PCI, type I or type II
*/
-void pci_set_method(void)
+void pci_set_method(device_t dev)
{
printk_info("Finding PCI configuration type.\n");
- pci_check_direct();
+ dev->ops->ops_pci_bus = pci_check_direct();
post_code(0x5f);
}
diff --git a/src/arch/i386/lib/pci_ops_conf1.c b/src/arch/i386/lib/pci_ops_conf1.c
index 1324add74a..fb0a434d53 100644
--- a/src/arch/i386/lib/pci_ops_conf1.c
+++ b/src/arch/i386/lib/pci_ops_conf1.c
@@ -10,37 +10,37 @@
#define CONFIG_CMD(bus,devfn, where) (0x80000000 | (bus << 16) | (devfn << 8) | (where & ~3))
-static uint8_t pci_conf1_read_config8(unsigned char bus, int devfn, int where)
+static uint8_t pci_conf1_read_config8(struct bus *pbus, unsigned char bus, int devfn, int where)
{
outl(CONFIG_CMD(bus, devfn, where), 0xCF8);
return inb(0xCFC + (where & 3));
}
-static uint16_t pci_conf1_read_config16(unsigned char bus, int devfn, int where)
+static uint16_t pci_conf1_read_config16(struct bus *pbus, unsigned char bus, int devfn, int where)
{
outl(CONFIG_CMD(bus, devfn, where), 0xCF8);
return inw(0xCFC + (where & 2));
}
-static uint32_t pci_conf1_read_config32(unsigned char bus, int devfn, int where)
+static uint32_t pci_conf1_read_config32(struct bus *pbus, unsigned char bus, int devfn, int where)
{
outl(CONFIG_CMD(bus, devfn, where), 0xCF8);
return inl(0xCFC);
}
-static void pci_conf1_write_config8(unsigned char bus, int devfn, int where, uint8_t value)
+static void pci_conf1_write_config8(struct bus *pbus, unsigned char bus, int devfn, int where, uint8_t value)
{
outl(CONFIG_CMD(bus, devfn, where), 0xCF8);
outb(value, 0xCFC + (where & 3));
}
-static void pci_conf1_write_config16(unsigned char bus, int devfn, int where, uint16_t value)
+static void pci_conf1_write_config16(struct bus *pbus, unsigned char bus, int devfn, int where, uint16_t value)
{
outl(CONFIG_CMD(bus, devfn, where), 0xCF8);
outw(value, 0xCFC + (where & 2));
}
-static void pci_conf1_write_config32(unsigned char bus, int devfn, int where, uint32_t value)
+static void pci_conf1_write_config32(struct bus *pbus, unsigned char bus, int devfn, int where, uint32_t value)
{
outl(CONFIG_CMD(bus, devfn, where), 0xCF8);
outl(value, 0xCFC);
@@ -48,7 +48,7 @@ static void pci_conf1_write_config32(unsigned char bus, int devfn, int where, ui
#undef CONFIG_CMD
-static const struct pci_ops pci_direct_conf1 =
+const struct pci_bus_operations pci_cf8_conf1 =
{
.read8 = pci_conf1_read_config8,
.read16 = pci_conf1_read_config16,
@@ -57,8 +57,3 @@ static const struct pci_ops pci_direct_conf1 =
.write16 = pci_conf1_write_config16,
.write32 = pci_conf1_write_config32,
};
-
-void pci_set_method_conf1(void)
-{
- conf = &pci_direct_conf1;
-}
diff --git a/src/arch/i386/lib/pci_ops_conf2.c b/src/arch/i386/lib/pci_ops_conf2.c
index 9fa03f18a8..10fde93346 100644
--- a/src/arch/i386/lib/pci_ops_conf2.c
+++ b/src/arch/i386/lib/pci_ops_conf2.c
@@ -12,7 +12,7 @@
#define FUNC(devfn) (((devfn & 7) << 1) | 0xf0)
#define SET(bus,devfn) outb(FUNC(devfn), 0xCF8); outb(bus, 0xCFA);
-static uint8_t pci_conf2_read_config8(unsigned char bus, int devfn, int where)
+static uint8_t pci_conf2_read_config8(struct bus *pbus, unsigned char bus, int devfn, int where)
{
uint8_t value;
SET(bus, devfn);
@@ -21,7 +21,7 @@ static uint8_t pci_conf2_read_config8(unsigned char bus, int devfn, int where)
return value;
}
-static uint16_t pci_conf2_read_config16(unsigned char bus, int devfn, int where)
+static uint16_t pci_conf2_read_config16(struct bus *pbus, unsigned char bus, int devfn, int where)
{
uint16_t value;
SET(bus, devfn);
@@ -30,7 +30,7 @@ static uint16_t pci_conf2_read_config16(unsigned char bus, int devfn, int where)
return value;
}
-static uint32_t pci_conf2_read_config32(unsigned char bus, int devfn, int where)
+static uint32_t pci_conf2_read_config32(struct bus *pbus, unsigned char bus, int devfn, int where)
{
uint32_t value;
SET(bus, devfn);
@@ -39,21 +39,21 @@ static uint32_t pci_conf2_read_config32(unsigned char bus, int devfn, int where)
return value;
}
-static void pci_conf2_write_config8(unsigned char bus, int devfn, int where, uint8_t value)
+static void pci_conf2_write_config8(struct bus *pbus, unsigned char bus, int devfn, int where, uint8_t value)
{
SET(bus, devfn);
outb(value, IOADDR(devfn, where));
outb(0, 0xCF8);
}
-static void pci_conf2_write_config16(unsigned char bus, int devfn, int where, uint16_t value)
+static void pci_conf2_write_config16(struct bus *pbus, unsigned char bus, int devfn, int where, uint16_t value)
{
SET(bus, devfn);
outw(value, IOADDR(devfn, where));
outb(0, 0xCF8);
}
-static void pci_conf2_write_config32(unsigned char bus, int devfn, int where, uint32_t value)
+static void pci_conf2_write_config32(struct bus *pbus, unsigned char bus, int devfn, int where, uint32_t value)
{
SET(bus, devfn);
outl(value, IOADDR(devfn, where));
@@ -64,7 +64,7 @@ static void pci_conf2_write_config32(unsigned char bus, int devfn, int where, ui
#undef IOADDR
#undef FUNC
-static const struct pci_ops pci_direct_conf2 =
+const struct pci_bus_operations pci_cf8_conf2 =
{
.read8 = pci_conf2_read_config8,
.read16 = pci_conf2_read_config16,
@@ -74,7 +74,3 @@ static const struct pci_ops pci_direct_conf2 =
.write32 = pci_conf2_write_config32,
};
-void pci_set_method_conf2(void)
-{
- conf = &pci_direct_conf2;
-}
diff --git a/src/arch/ppc/include/arch/cpu.h b/src/arch/ppc/include/arch/cpu.h
index 48293b2425..e0ed4ff66a 100644
--- a/src/arch/ppc/include/arch/cpu.h
+++ b/src/arch/ppc/include/arch/cpu.h
@@ -1,3 +1,60 @@
+#ifndef ARCH_CPU_H
+#define ARCH_CPU_H
/*
* this should probably integrate code from src/arch/ppc/lib/cpuid.c
*/
+
+struct cpu_device_id {
+ unsigned pvr;
+};
+
+struct cpu_driver {
+ struct device_operations *ops;
+ struct cpu_device_id *id_table;
+};
+
+#ifndef STACK_SIZE
+#error STACK_SIZE not defined
+#endif
+
+/* The basic logic comes from the Linux kernel.
+ * The invariant is that (1 << 31 - STACK_BITS) == STACK_SIZE
+ * I wish there was simpler way to support multiple stack sizes.
+ * Oh well.
+ */
+#if STACK_SIZE == 4096
+#define STACK_BITS "19"
+#elif STACK_SIZE == 8192
+#define STACK_BITS "18"
+#elif STACK_SIZE == 16384
+#define STACK_BITS "17"
+#elif STACK_SIZE == 32768
+#define STACK_BITS "16"
+#elif STACK_SIZE == 65536
+#define STACK_BITS "15"
+#else
+#error Unimplemented stack size
+#endif
+
+
+struct cpu_info {
+ struct device *cpu;
+ unsigned long index;
+};
+
+
+static inline struct cpu_info *cpu_info(void)
+{
+ struct cpu_info *ci;
+ __asm__("rlwinm %0,1,0,0," STACK_BITS : "=r"(ci));
+ return ci;
+}
+
+static inline unsigned long cpu_index(void)
+{
+ struct cpu_info *ci;
+ ci = cpu_info();
+ return ci->index;
+}
+
+#endif /* ARCH_CPU_H */
diff --git a/src/arch/ppc/include/arch/pci_ops.h b/src/arch/ppc/include/arch/pci_ops.h
index 6f9c3af3af..95f8941e42 100644
--- a/src/arch/ppc/include/arch/pci_ops.h
+++ b/src/arch/ppc/include/arch/pci_ops.h
@@ -1,6 +1,6 @@
-#ifndef ARCH_I386_PCI_OPS_H
-#define ARCH_I386_PCI_OPS_H
+#ifndef ARCH_PPC_PCI_OPS_H
+#define ARCH_PPC_PCI_OPS_H
-void pci_set_method(void);
+const struct pci_bus_operations pci_ppc_conf1;
-#endif /* ARCH_I386_PCI_OPS_H */
+#endif /* ARCH_PPC_PCI_OPS_H */
diff --git a/src/arch/ppc/lib/Config.lb b/src/arch/ppc/lib/Config.lb
index 0c5aac9d5b..e501592683 100644
--- a/src/arch/ppc/lib/Config.lb
+++ b/src/arch/ppc/lib/Config.lb
@@ -1,15 +1,17 @@
object c_start.S
object setup.o
-object pci_ops.o
+object pci_ppc_conf1_ops.o
object pci_dev.o
object timer.o
object cpuid.o
object cpu.o
object timebase.S
object floats.S
+object div64.S
initobject pci_dev.o
initobject printk_init.o
initobject timebase.S
initobject timer.o
initobject setup.o
initobject floats.S
+initobject div64.S
diff --git a/src/arch/ppc/lib/c_start.S b/src/arch/ppc/lib/c_start.S
index 3fcf840615..d0d2a8f3d7 100644
--- a/src/arch/ppc/lib/c_start.S
+++ b/src/arch/ppc/lib/c_start.S
@@ -17,6 +17,8 @@
_start:
/*
* init stack pointer to real ram now that memory is on
+ * Note: We use the last 8 bytes on the stack to hold struct cpu_info,
+ * Which are initialized to zero as we clear the stack.
*/
li r0, 0
lis r1, _estack@ha
diff --git a/src/arch/ppc/lib/cpu.c b/src/arch/ppc/lib/cpu.c
index adf5358c28..3b6a256908 100644
--- a/src/arch/ppc/lib/cpu.c
+++ b/src/arch/ppc/lib/cpu.c
@@ -1,12 +1,32 @@
#include <console/console.h>
#include <arch/io.h>
#include <string.h>
+#include <device/device.h>
#include <cpu/cpu.h>
#include <cpu/ppc/cpuid.h>
#include "ppc.h"
#include "ppcreg.h"
-#error "FIXME what should call cpu_initialize?"
+#if 0
+static void set_cpu_ops(struct device *cpu)
+{
+ struct cpu_driver *driver;
+ cpu->ops = 0;
+ for (driver = cpu_drivers; driver < ecpu_drivers; driver++) {
+ struct cpu_device_id *id;
+ for(id = driver->id_table; id->pvr != 0; id++) {
+ if (cpu->device == id->pvr)
+ {
+ goto found;
+ }
+ }
+ }
+ die("Unknown cpu");
+ return;
+ found:
+ cpu->ops = driver->ops;
+}
+#endif
void cpu_initialize(void)
{
@@ -27,7 +47,7 @@ void cpu_initialize(void)
}
/* Find what type of cpu we are dealing with */
- cpu->vendor 0; /* PPC cpus do not have a vendor field */
+ cpu->vendor = 0; /* PPC cpus do not have a vendor field */
cpu->device = ppc_getpvr();
display_cpuid(cpu);
@@ -44,7 +64,6 @@ void cpu_initialize(void)
#endif
/* Turn on caching if we haven't already */
- printk_info("CPU #%d Initialized\n", processor_id);
- return processor_id;
+ printk_info("CPU #%d Initialized\n", info->index);
+ return;
}
-
diff --git a/src/arch/ppc/lib/div64.S b/src/arch/ppc/lib/div64.S
new file mode 100644
index 0000000000..48047747e0
--- /dev/null
+++ b/src/arch/ppc/lib/div64.S
@@ -0,0 +1,58 @@
+/*
+ * Divide a 64-bit unsigned number by a 32-bit unsigned number.
+ * This routine assumes that the top 32 bits of the dividend are
+ * non-zero to start with.
+ * On entry, r3 points to the dividend, which get overwritten with
+ * the 64-bit quotient, and r4 contains the divisor.
+ * On exit, r3 contains the remainder.
+ *
+ * Copyright (C) 2002 Paul Mackerras, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <ppc_asm.tmpl>
+
+ .globl __div64_32
+__div64_32:
+ lwz r5,0(r3) # get the dividend into r5/r6
+ lwz r6,4(r3)
+ cmplw r5,r4
+ li r7,0
+ li r8,0
+ blt 1f
+ divwu r7,r5,r4 # if dividend.hi >= divisor,
+ mullw r0,r7,r4 # quotient.hi = dividend.hi / divisor
+ subf. r5,r0,r5 # dividend.hi %= divisor
+ beq 3f
+1: mr r11,r5 # here dividend.hi != 0
+ andis. r0,r5,0xc000
+ bne 2f
+ cntlzw r0,r5 # we are shifting the dividend right
+ li r10,-1 # to make it < 2^32, and shifting
+ srw r10,r10,r0 # the divisor right the same amount,
+ add r9,r4,r10 # rounding up (so the estimate cannot
+ andc r11,r6,r10 # ever be too large, only too small)
+ andc r9,r9,r10
+ or r11,r5,r11
+ rotlw r9,r9,r0
+ rotlw r11,r11,r0
+ divwu r11,r11,r9 # then we divide the shifted quantities
+2: mullw r10,r11,r4 # to get an estimate of the quotient,
+ mulhwu r9,r11,r4 # multiply the estimate by the divisor,
+ subfc r6,r10,r6 # take the product from the divisor,
+ add r8,r8,r11 # and add the estimate to the accumulated
+ subfe. r5,r9,r5 # quotient
+ bne 1b
+3: cmplw r6,r4
+ blt 4f
+ divwu r0,r6,r4 # perform the remaining 32-bit division
+ mullw r10,r0,r4 # and get the remainder
+ add r8,r8,r0
+ subf r6,r10,r6
+4: stw r7,0(r3) # return the quotient in *r3
+ stw r8,4(r3)
+ mr r3,r6 # return the remainder in r3
+ blr
diff --git a/src/arch/ppc/lib/pci_ops.c b/src/arch/ppc/lib/pci_ops.c
deleted file mode 100644
index 1e72fb0599..0000000000
--- a/src/arch/ppc/lib/pci_ops.c
+++ /dev/null
@@ -1,105 +0,0 @@
-#include <console/console.h>
-#include <arch/pciconf.h>
-#include <device/pci.h>
-#include <device/pci_ids.h>
-#include <device/pci_ops.h>
-
-static const struct pci_ops *conf;
-struct pci_ops {
- uint8_t (*read8) (uint8_t bus, int devfn, int where);
- uint16_t (*read16) (uint8_t bus, int devfn, int where);
- uint32_t (*read32) (uint8_t bus, int devfn, int where);
- int (*write8) (uint8_t bus, int devfn, int where, uint8_t val);
- int (*write16) (uint8_t bus, int devfn, int where, uint16_t val);
- int (*write32) (uint8_t bus, int devfn, int where, uint32_t val);
-};
-
-struct pci_ops pci_direct_ppc;
-
-/*
- * Before we decide to use direct hardware access mechanisms, we try to do some
- * trivial checks to ensure it at least _seems_ to be working -- we just test
- * whether bus 00 contains a host bridge (this is similar to checking
- * techniques used in XFree86, but ours should be more reliable since we
- * attempt to make use of direct access hints provided by the PCI BIOS).
- *
- * This should be close to trivial, but it isn't, because there are buggy
- * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
- */
-static int pci_sanity_check(const struct pci_ops *o)
-{
- uint16_t class, vendor;
- uint8_t bus;
- int devfn;
-#define PCI_CLASS_BRIDGE_HOST 0x0600
-#define PCI_CLASS_DISPLAY_VGA 0x0300
-#define PCI_VENDOR_ID_COMPAQ 0x0e11
-#define PCI_VENDOR_ID_INTEL 0x8086
-#define PCI_VENDOR_ID_MOTOROLA 0x1057
-#define PCI_VENDOR_ID_IBM 0x1014
-
- for (bus = 0, devfn = 0; devfn < 0x100; devfn++) {
- class = o->read16(bus, devfn, PCI_CLASS_DEVICE);
- vendor = o->read16(bus, devfn, PCI_VENDOR_ID);
- if (((class == PCI_CLASS_BRIDGE_HOST) ||
- (class == PCI_CLASS_DISPLAY_VGA)) ||
- ((vendor == PCI_VENDOR_ID_INTEL) ||
- (vendor == PCI_VENDOR_ID_COMPAQ) ||
- (vendor == PCI_VENDOR_ID_MOTOROLA) ||
- (vendor == PCI_VENDOR_ID_IBM))) {
- return 1;
- }
- }
-
- printk_err("PCI: Sanity check failed\n");
- return 0;
-}
-
-uint8_t pci_read_config8(device_t dev, unsigned where)
-{
- return conf->read8(dev->bus->secondary, dev->path.u.pci.devfn, where);
-}
-
-uint16_t pci_read_config16(struct device *dev, unsigned where)
-{
- return conf->read16(dev->bus->secondary, dev->path.u.pci.devfn, where);
-}
-
-uint32_t pci_read_config32(struct device *dev, unsigned where)
-{
- return conf->read32(dev->bus->secondary, dev->path.u.pci.devfn, where);
-}
-
-void pci_write_config8(struct device *dev, unsigned where, uint8_t val)
-{
- conf->write8(dev->bus->secondary, dev->path.u.pci.devfn, where, val);
-}
-
-void pci_write_config16(struct device *dev, unsigned where, uint16_t val)
-{
- conf->write16(dev->bus->secondary, dev->path.u.pci.devfn, where, val);
-}
-
-void pci_write_config32(struct device *dev, unsigned where, uint32_t val)
-{
- conf->write32(dev->bus->secondary, dev->path.u.pci.devfn, where, val);
-}
-
-/** Set the method to be used for PCI
- */
-void pci_set_method(void)
-{
- conf = &pci_direct_ppc;
- pci_sanity_check(conf);
-}
-
-struct pci_ops pci_direct_ppc =
-{
- pci_ppc_read_config8,
- pci_ppc_read_config16,
- pci_ppc_read_config32,
- pci_ppc_write_config8,
- pci_ppc_write_config16,
- pci_ppc_write_config32
-};
-
diff --git a/src/arch/ppc/lib/pci_ppc_conf1_ops.c b/src/arch/ppc/lib/pci_ppc_conf1_ops.c
new file mode 100644
index 0000000000..12e4529784
--- /dev/null
+++ b/src/arch/ppc/lib/pci_ppc_conf1_ops.c
@@ -0,0 +1,46 @@
+#include <console/console.h>
+#include <arch/pciconf.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+
+static uint8_t ppc_conf1_read_config8(struct bus *pbus, unsigned char bus, int devfn, int where)
+{
+ return pci_ppc_read_config8(bus, devfn, where);
+}
+
+static uint16_t ppc_conf1_read_config16(struct bus *pbus, unsigned char bus, int devfn, int where)
+{
+ return pci_ppc_read_config16(bus, devfn, where);
+}
+
+static uint32_t ppc_conf1_read_config32(struct bus *pbus, unsigned char bus, int devfn, int where)
+{
+ return pci_ppc_read_config32(bus, devfn, where);
+}
+
+static void ppc_conf1_write_config8(struct bus *pbus, unsigned char bus, int devfn, int where, uint8_t val)
+{
+ pci_ppc_write_config8(bus, devfn, where, val);
+}
+
+static void ppc_conf1_write_config16(struct bus *pbus, unsigned char bus, int devfn, int where, uint16_t val)
+{
+ pci_ppc_write_config16(bus, devfn, where, val);
+}
+
+static void ppc_conf1_write_config32(struct bus *pbus, unsigned char bus, int devfn, int where, uint32_t val)
+{
+ pci_ppc_write_config32(bus, devfn, where, val);
+}
+
+const struct pci_bus_operations pci_ppc_conf1 =
+{
+ .read8 = ppc_conf1_read_config8,
+ .read16 = ppc_conf1_read_config16,
+ .read32 = ppc_conf1_read_config32,
+ .write8 = ppc_conf1_write_config8,
+ .write16 = ppc_conf1_write_config16,
+ .write32 = ppc_conf1_write_config32,
+};