this repo has no description
1/*
2 PMUEMDEV.c
3
4 Copyright (C) 2008 Paul C. Pratt
5
6 You can redistribute this file and/or modify it under the terms
7 of version 2 of the GNU General Public License as published by
8 the Free Software Foundation. You should have received a copy
9 of the license along with this file; see the file COPYING.
10
11 This file is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 license for more details.
15*/
16
17/*
18 Power Management Unit EMulated DEVice
19*/
20
21#include "PICOMMON.h"
22
23#if EmPMU
24
25#include "VIAEMDEV.h"
26
27#include "PMUEMDEV.h"
28
29/*
30 ReportAbnormalID unused 0x0E0E - 0x0EFF
31*/
32
33enum {
34 kPMUStateReadyForCommand,
35 kPMUStateRecievingLength,
36 kPMUStateRecievingBuffer,
37 kPMUStateRecievedCommand,
38 kPMUStateSendLength,
39 kPMUStateSendBuffer,
40
41 kPMUStates
42};
43
44#define PMU_BuffSz 8
45LOCALVAR ui3b PMU_BuffA[PMU_BuffSz];
46LOCALVAR ui3p PMU_p;
47LOCALVAR ui3r PMU_rem;
48LOCALVAR ui3r PMU_i;
49
50LOCALVAR int PMUState = kPMUStateReadyForCommand;
51
52LOCALVAR ui3r PMU_CurCommand;
53LOCALVAR ui3r PMU_SendNext;
54LOCALVAR ui3r PMU_BuffL;
55
56LOCALPROC PmuStartSendResult(ui3r ResultCode, ui3r L)
57{
58 PMU_SendNext = ResultCode;
59 PMU_BuffL = L;
60 PMUState = kPMUStateSendLength;
61}
62
63LOCALVAR ui3b PARAMRAM[128];
64
65LOCALPROC PmuCheckCommandOp(void)
66{
67 switch (PMU_CurCommand) {
68 case 0x10: /* kPMUpowerCntl - power plane/clock control */
69 break;
70 case 0x32: /* kPMUxPramWrite - write extended PRAM byte(s) */
71 if (kPMUStateRecievingBuffer == PMUState) {
72 if (0 == PMU_i) {
73 if (PMU_BuffL >= 2) {
74 PMU_p = PMU_BuffA;
75 PMU_rem = 2;
76 } else {
77 ReportAbnormalID(0x0E01,
78 "PMU_BuffL too small for kPMUxPramWrite");
79 }
80 } else if (2 == PMU_i) {
81 if ((PMU_BuffA[1] + 2 == PMU_BuffL)
82 && (PMU_BuffA[0] + PMU_BuffA[1] <= 0x80))
83 {
84 PMU_p = &PARAMRAM[PMU_BuffA[0]];
85 PMU_rem = PMU_BuffA[1];
86 } else {
87 ReportAbnormalID(0x0E02,
88 "bad range for kPMUxPramWrite");
89 }
90 } else {
91 ReportAbnormalID(0x0E03,
92 "Wrong PMU_i for kPMUpramWrite");
93 }
94 } else if (kPMUStateRecievedCommand == PMUState) {
95 /* already done */
96 }
97 break;
98#if 0
99 case 0xE2: /* kPMUdownloadStatus - PRAM status */
100 break;
101#endif
102 case 0xE0: /* kPMUwritePmgrRAM - write to internal PMGR RAM */
103 break;
104 case 0x21: /* kPMUpMgrADBoff - turn ADB auto-poll off */
105 if (kPMUStateRecievedCommand == PMUState) {
106 if (0 != PMU_BuffL) {
107 ReportAbnormalID(0x0E04,
108 "kPMUpMgrADBoff nonzero length");
109 }
110 }
111 break;
112 case 0xEC: /* kPMUPmgrSelfTest - run the PMGR selftest */
113 if (kPMUStateRecievedCommand == PMUState) {
114 PmuStartSendResult(0, 0);
115 }
116 break;
117 case 0x78:
118 /* kPMUreadINT - get PMGR interrupt data */
119 case 0x68:
120 /*
121 kPMUbatteryRead - read battery/charger level and status
122 */
123 case 0x7F:
124 /*
125 kPMUsleepReq - put the system to sleep (sleepSig='MATT')
126 */
127 if (kPMUStateRecievedCommand == PMUState) {
128 PMU_BuffA[0] = 0;
129 PmuStartSendResult(0, 1);
130 }
131 break;
132 case 0xE8: /* kPMUreadPmgrRAM - read from internal PMGR RAM */
133 if (kPMUStateRecievedCommand == PMUState) {
134 if ((3 == PMU_BuffL)
135 && (0 == PMU_BuffA[0])
136 && (0xEE == PMU_BuffA[1])
137 && (1 == PMU_BuffA[2]))
138 {
139 PMU_BuffA[0] = 1 << 5;
140 PmuStartSendResult(0, 1);
141 } else {
142 PMU_BuffA[0] = 0;
143 PmuStartSendResult(0, 1);
144 /* ReportAbnormal("Unknown kPMUreadPmgrRAM op"); */
145 }
146 }
147 break;
148 case 0x3A: /* kPMUxPramRead - read extended PRAM byte(s) */
149 if (kPMUStateRecievedCommand == PMUState) {
150 if ((2 == PMU_BuffL)
151 && (PMU_BuffA[0] + PMU_BuffA[1] <= 0x80))
152 {
153 PMU_p = &PARAMRAM[PMU_BuffA[0]];
154 PMU_rem = PMU_BuffA[1];
155 PmuStartSendResult(0, PMU_rem);
156 } else {
157 ReportAbnormalID(0x0E05,
158 "Unknown kPMUxPramRead op");
159 }
160 }
161 break;
162 case 0x38:
163 /* kPMUtimeRead - read the time from the clock chip */
164 if (kPMUStateRecievedCommand == PMUState) {
165 if (0 == PMU_BuffL) {
166 PMU_BuffA[0] = 0;
167 PMU_BuffA[1] = 0;
168 PMU_BuffA[2] = 0;
169 PMU_BuffA[3] = 0;
170 PmuStartSendResult(0, 4);
171 } else {
172 ReportAbnormalID(0x0E06, "Unknown kPMUtimeRead op");
173 }
174 }
175 break;
176 case 0x31:
177 /*
178 kPMUpramWrite - write the original 20 bytes of PRAM
179 (Portable only)
180 */
181 if (kPMUStateRecievedCommand == PMUState) {
182 if (20 == PMU_BuffL) {
183 /* done */
184 } else {
185 ReportAbnormalID(0x0E07,
186 "Unknown kPMUpramWrite op");
187 }
188 } else if (kPMUStateRecievingBuffer == PMUState) {
189 if (20 == PMU_BuffL) {
190 if (0 == PMU_i) {
191 PMU_p = &PARAMRAM[16];
192 PMU_rem = 16;
193 } else if (16 == PMU_i) {
194 PMU_p = &PARAMRAM[8];
195 PMU_rem = 4;
196 } else {
197 ReportAbnormalID(0x0E08,
198 "Wrong PMU_i for kPMUpramWrite");
199 }
200 }
201 }
202 break;
203 case 0x39:
204 /*
205 kPMUpramRead - read the original 20 bytes of PRAM
206 (Portable only)
207 */
208 if (kPMUStateRecievedCommand == PMUState) {
209 if (0 == PMU_BuffL) {
210 PmuStartSendResult(0, 20);
211 } else {
212 ReportAbnormalID(0x0E09, "Unknown kPMUpramRead op");
213 }
214 } else if (kPMUStateSendBuffer == PMUState) {
215#if 0
216 {
217 int i;
218
219 for (i = 0; i < PMU_BuffSz; ++i) {
220 PMU_BuffA[i] = 0;
221 }
222 }
223#endif
224 if (0 == PMU_i) {
225 PMU_p = &PARAMRAM[16];
226 PMU_rem = 16;
227 } else if (16 == PMU_i) {
228 PMU_p = &PARAMRAM[8];
229 PMU_rem = 4;
230 } else {
231 ReportAbnormalID(0x0E0A,
232 "Wrong PMU_i for kPMUpramRead");
233 }
234 }
235 break;
236 default:
237 if (kPMUStateRecievedCommand == PMUState) {
238 ReportAbnormalID(0x0E0B, "Unknown PMU op");
239#if dbglog_HAVE
240 dbglog_writeCStr("Unknown PMU op ");
241 dbglog_writeHex(PMU_CurCommand);
242 dbglog_writeReturn();
243 dbglog_writeCStr("PMU_BuffL = ");
244 dbglog_writeHex(PMU_BuffL);
245 dbglog_writeReturn();
246 if (PMU_BuffL <= PMU_BuffSz) {
247 int i;
248
249 for (i = 0; i < PMU_BuffL; ++i) {
250 dbglog_writeCStr("PMU_BuffA[");
251 dbglog_writeNum(i);
252 dbglog_writeCStr("] = ");
253 dbglog_writeHex(PMU_BuffA[i]);
254 dbglog_writeReturn();
255 }
256 }
257#endif
258 }
259 break;
260 }
261}
262
263LOCALPROC LocBuffSetUpNextChunk(void)
264{
265 PMU_p = PMU_BuffA;
266 PMU_rem = PMU_BuffL - PMU_i;
267 if (PMU_rem >= PMU_BuffSz) {
268 PMU_rem = PMU_BuffSz;
269 }
270}
271
272LOCALFUNC ui3r GetPMUbus(void)
273{
274 ui3r v;
275
276 v = VIA1_iA7;
277 v <<= 1;
278 v |= VIA1_iA6;
279 v <<= 1;
280 v |= VIA1_iA5;
281 v <<= 1;
282 v |= VIA1_iA4;
283 v <<= 1;
284 v |= VIA1_iA3;
285 v <<= 1;
286 v |= VIA1_iA2;
287 v <<= 1;
288 v |= VIA1_iA1;
289 v <<= 1;
290 v |= VIA1_iA0;
291
292 return v;
293}
294
295LOCALPROC SetPMUbus(ui3r v)
296{
297 VIA1_iA0 = v & 0x01;
298 v >>= 1;
299 VIA1_iA1 = v & 0x01;
300 v >>= 1;
301 VIA1_iA2 = v & 0x01;
302 v >>= 1;
303 VIA1_iA3 = v & 0x01;
304 v >>= 1;
305 VIA1_iA4 = v & 0x01;
306 v >>= 1;
307 VIA1_iA5 = v & 0x01;
308 v >>= 1;
309 VIA1_iA6 = v & 0x01;
310 v >>= 1;
311 VIA1_iA7 = v & 0x01;
312}
313
314LOCALVAR blnr PMU_Sending = falseblnr;
315
316LOCALPROC PmuCheckCommandCompletion(void)
317{
318 if (PMU_i == PMU_BuffL) {
319 PMUState = kPMUStateRecievedCommand;
320 PmuCheckCommandOp();
321 if ((PMU_CurCommand & 0x08) == 0) {
322 PMUState = kPMUStateReadyForCommand;
323 SetPMUbus(0xFF);
324 } else {
325 if (PMUState != kPMUStateSendLength) {
326 PmuStartSendResult(0xFF, 0);
327 PMUState = kPMUStateSendLength;
328 }
329 PMU_i = 0;
330 PMU_Sending = trueblnr;
331 ICT_add(kICT_PMU_Task,
332 20400UL * kCycleScale / 64 * kMyClockMult);
333 }
334 }
335}
336
337GLOBALPROC PmuToReady_ChangeNtfy(void)
338{
339 if (PMU_Sending) {
340 PMU_Sending = falseblnr;
341 ReportAbnormalID(0x0E0C,
342 "PmuToReady_ChangeNtfy while PMU_Sending");
343 PmuFromReady = 0;
344 }
345 switch (PMUState) {
346 case kPMUStateReadyForCommand:
347 if (! PmuToReady) {
348 PmuFromReady = 0;
349 } else {
350 PMU_CurCommand = GetPMUbus();
351 PMUState = kPMUStateRecievingLength;
352 PmuFromReady = 1;
353 }
354 break;
355 case kPMUStateRecievingLength:
356 if (! PmuToReady) {
357 PmuFromReady = 0;
358 } else {
359 PMU_BuffL = GetPMUbus();
360 PMU_i = 0;
361 PMU_rem = 0;
362 PMUState = kPMUStateRecievingBuffer;
363 PmuCheckCommandCompletion();
364 PmuFromReady = 1;
365 }
366 break;
367 case kPMUStateRecievingBuffer:
368 if (! PmuToReady) {
369 PmuFromReady = 0;
370 } else {
371 ui3r v = GetPMUbus();
372 if (0 == PMU_rem) {
373 PMU_p = nullpr;
374 PmuCheckCommandOp();
375 if (nullpr == PMU_p) {
376 /* default handler */
377 LocBuffSetUpNextChunk();
378 }
379 }
380 if (nullpr == PMU_p) {
381 /* mini vmac bug if ever happens */
382 ReportAbnormalID(0x0E0D,
383 "PMU_p null while kPMUStateRecievingBuffer");
384 }
385 *PMU_p++ = v;
386 --PMU_rem;
387 ++PMU_i;
388 PmuCheckCommandCompletion();
389 PmuFromReady = 1;
390 }
391 break;
392 case kPMUStateSendLength:
393 if (! PmuToReady) {
394 /* receiving */
395 PmuFromReady = 1;
396 } else {
397 PMU_SendNext = PMU_BuffL;
398 PMUState = kPMUStateSendBuffer;
399 PMU_Sending = trueblnr;
400 ICT_add(kICT_PMU_Task,
401 20400UL * kCycleScale / 64 * kMyClockMult);
402 }
403 break;
404 case kPMUStateSendBuffer:
405 if (! PmuToReady) {
406 /* receiving */
407 PmuFromReady = 1;
408 } else {
409 if (PMU_i == PMU_BuffL) {
410 PMUState = kPMUStateReadyForCommand;
411 SetPMUbus(0xFF);
412 } else {
413 if (0 == PMU_rem) {
414 PMU_p = nullpr;
415 PmuCheckCommandOp();
416 if (nullpr == PMU_p) {
417 /* default handler */
418 LocBuffSetUpNextChunk();
419 }
420 }
421 PMU_SendNext = *PMU_p++;
422 --PMU_rem;
423 ++PMU_i;
424 PMU_Sending = trueblnr;
425 ICT_add(kICT_PMU_Task,
426 20400UL * kCycleScale / 64 * kMyClockMult);
427 }
428 }
429 break;
430 }
431}
432
433GLOBALPROC PMU_DoTask(void)
434{
435 if (PMU_Sending) {
436 PMU_Sending = falseblnr;
437 SetPMUbus(PMU_SendNext);
438 PmuFromReady = 0;
439 }
440}
441
442#endif /* EmPMU */