qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

lm832x.c (15091B)


      1 /*
      2  * National Semiconductor LM8322/8323 GPIO keyboard & PWM chips.
      3  *
      4  * Copyright (C) 2008 Nokia Corporation
      5  * Written by Andrzej Zaborowski <andrew@openedhand.com>
      6  *
      7  * This program is free software; you can redistribute it and/or
      8  * modify it under the terms of the GNU General Public License as
      9  * published by the Free Software Foundation; either version 2 or
     10  * (at your option) version 3 of the License.
     11  *
     12  * This program is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15  * GNU General Public License for more details.
     16  *
     17  * You should have received a copy of the GNU General Public License along
     18  * with this program; if not, see <http://www.gnu.org/licenses/>.
     19  */
     20 
     21 #include "qemu/osdep.h"
     22 #include "hw/input/lm832x.h"
     23 #include "hw/i2c/i2c.h"
     24 #include "hw/irq.h"
     25 #include "migration/vmstate.h"
     26 #include "qemu/module.h"
     27 #include "qemu/timer.h"
     28 #include "ui/console.h"
     29 #include "qom/object.h"
     30 
     31 OBJECT_DECLARE_SIMPLE_TYPE(LM823KbdState, LM8323)
     32 
     33 struct LM823KbdState {
     34     I2CSlave parent_obj;
     35 
     36     uint8_t i2c_dir;
     37     uint8_t i2c_cycle;
     38     uint8_t reg;
     39 
     40     qemu_irq nirq;
     41     uint16_t model;
     42 
     43     struct {
     44         qemu_irq out[2];
     45         int in[2][2];
     46     } mux;
     47 
     48     uint8_t config;
     49     uint8_t status;
     50     uint8_t acttime;
     51     uint8_t error;
     52     uint8_t clock;
     53 
     54     struct {
     55         uint16_t pull;
     56         uint16_t mask;
     57         uint16_t dir;
     58         uint16_t level;
     59         qemu_irq out[16];
     60     } gpio;
     61 
     62     struct {
     63         uint8_t dbnctime;
     64         uint8_t size;
     65         uint8_t start;
     66         uint8_t len;
     67         uint8_t fifo[16];
     68     } kbd;
     69 
     70     struct {
     71         uint16_t file[256];
     72         uint8_t faddr;
     73         uint8_t addr[3];
     74         QEMUTimer *tm[3];
     75     } pwm;
     76 };
     77 
     78 #define INT_KEYPAD		(1 << 0)
     79 #define INT_ERROR		(1 << 3)
     80 #define INT_NOINIT		(1 << 4)
     81 #define INT_PWMEND(n)		(1 << (5 + n))
     82 
     83 #define ERR_BADPAR		(1 << 0)
     84 #define ERR_CMDUNK		(1 << 1)
     85 #define ERR_KEYOVR		(1 << 2)
     86 #define ERR_FIFOOVR		(1 << 6)
     87 
     88 static void lm_kbd_irq_update(LM823KbdState *s)
     89 {
     90     qemu_set_irq(s->nirq, !s->status);
     91 }
     92 
     93 static void lm_kbd_gpio_update(LM823KbdState *s)
     94 {
     95 }
     96 
     97 static void lm_kbd_reset(DeviceState *dev)
     98 {
     99     LM823KbdState *s = LM8323(dev);
    100 
    101     s->config = 0x80;
    102     s->status = INT_NOINIT;
    103     s->acttime = 125;
    104     s->kbd.dbnctime = 3;
    105     s->kbd.size = 0x33;
    106     s->clock = 0x08;
    107 
    108     lm_kbd_irq_update(s);
    109     lm_kbd_gpio_update(s);
    110 }
    111 
    112 static void lm_kbd_error(LM823KbdState *s, int err)
    113 {
    114     s->error |= err;
    115     s->status |= INT_ERROR;
    116     lm_kbd_irq_update(s);
    117 }
    118 
    119 static void lm_kbd_pwm_tick(LM823KbdState *s, int line)
    120 {
    121 }
    122 
    123 static void lm_kbd_pwm_start(LM823KbdState *s, int line)
    124 {
    125     lm_kbd_pwm_tick(s, line);
    126 }
    127 
    128 static void lm_kbd_pwm0_tick(void *opaque)
    129 {
    130     lm_kbd_pwm_tick(opaque, 0);
    131 }
    132 static void lm_kbd_pwm1_tick(void *opaque)
    133 {
    134     lm_kbd_pwm_tick(opaque, 1);
    135 }
    136 static void lm_kbd_pwm2_tick(void *opaque)
    137 {
    138     lm_kbd_pwm_tick(opaque, 2);
    139 }
    140 
    141 enum {
    142     LM832x_CMD_READ_ID		= 0x80, /* Read chip ID. */
    143     LM832x_CMD_WRITE_CFG	= 0x81, /* Set configuration item. */
    144     LM832x_CMD_READ_INT		= 0x82, /* Get interrupt status. */
    145     LM832x_CMD_RESET		= 0x83, /* Reset, same as external one */
    146     LM823x_CMD_WRITE_PULL_DOWN	= 0x84, /* Select GPIO pull-up/down. */
    147     LM832x_CMD_WRITE_PORT_SEL	= 0x85, /* Select GPIO in/out. */
    148     LM832x_CMD_WRITE_PORT_STATE	= 0x86, /* Set GPIO pull-up/down. */
    149     LM832x_CMD_READ_PORT_SEL	= 0x87, /* Get GPIO in/out. */
    150     LM832x_CMD_READ_PORT_STATE	= 0x88, /* Get GPIO pull-up/down. */
    151     LM832x_CMD_READ_FIFO	= 0x89, /* Read byte from FIFO. */
    152     LM832x_CMD_RPT_READ_FIFO	= 0x8a, /* Read FIFO (no increment). */
    153     LM832x_CMD_SET_ACTIVE	= 0x8b, /* Set active time. */
    154     LM832x_CMD_READ_ERROR	= 0x8c, /* Get error status. */
    155     LM832x_CMD_READ_ROTATOR	= 0x8e, /* Read rotator status. */
    156     LM832x_CMD_SET_DEBOUNCE	= 0x8f, /* Set debouncing time. */
    157     LM832x_CMD_SET_KEY_SIZE	= 0x90, /* Set keypad size. */
    158     LM832x_CMD_READ_KEY_SIZE	= 0x91, /* Get keypad size. */
    159     LM832x_CMD_READ_CFG		= 0x92, /* Get configuration item. */
    160     LM832x_CMD_WRITE_CLOCK	= 0x93, /* Set clock config. */
    161     LM832x_CMD_READ_CLOCK	= 0x94, /* Get clock config. */
    162     LM832x_CMD_PWM_WRITE	= 0x95, /* Write PWM script. */
    163     LM832x_CMD_PWM_START	= 0x96, /* Start PWM engine. */
    164     LM832x_CMD_PWM_STOP		= 0x97, /* Stop PWM engine. */
    165     LM832x_GENERAL_ERROR	= 0xff, /* There was one error.
    166                                            Previously was represented by -1
    167                                            This is not a command */
    168 };
    169 
    170 #define LM832x_MAX_KPX		8
    171 #define LM832x_MAX_KPY		12
    172 
    173 static uint8_t lm_kbd_read(LM823KbdState *s, int reg, int byte)
    174 {
    175     int ret;
    176 
    177     switch (reg) {
    178     case LM832x_CMD_READ_ID:
    179         ret = 0x0400;
    180         break;
    181 
    182     case LM832x_CMD_READ_INT:
    183         ret = s->status;
    184         if (!(s->status & INT_NOINIT)) {
    185             s->status = 0;
    186             lm_kbd_irq_update(s);
    187         }
    188         break;
    189 
    190     case LM832x_CMD_READ_PORT_SEL:
    191         ret = s->gpio.dir;
    192         break;
    193     case LM832x_CMD_READ_PORT_STATE:
    194         ret = s->gpio.mask;
    195         break;
    196 
    197     case LM832x_CMD_READ_FIFO:
    198         if (s->kbd.len <= 1)
    199             return 0x00;
    200 
    201         /* Example response from the two commands after a INT_KEYPAD
    202          * interrupt caused by the key 0x3c being pressed:
    203          * RPT_READ_FIFO: 55 bc 00 4e ff 0a 50 08 00 29 d9 08 01 c9 01
    204          *     READ_FIFO: bc 00 00 4e ff 0a 50 08 00 29 d9 08 01 c9 01
    205          * RPT_READ_FIFO: bc 00 00 4e ff 0a 50 08 00 29 d9 08 01 c9 01
    206          *
    207          * 55 is the code of the key release event serviced in the previous
    208          * interrupt handling.
    209          *
    210          * TODO: find out whether the FIFO is advanced a single character
    211          * before reading every byte or the whole size of the FIFO at the
    212          * last LM832x_CMD_READ_FIFO.  This affects LM832x_CMD_RPT_READ_FIFO
    213          * output in cases where there are more than one event in the FIFO.
    214          * Assume 0xbc and 0x3c events are in the FIFO:
    215          * RPT_READ_FIFO: 55 bc 3c 00 4e ff 0a 50 08 00 29 d9 08 01 c9
    216          *     READ_FIFO: bc 3c 00 00 4e ff 0a 50 08 00 29 d9 08 01 c9
    217          * Does RPT_READ_FIFO now return 0xbc and 0x3c or only 0x3c?
    218          */
    219         s->kbd.start ++;
    220         s->kbd.start &= sizeof(s->kbd.fifo) - 1;
    221         s->kbd.len --;
    222 
    223         return s->kbd.fifo[s->kbd.start];
    224     case LM832x_CMD_RPT_READ_FIFO:
    225         if (byte >= s->kbd.len)
    226             return 0x00;
    227 
    228         return s->kbd.fifo[(s->kbd.start + byte) & (sizeof(s->kbd.fifo) - 1)];
    229 
    230     case LM832x_CMD_READ_ERROR:
    231         return s->error;
    232 
    233     case LM832x_CMD_READ_ROTATOR:
    234         return 0;
    235 
    236     case LM832x_CMD_READ_KEY_SIZE:
    237         return s->kbd.size;
    238 
    239     case LM832x_CMD_READ_CFG:
    240         return s->config & 0xf;
    241 
    242     case LM832x_CMD_READ_CLOCK:
    243         return (s->clock & 0xfc) | 2;
    244 
    245     default:
    246         lm_kbd_error(s, ERR_CMDUNK);
    247         fprintf(stderr, "%s: unknown command %02x\n", __func__, reg);
    248         return 0x00;
    249     }
    250 
    251     return ret >> (byte << 3);
    252 }
    253 
    254 static void lm_kbd_write(LM823KbdState *s, int reg, int byte, uint8_t value)
    255 {
    256     switch (reg) {
    257     case LM832x_CMD_WRITE_CFG:
    258         s->config = value;
    259         /* This must be done whenever s->mux.in is updated (never).  */
    260         if ((s->config >> 1) & 1)			/* MUX1EN */
    261             qemu_set_irq(s->mux.out[0], s->mux.in[0][(s->config >> 0) & 1]);
    262         if ((s->config >> 3) & 1)			/* MUX2EN */
    263             qemu_set_irq(s->mux.out[0], s->mux.in[0][(s->config >> 2) & 1]);
    264         /* TODO: check that this is issued only following the chip reset
    265          * and not in the middle of operation and that it is followed by
    266          * the GPIO ports re-resablishing through WRITE_PORT_SEL and
    267          * WRITE_PORT_STATE (using a timer perhaps) and otherwise output
    268          * warnings.  */
    269         s->status = 0;
    270         lm_kbd_irq_update(s);
    271         s->kbd.len = 0;
    272         s->kbd.start = 0;
    273         s->reg = LM832x_GENERAL_ERROR;
    274         break;
    275 
    276     case LM832x_CMD_RESET:
    277         if (value == 0xaa)
    278             lm_kbd_reset(DEVICE(s));
    279         else
    280             lm_kbd_error(s, ERR_BADPAR);
    281         s->reg = LM832x_GENERAL_ERROR;
    282         break;
    283 
    284     case LM823x_CMD_WRITE_PULL_DOWN:
    285         if (!byte)
    286             s->gpio.pull = value;
    287         else {
    288             s->gpio.pull |= value << 8;
    289             lm_kbd_gpio_update(s);
    290             s->reg = LM832x_GENERAL_ERROR;
    291         }
    292         break;
    293     case LM832x_CMD_WRITE_PORT_SEL:
    294         if (!byte)
    295             s->gpio.dir = value;
    296         else {
    297             s->gpio.dir |= value << 8;
    298             lm_kbd_gpio_update(s);
    299             s->reg = LM832x_GENERAL_ERROR;
    300         }
    301         break;
    302     case LM832x_CMD_WRITE_PORT_STATE:
    303         if (!byte)
    304             s->gpio.mask = value;
    305         else {
    306             s->gpio.mask |= value << 8;
    307             lm_kbd_gpio_update(s);
    308             s->reg = LM832x_GENERAL_ERROR;
    309         }
    310         break;
    311 
    312     case LM832x_CMD_SET_ACTIVE:
    313         s->acttime = value;
    314         s->reg = LM832x_GENERAL_ERROR;
    315         break;
    316 
    317     case LM832x_CMD_SET_DEBOUNCE:
    318         s->kbd.dbnctime = value;
    319         s->reg = LM832x_GENERAL_ERROR;
    320         if (!value)
    321             lm_kbd_error(s, ERR_BADPAR);
    322         break;
    323 
    324     case LM832x_CMD_SET_KEY_SIZE:
    325         s->kbd.size = value;
    326         s->reg = LM832x_GENERAL_ERROR;
    327         if (
    328                         (value & 0xf) < 3 || (value & 0xf) > LM832x_MAX_KPY ||
    329                         (value >> 4) < 3 || (value >> 4) > LM832x_MAX_KPX)
    330             lm_kbd_error(s, ERR_BADPAR);
    331         break;
    332 
    333     case LM832x_CMD_WRITE_CLOCK:
    334         s->clock = value;
    335         s->reg = LM832x_GENERAL_ERROR;
    336         if ((value & 3) && (value & 3) != 3) {
    337             lm_kbd_error(s, ERR_BADPAR);
    338             fprintf(stderr, "%s: invalid clock setting in RCPWM\n",
    339                             __func__);
    340         }
    341         /* TODO: Validate that the command is only issued once */
    342         break;
    343 
    344     case LM832x_CMD_PWM_WRITE:
    345         if (byte == 0) {
    346             if (!(value & 3) || (value >> 2) > 59) {
    347                 lm_kbd_error(s, ERR_BADPAR);
    348                 s->reg = LM832x_GENERAL_ERROR;
    349                 break;
    350             }
    351 
    352             s->pwm.faddr = value;
    353             s->pwm.file[s->pwm.faddr] = 0;
    354         } else if (byte == 1) {
    355             s->pwm.file[s->pwm.faddr] |= value << 8;
    356         } else if (byte == 2) {
    357             s->pwm.file[s->pwm.faddr] |= value << 0;
    358             s->reg = LM832x_GENERAL_ERROR;
    359         }
    360         break;
    361     case LM832x_CMD_PWM_START:
    362         s->reg = LM832x_GENERAL_ERROR;
    363         if (!(value & 3) || (value >> 2) > 59) {
    364             lm_kbd_error(s, ERR_BADPAR);
    365             break;
    366         }
    367 
    368         s->pwm.addr[(value & 3) - 1] = value >> 2;
    369         lm_kbd_pwm_start(s, (value & 3) - 1);
    370         break;
    371     case LM832x_CMD_PWM_STOP:
    372         s->reg = LM832x_GENERAL_ERROR;
    373         if (!(value & 3)) {
    374             lm_kbd_error(s, ERR_BADPAR);
    375             break;
    376         }
    377 
    378         timer_del(s->pwm.tm[(value & 3) - 1]);
    379         break;
    380 
    381     case LM832x_GENERAL_ERROR:
    382         lm_kbd_error(s, ERR_BADPAR);
    383         break;
    384     default:
    385         lm_kbd_error(s, ERR_CMDUNK);
    386         fprintf(stderr, "%s: unknown command %02x\n", __func__, reg);
    387         break;
    388     }
    389 }
    390 
    391 static int lm_i2c_event(I2CSlave *i2c, enum i2c_event event)
    392 {
    393     LM823KbdState *s = LM8323(i2c);
    394 
    395     switch (event) {
    396     case I2C_START_RECV:
    397     case I2C_START_SEND:
    398         s->i2c_cycle = 0;
    399         s->i2c_dir = (event == I2C_START_SEND);
    400         break;
    401 
    402     default:
    403         break;
    404     }
    405 
    406     return 0;
    407 }
    408 
    409 static uint8_t lm_i2c_rx(I2CSlave *i2c)
    410 {
    411     LM823KbdState *s = LM8323(i2c);
    412 
    413     return lm_kbd_read(s, s->reg, s->i2c_cycle ++);
    414 }
    415 
    416 static int lm_i2c_tx(I2CSlave *i2c, uint8_t data)
    417 {
    418     LM823KbdState *s = LM8323(i2c);
    419 
    420     if (!s->i2c_cycle)
    421         s->reg = data;
    422     else
    423         lm_kbd_write(s, s->reg, s->i2c_cycle - 1, data);
    424     s->i2c_cycle ++;
    425 
    426     return 0;
    427 }
    428 
    429 static int lm_kbd_post_load(void *opaque, int version_id)
    430 {
    431     LM823KbdState *s = opaque;
    432 
    433     lm_kbd_irq_update(s);
    434     lm_kbd_gpio_update(s);
    435 
    436     return 0;
    437 }
    438 
    439 static const VMStateDescription vmstate_lm_kbd = {
    440     .name = "LM8323",
    441     .version_id = 0,
    442     .minimum_version_id = 0,
    443     .post_load = lm_kbd_post_load,
    444     .fields = (VMStateField[]) {
    445         VMSTATE_I2C_SLAVE(parent_obj, LM823KbdState),
    446         VMSTATE_UINT8(i2c_dir, LM823KbdState),
    447         VMSTATE_UINT8(i2c_cycle, LM823KbdState),
    448         VMSTATE_UINT8(reg, LM823KbdState),
    449         VMSTATE_UINT8(config, LM823KbdState),
    450         VMSTATE_UINT8(status, LM823KbdState),
    451         VMSTATE_UINT8(acttime, LM823KbdState),
    452         VMSTATE_UINT8(error, LM823KbdState),
    453         VMSTATE_UINT8(clock, LM823KbdState),
    454         VMSTATE_UINT16(gpio.pull, LM823KbdState),
    455         VMSTATE_UINT16(gpio.mask, LM823KbdState),
    456         VMSTATE_UINT16(gpio.dir, LM823KbdState),
    457         VMSTATE_UINT16(gpio.level, LM823KbdState),
    458         VMSTATE_UINT8(kbd.dbnctime, LM823KbdState),
    459         VMSTATE_UINT8(kbd.size, LM823KbdState),
    460         VMSTATE_UINT8(kbd.start, LM823KbdState),
    461         VMSTATE_UINT8(kbd.len, LM823KbdState),
    462         VMSTATE_BUFFER(kbd.fifo, LM823KbdState),
    463         VMSTATE_UINT16_ARRAY(pwm.file, LM823KbdState, 256),
    464         VMSTATE_UINT8(pwm.faddr, LM823KbdState),
    465         VMSTATE_BUFFER(pwm.addr, LM823KbdState),
    466         VMSTATE_TIMER_PTR_ARRAY(pwm.tm, LM823KbdState, 3),
    467         VMSTATE_END_OF_LIST()
    468     }
    469 };
    470 
    471 
    472 static void lm8323_realize(DeviceState *dev, Error **errp)
    473 {
    474     LM823KbdState *s = LM8323(dev);
    475 
    476     s->model = 0x8323;
    477     s->pwm.tm[0] = timer_new_ns(QEMU_CLOCK_VIRTUAL, lm_kbd_pwm0_tick, s);
    478     s->pwm.tm[1] = timer_new_ns(QEMU_CLOCK_VIRTUAL, lm_kbd_pwm1_tick, s);
    479     s->pwm.tm[2] = timer_new_ns(QEMU_CLOCK_VIRTUAL, lm_kbd_pwm2_tick, s);
    480     qdev_init_gpio_out(dev, &s->nirq, 1);
    481 }
    482 
    483 void lm832x_key_event(DeviceState *dev, int key, int state)
    484 {
    485     LM823KbdState *s = LM8323(dev);
    486 
    487     if ((s->status & INT_ERROR) && (s->error & ERR_FIFOOVR))
    488         return;
    489 
    490     if (s->kbd.len >= sizeof(s->kbd.fifo)) {
    491         lm_kbd_error(s, ERR_FIFOOVR);
    492         return;
    493     }
    494 
    495     s->kbd.fifo[(s->kbd.start + s->kbd.len ++) & (sizeof(s->kbd.fifo) - 1)] =
    496             key | (state << 7);
    497 
    498     /* We never set ERR_KEYOVR because we support multiple keys fine.  */
    499     s->status |= INT_KEYPAD;
    500     lm_kbd_irq_update(s);
    501 }
    502 
    503 static void lm8323_class_init(ObjectClass *klass, void *data)
    504 {
    505     DeviceClass *dc = DEVICE_CLASS(klass);
    506     I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
    507 
    508     dc->reset = lm_kbd_reset;
    509     dc->realize = lm8323_realize;
    510     k->event = lm_i2c_event;
    511     k->recv = lm_i2c_rx;
    512     k->send = lm_i2c_tx;
    513     dc->vmsd = &vmstate_lm_kbd;
    514 }
    515 
    516 static const TypeInfo lm8323_info = {
    517     .name          = TYPE_LM8323,
    518     .parent        = TYPE_I2C_SLAVE,
    519     .instance_size = sizeof(LM823KbdState),
    520     .class_init    = lm8323_class_init,
    521 };
    522 
    523 static void lm832x_register_types(void)
    524 {
    525     type_register_static(&lm8323_info);
    526 }
    527 
    528 type_init(lm832x_register_types)