qemu/hw/misc/zynqmp-iou-slcr.c
<<
>>
Prefs
   1/*
   2 * Ronlado IOU system level control registers (SLCR)
   3 *
   4 * Copyright (c) 2013 Xilinx Inc
   5 * Copyright (c) 2013 Peter Crosthwaite <peter.crosthwaite@xilinx.com>
   6 *
   7 * Permission is hereby granted, free of charge, to any person obtaining a copy
   8 * of this software and associated documentation files (the "Software"), to deal
   9 * in the Software without restriction, including without limitation the rights
  10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11 * copies of the Software, and to permit persons to whom the Software is
  12 * furnished to do so, subject to the following conditions:
  13 *
  14 * The above copyright notice and this permission notice shall be included in
  15 * all copies or substantial portions of the Software.
  16 *
  17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23 * THE SOFTWARE.
  24 */
  25
  26#include "qemu/osdep.h"
  27#include "hw/sysbus.h"
  28#include "qemu/log.h"
  29
  30#include "qemu/bitops.h"
  31#include "qapi/qmp/qerror.h"
  32#include "hw/register-dep.h"
  33#include "hw/fdt_generic_util.h"
  34
  35#ifndef ZYNQMP_IOU_SLCR_ERR_DEBUG
  36#define ZYNQMP_IOU_SLCR_ERR_DEBUG 0
  37#endif
  38
  39#define TYPE_ZYNQMP_IOU_SLCR "xilinx.zynqmp-iou-slcr"
  40
  41#define ZYNQMP_IOU_SLCR(obj) \
  42     OBJECT_CHECK(ZynqMPIOUSLCR, (obj), TYPE_ZYNQMP_IOU_SLCR)
  43
  44DEP_REG32(MIO, 0x0)
  45    #define R_MIO_RSVD               0xffffff01
  46DEP_REG32(BANK0_CTRL0, 0x138)
  47    DEP_FIELD(BANK0_CTRL0, DRIVE0, 26, 0)
  48DEP_REG32(BANK0_CTRL1, 0x13c)
  49    DEP_FIELD(BANK0_CTRL1, DRIVE1, 26, 0)
  50DEP_REG32(BANK0_CTRL3, 0x140)
  51    DEP_FIELD(BANK0_CTRL3, SCHMITT_CMOS_N, 26, 0)
  52DEP_REG32(BANK0_CTRL4, 0x144)
  53    DEP_FIELD(BANK0_CTRL4, PULL_HIGH_LOW_N, 26, 0)
  54DEP_REG32(BANK0_CTRL5, 0x148)
  55    DEP_FIELD(BANK0_CTRL5, PULL_ENABLE, 26, 0)
  56DEP_REG32(BANK0_CTRL6, 0x14c)
  57    DEP_FIELD(BANK0_CTRL6, SLOW_FAST_SLEW_N, 26, 0)
  58DEP_REG32(BANK0_STATUS, 0x150)
  59    DEP_FIELD(BANK0_STATUS, VOLTAGE_MODE, 1, 0)
  60DEP_REG32(BANK1_CTRL0, 0x154)
  61    DEP_FIELD(BANK1_CTRL0, DRIVE0, 26, 0)
  62DEP_REG32(BANK1_CTRL1, 0x158)
  63    DEP_FIELD(BANK1_CTRL1, DRIVE1, 26, 0)
  64DEP_REG32(BANK1_CTRL3, 0x15c)
  65    DEP_FIELD(BANK1_CTRL3, SCHMITT_CMOS_N, 26, 0)
  66DEP_REG32(BANK1_CTRL4, 0x160)
  67    DEP_FIELD(BANK1_CTRL4, PULL_HIGH_LOW_N, 26, 0)
  68DEP_REG32(BANK1_CTRL5, 0x164)
  69    DEP_FIELD(BANK1_CTRL5, PULL_ENABLE_13_TO_0, 14, 12)
  70    DEP_FIELD(BANK1_CTRL5, PULL_ENABLE_25_TO_14, 12, 0)
  71DEP_REG32(BANK1_CTRL6, 0x168)
  72    DEP_FIELD(BANK1_CTRL6, SLOW_FAST_SLEW_N, 26, 0)
  73DEP_REG32(BANK1_STATUS, 0x16c)
  74    DEP_FIELD(BANK1_STATUS, VOLTAGE_MODE, 1, 0)
  75DEP_REG32(BANK2_CTRL0, 0x170)
  76    DEP_FIELD(BANK2_CTRL0, DRIVE0, 26, 0)
  77DEP_REG32(BANK2_CTRL1, 0x174)
  78    DEP_FIELD(BANK2_CTRL1, DRIVE1, 26, 0)
  79DEP_REG32(BANK2_CTRL3, 0x178)
  80    DEP_FIELD(BANK2_CTRL3, SCHMITT_CMOS_N, 26, 0)
  81DEP_REG32(BANK2_CTRL4, 0x17c)
  82    DEP_FIELD(BANK2_CTRL4, PULL_HIGH_LOW_N, 26, 0)
  83DEP_REG32(BANK2_CTRL5, 0x180)
  84    DEP_FIELD(BANK2_CTRL5, PULL_ENABLE, 26, 0)
  85DEP_REG32(BANK2_CTRL6, 0x184)
  86    DEP_FIELD(BANK2_CTRL6, SLOW_FAST_SLEW_N, 26, 0)
  87DEP_REG32(BANK2_STATUS, 0x188)
  88    DEP_FIELD(BANK2_STATUS, VOLTAGE_MODE, 1, 0)
  89DEP_REG32(SD_SLOTTYPE, 0x310)
  90    #define R_SD_SLOTTYPE_RSVD       0xffffff9c
  91
  92#define R_MAX ((R_SD_SLOTTYPE) + 1)
  93
  94typedef struct ZynqMPIOUSLCR ZynqMPIOUSLCR;
  95
  96struct ZynqMPIOUSLCR {
  97    SysBusDevice busdev;
  98    MemoryRegion iomem;
  99
 100    bool mio_bank0v;
 101    bool mio_bank1v;
 102    bool mio_bank2v;
 103    uint32_t regs[R_MAX];
 104    DepRegisterInfo regs_info[R_MAX];
 105};
 106
 107static const DepRegisterAccessInfo zynqmp_iou_slcr_regs_info[] = {
 108#define M(x) \
 109    {   .name = "MIO" #x,             .decode.addr = A_MIO + 4 * x,         \
 110            .rsvd = R_MIO_RSVD,                                             \
 111    },
 112    M( 0) M( 1) M( 2) M( 3) M( 4) M( 5) M( 6) M( 7) M( 8) M( 9)
 113    M(10) M(11) M(12) M(13) M(14) M(15) M(16) M(17) M(18) M(19)
 114    M(20) M(21) M(22) M(23) M(24) M(25) M(26) M(27) M(28) M(29)
 115    M(30) M(31) M(32) M(33) M(34) M(35) M(36) M(37) M(38) M(39)
 116    M(40) M(41) M(42) M(43) M(44) M(45) M(46) M(47) M(48) M(49)
 117    M(50) M(51) M(52) M(53) M(54) M(55) M(56) M(57) M(58) M(59)
 118    M(60) M(61) M(62) M(63) M(64) M(65) M(66) M(67) M(78) M(69)
 119    M(70) M(71) M(72) M(73) M(74) M(75) M(76) M(77)
 120#undef M
 121    { .name = "BANK0_CTRL0",  .decode.addr = A_BANK0_CTRL0,
 122        .reset = 0x3ffffff,
 123    },{ .name = "BANK0_CTRL1",  .decode.addr = A_BANK0_CTRL1,
 124    },{ .name = "BANK0_CTRL3",  .decode.addr = A_BANK0_CTRL3,
 125    },{ .name = "BANK0_CTRL4",  .decode.addr = A_BANK0_CTRL4,
 126        .reset = 0x3ffffff,
 127    },{ .name = "BANK0_CTRL5",  .decode.addr = A_BANK0_CTRL5,
 128        .reset = 0x3ffffff,
 129    },{ .name = "BANK0_CTRL6",  .decode.addr = A_BANK0_CTRL6,
 130    },{ .name = "BANK0_STATUS",  .decode.addr = A_BANK0_STATUS,
 131        .ro = 0x1,
 132    },{ .name = "BANK1_CTRL0",  .decode.addr = A_BANK1_CTRL0,
 133        .reset = 0x3ffffff,
 134    },{ .name = "BANK1_CTRL1",  .decode.addr = A_BANK1_CTRL1,
 135    },{ .name = "BANK1_CTRL3",  .decode.addr = A_BANK1_CTRL3,
 136    },{ .name = "BANK1_CTRL4",  .decode.addr = A_BANK1_CTRL4,
 137        .reset = 0x3ffffff,
 138    },{ .name = "BANK1_CTRL5",  .decode.addr = A_BANK1_CTRL5,
 139        .reset = 0x3ffffff,
 140    },{ .name = "BANK1_CTRL6",  .decode.addr = A_BANK1_CTRL6,
 141    },{ .name = "BANK1_STATUS",  .decode.addr = A_BANK1_STATUS,
 142        .ro = 0x1,
 143    },{ .name = "BANK2_CTRL0",  .decode.addr = A_BANK2_CTRL0,
 144        .reset = 0x3ffffff,
 145    },{ .name = "BANK2_CTRL1",  .decode.addr = A_BANK2_CTRL1,
 146    },{ .name = "BANK2_CTRL3",  .decode.addr = A_BANK2_CTRL3,
 147    },{ .name = "BANK2_CTRL4",  .decode.addr = A_BANK2_CTRL4,
 148        .reset = 0x3ffffff,
 149    },{ .name = "BANK2_CTRL5",  .decode.addr = A_BANK2_CTRL5,
 150        .reset = 0x3ffffff,
 151    },{ .name = "BANK2_CTRL6",  .decode.addr = A_BANK2_CTRL6,
 152    },{ .name = "BANK2_STATUS",  .decode.addr = A_BANK2_STATUS,
 153        .ro = 0x1,
 154    },
 155    {   .name = "SD Slot TYPE",             .decode.addr = A_SD_SLOTTYPE,
 156            .rsvd = R_SD_SLOTTYPE_RSVD,
 157            .gpios = (DepRegisterGPIOMapping []) {
 158                { .name = "SD0_SLOTTYPE",   .bit_pos = 0,    .width = 2 },
 159                { .name = "SD1_SLOTTYPE",   .bit_pos = 15,    .width = 2 },
 160                {},
 161            }
 162    }
 163};
 164
 165static void zynqmp_iou_slcr_reset(DeviceState *dev)
 166{
 167    ZynqMPIOUSLCR *s = ZYNQMP_IOU_SLCR(dev);
 168    int i;
 169
 170    for (i = 0; i < R_MAX; ++i) {
 171        dep_register_reset(&s->regs_info[i]);
 172    }
 173    DEP_AF_DP32(s->regs, BANK0_STATUS, VOLTAGE_MODE, s->mio_bank0v);
 174    DEP_AF_DP32(s->regs, BANK1_STATUS, VOLTAGE_MODE, s->mio_bank1v);
 175    DEP_AF_DP32(s->regs, BANK2_STATUS, VOLTAGE_MODE, s->mio_bank2v);
 176}
 177
 178static const MemoryRegionOps zynqmp_iou_slcr_ops = {
 179    .read = dep_register_read_memory_le,
 180    .write = dep_register_write_memory_le,
 181    .endianness = DEVICE_LITTLE_ENDIAN,
 182    .valid = {
 183        .min_access_size = 4,
 184        .max_access_size = 4,
 185    }
 186};
 187
 188static void zynqmp_iou_slcr_realize(DeviceState *dev, Error **errp)
 189{
 190    ZynqMPIOUSLCR *s = ZYNQMP_IOU_SLCR(dev);
 191    const char *prefix = object_get_canonical_path(OBJECT(dev));
 192    int i;
 193
 194    for (i = 0; i < ARRAY_SIZE(zynqmp_iou_slcr_regs_info); ++i) {
 195        DepRegisterInfo *r = &s->regs_info[i];
 196
 197        *r = (DepRegisterInfo) {
 198            .data = (uint8_t *)&s->regs[
 199                    zynqmp_iou_slcr_regs_info[i].decode.addr/4],
 200            .data_size = sizeof(uint32_t),
 201            .access = &zynqmp_iou_slcr_regs_info[i],
 202            .debug = ZYNQMP_IOU_SLCR_ERR_DEBUG,
 203            .prefix = prefix,
 204            .opaque = s,
 205        };
 206        dep_register_init(r);
 207        qdev_pass_all_gpios(DEVICE(r), dev);
 208
 209        memory_region_init_io(&r->mem, OBJECT(dev), &zynqmp_iou_slcr_ops, r,
 210                              r->access->name, 4);
 211        memory_region_add_subregion(&s->iomem, r->access->decode.addr, &r->mem);
 212    }
 213    return;
 214}
 215
 216static void zynqmp_iou_slcr_init(Object *obj)
 217{
 218    ZynqMPIOUSLCR *s = ZYNQMP_IOU_SLCR(obj);
 219
 220    memory_region_init(&s->iomem, obj, "MMIO", R_MAX * 4);
 221    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
 222}
 223
 224static const VMStateDescription vmstate_zynqmp_iou_slcr = {
 225    .name = "zynqmp_iou_slcr",
 226    .version_id = 1,
 227    .minimum_version_id = 1,
 228    .minimum_version_id_old = 1,
 229    .fields = (VMStateField[]) {
 230        VMSTATE_UINT32_ARRAY(regs, ZynqMPIOUSLCR, R_MAX),
 231        VMSTATE_END_OF_LIST(),
 232    }
 233};
 234
 235static const FDTGenericGPIOSet zynqmp_iou_slcr_controller_gpios [] = {
 236    {
 237        /* FIXME: this could be a much better name */
 238        .names = &fdt_generic_gpio_name_set_gpio,
 239        .gpios = (FDTGenericGPIOConnection []) {
 240            { .name = "SD0_SLOTTYPE",   .fdt_index = 0 },
 241            { .name = "SD1_SLOTTYPE",   .fdt_index = 1 },
 242            { },
 243        },
 244    },
 245    { },
 246};
 247
 248static Property zynqmp_iou_slcr_props[] = {
 249    DEFINE_PROP_BOOL("mio-bank0-1.8v", ZynqMPIOUSLCR, mio_bank0v, false),
 250    DEFINE_PROP_BOOL("mio-bank1-1.8v", ZynqMPIOUSLCR, mio_bank1v, false),
 251    DEFINE_PROP_BOOL("mio-bank2-1.8v", ZynqMPIOUSLCR, mio_bank2v, false),
 252    DEFINE_PROP_END_OF_LIST(),
 253};
 254
 255static void zynqmp_iou_slcr_class_init(ObjectClass *klass, void *data)
 256{
 257    DeviceClass *dc = DEVICE_CLASS(klass);
 258    FDTGenericGPIOClass *fggc = FDT_GENERIC_GPIO_CLASS(klass);
 259
 260    dc->reset = zynqmp_iou_slcr_reset;
 261    dc->realize = zynqmp_iou_slcr_realize;
 262    dc->vmsd = &vmstate_zynqmp_iou_slcr;
 263    dc->props = zynqmp_iou_slcr_props;
 264
 265    fggc->controller_gpios = zynqmp_iou_slcr_controller_gpios;
 266}
 267
 268static const TypeInfo zynqmp_iou_slcr_info = {
 269    .name          = TYPE_ZYNQMP_IOU_SLCR,
 270    .parent        = TYPE_SYS_BUS_DEVICE,
 271    .instance_size = sizeof(ZynqMPIOUSLCR),
 272    .class_init    = zynqmp_iou_slcr_class_init,
 273    .instance_init = zynqmp_iou_slcr_init,
 274    .interfaces    = (InterfaceInfo[]) {
 275        { TYPE_FDT_GENERIC_GPIO },
 276        { },
 277    }
 278};
 279
 280static void zynqmp_iou_slcr_register_types(void)
 281{
 282    type_register_static(&zynqmp_iou_slcr_info);
 283}
 284
 285type_init(zynqmp_iou_slcr_register_types)
 286