]> git.proxmox.com Git - qemu.git/blob - hw/cbus.c
SCSI divide capacity by s->cluster_size (Rik van Riel)
[qemu.git] / hw / cbus.c
1 /*
2 * CBUS three-pin bus and the Retu / Betty / Tahvo / Vilma / Avilma /
3 * Hinku / Vinku / Ahne / Pihi chips used in various Nokia platforms.
4 * Based on reverse-engineering of a linux driver.
5 *
6 * Copyright (C) 2008 Nokia Corporation
7 * Written by Andrzej Zaborowski <andrew@openedhand.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 or
12 * (at your option) version 3 of the License.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23
24 #include "qemu-common.h"
25 #include "irq.h"
26 #include "devices.h"
27 #include "sysemu.h"
28
29 //#define DEBUG
30
31 struct cbus_slave_s;
32 struct cbus_priv_s {
33 struct cbus_s cbus;
34
35 int sel;
36 int dat;
37 int clk;
38 int bit;
39 int dir;
40 uint16_t val;
41 qemu_irq dat_out;
42
43 int addr;
44 int reg;
45 int rw;
46 enum {
47 cbus_address,
48 cbus_value,
49 } cycle;
50
51 struct cbus_slave_s *slave[8];
52 };
53
54 struct cbus_slave_s {
55 void *opaque;
56 void (*io)(void *opaque, int rw, int reg, uint16_t *val);
57 int addr;
58 };
59
60 static void cbus_io(struct cbus_priv_s *s)
61 {
62 if (s->slave[s->addr])
63 s->slave[s->addr]->io(s->slave[s->addr]->opaque,
64 s->rw, s->reg, &s->val);
65 else
66 cpu_abort(cpu_single_env, "%s: bad slave address %i\n",
67 __FUNCTION__, s->addr);
68 }
69
70 static void cbus_cycle(struct cbus_priv_s *s)
71 {
72 switch (s->cycle) {
73 case cbus_address:
74 s->addr = (s->val >> 6) & 7;
75 s->rw = (s->val >> 5) & 1;
76 s->reg = (s->val >> 0) & 0x1f;
77
78 s->cycle = cbus_value;
79 s->bit = 15;
80 s->dir = !s->rw;
81 s->val = 0;
82
83 if (s->rw)
84 cbus_io(s);
85 break;
86
87 case cbus_value:
88 if (!s->rw)
89 cbus_io(s);
90
91 s->cycle = cbus_address;
92 s->bit = 8;
93 s->dir = 1;
94 s->val = 0;
95 break;
96 }
97 }
98
99 static void cbus_clk(void *opaque, int line, int level)
100 {
101 struct cbus_priv_s *s = (struct cbus_priv_s *) opaque;
102
103 if (!s->sel && level && !s->clk) {
104 if (s->dir)
105 s->val |= s->dat << (s->bit --);
106 else
107 qemu_set_irq(s->dat_out, (s->val >> (s->bit --)) & 1);
108
109 if (s->bit < 0)
110 cbus_cycle(s);
111 }
112
113 s->clk = level;
114 }
115
116 static void cbus_dat(void *opaque, int line, int level)
117 {
118 struct cbus_priv_s *s = (struct cbus_priv_s *) opaque;
119
120 s->dat = level;
121 }
122
123 static void cbus_sel(void *opaque, int line, int level)
124 {
125 struct cbus_priv_s *s = (struct cbus_priv_s *) opaque;
126
127 if (!level) {
128 s->dir = 1;
129 s->bit = 8;
130 s->val = 0;
131 }
132
133 s->sel = level;
134 }
135
136 struct cbus_s *cbus_init(qemu_irq dat)
137 {
138 struct cbus_priv_s *s = (struct cbus_priv_s *) qemu_mallocz(sizeof(*s));
139
140 s->dat_out = dat;
141 s->cbus.clk = qemu_allocate_irqs(cbus_clk, s, 1)[0];
142 s->cbus.dat = qemu_allocate_irqs(cbus_dat, s, 1)[0];
143 s->cbus.sel = qemu_allocate_irqs(cbus_sel, s, 1)[0];
144
145 s->sel = 1;
146 s->clk = 0;
147 s->dat = 0;
148
149 return &s->cbus;
150 }
151
152 void cbus_attach(struct cbus_s *bus, void *slave_opaque)
153 {
154 struct cbus_slave_s *slave = (struct cbus_slave_s *) slave_opaque;
155 struct cbus_priv_s *s = (struct cbus_priv_s *) bus;
156
157 s->slave[slave->addr] = slave;
158 }
159
160 /* Retu/Vilma */
161 struct cbus_retu_s {
162 uint16_t irqst;
163 uint16_t irqen;
164 uint16_t cc[2];
165 int channel;
166 uint16_t result[16];
167 uint16_t sample;
168 uint16_t status;
169
170 struct {
171 uint16_t cal;
172 } rtc;
173
174 int is_vilma;
175 qemu_irq irq;
176 struct cbus_slave_s cbus;
177 };
178
179 static void retu_interrupt_update(struct cbus_retu_s *s)
180 {
181 qemu_set_irq(s->irq, s->irqst & ~s->irqen);
182 }
183
184 #define RETU_REG_ASICR 0x00 /* (RO) ASIC ID & revision */
185 #define RETU_REG_IDR 0x01 /* (T) Interrupt ID */
186 #define RETU_REG_IMR 0x02 /* (RW) Interrupt mask */
187 #define RETU_REG_RTCDSR 0x03 /* (RW) RTC seconds register */
188 #define RETU_REG_RTCHMR 0x04 /* (RO) RTC hours and minutes reg */
189 #define RETU_REG_RTCHMAR 0x05 /* (RW) RTC hours and minutes set reg */
190 #define RETU_REG_RTCCALR 0x06 /* (RW) RTC calibration register */
191 #define RETU_REG_ADCR 0x08 /* (RW) ADC result register */
192 #define RETU_REG_ADCSCR 0x09 /* (RW) ADC sample control register */
193 #define RETU_REG_AFCR 0x0a /* (RW) AFC register */
194 #define RETU_REG_ANTIFR 0x0b /* (RW) AntiF register */
195 #define RETU_REG_CALIBR 0x0c /* (RW) CalibR register*/
196 #define RETU_REG_CCR1 0x0d /* (RW) Common control register 1 */
197 #define RETU_REG_CCR2 0x0e /* (RW) Common control register 2 */
198 #define RETU_REG_RCTRL_CLR 0x0f /* (T) Regulator clear register */
199 #define RETU_REG_RCTRL_SET 0x10 /* (T) Regulator set register */
200 #define RETU_REG_TXCR 0x11 /* (RW) TxC register */
201 #define RETU_REG_STATUS 0x16 /* (RO) Status register */
202 #define RETU_REG_WATCHDOG 0x17 /* (RW) Watchdog register */
203 #define RETU_REG_AUDTXR 0x18 /* (RW) Audio Codec Tx register */
204 #define RETU_REG_AUDPAR 0x19 /* (RW) AudioPA register */
205 #define RETU_REG_AUDRXR1 0x1a /* (RW) Audio receive register 1 */
206 #define RETU_REG_AUDRXR2 0x1b /* (RW) Audio receive register 2 */
207 #define RETU_REG_SGR1 0x1c /* (RW) */
208 #define RETU_REG_SCR1 0x1d /* (RW) */
209 #define RETU_REG_SGR2 0x1e /* (RW) */
210 #define RETU_REG_SCR2 0x1f /* (RW) */
211
212 /* Retu Interrupt sources */
213 enum {
214 retu_int_pwr = 0, /* Power button */
215 retu_int_char = 1, /* Charger */
216 retu_int_rtcs = 2, /* Seconds */
217 retu_int_rtcm = 3, /* Minutes */
218 retu_int_rtcd = 4, /* Days */
219 retu_int_rtca = 5, /* Alarm */
220 retu_int_hook = 6, /* Hook */
221 retu_int_head = 7, /* Headset */
222 retu_int_adcs = 8, /* ADC sample */
223 };
224
225 /* Retu ADC channel wiring */
226 enum {
227 retu_adc_bsi = 1, /* BSI */
228 retu_adc_batt_temp = 2, /* Battery temperature */
229 retu_adc_chg_volt = 3, /* Charger voltage */
230 retu_adc_head_det = 4, /* Headset detection */
231 retu_adc_hook_det = 5, /* Hook detection */
232 retu_adc_rf_gp = 6, /* RF GP */
233 retu_adc_tx_det = 7, /* Wideband Tx detection */
234 retu_adc_batt_volt = 8, /* Battery voltage */
235 retu_adc_sens = 10, /* Light sensor */
236 retu_adc_sens_temp = 11, /* Light sensor temperature */
237 retu_adc_bbatt_volt = 12, /* Backup battery voltage */
238 retu_adc_self_temp = 13, /* RETU temperature */
239 };
240
241 static inline uint16_t retu_read(struct cbus_retu_s *s, int reg)
242 {
243 #ifdef DEBUG
244 printf("RETU read at %02x\n", reg);
245 #endif
246
247 switch (reg) {
248 case RETU_REG_ASICR:
249 return 0x0215 | (s->is_vilma << 7);
250
251 case RETU_REG_IDR: /* TODO: Or is this ffs(s->irqst)? */
252 return s->irqst;
253
254 case RETU_REG_IMR:
255 return s->irqen;
256
257 case RETU_REG_RTCDSR:
258 case RETU_REG_RTCHMR:
259 case RETU_REG_RTCHMAR:
260 /* TODO */
261 return 0x0000;
262
263 case RETU_REG_RTCCALR:
264 return s->rtc.cal;
265
266 case RETU_REG_ADCR:
267 return (s->channel << 10) | s->result[s->channel];
268 case RETU_REG_ADCSCR:
269 return s->sample;
270
271 case RETU_REG_AFCR:
272 case RETU_REG_ANTIFR:
273 case RETU_REG_CALIBR:
274 /* TODO */
275 return 0x0000;
276
277 case RETU_REG_CCR1:
278 return s->cc[0];
279 case RETU_REG_CCR2:
280 return s->cc[1];
281
282 case RETU_REG_RCTRL_CLR:
283 case RETU_REG_RCTRL_SET:
284 case RETU_REG_TXCR:
285 /* TODO */
286 return 0x0000;
287
288 case RETU_REG_STATUS:
289 return s->status;
290
291 case RETU_REG_WATCHDOG:
292 case RETU_REG_AUDTXR:
293 case RETU_REG_AUDPAR:
294 case RETU_REG_AUDRXR1:
295 case RETU_REG_AUDRXR2:
296 case RETU_REG_SGR1:
297 case RETU_REG_SCR1:
298 case RETU_REG_SGR2:
299 case RETU_REG_SCR2:
300 /* TODO */
301 return 0x0000;
302
303 default:
304 cpu_abort(cpu_single_env, "%s: bad register %02x\n",
305 __FUNCTION__, reg);
306 }
307 }
308
309 static inline void retu_write(struct cbus_retu_s *s, int reg, uint16_t val)
310 {
311 #ifdef DEBUG
312 printf("RETU write of %04x at %02x\n", val, reg);
313 #endif
314
315 switch (reg) {
316 case RETU_REG_IDR:
317 s->irqst ^= val;
318 retu_interrupt_update(s);
319 break;
320
321 case RETU_REG_IMR:
322 s->irqen = val;
323 retu_interrupt_update(s);
324 break;
325
326 case RETU_REG_RTCDSR:
327 case RETU_REG_RTCHMAR:
328 /* TODO */
329 break;
330
331 case RETU_REG_RTCCALR:
332 s->rtc.cal = val;
333 break;
334
335 case RETU_REG_ADCR:
336 s->channel = (val >> 10) & 0xf;
337 s->irqst |= 1 << retu_int_adcs;
338 retu_interrupt_update(s);
339 break;
340 case RETU_REG_ADCSCR:
341 s->sample &= ~val;
342 break;
343
344 case RETU_REG_AFCR:
345 case RETU_REG_ANTIFR:
346 case RETU_REG_CALIBR:
347
348 case RETU_REG_CCR1:
349 s->cc[0] = val;
350 break;
351 case RETU_REG_CCR2:
352 s->cc[1] = val;
353 break;
354
355 case RETU_REG_RCTRL_CLR:
356 case RETU_REG_RCTRL_SET:
357 /* TODO */
358 break;
359
360 case RETU_REG_WATCHDOG:
361 if (val == 0 && (s->cc[0] & 2))
362 qemu_system_shutdown_request();
363 break;
364
365 case RETU_REG_TXCR:
366 case RETU_REG_AUDTXR:
367 case RETU_REG_AUDPAR:
368 case RETU_REG_AUDRXR1:
369 case RETU_REG_AUDRXR2:
370 case RETU_REG_SGR1:
371 case RETU_REG_SCR1:
372 case RETU_REG_SGR2:
373 case RETU_REG_SCR2:
374 /* TODO */
375 break;
376
377 default:
378 cpu_abort(cpu_single_env, "%s: bad register %02x\n",
379 __FUNCTION__, reg);
380 }
381 }
382
383 static void retu_io(void *opaque, int rw, int reg, uint16_t *val)
384 {
385 struct cbus_retu_s *s = (struct cbus_retu_s *) opaque;
386
387 if (rw)
388 *val = retu_read(s, reg);
389 else
390 retu_write(s, reg, *val);
391 }
392
393 void *retu_init(qemu_irq irq, int vilma)
394 {
395 struct cbus_retu_s *s = (struct cbus_retu_s *) qemu_mallocz(sizeof(*s));
396
397 s->irq = irq;
398 s->irqen = 0xffff;
399 s->irqst = 0x0000;
400 s->status = 0x0020;
401 s->is_vilma = !!vilma;
402 s->rtc.cal = 0x01;
403 s->result[retu_adc_bsi] = 0x3c2;
404 s->result[retu_adc_batt_temp] = 0x0fc;
405 s->result[retu_adc_chg_volt] = 0x165;
406 s->result[retu_adc_head_det] = 123;
407 s->result[retu_adc_hook_det] = 1023;
408 s->result[retu_adc_rf_gp] = 0x11;
409 s->result[retu_adc_tx_det] = 0x11;
410 s->result[retu_adc_batt_volt] = 0x250;
411 s->result[retu_adc_sens] = 2;
412 s->result[retu_adc_sens_temp] = 0x11;
413 s->result[retu_adc_bbatt_volt] = 0x3d0;
414 s->result[retu_adc_self_temp] = 0x330;
415
416 s->cbus.opaque = s;
417 s->cbus.io = retu_io;
418 s->cbus.addr = 1;
419
420 return &s->cbus;
421 }
422
423 void retu_key_event(void *retu, int state)
424 {
425 struct cbus_slave_s *slave = (struct cbus_slave_s *) retu;
426 struct cbus_retu_s *s = (struct cbus_retu_s *) slave->opaque;
427
428 s->irqst |= 1 << retu_int_pwr;
429 retu_interrupt_update(s);
430
431 if (state)
432 s->status &= ~(1 << 5);
433 else
434 s->status |= 1 << 5;
435 }
436
437 #if 0
438 static void retu_head_event(void *retu, int state)
439 {
440 struct cbus_slave_s *slave = (struct cbus_slave_s *) retu;
441 struct cbus_retu_s *s = (struct cbus_retu_s *) slave->opaque;
442
443 if ((s->cc[0] & 0x500) == 0x500) { /* TODO: Which bits? */
444 /* TODO: reissue the interrupt every 100ms or so. */
445 s->irqst |= 1 << retu_int_head;
446 retu_interrupt_update(s);
447 }
448
449 if (state)
450 s->result[retu_adc_head_det] = 50;
451 else
452 s->result[retu_adc_head_det] = 123;
453 }
454
455 static void retu_hook_event(void *retu, int state)
456 {
457 struct cbus_slave_s *slave = (struct cbus_slave_s *) retu;
458 struct cbus_retu_s *s = (struct cbus_retu_s *) slave->opaque;
459
460 if ((s->cc[0] & 0x500) == 0x500) {
461 /* TODO: reissue the interrupt every 100ms or so. */
462 s->irqst |= 1 << retu_int_hook;
463 retu_interrupt_update(s);
464 }
465
466 if (state)
467 s->result[retu_adc_hook_det] = 50;
468 else
469 s->result[retu_adc_hook_det] = 123;
470 }
471 #endif
472
473 /* Tahvo/Betty */
474 struct cbus_tahvo_s {
475 uint16_t irqst;
476 uint16_t irqen;
477 uint8_t charger;
478 uint8_t backlight;
479 uint16_t usbr;
480 uint16_t power;
481
482 int is_betty;
483 qemu_irq irq;
484 struct cbus_slave_s cbus;
485 };
486
487 static void tahvo_interrupt_update(struct cbus_tahvo_s *s)
488 {
489 qemu_set_irq(s->irq, s->irqst & ~s->irqen);
490 }
491
492 #define TAHVO_REG_ASICR 0x00 /* (RO) ASIC ID & revision */
493 #define TAHVO_REG_IDR 0x01 /* (T) Interrupt ID */
494 #define TAHVO_REG_IDSR 0x02 /* (RO) Interrupt status */
495 #define TAHVO_REG_IMR 0x03 /* (RW) Interrupt mask */
496 #define TAHVO_REG_CHAPWMR 0x04 /* (RW) Charger PWM */
497 #define TAHVO_REG_LEDPWMR 0x05 /* (RW) LED PWM */
498 #define TAHVO_REG_USBR 0x06 /* (RW) USB control */
499 #define TAHVO_REG_RCR 0x07 /* (RW) Some kind of power management */
500 #define TAHVO_REG_CCR1 0x08 /* (RW) Common control register 1 */
501 #define TAHVO_REG_CCR2 0x09 /* (RW) Common control register 2 */
502 #define TAHVO_REG_TESTR1 0x0a /* (RW) Test register 1 */
503 #define TAHVO_REG_TESTR2 0x0b /* (RW) Test register 2 */
504 #define TAHVO_REG_NOPR 0x0c /* (RW) Number of periods */
505 #define TAHVO_REG_FRR 0x0d /* (RO) FR */
506
507 static inline uint16_t tahvo_read(struct cbus_tahvo_s *s, int reg)
508 {
509 #ifdef DEBUG
510 printf("TAHVO read at %02x\n", reg);
511 #endif
512
513 switch (reg) {
514 case TAHVO_REG_ASICR:
515 return 0x0021 | (s->is_betty ? 0x0b00 : 0x0300); /* 22 in N810 */
516
517 case TAHVO_REG_IDR:
518 case TAHVO_REG_IDSR: /* XXX: what does this do? */
519 return s->irqst;
520
521 case TAHVO_REG_IMR:
522 return s->irqen;
523
524 case TAHVO_REG_CHAPWMR:
525 return s->charger;
526
527 case TAHVO_REG_LEDPWMR:
528 return s->backlight;
529
530 case TAHVO_REG_USBR:
531 return s->usbr;
532
533 case TAHVO_REG_RCR:
534 return s->power;
535
536 case TAHVO_REG_CCR1:
537 case TAHVO_REG_CCR2:
538 case TAHVO_REG_TESTR1:
539 case TAHVO_REG_TESTR2:
540 case TAHVO_REG_NOPR:
541 case TAHVO_REG_FRR:
542 return 0x0000;
543
544 default:
545 cpu_abort(cpu_single_env, "%s: bad register %02x\n",
546 __FUNCTION__, reg);
547 }
548 }
549
550 static inline void tahvo_write(struct cbus_tahvo_s *s, int reg, uint16_t val)
551 {
552 #ifdef DEBUG
553 printf("TAHVO write of %04x at %02x\n", val, reg);
554 #endif
555
556 switch (reg) {
557 case TAHVO_REG_IDR:
558 s->irqst ^= val;
559 tahvo_interrupt_update(s);
560 break;
561
562 case TAHVO_REG_IMR:
563 s->irqen = val;
564 tahvo_interrupt_update(s);
565 break;
566
567 case TAHVO_REG_CHAPWMR:
568 s->charger = val;
569 break;
570
571 case TAHVO_REG_LEDPWMR:
572 if (s->backlight != (val & 0x7f)) {
573 s->backlight = val & 0x7f;
574 printf("%s: LCD backlight now at %i / 127\n",
575 __FUNCTION__, s->backlight);
576 }
577 break;
578
579 case TAHVO_REG_USBR:
580 s->usbr = val;
581 break;
582
583 case TAHVO_REG_RCR:
584 s->power = val;
585 break;
586
587 case TAHVO_REG_CCR1:
588 case TAHVO_REG_CCR2:
589 case TAHVO_REG_TESTR1:
590 case TAHVO_REG_TESTR2:
591 case TAHVO_REG_NOPR:
592 case TAHVO_REG_FRR:
593 break;
594
595 default:
596 cpu_abort(cpu_single_env, "%s: bad register %02x\n",
597 __FUNCTION__, reg);
598 }
599 }
600
601 static void tahvo_io(void *opaque, int rw, int reg, uint16_t *val)
602 {
603 struct cbus_tahvo_s *s = (struct cbus_tahvo_s *) opaque;
604
605 if (rw)
606 *val = tahvo_read(s, reg);
607 else
608 tahvo_write(s, reg, *val);
609 }
610
611 void *tahvo_init(qemu_irq irq, int betty)
612 {
613 struct cbus_tahvo_s *s = (struct cbus_tahvo_s *) qemu_mallocz(sizeof(*s));
614
615 s->irq = irq;
616 s->irqen = 0xffff;
617 s->irqst = 0x0000;
618 s->is_betty = !!betty;
619
620 s->cbus.opaque = s;
621 s->cbus.io = tahvo_io;
622 s->cbus.addr = 2;
623
624 return &s->cbus;
625 }