1 /*
2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
3 * Copyright 2016-2019 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_sdramc.h"
10
11 /*******************************************************************************
12 * Definitions
13 ******************************************************************************/
14
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.sdramc"
18 #endif
19
20 /*! @brief Define macros for SDRAM driver. */
21 #define SDRAMC_ONEMILLSEC_NANOSECONDS (1000000U)
22 #define SDRAMC_ONESECOND_MILLISECONDS (1000U)
23
24 /*******************************************************************************
25 * Prototypes
26 ******************************************************************************/
27 /*!
28 * @brief Get instance number for SDRAMC module.
29 *
30 * @param base SDRAMC peripheral base address
31 */
32 static uint32_t SDRAMC_GetInstance(SDRAM_Type *base);
33
34 /*******************************************************************************
35 * Variables
36 ******************************************************************************/
37
38 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
39 /*! @brief Pointers to SDRAMC clocks for each instance. */
40 static const clock_ip_name_t s_sdramClock[FSL_FEATURE_SOC_SDRAM_COUNT] = SDRAM_CLOCKS;
41 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
42
43 /*! @brief Pointers to SDRAMC bases for each instance. */
44 static SDRAM_Type *const s_sdramcBases[] = SDRAM_BASE_PTRS;
45 /*******************************************************************************
46 * Code
47 ******************************************************************************/
48
SDRAMC_GetInstance(SDRAM_Type * base)49 static uint32_t SDRAMC_GetInstance(SDRAM_Type *base)
50 {
51 uint32_t instance;
52
53 /* Find the instance index from base address mappings. */
54 for (instance = 0; instance < ARRAY_SIZE(s_sdramcBases); instance++)
55 {
56 if (s_sdramcBases[instance] == base)
57 {
58 break;
59 }
60 }
61
62 assert(instance < ARRAY_SIZE(s_sdramcBases));
63
64 return instance;
65 }
66
67 /*!
68 * brief Initializes the SDRAM controller.
69 * This function ungates the SDRAM controller clock and initializes the SDRAM controller.
70 * This function must be called before calling any other SDRAM controller driver functions.
71 * Example
72 code
73 sdramc_refresh_config_t refreshConfig;
74 sdramc_blockctl_config_t blockConfig;
75 sdramc_config_t config;
76
77 refreshConfig.refreshTime = kSDRAM_RefreshThreeClocks;
78 refreshConfig.sdramRefreshRow = 15625;
79 refreshConfig.busClock = 60000000;
80
81 blockConfig.block = kSDRAMC_Block0;
82 blockConfig.portSize = kSDRAMC_PortSize16Bit;
83 blockConfig.location = kSDRAMC_Commandbit19;
84 blockConfig.latency = kSDRAMC_RefreshThreeClocks;
85 blockConfig.address = SDRAM_START_ADDRESS;
86 blockConfig.addressMask = 0x7c0000;
87
88 config.refreshConfig = &refreshConfig,
89 config.blockConfig = &blockConfig,
90 config.totalBlocks = 1;
91
92 SDRAMC_Init(SDRAM, &config);
93 endcode
94 *
95 * param base SDRAM controller peripheral base address.
96 * param configure The SDRAM configuration structure pointer.
97 */
SDRAMC_Init(SDRAM_Type * base,sdramc_config_t * configure)98 void SDRAMC_Init(SDRAM_Type *base, sdramc_config_t *configure)
99 {
100 assert(configure);
101 assert(configure->refreshConfig);
102 assert(configure->blockConfig);
103 assert(configure->refreshConfig->busClock_Hz);
104
105 sdramc_blockctl_config_t *bctlConfig = configure->blockConfig;
106 sdramc_refresh_config_t *refreshConfig = configure->refreshConfig;
107 uint32_t count;
108 uint32_t index;
109
110 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
111 /* Un-gate sdram controller clock. */
112 CLOCK_EnableClock(s_sdramClock[SDRAMC_GetInstance(base)]);
113 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
114
115 /* Initialize sdram Auto refresh timing. */
116 count = refreshConfig->sdramRefreshRow * (refreshConfig->busClock_Hz / SDRAMC_ONESECOND_MILLISECONDS);
117 count = (count / SDRAMC_ONEMILLSEC_NANOSECONDS) / 16U - 1U;
118 base->CTRL = SDRAM_CTRL_RC(count) | SDRAM_CTRL_RTIM(refreshConfig->refreshTime);
119
120 for (index = 0; index < configure->numBlockConfig; index++)
121 {
122 /* Set the sdram block control. */
123 base->BLOCK[index].AC = SDRAM_AC_PS(bctlConfig->portSize) | SDRAM_AC_CASL(bctlConfig->latency) |
124 SDRAM_AC_CBM(bctlConfig->location) | (bctlConfig->address & SDRAM_AC_BA_MASK);
125
126 base->BLOCK[index].CM = (bctlConfig->addressMask & SDRAM_CM_BAM_MASK) | SDRAM_CM_V_MASK;
127
128 /* Increases to the next sdram block. */
129 bctlConfig++;
130 }
131 }
132
133 /*!
134 * brief Deinitializes the SDRAM controller module and gates the clock.
135 * This function gates the SDRAM controller clock. As a result, the SDRAM
136 * controller module doesn't work after calling this function.
137 *
138 * param base SDRAM controller peripheral base address.
139 */
SDRAMC_Deinit(SDRAM_Type * base)140 void SDRAMC_Deinit(SDRAM_Type *base)
141 {
142 /* Set the SDRAMC invalid, do not decode DRAM accesses. */
143 SDRAMC_EnableOperateValid(base, kSDRAMC_Block0, false);
144 SDRAMC_EnableOperateValid(base, kSDRAMC_Block1, false);
145
146 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
147 /* Disable SDRAM clock. */
148 CLOCK_DisableClock(s_sdramClock[SDRAMC_GetInstance(base)]);
149 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
150 }
151
152 /*!
153 * brief Sends the SDRAM command.
154 * This function sends commands to SDRAM. The commands are precharge command, initialization MRS command,
155 * auto-refresh enable/disable command, and self-refresh enter/exit commands.
156 * Note that the self-refresh enter/exit commands are all blocks setting and "block"
157 * is ignored. Ensure to set the correct "block" when send other commands.
158 *
159 * param base SDRAM controller peripheral base address.
160 * param block The block selection.
161 * param command The SDRAM command, see "sdramc_command_t".
162 * kSDRAMC_ImrsCommand - Initialize MRS command \n
163 * kSDRAMC_PrechargeCommand - Initialize precharge command \n
164 * kSDRAMC_SelfrefreshEnterCommand - Enter self-refresh command \n
165 * kSDRAMC_SelfrefreshExitCommand - Exit self-refresh command \n
166 * kSDRAMC_AutoRefreshEnableCommand - Enable auto refresh command \n
167 * kSDRAMC_AutoRefreshDisableCommand - Disable auto refresh command
168 */
SDRAMC_SendCommand(SDRAM_Type * base,sdramc_block_selection_t block,sdramc_command_t command)169 void SDRAMC_SendCommand(SDRAM_Type *base, sdramc_block_selection_t block, sdramc_command_t command)
170 {
171 switch (command)
172 {
173 /* Initiate mrs command. */
174 case kSDRAMC_ImrsCommand:
175 base->BLOCK[block].AC |= SDRAM_AC_IMRS_MASK;
176 break;
177 /* Initiate precharge command. */
178 case kSDRAMC_PrechargeCommand:
179 base->BLOCK[block].AC |= SDRAM_AC_IP_MASK;
180 break;
181 /* Enable Auto refresh command. */
182 case kSDRAMC_AutoRefreshEnableCommand:
183 base->BLOCK[block].AC |= SDRAM_AC_RE_MASK;
184 break;
185 /* Disable Auto refresh command. */
186 case kSDRAMC_AutoRefreshDisableCommand:
187 base->BLOCK[block].AC &= ~SDRAM_AC_RE_MASK;
188 break;
189 /* Enter self-refresh command. */
190 case kSDRAMC_SelfrefreshEnterCommand:
191 base->CTRL |= SDRAM_CTRL_IS_MASK;
192 break;
193 /* Exit self-refresh command. */
194 case kSDRAMC_SelfrefreshExitCommand:
195 base->CTRL &= ~(uint16_t)SDRAM_CTRL_IS_MASK;
196 break;
197 default:
198 assert(false);
199 break;
200 }
201 }
202