[RFC/WIP 0/3] WIP CTU CAN FD IP core mapping to the platform bus

Pavel Pisa posted 3 patches 4 months ago
hw/arm/xilinx_zynq.c   |   1 +
hw/net/can/ctucan_mm.c | 291 +++++++++++++++++++++++++++++++++++++++++
hw/net/can/meson.build |   1 +
3 files changed, 293 insertions(+)
create mode 100644 hw/net/can/ctucan_mm.c
[RFC/WIP 0/3] WIP CTU CAN FD IP core mapping to the platform bus
Posted by Pavel Pisa 4 months ago
From: Pavel Pisa <pisa@cmp.felk.cvut.cz>

Hello Peter, Gustavo and others,

our CTU CAN FD IP core is used on many FPGA platforms
and has been even tapeout on some other university
and even prototypes of the massive production chips
(support for that organized by our former student
in his company).

But actual QEMU emulation targets only PCI/PCIe mapping in

  hw/net/can/ctucan_pci.c

of the core in

  hw/net/can/ctucan_core.c

I would like to add support to map the core at fixed position for
SoCs and command line controlled location for FPGA targets.

I have working proof of concept on the branch net-can-ctucanfd-platform/

  https://github.com/ppisa/qemu/commits/net-can-ctucanfd-platform/

But I am sure that IRQ delivery should be cleaned and even for PCI/PCIe
the logical OR function should be added into delivery of interrupts
from individual cores to the IRQ on platform or PCI/PCIe level

The code at this moment:

hw/net/can/ctucan_core.h

typedef struct CtuCanCoreState {
...
    qemu_irq        irq;
    CanBusClientState bus_client;
} CtuCanCoreState;


hw/net/can/ctucan_core.c:
int ctucan_init(CtuCanCoreState *s, qemu_irq irq)
{
    s->irq = irq;

    qemu_irq_lower(s->irq);

    ctucan_hardware_reset(s);

    return 0;
}

static void ctucan_update_irq(CtuCanCoreState *s)
{
...
    if (s->int_stat.u32 & s->int_ena.u32) {
        qemu_irq_raise(s->irq);
    } else {
        qemu_irq_lower(s->irq);
    }
}

Memory mapping of the core
hw/net/can/ctucan_mm.c:

struct CtuCanMmState {
    /*< private >*/
    SysBusDevice    parent_obj;
    /*< public >*/

    struct {
        uint64_t    iobase;
        uint32_t    irqnum;
        char        *irqctrl;
    } cfg;

    MemoryRegion    ctucan_io_region;

    CtuCanCoreState ctucan_state[CTUCAN_MM_CORE_COUNT];
    qemu_irq        irq;

    char            *model;
    CanBusState     *canbus[CTUCAN_MM_CORE_COUNT];
};

and qemu_irq value is propagated into CTU CAN FD cores
in

hw/net/can/ctucan_mm.c:
static void ctucan_mm_realize(DeviceState *dev, Error **errp)
{
    CtuCanMmState *d = CTUCAN_MM_DEV(dev);
    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
    int i;
...
    /* memory_region_add_subregion(get_system_memory(), 0x43c30000, &d->ctucan_io_region); */
    if (d->cfg.iobase != 0) {
        sysbus_mmio_map(sbd, 0, d->cfg.iobase);
    }
    if (d->cfg.irqnum != 0) {
        //const char *id = "/machine/unattached/device[3]/gic";
        //const char *id = "/machine/unattached/device[3]";
        char *id = d->cfg.irqctrl;

        if (!id) {
            error_setg(errp, "irqctrl object path is mandatory when irqnum is specified");
            return;
        }

        Object *obj = object_resolve_path_at(container_get(qdev_get_machine(), "/peripheral"), id);
        DeviceState *gicdev;
        if (!obj) {
            error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, "Device '%s' not found", id);
            return;
        }
        gicdev = (DeviceState *)object_dynamic_cast(obj, TYPE_DEVICE);
        if (!gicdev) {
            error_setg(errp, "%s is not a hotpluggable device", id);
            return;
        }
        sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(gicdev, d->cfg.irqnum));
    }
    for (i = 0 ; i < CTUCAN_MM_CORE_COUNT; i++) {
        ctucan_init(&d->ctucan_state[i], d->irq);
    }
}

There is magic how to obtain interrupt controller object
of the SoC. I have found that next parameters are working
for Xilinx Zynq platform

qemu-system-arm -m 1G -M xilinx-zynq-a9 \
      -kernel kernel-zynq \
      -dtb zynq-microzed-uart1-2x-xcan-4x-ctu-axi.dtb \
      -initrd ramdisk.cpio \
      -serial null -serial mon:stdio \
      -nographic \
      -object can-bus,id=canbus0-bus \
      -object can-host-socketcan,if=can0,canbus=canbus0-bus,id=canbus0-socketcan \
      -device ctucan_mm,iobase=0x43c30000,irqnum=29,irqctrl=/machine/unattached/device[3],canbus=canbus0-bus \
      -device ctucan_mm,iobase=0x43c70000,irqnum=30,irqctrl=/machine/unattached/device[3],canbus=canbus0-bus \
      -device ctucan_mm,iobase=0x43bf0000,irqnum=31,irqctrl=/machine/unattached/device[3],canbus=canbus0-bus \
      -device ctucan_mm,iobase=0x43bb0000,irqnum=32,irqctrl=/machine/unattached/device[3],canbus=canbus0-bus \

