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