qemu

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

zaurus.c (7654B)


      1 /*
      2  * Copyright (c) 2006-2008 Openedhand Ltd.
      3  * Written by Andrzej Zaborowski <balrog@zabor.org>
      4  *
      5  * This program is free software; you can redistribute it and/or
      6  * modify it under the terms of the GNU General Public License as
      7  * published by the Free Software Foundation; either version 2 or
      8  * (at your option) version 3 of the License.
      9  *
     10  * This program is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  * GNU General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License along
     16  * with this program; if not, see <http://www.gnu.org/licenses/>.
     17  */
     18 
     19 #include "qemu/osdep.h"
     20 #include "hw/irq.h"
     21 #include "hw/arm/sharpsl.h"
     22 #include "hw/sysbus.h"
     23 #include "migration/vmstate.h"
     24 #include "qemu/module.h"
     25 #include "qemu/log.h"
     26 #include "qom/object.h"
     27 
     28 /* SCOOP devices */
     29 
     30 #define TYPE_SCOOP "scoop"
     31 OBJECT_DECLARE_SIMPLE_TYPE(ScoopInfo, SCOOP)
     32 
     33 struct ScoopInfo {
     34     SysBusDevice parent_obj;
     35 
     36     qemu_irq handler[16];
     37     MemoryRegion iomem;
     38     uint16_t status;
     39     uint16_t power;
     40     uint32_t gpio_level;
     41     uint32_t gpio_dir;
     42     uint32_t prev_level;
     43 
     44     uint16_t mcr;
     45     uint16_t cdr;
     46     uint16_t ccr;
     47     uint16_t irr;
     48     uint16_t imr;
     49     uint16_t isr;
     50 };
     51 
     52 #define SCOOP_MCR	0x00
     53 #define SCOOP_CDR	0x04
     54 #define SCOOP_CSR	0x08
     55 #define SCOOP_CPR	0x0c
     56 #define SCOOP_CCR	0x10
     57 #define SCOOP_IRR_IRM	0x14
     58 #define SCOOP_IMR	0x18
     59 #define SCOOP_ISR	0x1c
     60 #define SCOOP_GPCR	0x20
     61 #define SCOOP_GPWR	0x24
     62 #define SCOOP_GPRR	0x28
     63 
     64 static inline void scoop_gpio_handler_update(ScoopInfo *s) {
     65     uint32_t level, diff;
     66     int bit;
     67     level = s->gpio_level & s->gpio_dir;
     68 
     69     for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) {
     70         bit = ctz32(diff);
     71         qemu_set_irq(s->handler[bit], (level >> bit) & 1);
     72     }
     73 
     74     s->prev_level = level;
     75 }
     76 
     77 static uint64_t scoop_read(void *opaque, hwaddr addr,
     78                            unsigned size)
     79 {
     80     ScoopInfo *s = (ScoopInfo *) opaque;
     81 
     82     switch (addr & 0x3f) {
     83     case SCOOP_MCR:
     84         return s->mcr;
     85     case SCOOP_CDR:
     86         return s->cdr;
     87     case SCOOP_CSR:
     88         return s->status;
     89     case SCOOP_CPR:
     90         return s->power;
     91     case SCOOP_CCR:
     92         return s->ccr;
     93     case SCOOP_IRR_IRM:
     94         return s->irr;
     95     case SCOOP_IMR:
     96         return s->imr;
     97     case SCOOP_ISR:
     98         return s->isr;
     99     case SCOOP_GPCR:
    100         return s->gpio_dir;
    101     case SCOOP_GPWR:
    102     case SCOOP_GPRR:
    103         return s->gpio_level;
    104     default:
    105         qemu_log_mask(LOG_GUEST_ERROR,
    106                       "scoop_read: bad register offset 0x%02" HWADDR_PRIx "\n",
    107                       addr);
    108     }
    109 
    110     return 0;
    111 }
    112 
    113 static void scoop_write(void *opaque, hwaddr addr,
    114                         uint64_t value, unsigned size)
    115 {
    116     ScoopInfo *s = (ScoopInfo *) opaque;
    117     value &= 0xffff;
    118 
    119     switch (addr & 0x3f) {
    120     case SCOOP_MCR:
    121         s->mcr = value;
    122         break;
    123     case SCOOP_CDR:
    124         s->cdr = value;
    125         break;
    126     case SCOOP_CPR:
    127         s->power = value;
    128         if (value & 0x80)
    129             s->power |= 0x8040;
    130         break;
    131     case SCOOP_CCR:
    132         s->ccr = value;
    133         break;
    134     case SCOOP_IRR_IRM:
    135         s->irr = value;
    136         break;
    137     case SCOOP_IMR:
    138         s->imr = value;
    139         break;
    140     case SCOOP_ISR:
    141         s->isr = value;
    142         break;
    143     case SCOOP_GPCR:
    144         s->gpio_dir = value;
    145         scoop_gpio_handler_update(s);
    146         break;
    147     case SCOOP_GPWR:
    148     case SCOOP_GPRR:	/* GPRR is probably R/O in real HW */
    149         s->gpio_level = value & s->gpio_dir;
    150         scoop_gpio_handler_update(s);
    151         break;
    152     default:
    153         qemu_log_mask(LOG_GUEST_ERROR,
    154                       "scoop_write: bad register offset 0x%02" HWADDR_PRIx "\n",
    155                       addr);
    156     }
    157 }
    158 
    159 static const MemoryRegionOps scoop_ops = {
    160     .read = scoop_read,
    161     .write = scoop_write,
    162     .endianness = DEVICE_NATIVE_ENDIAN,
    163 };
    164 
    165 static void scoop_gpio_set(void *opaque, int line, int level)
    166 {
    167     ScoopInfo *s = (ScoopInfo *) opaque;
    168 
    169     if (level)
    170         s->gpio_level |= (1 << line);
    171     else
    172         s->gpio_level &= ~(1 << line);
    173 }
    174 
    175 static void scoop_init(Object *obj)
    176 {
    177     DeviceState *dev = DEVICE(obj);
    178     ScoopInfo *s = SCOOP(obj);
    179     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
    180 
    181     s->status = 0x02;
    182     qdev_init_gpio_out(dev, s->handler, 16);
    183     qdev_init_gpio_in(dev, scoop_gpio_set, 16);
    184     memory_region_init_io(&s->iomem, obj, &scoop_ops, s, "scoop", 0x1000);
    185 
    186     sysbus_init_mmio(sbd, &s->iomem);
    187 }
    188 
    189 static int scoop_post_load(void *opaque, int version_id)
    190 {
    191     ScoopInfo *s = (ScoopInfo *) opaque;
    192     int i;
    193     uint32_t level;
    194 
    195     level = s->gpio_level & s->gpio_dir;
    196 
    197     for (i = 0; i < 16; i++) {
    198         qemu_set_irq(s->handler[i], (level >> i) & 1);
    199     }
    200 
    201     s->prev_level = level;
    202 
    203     return 0;
    204 }
    205 
    206 static bool is_version_0 (void *opaque, int version_id)
    207 {
    208     return version_id == 0;
    209 }
    210 
    211 static bool vmstate_scoop_validate(void *opaque, int version_id)
    212 {
    213     ScoopInfo *s = opaque;
    214 
    215     return !(s->prev_level & 0xffff0000) &&
    216         !(s->gpio_level & 0xffff0000) &&
    217         !(s->gpio_dir & 0xffff0000);
    218 }
    219 
    220 static const VMStateDescription vmstate_scoop_regs = {
    221     .name = "scoop",
    222     .version_id = 1,
    223     .minimum_version_id = 0,
    224     .post_load = scoop_post_load,
    225     .fields = (VMStateField[]) {
    226         VMSTATE_UINT16(status, ScoopInfo),
    227         VMSTATE_UINT16(power, ScoopInfo),
    228         VMSTATE_UINT32(gpio_level, ScoopInfo),
    229         VMSTATE_UINT32(gpio_dir, ScoopInfo),
    230         VMSTATE_UINT32(prev_level, ScoopInfo),
    231         VMSTATE_VALIDATE("irq levels are 16 bit", vmstate_scoop_validate),
    232         VMSTATE_UINT16(mcr, ScoopInfo),
    233         VMSTATE_UINT16(cdr, ScoopInfo),
    234         VMSTATE_UINT16(ccr, ScoopInfo),
    235         VMSTATE_UINT16(irr, ScoopInfo),
    236         VMSTATE_UINT16(imr, ScoopInfo),
    237         VMSTATE_UINT16(isr, ScoopInfo),
    238         VMSTATE_UNUSED_TEST(is_version_0, 2),
    239         VMSTATE_END_OF_LIST(),
    240     },
    241 };
    242 
    243 static void scoop_sysbus_class_init(ObjectClass *klass, void *data)
    244 {
    245     DeviceClass *dc = DEVICE_CLASS(klass);
    246 
    247     dc->desc = "Scoop2 Sharp custom ASIC";
    248     dc->vmsd = &vmstate_scoop_regs;
    249 }
    250 
    251 static const TypeInfo scoop_sysbus_info = {
    252     .name          = TYPE_SCOOP,
    253     .parent        = TYPE_SYS_BUS_DEVICE,
    254     .instance_size = sizeof(ScoopInfo),
    255     .instance_init = scoop_init,
    256     .class_init    = scoop_sysbus_class_init,
    257 };
    258 
    259 static void scoop_register_types(void)
    260 {
    261     type_register_static(&scoop_sysbus_info);
    262 }
    263 
    264 type_init(scoop_register_types)
    265 
    266 /* Write the bootloader parameters memory area.  */
    267 
    268 #define MAGIC_CHG(a, b, c, d)	((d << 24) | (c << 16) | (b << 8) | a)
    269 
    270 static struct QEMU_PACKED sl_param_info {
    271     uint32_t comadj_keyword;
    272     int32_t comadj;
    273 
    274     uint32_t uuid_keyword;
    275     char uuid[16];
    276 
    277     uint32_t touch_keyword;
    278     int32_t touch_xp;
    279     int32_t touch_yp;
    280     int32_t touch_xd;
    281     int32_t touch_yd;
    282 
    283     uint32_t adadj_keyword;
    284     int32_t adadj;
    285 
    286     uint32_t phad_keyword;
    287     int32_t phadadj;
    288 } zaurus_bootparam = {
    289     .comadj_keyword	= MAGIC_CHG('C', 'M', 'A', 'D'),
    290     .comadj		= 125,
    291     .uuid_keyword	= MAGIC_CHG('U', 'U', 'I', 'D'),
    292     .uuid		= { -1 },
    293     .touch_keyword	= MAGIC_CHG('T', 'U', 'C', 'H'),
    294     .touch_xp		= -1,
    295     .adadj_keyword	= MAGIC_CHG('B', 'V', 'A', 'D'),
    296     .adadj		= -1,
    297     .phad_keyword	= MAGIC_CHG('P', 'H', 'A', 'D'),
    298     .phadadj		= 0x01,
    299 };
    300 
    301 void sl_bootparam_write(hwaddr ptr)
    302 {
    303     cpu_physical_memory_write(ptr, &zaurus_bootparam,
    304                               sizeof(struct sl_param_info));
    305 }