summaryrefslogtreecommitdiff
path: root/os/ipengine/archipe.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/ipengine/archipe.c
parent46439007cf417cbd9ac8049bb4122c890097a0fa (diff)
20060303
Diffstat (limited to 'os/ipengine/archipe.c')
-rw-r--r--os/ipengine/archipe.c488
1 files changed, 488 insertions, 0 deletions
diff --git a/os/ipengine/archipe.c b/os/ipengine/archipe.c
new file mode 100644
index 00000000..151f72f7
--- /dev/null
+++ b/os/ipengine/archipe.c
@@ -0,0 +1,488 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include <draw.h>
+#include <memdraw.h>
+#include "screen.h"
+
+#include "../port/netif.h"
+#include "etherif.h"
+#include "../port/flashif.h"
+
+#include "archipe.h"
+
+/*
+ * board-specific support for the Bright Star Engineering ipEngine-1
+ */
+
+enum {
+ /* sccr */
+ COM3= IBIT(1)|IBIT(2), /* clock output disabled */
+ TBS = IBIT(6), /* =0, time base is OSCCLK/{4,16}; =1, time base is GCLK2/16 */
+ 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 */
+
+ Showports = 0, /* used to find lightly-documented bits set by bootstrap (eg, PDN) */
+};
+
+static ulong ports[4*4];
+
+/*
+ * 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;
+
+ io = m->iomem; /* run by reset code: no need to lock */
+ m->clockgen = 4000000; /* crystal frequency */
+ m->oscclk = m->clockgen/MHz;
+ io->plprcrk = KEEP_ALIVE_KEY;
+ io->plprcr &= ~CSRC; /* general system clock is DFNH */
+ mf = (io->plprcr >> 20)+1; /* use timing set by bootstrap */
+ io->plprcrk = ~KEEP_ALIVE_KEY;
+ io->sccrk = KEEP_ALIVE_KEY;
+ io->sccr |= CRQEN | PRQEN | RTDIV | COM3; /* devfpga.c resets COM3 if needed */
+ io->sccrk = ~KEEP_ALIVE_KEY;
+ m->cpuhz = m->clockgen*mf;
+ m->speed = m->cpuhz/MHz;
+ if((io->memc[CLOCKCS].base & 1) == 0){ /* prom hasn't mapped it */
+ io->memc[CLOCKCS].option = 0xFFFF0F24;
+ io->memc[CLOCKCS].base = 0xFF020001;
+ }
+ if(Showports){
+ ports[0] = io->padat;
+ ports[1] = io->padir;
+ ports[2] = io->papar;
+ ports[3] = io->paodr;
+ ports[4] = io->pbdat;
+ ports[5] = io->pbdir;
+ ports[6] = io->pbpar;
+ ports[7] = io->pbodr;
+ ports[8] = io->pcdat;
+ ports[9] = io->pcdir;
+ ports[10] = io->pcpar;
+ ports[11] = io->pcso;
+ ports[12] = io->pddat;
+ ports[13] = io->pddir;
+ ports[14] = io->pdpar;
+ ports[15] = 0;
+ }
+}
+
+static ulong
+banksize(int x, ulong *pa)
+{
+ IMM *io;
+
+ io = m->iomem;
+ if((io->memc[x].base & 1) == 0)
+ return 0; /* bank not valid */
+ *pa = io->memc[x].base & ~0x7FFF;
+ return -(io->memc[x].option&~0x7FFF);
+}
+
+/*
+ * initialise the kernel's memory configuration:
+ * there are two banks (base0, npage0) and (base1, npage1).
+ * initialise any other values in conf that are board-specific.
+ */
+void
+archconfinit(void)
+{
+ ulong pa, nbytes, ktop;
+
+ conf.nscc = 2;
+ conf.sccuarts = 0; /* no SCC uarts */
+ conf.smcuarts = (1<<0)|(1<<1); /* SMC1 (console) and SMC2 */
+
+ nbytes = banksize(DRAMCS, &pa);
+ if(nbytes == 0){ /* force default */
+ nbytes = 16*1024*1024;
+ pa = 0;
+ }
+ conf.npage0 = nbytes/BY2PG;
+ conf.base0 = pa;
+
+ conf.npage1 = 0;
+
+ /* the following assumes the kernel text and/or data is in bank 0 */
+ ktop = PGROUND((ulong)end);
+ ktop = PADDR(ktop) - conf.base0;
+ conf.npage0 -= ktop/BY2PG;
+ conf.base0 += ktop;
+}
+
+void
+cpuidprint(void)
+{
+ ulong v;
+
+ print("PVR: ");
+ switch(m->cputype){
+ 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", m->cputype); 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("%lud MHz system\n", m->cpuhz/MHz);
+ print("\n");
+
+ if(Showports){
+
+ print("plprcr=%8.8lux sccr=%8.8lux\n", m->iomem->plprcr, m->iomem->sccr);
+ print("pipr=%8.8lux\n", m->iomem->pipr);
+
+ print("ports:\n");
+ for(v=0;v<nelem(ports);v++)
+ print("%2ld %8.8lux\n", v, ports[v]);
+
+ /* dump the memory configuration while we're at it */
+ for(v=0; v<nelem(m->iomem->memc); v++)
+ if(m->iomem->memc[v].base & 1)
+ print("%ld %8.8lux %8.8lux\n", v, m->iomem->memc[v].base, m->iomem->memc[v].option);
+ }
+}
+
+/*
+ * fetch parameters from flash, as stored by BSE bootstrap,
+ * compensating for a bug in its fset that produces silly entries.
+ */
+
+static int
+envnameok(char *s)
+{
+ if(*s == '*')
+ s++;
+ if(*s >= '0' && *s <= '9' || *s == 0)
+ return 0;
+ for(; *s; s++)
+ if(*s >= '0' && *s <= '9' ||
+ *s >= 'a' && *s <= 'z' ||
+ *s >= 'A' && *s <= 'Z' ||
+ *s == '.' || *s == '_' || *s == '#'){
+ /* ok */
+ }else
+ return 0;
+ return 1;
+}
+
+int
+archconfval(char **names, char **vals, int limit)
+{
+ uchar *b, *e;
+ char *s;
+ int n, v, l, o;
+ static char bootargs[512];
+
+ /* we assume we can access this space before mmuinit() */
+ b = KADDR(PHYSFLASH+0x4000);
+ if(*b & 1){
+ b += 0x2000; /* try alternative location */
+ if(*b & 1)
+ return 0;
+ }
+ v = (b[2]<<8)|b[3];
+ b += 4;
+ if(v >= 0x2000-4)
+ return 0;
+ n = 0;
+ o = 0;
+ e = b+v;
+ for(; b < e; b += v){
+ v = *b;
+ if(v == 0xFF || n >= limit)
+ break;
+ s = (char*)b+1;
+ if(v >= 0x80){
+ v = ((v&0x7F)<<8) | b[1];
+ s++;
+ }
+ if(envnameok(s)){
+ names[n] = s;
+ s += strlen(s)+1;
+ l = strlen(s)+1;
+ if(o+l > sizeof(bootargs))
+ break;
+ vals[n] = bootargs+o;
+ memmove(vals[n], s, l);
+ o += l;
+ n++;
+ }
+ }
+ return n;
+}
+
+void
+toggleled(int b)
+{
+ int s;
+ s = splhi();
+ m->iomem->pdpar &= ~(0x20<<b);
+ m->iomem->pddir |= 0x20<<b;
+ m->iomem->pddat ^= 0x020<<b;
+ splx(s);
+}
+
+/*
+ * provide value for #r/switch (devrtc.c)
+ */
+int
+archoptionsw(void)
+{
+ return 0;
+}
+
+/*
+ * invoked by clock.c:/^clockintr
+ */
+static void
+twinkle(void)
+{
+ if(m->ticks%MS2TK(1000) == 0 && m->iomem)
+ toggleled(0);
+}
+
+void (*archclocktick)(void) = twinkle;
+
+/*
+ * invoked by ../port/taslock.c:/^ilock:
+ * reset watchdog timer here, if there is one and it is enabled
+ */
+void
+clockcheck(void)
+{
+}
+
+/*
+ * for ../port/devflash.c:/^flashreset
+ * retrieve flash type, virtual base and length and return 0;
+ * return -1 on error (no flash)
+ */
+int
+archflashreset(int bank, Flash *f)
+{
+ if(bank != 0)
+ return -1;
+ f->type = "Intel28F320B3B";
+ f->addr = KADDR(PHYSFLASH);
+ f->size = 4*1024*1024;
+ f->width = 2;
+ return 0;
+}
+
+void
+archflashwp(Flash*, int)
+{
+}
+
+/*
+ * set ether parameters: the contents should be derived from EEPROM or NVRAM
+ */
+int
+archether(int ctlno, Ether *ether)
+{
+ if(isaconfig("ether", ctlno, ether) == 0 && ctlno > 0)
+ return -1;
+ if(ctlno == 0){
+ ether->type = "SCC";
+ ether->port = 2;
+ }
+ memmove(ether->ea, KADDR(PHYSFLASH+0x3FFA), Eaddrlen);
+ 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, int mbps, int fd)
+{
+ IMM *io;
+
+ if(cpmid != CPscc2)
+ return -1;
+ USED(mbps);
+ io = ioplock();
+ io->pcpar &= ~EnetLoopback;
+ io->pcso &= ~EnetLoopback;
+ io->pcdir |= EnetLoopback;
+ io->pcdat &= ~EnetLoopback;
+ if(0){ /* TO CHECK: causes ether errors if used */
+ io->pbpar &= ~EnetFullDuplex;
+ io->pbdir |= EnetFullDuplex;
+ if(fd)
+ io->pbdat |= EnetFullDuplex;
+ else
+ io->pbdat &= ~EnetFullDuplex;
+ }
+ io->pbpar &= ~EnableEnet;
+ io->pbdir |= EnableEnet;
+ io->pbdat |= EnableEnet;
+ io->papar |= SIBIT(7)|SIBIT(6); /* enable CLK1 and CLK2 */
+ io->padir &= ~(SIBIT(7)|SIBIT(6));
+ iopunlock();
+ *rcs = CLK2;
+ *tcs = CLK1;
+ return 0;
+}
+
+/*
+ * do anything extra required to enable the UART on the given CPM port
+ */
+static ulong uartsactive;
+
+void
+archenableuart(int id, int irda)
+{
+ IMM *io;
+
+ USED(id); /* both uarts seem to be controlled by the same bit */
+ USED(irda); /* no IrDA on ipEngine */
+ io = ioplock();
+ if(uartsactive == 0){
+ io->pbpar &= ~EnableRS232;
+ io->pbdir |= EnableRS232;
+ io->pbdat |= EnableRS232;
+ }
+ uartsactive |= 1<<id;
+ iopunlock();
+}
+
+/*
+ * do anything extra required to disable the UART on the given CPM port
+ */
+void
+archdisableuart(int id)
+{
+ IMM *io;
+
+ io = ioplock();
+ uartsactive &= ~(1<<id);
+ if(uartsactive == 0)
+ io->pbdat &= ~EnableRS232;
+ iopunlock();
+}
+
+/*
+ * enable the external USB transceiver
+ * speed is 12MHz if highspeed is non-zero; 1.5MHz if zero
+ * master is non-zero if the node is acting as USB Host and should provide power
+ */
+void
+archenableusb(int highspeed, int master)
+{
+ IMM *io;
+
+ USED(master);
+ io = ioplock();
+ io->pcpar &= ~USBFullSpeed;
+ io->pcso &= ~USBFullSpeed;
+ if(highspeed)
+ io->pcdat |= USBFullSpeed;
+ else
+ io->pcdat &= ~USBFullSpeed;
+ io->pcdir |= USBFullSpeed;
+ iopunlock();
+}
+
+/*
+ * shut down the USB transceiver
+ */
+void
+archdisableusb(void)
+{
+ /* nothing to be done on ipEngine, apparently */
+}
+
+/*
+ * set the external infrared transceiver to the given speed
+ */
+void
+archsetirxcvr(int highspeed)
+{
+ USED(highspeed);
+}
+
+/*
+ * force hardware reset/reboot
+ */
+void
+archreboot(void)
+{
+ IMM *io;
+
+ io = m->iomem;
+ io->plprcrk = KEEP_ALIVE_KEY;
+ io->plprcr |= 1<<7; /* checkstop reset enable */
+ io->plprcrk = ~KEEP_ALIVE_KEY;
+ eieio();
+ io->sdcr = 1;
+ eieio();
+ io->lccr = 0; /* switch LCD off */
+ eieio();
+ firmware(0);
+}
+
+/*
+ * enable/disable the LCD panel's backlight
+ */
+void
+archbacklight(int on)
+{
+ USED(on);
+}
+
+/*
+ * set parameters to describe the screen
+ */
+int
+archlcdmode(Mode *m)
+{
+ /* sample parameters in case a panel is attached to the external pins */
+ m->x = 640;
+ m->y = 480;
+ m->d = 3;
+ m->lcd.freq = 25000000;
+ m->lcd.ac = 0;
+ m->lcd.vpw = 1;
+ m->lcd.wbf = 33;
+ m->lcd.wbl = 228;
+ m->lcd.flags = IsColour | IsTFT | OELow | VsyncLow | ClockLow;
+ return -1; /* there isn't a screen */
+}
+
+/*
+ * there isn't a keyboard port
+ */
+void
+archkbdinit(void)
+{
+}