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