summaryrefslogtreecommitdiff
path: root/os/rpcg/archrpcg.c
diff options
context:
space:
mode:
Diffstat (limited to 'os/rpcg/archrpcg.c')
-rw-r--r--os/rpcg/archrpcg.c428
1 files changed, 428 insertions, 0 deletions
diff --git a/os/rpcg/archrpcg.c b/os/rpcg/archrpcg.c
new file mode 100644
index 00000000..8da2cab1
--- /dev/null
+++ b/os/rpcg/archrpcg.c
@@ -0,0 +1,428 @@
+#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 <cursor.h>
+#include "screen.h"
+
+#include "../port/netif.h"
+#include "../mpc/etherif.h"
+#include "../port/flashif.h"
+#include "archrpcg.h"
+
+/*
+ * board-specific support for the 850/823 RPCG board
+ */
+
+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 */
+ EDBF2 = IBIT(14), /* =1, CLKOUT is GCLK2/2 */
+
+ /* plprcr */
+ CSRC = IBIT(21), /* =0, clock is DFNH; =1, clock is DFNL */
+};
+
+/*
+ * 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, i;
+
+ m->bcsr = KADDR(PHYSBCSR);
+ m->bcsr[0] &= ~EnableEnet;
+ io = m->iomem; /* run by reset code: no need to lock */
+ m->clockgen = 8000000; /* 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 */
+ m->cpuhz = m->clockgen*mf;
+ m->speed = m->cpuhz/MHz;
+ io->plprcrk = ~KEEP_ALIVE_KEY;
+ io->sccrk = KEEP_ALIVE_KEY;
+ io->sccr |= COM3 | TBS | CRQEN | PRQEN;
+ io->sccrk = ~KEEP_ALIVE_KEY;
+ if(0){
+ /* reset PCMCIA in case monitor hasn't */
+ io->pgcr[1] = 1<<7; /* OP2 high to disable PCMCIA */
+ io->per = 0;
+ io->pscr = ~0;
+ for(i=0; i<8; i++)
+ io->pcmr[i].base = io->pcmr[i].option = 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 nbytes, pa, ktop;
+
+ conf.nscc = 2;
+ conf.nocts2 = 1; /* TO DO: check this */
+
+ conf.npage0 = 0;
+ nbytes = banksize(DRAM1CS, &pa);
+ if(nbytes){
+ 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;
+
+ /* check for NVRAM */
+ if(m->bcsr[0] & NVRAMBattGood){
+ conf.nvramsize = banksize(NVRAMCS, &pa);
+ conf.nvrambase = KADDR(pa);
+ }
+}
+
+void
+cpuidprint(void)
+{
+ ulong v;
+ int i;
+
+ 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("plprcr=%8.8lux sccr=%8.8lux bcsr=%8.8lux\n", m->iomem->plprcr, m->iomem->sccr, m->bcsr[0]);
+ print("%lud MHz system\n", m->cpuhz/MHz);
+ print("%lud pages\n", (conf.npage0-conf.base0)/BY2PG);
+ print("%ludK NVRAM\n", conf.nvramsize/1024);
+ print("\n");
+ for(i=0; i<nelem(m->iomem->pcmr); i++)
+ print("%d: %8.8lux %8.8lux\n", i, m->iomem->memc[i].base, m->iomem->memc[i].option);
+}
+
+/*
+ * 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;
+
+/*
+ * invoked by ../port/taslock.c:/^ilock:
+ * reset watchdog timer here, if there is one and it is enabled
+ * (qboot currently disables it on the FADS board)
+ */
+void
+clockcheck(void)
+{
+}
+
+/*
+ * for 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 = "AMD29F0x0";
+// f->type = "cfi16";
+ f->addr = KADDR(PHYSFLASH);
+ f->size = 4*1024*1024;
+ f->width = 4;
+ f->interleave = 1;
+ return 0;
+}
+
+int
+archether(int ctlrno, Ether *ether)
+{
+ if(isaconfig("ether", ctlrno, ether) == 0)
+ return -1;
+ 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 fullduplex)
+{
+ IMM *io;
+
+ if(cpmid != CPscc2)
+ return -1;
+ USED(mbps);
+ USED(fullduplex);
+ io = ioplock();
+ m->bcsr[0] = (m->bcsr[0] & ~(EnableXcrLB|DisableColTest)) | EnableEnet;
+ eieio();
+ io->papar |= SIBIT(6)|SIBIT(4); /* enable CLK2 and CLK4 */
+ io->padir &= ~(SIBIT(6)|SIBIT(4));
+ iopunlock();
+ *rcs = CLK4;
+ *tcs = CLK2;
+ return 0;
+}
+
+/*
+ * 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 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)
+{
+ ioplock();
+ if(master)
+ m->bcsr[0] |= EnableUSBPwr;
+ else
+ m->bcsr[0] &= ~EnableUSBPwr;
+ m->bcsr[0] &= ~DisableUSB;
+ if(highspeed)
+ m->bcsr[0] |= HighSpdUSB;
+ else
+ m->bcsr[0] &= ~HighSpdUSB;
+ iopunlock();
+}
+
+/*
+ * shut down the USB transceiver
+ */
+void
+archdisableusb(void)
+{
+ ioplock();
+ m->bcsr[0] |= DisableUSB;
+ m->bcsr[0] &= ~EnableUSBPwr;
+ iopunlock();
+}
+
+/*
+ * 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);
+}
+
+/*
+ * board-specific PCMCIA support: assumes slot B on 82xFADS
+ */
+int
+pcmslotavail(int slotno)
+{
+ return slotno == 1;
+}
+
+void
+pcmenable(void)
+{
+ ioplock();
+ m->bcsr[0] = m->bcsr[0] & ~(VPPMask|VCCMask); /* power off */
+ eieio();
+ m->bcsr[0] |= VCC5V | VPPVCC; /* apply Vcc */
+ eieio();
+ m->iomem->pgcr[1] = 0; /* OP2 low to enable PCMCIA */
+ iopunlock();
+iprint("B=%8.8lux\n", m->bcsr[0]);
+}
+
+int
+pcmpowered(int)
+{
+ ulong r;
+
+ r = m->bcsr[0]&VCCMask;
+ if(r == VCC5V)
+ return 5;
+ if(r == VCC3V)
+ return 3;
+ return 0;
+}
+
+void
+pcmsetvcc(int, int v)
+{
+ if(v == 5)
+ v = VCC5V;
+ else if(v == 3)
+ v = VCC3V;
+ else
+ v = VCC0V;
+ ioplock();
+ m->bcsr[0] = (m->bcsr[0] & ~VCCMask) | v;
+ iopunlock();
+}
+
+void
+pcmsetvpp(int, int v)
+{
+ if(v == 5 || v == 3)
+ v = VPPVCC;
+ else if(v == 12)
+ v = VPP12V;
+ else if(v == 0)
+ v = VPP0V;
+ else
+ v = VPPHiZ;
+ ioplock();
+ m->bcsr[0] = (m->bcsr[0] & ~VPPMask) | v;
+ iopunlock();
+}
+
+void
+pcmpower(int slotno, int on)
+{
+ if(!on){
+ pcmsetvcc(slotno, 0); /* turn off card power */
+ pcmsetvpp(slotno, -1); /* turn off programming voltage (Hi-Z) */
+ }else
+ pcmsetvcc(slotno, 5);
+}
+
+/*
+ * enable/disable the LCD panel's backlight
+ */
+void
+archbacklight(int on)
+{
+ USED(on);
+}
+
+/*
+ * set parameters to describe the screen
+ */
+int
+archlcdmode(Mode *m)
+{
+ 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)
+{
+}
+
+void
+archflashwp(Flash*, int)
+{
+}