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