qemu-arm
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: [PATCH v3 08/16] aspeed/smc: support 64 bits dma dram address


From: Jamin Lin
Subject: RE: [PATCH v3 08/16] aspeed/smc: support 64 bits dma dram address
Date: Tue, 30 Apr 2024 07:56:57 +0000

Hi Cedric,

> -----Original Message-----
> From: Cédric Le Goater <clg@kaod.org>
> Sent: Tuesday, April 30, 2024 3:26 PM
> To: Jamin Lin <jamin_lin@aspeedtech.com>; Peter Maydell
> <peter.maydell@linaro.org>; Andrew Jeffery <andrew@codeconstruct.com.au>;
> Joel Stanley <joel@jms.id.au>; Alistair Francis <alistair@alistair23.me>; 
> Cleber
> Rosa <crosa@redhat.com>; Philippe Mathieu-Daudé <philmd@linaro.org>;
> Wainer dos Santos Moschetta <wainersm@redhat.com>; Beraldo Leal
> <bleal@redhat.com>; open list:ASPEED BMCs <qemu-arm@nongnu.org>; open
> list:All patches CC here <qemu-devel@nongnu.org>
> Cc: Troy Lee <troy_lee@aspeedtech.com>; Yunlin Tang
> <yunlin.tang@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_lee@aspeedtech.com>
> >>> Signed-off-by: Jamin Lin <jamin_lin@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.
> 
> 


reply via email to

[Prev in Thread] Current Thread [Next in Thread]