12585c679SThomas Huth /* 22585c679SThomas Huth * QEMU Allwinner AHCI Emulation 32585c679SThomas Huth * 42585c679SThomas Huth * This program is free software; you can redistribute it and/or 52585c679SThomas Huth * modify it under the terms of the GNU General Public License 62585c679SThomas Huth * as published by the Free Software Foundation; either version 2 72585c679SThomas Huth * of the License, or (at your option) any later version. 82585c679SThomas Huth * 92585c679SThomas Huth * This program is distributed in the hope that it will be useful, 102585c679SThomas Huth * but WITHOUT ANY WARRANTY; without even the implied warranty of 112585c679SThomas Huth * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 122585c679SThomas Huth * GNU General Public License for more details. 132585c679SThomas Huth * 142585c679SThomas Huth * You should have received a copy of the GNU General Public License 152585c679SThomas Huth * along with this program; if not, see <http://www.gnu.org/licenses/>. 162585c679SThomas Huth */ 172585c679SThomas Huth 182585c679SThomas Huth #include "qemu/osdep.h" 192585c679SThomas Huth #include "hw/hw.h" 202585c679SThomas Huth #include "qemu/error-report.h" 21*0b8fa32fSMarkus Armbruster #include "qemu/module.h" 222585c679SThomas Huth #include "sysemu/dma.h" 232585c679SThomas Huth #include "hw/ide/internal.h" 249314b859SMichael S. Tsirkin #include "ahci_internal.h" 252585c679SThomas Huth 262585c679SThomas Huth #include "trace.h" 272585c679SThomas Huth 286b187547SPhilippe Mathieu-Daudé #define ALLWINNER_AHCI(obj) \ 296b187547SPhilippe Mathieu-Daudé OBJECT_CHECK(AllwinnerAHCIState, (obj), TYPE_ALLWINNER_AHCI) 306b187547SPhilippe Mathieu-Daudé 312585c679SThomas Huth #define ALLWINNER_AHCI_BISTAFR ((0xa0 - ALLWINNER_AHCI_MMIO_OFF) / 4) 322585c679SThomas Huth #define ALLWINNER_AHCI_BISTCR ((0xa4 - ALLWINNER_AHCI_MMIO_OFF) / 4) 332585c679SThomas Huth #define ALLWINNER_AHCI_BISTFCTR ((0xa8 - ALLWINNER_AHCI_MMIO_OFF) / 4) 342585c679SThomas Huth #define ALLWINNER_AHCI_BISTSR ((0xac - ALLWINNER_AHCI_MMIO_OFF) / 4) 352585c679SThomas Huth #define ALLWINNER_AHCI_BISTDECR ((0xb0 - ALLWINNER_AHCI_MMIO_OFF) / 4) 362585c679SThomas Huth #define ALLWINNER_AHCI_DIAGNR0 ((0xb4 - ALLWINNER_AHCI_MMIO_OFF) / 4) 372585c679SThomas Huth #define ALLWINNER_AHCI_DIAGNR1 ((0xb8 - ALLWINNER_AHCI_MMIO_OFF) / 4) 382585c679SThomas Huth #define ALLWINNER_AHCI_OOBR ((0xbc - ALLWINNER_AHCI_MMIO_OFF) / 4) 392585c679SThomas Huth #define ALLWINNER_AHCI_PHYCS0R ((0xc0 - ALLWINNER_AHCI_MMIO_OFF) / 4) 402585c679SThomas Huth #define ALLWINNER_AHCI_PHYCS1R ((0xc4 - ALLWINNER_AHCI_MMIO_OFF) / 4) 412585c679SThomas Huth #define ALLWINNER_AHCI_PHYCS2R ((0xc8 - ALLWINNER_AHCI_MMIO_OFF) / 4) 422585c679SThomas Huth #define ALLWINNER_AHCI_TIMER1MS ((0xe0 - ALLWINNER_AHCI_MMIO_OFF) / 4) 432585c679SThomas Huth #define ALLWINNER_AHCI_GPARAM1R ((0xe8 - ALLWINNER_AHCI_MMIO_OFF) / 4) 442585c679SThomas Huth #define ALLWINNER_AHCI_GPARAM2R ((0xec - ALLWINNER_AHCI_MMIO_OFF) / 4) 452585c679SThomas Huth #define ALLWINNER_AHCI_PPARAMR ((0xf0 - ALLWINNER_AHCI_MMIO_OFF) / 4) 462585c679SThomas Huth #define ALLWINNER_AHCI_TESTR ((0xf4 - ALLWINNER_AHCI_MMIO_OFF) / 4) 472585c679SThomas Huth #define ALLWINNER_AHCI_VERSIONR ((0xf8 - ALLWINNER_AHCI_MMIO_OFF) / 4) 482585c679SThomas Huth #define ALLWINNER_AHCI_IDR ((0xfc - ALLWINNER_AHCI_MMIO_OFF) / 4) 492585c679SThomas Huth #define ALLWINNER_AHCI_RWCR ((0xfc - ALLWINNER_AHCI_MMIO_OFF) / 4) 502585c679SThomas Huth 512585c679SThomas Huth static uint64_t allwinner_ahci_mem_read(void *opaque, hwaddr addr, 522585c679SThomas Huth unsigned size) 532585c679SThomas Huth { 542585c679SThomas Huth AllwinnerAHCIState *a = opaque; 552585c679SThomas Huth AHCIState *s = &(SYSBUS_AHCI(a)->ahci); 562585c679SThomas Huth uint64_t val = a->regs[addr / 4]; 572585c679SThomas Huth 582585c679SThomas Huth switch (addr / 4) { 592585c679SThomas Huth case ALLWINNER_AHCI_PHYCS0R: 602585c679SThomas Huth val |= 0x2 << 28; 612585c679SThomas Huth break; 622585c679SThomas Huth case ALLWINNER_AHCI_PHYCS2R: 632585c679SThomas Huth val &= ~(0x1 << 24); 642585c679SThomas Huth break; 652585c679SThomas Huth } 662585c679SThomas Huth trace_allwinner_ahci_mem_read(s, a, addr, val, size); 672585c679SThomas Huth return val; 682585c679SThomas Huth } 692585c679SThomas Huth 702585c679SThomas Huth static void allwinner_ahci_mem_write(void *opaque, hwaddr addr, 712585c679SThomas Huth uint64_t val, unsigned size) 722585c679SThomas Huth { 732585c679SThomas Huth AllwinnerAHCIState *a = opaque; 742585c679SThomas Huth AHCIState *s = &(SYSBUS_AHCI(a)->ahci); 752585c679SThomas Huth 762585c679SThomas Huth trace_allwinner_ahci_mem_write(s, a, addr, val, size); 772585c679SThomas Huth a->regs[addr / 4] = val; 782585c679SThomas Huth } 792585c679SThomas Huth 802585c679SThomas Huth static const MemoryRegionOps allwinner_ahci_mem_ops = { 812585c679SThomas Huth .read = allwinner_ahci_mem_read, 822585c679SThomas Huth .write = allwinner_ahci_mem_write, 832585c679SThomas Huth .valid.min_access_size = 4, 842585c679SThomas Huth .valid.max_access_size = 4, 852585c679SThomas Huth .endianness = DEVICE_LITTLE_ENDIAN, 862585c679SThomas Huth }; 872585c679SThomas Huth 882585c679SThomas Huth static void allwinner_ahci_init(Object *obj) 892585c679SThomas Huth { 902585c679SThomas Huth SysbusAHCIState *s = SYSBUS_AHCI(obj); 912585c679SThomas Huth AllwinnerAHCIState *a = ALLWINNER_AHCI(obj); 922585c679SThomas Huth 932585c679SThomas Huth memory_region_init_io(&a->mmio, OBJECT(obj), &allwinner_ahci_mem_ops, a, 942585c679SThomas Huth "allwinner-ahci", ALLWINNER_AHCI_MMIO_SIZE); 952585c679SThomas Huth memory_region_add_subregion(&s->ahci.mem, ALLWINNER_AHCI_MMIO_OFF, 962585c679SThomas Huth &a->mmio); 972585c679SThomas Huth } 982585c679SThomas Huth 992585c679SThomas Huth static const VMStateDescription vmstate_allwinner_ahci = { 1002585c679SThomas Huth .name = "allwinner-ahci", 1012585c679SThomas Huth .version_id = 1, 1022585c679SThomas Huth .minimum_version_id = 1, 1032585c679SThomas Huth .fields = (VMStateField[]) { 1042585c679SThomas Huth VMSTATE_UINT32_ARRAY(regs, AllwinnerAHCIState, 1052585c679SThomas Huth ALLWINNER_AHCI_MMIO_SIZE / 4), 1062585c679SThomas Huth VMSTATE_END_OF_LIST() 1072585c679SThomas Huth } 1082585c679SThomas Huth }; 1092585c679SThomas Huth 1102585c679SThomas Huth static void allwinner_ahci_class_init(ObjectClass *klass, void *data) 1112585c679SThomas Huth { 1122585c679SThomas Huth DeviceClass *dc = DEVICE_CLASS(klass); 1132585c679SThomas Huth 1142585c679SThomas Huth dc->vmsd = &vmstate_allwinner_ahci; 1152585c679SThomas Huth } 1162585c679SThomas Huth 1172585c679SThomas Huth static const TypeInfo allwinner_ahci_info = { 1182585c679SThomas Huth .name = TYPE_ALLWINNER_AHCI, 1192585c679SThomas Huth .parent = TYPE_SYSBUS_AHCI, 1202585c679SThomas Huth .instance_size = sizeof(AllwinnerAHCIState), 1212585c679SThomas Huth .instance_init = allwinner_ahci_init, 1222585c679SThomas Huth .class_init = allwinner_ahci_class_init, 1232585c679SThomas Huth }; 1242585c679SThomas Huth 1252585c679SThomas Huth static void sysbus_ahci_register_types(void) 1262585c679SThomas Huth { 1272585c679SThomas Huth type_register_static(&allwinner_ahci_info); 1282585c679SThomas Huth } 1292585c679SThomas Huth 1302585c679SThomas Huth type_init(sysbus_ahci_register_types) 131