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