qemu-devel
[Top][All Lists]
Advanced

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

RE: [PATCH v2 3/9] aspeed/sdmc: Add AST2700 support


From: Jamin Lin
Subject: RE: [PATCH v2 3/9] aspeed/sdmc: Add AST2700 support
Date: Mon, 11 Mar 2024 07:21:09 +0000

> -----Original Message-----
> From: Cédric Le Goater <clg@kaod.org>
> Sent: Monday, March 4, 2024 10:47 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>; 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 v2 3/9] aspeed/sdmc: Add AST2700 support
>
Hi Cedrice,

Thanks for review and sorry reply you late.
 
> On 3/4/24 10:29, Jamin Lin wrote:
> > The SDRAM memory controller(DRAMC) controls the access to external
> > DDR4 and DDR5 SDRAM and power up to DDR4 and DDR5 PHY.
> >
> > The DRAM memory controller of AST2700 is not backward compatible to
> > previous chips such AST2600, AST2500 and AST2400.
> >
> > Max memory is now 8GiB on the AST2700. Introduce new
> aspeed_2700_sdmc
> > and class with read/write operation and reset handlers.
> >
> > Define DRAMC necessary protected registers and unprotected registers
> > for AST2700 and increase the register set to 0x1000.
> >
> > Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
> > Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
> > ---
> >   hw/misc/aspeed_sdmc.c         | 215
> ++++++++++++++++++++++++++++++----
> >   include/hw/misc/aspeed_sdmc.h |   4 +-
> >   2 files changed, 198 insertions(+), 21 deletions(-)
> >
> > diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c index
> > 64cd1a81dc..63fb7936c4 100644
> > --- a/hw/misc/aspeed_sdmc.c
> > +++ b/hw/misc/aspeed_sdmc.c
> > @@ -27,6 +27,7 @@
> >   #define   PROT_SOFTLOCKED    0x00
> >
> >   #define   PROT_KEY_UNLOCK     0xFC600309
> > +#define   PROT_2700_KEY_UNLOCK  0x1688A8A8
> >   #define   PROT_KEY_HARDLOCK   0xDEADDEAD /* AST2600 */
> >
> >   /* Configuration Register */
> > @@ -54,6 +55,46 @@
> >   #define R_DRAM_TIME       (0x8c / 4)
> >   #define R_ECC_ERR_INJECT  (0xb4 / 4)
> >
> > +/* AST2700 Register */
> > +#define R_2700_PROT                 (0x00 / 4)
> > +#define R_INT_STATUS                (0x04 / 4)
> > +#define R_INT_CLEAR                 (0x08 / 4)
> > +#define R_INT_MASK                  (0x0c / 4)
> > +#define R_MAIN_CONF                 (0x10 / 4)
> > +#define R_MAIN_CONTROL              (0x14 / 4)
> > +#define R_MAIN_STATUS               (0x18 / 4)
> > +#define R_ERR_STATUS                (0x1c / 4)
> > +#define R_ECC_FAIL_STATUS           (0x78 / 4)
> > +#define R_ECC_FAIL_ADDR             (0x7c / 4)
> > +#define R_ECC_TESTING_CONTROL       (0x80 / 4)
> > +#define R_PROT_REGION_LOCK_STATUS   (0x94 / 4)
> > +#define R_TEST_FAIL_ADDR            (0xd4 / 4)
> > +#define R_TEST_FAIL_D0              (0xd8 / 4)
> > +#define R_TEST_FAIL_D1              (0xdc / 4)
> > +#define R_TEST_FAIL_D2              (0xe0 / 4)
> > +#define R_TEST_FAIL_D3              (0xe4 / 4)
> > +#define R_DBG_STATUS                (0xf4 / 4)
> > +#define R_PHY_INTERFACE_STATUS      (0xf8 / 4)
> > +#define R_GRAPHIC_MEM_BASE_ADDR     (0x10c / 4)
> > +#define R_PORT0_INTERFACE_MONITOR0  (0x240 / 4) #define
> > +R_PORT0_INTERFACE_MONITOR1  (0x244 / 4) #define
> > +R_PORT0_INTERFACE_MONITOR2  (0x248 / 4) #define
> > +R_PORT1_INTERFACE_MONITOR0  (0x2c0 / 4) #define
> > +R_PORT1_INTERFACE_MONITOR1  (0x2c4 / 4) #define
> > +R_PORT1_INTERFACE_MONITOR2  (0x2c8 / 4) #define
> > +R_PORT2_INTERFACE_MONITOR0  (0x340 / 4) #define
> > +R_PORT2_INTERFACE_MONITOR1  (0x344 / 4) #define
> > +R_PORT2_INTERFACE_MONITOR2  (0x348 / 4) #define
> > +R_PORT3_INTERFACE_MONITOR0  (0x3c0 / 4) #define
> > +R_PORT3_INTERFACE_MONITOR1  (0x3c4 / 4) #define
> > +R_PORT3_INTERFACE_MONITOR2  (0x3c8 / 4) #define
> > +R_PORT4_INTERFACE_MONITOR0  (0x440 / 4) #define
> > +R_PORT4_INTERFACE_MONITOR1  (0x444 / 4) #define
> > +R_PORT4_INTERFACE_MONITOR2  (0x448 / 4) #define
> > +R_PORT5_INTERFACE_MONITOR0  (0x4c0 / 4) #define
> > +R_PORT5_INTERFACE_MONITOR1  (0x4c4 / 4) #define
> > +R_PORT5_INTERFACE_MONITOR2  (0x4c8 / 4)
> > +
> >   /*
> >    * Configuration register Ox4 (for Aspeed AST2400 SOC)
> >    *
> > @@ -76,10 +117,6 @@
> >   #define     ASPEED_SDMC_VGA_32MB            0x2
> >   #define     ASPEED_SDMC_VGA_64MB            0x3
> >   #define ASPEED_SDMC_DRAM_SIZE(x)        (x & 0x3)
> > -#define     ASPEED_SDMC_DRAM_64MB           0x0
> > -#define     ASPEED_SDMC_DRAM_128MB          0x1
> > -#define     ASPEED_SDMC_DRAM_256MB          0x2
> > -#define     ASPEED_SDMC_DRAM_512MB          0x3
> >
> >   #define ASPEED_SDMC_READONLY_MASK                       \
> >       (ASPEED_SDMC_RESERVED | ASPEED_SDMC_VGA_COMPAT |    \
> > @@ -100,22 +137,24 @@
> >   #define ASPEED_SDMC_CACHE_ENABLE        (1 << 10) /* differs
> from AST2400 */
> >   #define ASPEED_SDMC_DRAM_TYPE           (1 << 4)  /* differs
> from AST2400 */
> >
> > -/* DRAM size definitions differs */
> > -#define     ASPEED_SDMC_AST2500_128MB       0x0
> > -#define     ASPEED_SDMC_AST2500_256MB       0x1
> > -#define     ASPEED_SDMC_AST2500_512MB       0x2
> > -#define     ASPEED_SDMC_AST2500_1024MB      0x3
> > -
> > -#define     ASPEED_SDMC_AST2600_256MB       0x0
> > -#define     ASPEED_SDMC_AST2600_512MB       0x1
> > -#define     ASPEED_SDMC_AST2600_1024MB      0x2
> > -#define     ASPEED_SDMC_AST2600_2048MB      0x3
> > -
> Please move the removal above in a separate patch.
Will fix
> 
> >   #define ASPEED_SDMC_AST2500_READONLY_MASK
> \
> >       (ASPEED_SDMC_HW_VERSION(0xf) |
> ASPEED_SDMC_CACHE_INITIAL_DONE |     \
> >        ASPEED_SDMC_AST2500_RESERVED |
> ASPEED_SDMC_VGA_COMPAT |            \
> >        ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB))
> >
> > +/*
> > + * Main Configuration register Ox10 (for Aspeed AST2700 SOC and
> > +higher)
> > + *
> > + */
> > +#define ASPEED_SDMC_AST2700_RESERVED        0xFFFF2082 /* 31:16,
> 13, 7, 1 */
> > +#define ASPEED_SDMC_AST2700_DATA_SCRAMBLE           (1 << 8)
> > +#define ASPEED_SDMC_AST2700_ECC_ENABLE              (1 << 6)
> > +#define ASPEED_SDMC_AST2700_PAGE_MATCHING_ENABLE    (1 << 5)
> > +#define ASPEED_SDMC_AST2700_DRAM_SIZE(x)            ((x & 0x7)
> << 2)
> > +
> > +#define ASPEED_SDMC_AST2700_READONLY_MASK   \
> > +     (ASPEED_SDMC_AST2700_RESERVED)
> > +
> >   static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr, unsigned
> size)
> >   {
> >       AspeedSDMCState *s = ASPEED_SDMC(opaque); @@ -231,7 +270,10
> @@
> > static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
> >       AspeedSDMCState *s = ASPEED_SDMC(dev);
> >       AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s);
> >
> > -    assert(asc->max_ram_size < 4 * GiB); /* 32-bit address bus */
> > +    if (!asc->is_bus64bit) {
> > +        assert(asc->max_ram_size < 4 * GiB); /* 32-bit address bus */
> > +    }
> 
> May be :
> 
>     assert(asc->max_ram_size < 4 * GiB || asc->is_bus64bit);
> 
> ?
Will fix
> 
> > +
> >       s->max_ram_size = asc->max_ram_size;
> >
> >       memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sdmc_ops,
> s,
> > @@ -311,7 +353,8 @@ static void
> aspeed_2400_sdmc_write(AspeedSDMCState *s, uint32_t reg,
> >                                      uint32_t data)
> >   {
> >       if (reg == R_PROT) {
> > -        s->regs[reg] = (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED :
> PROT_SOFTLOCKED;
> > +        s->regs[reg] =
> > +            (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED :
> > + PROT_SOFTLOCKED;
> >           return;
> >       }
> >
> > @@ -369,7 +412,8 @@ static void
> aspeed_2500_sdmc_write(AspeedSDMCState *s, uint32_t reg,
> >                                      uint32_t data)
> >   {
> >       if (reg == R_PROT) {
> > -        s->regs[reg] = (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED :
> PROT_SOFTLOCKED;
> > +        s->regs[reg] =
> > +            (data == PROT_KEY_UNLOCK) ? PROT_UNLOCKED :
> > + PROT_SOFTLOCKED;
> >           return;
> >       }
> >
> > @@ -449,8 +493,9 @@ static void
> aspeed_2600_sdmc_write(AspeedSDMCState *s, uint32_t reg,
> >       }
> >
> >       if (s->regs[R_PROT] == PROT_HARDLOCKED) {
> > -        qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked until
> system reset!\n",
> > -                __func__);
> > +        qemu_log_mask(LOG_GUEST_ERROR,
> > +                      "%s: SDMC is locked until system reset!\n",
> > +                      __func__);
> >           return;
> >       }
> 
> The checkpatch changes could be in a separate patch. This is minor.
Will fix
> 
> >
> > @@ -512,12 +557,142 @@ static const TypeInfo aspeed_2600_sdmc_info = {
> >       .class_init = aspeed_2600_sdmc_class_init,
> >   };
> >
> > +static void aspeed_2700_sdmc_reset(DeviceState *dev) {
> > +    AspeedSDMCState *s = ASPEED_SDMC(dev);
> > +    AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s);
> > +
> > +    memset(s->regs, 0, sizeof(s->regs));
> > +
> > +    /* Set ram size bit and defaults values */
> > +    s->regs[R_MAIN_CONF] = asc->compute_conf(s, 0);
> > +    s->regs[R_2700_PROT] = PROT_UNLOCKED;
> 
> The default reset value is unlocked ?
> 
The sdmc controller is unlocked at the SPL stage for AST2700.
However, currently QEMU only support to emulate that AST2700 booting start at 
the u-boot stage.
That was why I set the default value was unlocked, so firmware(u-boot)
able to write the sdmc registers.
https://github.com/AspeedTech-BMC/u-boot/blob/aspeed-master-v2023.10/board/aspeed/ibex_ast2700/sdram_ast2700.c#L716
 
https://github.com/AspeedTech-BMC/u-boot/blob/aspeed-master-v2023.10/board/aspeed/ibex_ast2700/sdram_ast2700.c#L277

Thanks-Jamin

> 
> Thanks,
> 
> C.
> 
> 
> 
> > +}
> > +
> > +static uint32_t aspeed_2700_sdmc_compute_conf(AspeedSDMCState *s,
> > +uint32_t data) {
> > +    uint32_t fixed_conf =
> ASPEED_SDMC_AST2700_PAGE_MATCHING_ENABLE |
> > +
> ASPEED_SDMC_AST2700_DRAM_SIZE(aspeed_sdmc_get_ram_bits(s));
> > +
> > +    /* Make sure readonly bits are kept */
> > +    data &= ~ASPEED_SDMC_AST2700_READONLY_MASK;
> > +
> > +    return data | fixed_conf;
> > +}
> > +
> > +static void aspeed_2700_sdmc_write(AspeedSDMCState *s, uint32_t reg,
> > +                                   uint32_t data) {
> > +    /* Unprotected registers */
> > +    switch (reg) {
> > +    case R_INT_STATUS:
> > +    case R_INT_CLEAR:
> > +    case R_INT_MASK:
> > +    case R_MAIN_STATUS:
> > +    case R_ERR_STATUS:
> > +    case R_ECC_FAIL_STATUS:
> > +    case R_ECC_FAIL_ADDR:
> > +    case R_PROT_REGION_LOCK_STATUS:
> > +    case R_TEST_FAIL_ADDR:
> > +    case R_TEST_FAIL_D0:
> > +    case R_TEST_FAIL_D1:
> > +    case R_TEST_FAIL_D2:
> > +    case R_TEST_FAIL_D3:
> > +    case R_DBG_STATUS:
> > +    case R_PHY_INTERFACE_STATUS:
> > +    case R_GRAPHIC_MEM_BASE_ADDR:
> > +    case R_PORT0_INTERFACE_MONITOR0:
> > +    case R_PORT0_INTERFACE_MONITOR1:
> > +    case R_PORT0_INTERFACE_MONITOR2:
> > +    case R_PORT1_INTERFACE_MONITOR0:
> > +    case R_PORT1_INTERFACE_MONITOR1:
> > +    case R_PORT1_INTERFACE_MONITOR2:
> > +    case R_PORT2_INTERFACE_MONITOR0:
> > +    case R_PORT2_INTERFACE_MONITOR1:
> > +    case R_PORT2_INTERFACE_MONITOR2:
> > +    case R_PORT3_INTERFACE_MONITOR0:
> > +    case R_PORT3_INTERFACE_MONITOR1:
> > +    case R_PORT3_INTERFACE_MONITOR2:
> > +    case R_PORT4_INTERFACE_MONITOR0:
> > +    case R_PORT4_INTERFACE_MONITOR1:
> > +    case R_PORT4_INTERFACE_MONITOR2:
> > +    case R_PORT5_INTERFACE_MONITOR0:
> > +    case R_PORT5_INTERFACE_MONITOR1:
> > +    case R_PORT5_INTERFACE_MONITOR2:
> > +        s->regs[reg] = data;
> > +        return;
> > +    }
> > +
> > +    if (s->regs[R_2700_PROT] == PROT_HARDLOCKED) {
> > +        qemu_log_mask(LOG_GUEST_ERROR,
> > +                      "%s: SDMC is locked until system reset!\n",
> > +                      __func__);
> > +        return;
> > +    }
> > +
> > +    if (reg != R_2700_PROT && s->regs[R_2700_PROT] ==
> PROT_SOFTLOCKED) {
> > +        qemu_log_mask(LOG_GUEST_ERROR,
> > +                      "%s: SDMC is locked! (write to MCR%02x
> blocked)\n",
> > +                      __func__, reg * 4);
> > +        return;
> > +    }
> > +
> > +    switch (reg) {
> > +    case R_2700_PROT:
> > +        if (data == PROT_2700_KEY_UNLOCK)  {
> > +            data = PROT_UNLOCKED;
> > +        } else if (data == PROT_KEY_HARDLOCK) {
> > +            data = PROT_HARDLOCKED;
> > +        } else {
> > +            data = PROT_SOFTLOCKED;
> > +        }
> > +        break;
> > +    case R_MAIN_CONF:
> > +        data = aspeed_2700_sdmc_compute_conf(s, data);
> > +        break;
> > +    case R_MAIN_STATUS:
> > +        /* Will never return 'busy'. */
> > +        data &= ~PHY_BUSY_STATE;
> > +        break;
> > +    default:
> > +        break;
> > +    }
> > +
> > +    s->regs[reg] = data;
> > +}
> > +
> > +static const uint64_t
> > +    aspeed_2700_ram_sizes[] = { 256 * MiB, 512 * MiB, 1024 * MiB,
> > +                                2048 * MiB, 4096 * MiB, 8192 *
> MiB,
> > +0};
> > +
> > +static void aspeed_2700_sdmc_class_init(ObjectClass *klass, void
> > +*data) {
> > +    DeviceClass *dc = DEVICE_CLASS(klass);
> > +    AspeedSDMCClass *asc = ASPEED_SDMC_CLASS(klass);
> > +
> > +    dc->desc = "ASPEED 2700 SDRAM Memory Controller";
> > +    dc->reset = aspeed_2700_sdmc_reset;
> > +
> > +    asc->is_bus64bit = true;
> > +    asc->max_ram_size = 8 * GiB;
> > +    asc->compute_conf = aspeed_2700_sdmc_compute_conf;
> > +    asc->write = aspeed_2700_sdmc_write;
> > +    asc->valid_ram_sizes = aspeed_2700_ram_sizes; }
> > +
> > +static const TypeInfo aspeed_2700_sdmc_info = {
> > +    .name = TYPE_ASPEED_2700_SDMC,
> > +    .parent = TYPE_ASPEED_SDMC,
> > +    .class_init = aspeed_2700_sdmc_class_init, };
> > +
> >   static void aspeed_sdmc_register_types(void)
> >   {
> >       type_register_static(&aspeed_sdmc_info);
> >       type_register_static(&aspeed_2400_sdmc_info);
> >       type_register_static(&aspeed_2500_sdmc_info);
> >       type_register_static(&aspeed_2600_sdmc_info);
> > +    type_register_static(&aspeed_2700_sdmc_info);
> >   }
> >
> >   type_init(aspeed_sdmc_register_types);
> > diff --git a/include/hw/misc/aspeed_sdmc.h
> > b/include/hw/misc/aspeed_sdmc.h index ec2d59a14f..6df2f0a3b7 100644
> > --- a/include/hw/misc/aspeed_sdmc.h
> > +++ b/include/hw/misc/aspeed_sdmc.h
> > @@ -17,6 +17,7 @@ OBJECT_DECLARE_TYPE(AspeedSDMCState,
> AspeedSDMCClass, ASPEED_SDMC)
> >   #define TYPE_ASPEED_2400_SDMC TYPE_ASPEED_SDMC "-ast2400"
> >   #define TYPE_ASPEED_2500_SDMC TYPE_ASPEED_SDMC "-ast2500"
> >   #define TYPE_ASPEED_2600_SDMC TYPE_ASPEED_SDMC "-ast2600"
> > +#define TYPE_ASPEED_2700_SDMC TYPE_ASPEED_SDMC "-ast2700"
> >
> >   /*
> >    * SDMC has 174 documented registers. In addition the u-boot device
> > tree @@ -29,7 +30,7 @@ OBJECT_DECLARE_TYPE(AspeedSDMCState,
> AspeedSDMCClass, ASPEED_SDMC)
> >    * time, and the other is in the DDR-PHY IP which is used during DDR-PHY
> >    * training.
> >    */
> > -#define ASPEED_SDMC_NR_REGS (0x500 >> 2)
> > +#define ASPEED_SDMC_NR_REGS (0x1000 >> 2)
> >
> >   struct AspeedSDMCState {
> >       /*< private >*/
> > @@ -51,6 +52,7 @@ struct AspeedSDMCClass {
> >       const uint64_t *valid_ram_sizes;
> >       uint32_t (*compute_conf)(AspeedSDMCState *s, uint32_t data);
> >       void (*write)(AspeedSDMCState *s, uint32_t reg, uint32_t data);
> > +    bool is_bus64bit;
> >   };
> >
> >   #endif /* ASPEED_SDMC_H */


reply via email to

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