xref: /inferno-os/os/boot/mpc/archpaq.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	"archpaq.h"
9 
10 /*
11  * board-specific support for the 82x PowerPAQ
12  */
13 
14 enum {
15 	SYSMHZ = 50,	/* desired system clock in MHz */
16 
17 	/* sccr */
18 	RTSEL = IBIT(8),	/* =0, select main oscillator (OSCM); =1, select external crystal (EXTCLK) */
19 	RTDIV = IBIT(7),	/* =0, divide by 4; =1, divide by 512 */
20 	CRQEN = IBIT(9),	/* =1, switch to high frequency when CPM active */
21 	PRQEN = IBIT(10),	/* =1, switch to high frequency when interrupt pending */
22 
23 	/* plprcr */
24 	CSRC = IBIT(21),	/* =0, clock is DFNH; =1, clock is DFNL */
25 };
26 
27 /*
28  * called early in main.c, after machinit:
29  * using board and architecture specific registers, initialise
30  * 8xx registers that need it and complete initialisation of the Mach structure.
31  */
32 void
archinit(void)33 archinit(void)
34 {
35 	IMM *io;
36 	int mf, t;
37 
38 	switch((getimmr()>>8)&0xFF){
39 	case 0x00:	t = 0x86000; break;	/* also 821 */
40 	case 0x20:	t = 0x82300; break;
41 	case 0x21:	t = 0x823a0; break;
42 	default:	t = 0; break;
43 	}
44 	m->cputype = t;
45 	m->bcsr = nil;	/* there isn't one */
46 	m->clockgen = 32*1024;	/* crystal frequency */
47 	io = m->iomem;
48 	io->sccrk = KEEP_ALIVE_KEY;
49 	io->sccr &= ~RTDIV;	/* divide 32k by 4 */
50 	io->sccr |= RTSEL;
51 	io->sccrk = ~KEEP_ALIVE_KEY;
52 	mf = (SYSMHZ*MHz)/m->clockgen;
53 	m->cpuhz = m->clockgen*mf;
54 	io->plprcrk = KEEP_ALIVE_KEY;
55 	io->plprcr &= ~IBIT(21);	/* general system clock is DFNH */
56 	io->plprcr = (io->plprcr & ((1<<20)-1)) | ((mf-1)<<20);
57 	io->mptpr = 0x0400;	/* memory prescaler = 16 for refresh */
58 	io->plprcrk = ~KEEP_ALIVE_KEY;
59 }
60 
61 void
cpuidprint(void)62 cpuidprint(void)
63 {
64 	int t, v;
65 
66 	print("PVR: ");
67 	t = getpvr()>>16;
68 	switch(t){
69 	case 0x01:	print("MPC601"); break;
70 	case 0x03:	print("MPC603"); break;
71 	case 0x04:	print("MPC604"); break;
72 	case 0x06:	print("MPC603e"); break;
73 	case 0x07:	print("MPC603e-v7"); break;
74 	case 0x50:	print("MPC8xx"); break;
75 	default:	print("PowerPC version #%x", t); break;
76 	}
77 	print(", revision #%lux\n", getpvr()&0xffff);
78 	print("IMMR: ");
79 	v = getimmr() & 0xFFFF;
80 	switch(v>>8){
81 	case 0x00:	print("MPC860/821"); break;
82 	case 0x20:	print("MPC823"); break;
83 	case 0x21:	print("MPC823A"); break;
84 	default:	print("Type #%lux", v>>8); break;
85 	}
86 	print(", mask #%lux\n", v&0xFF);
87 	print("plprcr=%8.8lux sccr=%8.8lux\n", m->iomem->plprcr, m->iomem->sccr);
88 	print("%lud MHz system\n", m->cpuhz/MHz);
89 	print("\n");
90 }
91 
92 static	char*	defplan9ini[2] = {
93 	/* 860/821 */
94 	"ether0=type=SCC port=1 ea=00108bf12900\r\n"
95 	"vgasize=640x480x8\r\n"
96 	"kernelpercent=40\r\n"
97 	"console=0 lcd\r\nbaud=19200\r\n",
98 
99 	/* 823 */
100 	"ether0=type=SCC port=2 ea=00108bf12900\r\n"
101 	"vgasize=640x480x8\r\n"
102 	"kernelpercent=40\r\n"
103 	"console=0 lcd\r\nbaud=19200\r\n",
104 };
105 
106 char *
archconfig(void)107 archconfig(void)
108 {
109 	print("Using default configuration\n");
110 	return defplan9ini[MPCMODEL(m->cputype) == 0x823];
111 }
112 
113 /*
114  * provide value for #r/switch (devrtc.c)
115  */
116 int
archoptionsw(void)117 archoptionsw(void)
118 {
119 	return 0;
120 }
121 
122 /*
123  * invoked by clock.c:/^clockintr
124  */
125 static void
twinkle(void)126 twinkle(void)
127 {
128 	/* no easy-to-use LED on PAQ (they use i2c) */
129 }
130 
131 void	(*archclocktick)(void) = twinkle;
132 
133 /*
134  * for flash.c:/^flashinit
135  * retrieve flash type, virtual base and length and return 0;
136  * return -1 on error (no flash)
137  */
138 int
archflashreset(char * type,void ** addr,long * length)139 archflashreset(char *type, void **addr, long *length)
140 {
141 	strcpy(type, "AMD29F0x0");
142 	*addr = KADDR(FLASHMEM);
143 	*length = 8*1024*1024;	/* 8mbytes on some models */
144 	return 0;
145 }
146 
147 /*
148  * enable the clocks for the given SCC ether and reveal them to the caller.
149  * do anything else required to prepare the transceiver (eg, set full-duplex, reset loopback).
150  */
151 int
archetherenable(int cpmid,int * rcs,int * tcs)152 archetherenable(int cpmid, int *rcs, int *tcs)
153 {
154 	USED(cpmid, rcs, tcs);
155 	return -1;	/* there isn't an ether on the PAQs */
156 }
157 
158 void
archetherdisable(int id)159 archetherdisable(int id)
160 {
161 	USED(id);
162 }
163 
164 /*
165  * do anything extra required to enable the UART on the given CPM port
166  */
167 void
archenableuart(int id,int irda)168 archenableuart(int id, int irda)
169 {
170 	IMM *io;
171 
172 	USED(irda);
173 	switch(id){
174 	case SMC1ID:
175 		io = ioplock();
176 		io->pbodr &= ~0xc0;
177 		io->pbdat |= 0xc0;
178 		io->pcdat |= 0x400;
179 		io->pcpar &= ~0x400;
180 		io->pcdir |= 0x400;
181 		io->pcdat &= ~0x400;	/* enable SMC RS232 buffer */
182 		iopunlock();
183 		break;
184 	case SCC2ID:
185 		/* TO DO */
186 		break;
187 	default:
188 		/* nothing special */
189 		break;
190 	}
191 }
192 
193 /*
194  * do anything extra required to disable the UART on the given CPM port
195  */
196 void
archdisableuart(int id)197 archdisableuart(int id)
198 {
199 	switch(id){
200 	case SMC1ID:
201 		/* TO DO */
202 		break;
203 	case SCC2ID:
204 		/* TO DO */
205 		break;
206 	default:
207 		/* nothing special */
208 		break;
209 	}
210 }
211 
212 /*
213  * enable/disable the LCD panel's backlight via i2c
214  */
215 void
archbacklight(int on)216 archbacklight(int on)
217 {
218 	uchar msg;
219 	IMM *io;
220 
221 	i2csetup();
222 	msg = ~7;
223 	i2csend(LEDRegI2C, &msg, 1);
224 	io = ioplock();
225 	io->pbpar &= ~EnableLCD;
226 	io->pbodr &= ~EnableLCD;
227 	io->pbdir |= EnableLCD;
228 	if(on)
229 		io->pbdat |= EnableLCD;
230 	else
231 		io->pbdat &= ~EnableLCD;
232 	iopunlock();
233 	if(on){
234 		msg = ~(DisablePanelVCC5|DisableTFT);
235 		i2csend(PanelI2C, &msg, 1);
236 	}else{
237 		msg = ~0;
238 		i2csend(PanelI2C, &msg, 1);
239 	}
240 }
241