[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [RFC PATCH 2/2] arm/virt: Add aspeed-i2c controller and MCTP EP to e
From: |
Ben Widawsky |
Subject: |
Re: [RFC PATCH 2/2] arm/virt: Add aspeed-i2c controller and MCTP EP to enable MCTP testing |
Date: |
Tue, 24 May 2022 09:36:44 -0700 |
On 22-05-20 18:01:28, Jonathan Cameron wrote:
> As the only I2C emulation in QEMU that supports being both
> a master and a slave, suitable for MCTP over i2c is aspeed-i2c
> add this controller to the arm virt model and hook up our new
> i2c_mctp_cxl_fmapi device.
>
> The current Linux driver for aspeed-i2c has a hard requirement on
> a reset controller. Throw down the simplest reset controller
> I could find so as to avoid need to make any chance to the kernel
> code.
s/chance/change
>
> Patch also builds appropriate device tree. Unfortunately for CXL
> we need to use ACPI (no DT bindings yet defined). Enabling this will
> either require appropriate support for MCTP on an i2c master that
> has ACPI bindings, or modifications of the kernel driver to support
> ACPI with aspeed-i2c (which might be a little controversial ;)
I'm naive to what DT defines, but I assume what's there already is insufficient
to make the bindings for CXL. I say this because I believe it wouldn't be too
bad at all to make a cxl_dt.ko, and it's certainly less artificial than
providing ACPI support for things which don't naturally have ACPI support.
>
> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> ---
> hw/arm/Kconfig | 1 +
> hw/arm/virt.c | 77 +++++++++++++++++++++++++++++++++++++++++++
> include/hw/arm/virt.h | 2 ++
> 3 files changed, 80 insertions(+)
>
> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> index 219262a8da..4a733298cd 100644
> --- a/hw/arm/Kconfig
> +++ b/hw/arm/Kconfig
> @@ -30,6 +30,7 @@ config ARM_VIRT
> select ACPI_VIOT
> select VIRTIO_MEM_SUPPORTED
> select ACPI_CXL
> + select I2C_MCTP_CXL_FMAPI
>
> config CHEETAH
> bool
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index d818131b57..ea04279515 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -80,6 +80,9 @@
> #include "hw/char/pl011.h"
> #include "hw/cxl/cxl.h"
> #include "qemu/guest-random.h"
> +#include "hw/i2c/i2c.h"
> +#include "hw/i2c/aspeed_i2c.h"
> +#include "hw/misc/i2c_mctp_cxl_fmapi.h"
>
> #define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \
> static void virt_##major##_##minor##_class_init(ObjectClass *oc, \
> @@ -156,6 +159,8 @@ static const MemMapEntry base_memmap[] = {
> [VIRT_PVTIME] = { 0x090a0000, 0x00010000 },
> [VIRT_SECURE_GPIO] = { 0x090b0000, 0x00001000 },
> [VIRT_MMIO] = { 0x0a000000, 0x00000200 },
> + [VIRT_I2C] = { 0x0b000000, 0x00004000 },
> + [VIRT_RESET_FAKE] = { 0x0b004000, 0x00000010 },
> /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size
> */
> [VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 },
> [VIRT_SECURE_MEM] = { 0x0e000000, 0x01000000 },
> @@ -192,6 +197,7 @@ static const int a15irqmap[] = {
> [VIRT_GPIO] = 7,
> [VIRT_SECURE_UART] = 8,
> [VIRT_ACPI_GED] = 9,
> + [VIRT_I2C] = 10,
> [VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */
> [VIRT_GIC_V2M] = 48, /* ...to 48 + NUM_GICV2M_SPIS - 1 */
> [VIRT_SMMU] = 74, /* ...to 74 + NUM_SMMU_IRQS - 1 */
> @@ -1996,6 +2002,75 @@ static void virt_cpu_post_init(VirtMachineState *vms,
> MemoryRegion *sysmem)
> }
> }
>
> +static void create_mctp_test(MachineState *ms)
> +{
> + VirtMachineState *vms = VIRT_MACHINE(ms);
> + MemoryRegion *sysmem = get_system_memory();
> + AspeedI2CState *aspeedi2c;
> + struct DeviceState *dev;
> + char *nodename_i2c_master;
> + char *nodename_i2c_sub;
> + char *nodename_reset;
> + uint32_t clk_phandle, reset_phandle;
> + MemoryRegion *sysmem2;
> +
> + dev = qdev_new("aspeed.i2c-ast2600");
> + aspeedi2c = ASPEED_I2C(dev);
> + object_property_set_link(OBJECT(dev), "dram", OBJECT(ms->ram),
> &error_fatal);
> + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
> + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_I2C].base);
> + sysbus_connect_irq(SYS_BUS_DEVICE(&aspeedi2c->busses[0]), 0,
> qdev_get_gpio_in(vms->gic, vms->irqmap[VIRT_I2C]));
> +
> + /* I2C bus DT */
> + reset_phandle = qemu_fdt_alloc_phandle(ms->fdt);
> + nodename_reset = g_strdup_printf("/reset@%" PRIx64,
> vms->memmap[VIRT_RESET_FAKE].base);
> + qemu_fdt_add_subnode(ms->fdt, nodename_reset);
> + qemu_fdt_setprop_string(ms->fdt, nodename_reset, "compatible",
> "snps,dw-low-reset");
> + qemu_fdt_setprop_sized_cells(ms->fdt, nodename_reset, "reg",
> + 2, vms->memmap[VIRT_RESET_FAKE].base,
> + 2, vms->memmap[VIRT_RESET_FAKE].size);
> + qemu_fdt_setprop_cell(ms->fdt, nodename_reset, "#reset-cells", 0x1);
> + qemu_fdt_setprop_cell(ms->fdt, nodename_reset, "phandle", reset_phandle);
> + sysmem2 = g_new(MemoryRegion, 1);
> + memory_region_init_ram(sysmem2, NULL, "reset",
> vms->memmap[VIRT_RESET_FAKE].size, NULL);
> + memory_region_add_subregion(sysmem, vms->memmap[VIRT_RESET_FAKE].base,
> sysmem2);
> +
> + clk_phandle = qemu_fdt_alloc_phandle(ms->fdt);
> +
> + qemu_fdt_add_subnode(ms->fdt, "/mclk");
> + qemu_fdt_setprop_string(ms->fdt, "/mclk", "compatible", "fixed-clock");
> + qemu_fdt_setprop_cell(ms->fdt, "/mclk", "#clock-cells", 0x0);
> + qemu_fdt_setprop_cell(ms->fdt, "/mclk", "clock-frequency", 24000);
> + qemu_fdt_setprop_string(ms->fdt, "/mclk", "clock-output-names",
> "bobsclk");
> + qemu_fdt_setprop_cell(ms->fdt, "/mclk", "phandle", clk_phandle);
> +
> + nodename_i2c_master = g_strdup_printf("/i2c@%" PRIx64,
> vms->memmap[VIRT_I2C].base);
> + qemu_fdt_add_subnode(ms->fdt, nodename_i2c_master);
> + qemu_fdt_setprop_string(ms->fdt, nodename_i2c_master, "compatible",
> "aspeed,ast2600-i2c-bus");
> + qemu_fdt_setprop_cells(ms->fdt, nodename_i2c_master, "multi-master");
> + qemu_fdt_setprop_cell(ms->fdt, nodename_i2c_master, "#size-cells", 0);
> + qemu_fdt_setprop_cell(ms->fdt, nodename_i2c_master, "#address-cells", 1);
> + qemu_fdt_setprop_cell(ms->fdt, nodename_i2c_master, "clocks",
> clk_phandle);
> + qemu_fdt_setprop_string(ms->fdt, nodename_i2c_master, "clock-names",
> "bobsclk");
> + qemu_fdt_setprop(ms->fdt, nodename_i2c_master, "mctp-controller", NULL,
> 0);
> + qemu_fdt_setprop_cells(ms->fdt, nodename_i2c_master, "interrupts",
> GIC_FDT_IRQ_TYPE_SPI,
> + vms->irqmap[VIRT_I2C],
> GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> + /* Offset to the first bus is 0x80, next one at 0x100 etc */
> + qemu_fdt_setprop_sized_cells(ms->fdt, nodename_i2c_master, "reg",
> + 2, vms->memmap[VIRT_I2C].base + 0x80,
> + 2, 0x80);
> + qemu_fdt_setprop_cells(ms->fdt, nodename_i2c_master, "resets",
> reset_phandle, 0);
> +
> + nodename_i2c_sub = g_strdup_printf("/i2c@%" PRIx64 "/mctp@%" PRIx64,
> vms->memmap[VIRT_I2C].base, 0x50l);
> + qemu_fdt_add_subnode(ms->fdt, nodename_i2c_sub);
> + qemu_fdt_setprop_string(ms->fdt, nodename_i2c_sub, "compatible",
> "mctp-i2c-controller");
> + qemu_fdt_setprop_sized_cells(ms->fdt, nodename_i2c_sub, "reg", 1, 0x50 |
> 0x40000000);
> +
> +
> + /* Slave device - linux doesn't use the presence of dt node for this so
> don't create one*/
> + i2c_slave_create_simple(aspeed_i2c_get_bus(aspeedi2c, 0),
> "i2c_mctp_cxl_switch", 0x4d);
> +}
> +
> static void machvirt_init(MachineState *machine)
> {
> VirtMachineState *vms = VIRT_MACHINE(machine);
> @@ -2289,6 +2364,8 @@ static void machvirt_init(MachineState *machine)
> create_gpio_devices(vms, VIRT_SECURE_GPIO, secure_sysmem);
> }
>
> + create_mctp_test(machine);
> +
> /* connect powerdown request */
> vms->powerdown_notifier.notify = virt_powerdown_req;
> qemu_register_powerdown_notifier(&vms->powerdown_notifier);
> diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
> index 67c08a62af..abbfac7c48 100644
> --- a/include/hw/arm/virt.h
> +++ b/include/hw/arm/virt.h
> @@ -71,6 +71,8 @@ enum {
> VIRT_SMMU,
> VIRT_UART,
> VIRT_MMIO,
> + VIRT_I2C,
> + VIRT_RESET_FAKE,
> VIRT_RTC,
> VIRT_FW_CFG,
> VIRT_PCIE,
> --
> 2.32.0
>