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