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