Skip to contentSkip to conversation

hw/arm/sabrelite: Add FlexCAN support

PATCH Superseded Matyáš Bobek 9 participants 22 messages Apr 30 – May 28

Subsystems (3)

v3 of 6 Superseded Latest is v6 →

lore
Share & tools
lore
#0 lore raw

v3 cover hw/arm/sabrelite: Add FlexCAN support

This series adds emulation of the FlexCAN CAN controller, version 2, found in NXP i.MX6 series SoCs. The controller is integrated into fsl-imx6 and the Sabrelite ARM board.

The chip has two FlexCAN controllers, but the Linux Sabrelite device tree enables only one by default. Linux kernel with both controllers enabled has been tested to work properly (using a custom device tree).
See docs/system/devices/can.rst for an example of QEMU command line invocation.

More information about the implementation can be found in my bachelor thesis [1].

The headers (struct FlexcanRegs and flexcan_regs.h macros) were copied from the Linux kernel. Marc Kleine-Budde is the copyright holder. He has been kindly asked to provide consent, to confirm his approval for the inclusion of said header fragments into QEMU. The approval is still pending, hopefully it will be resolved soon. I will update the patchset on request if another wording/solution for the copyright statement is proposed/requested.

Changes from v2:
- moved variable declarations to the top-of-the-block
- cleanup
- removed redundant license boilerplate
- rebased onto latest master
- Link to v2: https://lore.kernel.org/qemu-devel/[email protected]/

Changes from v1 to v2:
- removed DPRINTF (turned into traces or guest errors)
- removed gotos and unnecessary continues
- register memory region shortened to actual length w/o padding
- make flexcan_* fns private
- used DEVICE(s)->canonical_path instead of allocating new strings
- changed DEVICE_NATIVE_ENDIAN to DEVICE_LITTLE_ENDIAN
- removed ugly USE macro
- used enums instead of define sequences in flexcan.c
- fixed FlexCAN KConfig conf (fixes build on non-arm-softmmu)
- fixed style and other issues from Bernhard's review
- better wording in docs
- rebased onto latest master
- Link to v1: https://lore.kernel.org/qemu-devel/[email protected]

Thanks Bernhard Beschow for the review and his patience. I borrowed some fixes from his flexcan branch at [2].

[1] http://dspace.cvut.cz/bitstream/handle/10467/122654/F3-BP-2025-Bobek-Matyas-BP_Bobek_FlexCAN_final_4.pdf
[2] https://github.com/shentok/qemu/tree/flexcan

Matyáš Bobek (7):
hw/arm/sabrelite: Open code DEFINE_MACHINE_ARM hw/arm/sabrelite: Introduce class SabreliteMachineState hw/misc/imx6_ccm: Add PLL3 and CAN clock hw/net/can/flexcan: NXP FlexCAN core emulation hw/arm: Plug FlexCAN into FSL_IMX6 and Sabrelite
tests: Add qtests for FlexCAN docs/arm/sabrelite: Mention FlexCAN support

 MAINTAINERS                   |    9 +
 docs/system/arm/sabrelite.rst |    1 +
 docs/system/devices/can.rst   |   24 +
 hw/arm/Kconfig                |    1 +
 hw/arm/fsl-imx6.c             |   29 +
 hw/arm/sabrelite.c            |   68 +-
 hw/misc/imx6_ccm.c            |   24 +
 hw/misc/trace-events          |    2 +
 hw/net/Kconfig                |    5 +
 hw/net/can/flexcan.c          | 1395 +++++++++++++++++++++++++++++++++
 hw/net/can/flexcan_regs.h     |  193 +++++
 hw/net/can/meson.build        |    1 +
 hw/net/can/trace-events       |   18 +
 include/hw/arm/fsl-imx6.h     |    6 +
 include/hw/misc/imx6_ccm.h    |    4 +
 include/hw/misc/imx_ccm.h     |    1 +
 include/hw/net/flexcan.h      |  139 ++++
 tests/qtest/flexcan-test.c    |  421 ++++++++++
 tests/qtest/meson.build       |    1 +
 19 files changed, 2332 insertions(+), 10 deletions(-)
 create mode 100644 hw/net/can/flexcan.c
 create mode 100644 hw/net/can/flexcan_regs.h
 create mode 100644 include/hw/net/flexcan.h
 create mode 100644 tests/qtest/flexcan-test.c
Signature · 1 line
2.53.0
#4 lore raw

PATCH v3 4/7 hw/net/can/flexcan: NXP FlexCAN core emulation

Added the FlexCAN2 emulator implementation core, with CAN_FLEXCAN Kconfig flag and MAINTAINERS entry.

FlexCAN2 version can be found in i.MX6 SoCs and others.

More information about the implementation can be found in [1].

[1] http://dspace.cvut.cz/bitstream/handle/10467/122654/F3-BP-2025-Bobek-Matyas-BP_Bobek_FlexCAN_final_4.pdf

---
 MAINTAINERS               |    8 +
 hw/net/Kconfig            |    5 +
 hw/net/can/flexcan.c      | 1395 +++++++++++++++++++++++++++++++++++++
 hw/net/can/flexcan_regs.h |  193 +++++
 hw/net/can/meson.build    |    1 +
 hw/net/can/trace-events   |   18 +
 include/hw/net/flexcan.h  |  139 ++++
 7 files changed, 1759 insertions(+)
 create mode 100644 hw/net/can/flexcan.c
 create mode 100644 hw/net/can/flexcan_regs.h
 create mode 100644 include/hw/net/flexcan.h
MAINTAINERS +8 -0
index f109e46172..59a3614a58 100644
@@ -2091,6 +2091,14 @@ F: hw/net/can/xlnx-*
 F: include/hw/net/xlnx-*
 F: tests/qtest/xlnx-can*-test*
 
+FlexCAN
+M: Matyas Bobek <[email protected]>
+M: Pavel Pisa <[email protected]>
+S: Maintained
+F: hw/net/can/flexcan.c
+F: hw/net/can/flexcan_regs.h
+F: include/hw/net/flexcan.h
+
 EDU
 M: Jiri Slaby <[email protected]>
 S: Maintained
hw/net/Kconfig +5 -0
index f9a1dfb80d..b56a173eed 100644
@@ -157,3 +157,8 @@ config CAN_CTUCANFD_PCI
     default y if PCI_DEVICES
     depends on PCI && CAN_CTUCANFD
     select CAN_BUS
+
+config CAN_FLEXCAN
+    bool
+    depends on IMX
+    select CAN_BUS
hw/net/can/flexcan.c new file +1395 -0

1,395 lines not on this page · raw message

hw/net/can/flexcan_regs.h new file +193 -0

193 lines not on this page · raw message

hw/net/can/meson.build +1 -0
index 7382344628..401afde2e4 100644
@@ -6,3 +6,4 @@ system_ss.add(when: 'CONFIG_CAN_CTUCANFD', if_true: files('ctucan_core.c'))
 system_ss.add(when: 'CONFIG_CAN_CTUCANFD_PCI', if_true: files('ctucan_pci.c'))
 system_ss.add(when: 'CONFIG_XLNX_ZYNQMP', if_true: files('xlnx-zynqmp-can.c'))
 system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-canfd.c'))
+system_ss.add(when: 'CONFIG_CAN_FLEXCAN', if_true: files('flexcan.c'))
hw/net/can/trace-events +18 -0
index de64ac1b31..7500f10d7a 100644
@@ -1,3 +1,21 @@
+# flexcan.c
+flexcan_irq_update(const char *inst, uint32_t mb_irqs1, uint32_t mb_irqs2, int setting) "%s: irqs1 0x%08x irqs2 0x%08x request %i"
+flexcan_set_mcr(const char *inst, const char *enabled, const char *freeze, const char *fifo, const char *rdy, const char *sync) "%s: %s %s %s %s %s"
+flexcan_mb_write(const char *inst, int mbidx, const char *code, int is_mailbox, uint32_t ctrl, uint32_t id) "%s: mbidx %i code %s is_mailbox %i ctrl 0x%08x id 0x%08x"
+flexcan_mb_lock(const char *inst, int mbidx, int had_rx_code) "%s: mbidx %i had_rx_code %i"
+flexcan_mb_unlock(const char *inst, int mbidx, const char *pending_frame) "%s: mbidx %i%s"
+flexcan_fifo_pop(const char *inst, int non_empty_before, int non_empty_after) "%s: non_empty before %i non_empty_after %i"
+flexcan_fifo_push(const char *inst, int n_occupied) "%s: n_slots_occupied %i"
+flexcan_reset(const char *inst) "%s: resetting"
+flexcan_mem_op(const char *inst, const char *op, uint32_t v, int offset, const char *reg_name, int size) "%s: %s 0x%08x at offset %i register %s size %i"
+flexcan_get_timestamp(const char *inst, int64_t time_elapsed_ms, uint32_t bitrate, uint64_t cycles, uint32_t shift, uint32_t timestamp) "%s: time_elapsed %" PRIi64 "ms bitrate %ub/s cycles %" PRIu64 " shift %u timestamp 0x%04x"
+flexcan_get_bitrate(const char *inst, uint32_t pe_freq, uint32_t prediv, uint32_t s_freq, uint32_t tseg1, uint32_t tseg2, uint32_t quata_per_bit, uint32_t bitrate) "%s: pe_freq %uHz prescaler %u s_freq %uHz tseg1 %uq tseg2 %uq total %uq/b bitrate %ub/s"
+flexcan_timer_start(const char *inst, uint32_t bitrate, uint32_t value) "%s: bitrate %ub/s value 0x%04x"
+flexcan_timer_stop(const char *inst, uint32_t bitrate, uint32_t value) "%s: bitrate %ub/s value 0x%04x"
+flexcan_timer_overflow(const char *inst, int64_t current_time, int64_t timer_start, int64_t elapsed_ns) "%s: current_time %" PRIi64 "timer_start %" PRIi64 "elapsed_ns %" PRIi64
+flexcan_mb_rx_check_mb(const char *inst, int mbidx, const char *code, int is_matched, int is_ftr, int is_serviced, int is_locked) "%s: checking mb %i code %s is_matched %i is_free_to_receive %i is_serviced %i is_locked %i"
+flexcan_receive(const char *inst, size_t n_frames) "%s: received %zu frames"
+
 # xlnx-zynqmp-can.c
 xlnx_can_update_irq(uint32_t isr, uint32_t ier, uint32_t irq) "ISR: 0x%08x IER: 0x%08x IRQ: 0x%08x"
 xlnx_can_reset(uint32_t val) "Resetting controller with value = 0x%08x"
include/hw/net/flexcan.h new file +139 -0

139 lines not on this page · raw message

Signature · 1 line
2.53.0
#2 lore raw

PATCH v3 2/7 hw/arm/sabrelite: Introduce class SabreliteMachineState

In reply to Matyáš Bobek

Create full class SabreliteMachineState extending MachineState.

Previously, Sabrelite board MachineState was declared indirectly by the DEFINE_MACHINE_ARM macro. FslIMX6State was only instantiated in the sabrelite_init function. For FlexCAN device, machine properties will be used to select QEMU CAN buses. A custom class is therefore required, so the CanBusState "connections" can then be added as fields.

---
 hw/arm/sabrelite.c | 28 ++++++++++++++++++----------
 1 file changed, 18 insertions(+), 10 deletions(-)
