2009-01-05 20:30:39 +00:00
|
|
|
/*
|
|
|
|
|
* derived from mol/mol.c,
|
|
|
|
|
* Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
|
|
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
|
* version 2
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "openbios/config.h"
|
|
|
|
|
#include "openbios/nvram.h"
|
2010-03-14 15:05:53 +00:00
|
|
|
#include "libopenbios/bindings.h"
|
2009-01-05 20:30:39 +00:00
|
|
|
#include "libc/byteorder.h"
|
|
|
|
|
#include "libc/vsprintf.h"
|
|
|
|
|
|
2010-03-14 15:19:41 +00:00
|
|
|
#include "drivers/drivers.h"
|
2009-01-05 20:30:39 +00:00
|
|
|
#include "macio.h"
|
|
|
|
|
#include "cuda.h"
|
2009-01-12 17:47:56 +00:00
|
|
|
#include "escc.h"
|
2010-03-14 15:19:41 +00:00
|
|
|
#include "drivers/pci.h"
|
2009-01-05 20:30:39 +00:00
|
|
|
|
2009-02-08 12:22:04 +00:00
|
|
|
#define OW_IO_NVRAM_SIZE 0x00020000
|
|
|
|
|
#define OW_IO_NVRAM_OFFSET 0x00060000
|
|
|
|
|
#define OW_IO_NVRAM_SHIFT 4
|
|
|
|
|
|
|
|
|
|
#define NW_IO_NVRAM_SIZE 0x00004000
|
|
|
|
|
#define NW_IO_NVRAM_OFFSET 0xfff04000
|
|
|
|
|
#define NW_IO_NVRAM_SHIFT 1
|
|
|
|
|
|
|
|
|
|
#define IO_OPENPIC_SIZE 0x00040000
|
|
|
|
|
#define IO_OPENPIC_OFFSET 0x00040000
|
2009-01-05 20:30:39 +00:00
|
|
|
|
|
|
|
|
static char *nvram;
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
arch_nvram_size( void )
|
|
|
|
|
{
|
2009-02-08 12:22:04 +00:00
|
|
|
if (is_oldworld())
|
|
|
|
|
return OW_IO_NVRAM_SIZE >> OW_IO_NVRAM_SHIFT;
|
|
|
|
|
else
|
|
|
|
|
return NW_IO_NVRAM_SIZE >> NW_IO_NVRAM_SHIFT;
|
2009-01-05 20:30:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void macio_nvram_init(const char *path, uint32_t addr)
|
|
|
|
|
{
|
|
|
|
|
phandle_t chosen, aliases;
|
|
|
|
|
phandle_t dnode;
|
|
|
|
|
int props[2];
|
|
|
|
|
char buf[64];
|
2009-02-08 12:22:04 +00:00
|
|
|
unsigned long nvram_size, nvram_offset;
|
|
|
|
|
|
|
|
|
|
if (is_oldworld()) {
|
|
|
|
|
nvram_offset = OW_IO_NVRAM_OFFSET;
|
|
|
|
|
nvram_size = OW_IO_NVRAM_SIZE;
|
|
|
|
|
} else {
|
|
|
|
|
nvram_offset = NW_IO_NVRAM_OFFSET;
|
|
|
|
|
nvram_size = NW_IO_NVRAM_SIZE;
|
|
|
|
|
push_str("/");
|
|
|
|
|
fword("find-device");
|
|
|
|
|
fword("new-device");
|
|
|
|
|
push_str("nvram");
|
|
|
|
|
fword("device-name");
|
|
|
|
|
fword("finish-device");
|
|
|
|
|
}
|
|
|
|
|
nvram = (char*)addr + nvram_offset;
|
2009-01-05 20:30:39 +00:00
|
|
|
snprintf(buf, sizeof(buf), "%s/nvram", path);
|
|
|
|
|
nvram_init(buf);
|
|
|
|
|
dnode = find_dev(buf);
|
|
|
|
|
set_int_property(dnode, "#bytes", arch_nvram_size() );
|
2009-02-08 12:22:04 +00:00
|
|
|
props[0] = __cpu_to_be32(nvram_offset);
|
|
|
|
|
props[1] = __cpu_to_be32(nvram_size);
|
2009-01-05 20:30:39 +00:00
|
|
|
set_property(dnode, "reg", (char *)&props, sizeof(props));
|
|
|
|
|
set_property(dnode, "device_type", "nvram", 6);
|
2009-03-08 01:03:17 +00:00
|
|
|
NEWWORLD(set_property(dnode, "compatible", "nvram,flash", 12));
|
2009-01-05 20:30:39 +00:00
|
|
|
|
|
|
|
|
chosen = find_dev("/chosen");
|
|
|
|
|
push_str(buf);
|
|
|
|
|
fword("open-dev");
|
|
|
|
|
set_int_property(chosen, "nvram", POP());
|
|
|
|
|
|
|
|
|
|
aliases = find_dev("/aliases");
|
|
|
|
|
set_property(aliases, "nvram", buf, strlen(buf) + 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef DUMP_NVRAM
|
|
|
|
|
static void
|
|
|
|
|
dump_nvram(void)
|
|
|
|
|
{
|
|
|
|
|
int i, j;
|
|
|
|
|
for (i = 0; i < 10; i++)
|
|
|
|
|
{
|
|
|
|
|
for (j = 0; j < 16; j++)
|
|
|
|
|
printk ("%02x ", nvram[(i*16+j)<<4]);
|
|
|
|
|
printk (" ");
|
|
|
|
|
for (j = 0; j < 16; j++)
|
|
|
|
|
if (isprint(nvram[(i*16+j)<<4]))
|
|
|
|
|
printk("%c", nvram[(i*16+j)<<4]);
|
|
|
|
|
else
|
|
|
|
|
printk(".");
|
|
|
|
|
printk ("\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
arch_nvram_put( char *buf )
|
|
|
|
|
{
|
|
|
|
|
int i;
|
2009-02-08 12:22:04 +00:00
|
|
|
unsigned int it_shift;
|
|
|
|
|
|
|
|
|
|
if (is_oldworld())
|
|
|
|
|
it_shift = OW_IO_NVRAM_SHIFT;
|
|
|
|
|
else
|
|
|
|
|
it_shift = NW_IO_NVRAM_SHIFT;
|
|
|
|
|
|
2009-01-05 20:30:39 +00:00
|
|
|
for (i=0; i< arch_nvram_size() ; i++)
|
2009-02-08 12:22:04 +00:00
|
|
|
nvram[i << it_shift] = buf[i];
|
2009-01-05 20:30:39 +00:00
|
|
|
#ifdef DUMP_NVRAM
|
|
|
|
|
printk("new nvram:\n");
|
|
|
|
|
dump_nvram();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
arch_nvram_get( char *buf )
|
|
|
|
|
{
|
|
|
|
|
int i;
|
2009-02-08 12:22:04 +00:00
|
|
|
unsigned int it_shift;
|
|
|
|
|
|
|
|
|
|
if (is_oldworld())
|
|
|
|
|
it_shift = OW_IO_NVRAM_SHIFT;
|
|
|
|
|
else
|
|
|
|
|
it_shift = NW_IO_NVRAM_SHIFT;
|
|
|
|
|
|
2009-01-05 20:30:39 +00:00
|
|
|
for (i=0; i< arch_nvram_size(); i++)
|
2009-02-08 12:22:04 +00:00
|
|
|
buf[i] = nvram[i << it_shift];
|
2009-01-05 20:30:39 +00:00
|
|
|
|
|
|
|
|
#ifdef DUMP_NVRAM
|
|
|
|
|
printk("current nvram:\n");
|
|
|
|
|
dump_nvram();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-08 12:22:04 +00:00
|
|
|
static void
|
|
|
|
|
openpic_init(const char *path, uint32_t addr)
|
|
|
|
|
{
|
2009-12-18 23:38:08 +00:00
|
|
|
phandle_t target_node;
|
2009-02-08 12:22:04 +00:00
|
|
|
phandle_t dnode;
|
|
|
|
|
int props[2];
|
|
|
|
|
char buf[128];
|
|
|
|
|
|
|
|
|
|
push_str(path);
|
|
|
|
|
fword("find-device");
|
|
|
|
|
fword("new-device");
|
|
|
|
|
push_str("interrupt-controller");
|
|
|
|
|
fword("device-name");
|
|
|
|
|
|
|
|
|
|
snprintf(buf, sizeof(buf), "%s/interrupt-controller", path);
|
|
|
|
|
dnode = find_dev(buf);
|
|
|
|
|
set_property(dnode, "device_type", "open-pic", 9);
|
|
|
|
|
set_property(dnode, "compatible", "chrp,open-pic", 14);
|
|
|
|
|
set_property(dnode, "built-in", "", 0);
|
|
|
|
|
props[0] = __cpu_to_be32(IO_OPENPIC_OFFSET);
|
|
|
|
|
props[1] = __cpu_to_be32(IO_OPENPIC_SIZE);
|
|
|
|
|
set_property(dnode, "reg", (char *)&props, sizeof(props));
|
|
|
|
|
set_int_property(dnode, "#interrupt-cells", 2);
|
|
|
|
|
set_int_property(dnode, "#address-cells", 0);
|
|
|
|
|
set_property(dnode, "interrupt-controller", "", 0);
|
|
|
|
|
set_int_property(dnode, "clock-frequency", 4166666);
|
2009-12-18 23:38:08 +00:00
|
|
|
|
|
|
|
|
fword("finish-device");
|
|
|
|
|
|
|
|
|
|
if (is_newworld()) {
|
2010-02-22 18:52:26 +00:00
|
|
|
u32 *interrupt_map;
|
|
|
|
|
int len, i;
|
|
|
|
|
|
2009-12-18 23:38:08 +00:00
|
|
|
/* patch in interrupt parent */
|
|
|
|
|
dnode = find_dev(buf);
|
2010-02-22 18:52:26 +00:00
|
|
|
|
|
|
|
|
target_node = find_dev("/pci/mac-io");
|
2009-12-18 23:38:08 +00:00
|
|
|
set_int_property(target_node, "interrupt-parent", dnode);
|
|
|
|
|
|
|
|
|
|
target_node = find_dev("/pci/mac-io/escc/ch-a");
|
|
|
|
|
set_int_property(target_node, "interrupt-parent", dnode);
|
|
|
|
|
|
|
|
|
|
target_node = find_dev("/pci/mac-io/escc/ch-b");
|
|
|
|
|
set_int_property(target_node, "interrupt-parent", dnode);
|
2010-02-22 18:52:26 +00:00
|
|
|
|
|
|
|
|
target_node = find_dev("/pci");
|
|
|
|
|
set_int_property(target_node, "interrupt-parent", dnode);
|
|
|
|
|
|
|
|
|
|
interrupt_map = (u32 *)get_property(target_node, "interrupt-map", &len);
|
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
|
interrupt_map[(i * 7) + PCI_INT_MAP_PIC_HANDLE] = (u32)dnode;
|
|
|
|
|
}
|
|
|
|
|
set_property(target_node, "interrupt-map", (char *)interrupt_map, len);
|
2009-12-18 23:38:08 +00:00
|
|
|
}
|
2009-02-08 12:22:04 +00:00
|
|
|
}
|
|
|
|
|
|
2009-11-10 21:50:36 +00:00
|
|
|
DECLARE_NODE(ob_macio, INSTALL_OPEN, sizeof(int), "Tmac-io");
|
|
|
|
|
|
|
|
|
|
/* ( str len -- addr ) */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ob_macio_decode_unit(void *private)
|
|
|
|
|
{
|
|
|
|
|
ucell addr;
|
|
|
|
|
|
|
|
|
|
const char *arg = pop_fstr_copy();
|
|
|
|
|
|
|
|
|
|
addr = strtol(arg, NULL, 16);
|
|
|
|
|
|
|
|
|
|
free((char*)arg);
|
|
|
|
|
|
|
|
|
|
PUSH(addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ( addr -- str len ) */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ob_macio_encode_unit(void *private)
|
|
|
|
|
{
|
|
|
|
|
char buf[8];
|
|
|
|
|
|
|
|
|
|
ucell addr = POP();
|
|
|
|
|
|
|
|
|
|
snprintf(buf, sizeof(buf), "%x", addr);
|
|
|
|
|
|
|
|
|
|
push_str(buf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NODE_METHODS(ob_macio) = {
|
|
|
|
|
{ "decode-unit", ob_macio_decode_unit },
|
|
|
|
|
{ "encode-unit", ob_macio_encode_unit },
|
|
|
|
|
};
|
|
|
|
|
|
2009-01-05 20:30:39 +00:00
|
|
|
void
|
2009-02-08 12:22:04 +00:00
|
|
|
ob_macio_heathrow_init(const char *path, uint32_t addr)
|
2009-01-05 20:30:39 +00:00
|
|
|
{
|
2009-01-10 20:40:11 +00:00
|
|
|
phandle_t aliases;
|
2009-01-05 20:30:39 +00:00
|
|
|
|
2009-11-10 21:50:36 +00:00
|
|
|
REGISTER_NODE(ob_macio);
|
2009-01-05 20:30:39 +00:00
|
|
|
aliases = find_dev("/aliases");
|
|
|
|
|
set_property(aliases, "mac-io", path, strlen(path) + 1);
|
|
|
|
|
|
|
|
|
|
cuda_init(path, addr);
|
|
|
|
|
macio_nvram_init(path, addr);
|
2009-01-12 17:47:56 +00:00
|
|
|
escc_init(path, addr);
|
2009-01-30 07:44:48 +00:00
|
|
|
macio_ide_init(path, addr, 1);
|
2009-01-05 20:30:39 +00:00
|
|
|
}
|
2009-02-08 12:22:04 +00:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ob_macio_keylargo_init(const char *path, uint32_t addr)
|
|
|
|
|
{
|
|
|
|
|
phandle_t aliases;
|
|
|
|
|
|
|
|
|
|
aliases = find_dev("/aliases");
|
|
|
|
|
set_property(aliases, "mac-io", path, strlen(path) + 1);
|
|
|
|
|
|
|
|
|
|
cuda_init(path, addr);
|
|
|
|
|
/* The NewWorld NVRAM is not located in the MacIO device */
|
|
|
|
|
macio_nvram_init("", 0);
|
|
|
|
|
escc_init(path, addr);
|
|
|
|
|
macio_ide_init(path, addr, 3);
|
|
|
|
|
openpic_init(path, addr);
|
|
|
|
|
}
|