Re: [PATCH 13/24] hw/misc/aspeed_xdma: Add AST2600 support
On Wed, 2021-04-07 at 19:16 +0200, Cédric Le Goater wrote: > When we introduced support for the AST2600 SoC, the XDMA controller > was forgotten. It went unnoticed because it's not used under > emulation. > But the register layout being different, the reset procedure is bogus > and this breaks kexec. > > Add a AspeedXDMAClass to take into account the register differences. Thanks Cedric! Reviewed-by: Eddie James > > Cc: Eddie James > Signed-off-by: Cédric Le Goater > --- > include/hw/misc/aspeed_xdma.h | 17 - > hw/arm/aspeed_ast2600.c | 3 +- > hw/arm/aspeed_soc.c | 3 +- > hw/misc/aspeed_xdma.c | 124 +++- > -- > 4 files changed, 121 insertions(+), 26 deletions(-) > > diff --git a/include/hw/misc/aspeed_xdma.h > b/include/hw/misc/aspeed_xdma.h > index a2dea96984f3..b1478fd1c681 100644 > --- a/include/hw/misc/aspeed_xdma.h > +++ b/include/hw/misc/aspeed_xdma.h > @@ -13,7 +13,10 @@ > #include "qom/object.h" > > #define TYPE_ASPEED_XDMA "aspeed.xdma" > -OBJECT_DECLARE_SIMPLE_TYPE(AspeedXDMAState, ASPEED_XDMA) > +#define TYPE_ASPEED_2400_XDMA TYPE_ASPEED_XDMA "-ast2400" > +#define TYPE_ASPEED_2500_XDMA TYPE_ASPEED_XDMA "-ast2500" > +#define TYPE_ASPEED_2600_XDMA TYPE_ASPEED_XDMA "-ast2600" > +OBJECT_DECLARE_TYPE(AspeedXDMAState, AspeedXDMAClass, ASPEED_XDMA) > > #define ASPEED_XDMA_NUM_REGS (ASPEED_XDMA_REG_SIZE / > sizeof(uint32_t)) > #define ASPEED_XDMA_REG_SIZE 0x7C > @@ -28,4 +31,16 @@ struct AspeedXDMAState { > uint32_t regs[ASPEED_XDMA_NUM_REGS]; > }; > > +struct AspeedXDMAClass { > +SysBusDeviceClass parent_class; > + > +uint8_t cmdq_endp; > +uint8_t cmdq_wrp; > +uint8_t cmdq_rdp; > +uint8_t intr_ctrl; > +uint32_t intr_ctrl_mask; > +uint8_t intr_status; > +uint32_t intr_complete; > +}; > + > #endif /* ASPEED_XDMA_H */ > diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c > index e0fbb020c770..c60824bfeecb 100644 > --- a/hw/arm/aspeed_ast2600.c > +++ b/hw/arm/aspeed_ast2600.c > @@ -187,7 +187,8 @@ static void aspeed_soc_ast2600_init(Object *obj) > object_initialize_child(obj, "mii[*]", >mii[i], > TYPE_ASPEED_MII); > } > > -object_initialize_child(obj, "xdma", >xdma, > TYPE_ASPEED_XDMA); > +snprintf(typename, sizeof(typename), TYPE_ASPEED_XDMA "-%s", > socname); > +object_initialize_child(obj, "xdma", >xdma, typename); > > snprintf(typename, sizeof(typename), "aspeed.gpio-%s", socname); > object_initialize_child(obj, "gpio", >gpio, typename); > diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c > index 8ed29113f79f..4a95d27d9d63 100644 > --- a/hw/arm/aspeed_soc.c > +++ b/hw/arm/aspeed_soc.c > @@ -199,7 +199,8 @@ static void aspeed_soc_init(Object *obj) > TYPE_FTGMAC100); > } > > -object_initialize_child(obj, "xdma", >xdma, > TYPE_ASPEED_XDMA); > +snprintf(typename, sizeof(typename), TYPE_ASPEED_XDMA "-%s", > socname); > +object_initialize_child(obj, "xdma", >xdma, typename); > > snprintf(typename, sizeof(typename), "aspeed.gpio-%s", socname); > object_initialize_child(obj, "gpio", >gpio, typename); > diff --git a/hw/misc/aspeed_xdma.c b/hw/misc/aspeed_xdma.c > index 533d237e3ce2..1c21577c98c9 100644 > --- a/hw/misc/aspeed_xdma.c > +++ b/hw/misc/aspeed_xdma.c > @@ -30,6 +30,19 @@ > #define XDMA_IRQ_ENG_STAT_US_COMP BIT(4) > #define XDMA_IRQ_ENG_STAT_DS_COMP BIT(5) > #define XDMA_IRQ_ENG_STAT_RESET 0xF800 > + > +#define XDMA_AST2600_BMC_CMDQ_ADDR 0x14 > +#define XDMA_AST2600_BMC_CMDQ_ENDP 0x18 > +#define XDMA_AST2600_BMC_CMDQ_WRP0x1c > +#define XDMA_AST2600_BMC_CMDQ_RDP0x20 > +#define XDMA_AST2600_IRQ_CTRL0x38 > +#define XDMA_AST2600_IRQ_CTRL_US_COMPBIT(16) > +#define XDMA_AST2600_IRQ_CTRL_DS_COMPBIT(17) > +#define XDMA_AST2600_IRQ_CTRL_W_MASK 0x017003FF > +#define XDMA_AST2600_IRQ_STATUS 0x3c > +#define XDMA_AST2600_IRQ_STATUS_US_COMP BIT(16) > +#define XDMA_AST2600_IRQ_STATUS_DS_COMP BIT(17) > + > #define XDMA_MEM_SIZE 0x1000 > > #define TO_REG(addr) ((addr) / sizeof(uint32_t)) > @@ -52,56 +65,48 @@ static void aspeed_xdma_write(void *opaque, > hwaddr addr, uint64_t val, > unsigned int idx; > uint32_t val32 = (uint32_t)val; > AspeedXDMAState *xdma = opaque; > +AspeedXDMAClass *axc = ASPEED_XDMA_GET_CLASS(xdma); > > if (
Re: [Qemu-devel] [RFC v2] hw/sd/aspeed_sdhci: New device
On 8/19/19 1:41 AM, Cédric Le Goater wrote: On 15/08/2019 22:13, Eddie James wrote: On 8/15/19 3:05 AM, Cédric Le Goater wrote: Hello Eddie, On 14/08/2019 22:27, Eddie James wrote: The Aspeed SOCs have two SD/MMC controllers. Add a device that encapsulates both of these controllers and models the Aspeed-specific registers and behavior. Tested by reading from mmcblk0 in Linux: qemu-system-arm -machine romulus-bmc -nographic -serial mon:stdio \ -drive file=_tmp/flash-romulus,format=raw,if=mtd \ -device sd-card,drive=sd0 -drive file=_tmp/kernel,format=raw,if=sd Signed-off-by: Eddie James --- This patch applies on top of Cedric's set of recent Aspeed changes. Therefore, I'm sending as an RFC rather than a patch. yes. we can worked that out when the patch is reviewed. You can base on mainline when ready. My tree serves as an overall test base. Changes since v1: - Move slot realize code into the Aspeed SDHCI realize function - Fix interrupt handling by creating input irqs and connecting them to the slot irqs. - Removed card device creation code I think all the code is here but it needs some more reshuffling :) The raspi machine is a good source for modelling pratices. hw/arm/aspeed.c | 1 - hw/arm/aspeed_soc.c | 24 ++ hw/sd/Makefile.objs | 1 + hw/sd/aspeed_sdhci.c | 190 +++ include/hw/arm/aspeed_soc.h | 3 + include/hw/sd/aspeed_sdhci.h | 35 6 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 hw/sd/aspeed_sdhci.c create mode 100644 include/hw/sd/aspeed_sdhci.h diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 2574425..aeed5b6 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -480,7 +480,6 @@ static void aspeed_machine_class_init(ObjectClass *oc, void *data) mc->desc = board->desc; mc->init = aspeed_machine_init; mc->max_cpus = ASPEED_CPUS_NUM; - mc->no_sdcard = 1; mc->no_floppy = 1; mc->no_cdrom = 1; mc->no_parallel = 1; diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c index 8df96f2..a12f14a 100644 --- a/hw/arm/aspeed_soc.c +++ b/hw/arm/aspeed_soc.c @@ -22,6 +22,7 @@ #include "qemu/error-report.h" #include "hw/i2c/aspeed_i2c.h" #include "net/net.h" +#include "sysemu/blockdev.h" I would expect block devices to be handled at the machine level in aspeed.c, like the flash devices are. Something like : OK, I did have that in v1 but Peter mentioned it was typically done at the command line? yes, indeed. This works also and this is less code which is even better. I guess it can go in aspeed.c too. Well, let's do without if we can. We might be able to get rid of aspeed_board_init_flashes() now. We should start writing a QEMU cookbook page on the OpenBMC wiki to document the Aspeed machine command line. /* Create and plug in the SD cards */ for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; i++) { BusState *bus; DriveInfo *di = drive_get_next(IF_SD); BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL; DeviceState *carddev; bus = qdev_get_child_bus(DEVICE(>soc), "sd-bus"); if (!bus) { error_report("No SD bus found for SD card %d", i); exit(1); } carddev = qdev_create(bus, TYPE_SD_CARD); qdev_prop_set_drive(carddev, "drive", blk, _fatal); object_property_set_bool(OBJECT(carddev), true, "realized", _fatal); } #define ASPEED_SOC_IOMEM_SIZE 0x0020 @@ -62,6 +63,7 @@ static const hwaddr aspeed_soc_ast2500_memmap[] = { [ASPEED_XDMA] = 0x1E6E7000, [ASPEED_ADC] = 0x1E6E9000, [ASPEED_SRAM] = 0x1E72, + [ASPEED_SDHCI] = 0x1E74, [ASPEED_GPIO] = 0x1E78, [ASPEED_RTC] = 0x1E781000, [ASPEED_TIMER1] = 0x1E782000, @@ -100,6 +102,7 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = { [ASPEED_XDMA] = 0x1E6E7000, [ASPEED_ADC] = 0x1E6E9000, [ASPEED_VIDEO] = 0x1E70, + [ASPEED_SDHCI] = 0x1E74, [ASPEED_GPIO] = 0x1E78, [ASPEED_RTC] = 0x1E781000, [ASPEED_TIMER1] = 0x1E782000, @@ -146,6 +149,7 @@ static const int aspeed_soc_ast2400_irqmap[] = { [ASPEED_ETH1] = 2, [ASPEED_ETH2] = 3, [ASPEED_XDMA] = 6, + [ASPEED_SDHCI] = 26, }; #define aspeed_soc_ast2500_irqmap aspeed_soc_ast2400_irqmap @@ -163,6 +167,7 @@ static const int aspeed_soc_ast2600_irqmap[] = { [ASPEED_SDMC] = 0, [ASPEED_SCU] = 12, [ASPEED_XDMA] = 6, + [ASPEED_SDHCI] = 43, [ASPEED_ADC] = 46, [ASPEED_GPIO] = 40, [ASPEED_RTC] = 13, @@ -350,6 +355,15 @@ static void aspeed_soc_init(Object *obj)
[Qemu-devel] [RFC v3] hw/sd/aspeed_sdhci: New device
The Aspeed SOCs have two SD/MMC controllers. Add a device that encapsulates both of these controllers and models the Aspeed-specific registers and behavior. Tested by reading from mmcblk0 in Linux: qemu-system-arm -machine romulus-bmc -nographic \ -drive file=flash-romulus,format=raw,if=mtd \ -device sd-card,drive=sd0 -drive file=_tmp/kernel,format=raw,if=sd Signed-off-by: Eddie James --- This patch applies on top of Cedric's set of recent Aspeed changes. Therefore, I'm sending as an RFC rather than a patch for review. Changes since v2: - Do the memory mapping at the SOC level - Add guest errors for out-of-bounds access to the SDHCI regs - Remove unnecessary blockdev include in aspeed_soc.c - Better naming for SDHCI objects. Changes since v1: - Move slot realize code into the Aspeed SDHCI realize function - Fix interrupt handling by creating input irqs and connecting them to the slot irqs. - Removed card device creation code hw/arm/aspeed.c | 1 - hw/arm/aspeed_soc.c | 28 +++ hw/sd/Makefile.objs | 1 + hw/sd/aspeed_sdhci.c | 194 +++ include/hw/arm/aspeed_soc.h | 3 + include/hw/sd/aspeed_sdhci.h | 34 6 files changed, 260 insertions(+), 1 deletion(-) create mode 100644 hw/sd/aspeed_sdhci.c create mode 100644 include/hw/sd/aspeed_sdhci.h diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 2574425..aeed5b6 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -480,7 +480,6 @@ static void aspeed_machine_class_init(ObjectClass *oc, void *data) mc->desc = board->desc; mc->init = aspeed_machine_init; mc->max_cpus = ASPEED_CPUS_NUM; -mc->no_sdcard = 1; mc->no_floppy = 1; mc->no_cdrom = 1; mc->no_parallel = 1; diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c index c9f6e01..292751e 100644 --- a/hw/arm/aspeed_soc.c +++ b/hw/arm/aspeed_soc.c @@ -62,6 +62,7 @@ static const hwaddr aspeed_soc_ast2500_memmap[] = { [ASPEED_XDMA] = 0x1E6E7000, [ASPEED_ADC]= 0x1E6E9000, [ASPEED_SRAM] = 0x1E72, +[ASPEED_SDHCI] = 0x1E74, [ASPEED_GPIO] = 0x1E78, [ASPEED_RTC]= 0x1E781000, [ASPEED_TIMER1] = 0x1E782000, @@ -102,6 +103,7 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = { [ASPEED_XDMA] = 0x1E6E7000, [ASPEED_ADC] = 0x1E6E9000, [ASPEED_VIDEO] = 0x1E70, +[ASPEED_SDHCI] = 0x1E74, [ASPEED_GPIO] = 0x1E78, [ASPEED_GPIO_1_8V] = 0x1E780800, [ASPEED_RTC] = 0x1E781000, @@ -147,6 +149,7 @@ static const int aspeed_soc_ast2400_irqmap[] = { [ASPEED_ETH1] = 2, [ASPEED_ETH2] = 3, [ASPEED_XDMA] = 6, +[ASPEED_SDHCI] = 26, }; #define aspeed_soc_ast2500_irqmap aspeed_soc_ast2400_irqmap @@ -185,6 +188,7 @@ static const int aspeed_soc_ast2600_irqmap[] = { [ASPEED_ETH2] = 3, [ASPEED_FSI1] = 100, [ASPEED_FSI2] = 101, +[ASPEED_SDHCI] = 43, }; static const AspeedSoCInfo aspeed_socs[] = { @@ -357,6 +361,15 @@ static void aspeed_soc_init(Object *obj) sysbus_init_child_obj(obj, "fsi[*]", OBJECT(>fsi[0]), sizeof(s->fsi[0]), TYPE_ASPEED_FSI); } + +sysbus_init_child_obj(obj, "sdc", OBJECT(>sdhci), sizeof(s->sdhci), + TYPE_ASPEED_SDHCI); + +/* Init sd card slot class here so that they're under the correct parent */ +for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) { +sysbus_init_child_obj(obj, "sdhci[*]", OBJECT(>sdhci.slots[i]), + sizeof(s->sdhci.slots[i]), TYPE_SYSBUS_SDHCI); +} } /* @@ -698,6 +711,21 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(>fsi[0]), 0, aspeed_soc_get_irq(s, ASPEED_FSI1)); } + +/* SDHCI */ +object_property_set_bool(OBJECT(>sdhci), true, "realized", ); +if (err) { +error_propagate(errp, err); +return; +} +for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) { +sysbus_mmio_map(SYS_BUS_DEVICE(>sdhci.slots[i]), 0, +sc->info->memmap[ASPEED_SDHCI] + ((i + 1) * 0x100)); +} +sysbus_mmio_map(SYS_BUS_DEVICE(>sdhci), 0, +sc->info->memmap[ASPEED_SDHCI]); +sysbus_connect_irq(SYS_BUS_DEVICE(>sdhci), 0, + aspeed_soc_get_irq(s, ASPEED_SDHCI)); } static Property aspeed_soc_properties[] = { DEFINE_PROP_UINT32("num-cpus", AspeedSoCState, num_cpus, 0), diff --git a/hw/sd/Makefile.objs b/hw/sd/Makefile.objs index 0665727..a884c23 100644 --- a/hw/sd/Makefile.objs +++ b/hw/sd/Makefile.objs @@ -8,3 +8,4 @@ obj-$(CONFIG_MILKYMIST) += milkymist-memcard.o obj-$(CONFIG_OMAP) += omap_mmc.o obj-$(CONFIG_PXA2XX) += pxa2xx_mmci.o
Re: [Qemu-devel] [RFC v2] hw/sd/aspeed_sdhci: New device
On 8/15/19 3:13 PM, Eddie James wrote: On 8/15/19 3:05 AM, Cédric Le Goater wrote: Hello Eddie, On 14/08/2019 22:27, Eddie James wrote: + sdhci->slots[0].capareg = (uint64_t)(uint32_t)val; + break; + case ASPEED_SDHCI_SDIO_148: + sdhci->slots[0].maxcurr = (uint64_t)(uint32_t)val; + break; + case ASPEED_SDHCI_SDIO_240: + sdhci->slots[1].capareg = (uint64_t)(uint32_t)val; + break; + case ASPEED_SDHCI_SDIO_248: + sdhci->slots[1].maxcurr = (uint64_t)(uint32_t)val; + break; I think these regs are readonly. Well the actual regs at slot + 0x40/0x48 are indeed, but not the Aspeed-specific ones that mirror there. I think the idea is that Aspeed-specific code can set it's capabilities differently if desired. This may prevent the use of alias regions here. Actually I could be wrong after reading the specs again. It's a little confusing. I'm fine with making it read-only anyway, I doubt there will be any code that needs to write it. + default: + if (addr < ASPEED_SDHCI_REG_SIZE) { + sdhci->regs[TO_REG(addr)] = (uint32_t)val; + } + } +} + +static const MemoryRegionOps aspeed_sdhci_ops = { + .read = aspeed_sdhci_read, + .write = aspeed_sdhci_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid.min_access_size = 4,
Re: [Qemu-devel] [RFC v2] hw/sd/aspeed_sdhci: New device
On 8/15/19 3:05 AM, Cédric Le Goater wrote: Hello Eddie, On 14/08/2019 22:27, Eddie James wrote: The Aspeed SOCs have two SD/MMC controllers. Add a device that encapsulates both of these controllers and models the Aspeed-specific registers and behavior. Tested by reading from mmcblk0 in Linux: qemu-system-arm -machine romulus-bmc -nographic -serial mon:stdio \ -drive file=_tmp/flash-romulus,format=raw,if=mtd \ -device sd-card,drive=sd0 -drive file=_tmp/kernel,format=raw,if=sd Signed-off-by: Eddie James --- This patch applies on top of Cedric's set of recent Aspeed changes. Therefore, I'm sending as an RFC rather than a patch. yes. we can worked that out when the patch is reviewed. You can base on mainline when ready. My tree serves as an overall test base. Changes since v1: - Move slot realize code into the Aspeed SDHCI realize function - Fix interrupt handling by creating input irqs and connecting them to the slot irqs. - Removed card device creation code I think all the code is here but it needs some more reshuffling :) The raspi machine is a good source for modelling pratices. hw/arm/aspeed.c | 1 - hw/arm/aspeed_soc.c | 24 ++ hw/sd/Makefile.objs | 1 + hw/sd/aspeed_sdhci.c | 190 +++ include/hw/arm/aspeed_soc.h | 3 + include/hw/sd/aspeed_sdhci.h | 35 6 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 hw/sd/aspeed_sdhci.c create mode 100644 include/hw/sd/aspeed_sdhci.h diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 2574425..aeed5b6 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -480,7 +480,6 @@ static void aspeed_machine_class_init(ObjectClass *oc, void *data) mc->desc = board->desc; mc->init = aspeed_machine_init; mc->max_cpus = ASPEED_CPUS_NUM; -mc->no_sdcard = 1; mc->no_floppy = 1; mc->no_cdrom = 1; mc->no_parallel = 1; diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c index 8df96f2..a12f14a 100644 --- a/hw/arm/aspeed_soc.c +++ b/hw/arm/aspeed_soc.c @@ -22,6 +22,7 @@ #include "qemu/error-report.h" #include "hw/i2c/aspeed_i2c.h" #include "net/net.h" +#include "sysemu/blockdev.h" I would expect block devices to be handled at the machine level in aspeed.c, like the flash devices are. Something like : OK, I did have that in v1 but Peter mentioned it was typically done at the command line? I guess it can go in aspeed.c too. /* Create and plug in the SD cards */ for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; i++) { BusState *bus; DriveInfo *di = drive_get_next(IF_SD); BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL; DeviceState *carddev; bus = qdev_get_child_bus(DEVICE(>soc), "sd-bus"); if (!bus) { error_report("No SD bus found for SD card %d", i); exit(1); } carddev = qdev_create(bus, TYPE_SD_CARD); qdev_prop_set_drive(carddev, "drive", blk, _fatal); object_property_set_bool(OBJECT(carddev), true, "realized", _fatal); } #define ASPEED_SOC_IOMEM_SIZE 0x0020 @@ -62,6 +63,7 @@ static const hwaddr aspeed_soc_ast2500_memmap[] = { [ASPEED_XDMA] = 0x1E6E7000, [ASPEED_ADC]= 0x1E6E9000, [ASPEED_SRAM] = 0x1E72, +[ASPEED_SDHCI] = 0x1E74, [ASPEED_GPIO] = 0x1E78, [ASPEED_RTC]= 0x1E781000, [ASPEED_TIMER1] = 0x1E782000, @@ -100,6 +102,7 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = { [ASPEED_XDMA] = 0x1E6E7000, [ASPEED_ADC]= 0x1E6E9000, [ASPEED_VIDEO] = 0x1E70, +[ASPEED_SDHCI] = 0x1E74, [ASPEED_GPIO] = 0x1E78, [ASPEED_RTC]= 0x1E781000, [ASPEED_TIMER1] = 0x1E782000, @@ -146,6 +149,7 @@ static const int aspeed_soc_ast2400_irqmap[] = { [ASPEED_ETH1] = 2, [ASPEED_ETH2] = 3, [ASPEED_XDMA] = 6, +[ASPEED_SDHCI] = 26, }; #define aspeed_soc_ast2500_irqmap aspeed_soc_ast2400_irqmap @@ -163,6 +167,7 @@ static const int aspeed_soc_ast2600_irqmap[] = { [ASPEED_SDMC] = 0, [ASPEED_SCU]= 12, [ASPEED_XDMA] = 6, +[ASPEED_SDHCI] = 43, [ASPEED_ADC]= 46, [ASPEED_GPIO] = 40, [ASPEED_RTC]= 13, @@ -350,6 +355,15 @@ static void aspeed_soc_init(Object *obj) sysbus_init_child_obj(obj, "fsi[*]", OBJECT(>fsi[0]), sizeof(s->fsi[0]), TYPE_ASPEED_FSI); } + +sysbus_init_child_obj(obj, "sdhci", OBJECT(>sdhci), sizeof(s->sdhci), + TYPE_ASPEED_SDHCI); This is the Aspeed SD host interface. May be we should call it sdhost ? I suppose this is our "sd-bus" device ? +/*
[Qemu-devel] [RFC v2] hw/sd/aspeed_sdhci: New device
The Aspeed SOCs have two SD/MMC controllers. Add a device that encapsulates both of these controllers and models the Aspeed-specific registers and behavior. Tested by reading from mmcblk0 in Linux: qemu-system-arm -machine romulus-bmc -nographic -serial mon:stdio \ -drive file=_tmp/flash-romulus,format=raw,if=mtd \ -device sd-card,drive=sd0 -drive file=_tmp/kernel,format=raw,if=sd Signed-off-by: Eddie James --- This patch applies on top of Cedric's set of recent Aspeed changes. Therefore, I'm sending as an RFC rather than a patch. Changes since v1: - Move slot realize code into the Aspeed SDHCI realize function - Fix interrupt handling by creating input irqs and connecting them to the slot irqs. - Removed card device creation code hw/arm/aspeed.c | 1 - hw/arm/aspeed_soc.c | 24 ++ hw/sd/Makefile.objs | 1 + hw/sd/aspeed_sdhci.c | 190 +++ include/hw/arm/aspeed_soc.h | 3 + include/hw/sd/aspeed_sdhci.h | 35 6 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 hw/sd/aspeed_sdhci.c create mode 100644 include/hw/sd/aspeed_sdhci.h diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 2574425..aeed5b6 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -480,7 +480,6 @@ static void aspeed_machine_class_init(ObjectClass *oc, void *data) mc->desc = board->desc; mc->init = aspeed_machine_init; mc->max_cpus = ASPEED_CPUS_NUM; -mc->no_sdcard = 1; mc->no_floppy = 1; mc->no_cdrom = 1; mc->no_parallel = 1; diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c index 8df96f2..a12f14a 100644 --- a/hw/arm/aspeed_soc.c +++ b/hw/arm/aspeed_soc.c @@ -22,6 +22,7 @@ #include "qemu/error-report.h" #include "hw/i2c/aspeed_i2c.h" #include "net/net.h" +#include "sysemu/blockdev.h" #define ASPEED_SOC_IOMEM_SIZE 0x0020 @@ -62,6 +63,7 @@ static const hwaddr aspeed_soc_ast2500_memmap[] = { [ASPEED_XDMA] = 0x1E6E7000, [ASPEED_ADC]= 0x1E6E9000, [ASPEED_SRAM] = 0x1E72, +[ASPEED_SDHCI] = 0x1E74, [ASPEED_GPIO] = 0x1E78, [ASPEED_RTC]= 0x1E781000, [ASPEED_TIMER1] = 0x1E782000, @@ -100,6 +102,7 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = { [ASPEED_XDMA] = 0x1E6E7000, [ASPEED_ADC]= 0x1E6E9000, [ASPEED_VIDEO] = 0x1E70, +[ASPEED_SDHCI] = 0x1E74, [ASPEED_GPIO] = 0x1E78, [ASPEED_RTC]= 0x1E781000, [ASPEED_TIMER1] = 0x1E782000, @@ -146,6 +149,7 @@ static const int aspeed_soc_ast2400_irqmap[] = { [ASPEED_ETH1] = 2, [ASPEED_ETH2] = 3, [ASPEED_XDMA] = 6, +[ASPEED_SDHCI] = 26, }; #define aspeed_soc_ast2500_irqmap aspeed_soc_ast2400_irqmap @@ -163,6 +167,7 @@ static const int aspeed_soc_ast2600_irqmap[] = { [ASPEED_SDMC] = 0, [ASPEED_SCU]= 12, [ASPEED_XDMA] = 6, +[ASPEED_SDHCI] = 43, [ASPEED_ADC]= 46, [ASPEED_GPIO] = 40, [ASPEED_RTC]= 13, @@ -350,6 +355,15 @@ static void aspeed_soc_init(Object *obj) sysbus_init_child_obj(obj, "fsi[*]", OBJECT(>fsi[0]), sizeof(s->fsi[0]), TYPE_ASPEED_FSI); } + +sysbus_init_child_obj(obj, "sdhci", OBJECT(>sdhci), sizeof(s->sdhci), + TYPE_ASPEED_SDHCI); + +/* Init sd card slot class here so that they're under the correct parent */ +for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) { +sysbus_init_child_obj(obj, "sdhci_slot[*]", OBJECT(>sdhci.slots[i]), + sizeof(s->sdhci.slots[i]), TYPE_SYSBUS_SDHCI); +} } /* @@ -680,6 +694,16 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(>fsi[0]), 0, aspeed_soc_get_irq(s, ASPEED_FSI1)); } + +/* SD/SDIO - set the reg address so slot memory mapping can be set up */ +s->sdhci.ioaddr = sc->info->memmap[ASPEED_SDHCI]; +object_property_set_bool(OBJECT(>sdhci), true, "realized", ); +if (err) { +error_propagate(errp, err); +return; +} +sysbus_connect_irq(SYS_BUS_DEVICE(>sdhci), 0, + aspeed_soc_get_irq(s, ASPEED_SDHCI)); } static Property aspeed_soc_properties[] = { DEFINE_PROP_UINT32("num-cpus", AspeedSoCState, num_cpus, 0), diff --git a/hw/sd/Makefile.objs b/hw/sd/Makefile.objs index 0665727..a884c23 100644 --- a/hw/sd/Makefile.objs +++ b/hw/sd/Makefile.objs @@ -8,3 +8,4 @@ obj-$(CONFIG_MILKYMIST) += milkymist-memcard.o obj-$(CONFIG_OMAP) += omap_mmc.o obj-$(CONFIG_PXA2XX) += pxa2xx_mmci.o obj-$(CONFIG_RASPI) += bcm2835_sdhost.o +obj-$(CONFIG_ASPEED_SOC) += aspeed_sdhci.o diff --git a/hw/sd/aspeed_sdhci.c b/hw/sd/aspeed_sdhci.c new file mode 100644 index 000..
Re: [Qemu-devel] [PATCH] hw/sd/aspeed_sdhci: New device
On 8/5/19 9:31 AM, Peter Maydell wrote: On Wed, 26 Jun 2019 at 19:43, Eddie James wrote: The Aspeed SOCs have two SD/MMC controllers. Add a device that encapsulates both of these controllers and models the Aspeed-specific registers and behavior. Both controllers use a single HW interrupt. In order to trigger that interrupt, a function pointer was added to the generic SDHCI structure. This function (if the pointer is set) is called when the SDHCI model changes it's interrupt status, allowing the user (the Aspeed SDHCI model in this case) to set it's own interrupt. This goes on top of Cedric's set of Aspeed changes. Tested, booted, and read from /dev/mmcblk0 and /dev/mmcblk1: ./arm-softmmu/qemu-system-arm -M ast2500-evb -nographic \ -drive file=flash-romulus,format=raw,if=mtd \ -drive file=,format=raw,if=sd \ -drive file=,format=raw,if=sd \ -kernel zImage \ -dtb aspeed-ast2500-evb.dtb \ -initrd romulus.cpio.lzma \ -d trace:sdhci* -no-reboot Signed-off-by: Eddie James (Apologies for the rather delayed review -- combination of the 4.1 release work, and hoping one of the other Aspeed developers would get to it.) No problem, thanks for the review! #define aspeed_soc_ast2500_irqmap aspeed_soc_ast2400_irqmap @@ -378,6 +381,16 @@ static void aspeed_soc_init(Object *obj) sysbus_init_child_obj(obj, "fsi[*]", OBJECT(>fsi[0]), sizeof(s->fsi[0]), TYPE_ASPEED_FSI); } + +sysbus_init_child_obj(obj, "sdhci", OBJECT(>sdhci), sizeof(s->sdhci), + TYPE_ASPEED_SDHCI); + +for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) { +sysbus_init_child_obj(obj, "sdhci_slot[*]", + OBJECT(>sdhci.slots[i].sdhci), + sizeof(s->sdhci.slots[i].sdhci), + TYPE_SYSBUS_SDHCI); +} This seems a bit odd. Why does the SoC init the slots[i].sdhci objects, rather than letting the TYPE_ASPEED_SDHCI object itself take care of initializing and realizing its own child objects? I couldn't get it to work with the actual sdhci objects underneath the Aspeed object. Qemu wouldn't start with an sd card drive in the command line. I'm thinking it can't find the actual sdhci objects if they're not on that parent bus? } static void aspeed_soc_realize(DeviceState *dev, Error **errp) @@ -699,6 +712,60 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(>fsi[0]), 0, aspeed_soc_get_irq(s, ASPEED_FSI1)); } + +/* SD/SDIO */ +for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; i++) { +hwaddr hci_addr = sc->info->memmap[ASPEED_SDHCI] + (0x100 * (i + 1)); +DriveInfo *di; +BlockBackend *blk; +DeviceState *card; + +/* + * Compatible with: + * - SD Host Controller Specification Version 2.0 + * - SDIO Specification Version 2.0 + * - MMC Specification Version 4.3 + */ +object_property_set_int(OBJECT(>sdhci.slots[i].sdhci), 2, +"sd-spec-version", ); +if (err) { +error_propagate(errp, err); +return; +} + +object_property_set_uint(OBJECT(>sdhci.slots[i].sdhci), + ASPEED_SDHCI_CAPABILITIES, "capareg", ); +if (err) { +error_propagate(errp, err); +return; +} + +object_property_set_bool(OBJECT(>sdhci.slots[i].sdhci), true, + "realized", ); +if (err) { +error_propagate(errp, err); +return; +} + +sysbus_mmio_map(SYS_BUS_DEVICE(>sdhci.slots[i].sdhci), 0, hci_addr); + +di = drive_get_next(IF_SD); +blk = di ? blk_by_legacy_dinfo(di) : NULL; +card = qdev_create(qdev_get_child_bus(DEVICE(>sdhci.slots[i].sdhci), + "sd-bus"), TYPE_SD_CARD); +qdev_prop_set_drive(card, "drive", blk, _fatal); +object_property_set_bool(OBJECT(card), true, "realized", _fatal); Code at the SoC level shouldn't be calling drive_get_next() or creating SD card objects directly itself -- it should leave this up to either the board code or to the command line. OK. +} + +object_property_set_bool(OBJECT(>sdhci), true, "realized", ); +if (err) { +error_propagate(errp, err); +return; +} +sysbus_mmio_map(SYS_BUS_DEVICE(>sdhci), 0, +sc->info->memmap[ASPEED_SDHCI]); +sysbus_connect_irq(SYS_BUS_DEVICE(>sdhci), 0, + aspeed_soc_get_irq(s, ASPEED_SDHCI)); } static Property aspeed_soc_properties[] = { DEFINE_PROP_UINT32("num-cpus", AspeedSoCStat
[Qemu-devel] [PATCH] hw/sd/aspeed_sdhci: New device
The Aspeed SOCs have two SD/MMC controllers. Add a device that encapsulates both of these controllers and models the Aspeed-specific registers and behavior. Both controllers use a single HW interrupt. In order to trigger that interrupt, a function pointer was added to the generic SDHCI structure. This function (if the pointer is set) is called when the SDHCI model changes it's interrupt status, allowing the user (the Aspeed SDHCI model in this case) to set it's own interrupt. This goes on top of Cedric's set of Aspeed changes. Tested, booted, and read from /dev/mmcblk0 and /dev/mmcblk1: ./arm-softmmu/qemu-system-arm -M ast2500-evb -nographic \ -drive file=flash-romulus,format=raw,if=mtd \ -drive file=,format=raw,if=sd \ -drive file=,format=raw,if=sd \ -kernel zImage \ -dtb aspeed-ast2500-evb.dtb \ -initrd romulus.cpio.lzma \ -d trace:sdhci* -no-reboot Signed-off-by: Eddie James --- hw/arm/aspeed.c | 1 - hw/arm/aspeed_soc.c | 67 ++ hw/sd/Makefile.objs | 1 + hw/sd/aspeed_sdhci.c | 163 +++ hw/sd/sdhci.c| 8 ++- include/hw/arm/aspeed_soc.h | 3 + include/hw/sd/aspeed_sdhci.h | 39 +++ include/hw/sd/sdhci.h| 1 + 8 files changed, 281 insertions(+), 2 deletions(-) create mode 100644 hw/sd/aspeed_sdhci.c create mode 100644 include/hw/sd/aspeed_sdhci.h diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 5fee2f5..fbec946 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -422,7 +422,6 @@ static void aspeed_machine_class_init(ObjectClass *oc, void *data) mc->desc = board->desc; mc->init = aspeed_machine_init; mc->max_cpus = ASPEED_CPUS_NUM; -mc->no_sdcard = 1; mc->no_floppy = 1; mc->no_cdrom = 1; mc->no_parallel = 1; diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c index 1bbbdae..1378498 100644 --- a/hw/arm/aspeed_soc.c +++ b/hw/arm/aspeed_soc.c @@ -22,6 +22,7 @@ #include "qemu/error-report.h" #include "hw/i2c/aspeed_i2c.h" #include "net/net.h" +#include "sysemu/blockdev.h" #define ASPEED_SOC_IOMEM_SIZE 0x0020 @@ -62,6 +63,7 @@ static const hwaddr aspeed_soc_ast2500_memmap[] = { [ASPEED_XDMA] = 0x1E6E7000, [ASPEED_ADC]= 0x1E6E9000, [ASPEED_SRAM] = 0x1E72, +[ASPEED_SDHCI] = 0x1E74, [ASPEED_GPIO] = 0x1E78, [ASPEED_RTC]= 0x1E781000, [ASPEED_TIMER1] = 0x1E782000, @@ -142,6 +144,7 @@ static const int aspeed_soc_ast2400_irqmap[] = { [ASPEED_ETH1] = 2, [ASPEED_ETH2] = 3, [ASPEED_XDMA] = 6, +[ASPEED_SDHCI] = 26, }; #define aspeed_soc_ast2500_irqmap aspeed_soc_ast2400_irqmap @@ -378,6 +381,16 @@ static void aspeed_soc_init(Object *obj) sysbus_init_child_obj(obj, "fsi[*]", OBJECT(>fsi[0]), sizeof(s->fsi[0]), TYPE_ASPEED_FSI); } + +sysbus_init_child_obj(obj, "sdhci", OBJECT(>sdhci), sizeof(s->sdhci), + TYPE_ASPEED_SDHCI); + +for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) { +sysbus_init_child_obj(obj, "sdhci_slot[*]", + OBJECT(>sdhci.slots[i].sdhci), + sizeof(s->sdhci.slots[i].sdhci), + TYPE_SYSBUS_SDHCI); +} } static void aspeed_soc_realize(DeviceState *dev, Error **errp) @@ -699,6 +712,60 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(>fsi[0]), 0, aspeed_soc_get_irq(s, ASPEED_FSI1)); } + +/* SD/SDIO */ +for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; i++) { +hwaddr hci_addr = sc->info->memmap[ASPEED_SDHCI] + (0x100 * (i + 1)); +DriveInfo *di; +BlockBackend *blk; +DeviceState *card; + +/* + * Compatible with: + * - SD Host Controller Specification Version 2.0 + * - SDIO Specification Version 2.0 + * - MMC Specification Version 4.3 + */ +object_property_set_int(OBJECT(>sdhci.slots[i].sdhci), 2, +"sd-spec-version", ); +if (err) { +error_propagate(errp, err); +return; +} + +object_property_set_uint(OBJECT(>sdhci.slots[i].sdhci), + ASPEED_SDHCI_CAPABILITIES, "capareg", ); +if (err) { +error_propagate(errp, err); +return; +} + +object_property_set_bool(OBJECT(>sdhci.slots[i].sdhci), true, + "realized", ); +if (err) { +error_propagate(errp, err); +return; +} + +sysbus_mmio_map(SYS_BUS_DEVICE(>sdhci.slots[i].sdhci), 0, hci_addr
[Qemu-devel] [PATCH v2] hw: misc: Add Aspeed XDMA device
The XDMA engine embedded in the Aspeed SOCs performs PCI DMA operations between the SOC (acting as a BMC) and a host processor in a server. The XDMA engine exists on the AST2400, AST2500, and AST2600 SOCs, so enable it for all of those. Add trace events on the important register writes in the XDMA engine. Signed-off-by: Eddie James --- Changes since v1: - add trace events - minor cleanup This patch is based on Cedric's big Aspeed update: http://patchwork.ozlabs.org/cover/1105343/ hw/arm/aspeed_soc.c | 19 + hw/misc/Makefile.objs | 1 + hw/misc/aspeed_xdma.c | 165 ++ hw/misc/trace-events | 3 + include/hw/arm/aspeed_soc.h | 3 + include/hw/misc/aspeed_xdma.h | 30 6 files changed, 221 insertions(+) create mode 100644 hw/misc/aspeed_xdma.c create mode 100644 include/hw/misc/aspeed_xdma.h diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c index 0a0ab87..6901697 100644 --- a/hw/arm/aspeed_soc.c +++ b/hw/arm/aspeed_soc.c @@ -31,6 +31,7 @@ static const hwaddr aspeed_soc_ast2400_memmap[] = { [ASPEED_VIC]= 0x1E6C, [ASPEED_SDMC] = 0x1E6E, [ASPEED_SCU]= 0x1E6E2000, +[ASPEED_XDMA] = 0x1E6E7000, [ASPEED_ADC]= 0x1E6E9000, [ASPEED_SRAM] = 0x1E72, [ASPEED_GPIO] = 0x1E78, @@ -57,6 +58,7 @@ static const hwaddr aspeed_soc_ast2500_memmap[] = { [ASPEED_VIC]= 0x1E6C, [ASPEED_SDMC] = 0x1E6E, [ASPEED_SCU]= 0x1E6E2000, +[ASPEED_XDMA] = 0x1E6E7000, [ASPEED_ADC]= 0x1E6E9000, [ASPEED_SRAM] = 0x1E72, [ASPEED_GPIO] = 0x1E78, @@ -90,6 +92,7 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = { [ASPEED_VIC]= 0x1E6C, [ASPEED_SDMC] = 0x1E6E, [ASPEED_SCU]= 0x1E6E2000, +[ASPEED_XDMA] = 0x1E6E7000, [ASPEED_ADC]= 0x1E6E9000, [ASPEED_SRAM] = 0x1E72, [ASPEED_GPIO] = 0x1E78, @@ -137,6 +140,7 @@ static const int aspeed_soc_ast2400_irqmap[] = { [ASPEED_I2C]= 12, [ASPEED_ETH1] = 2, [ASPEED_ETH2] = 3, +[ASPEED_XDMA] = 6, }; #define aspeed_soc_ast2500_irqmap aspeed_soc_ast2400_irqmap @@ -174,6 +178,7 @@ static const int aspeed_soc_ast2600_irqmap[] = { [ASPEED_ETH2] = 3, [ASPEED_FSI1] = 100, [ASPEED_FSI2] = 101, +[ASPEED_XDMA] = 6, }; static const char *aspeed_soc_ast2400_typenames[] = { "aspeed.smc.spi" }; @@ -359,6 +364,9 @@ static void aspeed_soc_init(Object *obj) sysbus_init_child_obj(obj, "fsi[*]", OBJECT(>fsi[0]), sizeof(s->fsi[0]), TYPE_ASPEED_FSI); } + +sysbus_init_child_obj(obj, "xdma", OBJECT(>xdma), sizeof(s->xdma), + TYPE_ASPEED_XDMA); } static void aspeed_soc_realize(DeviceState *dev, Error **errp) @@ -662,6 +670,17 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(>fsi[0]), 0, aspeed_soc_get_irq(s, ASPEED_FSI1)); } + +/* XDMA */ +object_property_set_bool(OBJECT(>xdma), true, "realized", ); +if (err) { +error_propagate(errp, err); +return; +} +sysbus_mmio_map(SYS_BUS_DEVICE(>xdma), 0, +sc->info->memmap[ASPEED_XDMA]); +sysbus_connect_irq(SYS_BUS_DEVICE(>xdma), 0, + aspeed_soc_get_irq(s, ASPEED_XDMA)); } static void aspeed_soc_class_init(ObjectClass *oc, void *data) diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index d33c1c6..dc2b9c3 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -78,6 +78,7 @@ obj-$(CONFIG_PVPANIC) += pvpanic.o obj-$(CONFIG_AUX) += auxbus.o obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o aspeed_ibt.o obj-$(CONFIG_ASPEED_SOC) += aspeed_pwm.o aspeed_lpc.o aspeed_fsi.o +obj-$(CONFIG_ASPEED_SOC) += aspeed_xdma.o obj-$(CONFIG_MSF2) += msf2-sysreg.o obj-$(CONFIG_NRF51_SOC) += nrf51_rng.o diff --git a/hw/misc/aspeed_xdma.c b/hw/misc/aspeed_xdma.c new file mode 100644 index 000..eebd4ad --- /dev/null +++ b/hw/misc/aspeed_xdma.c @@ -0,0 +1,165 @@ +/* + * ASPEED XDMA Controller + * Eddie James + * + * Copyright (C) 2019 IBM Corp + * SPDX-License-Identifer: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "hw/misc/aspeed_xdma.h" +#include "qapi/error.h" + +#include "trace.h" + +#define XDMA_BMC_CMDQ_ADDR 0x10 +#define XDMA_BMC_CMDQ_ENDP 0x14 +#define XDMA_BMC_CMDQ_WRP 0x18 +#define XDMA_BMC_CMDQ_W_MASK 0x0003 +#define XDMA_BMC_CMDQ_RDP 0x1C +#define XDMA_BMC_CMDQ_RDP_MAGIC 0xEE882266 +#define XDMA_IRQ_ENG_CTRL 0x20 +#define XDMA_IRQ_ENG_CTRL_US_COMP BIT(4) +#define XDMA_IRQ_ENG_CTRL_DS_COMP BIT(5)
Re: [Qemu-devel] [PATCH] hw: misc: Add Aspeed XDMA device
On 6/6/19 6:34 PM, Philippe Mathieu-Daudé wrote: Hi Eddie, On 6/4/19 12:09 AM, Eddie James wrote: The XDMA engine embedded in the Aspeed SOCs performs PCI DMA operations between the SOC (acting as a BMC) and a host processor in a server. If I got your model correctly, it does no DMA operation but simply answer correctly to the BMC, and set 'operation done' IRQ with no delay. So this is a dummy device. Then it would be more useful having ignored DMA ops traced with trace-events. Thats correct. Good idea, I will add some tracing. The XDMA engine exists on the AST2400, AST2500, and AST2600 SOCs, so enable it for all of those. Signed-off-by: Eddie James --- hw/arm/aspeed_soc.c | 14 hw/misc/Makefile.objs | 2 +- hw/misc/aspeed_xdma.c | 156 ++ include/hw/arm/aspeed_soc.h | 2 + include/hw/misc/aspeed_xdma.h | 31 + 5 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 hw/misc/aspeed_xdma.c create mode 100644 include/hw/misc/aspeed_xdma.h diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c index faff42b..b25bb18 100644 --- a/hw/arm/aspeed_soc.c +++ b/hw/arm/aspeed_soc.c @@ -31,6 +31,7 @@ #define ASPEED_SOC_VIC_BASE 0x1E6C #define ASPEED_SOC_SDMC_BASE0x1E6E #define ASPEED_SOC_SCU_BASE 0x1E6E2000 +#define ASPEED_SOC_XDMA_BASE0x1E6E7000 #define ASPEED_SOC_SRAM_BASE0x1E72 #define ASPEED_SOC_TIMER_BASE 0x1E782000 #define ASPEED_SOC_WDT_BASE 0x1E785000 @@ -159,6 +160,9 @@ static void aspeed_soc_init(Object *obj) sysbus_init_child_obj(obj, "ftgmac100", OBJECT(>ftgmac100), sizeof(s->ftgmac100), TYPE_FTGMAC100); + +sysbus_init_child_obj(obj, "xdma", OBJECT(>xdma), sizeof(s->xdma), + TYPE_ASPEED_XDMA); } static void aspeed_soc_realize(DeviceState *dev, Error **errp) @@ -298,6 +302,16 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) sysbus_mmio_map(SYS_BUS_DEVICE(>ftgmac100), 0, ASPEED_SOC_ETH1_BASE); sysbus_connect_irq(SYS_BUS_DEVICE(>ftgmac100), 0, qdev_get_gpio_in(DEVICE(>vic), 2)); + +/* XDMA */ +object_property_set_bool(OBJECT(>xdma), true, "realized", ); +if (err) { +error_propagate(errp, err); +return; +} +sysbus_mmio_map(SYS_BUS_DEVICE(>xdma), 0, ASPEED_SOC_XDMA_BASE); +sysbus_connect_irq(SYS_BUS_DEVICE(>xdma), 0, + qdev_get_gpio_in(DEVICE(>vic), 6)); } static void aspeed_soc_class_init(ObjectClass *oc, void *data) diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index 77b9df9..a4483af 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -74,7 +74,7 @@ obj-$(CONFIG_ARMSSE_MHU) += armsse-mhu.o obj-$(CONFIG_PVPANIC) += pvpanic.o obj-$(CONFIG_AUX) += auxbus.o -obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o +obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o aspeed_xdma.o obj-$(CONFIG_MSF2) += msf2-sysreg.o obj-$(CONFIG_NRF51_SOC) += nrf51_rng.o diff --git a/hw/misc/aspeed_xdma.c b/hw/misc/aspeed_xdma.c new file mode 100644 index 000..fe3a32e --- /dev/null +++ b/hw/misc/aspeed_xdma.c @@ -0,0 +1,156 @@ +/* + * ASPEED XDMA Controller + * Eddie James + * + * Copyright (C) 2019 IBM Corp + * SPDX-License-Identifer: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "hw/misc/aspeed_xdma.h" +#include "qapi/error.h" + +#define XDMA_BMC_CMDQ_ADDR 0x10 +#define XDMA_BMC_CMDQ_ENDP 0x14 +#define XDMA_BMC_CMDQ_WRP 0x18 +#define XDMA_BMC_CMDQ_W_MASK 0x0003 +#define XDMA_BMC_CMDQ_RDP 0x1C +#define XDMA_BMC_CMDQ_RDP_MAGIC 0xEE882266 +#define XDMA_IRQ_ENG_CTRL 0x20 +#define XDMA_IRQ_ENG_CTRL_US_COMP BIT(4) +#define XDMA_IRQ_ENG_CTRL_DS_COMP BIT(5) +#define XDMA_IRQ_ENG_CTRL_W_MASK 0xBFEFF07F +#define XDMA_IRQ_ENG_STAT 0x24 +#define XDMA_IRQ_ENG_STAT_US_COMP BIT(4) +#define XDMA_IRQ_ENG_STAT_DS_COMP BIT(5) +#define XDMA_IRQ_ENG_STAT_RESET 0xF800 + +#define TO_REG(addr) ((addr) / sizeof(uint32_t)) + +static uint64_t aspeed_xdma_read(void *opaque, hwaddr addr, unsigned int size) +{ +uint32_t val = 0; +AspeedXDMAState *xdma = opaque; + +if (addr < ASPEED_XDMA_REG_SIZE) { +val = xdma->regs[TO_REG(addr)]; +} + +return (uint64_t)val; +} + +static void aspeed_xdma_write(void *opaque, hwaddr addr, uint64_t val, + unsigned int size) +{ +unsigned int idx; +uint32_t val32 = (uint32_t)val; +AspeedXDMAState *xdma = opaque; + +if (addr >= ASPEED_XDMA_REG_SIZE) { +return; +} + +switch (addr) { +case XDMA_BMC_CMDQ_ENDP: +xdma-&
Re: [Qemu-devel] [PATCH] hw: misc: Add Aspeed XDMA device
On 6/6/19 1:16 AM, Cédric Le Goater wrote: Hello Eddie, On 04/06/2019 00:09, Eddie James wrote: The XDMA engine embedded in the Aspeed SOCs performs PCI DMA operations between the SOC (acting as a BMC) and a host processor in a server. The XDMA engine exists on the AST2400, AST2500, and AST2600 SOCs, so enable it for all of those. Signed-off-by: Eddie James This looks correct to me. It's sufficient to exercise the BMC driver. However, we will need to rebase on an Aspeed patchset I sent earlier : http://patchwork.ozlabs.org/cover/1105343/ I can do that and include the patch in my tree for the moment. I built and tested the model on your tree, so let me know if you want me to send that patch instead? For my understanding, how can we interact with the model and pretend there is a host side ? I have an application that can test the driver here: https://github.com/eddiejames/xdma-test But as you say there is no host side; the operations don't copy any memory anywhere. Joel suggested adding some way to copy and check some dummy memory contents, but I haven't looked into that yet. Thanks, Eddie Thanks, C. --- hw/arm/aspeed_soc.c | 14 hw/misc/Makefile.objs | 2 +- hw/misc/aspeed_xdma.c | 156 ++ include/hw/arm/aspeed_soc.h | 2 + include/hw/misc/aspeed_xdma.h | 31 + 5 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 hw/misc/aspeed_xdma.c create mode 100644 include/hw/misc/aspeed_xdma.h diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c index faff42b..b25bb18 100644 --- a/hw/arm/aspeed_soc.c +++ b/hw/arm/aspeed_soc.c @@ -31,6 +31,7 @@ #define ASPEED_SOC_VIC_BASE 0x1E6C #define ASPEED_SOC_SDMC_BASE0x1E6E #define ASPEED_SOC_SCU_BASE 0x1E6E2000 +#define ASPEED_SOC_XDMA_BASE0x1E6E7000 #define ASPEED_SOC_SRAM_BASE0x1E72 #define ASPEED_SOC_TIMER_BASE 0x1E782000 #define ASPEED_SOC_WDT_BASE 0x1E785000 @@ -159,6 +160,9 @@ static void aspeed_soc_init(Object *obj) sysbus_init_child_obj(obj, "ftgmac100", OBJECT(>ftgmac100), sizeof(s->ftgmac100), TYPE_FTGMAC100); + +sysbus_init_child_obj(obj, "xdma", OBJECT(>xdma), sizeof(s->xdma), + TYPE_ASPEED_XDMA); } static void aspeed_soc_realize(DeviceState *dev, Error **errp) @@ -298,6 +302,16 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) sysbus_mmio_map(SYS_BUS_DEVICE(>ftgmac100), 0, ASPEED_SOC_ETH1_BASE); sysbus_connect_irq(SYS_BUS_DEVICE(>ftgmac100), 0, qdev_get_gpio_in(DEVICE(>vic), 2)); + +/* XDMA */ +object_property_set_bool(OBJECT(>xdma), true, "realized", ); +if (err) { +error_propagate(errp, err); +return; +} +sysbus_mmio_map(SYS_BUS_DEVICE(>xdma), 0, ASPEED_SOC_XDMA_BASE); +sysbus_connect_irq(SYS_BUS_DEVICE(>xdma), 0, + qdev_get_gpio_in(DEVICE(>vic), 6)); } static void aspeed_soc_class_init(ObjectClass *oc, void *data) diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index 77b9df9..a4483af 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -74,7 +74,7 @@ obj-$(CONFIG_ARMSSE_MHU) += armsse-mhu.o obj-$(CONFIG_PVPANIC) += pvpanic.o obj-$(CONFIG_AUX) += auxbus.o -obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o +obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o aspeed_xdma.o obj-$(CONFIG_MSF2) += msf2-sysreg.o obj-$(CONFIG_NRF51_SOC) += nrf51_rng.o diff --git a/hw/misc/aspeed_xdma.c b/hw/misc/aspeed_xdma.c new file mode 100644 index 000..fe3a32e --- /dev/null +++ b/hw/misc/aspeed_xdma.c @@ -0,0 +1,156 @@ +/* + * ASPEED XDMA Controller + * Eddie James + * + * Copyright (C) 2019 IBM Corp + * SPDX-License-Identifer: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "hw/misc/aspeed_xdma.h" +#include "qapi/error.h" + +#define XDMA_BMC_CMDQ_ADDR 0x10 +#define XDMA_BMC_CMDQ_ENDP 0x14 +#define XDMA_BMC_CMDQ_WRP 0x18 +#define XDMA_BMC_CMDQ_W_MASK 0x0003 +#define XDMA_BMC_CMDQ_RDP 0x1C +#define XDMA_BMC_CMDQ_RDP_MAGIC 0xEE882266 +#define XDMA_IRQ_ENG_CTRL 0x20 +#define XDMA_IRQ_ENG_CTRL_US_COMP BIT(4) +#define XDMA_IRQ_ENG_CTRL_DS_COMP BIT(5) +#define XDMA_IRQ_ENG_CTRL_W_MASK 0xBFEFF07F +#define XDMA_IRQ_ENG_STAT 0x24 +#define XDMA_IRQ_ENG_STAT_US_COMP BIT(4) +#define XDMA_IRQ_ENG_STAT_DS_COMP BIT(5) +#define XDMA_IRQ_ENG_STAT_RESET 0xF800 + +#define TO_REG(addr) ((addr) / sizeof(uint32_t)) + +static uint64_t aspeed_xdma_read(void *opaque, hwaddr addr, unsigned int size) +{ +uint32_t val = 0; +AspeedXDMAState *xdma = opaque; + +
[Qemu-devel] [PATCH] hw: misc: Add Aspeed XDMA device
The XDMA engine embedded in the Aspeed SOCs performs PCI DMA operations between the SOC (acting as a BMC) and a host processor in a server. The XDMA engine exists on the AST2400, AST2500, and AST2600 SOCs, so enable it for all of those. Signed-off-by: Eddie James --- hw/arm/aspeed_soc.c | 14 hw/misc/Makefile.objs | 2 +- hw/misc/aspeed_xdma.c | 156 ++ include/hw/arm/aspeed_soc.h | 2 + include/hw/misc/aspeed_xdma.h | 31 + 5 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 hw/misc/aspeed_xdma.c create mode 100644 include/hw/misc/aspeed_xdma.h diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c index faff42b..b25bb18 100644 --- a/hw/arm/aspeed_soc.c +++ b/hw/arm/aspeed_soc.c @@ -31,6 +31,7 @@ #define ASPEED_SOC_VIC_BASE 0x1E6C #define ASPEED_SOC_SDMC_BASE0x1E6E #define ASPEED_SOC_SCU_BASE 0x1E6E2000 +#define ASPEED_SOC_XDMA_BASE0x1E6E7000 #define ASPEED_SOC_SRAM_BASE0x1E72 #define ASPEED_SOC_TIMER_BASE 0x1E782000 #define ASPEED_SOC_WDT_BASE 0x1E785000 @@ -159,6 +160,9 @@ static void aspeed_soc_init(Object *obj) sysbus_init_child_obj(obj, "ftgmac100", OBJECT(>ftgmac100), sizeof(s->ftgmac100), TYPE_FTGMAC100); + +sysbus_init_child_obj(obj, "xdma", OBJECT(>xdma), sizeof(s->xdma), + TYPE_ASPEED_XDMA); } static void aspeed_soc_realize(DeviceState *dev, Error **errp) @@ -298,6 +302,16 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp) sysbus_mmio_map(SYS_BUS_DEVICE(>ftgmac100), 0, ASPEED_SOC_ETH1_BASE); sysbus_connect_irq(SYS_BUS_DEVICE(>ftgmac100), 0, qdev_get_gpio_in(DEVICE(>vic), 2)); + +/* XDMA */ +object_property_set_bool(OBJECT(>xdma), true, "realized", ); +if (err) { +error_propagate(errp, err); +return; +} +sysbus_mmio_map(SYS_BUS_DEVICE(>xdma), 0, ASPEED_SOC_XDMA_BASE); +sysbus_connect_irq(SYS_BUS_DEVICE(>xdma), 0, + qdev_get_gpio_in(DEVICE(>vic), 6)); } static void aspeed_soc_class_init(ObjectClass *oc, void *data) diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index 77b9df9..a4483af 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -74,7 +74,7 @@ obj-$(CONFIG_ARMSSE_MHU) += armsse-mhu.o obj-$(CONFIG_PVPANIC) += pvpanic.o obj-$(CONFIG_AUX) += auxbus.o -obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o +obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o aspeed_xdma.o obj-$(CONFIG_MSF2) += msf2-sysreg.o obj-$(CONFIG_NRF51_SOC) += nrf51_rng.o diff --git a/hw/misc/aspeed_xdma.c b/hw/misc/aspeed_xdma.c new file mode 100644 index 000..fe3a32e --- /dev/null +++ b/hw/misc/aspeed_xdma.c @@ -0,0 +1,156 @@ +/* + * ASPEED XDMA Controller + * Eddie James + * + * Copyright (C) 2019 IBM Corp + * SPDX-License-Identifer: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "hw/misc/aspeed_xdma.h" +#include "qapi/error.h" + +#define XDMA_BMC_CMDQ_ADDR 0x10 +#define XDMA_BMC_CMDQ_ENDP 0x14 +#define XDMA_BMC_CMDQ_WRP 0x18 +#define XDMA_BMC_CMDQ_W_MASK 0x0003 +#define XDMA_BMC_CMDQ_RDP 0x1C +#define XDMA_BMC_CMDQ_RDP_MAGIC 0xEE882266 +#define XDMA_IRQ_ENG_CTRL 0x20 +#define XDMA_IRQ_ENG_CTRL_US_COMP BIT(4) +#define XDMA_IRQ_ENG_CTRL_DS_COMP BIT(5) +#define XDMA_IRQ_ENG_CTRL_W_MASK 0xBFEFF07F +#define XDMA_IRQ_ENG_STAT 0x24 +#define XDMA_IRQ_ENG_STAT_US_COMP BIT(4) +#define XDMA_IRQ_ENG_STAT_DS_COMP BIT(5) +#define XDMA_IRQ_ENG_STAT_RESET 0xF800 + +#define TO_REG(addr) ((addr) / sizeof(uint32_t)) + +static uint64_t aspeed_xdma_read(void *opaque, hwaddr addr, unsigned int size) +{ +uint32_t val = 0; +AspeedXDMAState *xdma = opaque; + +if (addr < ASPEED_XDMA_REG_SIZE) { +val = xdma->regs[TO_REG(addr)]; +} + +return (uint64_t)val; +} + +static void aspeed_xdma_write(void *opaque, hwaddr addr, uint64_t val, + unsigned int size) +{ +unsigned int idx; +uint32_t val32 = (uint32_t)val; +AspeedXDMAState *xdma = opaque; + +if (addr >= ASPEED_XDMA_REG_SIZE) { +return; +} + +switch (addr) { +case XDMA_BMC_CMDQ_ENDP: +xdma->regs[TO_REG(addr)] = val32 & XDMA_BMC_CMDQ_W_MASK; +break; +case XDMA_BMC_CMDQ_WRP: +idx = TO_REG(addr); +xdma->regs[idx] = val32 & XDMA_BMC_CMDQ_W_MASK; +xdma->regs[TO_REG(XDMA_BMC_CMDQ_RDP)] = xdma->regs[idx]; + +if (xdma->bmc_cmdq_readp_set) { +xdma->bmc_cmdq_readp_set = 0; +} else { +xdma->regs[TO_RE