qemu

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

allwinner-h3-sysctrl.c (4176B)


      1 /*
      2  * Allwinner H3 System Control emulation
      3  *
      4  * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
      5  *
      6  * This program is free software: you can redistribute it and/or modify
      7  * it under the terms of the GNU General Public License as published by
      8  * the Free Software Foundation, either version 2 of the License, or
      9  * (at your option) any later version.
     10  *
     11  * This program is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14  * GNU General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU General Public License
     17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     18  */
     19 
     20 #include "qemu/osdep.h"
     21 #include "qemu/units.h"
     22 #include "hw/sysbus.h"
     23 #include "migration/vmstate.h"
     24 #include "qemu/log.h"
     25 #include "qemu/module.h"
     26 #include "hw/misc/allwinner-h3-sysctrl.h"
     27 
     28 /* System Control register offsets */
     29 enum {
     30     REG_VER               = 0x24,  /* Version */
     31     REG_EMAC_PHY_CLK      = 0x30,  /* EMAC PHY Clock */
     32 };
     33 
     34 #define REG_INDEX(offset)   (offset / sizeof(uint32_t))
     35 
     36 /* System Control register reset values */
     37 enum {
     38     REG_VER_RST           = 0x0,
     39     REG_EMAC_PHY_CLK_RST  = 0x58000,
     40 };
     41 
     42 static uint64_t allwinner_h3_sysctrl_read(void *opaque, hwaddr offset,
     43                                           unsigned size)
     44 {
     45     const AwH3SysCtrlState *s = AW_H3_SYSCTRL(opaque);
     46     const uint32_t idx = REG_INDEX(offset);
     47 
     48     if (idx >= AW_H3_SYSCTRL_REGS_NUM) {
     49         qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
     50                       __func__, (uint32_t)offset);
     51         return 0;
     52     }
     53 
     54     return s->regs[idx];
     55 }
     56 
     57 static void allwinner_h3_sysctrl_write(void *opaque, hwaddr offset,
     58                                        uint64_t val, unsigned size)
     59 {
     60     AwH3SysCtrlState *s = AW_H3_SYSCTRL(opaque);
     61     const uint32_t idx = REG_INDEX(offset);
     62 
     63     if (idx >= AW_H3_SYSCTRL_REGS_NUM) {
     64         qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
     65                       __func__, (uint32_t)offset);
     66         return;
     67     }
     68 
     69     switch (offset) {
     70     case REG_VER:       /* Version */
     71         break;
     72     default:
     73         s->regs[idx] = (uint32_t) val;
     74         break;
     75     }
     76 }
     77 
     78 static const MemoryRegionOps allwinner_h3_sysctrl_ops = {
     79     .read = allwinner_h3_sysctrl_read,
     80     .write = allwinner_h3_sysctrl_write,
     81     .endianness = DEVICE_NATIVE_ENDIAN,
     82     .valid = {
     83         .min_access_size = 4,
     84         .max_access_size = 4,
     85     },
     86     .impl.min_access_size = 4,
     87 };
     88 
     89 static void allwinner_h3_sysctrl_reset(DeviceState *dev)
     90 {
     91     AwH3SysCtrlState *s = AW_H3_SYSCTRL(dev);
     92 
     93     /* Set default values for registers */
     94     s->regs[REG_INDEX(REG_VER)] = REG_VER_RST;
     95     s->regs[REG_INDEX(REG_EMAC_PHY_CLK)] = REG_EMAC_PHY_CLK_RST;
     96 }
     97 
     98 static void allwinner_h3_sysctrl_init(Object *obj)
     99 {
    100     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
    101     AwH3SysCtrlState *s = AW_H3_SYSCTRL(obj);
    102 
    103     /* Memory mapping */
    104     memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_h3_sysctrl_ops, s,
    105                            TYPE_AW_H3_SYSCTRL, 4 * KiB);
    106     sysbus_init_mmio(sbd, &s->iomem);
    107 }
    108 
    109 static const VMStateDescription allwinner_h3_sysctrl_vmstate = {
    110     .name = "allwinner-h3-sysctrl",
    111     .version_id = 1,
    112     .minimum_version_id = 1,
    113     .fields = (VMStateField[]) {
    114         VMSTATE_UINT32_ARRAY(regs, AwH3SysCtrlState, AW_H3_SYSCTRL_REGS_NUM),
    115         VMSTATE_END_OF_LIST()
    116     }
    117 };
    118 
    119 static void allwinner_h3_sysctrl_class_init(ObjectClass *klass, void *data)
    120 {
    121     DeviceClass *dc = DEVICE_CLASS(klass);
    122 
    123     dc->reset = allwinner_h3_sysctrl_reset;
    124     dc->vmsd = &allwinner_h3_sysctrl_vmstate;
    125 }
    126 
    127 static const TypeInfo allwinner_h3_sysctrl_info = {
    128     .name          = TYPE_AW_H3_SYSCTRL,
    129     .parent        = TYPE_SYS_BUS_DEVICE,
    130     .instance_init = allwinner_h3_sysctrl_init,
    131     .instance_size = sizeof(AwH3SysCtrlState),
    132     .class_init    = allwinner_h3_sysctrl_class_init,
    133 };
    134 
    135 static void allwinner_h3_sysctrl_register(void)
    136 {
    137     type_register_static(&allwinner_h3_sysctrl_info);
    138 }
    139 
    140 type_init(allwinner_h3_sysctrl_register)