hw/arm: Plug FlexCAN into FSL_IMX6 and Sabrelite
FlexcanState is added to the FslIMX6State struct like other peripherals. Add two new machine properties to Sabrelite machine for linking the embedded FlexCAN instances to QEMU CAN buses by name. No other machine uses FslIMX6State. Signed-off-by: Matyáš Bobek <matyas.bobek@gmail.com> Signed-off-by: Pavel Pisa <pisa@fel.cvut.cz> Tested-by: Pavel Pisa <pisa@fel.cvut.cz> Reviewed-by: Bernhard Beschow <shentey@gmail.com> Reviewed-by: Pavel Pisa <pisa@fel.cvut.cz> Message-id: 4159df998b0508bb411284ef406de23bbc5edfd8.1782140438.git.matyas.bobek@gmail.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Matyáš Bobek committed
Jun 22, 2026 at 18:08 UTC
c60f8779127204a5b6437a39e4bd1ce211fa7d90
4 files changed
+60
hw/arm/Kconfig
+1
@@ -520,6 +520,7 @@ config FSL_IMX6
520
select IMX_FEC
521
select IMX_I2C
522
select IMX_USBPHY
523
+ select CAN_FLEXCAN
524
select WDT_IMX2
525
select PL310 # cache controller
526
select PCI_EXPRESS_DESIGNWARE
hw/arm/fsl-imx6.c
+29
@@ -90,6 +90,10 @@ static void fsl_imx6_init(Object *obj)
90
snprintf(name, NAME_SIZE, "spi%d", i + 1);
91
object_initialize_child(obj, name, &s->spi[i], TYPE_IMX_SPI);
92
}
93
+ for (i = 0; i < FSL_IMX6_NUM_CANS; i++) {
94
+ snprintf(name, NAME_SIZE, "flexcan%d", i + 1);
95
+ object_initialize_child(obj, name, &s->flexcan[i], TYPE_CAN_FLEXCAN);
96
+ }
97
for (i = 0; i < FSL_IMX6_NUM_WDTS; i++) {
98
snprintf(name, NAME_SIZE, "wdt%d", i);
99
object_initialize_child(obj, name, &s->wdt[i], TYPE_IMX2_WDT);
@@ -377,6 +381,27 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
381
qdev_get_gpio_in(gic, spi_table[i].irq));
382
}
383
384
+ /* Initialize all FLEXCANs */
385
+ for (i = 0; i < FSL_IMX6_NUM_CANS; i++) {
386
+ static const struct {
387
+ hwaddr addr;
388
+ unsigned int irq;
389
+ } flexcan_table[FSL_IMX6_NUM_CANS] = {
390
+ { FSL_IMX6_CAN1_ADDR, FSL_IMX6_FLEXCAN1_IRQ },
391
+ { FSL_IMX6_CAN2_ADDR, FSL_IMX6_FLEXCAN2_IRQ },
392
+ };
393
+
394
+ s->flexcan[i].ccm = IMX_CCM(&s->ccm);
395
+ object_property_set_link(OBJECT(&s->flexcan[i]), "canbus",
396
+ OBJECT(s->canbus[i]), &error_abort);
397
+
398
+ sysbus_realize(SYS_BUS_DEVICE(&s->flexcan[i]), &error_abort);
399
+
400
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->flexcan[i]), 0, flexcan_table[i].addr);
401
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->flexcan[i]), 0,
402
+ qdev_get_gpio_in(gic, flexcan_table[i].irq));
403
+ }
404
+
405
object_property_set_uint(OBJECT(&s->eth), "phy-num", s->phy_num,
406
&error_abort);
407
qemu_configure_nic_device(DEVICE(&s->eth), true, NULL);
@@ -480,6 +505,10 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
505
506
static const Property fsl_imx6_properties[] = {
507
DEFINE_PROP_UINT32("fec-phy-num", FslIMX6State, phy_num, 0),
508
+ DEFINE_PROP_LINK("canbus0", FslIMX6State, canbus[0], TYPE_CAN_BUS,
509
+ CanBusState *),
510
+ DEFINE_PROP_LINK("canbus1", FslIMX6State, canbus[1], TYPE_CAN_BUS,
511
+ CanBusState *),
512
};
513
514
static void fsl_imx6_class_init(ObjectClass *oc, const void *data)
hw/arm/sabrelite.c
+24
@@ -24,6 +24,7 @@ struct SabreliteMachineState {
24
MachineState parent_obj;
25
26
FslIMX6State soc;
27
+ CanBusState *canbus[FSL_IMX6_NUM_CANS];
28
};
29
30
#define TYPE_SABRELITE_MACHINE MACHINE_TYPE_NAME("sabrelite")
@@ -64,6 +65,13 @@ static void sabrelite_init(MachineState *machine)
65
/* Ethernet PHY address is 6 */
66
object_property_set_int(OBJECT(&s->soc), "fec-phy-num", 6, &error_fatal);
67
68
+ for (int i = 0; i < FSL_IMX6_NUM_CANS; i++) {
69
+ g_autofree char *bus_name = g_strdup_printf("canbus%d", i);
70
+
71
+ object_property_set_link(OBJECT(&s->soc), bus_name,
72
+ OBJECT(s->canbus[i]), &error_fatal);
73
+ }
74
+
75
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
76
77
memory_region_add_subregion(get_system_memory(), FSL_IMX6_MMDC_ADDR,
@@ -112,6 +120,21 @@ static void sabrelite_init(MachineState *machine)
120
}
121
}
122
123
+static void sabrelite_machine_instance_init(Object *obj)
124
+{
125
+ SabreliteMachineState *s = SABRELITE_MACHINE(obj);
126
+
127
+ object_property_add_link(obj, "canbus0", TYPE_CAN_BUS,
128
+ (Object **)&s->canbus[0],
129
+ object_property_allow_set_link,
130
+ 0);
131
+
132
+ object_property_add_link(obj, "canbus1", TYPE_CAN_BUS,
133
+ (Object **)&s->canbus[1],
134
+ object_property_allow_set_link,
135
+ 0);
136
+}
137
+
138
static void sabrelite_machine_class_init(ObjectClass *oc, const void *data)
139
{
140
MachineClass *mc = MACHINE_CLASS(oc);
@@ -128,6 +151,7 @@ static const TypeInfo sabrelite_machine_init_typeinfo = {
151
.name = TYPE_SABRELITE_MACHINE,
152
.parent = TYPE_MACHINE,
153
.class_init = sabrelite_machine_class_init,
154
+ .instance_init = sabrelite_machine_instance_init,
155
.instance_size = sizeof(SabreliteMachineState),
156
.abstract = false,
157
.interfaces = arm_machine_interfaces,
include/hw/arm/fsl-imx6.h
+6
@@ -30,12 +30,14 @@
30
#include "hw/sd/sdhci.h"
31
#include "hw/ssi/imx_spi.h"
32
#include "hw/net/imx_fec.h"
33
+#include "hw/net/flexcan.h"
34
#include "hw/usb/chipidea.h"
35
#include "hw/usb/imx-usb-phy.h"
36
#include "hw/pci-host/designware.h"
37
#include "hw/core/or-irq.h"
38
#include "system/memory.h"
39
#include "target/arm/cpu.h"
40
+#include "net/can_emu.h"
41
#include "qom/object.h"
42
43
#define TYPE_FSL_IMX6 "fsl-imx6"
@@ -51,6 +53,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(FslIMX6State, FSL_IMX6)
53
#define FSL_IMX6_NUM_WDTS 2
54
#define FSL_IMX6_NUM_USB_PHYS 2
55
#define FSL_IMX6_NUM_USBS 4
56
+#define FSL_IMX6_NUM_CANS 2
57
58
struct FslIMX6State {
59
/*< private >*/
@@ -73,6 +76,7 @@ struct FslIMX6State {
76
IMXUSBPHYState usbphy[FSL_IMX6_NUM_USB_PHYS];
77
ChipideaState usb[FSL_IMX6_NUM_USBS];
78
IMXFECState eth;
79
+ FlexcanState flexcan[FSL_IMX6_NUM_CANS];
80
DesignwarePCIEHost pcie;
81
OrIRQState pcie4_msi_irq;
82
MemoryRegion rom;
@@ -80,6 +84,8 @@ struct FslIMX6State {
84
MemoryRegion ocram;
85
MemoryRegion ocram_alias;
86
uint32_t phy_num;
87
+
88
+ CanBusState *canbus[FSL_IMX6_NUM_CANS];
89
};
90
91