cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

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
     18static 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
     28static 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
     36static 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
     49static 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
     99static 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
    176static 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
    193static 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
    202static 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
    212static 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
    219static void imx_usbphy_register_types(void)
    220{
    221    type_register_static(&imx_usbphy_info);
    222}
    223
    224type_init(imx_usbphy_register_types)