kind of fixed lpddr2 detection, added addressing modes for 512mb and 1gb lpddr2 chips...
authorkristina <kb@kbs-iMac.local>
Mon, 30 May 2016 13:10:16 +0000 (14:10 +0100)
committerkristina <kb@kbs-iMac.local>
Mon, 30 May 2016 13:10:16 +0000 (14:10 +0100)
sdram.c

diff --git a/sdram.c b/sdram.c
index 6cac906..59b8a85 100755 (executable)
--- a/sdram.c
+++ b/sdram.c
@@ -1,5 +1,6 @@
 /*=============================================================================\r
 Copyright (C) 2016 Kristina Brooks\r
+Copyright (C) 2016 Julian Brown\r
 All rights reserved.\r
 \r
 This program is free software; you can redistribute it and/or\r
@@ -17,37 +18,96 @@ VideoCoreIV SDRAM initialization code.
 \r
 =============================================================================*/\r
 \r
-#include "lib/common.h"\r
-#include "hardware.h"\r
+#include <common.h>\r
+#include <hardware.h>\r
 \r
 \r
+/*\r
+ Registers\r
+ =========\r
+\r
+ SC: AC Timing (Page 202)\r
+ SB: ???\r
+ SD: AC Timing (Page 202)\r
+ SE: AC Timing (Page 202)\r
+\r
+ PT1:\r
+       Minimum Idle time after first CKE assertion\r
+       Minimum CKE low time after completion of power ramp\r
+ PT2: \r
+       DAI Duration\r
+ */\r
+\r
 extern uint32_t g_CPUID;\r
 \r
 #define MR_REQUEST_SUCCESS(x) ((SD_MR_TIMEOUT_SET & x) != SD_MR_TIMEOUT_SET)\r
 #define MR_GET_RDATA(x) ((x & SD_MR_RDATA_SET) >> SD_MR_RDATA_LSB)\r
 \r
-#define RAM_TEST_ADDR 0xC0000000\r
-#define RAM_TEST_PATTERN 0xAAAAAAAA\r
-\r
 #define SIP_DEBUG(x) x\r
 #define SCLKU_DEBUG(x) //SIP_DEBUG(x)\r
 \r
