|
|
1.1 root 1: #include "config.h"
2: #include "libopenbios/bindings.h"
3: #include "drivers/drivers.h"
4: #include "libc/byteorder.h"
5: #include "libc/vsprintf.h"
6:
7: #include "macio.h"
8: #include "cuda.h"
9:
10: //#define DEBUG_CUDA
11: #ifdef DEBUG_CUDA
12: #define CUDA_DPRINTF(fmt, args...) \
13: do { printk("CUDA - %s: " fmt, __func__ , ##args); } while (0)
14: #else
15: #define CUDA_DPRINTF(fmt, args...) do { } while (0)
16: #endif
17:
18: #define IO_CUDA_OFFSET 0x00016000
19: #define IO_CUDA_SIZE 0x00002000
20:
21: /* VIA registers - spaced 0x200 bytes apart */
22: #define RS 0x200 /* skip between registers */
23: #define B 0 /* B-side data */
24: #define A RS /* A-side data */
25: #define DIRB (2*RS) /* B-side direction (1=output) */
26: #define DIRA (3*RS) /* A-side direction (1=output) */
27: #define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */
28: #define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */
29: #define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */
30: #define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */
31: #define T2CL (8*RS) /* Timer 2 ctr/latch (low 8 bits) */
32: #define T2CH (9*RS) /* Timer 2 counter (high 8 bits) */
33: #define SR (10*RS) /* Shift register */
34: #define ACR (11*RS) /* Auxiliary control register */
35: #define PCR (12*RS) /* Peripheral control register */
36: #define IFR (13*RS) /* Interrupt flag register */
37: #define IER (14*RS) /* Interrupt enable register */
38: #define ANH (15*RS) /* A-side data, no handshake */
39:
40: /* Bits in B data register: all active low */
41: #define TREQ 0x08 /* Transfer request (input) */
42: #define TACK 0x10 /* Transfer acknowledge (output) */
43: #define TIP 0x20 /* Transfer in progress (output) */
44:
45: /* Bits in ACR */
46: #define SR_CTRL 0x1c /* Shift register control bits */
47: #define SR_EXT 0x0c /* Shift on external clock */
48: #define SR_OUT 0x10 /* Shift out if 1 */
49:
50: /* Bits in IFR and IER */
51: #define IER_SET 0x80 /* set bits in IER */
52: #define IER_CLR 0 /* clear bits in IER */
53: #define SR_INT 0x04 /* Shift register full/empty */
54:
55: #define CUDA_BUF_SIZE 16
56:
57: #define ADB_PACKET 0
58: #define CUDA_PACKET 1
59:
60: /* CUDA commands (2nd byte) */
61: #define CUDA_GET_TIME 0x03
62: #define CUDA_SET_TIME 0x09
63: #define CUDA_POWERDOWN 0x0a
64: #define CUDA_RESET_SYSTEM 0x11
65:
66: static uint8_t cuda_readb (cuda_t *dev, int reg)
67: {
68: return *(volatile uint8_t *)(dev->base + reg);
69: }
70:
71: static void cuda_writeb (cuda_t *dev, int reg, uint8_t val)
72: {
73: *(volatile uint8_t *)(dev->base + reg) = val;
74: }
75:
76: static void cuda_wait_irq (cuda_t *dev)
77: {
78: int val;
79:
80: // CUDA_DPRINTF("\n");
81: for(;;) {
82: val = cuda_readb(dev, IFR);
83: cuda_writeb(dev, IFR, val & 0x7f);
84: if (val & SR_INT)
85: break;
86: }
87: }
88:
89:
90:
91: static int cuda_request (cuda_t *dev, uint8_t pkt_type, const uint8_t *buf,
92: int buf_len, uint8_t *obuf)
93: {
94: int i, obuf_len, val;
95:
96: cuda_writeb(dev, ACR, cuda_readb(dev, ACR) | SR_OUT);
97: cuda_writeb(dev, SR, pkt_type);
98: cuda_writeb(dev, B, cuda_readb(dev, B) & ~TIP);
99: if (buf) {
100: //CUDA_DPRINTF("Send buf len: %d\n", buf_len);
101: /* send 'buf' */
102: for(i = 0; i < buf_len; i++) {
103: cuda_wait_irq(dev);
104: cuda_writeb(dev, SR, buf[i]);
105: cuda_writeb(dev, B, cuda_readb(dev, B) ^ TACK);
106: }
107: }
108: cuda_wait_irq(dev);
109: cuda_writeb(dev, ACR, cuda_readb(dev, ACR) & ~SR_OUT);
110: cuda_readb(dev, SR);
111: cuda_writeb(dev, B, cuda_readb(dev, B) | TIP | TACK);
112:
113: obuf_len = 0;
114: if (obuf) {
115: cuda_wait_irq(dev);
116: cuda_readb(dev, SR);
117: cuda_writeb(dev, B, cuda_readb(dev, B) & ~TIP);
118: for(;;) {
119: cuda_wait_irq(dev);
120: val = cuda_readb(dev, SR);
121: if (obuf_len < CUDA_BUF_SIZE)
122: obuf[obuf_len++] = val;
123: if (cuda_readb(dev, B) & TREQ)
124: break;
125: cuda_writeb(dev, B, cuda_readb(dev, B) ^ TACK);
126: }
127: cuda_writeb(dev, B, cuda_readb(dev, B) | TIP | TACK);
128:
129: cuda_wait_irq(dev);
130: cuda_readb(dev, SR);
131: }
132: // CUDA_DPRINTF("Got len: %d\n", obuf_len);
133:
134: return obuf_len;
135: }
136:
137:
138:
139: static int cuda_adb_req (void *host, const uint8_t *snd_buf, int len,
140: uint8_t *rcv_buf)
141: {
142: uint8_t buffer[CUDA_BUF_SIZE], *pos;
143:
144: // CUDA_DPRINTF("len: %d %02x\n", len, snd_buf[0]);
145: len = cuda_request(host, ADB_PACKET, snd_buf, len, buffer);
146: if (len > 1 && buffer[0] == ADB_PACKET) {
147: pos = buffer + 2;
148: len -= 2;
149: } else {
150: pos = buffer + 1;
151: len = -1;
152: }
153: memcpy(rcv_buf, pos, len);
154:
155: return len;
156: }
157:
158:
159: DECLARE_UNNAMED_NODE(ob_cuda, INSTALL_OPEN, sizeof(int));
160:
161: static cuda_t *main_cuda;
162:
163: static void
164: ppc32_reset_all(void)
165: {
166: uint8_t cmdbuf[2], obuf[64];
167:
168: cmdbuf[0] = CUDA_RESET_SYSTEM;
169: cuda_request(main_cuda, CUDA_PACKET, cmdbuf, sizeof(cmdbuf), obuf);
170: }
171:
172: static void
173: ppc32_poweroff(void)
174: {
175: uint8_t cmdbuf[2], obuf[64];
176:
177: cmdbuf[0] = CUDA_POWERDOWN;
178: cuda_request(main_cuda, CUDA_PACKET, cmdbuf, sizeof(cmdbuf), obuf);
179: }
180:
181: static void
182: ob_cuda_initialize (int *idx)
183: {
184: phandle_t ph=get_cur_dev();
185: int props[2];
186:
187: push_str("via-cuda");
188: fword("device-type");
189:
190: set_int_property(ph, "#address-cells", 1);
191: set_int_property(ph, "#size-cells", 0);
192:
193: set_property(ph, "compatible", "cuda", 5);
194:
195: props[0] = __cpu_to_be32(IO_CUDA_OFFSET);
196: props[1] = __cpu_to_be32(IO_CUDA_SIZE);
197:
198: set_property(ph, "reg", (char *)&props, sizeof(props));
199:
200: /* on newworld machines the cuda is on interrupt 0x19 */
201:
202: props[0] = 0x19;
203: props[1] = 0;
204: NEWWORLD(set_property(ph, "interrupts", (char *)props, sizeof(props)));
205: NEWWORLD(set_int_property(ph, "#interrupt-cells", 2));
206:
207: /* we emulate an oldworld hardware, so we must use
208: * non-standard oldworld property (needed by linux 2.6.18)
209: */
210:
211: OLDWORLD(set_int_property(ph, "AAPL,interrupts", 0x12));
212:
213: bind_func("ppc32-reset-all", ppc32_reset_all);
214: push_str("' ppc32-reset-all to reset-all");
215: fword("eval");
216: }
217:
218: static void
219: ob_cuda_open(int *idx)
220: {
221: RET(-1);
222: }
223:
224: static void
225: ob_cuda_close(int *idx)
226: {
227: }
228:
229: NODE_METHODS(ob_cuda) = {
230: { NULL, ob_cuda_initialize },
231: { "open", ob_cuda_open },
232: { "close", ob_cuda_close },
233: };
234:
235: DECLARE_UNNAMED_NODE(rtc, INSTALL_OPEN, sizeof(int));
236:
237: static void
238: rtc_open(int *idx)
239: {
240: RET(-1);
241: }
242:
243: /*
244: * get-time ( -- second minute hour day month year )
245: *
246: */
247:
248: static const int days_month[12] =
249: { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
250: static const int days_month_leap[12] =
251: { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
252:
253: static inline int is_leap(int year)
254: {
255: return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
256: }
257:
258: static void
259: rtc_get_time(int *idx)
260: {
261: uint8_t cmdbuf[2], obuf[64];
262: ucell second, minute, hour, day, month, year;
263: uint32_t now;
264: int current;
265: const int *days;
266:
267: cmdbuf[0] = CUDA_GET_TIME;
268: cuda_request(main_cuda, CUDA_PACKET, cmdbuf, sizeof(cmdbuf), obuf);
269:
270: /* seconds since 01/01/1904 */
271:
272: now = (obuf[3] << 24) + (obuf[4] << 16) + (obuf[5] << 8) + obuf[6];
273:
274: second = now % 60;
275: now /= 60;
276:
277: minute = now % 60;
278: now /= 60;
279:
280: hour = now % 24;
281: now /= 24;
282:
283: year = now * 100 / 36525;
284: now -= year * 36525 / 100;
285: year += 1904;
286:
287: days = is_leap(year) ? days_month_leap : days_month;
288:
289: current = 0;
290: month = 0;
291: while (month < 12) {
292: if (now <= current + days[month]) {
293: break;
294: }
295: current += days[month];
296: month++;
297: }
298: month++;
299:
300: day = now - current;
301:
302: PUSH(second);
303: PUSH(minute);
304: PUSH(hour);
305: PUSH(day);
306: PUSH(month);
307: PUSH(year);
308: }
309:
310: /*
311: * set-time ( second minute hour day month year -- )
312: *
313: */
314:
315: static void
316: rtc_set_time(int *idx)
317: {
318: uint8_t cmdbuf[5], obuf[3];
319: ucell second, minute, hour, day, month, year;
320: const int *days;
321: uint32_t now;
322: unsigned int nb_days;
323: int i;
324:
325: year = POP();
326: month = POP();
327: day = POP();
328: hour = POP();
329: minute = POP();
330: second = POP();
331:
332: days = is_leap(year) ? days_month_leap : days_month;
333: nb_days = (year - 1904) * 36525 / 100 + day;
334: for (i = 0; i < month - 1; i++)
335: nb_days += days[i];
336:
337: now = (((nb_days * 24) + hour) * 60 + minute) * 60 + second;
338:
339: cmdbuf[0] = CUDA_SET_TIME;
340: cmdbuf[1] = now >> 24;
341: cmdbuf[2] = now >> 16;
342: cmdbuf[3] = now >> 8;
343: cmdbuf[4] = now;
344:
345: cuda_request(main_cuda, CUDA_PACKET, cmdbuf, sizeof(cmdbuf), obuf);
346: }
347:
348: NODE_METHODS(rtc) = {
349: { "open", rtc_open },
350: { "get-time", rtc_get_time },
351: { "set-time", rtc_set_time },
352: };
353:
354: static void
355: rtc_init(char *path)
356: {
357: phandle_t ph, aliases;
358: char buf[64];
359:
360: snprintf(buf, sizeof(buf), "%s/rtc", path);
361: REGISTER_NAMED_NODE(rtc, buf);
362:
363: ph = find_dev(buf);
364: set_property(ph, "device_type", "rtc", 4);
365: set_property(ph, "compatible", "rtc", 4);
366:
367: aliases = find_dev("/aliases");
368: set_property(aliases, "rtc", buf, strlen(buf) + 1);
369:
370: }
371:
372: cuda_t *cuda_init (const char *path, phys_addr_t base)
373: {
374: cuda_t *cuda;
375: char buf[64];
376: phandle_t aliases;
377:
378: base += IO_CUDA_OFFSET;
379: CUDA_DPRINTF(" base=" FMT_plx "\n", base);
380: cuda = malloc(sizeof(cuda_t));
381: if (cuda == NULL)
382: return NULL;
383:
384: snprintf(buf, sizeof(buf), "%s/via-cuda", path);
385: REGISTER_NAMED_NODE(ob_cuda, buf);
386:
387: aliases = find_dev("/aliases");
388: set_property(aliases, "via-cuda", buf, strlen(buf) + 1);
389:
390: cuda->base = base;
391: cuda_writeb(cuda, B, cuda_readb(cuda, B) | TREQ | TIP);
392: #ifdef CONFIG_DRIVER_ADB
393: cuda->adb_bus = adb_bus_new(cuda, &cuda_adb_req);
394: if (cuda->adb_bus == NULL) {
395: free(cuda);
396: return NULL;
397: }
398: adb_bus_init(buf, cuda->adb_bus);
399: #endif
400:
401: rtc_init(buf);
402:
403: main_cuda = cuda;
404:
405: device_end();
406: bind_func("poweroff", ppc32_poweroff);
407:
408: return cuda;
409: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.