Annotation of qemu/hw/cbus.c, revision 1.1.1.3

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.