|
|
1.1 ! root 1: /* ! 2: * QEMU model of the Milkymist High Performance Dynamic Memory Controller. ! 3: * ! 4: * Copyright (c) 2010 Michael Walle <[email protected]> ! 5: * ! 6: * This library is free software; you can redistribute it and/or ! 7: * modify it under the terms of the GNU Lesser General Public ! 8: * License as published by the Free Software Foundation; either ! 9: * version 2 of the License, or (at your option) any later version. ! 10: * ! 11: * This library is distributed in the hope that it will be useful, ! 12: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 14: * Lesser General Public License for more details. ! 15: * ! 16: * You should have received a copy of the GNU Lesser General Public ! 17: * License along with this library; if not, see <http://www.gnu.org/licenses/>. ! 18: * ! 19: * ! 20: * Specification available at: ! 21: * http://www.milkymist.org/socdoc/hpdmc.pdf ! 22: */ ! 23: ! 24: #include "hw.h" ! 25: #include "sysbus.h" ! 26: #include "trace.h" ! 27: #include "qemu-error.h" ! 28: ! 29: enum { ! 30: R_SYSTEM = 0, ! 31: R_BYPASS, ! 32: R_TIMING, ! 33: R_IODELAY, ! 34: R_MAX ! 35: }; ! 36: ! 37: enum { ! 38: IODELAY_DQSDELAY_RDY = (1<<5), ! 39: IODELAY_PLL1_LOCKED = (1<<6), ! 40: IODELAY_PLL2_LOCKED = (1<<7), ! 41: }; ! 42: ! 43: struct MilkymistHpdmcState { ! 44: SysBusDevice busdev; ! 45: ! 46: uint32_t regs[R_MAX]; ! 47: }; ! 48: typedef struct MilkymistHpdmcState MilkymistHpdmcState; ! 49: ! 50: static uint32_t hpdmc_read(void *opaque, target_phys_addr_t addr) ! 51: { ! 52: MilkymistHpdmcState *s = opaque; ! 53: uint32_t r = 0; ! 54: ! 55: addr >>= 2; ! 56: switch (addr) { ! 57: case R_SYSTEM: ! 58: case R_BYPASS: ! 59: case R_TIMING: ! 60: case R_IODELAY: ! 61: r = s->regs[addr]; ! 62: break; ! 63: ! 64: default: ! 65: error_report("milkymist_hpdmc: read access to unknown register 0x" ! 66: TARGET_FMT_plx, addr << 2); ! 67: break; ! 68: } ! 69: ! 70: trace_milkymist_hpdmc_memory_read(addr << 2, r); ! 71: ! 72: return r; ! 73: } ! 74: ! 75: static void hpdmc_write(void *opaque, target_phys_addr_t addr, uint32_t value) ! 76: { ! 77: MilkymistHpdmcState *s = opaque; ! 78: ! 79: trace_milkymist_hpdmc_memory_write(addr, value); ! 80: ! 81: addr >>= 2; ! 82: switch (addr) { ! 83: case R_SYSTEM: ! 84: case R_BYPASS: ! 85: case R_TIMING: ! 86: s->regs[addr] = value; ! 87: break; ! 88: case R_IODELAY: ! 89: /* ignore writes */ ! 90: break; ! 91: ! 92: default: ! 93: error_report("milkymist_hpdmc: write access to unknown register 0x" ! 94: TARGET_FMT_plx, addr << 2); ! 95: break; ! 96: } ! 97: } ! 98: ! 99: static CPUReadMemoryFunc * const hpdmc_read_fn[] = { ! 100: NULL, ! 101: NULL, ! 102: &hpdmc_read, ! 103: }; ! 104: ! 105: static CPUWriteMemoryFunc * const hpdmc_write_fn[] = { ! 106: NULL, ! 107: NULL, ! 108: &hpdmc_write, ! 109: }; ! 110: ! 111: static void milkymist_hpdmc_reset(DeviceState *d) ! 112: { ! 113: MilkymistHpdmcState *s = container_of(d, MilkymistHpdmcState, busdev.qdev); ! 114: int i; ! 115: ! 116: for (i = 0; i < R_MAX; i++) { ! 117: s->regs[i] = 0; ! 118: } ! 119: ! 120: /* defaults */ ! 121: s->regs[R_IODELAY] = IODELAY_DQSDELAY_RDY | IODELAY_PLL1_LOCKED ! 122: | IODELAY_PLL2_LOCKED; ! 123: } ! 124: ! 125: static int milkymist_hpdmc_init(SysBusDevice *dev) ! 126: { ! 127: MilkymistHpdmcState *s = FROM_SYSBUS(typeof(*s), dev); ! 128: int hpdmc_regs; ! 129: ! 130: hpdmc_regs = cpu_register_io_memory(hpdmc_read_fn, hpdmc_write_fn, s, ! 131: DEVICE_NATIVE_ENDIAN); ! 132: sysbus_init_mmio(dev, R_MAX * 4, hpdmc_regs); ! 133: ! 134: return 0; ! 135: } ! 136: ! 137: static const VMStateDescription vmstate_milkymist_hpdmc = { ! 138: .name = "milkymist-hpdmc", ! 139: .version_id = 1, ! 140: .minimum_version_id = 1, ! 141: .minimum_version_id_old = 1, ! 142: .fields = (VMStateField[]) { ! 143: VMSTATE_UINT32_ARRAY(regs, MilkymistHpdmcState, R_MAX), ! 144: VMSTATE_END_OF_LIST() ! 145: } ! 146: }; ! 147: ! 148: static SysBusDeviceInfo milkymist_hpdmc_info = { ! 149: .init = milkymist_hpdmc_init, ! 150: .qdev.name = "milkymist-hpdmc", ! 151: .qdev.size = sizeof(MilkymistHpdmcState), ! 152: .qdev.vmsd = &vmstate_milkymist_hpdmc, ! 153: .qdev.reset = milkymist_hpdmc_reset, ! 154: }; ! 155: ! 156: static void milkymist_hpdmc_register(void) ! 157: { ! 158: sysbus_register_withprop(&milkymist_hpdmc_info); ! 159: } ! 160: ! 161: device_init(milkymist_hpdmc_register)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.