ref: babf901b4a508c3ec5d1f89655f10377bbdf9637
dir: /os/boot/rpcg/archrpcg.c/
#include "u.h"
#include "lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "archrpcg.h"
#include "etherif.h"
/*
* board-specific support for the RPCG RXLite
*/
enum {
SYSMHZ = 66, /* target frequency */
/* sccr */
RTSEL = IBIT(8), /* =0, select main oscillator (OSCM); =1, select external crystal (EXTCLK) */
RTDIV = IBIT(7), /* =0, divide by 4; =1, divide by 512 */
CRQEN = IBIT(9), /* =1, switch to high frequency when CPM active */
PRQEN = IBIT(10), /* =1, switch to high frequency when interrupt pending */
/* plprcr */
CSRC = IBIT(21), /* =0, clock is DFNH; =1, clock is DFNL */
};
static char flashsig[] = "RPXsignature=1.0\nNAME=qbrpcg\nSTART=FFC20100\nVERSION=1.1\n";
static char* geteeprom(char*);
/*
* called early in main.c, after machinit:
* using board and architecture specific registers, initialise
* 8xx registers that need it and complete initialisation of the Mach structure.
*/
void
archinit(void)
{
IMM *io;
int mf, t;
ulong v;
v = getimmr() & 0xFFFF;
switch(v>>8){
case 0x00: t = 0x86000; break;
case 0x20: t = 0x82300; break;
case 0x21: t = 0x823a0; break;
default: t = 0; break;
}
m->cputype = t;
m->bcsr = KADDR(BCSRMEM);
io = m->iomem;
m->clockgen = 8*MHz;
mf = (io->plprcr >> 20)+1; /* use timing set by bootstrap */
m->cpuhz = m->clockgen*mf;
m->bcsr[0] = DisableColTest | DisableFullDplx | DisableUSB | HighSpdUSB | LedOff; /* first write enables bcsr regs */
return;
io->plprcrk = KEEP_ALIVE_KEY;
io->plprcr &= ~CSRC; /* general system clock is DFNH */
/* io->mptpr = 0x0800; /* memory prescaler = 8 for refresh */
/* use memory refresh time set by RPXLite monitor */
io->plprcrk = ~KEEP_ALIVE_KEY;
}
void
cpuidprint(void)
{
int t, v;
print("Inferno bootstrap\n");
print("PVR: ");
t = getpvr()>>16;
switch(t){
case 0x01: print("MPC601"); break;
case 0x03: print("MPC603"); break;
case 0x04: print("MPC604"); break;
case 0x06: print("MPC603e"); break;
case 0x07: print("MPC603e-v7"); break;
case 0x50: print("MPC8xx"); break;
default: print("PowerPC version #%x", t); break;
}
print(", revision #%lux\n", getpvr()&0xffff);
print("IMMR: ");
v = getimmr() & 0xFFFF;
switch(v>>8){
case 0x00: print("MPC860/821"); break;
case 0x20: print("MPC823"); break;
case 0x21: print("MPC823A"); break;
default: print("Type #%lux", v>>8); break;
}
print(", mask #%lux\n", v&0xFF);
print("options: #%lux\n", archoptionsw());
print("bcsr: %8.8lux\n", m->bcsr[0]);
print("PLPRCR=%8.8lux SCCR=%8.8lux\n", m->iomem->plprcr, m->iomem->sccr);
print("%lud MHz system\n", m->cpuhz/MHz);
print("\n");
//print("%s\n", geteeprom("EA"));
print("BR0=%8.8lux OR0=%8.8lux\n", m->iomem->memc[0].base, m->iomem->memc[0].option);
print("MPTPR=%8.8lux\n", m->iomem->mptpr);
}
static char* defplan9ini[2] = {
/* 860/821 */
"ether0=type=SCC port=1 ea=0010ec000051\r\n"
"vgasize=640x480x8\r\n"
"kernelpercent=40\r\n"
"console=0\r\nbaud=9600\r\n",
/* 823 */
"ether0=type=SCC port=2 ea=0010ec000051\r\n"
"vgasize=640x480x8\r\n"
"kernelpercent=40\r\n"
"console=0\r\nbaud=9600\r\n",
};
char *
archconfig(void)
{
print("Using default configuration\n");
return defplan9ini[MPCMODEL(m->cputype) == 0x823];
}
/*
* provide value for #r/switch (devrtc.c)
*/
int
archoptionsw(void)
{
return (m->bcsr[0]&DipSwitchMask)>>4;
}
/*
* invoked by clock.c:/^clockintr
*/
static void
twinkle(void)
{
if(m->ticks%MS2TK(1000) == 0)
m->bcsr[0] ^= LedOff;
}
void (*archclocktick)(void) = twinkle;
/*
* for flash.c:/^flashreset
* retrieve flash type, virtual base and length and return 0;
* return -1 on error (no flash)
*/
int
archflashreset(char *type, void **addr, long *length)
{
if((m->iomem->memc[BOOTCS].base & 1) == 0)
return -1; /* shouldn't happen */
strcpy(type, "AMD29F0x0");
*addr = KADDR(FLASHMEM);
*length = 4*1024*1024;
return 0;
}
int
archether(int ctlrno, Card *ether)
{
char *ea;
if(ctlrno > 0)
return -1;
strcpy(ether->type, "SCC");
ether->port = 2;
ea = geteeprom("EA");
if(ea != nil)
parseether(ether->ea, ea);
return 1;
}
/*
* enable the clocks for the given SCC ether and reveal them to the caller.
* do anything else required to prepare the transceiver (eg, set full-duplex, reset loopback).
*/
int
archetherenable(int cpmid, int *rcs, int *tcs)
{
IMM *io;
switch(cpmid){
default:
/* no other SCCs are wired for ether on RPXLite*/
return -1;
case SCC2ID:
io = ioplock();
m->bcsr[0] |= EnableEnet;
io->papar |= SIBIT(6)|SIBIT(4); /* enable CLK2 and CLK4 */
io->padir &= ~(SIBIT(6)|SIBIT(4));
*rcs = CLK4;
*tcs = CLK2;
iopunlock();
break;
}
return 0;
}
void
archetherdisable(int id)
{
USED(id);
m->bcsr[0] &= ~EnableEnet;
}
/*
* do anything extra required to enable the UART on the given CPM port
*/
void
archenableuart(int id, int irda)
{
USED(id, irda);
}
/*
* do anything extra required to disable the UART on the given CPM port
*/
void
archdisableuart(int id)
{
USED(id);
}
/*
* enable/disable the LCD panel's backlight
*/
void
archbacklight(int on)
{
USED(on);
}
static char*
geteeprom(char *s)
{
static int init;
static char res[64];
static uchar eeprom[257];
uchar *l, *p;
int i, j;
if(!init){
i2csetup();
if(i2crecv(0xa8|1|(0<<8), eeprom, 128) < 0 ||
i2crecv(0xa8|1|(128<<8), eeprom+128, 128) < 0){
print("i2c failed\n");
return nil;
}
if(0){
print("eeprom:\n");
for(i=0; i<16; i++){for(j=0; j<16; j++)print(" %2.2ux[%c]", eeprom[i*16+j], eeprom[i*16+j]); print("\n");}
}
eeprom[256] = 0xFF;
init = 1;
}
for(l = eeprom; *l != 0xFF && *l != '\n';){
p = l;
while(*l != '\n' && *l != 0xFF && *l != '=')
l++;
if(*l == '='){
if(l-p == strlen(s) && strncmp(s, (char*)p, strlen(s)) == 0){
p = l+1;
while(*l != '\n' && *l != 0xFF)
l++;
memmove(res, p, l-p);
res[l-p] = 0;
return res;
}
}
while(*l != '\n' && *l != 0xFF)
l++;
if(*l == '\n')
l++;
}
return nil;
}