Annotation of qemu/hw/pxa2xx_keypad.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  * Intel PXA27X Keypad Controller emulation.
                      3:  *
                      4:  * Copyright (c) 2007 MontaVista Software, Inc
                      5:  * Written by Armin Kuster <akuster@kama-aina.net>
                      6:  *              or  <Akuster@mvista.com>
                      7:  *
                      8:  * This code is licensed under the GPLv2.
                      9:  */
                     10: 
                     11: #include "hw.h"
                     12: #include "pxa.h"
                     13: #include "console.h"
                     14: 
                     15: /*
                     16:  * Keypad
                     17:  */
                     18: #define KPC         0x00    /* Keypad Interface Control register */
                     19: #define KPDK        0x08    /* Keypad Interface Direct Key register */
                     20: #define KPREC       0x10    /* Keypad Interface Rotary Encoder register */
                     21: #define KPMK        0x18    /* Keypad Interface Matrix Key register */
                     22: #define KPAS        0x20    /* Keypad Interface Automatic Scan register */
                     23: #define KPASMKP0    0x28    /* Keypad Interface Automatic Scan Multiple
                     24:                                 Key Presser register 0 */
                     25: #define KPASMKP1    0x30    /* Keypad Interface Automatic Scan Multiple
                     26:                                 Key Presser register 1 */
                     27: #define KPASMKP2    0x38    /* Keypad Interface Automatic Scan Multiple
                     28:                                 Key Presser register 2 */
                     29: #define KPASMKP3    0x40    /* Keypad Interface Automatic Scan Multiple
                     30:                                 Key Presser register 3 */
                     31: #define KPKDI       0x48    /* Keypad Interface Key Debounce Interval
                     32:                                 register */
                     33: 
                     34: /* Keypad defines */
                     35: #define KPC_AS          (0x1 << 30)  /* Automatic Scan bit */
                     36: #define KPC_ASACT       (0x1 << 29)  /* Automatic Scan on Activity */
                     37: #define KPC_MI          (0x1 << 22)  /* Matrix interrupt bit */
                     38: #define KPC_IMKP        (0x1 << 21)  /* Ignore Multiple Key Press */
                     39: #define KPC_MS7         (0x1 << 20)  /* Matrix scan line 7 */
                     40: #define KPC_MS6         (0x1 << 19)  /* Matrix scan line 6 */
                     41: #define KPC_MS5         (0x1 << 18)  /* Matrix scan line 5 */
                     42: #define KPC_MS4         (0x1 << 17)  /* Matrix scan line 4 */
                     43: #define KPC_MS3         (0x1 << 16)  /* Matrix scan line 3 */
                     44: #define KPC_MS2         (0x1 << 15)  /* Matrix scan line 2 */
                     45: #define KPC_MS1         (0x1 << 14)  /* Matrix scan line 1 */
                     46: #define KPC_MS0         (0x1 << 13)  /* Matrix scan line 0 */
                     47: #define KPC_ME          (0x1 << 12)  /* Matrix Keypad Enable */
                     48: #define KPC_MIE         (0x1 << 11)  /* Matrix Interrupt Enable */
                     49: #define KPC_DK_DEB_SEL  (0x1 <<  9)  /* Direct Keypad Debounce Select */
                     50: #define KPC_DI          (0x1 <<  5)  /* Direct key interrupt bit */
                     51: #define KPC_RE_ZERO_DEB (0x1 <<  4)  /* Rotary Encoder Zero Debounce */
                     52: #define KPC_REE1        (0x1 <<  3)  /* Rotary Encoder1 Enable */
                     53: #define KPC_REE0        (0x1 <<  2)  /* Rotary Encoder0 Enable */
                     54: #define KPC_DE          (0x1 <<  1)  /* Direct Keypad Enable */
                     55: #define KPC_DIE         (0x1 <<  0)  /* Direct Keypad interrupt Enable */
                     56: 
                     57: #define KPDK_DKP        (0x1 << 31)
                     58: #define KPDK_DK7        (0x1 <<  7)
                     59: #define KPDK_DK6        (0x1 <<  6)
                     60: #define KPDK_DK5        (0x1 <<  5)
                     61: #define KPDK_DK4        (0x1 <<  4)
                     62: #define KPDK_DK3        (0x1 <<  3)
                     63: #define KPDK_DK2        (0x1 <<  2)
                     64: #define KPDK_DK1        (0x1 <<  1)
                     65: #define KPDK_DK0        (0x1 <<  0)
                     66: 
                     67: #define KPREC_OF1       (0x1 << 31)
                     68: #define KPREC_UF1       (0x1 << 30)
                     69: #define KPREC_OF0       (0x1 << 15)
                     70: #define KPREC_UF0       (0x1 << 14)
                     71: 
                     72: #define KPMK_MKP        (0x1 << 31)
                     73: #define KPAS_SO         (0x1 << 31)
                     74: #define KPASMKPx_SO     (0x1 << 31)
                     75: 
                     76: 
                     77: #define KPASMKPx_MKC(row, col)  (1 << (row + 16 * (col % 2)))
                     78: 
                     79: #define PXAKBD_MAXROW   8
                     80: #define PXAKBD_MAXCOL   8
                     81: 
                     82: struct pxa2xx_keypad_s{
                     83:     qemu_irq    irq;
                     84:     struct  keymap *map;
                     85: 
                     86:     uint32_t    kpc;
                     87:     uint32_t    kpdk;
                     88:     uint32_t    kprec;
                     89:     uint32_t    kpmk;
                     90:     uint32_t    kpas;
                     91:     uint32_t    kpasmkp0;
                     92:     uint32_t    kpasmkp1;
                     93:     uint32_t    kpasmkp2;
                     94:     uint32_t    kpasmkp3;
                     95:     uint32_t    kpkdi;
                     96: };
                     97: 
                     98: static void pxa27x_keyboard_event (struct  pxa2xx_keypad_s *kp, int keycode)
                     99: {
                    100:     int row, col,rel;
                    101: 
                    102:     if(!(kp->kpc & KPC_ME)) /* skip if not enabled */
                    103:         return;
                    104: 
                    105:     if(kp->kpc & KPC_AS || kp->kpc & KPC_ASACT) {
                    106:         if(kp->kpc & KPC_AS)
                    107:             kp->kpc &= ~(KPC_AS);
                    108: 
                    109:         rel = (keycode & 0x80) ? 1 : 0; /* key release from qemu */
                    110:         keycode &= ~(0x80); /* strip qemu key release bit */
                    111:         row = kp->map[keycode].row;
                    112:         col = kp->map[keycode].column;
                    113:         if(row == -1 || col == -1)
                    114:             return;
                    115:         switch (col) {
                    116:         case 0:
                    117:         case 1:
                    118:             if(rel)
                    119:                 kp->kpasmkp0 = ~(0xffffffff);
                    120:             else
                    121:                 kp->kpasmkp0 |= KPASMKPx_MKC(row,col);
                    122:             break;
                    123:         case 2:
                    124:         case 3:
                    125:             if(rel)
                    126:                 kp->kpasmkp1 = ~(0xffffffff);
                    127:             else
                    128:                 kp->kpasmkp1 |= KPASMKPx_MKC(row,col);
                    129:             break;
                    130:         case 4:
                    131:         case 5:
                    132:             if(rel)
                    133:                 kp->kpasmkp2 = ~(0xffffffff);
                    134:             else
                    135:                 kp->kpasmkp2 |= KPASMKPx_MKC(row,col);
                    136:             break;
                    137:         case 6:
                    138:         case 7:
                    139:             if(rel)
                    140:                 kp->kpasmkp3 = ~(0xffffffff);
                    141:             else
                    142:                 kp->kpasmkp3 |= KPASMKPx_MKC(row,col);
                    143:             break;
                    144:         } /* switch */
                    145:         goto out;
                    146:     }
                    147:     return;
                    148: 
                    149: out:
                    150:     if(kp->kpc & KPC_MIE) {
                    151:         kp->kpc |= KPC_MI;
                    152:         qemu_irq_raise(kp->irq);
                    153:     }
                    154:     return;
                    155: }
                    156: 
                    157: static uint32_t pxa2xx_keypad_read(void *opaque, target_phys_addr_t offset)
                    158: {
                    159:     struct pxa2xx_keypad_s *s = (struct pxa2xx_keypad_s *) opaque;
                    160:     uint32_t tmp;
                    161: 
                    162:     switch (offset) {
                    163:     case KPC:
                    164:         tmp = s->kpc;
                    165:         if(tmp & KPC_MI)
                    166:             s->kpc &= ~(KPC_MI);
                    167:         if(tmp & KPC_DI)
                    168:             s->kpc &= ~(KPC_DI);
                    169:         qemu_irq_lower(s->irq);
                    170:         return tmp;
                    171:         break;
                    172:     case KPDK:
                    173:         return s->kpdk;
                    174:         break;
                    175:     case KPREC:
                    176:         tmp = s->kprec;
                    177:         if(tmp & KPREC_OF1)
                    178:             s->kprec &= ~(KPREC_OF1);
                    179:         if(tmp & KPREC_UF1)
                    180:             s->kprec &= ~(KPREC_UF1);
                    181:         if(tmp & KPREC_OF0)
                    182:             s->kprec &= ~(KPREC_OF0);
                    183:         if(tmp & KPREC_UF0)
                    184:             s->kprec &= ~(KPREC_UF0);
                    185:         return tmp;
                    186:         break;
                    187:     case KPMK:
                    188:         tmp = s->kpmk;
                    189:         if(tmp & KPMK_MKP)
                    190:             s->kpmk &= ~(KPMK_MKP);
                    191:         return tmp;
                    192:         break;
                    193:     case KPAS:
                    194:         return s->kpas;
                    195:         break;
                    196:     case KPASMKP0:
                    197:         return s->kpasmkp0;
                    198:         break;
                    199:     case KPASMKP1:
                    200:         return s->kpasmkp1;
                    201:         break;
                    202:     case KPASMKP2:
                    203:         return s->kpasmkp2;
                    204:         break;
                    205:     case KPASMKP3:
                    206:         return s->kpasmkp3;
                    207:         break;
                    208:     case KPKDI:
                    209:         return s->kpkdi;
                    210:         break;
                    211:     default:
                    212:         cpu_abort(cpu_single_env, "%s: Bad offset " REG_FMT "\n",
                    213:                         __FUNCTION__, offset);
                    214:     }
                    215: 
                    216:     return 0;
                    217: }
                    218: 
                    219: static void pxa2xx_keypad_write(void *opaque,
                    220:                 target_phys_addr_t offset, uint32_t value)
                    221: {
                    222:     struct pxa2xx_keypad_s *s = (struct pxa2xx_keypad_s *) opaque;
                    223: 
                    224:     switch (offset) {
                    225:     case KPC:
                    226:         s->kpc = value;
                    227:         break;
                    228:     case KPDK:
                    229:         s->kpdk = value;
                    230:         break;
                    231:     case KPREC:
                    232:         s->kprec = value;
                    233:         break;
                    234:     case KPMK:
                    235:         s->kpmk = value;
                    236:         break;
                    237:     case KPAS:
                    238:         s->kpas = value;
                    239:         break;
                    240:     case KPASMKP0:
                    241:         s->kpasmkp0 = value;
                    242:         break;
                    243:     case KPASMKP1:
                    244:         s->kpasmkp1 = value;
                    245:         break;
                    246:     case KPASMKP2:
                    247:         s->kpasmkp2 = value;
                    248:         break;
                    249:     case KPASMKP3:
                    250:         s->kpasmkp3 = value;
                    251:         break;
                    252:     case KPKDI:
                    253:         s->kpkdi = value;
                    254:         break;
                    255: 
                    256:     default:
                    257:         cpu_abort(cpu_single_env, "%s: Bad offset " REG_FMT "\n",
                    258:                         __FUNCTION__, offset);
                    259:     }
                    260: }
                    261: 
                    262: static CPUReadMemoryFunc *pxa2xx_keypad_readfn[] = {
                    263:     pxa2xx_keypad_read,
                    264:     pxa2xx_keypad_read,
                    265:     pxa2xx_keypad_read
                    266: };
                    267: 
                    268: static CPUWriteMemoryFunc *pxa2xx_keypad_writefn[] = {
                    269:     pxa2xx_keypad_write,
                    270:     pxa2xx_keypad_write,
                    271:     pxa2xx_keypad_write
                    272: };
                    273: 
                    274: static void pxa2xx_keypad_save(QEMUFile *f, void *opaque)
                    275: {
                    276:     struct pxa2xx_keypad_s *s = (struct pxa2xx_keypad_s *) opaque;
                    277: 
                    278:     qemu_put_be32s(f, &s->kpc);
                    279:     qemu_put_be32s(f, &s->kpdk);
                    280:     qemu_put_be32s(f, &s->kprec);
                    281:     qemu_put_be32s(f, &s->kpmk);
                    282:     qemu_put_be32s(f, &s->kpas);
                    283:     qemu_put_be32s(f, &s->kpasmkp0);
                    284:     qemu_put_be32s(f, &s->kpasmkp1);
                    285:     qemu_put_be32s(f, &s->kpasmkp2);
                    286:     qemu_put_be32s(f, &s->kpasmkp3);
                    287:     qemu_put_be32s(f, &s->kpkdi);
                    288: 
                    289: }
                    290: 
                    291: static int pxa2xx_keypad_load(QEMUFile *f, void *opaque, int version_id)
                    292: {
                    293:     struct pxa2xx_keypad_s *s = (struct pxa2xx_keypad_s *) opaque;
                    294: 
                    295:     qemu_get_be32s(f, &s->kpc);
                    296:     qemu_get_be32s(f, &s->kpdk);
                    297:     qemu_get_be32s(f, &s->kprec);
                    298:     qemu_get_be32s(f, &s->kpmk);
                    299:     qemu_get_be32s(f, &s->kpas);
                    300:     qemu_get_be32s(f, &s->kpasmkp0);
                    301:     qemu_get_be32s(f, &s->kpasmkp1);
                    302:     qemu_get_be32s(f, &s->kpasmkp2);
                    303:     qemu_get_be32s(f, &s->kpasmkp3);
                    304:     qemu_get_be32s(f, &s->kpkdi);
                    305: 
                    306:     return 0;
                    307: }
                    308: 
                    309: struct pxa2xx_keypad_s *pxa27x_keypad_init(target_phys_addr_t base,
                    310:         qemu_irq irq)
                    311: {
                    312:     int iomemtype;
                    313:     struct pxa2xx_keypad_s *s;
                    314: 
                    315:     s = (struct pxa2xx_keypad_s *) qemu_mallocz(sizeof(struct pxa2xx_keypad_s));
                    316:     s->irq = irq;
                    317: 
                    318:     iomemtype = cpu_register_io_memory(0, pxa2xx_keypad_readfn,
                    319:                     pxa2xx_keypad_writefn, s);
                    320:     cpu_register_physical_memory(base, 0x00100000, iomemtype);
                    321: 
                    322:     register_savevm("pxa2xx_keypad", 0, 0,
                    323:                     pxa2xx_keypad_save, pxa2xx_keypad_load, s);
                    324: 
                    325:     return s;
                    326: }
                    327: 
                    328: void pxa27x_register_keypad(struct pxa2xx_keypad_s *kp, struct keymap *map,
                    329:         int size)
                    330: {
                    331:     if(!map || size < 0x80) {
                    332:         fprintf(stderr, "%s - No PXA keypad map defined\n", __FUNCTION__);
                    333:         exit(-1);
                    334:     }
                    335: 
                    336:     kp->map = map;
                    337:     qemu_add_kbd_event_handler((QEMUPutKBDEvent *) pxa27x_keyboard_event, kp);
                    338: }

unix.superglobalmegacorp.com