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