Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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 <vikram.garhwal@amd.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
Vikram Garhwal authored and pm215 committed Jun 6, 2023
1 parent 32dbebc commit 042d6b0
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 0 deletions.
31 changes: 31 additions & 0 deletions docs/system/arm/xlnx-versal-virt.rst
Expand Up @@ -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.

Expand Down Expand Up @@ -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
53 changes: 53 additions & 0 deletions hw/arm/xlnx-versal-virt.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -639,12 +673,17 @@ static void versal_virt_init(MachineState *machine)
TYPE_XLNX_VERSAL);
object_property_set_link(OBJECT(&s->soc), "ddr", OBJECT(machine->ram),
&error_abort);
object_property_set_link(OBJECT(&s->soc), "canbus0", OBJECT(s->canbus[0]),
&error_abort);
object_property_set_link(OBJECT(&s->soc), "canbus1", OBJECT(s->canbus[1]),
&error_abort);
sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_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);
Expand Down Expand Up @@ -712,6 +751,20 @@ static void versal_virt_init(MachineState *machine)

static void versal_virt_machine_instance_init(Object *obj)
{
VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);

/*
* User can set canbus0 and canbus1 properties to can-bus object and connect
* to socketcan(optional) interface via command line.
*/
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 versal_virt_machine_class_init(ObjectClass *oc, void *data)
Expand Down
37 changes: 37 additions & 0 deletions hw/arm/xlnx-versal.c
Expand Up @@ -184,6 +184,38 @@ static void versal_create_uarts(Versal *s, qemu_irq *pic)
}
}

static void versal_create_canfds(Versal *s, qemu_irq *pic)
{
int i;
uint32_t irqs[] = { VERSAL_CANFD0_IRQ_0, VERSAL_CANFD1_IRQ_0};
uint64_t addrs[] = { MM_CANFD0, MM_CANFD1 };

for (i = 0; i < ARRAY_SIZE(s->lpd.iou.canfd); i++) {
char *name = g_strdup_printf("canfd%d", i);
SysBusDevice *sbd;
MemoryRegion *mr;

object_initialize_child(OBJECT(s), name, &s->lpd.iou.canfd[i],
TYPE_XILINX_CANFD);
sbd = SYS_BUS_DEVICE(&s->lpd.iou.canfd[i]);

object_property_set_int(OBJECT(&s->lpd.iou.canfd[i]), "ext_clk_freq",
XLNX_VERSAL_CANFD_REF_CLK , &error_abort);

object_property_set_link(OBJECT(&s->lpd.iou.canfd[i]), "canfdbus",
OBJECT(s->lpd.iou.canbus[i]),
&error_abort);

sysbus_realize(sbd, &error_fatal);

mr = sysbus_mmio_get_region(sbd, 0);
memory_region_add_subregion(&s->mr_ps, addrs[i], mr);

sysbus_connect_irq(sbd, 0, pic[irqs[i]]);
g_free(name);
}
}

static void versal_create_usbs(Versal *s, qemu_irq *pic)
{
DeviceState *dev;
Expand Down Expand Up @@ -718,6 +750,7 @@ static void versal_realize(DeviceState *dev, Error **errp)
versal_create_apu_gic(s, pic);
versal_create_rpu_cpus(s);
versal_create_uarts(s, pic);
versal_create_canfds(s, pic);
versal_create_usbs(s, pic);
versal_create_gems(s, pic);
versal_create_admas(s, pic);
Expand Down Expand Up @@ -757,6 +790,10 @@ static void versal_init(Object *obj)
static Property versal_properties[] = {
DEFINE_PROP_LINK("ddr", Versal, cfg.mr_ddr, TYPE_MEMORY_REGION,
MemoryRegion *),
DEFINE_PROP_LINK("canbus0", Versal, lpd.iou.canbus[0],
TYPE_CAN_BUS, CanBusState *),
DEFINE_PROP_LINK("canbus1", Versal, lpd.iou.canbus[1],
TYPE_CAN_BUS, CanBusState *),
DEFINE_PROP_END_OF_LIST()
};

Expand Down
12 changes: 12 additions & 0 deletions include/hw/arm/xlnx-versal.h
Expand Up @@ -31,6 +31,7 @@
#include "hw/dma/xlnx_csu_dma.h"
#include "hw/misc/xlnx-versal-crl.h"
#include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
#include "hw/net/xlnx-versal-canfd.h"

#define TYPE_XLNX_VERSAL "xlnx-versal"
OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
Expand All @@ -43,6 +44,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
#define XLNX_VERSAL_NR_SDS 2
#define XLNX_VERSAL_NR_XRAM 4
#define XLNX_VERSAL_NR_IRQS 192
#define XLNX_VERSAL_NR_CANFD 2
#define XLNX_VERSAL_CANFD_REF_CLK (24 * 1000 * 1000)

struct Versal {
/*< private >*/
Expand Down Expand Up @@ -73,6 +76,8 @@ struct Versal {
CadenceGEMState gem[XLNX_VERSAL_NR_GEMS];
XlnxZDMA adma[XLNX_VERSAL_NR_ADMAS];
VersalUsb2 usb;
CanBusState *canbus[XLNX_VERSAL_NR_CANFD];
XlnxVersalCANFDState canfd[XLNX_VERSAL_NR_CANFD];
} iou;

/* Real-time Processing Unit. */
Expand Down Expand Up @@ -133,6 +138,8 @@ struct Versal {
#define VERSAL_CRL_IRQ 10
#define VERSAL_UART0_IRQ_0 18
#define VERSAL_UART1_IRQ_0 19
#define VERSAL_CANFD0_IRQ_0 20
#define VERSAL_CANFD1_IRQ_0 21
#define VERSAL_USB0_IRQ_0 22
#define VERSAL_GEM0_IRQ_0 56
#define VERSAL_GEM0_WAKE_IRQ_0 57
Expand Down Expand Up @@ -163,6 +170,11 @@ struct Versal {
#define MM_UART1 0xff010000U
#define MM_UART1_SIZE 0x10000

#define MM_CANFD0 0xff060000U
#define MM_CANFD0_SIZE 0x10000
#define MM_CANFD1 0xff070000U
#define MM_CANFD1_SIZE 0x10000

#define MM_GEM0 0xff0c0000U
#define MM_GEM0_SIZE 0x10000
#define MM_GEM1 0xff0d0000U
Expand Down

0 comments on commit 042d6b0

Please sign in to comment.