diff options
author | Greg Watson <jarrah@users.sourceforge.net> | 2003-06-13 22:07:53 +0000 |
---|---|---|
committer | Greg Watson <jarrah@users.sourceforge.net> | 2003-06-13 22:07:53 +0000 |
commit | f7092040fd4aba081aad75116c2b9594149d5c66 (patch) | |
tree | 9fff13449dd1e397292668313b57537ade1739d8 /src/arch/ppc | |
parent | 26ba0f5f9bb04e296c3a6320a855639c2f14e83c (diff) |
More FB2 stuff
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@877 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/arch/ppc')
-rw-r--r-- | src/arch/ppc/boot/linuxbios_table.h | 33 | ||||
-rw-r--r-- | src/arch/ppc/include/arch/io.h | 73 | ||||
-rw-r--r-- | src/arch/ppc/include/arch/pciconf.h | 9 | ||||
-rw-r--r-- | src/arch/ppc/lib/pci_ops.c | 148 |
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 +}; + |