summaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/ppc/boot/linuxbios_table.h33
-rw-r--r--src/arch/ppc/include/arch/io.h73
-rw-r--r--src/arch/ppc/include/arch/pciconf.h9
-rw-r--r--src/arch/ppc/lib/pci_ops.c148
4 files changed, 227 insertions, 36 deletions
diff --git a/src/arch/ppc/boot/linuxbios_table.h b/src/arch/ppc/boot/linuxbios_table.h
new file mode 100644
index 0000000000..42c0a07dac
--- /dev/null
+++ b/src/arch/ppc/boot/linuxbios_table.h
@@ -0,0 +1,33 @@
+#ifndef LINUXBIOS_TABLE_H
+#define LINUXBIOS_TABLE_H
+
+#include <boot/linuxbios_tables.h>
+
+struct mem_range;
+
+/* This file holds function prototypes for building the linuxbios table. */
+unsigned long write_linuxbios_table(
+ unsigned long *processor_map,
+ struct mem_range *ram,
+ unsigned long low_table_start, unsigned long low_table_end,
+ unsigned long rom_table_start, unsigned long rom_table_end);
+
+struct lb_header *lb_table_init(unsigned long addr);
+struct lb_record *lb_first_record(struct lb_header *header);
+struct lb_record *lb_last_record(struct lb_header *header);
+struct lb_record *lb_next_record(struct lb_record *rec);
+struct lb_record *lb_new_record(struct lb_header *header);
+struct lb_memory *lb_memory(struct lb_header *header);
+void lb_memory_range(struct lb_memory *mem,
+ uint32_t type, unsigned long startk, unsigned long sizek);
+struct lb_mainboard *lb_mainboard(struct lb_header *header);
+unsigned long lb_table_fini(struct lb_header *header);
+
+/* Routines to extract part so the linuxBIOS table or information
+ * from the linuxBIOS table.
+ */
+struct lb_memory *get_lb_mem(void);
+
+extern struct cmos_option_table option_table;
+
+#endif /* LINUXBIOS_TABLE_H */
diff --git a/src/arch/ppc/include/arch/io.h b/src/arch/ppc/include/arch/io.h
index f51f14089e..bc68239a83 100644
--- a/src/arch/ppc/include/arch/io.h
+++ b/src/arch/ppc/include/arch/io.h
@@ -3,7 +3,8 @@
*/
#ifndef _PPC_IO_H
#define _PPC_IO_H
-#include <types.h>
+
+#include <stdint.h>
#define SIO_CONFIG_RA 0x398
#define SIO_CONFIG_RD 0x399
@@ -21,12 +22,12 @@
#define _IO_BASE 0xfe000000
-#define readb(addr) in_8((volatile u8 *)(addr))
-#define writeb(b,addr) out_8((volatile u8 *)(addr), (b))
-#define readw(addr) in_le16((volatile u16 *)(addr))
-#define readl(addr) in_le32((volatile u32 *)(addr))
-#define writew(b,addr) out_le16((volatile u16 *)(addr),(b))
-#define writel(b,addr) out_le32((volatile u32 *)(addr),(b))
+#define readb(addr) in_8((volatile uint8_t *)(addr))
+#define writeb(b,addr) out_8((volatile uint8_t *)(addr), (b))
+#define readw(addr) in_le16((volatile uint16_t *)(addr))
+#define readl(addr) in_le32((volatile uint32_t *)(addr))
+#define writew(b,addr) out_le16((volatile uint16_t *)(addr),(b))
+#define writel(b,addr) out_le32((volatile uint32_t *)(addr),(b))
#define __raw_readb(addr) (*(volatile unsigned char *)(addr))
@@ -42,19 +43,19 @@
* are arrays of bytes, and byte-swapping is not appropriate in
* that case. - paulus
*/
-#define insb(port, buf, ns) _insb((u8 *)((port)+_IO_BASE), (buf), (ns))
-#define outsb(port, buf, ns) _outsb((u8 *)((port)+_IO_BASE), (buf), (ns))
-#define insw(port, buf, ns) _insw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
-#define outsw(port, buf, ns) _outsw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
-#define insl(port, buf, nl) _insl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
-#define outsl(port, buf, nl) _outsl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
-
-#define inb(port) in_8((u8 *)((port)+_IO_BASE))
-#define outb(val, port) out_8((u8 *)((port)+_IO_BASE), (val))
-#define inw(port) in_le16((u16 *)((port)+_IO_BASE))
-#define outw(val, port) out_le16((u16 *)((port)+_IO_BASE), (val))
-#define inl(port) in_le32((u32 *)((port)+_IO_BASE))
-#define outl(val, port) out_le32((u32 *)((port)+_IO_BASE), (val))
+#define insb(port, buf, ns) _insb((uint8_t *)((port)+_IO_BASE), (buf), (ns))
+#define outsb(port, buf, ns) _outsb((uint8_t *)((port)+_IO_BASE), (buf), (ns))
+#define insw(port, buf, ns) _insw_ns((uint16_t *)((port)+_IO_BASE), (buf), (ns))
+#define outsw(port, buf, ns) _outsw_ns((uint16_t *)((port)+_IO_BASE), (buf), (ns))
+#define insl(port, buf, nl) _insl_ns((uint32_t *)((port)+_IO_BASE), (buf), (nl))
+#define outsl(port, buf, nl) _outsl_ns((uint32_t *)((port)+_IO_BASE), (buf), (nl))
+
+#define inb(port) in_8((uint8_t *)((port)+_IO_BASE))
+#define outb(val, port) out_8((uint8_t *)((port)+_IO_BASE), (val))
+#define inw(port) in_le16((uint16_t *)((port)+_IO_BASE))
+#define outw(val, port) out_le16((uint16_t *)((port)+_IO_BASE), (val))
+#define inl(port) in_le32((uint32_t *)((port)+_IO_BASE))
+#define outl(val, port) out_le32((uint32_t *)((port)+_IO_BASE), (val))
#define inb_p(port) inb((port))
#define outb_p(val, port) outb((val), (port))
@@ -63,26 +64,26 @@
#define inl_p(port) inl((port))
#define outl_p(val, port) outl((val), (port))
-extern void _insb(volatile u8 *port, void *buf, int ns);
-extern void _outsb(volatile u8 *port, const void *buf, int ns);
-extern void _insw(volatile u16 *port, void *buf, int ns);
-extern void _outsw(volatile u16 *port, const void *buf, int ns);
-extern void _insl(volatile u32 *port, void *buf, int nl);
-extern void _outsl(volatile u32 *port, const void *buf, int nl);
-extern void _insw_ns(volatile u16 *port, void *buf, int ns);
-extern void _outsw_ns(volatile u16 *port, const void *buf, int ns);
-extern void _insl_ns(volatile u32 *port, void *buf, int nl);
-extern void _outsl_ns(volatile u32 *port, const void *buf, int nl);
+extern void _insb(volatile uint8_t *port, void *buf, int ns);
+extern void _outsb(volatile uint8_t *port, const void *buf, int ns);
+extern void _insw(volatile uint16_t *port, void *buf, int ns);
+extern void _outsw(volatile uint16_t *port, const void *buf, int ns);
+extern void _insl(volatile uint32_t *port, void *buf, int nl);
+extern void _outsl(volatile uint32_t *port, const void *buf, int nl);
+extern void _insw_ns(volatile uint16_t *port, void *buf, int ns);
+extern void _outsw_ns(volatile uint16_t *port, const void *buf, int ns);
+extern void _insl_ns(volatile uint32_t *port, void *buf, int nl);
+extern void _outsl_ns(volatile uint32_t *port, const void *buf, int nl);
/*
* The *_ns versions below don't do byte-swapping.
* Neither do the standard versions now, these are just here
* for older code.
*/
-#define insw_ns(port, buf, ns) _insw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
-#define outsw_ns(port, buf, ns) _outsw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
-#define insl_ns(port, buf, nl) _insl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
-#define outsl_ns(port, buf, nl) _outsl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
+#define insw_ns(port, buf, ns) _insw_ns((uint16_t *)((port)+_IO_BASE), (buf), (ns))
+#define outsw_ns(port, buf, ns) _outsw_ns((uint16_t *)((port)+_IO_BASE), (buf), (ns))
+#define insl_ns(port, buf, nl) _insl_ns((uint32_t *)((port)+_IO_BASE), (buf), (nl))
+#define outsl_ns(port, buf, nl) _outsl_ns((uint32_t *)((port)+_IO_BASE), (buf), (nl))
#define IO_SPACE_LIMIT ~0
@@ -180,9 +181,9 @@ extern inline void out_be32(volatile unsigned *addr, int val)
__asm__ __volatile__("stw%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val));
}
-extern inline void _insw_ns(volatile u16 *port, void *buf, int ns)
+extern inline void _insw_ns(volatile uint16_t *port, void *buf, int ns)
{
- u16 * b = (u16 *)buf;
+ uint16_t * b = (uint16_t *)buf;
while (ns > 0) {
*b++ = readw(port);
diff --git a/src/arch/ppc/include/arch/pciconf.h b/src/arch/ppc/include/arch/pciconf.h
new file mode 100644
index 0000000000..8695ee2294
--- /dev/null
+++ b/src/arch/ppc/include/arch/pciconf.h
@@ -0,0 +1,9 @@
+#ifndef PCI_CONF_REG_INDEX
+
+// These are defined in the PCI spec, and hence are theoretically
+// inclusive of ANYTHING that uses a PCI bus.
+#define PCI_CONF_REG_INDEX 0xcf8
+#define PCI_CONF_REG_DATA 0xcfc
+#define CONFIG_ADDR(bus,devfn,where) (((bus) << 16) | ((devfn) << 8) | (where))
+
+#endif
diff --git a/src/arch/ppc/lib/pci_ops.c b/src/arch/ppc/lib/pci_ops.c
new file mode 100644
index 0000000000..69c9915ad6
--- /dev/null
+++ b/src/arch/ppc/lib/pci_ops.c
@@ -0,0 +1,148 @@
+#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>
+
+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;
+
+extern unsigned __pci_config_read_32(unsigned address);
+extern unsigned __pci_config_read_16(unsigned address);
+extern unsigned __pci_config_read_8(unsigned address);
+extern void __pci_config_write_32(unsigned address, unsigned data);
+extern void __pci_config_write_16(unsigned address, unsigned short data);
+extern void __pci_config_write_8(unsigned address, unsigned char data);
+
+#define CONFIG_CMD(bus,devfn,where) (bus << 16 | devfn << 8 | where | 0x80000000)
+
+/*
+ * Direct access to PCI hardware...
+ */
+
+/*
+ * 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
+
+ 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))) {
+ return 1;
+ }
+ }
+
+ printk_err("PCI: Sanity check failed\n");
+ return 0;
+}
+
+uint8_t pci_read_config8(struct device *dev, unsigned where)
+{
+ return conf->read8(dev->bus->secondary, dev->devfn, where);
+}
+
+uint16_t pci_read_config16(struct device *dev, unsigned where)
+{
+ return conf->read16(dev->bus->secondary, dev->devfn, where);
+}
+
+uint32_t pci_read_config32(struct device *dev, unsigned where)
+{
+ return conf->read32(dev->bus->secondary, dev->devfn, where);
+}
+
+void pci_write_config8(struct device *dev, unsigned where, uint8_t val)
+{
+ conf->write8(dev->bus->secondary, dev->devfn, where, val);
+}
+
+void pci_write_config16(struct device *dev, unsigned where, uint16_t val)
+{
+ conf->write16(dev->bus->secondary, dev->devfn, where, val);
+}
+
+void pci_write_config32(struct device *dev, unsigned where, uint32_t val)
+{
+ conf->write32(dev->bus->secondary, dev->devfn, where, val);
+}
+
+/** Set the method to be used for PCI
+ */
+void pci_set_method(void)
+{
+ conf = &pci_direct_ppc;
+ pci_sanity_check(conf);
+}
+
+static uint8_t pci_ppc_read_config8(unsigned char bus, int devfn, int where)
+{
+ return (uint8_t)__pci_config_read_8(CONFIG_CMD(bus, devfn, where));
+}
+
+static uint16_t pci_ppc_read_config16(unsigned char bus, int devfn, int where)
+{
+ return (uint16_t)__pci_config_read_16(CONFIG_CMD(bus, devfn, where));
+}
+
+static uint32_t pci_ppc_read_config32(unsigned char bus, int devfn, int where)
+{
+ return (uint32_t)__pci_config_read_32(CONFIG_CMD(bus, devfn, where));
+}
+
+static int pci_ppc_write_config8(unsigned char bus, int devfn, int where, uint8_t data)
+{
+ __pci_config_write_8(CONFIG_CMD(bus, devfn, where), data);
+ return 0;
+}
+
+static int pci_ppc_write_config16(unsigned char bus, int devfn, int where, uint16_t data)
+{
+ __pci_config_write_16(CONFIG_CMD(bus, devfn, where), data);
+ return 0;
+}
+
+static int pci_ppc_write_config32(unsigned char bus, int devfn, int where, uint32_t data)
+{
+ __pci_config_write_32(CONFIG_CMD(bus, devfn, where), data);
+ return 0;
+}
+
+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
+};
+