qemu

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

arm_l2x0.c (5097B)


      1 /*
      2  * ARM dummy L210, L220, PL310 cache controller.
      3  *
      4  * Copyright (c) 2010-2012 Calxeda
      5  *
      6  * This program is free software; you can redistribute it and/or modify it
      7  * under the terms and conditions of the GNU General Public License,
      8  * version 2 or any later version, as published by the Free Software
      9  * Foundation.
     10  *
     11  * This program is distributed in the hope it will be useful, but WITHOUT
     12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     14  * more details.
     15  *
     16  * You should have received a copy of the GNU General Public License along with
     17  * this program.  If not, see <http://www.gnu.org/licenses/>.
     18  *
     19  */
     20 
     21 #include "qemu/osdep.h"
     22 #include "hw/qdev-properties.h"
     23 #include "hw/sysbus.h"
     24 #include "migration/vmstate.h"
     25 #include "qemu/log.h"
     26 #include "qemu/module.h"
     27 #include "qom/object.h"
     28 
     29 /* L2C-310 r3p2 */
     30 #define CACHE_ID 0x410000c8
     31 
     32 #define TYPE_ARM_L2X0 "l2x0"
     33 OBJECT_DECLARE_SIMPLE_TYPE(L2x0State, ARM_L2X0)
     34 
     35 struct L2x0State {
     36     SysBusDevice parent_obj;
     37 
     38     MemoryRegion iomem;
     39     uint32_t cache_type;
     40     uint32_t ctrl;
     41     uint32_t aux_ctrl;
     42     uint32_t data_ctrl;
     43     uint32_t tag_ctrl;
     44     uint32_t filter_start;
     45     uint32_t filter_end;
     46 };
     47 
     48 static const VMStateDescription vmstate_l2x0 = {
     49     .name = "l2x0",
     50     .version_id = 1,
     51     .minimum_version_id = 1,
     52     .fields = (VMStateField[]) {
     53         VMSTATE_UINT32(ctrl, L2x0State),
     54         VMSTATE_UINT32(aux_ctrl, L2x0State),
     55         VMSTATE_UINT32(data_ctrl, L2x0State),
     56         VMSTATE_UINT32(tag_ctrl, L2x0State),
     57         VMSTATE_UINT32(filter_start, L2x0State),
     58         VMSTATE_UINT32(filter_end, L2x0State),
     59         VMSTATE_END_OF_LIST()
     60     }
     61 };
     62 
     63 
     64 static uint64_t l2x0_priv_read(void *opaque, hwaddr offset,
     65                                unsigned size)
     66 {
     67     uint32_t cache_data;
     68     L2x0State *s = (L2x0State *)opaque;
     69     offset &= 0xfff;
     70     if (offset >= 0x730 && offset < 0x800) {
     71         return 0; /* cache ops complete */
     72     }
     73     switch (offset) {
     74     case 0:
     75         return CACHE_ID;
     76     case 0x4:
     77         /* aux_ctrl values affect cache_type values */
     78         cache_data = (s->aux_ctrl & (7 << 17)) >> 15;
     79         cache_data |= (s->aux_ctrl & (1 << 16)) >> 16;
     80         return s->cache_type |= (cache_data << 18) | (cache_data << 6);
     81     case 0x100:
     82         return s->ctrl;
     83     case 0x104:
     84         return s->aux_ctrl;
     85     case 0x108:
     86         return s->tag_ctrl;
     87     case 0x10C:
     88         return s->data_ctrl;
     89     case 0xC00:
     90         return s->filter_start;
     91     case 0xC04:
     92         return s->filter_end;
     93     case 0xF40:
     94         return 0;
     95     case 0xF60:
     96         return 0;
     97     case 0xF80:
     98         return 0;
     99     default:
    100         qemu_log_mask(LOG_GUEST_ERROR,
    101                       "l2x0_priv_read: Bad offset %x\n", (int)offset);
    102         break;
    103     }
    104     return 0;
    105 }
    106 
    107 static void l2x0_priv_write(void *opaque, hwaddr offset,
    108                             uint64_t value, unsigned size)
    109 {
    110     L2x0State *s = (L2x0State *)opaque;
    111     offset &= 0xfff;
    112     if (offset >= 0x730 && offset < 0x800) {
    113         /* ignore */
    114         return;
    115     }
    116     switch (offset) {
    117     case 0x100:
    118         s->ctrl = value & 1;
    119         break;
    120     case 0x104:
    121         s->aux_ctrl = value;
    122         break;
    123     case 0x108:
    124         s->tag_ctrl = value;
    125         break;
    126     case 0x10C:
    127         s->data_ctrl = value;
    128         break;
    129     case 0xC00:
    130         s->filter_start = value;
    131         break;
    132     case 0xC04:
    133         s->filter_end = value;
    134         break;
    135     case 0xF40:
    136         return;
    137     case 0xF60:
    138         return;
    139     case 0xF80:
    140         return;
    141     default:
    142         qemu_log_mask(LOG_GUEST_ERROR,
    143                       "l2x0_priv_write: Bad offset %x\n", (int)offset);
    144         break;
    145     }
    146 }
    147 
    148 static void l2x0_priv_reset(DeviceState *dev)
    149 {
    150     L2x0State *s = ARM_L2X0(dev);
    151 
    152     s->ctrl = 0;
    153     s->aux_ctrl = 0x02020000;
    154     s->tag_ctrl = 0;
    155     s->data_ctrl = 0;
    156     s->filter_start = 0;
    157     s->filter_end = 0;
    158 }
    159 
    160 static const MemoryRegionOps l2x0_mem_ops = {
    161     .read = l2x0_priv_read,
    162     .write = l2x0_priv_write,
    163     .endianness = DEVICE_NATIVE_ENDIAN,
    164  };
    165 
    166 static void l2x0_priv_init(Object *obj)
    167 {
    168     L2x0State *s = ARM_L2X0(obj);
    169     SysBusDevice *dev = SYS_BUS_DEVICE(obj);
    170 
    171     memory_region_init_io(&s->iomem, obj, &l2x0_mem_ops, s,
    172                           "l2x0_cc", 0x1000);
    173     sysbus_init_mmio(dev, &s->iomem);
    174 }
    175 
    176 static Property l2x0_properties[] = {
    177     DEFINE_PROP_UINT32("cache-type", L2x0State, cache_type, 0x1c100100),
    178     DEFINE_PROP_END_OF_LIST(),
    179 };
    180 
    181 static void l2x0_class_init(ObjectClass *klass, void *data)
    182 {
    183     DeviceClass *dc = DEVICE_CLASS(klass);
    184 
    185     dc->vmsd = &vmstate_l2x0;
    186     device_class_set_props(dc, l2x0_properties);
    187     dc->reset = l2x0_priv_reset;
    188 }
    189 
    190 static const TypeInfo l2x0_info = {
    191     .name = TYPE_ARM_L2X0,
    192     .parent = TYPE_SYS_BUS_DEVICE,
    193     .instance_size = sizeof(L2x0State),
    194     .instance_init = l2x0_priv_init,
    195     .class_init = l2x0_class_init,
    196 };
    197 
    198 static void l2x0_register_types(void)
    199 {
    200     type_register_static(&l2x0_info);
    201 }
    202 
    203 type_init(l2x0_register_types)