hw/arm/sabrelite.c +18 -10
index 04484aaa14..7e036e6388 100644
@@ -20,6 +20,15 @@
 #include "qemu/error-report.h"
 #include "system/qtest.h"
 
+struct SabreliteMachineState {
+    MachineState parent_obj;
+
+    FslIMX6State soc;
+};
+
+#define TYPE_SABRELITE_MACHINE MACHINE_TYPE_NAME("sabrelite")
+OBJECT_DECLARE_SIMPLE_TYPE(SabreliteMachineState, SABRELITE_MACHINE)
+
 static struct arm_boot_info sabrelite_binfo = {
     /* DDR memory start */
     .loader_start = FSL_IMX6_MMDC_ADDR,
@@ -41,7 +50,7 @@ static void sabrelite_reset_secondary(ARMCPU *cpu,
 
 static void sabrelite_init(MachineState *machine)
 {
-    FslIMX6State *s;
+    SabreliteMachineState *s = SABRELITE_MACHINE(machine);
 
     /* Check the amount of memory is compatible with the SOC */
     if (machine->ram_size > FSL_IMX6_MMDC_SIZE) {
@@ -50,13 +59,12 @@ static void sabrelite_init(MachineState *machine)
         exit(1);
     }
 
-    s = FSL_IMX6(object_new(TYPE_FSL_IMX6));
-    object_property_add_child(OBJECT(machine), "soc", OBJECT(s));
+    object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_FSL_IMX6);
 
     /* Ethernet PHY address is 6 */
-    object_property_set_int(OBJECT(s), "fec-phy-num", 6, &error_fatal);
+    object_property_set_int(OBJECT(&s->soc), "fec-phy-num", 6, &error_fatal);
 
-    qdev_realize(DEVICE(s), NULL, &error_fatal);
+    qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
 
     memory_region_add_subregion(get_system_memory(), FSL_IMX6_MMDC_ADDR,
                                 machine->ram);
@@ -70,7 +78,7 @@ static void sabrelite_init(MachineState *machine)
         /* Add the sst25vf016b NOR FLASH memory to first SPI */
         Object *spi_dev;
 
-        spi_dev = object_resolve_path_component(OBJECT(s), "spi1");
+        spi_dev = object_resolve_path_component(OBJECT(&s->soc), "spi1");
         if (spi_dev) {
             SSIBus *spi_bus;
 
@@ -89,7 +97,7 @@ static void sabrelite_init(MachineState *machine)
                 qdev_realize_and_unref(flash_dev, BUS(spi_bus), &error_fatal);
 
                 cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0);
-                qdev_connect_gpio_out(DEVICE(&s->gpio[2]), 19, cs_line);
+                qdev_connect_gpio_out(DEVICE(&s->soc.gpio[2]), 19, cs_line);
             }
         }
     }
@@ -100,7 +108,7 @@ static void sabrelite_init(MachineState *machine)
     sabrelite_binfo.secondary_cpu_reset_hook = sabrelite_reset_secondary;
 
     if (!qtest_enabled()) {
-        arm_load_kernel(&s->cpu[0], machine, &sabrelite_binfo);
+        arm_load_kernel(&s->soc.cpu[0], machine, &sabrelite_binfo);
     }
 }
 
@@ -117,10 +125,10 @@ static void sabrelite_machine_class_init(ObjectClass *oc, const void *data)
 }
 
 static const TypeInfo sabrelite_machine_init_typeinfo = {
-    .name          = MACHINE_TYPE_NAME("sabrelite"),
+    .name          = TYPE_SABRELITE_MACHINE,
     .parent        = TYPE_MACHINE,
     .class_init    = sabrelite_machine_class_init,
-    .instance_size = sizeof(MachineState),
+    .instance_size = sizeof(SabreliteMachineState),
     .abstract      = false,
     .interfaces    = arm_machine_interfaces,
 };
Signature · 1 line
2.53.0
#6 lore raw

PATCH v3 6/7 tests: Add qtests for FlexCAN

In reply to Matyáš Bobek

The tests do not test all of the FlexCAN emulator functionality.

---
 MAINTAINERS                |   1 +
 tests/qtest/flexcan-test.c | 421 +++++++++++++++++++++++++++++++++++++
 tests/qtest/meson.build    |   1 +
 3 files changed, 423 insertions(+)
 create mode 100644 tests/qtest/flexcan-test.c
MAINTAINERS +1 -0
index 59a3614a58..7b1fe85961 100644
@@ -2098,6 +2098,7 @@ S: Maintained
 F: hw/net/can/flexcan.c
 F: hw/net/can/flexcan_regs.h
 F: include/hw/net/flexcan.h
+F: tests/qtest/flexcan-test.c
 
 EDU
 M: Jiri Slaby <[email protected]>
tests/qtest/flexcan-test.c new file +421 -0

421 lines not on this page · raw message

tests/qtest/meson.build +1 -0
index 43f83ffd3a..17e68d9963 100644
@@ -248,6 +248,7 @@ qtests_arm = \
   (config_all_devices.has_key('CONFIG_MICROBIT') ? ['microbit-test'] : []) + \
   (config_all_devices.has_key('CONFIG_STM32L4X5_SOC') ? qtests_stm32l4x5 : []) + \
   (config_all_devices.has_key('CONFIG_FSI_APB2OPB_ASPEED') ? ['aspeed_fsi-test'] : []) + \
+  (config_all_devices.has_key('CONFIG_CAN_FLEXCAN') ? ['flexcan-test'] : []) + \
   (config_all_devices.has_key('CONFIG_STM32L4X5_SOC') and
    config_all_devices.has_key('CONFIG_DM163')? ['dm163-test'] : []) + \
   ['arm-cpu-features',
Signature · 1 line
2.53.0
#3 lore raw

PATCH v3 3/7 hw/misc/imx6_ccm: Add PLL3 and CAN clock

In reply to Matyáš Bobek

Add fixed frequency (480 MHz) PLL3, of which the FlexCAN clock is derived, and compute FlexCAN frequency based on the divider configuration (CCM_CSCMR2).

The clock frequency will be used for computing timestamps in FlexCAN emulator.

---
 hw/misc/imx6_ccm.c         | 24 ++++++++++++++++++++++++
 hw/misc/trace-events       |  2 ++
 include/hw/misc/imx6_ccm.h |  4 ++++
 include/hw/misc/imx_ccm.h  |  1 +
 4 files changed, 31 insertions(+)
hw/misc/imx6_ccm.c +24 -0
index a10b67d396..45fdd0d5a8 100644
@@ -257,6 +257,15 @@ static uint64_t imx6_analog_get_pll2_clk(IMX6CCMState *dev)
     return freq;
 }
 
+static uint64_t imx6_analog_get_pll3_clk(IMX6CCMState *dev)
+{
+    uint64_t freq = 480000000;
+
+    trace_imx6_analog_get_pll3_clk(freq);
+
+    return freq;
+}
+
 static uint64_t imx6_analog_get_pll2_pfd0_clk(IMX6CCMState *dev)
 {
     uint64_t freq = 0;
@@ -344,6 +353,18 @@ static uint64_t imx6_ccm_get_per_clk(IMX6CCMState *dev)
     return freq;
 }
 
+static uint64_t imx6_ccm_get_can_clk(IMX6CCMState *dev)
+{
+    uint64_t freq = 0;
+
+    freq = imx6_analog_get_pll3_clk(dev) / 8;
+    freq /= (1 + EXTRACT(dev->ccm[CCM_CSCMR2], CAN_CLK_PODF));
+
+    trace_imx6_ccm_get_can_clk(freq);
+
+    return freq;
+}
+
 static uint32_t imx6_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
 {
     uint32_t freq = 0;
@@ -358,6 +379,9 @@ static uint32_t imx6_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
     case CLK_IPG_HIGH:
         freq = imx6_ccm_get_per_clk(s);
         break;
+    case CLK_CAN:
+        freq = imx6_ccm_get_can_clk(s);
+        break;
     case CLK_32k:
         freq = CKIL_FREQ;
         break;
hw/misc/trace-events +2 -0
index b88accc437..99910fc068 100644
@@ -242,11 +242,13 @@ imx6_analog_get_periph_clk(uint32_t freq) "freq = %u Hz"
 imx6_analog_get_pll2_clk(uint32_t freq) "freq = %u Hz"
 imx6_analog_get_pll2_pfd0_clk(uint32_t freq) "freq = %u Hz"
 imx6_analog_get_pll2_pfd2_clk(uint32_t freq) "freq = %u Hz"
+imx6_analog_get_pll3_clk(uint32_t freq) "freq = %u Hz"
 imx6_analog_read(const char *reg, uint32_t value) "reg[%s] => 0x%" PRIx32
 imx6_analog_write(const char *reg, uint32_t value) "reg[%s] <= 0x%" PRIx32
 imx6_ccm_get_ahb_clk(uint32_t freq) "freq = %u Hz"
 imx6_ccm_get_ipg_clk(uint32_t freq) "freq = %u Hz"
 imx6_ccm_get_per_clk(uint32_t freq) "freq = %u Hz"
+imx6_ccm_get_can_clk(uint32_t freq) "freq = %u Hz"
 imx6_ccm_get_clock_frequency(unsigned clock, uint32_t freq) "(Clock = %d) = %u"
 imx6_ccm_read(const char *reg, uint32_t value) "reg[%s] => 0x%" PRIx32
 imx6_ccm_reset(void) ""
include/hw/misc/imx6_ccm.h +4 -0
index ccf46d7353..a54b940686 100644
@@ -164,6 +164,10 @@
 #define PERCLK_PODF_SHIFT        (0)
 #define PERCLK_PODF_LENGTH       (6)
 
+/* CCM_CSCMR2 */
+#define CAN_CLK_PODF_SHIFT       (2)
+#define CAN_CLK_PODF_LENGTH      (6)
+
 /* CCM_ANALOG_PFD_528 */
 #define PFD0_FRAC_SHIFT          (0)
 #define PFD0_FRAC_LENGTH         (6)
include/hw/misc/imx_ccm.h +1 -0
index c4212d04ea..6839716ea3 100644
@@ -46,6 +46,7 @@ typedef enum  {
     CLK_EXT,
     CLK_HIGH_DIV,
     CLK_HIGH,
+    CLK_CAN,
 } IMXClk;
 
 struct IMXCCMClass {
Signature · 1 line
2.53.0
#7 lore raw

PATCH v3 7/7 docs/arm/sabrelite: Mention FlexCAN support

In reply to Matyáš Bobek

Also added example command line usage of the Sabrelite board with FlexCAN controllers.

---
 docs/system/arm/sabrelite.rst |  1 +
 docs/system/devices/can.rst   | 24 ++++++++++++++++++++++++
 2 files changed, 25 insertions(+)
docs/system/arm/sabrelite.rst +1 -0
index 4ccb0560af..d3a3c01dd6 100644
@@ -24,6 +24,7 @@ The SABRE Lite machine supports the following devices:
  * 4 SDHC storage controllers
  * 4 USB 2.0 host controllers
  * 5 ECSPI controllers
+ * 2 FlexCAN CAN controllers
  * 1 SST 25VF016B flash
 
 Please note above list is a complete superset the QEMU SABRE Lite machine can
docs/system/devices/can.rst +24 -0
index 09121836fd..622f898952 100644
@@ -173,6 +173,30 @@ The test can also be run the other way around, generating messages in the
 guest system and capturing them in the host system. Other combinations are
 also possible.
 
+Examples on how to use CAN emulation for FlexCAN on SabreLite board
+-------------------------------------------------------------------
+FlexCANs are connected to QEMU CAN buses by passing the bus IDs as machine
+properties:
+
+* property ``canbus0`` for connecting ``flexcan1``
+* property ``canbus1`` for connecting ``flexcan2``
+
+Note that upstream Linux SabreLite DTs have only a single FlexCAN (``flexcan1``)
+enabled.
+
+An example command to run QEMU emulating a Sabrelite development board
+with both FlexCANs connected to a single QEMU CAN bus (called ``qcan0``),
+bridged to host system ``can0`` interface::
+
+  qemu-system-arm -M sabrelite -smp 4 -m 1G \
+    -object can-bus,id=qcan0 \
+    -machine canbus0=qcan0 -machine canbus1=qcan0 \
+    -object can-host-socketcan,if=can0,canbus=qcan0,id=qcan0-socketcan \
+    -kernel ... -dtb ... -initrd ...
+
+Note that in the Linux guest, bitrate for the FlexCAN device is ignored,
+but needs to be set via the ``ip`` command.
+
 Links to other resources
 ------------------------
 
Signature · 1 line
2.53.0
#5 lore raw

PATCH v3 5/7 hw/arm: Plug FlexCAN into FSL_IMX6 and Sabrelite

In reply to Matyáš Bobek

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.

---
 hw/arm/Kconfig            |  1 +
 hw/arm/fsl-imx6.c         | 29 +++++++++++++++++++++++++++++
 hw/arm/sabrelite.c        | 24 ++++++++++++++++++++++++
 include/hw/arm/fsl-imx6.h |  6 ++++++
 4 files changed, 60 insertions(+)
hw/arm/Kconfig +1 -0
index c31752e83a..5bd0d0972e 100644
@@ -518,6 +518,7 @@ config FSL_IMX6
     select IMX_FEC
     select IMX_I2C
     select IMX_USBPHY
+    select CAN_FLEXCAN
     select WDT_IMX2
     select PL310  # cache controller
     select PCI_EXPRESS_DESIGNWARE
hw/arm/fsl-imx6.c +29 -0
index f663ddbf0a..337921d17d 100644
@@ -90,6 +90,10 @@ static void fsl_imx6_init(Object *obj)
         snprintf(name, NAME_SIZE, "spi%d", i + 1);
         object_initialize_child(obj, name, &s->spi[i], TYPE_IMX_SPI);
     }
+    for (i = 0; i < FSL_IMX6_NUM_CANS; i++) {
+        snprintf(name, NAME_SIZE, "flexcan%d", i + 1);
+        object_initialize_child(obj, name, &s->can[i], TYPE_CAN_FLEXCAN);
+    }
     for (i = 0; i < FSL_IMX6_NUM_WDTS; i++) {
         snprintf(name, NAME_SIZE, "wdt%d", i);
         object_initialize_child(obj, name, &s->wdt[i], TYPE_IMX2_WDT);
@@ -377,6 +381,27 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
                            qdev_get_gpio_in(gic, spi_table[i].irq));
     }
 
