xref: /qemu/hw/net/can/can_kvaser_pci.c (revision ab9056ff)
1 /*
2  * Kvaser PCI CAN device (SJA1000 based) emulation
3  *
4  * Copyright (c) 2013-2014 Jin Yang
5  * Copyright (c) 2014-2018 Pavel Pisa
6  *
7  * Partially based on educational PCIexpress APOHW hardware
8  * emulator used fro class A0B36APO at CTU FEE course by
9  *    Rostislav Lisovy and Pavel Pisa
10  *
11  * Initial development supported by Google GSoC 2013 from RTEMS project slot
12  *
13  * Permission is hereby granted, free of charge, to any person obtaining a copy
14  * of this software and associated documentation files (the "Software"), to deal
15  * in the Software without restriction, including without limitation the rights
16  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17  * copies of the Software, and to permit persons to whom the Software is
18  * furnished to do so, subject to the following conditions:
19  *
20  * The above copyright notice and this permission notice shall be included in
21  * all copies or substantial portions of the Software.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29  * THE SOFTWARE.
30  */
31 
32 #include "qemu/osdep.h"
33 #include "qemu/event_notifier.h"
34 #include "qemu/module.h"
35 #include "qemu/thread.h"
36 #include "qemu/sockets.h"
37 #include "qapi/error.h"
38 #include "chardev/char.h"
39 #include "hw/irq.h"
40 #include "hw/pci/pci.h"
41 #include "hw/qdev-properties.h"
42 #include "migration/vmstate.h"
43 #include "net/can_emu.h"
44 
45 #include "can_sja1000.h"
46 
47 #define TYPE_CAN_PCI_DEV "kvaser_pci"
48 
49 #define KVASER_PCI_DEV(obj) \
50     OBJECT_CHECK(KvaserPCIState, (obj), TYPE_CAN_PCI_DEV)
51 
52 #ifndef KVASER_PCI_VENDOR_ID1
53 #define KVASER_PCI_VENDOR_ID1     0x10e8    /* the PCI device and vendor IDs */
54 #endif
55 
56 #ifndef KVASER_PCI_DEVICE_ID1
57 #define KVASER_PCI_DEVICE_ID1     0x8406
58 #endif
59 
60 #define KVASER_PCI_S5920_RANGE    0x80
61 #define KVASER_PCI_SJA_RANGE      0x80
62 #define KVASER_PCI_XILINX_RANGE   0x8
63 
64 #define KVASER_PCI_BYTES_PER_SJA  0x20
65 
66 #define S5920_OMB                 0x0C
67 #define S5920_IMB                 0x1C
68 #define S5920_MBEF                0x34
69 #define S5920_INTCSR              0x38
70 #define S5920_RCR                 0x3C
71 #define S5920_PTCR                0x60
72 
73 #define S5920_INTCSR_ADDON_INTENABLE_M        0x2000
74 #define S5920_INTCSR_INTERRUPT_ASSERTED_M     0x800000
75 
76 #define KVASER_PCI_XILINX_VERINT  7   /* Lower nibble simulate interrupts,
77                                          high nibble version number. */
78 
79 #define KVASER_PCI_XILINX_VERSION_NUMBER 13
80 
81 typedef struct KvaserPCIState {
82     /*< private >*/
83     PCIDevice       dev;
84     /*< public >*/
85     MemoryRegion    s5920_io;
86     MemoryRegion    sja_io;
87     MemoryRegion    xilinx_io;
88 
89     CanSJA1000State sja_state;
90     qemu_irq        irq;
91 
92     uint32_t        s5920_intcsr;
93     uint32_t        s5920_irqstate;
94 
95     CanBusState     *canbus;
96 } KvaserPCIState;
97 
98 static void kvaser_pci_irq_handler(void *opaque, int irq_num, int level)
99 {
100     KvaserPCIState *d = (KvaserPCIState *)opaque;
101 
102     d->s5920_irqstate = level;
103     if (d->s5920_intcsr & S5920_INTCSR_ADDON_INTENABLE_M) {
104         pci_set_irq(&d->dev, level);
105     }
106 }
107 
108 static void kvaser_pci_reset(DeviceState *dev)
109 {
110     KvaserPCIState *d = KVASER_PCI_DEV(dev);
111     CanSJA1000State *s = &d->sja_state;
112 
113     can_sja_hardware_reset(s);
114 }
115 
116 static uint64_t kvaser_pci_s5920_io_read(void *opaque, hwaddr addr,
117                                          unsigned size)
118 {
119     KvaserPCIState *d = opaque;
120     uint64_t val;
121 
122     switch (addr) {
123     case S5920_INTCSR:
124         val = d->s5920_intcsr;
125         val &= ~S5920_INTCSR_INTERRUPT_ASSERTED_M;
126         if (d->s5920_irqstate) {
127             val |= S5920_INTCSR_INTERRUPT_ASSERTED_M;
128         }
129         return val;
130     }
131     return 0;
132 }
133 
134 static void kvaser_pci_s5920_io_write(void *opaque, hwaddr addr, uint64_t data,
135                                       unsigned size)
136 {
137     KvaserPCIState *d = opaque;
138 
139     switch (addr) {
140     case S5920_INTCSR:
141         if (d->s5920_irqstate &&
142             ((d->s5920_intcsr ^ data) & S5920_INTCSR_ADDON_INTENABLE_M)) {
143             pci_set_irq(&d->dev, !!(data & S5920_INTCSR_ADDON_INTENABLE_M));
144         }
145         d->s5920_intcsr = data;
146         break;
147     }
148 }
149 
150 static uint64_t kvaser_pci_sja_io_read(void *opaque, hwaddr addr, unsigned size)
151 {
152     KvaserPCIState *d = opaque;
153     CanSJA1000State *s = &d->sja_state;
154 
155     if (addr >= KVASER_PCI_BYTES_PER_SJA) {
156         return 0;
157     }
158 
159     return can_sja_mem_read(s, addr, size);
160 }
161 
162 static void kvaser_pci_sja_io_write(void *opaque, hwaddr addr, uint64_t data,
163                                     unsigned size)
164 {
165     KvaserPCIState *d = opaque;
166     CanSJA1000State *s = &d->sja_state;
167 
168     if (addr >= KVASER_PCI_BYTES_PER_SJA) {
169         return;
170     }
171 
172     can_sja_mem_write(s, addr, data, size);
173 }
174 
175 static uint64_t kvaser_pci_xilinx_io_read(void *opaque, hwaddr addr,
176                                           unsigned size)
177 {
178     switch (addr) {
179     case KVASER_PCI_XILINX_VERINT:
180         return (KVASER_PCI_XILINX_VERSION_NUMBER << 4) | 0;
181     }
182 
183     return 0;
184 }
185 
186 static void kvaser_pci_xilinx_io_write(void *opaque, hwaddr addr, uint64_t data,
187                              unsigned size)
188 {
189 
190 }
191 
192 static const MemoryRegionOps kvaser_pci_s5920_io_ops = {
193     .read = kvaser_pci_s5920_io_read,
194     .write = kvaser_pci_s5920_io_write,
195     .endianness = DEVICE_LITTLE_ENDIAN,
196     .impl = {
197         .min_access_size = 4,
198         .max_access_size = 4,
199     },
200 };
201 
202 static const MemoryRegionOps kvaser_pci_sja_io_ops = {
203     .read = kvaser_pci_sja_io_read,
204     .write = kvaser_pci_sja_io_write,
205     .endianness = DEVICE_LITTLE_ENDIAN,
206     .impl = {
207         .max_access_size = 1,
208     },
209 };
210 
211 static const MemoryRegionOps kvaser_pci_xilinx_io_ops = {
212     .read = kvaser_pci_xilinx_io_read,
213     .write = kvaser_pci_xilinx_io_write,
214     .endianness = DEVICE_LITTLE_ENDIAN,
215     .impl = {
216         .max_access_size = 1,
217     },
218 };
219 
220 static void kvaser_pci_realize(PCIDevice *pci_dev, Error **errp)
221 {
222     KvaserPCIState *d = KVASER_PCI_DEV(pci_dev);
223     CanSJA1000State *s = &d->sja_state;
224     uint8_t *pci_conf;
225 
226     pci_conf = pci_dev->config;
227     pci_conf[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */
228 
229     d->irq = qemu_allocate_irq(kvaser_pci_irq_handler, d, 0);
230 
231     can_sja_init(s, d->irq);
232 
233     if (can_sja_connect_to_bus(s, d->canbus) < 0) {
234         error_setg(errp, "can_sja_connect_to_bus failed");
235         return;
236     }
237 
238     memory_region_init_io(&d->s5920_io, OBJECT(d), &kvaser_pci_s5920_io_ops,
239                           d, "kvaser_pci-s5920", KVASER_PCI_S5920_RANGE);
240     memory_region_init_io(&d->sja_io, OBJECT(d), &kvaser_pci_sja_io_ops,
241                           d, "kvaser_pci-sja", KVASER_PCI_SJA_RANGE);
242     memory_region_init_io(&d->xilinx_io, OBJECT(d), &kvaser_pci_xilinx_io_ops,
243                           d, "kvaser_pci-xilinx", KVASER_PCI_XILINX_RANGE);
244 
245     pci_register_bar(&d->dev, /*BAR*/ 0, PCI_BASE_ADDRESS_SPACE_IO,
246                                             &d->s5920_io);
247     pci_register_bar(&d->dev, /*BAR*/ 1, PCI_BASE_ADDRESS_SPACE_IO,
248                                             &d->sja_io);
249     pci_register_bar(&d->dev, /*BAR*/ 2, PCI_BASE_ADDRESS_SPACE_IO,
250                                             &d->xilinx_io);
251 }
252 
253 static void kvaser_pci_exit(PCIDevice *pci_dev)
254 {
255     KvaserPCIState *d = KVASER_PCI_DEV(pci_dev);
256     CanSJA1000State *s = &d->sja_state;
257 
258     can_sja_disconnect(s);
259 
260     qemu_free_irq(d->irq);
261 }
262 
263 static const VMStateDescription vmstate_kvaser_pci = {
264     .name = "kvaser_pci",
265     .version_id = 1,
266     .minimum_version_id = 1,
267     .minimum_version_id_old = 1,
268     .fields = (VMStateField[]) {
269         VMSTATE_PCI_DEVICE(dev, KvaserPCIState),
270         /* Load this before sja_state.  */
271         VMSTATE_UINT32(s5920_intcsr, KvaserPCIState),
272         VMSTATE_STRUCT(sja_state, KvaserPCIState, 0, vmstate_can_sja,
273                        CanSJA1000State),
274         VMSTATE_END_OF_LIST()
275     }
276 };
277 
278 static void kvaser_pci_instance_init(Object *obj)
279 {
280     KvaserPCIState *d = KVASER_PCI_DEV(obj);
281 
282     object_property_add_link(obj, "canbus", TYPE_CAN_BUS,
283                              (Object **)&d->canbus,
284                              qdev_prop_allow_set_link_before_realize,
285                              0, &error_abort);
286 }
287 
288 static void kvaser_pci_class_init(ObjectClass *klass, void *data)
289 {
290     DeviceClass *dc = DEVICE_CLASS(klass);
291     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
292 
293     k->realize = kvaser_pci_realize;
294     k->exit = kvaser_pci_exit;
295     k->vendor_id = KVASER_PCI_VENDOR_ID1;
296     k->device_id = KVASER_PCI_DEVICE_ID1;
297     k->revision = 0x00;
298     k->class_id = 0x00ff00;
299     dc->desc = "Kvaser PCICANx";
300     dc->vmsd = &vmstate_kvaser_pci;
301     dc->reset = kvaser_pci_reset;
302     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
303 }
304 
305 static const TypeInfo kvaser_pci_info = {
306     .name          = TYPE_CAN_PCI_DEV,
307     .parent        = TYPE_PCI_DEVICE,
308     .instance_size = sizeof(KvaserPCIState),
309     .class_init    = kvaser_pci_class_init,
310     .instance_init = kvaser_pci_instance_init,
311     .interfaces = (InterfaceInfo[]) {
312         { INTERFACE_CONVENTIONAL_PCI_DEVICE },
313         { },
314     },
315 };
316 
317 static void kvaser_pci_register_types(void)
318 {
319     type_register_static(&kvaser_pci_info);
320 }
321 
322 type_init(kvaser_pci_register_types)
323