qemu-arm
[Top][All Lists]
Advanced

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

Re: [PATCH for-5.2 16/19] aspeed/sdmc: Perform memory training


From: Philippe Mathieu-Daudé
Subject: Re: [PATCH for-5.2 16/19] aspeed/sdmc: Perform memory training
Date: Thu, 6 Aug 2020 15:38:08 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.5.0

On 8/6/20 3:21 PM, Cédric Le Goater wrote:
> From: Joel Stanley <joel@jms.id.au>
> 
> This allows qemu to run the "normal" power on reset boot path through
> u-boot, where the DDR is trained.
> 
> An enhancement would be to have the SCU bit stick across qemu reboots,
> but be unset on initial boot.
> 
> Proper modelling would be to discard all writes to the phy setting regs
> at offset 0x100 - 0x400 and to model the phy status regs at offset
> 0x400.
> 
> The status regs model would only need to account for offets 0x00,
> 0x50, 0x68 and 0x7c.
> 
> Signed-off-by: Joel Stanley <joel@jms.id.au>
> [ clg: checkpatch fixes ]
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> ---
>  include/hw/misc/aspeed_sdmc.h | 13 ++++++++++++-
>  hw/misc/aspeed_scu.c          |  2 +-
>  hw/misc/aspeed_sdmc.c         | 19 +++++++++++++++++--
>  3 files changed, 30 insertions(+), 4 deletions(-)
> 
> diff --git a/include/hw/misc/aspeed_sdmc.h b/include/hw/misc/aspeed_sdmc.h
> index cea1e67fe365..c6226957dd3d 100644
> --- a/include/hw/misc/aspeed_sdmc.h
> +++ b/include/hw/misc/aspeed_sdmc.h
> @@ -17,7 +17,18 @@
>  #define TYPE_ASPEED_2500_SDMC TYPE_ASPEED_SDMC "-ast2500"
>  #define TYPE_ASPEED_2600_SDMC TYPE_ASPEED_SDMC "-ast2600"
>  
> -#define ASPEED_SDMC_NR_REGS (0x174 >> 2)
> +/*
> + * SDMC has 174 documented registers. In addition the u-boot device tree
> + * describes the following regions:
> + *  - PHY status regs at offset 0x400, length 0x200
> + *  - PHY setting regs at offset 0x100, length 0x300
> + *
> + * There are two sets of MRS (Mode Registers) configuration in ast2600 memory
> + * system: one is in the SDRAM MC (memory controller) which is used in run
> + * time, and the other is in the DDR-PHY IP which is used during DDR-PHY
> + * training.
> + */
> +#define ASPEED_SDMC_NR_REGS (0x500 >> 2)
>  
>  typedef struct AspeedSDMCState {
>      /*< private >*/
> diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
> index 764222404bef..dc6dd87c22f4 100644
> --- a/hw/misc/aspeed_scu.c
> +++ b/hw/misc/aspeed_scu.c
> @@ -656,7 +656,7 @@ static const uint32_t 
> ast2600_a1_resets[ASPEED_AST2600_SCU_NR_REGS] = {
>      [AST2600_SYS_RST_CTRL2]     = 0xFFFFFFFC,
>      [AST2600_CLK_STOP_CTRL]     = 0xFFFF7F8A,
>      [AST2600_CLK_STOP_CTRL2]    = 0xFFF0FFF0,
> -    [AST2600_SDRAM_HANDSHAKE]   = 0x00000040,  /* SoC completed DRAM init */
> +    [AST2600_SDRAM_HANDSHAKE]   = 0x00000000,
>      [AST2600_HPLL_PARAM]        = 0x1000405F,
>      [AST2600_CHIP_ID0]          = 0x1234ABCD,
>      [AST2600_CHIP_ID1]          = 0x88884444,
> diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
> index 855848b7d23a..ff2809a09965 100644
> --- a/hw/misc/aspeed_sdmc.c
> +++ b/hw/misc/aspeed_sdmc.c
> @@ -113,7 +113,7 @@ static uint64_t aspeed_sdmc_read(void *opaque, hwaddr 
> addr, unsigned size)
>      if (addr >= ARRAY_SIZE(s->regs)) {
>          qemu_log_mask(LOG_GUEST_ERROR,
>                        "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx 
> "\n",
> -                      __func__, addr);
> +                      __func__, addr * 4);
>          return 0;
>      }
>  
> @@ -206,6 +206,19 @@ static void aspeed_sdmc_reset(DeviceState *dev)
>  
>      /* Set ram size bit and defaults values */
>      s->regs[R_CONF] = asc->compute_conf(s, 0);
> +
> +    /*
> +     * PHY status:
> +     *  - set phy status ok (set bit 1)
> +     *  - initial PVT calibration ok (clear bit 3)
> +     *  - runtime calibration ok (clear bit 5)
> +     */
> +    s->regs[0x100] = BIT(1);

This is usually implemented with a one-shot timer, see
sd_ocr_powerup() in hw/sd/sd.c (migration is handled).

> +
> +    /* PHY eye window: set all as passing */
> +    s->regs[0x100 | (0x68 / 4)] = 0xff;
> +    s->regs[0x100 | (0x7c / 4)] = 0xff;
> +    s->regs[0x100 | (0x50 / 4)] = 0xfffffff;
>  }
>  
>  static void aspeed_sdmc_get_ram_size(Object *obj, Visitor *v, const char 
> *name,
> @@ -443,7 +456,9 @@ static void aspeed_2600_sdmc_write(AspeedSDMCState *s, 
> uint32_t reg,
>      }
>  
>      if (reg != R_PROT && s->regs[R_PROT] == PROT_SOFTLOCKED) {
> -        qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked!\n", __func__);
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +                      "%s: SDMC is locked! (write to MCR%02x blocked)\n",
> +                      __func__, reg * 4);
>          return;
>      }
>  
> 




reply via email to

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