But in general, I am not sure if copying of qemu_irq object
(s->irq = irq;) is correct according to the conventions and
I would like more some solution which allows to process/combine
multiple requests in some callback on the level of PCI/PCIe
or platform level integration object before passing to the
parent bus/interrupt controller level. 

Pavel Pisa (3):
  hw/net/can: WIP CTU CAN FD IP core mapping to the platform bus
  hw/net/can: WIP CTU CAN FD mapping of IRQ for platform device solved.
  hw/net/can: WIP CTU CAN FD add parameter to specify IRQ controller on
    command line

 hw/arm/xilinx_zynq.c   |   1 +
 hw/net/can/ctucan_mm.c | 291 +++++++++++++++++++++++++++++++++++++++++
 hw/net/can/meson.build |   1 +
 3 files changed, 293 insertions(+)
 create mode 100644 hw/net/can/ctucan_mm.c

-- 
2.39.5
Re: [RFC/WIP 0/3] WIP CTU CAN FD IP core mapping to the platform bus
Posted by Peter Maydell 3 months, 4 weeks ago
On Mon, 9 Dec 2024 at 23:33, Pavel Pisa <pisa@fel.cvut.cz> wrote:
> our CTU CAN FD IP core is used on many FPGA platforms
> and has been even tapeout on some other university
> and even prototypes of the massive production chips
> (support for that organized by our former student
> in his company).
>
> But actual QEMU emulation targets only PCI/PCIe mapping in
>
>   hw/net/can/ctucan_pci.c
>
> of the core in
>
>   hw/net/can/ctucan_core.c
>
> I would like to add support to map the core at fixed position for
> SoCs and command line controlled location for FPGA targets.

Command line instantiation of devices at command line
controlled addresses and with command line connection
of IRQ lines is basically something we do not
currently support. There is some prototype/design work
going on about generic "create a machine from
the command line" handling, which would inevitably
involve allowing the user to specify addresses and IRQ
lines. But I don't really want to see ad-hoc device-specific
additions of small parts of similar functionality.

If there's a SoC that QEMU models that has this CAN
controller, then it's the SoC model (written in C)
that defines where it is mapped in memory and what
IRQ lines it is wired up to.

thanks
-- PMM
Re: [RFC/WIP 0/3] WIP CTU CAN FD IP core mapping to the platform bus
Posted by Pavel Pisa 3 months, 4 weeks ago
Hello Peter,

On Tuesday 10 of December 2024 11:08:53 Peter Maydell wrote:
> On Mon, 9 Dec 2024 at 23:33, Pavel Pisa <pisa@fel.cvut.cz> wrote:
> > our CTU CAN FD IP core is used on many FPGA platforms
> > and has been even tapeout on some other university
> > and even prototypes of the massive production chips
> > (support for that organized by our former student
> > in his company).
> >
> > But actual QEMU emulation targets only PCI/PCIe mapping in
> >
> >   hw/net/can/ctucan_pci.c
> >
> > of the core in
> >
> >   hw/net/can/ctucan_core.c
> >
> > I would like to add support to map the core at fixed position for
> > SoCs and command line controlled location for FPGA targets.
>
> Command line instantiation of devices at command line
> controlled addresses and with command line connection
> of IRQ lines is basically something we do not
> currently support. There is some prototype/design work
> going on about generic "create a machine from
> the command line" handling, which would inevitably
> involve allowing the user to specify addresses and IRQ
> lines. But I don't really want to see ad-hoc device-specific
> additions of small parts of similar functionality.
>
> If there's a SoC that QEMU models that has this CAN
> controller, then it's the SoC model (written in C)
> that defines where it is mapped in memory and what
> IRQ lines it is wired up to.

There should be such SoC in some time even in public.
I understand that in such case the mapping should
be part of its support.

But main area of the CTU CAN FD IP core use
are FPGAs for now, Xilinx Zynq and above, Intel/Altera
SoC+FPGAs, actual next target to test is Microchip
PolarFire on BeagleV-Fire which allows to develop
and test driver for Linux, NuttX and RTEMS on the single
chip. And it would be great if there is option to
run that on CI and have (still simplified - no bitrate
miscmatch check etc) model for SW development with QEMU.

And CTU CAN FD does not belong to the core Zynq or PolarFire
support in such cases. So even this actual solution is usable
in such cases. But as I have expected, it is not so welcomed
in mainline... which is why I attempt to find what can be done.

Do you consider the the proposed trick (target object specified by
"irqctrl" parameter on commad line and then resolved by
object_resolve_path_at()) as unacceptable for mainline?

Another problem is if the qemu_irq can be copied in ctucan_mm_realize.
I have tried even another solution where chip core kept pointer
to qemu_irq in the bus integration wrapper (PCI/PCIe and platform).

But even for mainlined PCI/PCIe CTU CAN FD support I would like
to update support to provide real "or" operation between IRQs
outputs from individual controllers to PCI/PCIe interrupt link.
So in this case, I would be happy to hear if I can reuse
qemu_irq and some routing or if I should define own mechanism
to activate callback provided by the bus integration wrapper
from the core emulation code. But may it be some pin logic
already implemented in QEMU can be used there.

Best wishes,

                Pavel

PS: does somebody have some experience, information for
use of "16c3:abcd" DWC_usb3 / PCIe bridge on i.MX6 Sabre
Litte, I have sent plea for help two months ago without
any respone and it would help our another CAN controller
development project, iMX6 FlexCAN support.
 
--
                Pavel Pisa
    phone:      +420 603531357
    e-mail:     pisa@cmp.felk.cvut.cz
    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