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.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
  44REG32(MIO, 0x0)
  45    #define R_MIO_RSVD               0xffffff01
  46
  47REG32(SD_SLOTTYPE, 0x310)
  48    #define R_SD_SLOTTYPE_RSVD       0xffffff9c
  49
  50#define R_MAX ((R_SD_SLOTTYPE) + 1)
  51
  52typedef struct ZynqMPIOUSLCR ZynqMPIOUSLCR;
  53
  54struct ZynqMPIOUSLCR {
  55    SysBusDevice busdev;
  56    MemoryRegion iomem;
  57
  58    uint32_t regs[R_MAX];
  59    RegisterInfo regs_info[R_MAX];
  60};
  61
  62static const RegisterAccessInfo zynqmp_iou_slcr_regs_info[] = {
  63#define M(x) \
  64    {   .name = "MIO" #x,             .decode.addr = A_MIO + 4 * x,         \
  65            .rsvd = R_MIO_RSVD,                                             \
  66    },
  67    M( 0) M( 1) M( 2) M( 3) M( 4) M( 5) M( 6) M( 7) M( 8) M( 9)
  68    M(10) M(11) M(12) M(13) M(14) M(15) M(16) M(17) M(18) M(19)
  69    M(20) M(21) M(22) M(23) M(24) M(25) M(26) M(27) M(28) M(29)
  70    M(30) M(31) M(32) M(33) M(34) M(35) M(36) M(37) M(38) M(39)
  71    M(40) M(41) M(42) M(43) M(44) M(45) M(46) M(47) M(48) M(49)
  72    M(50) M(51) M(52) M(53) M(54) M(55) M(56) M(57) M(58) M(59)
  73    M(60) M(61) M(62) M(63) M(64) M(65) M(66) M(67) M(78) M(69)
  74    M(70) M(71) M(72) M(73) M(74) M(75) M(76) M(77)
  75#undef M
  76    {   .name = "SD Slot TYPE",             .decode.addr = A_SD_SLOTTYPE,
  77            .rsvd = R_SD_SLOTTYPE_RSVD,
  78            .gpios = (RegisterGPIOMapping []) {
  79                { .name = "SD0_SLOTTYPE",   .bit_pos = 0,    .width = 2 },
  80                { .name = "SD1_SLOTTYPE",   .bit_pos = 15,    .width = 2 },
  81                {},
  82            }
  83    }
  84};
  85
  86static void zynqmp_iou_slcr_reset(DeviceState *dev)
  87{
  88    ZynqMPIOUSLCR *s = ZYNQMP_IOU_SLCR(dev);
  89    int i;
  90
  91    for (i = 0; i < R_MAX; ++i) {
  92        register_reset(&s->regs_info[i]);
  93    }
  94}
  95
  96static const MemoryRegionOps zynqmp_iou_slcr_ops = {
  97    .read = register_read_memory_le,
  98    .write = register_write_memory_le,
  99    .endianness = DEVICE_LITTLE_ENDIAN,
 100    .valid = {
 101        .min_access_size = 4,
 102        .max_access_size = 4,
 103    }
 104};
 105
 106static void zynqmp_iou_slcr_realize(DeviceState *dev, Error **errp)
 107{
 108    ZynqMPIOUSLCR *s = ZYNQMP_IOU_SLCR(dev);
 109    const char *prefix = object_get_canonical_path(OBJECT(dev));
 110    int i;
 111
 112    for (i = 0; i < ARRAY_SIZE(zynqmp_iou_slcr_regs_info); ++i) {
 113        RegisterInfo *r = &s->regs_info[i];
 114
 115        *r = (RegisterInfo) {
 116            .data = (uint8_t *)&s->regs[
 117                    zynqmp_iou_slcr_regs_info[i].decode.addr/4],
 118            .data_size = sizeof(uint32_t),
 119            .access = &zynqmp_iou_slcr_regs_info[i],
 120            .debug = ZYNQMP_IOU_SLCR_ERR_DEBUG,
 121            .prefix = prefix,
 122            .opaque = s,
 123        };
 124        register_init(r);
 125        qdev_pass_all_gpios(DEVICE(r), dev);
 126
 127        memory_region_init_io(&r->mem, OBJECT(dev), &zynqmp_iou_slcr_ops, r,
 128                              r->access->name, 4);
 129        memory_region_add_subregion(&s->iomem, r->access->decode.addr, &r->mem);
 130    }
 131    return;
 132}
 133
 134static void zynqmp_iou_slcr_init(Object *obj)
 135{
 136    ZynqMPIOUSLCR *s = ZYNQMP_IOU_SLCR(obj);
 137
 138    memory_region_init(&s->iomem, obj, "MMIO", R_MAX * 4);
 139    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
 140}
 141
 142static const VMStateDescription vmstate_zynqmp_iou_slcr = {
 143    .name = "zynqmp_iou_slcr",
 144    .version_id = 1,
 145    .minimum_version_id = 1,
 146    .minimum_version_id_old = 1,
 147    .fields = (VMStateField[]) {
 148        VMSTATE_UINT32_ARRAY(regs, ZynqMPIOUSLCR, R_MAX),
 149        VMSTATE_END_OF_LIST(),
 150    }
 151};
 152
 153static const FDTGenericGPIOSet zynqmp_iou_slcr_controller_gpios [] = {
 154    {
 155        /* FIXME: this could be a much better name */
 156        .names = &fdt_generic_gpio_name_set_gpio,
 157        .gpios = (FDTGenericGPIOConnection []) {
 158            { .name = "SD0_SLOTTYPE",   .fdt_index = 0 },
 159            { .name = "SD1_SLOTTYPE",   .fdt_index = 1 },
 160            { },
 161        },
 162    },
 163    { },
 164};
 165
 166static void zynqmp_iou_slcr_class_init(ObjectClass *klass, void *data)
 167{
 168    DeviceClass *dc = DEVICE_CLASS(klass);
 169    FDTGenericGPIOClass *fggc = FDT_GENERIC_GPIO_CLASS(klass);
 170
 171    dc->reset = zynqmp_iou_slcr_reset;
 172    dc->realize = zynqmp_iou_slcr_realize;
 173    dc->vmsd = &vmstate_zynqmp_iou_slcr;
 174
 175    fggc->controller_gpios = zynqmp_iou_slcr_controller_gpios;
 176}
 177
 178static const TypeInfo zynqmp_iou_slcr_info = {
 179    .name          = TYPE_ZYNQMP_IOU_SLCR,
 180    .parent        = TYPE_SYS_BUS_DEVICE,
 181    .instance_size = sizeof(ZynqMPIOUSLCR),
 182    .class_init    = zynqmp_iou_slcr_class_init,
 183    .instance_init = zynqmp_iou_slcr_init,
 184    .interfaces    = (InterfaceInfo[]) {
 185        { TYPE_FDT_GENERIC_GPIO },
 186        { },
 187    }
 188};
 189
 190static void zynqmp_iou_slcr_register_types(void)
 191{
 192    type_register_static(&zynqmp_iou_slcr_info);
 193}
 194
 195type_init(zynqmp_iou_slcr_register_types)
 196