qemu

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

imx_gpcv2.c (3501B)


      1 /*
      2  * Copyright (c) 2018, Impinj, Inc.
      3  *
      4  * i.MX7 GPCv2 block emulation code
      5  *
      6  * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
      7  *
      8  * This work is licensed under the terms of the GNU GPL, version 2 or later.
      9  * See the COPYING file in the top-level directory.
     10  */
     11 
     12 #include "qemu/osdep.h"
     13 #include "hw/intc/imx_gpcv2.h"
     14 #include "migration/vmstate.h"
     15 #include "qemu/module.h"
     16 
     17 #define GPC_PU_PGC_SW_PUP_REQ       0x0f8
     18 #define GPC_PU_PGC_SW_PDN_REQ       0x104
     19 
     20 #define USB_HSIC_PHY_SW_Pxx_REQ     BIT(4)
     21 #define USB_OTG2_PHY_SW_Pxx_REQ     BIT(3)
     22 #define USB_OTG1_PHY_SW_Pxx_REQ     BIT(2)
     23 #define PCIE_PHY_SW_Pxx_REQ         BIT(1)
     24 #define MIPI_PHY_SW_Pxx_REQ         BIT(0)
     25 
     26 
     27 static void imx_gpcv2_reset(DeviceState *dev)
     28 {
     29     IMXGPCv2State *s = IMX_GPCV2(dev);
     30 
     31     memset(s->regs, 0, sizeof(s->regs));
     32 }
     33 
     34 static uint64_t imx_gpcv2_read(void *opaque, hwaddr offset,
     35                                unsigned size)
     36 {
     37     IMXGPCv2State *s = opaque;
     38 
     39     return s->regs[offset / sizeof(uint32_t)];
     40 }
     41 
     42 static void imx_gpcv2_write(void *opaque, hwaddr offset,
     43                             uint64_t value, unsigned size)
     44 {
     45     IMXGPCv2State *s = opaque;
     46     const size_t idx = offset / sizeof(uint32_t);
     47 
     48     s->regs[idx] = value;
     49 
     50     /*
     51      * Real HW will clear those bits once as a way to indicate that
     52      * power up request is complete
     53      */
     54     if (offset == GPC_PU_PGC_SW_PUP_REQ ||
     55         offset == GPC_PU_PGC_SW_PDN_REQ) {
     56         s->regs[idx] &= ~(USB_HSIC_PHY_SW_Pxx_REQ |
     57                           USB_OTG2_PHY_SW_Pxx_REQ |
     58                           USB_OTG1_PHY_SW_Pxx_REQ |
     59                           PCIE_PHY_SW_Pxx_REQ     |
     60                           MIPI_PHY_SW_Pxx_REQ);
     61     }
     62 }
     63 
     64 static const struct MemoryRegionOps imx_gpcv2_ops = {
     65     .read = imx_gpcv2_read,
     66     .write = imx_gpcv2_write,
     67     .endianness = DEVICE_NATIVE_ENDIAN,
     68     .impl = {
     69         /*
     70          * Our device would not work correctly if the guest was doing
     71          * unaligned access. This might not be a limitation on the real
     72          * device but in practice there is no reason for a guest to access
     73          * this device unaligned.
     74          */
     75         .min_access_size = 4,
     76         .max_access_size = 4,
     77         .unaligned = false,
     78     },
     79 };
     80 
     81 static void imx_gpcv2_init(Object *obj)
     82 {
     83     SysBusDevice *sd = SYS_BUS_DEVICE(obj);
     84     IMXGPCv2State *s = IMX_GPCV2(obj);
     85 
     86     memory_region_init_io(&s->iomem,
     87                           obj,
     88                           &imx_gpcv2_ops,
     89                           s,
     90                           TYPE_IMX_GPCV2 ".iomem",
     91                           sizeof(s->regs));
     92     sysbus_init_mmio(sd, &s->iomem);
     93 }
     94 
     95 static const VMStateDescription vmstate_imx_gpcv2 = {
     96     .name = TYPE_IMX_GPCV2,
     97     .version_id = 1,
     98     .minimum_version_id = 1,
     99     .fields = (VMStateField[]) {
    100         VMSTATE_UINT32_ARRAY(regs, IMXGPCv2State, GPC_NUM),
    101         VMSTATE_END_OF_LIST()
    102     },
    103 };
    104 
    105 static void imx_gpcv2_class_init(ObjectClass *klass, void *data)
    106 {
    107     DeviceClass *dc = DEVICE_CLASS(klass);
    108 
    109     dc->reset = imx_gpcv2_reset;
    110     dc->vmsd  = &vmstate_imx_gpcv2;
    111     dc->desc  = "i.MX GPCv2 Module";
    112 }
    113 
    114 static const TypeInfo imx_gpcv2_info = {
    115     .name          = TYPE_IMX_GPCV2,
    116     .parent        = TYPE_SYS_BUS_DEVICE,
    117     .instance_size = sizeof(IMXGPCv2State),
    118     .instance_init = imx_gpcv2_init,
    119     .class_init    = imx_gpcv2_class_init,
    120 };
    121 
    122 static void imx_gpcv2_register_type(void)
    123 {
    124     type_register_static(&imx_gpcv2_info);
    125 }
    126 type_init(imx_gpcv2_register_type)