xref: /inferno-os/os/boot/mpc/archfads.c (revision 7ef44d652ae9e5e1f5b3465d73684e4a54de73c0)
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 #include	"archfads.h"
8 
9 /*
10  * board-specific support for the 8xxFADS (including 860/21 development system)
11  */
12 
13 enum {
14 	USESDRAM = 0,	/* set to 1 if kernel is to use SDRAM as well as DRAM */
15 
16 	/* sccr */
17 	RTSEL = IBIT(8),	/* =0, select main oscillator (OSCM); =1, select external crystal (EXTCLK) */
18 	RTDIV = IBIT(7),	/* =0, divide by 4; =1, divide by 512 */
19 	CRQEN = IBIT(9),	/* =1, switch to high frequency when CPM active */
20 	PRQEN = IBIT(10),	/* =1, switch to high frequency when interrupt pending */
21 
22 	/* plprcr */
23 	CSRC = IBIT(21),	/* =0, clock is DFNH; =1, clock is DFNL */
24 };
25 
26 /*
27  * called early in main.c, after machinit:
28  * using board and architecture specific registers, initialise
29  * 8xx registers that need it and complete initialisation of the Mach structure.
30  */
31 void
32 archinit(void)
33 {
34 	IMM *io;
35 	int mf, isfads, sysmhz, t;
36 	ulong v;
37 
38 	v = getimmr() & 0xFFFF;
39 	isfads = 0;		/* assume it's the 860/821 board */
40 	sysmhz = 40;
41 	switch(v>>8){
42 	case 0x00:	t = 0x86000; break;
43 	case 0x20:	t = 0x82300; isfads = 1; break;
44 	case 0x21:	t = 0x823a0; isfads = 1; break;
45 	default:	t = 0; break;
46 	}
47 	m->cputype = t;
48 	m->bcsr = KADDR(BCSRMEM);
49 	m->bcsr[1] |= DisableRS232a | DisableIR | DisableEther | DisablePCMCIA | DisableRS232b;
50 	m->bcsr[1] &= ~(DisableDRAM|DisableFlash);
51 	if(isfads){
52 		sysmhz = 50;
53 		m->bcsr[1] &= ~EnableSDRAM;
54 		m->bcsr[4] &= ~(EnableVideoClock|EnableVideoPort);
55 		m->bcsr[4] |= DisableVideoLamp;
56 	}
57 	io = m->iomem;
58 	if(1 || io->sccr & IBIT(7)){	/* RTDIV=1 */
59 		/* oscillator frequency can't be determined independently: check a switch */
60 		if((m->bcsr[2]>>19)&(1<<2))
61 			m->clockgen = 5*MHz;
62 		else
63 			m->clockgen = 4*MHz;
64 	} else
65 		m->clockgen = 32768;
66 	mf = (sysmhz*MHz)/m->clockgen;
67 	m->cpuhz = m->clockgen*mf;
68 	io->plprcrk = KEEP_ALIVE_KEY;
69 	io->plprcr &= ~IBIT(21);	/* general system clock is DFNH */
70 	io->plprcr = (io->plprcr & ((1<<20)-1)) | ((mf-1)<<20);
71 	io->mptpr = 0x0400;	/* memory prescaler = 16 for refresh */
72 	io->plprcrk = ~KEEP_ALIVE_KEY;
73 	if(isfads){
74 		m->bcsr[1] |= EnableSDRAM;
75 		sdraminit(SDRAMMEM);
76 		if(!USESDRAM)
77 			m->bcsr[1] &= ~EnableSDRAM;	/* tells kernel not to map it */
78 	}
79 }
80 
81 static void
82 archidprint(void)
83 {
84 	int f, i;
85 	ulong v;
86 
87 	/* 8xx and FADS specific */
88 	print("IMMR: ");
89 	v = getimmr() & 0xFFFF;
90 	switch(v>>8){
91 	case 0x00:	print("MPC860/821"); break;
92 	case 0x20:	print("MPC823"); break;
93 	case 0x21:	print("MPC823A"); break;
94 	default:	print("Type #%lux", v>>8); break;
95 	}
96 	print(", mask #%lux\n", v&0xFF);
97 	v = m->bcsr[3]>>16;
98 	print("MPC8xxFADS rev %lud, DB: ", ((v>>4)&8)|((v>>1)&4)|(v&3));
99 	f = (v>>8)&0x3F;
100 	switch(f){
101 	default:	print("ID#%x", f); break;
102 	case 0x00:	print("MPC860/821"); break;
103 	case 0x01:	print("MPC813"); break;
104 	case 0x02:	print("MPC821"); break;
105 	case 0x03:	print("MPC823"); break;
106 	case 0x20:	print("MPC801"); break;
107 	case 0x21:	print("MPC850"); break;
108 	case 0x22:	print("MPC860"); break;
109 	case 0x23:	print("MPC860SAR"); break;
110 	case 0x24:	print("MPC860T"); break;
111 	}
112 	print("ADS, rev #%lux\n", (m->bcsr[2]>>16)&7);
113 	for(i=0; i<=4; i++)
114 		print("BCSR%d: %8.8lux\n", i, m->bcsr[i]);
115 	v = m->bcsr[2];
116 	f = (v>>28)&0xF;
117 	switch(f){
118 	default:	print("Unknown"); break;
119 	case 4:	print("SM732A2000/SM73228 - 8M SIMM"); break;
120 	case 5:	print("SM732A1000A/SM73218 - 4M SIMM"); break;
121 	case 6:	print("MCM29080 - 8M SIMM"); break;
122 	case 7:	print("MCM29040 - 4M SIMM"); break;
123 	case 8:	print("MCM29020 - 2M SIMM"); break;
124 	}
125 	switch((m->bcsr[3]>>20)&7){
126 	default:	i = 0; break;
127 	case 1:	i = 150; break;
128 	case 2:	i = 120; break;
129 	case 3:	i = 90; break;
130 	}
131 	print(" flash, %dns\n", i);
132 	f = (v>>23)&0xF;
133 	switch(f&3){
134 	case 0:	i = 4; break;
135 	case 1:	i = 32; break;
136 	case 2:	i = 16; break;
137 	case 3:	i = 8; break;
138 	}
139 	print("%dM SIMM, ", i);
140 	switch(f>>2){
141 	default: 	i = 0; break;
142 	case 2:	i = 70; break;
143 	case 3:	i = 60; break;
144 	}
145 	print("%dns\n", i);
146 	print("options: #%lux\n", (m->bcsr[2]>>19)&0xF);
147 	print("plprcr=%8.8lux sccr=%8.8lux\n", m->iomem->plprcr, m->iomem->sccr);
148 }
149 
150 void
151 cpuidprint(void)
152 {
153 	int t;
154 
155 	print("PVR: ");
156 	t = getpvr()>>16;
157 	switch(t){
158 	case 0x01:	print("MPC601"); break;
159 	case 0x03:	print("MPC603"); break;
160 	case 0x04:	print("MPC604"); break;
161 	case 0x06:	print("MPC603e"); break;
162 	case 0x07:	print("MPC603e-v7"); break;
163 	case 0x50:	print("MPC8xx"); break;
164 	default:	print("PowerPC version #%x", t); break;
165 	}
166 	print(", revision #%lux\n", getpvr()&0xffff);
167 	archidprint();
168 	print("%lud MHz system\n", m->cpuhz/MHz);
169 	print("\n");
170 }
171 
172 static	char*	defplan9ini[2] = {
173 	/* 860/821 */
174 	"ether0=type=SCC port=1 ea=00108bf12900\r\n"
175 	"vgasize=640x480x8\r\n"
176 	"kernelpercent=40\r\n"
177 	"console=0 lcd\r\nbaud=9600\r\n",
178 
179 	/* 823 */
180 	"ether0=type=SCC port=2 ea=00108bf12900\r\n"
181 	"vgasize=640x480x8\r\n"
182 	"kernelpercent=40\r\n"
183 	"console=0 lcd\r\nbaud=9600\r\n",
184 };
185 
186 char *
187 archconfig(void)
188 {
189 	print("Using default configuration\n");
190 	return defplan9ini[MPCMODEL(m->cputype) == 0x823];
191 }
192 
193 /*
194  * provide value for #r/switch (devrtc.c)
195  */
196 int
197 archoptionsw(void)
198 {
199 	return (m->bcsr[2]>>19)&0xF;	/* value of switch DS1 */
200 }
201 
202 /*
203  * invoked by clock.c:/^clockintr
204  */
205 static void
206 twinkle(void)
207 {
208 	if(m->ticks%MS2TK(1000) == 0)
209 		m->bcsr[4] ^= DisableLamp;
210 }
211 
212 void	(*archclocktick)(void) = twinkle;
213 
214 /*
215  * for flash.c:/^flashreset
216  * retrieve flash type, virtual base and length and return 0;
217  * return -1 on error (no flash)
218  */
219 int
220 archflashreset(char *type, void **addr, long *length)
221 {
222 	char *t;
223 	int mbyte;
224 
225 	if((m->iomem->memc[0].base & 1) == 0)
226 		return -1;		/* shouldn't happen */
227 	switch((m->bcsr[2]>>28)&0xF){
228 	default:	return -1;	/* unknown or not there */
229 	case 4:	mbyte=8; t = "SM732x8"; break;
230 	case 5:	mbyte=4; t = "SM732x8"; break;
231 	case 6:	mbyte=8; t = "AMD29F0x0"; break;
232 	case 7:	mbyte=4; t = "AMD29F0x0"; break;
233 	case 8:	mbyte=2; t = "AMD29F0x0"; break;
234 	}
235 	strcpy(type, t);
236 	*addr = KADDR(FLASHMEM);
237 	*length = mbyte*1024*1024;
238 	return 0;
239 }
240 
241 /*
242  * enable the clocks for the given SCC ether and reveal them to the caller.
243  * do anything else required to prepare the transceiver (eg, set full-duplex, reset loopback).
244  */
245 int
246 archetherenable(int cpmid, int *rcs, int *tcs)
247 {
248 	IMM *io;
249 
250 	switch(cpmid){
251 	default:
252 		/* no other SCCs are wired on the FADS board */
253 		return -1;
254 
255 	case SCC2ID:	/* assume 8xxFADS board with 823DABS */
256 		io = ioplock();
257 		m->bcsr[1] |= DisableIR|DisableRS232b;
258 		m->bcsr[1] &= ~DisableEther;
259 		io->papar |= SIBIT(6)|SIBIT(5);	/* enable CLK2 and CLK3 */
260 		io->padir &= ~(SIBIT(6)|SIBIT(5));
261 
262 		/* ETHLOOP etc set in BCSR elsewhere */
263 		*rcs = CLK2;
264 		*tcs = CLK3;
265 		iopunlock();
266 		break;
267 
268 	case SCC1ID:	/* assume 860/21 development board */
269 		io = ioplock();
270 		m->bcsr[1] |= DisableIR|DisableRS232b;	/* TO DO: might not be shared with RS232b */
271 		m->bcsr[1] &= ~DisableEther;
272 		io->papar |= SIBIT(6)|SIBIT(7);	/* enable CLK2 and CLK1 */
273 		io->padir &= ~(SIBIT(6)|SIBIT(7));
274 
275 		/* settings peculiar to 860/821 development board */
276 		io->pcpar &= ~(SIBIT(4)|SIBIT(5)|SIBIT(6));	/* ETHLOOP, TPFULDL~, TPSQEL~ */
277 		io->pcdir |= SIBIT(4)|SIBIT(5)|SIBIT(6);
278 		io->pcdat &= ~SIBIT(4);
279 		io->pcdat |= SIBIT(5)|SIBIT(6);
280 		*rcs = CLK2;
281 		*tcs = CLK1;
282 		iopunlock();
283 		break;
284 	}
285 	return 0;
286 }
287 
288 void
289 archetherdisable(int id)
290 {
291 	USED(id);
292 	m->bcsr[1] |= DisableEther|DisableIR|DisableRS232b;
293 }
294 
295 /*
296  * do anything extra required to enable the UART on the given CPM port
297  */
298 void
299 archenableuart(int id, int irda)
300 {
301 	switch(id){
302 	case SMC1ID:
303 		m->bcsr[1] &= ~DisableRS232a;
304 		break;
305 	case SCC2ID:
306 		m->bcsr[1] |= DisableEther|DisableIR|DisableRS232b;
307 		if(irda)
308 			m->bcsr[1] &= ~DisableIR;
309 		else
310 			m->bcsr[1] &= ~DisableRS232b;
311 		break;
312 	default:
313 		/* nothing special */
314 		break;
315 	}
316 }
317 
318 /*
319  * do anything extra required to disable the UART on the given CPM port
320  */
321 void
322 archdisableuart(int id)
323 {
324 	switch(id){
325 	case SMC1ID:
326 		m->bcsr[1] |= DisableRS232a;
327 		break;
328 	case SCC2ID:
329 		m->bcsr[1] |= DisableIR|DisableRS232b;
330 		break;
331 	default:
332 		/* nothing special */
333 		break;
334 	}
335 }
336 
337 /*
338  * enable/disable the LCD panel's backlight via
339  * York touch panel interface (does no harm without it)
340  */
341 void
342 archbacklight(int on)
343 {
344 	IMM *io;
345 
346 	delay(2);
347 	io = ioplock();
348 	io->papar &= ~SIBIT(4);
349 	io->padir |= SIBIT(4);
350 	if(on)
351 		io->padat |= SIBIT(4);
352 	else
353 		io->padat &= ~SIBIT(4);
354 	iopunlock();
355 }
356