1 /*
2  * Copyright 2017 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include <rtthread.h>
9 #ifdef BSP_USING_SDRAM
10 
11 #include "sdram_port.h"
12 #include "board.h"
13 #include "fsl_semc.h"
14 #include "drv_sdram.h"
15 
16 //#define DBG_COLOR
17 //#define DRV_DEBUG
18 //#define LOG_TAG             "drv.sdram"
19 //#include <drv_log.h>
20 
21 #define DBG_ENABLE
22 #define DBG_SECTION_NAME "[drv.sdram]"
23 #define DBG_COLOR
24 #define DBG_LEVEL DBG_INFO
25 #include <rtdbg.h>
26 
27 #ifdef RT_USING_MEMHEAP
28 static struct rt_memheap system_heap;
29 #endif
30 
rt_hw_sdram_init(void)31 int rt_hw_sdram_init(void)
32 {
33     int result = RT_EOK;
34     semc_config_t config;
35     semc_sdram_config_t sdramconfig;
36 
37 #if defined(SOC_IMXRT1170_SERIES)
38     rt_uint32_t clockFrq = CLOCK_GetRootClockFreq(kCLOCK_Root_Semc);
39 #else
40     rt_uint32_t clockFrq = CLOCK_GetFreq(kCLOCK_SemcClk);
41 #endif
42 
43     /* Initializes the MAC configure structure to zero. */
44     rt_memset(&config, 0, sizeof(semc_config_t));
45     rt_memset(&sdramconfig, 0, sizeof(semc_sdram_config_t));
46 
47     /* Initialize SEMC. */
48     SEMC_GetDefaultConfig(&config);
49     config.dqsMode = kSEMC_Loopbackdqspad;  /* For more accurate timing. */
50     SEMC_Init(SEMC, &config);
51 
52     /* Configure SDRAM. */
53     sdramconfig.csxPinMux               = SDRAM_CS_PIN;
54     sdramconfig.address                 = SDRAM_BANK_ADDR;
55     sdramconfig.memsize_kbytes          = SDRAM_SIZE;
56     sdramconfig.portSize                = SDRAM_DATA_WIDTH;
57     sdramconfig.burstLen                = kSEMC_Sdram_BurstLen8;
58     sdramconfig.columnAddrBitNum        = SDRAM_COLUMN_BITS;
59     sdramconfig.casLatency              = SDRAM_CAS_LATENCY;
60     sdramconfig.tPrecharge2Act_Ns       = SDRAM_TRP;
61     sdramconfig.tAct2ReadWrite_Ns       = SDRAM_TRCD;
62     sdramconfig.tRefreshRecovery_Ns     = SDRAM_REFRESH_RECOVERY;
63     sdramconfig.tWriteRecovery_Ns       = SDRAM_TWR;
64     sdramconfig.tCkeOff_Ns              = 42;  /* The minimum cycle of SDRAM CLK off state. CKE is off in self refresh at a minimum period tRAS.*/
65     sdramconfig.tAct2Prechage_Ns        = SDRAM_TRAS;
66     sdramconfig.tSelfRefRecovery_Ns     = 67;
67     sdramconfig.tRefresh2Refresh_Ns     = SDRAM_TRC;
68     sdramconfig.tAct2Act_Ns             = SDRAM_ACT2ACT;
69     sdramconfig.tPrescalePeriod_Ns      = 160 * (1000000000 / clockFrq);
70     sdramconfig.refreshPeriod_nsPerRow  = SDRAM_REFRESH_ROW;
71     sdramconfig.refreshUrgThreshold     = sdramconfig.refreshPeriod_nsPerRow;
72     sdramconfig.refreshBurstLen         = 1;
73     result = SEMC_ConfigureSDRAM(SEMC, SDRAM_REGION, &sdramconfig, clockFrq);
74     if(result != kStatus_Success)
75     {
76         LOG_E("SDRAM init failed!");
77         result = -RT_ERROR;
78     }
79     else
80     {
81         LOG_I("sdram init success, mapped at 0x%X, size is %d Kbytes.", SDRAM_BANK_ADDR, SDRAM_SIZE);
82 #ifdef RT_USING_MEMHEAP
83     /*
84      * If RT_USING_MEMHEAP is enabled, SDRAM is initialized to the heap.
85      * The heap start address is (base + half size), and the size is (half size - 2M).
86      * The reasons are:
87      *      1. Reserve the half space for SDRAM link case
88      *      2. Reserve the 2M for non-cache space
89      */
90         rt_memheap_init(&system_heap, "sdram", (void *)(SDRAM_BANK_ADDR + (SDRAM_SIZE * 1024)/2),
91             (SDRAM_SIZE * 1024)/2 - (2 * 1024 * 1024));
92 #endif
93     }
94 
95     return result;
96 }
97 INIT_PREV_EXPORT(rt_hw_sdram_init);
98 
99 #ifdef DBG_ENABLE
100 #ifdef FINSH_USING_MSH
101 
102 #define SEMC_DATALEN                (0x1000U)
103 rt_uint32_t sdram_writeBuffer[SEMC_DATALEN];
104 rt_uint32_t sdram_readBuffer[SEMC_DATALEN];
105 
106 /* read write 32bit test */
sdram_test(void)107 static void sdram_test(void)
108 {
109     rt_uint32_t index;
110     rt_uint32_t datalen = SEMC_DATALEN;
111     rt_uint32_t *sdram = (rt_uint32_t *)SDRAM_BANK_ADDR; /* SDRAM start address. */
112     bool result = true;
113 
114     LOG_D("SEMC SDRAM Memory 32 bit Write Start, Start Address 0x%x, Data Length %d !", sdram, datalen);
115     /* Prepare data and write to SDRAM. */
116     for (index = 0; index < datalen; index++)
117     {
118         sdram_writeBuffer[index] = index;
119         sdram[index] = sdram_writeBuffer[index];
120     }
121 
122     LOG_D("SEMC SDRAM Read 32 bit Data Start, Start Address 0x%x, Data Length %d !", sdram, datalen);
123     /* Read data from the SDRAM. */
124     for (index = 0; index < datalen; index++)
125     {
126         sdram_readBuffer[index] = sdram[index];
127     }
128 
129     LOG_I("SEMC SDRAM 32 bit Data Write and Read Compare Start!");
130     /* Compare the two buffers. */
131     while (datalen--)
132     {
133         if (sdram_writeBuffer[datalen] != sdram_readBuffer[datalen])
134         {
135             result = false;
136             break;
137         }
138     }
139 
140     if (!result)
141     {
142         LOG_E("SEMC SDRAM 32 bit Data Write and Read Compare Failed!");
143     }
144     else
145     {
146         LOG_I("SEMC SDRAM 32 bit Data Write and Read Compare Succeed!");
147     }
148 }
149 MSH_CMD_EXPORT(sdram_test, sdram test)
150 
151 #endif /* DRV_DEBUG */
152 #endif /* FINSH_USING_MSH */
153 #endif /* BSP_USING_SDRAM */
154