xref: /openbmc/qemu/hw/net/can/can_kvaser_pci.c (revision 3d9569b8)
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/hw.h"
40 #include "hw/pci/pci.h"
41 #include "net/can_emu.h"
42 
43 #include "can_sja1000.h"
44 
45 #define TYPE_CAN_PCI_DEV "kvaser_pci"
46 
47 #define KVASER_PCI_DEV(obj) \
48     OBJECT_CHECK(KvaserPCIState, (obj), TYPE_CAN_PCI_DEV)
49 
50 #ifndef KVASER_PCI_VENDOR_ID1
51 #define KVASER_PCI_VENDOR_ID1     0x10e8    /* the PCI device and vendor IDs */
52 #endif
53 
54 #ifndef KVASER_PCI_DEVICE_ID1
55 #define KVASER_PCI_DEVICE_ID1     0x8406
56 #endif
57 
58 #define KVASER_PCI_S5920_RANGE    0x80
59 #define KVASER_PCI_SJA_RANGE      0x80
60 #define KVASER_PCI_XILINX_RANGE   0x8
61 
62 #define KVASER_PCI_BYTES_PER_SJA  0x20
63 
64 #define S5920_OMB                 0x0C
65 #define S5920_IMB                 0x1C
66 #define S5920_MBEF                0x34
67 #define S5920_INTCSR              0x38
68 #define S5920_RCR                 0x3C
69 #define S5920_PTCR                0x60
70 
71 #define S5920_INTCSR_ADDON_INTENABLE_M        0x2000
72 #define S5920_INTCSR_INTERRUPT_ASSERTED_M     0x800000
73 
74 #define KVASER_PCI_XILINX_VERINT  7   /* Lower nibble simulate interrupts,
75                                          high nibble version number. */
76 
77 #define KVASER_PCI_XILINX_VERSION_NUMBER 13
78 
79 typedef struct KvaserPCIState {
80     /*< private >*/
81     PCIDevice       dev;
82     /*< public >*/
83     MemoryRegion    s5920_io;
84     MemoryRegion    sja_io;
85     MemoryRegion    xilinx_io;
86 
87     CanSJA1000State sja_state;
88     qemu_irq        irq;
89 
90     uint32_t        s5920_intcsr;
91     uint32_t        s5920_irqstate;
92 
93     CanBusState     *canbus;
94 } KvaserPCIState;
95 
96 static void kvaser_pci_irq_handler(void *opaque, int irq_num, int level)
97 {
98     KvaserPCIState *d = (KvaserPCIState *)opaque;
99 
100     d->s5920_irqstate = level;
101     if (d->s5920_intcsr & S5920_INTCSR_ADDON_INTENABLE_M) {
102         pci_set_irq(&d->dev, level);
103     }
104 }
105 
106 static void kvaser_pci_reset(DeviceState *dev)
107 {
108     KvaserPCIState *d = KVASER_PCI_DEV(dev);
109     CanSJA1000State *s = &d->sja_state;
110 
111     can_sja_hardware_reset(s);
112 }
113 
114 static uint64_t kvaser_pci_s5920_io_read(void *opaque, hwaddr addr,
115                                          unsigned size)
116 {
117     KvaserPCIState *d = opaque;
118     uint64_t val;
119 
120     switch (addr) {
121     case S5920_INTCSR:
122         val = d->s5920_intcsr;
123         val &= ~S5920_INTCSR_INTERRUPT_ASSERTED_M;
124         if (d->s5920_irqstate) {
125             val |= S5920_INTCSR_INTERRUPT_ASSERTED_M;
126         }
127         return val;
128     }
129     return 0;
130 }
131 
132 static void kvaser_pci_s5920_io_write(void *opaque, hwaddr addr, uint64_t data,
133                                       unsigned size)
134 {
135     KvaserPCIState *d = opaque;
136 
137     switch (addr) {
138     case S5920_INTCSR:
139         if (d->s5920_irqstate &&
140             ((d->s5920_intcsr ^ data) & S5920_INTCSR_ADDON_INTENABLE_M)) {
141             pci_set_irq(&d->dev, !!(data & S5920_INTCSR_ADDON_INTENABLE_M));
142         }
143         d->s5920_intcsr = data;
144         break;
145     }
146 }
147 
148 static uint64_t kvaser_pci_sja_io_read(void *opaque, hwaddr addr, unsigned size)
149 {
150     KvaserPCIState *d = opaque;
151     CanSJA1000State *s = &d->sja_state;
152 
153     if (addr >= KVASER_PCI_BYTES_PER_SJA) {
154         return 0;
155     }
156 
157     return can_sja_mem_read(s, addr, size);
158 }
159 
160 static void kvaser_pci_sja_io_write(void *opaque, hwaddr addr, uint64_t data,
161                                     unsigned size)
162 {
163     KvaserPCIState *d = opaque;
164     CanSJA1000State *s = &d->sja_state;
165 
166     if (addr >= KVASER_PCI_BYTES_PER_SJA) {
167         return;
168     }
169 
170     can_sja_mem_write(s, addr, data, size);
171 }
172 
173 static uint64_t kvaser_pci_xilinx_io_read(void *opaque, hwaddr addr,
174                                           unsigned size)
175 {
176     switch (addr) {
177     case KVASER_PCI_XILINX_VERINT:
178         return (KVASER_PCI_XILINX_VERSION_NUMBER << 4) | 0;
179     }
180 
181     return 0;
182 }
183 
184 static void kvaser_pci_xilinx_io_write(void *opaque, hwaddr addr, uint64_t data,
185                              unsigned size)
186 {
187 
188 }
189 
190 static const MemoryRegionOps kvaser_pci_s5920_io_ops = {
191     .read = kvaser_pci_s5920_io_read,
192     .write = kvaser_pci_s5920_io_write,
193     .endianness = DEVICE_LITTLE_ENDIAN,
194     .impl = {
195         .min_access_size = 4,
196         .max_access_size = 4,
197     },
198 };
199 
200 static const MemoryRegionOps kvaser_pci_sja_io_ops = {
201     .read = kvaser_pci_sja_io_read,
202     .write = kvaser_pci_sja_io_write,
203     .endianness = DEVICE_LITTLE_ENDIAN,
204     .impl = {
205         .max_access_size = 1,
206     },
207 };
208 
209 static const MemoryRegionOps kvaser_pci_xilinx_io_ops = {
210     .read = kvaser_pci_xilinx_io_read,
211     .write = kvaser_pci_xilinx_io_write,
212     .endianness = DEVICE_LITTLE_ENDIAN,
213     .impl = {
214         .max_access_size = 1,
215     },
216 };
217 
218 static void kvaser_pci_realize(PCIDevice *pci_dev, Error **errp)
219 {
220     KvaserPCIState *d = KVASER_PCI_DEV(pci_dev);
221     CanSJA1000State *s = &d->sja_state;
222     uint8_t *pci_conf;
223 
224     pci_conf = pci_dev->config;
225     pci_conf[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */
226 
227     d->irq = qemu_allocate_irq(kvaser_pci_irq_handler, d, 0);
228 
229     can_sja_init(s, d->irq);
230 
231     if (can_sja_connect_to_bus(s, d->canbus) < 0) {
232         error_setg(errp, "can_sja_connect_to_bus failed");
233         return;
234     }
235 
236     memory_region_init_io(&d->s5920_io, OBJECT(d), &kvaser_pci_s5920_io_ops,
237                           d, "kvaser_pci-s5920", KVASER_PCI_S5920_RANGE);
238     memory_region_init_io(&d->sja_io, OBJECT(d), &kvaser_pci_sja_io_ops,
239                           d, "kvaser_pci-sja", KVASER_PCI_SJA_RANGE);
240     memory_region_init_io(&d->xilinx_io, OBJECT(d), &kvaser_pci_xilinx_io_ops,
241                           d, "kvaser_pci-xilinx", KVASER_PCI_XILINX_RANGE);
242 
243     pci_register_bar(&d->dev, /*BAR*/ 0, PCI_BASE_ADDRESS_SPACE_IO,
244                                             &d->s5920_io);
245     pci_register_bar(&d->dev, /*BAR*/ 1, PCI_BASE_ADDRESS_SPACE_IO,
246                                             &d->sja_io);
247     pci_register_bar(&d->dev, /*BAR*/ 2, PCI_BASE_ADDRESS_SPACE_IO,
248                                             &d->xilinx_io);
249 }
250 
251 static void kvaser_pci_exit(PCIDevice *pci_dev)
252 {
253     KvaserPCIState *d = KVASER_PCI_DEV(pci_dev);
254     CanSJA1000State *s = &d->sja_state;
255 
256     can_sja_disconnect(s);
257 
258     qemu_free_irq(d->irq);
259 }
260 
261 static const VMStateDescription vmstate_kvaser_pci = {
262     .name = "kvaser_pci",
263     .version_id = 1,
264     .minimum_version_id = 1,
265     .minimum_version_id_old = 1,
266     .fields = (VMStateField[]) {
267         VMSTATE_PCI_DEVICE(dev, KvaserPCIState),
268         /* Load this before sja_state.  */
269         VMSTATE_UINT32(s5920_intcsr, KvaserPCIState),
270         VMSTATE_STRUCT(sja_state, KvaserPCIState, 0, vmstate_can_sja,
271                        CanSJA1000State),
272         VMSTATE_END_OF_LIST()
273     }
274 };
275 
276 static void kvaser_pci_instance_init(Object *obj)
277 {
278     KvaserPCIState *d = KVASER_PCI_DEV(obj);
279 
280     object_property_add_link(obj, "canbus", TYPE_CAN_BUS,
281                              (Object **)&d->canbus,
282                              qdev_prop_allow_set_link_before_realize,
283                              0, &error_abort);
284 }
285 
286 static void kvaser_pci_class_init(ObjectClass *klass, void *data)
287 {
288     DeviceClass *dc = DEVICE_CLASS(klass);
289     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
290 
291     k->realize = kvaser_pci_realize;
292     k->exit = kvaser_pci_exit;
293     k->vendor_id = KVASER_PCI_VENDOR_ID1;
294     k->device_id = KVASER_PCI_DEVICE_ID1;
295     k->revision = 0x00;
296     k->class_id = 0x00ff00;
297     dc->desc = "Kvaser PCICANx";
298     dc->vmsd = &vmstate_kvaser_pci;
299     dc->reset = kvaser_pci_reset;
300     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
301 }
302 
303 static const TypeInfo kvaser_pci_info = {
304     .name          = TYPE_CAN_PCI_DEV,
305     .parent        = TYPE_PCI_DEVICE,
306     .instance_size = sizeof(KvaserPCIState),
307     .class_init    = kvaser_pci_class_init,
308     .instance_init = kvaser_pci_instance_init,
309     .interfaces = (InterfaceInfo[]) {
310         { INTERFACE_CONVENTIONAL_PCI_DEVICE },
311         { },
312     },
313 };
314 
315 static void kvaser_pci_register_types(void)
316 {
317     type_register_static(&kvaser_pci_info);
318 }
319 
320 type_init(kvaser_pci_register_types)
321