Re: [QEMU][PATCH v5 3/4] xlnx-versal: Connect Xilinx VERSAL CANFD controllers
On [2023 May 19] Fri 13:36:57, Vikram Garhwal wrote: > Connect CANFD0 and CANFD1 on the Versal-virt machine and update > xlnx-versal-virt > document with CANFD command line examples. > > Signed-off-by: Vikram Garhwal > Reviewed-by: Peter Maydell Reviewed-by: Francisco Iglesias > --- > docs/system/arm/xlnx-versal-virt.rst | 31 > hw/arm/xlnx-versal-virt.c| 53 > hw/arm/xlnx-versal.c | 37 +++ > include/hw/arm/xlnx-versal.h | 12 +++ > 4 files changed, 133 insertions(+) > > diff --git a/docs/system/arm/xlnx-versal-virt.rst > b/docs/system/arm/xlnx-versal-virt.rst > index 92ad10d2da..d2d1b26692 100644 > --- a/docs/system/arm/xlnx-versal-virt.rst > +++ b/docs/system/arm/xlnx-versal-virt.rst > @@ -34,6 +34,7 @@ Implemented devices: > - DDR memory > - BBRAM (36 bytes of Battery-backed RAM) > - eFUSE (3072 bytes of one-time field-programmable bit array) > +- 2 CANFDs > > QEMU does not yet model any other devices, including the PL and the AI > Engine. > > @@ -224,3 +225,33 @@ To use a different index value, N, from default of 1, > add: > >Better yet, do not use actual product data when running guest image >on this Xilinx Versal Virt board. > + > +Using CANFDs for Versal Virt > + > +Versal CANFD controller is developed based on SocketCAN and QEMU CAN bus > +implementation. Bus connection and socketCAN connection for each CAN module > +can be set through command lines. > + > +To connect both CANFD0 and CANFD1 on the same bus: > + > +.. code-block:: bash > + > +-object can-bus,id=canbus -machine canbus0=canbus -machine canbus1=canbus > + > +To connect CANFD0 and CANFD1 to separate buses: > + > +.. code-block:: bash > + > +-object can-bus,id=canbus0 -object can-bus,id=canbus1 \ > +-machine canbus0=canbus0 -machine canbus1=canbus1 > + > +The SocketCAN interface can connect to a Physical or a Virtual CAN > interfaces on > +the host machine. Please check this document to learn about CAN interface on > +Linux: docs/system/devices/can.rst > + > +To connect CANFD0 and CANFD1 to host machine's CAN interface can0: > + > +.. code-block:: bash > + > +-object can-bus,id=canbus -machine canbus0=canbus -machine canbus1=canbus > +-object can-host-socketcan,id=canhost0,if=can0,canbus=canbus > diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c > index 668a9d65a4..1ee2b8697f 100644 > --- a/hw/arm/xlnx-versal-virt.c > +++ b/hw/arm/xlnx-versal-virt.c > @@ -40,9 +40,11 @@ struct VersalVirt { > uint32_t clk_25Mhz; > uint32_t usb; > uint32_t dwc; > +uint32_t canfd[2]; > } phandle; > struct arm_boot_info binfo; > > +CanBusState *canbus[XLNX_VERSAL_NR_CANFD]; > struct { > bool secure; > } cfg; > @@ -235,6 +237,38 @@ static void fdt_add_uart_nodes(VersalVirt *s) > } > } > > +static void fdt_add_canfd_nodes(VersalVirt *s) > +{ > +uint64_t addrs[] = { MM_CANFD1, MM_CANFD0 }; > +uint32_t size[] = { MM_CANFD1_SIZE, MM_CANFD0_SIZE }; > +unsigned int irqs[] = { VERSAL_CANFD1_IRQ_0, VERSAL_CANFD0_IRQ_0 }; > +const char clocknames[] = "can_clk\0s_axi_aclk"; > +int i; > + > +/* Create and connect CANFD0 and CANFD1 nodes to canbus0. */ > +for (i = 0; i < ARRAY_SIZE(addrs); i++) { > +char *name = g_strdup_printf("/canfd@%" PRIx64, addrs[i]); > +qemu_fdt_add_subnode(s->fdt, name); > + > +qemu_fdt_setprop_cell(s->fdt, name, "rx-fifo-depth", 0x40); > +qemu_fdt_setprop_cell(s->fdt, name, "tx-mailbox-count", 0x20); > + > +qemu_fdt_setprop_cells(s->fdt, name, "clocks", > + s->phandle.clk_25Mhz, s->phandle.clk_25Mhz); > +qemu_fdt_setprop(s->fdt, name, "clock-names", > + clocknames, sizeof(clocknames)); > +qemu_fdt_setprop_cells(s->fdt, name, "interrupts", > + GIC_FDT_IRQ_TYPE_SPI, irqs[i], > + GIC_FDT_IRQ_FLAGS_LEVEL_HI); > +qemu_fdt_setprop_sized_cells(s->fdt, name, "reg", > + 2, addrs[i], 2, size[i]); > +qemu_fdt_setprop_string(s->fdt, name, "compatible", > +"xlnx,canfd-2.0"); > + > +g_free(name); > +} > +} > + > static void fdt_add_fixed_link_nodes(VersalVirt *s, char *gemname, > uint32_t phandle) > { > @@ -639,12 +673,17 @@ static void versal_virt_init(MachineState *machine) > TYPE_XLNX_VERSAL); > object_property_set_link(OBJECT(>soc), "ddr", OBJECT(machine->ram), > _abort); > +object_property_set_link(OBJECT(>soc), "canbus0", > OBJECT(s->canbus[0]), > + _abort); > +object_property_set_link(OBJECT(>soc), "canbus1", > OBJECT(s->canbus[1]), > +
[QEMU][PATCH v5 3/4] xlnx-versal: Connect Xilinx VERSAL CANFD controllers
Connect CANFD0 and CANFD1 on the Versal-virt machine and update xlnx-versal-virt document with CANFD command line examples. Signed-off-by: Vikram Garhwal Reviewed-by: Peter Maydell --- docs/system/arm/xlnx-versal-virt.rst | 31 hw/arm/xlnx-versal-virt.c| 53 hw/arm/xlnx-versal.c | 37 +++ include/hw/arm/xlnx-versal.h | 12 +++ 4 files changed, 133 insertions(+) diff --git a/docs/system/arm/xlnx-versal-virt.rst b/docs/system/arm/xlnx-versal-virt.rst index 92ad10d2da..d2d1b26692 100644 --- a/docs/system/arm/xlnx-versal-virt.rst +++ b/docs/system/arm/xlnx-versal-virt.rst @@ -34,6 +34,7 @@ Implemented devices: - DDR memory - BBRAM (36 bytes of Battery-backed RAM) - eFUSE (3072 bytes of one-time field-programmable bit array) +- 2 CANFDs QEMU does not yet model any other devices, including the PL and the AI Engine. @@ -224,3 +225,33 @@ To use a different index value, N, from default of 1, add: Better yet, do not use actual product data when running guest image on this Xilinx Versal Virt board. + +Using CANFDs for Versal Virt + +Versal CANFD controller is developed based on SocketCAN and QEMU CAN bus +implementation. Bus connection and socketCAN connection for each CAN module +can be set through command lines. + +To connect both CANFD0 and CANFD1 on the same bus: + +.. code-block:: bash + +-object can-bus,id=canbus -machine canbus0=canbus -machine canbus1=canbus + +To connect CANFD0 and CANFD1 to separate buses: + +.. code-block:: bash + +-object can-bus,id=canbus0 -object can-bus,id=canbus1 \ +-machine canbus0=canbus0 -machine canbus1=canbus1 + +The SocketCAN interface can connect to a Physical or a Virtual CAN interfaces on +the host machine. Please check this document to learn about CAN interface on +Linux: docs/system/devices/can.rst + +To connect CANFD0 and CANFD1 to host machine's CAN interface can0: + +.. code-block:: bash + +-object can-bus,id=canbus -machine canbus0=canbus -machine canbus1=canbus +-object can-host-socketcan,id=canhost0,if=can0,canbus=canbus diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c index 668a9d65a4..1ee2b8697f 100644 --- a/hw/arm/xlnx-versal-virt.c +++ b/hw/arm/xlnx-versal-virt.c @@ -40,9 +40,11 @@ struct VersalVirt { uint32_t clk_25Mhz; uint32_t usb; uint32_t dwc; +uint32_t canfd[2]; } phandle; struct arm_boot_info binfo; +CanBusState *canbus[XLNX_VERSAL_NR_CANFD]; struct { bool secure; } cfg; @@ -235,6 +237,38 @@ static void fdt_add_uart_nodes(VersalVirt *s) } } +static void fdt_add_canfd_nodes(VersalVirt *s) +{ +uint64_t addrs[] = { MM_CANFD1, MM_CANFD0 }; +uint32_t size[] = { MM_CANFD1_SIZE, MM_CANFD0_SIZE }; +unsigned int irqs[] = { VERSAL_CANFD1_IRQ_0, VERSAL_CANFD0_IRQ_0 }; +const char clocknames[] = "can_clk\0s_axi_aclk"; +int i; + +/* Create and connect CANFD0 and CANFD1 nodes to canbus0. */ +for (i = 0; i < ARRAY_SIZE(addrs); i++) { +char *name = g_strdup_printf("/canfd@%" PRIx64, addrs[i]); +qemu_fdt_add_subnode(s->fdt, name); + +qemu_fdt_setprop_cell(s->fdt, name, "rx-fifo-depth", 0x40); +qemu_fdt_setprop_cell(s->fdt, name, "tx-mailbox-count", 0x20); + +qemu_fdt_setprop_cells(s->fdt, name, "clocks", + s->phandle.clk_25Mhz, s->phandle.clk_25Mhz); +qemu_fdt_setprop(s->fdt, name, "clock-names", + clocknames, sizeof(clocknames)); +qemu_fdt_setprop_cells(s->fdt, name, "interrupts", + GIC_FDT_IRQ_TYPE_SPI, irqs[i], + GIC_FDT_IRQ_FLAGS_LEVEL_HI); +qemu_fdt_setprop_sized_cells(s->fdt, name, "reg", + 2, addrs[i], 2, size[i]); +qemu_fdt_setprop_string(s->fdt, name, "compatible", +"xlnx,canfd-2.0"); + +g_free(name); +} +} + static void fdt_add_fixed_link_nodes(VersalVirt *s, char *gemname, uint32_t phandle) { @@ -639,12 +673,17 @@ static void versal_virt_init(MachineState *machine) TYPE_XLNX_VERSAL); object_property_set_link(OBJECT(>soc), "ddr", OBJECT(machine->ram), _abort); +object_property_set_link(OBJECT(>soc), "canbus0", OBJECT(s->canbus[0]), + _abort); +object_property_set_link(OBJECT(>soc), "canbus1", OBJECT(s->canbus[1]), + _abort); sysbus_realize(SYS_BUS_DEVICE(>soc), _fatal); fdt_create(s); create_virtio_regions(s); fdt_add_gem_nodes(s); fdt_add_uart_nodes(s); +fdt_add_canfd_nodes(s); fdt_add_gic_nodes(s); fdt_add_timer_nodes(s); fdt_add_zdma_nodes(s); @@ -712,6 +751,20 @@ static void