[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: |
Tue, 12 Mar 2024 03:42:09 +0000 |
> >>
> > 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/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 */
> >
[PATCH v2 4/9] aspeed/smc: Add AST2700 support, Jamin Lin, 2024/03/04
[PATCH v2 5/9] aspeed/scu: Add AST2700 support, Jamin Lin, 2024/03/04
[PATCH v2 6/9] aspeed/intc: Add AST2700 support, Jamin Lin, 2024/03/04
Message not available
Message not available