> >>
> > 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_...@aspeedtech.com>
> >>> Signed-off-by: Jamin Lin <jamin_...@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/b
> > oard/aspeed/ibex_ast2700/sdram_ast2700.c#L716
> >
> https://github.com/AspeedTech-BMC/u-boot/blob/aspeed-master-v2023.10/b
> > oard/aspeed/ibex_ast2700/sdram_ast2700.c#L277
> 
> Since the model is diverging from HW, a comment explaining the reason why
> would be useful.
> 
> As an extension preparing SPL support, you could add a new "unlocked"
> property, set to "false" by default. The AST2700 SoC realize handler would set
> it to "true" and the reset handler would test the value to initialize the 
> R_PROT
> register.
> 
Hi Cedric,

Thanks for your suggestion. Will add

Jamin

> Thanks,
> 
> C.
> 
> 
> 
> >
> > 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