[PATCH qemu 26/38] aspeed/sdmc: fake a few more registers to let DRAM calibration run
Cédric Le Goater
clg at kaod.org
Sat Nov 19 01:22:06 AEDT 2016
It helps in understanding the DRAM calibration sequence which is all
written in assembly, and may be rewritten in C one day.
This provides support only for the AST2400 SoC (DDR3). AST2500 still
uses the SOC_SCRATCH1 to pretend DRAM was already initialized.
Signed-off-by: Cédric Le Goater <clg at kaod.org>
---
hw/misc/aspeed_scu.c | 2 +-
hw/misc/aspeed_sdmc.c | 188 ++++++++++++++++++++++++++++++++++++++++++
include/hw/misc/aspeed_sdmc.h | 2 +-
3 files changed, 190 insertions(+), 2 deletions(-)
diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
index 95022d3607ad..b5efba9121b2 100644
--- a/hw/misc/aspeed_scu.c
+++ b/hw/misc/aspeed_scu.c
@@ -100,7 +100,7 @@ static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
[PCI_CTRL2] = 0x20001A03U,
[PCI_CTRL3] = 0x04000030U,
[SYS_RST_STATUS] = 0x00000001U,
- [SOC_SCRATCH1] = 0x000000C0U, /* SoC completed DRAM init */
+ [SOC_SCRATCH1] = 0x00000000U,
[MISC_CTRL2] = 0x00000023U,
[RNG_CTRL] = 0x0000000EU,
[PINMUX_CTRL2] = 0x0000F000U,
diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
index 867caa2d64dc..c71d18953c1c 100644
--- a/hw/misc/aspeed_sdmc.c
+++ b/hw/misc/aspeed_sdmc.c
@@ -80,6 +80,114 @@
ASPEED_SDMC_AST2500_RESERVED | ASPEED_SDMC_VGA_COMPAT | \
ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB))
+/* MCR08: Graphics Memory Protection Register */
+#define R_GRAPHIC_MEM_PROT (0x8 / 4)
+
+/* MCR0C: Refresh Timing Register */
+#define R_REFRESH_TIMING (0x0C / 4)
+
+/* MCR10: AC Timing Register #1 */
+#define R_AC_TIMING1 (0x10 / 4)
+
+/* MCR14: AC Timing Register #2 */
+#define R_AC_TIMING2 (0x14 / 4)
+
+/* MCR18: CK/DQS Delay Control Register */
+#define R_CQDQS_DELAY_CTRL (0x18 / 4)
+
+/* MCR1C: MCLK to MCLK2X Calibration(CBR) Status Register */
+#define R_MCLK_CALIB_STATUS (0x1C / 4)
+#define MCLK2X_PHASE (0x96 << 16)
+
+/* MCR20: DQS Input Phase Calibration Control and Status */
+#define R_DQS_INPUT_CALIB_STATUS (0x20 / 4)
+
+/* MCR24: ???? */
+#define R_MCR24 (0x24 / 4)
+
+/* MCR28: Mode Setting Control Register */
+#define R_MODE_SETTING_CTRL (0x28 / 4)
+
+/* MCR2C: MRS/EMRS2 Mode Setting Register */
+#define R_MRS_MODE_SETTING_CTRL (0x2C / 4)
+
+/* MCR30: EMRS/EMRS3 Mode Setting Register */
+#define R_EMRS_MODE_SETTING_CTRL (0x30 / 4)
+
+/* MCR34: Power Control Register */
+#define R_POWER_CTRL (0x34 / 4)
+
+/* MCR38: Page Miss Latency Mask Register */
+#define R_PAGE_MISS_MASK (0x38 / 4)
+
+/* MCR40: Maximum Grant Length Register #1 */
+#define R_MAX_GRANT_LEN1 (0x40 / 4)
+
+/* MCR44: Maximum Grant Length Register #2 */
+#define R_MAX_GRANT_LEN2 (0x44 / 4)
+
+/* MCR48: Maximum Grant Length Register #3 */
+#define R_MAX_GRANT_LEN3 (0x48 / 4)
+
+/* MCR4C: Maximum Grant Length Register #4 */
+#define R_MAX_GRANT_LEN4 (0x4C / 4)
+
+/* MCR50: Interrupt Control/Status Register */
+#define R_IRQ_STATUS_CTRL (0x50 / 4)
+
+/* MCR54: ECC Protection Address Range Register */
+#define R_ECC_PROTECT (0x54 / 4)
+
+/* MCR58: ???? */
+#define R_MCR58 (0x58 / 4)
+
+/* MCR60: IO Buffer Mode Register */
+#define R_IO_BUFFER_MODE (0x60 / 4)
+
+/* MCR64: DLL Control Register #1 */
+#define R_DLL_CTRL (0x64 / 4)
+
+/* MCR68: DLL Control Register #2 */
+#define R_DLL_CTRL2 (0x68 / 4)
+
+/* MCR6C: DDR IO Impedance Calibration Control */
+#define R_DDR_IO_IMPEDANCE_CTRL (0x6C / 4)
+
+/* MCR70: ECC Testing Control/Status Register */
+#define R_ECC_STATUS_CTRL (0x70 / 4)
+#define ECC_TEST_FINISH (1 << 12)
+
+/* MCR74: Testing Start Address and Length Register */
+#define R_START_ADDR_LEN (0x74 / 4)
+
+/* MCR78: Testing Fail DQ Bit Register */
+#define R_FAIL_DQ (0x78 / 4)
+
+/* MCR7C: Test Initial Value Register */
+#define R_TEST_INIT_VALUE (0x7C / 4)
+
+/* MCR80: DQ Input Delay Calibration Control #1 */
+#define R_DQ_DELAY_CALIB_CTRL1 (0x80 / 4)
+#define DQ_DELAY_CALIB_COUNT_DONE (1 << 31)
+
+/* MCR84: DQ Input Delay Calibration Control #2 */
+#define R_DQ_DELAY_CALIB_CTRL2 (0x84 / 4)
+
+/* MCR88: DQ Input Delay Calibration Control #3 */
+#define R_DQ_DELAY_CALIB_CTRL3 (0x88 / 4)
+
+/* MCR8C: CK Duty Counter Value */
+#define R_CK_DUTY_VALUE (0x8C / 4)
+
+/* MCR100: AST2000 Backward Compatible SCU Password */
+#define R_COMPAT_SCU_PASSWORD (0x100 / 4)
+
+/* MCR120: AST2000 Backward Compatible SCU MPLL Parameter */
+#define R_COMPAT_SCU_MPLL (0x120 / 4)
+
+/* MCR170: AST2000 Backward Compatible SCU Hardware Strapping Value */
+#define R_COMPAT_SCU_HW_STRAPPING (0x170 / 4)
+
static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr, unsigned size)
{
AspeedSDMCState *s = ASPEED_SDMC(opaque);
@@ -91,6 +199,48 @@ static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr, unsigned size)
case R_PROT:
val = s->unlocked;
break;
+ case R_CONF:
+ case R_GRAPHIC_MEM_PROT:
+ case R_REFRESH_TIMING:
+ case R_AC_TIMING1:
+ case R_AC_TIMING2:
+ case R_CQDQS_DELAY_CTRL:
+ case R_MCLK_CALIB_STATUS:
+ case R_DQS_INPUT_CALIB_STATUS:
+ case R_MCR24:
+ case R_MODE_SETTING_CTRL:
+ case R_MRS_MODE_SETTING_CTRL:
+ case R_EMRS_MODE_SETTING_CTRL:
+ case R_POWER_CTRL:
+ case R_PAGE_MISS_MASK:
+ case R_MAX_GRANT_LEN1:
+ case R_MAX_GRANT_LEN2:
+ case R_MAX_GRANT_LEN3:
+ case R_MAX_GRANT_LEN4:
+ case R_IRQ_STATUS_CTRL:
+ case R_ECC_PROTECT:
+ case R_MCR58:
+ case R_IO_BUFFER_MODE:
+ case R_DLL_CTRL:
+ case R_DLL_CTRL2:
+ case R_DDR_IO_IMPEDANCE_CTRL:
+ case R_START_ADDR_LEN:
+ case R_FAIL_DQ:
+ case R_TEST_INIT_VALUE:
+ case R_DQ_DELAY_CALIB_CTRL2:
+ case R_DQ_DELAY_CALIB_CTRL3:
+ case R_CK_DUTY_VALUE:
+ case R_COMPAT_SCU_PASSWORD:
+ case R_COMPAT_SCU_MPLL:
+ case R_COMPAT_SCU_HW_STRAPPING:
+ val = s->regs[addr];
+ break;
+ case R_DQ_DELAY_CALIB_CTRL1:
+ val = s->regs[addr] | DQ_DELAY_CALIB_COUNT_DONE;
+ break;
+ case R_ECC_STATUS_CTRL:
+ val = s->regs[addr] | ECC_TEST_FINISH;
+ break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
@@ -133,6 +283,42 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
g_assert_not_reached();
}
break;
+ case R_GRAPHIC_MEM_PROT:
+ case R_REFRESH_TIMING:
+ case R_AC_TIMING1:
+ case R_AC_TIMING2:
+ case R_CQDQS_DELAY_CTRL:
+ case R_MCLK_CALIB_STATUS:
+ case R_DQS_INPUT_CALIB_STATUS:
+ case R_MCR24:
+ case R_MODE_SETTING_CTRL:
+ case R_MRS_MODE_SETTING_CTRL:
+ case R_EMRS_MODE_SETTING_CTRL:
+ case R_POWER_CTRL:
+ case R_PAGE_MISS_MASK:
+ case R_MAX_GRANT_LEN1:
+ case R_MAX_GRANT_LEN2:
+ case R_MAX_GRANT_LEN3:
+ case R_MAX_GRANT_LEN4:
+ case R_IRQ_STATUS_CTRL:
+ case R_ECC_PROTECT:
+ case R_MCR58:
+ case R_IO_BUFFER_MODE:
+ case R_DLL_CTRL:
+ case R_DLL_CTRL2:
+ case R_DDR_IO_IMPEDANCE_CTRL:
+ case R_ECC_STATUS_CTRL:
+ case R_START_ADDR_LEN:
+ case R_FAIL_DQ:
+ case R_TEST_INIT_VALUE:
+ case R_DQ_DELAY_CALIB_CTRL1:
+ case R_DQ_DELAY_CALIB_CTRL2:
+ case R_DQ_DELAY_CALIB_CTRL3:
+ case R_CK_DUTY_VALUE:
+ case R_COMPAT_SCU_PASSWORD:
+ case R_COMPAT_SCU_MPLL:
+ case R_COMPAT_SCU_HW_STRAPPING:
+ break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
@@ -221,6 +407,8 @@ static void aspeed_sdmc_reset(DeviceState *dev)
default:
g_assert_not_reached();
}
+
+ s->regs[R_MCLK_CALIB_STATUS] = MCLK2X_PHASE;
}
static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
diff --git a/include/hw/misc/aspeed_sdmc.h b/include/hw/misc/aspeed_sdmc.h
index a4415d9efc2f..e073a6c9419a 100644
--- a/include/hw/misc/aspeed_sdmc.h
+++ b/include/hw/misc/aspeed_sdmc.h
@@ -14,7 +14,7 @@
#define TYPE_ASPEED_SDMC "aspeed.sdmc"
#define ASPEED_SDMC(obj) OBJECT_CHECK(AspeedSDMCState, (obj), TYPE_ASPEED_SDMC)
-#define ASPEED_SDMC_NR_REGS (0x8 >> 2)
+#define ASPEED_SDMC_NR_REGS (0x174 >> 2)
typedef struct AspeedSDMCState {
/*< private >*/
--
2.7.4
More information about the openbmc
mailing list