Hi Cedric, > -----Original Message----- > From: Cédric Le Goater <c...@kaod.org> > Sent: Tuesday, April 30, 2024 3:26 PM > To: Jamin Lin <jamin_...@aspeedtech.com>; Peter Maydell > <peter.mayd...@linaro.org>; Andrew Jeffery <and...@codeconstruct.com.au>; > Joel Stanley <j...@jms.id.au>; Alistair Francis <alist...@alistair23.me>; > Cleber > Rosa <cr...@redhat.com>; Philippe Mathieu-Daudé <phi...@linaro.org>; > Wainer dos Santos Moschetta <waine...@redhat.com>; Beraldo Leal > <bl...@redhat.com>; open list:ASPEED BMCs <qemu-...@nongnu.org>; open > list:All patches CC here <qemu-devel@nongnu.org> > Cc: Troy Lee <troy_...@aspeedtech.com>; Yunlin Tang > <yunlin.t...@aspeedtech.com> > Subject: Re: [PATCH v3 08/16] aspeed/smc: support 64 bits dma dram address > > On 4/19/24 08:00, Jamin Lin wrote: > > Hi Cedric, > >> > >> Hello Jamin, > >> > >> On 4/16/24 11:18, Jamin Lin wrote: > >>> AST2700 support the maximum dram size is 8GiB and has a "DMA DRAM > >> Side > >>> Address High Part(0x7C)" > >>> register to support 64 bits dma dram address. > >>> Add helper routines functions to compute the dma dram address, new > >>> features and update trace-event to support 64 bits dram address. > >>> > >>> Signed-off-by: Troy Lee <troy_...@aspeedtech.com> > >>> Signed-off-by: Jamin Lin <jamin_...@aspeedtech.com> > >>> --- > >>> hw/ssi/aspeed_smc.c | 66 > >> +++++++++++++++++++++++++++++++++++++++------ > >>> hw/ssi/trace-events | 2 +- > >>> 2 files changed, 59 insertions(+), 9 deletions(-) > >>> > >>> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c index > >>> 71abc7a2d8..a67cac3d0f 100644 > >>> --- a/hw/ssi/aspeed_smc.c > >>> +++ b/hw/ssi/aspeed_smc.c > >>> @@ -132,6 +132,9 @@ > >>> #define FMC_WDT2_CTRL_BOOT_SOURCE BIT(4) /* O: > primary > >> 1: alternate */ > >>> #define FMC_WDT2_CTRL_EN BIT(0) > >>> > >>> +/* DMA DRAM Side Address High Part (AST2700) */ > >>> +#define R_DMA_DRAM_ADDR_HIGH (0x7c / 4) > >>> + > >>> /* DMA Control/Status Register */ > >>> #define R_DMA_CTRL (0x80 / 4) > >>> #define DMA_CTRL_REQUEST (1 << 31) > >>> @@ -187,6 +190,7 @@ > >>> * 0x1FFFFFF: 32M bytes > >>> */ > >>> #define DMA_DRAM_ADDR(asc, val) ((val) & > (asc)->dma_dram_mask) > >>> +#define DMA_DRAM_ADDR_HIGH(val) ((val) & 0xf) > >>> #define DMA_FLASH_ADDR(asc, val) ((val) & > (asc)->dma_flash_mask) > >>> #define DMA_LENGTH(val) ((val) & 0x01FFFFFF) > >>> > >>> @@ -207,6 +211,7 @@ static const AspeedSegments > >> aspeed_2500_spi2_segments[]; > >>> #define ASPEED_SMC_FEATURE_DMA 0x1 > >>> #define ASPEED_SMC_FEATURE_DMA_GRANT 0x2 > >>> #define ASPEED_SMC_FEATURE_WDT_CONTROL 0x4 > >>> +#define ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH 0x08 > >>> > >>> static inline bool aspeed_smc_has_dma(const AspeedSMCClass *asc) > >>> { > >>> @@ -218,6 +223,11 @@ static inline bool > >> aspeed_smc_has_wdt_control(const AspeedSMCClass *asc) > >>> return !!(asc->features & > ASPEED_SMC_FEATURE_WDT_CONTROL); > >>> } > >>> > >>> +static inline bool aspeed_smc_has_dma_dram_addr_high(const > >>> +AspeedSMCClass *asc) > >> > >> To ease the reading, I would call the helper aspeed_smc_has_dma64() > > Will fix it > >> > >>> +{ > >>> + return !!(asc->features & > >> ASPEED_SMC_FEATURE_DMA_DRAM_ADDR_HIGH); > >>> +} > >>> + > >>> #define aspeed_smc_error(fmt, ...) > >> \ > >>> qemu_log_mask(LOG_GUEST_ERROR, "%s: " fmt "\n", __func__, > ## > >>> __VA_ARGS__) > >>> > >>> @@ -747,6 +757,9 @@ static uint64_t aspeed_smc_read(void *opaque, > >> hwaddr addr, unsigned int size) > >>> (aspeed_smc_has_dma(asc) && addr == R_DMA_CTRL) || > >>> (aspeed_smc_has_dma(asc) && addr == > R_DMA_FLASH_ADDR) > >> || > >>> (aspeed_smc_has_dma(asc) && addr == > R_DMA_DRAM_ADDR) > >> || > >>> + (aspeed_smc_has_dma(asc) && > >>> + aspeed_smc_has_dma_dram_addr_high(asc) && > >>> + addr == R_DMA_DRAM_ADDR_HIGH) || > >>> (aspeed_smc_has_dma(asc) && addr == R_DMA_LEN) || > >>> (aspeed_smc_has_dma(asc) && addr == > R_DMA_CHECKSUM) > >> || > >>> (addr >= R_SEG_ADDR0 && > >>> @@ -847,6 +860,23 @@ static bool > >> aspeed_smc_inject_read_failure(AspeedSMCState *s) > >>> } > >>> } > >>> > >>> +static uint64_t aspeed_smc_dma_dram_addr(AspeedSMCState *s) { > >>> + AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s); > >>> + uint64_t dram_addr_high; > >>> + uint64_t dma_dram_addr; > >>> + > >>> + if (aspeed_smc_has_dma_dram_addr_high(asc)) { > >>> + dram_addr_high = s->regs[R_DMA_DRAM_ADDR_HIGH]; > >>> + dram_addr_high <<= 32; > >>> + dma_dram_addr = dram_addr_high | > >> s->regs[R_DMA_DRAM_ADDR]; > >> > >> Here is a proposal to shorten the routine : > >> > >> return ((uint64_t) s->regs[R_DMA_DRAM_ADDR_HIGH] << 32) > | > >> s->regs[R_DMA_DRAM_ADDR]; > >> > >> > >>> + } else { > >>> + dma_dram_addr = s->regs[R_DMA_DRAM_ADDR]; > >> > >> and > >> return s->regs[R_DMA_DRAM_ADDR]; > >> > >>> + } > >>> + > >>> + return dma_dram_addr; > >>> +} > >>> + > > Thanks for your suggestion. Will fix. > >>> static uint32_t aspeed_smc_dma_len(AspeedSMCState *s) > >>> { > >>> AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s); @@ > -914,24 > >>> +944,34 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s) > >>> > >>> static void aspeed_smc_dma_rw(AspeedSMCState *s) > >>> { > >>> + AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s); > >>> + uint64_t dram_addr_high; > >> > >> This variable doesn't look very useful > > Will try to remove it. > >> > >>> + uint64_t dma_dram_addr; > >>> + uint64_t dram_addr; > >> > >> and dram_addr is redundant with dma_dram_addr. Please use only one. > > Please see my below description and please give us any suggestion. > >> > >> > >>> MemTxResult result; > >>> uint32_t dma_len; > >>> uint32_t data; > >>> > >>> dma_len = aspeed_smc_dma_len(s); > >>> + dma_dram_addr = aspeed_smc_dma_dram_addr(s); > >>> + > >>> + if (aspeed_smc_has_dma_dram_addr_high(asc)) { > >>> + dram_addr = dma_dram_addr - s->dram_mr->container->addr; > >> > >> Why do you truncate the address again ? It should already be done > >> with > >> > >> #define DMA_DRAM_ADDR_HIGH(val) ((val) & 0xf) > >> > > The reason is that our firmware set the real address in SMC registers. > > For example: If users want to move data from flash to the DRAM at > > address 0, It set R_DMA_DRAM_ADDR_HIGH 4 and R_DMA_DRAM_ADDR 0 > because > > the dram base address is 0x 4 00000000 for AST2700. > > > Could you please share the specs of the R_DMA_DRAM_ADDR and > R_DMA_DRAM_ADDR_HIGH registers to see what are the init values, how > these registers should be set, their alignment constraints if any, how the > values > evolve while the HW does the DMA transactions, etc. > DMA_DRAM_SIDE_ADDRESS 0x088 Init=0x00000000 31:0 RW DMA_RO DRAM side start address For DMA Read flash, this the destination address. For DMA Write flash, the is the source address DMA only execute on 4 bytes boundary When read, it shows the current working address
DMA DRAM Side Address High Part 0x07c Init=0x00000000 32:8 RO reserved 7:0 RW DMA_RO_HI dma_ro[39:32] Therefore, DMA address is dma_ro[39:0] Our FW settings, In u-boot shell, execute the following command cp.b 100220000 403000000 100 100220000 flash address for kernel fit image 403000000 dram address at offset 3000000 https://github.com/AspeedTech-BMC/u-boot/blob/aspeed-master-v2023.10/lib/string.c#L553C8-L553C29 https://github.com/AspeedTech-BMC/u-boot/blob/aspeed-master-v2023.10/arch/arm/mach-aspeed/ast2700/spi.c#L156 https://github.com/AspeedTech-BMC/u-boot/blob/aspeed-master-v2023.10/arch/arm/mach-aspeed/ast2700/spi.c#L179-L183 Thanks-Jamin > Thanks, > > C. > >