-ALWAYS_INLINE inline void sdram_clkman_update_begin() {\r
+#define BIST_pvt    0x20\r
+#define BIST_reset  0x10\r
+\r
+#define PVT_calibrate_request 0x1\r
+\r
+#define logf(fmt, ...) printf("[SDRAM::%s]: " fmt, __FUNCTION__, ##__VA_ARGS__);\r
+\r
+unsigned g_RAMSize = RAM_SIZE_UNKNOWN;\r
+\r
+static const char* lpddr2_manufacturer_name(uint32_t mr) {\r
+       switch (mr) {\r
+               case 1: return "Samsung";\r
+               case 2: return "Qimonda";\r
+               case 3: return "Elpida";\r
+               case 4: return "Etron";\r
+               case 5: return "Nanya";\r
+               case 6: return "Hynix";\r
+               default: return "Unknown";\r
+       }\r
+}\r
+\r
+#define MR8_DENSITY_SHIFT      0x2\r
+#define MR8_DENSITY_MASK       (0xF << 0x2)\r
+\r
+static unsigned lpddr2_size(uint32_t mr) {\r
+       switch (mr) {\r
+               case 0x58: return RAM_SIZE_1GB;\r
+               case 0x18: return RAM_SIZE_512MB;\r
+               case 0x14: return RAM_SIZE_256MB;\r
+               case 0x10: return RAM_SIZE_128MB;\r
+               default: return RAM_SIZE_UNKNOWN;\r
+       }\r
+}\r
+\r
+const char* size_to_string[] = {\r
+       "1GB",\r
+       "512MB",\r
+       "256MB",\r
+       "128MB",\r
+       "UNKNOWN"\r
+};\r
+\r
+/*****************************************************************************\r
+ * Guts\r
+ *****************************************************************************/\r
+\r
+ALWAYS_INLINE inline void clkman_update_begin() {\r
        CM_SDCCTL |= CM_PASSWORD | CM_SDCCTL_UPDATE_SET;\r
-       SCLKU_DEBUG(printf("%s: waiting for ACCPT (%X) ...\n", __FUNCTION__, CM_SDCCTL));\r
+       SCLKU_DEBUG(logf("waiting for ACCPT (%X) ...\n", CM_SDCCTL));\r
        for (;;) if (CM_SDCCTL & CM_SDCCTL_ACCPT_SET) break;\r
-       SCLKU_DEBUG(printf("%s: ACCPT received! (%X)\n", __FUNCTION__, CM_SDCCTL));\r
+       SCLKU_DEBUG(logf("ACCPT received! (%X)\n", CM_SDCCTL));\r
 }\r
 \r
-ALWAYS_INLINE inline void sdram_clkman_update_end() {\r
+ALWAYS_INLINE inline void clkman_update_end() {\r
        CM_SDCCTL = CM_PASSWORD | (CM_SDCCTL & CM_SDCCTL_UPDATE_CLR);\r
-       SCLKU_DEBUG(printf("%s: waiting for ACCPT clear (%X) ...\n", __FUNCTION__, CM_SDCCTL));\r
+       SCLKU_DEBUG(logf("waiting for ACCPT clear (%X) ...\n", CM_SDCCTL));\r
        for (;;) if ((CM_SDCCTL & CM_SDCCTL_ACCPT_SET) == 0) break;\r
-       SCLKU_DEBUG(printf("%s: ACCPT cleared! (%X)\n", __FUNCTION__, CM_SDCCTL));\r
+       SCLKU_DEBUG(logf("ACCPT cleared! (%X)\n", CM_SDCCTL));\r
 }\r
 \r
-ALWAYS_INLINE void sdram_reset_phy_lines() {\r
-       SIP_DEBUG(printf("%s: resetting APHY/DPHY lines ...\n", __FUNCTION__));\r
+ALWAYS_INLINE void reset_phy_dll() {\r
+       SIP_DEBUG(logf("resetting aphy and dphy dlls ...\n", __FUNCTION__));\r
 \r
        /* politely tell sdc that we'll be messing with address lines */\r
        APHY_CSR_PHY_BIST_CNTRL_SPR = 0x30;\r
@@ -64,77 +124,182 @@ ALWAYS_INLINE void sdram_reset_phy_lines() {
        DPHY_CSR_GLBL_DQ_DLL_RESET = 0x0;\r
        APHY_CSR_GLBL_ADDR_DLL_RESET = 0x0;\r
 \r
-       SIP_DEBUG(printf("%s: waiting for DPHY master PLL to lock ...\n", __FUNCTION__));\r
+       SIP_DEBUG(logf("waiting for dphy master dll to lock ...\n", __FUNCTION__));\r
        for (;;) if ((DPHY_CSR_GLBL_MSTR_DLL_LOCK_STAT & 0xFFFF) == 0xFFFF) break;\r
-       SIP_DEBUG(printf("%s: DPHY master PLL locked!\n", __FUNCTION__));\r
+       SIP_DEBUG(logf("dphy master dll locked!\n", __FUNCTION__));\r
 }\r
 \r
-void sdram_init_late() {\r
+typedef struct {\r
+       uint32_t max_freq;\r
+       uint32_t RL;\r
+       uint32_t tRPab;\r
+       uint32_t tRPpb;\r
+       uint32_t tRCD;\r
+       uint32_t tWR;\r
+       uint32_t tRASmin;\r
+       uint32_t tRRD;\r
+       uint32_t tWTR;\r
+       uint32_t tXSR;\r
+       uint32_t tXP;\r
+       uint32_t tRFCab;\r
+       uint32_t tRTP;\r
+       uint32_t tCKE;\r
+       uint32_t tCKESR;\r
+       uint32_t tDQSCKMAXx2;\r
+       uint32_t tRASmax;\r
+       uint32_t tFAW;\r
+       uint32_t tRC;\r
+       uint32_t tREFI;\r
+\r
+       uint32_t tINIT1;\r
+       uint32_t tINIT3;\r
+       uint32_t tINIT5;\r
+\r
+       uint32_t rowbits;\r
+       uint32_t colbits;\r
+       uint32_t banklow;\r
+} lpddr2_timings_t;\r
+\r
+// 7.8 / (1.0 / 400)\r
+\r
+lpddr2_timings_t g_InitSdramParameters = {\r
+       /* SA (us) */\r
+       .tREFI = 3113, //Refresh rate: 3113 * (1.0 / 400) = 7.78us\r
+       /* SC (ns) */\r
+       .tRFCab = 50,\r
+       .tRRD = 2,\r
+       .tWR = 7,\r
+       .tWTR = 4,\r
+       /* SD (ns) */\r
+       .tRPab = 7,\r
+       .tRC = 24,\r
+       .tXP = 1,\r
+       .tRASmin = 15,\r
+       .tRPpb = 6,\r
+       .tRCD = 6,\r
+       /* SE (ns) */\r
+       .tFAW = 18,\r
+       .tRTP = 1,\r
+       .tXSR = 54,\r
+       /* PT */\r
+       .tINIT1 = 40, // Minimum CKE low time after completion of power ramp: 40 * (1.0 / 0.4) = 100ns\r
+       .tINIT3 = 79800, // Minimum Idle time after first CKE assertion: 79800 * (1.0 / 400) = 199.5us ~ 200us\r
+       .tINIT5 = 3990, //Max DAI: 3990* (1.0 / 400) = 9.9us ~ 10us\r
+       /* SB */\r
+       .rowbits = 2,\r
+       .colbits = 1,\r
+       .banklow = 2\r
+};\r
+\r
+void reset_with_timing(lpddr2_timings_t* T) {\r
        uint32_t ctrl = 0x4;\r
 \r
        SD_CS = (SD_CS & ~(SD_CS_DEL_KEEP_SET|SD_CS_DPD_SET|SD_CS_RESTRT_SET)) | SD_CS_STBY_SET;\r
 \r
        /* wait for SDRAM controller to go down */\r
-       SIP_DEBUG(printf("%s: waiting for SDRAM controller to go down (%X) ...\n", __FUNCTION__, SD_CS));\r
+       SIP_DEBUG(logf("waiting for SDRAM controller to go down (%X) ...\n", SD_CS));\r
        for (;;) if ((SD_CS & SD_CS_SDUP_SET) == 0) break;\r
-       SIP_DEBUG(printf("%s: SDRAM controller down!\n", __FUNCTION__));\r
+       SIP_DEBUG(logf("SDRAM controller down!\n"));\r
 \r
        /* disable SDRAM clock */\r
-       sdram_clkman_update_begin();\r
+       clkman_update_begin();\r
        CM_SDCCTL = (CM_SDCCTL & ~(CM_SDCCTL_ENAB_SET|CM_SDCCTL_CTRL_SET)) | CM_PASSWORD;\r
-       sdram_clkman_update_end();\r
+       clkman_update_end();\r
 \r
-       SIP_DEBUG(printf("%s: SDRAM clock disabled!\n", __FUNCTION__));\r
+       SIP_DEBUG(logf("SDRAM clock disabled!\n"));\r
 \r
-       /* left */\r
+       /*\r
+        * Migrate over to master PLL.\r
+        */\r
 \r
        APHY_CSR_DDR_PLL_PWRDWN = 0;\r
        APHY_CSR_DDR_PLL_GLOBAL_RESET = 0;\r
        APHY_CSR_DDR_PLL_POST_DIV_RESET = 0;\r
 \r
-       APHY_CSR_DDR_PLL_VCO_FREQ_CNTRL0 = (1 << 16) | 0x53 /* magic */;\r
+       /* 400MHz */\r
+       APHY_CSR_DDR_PLL_VCO_FREQ_CNTRL0 = (1 << 16) | 0x53;\r
        APHY_CSR_DDR_PLL_VCO_FREQ_CNTRL1 = 0;\r
        APHY_CSR_DDR_PLL_MDIV_VALUE = 0;\r
+\r
        APHY_CSR_DDR_PLL_GLOBAL_RESET = 1;\r
 \r
-       SIP_DEBUG(printf("%s: waiting for APHY DDR PLL to lock ...\n", __FUNCTION__));\r
+       SIP_DEBUG(logf("waiting for master ddr pll to lock ...\n"));\r
        for (;;) if (APHY_CSR_DDR_PLL_LOCK_STATUS & (1 << 16)) break;\r
-       SIP_DEBUG(printf("%s: APHY DDR PLL locked!\n", __FUNCTION__));\r
-\r
-       APHY_CSR_DDR_PLL_POST_DIV_RESET = 1;\r
+       SIP_DEBUG(logf("master ddr pll locked!\n"));\r
 \r
-       sdram_clkman_update_begin();\r
+       APHY_CSR_DDR_PLL_POST_DIV_RESET = 1;\r
 \r
+       clkman_update_begin();\r
        CM_SDCCTL = CM_PASSWORD | (ctrl << CM_SDCCTL_CTRL_LSB) | (CM_SDCCTL & CM_SDCCTL_CTRL_CLR);\r
-       sdram_clkman_update_end();\r
-\r
-       SIP_DEBUG(printf("%s: CM_SDCCTL = 0x%X\n", __FUNCTION__, CM_SDCCTL));\r
-\r
-       /* second stage magic values */\r
-       SD_SA = 0x0C293395;\r
-       SD_SB = 0x0F9;\r
-       SD_SC = 0x32200743;\r
-       SD_SD = 0x71810F66;\r
-       SD_SE = 0x10412136;\r
-       SD_PT1 = 0x137B828;\r
-       SD_PT2 = 0x0F96;\r
-       SD_MRT = 0x3;\r
-\r
-       sdram_reset_phy_lines();\r
+       clkman_update_end();\r
+\r
+       SD_SA =\r
+               (T->tREFI << SD_SA_RFSH_T_LSB)\r
+                       | SD_SA_PGEHLDE_SET\r
+                       | SD_SA_CLKSTOP_SET\r
+                       | SD_SA_POWSAVE_SET\r
+                       | 0x3214;\r
+\r
+       SD_SB =\r
+               SD_SB_REORDER_SET\r
+                       | (T->banklow << SD_SB_BANKLOW_LSB)\r
+                       | SD_SB_EIGHTBANK_SET\r
+                       | (T->rowbits << SD_SB_ROWBITS_LSB)\r
+                       | (T->colbits << SD_SB_COLBITS_LSB);\r
+\r
+       logf("SDRAM Addressing Mode: Bank=%d Row=%d Col=%d SB=0x%X\n", T->banklow, T->rowbits, T->colbits, SD_SB);\r
+\r
+       SD_SC =\r
+               (T->tRFCab << SD_SC_T_RFC_LSB)\r
+                       | (T->tRRD << SD_SC_T_RRD_LSB)\r
+                       | (T->tWR << SD_SC_T_WR_LSB)\r
+                       | (T->tWTR << SD_SC_T_WTR_LSB)\r
+                       | (3 << SD_SC_WL_LSB);\r
+\r
+       SD_SD =\r
+               (T->tRPab << SD_SD_T_RPab_LSB)\r
+                       | (T->tRC << SD_SD_T_RC_LSB)\r
+                       | (T->tXP << SD_SD_T_XP_LSB)\r
+                       | (T->tRASmin << SD_SD_T_RAS_LSB)\r
+                       | (T->tRPpb << SD_SD_T_RPpb_LSB)\r
+                       | (T->tRCD << SD_SD_T_RCD_LSB);\r
+\r
+       SD_SE =\r
+               (1 << SD_SE_RL_EN_LSB)\r
+                       | (4 << SD_SE_RL_LSB)\r
+                       | (T->tFAW << SD_SE_T_FAW_LSB)\r
+                       | (T->tRTP << SD_SE_T_RTP_LSB)\r
+                       | (T->tXSR << SD_SE_T_XSR_LSB);\r
+\r
+       SD_PT1 =\r
+               (T->tINIT3 << SD_PT1_T_INIT3_LSB)\r
+                       | (T->tINIT1 << SD_PT1_T_INIT1_LSB);\r
+\r
+       SD_PT2 =\r
+               T->tINIT5 << SD_PT2_T_INIT5_LSB;\r
+\r
+       SD_MRT =\r
+               0x3 << SD_MRT_T_MRW_LSB;\r
+\r
+       reset_phy_dll();\r
 \r
        /* wait for address line pll to come back */\r
-       SIP_DEBUG(printf("%s: waiting for APHY global PLL to lock ...\n", __FUNCTION__));\r
+       SIP_DEBUG(logf("waiting for address dll to lock ...\n"));\r
        for (;;) if (APHY_CSR_GLBL_ADR_DLL_LOCK_STAT == 3) break;\r
-       SIP_DEBUG(printf("%s: APHY global PLL locked!\n", __FUNCTION__));\r
+       SIP_DEBUG(logf("address dll locked!\n"));\r
 \r
        /* tell sdc we're done messing with address lines */\r
        APHY_CSR_PHY_BIST_CNTRL_SPR = 0x0;\r
 \r
        /* woo, turn on sdram! */\r
-       SD_CS = (0x200042 & ~(SD_CS_STOP_SET|SD_CS_STBY_SET)) | SD_CS_RESTRT_SET;\r
+       SD_CS =\r
+               (((4 << SD_CS_ASHDN_T_LSB)\r
+                       | SD_CS_STATEN_SET\r
+                       | SD_CS_EN_SET)\r
+               & ~(SD_CS_STOP_SET|SD_CS_STBY_SET)) | SD_CS_RESTRT_SET;\r
 }\r
 \r
-unsigned int sdram_read_mr(unsigned int addr) {\r
+unsigned int read_mr(unsigned int addr) {\r
        while ((SD_MR & SD_MR_DONE_SET) != SD_MR_DONE_SET) {}\r
        SD_MR = addr & 0xFF;\r
        unsigned int mrr;\r
@@ -142,7 +307,7 @@ unsigned int sdram_read_mr(unsigned int addr) {
        return mrr;\r
 }\r
 \r
-unsigned int sdram_write_mr(unsigned int addr, unsigned int data, bool wait) {\r
+unsigned int write_mr(unsigned int addr, unsigned int data, bool wait) {\r
        while ((SD_MR & SD_MR_DONE_SET) != SD_MR_DONE_SET) {}\r
 \r
        SD_MR = (addr & 0xFF) | ((data & 0xFF) << 8) | SD_MR_RW_SET;\r
@@ -161,98 +326,78 @@ unsigned int sdram_write_mr(unsigned int addr, unsigned int data, bool wait) {
        }\r
 }\r
 \r
-void sdram_reset_phy() {\r
-       printf("%s: resetting SDRAM PHY ...\n", __FUNCTION__);\r
+void reset_phy() {\r
+       logf("%s: resetting SDRAM PHY ...\n", __FUNCTION__);\r
 \r
        /* reset PHYC */\r
        SD_PHYC = SD_PHYC_PHYRST_SET;\r
        udelay(64);\r
        SD_PHYC = 0;\r
 \r
-       printf("%s: resetting DPHY CTRL ...\n", __FUNCTION__);\r
+       logf("%s: resetting DPHY CTRL ...\n", __FUNCTION__);\r
 \r
        DPHY_CSR_DQ_PHY_MISC_CTRL = 0x7;\r
        DPHY_CSR_DQ_PAD_MISC_CTRL = 0x0;\r
        DPHY_CSR_BOOT_READ_DQS_GATE_CTRL = 0x11;\r
 \r
-       sdram_reset_phy_lines();\r
+       reset_phy_dll();\r
 \r
        APHY_CSR_PHY_BIST_CNTRL_SPR = 0x0;\r
 }\r
 \r
-static void sdram_set_clock_source(unsigned int source, unsigned int div_) {\r
-       CM_SDCDIV = CM_PASSWORD | (div_ << CM_SDCDIV_DIV_LSB);\r
+static void switch_to_cprman_clock(unsigned int source, unsigned int div) {\r
+       CM_SDCDIV = CM_PASSWORD | (div << CM_SDCDIV_DIV_LSB);\r
        CM_SDCCTL = CM_PASSWORD | (CM_SDCCTL & CM_SDCCTL_SRC_CLR) | source;\r
        CM_SDCCTL |= CM_PASSWORD | CM_SDCCTL_ENAB_SET;\r
 \r
-       printf("%s: source set to %d, div to %d, waiting for BUSY set (%X) ... \n", __FUNCTION__, source, div_, CM_SDCCTL);\r
+       logf("switching sdram to cprman clock (src=%d, div=%d), waiting for busy (%X) ...\n", source, div, CM_SDCCTL);\r
 \r
        for (;;) if (CM_SDCCTL & CM_SDCCTL_BUSY_SET) break;\r
 \r
-       printf("%s: BUSY set! (%X)\n", __FUNCTION__, CM_SDCCTL);\r
+       logf("busy set, switch complete!\n");\r
 }\r
 \r
-static void sdram_init_clkman()\r
+static void init_clkman()\r
 {\r
        uint32_t ctrl = 0;\r
 \r
-       sdram_clkman_update_begin();\r
+       clkman_update_begin();\r
        CM_SDCCTL = CM_PASSWORD | (ctrl << CM_SDCCTL_CTRL_LSB) | (CM_SDCCTL & CM_SDCCTL_CTRL_CLR);\r
-       sdram_clkman_update_end();\r
+       clkman_update_end();\r
 }\r
 \r
-static const char* lpddr2_manufacturer_name(uint32_t mr) {\r
-       switch (mr) {\r
-               case 1: return "Samsung";\r
-               case 2: return "Qimonda";\r
-               case 3: return "Elpida";\r
-               case 4: return "Etron";\r
-               case 5: return "Nanya";\r
-               case 6: return "Hynix";\r
-               default: return "Unknown";\r
-       }\r
-}\r
+       #define CALL_INIT_CLKMAN init_clkman();\r
 \r
-static const char* lpddr2_density(uint32_t mr) {\r
-       /*\r
-        * i'm so stupid, why did i not notice that LPDDR2\r
-        * spec listed those as bits, not bytes *sigh*\r
-        */\r
-       switch ((mr & 0x33) >> 3) {\r
-               case 1: return "128MB";\r
-               case 2: return "256MB";\r
-               case 3: return "512MB";\r
-               case 4: return "1GB";\r
-               case 5: return "2GB";\r
-               case 6: return "4GB";\r
-               default: return "Unknown";\r
-       }\r
-}\r
 \r
-static void sdram_calibrate() {\r
+/*****************************************************************************\r
+ * Calibration\r
+ *****************************************************************************/\r
+\r
+static void calibrate_pvt_early() {\r
        /* some hw revisions require different slews */\r
        bool st = ((g_CPUID >> 4) & 0xFFF) == 0x14;\r
        uint32_t dq_slew = (st ? 2 : 3);\r
 \r
        /* i don't get it, the spec says do not use this register */\r
-       sdram_write_mr(0xFF, 0, true);\r
+       write_mr(0xFF, 0, true);\r
        /* RL = 6 / WL = 3 */\r
-       sdram_write_mr(LPDDR2_MR_DEVICE_FEATURE_2, 4, true);\r
+       write_mr(LPDDR2_MR_DEVICE_FEATURE_2, 4, true);\r
 \r
        APHY_CSR_ADDR_PAD_DRV_SLEW_CTRL = 0x333;\r
        DPHY_CSR_DQ_PAD_DRV_SLEW_CTRL = (dq_slew << 8) | (dq_slew << 4) | 3;\r
 \r
-       printf("%s: DPHY_CSR_DQ_PAD_DRV_SLEW_CTRL = 0x%X\n", __FUNCTION__, DPHY_CSR_DQ_PAD_DRV_SLEW_CTRL);\r
+       logf("DPHY_CSR_DQ_PAD_DRV_SLEW_CTRL = 0x%X\n", DPHY_CSR_DQ_PAD_DRV_SLEW_CTRL);\r
 \r
        /* tell sdc we want to calibrate */\r
-       APHY_CSR_PHY_BIST_CNTRL_SPR = 0x20;\r
+       APHY_CSR_PHY_BIST_CNTRL_SPR = BIST_pvt;\r
 \r
-       APHY_CSR_ADDR_PVT_COMP_CTRL = 0x1;\r
-       printf("%s: waiting for address PVT calibration ...\n", __FUNCTION__);\r
+       /* pvt compensation */\r
+       APHY_CSR_ADDR_PVT_COMP_CTRL = PVT_calibrate_request;\r
+       logf("waiting for address PVT calibration ...\n");\r
        for (;;) if (APHY_CSR_ADDR_PVT_COMP_STATUS & 2) break;\r
 \r
-       DPHY_CSR_DQ_PVT_COMP_CTRL = 0x1;\r
-       printf("%s: waiting for data PVT calibration ...\n", __FUNCTION__);\r
+       DPHY_CSR_DQ_PVT_COMP_CTRL = PVT_calibrate_request;\r
+       logf("waiting for data PVT calibration ...\n");\r
        for (;;) if (DPHY_CSR_DQ_PVT_COMP_STATUS & 2) break;\r
 \r
        /* tell sdc we're done calibrating */\r
@@ -261,33 +406,87 @@ static void sdram_calibrate() {
        /* send calibration command */\r
        uint32_t old_mrt = SD_MRT;\r
        SD_MRT = 20;\r
-       printf("%s: waiting for SDRAM calibration command ...\n", __FUNCTION__);\r
+       logf("waiting for SDRAM calibration command ...\n");\r
        SD_MR = LPDDR2_MR_CALIBRATION | (0xFF << 8) | SD_MR_RW_SET | SD_MR_HI_Z_SET;\r
        while ((SD_MR & SD_MR_DONE_SET) != SD_MR_DONE_SET) {}\r
        SD_MRT = old_mrt;\r
 \r
-       sdram_write_mr(LPDDR2_MR_IO_CONFIG, st ? 3 : 2, false);\r
+       write_mr(LPDDR2_MR_IO_CONFIG, st ? 3 : 2, false);\r
+}\r
+\r
+\r
+/*****************************************************************************\r
+ * Late init\r
+ *****************************************************************************/\r
+\r
+static void init_late() {\r
+}\r
+\r
+/*****************************************************************************\r
+ * Self-test\r
+ *****************************************************************************/\r
+\r
+#define RT_BASE 0xC0000000\r
+\r
+#define RT_PAT0 0xAAAAAAAA\r
+#define RT_PAT1 0xFF00AA00\r
+#define RT_PAT2 0x99999999\r
+\r
+#define RT_ASSERT(i_, expected) \\r
+       if (ram[(i_)] != expected) { \\r
+               logf("ERROR: At 0x%X, was expecting 0x%X from read, got 0x%X instead!\n", \\r
+                       (uint32_t)&ram[(i_)], \\r
+                       expected, \\r
+                       ram[(i_)]); \\r
+               panic("SDRAM self test failed!"); \\r
+       }\r
+\r
+static void selftest_at(uint32_t addr) {\r
+       volatile uint32_t* ram = (volatile uint32_t*)addr;\r
+\r
+       logf("Testing region at 0x%X ...\n", addr);\r
+\r
+       for (int i = 0; i < 0x1000; i += 4) {\r
+               ram[i]     = RT_PAT0;\r
+               ram[i + 1] = RT_PAT1;\r
+               ram[i + 2] = RT_PAT2;\r
+               ram[i + 3] = RT_PAT0;\r
+       }\r
+\r
+       for (int i = 0; i < 0x1000; i += 4) {\r
+               RT_ASSERT(i,     RT_PAT0);\r
+               RT_ASSERT(i + 1, RT_PAT1);\r
+               RT_ASSERT(i + 2, RT_PAT2);\r
+               RT_ASSERT(i + 3, RT_PAT0);\r
+       }\r
 }\r
 \r
-static void sdram_selftest()\r
+static void selftest()\r
 {\r
-       volatile uint32_t* p = (volatile uint32_t*)RAM_TEST_ADDR;\r
+       logf("Starting self test ...\n");\r
 \r
-       printf("Testing SDRAM ...\n");\r
+       selftest_at(RT_BASE);\r
 \r
-       for (int i = 0; i < 0x100000; i++) {\r
-               p[i] = RAM_TEST_PATTERN;\r
-               if (p[i] != RAM_TEST_PATTERN)\r
-                       panic("sdram initialization failed (idx=%d exptected=0x%x got=0x%x)", i, RAM_TEST_PATTERN, p[i]);\r
+       if (g_RAMSize == RAM_SIZE_256MB || g_RAMSize == RAM_SIZE_512MB || g_RAMSize == RAM_SIZE_1GB) {\r
+               selftest_at(RT_BASE + 0xFF00000);\r
+       }\r
+       if (g_RAMSize == RAM_SIZE_512MB || g_RAMSize == RAM_SIZE_1GB) {\r
+               selftest_at(RT_BASE + 0x1FF00000);\r
+       }\r
+       if (g_RAMSize == RAM_SIZE_1GB) {\r
+               selftest_at(RT_BASE + 0x2FF00000);\r
+               selftest_at(RT_BASE + 0x3FF00000);\r
        }\r
 \r
-       printf("SDRAM test successful!\n");\r
+       logf("Self test successful!\n");\r
 }\r
 \r
+#undef RT_ASSERT\r
+\r
 void sdram_init() {\r
        uint32_t vendor_id, bc;\r
 \r
-       printf("%s: (0) SD_CS = 0x%X\n", __FUNCTION__, SD_CS);\r
+       logf("(0) SD_CS = 0x%X\n", SD_CS);\r
 \r
        PM_SMPS = PM_PASSWORD | 0x1;\r
        A2W_SMPS_LDO1 = A2W_PASSWORD | 0x40000;\r
@@ -301,14 +500,14 @@ void sdram_init() {
         * the calibration sequence.\r
         */\r
 \r
-       sdram_set_clock_source(CM_SRC_OSC, 1);\r
-       \r
-       sdram_init_clkman();\r
+       switch_to_cprman_clock(CM_SRC_OSC, 1);\r
+\r
+       CALL_INIT_CLKMAN;\r
 \r
-       sdram_reset_phy();\r
+       reset_phy();\r
 \r
        /* magic values */\r
-       SD_SA = 0x6E3395;\r
+       SD_SA = 0x006E3395;\r
        SD_SB = 0x0F9;\r
        SD_SC = 0x6000431;\r
        SD_SD = 0x10000011;\r
@@ -319,32 +518,37 @@ void sdram_init() {
        SD_CS = 0x200042;\r
 \r
        /* wait for SDRAM controller */\r
-       printf("%s: waiting for SDUP (%X) ...\n", __FUNCTION__, SD_CS);\r
+       logf("waiting for SDUP (%X) ...\n", SD_CS);\r
        for (;;) if (SD_CS & SD_CS_SDUP_SET) break;\r
-       printf("%s: SDRAM controller has arrived! (%X)\n", __FUNCTION__, SD_CS);\r
+       logf("SDRAM controller has arrived! (%X)\n", SD_CS);\r
        \r
        /* RL = 6 / WL = 3 */\r
-       sdram_write_mr(LPDDR2_MR_DEVICE_FEATURE_2, 4, false);\r
-       sdram_calibrate();\r
+       write_mr(LPDDR2_MR_DEVICE_FEATURE_2, 4, false);\r
+       calibrate_pvt_early();\r
 \r
        /* identify installed memory */\r
-       vendor_id = sdram_read_mr(LPDDR2_MR_MANUFACTURER_ID);\r
+       vendor_id = read_mr(LPDDR2_MR_MANUFACTURER_ID);\r
        if (!MR_REQUEST_SUCCESS(vendor_id)) {\r
                panic("vendor id memory register read timed out");\r
        }\r
        vendor_id = MR_GET_RDATA(vendor_id);\r
 \r
-       bc = sdram_read_mr(LPDDR2_MR_METRICS);\r
+       bc = read_mr(LPDDR2_MR_METRICS);\r
        if (!MR_REQUEST_SUCCESS(bc)) {\r
                panic("basic configuration memory register read timed out");\r
        }\r
        bc = MR_GET_RDATA(bc);\r
 \r
-       printf("SDRAM Type: %s %s LPDDR2 (BC=0x%X)\n",\r
+       g_RAMSize = lpddr2_size(bc);\r
+\r
+       logf("SDRAM Type: %s %s LPDDR2 (BC=0x%X)\n",\r
                lpddr2_manufacturer_name(vendor_id),\r
-               lpddr2_density(bc),\r
+               size_to_string[g_RAMSize],\r
                bc);\r
 \r
+       if (g_RAMSize == RAM_SIZE_UNKNOWN)\r
+               panic("unknown ram size (MR8 response was 0x%X)", bc);\r
+\r
        /*\r
         * STEP 2:\r
         * after calibration, enable high-freq SDRAM PLL. because we're\r
@@ -354,7 +558,21 @@ void sdram_init() {
         * mess with SDRAM clock it would need to do that.\r
         */\r
 \r
-       sdram_init_late();\r
-       sdram_selftest();\r
+       if (g_RAMSize == RAM_SIZE_1GB) {\r
+               logf("*** USING LOW tREFI (~7.8us) FOR 1GB, YOUR RAM MAY LEAK!!!!\n");\r
+\r
+               g_InitSdramParameters.colbits = 3;\r
+               g_InitSdramParameters.rowbits = 3;\r
+               g_InitSdramParameters.banklow = 3;\r
+       }\r
+       else if (g_RAMSize == RAM_SIZE_512MB) {\r
+               logf("*** USING LOW tREFI (~7.8us) FOR 512MB, YOUR RAM MAY LEAK!!!!\n");\r
+\r
+               g_InitSdramParameters.colbits = 2;\r
+       }\r
+\r
+       reset_with_timing(&g_InitSdramParameters);\r
+       init_late();\r
+       selftest();\r
 }\r
 \r
This page took 0.059266 seconds and 4 git commands to generate.