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