+    /* Initialize all FLEXCANs */
+    for (i = 0; i < FSL_IMX6_NUM_CANS; i++) {
+        static const struct {
+            hwaddr addr;
+            unsigned int irq;
+        } flexcan_table[FSL_IMX6_NUM_CANS] = {
+            { FSL_IMX6_CAN1_ADDR, FSL_IMX6_FLEXCAN1_IRQ },
+            { FSL_IMX6_CAN2_ADDR, FSL_IMX6_FLEXCAN2_IRQ },
+        };
+
+        s->can[i].ccm = IMX_CCM(&s->ccm);
+        object_property_set_link(OBJECT(&s->can[i]), "canbus",
+                                 OBJECT(s->canbus[i]), &error_abort);
+
+        sysbus_realize(SYS_BUS_DEVICE(&s->can[i]), &error_abort);
+
+        sysbus_mmio_map(SYS_BUS_DEVICE(&s->can[i]), 0, flexcan_table[i].addr);
+        sysbus_connect_irq(SYS_BUS_DEVICE(&s->can[i]), 0,
+                           qdev_get_gpio_in(gic, flexcan_table[i].irq));
+    }
+
     object_property_set_uint(OBJECT(&s->eth), "phy-num", s->phy_num,
                              &error_abort);
     qemu_configure_nic_device(DEVICE(&s->eth), true, NULL);
@@ -480,6 +505,10 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
 
 static const Property fsl_imx6_properties[] = {
     DEFINE_PROP_UINT32("fec-phy-num", FslIMX6State, phy_num, 0),
+    DEFINE_PROP_LINK("canbus0", FslIMX6State, canbus[0], TYPE_CAN_BUS,
+                     CanBusState *),
+    DEFINE_PROP_LINK("canbus1", FslIMX6State, canbus[1], TYPE_CAN_BUS,
+                     CanBusState *),
 };
 
 static void fsl_imx6_class_init(ObjectClass *oc, const void *data)
hw/arm/sabrelite.c +24 -0
index 7e036e6388..84bbc2f979 100644
@@ -24,6 +24,7 @@ struct SabreliteMachineState {
     MachineState parent_obj;
 
     FslIMX6State soc;
+    CanBusState *canbus[FSL_IMX6_NUM_CANS];
 };
 
 #define TYPE_SABRELITE_MACHINE MACHINE_TYPE_NAME("sabrelite")
@@ -64,6 +65,13 @@ static void sabrelite_init(MachineState *machine)
     /* Ethernet PHY address is 6 */
     object_property_set_int(OBJECT(&s->soc), "fec-phy-num", 6, &error_fatal);
 
+    for (int i = 0; i < FSL_IMX6_NUM_CANS; i++) {
+        g_autofree char *bus_name = g_strdup_printf("canbus%d", i);
+
+        object_property_set_link(OBJECT(&s->soc), bus_name,
+                                 OBJECT(s->canbus[i]), &error_fatal);
+    }
+
     qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
 
     memory_region_add_subregion(get_system_memory(), FSL_IMX6_MMDC_ADDR,
@@ -112,6 +120,21 @@ static void sabrelite_init(MachineState *machine)
     }
 }
 
