@samitouri / QOSamiQemu / commits / c60f877912

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