1db3e6379SDeniz Eren /* 2db3e6379SDeniz Eren * MIOe-3680 PCI CAN device (SJA1000 based) emulation 3db3e6379SDeniz Eren * 4db3e6379SDeniz Eren * Copyright (c) 2016 Deniz Eren (deniz.eren@icloud.com) 5db3e6379SDeniz Eren * 6db3e6379SDeniz Eren * Based on Kvaser PCI CAN device (SJA1000 based) emulation implemented by 7db3e6379SDeniz Eren * Jin Yang and Pavel Pisa 8db3e6379SDeniz Eren * 9db3e6379SDeniz Eren * Permission is hereby granted, free of charge, to any person obtaining a copy 10db3e6379SDeniz Eren * of this software and associated documentation files (the "Software"), to deal 11db3e6379SDeniz Eren * in the Software without restriction, including without limitation the rights 12db3e6379SDeniz Eren * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13db3e6379SDeniz Eren * copies of the Software, and to permit persons to whom the Software is 14db3e6379SDeniz Eren * furnished to do so, subject to the following conditions: 15db3e6379SDeniz Eren * 16db3e6379SDeniz Eren * The above copyright notice and this permission notice shall be included in 17db3e6379SDeniz Eren * all copies or substantial portions of the Software. 18db3e6379SDeniz Eren * 19db3e6379SDeniz Eren * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20db3e6379SDeniz Eren * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21db3e6379SDeniz Eren * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22db3e6379SDeniz Eren * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23db3e6379SDeniz Eren * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24db3e6379SDeniz Eren * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25db3e6379SDeniz Eren * THE SOFTWARE. 26db3e6379SDeniz Eren */ 27db3e6379SDeniz Eren 28db3e6379SDeniz Eren #include "qemu/osdep.h" 29db3e6379SDeniz Eren #include "qemu/event_notifier.h" 300b8fa32fSMarkus Armbruster #include "qemu/module.h" 31db3e6379SDeniz Eren #include "qemu/thread.h" 32db3e6379SDeniz Eren #include "qemu/sockets.h" 33db3e6379SDeniz Eren #include "qapi/error.h" 34db3e6379SDeniz Eren #include "chardev/char.h" 3564552b6bSMarkus Armbruster #include "hw/irq.h" 36db3e6379SDeniz Eren #include "hw/pci/pci.h" 37a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 38d6454270SMarkus Armbruster #include "migration/vmstate.h" 39db3e6379SDeniz Eren #include "net/can_emu.h" 40db3e6379SDeniz Eren 41db3e6379SDeniz Eren #include "can_sja1000.h" 42db3e6379SDeniz Eren 43db3e6379SDeniz Eren #define TYPE_CAN_PCI_DEV "mioe3680_pci" 44db3e6379SDeniz Eren 45db3e6379SDeniz Eren #define MIOe3680_PCI_DEV(obj) \ 46db3e6379SDeniz Eren OBJECT_CHECK(Mioe3680PCIState, (obj), TYPE_CAN_PCI_DEV) 47db3e6379SDeniz Eren 48db3e6379SDeniz Eren /* the PCI device and vendor IDs */ 49db3e6379SDeniz Eren #ifndef MIOe3680_PCI_VENDOR_ID1 50db3e6379SDeniz Eren #define MIOe3680_PCI_VENDOR_ID1 0x13fe 51db3e6379SDeniz Eren #endif 52db3e6379SDeniz Eren 53db3e6379SDeniz Eren #ifndef MIOe3680_PCI_DEVICE_ID1 54db3e6379SDeniz Eren #define MIOe3680_PCI_DEVICE_ID1 0xc302 55db3e6379SDeniz Eren #endif 56db3e6379SDeniz Eren 57db3e6379SDeniz Eren #define MIOe3680_PCI_SJA_COUNT 2 58db3e6379SDeniz Eren #define MIOe3680_PCI_SJA_RANGE 0x400 59db3e6379SDeniz Eren 60db3e6379SDeniz Eren #define MIOe3680_PCI_BYTES_PER_SJA 0x80 61db3e6379SDeniz Eren 62db3e6379SDeniz Eren typedef struct Mioe3680PCIState { 63db3e6379SDeniz Eren /*< private >*/ 64db3e6379SDeniz Eren PCIDevice dev; 65db3e6379SDeniz Eren /*< public >*/ 66db3e6379SDeniz Eren MemoryRegion sja_io[MIOe3680_PCI_SJA_COUNT]; 67db3e6379SDeniz Eren 68db3e6379SDeniz Eren CanSJA1000State sja_state[MIOe3680_PCI_SJA_COUNT]; 69db3e6379SDeniz Eren qemu_irq irq; 70db3e6379SDeniz Eren 71db3e6379SDeniz Eren char *model; /* The model that support, only SJA1000 now. */ 72db3e6379SDeniz Eren CanBusState *canbus[MIOe3680_PCI_SJA_COUNT]; 73db3e6379SDeniz Eren } Mioe3680PCIState; 74db3e6379SDeniz Eren 75db3e6379SDeniz Eren static void mioe3680_pci_reset(DeviceState *dev) 76db3e6379SDeniz Eren { 77db3e6379SDeniz Eren Mioe3680PCIState *d = MIOe3680_PCI_DEV(dev); 78db3e6379SDeniz Eren int i; 79db3e6379SDeniz Eren 80db3e6379SDeniz Eren for (i = 0 ; i < MIOe3680_PCI_SJA_COUNT; i++) { 81db3e6379SDeniz Eren can_sja_hardware_reset(&d->sja_state[i]); 82db3e6379SDeniz Eren } 83db3e6379SDeniz Eren } 84db3e6379SDeniz Eren 85db3e6379SDeniz Eren static uint64_t mioe3680_pci_sja1_io_read(void *opaque, hwaddr addr, 86db3e6379SDeniz Eren unsigned size) 87db3e6379SDeniz Eren { 88db3e6379SDeniz Eren Mioe3680PCIState *d = opaque; 89db3e6379SDeniz Eren CanSJA1000State *s = &d->sja_state[0]; 90db3e6379SDeniz Eren 91db3e6379SDeniz Eren if (addr >= MIOe3680_PCI_BYTES_PER_SJA) { 92db3e6379SDeniz Eren return 0; 93db3e6379SDeniz Eren } 94db3e6379SDeniz Eren 95db3e6379SDeniz Eren return can_sja_mem_read(s, addr >> 2, size); 96db3e6379SDeniz Eren } 97db3e6379SDeniz Eren 98db3e6379SDeniz Eren static void mioe3680_pci_sja1_io_write(void *opaque, hwaddr addr, uint64_t data, 99db3e6379SDeniz Eren unsigned size) 100db3e6379SDeniz Eren { 101db3e6379SDeniz Eren Mioe3680PCIState *d = opaque; 102db3e6379SDeniz Eren CanSJA1000State *s = &d->sja_state[0]; 103db3e6379SDeniz Eren 104db3e6379SDeniz Eren if (addr >= MIOe3680_PCI_BYTES_PER_SJA) { 105db3e6379SDeniz Eren return; 106db3e6379SDeniz Eren } 107db3e6379SDeniz Eren 108db3e6379SDeniz Eren can_sja_mem_write(s, addr >> 2, data, size); 109db3e6379SDeniz Eren } 110db3e6379SDeniz Eren 111db3e6379SDeniz Eren static uint64_t mioe3680_pci_sja2_io_read(void *opaque, hwaddr addr, 112db3e6379SDeniz Eren unsigned size) 113db3e6379SDeniz Eren { 114db3e6379SDeniz Eren Mioe3680PCIState *d = opaque; 115db3e6379SDeniz Eren CanSJA1000State *s = &d->sja_state[1]; 116db3e6379SDeniz Eren 117db3e6379SDeniz Eren if (addr >= MIOe3680_PCI_BYTES_PER_SJA) { 118db3e6379SDeniz Eren return 0; 119db3e6379SDeniz Eren } 120db3e6379SDeniz Eren 121db3e6379SDeniz Eren return can_sja_mem_read(s, addr >> 2, size); 122db3e6379SDeniz Eren } 123db3e6379SDeniz Eren 124db3e6379SDeniz Eren static void mioe3680_pci_sja2_io_write(void *opaque, hwaddr addr, uint64_t data, 125db3e6379SDeniz Eren unsigned size) 126db3e6379SDeniz Eren { 127db3e6379SDeniz Eren Mioe3680PCIState *d = opaque; 128db3e6379SDeniz Eren CanSJA1000State *s = &d->sja_state[1]; 129db3e6379SDeniz Eren 130db3e6379SDeniz Eren if (addr >= MIOe3680_PCI_BYTES_PER_SJA) { 131db3e6379SDeniz Eren return; 132db3e6379SDeniz Eren } 133db3e6379SDeniz Eren 134db3e6379SDeniz Eren can_sja_mem_write(s, addr >> 2, data, size); 135db3e6379SDeniz Eren } 136db3e6379SDeniz Eren 137db3e6379SDeniz Eren static const MemoryRegionOps mioe3680_pci_sja1_io_ops = { 138db3e6379SDeniz Eren .read = mioe3680_pci_sja1_io_read, 139db3e6379SDeniz Eren .write = mioe3680_pci_sja1_io_write, 140db3e6379SDeniz Eren .endianness = DEVICE_LITTLE_ENDIAN, 141db3e6379SDeniz Eren .impl = { 142db3e6379SDeniz Eren .max_access_size = 1, 143db3e6379SDeniz Eren }, 144db3e6379SDeniz Eren }; 145db3e6379SDeniz Eren 146db3e6379SDeniz Eren static const MemoryRegionOps mioe3680_pci_sja2_io_ops = { 147db3e6379SDeniz Eren .read = mioe3680_pci_sja2_io_read, 148db3e6379SDeniz Eren .write = mioe3680_pci_sja2_io_write, 149db3e6379SDeniz Eren .endianness = DEVICE_LITTLE_ENDIAN, 150db3e6379SDeniz Eren .impl = { 151db3e6379SDeniz Eren .max_access_size = 1, 152db3e6379SDeniz Eren }, 153db3e6379SDeniz Eren }; 154db3e6379SDeniz Eren 155db3e6379SDeniz Eren static void mioe3680_pci_realize(PCIDevice *pci_dev, Error **errp) 156db3e6379SDeniz Eren { 157db3e6379SDeniz Eren Mioe3680PCIState *d = MIOe3680_PCI_DEV(pci_dev); 158db3e6379SDeniz Eren uint8_t *pci_conf; 159db3e6379SDeniz Eren int i; 160db3e6379SDeniz Eren 161db3e6379SDeniz Eren pci_conf = pci_dev->config; 162db3e6379SDeniz Eren pci_conf[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */ 163db3e6379SDeniz Eren 164db3e6379SDeniz Eren d->irq = pci_allocate_irq(&d->dev); 165db3e6379SDeniz Eren 166db3e6379SDeniz Eren for (i = 0 ; i < MIOe3680_PCI_SJA_COUNT; i++) { 167db3e6379SDeniz Eren can_sja_init(&d->sja_state[i], d->irq); 168db3e6379SDeniz Eren } 169db3e6379SDeniz Eren 170db3e6379SDeniz Eren for (i = 0 ; i < MIOe3680_PCI_SJA_COUNT; i++) { 171db3e6379SDeniz Eren if (can_sja_connect_to_bus(&d->sja_state[i], d->canbus[i]) < 0) { 172db3e6379SDeniz Eren error_setg(errp, "can_sja_connect_to_bus failed"); 173db3e6379SDeniz Eren return; 174db3e6379SDeniz Eren } 175db3e6379SDeniz Eren } 176db3e6379SDeniz Eren 177db3e6379SDeniz Eren memory_region_init_io(&d->sja_io[0], OBJECT(d), &mioe3680_pci_sja1_io_ops, 178db3e6379SDeniz Eren d, "mioe3680_pci-sja1", MIOe3680_PCI_SJA_RANGE); 179db3e6379SDeniz Eren memory_region_init_io(&d->sja_io[1], OBJECT(d), &mioe3680_pci_sja2_io_ops, 180db3e6379SDeniz Eren d, "mioe3680_pci-sja2", MIOe3680_PCI_SJA_RANGE); 181db3e6379SDeniz Eren 182db3e6379SDeniz Eren for (i = 0 ; i < MIOe3680_PCI_SJA_COUNT; i++) { 183db3e6379SDeniz Eren pci_register_bar(&d->dev, /*BAR*/ i, PCI_BASE_ADDRESS_SPACE_IO, 184db3e6379SDeniz Eren &d->sja_io[i]); 185db3e6379SDeniz Eren } 186db3e6379SDeniz Eren } 187db3e6379SDeniz Eren 188db3e6379SDeniz Eren static void mioe3680_pci_exit(PCIDevice *pci_dev) 189db3e6379SDeniz Eren { 190db3e6379SDeniz Eren Mioe3680PCIState *d = MIOe3680_PCI_DEV(pci_dev); 191db3e6379SDeniz Eren int i; 192db3e6379SDeniz Eren 193db3e6379SDeniz Eren for (i = 0 ; i < MIOe3680_PCI_SJA_COUNT; i++) { 194db3e6379SDeniz Eren can_sja_disconnect(&d->sja_state[i]); 195db3e6379SDeniz Eren } 196db3e6379SDeniz Eren 197db3e6379SDeniz Eren qemu_free_irq(d->irq); 198db3e6379SDeniz Eren } 199db3e6379SDeniz Eren 200db3e6379SDeniz Eren static const VMStateDescription vmstate_mioe3680_pci = { 201db3e6379SDeniz Eren .name = "mioe3680_pci", 202db3e6379SDeniz Eren .version_id = 1, 203db3e6379SDeniz Eren .minimum_version_id = 1, 204db3e6379SDeniz Eren .minimum_version_id_old = 1, 205db3e6379SDeniz Eren .fields = (VMStateField[]) { 206db3e6379SDeniz Eren VMSTATE_PCI_DEVICE(dev, Mioe3680PCIState), 207db3e6379SDeniz Eren VMSTATE_STRUCT(sja_state[0], Mioe3680PCIState, 0, vmstate_can_sja, 208db3e6379SDeniz Eren CanSJA1000State), 209db3e6379SDeniz Eren VMSTATE_STRUCT(sja_state[1], Mioe3680PCIState, 0, vmstate_can_sja, 210db3e6379SDeniz Eren CanSJA1000State), 211db3e6379SDeniz Eren VMSTATE_END_OF_LIST() 212db3e6379SDeniz Eren } 213db3e6379SDeniz Eren }; 214db3e6379SDeniz Eren 215db3e6379SDeniz Eren static void mioe3680_pci_instance_init(Object *obj) 216db3e6379SDeniz Eren { 217db3e6379SDeniz Eren Mioe3680PCIState *d = MIOe3680_PCI_DEV(obj); 218db3e6379SDeniz Eren 219db3e6379SDeniz Eren object_property_add_link(obj, "canbus0", TYPE_CAN_BUS, 220db3e6379SDeniz Eren (Object **)&d->canbus[0], 221db3e6379SDeniz Eren qdev_prop_allow_set_link_before_realize, 222*d2623129SMarkus Armbruster 0); 223db3e6379SDeniz Eren object_property_add_link(obj, "canbus1", TYPE_CAN_BUS, 224db3e6379SDeniz Eren (Object **)&d->canbus[1], 225db3e6379SDeniz Eren qdev_prop_allow_set_link_before_realize, 226*d2623129SMarkus Armbruster 0); 227db3e6379SDeniz Eren } 228db3e6379SDeniz Eren 229db3e6379SDeniz Eren static void mioe3680_pci_class_init(ObjectClass *klass, void *data) 230db3e6379SDeniz Eren { 231db3e6379SDeniz Eren DeviceClass *dc = DEVICE_CLASS(klass); 232db3e6379SDeniz Eren PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 233db3e6379SDeniz Eren 234db3e6379SDeniz Eren k->realize = mioe3680_pci_realize; 235db3e6379SDeniz Eren k->exit = mioe3680_pci_exit; 236db3e6379SDeniz Eren k->vendor_id = MIOe3680_PCI_VENDOR_ID1; 237db3e6379SDeniz Eren k->device_id = MIOe3680_PCI_DEVICE_ID1; 238db3e6379SDeniz Eren k->revision = 0x00; 239db3e6379SDeniz Eren k->class_id = 0x000c09; 240db3e6379SDeniz Eren k->subsystem_vendor_id = MIOe3680_PCI_VENDOR_ID1; 241db3e6379SDeniz Eren k->subsystem_id = MIOe3680_PCI_DEVICE_ID1; 242db3e6379SDeniz Eren dc->desc = "Mioe3680 PCICANx"; 243db3e6379SDeniz Eren dc->vmsd = &vmstate_mioe3680_pci; 244db3e6379SDeniz Eren set_bit(DEVICE_CATEGORY_MISC, dc->categories); 245db3e6379SDeniz Eren dc->reset = mioe3680_pci_reset; 246db3e6379SDeniz Eren } 247db3e6379SDeniz Eren 248db3e6379SDeniz Eren static const TypeInfo mioe3680_pci_info = { 249db3e6379SDeniz Eren .name = TYPE_CAN_PCI_DEV, 250db3e6379SDeniz Eren .parent = TYPE_PCI_DEVICE, 251db3e6379SDeniz Eren .instance_size = sizeof(Mioe3680PCIState), 252db3e6379SDeniz Eren .class_init = mioe3680_pci_class_init, 253db3e6379SDeniz Eren .instance_init = mioe3680_pci_instance_init, 254db3e6379SDeniz Eren .interfaces = (InterfaceInfo[]) { 255db3e6379SDeniz Eren { INTERFACE_CONVENTIONAL_PCI_DEVICE }, 256db3e6379SDeniz Eren { }, 257db3e6379SDeniz Eren }, 258db3e6379SDeniz Eren }; 259db3e6379SDeniz Eren 260db3e6379SDeniz Eren static void mioe3680_pci_register_types(void) 261db3e6379SDeniz Eren { 262db3e6379SDeniz Eren type_register_static(&mioe3680_pci_info); 263db3e6379SDeniz Eren } 264db3e6379SDeniz Eren 265db3e6379SDeniz Eren type_init(mioe3680_pci_register_types) 266