|
|
1.1 ! root 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 "sysbus.h" ! 22: ! 23: /* L2C-310 r3p2 */ ! 24: #define CACHE_ID 0x410000c8 ! 25: ! 26: typedef struct l2x0_state { ! 27: SysBusDevice busdev; ! 28: MemoryRegion iomem; ! 29: uint32_t cache_type; ! 30: uint32_t ctrl; ! 31: uint32_t aux_ctrl; ! 32: uint32_t data_ctrl; ! 33: uint32_t tag_ctrl; ! 34: uint32_t filter_start; ! 35: uint32_t filter_end; ! 36: } l2x0_state; ! 37: ! 38: static const VMStateDescription vmstate_l2x0 = { ! 39: .name = "l2x0", ! 40: .version_id = 1, ! 41: .minimum_version_id = 1, ! 42: .fields = (VMStateField[]) { ! 43: VMSTATE_UINT32(ctrl, l2x0_state), ! 44: VMSTATE_UINT32(aux_ctrl, l2x0_state), ! 45: VMSTATE_UINT32(data_ctrl, l2x0_state), ! 46: VMSTATE_UINT32(tag_ctrl, l2x0_state), ! 47: VMSTATE_UINT32(filter_start, l2x0_state), ! 48: VMSTATE_UINT32(filter_end, l2x0_state), ! 49: VMSTATE_END_OF_LIST() ! 50: } ! 51: }; ! 52: ! 53: ! 54: static uint64_t l2x0_priv_read(void *opaque, target_phys_addr_t offset, ! 55: unsigned size) ! 56: { ! 57: uint32_t cache_data; ! 58: l2x0_state *s = (l2x0_state *)opaque; ! 59: offset &= 0xfff; ! 60: if (offset >= 0x730 && offset < 0x800) { ! 61: return 0; /* cache ops complete */ ! 62: } ! 63: switch (offset) { ! 64: case 0: ! 65: return CACHE_ID; ! 66: case 0x4: ! 67: /* aux_ctrl values affect cache_type values */ ! 68: cache_data = (s->aux_ctrl & (7 << 17)) >> 15; ! 69: cache_data |= (s->aux_ctrl & (1 << 16)) >> 16; ! 70: return s->cache_type |= (cache_data << 18) | (cache_data << 6); ! 71: case 0x100: ! 72: return s->ctrl; ! 73: case 0x104: ! 74: return s->aux_ctrl; ! 75: case 0x108: ! 76: return s->tag_ctrl; ! 77: case 0x10C: ! 78: return s->data_ctrl; ! 79: case 0xC00: ! 80: return s->filter_start; ! 81: case 0xC04: ! 82: return s->filter_end; ! 83: case 0xF40: ! 84: return 0; ! 85: case 0xF60: ! 86: return 0; ! 87: case 0xF80: ! 88: return 0; ! 89: default: ! 90: fprintf(stderr, "l2x0_priv_read: Bad offset %x\n", (int)offset); ! 91: break; ! 92: } ! 93: return 0; ! 94: } ! 95: ! 96: static void l2x0_priv_write(void *opaque, target_phys_addr_t offset, ! 97: uint64_t value, unsigned size) ! 98: { ! 99: l2x0_state *s = (l2x0_state *)opaque; ! 100: offset &= 0xfff; ! 101: if (offset >= 0x730 && offset < 0x800) { ! 102: /* ignore */ ! 103: return; ! 104: } ! 105: switch (offset) { ! 106: case 0x100: ! 107: s->ctrl = value & 1; ! 108: break; ! 109: case 0x104: ! 110: s->aux_ctrl = value; ! 111: break; ! 112: case 0x108: ! 113: s->tag_ctrl = value; ! 114: break; ! 115: case 0x10C: ! 116: s->data_ctrl = value; ! 117: break; ! 118: case 0xC00: ! 119: s->filter_start = value; ! 120: break; ! 121: case 0xC04: ! 122: s->filter_end = value; ! 123: break; ! 124: case 0xF40: ! 125: return; ! 126: case 0xF60: ! 127: return; ! 128: case 0xF80: ! 129: return; ! 130: default: ! 131: fprintf(stderr, "l2x0_priv_write: Bad offset %x\n", (int)offset); ! 132: break; ! 133: } ! 134: } ! 135: ! 136: static void l2x0_priv_reset(DeviceState *dev) ! 137: { ! 138: l2x0_state *s = DO_UPCAST(l2x0_state, busdev.qdev, dev); ! 139: ! 140: s->ctrl = 0; ! 141: s->aux_ctrl = 0x02020000; ! 142: s->tag_ctrl = 0; ! 143: s->data_ctrl = 0; ! 144: s->filter_start = 0; ! 145: s->filter_end = 0; ! 146: } ! 147: ! 148: static const MemoryRegionOps l2x0_mem_ops = { ! 149: .read = l2x0_priv_read, ! 150: .write = l2x0_priv_write, ! 151: .endianness = DEVICE_NATIVE_ENDIAN, ! 152: }; ! 153: ! 154: static int l2x0_priv_init(SysBusDevice *dev) ! 155: { ! 156: l2x0_state *s = FROM_SYSBUS(l2x0_state, dev); ! 157: ! 158: memory_region_init_io(&s->iomem, &l2x0_mem_ops, s, "l2x0_cc", 0x1000); ! 159: sysbus_init_mmio(dev, &s->iomem); ! 160: return 0; ! 161: } ! 162: ! 163: static Property l2x0_properties[] = { ! 164: DEFINE_PROP_UINT32("type", l2x0_state, cache_type, 0x1c100100), ! 165: DEFINE_PROP_END_OF_LIST(), ! 166: }; ! 167: ! 168: static void l2x0_class_init(ObjectClass *klass, void *data) ! 169: { ! 170: SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); ! 171: DeviceClass *dc = DEVICE_CLASS(klass); ! 172: ! 173: k->init = l2x0_priv_init; ! 174: dc->vmsd = &vmstate_l2x0; ! 175: dc->no_user = 1; ! 176: dc->props = l2x0_properties; ! 177: dc->reset = l2x0_priv_reset; ! 178: } ! 179: ! 180: static TypeInfo l2x0_info = { ! 181: .name = "l2x0", ! 182: .parent = TYPE_SYS_BUS_DEVICE, ! 183: .instance_size = sizeof(l2x0_state), ! 184: .class_init = l2x0_class_init, ! 185: }; ! 186: ! 187: static void l2x0_register_types(void) ! 188: { ! 189: type_register_static(&l2x0_info); ! 190: } ! 191: ! 192: type_init(l2x0_register_types)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.