+static void sabrelite_machine_instance_init(Object *obj)
+{
+    SabreliteMachineState *s = SABRELITE_MACHINE(obj);
+
+    object_property_add_link(obj, "canbus0", TYPE_CAN_BUS,
+                             (Object **)&s->canbus[0],
+                             object_property_allow_set_link,
+                             0);
+
+    object_property_add_link(obj, "canbus1", TYPE_CAN_BUS,
+                             (Object **)&s->canbus[1],
+                             object_property_allow_set_link,
+                             0);
+}
+
 static void sabrelite_machine_class_init(ObjectClass *oc, const void *data)
 {
     MachineClass *mc = MACHINE_CLASS(oc);
@@ -128,6 +151,7 @@ static const TypeInfo sabrelite_machine_init_typeinfo = {
     .name          = TYPE_SABRELITE_MACHINE,
     .parent        = TYPE_MACHINE,
     .class_init    = sabrelite_machine_class_init,
+    .instance_init = sabrelite_machine_instance_init,
     .instance_size = sizeof(SabreliteMachineState),
     .abstract      = false,
     .interfaces    = arm_machine_interfaces,
include/hw/arm/fsl-imx6.h +6 -0
index cddd100dd6..8ea1677e86 100644
@@ -30,12 +30,14 @@
 #include "hw/sd/sdhci.h"
 #include "hw/ssi/imx_spi.h"
 #include "hw/net/imx_fec.h"
+#include "hw/net/flexcan.h"
 #include "hw/usb/chipidea.h"
 #include "hw/usb/imx-usb-phy.h"
 #include "hw/pci-host/designware.h"
 #include "hw/core/or-irq.h"
 #include "system/memory.h"
 #include "target/arm/cpu.h"
+#include "net/can_emu.h"
 #include "qom/object.h"
 
 #define TYPE_FSL_IMX6 "fsl-imx6"
@@ -51,6 +53,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(FslIMX6State, FSL_IMX6)
 #define FSL_IMX6_NUM_WDTS 2
 #define FSL_IMX6_NUM_USB_PHYS 2
 #define FSL_IMX6_NUM_USBS 4
+#define FSL_IMX6_NUM_CANS 2
 
 struct FslIMX6State {
     /*< private >*/
@@ -73,6 +76,7 @@ struct FslIMX6State {
     IMXUSBPHYState     usbphy[FSL_IMX6_NUM_USB_PHYS];
     ChipideaState      usb[FSL_IMX6_NUM_USBS];
     IMXFECState        eth;
+    FlexcanState       can[FSL_IMX6_NUM_CANS];
     DesignwarePCIEHost pcie;
     OrIRQState         pcie4_msi_irq;
     MemoryRegion       rom;
@@ -80,6 +84,8 @@ struct FslIMX6State {
     MemoryRegion       ocram;
     MemoryRegion       ocram_alias;
     uint32_t           phy_num;
+
+    CanBusState       *canbus[FSL_IMX6_NUM_CANS];
 };
 
 
Signature · 1 line
2.53.0
#1 lore raw

PATCH v3 1/7 hw/arm/sabrelite: Open code DEFINE_MACHINE_ARM

In reply to Matyáš Bobek

Open code the DEFINE_MACHINE_ARM macro in preparation of creating SabreliteMachineState class.

---
 hw/arm/sabrelite.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)
hw/arm/sabrelite.c +18 -2
index db5669c5c2..04484aaa14 100644
@@ -104,8 +104,10 @@ static void sabrelite_init(MachineState *machine)
     }
 }
 
-static void sabrelite_machine_init(MachineClass *mc)
+static void sabrelite_machine_class_init(ObjectClass *oc, const void *data)
 {
+    MachineClass *mc = MACHINE_CLASS(oc);
+
     mc->desc = "Freescale i.MX6 Quad SABRE Lite Board (Cortex-A9)";
     mc->init = sabrelite_init;
     mc->max_cpus = FSL_IMX6_NUM_CPUS;
@@ -114,4 +116,18 @@ static void sabrelite_machine_init(MachineClass *mc)
     mc->auto_create_sdcard = true;
 }
 
-DEFINE_MACHINE_ARM("sabrelite", sabrelite_machine_init)
+static const TypeInfo sabrelite_machine_init_typeinfo = {
+    .name          = MACHINE_TYPE_NAME("sabrelite"),
+    .parent        = TYPE_MACHINE,
+    .class_init    = sabrelite_machine_class_init,
+    .instance_size = sizeof(MachineState),
+    .abstract      = false,
+    .interfaces    = arm_machine_interfaces,
+};
+
+static void sabrelite_machine_init_register_types(void)
+{
+    type_register_static(&sabrelite_machine_init_typeinfo);
+}
+
+type_init(sabrelite_machine_init_register_types)
Signature · 1 line
2.53.0
#8 lore raw
In reply to Matyáš Bobek

Am 30. April 2026 18:26:02 UTC schrieb "Matyáš Bobek" <[email protected]>:

Quoted 14 lines

This series adds emulation of the FlexCAN CAN controller, version 2, found in NXP i.MX6 series SoCs. The controller is integrated into fsl-imx6 and the Sabrelite ARM board.

The chip has two FlexCAN controllers, but the Linux Sabrelite device tree enables only one by default. Linux kernel with both controllers enabled has been tested to work properly (using a custom device tree).
See docs/system/devices/can.rst for an example of QEMU command line invocation.

More information about the implementation can be found in my bachelor thesis [1].

Quoted 7 lines

The headers (struct FlexcanRegs and flexcan_regs.h macros) were copied from the Linux kernel. Marc Kleine-Budde is the copyright holder. He has been kindly asked to provide consent, to confirm his approval for the inclusion of said header fragments into QEMU. The approval is still pending, hopefully it will be resolved soon. I will update the patchset on request if another wording/solution for the copyright statement is proposed/requested.

Tested with imx8mp-evk: https://github.com/shentok/qemu/commits/imx8mp-flexcan/ which works excellent. Next step after this series is merged would be upstreaming that branch.

I guess the only open issue is the licensing of struct FlexcanRegs [1] which originates from Linux? How do we proceed here?

Best regards,
Bernhard

[1] https://lore.kernel.org/qemu-devel/[email protected]/

Quoted 63 lines

Changes from v2:
- moved variable declarations to the top-of-the-block
- cleanup
- removed redundant license boilerplate
- rebased onto latest master
- Link to v2: https://lore.kernel.org/qemu-devel/[email protected]/

Changes from v1 to v2:
- removed DPRINTF (turned into traces or guest errors)
- removed gotos and unnecessary continues
- register memory region shortened to actual length w/o padding
- make flexcan_* fns private
- used DEVICE(s)->canonical_path instead of allocating new strings
- changed DEVICE_NATIVE_ENDIAN to DEVICE_LITTLE_ENDIAN
- removed ugly USE macro
- used enums instead of define sequences in flexcan.c
- fixed FlexCAN KConfig conf (fixes build on non-arm-softmmu)
- fixed style and other issues from Bernhard's review
- better wording in docs
- rebased onto latest master
- Link to v1: https://lore.kernel.org/qemu-devel/[email protected]

Thanks Bernhard Beschow for the review and his patience. I borrowed some fixes from his flexcan branch at [2].

[1] http://dspace.cvut.cz/bitstream/handle/10467/122654/F3-BP-2025-Bobek-Matyas-BP_Bobek_FlexCAN_final_4.pdf
[2] https://github.com/shentok/qemu/tree/flexcan

Matyáš Bobek (7):
hw/arm/sabrelite: Open code DEFINE_MACHINE_ARM hw/arm/sabrelite: Introduce class SabreliteMachineState hw/misc/imx6_ccm: Add PLL3 and CAN clock hw/net/can/flexcan: NXP FlexCAN core emulation hw/arm: Plug FlexCAN into FSL_IMX6 and Sabrelite
tests: Add qtests for FlexCAN docs/arm/sabrelite: Mention FlexCAN support

MAINTAINERS                   |    9 +
docs/system/arm/sabrelite.rst |    1 +
docs/system/devices/can.rst   |   24 +
hw/arm/Kconfig                |    1 +
hw/arm/fsl-imx6.c             |   29 +
hw/arm/sabrelite.c            |   68 +-
hw/misc/imx6_ccm.c            |   24 +
hw/misc/trace-events          |    2 +
hw/net/Kconfig                |    5 +
hw/net/can/flexcan.c          | 1395 +++++++++++++++++++++++++++++++++
hw/net/can/flexcan_regs.h     |  193 +++++
hw/net/can/meson.build        |    1 +
hw/net/can/trace-events       |   18 +
include/hw/arm/fsl-imx6.h     |    6 +
include/hw/misc/imx6_ccm.h    |    4 +
include/hw/misc/imx_ccm.h     |    1 +
include/hw/net/flexcan.h      |  139 ++++
tests/qtest/flexcan-test.c    |  421 ++++++++++
tests/qtest/meson.build       |    1 +
19 files changed, 2332 insertions(+), 10 deletions(-)

create mode 100644 hw/net/can/flexcan.c
create mode 100644 hw/net/can/flexcan_regs.h
create mode 100644 include/hw/net/flexcan.h
create mode 100644 tests/qtest/flexcan-test.c

#9 lore raw
Quoted 26 lines · Bernhard Beschow

Am 30. April 2026 18:26:02 UTC schrieb "Matyáš Bobek" <[email protected]>:

Quoted 14 lines

This series adds emulation of the FlexCAN CAN controller, version 2, found in NXP i.MX6 series SoCs. The controller is integrated into fsl-imx6 and the Sabrelite ARM board.

The chip has two FlexCAN controllers, but the Linux Sabrelite device tree enables only one by default. Linux kernel with both controllers enabled has been tested to work properly (using a custom device tree).
See docs/system/devices/can.rst for an example of QEMU command line invocation.

More information about the implementation can be found in my bachelor thesis [1].

Quoted 7 lines

The headers (struct FlexcanRegs and flexcan_regs.h macros) were copied from the Linux kernel. Marc Kleine-Budde is the copyright holder. He has been kindly asked to provide consent, to confirm his approval for the inclusion of said header fragments into QEMU. The approval is still pending, hopefully it will be resolved soon. I will update the patchset on request if another wording/solution for the copyright statement is proposed/requested.

Quoted 8 lines

Tested with imx8mp-evk: https://github.com/shentok/qemu/commits/imx8mp-flexcan/ which works excellent. Next step after this series is merged would be upstreaming that branch.

I guess the only open issue is the licensing of struct FlexcanRegs [1] which originates from Linux? How do we proceed here?

Best regards,
Bernhard

[1] https://lore.kernel.org/qemu-devel/[email protected]/

Could you say what the problem is? In general there is no problem with taking header structs from the Linux kernel, as they are GPL-2-only and that is a QEMU-compatible license. The relevant source files or pieces of source files would need to be noted as 2-only rather than our default of 2-or-later, but that is doable -- we already do that for other things we have borrowed from the kernel.

thanks
-- PMM

#10 lore raw

Am 5. Mai 2026 18:41:52 UTC schrieb Peter Maydell <[email protected]>:

Quoted 36 lines · Bernhard Beschow
Quoted 26 lines

Am 30. April 2026 18:26:02 UTC schrieb "Matyáš Bobek" <[email protected]>:

Quoted 14 lines

This series adds emulation of the FlexCAN CAN controller, version 2, found in NXP i.MX6 series SoCs. The controller is integrated into fsl-imx6 and the Sabrelite ARM board.

The chip has two FlexCAN controllers, but the Linux Sabrelite device tree enables only one by default. Linux kernel with both controllers enabled has been tested to work properly (using a custom device tree).
See docs/system/devices/can.rst for an example of QEMU command line invocation.

More information about the implementation can be found in my bachelor thesis [1].

Quoted 7 lines

The headers (struct FlexcanRegs and flexcan_regs.h macros) were copied from the Linux kernel. Marc Kleine-Budde is the copyright holder. He has been kindly asked to provide consent, to confirm his approval for the inclusion of said header fragments into QEMU. The approval is still pending, hopefully it will be resolved soon. I will update the patchset on request if another wording/solution for the copyright statement is proposed/requested.

Quoted 8 lines

Tested with imx8mp-evk: https://github.com/shentok/qemu/commits/imx8mp-flexcan/ which works excellent. Next step after this series is merged would be upstreaming that branch.

I guess the only open issue is the licensing of struct FlexcanRegs [1] which originates from Linux? How do we proceed here?

Best regards,
Bernhard

[1] https://lore.kernel.org/qemu-devel/[email protected]/

Quoted 7 lines

Could you say what the problem is? In general there is no problem with taking header structs from the Linux kernel, as they are GPL-2-only and that is a QEMU-compatible license. The relevant source files or pieces of source files would need to be noted as 2-only rather than our default of 2-or-later, but that is doable -- we already do that for other things we have borrowed from the kernel.

In https://lore.kernel.org/qemu-devel/[email protected]/ I raised this review question: "The following structure looks like being based on Linux. Does this affect the copyright of this file?" I was just asking for advice and I'm glad the solution is that easy.

Best regards,
Bernhard

#11 lore raw
Quoted 17 lines · Bernhard Beschow

Am 5. Mai 2026 18:41:52 UTC schrieb Peter Maydell <[email protected]>:

Quoted 8 lines · Bernhard Beschow
Quoted 6 lines

I guess the only open issue is the licensing of struct FlexcanRegs [1] which originates from Linux? How do we proceed here?

Best regards,
Bernhard

[1] https://lore.kernel.org/qemu-devel/[email protected]/

Quoted 7 lines

Could you say what the problem is? In general there is no problem with taking header structs from the Linux kernel, as they are GPL-2-only and that is a QEMU-compatible license. The relevant source files or pieces of source files would need to be noted as 2-only rather than our default of 2-or-later, but that is doable -- we already do that for other things we have borrowed from the kernel.

Quoted 1 line

In https://lore.kernel.org/qemu-devel/[email protected]/ I raised this review question: "The following structure looks like being based on Linux. Does this affect the copyright of this file?" I was just asking for advice and I'm glad the solution is that easy.

If the struct was copied from the kernel, then it's GPL-2.0-only, and we should just note the license and where we got the code from.

If the struct is just very similar to the kernel's one because it's the obvious representation taken from the datasheet, then it's not related to the kernel code and we can treat it as GPL-2.0-or-later like the rest of the file.

Since Matyáš says in the cover letter here "the headers (struct FlexcanRegs and flexcan_regs.h macros) were copied from the Linux kernel" then we're in case 1.

You can mark this up by having the file's SPDX tag be "SPDX-License-Identifier: (GPL-2.0-only AND GPL-2.0-or-later)" Then have a normal comment in the file next to the part that is 2.0-only that says
/*
* [This struct / the macros X, Y, Z / whatever ] are borrowed
* from the Linux kernel, and so (unlike the rest of this file)
* they are GPL-2.0-only.
*/

thanks
-- PMM

#12 lore raw

Am 8. Mai 2026 12:10:21 UTC schrieb Peter Maydell <[email protected]>:

Quoted 32 lines · Bernhard Beschow
Quoted 17 lines

Am 5. Mai 2026 18:41:52 UTC schrieb Peter Maydell <[email protected]>:

Quoted 8 lines · Bernhard Beschow
Quoted 6 lines

I guess the only open issue is the licensing of struct FlexcanRegs [1] which originates from Linux? How do we proceed here?

Best regards,
Bernhard

[1] https://lore.kernel.org/qemu-devel/[email protected]/

Quoted 7 lines

Could you say what the problem is? In general there is no problem with taking header structs from the Linux kernel, as they are GPL-2-only and that is a QEMU-compatible license. The relevant source files or pieces of source files would need to be noted as 2-only rather than our default of 2-or-later, but that is doable -- we already do that for other things we have borrowed from the kernel.

Quoted 1 line

In https://lore.kernel.org/qemu-devel/[email protected]/ I raised this review question: "The following structure looks like being based on Linux. Does this affect the copyright of this file?" I was just asking for advice and I'm glad the solution is that easy.

If the struct was copied from the kernel, then it's GPL-2.0-only, and we should just note the license and where we got the code from.

If the struct is just very similar to the kernel's one because it's the obvious representation taken from the datasheet, then it's not related to the kernel code and we can treat it as GPL-2.0-or-later like the rest of the file.

Since Matyáš says in the cover letter here "the headers (struct FlexcanRegs and flexcan_regs.h macros) were copied from the Linux kernel" then we're in case 1.

Quoted 9 lines

You can mark this up by having the file's SPDX tag be "SPDX-License-Identifier: (GPL-2.0-only AND GPL-2.0-or-later)" Then have a normal comment in the file next to the part that is 2.0-only that says
/*
* [This struct / the macros X, Y, Z / whatever ] are borrowed
* from the Linux kernel, and so (unlike the rest of this file)
* they are GPL-2.0-only.
*/

Ping

Any news? With just the license issue remaining, it would be nice to get FlexCAN support into the upcoming release.

Quoted 3 lines

thanks
-- PMM

#13 lore raw

Hello Marc,

please, provide your opinion, the license for small Linux kernel headers excepts seems to be the last and only blocker for mainlining. See the copied code below.

Quoted 50 lines · On Wednesday 27 of May 2026 12:42:23 Bernhard Beschow wrote:

Am 8. Mai 2026 12:10:21 UTC schrieb Peter Maydell <[email protected]>:

Quoted 39 lines · Bernhard Beschow
Quoted 20 lines

Am 5. Mai 2026 18:41:52 UTC schrieb Peter Maydell <[email protected]>:

Quoted 11 lines · Bernhard Beschow
Quoted 9 lines

I guess the only open issue is the licensing of struct FlexcanRegs
[1] which originates from Linux? How do we proceed here?

Best regards,
Bernhard

[1]
https://lore.kernel.org/qemu-devel/[email protected]
z/

Quoted 7 lines

Could you say what the problem is? In general there is no problem with taking header structs from the Linux kernel, as they are GPL-2-only and that is a QEMU-compatible license. The relevant source files or pieces of source files would need to be noted as 2-only rather than our default of 2-or-later, but that is doable -- we already do that for other things we have borrowed from the kernel.

Quoted 5 lines

In
https://lore.kernel.org/qemu-devel/f3cb3166-c3f8-4ed8-8c9a-cbf48b071d1e@
gmail.com/ I raised this review question: "The following structure looks like being based on Linux. Does this affect the copyright of this file?" I was just asking for advice and I'm glad the solution is that easy.

If the struct was copied from the kernel, then it's GPL-2.0-only, and we should just note the license and where we got the code from.

If the struct is just very similar to the kernel's one because it's the obvious representation taken from the datasheet, then it's not related to the kernel code and we can treat it as GPL-2.0-or-later like the rest of the file.

Since Matyáš says in the cover letter here "the headers (struct FlexcanRegs and flexcan_regs.h macros) were copied from the Linux kernel" then we're in case 1.

Quoted 9 lines

You can mark this up by having the file's SPDX tag be "SPDX-License-Identifier: (GPL-2.0-only AND GPL-2.0-or-later)" Then have a normal comment in the file next to the part that is 2.0-only that says
/*
* [This struct / the macros X, Y, Z / whatever ] are borrowed
* from the Linux kernel, and so (unlike the rest of this file)
* they are GPL-2.0-only.
*/

Quoted 4 lines

Ping

Any news? With just the license issue remaining, it would be nice to get FlexCAN support into the upcoming release.

The problem is that QEMU maintainers decided to prefer GPL-2.0-or-later as the rule for new contributions and Matyas Bobek has reused next excepts from Linux kernel sources

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/can/flexcan/flexcan-core.c

which have license

// SPDX-License-Identifier: GPL-2.0
//
// flexcan.c - FLEXCAN CAN controller driver
//
// Copyright (c) 2005-2006 Varma Electronics Oy
// Copyright (c) 2009 Sascha Hauer, Pengutronix
// Copyright (c) 2010-2017 Pengutronix, Marc Kleine-Budde <[email protected]> // Copyright (c) 2014 David Jander, Protonic Holland
//
// Based on code originally by Andrey Volkov <[email protected]>

I think, personally, that the code excepts are on the edge of the rules for copyright applications because the lines are direct transformation of the offests and bit-fields found in the original FreeScale/NXP manuals so there should be no problem to use them for QEMU and revwite from scratch for copyright clarity with a little different naming rules would make only more mess for future updates to FexCAN 3 etc.

Thanaks in advance

Pavel

hw/net/can/flexcan_regs.h

+/**
+ * These macros ware originally written for the Linux kernel
+ * by Marc Kleine-Budde.
+ */
+
+/* FLEXCAN module configuration register (CANMCR) bits */

+#define FLEXCAN_MCR_MDIS                BIT(31)
+#define FLEXCAN_MCR_FRZ                 BIT(30)
+#define FLEXCAN_MCR_FEN                 BIT(29)
+#define FLEXCAN_MCR_HALT                BIT(28)
+#define FLEXCAN_MCR_NOT_RDY             BIT(27)
+#define FLEXCAN_MCR_WAK_MSK             BIT(26)
+#define FLEXCAN_MCR_SOFTRST             BIT(25)
+#define FLEXCAN_MCR_FRZ_ACK             BIT(24)
+#define FLEXCAN_MCR_SUPV                BIT(23)
+#define FLEXCAN_MCR_SLF_WAK             BIT(22)
+#define FLEXCAN_MCR_WRN_EN              BIT(21)
+#define FLEXCAN_MCR_LPM_ACK             BIT(20)
+#define FLEXCAN_MCR_WAK_SRC             BIT(19)
+#define FLEXCAN_MCR_DOZE                BIT(18)
+#define FLEXCAN_MCR_SRX_DIS             BIT(17)
+#define FLEXCAN_MCR_IRMQ                BIT(16)
+#define FLEXCAN_MCR_LPRIO_EN            BIT(13)
+#define FLEXCAN_MCR_AEN                 BIT(12)
+#define FLEXCAN_MCR_FDEN                BIT(11)
+#define FLEXCAN_MCR_MAXMB(x)            ((x) & 0x7f)
+#define FLEXCAN_MCR_IDAM_A              (0x0 << 8)
+#define FLEXCAN_MCR_IDAM_B              (0x1 << 8)
+#define FLEXCAN_MCR_IDAM_C              (0x2 << 8)
+#define FLEXCAN_MCR_IDAM_D              (0x3 << 8)
+#define FLEXCAN_MCR_IDAM_MASK           (0x3 << 8)
+
+/* FLEXCAN control register (CANCTRL) bits */
+#define FLEXCAN_CTRL_PRESDIV(x)         (((x) & 0xFF) << 24)
+#define FLEXCAN_CTRL_PRESDIV_MASK       FLEXCAN_CTRL_PRESDIV(UINT32_MAX)
+#define FLEXCAN_CTRL_RJW(x)             (((x) & 0x03) << 22)
+#define FLEXCAN_CTRL_RJW_MASK           FLEXCAN_CTRL_RJW(UINT32_MAX)
+#define FLEXCAN_CTRL_PSEG1(x)           (((x) & 0x07) << 19)
+#define FLEXCAN_CTRL_PSEG1_MASK         FLEXCAN_CTRL_PSEG1(UINT32_MAX)
+#define FLEXCAN_CTRL_PSEG2(x)           (((x) & 0x07) << 16)
+#define FLEXCAN_CTRL_PSEG2_MASK         FLEXCAN_CTRL_PSEG2(UINT32_MAX)
+#define FLEXCAN_CTRL_BOFF_MSK           BIT(15)
+#define FLEXCAN_CTRL_ERR_MSK            BIT(14)
+#define FLEXCAN_CTRL_CLK_SRC            BIT(13)
+#define FLEXCAN_CTRL_LPB                BIT(12)
+#define FLEXCAN_CTRL_TWRN_MSK           BIT(11)
+#define FLEXCAN_CTRL_RWRN_MSK           BIT(10)
+#define FLEXCAN_CTRL_SMP                BIT(7)
+#define FLEXCAN_CTRL_BOFF_REC           BIT(6)
+#define FLEXCAN_CTRL_TSYN               BIT(5)
+#define FLEXCAN_CTRL_LBUF               BIT(4)
+#define FLEXCAN_CTRL_LOM                BIT(3)
+#define FLEXCAN_CTRL_PROPSEG(x)         ((x) & 0x07)
+#define FLEXCAN_CTRL_PROPSEG_MASK       FLEXCAN_CTRL_PROPSEG(UINT32_MAX)
+#define FLEXCAN_CTRL_ERR_BUS            (FLEXCAN_CTRL_ERR_MSK)

+#define FLEXCAN_CTRL_ERR_STATE \
+ (FLEXCAN_CTRL_TWRN_MSK | FLEXCAN_CTRL_RWRN_MSK | \
+ FLEXCAN_CTRL_BOFF_MSK)
+#define FLEXCAN_CTRL_ERR_ALL \
+ (FLEXCAN_CTRL_ERR_BUS | FLEXCAN_CTRL_ERR_STATE)
+
+/* FLEXCAN control register 2 (CTRL2) bits */

+#define FLEXCAN_CTRL2_ECRWRE            BIT(29)
+#define FLEXCAN_CTRL2_WRMFRZ            BIT(28)
+#define FLEXCAN_CTRL2_RFFN(x)           (((x) & 0x0f) << 24)
+#define FLEXCAN_CTRL2_TASD(x)           (((x) & 0x1f) << 19)
+#define FLEXCAN_CTRL2_MRP               BIT(18)
+#define FLEXCAN_CTRL2_RRS               BIT(17)
+#define FLEXCAN_CTRL2_EACEN             BIT(16)
+#define FLEXCAN_CTRL2_ISOCANFDEN        BIT(12)
+
+/* FLEXCAN memory error control register (MECR) bits */
+#define FLEXCAN_MECR_ECRWRDIS           BIT(31)
+#define FLEXCAN_MECR_HANCEI_MSK         BIT(19)
+#define FLEXCAN_MECR_FANCEI_MSK         BIT(18)
+#define FLEXCAN_MECR_CEI_MSK            BIT(16)
+#define FLEXCAN_MECR_HAERRIE            BIT(15)
+#define FLEXCAN_MECR_FAERRIE            BIT(14)
+#define FLEXCAN_MECR_EXTERRIE           BIT(13)
+#define FLEXCAN_MECR_RERRDIS            BIT(9)
+#define FLEXCAN_MECR_ECCDIS             BIT(8)
+#define FLEXCAN_MECR_NCEFAFRZ           BIT(7)
+
+/* FLEXCAN error and status register (ESR) bits */
+#define FLEXCAN_ESR_SYNCH               BIT(18)
+#define FLEXCAN_ESR_TWRN_INT            BIT(17)
+#define FLEXCAN_ESR_RWRN_INT            BIT(16)
+#define FLEXCAN_ESR_BIT1_ERR            BIT(15)
+#define FLEXCAN_ESR_BIT0_ERR            BIT(14)
+#define FLEXCAN_ESR_ACK_ERR             BIT(13)
+#define FLEXCAN_ESR_CRC_ERR             BIT(12)
+#define FLEXCAN_ESR_FRM_ERR             BIT(11)
+#define FLEXCAN_ESR_STF_ERR             BIT(10)
+#define FLEXCAN_ESR_TX_WRN              BIT(9)
+#define FLEXCAN_ESR_RX_WRN              BIT(8)
+#define FLEXCAN_ESR_IDLE                BIT(7)
+#define FLEXCAN_ESR_BOFF_INT            BIT(2)
+#define FLEXCAN_ESR_ERR_INT             BIT(1)
+#define FLEXCAN_ESR_WAK_INT             BIT(0)
+
+/* FLEXCAN Bit Timing register (CBT) bits */
+#define FLEXCAN_CBT_BTF                 BIT(31)
+#define FLEXCAN_CBT_EPRESDIV_MASK       FLEXCAN_GENMASK(30, 21)
+#define FLEXCAN_CBT_ERJW_MASK           FLEXCAN_GENMASK(20, 16)
+#define FLEXCAN_CBT_EPROPSEG_MASK       FLEXCAN_GENMASK(15, 10)
+#define FLEXCAN_CBT_EPSEG1_MASK         FLEXCAN_GENMASK(9, 5)
+#define FLEXCAN_CBT_EPSEG2_MASK         FLEXCAN_GENMASK(4, 0)
+
+/* FLEXCAN FD control register (FDCTRL) bits */
+#define FLEXCAN_FDCTRL_FDRATE           BIT(31)
+#define FLEXCAN_FDCTRL_MBDSR1           FLEXCAN_GENMASK(20, 19)
+#define FLEXCAN_FDCTRL_MBDSR0           FLEXCAN_GENMASK(17, 16)
+#define FLEXCAN_FDCTRL_MBDSR_8          0x0
+#define FLEXCAN_FDCTRL_MBDSR_12         0x1
+#define FLEXCAN_FDCTRL_MBDSR_32         0x2
+#define FLEXCAN_FDCTRL_MBDSR_64         0x3
+#define FLEXCAN_FDCTRL_TDCEN            BIT(15)
+#define FLEXCAN_FDCTRL_TDCFAIL          BIT(14)
+#define FLEXCAN_FDCTRL_TDCOFF           FLEXCAN_GENMASK(12, 8)
+#define FLEXCAN_FDCTRL_TDCVAL           FLEXCAN_GENMASK(5, 0)
+
+/* FLEXCAN FD Bit Timing register (FDCBT) bits */
+#define FLEXCAN_FDCBT_FPRESDIV_MASK     FLEXCAN_GENMASK(29, 20)
+#define FLEXCAN_FDCBT_FRJW_MASK         FLEXCAN_GENMASK(18, 16)
+#define FLEXCAN_FDCBT_FPROPSEG_MASK     FLEXCAN_GENMASK(14, 10)
+#define FLEXCAN_FDCBT_FPSEG1_MASK       FLEXCAN_GENMASK(7, 5)
+#define FLEXCAN_FDCBT_FPSEG2_MASK       FLEXCAN_GENMASK(2, 0)
+
+/* FLEXCAN CRC Register (CRCR) bits */
+#define FLEXCAN_CRCR_MBCRC_MASK         FLEXCAN_GENMASK(22, 16)
+#define FLEXCAN_CRCR_MBCRC(x)           (((x) & FLEXCAN_CRCR_MBCRC_MASK) << 16)
+#define FLEXCAN_CRCR_TXCRC_MASK         FLEXCAN_GENMASK(14, 0)
+#define FLEXCAN_CRCR_TXCRC(x)           ((x) & FLEXCAN_CRCR_TXCRC_MASK)

+
+/* FLEXCAN interrupt flag register (IFLAG) bits */ +/* Errata ERR005829 step7: Reserve first valid MB */ +#define I_FIFO_OVERFLOW 7
+#define I_FIFO_WARN 6
+#define I_FIFO_AVAILABLE 5
+
+#define FLEXCAN_TX_MB_RESERVED_RX_FIFO 8
+#define FLEXCAN_TX_MB_RESERVED_RX_MAILBOX 0

+#define FLEXCAN_RX_MB_RX_MAILBOX_FIRST  (FLEXCAN_TX_MB_RESERVED_RX_MAILBOX + 1)
+#define FLEXCAN_IFLAG_MB(x)             BIT_ULL(x)
+#define FLEXCAN_IFLAG_RX_FIFO_OVERFLOW  BIT(I_FIFO_OVERFLOW)
+#define FLEXCAN_IFLAG_RX_FIFO_WARN      BIT(I_FIFO_WARN)
+#define FLEXCAN_IFLAG_RX_FIFO_AVAILABLE BIT(I_FIFO_AVAILABLE)
+
+/* FLEXCAN message buffers */
+#define FLEXCAN_MB_CODE_RX_BUSY_BIT     (0x1 << 24)
+#define FLEXCAN_MB_CODE_RX_INACTIVE     (0x0 << 24)
+#define FLEXCAN_MB_CODE_RX_EMPTY        (0x4 << 24)
+#define FLEXCAN_MB_CODE_RX_FULL         (0x2 << 24)
+#define FLEXCAN_MB_CODE_RX_OVERRUN      (0x6 << 24)
+#define FLEXCAN_MB_CODE_RX_RANSWER      (0xa << 24)
+
+#define FLEXCAN_MB_CODE_TX_INACTIVE     (0x8 << 24)
+#define FLEXCAN_MB_CODE_TX_ABORT        (0x9 << 24)
+#define FLEXCAN_MB_CODE_TX_DATA         (0xc << 24)
+#define FLEXCAN_MB_CODE_TX_TANSWER      (0xe << 24)

+
+#define FLEXCAN_MB_CODE(x) (((x) & 0xF) << 24)
+#define FLEXCAN_MB_CODE_MASK FLEXCAN_MB_CODE(UINT32_MAX)
+

+#define FLEXCAN_MB_CNT_EDL              BIT(31)
+#define FLEXCAN_MB_CNT_BRS              BIT(30)
+#define FLEXCAN_MB_CNT_ESI              BIT(29)
+#define FLEXCAN_MB_CNT_SRR              BIT(22)
+#define FLEXCAN_MB_CNT_IDE              BIT(21)
+#define FLEXCAN_MB_CNT_RTR              BIT(20)
+#define FLEXCAN_MB_CNT_LENGTH(x)        (((x) & 0xF) << 16)
+#define FLEXCAN_MB_CNT_TIMESTAMP(x)     ((x) & 0xFFFF)
+#define FLEXCAN_MB_CNT_TIMESTAMP_MASK   FLEXCAN_MB_CNT_TIMESTAMP(UINT32_MAX)

+/* view of single message buffer registers */
+typedef struct FlexcanRegsMessageBuffer {

+    uint32_t can_ctrl;
+    uint32_t can_id;
+    uint32_t data[2];

+} FlexcanRegsMessageBuffer;

include/hw/net/flexcan.h

+/**
+ * Structure of the hardware registers
+ *
+ * originally created for the Linux kernel by Marc Kleine-Budde
+ */
+typedef struct FlexcanRegs {

+    uint32_t mcr;                /* 0x00 */
+    uint32_t ctrl;               /* 0x04 - not affected by soft reset */
+    uint32_t timer;              /* 0x08 */
+    uint32_t tcr;                /* 0x0C */
+    uint32_t rxmgmask;           /* 0x10 - not affected by soft reset */
+    uint32_t rx14mask;           /* 0x14 - not affected by soft reset */
+    uint32_t rx15mask;           /* 0x18 - not affected by soft reset */
+    uint32_t ecr;                /* 0x1C */
+    uint32_t esr;                /* 0x20 */
+    uint32_t imask2;             /* 0x24 */
+    uint32_t imask1;             /* 0x28 */
+    uint32_t iflag2;             /* 0x2C */
+    uint32_t iflag1;             /* 0x30 */
+    union {                      /* 0x34 */
+        uint32_t gfwr_mx28;      /* MX28, MX53 */
+        uint32_t ctrl2;          /* MX6, VF610 - not affected by soft reset */
+    };
+    uint32_t esr2;               /* 0x38 */
+    uint32_t imeur;              /* 0x3C, unused */
+    uint32_t lrfr;               /* 0x40, unused */
+    uint32_t crcr;               /* 0x44 */
+    uint32_t rxfgmask;           /* 0x48 */
+    uint32_t rxfir;              /* 0x4C - not affected by soft reset */
+    uint32_t cbt;                /* 0x50, unused - not affected by soft reset */
+    uint32_t _reserved2;         /* 0x54 */
+    uint32_t dbg1;               /* 0x58, unused */
+    uint32_t dbg2;               /* 0x5C, unused */
+    uint32_t _reserved3[8];      /* 0x60 */
+    union {                      /* 0x80 - not affected by soft reset */
+        uint32_t mb[sizeof(FlexcanRegsMessageBuffer) * FLEXCAN_MAILBOX_COUNT];
+        FlexcanRegsMessageBuffer mbs[FLEXCAN_MAILBOX_COUNT];
+        FlexcanRegsRXFifo fifo;
+    };
+    uint32_t _reserved4[256];    /* 0x480 */
+    uint32_t rximr[64];          /* 0x880 - not affected by soft reset */
+    uint32_t _reserved5[24];     /* 0x980 */
+    uint32_t gfwr_mx6;           /* 0x9E0 - MX6 */
+
+    /* the rest is unused except for SMB */
+    uint32_t _reserved6[39];     /* 0x9E4 */
+    uint32_t _rxfir[6];          /* 0xA80 */
+    uint32_t _reserved8[2];      /* 0xA98 */
+    uint32_t _rxmgmask;          /* 0xAA0 */
+    uint32_t _rxfgmask;          /* 0xAA4 */
+    uint32_t _rx14mask;          /* 0xAA8 */
+    uint32_t _rx15mask;          /* 0xAAC */
+    uint32_t tx_smb[4];          /* 0xAB0 */
+    union {                      /* 0xAC0, used for SMB emulation */
+        uint32_t rx_smb0_raw[4];
+        FlexcanRegsMessageBuffer rx_smb0;
+    };
+    uint32_t rx_smb1[4];         /* 0xAD0 */
+    uint32_t mecr;               /* 0xAE0 */
+    uint32_t erriar;             /* 0xAE4 */
+    uint32_t erridpr;            /* 0xAE8 */
+    uint32_t errippr;            /* 0xAEC */
+    uint32_t rerrar;             /* 0xAF0 */
+    uint32_t rerrdr;             /* 0xAF4 */
+    uint32_t rerrsynr;           /* 0xAF8 */
+    uint32_t errsr;              /* 0xAFC */
+    uint32_t _reserved7[64];     /* 0xB00 */
+    uint32_t fdctrl;             /* 0xC00 - not affected by soft reset */
+    uint32_t fdcbt;              /* 0xC04 - not affected by soft reset */
+    uint32_t fdcrc;              /* 0xC08 */
+    uint32_t _reserved9[199];    /* 0xC0C */
+    uint32_t tx_smb_fd[18];      /* 0xF28 */
+    uint32_t rx_smb0_fd[18];     /* 0xF70 */
+    uint32_t rx_smb1_fd[18];     /* 0xFB8 */

+} FlexcanRegs;
+

#14 lore raw

Hello,

Quoted 3 lines · Pavel Pisa

please, provide your opinion, the license for small Linux kernel headers excepts seems to be the last and only blocker for mainlining. See the copied code below.

not sure how much help I can provide...

Quoted 15 lines · On Wednesday 27 of May 2026 12:42:23 Bernhard Beschow wrote:
Quoted 14 lines

Am 8. Mai 2026 12:10:21 UTC schrieb Peter Maydell <[email protected]>:

Quoted 13 lines · Bernhard Beschow
Quoted 12 lines

Am 5. Mai 2026 18:41:52 UTC schrieb Peter Maydell <[email protected]>:

Quoted 11 lines · Bernhard Beschow
Quoted 9 lines

I guess the only open issue is the licensing of struct FlexcanRegs
[1] which originates from Linux? How do we proceed here?

Best regards,
Bernhard

[1]
https://lore.kernel.org/qemu-devel/[email protected]
z/

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

Could you say what the problem is? In general there is no problem with taking header structs from the Linux kernel, as they are GPL-2-only and that is a QEMU-compatible license. The relevant source files or pieces of source files would need to be noted as 2-only rather than our default of 2-or-later, but that is doable -- we already do that for other things we have borrowed from the kernel.

This would be IMHO the cleared solution. Put these macros into a separate file with the proper license and copyright headers copied from the kernel driver.

Quoted 53 lines
Quoted 28 lines
Quoted 18 lines
Quoted 5 lines

In
https://lore.kernel.org/qemu-devel/f3cb3166-c3f8-4ed8-8c9a-cbf48b071d1e@
gmail.com/ I raised this review question: "The following structure looks like being based on Linux. Does this affect the copyright of this file?" I was just asking for advice and I'm glad the solution is that easy.

If the struct was copied from the kernel, then it's GPL-2.0-only, and we should just note the license and where we got the code from.

If the struct is just very similar to the kernel's one because it's the obvious representation taken from the datasheet, then it's not related to the kernel code and we can treat it as GPL-2.0-or-later like the rest of the file.

Since Matyáš says in the cover letter here "the headers (struct FlexcanRegs and flexcan_regs.h macros) were copied from the Linux kernel" then we're in case 1.

Quoted 9 lines

You can mark this up by having the file's SPDX tag be "SPDX-License-Identifier: (GPL-2.0-only AND GPL-2.0-or-later)" Then have a normal comment in the file next to the part that is 2.0-only that says
/*
* [This struct / the macros X, Y, Z / whatever ] are borrowed
* from the Linux kernel, and so (unlike the rest of this file)
* they are GPL-2.0-only.
*/

Quoted 4 lines

Ping

Any news? With just the license issue remaining, it would be nice to get FlexCAN support into the upcoming release.

The problem is that QEMU maintainers decided to prefer GPL-2.0-or-later as the rule for new contributions and Matyas Bobek has reused next excepts from Linux kernel sources

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/can/flexcan/flexcan-core.c

which have license

// SPDX-License-Identifier: GPL-2.0
//
// flexcan.c - FLEXCAN CAN controller driver
//
// Copyright (c) 2005-2006 Varma Electronics Oy
// Copyright (c) 2009 Sascha Hauer, Pengutronix
// Copyright (c) 2010-2017 Pengutronix, Marc Kleine-Budde <[email protected]> // Copyright (c) 2014 David Jander, Protonic Holland
//
// Based on code originally by Andrey Volkov <[email protected]>

Quoted 7 lines

I think, personally, that the code excepts are on the edge of the rules for copyright applications because the lines are direct transformation of the offests and bit-fields found in the original FreeScale/NXP manuals so there should be no problem to use them for QEMU and revwite from scratch for copyright clarity with a little different naming rules would make only more mess for future updates to FexCAN 3 etc.

As you target currently imx6 only, you can re-create them from the imx6 data sheet, it already comes with "C" compatible naming scheme, e.g.:

| "Rx Mailboxes Global Mask Register (FLEXCAN1_RXMGMASK)"

Quoted 6 lines

hw/net/can/flexcan_regs.h

+/**
+ * These macros ware originally written for the Linux kernel
+ * by Marc Kleine-Budde.
+ */

This is not 100% correct. I'm the git-author of the initial mainline flexcan commit e955cead0311 ("CAN: Add Flexcan CAN controller driver"), but it already comes with these copyright statements:

+ * Copyright (c) 2005-2006 Varma Electronics Oy
+ * Copyright (c) 2009 Sascha Hauer, Pengutronix
+ * Copyright (c) 2010 Marc Kleine-Budde, Pengutronix
+ *
+ * Based on code originally by Andrey Volkov <[email protected]>

So I cannot re-license even the initial file alone, Sascha is my co-worker.

Hope that helps,
Marc

--

Pengutronix e.K.                 | Marc Kleine-Budde          |
Embedded Linux                   | https://www.pengutronix.de |

Vertretung Nürnberg | Phone: +49-5121-206917-129 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-9 |

#15 lore raw

Hello Pavel, Marc,

As the original author, I have no objection to reusing (my part of) the header under GPL-2.0-or-later. The reason it was not done that way in 2005/2006 is simple: only GPLv2 existed at the time.

All the more so since, as already noted, the code in question is essentially a direct transcription of offsets and bit-fields from the Freescale/NXP datasheets, which leaves very little room for a meaningful copyright claim in the first place.

Personally, I would prefer that this code not be rewritten and be kept as is, to avoid introducing subtle bugs in QEMU later on. That said, @Sascha and @David may have a different opinion.

PS: [email protected] is my correct current work address, but I would prefer to use my personal one for this discussion.

Regards,
Andrey Volkov

Le 27/05/2026 à 18:09, Marc Kleine-Budde a écrit :

Quoted 122 lines

Hello,

Quoted 3 lines · Pavel Pisa

please, provide your opinion, the license for small Linux kernel headers excepts seems to be the last and only blocker for mainlining. See the copied code below.

not sure how much help I can provide...

Quoted 14 lines · On Wednesday 27 of May 2026 12:42:23 Bernhard Beschow wrote:
Quoted 13 lines

Am 8. Mai 2026 12:10:21 UTC schrieb Peter Maydell<[email protected]>:

Quoted 12 lines · Bernhard Beschow
Quoted 11 lines

Am 5. Mai 2026 18:41:52 UTC schrieb Peter Maydell<[email protected]>:

Quoted 10 lines · Bernhard Beschow
Quoted 9 lines

I guess the only open issue is the licensing of struct FlexcanRegs
[1] which originates from Linux? How do we proceed here?

Best regards,
Bernhard

[1]
https://lore.kernel.org/qemu-devel/[email protected]
z/

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

Could you say what the problem is? In general there is no problem with taking header structs from the Linux kernel, as they are GPL-2-only and that is a QEMU-compatible license. The relevant source files or pieces of source files would need to be noted as 2-only rather than our default of 2-or-later, but that is doable -- we already do that for other things we have borrowed from the kernel.

This would be IMHO the cleared solution. Put these macros into a separate file with the proper license and copyright headers copied from the kernel driver.

Quoted 50 lines
Quoted 26 lines
Quoted 17 lines
Quoted 5 lines

In
https://lore.kernel.org/qemu-devel/f3cb3166-c3f8-4ed8-8c9a-cbf48b071d1e@
gmail.com/ I raised this review question: "The following structure looks like being based on Linux. Does this affect the copyright of this file?" I was just asking for advice and I'm glad the solution is that easy.

If the struct was copied from the kernel, then it's GPL-2.0-only, and we should just note the license and where we got the code from.

If the struct is just very similar to the kernel's one because it's the obvious representation taken from the datasheet, then it's not related to the kernel code and we can treat it as GPL-2.0-or-later like the rest of the file.

Since Matyáš says in the cover letter here "the headers (struct FlexcanRegs and flexcan_regs.h macros) were copied from the Linux kernel" then we're in case 1.

Quoted 9 lines

You can mark this up by having the file's SPDX tag be "SPDX-License-Identifier: (GPL-2.0-only AND GPL-2.0-or-later)" Then have a normal comment in the file next to the part that is 2.0-only that says
/*
* [This struct / the macros X, Y, Z / whatever ] are borrowed
* from the Linux kernel, and so (unlike the rest of this file)
* they are GPL-2.0-only.
*/

Quoted 4 lines

Ping

Any news? With just the license issue remaining, it would be nice to get FlexCAN support into the upcoming release.

The problem is that QEMU maintainers decided to prefer GPL-2.0-or-later as the rule for new contributions and Matyas Bobek has reused next excepts from Linux kernel sources

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/can/flexcan/flexcan-core.c

which have license

// SPDX-License-Identifier: GPL-2.0
//
// flexcan.c - FLEXCAN CAN controller driver
//
// Copyright (c) 2005-2006 Varma Electronics Oy
// Copyright (c) 2009 Sascha Hauer, Pengutronix
// Copyright (c) 2010-2017 Pengutronix, Marc Kleine-Budde<[email protected]> // Copyright (c) 2014 David Jander, Protonic Holland
//
// Based on code originally by Andrey Volkov<[email protected]>

Quoted 7 lines

I think, personally, that the code excepts are on the edge of the rules for copyright applications because the lines are direct transformation of the offests and bit-fields found in the original FreeScale/NXP manuals so there should be no problem to use them for QEMU and revwite from scratch for copyright clarity with a little different naming rules would make only more mess for future updates to FexCAN 3 etc.

As you target currently imx6 only, you can re-create them from the imx6 data sheet, it already comes with "C" compatible naming scheme, e.g.:

| "Rx Mailboxes Global Mask Register (FLEXCAN1_RXMGMASK)"

Quoted 6 lines

hw/net/can/flexcan_regs.h

+/**
+ * These macros ware originally written for the Linux kernel
+ * by Marc Kleine-Budde.
+ */

This is not 100% correct. I'm the git-author of the initial mainline flexcan commit e955cead0311 ("CAN: Add Flexcan CAN controller driver"), but it already comes with these copyright statements:

+ * Copyright (c) 2005-2006 Varma Electronics Oy
+ * Copyright (c) 2009 Sascha Hauer, Pengutronix
+ * Copyright (c) 2010 Marc Kleine-Budde, Pengutronix
+ *
+ * Based on code originally by Andrey Volkov<[email protected]>

So I cannot re-license even the initial file alone, Sascha is my co-worker.

Hope that helps,
Marc

--
Pengutronix e.K. | Marc Kleine-Budde |
Embedded Linux |https://www.pengutronix.de |
Vertretung Nürnberg | Phone: +49-5121-206917-129 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-9 |

Signature · 8 lines
*Andrei VOLKOV — MUNIC CAR DATA
*Senior Software Engineer**

https://www.munic.io

39 avenue de Paris, 94800 Villejuif — France

tel: +33 (0) 1 42 11 93 25
#16 lore raw

Le 27/05/2026 à 18:25, Andrei VOLKOV a écrit :

Quoted 12 lines

Hello Pavel, Marc,

As the original author, I have no objection to reusing (my part of) the header under GPL-2.0-or-later. The reason it was not done that way in 2005/2006 is simple: only GPLv2 existed at the time.

All the more so since, as already noted, the code in question is essentially a direct transcription of offsets and bit-fields from the Freescale/NXP datasheets, which leaves very little room for a meaningful copyright claim in the first place.

Personally, I would prefer that this code not be rewritten and be kept as is, to avoid introducing subtle bugs in QEMU later on. That said, @Sascha and @David may have a different opinion.

PS: [email protected] is my correct current work address, but I would prefer to use my personal one for this discussion.

This one: [email protected]

Quoted 138 lines

Regards,
Andrey Volkov

Le 27/05/2026 à 18:09, Marc Kleine-Budde a écrit :

Quoted 122 lines

Hello,

Quoted 3 lines · Pavel Pisa

please, provide your opinion, the license for small Linux kernel headers excepts seems to be the last and only blocker for mainlining. See the copied code below.

not sure how much help I can provide...

Quoted 14 lines · On Wednesday 27 of May 2026 12:42:23 Bernhard Beschow wrote:
Quoted 13 lines

Am 8. Mai 2026 12:10:21 UTC schrieb Peter Maydell<[email protected]>:

Quoted 12 lines · Bernhard Beschow
Quoted 11 lines

Am 5. Mai 2026 18:41:52 UTC schrieb Peter Maydell<[email protected]>:

Quoted 10 lines · Bernhard Beschow
Quoted 9 lines

I guess the only open issue is the licensing of struct FlexcanRegs
[1] which originates from Linux? How do we proceed here?

Best regards,
Bernhard

[1]
https://lore.kernel.org/qemu-devel/[email protected]
z/

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

Could you say what the problem is? In general there is no problem with taking header structs from the Linux kernel, as they are GPL-2-only and that is a QEMU-compatible license. The relevant source files or pieces of source files would need to be noted as 2-only rather than our default of 2-or-later, but that is doable -- we already do that for other things we have borrowed from the kernel.

This would be IMHO the cleared solution. Put these macros into a separate file with the proper license and copyright headers copied from the kernel driver.

Quoted 50 lines
Quoted 26 lines
Quoted 17 lines
Quoted 5 lines

In
https://lore.kernel.org/qemu-devel/f3cb3166-c3f8-4ed8-8c9a-cbf48b071d1e@
gmail.com/ I raised this review question: "The following structure looks like being based on Linux. Does this affect the copyright of this file?" I was just asking for advice and I'm glad the solution is that easy.

If the struct was copied from the kernel, then it's GPL-2.0-only, and we should just note the license and where we got the code from.

If the struct is just very similar to the kernel's one because it's the obvious representation taken from the datasheet, then it's not related to the kernel code and we can treat it as GPL-2.0-or-later like the rest of the file.

Since Matyáš says in the cover letter here "the headers (struct FlexcanRegs and flexcan_regs.h macros) were copied from the Linux kernel" then we're in case 1.

Quoted 9 lines

You can mark this up by having the file's SPDX tag be "SPDX-License-Identifier: (GPL-2.0-only AND GPL-2.0-or-later)" Then have a normal comment in the file next to the part that is 2.0-only that says
/*
* [This struct / the macros X, Y, Z / whatever ] are borrowed
* from the Linux kernel, and so (unlike the rest of this file)
* they are GPL-2.0-only.
*/

Quoted 4 lines

Ping

Any news? With just the license issue remaining, it would be nice to get FlexCAN support into the upcoming release.

The problem is that QEMU maintainers decided to prefer GPL-2.0-or-later as the rule for new contributions and Matyas Bobek has reused next excepts from Linux kernel sources

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/can/flexcan/flexcan-core.c

which have license

// SPDX-License-Identifier: GPL-2.0
//
// flexcan.c - FLEXCAN CAN controller driver
//
// Copyright (c) 2005-2006 Varma Electronics Oy
// Copyright (c) 2009 Sascha Hauer, Pengutronix
// Copyright (c) 2010-2017 Pengutronix, Marc Kleine-Budde<[email protected]> // Copyright (c) 2014 David Jander, Protonic Holland
//
// Based on code originally by Andrey Volkov<[email protected]>

Quoted 7 lines

I think, personally, that the code excepts are on the edge of the rules for copyright applications because the lines are direct transformation of the offests and bit-fields found in the original FreeScale/NXP manuals so there should be no problem to use them for QEMU and revwite from scratch for copyright clarity with a little different naming rules would make only more mess for future updates to FexCAN 3 etc.

As you target currently imx6 only, you can re-create them from the imx6 data sheet, it already comes with "C" compatible naming scheme, e.g.:

| "Rx Mailboxes Global Mask Register (FLEXCAN1_RXMGMASK)"

Quoted 6 lines

hw/net/can/flexcan_regs.h

+/**
+ * These macros ware originally written for the Linux kernel
+ * by Marc Kleine-Budde.
+ */

This is not 100% correct. I'm the git-author of the initial mainline flexcan commit e955cead0311 ("CAN: Add Flexcan CAN controller driver"), but it already comes with these copyright statements:

+ * Copyright (c) 2005-2006 Varma Electronics Oy
+ * Copyright (c) 2009 Sascha Hauer, Pengutronix
+ * Copyright (c) 2010 Marc Kleine-Budde, Pengutronix
+ *
+ * Based on code originally by Andrey Volkov<[email protected]>

So I cannot re-license even the initial file alone, Sascha is my co-worker.

Hope that helps,
Marc

--
Pengutronix e.K. | Marc Kleine-Budde |
Embedded Linux |https://www.pengutronix.de |
Vertretung Nürnberg | Phone: +49-5121-206917-129 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-9 |

Signature · 8 lines
*Andrei VOLKOV — MUNIC CAR DATA
*Senior Software Engineer**

https://www.munic.io

39 avenue de Paris, 94800 Villejuif — France

tel: +33 (0) 1 42 11 93 25
#17 lore raw
In reply to Andrei VOLKOV
Quoted 9 lines · Andrei VOLKOV

As the original author, I have no objection to reusing (my part of) the header under GPL-2.0-or-later. The reason it was not done that way in 2005/2006 is simple: only GPLv2 existed at the time.

All the more so since, as already noted, the code in question is essentially a direct transcription of offsets and bit-fields from the Freescale/NXP datasheets, which leaves very little room for a meaningful copyright claim in the first place.

Quoted 6 lines

Personally, I would prefer that this code not be rewritten and be kept as is, to avoid introducing subtle bugs in QEMU later on.
That said, @Sascha and @David may have a different opinion.

PS: [email protected] is my correct current work address, but I would prefer to use my personal one for this discussion.

I've added David on Cc and given them a short overview of this discussion and linked this thread.

I'll agree to re-license the register definitions of the flexcan driver to GPL-2.0-or-later. I'll poke Sasha tomorrow.

regards,
Marc

Signature · 4 lines
Pengutronix e.K.                 | Marc Kleine-Budde          |
Embedded Linux                   | https://www.pengutronix.de |
Vertretung Nürnberg              | Phone: +49-5121-206917-129 |
Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-9   |
#18 lore raw
Quoted 2 lines · Marc Kleine-Budde

I'll agree to re-license the register definitions of the flexcan driver to GPL-2.0-or-later. I'll poke Sasha tomorrow.

Typo: Sascha

Sorry,
Marc

Signature · 4 lines
Pengutronix e.K.                 | Marc Kleine-Budde          |
Embedded Linux                   | https://www.pengutronix.de |
Vertretung Nürnberg              | Phone: +49-5121-206917-129 |
Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-9   |
#19 lore raw
In reply to Marc Kleine-Budde
Quoted 14 lines · On Wed, 27 May 2026 20:38:10 +0200 Marc Kleine-Budde <[email protected]> wrote:
Quoted 13 lines · Andrei VOLKOV

As the original author, I have no objection to reusing (my part of) the header under GPL-2.0-or-later. The reason it was not done that way in 2005/2006 is simple: only GPLv2 existed at the time.

All the more so since, as already noted, the code in question is essentially a direct transcription of offsets and bit-fields from the Freescale/NXP datasheets, which leaves very little room for a meaningful copyright claim in the first place.

Personally, I would prefer that this code not be rewritten and be kept as is, to avoid introducing subtle bugs in QEMU later on.
That said, @Sascha and @David may have a different opinion.

Quoted 8 lines
Quoted 2 lines

PS: [email protected] is my correct current work address, but I would prefer to use my personal one for this discussion.

I've added David on Cc and given them a short overview of this discussion and linked this thread.

I'll agree to re-license the register definitions of the flexcan driver to GPL-2.0-or-later. I'll poke Sasha tomorrow.

I have no objections for this part to be used under GPL-2.0-or-later.

Best regards,

Signature · 1 line
David Jander
maintainer
#20 lore raw
In reply to Marc Kleine-Budde
Quoted 14 lines · Marc Kleine-Budde
Quoted 13 lines · Andrei VOLKOV

As the original author, I have no objection to reusing (my part of) the header under GPL-2.0-or-later. The reason it was not done that way in 2005/2006 is simple: only GPLv2 existed at the time.

All the more so since, as already noted, the code in question is essentially a direct transcription of offsets and bit-fields from the Freescale/NXP datasheets, which leaves very little room for a meaningful copyright claim in the first place.

Personally, I would prefer that this code not be rewritten and be kept as is, to avoid introducing subtle bugs in QEMU later on.
That said, @Sascha and @David may have a different opinion.

Quoted 8 lines
Quoted 2 lines

PS: [email protected] is my correct current work address, but I would prefer to use my personal one for this discussion.

I've added David on Cc and given them a short overview of this discussion and linked this thread.

I'll agree to re-license the register definitions of the flexcan driver to GPL-2.0-or-later. I'll poke Sasha tomorrow.

No objections from me as well.

Sascha

--

Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
#21 lore raw

Hello All,

Quoted 5 lines · On Thursday 28 of May 2026 10:53:42 Sascha Hauer wrote:
Quoted 4 lines · Marc Kleine-Budde
Quoted 3 lines · Andrei VOLKOV

As the original author, I have no objection to reusing (my part of) the header under GPL-2.0-or-later. The reason it was not done that way in 2005/2006 is simple: only GPLv2 existed at the time.

thanks everybody for the approval to reticence
as GPL-2.0 and latter.

To Andrey Volkov, excuse for using inappropriate address, but the questionable copyright situation has been raised and was main problem even for the v2 series version from March and it seems not to move forward from that time so I have tried to find some address on which you could respond as the original author and I expect that your original address at varma-el.com is no longer valid.

I think/remeber that there is no other request for changes in this round of review. May it be, the additional authors can be added to the headers code excerpt.

But generally I approve this FlexCAN support to be merged into QEMU master as CAN subsystem co-maintainer and I would be happy merge is proceed by somebody with commit right. Directly, directly with addition of Andrey Volkov and Sascha Hauer to the last line of notice in

hw/net/can/flexcan_regs.h

and

include/hw/net/flexcan.h

+/**
+ * These macros ware originally written for the Linux kernel
+ * by Andrey Volkov, Sascha Hauer and Marc Kleine-Budde.
+ */

or Matyas Bobek can modify the line and send
v4 version.

I would be happy if the code is merged, and it can be the base for some future project to extend support to iMX8 FlexCAN 3. Maybe I can find a student or somebody provides resources, time, GSoC funding, or some other option to attract some students to take the opportunity
to work on a project and learn something as a summer job... There are a lot more interesting controllers to support, I (with Michal Lenc) lead RTEMS D-CAN driver support GSoC for AM335x this year, QEMU support would be nice for CI there, we would continue on the PolarFire driver for RTEMS, one day, matching QEMU support would help. Long-term, multiqueue and priority for Linux would be worth solving; results on CTU CAN FD on RTEMS are exceptional. There are plenty of opportunities to have fun.

Best wishes,

Pavel

Pavel Pisa
phone: +420 603531357
e-mail: [email protected]
Department of Control Engineering FEE CVUT Karlovo namesti 13, 121 35, Prague 2
university: http://control.fel.cvut.cz/
personal: http://cmp.felk.cvut.cz/~pisa
social: https://social.kernel.org/ppisa
projects: https://www.openhub.net/accounts/ppisa
CAN related:http://canbus.pages.fel.cvut.cz/ RISC-V education: https://comparch.edu.cvut.cz/
Open Technologies Research Education and Exchange Services
https://gitlab.fel.cvut.cz/otrees/org/-/wikis/home