Moved from freebios
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@862 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
83
src/arch/ppc/boot/boot.c
Normal file
83
src/arch/ppc/boot/boot.c
Normal file
@@ -0,0 +1,83 @@
|
||||
#include <ip_checksum.h>
|
||||
#include <boot/elf.h>
|
||||
#include <boot/elf_boot.h>
|
||||
#include <string.h>
|
||||
#include <printk.h>
|
||||
|
||||
|
||||
#ifndef CMD_LINE
|
||||
#define CMD_LINE ""
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define UPSZ(X) ((sizeof(X) + 3) &~3)
|
||||
|
||||
static struct {
|
||||
Elf_Bhdr hdr;
|
||||
Elf_Nhdr ft_hdr;
|
||||
unsigned char ft_desc[UPSZ(FIRMWARE_TYPE)];
|
||||
Elf_Nhdr bl_hdr;
|
||||
unsigned char bl_desc[UPSZ(BOOTLOADER)];
|
||||
Elf_Nhdr blv_hdr;
|
||||
unsigned char blv_desc[UPSZ(BOOTLOADER_VERSION)];
|
||||
Elf_Nhdr cmd_hdr;
|
||||
unsigned char cmd_desc[UPSZ(CMD_LINE)];
|
||||
} elf_boot_notes = {
|
||||
.hdr = {
|
||||
.b_signature = 0x0E1FB007,
|
||||
.b_size = sizeof(elf_boot_notes),
|
||||
.b_checksum = 0,
|
||||
.b_records = 4,
|
||||
},
|
||||
.ft_hdr = {
|
||||
.n_namesz = 0,
|
||||
.n_descsz = sizeof(FIRMWARE_TYPE),
|
||||
.n_type = EBN_FIRMWARE_TYPE,
|
||||
},
|
||||
.ft_desc = FIRMWARE_TYPE,
|
||||
.bl_hdr = {
|
||||
.n_namesz = 0,
|
||||
.n_descsz = sizeof(BOOTLOADER),
|
||||
.n_type = EBN_BOOTLOADER_NAME,
|
||||
},
|
||||
.bl_desc = BOOTLOADER,
|
||||
.blv_hdr = {
|
||||
.n_namesz = 0,
|
||||
.n_descsz = sizeof(BOOTLOADER_VERSION),
|
||||
.n_type = EBN_BOOTLOADER_VERSION,
|
||||
},
|
||||
.blv_desc = BOOTLOADER_VERSION,
|
||||
.cmd_hdr = {
|
||||
.n_namesz = 0,
|
||||
.n_descsz = sizeof(CMD_LINE),
|
||||
.n_type = EBN_COMMAND_LINE,
|
||||
},
|
||||
.cmd_desc = CMD_LINE,
|
||||
};
|
||||
|
||||
|
||||
int elf_check_arch(Elf_ehdr *ehdr)
|
||||
{
|
||||
return (
|
||||
(ehdr->e_machine == EM_PPC) &&
|
||||
(ehdr->e_ident[EI_CLASS] == ELFCLASS32) &&
|
||||
(ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
void jmp_to_elf_entry(void *entry, unsigned long buffer)
|
||||
{
|
||||
void (*kernel_entry)(void);
|
||||
kernel_entry = entry;
|
||||
|
||||
/* On ppc we don't currently support loading over LinuxBIOS.
|
||||
* So ignore the buffer.
|
||||
*/
|
||||
|
||||
/* Jump to kernel */
|
||||
kernel_entry();
|
||||
}
|
||||
|
||||
|
285
src/arch/ppc/boot/linuxbios_table.c
Normal file
285
src/arch/ppc/boot/linuxbios_table.c
Normal file
@@ -0,0 +1,285 @@
|
||||
#include <mem.h>
|
||||
#include <ip_checksum.h>
|
||||
#include <boot/linuxbios_tables.h>
|
||||
#include <boot/linuxbios_table.h>
|
||||
#include <printk.h>
|
||||
#include <string.h>
|
||||
#include <version.h>
|
||||
|
||||
|
||||
struct lb_header *lb_table_init(unsigned long addr)
|
||||
{
|
||||
struct lb_header *header;
|
||||
|
||||
/* 16 byte align the address */
|
||||
addr += 15;
|
||||
addr &= ~15;
|
||||
|
||||
header = (void *)addr;
|
||||
header->signature[0] = 'L';
|
||||
header->signature[1] = 'B';
|
||||
header->signature[2] = 'I';
|
||||
header->signature[3] = 'O';
|
||||
header->header_bytes = sizeof(*header);
|
||||
header->header_checksum = 0;
|
||||
header->table_bytes = 0;
|
||||
header->table_checksum = 0;
|
||||
header->table_entries = 0;
|
||||
return header;
|
||||
}
|
||||
|
||||
struct lb_record *lb_first_record(struct lb_header *header)
|
||||
{
|
||||
struct lb_record *rec;
|
||||
rec = (void *)(((char *)header) + sizeof(*header));
|
||||
return rec;
|
||||
}
|
||||
|
||||
struct lb_record *lb_last_record(struct lb_header *header)
|
||||
{
|
||||
struct lb_record *rec;
|
||||
rec = (void *)(((char *)header) + sizeof(*header) + header->table_bytes);
|
||||
return rec;
|
||||
}
|
||||
|
||||
struct lb_record *lb_next_record(struct lb_record *rec)
|
||||
{
|
||||
rec = (void *)(((char *)rec) + rec->size);
|
||||
return rec;
|
||||
}
|
||||
|
||||
struct lb_record *lb_new_record(struct lb_header *header)
|
||||
{
|
||||
struct lb_record *rec;
|
||||
rec = lb_last_record(header);
|
||||
if (header->table_entries) {
|
||||
header->table_bytes += rec->size;
|
||||
}
|
||||
rec = lb_last_record(header);
|
||||
header->table_entries++;
|
||||
rec->tag = LB_TAG_UNUSED;
|
||||
rec->size = sizeof(*rec);
|
||||
return rec;
|
||||
}
|
||||
|
||||
|
||||
struct lb_memory *lb_memory(struct lb_header *header)
|
||||
{
|
||||
struct lb_record *rec;
|
||||
struct lb_memory *mem;
|
||||
rec = lb_new_record(header);
|
||||
mem = (struct lb_memory *)rec;
|
||||
mem->tag = LB_TAG_MEMORY;
|
||||
mem->size = sizeof(*mem);
|
||||
return mem;
|
||||
}
|
||||
|
||||
struct lb_mainboard *lb_mainboard(struct lb_header *header)
|
||||
{
|
||||
struct lb_record *rec;
|
||||
struct lb_mainboard *mainboard;
|
||||
rec = lb_new_record(header);
|
||||
mainboard = (struct lb_mainboard *)rec;
|
||||
mainboard->tag = LB_TAG_MAINBOARD;
|
||||
|
||||
mainboard->size = (sizeof(*mainboard) +
|
||||
strlen(mainboard_vendor) + 1 +
|
||||
strlen(mainboard_part_number) + 1 +
|
||||
3) & ~3;
|
||||
|
||||
mainboard->vendor_idx = 0;
|
||||
mainboard->part_number_idx = strlen(mainboard_vendor) + 1;
|
||||
|
||||
memcpy(mainboard->strings + mainboard->vendor_idx,
|
||||
mainboard_vendor, strlen(mainboard_vendor) + 1);
|
||||
memcpy(mainboard->strings + mainboard->part_number_idx,
|
||||
mainboard_part_number, strlen(mainboard_part_number) + 1);
|
||||
|
||||
return mainboard;
|
||||
}
|
||||
|
||||
void lb_strings(struct lb_header *header)
|
||||
{
|
||||
static const struct {
|
||||
uint32_t tag;
|
||||
const uint8_t *string;
|
||||
} strings[] = {
|
||||
{ LB_TAG_VERSION, linuxbios_version, },
|
||||
{ LB_TAG_EXTRA_VERSION, linuxbios_extra_version, },
|
||||
{ LB_TAG_BUILD, linuxbios_build, },
|
||||
{ LB_TAG_COMPILE_TIME, linuxbios_compile_time, },
|
||||
{ LB_TAG_COMPILE_BY, linuxbios_compile_by, },
|
||||
{ LB_TAG_COMPILE_HOST, linuxbios_compile_host, },
|
||||
{ LB_TAG_COMPILE_DOMAIN, linuxbios_compile_domain, },
|
||||
{ LB_TAG_COMPILER, linuxbios_compiler, },
|
||||
{ LB_TAG_LINKER, linuxbios_linker, },
|
||||
{ LB_TAG_ASSEMBLER, linuxbios_assembler, },
|
||||
};
|
||||
int i;
|
||||
for(i = 0; i < sizeof(strings)/sizeof(strings[0]); i++) {
|
||||
struct lb_record *rec;
|
||||
struct lb_string *str;
|
||||
size_t len;
|
||||
rec = lb_new_record(header);
|
||||
str = (struct lb_string *)rec;
|
||||
len = strlen(strings[i].string);
|
||||
str->tag = strings[i].tag;
|
||||
str->size = (sizeof(*rec) + len + 1 + 3) & ~3;
|
||||
memcpy(str->string, strings[i].string, len+1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Some version of gcc have problems with 64 bit types so
|
||||
* take an unsigned long instead of a uint64_t for now.
|
||||
*/
|
||||
void lb_memory_range(struct lb_memory *mem,
|
||||
uint32_t type, unsigned long start, unsigned long size)
|
||||
{
|
||||
int entries;
|
||||
entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]);
|
||||
mem->map[entries].start = start;
|
||||
mem->map[entries].size = size;
|
||||
mem->map[entries].type = type;
|
||||
mem->size += sizeof(mem->map[0]);
|
||||
}
|
||||
|
||||
static void lb_memory_rangek(struct lb_memory *mem,
|
||||
uint32_t type, unsigned long startk, unsigned long endk)
|
||||
{
|
||||
int entries;
|
||||
entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]);
|
||||
mem->map[entries].start = startk;
|
||||
mem->map[entries].start <<= 10;
|
||||
mem->map[entries].size = endk - startk;
|
||||
mem->map[entries].size <<= 10;
|
||||
mem->map[entries].type = type;
|
||||
mem->size += sizeof(mem->map[0]);
|
||||
}
|
||||
|
||||
static void lb_reserve_table_memory(struct lb_header *head)
|
||||
{
|
||||
struct lb_record *last_rec;
|
||||
struct lb_memory *mem;
|
||||
uint64_t start;
|
||||
uint64_t end;
|
||||
int i, entries;
|
||||
|
||||
last_rec = lb_last_record(head);
|
||||
mem = get_lb_mem();
|
||||
start = (unsigned long)head;
|
||||
end = (unsigned long)last_rec;
|
||||
entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]);
|
||||
/* Resize the right two memory areas so this table is in
|
||||
* a reserved area of memory. Everything has been carefully
|
||||
* setup so that is all we need to do.
|
||||
*/
|
||||
for(i = 0; i < entries; i++ ) {
|
||||
uint64_t map_start = mem->map[i].start;
|
||||
uint64_t map_end = map_start + mem->map[i].size;
|
||||
/* Does this area need to be expanded? */
|
||||
if (map_end == start) {
|
||||
mem->map[i].size = end - map_start;
|
||||
}
|
||||
/* Does this area need to be contracted? */
|
||||
else if (map_start == start) {
|
||||
mem->map[i].start = end;
|
||||
mem->map[i].size = map_end - end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned long lb_table_fini(struct lb_header *head)
|
||||
{
|
||||
struct lb_record *rec, *first_rec;
|
||||
rec = lb_last_record(head);
|
||||
if (head->table_entries) {
|
||||
head->table_bytes += rec->size;
|
||||
}
|
||||
lb_reserve_table_memory(head);
|
||||
first_rec = lb_first_record(head);
|
||||
head->table_checksum = compute_ip_checksum(first_rec, head->table_bytes);
|
||||
head->header_checksum = 0;
|
||||
head->header_checksum = compute_ip_checksum(head, sizeof(*head));
|
||||
printk_debug("Wrote linuxbios table at: %p - %p checksum %lx\n",
|
||||
head, rec, head->table_checksum);
|
||||
return (unsigned long)rec;
|
||||
}
|
||||
|
||||
|
||||
/* Routines to extract part so the linuxBIOS table or
|
||||
* information from the linuxBIOS table after we have written it.
|
||||
* Currently get_lb_mem relies on a global we can change the
|
||||
* implementaiton.
|
||||
*/
|
||||
static struct lb_memory *mem_ranges = 0;
|
||||
struct lb_memory *get_lb_mem(void)
|
||||
{
|
||||
return mem_ranges;
|
||||
}
|
||||
|
||||
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_startk, unsigned long rom_table_endk)
|
||||
{
|
||||
unsigned long table_size;
|
||||
struct mem_range *ramp;
|
||||
struct lb_header *head;
|
||||
struct lb_memory *mem;
|
||||
#if HAVE_OPTION_TABLE == 1
|
||||
struct lb_record *rec_dest, *rec_src;
|
||||
#endif
|
||||
|
||||
head = lb_table_init(low_table_end);
|
||||
low_table_end = (unsigned long)head;
|
||||
#if HAVE_OPTION_TABLE == 1
|
||||
/* Write the option config table... */
|
||||
rec_dest = lb_new_record(head);
|
||||
rec_src = (struct lb_record *)&option_table;
|
||||
memcpy(rec_dest, rec_src, rec_src->size);
|
||||
#endif
|
||||
mem = lb_memory(head);
|
||||
mem_ranges = mem;
|
||||
/* I assume there is always ram at address 0 */
|
||||
/* Reserve our tables in low memory */
|
||||
table_size = (low_table_end - low_table_start);
|
||||
lb_memory_range(mem, LB_MEM_TABLE, 0, table_size);
|
||||
lb_memory_range(mem, LB_MEM_RAM, table_size, (ram[0].sizek << 10) - table_size);
|
||||
/* Reserving pci memory mapped space will keep the kernel from booting seeing
|
||||
* any pci resources.
|
||||
*/
|
||||
for(ramp = &ram[1]; ramp->sizek; ramp++) {
|
||||
unsigned long startk, endk;
|
||||
startk = ramp->basek;
|
||||
endk = startk + ramp->sizek;
|
||||
if ((startk < rom_table_startk) && (endk > rom_table_startk)) {
|
||||
lb_memory_rangek(mem, LB_MEM_RAM, startk, rom_table_startk);
|
||||
startk = rom_table_startk;
|
||||
}
|
||||
if ((startk == rom_table_startk) && (endk > startk)) {
|
||||
unsigned long tend;
|
||||
tend = rom_table_endk;
|
||||
if (tend > endk) {
|
||||
tend = endk;
|
||||
}
|
||||
lb_memory_rangek(mem, LB_MEM_TABLE, rom_table_startk, tend);
|
||||
startk = tend;
|
||||
}
|
||||
if (endk > startk) {
|
||||
lb_memory_rangek(mem, LB_MEM_RAM, startk, endk);
|
||||
}
|
||||
}
|
||||
|
||||
/* Record our motheboard */
|
||||
lb_mainboard(head);
|
||||
/* Record our various random string information */
|
||||
lb_strings(head);
|
||||
|
||||
low_table_end = lb_table_fini(head);
|
||||
|
||||
/* Remember where my valid memory ranges are */
|
||||
return low_table_end;
|
||||
}
|
8
src/arch/ppc/include/arch/boot/boot.h
Normal file
8
src/arch/ppc/include/arch/boot/boot.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef ASM_I386_BOOT_H
|
||||
#define ASM_I386_BOOT_H
|
||||
|
||||
#define ELF_CLASS ELFCLASS32
|
||||
#define ELF_DATA ELFDATA2MSB
|
||||
#define ELF_ARCH EM_PPC
|
||||
|
||||
#endif /* ASM_I386_BOOT_H */
|
192
src/arch/ppc/include/arch/io.h
Normal file
192
src/arch/ppc/include/arch/io.h
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* BK Id: SCCS/s.io.h 1.14 10/16/01 15:58:42 trini
|
||||
*/
|
||||
#ifndef _PPC_IO_H
|
||||
#define _PPC_IO_H
|
||||
#include <types.h>
|
||||
|
||||
#define SIO_CONFIG_RA 0x398
|
||||
#define SIO_CONFIG_RD 0x399
|
||||
|
||||
#define SLOW_DOWN_IO
|
||||
|
||||
#define PMAC_ISA_MEM_BASE 0
|
||||
#define PMAC_PCI_DRAM_OFFSET 0
|
||||
#define CHRP_ISA_IO_BASE 0xf8000000
|
||||
#define CHRP_ISA_MEM_BASE 0xf7000000
|
||||
#define CHRP_PCI_DRAM_OFFSET 0
|
||||
#define PREP_ISA_IO_BASE 0x80000000
|
||||
#define PREP_ISA_MEM_BASE 0xc0000000
|
||||
#define PREP_PCI_DRAM_OFFSET 0x80000000
|
||||
|
||||
#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 __raw_readb(addr) (*(volatile unsigned char *)(addr))
|
||||
#define __raw_readw(addr) (*(volatile unsigned short *)(addr))
|
||||
#define __raw_readl(addr) (*(volatile unsigned int *)(addr))
|
||||
#define __raw_writeb(v, addr) (*(volatile unsigned char *)(addr) = (v))
|
||||
#define __raw_writew(v, addr) (*(volatile unsigned short *)(addr) = (v))
|
||||
#define __raw_writel(v, addr) (*(volatile unsigned int *)(addr) = (v))
|
||||
|
||||
/*
|
||||
* The insw/outsw/insl/outsl macros don't do byte-swapping.
|
||||
* They are only used in practice for transferring buffers which
|
||||
* 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 inb_p(port) inb((port))
|
||||
#define outb_p(val, port) outb((val), (port))
|
||||
#define inw_p(port) inw((port))
|
||||
#define outw_p(val, port) outw((val), (port))
|
||||
#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);
|
||||
|
||||
/*
|
||||
* 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 IO_SPACE_LIMIT ~0
|
||||
|
||||
#define memset_io(a,b,c) memset((void *)(a),(b),(c))
|
||||
#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c))
|
||||
#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c))
|
||||
|
||||
/*
|
||||
* Enforce In-order Execution of I/O:
|
||||
* Acts as a barrier to ensure all previous I/O accesses have
|
||||
* completed before any further ones are issued.
|
||||
*/
|
||||
extern inline void eieio(void)
|
||||
{
|
||||
__asm__ __volatile__ ("eieio" : : : "memory");
|
||||
}
|
||||
|
||||
/* Enforce in-order execution of data I/O.
|
||||
* No distinction between read/write on PPC; use eieio for all three.
|
||||
*/
|
||||
#define iobarrier_rw() eieio()
|
||||
#define iobarrier_r() eieio()
|
||||
#define iobarrier_w() eieio()
|
||||
|
||||
/*
|
||||
* 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
|
||||
*/
|
||||
extern inline int in_8(volatile unsigned char *addr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
__asm__ __volatile__("lbz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr));
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern inline void out_8(volatile unsigned char *addr, int val)
|
||||
{
|
||||
__asm__ __volatile__("stb%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val));
|
||||
}
|
||||
|
||||
extern inline int in_le16(volatile unsigned short *addr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
__asm__ __volatile__("lhbrx %0,0,%1; eieio" : "=r" (ret) :
|
||||
"r" (addr), "m" (*addr));
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern inline int in_be16(volatile unsigned short *addr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
__asm__ __volatile__("lhz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr));
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern inline void out_le16(volatile unsigned short *addr, int val)
|
||||
{
|
||||
__asm__ __volatile__("sthbrx %1,0,%2; eieio" : "=m" (*addr) :
|
||||
"r" (val), "r" (addr));
|
||||
}
|
||||
|
||||
extern inline void out_be16(volatile unsigned short *addr, int val)
|
||||
{
|
||||
__asm__ __volatile__("sth%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val));
|
||||
}
|
||||
|
||||
extern inline unsigned in_le32(volatile unsigned *addr)
|
||||
{
|
||||
unsigned ret;
|
||||
|
||||
__asm__ __volatile__("lwbrx %0,0,%1; eieio" : "=r" (ret) :
|
||||
"r" (addr), "m" (*addr));
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern inline unsigned in_be32(volatile unsigned *addr)
|
||||
{
|
||||
unsigned ret;
|
||||
|
||||
__asm__ __volatile__("lwz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr));
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern inline void out_le32(volatile unsigned *addr, int val)
|
||||
{
|
||||
__asm__ __volatile__("stwbrx %1,0,%2; eieio" : "=m" (*addr) :
|
||||
"r" (val), "r" (addr));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
u16 * b = (u16 *)buf;
|
||||
|
||||
while (ns > 0) {
|
||||
*b++ = readw(port);
|
||||
ns--;
|
||||
}
|
||||
}
|
||||
#endif
|
54
src/arch/ppc/include/arch/pirq_routing.h
Normal file
54
src/arch/ppc/include/arch/pirq_routing.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#ifndef ARCH_PIRQ_ROUTING_H
|
||||
#define ARCH_PIRQ_ROUTING_H
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#define PIRQ_SIGNATURE (('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24))
|
||||
#define PIRQ_VERSION 0x0100
|
||||
|
||||
struct irq_info {
|
||||
u8 bus, devfn; /* Bus, device and function */
|
||||
struct {
|
||||
u8 link; /* IRQ line ID, chipset dependent, 0=not routed */
|
||||
u16 bitmap; /* Available IRQs */
|
||||
} __attribute__((packed)) irq[4];
|
||||
u8 slot; /* Slot number, 0=onboard */
|
||||
u8 rfu;
|
||||
} __attribute__((packed));
|
||||
|
||||
#if defined(IRQ_SLOT_COUNT)
|
||||
#define IRQ_SLOTS_COUNT IRQ_SLOT_COUNT
|
||||
#elif (__GNUC__ < 3)
|
||||
#define IRQ_SLOTS_COUNT 1
|
||||
#else
|
||||
#define IRQ_SLOTS_COUNT
|
||||
#endif
|
||||
|
||||
struct irq_routing_table {
|
||||
u32 signature; /* PIRQ_SIGNATURE should be here */
|
||||
u16 version; /* PIRQ_VERSION */
|
||||
u16 size; /* Table size in bytes */
|
||||
u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */
|
||||
u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */
|
||||
u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */
|
||||
u32 miniport_data; /* Crap */
|
||||
u8 rfu[11];
|
||||
u8 checksum; /* Modulo 256 checksum must give zero */
|
||||
struct irq_info slots[IRQ_SLOTS_COUNT];
|
||||
} __attribute__((packed));
|
||||
|
||||
extern const struct irq_routing_table intel_irq_routing_table;
|
||||
|
||||
#if defined(DEBUG) && defined(HAVE_PIRQ_TABLE)
|
||||
void check_pirq_routing_table(void);
|
||||
#else
|
||||
#define check_pirq_routing_table() do {} while(0)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_PIRQ_TABLE)
|
||||
unsigned long copy_pirq_routing_table(unsigned long start);
|
||||
#else
|
||||
#define copy_pirq_routing_table(start) (start)
|
||||
#endif
|
||||
|
||||
#endif /* ARCH_PIRQ_ROUTING_H */
|
22
src/arch/ppc/include/bitops.h
Normal file
22
src/arch/ppc/include/bitops.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef I386_BITOPS_H
|
||||
#define I386_BITOPS_H
|
||||
|
||||
/**
|
||||
* log2 - Find the truncated log base 2 of x
|
||||
*/
|
||||
|
||||
static inline unsigned long log2(unsigned long x)
|
||||
{
|
||||
unsigned long r = 0;
|
||||
/*
|
||||
__asm__(
|
||||
"bsrl %1, %0\n\t"
|
||||
"jnz 1f\n\t"
|
||||
"movl $-1, %0\n\t"
|
||||
"1:\n\t"
|
||||
: "=r" (r) : "r" (x));
|
||||
*/
|
||||
return r;
|
||||
|
||||
}
|
||||
#endif /* I386_BITOPS_H */
|
21
src/arch/ppc/include/ppc.h
Normal file
21
src/arch/ppc/include/ppc.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/* $Id$ */
|
||||
/* Copyright 2000 AG Electronics Ltd. */
|
||||
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
|
||||
|
||||
#ifndef _PPC_H
|
||||
#define _PPC_H
|
||||
|
||||
#define BIG_ENDIAN
|
||||
#define RODATA __attribute__ ((__section__ (".rodata")))
|
||||
|
||||
/* Do CPU specific setup, with optional icache */
|
||||
void ppc_setup_cpu(int icache);
|
||||
|
||||
void ppc_enable_dcache(void);
|
||||
void ppc_disable_dcache(void);
|
||||
void ppc_enable_mmu(void);
|
||||
|
||||
/* Describe which sort of ppc CPU I am */
|
||||
void ppc_identify(void);
|
||||
|
||||
#endif
|
293
src/arch/ppc/include/ppc_asm.tmpl
Normal file
293
src/arch/ppc/include/ppc_asm.tmpl
Normal file
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* (C) Copyright 2000
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains all the macros and symbols which define
|
||||
* a PowerPC assembly language environment.
|
||||
*/
|
||||
#ifndef __PPC_ASM_TMPL__
|
||||
#define __PPC_ASM_TMPL__
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* These definitions simplify the ugly declarations necessary for GOT
|
||||
* definitions.
|
||||
*
|
||||
* Stolen from prepboot/bootldr.h, (C) 1998 Gabriel Paubert, paubert@iram.es
|
||||
*
|
||||
* Uses r14 to access the GOT
|
||||
*/
|
||||
|
||||
#define START_GOT \
|
||||
.section ".got2","aw"; \
|
||||
.LCTOC1 = .+32768
|
||||
|
||||
#define END_GOT \
|
||||
.text
|
||||
|
||||
#define GET_GOT \
|
||||
bl 1f ; \
|
||||
.text 2 ; \
|
||||
0: .long .LCTOC1-1f ; \
|
||||
.text ; \
|
||||
1: mflr r14 ; \
|
||||
lwz r0,0b-1b(r14) ; \
|
||||
add r14,r0,r14 ;
|
||||
|
||||
#define GOT_ENTRY(NAME) .L_ ## NAME = . - .LCTOC1 ; .long NAME
|
||||
|
||||
#define GOT(NAME) .L_ ## NAME (r14)
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Register names
|
||||
*/
|
||||
#define r0 0
|
||||
#define r1 1
|
||||
#define r2 2
|
||||
#define r3 3
|
||||
#define r4 4
|
||||
#define r5 5
|
||||
#define r6 6
|
||||
#define r7 7
|
||||
#define r8 8
|
||||
#define r9 9
|
||||
#define r10 10
|
||||
#define r11 11
|
||||
#define r12 12
|
||||
#define r13 13
|
||||
#define r14 14
|
||||
#define r15 15
|
||||
#define r16 16
|
||||
#define r17 17
|
||||
#define r18 18
|
||||
#define r19 19
|
||||
#define r20 20
|
||||
#define r21 21
|
||||
#define r22 22
|
||||
#define r23 23
|
||||
#define r24 24
|
||||
#define r25 25
|
||||
#define r26 26
|
||||
#define r27 27
|
||||
#define r28 28
|
||||
#define r29 29
|
||||
#define r30 30
|
||||
#define r31 31
|
||||
|
||||
/*
|
||||
* FP register names
|
||||
*/
|
||||
#define fr0 0
|
||||
#define fr1 1
|
||||
#define fr2 2
|
||||
#define fr3 3
|
||||
#define fr4 4
|
||||
#define fr5 5
|
||||
#define fr6 6
|
||||
#define fr7 7
|
||||
#define fr8 8
|
||||
#define fr9 9
|
||||
#define fr10 10
|
||||
#define fr11 11
|
||||
#define fr12 12
|
||||
#define fr13 13
|
||||
#define fr14 14
|
||||
#define fr15 15
|
||||
#define fr16 16
|
||||
#define fr17 17
|
||||
#define fr18 18
|
||||
#define fr19 19
|
||||
#define fr20 20
|
||||
#define fr21 21
|
||||
#define fr22 22
|
||||
#define fr23 23
|
||||
#define fr24 24
|
||||
#define fr25 25
|
||||
#define fr26 26
|
||||
#define fr27 27
|
||||
#define fr28 28
|
||||
#define fr29 29
|
||||
#define fr30 30
|
||||
#define fr31 31
|
||||
|
||||
/* Some special registers */
|
||||
|
||||
#define TBRU 269 /* Time base Upper/Lower (Reading) */
|
||||
#define TBRL 268
|
||||
#define TBWU 284 /* Time base Upper/Lower (Writing) */
|
||||
#define TBWL 285
|
||||
#define XER 1
|
||||
#define LR 8
|
||||
#define CTR 9
|
||||
#define HID0 1008 /* Hardware Implementation */
|
||||
#define PVR 287 /* Processor Version */
|
||||
#define SDR1 25 /* MMU hash base register */
|
||||
#define DAR 19 /* Data Address Register */
|
||||
#define SPR0 272 /* Supervisor Private Registers */
|
||||
#define SPRG0 272
|
||||
#define SPR1 273
|
||||
#define SPRG1 273
|
||||
#define SPR2 274
|
||||
#define SPRG2 274
|
||||
#define SPR3 275
|
||||
#define SPRG3 275
|
||||
#define DSISR 18
|
||||
#define SRR0 26 /* Saved Registers (exception) */
|
||||
#define SRR1 27
|
||||
#define DEC 22 /* Decrementer */
|
||||
#define EAR 282 /* External Address Register */
|
||||
#define ICR 148 /* Interrupt Cause Register (37-44) */
|
||||
#define DER 149
|
||||
#define COUNTA 150 /* Breakpoint Counter (37-44) */
|
||||
#define COUNTB 151 /* Breakpoint Counter (37-44) */
|
||||
#define LCTRL1 156 /* Load/Store Support (37-40) */
|
||||
#define LCTRL2 157 /* Load/Store Support (37-41) */
|
||||
#define ICTRL 158
|
||||
|
||||
/* Registers in the processor's internal memory map that we use.
|
||||
*/
|
||||
#define IMMR 0xff000000
|
||||
|
||||
#define SYPCR 0x00000004
|
||||
#define BR0 0x00000100
|
||||
#define OR0 0x00000104
|
||||
#define BR1 0x00000108
|
||||
#define OR1 0x0000010c
|
||||
#define BR2 0x00000110
|
||||
#define OR2 0x00000114
|
||||
#define BR3 0x00000118
|
||||
#define OR3 0x0000011c
|
||||
#define BR4 0x00000120
|
||||
#define OR4 0x00000124
|
||||
|
||||
#define MAR 0x00000164
|
||||
#define MCR 0x00000168
|
||||
#define MAMR 0x00000170
|
||||
#define MBMR 0x00000174
|
||||
#define MSTAT 0x00000178
|
||||
#define MPTPR 0x0000017a
|
||||
#define MDR 0x0000017c
|
||||
|
||||
#define TBSCR 0x00000200
|
||||
#define TBREFF0 0x00000204
|
||||
|
||||
#define PLPRCR 0x00000284
|
||||
|
||||
#define curptr r2
|
||||
|
||||
#define SYNC \
|
||||
sync; \
|
||||
isync
|
||||
|
||||
/*
|
||||
* Macros for storing registers into and loading registers from
|
||||
* exception frames.
|
||||
*/
|
||||
#define SAVE_GPR(n, base) stw n,GPR0+4*(n)(base)
|
||||
#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base)
|
||||
#define SAVE_4GPRS(n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base)
|
||||
#define SAVE_8GPRS(n, base) SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base)
|
||||
#define SAVE_10GPRS(n, base) SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base)
|
||||
#define REST_GPR(n, base) lwz n,GPR0+4*(n)(base)
|
||||
#define REST_2GPRS(n, base) REST_GPR(n, base); REST_GPR(n+1, base)
|
||||
#define REST_4GPRS(n, base) REST_2GPRS(n, base); REST_2GPRS(n+2, base)
|
||||
#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base)
|
||||
#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base)
|
||||
|
||||
/*
|
||||
* GCC sometimes accesses words at negative offsets from the stack
|
||||
* pointer, although the SysV ABI says it shouldn't. To cope with
|
||||
* this, we leave this much untouched space on the stack on exception
|
||||
* entry.
|
||||
*/
|
||||
#define STACK_UNDERHEAD 64
|
||||
|
||||
#if 0 /* we don't use virtual addresses in PPCBOOT */
|
||||
#define tophys(rd,rs,rt) addis rd,rs,-KERNELBASE@h
|
||||
#define tovirt(rd,rs,rt) addis rd,rs,KERNELBASE@h
|
||||
#else
|
||||
#define tophys(rd,rs,rt) mr rd,rs
|
||||
#define tovirt(rd,rs,rt) mr rd,rs
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Exception entry code. This code runs with address translation
|
||||
* turned off, i.e. using physical addresses.
|
||||
* We assume sprg3 has the physical address of the current
|
||||
* task's thread_struct.
|
||||
*/
|
||||
#define EXCEPTION_PROLOG \
|
||||
mtspr SPRG0,r20; \
|
||||
mtspr SPRG1,r21; \
|
||||
mfcr r20; \
|
||||
tophys(r21,r1,r21); /* use tophys(kernel sp) otherwise */ \
|
||||
subi r21,r21,INT_FRAME_SIZE+STACK_UNDERHEAD; /* alloc exc. frame */\
|
||||
1: stw r20,_CCR(r21); /* save registers */ \
|
||||
stw r22,GPR22(r21); \
|
||||
stw r23,GPR23(r21); \
|
||||
mfspr r20,SPRG0; \
|
||||
stw r20,GPR20(r21); \
|
||||
mfspr r22,SPRG1; \
|
||||
stw r22,GPR21(r21); \
|
||||
mflr r20; \
|
||||
stw r20,_LINK(r21); \
|
||||
mfctr r22; \
|
||||
stw r22,_CTR(r21); \
|
||||
mfspr r20,XER; \
|
||||
stw r20,_XER(r21); \
|
||||
mfspr r22,SRR0; \
|
||||
mfspr r23,SRR1; \
|
||||
stw r0,GPR0(r21); \
|
||||
stw r1,GPR1(r21); \
|
||||
stw r2,GPR2(r21); \
|
||||
stw r1,0(r21); \
|
||||
tovirt(r1,r21,r1); /* set new kernel sp */ \
|
||||
SAVE_4GPRS(3, r21);
|
||||
/*
|
||||
* Note: code which follows this uses cr0.eq (set if from kernel),
|
||||
* r21, r22 (SRR0), and r23 (SRR1).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Exception vectors.
|
||||
*
|
||||
* The data words for `hdlr' and `int_return' are initialized with
|
||||
* OFFSET values only; they must be relocated first before they can
|
||||
* be used!
|
||||
*/
|
||||
#define STD_EXCEPTION(n, label, hdlr) \
|
||||
. = n; \
|
||||
label: \
|
||||
EXCEPTION_PROLOG; \
|
||||
lwz r3,GOT(transfer_to_handler); \
|
||||
mtlr r3; \
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD; \
|
||||
li r20,MSR_KERNEL; \
|
||||
blrl ; \
|
||||
.L_ ## label : \
|
||||
.long hdlr - _start + EXC_OFF_SYS_RESET; \
|
||||
.long int_return - _start + EXC_OFF_SYS_RESET
|
||||
|
||||
|
||||
#endif /* __PPC_ASM_TMPL__ */
|
128
src/arch/ppc/include/ppcreg.h
Normal file
128
src/arch/ppc/include/ppcreg.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/* $Id$ */
|
||||
/* Copyright 2000 AG Electronics Ltd. */
|
||||
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
|
||||
|
||||
/* In the MSR, not all bits are interesting to us
|
||||
13 - POW - Power management
|
||||
14 - TGPR - temporary registers for page table routines
|
||||
15 - ILE - Exception little endian
|
||||
16 - EE - External interrupts
|
||||
17 - PR - Privilege level
|
||||
18 - FP - Floating Point available
|
||||
19 - ME - Machine check exception enable
|
||||
20 - FE0 - Floating exception mode 0
|
||||
21 - SE - Single step trace mode
|
||||
22 - BE - Branch trace enable
|
||||
23 - FE1 - Floating exception mode 1
|
||||
25 - IP - Exception prefix
|
||||
26 - IR - Instruction address translation
|
||||
27 - DR - Data address translation
|
||||
30 - RI - Recoverable exception
|
||||
31 - LE - Little endian mode
|
||||
MSR_MASK is the bits we do not change.
|
||||
*/
|
||||
|
||||
#define MSR_MASK 0xfff8008c
|
||||
#define MSR_POW 0x00040000
|
||||
#define MSR_TGPR 0x00020000
|
||||
#define MSR_ILE 0x00010000
|
||||
#define MSR_EE 0x00008000
|
||||
#define MSR_PR 0x00004000
|
||||
#define MSR_FP 0x00002000
|
||||
#define MSR_ME 0x00001000
|
||||
#define MSR_FE0 0x00000800
|
||||
#define MSR_SE 0x00000400
|
||||
#define MSR_BE 0x00000200
|
||||
#define MSR_FE1 0x00000100
|
||||
#define MSR_IP 0x00000040
|
||||
#define MSR_IR 0x00000020
|
||||
#define MSR_DR 0x00000010
|
||||
#define MSR_RI 0x00000002
|
||||
#define MSR_LE 0x00000001
|
||||
|
||||
#define MSR_DEFAULT (MSR_FP | MSR_IR | MSR_DR)
|
||||
|
||||
/* We are interested in the following hid0 bits:
|
||||
6 - ECLK - Enable external test clock (603 only)
|
||||
11 - DPM - Turn on dynamic power management (603 only)
|
||||
15 - NHR - Not hard reset
|
||||
16 - ICE - Instruction cache enable
|
||||
17 - DCE - Data cache enable
|
||||
18 - ILOCK - Instruction cache lock
|
||||
19 - DLOCK - Data cache lock
|
||||
20 - ICFI - Instruction cache invalidate
|
||||
21 - DCFI - Data cache invalidate
|
||||
24 - NOSER - Serial execution disable (604 only - turbo mode)
|
||||
24 - SGE - Store gathering enable (7410 only)
|
||||
29 - BHT - Branch history table (604 only)
|
||||
|
||||
I made up the tags for the 604 specific bits, as they aren't
|
||||
named in the 604 book. The 603 book calls the invalidate bits
|
||||
ICFI and DCI, and I have no idea why it isn't DCFI. Maybe IBM named
|
||||
one, and Motorola named the other. */
|
||||
|
||||
#define HID0_ECLK 0x02000000
|
||||
#define HID0_DPM 0x00100000
|
||||
#define HID0_NHR 0x00010000
|
||||
#define HID0_ICE 0x00008000
|
||||
#define HID0_DCE 0x00004000
|
||||
#define HID0_ILOCK 0x00002000
|
||||
#define HID0_DLOCK 0x00001000
|
||||
#define HID0_ICFI 0x00000800
|
||||
#define HID0_DCFI 0x00000400
|
||||
#define HID0_NOSER 0x00000080
|
||||
#define HID0_SGE 0x00000080
|
||||
#define HID0_BTIC 0x00000020
|
||||
#define HID0_BHT 0x00000004
|
||||
|
||||
/*
|
||||
* BAT defines
|
||||
*/
|
||||
|
||||
/*
|
||||
* BL field in upper BAT register
|
||||
*/
|
||||
#define BAT_BL_128K 0x00000000
|
||||
#define BAT_BL_256K 0x00000004
|
||||
#define BAT_BL_512K 0x0000000C
|
||||
#define BAT_BL_1M 0x0000001C
|
||||
#define BAT_BL_2M 0x0000003C
|
||||
#define BAT_BL_4M 0x0000007C
|
||||
#define BAT_BL_8M 0x000000FC
|
||||
#define BAT_BL_16M 0x000001FC
|
||||
#define BAT_BL_32M 0x000003FC
|
||||
#define BAT_BL_64M 0x000007FC
|
||||
#define BAT_BL_128M 0x00000FFC
|
||||
#define BAT_BL_256M 0x00001FFC
|
||||
|
||||
/*
|
||||
* Supervisor/user valid mode in upper BAT register
|
||||
*/
|
||||
#define BAT_VALID_SUPERVISOR 0x00000002
|
||||
#define BAT_VALID_USER 0x00000001
|
||||
#define BAT_INVALID 0x00000000
|
||||
|
||||
/*
|
||||
* WIMG bit setting in lower BAT register
|
||||
*/
|
||||
#define BAT_WRITE_THROUGH 0x00000040
|
||||
#define BAT_CACHE_INHIBITED 0x00000020
|
||||
#define BAT_COHERENT 0x00000010
|
||||
#define BAT_GUARDED 0x00000008
|
||||
|
||||
/*
|
||||
* Protection bits in lower BAT register
|
||||
*/
|
||||
#define BAT_NO_ACCESS 0x00000000
|
||||
#define BAT_READ_ONLY 0x00000001
|
||||
#define BAT_READ_WRITE 0x00000002
|
||||
|
||||
#ifndef ASM
|
||||
unsigned __getmsr(void);
|
||||
void __setmsr(unsigned value);
|
||||
unsigned __gethid0(void);
|
||||
unsigned __gethid1(void);
|
||||
void __sethid0(unsigned value);
|
||||
unsigned __getpvr(void);
|
||||
#endif
|
||||
|
15
src/arch/ppc/include/stddef.h
Normal file
15
src/arch/ppc/include/stddef.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef PPC_STDDEF_H
|
||||
#define PPC_STDDEF_H
|
||||
|
||||
typedef long ptrdiff_t;
|
||||
typedef unsigned long size_t;
|
||||
typedef long ssize_t;
|
||||
|
||||
typedef int wchar_t;
|
||||
typedef unsigned int wint_t;
|
||||
|
||||
#define NULL 0
|
||||
|
||||
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
|
||||
|
||||
#endif /* PPC_STDDEF_H */
|
52
src/arch/ppc/include/stdint.h
Normal file
52
src/arch/ppc/include/stdint.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef PPC_STDINT_H
|
||||
#define PPC_STDINT_H
|
||||
|
||||
/* Exact integral types */
|
||||
typedef unsigned char uint8_t;
|
||||
typedef signed char int8_t;
|
||||
|
||||
typedef unsigned short uint16_t;
|
||||
typedef signed short int16_t;
|
||||
|
||||
typedef unsigned int uint32_t;
|
||||
typedef signed int int32_t;
|
||||
|
||||
typedef unsigned long long uint64_t;
|
||||
typedef signed long long int64_t;
|
||||
|
||||
/* Small types */
|
||||
typedef unsigned char uint_least8_t;
|
||||
typedef signed char int_least8_t;
|
||||
|
||||
typedef unsigned short uint_least16_t;
|
||||
typedef signed short int_least16_t;
|
||||
|
||||
typedef unsigned int uint_least32_t;
|
||||
typedef signed int int_least32_t;
|
||||
|
||||
typedef unsigned long long uint_least64_t;
|
||||
typedef signed long long int_least64_t;
|
||||
|
||||
/* Fast Types */
|
||||
typedef unsigned char uint_fast8_t;
|
||||
typedef signed char int_fast8_t;
|
||||
|
||||
typedef unsigned int uint_fast16_t;
|
||||
typedef signed int int_fast16_t;
|
||||
|
||||
typedef unsigned int uint_fast32_t;
|
||||
typedef signed int int_fast32_t;
|
||||
|
||||
typedef unsigned long long uint_fast64_t;
|
||||
typedef signed long long int_fast64_t;
|
||||
|
||||
/* Types for `void *' pointers. */
|
||||
typedef int intptr_t;
|
||||
typedef unsigned int uintptr_t;
|
||||
|
||||
/* Largest integral types */
|
||||
typedef long long int intmax_t;
|
||||
typedef unsigned long long uintmax_t;
|
||||
|
||||
|
||||
#endif /* PPC_STDINT_H */
|
13
src/arch/ppc/include/timer.h
Normal file
13
src/arch/ppc/include/timer.h
Normal file
@@ -0,0 +1,13 @@
|
||||
/* $Id$ */
|
||||
/* Copyright 2000 AG Electronics Ltd. */
|
||||
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
|
||||
|
||||
#ifndef _TIMER_H
|
||||
#define __TIMER_H
|
||||
|
||||
unsigned get_hz(void);
|
||||
unsigned ticks_since_boot(void);
|
||||
void sleep_ticks(unsigned);
|
||||
void udelay(int);
|
||||
|
||||
#endif
|
109
src/arch/ppc/lib/c_start.S
Normal file
109
src/arch/ppc/lib/c_start.S
Normal file
@@ -0,0 +1,109 @@
|
||||
/* $Id$ */
|
||||
/* Copyright 2000 AG Electronics Ltd. */
|
||||
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
|
||||
|
||||
/*
|
||||
* The assumption is that we're located in ROM and we have a fake stack
|
||||
* located in cache. Our task is to turn on memory proper, the finish
|
||||
* configuring the machine.
|
||||
*/
|
||||
|
||||
#define ASM
|
||||
#include "ppcreg.h"
|
||||
#include <ppc_asm.tmpl>
|
||||
|
||||
.section ".text"
|
||||
.globl _start
|
||||
|
||||
_start:
|
||||
/*
|
||||
* init stack pointer to real ram now that memory is on
|
||||
*/
|
||||
lis r1, _estack@ha
|
||||
addi r1, r1, _estack@l
|
||||
stwu r0,-64(r1)
|
||||
stwu r1,-24(r1)
|
||||
|
||||
/*
|
||||
* Clear stack
|
||||
*/
|
||||
lis r4, _stack@ha
|
||||
addi r4, r4, _stack@l
|
||||
lis r7, _estack@ha
|
||||
addi r7, r7, _estack@l
|
||||
lis r5, 0
|
||||
1: stwx r5, 0, r4
|
||||
addi r4, r4, 4
|
||||
cmp 0, 0, r4, r7
|
||||
ble 1b
|
||||
sync
|
||||
|
||||
/*
|
||||
* Clear bss
|
||||
*/
|
||||
lis r4, _bss@ha
|
||||
addi r4, r4, _bss@l
|
||||
lis r7, _ebss@ha
|
||||
addi r7, r7, _ebss@l
|
||||
lis r5, 0
|
||||
1: stwx r5, 0, r4
|
||||
addi r4, r4, 4
|
||||
cmp 0, 0, r4, r7
|
||||
ble 1b
|
||||
sync
|
||||
|
||||
/*
|
||||
* Set up the EABI pointers, before we enter any C code
|
||||
*/
|
||||
lis r13, _SDA_BASE_@ha
|
||||
addi r13, r13, _SDA_BASE_@l
|
||||
lis r2, _SDA2_BASE_@ha
|
||||
addi r2, r2, _SDA2_BASE_@l
|
||||
|
||||
/*
|
||||
* load start address into SRR0 for rfi
|
||||
*/
|
||||
lis r3, hardwaremain@ha
|
||||
addi r3, r3, hardwaremain@l
|
||||
mtspr SRR0, r3
|
||||
|
||||
/*
|
||||
* load the current MSR into SRR1 so that it will be copied
|
||||
* back into MSR on rfi
|
||||
*/
|
||||
mfmsr r4
|
||||
mtspr SRR1, r4 // load SRR1 with r4
|
||||
|
||||
/*
|
||||
* If something returns after rfi then die
|
||||
*/
|
||||
lis r3, dead@ha
|
||||
addi r3, r3, dead@l
|
||||
mtlr r3
|
||||
|
||||
/*
|
||||
* Complete rest of initialization in C (hardwaremain)
|
||||
*/
|
||||
rfi
|
||||
|
||||
/*
|
||||
* Stop here if something goes wrong
|
||||
*/
|
||||
dead:
|
||||
b dead
|
||||
/*NOTREACHED*/
|
||||
|
||||
/* Remove need for ecrti.o and ectrn.o */
|
||||
.globl __init
|
||||
__init:
|
||||
.globl __fini
|
||||
__fini:
|
||||
.globl __CTOR_LIST__
|
||||
__CTOR_LIST__:
|
||||
.globl __CTOR_END__
|
||||
__CTOR_END__:
|
||||
.globl __DTOR_LIST__
|
||||
__DTOR_LIST__:
|
||||
.globl __DTOR_END__
|
||||
__DTOR_END__:
|
||||
blr
|
45
src/arch/ppc/lib/floats.S
Normal file
45
src/arch/ppc/lib/floats.S
Normal file
@@ -0,0 +1,45 @@
|
||||
/* $Id$ */
|
||||
/* Copyright 1999-2000 AG Electronics Ltd. */
|
||||
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
|
||||
|
||||
#include <ppc_asm.tmpl>
|
||||
|
||||
.globl _init_float_registers
|
||||
|
||||
_init_float_registers:
|
||||
lfd fr0, 0(r3)
|
||||
lfd fr1, 0(r3)
|
||||
lfd fr2, 0(r3)
|
||||
lfd fr3, 0(r3)
|
||||
lfd fr4, 0(r3)
|
||||
lfd fr5, 0(r3)
|
||||
lfd fr6, 0(r3)
|
||||
lfd fr7, 0(r3)
|
||||
lfd fr8, 0(r3)
|
||||
lfd fr9, 0(r3)
|
||||
lfd fr10, 0(r3)
|
||||
lfd fr11, 0(r3)
|
||||
lfd fr12, 0(r3)
|
||||
lfd fr13, 0(r3)
|
||||
lfd fr14, 0(r3)
|
||||
lfd fr15, 0(r3)
|
||||
lfd fr16, 0(r3)
|
||||
lfd fr17, 0(r3)
|
||||
lfd fr18, 0(r3)
|
||||
lfd fr19, 0(r3)
|
||||
lfd fr20, 0(r3)
|
||||
lfd fr21, 0(r3)
|
||||
lfd fr22, 0(r3)
|
||||
lfd fr23, 0(r3)
|
||||
lfd fr24, 0(r3)
|
||||
lfd fr25, 0(r3)
|
||||
lfd fr26, 0(r3)
|
||||
lfd fr27, 0(r3)
|
||||
lfd fr28, 0(r3)
|
||||
lfd fr29, 0(r3)
|
||||
lfd fr30, 0(r3)
|
||||
lfd fr31, 0(r3)
|
||||
blr
|
||||
|
||||
.end
|
||||
|
43
src/arch/ppc/lib/floats.inc
Normal file
43
src/arch/ppc/lib/floats.inc
Normal file
@@ -0,0 +1,43 @@
|
||||
/* $Id$ */
|
||||
/* Copyright 1999-2000 AG Electronics Ltd. */
|
||||
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
|
||||
|
||||
/* .text*/
|
||||
.globl _init_float_registers
|
||||
|
||||
_init_float_registers:
|
||||
lfd 0, 0(3)
|
||||
lfd 1, 0(3)
|
||||
lfd 2, 0(3)
|
||||
lfd 3, 0(3)
|
||||
lfd 4, 0(3)
|
||||
lfd 5, 0(3)
|
||||
lfd 6, 0(3)
|
||||
lfd 7, 0(3)
|
||||
lfd 8, 0(3)
|
||||
lfd 9, 0(3)
|
||||
lfd 10, 0(3)
|
||||
lfd 11, 0(3)
|
||||
lfd 12, 0(3)
|
||||
lfd 13, 0(3)
|
||||
lfd 14, 0(3)
|
||||
lfd 15, 0(3)
|
||||
lfd 16, 0(3)
|
||||
lfd 17, 0(3)
|
||||
lfd 18, 0(3)
|
||||
lfd 19, 0(3)
|
||||
lfd 20, 0(3)
|
||||
lfd 21, 0(3)
|
||||
lfd 22, 0(3)
|
||||
lfd 23, 0(3)
|
||||
lfd 24, 0(3)
|
||||
lfd 25, 0(3)
|
||||
lfd 26, 0(3)
|
||||
lfd 27, 0(3)
|
||||
lfd 28, 0(3)
|
||||
lfd 29, 0(3)
|
||||
lfd 30, 0(3)
|
||||
lfd 31, 0(3)
|
||||
blr
|
||||
.end
|
||||
|
130
src/arch/ppc/lib/setup.c
Normal file
130
src/arch/ppc/lib/setup.c
Normal file
@@ -0,0 +1,130 @@
|
||||
/* $Id$ */
|
||||
/* Copyright 2000 AG Electronics Ltd. */
|
||||
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
|
||||
|
||||
#include "ppc.h"
|
||||
#include "ppcreg.h"
|
||||
|
||||
unsigned __getmsr(void)
|
||||
{
|
||||
unsigned result;
|
||||
__asm__ volatile ("mfmsr %0" : "=r" (result));
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned __gethid0(void)
|
||||
{
|
||||
unsigned result;
|
||||
__asm__ volatile ("mfspr %0,1008" : "=r" (result));
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned __gethid1(void)
|
||||
{
|
||||
unsigned result;
|
||||
__asm__ volatile ("mfspr %0,1009" : "=r" (result));
|
||||
return result;
|
||||
}
|
||||
|
||||
void __sethid0(unsigned value)
|
||||
{
|
||||
__asm__ volatile ("mtspr 1008,%0" : : "r" (value));
|
||||
}
|
||||
|
||||
unsigned __getpvr(void)
|
||||
{
|
||||
int result;
|
||||
__asm__("mfspr %0, 287" : "=r" (result));
|
||||
return result;
|
||||
}
|
||||
|
||||
void __setmsr(unsigned value)
|
||||
{
|
||||
__asm__ volatile ("mtmsr %0; sync" :: "r" (value));
|
||||
}
|
||||
|
||||
void __set1015(unsigned value)
|
||||
{
|
||||
__asm__ volatile ("mtspr 1015,%0" : : "r" (value));
|
||||
}
|
||||
|
||||
extern void _init_float_registers(const double *);
|
||||
/*RODATA static const double dummy_float = 1.0;*/
|
||||
static const double dummy_float = 1.0;
|
||||
|
||||
#define HID0_DCACHE HID0_DCE
|
||||
#define MSR_DATA MSR_DR
|
||||
|
||||
void ppc_setup_cpu(int icache)
|
||||
{
|
||||
int type = __getpvr() >> 16;
|
||||
int version = __getpvr() & 0xffff;
|
||||
|
||||
if (type == 0xc)
|
||||
{
|
||||
if (version == 0x0200)
|
||||
__set1015(0x19000004);
|
||||
else if (((version & 0xff00) == 0x0200) &&
|
||||
(version != 0x0209))
|
||||
__set1015(0x01000000);
|
||||
}
|
||||
if (icache)
|
||||
{
|
||||
__sethid0(HID0_NHR | HID0_BHT | HID0_ICE | HID0_ICFI | HID0_BTIC
|
||||
| HID0_DCACHE);
|
||||
__sethid0(HID0_DPM | HID0_NHR | HID0_BHT | HID0_ICE | HID0_BTIC
|
||||
| HID0_DCACHE);
|
||||
}
|
||||
else
|
||||
{
|
||||
__sethid0(HID0_DPM | HID0_NHR | HID0_BHT | HID0_BTIC | HID0_DCACHE);
|
||||
}
|
||||
#if 1
|
||||
/* if (type == 8 || type == 12) */
|
||||
{
|
||||
__setmsr(MSR_FP | MSR_DATA);
|
||||
_init_float_registers(&dummy_float);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ppc_enable_dcache(void)
|
||||
{
|
||||
/*
|
||||
* Already enabled in crt0.S
|
||||
*/
|
||||
#if 0
|
||||
unsigned hid0 = __gethid0();
|
||||
__sethid0(hid0 | HID0_DCFI | HID0_DCE);
|
||||
__sethid0(hid0 | HID0_DCE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ppc_disable_dcache(void)
|
||||
{
|
||||
unsigned hid0 = __gethid0();
|
||||
__sethid0(hid0 & ~HID0_DCE);
|
||||
}
|
||||
|
||||
void ppc_enable_mmu(void)
|
||||
{
|
||||
unsigned msr = __getmsr();
|
||||
__setmsr(msr | MSR_DR | MSR_IR);
|
||||
}
|
||||
|
||||
void make_coherent(void *base, unsigned length)
|
||||
{
|
||||
unsigned hid0 = __gethid0();
|
||||
|
||||
if (hid0 & HID0_DCE)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned offset = 0x1f & (unsigned) base;
|
||||
unsigned adjusted_base = (unsigned) base & ~0x1f;
|
||||
for(i = 0; i < length + offset; i+= 32)
|
||||
__asm__ volatile ("dcbf %1,%0" : : "r" (adjusted_base), "r" (i));
|
||||
if (hid0 & HID0_ICE)
|
||||
for(i = 0; i < length + offset; i+= 32)
|
||||
__asm__ volatile ("icbi %1,%0" : : "r" (adjusted_base), "r" (i));
|
||||
}
|
||||
}
|
13
src/arch/ppc/lib/timebase.S
Normal file
13
src/arch/ppc/lib/timebase.S
Normal file
@@ -0,0 +1,13 @@
|
||||
/* $Id$ */
|
||||
/* Copyright 1999-2000 AG Electronics Ltd. */
|
||||
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
|
||||
|
||||
.text
|
||||
.globl _timebase
|
||||
_timebase:
|
||||
mftbu 3
|
||||
mftb 4
|
||||
mftbu 5
|
||||
cmpw 3, 5
|
||||
bne _timebase
|
||||
blr
|
31
src/arch/ppc/lib/timer.c
Normal file
31
src/arch/ppc/lib/timer.c
Normal file
@@ -0,0 +1,31 @@
|
||||
/* $Id$ */
|
||||
/* Copyright 2000 AG Electronics Ltd. */
|
||||
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
|
||||
|
||||
#include <timer.h>
|
||||
#include <bsp.h>
|
||||
|
||||
unsigned get_hz(void)
|
||||
{
|
||||
return bsp_clock_speed();
|
||||
}
|
||||
|
||||
unsigned ticks_since_boot(void)
|
||||
{
|
||||
extern unsigned long long _timebase(void);
|
||||
return (unsigned) (_timebase());
|
||||
}
|
||||
|
||||
void sleep_ticks(unsigned ticks)
|
||||
{
|
||||
unsigned then = ticks + ticks_since_boot();
|
||||
while(ticks_since_boot() < then)
|
||||
;
|
||||
}
|
||||
|
||||
void udelay(int usecs)
|
||||
{
|
||||
unsigned ticksperusec = get_hz() / 1000000;
|
||||
|
||||
sleep_ticks(ticksperusec * usecs);
|
||||
}
|
Reference in New Issue
Block a user