xref: /inferno-os/os/boot/rpcg/archrpcg.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
1 #include	"u.h"
2 #include	"lib.h"
3 #include	"mem.h"
4 #include	"dat.h"
5 #include	"fns.h"
6 #include	"io.h"
7 
8 #include	"archrpcg.h"
9 #include "etherif.h"
10 
11 /*
12  * board-specific support for the RPCG RXLite
13  */
14 
15 enum {
16 	SYSMHZ =	66,	/* target frequency */
17 
18 	/* sccr */
19 	RTSEL = IBIT(8),	/* =0, select main oscillator (OSCM); =1, select external crystal (EXTCLK) */
20 	RTDIV = IBIT(7),	/* =0, divide by 4; =1, divide by 512 */
21 	CRQEN = IBIT(9),	/* =1, switch to high frequency when CPM active */
22 	PRQEN = IBIT(10),	/* =1, switch to high frequency when interrupt pending */
23 
24 	/* plprcr */
25 	CSRC = IBIT(21),	/* =0, clock is DFNH; =1, clock is DFNL */
26 };
27 
28 static	char	flashsig[] = "RPXsignature=1.0\nNAME=qbrpcg\nSTART=FFC20100\nVERSION=1.1\n";
29 static	char*	geteeprom(char*);
30 
31 /*
32  * called early in main.c, after machinit:
33  * using board and architecture specific registers, initialise
34  * 8xx registers that need it and complete initialisation of the Mach structure.
35  */
36 void
archinit(void)37 archinit(void)
38 {
39 	IMM *io;
40 	int mf, t;
41 	ulong v;
42 
43 	v = getimmr() & 0xFFFF;
44 	switch(v>>8){
45 	case 0x00:	t = 0x86000; break;
46 	case 0x20:	t = 0x82300; break;
47 	case 0x21:	t = 0x823a0; break;
48 	default:	t = 0; break;
49 	}
50 	m->cputype = t;
51 	m->bcsr = KADDR(BCSRMEM);
52 	io = m->iomem;
53 	m->clockgen = 8*MHz;
54 	mf = (io->plprcr >> 20)+1;	/* use timing set by bootstrap */
55 	m->cpuhz = m->clockgen*mf;
56 	m->bcsr[0] = DisableColTest | DisableFullDplx | DisableUSB | HighSpdUSB | LedOff;	/* first write enables bcsr regs */
57 return;
58 	io->plprcrk = KEEP_ALIVE_KEY;
59 	io->plprcr &= ~CSRC;	/* general system clock is DFNH */
60 /*	io->mptpr = 0x0800;	/* memory prescaler = 8 for refresh */
61 	/* use memory refresh time set by RPXLite monitor */
62 	io->plprcrk = ~KEEP_ALIVE_KEY;
63 }
64 
65 void
cpuidprint(void)66 cpuidprint(void)
67 {
68 	int t, v;
69 
70 	print("Inferno bootstrap\n");
71 	print("PVR: ");
72 	t = getpvr()>>16;
73 	switch(t){
74 	case 0x01:	print("MPC601"); break;
75 	case 0x03:	print("MPC603"); break;
76 	case 0x04:	print("MPC604"); break;
77 	case 0x06:	print("MPC603e"); break;
78 	case 0x07:	print("MPC603e-v7"); break;
79 	case 0x50:	print("MPC8xx"); break;
80 	default:	print("PowerPC version #%x", t); break;
81 	}
82 	print(", revision #%lux\n", getpvr()&0xffff);
83 	print("IMMR: ");
84 	v = getimmr() & 0xFFFF;
85 	switch(v>>8){
86 	case 0x00:	print("MPC860/821"); break;
87 	case 0x20:	print("MPC823"); break;
88 	case 0x21:	print("MPC823A"); break;
89 	default:	print("Type #%lux", v>>8); break;
90 	}
91 	print(", mask #%lux\n", v&0xFF);
92 	print("options: #%lux\n", archoptionsw());
93 	print("bcsr: %8.8lux\n", m->bcsr[0]);
94 	print("PLPRCR=%8.8lux SCCR=%8.8lux\n", m->iomem->plprcr, m->iomem->sccr);
95 	print("%lud MHz system\n", m->cpuhz/MHz);
96 	print("\n");
97 //print("%s\n", geteeprom("EA"));
98 print("BR0=%8.8lux OR0=%8.8lux\n", m->iomem->memc[0].base, m->iomem->memc[0].option);
99 print("MPTPR=%8.8lux\n", m->iomem->mptpr);
100 }
101 
102 static	char*	defplan9ini[2] = {
103 	/* 860/821 */
104 	"ether0=type=SCC port=1 ea=0010ec000051\r\n"
105 	"vgasize=640x480x8\r\n"
106 	"kernelpercent=40\r\n"
107 	"console=0\r\nbaud=9600\r\n",
108 
109 	/* 823 */
110 	"ether0=type=SCC port=2 ea=0010ec000051\r\n"
111 	"vgasize=640x480x8\r\n"
112 	"kernelpercent=40\r\n"
113 	"console=0\r\nbaud=9600\r\n",
114 };
115 
116 char *
archconfig(void)117 archconfig(void)
118 {
119 	print("Using default configuration\n");
120 	return defplan9ini[MPCMODEL(m->cputype) == 0x823];
121 }
122 
123 /*
124  * provide value for #r/switch (devrtc.c)
125  */
126 int
archoptionsw(void)127 archoptionsw(void)
128 {
129 	return (m->bcsr[0]&DipSwitchMask)>>4;
130 }
131 
132 /*
133  * invoked by clock.c:/^clockintr
134  */
135 static void
twinkle(void)136 twinkle(void)
137 {
138 	if(m->ticks%MS2TK(1000) == 0)
139 		m->bcsr[0] ^= LedOff;
140 }
141 
142 void	(*archclocktick)(void) = twinkle;
143 
144 /*
145  * for flash.c:/^flashreset
146  * retrieve flash type, virtual base and length and return 0;
147  * return -1 on error (no flash)
148  */
149 int
archflashreset(char * type,void ** addr,long * length)150 archflashreset(char *type, void **addr, long *length)
151 {
152 	if((m->iomem->memc[BOOTCS].base & 1) == 0)
153 		return -1;		/* shouldn't happen */
154 	strcpy(type, "AMD29F0x0");
155 	*addr = KADDR(FLASHMEM);
156 	*length = 4*1024*1024;
157 	return 0;
158 }
159 
160 int
archether(int ctlrno,Card * ether)161 archether(int ctlrno, Card *ether)
162 {
163 	char *ea;
164 
165 	if(ctlrno > 0)
166 		return -1;
167 	strcpy(ether->type, "SCC");
168 	ether->port = 2;
169 	ea = geteeprom("EA");
170 	if(ea != nil)
171 		parseether(ether->ea, ea);
172 	return 1;
173 }
174 
175 /*
176  * enable the clocks for the given SCC ether and reveal them to the caller.
177  * do anything else required to prepare the transceiver (eg, set full-duplex, reset loopback).
178  */
179 int
archetherenable(int cpmid,int * rcs,int * tcs)180 archetherenable(int cpmid, int *rcs, int *tcs)
181 {
182 	IMM *io;
183 
184 	switch(cpmid){
185 	default:
186 		/* no other SCCs are wired for ether on RPXLite*/
187 		return -1;
188 
189 	case SCC2ID:
190 		io = ioplock();
191 		m->bcsr[0] |= EnableEnet;
192 		io->papar |= SIBIT(6)|SIBIT(4);	/* enable CLK2 and CLK4 */
193 		io->padir &= ~(SIBIT(6)|SIBIT(4));
194 		*rcs = CLK4;
195 		*tcs = CLK2;
196 		iopunlock();
197 		break;
198 	}
199 	return 0;
200 }
201 
202 void
archetherdisable(int id)203 archetherdisable(int id)
204 {
205 	USED(id);
206 	m->bcsr[0] &= ~EnableEnet;
207 }
208 
209 /*
210  * do anything extra required to enable the UART on the given CPM port
211  */
212 void
archenableuart(int id,int irda)213 archenableuart(int id, int irda)
214 {
215 	USED(id, irda);
216 }
217 
218 /*
219  * do anything extra required to disable the UART on the given CPM port
220  */
221 void
archdisableuart(int id)222 archdisableuart(int id)
223 {
224 	USED(id);
225 }
226 
227 /*
228  * enable/disable the LCD panel's backlight
229  */
230 void
archbacklight(int on)231 archbacklight(int on)
232 {
233 	USED(on);
234 }
235 
236 static char*
geteeprom(char * s)237 geteeprom(char *s)
238 {
239 	static int init;
240 	static char res[64];
241 	static uchar eeprom[257];
242 	uchar *l, *p;
243 	int i, j;
244 
245 	if(!init){
246 		i2csetup();
247 		if(i2crecv(0xa8|1|(0<<8), eeprom, 128) < 0 ||
248 		   i2crecv(0xa8|1|(128<<8), eeprom+128, 128) < 0){
249 			print("i2c failed\n");
250 			return nil;
251 		}
252 		if(0){
253 			print("eeprom:\n");
254 			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");}
255 		}
256 		eeprom[256] = 0xFF;
257 		init = 1;
258 	}
259 	for(l = eeprom; *l != 0xFF && *l != '\n';){
260 		p = l;
261 		while(*l != '\n' && *l != 0xFF && *l != '=')
262 			l++;
263 		if(*l == '='){
264 			if(l-p == strlen(s) && strncmp(s, (char*)p, strlen(s)) == 0){
265 				p = l+1;
266 				while(*l != '\n' && *l != 0xFF)
267 					l++;
268 				memmove(res, p, l-p);
269 				res[l-p] = 0;
270 				return res;
271 			}
272 		}
273 		while(*l != '\n' && *l != 0xFF)
274 			l++;
275 		if(*l == '\n')
276 			l++;
277 	}
278 	return nil;
279 }
280