summaryrefslogtreecommitdiff
path: root/os/boot/rpcg/archrpcg.c
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 21:39:35 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 21:39:35 +0000
commit74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a (patch)
treec6e220ba61db3a6ea4052e6841296d829654e664 /os/boot/rpcg/archrpcg.c
parent46439007cf417cbd9ac8049bb4122c890097a0fa (diff)
20060303
Diffstat (limited to 'os/boot/rpcg/archrpcg.c')
-rw-r--r--os/boot/rpcg/archrpcg.c279
1 files changed, 279 insertions, 0 deletions
diff --git a/os/boot/rpcg/archrpcg.c b/os/boot/rpcg/archrpcg.c
new file mode 100644
index 00000000..87df2196
--- /dev/null
+++ b/os/boot/rpcg/archrpcg.c
@@ -0,0 +1,279 @@
+#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;
+}