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