1 /* 2 * QEMU Allwinner AHCI Emulation 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include "qemu/osdep.h" 19 #include "qemu/error-report.h" 20 #include "qemu/module.h" 21 #include "sysemu/dma.h" 22 #include "hw/ide/internal.h" 23 #include "migration/vmstate.h" 24 #include "ahci_internal.h" 25 26 #include "trace.h" 27 28 #define ALLWINNER_AHCI(obj) \ 29 OBJECT_CHECK(AllwinnerAHCIState, (obj), TYPE_ALLWINNER_AHCI) 30 31 #define ALLWINNER_AHCI_BISTAFR ((0xa0 - ALLWINNER_AHCI_MMIO_OFF) / 4) 32 #define ALLWINNER_AHCI_BISTCR ((0xa4 - ALLWINNER_AHCI_MMIO_OFF) / 4) 33 #define ALLWINNER_AHCI_BISTFCTR ((0xa8 - ALLWINNER_AHCI_MMIO_OFF) / 4) 34 #define ALLWINNER_AHCI_BISTSR ((0xac - ALLWINNER_AHCI_MMIO_OFF) / 4) 35 #define ALLWINNER_AHCI_BISTDECR ((0xb0 - ALLWINNER_AHCI_MMIO_OFF) / 4) 36 #define ALLWINNER_AHCI_DIAGNR0 ((0xb4 - ALLWINNER_AHCI_MMIO_OFF) / 4) 37 #define ALLWINNER_AHCI_DIAGNR1 ((0xb8 - ALLWINNER_AHCI_MMIO_OFF) / 4) 38 #define ALLWINNER_AHCI_OOBR ((0xbc - ALLWINNER_AHCI_MMIO_OFF) / 4) 39 #define ALLWINNER_AHCI_PHYCS0R ((0xc0 - ALLWINNER_AHCI_MMIO_OFF) / 4) 40 #define ALLWINNER_AHCI_PHYCS1R ((0xc4 - ALLWINNER_AHCI_MMIO_OFF) / 4) 41 #define ALLWINNER_AHCI_PHYCS2R ((0xc8 - ALLWINNER_AHCI_MMIO_OFF) / 4) 42 #define ALLWINNER_AHCI_TIMER1MS ((0xe0 - ALLWINNER_AHCI_MMIO_OFF) / 4) 43 #define ALLWINNER_AHCI_GPARAM1R ((0xe8 - ALLWINNER_AHCI_MMIO_OFF) / 4) 44 #define ALLWINNER_AHCI_GPARAM2R ((0xec - ALLWINNER_AHCI_MMIO_OFF) / 4) 45 #define ALLWINNER_AHCI_PPARAMR ((0xf0 - ALLWINNER_AHCI_MMIO_OFF) / 4) 46 #define ALLWINNER_AHCI_TESTR ((0xf4 - ALLWINNER_AHCI_MMIO_OFF) / 4) 47 #define ALLWINNER_AHCI_VERSIONR ((0xf8 - ALLWINNER_AHCI_MMIO_OFF) / 4) 48 #define ALLWINNER_AHCI_IDR ((0xfc - ALLWINNER_AHCI_MMIO_OFF) / 4) 49 #define ALLWINNER_AHCI_RWCR ((0xfc - ALLWINNER_AHCI_MMIO_OFF) / 4) 50 51 static uint64_t allwinner_ahci_mem_read(void *opaque, hwaddr addr, 52 unsigned size) 53 { 54 AllwinnerAHCIState *a = opaque; 55 AHCIState *s = &(SYSBUS_AHCI(a)->ahci); 56 uint64_t val = a->regs[addr / 4]; 57 58 switch (addr / 4) { 59 case ALLWINNER_AHCI_PHYCS0R: 60 val |= 0x2 << 28; 61 break; 62 case ALLWINNER_AHCI_PHYCS2R: 63 val &= ~(0x1 << 24); 64 break; 65 } 66 trace_allwinner_ahci_mem_read(s, a, addr, val, size); 67 return val; 68 } 69 70 static void allwinner_ahci_mem_write(void *opaque, hwaddr addr, 71 uint64_t val, unsigned size) 72 { 73 AllwinnerAHCIState *a = opaque; 74 AHCIState *s = &(SYSBUS_AHCI(a)->ahci); 75 76 trace_allwinner_ahci_mem_write(s, a, addr, val, size); 77 a->regs[addr / 4] = val; 78 } 79 80 static const MemoryRegionOps allwinner_ahci_mem_ops = { 81 .read = allwinner_ahci_mem_read, 82 .write = allwinner_ahci_mem_write, 83 .valid.min_access_size = 4, 84 .valid.max_access_size = 4, 85 .endianness = DEVICE_LITTLE_ENDIAN, 86 }; 87 88 static void allwinner_ahci_init(Object *obj) 89 { 90 SysbusAHCIState *s = SYSBUS_AHCI(obj); 91 AllwinnerAHCIState *a = ALLWINNER_AHCI(obj); 92 93 memory_region_init_io(&a->mmio, obj, &allwinner_ahci_mem_ops, a, 94 "allwinner-ahci", ALLWINNER_AHCI_MMIO_SIZE); 95 memory_region_add_subregion(&s->ahci.mem, ALLWINNER_AHCI_MMIO_OFF, 96 &a->mmio); 97 } 98 99 static const VMStateDescription vmstate_allwinner_ahci = { 100 .name = "allwinner-ahci", 101 .version_id = 1, 102 .minimum_version_id = 1, 103 .fields = (VMStateField[]) { 104 VMSTATE_UINT32_ARRAY(regs, AllwinnerAHCIState, 105 ALLWINNER_AHCI_MMIO_SIZE / 4), 106 VMSTATE_END_OF_LIST() 107 } 108 }; 109 110 static void allwinner_ahci_class_init(ObjectClass *klass, void *data) 111 { 112 DeviceClass *dc = DEVICE_CLASS(klass); 113 114 dc->vmsd = &vmstate_allwinner_ahci; 115 } 116 117 static const TypeInfo allwinner_ahci_info = { 118 .name = TYPE_ALLWINNER_AHCI, 119 .parent = TYPE_SYSBUS_AHCI, 120 .instance_size = sizeof(AllwinnerAHCIState), 121 .instance_init = allwinner_ahci_init, 122 .class_init = allwinner_ahci_class_init, 123 }; 124 125 static void sysbus_ahci_register_types(void) 126 { 127 type_register_static(&allwinner_ahci_info); 128 } 129 130 type_init(sysbus_ahci_register_types) 131