qemu

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

imx-usb-phy.c (6305B)


      1 /*
      2  * i.MX USB PHY
      3  *
      4  * Copyright (c) 2020 Guenter Roeck <linux@roeck-us.net>
      5  *
      6  * This work is licensed under the terms of the GNU GPL, version 2 or later.
      7  * See the COPYING file in the top-level directory.
      8  *
      9  * We need to implement basic reset control in the PHY control register.
     10  * For everything else, it is sufficient to set whatever is written.
     11  */
     12 
     13 #include "qemu/osdep.h"
     14 #include "hw/usb/imx-usb-phy.h"
     15 #include "migration/vmstate.h"
     16 #include "qemu/module.h"
     17 
     18 static const VMStateDescription vmstate_imx_usbphy = {
     19     .name = TYPE_IMX_USBPHY,
     20     .version_id = 1,
     21     .minimum_version_id = 1,
     22     .fields = (VMStateField[]) {
     23         VMSTATE_UINT32_ARRAY(usbphy, IMXUSBPHYState, USBPHY_MAX),
     24         VMSTATE_END_OF_LIST()
     25     },
     26 };
     27 
     28 static void imx_usbphy_softreset(IMXUSBPHYState *s)
     29 {
     30     s->usbphy[USBPHY_PWD] = 0x001e1c00;
     31     s->usbphy[USBPHY_TX] = 0x10060607;
     32     s->usbphy[USBPHY_RX] = 0x00000000;
     33     s->usbphy[USBPHY_CTRL] = 0xc0200000;
     34 }
     35 
     36 static void imx_usbphy_reset(DeviceState *dev)
     37 {
     38     IMXUSBPHYState *s = IMX_USBPHY(dev);
     39 
     40     s->usbphy[USBPHY_STATUS] = 0x00000000;
     41     s->usbphy[USBPHY_DEBUG] = 0x7f180000;
     42     s->usbphy[USBPHY_DEBUG0_STATUS] = 0x00000000;
     43     s->usbphy[USBPHY_DEBUG1] = 0x00001000;
     44     s->usbphy[USBPHY_VERSION] = 0x04020000;
     45 
     46     imx_usbphy_softreset(s);
     47 }
     48 
     49 static uint64_t imx_usbphy_read(void *opaque, hwaddr offset, unsigned size)
     50 {
     51     IMXUSBPHYState *s = (IMXUSBPHYState *)opaque;
     52     uint32_t index = offset >> 2;
     53     uint32_t value;
     54 
     55     switch (index) {
     56     case USBPHY_PWD_SET:
     57     case USBPHY_TX_SET:
     58     case USBPHY_RX_SET:
     59     case USBPHY_CTRL_SET:
     60     case USBPHY_DEBUG_SET:
     61     case USBPHY_DEBUG1_SET:
     62         /*
     63          * All REG_NAME_SET register access are in fact targeting the
     64          * REG_NAME register.
     65          */
     66         value = s->usbphy[index - 1];
     67         break;
     68     case USBPHY_PWD_CLR:
     69     case USBPHY_TX_CLR:
     70     case USBPHY_RX_CLR:
     71     case USBPHY_CTRL_CLR:
     72     case USBPHY_DEBUG_CLR:
     73     case USBPHY_DEBUG1_CLR:
     74         /*
     75          * All REG_NAME_CLR register access are in fact targeting the
     76          * REG_NAME register.
     77          */
     78         value = s->usbphy[index - 2];
     79         break;
     80     case USBPHY_PWD_TOG:
     81     case USBPHY_TX_TOG:
     82     case USBPHY_RX_TOG:
     83     case USBPHY_CTRL_TOG:
     84     case USBPHY_DEBUG_TOG:
     85     case USBPHY_DEBUG1_TOG:
     86         /*
     87          * All REG_NAME_TOG register access are in fact targeting the
     88          * REG_NAME register.
     89          */
     90         value = s->usbphy[index - 3];
     91         break;
     92     default:
     93         value = s->usbphy[index];
     94         break;
     95     }
     96     return (uint64_t)value;
     97 }
     98 
     99 static void imx_usbphy_write(void *opaque, hwaddr offset, uint64_t value,
    100                              unsigned size)
    101 {
    102     IMXUSBPHYState *s = (IMXUSBPHYState *)opaque;
    103     uint32_t index = offset >> 2;
    104 
    105     switch (index) {
    106     case USBPHY_CTRL:
    107         s->usbphy[index] = value;
    108         if (value & USBPHY_CTRL_SFTRST) {
    109             imx_usbphy_softreset(s);
    110         }
    111         break;
    112     case USBPHY_PWD:
    113     case USBPHY_TX:
    114     case USBPHY_RX:
    115     case USBPHY_STATUS:
    116     case USBPHY_DEBUG:
    117     case USBPHY_DEBUG1:
    118         s->usbphy[index] = value;
    119         break;
    120     case USBPHY_CTRL_SET:
    121         s->usbphy[index - 1] |= value;
    122         if (value & USBPHY_CTRL_SFTRST) {
    123             imx_usbphy_softreset(s);
    124         }
    125         break;
    126     case USBPHY_PWD_SET:
    127     case USBPHY_TX_SET:
    128     case USBPHY_RX_SET:
    129     case USBPHY_DEBUG_SET:
    130     case USBPHY_DEBUG1_SET:
    131         /*
    132          * All REG_NAME_SET register access are in fact targeting the
    133          * REG_NAME register. So we change the value of the REG_NAME
    134          * register, setting bits passed in the value.
    135          */
    136         s->usbphy[index - 1] |= value;
    137         break;
    138     case USBPHY_PWD_CLR:
    139     case USBPHY_TX_CLR:
    140     case USBPHY_RX_CLR:
    141     case USBPHY_CTRL_CLR:
    142     case USBPHY_DEBUG_CLR:
    143     case USBPHY_DEBUG1_CLR:
    144         /*
    145          * All REG_NAME_CLR register access are in fact targeting the
    146          * REG_NAME register. So we change the value of the REG_NAME
    147          * register, unsetting bits passed in the value.
    148          */
    149         s->usbphy[index - 2] &= ~value;
    150         break;
    151     case USBPHY_CTRL_TOG:
    152         s->usbphy[index - 3] ^= value;
    153         if ((value & USBPHY_CTRL_SFTRST) &&
    154             (s->usbphy[index - 3] & USBPHY_CTRL_SFTRST)) {
    155             imx_usbphy_softreset(s);
    156         }
    157         break;
    158     case USBPHY_PWD_TOG:
    159     case USBPHY_TX_TOG:
    160     case USBPHY_RX_TOG:
    161     case USBPHY_DEBUG_TOG:
    162     case USBPHY_DEBUG1_TOG:
    163         /*
    164          * All REG_NAME_TOG register access are in fact targeting the
    165          * REG_NAME register. So we change the value of the REG_NAME
    166          * register, toggling bits passed in the value.
    167          */
    168         s->usbphy[index - 3] ^= value;
    169         break;
    170     default:
    171         /* Other registers are read-only */
    172         break;
    173     }
    174 }
    175 
    176 static const struct MemoryRegionOps imx_usbphy_ops = {
    177     .read = imx_usbphy_read,
    178     .write = imx_usbphy_write,
    179     .endianness = DEVICE_NATIVE_ENDIAN,
    180     .valid = {
    181         /*
    182          * Our device would not work correctly if the guest was doing
    183          * unaligned access. This might not be a limitation on the real
    184          * device but in practice there is no reason for a guest to access
    185          * this device unaligned.
    186          */
    187         .min_access_size = 4,
    188         .max_access_size = 4,
    189         .unaligned = false,
    190     },
    191 };
    192 
    193 static void imx_usbphy_realize(DeviceState *dev, Error **errp)
    194 {
    195     IMXUSBPHYState *s = IMX_USBPHY(dev);
    196 
    197     memory_region_init_io(&s->iomem, OBJECT(s), &imx_usbphy_ops, s,
    198                           "imx-usbphy", 0x1000);
    199     sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
    200 }
    201 
    202 static void imx_usbphy_class_init(ObjectClass *klass, void *data)
    203 {
    204     DeviceClass *dc = DEVICE_CLASS(klass);
    205 
    206     dc->reset = imx_usbphy_reset;
    207     dc->vmsd = &vmstate_imx_usbphy;
    208     dc->desc = "i.MX USB PHY Module";
    209     dc->realize = imx_usbphy_realize;
    210 }
    211 
    212 static const TypeInfo imx_usbphy_info = {
    213     .name          = TYPE_IMX_USBPHY,
    214     .parent        = TYPE_SYS_BUS_DEVICE,
    215     .instance_size = sizeof(IMXUSBPHYState),
    216     .class_init    = imx_usbphy_class_init,
    217 };
    218 
    219 static void imx_usbphy_register_types(void)
    220 {
    221     type_register_static(&imx_usbphy_info);
    222 }
    223 
    224 type_init(imx_usbphy_register_types)