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" 36edf5ca5dSMarkus Armbruster #include "hw/pci/pci_device.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" 42db1015e9SEduardo Habkost #include "qom/object.h" 43db3e6379SDeniz Eren 44db3e6379SDeniz Eren #define TYPE_CAN_PCI_DEV "mioe3680_pci" 45db3e6379SDeniz Eren 46db1015e9SEduardo Habkost typedef struct Mioe3680PCIState Mioe3680PCIState; 478110fa1dSEduardo Habkost DECLARE_INSTANCE_CHECKER(Mioe3680PCIState, MIOe3680_PCI_DEV, 488110fa1dSEduardo Habkost TYPE_CAN_PCI_DEV) 49db3e6379SDeniz Eren 50db3e6379SDeniz Eren /* the PCI device and vendor IDs */ 51db3e6379SDeniz Eren #ifndef MIOe3680_PCI_VENDOR_ID1 52db3e6379SDeniz Eren #define MIOe3680_PCI_VENDOR_ID1 0x13fe 53db3e6379SDeniz Eren #endif 54db3e6379SDeniz Eren 55db3e6379SDeniz Eren #ifndef MIOe3680_PCI_DEVICE_ID1 56db3e6379SDeniz Eren #define MIOe3680_PCI_DEVICE_ID1 0xc302 57db3e6379SDeniz Eren #endif 58db3e6379SDeniz Eren 59db3e6379SDeniz Eren #define MIOe3680_PCI_SJA_COUNT 2 60db3e6379SDeniz Eren #define MIOe3680_PCI_SJA_RANGE 0x400 61db3e6379SDeniz Eren 62db3e6379SDeniz Eren #define MIOe3680_PCI_BYTES_PER_SJA 0x80 63db3e6379SDeniz Eren 64db1015e9SEduardo Habkost struct Mioe3680PCIState { 65db3e6379SDeniz Eren /*< private >*/ 66db3e6379SDeniz Eren PCIDevice dev; 67db3e6379SDeniz Eren /*< public >*/ 68db3e6379SDeniz Eren MemoryRegion sja_io[MIOe3680_PCI_SJA_COUNT]; 69db3e6379SDeniz Eren 70db3e6379SDeniz Eren CanSJA1000State sja_state[MIOe3680_PCI_SJA_COUNT]; 71db3e6379SDeniz Eren qemu_irq irq; 72db3e6379SDeniz Eren 73db3e6379SDeniz Eren char *model; /* The model that support, only SJA1000 now. */ 74db3e6379SDeniz Eren CanBusState *canbus[MIOe3680_PCI_SJA_COUNT]; 75db1015e9SEduardo Habkost }; 76db3e6379SDeniz Eren 77db3e6379SDeniz Eren static void mioe3680_pci_reset(DeviceState *dev) 78db3e6379SDeniz Eren { 79db3e6379SDeniz Eren Mioe3680PCIState *d = MIOe3680_PCI_DEV(dev); 80db3e6379SDeniz Eren int i; 81db3e6379SDeniz Eren 82db3e6379SDeniz Eren for (i = 0 ; i < MIOe3680_PCI_SJA_COUNT; i++) { 83db3e6379SDeniz Eren can_sja_hardware_reset(&d->sja_state[i]); 84db3e6379SDeniz Eren } 85db3e6379SDeniz Eren } 86db3e6379SDeniz Eren 87db3e6379SDeniz Eren static uint64_t mioe3680_pci_sja1_io_read(void *opaque, hwaddr addr, 88db3e6379SDeniz Eren unsigned size) 89db3e6379SDeniz Eren { 90db3e6379SDeniz Eren Mioe3680PCIState *d = opaque; 91db3e6379SDeniz Eren CanSJA1000State *s = &d->sja_state[0]; 92db3e6379SDeniz Eren 93db3e6379SDeniz Eren if (addr >= MIOe3680_PCI_BYTES_PER_SJA) { 94db3e6379SDeniz Eren return 0; 95db3e6379SDeniz Eren } 96db3e6379SDeniz Eren 97db3e6379SDeniz Eren return can_sja_mem_read(s, addr >> 2, size); 98db3e6379SDeniz Eren } 99db3e6379SDeniz Eren 100db3e6379SDeniz Eren static void mioe3680_pci_sja1_io_write(void *opaque, hwaddr addr, uint64_t data, 101db3e6379SDeniz Eren unsigned size) 102db3e6379SDeniz Eren { 103db3e6379SDeniz Eren Mioe3680PCIState *d = opaque; 104db3e6379SDeniz Eren CanSJA1000State *s = &d->sja_state[0]; 105db3e6379SDeniz Eren 106db3e6379SDeniz Eren if (addr >= MIOe3680_PCI_BYTES_PER_SJA) { 107db3e6379SDeniz Eren return; 108db3e6379SDeniz Eren } 109db3e6379SDeniz Eren 110db3e6379SDeniz Eren can_sja_mem_write(s, addr >> 2, data, size); 111db3e6379SDeniz Eren } 112db3e6379SDeniz Eren 113db3e6379SDeniz Eren static uint64_t mioe3680_pci_sja2_io_read(void *opaque, hwaddr addr, 114db3e6379SDeniz Eren unsigned size) 115db3e6379SDeniz Eren { 116db3e6379SDeniz Eren Mioe3680PCIState *d = opaque; 117db3e6379SDeniz Eren CanSJA1000State *s = &d->sja_state[1]; 118db3e6379SDeniz Eren 119db3e6379SDeniz Eren if (addr >= MIOe3680_PCI_BYTES_PER_SJA) { 120db3e6379SDeniz Eren return 0; 121db3e6379SDeniz Eren } 122db3e6379SDeniz Eren 123db3e6379SDeniz Eren return can_sja_mem_read(s, addr >> 2, size); 124db3e6379SDeniz Eren } 125db3e6379SDeniz Eren 126db3e6379SDeniz Eren static void mioe3680_pci_sja2_io_write(void *opaque, hwaddr addr, uint64_t data, 127db3e6379SDeniz Eren unsigned size) 128db3e6379SDeniz Eren { 129db3e6379SDeniz Eren Mioe3680PCIState *d = opaque; 130db3e6379SDeniz Eren CanSJA1000State *s = &d->sja_state[1]; 131db3e6379SDeniz Eren 132db3e6379SDeniz Eren if (addr >= MIOe3680_PCI_BYTES_PER_SJA) { 133db3e6379SDeniz Eren return; 134db3e6379SDeniz Eren } 135db3e6379SDeniz Eren 136db3e6379SDeniz Eren can_sja_mem_write(s, addr >> 2, data, size); 137db3e6379SDeniz Eren } 138db3e6379SDeniz Eren 139db3e6379SDeniz Eren static const MemoryRegionOps mioe3680_pci_sja1_io_ops = { 140db3e6379SDeniz Eren .read = mioe3680_pci_sja1_io_read, 141db3e6379SDeniz Eren .write = mioe3680_pci_sja1_io_write, 142db3e6379SDeniz Eren .endianness = DEVICE_LITTLE_ENDIAN, 143db3e6379SDeniz Eren .impl = { 144db3e6379SDeniz Eren .max_access_size = 1, 145db3e6379SDeniz Eren }, 146db3e6379SDeniz Eren }; 147db3e6379SDeniz Eren 148db3e6379SDeniz Eren static const MemoryRegionOps mioe3680_pci_sja2_io_ops = { 149db3e6379SDeniz Eren .read = mioe3680_pci_sja2_io_read, 150db3e6379SDeniz Eren .write = mioe3680_pci_sja2_io_write, 151db3e6379SDeniz Eren .endianness = DEVICE_LITTLE_ENDIAN, 152db3e6379SDeniz Eren .impl = { 153db3e6379SDeniz Eren .max_access_size = 1, 154db3e6379SDeniz Eren }, 155db3e6379SDeniz Eren }; 156db3e6379SDeniz Eren 157db3e6379SDeniz Eren static void mioe3680_pci_realize(PCIDevice *pci_dev, Error **errp) 158db3e6379SDeniz Eren { 159db3e6379SDeniz Eren Mioe3680PCIState *d = MIOe3680_PCI_DEV(pci_dev); 160db3e6379SDeniz Eren uint8_t *pci_conf; 161db3e6379SDeniz Eren int i; 162db3e6379SDeniz Eren 163db3e6379SDeniz Eren pci_conf = pci_dev->config; 164db3e6379SDeniz Eren pci_conf[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */ 165db3e6379SDeniz Eren 166db3e6379SDeniz Eren d->irq = pci_allocate_irq(&d->dev); 167db3e6379SDeniz Eren 168db3e6379SDeniz Eren for (i = 0 ; i < MIOe3680_PCI_SJA_COUNT; i++) { 169db3e6379SDeniz Eren can_sja_init(&d->sja_state[i], d->irq); 170db3e6379SDeniz Eren } 171db3e6379SDeniz Eren 172db3e6379SDeniz Eren for (i = 0 ; i < MIOe3680_PCI_SJA_COUNT; i++) { 173db3e6379SDeniz Eren if (can_sja_connect_to_bus(&d->sja_state[i], d->canbus[i]) < 0) { 174db3e6379SDeniz Eren error_setg(errp, "can_sja_connect_to_bus failed"); 175db3e6379SDeniz Eren return; 176db3e6379SDeniz Eren } 177db3e6379SDeniz Eren } 178db3e6379SDeniz Eren 179db3e6379SDeniz Eren memory_region_init_io(&d->sja_io[0], OBJECT(d), &mioe3680_pci_sja1_io_ops, 180db3e6379SDeniz Eren d, "mioe3680_pci-sja1", MIOe3680_PCI_SJA_RANGE); 181db3e6379SDeniz Eren memory_region_init_io(&d->sja_io[1], OBJECT(d), &mioe3680_pci_sja2_io_ops, 182db3e6379SDeniz Eren d, "mioe3680_pci-sja2", MIOe3680_PCI_SJA_RANGE); 183db3e6379SDeniz Eren 184db3e6379SDeniz Eren for (i = 0 ; i < MIOe3680_PCI_SJA_COUNT; i++) { 185db3e6379SDeniz Eren pci_register_bar(&d->dev, /*BAR*/ i, PCI_BASE_ADDRESS_SPACE_IO, 186db3e6379SDeniz Eren &d->sja_io[i]); 187db3e6379SDeniz Eren } 188db3e6379SDeniz Eren } 189db3e6379SDeniz Eren 190db3e6379SDeniz Eren static void mioe3680_pci_exit(PCIDevice *pci_dev) 191db3e6379SDeniz Eren { 192db3e6379SDeniz Eren Mioe3680PCIState *d = MIOe3680_PCI_DEV(pci_dev); 193db3e6379SDeniz Eren int i; 194db3e6379SDeniz Eren 195db3e6379SDeniz Eren for (i = 0 ; i < MIOe3680_PCI_SJA_COUNT; i++) { 196db3e6379SDeniz Eren can_sja_disconnect(&d->sja_state[i]); 197db3e6379SDeniz Eren } 198db3e6379SDeniz Eren 199db3e6379SDeniz Eren qemu_free_irq(d->irq); 200db3e6379SDeniz Eren } 201db3e6379SDeniz Eren 202db3e6379SDeniz Eren static const VMStateDescription vmstate_mioe3680_pci = { 203db3e6379SDeniz Eren .name = "mioe3680_pci", 204db3e6379SDeniz Eren .version_id = 1, 205db3e6379SDeniz Eren .minimum_version_id = 1, 206*1de81b42SRichard Henderson .fields = (const VMStateField[]) { 207db3e6379SDeniz Eren VMSTATE_PCI_DEVICE(dev, Mioe3680PCIState), 208db3e6379SDeniz Eren VMSTATE_STRUCT(sja_state[0], Mioe3680PCIState, 0, vmstate_can_sja, 209db3e6379SDeniz Eren CanSJA1000State), 210db3e6379SDeniz Eren VMSTATE_STRUCT(sja_state[1], Mioe3680PCIState, 0, vmstate_can_sja, 211db3e6379SDeniz Eren CanSJA1000State), 212db3e6379SDeniz Eren VMSTATE_END_OF_LIST() 213db3e6379SDeniz Eren } 214db3e6379SDeniz Eren }; 215db3e6379SDeniz Eren 216db3e6379SDeniz Eren static void mioe3680_pci_instance_init(Object *obj) 217db3e6379SDeniz Eren { 218db3e6379SDeniz Eren Mioe3680PCIState *d = MIOe3680_PCI_DEV(obj); 219db3e6379SDeniz Eren 220db3e6379SDeniz Eren object_property_add_link(obj, "canbus0", TYPE_CAN_BUS, 221db3e6379SDeniz Eren (Object **)&d->canbus[0], 222db3e6379SDeniz Eren qdev_prop_allow_set_link_before_realize, 223d2623129SMarkus Armbruster 0); 224db3e6379SDeniz Eren object_property_add_link(obj, "canbus1", TYPE_CAN_BUS, 225db3e6379SDeniz Eren (Object **)&d->canbus[1], 226db3e6379SDeniz Eren qdev_prop_allow_set_link_before_realize, 227d2623129SMarkus Armbruster 0); 228db3e6379SDeniz Eren } 229db3e6379SDeniz Eren 230db3e6379SDeniz Eren static void mioe3680_pci_class_init(ObjectClass *klass, void *data) 231db3e6379SDeniz Eren { 232db3e6379SDeniz Eren DeviceClass *dc = DEVICE_CLASS(klass); 233db3e6379SDeniz Eren PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 234db3e6379SDeniz Eren 235db3e6379SDeniz Eren k->realize = mioe3680_pci_realize; 236db3e6379SDeniz Eren k->exit = mioe3680_pci_exit; 237db3e6379SDeniz Eren k->vendor_id = MIOe3680_PCI_VENDOR_ID1; 238db3e6379SDeniz Eren k->device_id = MIOe3680_PCI_DEVICE_ID1; 239db3e6379SDeniz Eren k->revision = 0x00; 240db3e6379SDeniz Eren k->class_id = 0x000c09; 241db3e6379SDeniz Eren k->subsystem_vendor_id = MIOe3680_PCI_VENDOR_ID1; 242db3e6379SDeniz Eren k->subsystem_id = MIOe3680_PCI_DEVICE_ID1; 243db3e6379SDeniz Eren dc->desc = "Mioe3680 PCICANx"; 244db3e6379SDeniz Eren dc->vmsd = &vmstate_mioe3680_pci; 245db3e6379SDeniz Eren set_bit(DEVICE_CATEGORY_MISC, dc->categories); 246db3e6379SDeniz Eren dc->reset = mioe3680_pci_reset; 247db3e6379SDeniz Eren } 248db3e6379SDeniz Eren 249db3e6379SDeniz Eren static const TypeInfo mioe3680_pci_info = { 250db3e6379SDeniz Eren .name = TYPE_CAN_PCI_DEV, 251db3e6379SDeniz Eren .parent = TYPE_PCI_DEVICE, 252db3e6379SDeniz Eren .instance_size = sizeof(Mioe3680PCIState), 253db3e6379SDeniz Eren .class_init = mioe3680_pci_class_init, 254db3e6379SDeniz Eren .instance_init = mioe3680_pci_instance_init, 255db3e6379SDeniz Eren .interfaces = (InterfaceInfo[]) { 256db3e6379SDeniz Eren { INTERFACE_CONVENTIONAL_PCI_DEVICE }, 257db3e6379SDeniz Eren { }, 258db3e6379SDeniz Eren }, 259db3e6379SDeniz Eren }; 260db3e6379SDeniz Eren 261db3e6379SDeniz Eren static void mioe3680_pci_register_types(void) 262db3e6379SDeniz Eren { 263db3e6379SDeniz Eren type_register_static(&mioe3680_pci_info); 264db3e6379SDeniz Eren } 265db3e6379SDeniz Eren 266db3e6379SDeniz Eren type_init(mioe3680_pci_register_types) 267