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 "hw/hw.h" 20 #include "qemu/error-report.h" 21 #include "qemu/module.h" 22 #include "sysemu/dma.h" 23 #include "hw/ide/internal.h" 24 #include "migration/vmstate.h" 25 #include "ahci_internal.h" 26 27 #include "trace.h" 28 29 #define ALLWINNER_AHCI(obj) \ 30 OBJECT_CHECK(AllwinnerAHCIState, (obj), TYPE_ALLWINNER_AHCI) 31 32 #define ALLWINNER_AHCI_BISTAFR ((0xa0 - ALLWINNER_AHCI_MMIO_OFF) / 4) 33 #define ALLWINNER_AHCI_BISTCR ((0xa4 - ALLWINNER_AHCI_MMIO_OFF) / 4) 34 #define ALLWINNER_AHCI_BISTFCTR ((0xa8 - ALLWINNER_AHCI_MMIO_OFF) / 4) 35 #define ALLWINNER_AHCI_BISTSR ((0xac - ALLWINNER_AHCI_MMIO_OFF) / 4) 36 #define ALLWINNER_AHCI_BISTDECR ((0xb0 - ALLWINNER_AHCI_MMIO_OFF) / 4) 37 #define ALLWINNER_AHCI_DIAGNR0 ((0xb4 - ALLWINNER_AHCI_MMIO_OFF) / 4) 38 #define ALLWINNER_AHCI_DIAGNR1 ((0xb8 - ALLWINNER_AHCI_MMIO_OFF) / 4) 39 #define ALLWINNER_AHCI_OOBR ((0xbc - ALLWINNER_AHCI_MMIO_OFF) / 4) 40 #define ALLWINNER_AHCI_PHYCS0R ((0xc0 - ALLWINNER_AHCI_MMIO_OFF) / 4) 41 #define ALLWINNER_AHCI_PHYCS1R ((0xc4 - ALLWINNER_AHCI_MMIO_OFF) / 4) 42 #define ALLWINNER_AHCI_PHYCS2R ((0xc8 - ALLWINNER_AHCI_MMIO_OFF) / 4) 43 #define ALLWINNER_AHCI_TIMER1MS ((0xe0 - ALLWINNER_AHCI_MMIO_OFF) / 4) 44 #define ALLWINNER_AHCI_GPARAM1R ((0xe8 - ALLWINNER_AHCI_MMIO_OFF) / 4) 45 #define ALLWINNER_AHCI_GPARAM2R ((0xec - ALLWINNER_AHCI_MMIO_OFF) / 4) 46 #define ALLWINNER_AHCI_PPARAMR ((0xf0 - ALLWINNER_AHCI_MMIO_OFF) / 4) 47 #define ALLWINNER_AHCI_TESTR ((0xf4 - ALLWINNER_AHCI_MMIO_OFF) / 4) 48 #define ALLWINNER_AHCI_VERSIONR ((0xf8 - ALLWINNER_AHCI_MMIO_OFF) / 4) 49 #define ALLWINNER_AHCI_IDR ((0xfc - ALLWINNER_AHCI_MMIO_OFF) / 4) 50 #define ALLWINNER_AHCI_RWCR ((0xfc - ALLWINNER_AHCI_MMIO_OFF) / 4) 51 52 static uint64_t allwinner_ahci_mem_read(void *opaque, hwaddr addr, 53 unsigned size) 54 { 55 AllwinnerAHCIState *a = opaque; 56 AHCIState *s = &(SYSBUS_AHCI(a)->ahci); 57 uint64_t val = a->regs[addr / 4]; 58 59 switch (addr / 4) { 60 case ALLWINNER_AHCI_PHYCS0R: 61 val |= 0x2 << 28; 62 break; 63 case ALLWINNER_AHCI_PHYCS2R: 64 val &= ~(0x1 << 24); 65 break; 66 } 67 trace_allwinner_ahci_mem_read(s, a, addr, val, size); 68 return val; 69 } 70 71 static void allwinner_ahci_mem_write(void *opaque, hwaddr addr, 72 uint64_t val, unsigned size) 73 { 74 AllwinnerAHCIState *a = opaque; 75 AHCIState *s = &(SYSBUS_AHCI(a)->ahci); 76 77 trace_allwinner_ahci_mem_write(s, a, addr, val, size); 78 a->regs[addr / 4] = val; 79 } 80 81 static const MemoryRegionOps allwinner_ahci_mem_ops = { 82 .read = allwinner_ahci_mem_read, 83 .write = allwinner_ahci_mem_write, 84 .valid.min_access_size = 4, 85 .valid.max_access_size = 4, 86 .endianness = DEVICE_LITTLE_ENDIAN, 87 }; 88 89 static void allwinner_ahci_init(Object *obj) 90 { 91 SysbusAHCIState *s = SYSBUS_AHCI(obj); 92 AllwinnerAHCIState *a = ALLWINNER_AHCI(obj); 93 94 memory_region_init_io(&a->mmio, OBJECT(obj), &allwinner_ahci_mem_ops, a, 95 "allwinner-ahci", ALLWINNER_AHCI_MMIO_SIZE); 96 memory_region_add_subregion(&s->ahci.mem, ALLWINNER_AHCI_MMIO_OFF, 97 &a->mmio); 98 } 99 100 static const VMStateDescription vmstate_allwinner_ahci = { 101 .name = "allwinner-ahci", 102 .version_id = 1, 103 .minimum_version_id = 1, 104 .fields = (VMStateField[]) { 105 VMSTATE_UINT32_ARRAY(regs, AllwinnerAHCIState, 106 ALLWINNER_AHCI_MMIO_SIZE / 4), 107 VMSTATE_END_OF_LIST() 108 } 109 }; 110 111 static void allwinner_ahci_class_init(ObjectClass *klass, void *data) 112 { 113 DeviceClass *dc = DEVICE_CLASS(klass); 114 115 dc->vmsd = &vmstate_allwinner_ahci; 116 } 117 118 static const TypeInfo allwinner_ahci_info = { 119 .name = TYPE_ALLWINNER_AHCI, 120 .parent = TYPE_SYSBUS_AHCI, 121 .instance_size = sizeof(AllwinnerAHCIState), 122 .instance_init = allwinner_ahci_init, 123 .class_init = allwinner_ahci_class_init, 124 }; 125 126 static void sysbus_ahci_register_types(void) 127 { 128 type_register_static(&allwinner_ahci_info); 129 } 130 131 type_init(sysbus_ahci_register_types) 132