1 /*!
2     \file    gd32f403_exmc.c
3     \brief   EXMC driver
4 
5     \version 2017-02-10, V1.0.0, firmware for GD32F403
6     \version 2018-12-25, V2.0.0, firmware for GD32F403
7     \version 2020-09-30, V2.1.0, firmware for GD32F403
8 */
9 
10 /*
11     Copyright (c) 2020, GigaDevice Semiconductor Inc.
12 
13     Redistribution and use in source and binary forms, with or without modification,
14 are permitted provided that the following conditions are met:
15 
16     1. Redistributions of source code must retain the above copyright notice, this
17        list of conditions and the following disclaimer.
18     2. Redistributions in binary form must reproduce the above copyright notice,
19        this list of conditions and the following disclaimer in the documentation
20        and/or other materials provided with the distribution.
21     3. Neither the name of the copyright holder nor the names of its contributors
22        may be used to endorse or promote products derived from this software without
23        specific prior written permission.
24 
25     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
34 OF SUCH DAMAGE.
35 */
36 
37 #include "gd32f403_exmc.h"
38 
39 /* EXMC bank0 register reset value */
40 #define BANK0_SNCTL_REGION0_RESET         ((uint32_t)0x000030DBU)
41 #define BANK0_SNCTL_REGION1_2_3_RESET     ((uint32_t)0x000030D2U)
42 #define BANK0_SNTCFG_RESET                ((uint32_t)0x0FFFFFFFU)
43 #define BANK0_SNWTCFG_RESET               ((uint32_t)0x0FFFFFFFU)
44 
45 /* EXMC bank1/2 register reset mask */
46 #define BANK1_2_NPCTL_RESET               ((uint32_t)0x00000018U)
47 #define BANK1_2_NPINTEN_RESET             ((uint32_t)0x00000042U)
48 #define BANK1_2_NPCTCFG_RESET             ((uint32_t)0xFCFCFCFCU)
49 #define BANK1_2_NPATCFG_RESET             ((uint32_t)0xFCFCFCFCU)
50 
51 /* EXMC bank3 register reset mask */
52 #define BANK3_NPCTL_RESET                 ((uint32_t)0x00000018U)
53 #define BANK3_NPINTEN_RESET               ((uint32_t)0x00000043U)
54 #define BANK3_NPCTCFG_RESET               ((uint32_t)0xFCFCFCFCU)
55 #define BANK3_NPATCFG_RESET               ((uint32_t)0xFCFCFCFCU)
56 #define BANK3_PIOTCFG3_RESET              ((uint32_t)0xFCFCFCFCU)
57 
58 /* EXMC register bit offset */
59 #define SNCTL_NRMUX_OFFSET                ((uint32_t)1U)
60 #define SNCTL_SBRSTEN_OFFSET              ((uint32_t)8U)
61 #define SNCTL_WRAPEN_OFFSET               ((uint32_t)10U)
62 #define SNCTL_WREN_OFFSET                 ((uint32_t)12U)
63 #define SNCTL_NRWTEN_OFFSET               ((uint32_t)13U)
64 #define SNCTL_EXMODEN_OFFSET              ((uint32_t)14U)
65 #define SNCTL_ASYNCWAIT_OFFSET            ((uint32_t)15U)
66 
67 #define SNTCFG_AHLD_OFFSET                ((uint32_t)4U)
68 #define SNTCFG_DSET_OFFSET                ((uint32_t)8U)
69 #define SNTCFG_BUSLAT_OFFSET              ((uint32_t)16U)
70 
71 #define SNWTCFG_WAHLD_OFFSET              ((uint32_t)4U)
72 #define SNWTCFG_WDSET_OFFSET              ((uint32_t)8U)
73 #define SNWTCFG_WBUSLAT_OFFSET            ((uint32_t)16U)
74 
75 #define NPCTL_NDWTEN_OFFSET               ((uint32_t)1U)
76 #define NPCTL_ECCEN_OFFSET                ((uint32_t)6U)
77 
78 #define NPCTCFG_COMWAIT_OFFSET            ((uint32_t)8U)
79 #define NPCTCFG_COMHLD_OFFSET             ((uint32_t)16U)
80 #define NPCTCFG_COMHIZ_OFFSET             ((uint32_t)24U)
81 
82 #define NPATCFG_ATTWAIT_OFFSET            ((uint32_t)8U)
83 #define NPATCFG_ATTHLD_OFFSET             ((uint32_t)16U)
84 #define NPATCFG_ATTHIZ_OFFSET             ((uint32_t)24U)
85 
86 #define PIOTCFG_IOWAIT_OFFSET             ((uint32_t)8U)
87 #define PIOTCFG_IOHLD_OFFSET              ((uint32_t)16U)
88 #define PIOTCFG_IOHIZ_OFFSET              ((uint32_t)24U)
89 
90 #define INTEN_INTS_OFFSET                 ((uint32_t)3U)
91 
92 /*!
93     \brief      deinitialize EXMC NOR/SRAM region
94     \param[in]  exmc_norsram_region: select the region of bank0
95                 only one parameter can be selected which is shown as below:
96       \arg        EXMC_BANK0_NORSRAM_REGIONx(x=0..3)
97     \param[out] none
98     \retval     none
99 */
exmc_norsram_deinit(uint32_t exmc_norsram_region)100 void exmc_norsram_deinit(uint32_t exmc_norsram_region)
101 {
102     /* reset the registers */
103     if(EXMC_BANK0_NORSRAM_REGION0 == exmc_norsram_region){
104         EXMC_SNCTL(exmc_norsram_region) = BANK0_SNCTL_REGION0_RESET;
105     }else{
106         EXMC_SNCTL(exmc_norsram_region) = BANK0_SNCTL_REGION1_2_3_RESET;
107     }
108     EXMC_SNTCFG(exmc_norsram_region) = BANK0_SNTCFG_RESET;
109     EXMC_SNWTCFG(exmc_norsram_region) = BANK0_SNWTCFG_RESET;
110 }
111 
112 /*!
113     \brief      initialize exmc_norsram_parameter_struct with the default values
114     \param[in]  none
115     \param[out] exmc_norsram_init_struct: the initialized struct exmc_norsram_parameter_struct pointer
116     \retval     none
117 */
exmc_norsram_struct_para_init(exmc_norsram_parameter_struct * exmc_norsram_init_struct)118 void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct)
119 {
120     /* configure the structure with default values */
121     exmc_norsram_init_struct->norsram_region = EXMC_BANK0_NORSRAM_REGION0;
122     exmc_norsram_init_struct->address_data_mux = ENABLE;
123     exmc_norsram_init_struct->memory_type = EXMC_MEMORY_TYPE_SRAM;
124     exmc_norsram_init_struct->databus_width = EXMC_NOR_DATABUS_WIDTH_8B;
125     exmc_norsram_init_struct->burst_mode = DISABLE;
126     exmc_norsram_init_struct->nwait_polarity = EXMC_NWAIT_POLARITY_LOW;
127     exmc_norsram_init_struct->wrap_burst_mode = DISABLE;
128     exmc_norsram_init_struct->nwait_config = EXMC_NWAIT_CONFIG_BEFORE;
129     exmc_norsram_init_struct->memory_write = ENABLE;
130     exmc_norsram_init_struct->nwait_signal = ENABLE;
131     exmc_norsram_init_struct->extended_mode = DISABLE;
132     exmc_norsram_init_struct->asyn_wait = DISABLE;
133     exmc_norsram_init_struct->write_mode = EXMC_ASYN_WRITE;
134 
135     /* read/write timing configure */
136     exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime = 0xFU;
137     exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime = 0xFU;
138     exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime = 0xFFU;
139     exmc_norsram_init_struct->read_write_timing->bus_latency = 0xFU;
140     exmc_norsram_init_struct->read_write_timing->syn_clk_division = EXMC_SYN_CLOCK_RATIO_16_CLK;
141     exmc_norsram_init_struct->read_write_timing->syn_data_latency = EXMC_DATALAT_17_CLK;
142     exmc_norsram_init_struct->read_write_timing->asyn_access_mode = EXMC_ACCESS_MODE_A;
143 
144     /* write timing configure, when extended mode is used */
145     exmc_norsram_init_struct->write_timing->asyn_address_setuptime = 0xFU;
146     exmc_norsram_init_struct->write_timing->asyn_address_holdtime = 0xFU;
147     exmc_norsram_init_struct->write_timing->asyn_data_setuptime = 0xFFU;
148     exmc_norsram_init_struct->write_timing->bus_latency = 0xFU;
149     exmc_norsram_init_struct->write_timing->asyn_access_mode = EXMC_ACCESS_MODE_A;
150 }
151 
152 /*!
153     \brief      initialize EXMC NOR/SRAM region
154     \param[in]  exmc_norsram_parameter_struct: configure the EXMC NOR/SRAM parameter
155                   norsram_region: EXMC_BANK0_NORSRAM_REGIONx,x=0..3
156                   write_mode: EXMC_ASYN_WRITE,EXMC_SYN_WRITE
157                   extended_mode: ENABLE or DISABLE
158                   asyn_wait: ENABLE or DISABLE
159                   nwait_signal: ENABLE or DISABLE
160                   memory_write: ENABLE or DISABLE
161                   nwait_config: EXMC_NWAIT_CONFIG_BEFORE,EXMC_NWAIT_CONFIG_DURING
162                   wrap_burst_mode: ENABLE or DISABLE
163                   nwait_polarity: EXMC_NWAIT_POLARITY_LOW,EXMC_NWAIT_POLARITY_HIGH
164                   burst_mode: ENABLE or DISABLE
165                   databus_width: EXMC_NOR_DATABUS_WIDTH_8B,EXMC_NOR_DATABUS_WIDTH_16B
166                   memory_type: EXMC_MEMORY_TYPE_SRAM,EXMC_MEMORY_TYPE_PSRAM,EXMC_MEMORY_TYPE_NOR
167                   address_data_mux: ENABLE or DISABLE
168                   read_write_timing: struct exmc_norsram_timing_parameter_struct set the time
169                   write_timing: struct exmc_norsram_timing_parameter_struct set the time
170     \param[out] none
171     \retval     none
172 */
exmc_norsram_init(exmc_norsram_parameter_struct * exmc_norsram_init_struct)173 void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct)
174 {
175     uint32_t snctl = 0x00000000U,sntcfg = 0x00000000U,snwtcfg = 0x00000000U;
176 
177     /* get the register value */
178     snctl = EXMC_SNCTL(exmc_norsram_init_struct->norsram_region);
179 
180     /* clear relative bits */
181     snctl &= ((uint32_t)~(EXMC_SNCTL_NRMUX | EXMC_SNCTL_NRTP | EXMC_SNCTL_NRW | EXMC_SNCTL_SBRSTEN |
182                           EXMC_SNCTL_NREN | EXMC_SNCTL_NRWTPOL | EXMC_SNCTL_WRAPEN | EXMC_SNCTL_NRWTCFG |
183                           EXMC_SNCTL_WREN | EXMC_SNCTL_NRWTEN | EXMC_SNCTL_EXMODEN | EXMC_SNCTL_ASYNCWAIT |
184                           EXMC_SNCTL_SYNCWR ));
185 
186     snctl |= (uint32_t)(exmc_norsram_init_struct->address_data_mux << SNCTL_NRMUX_OFFSET) |
187                         exmc_norsram_init_struct->memory_type |
188                         exmc_norsram_init_struct->databus_width |
189                        (exmc_norsram_init_struct->burst_mode << SNCTL_SBRSTEN_OFFSET) |
190                         exmc_norsram_init_struct->nwait_polarity |
191                        (exmc_norsram_init_struct->wrap_burst_mode << SNCTL_WRAPEN_OFFSET) |
192                         exmc_norsram_init_struct->nwait_config |
193                        (exmc_norsram_init_struct->memory_write << SNCTL_WREN_OFFSET) |
194                        (exmc_norsram_init_struct->nwait_signal << SNCTL_NRWTEN_OFFSET) |
195                        (exmc_norsram_init_struct->extended_mode << SNCTL_EXMODEN_OFFSET) |
196                        (exmc_norsram_init_struct->asyn_wait << SNCTL_ASYNCWAIT_OFFSET) |
197                         exmc_norsram_init_struct->write_mode;
198 
199     sntcfg = (uint32_t)((exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime - 1U ) & EXMC_SNTCFG_ASET )|
200                        (((exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime - 1U ) << SNTCFG_AHLD_OFFSET ) & EXMC_SNTCFG_AHLD ) |
201                        (((exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime - 1U ) << SNTCFG_DSET_OFFSET ) & EXMC_SNTCFG_DSET ) |
202                        (((exmc_norsram_init_struct->read_write_timing->bus_latency - 1U ) << SNTCFG_BUSLAT_OFFSET ) & EXMC_SNTCFG_BUSLAT )|
203                        exmc_norsram_init_struct->read_write_timing->syn_clk_division |
204                        exmc_norsram_init_struct->read_write_timing->syn_data_latency |
205                        exmc_norsram_init_struct->read_write_timing->asyn_access_mode;
206 
207     /* nor flash access enable */
208     if(EXMC_MEMORY_TYPE_NOR == exmc_norsram_init_struct->memory_type){
209         snctl |= (uint32_t)EXMC_SNCTL_NREN;
210     }
211 
212     /* extended mode configure */
213     if(ENABLE == exmc_norsram_init_struct->extended_mode){
214         snwtcfg = (uint32_t)((exmc_norsram_init_struct->write_timing->asyn_address_setuptime - 1U) & EXMC_SNWTCFG_WASET ) |
215                            (((exmc_norsram_init_struct->write_timing->asyn_address_holdtime -1U ) << SNWTCFG_WAHLD_OFFSET ) & EXMC_SNWTCFG_WAHLD )|
216                            (((exmc_norsram_init_struct->write_timing->asyn_data_setuptime -1U ) << SNWTCFG_WDSET_OFFSET ) & EXMC_SNWTCFG_WDSET )|
217                            (((exmc_norsram_init_struct->write_timing->bus_latency - 1U ) << SNWTCFG_WBUSLAT_OFFSET ) & EXMC_SNWTCFG_WBUSLAT ) |
218                             exmc_norsram_init_struct->write_timing->asyn_access_mode;
219     }else{
220         snwtcfg = BANK0_SNWTCFG_RESET;
221     }
222 
223     /* configure the registers */
224     EXMC_SNCTL(exmc_norsram_init_struct->norsram_region) = snctl;
225     EXMC_SNTCFG(exmc_norsram_init_struct->norsram_region) = sntcfg;
226     EXMC_SNWTCFG(exmc_norsram_init_struct->norsram_region) = snwtcfg;
227 }
228 
229 /*!
230     \brief      enable EXMC NOR/PSRAM bank region
231     \param[in]  exmc_norsram_region: specifie the region of NOR/PSRAM bank
232                 only one parameter can be selected which is shown as below:
233       \arg        EXMC_BANK0_NORSRAM_REGIONx(x=0..3)
234     \param[out] none
235     \retval     none
236 */
exmc_norsram_enable(uint32_t exmc_norsram_region)237 void exmc_norsram_enable(uint32_t exmc_norsram_region)
238 {
239     EXMC_SNCTL(exmc_norsram_region) |= (uint32_t)EXMC_SNCTL_NRBKEN;
240 }
241 
242 /*!
243     \brief      disable EXMC NOR/PSRAM bank region
244     \param[in]  exmc_norsram_region: specifie the region of NOR/PSRAM Bank
245                 only one parameter can be selected which is shown as below:
246       \arg        EXMC_BANK0_NORSRAM_REGIONx(x=0..3)
247     \param[out] none
248     \retval     none
249 */
exmc_norsram_disable(uint32_t exmc_norsram_region)250 void exmc_norsram_disable(uint32_t exmc_norsram_region)
251 {
252     EXMC_SNCTL(exmc_norsram_region) &= ~(uint32_t)EXMC_SNCTL_NRBKEN;
253 }
254 
255 /*!
256     \brief      deinitialize EXMC NAND bank
257     \param[in]  exmc_nand_bank: select the bank of NAND
258                 only one parameter can be selected which is shown as below:
259       \arg        EXMC_BANKx_NAND(x=1..2)
260     \param[out] none
261     \retval     none
262 */
exmc_nand_deinit(uint32_t exmc_nand_bank)263 void exmc_nand_deinit(uint32_t exmc_nand_bank)
264 {
265     /* EXMC_BANK1_NAND or EXMC_BANK2_NAND */
266     EXMC_NPCTL(exmc_nand_bank) = BANK1_2_NPCTL_RESET;
267     EXMC_NPINTEN(exmc_nand_bank) = BANK1_2_NPINTEN_RESET;
268     EXMC_NPCTCFG(exmc_nand_bank) = BANK1_2_NPCTCFG_RESET;
269     EXMC_NPATCFG(exmc_nand_bank) = BANK1_2_NPATCFG_RESET;
270 }
271 
272 /*!
273     \brief      initialize exmc_norsram_parameter_struct with the default values
274     \param[in]  none
275     \param[out] the initialized struct exmc_norsram_parameter_struct pointer
276     \retval     none
277 */
exmc_nand_struct_para_init(exmc_nand_parameter_struct * exmc_nand_init_struct)278 void exmc_nand_struct_para_init(exmc_nand_parameter_struct* exmc_nand_init_struct)
279 {
280     /* configure the structure with default values */
281     exmc_nand_init_struct->nand_bank = EXMC_BANK1_NAND;
282     exmc_nand_init_struct->wait_feature = DISABLE;
283     exmc_nand_init_struct->databus_width = EXMC_NAND_DATABUS_WIDTH_8B;
284     exmc_nand_init_struct->ecc_logic = DISABLE;
285     exmc_nand_init_struct->ecc_size = EXMC_ECC_SIZE_256BYTES;
286     exmc_nand_init_struct->ctr_latency = 0x0U;
287     exmc_nand_init_struct->atr_latency = 0x0U;
288     exmc_nand_init_struct->common_space_timing->setuptime = 0xFCU;
289     exmc_nand_init_struct->common_space_timing->waittime = 0xFCU;
290     exmc_nand_init_struct->common_space_timing->holdtime = 0xFCU;
291     exmc_nand_init_struct->common_space_timing->databus_hiztime = 0xFCU;
292     exmc_nand_init_struct->attribute_space_timing->setuptime = 0xFCU;
293     exmc_nand_init_struct->attribute_space_timing->waittime = 0xFCU;
294     exmc_nand_init_struct->attribute_space_timing->holdtime = 0xFCU;
295     exmc_nand_init_struct->attribute_space_timing->databus_hiztime = 0xFCU;
296 }
297 
298 /*!
299     \brief      initialize EXMC NAND bank
300     \param[in]  exmc_nand_parameter_struct: configure the EXMC NAND parameter
301                   nand_bank: EXMC_BANK1_NAND,EXMC_BANK2_NAND
302                   ecc_size: EXMC_ECC_SIZE_xBYTES,x=256,512,1024,2048,4096
303                   atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16
304                   ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16
305                   ecc_logic: ENABLE or DISABLE
306                   databus_width: EXMC_NAND_DATABUS_WIDTH_8B,EXMC_NAND_DATABUS_WIDTH_16B
307                   wait_feature: ENABLE or DISABLE
308                   common_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time
309                   attribute_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time
310     \param[out] none
311     \retval     none
312 */
exmc_nand_init(exmc_nand_parameter_struct * exmc_nand_init_struct)313 void exmc_nand_init(exmc_nand_parameter_struct* exmc_nand_init_struct)
314 {
315     uint32_t npctl = 0x00000000U, npctcfg = 0x00000000U, npatcfg = 0x00000000U;
316 
317     npctl = (uint32_t)(exmc_nand_init_struct->wait_feature << NPCTL_NDWTEN_OFFSET)|
318                        EXMC_NPCTL_NDTP |
319                        exmc_nand_init_struct->databus_width |
320                       (exmc_nand_init_struct->ecc_logic << NPCTL_ECCEN_OFFSET)|
321                        exmc_nand_init_struct->ecc_size |
322                        exmc_nand_init_struct->ctr_latency |
323                        exmc_nand_init_struct->atr_latency;
324 
325     npctcfg = (uint32_t)((exmc_nand_init_struct->common_space_timing->setuptime - 1U) & EXMC_NPCTCFG_COMSET ) |
326                         (((exmc_nand_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) & EXMC_NPCTCFG_COMWAIT ) |
327                         ((exmc_nand_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET) & EXMC_NPCTCFG_COMHLD ) |
328                         (((exmc_nand_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET) & EXMC_NPCTCFG_COMHIZ );
329 
330     npatcfg = (uint32_t)((exmc_nand_init_struct->attribute_space_timing->setuptime - 1U) & EXMC_NPATCFG_ATTSET ) |
331                         (((exmc_nand_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_ATTWAIT_OFFSET) & EXMC_NPATCFG_ATTWAIT ) |
332                         ((exmc_nand_init_struct->attribute_space_timing->holdtime << NPATCFG_ATTHLD_OFFSET) & EXMC_NPATCFG_ATTHLD ) |
333                         (((exmc_nand_init_struct->attribute_space_timing->databus_hiztime -1U) << NPATCFG_ATTHIZ_OFFSET) & EXMC_NPATCFG_ATTHIZ );
334 
335     /* EXMC_BANK1_NAND or EXMC_BANK2_NAND initialize */
336     EXMC_NPCTL(exmc_nand_init_struct->nand_bank) = npctl;
337     EXMC_NPCTCFG(exmc_nand_init_struct->nand_bank) = npctcfg;
338     EXMC_NPATCFG(exmc_nand_init_struct->nand_bank) = npatcfg;
339 }
340 
341 /*!
342     \brief      enable NAND bank
343     \param[in]  exmc_nand_bank: specifie the NAND bank
344                 only one parameter can be selected which is shown as below:
345       \arg        EXMC_BANKx_NAND(x=1,2)
346     \param[out] none
347     \retval     none
348 */
exmc_nand_enable(uint32_t exmc_nand_bank)349 void exmc_nand_enable(uint32_t exmc_nand_bank)
350 {
351     EXMC_NPCTL(exmc_nand_bank) |= EXMC_NPCTL_NDBKEN;
352 }
353 
354 /*!
355     \brief      disable NAND bank
356     \param[in]  exmc_nand_bank: specifie the NAND bank
357                 only one parameter can be selected which is shown as below:
358       \arg        EXMC_BANKx_NAND(x=1,2)
359     \param[out] none
360     \retval     none
361 */
exmc_nand_disable(uint32_t exmc_nand_bank)362 void exmc_nand_disable(uint32_t exmc_nand_bank)
363 {
364     EXMC_NPCTL(exmc_nand_bank) &= (~EXMC_NPCTL_NDBKEN);
365 }
366 
367 /*!
368     \brief      deinitialize EXMC PC card bank
369     \param[in]  none
370     \param[out] none
371     \retval     none
372 */
exmc_pccard_deinit(void)373 void exmc_pccard_deinit(void)
374 {
375     /* EXMC_BANK3_PCCARD */
376     EXMC_NPCTL3 = BANK3_NPCTL_RESET;
377     EXMC_NPINTEN3 = BANK3_NPINTEN_RESET;
378     EXMC_NPCTCFG3 = BANK3_NPCTCFG_RESET;
379     EXMC_NPATCFG3 = BANK3_NPATCFG_RESET;
380     EXMC_PIOTCFG3 = BANK3_PIOTCFG3_RESET;
381 }
382 
383 /*!
384     \brief      initialize exmc_pccard_parameter_struct parameter with the default values
385     \param[in]  none
386     \param[out] the initialized struct exmc_pccard_parameter_struct pointer
387     \retval     none
388 */
exmc_pccard_struct_para_init(exmc_pccard_parameter_struct * exmc_pccard_init_struct)389 void exmc_pccard_struct_para_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct)
390 {
391     /* configure the structure with default values */
392     exmc_pccard_init_struct->wait_feature = DISABLE;
393     exmc_pccard_init_struct->ctr_latency = 0x0U;
394     exmc_pccard_init_struct->atr_latency = 0x0U;
395     exmc_pccard_init_struct->common_space_timing->setuptime = 0xFCU;
396     exmc_pccard_init_struct->common_space_timing->waittime = 0xFCU;
397     exmc_pccard_init_struct->common_space_timing->holdtime = 0xFCU;
398     exmc_pccard_init_struct->common_space_timing->databus_hiztime = 0xFCU;
399     exmc_pccard_init_struct->attribute_space_timing->setuptime = 0xFCU;
400     exmc_pccard_init_struct->attribute_space_timing->waittime = 0xFCU;
401     exmc_pccard_init_struct->attribute_space_timing->holdtime = 0xFCU;
402     exmc_pccard_init_struct->attribute_space_timing->databus_hiztime = 0xFCU;
403     exmc_pccard_init_struct->io_space_timing->setuptime = 0xFCU;
404     exmc_pccard_init_struct->io_space_timing->waittime = 0xFCU;
405     exmc_pccard_init_struct->io_space_timing->holdtime = 0xFCU;
406     exmc_pccard_init_struct->io_space_timing->databus_hiztime = 0xFCU;
407 }
408 
409 /*!
410     \brief      initialize EXMC PC card bank
411     \param[in]  exmc_pccard_parameter_struct: configure the EXMC NAND parameter
412                   atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16
413                   ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16
414                   wait_feature: ENABLE or DISABLE
415                   common_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time
416                   attribute_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time
417                   io_space_timing: exmc_nand_pccard_timing_parameter_struct set the time
418     \param[out] none
419     \retval     none
420 */
exmc_pccard_init(exmc_pccard_parameter_struct * exmc_pccard_init_struct)421 void exmc_pccard_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct)
422 {
423     /* configure the EXMC bank3 PC card control register */
424     EXMC_NPCTL3 = (uint32_t)(exmc_pccard_init_struct->wait_feature << NPCTL_NDWTEN_OFFSET) |
425                              EXMC_NAND_DATABUS_WIDTH_16B |
426                              exmc_pccard_init_struct->ctr_latency |
427                              exmc_pccard_init_struct->atr_latency ;
428 
429     /* configure the EXMC bank3 PC card common space timing configuration register */
430     EXMC_NPCTCFG3 = (uint32_t)((exmc_pccard_init_struct->common_space_timing->setuptime - 1U)& EXMC_NPCTCFG_COMSET ) |
431                               (((exmc_pccard_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) & EXMC_NPCTCFG_COMWAIT ) |
432                               ((exmc_pccard_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET) & EXMC_NPCTCFG_COMHLD ) |
433                               (((exmc_pccard_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET) & EXMC_NPCTCFG_COMHIZ );
434 
435     /* configure the EXMC bank3 PC card attribute space timing configuration register */
436     EXMC_NPATCFG3 = (uint32_t)((exmc_pccard_init_struct->attribute_space_timing->setuptime - 1U) & EXMC_NPATCFG_ATTSET ) |
437                               (((exmc_pccard_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_ATTWAIT_OFFSET) & EXMC_NPATCFG_ATTWAIT ) |
438                               ((exmc_pccard_init_struct->attribute_space_timing->holdtime << NPATCFG_ATTHLD_OFFSET) & EXMC_NPATCFG_ATTHLD )|
439                               (((exmc_pccard_init_struct->attribute_space_timing->databus_hiztime -1U) << NPATCFG_ATTHIZ_OFFSET) & EXMC_NPATCFG_ATTHIZ );
440 
441     /* configure the EXMC bank3 PC card io space timing configuration register */
442     EXMC_PIOTCFG3 = (uint32_t)((exmc_pccard_init_struct->io_space_timing->setuptime - 1U) & EXMC_PIOTCFG3_IOSET ) |
443                               (((exmc_pccard_init_struct->io_space_timing->waittime - 1U) << PIOTCFG_IOWAIT_OFFSET) & EXMC_PIOTCFG3_IOWAIT ) |
444                               ((exmc_pccard_init_struct->io_space_timing->holdtime << PIOTCFG_IOHLD_OFFSET) & EXMC_PIOTCFG3_IOHLD )|
445                               ((exmc_pccard_init_struct->io_space_timing->databus_hiztime << PIOTCFG_IOHIZ_OFFSET) & EXMC_PIOTCFG3_IOHIZ );
446 }
447 
448 /*!
449     \brief      enable PC Card Bank
450     \param[in]  none
451     \param[out] none
452     \retval     none
453 */
exmc_pccard_enable(void)454 void exmc_pccard_enable(void)
455 {
456     EXMC_NPCTL3 |= EXMC_NPCTL_NDBKEN;
457 }
458 
459 /*!
460     \brief      disable PC Card Bank
461     \param[in]  none
462     \param[out] none
463     \retval     none
464 */
exmc_pccard_disable(void)465 void exmc_pccard_disable(void)
466 {
467    EXMC_NPCTL3 &= (~EXMC_NPCTL_NDBKEN);
468 }
469 
470 /*!
471     \brief      configure CRAM page size
472     \param[in]  exmc_norsram_region: specifie the region of NOR/PSRAM bank
473                 only one parameter can be selected which is shown as below:
474       \arg        EXMC_BANK0_NORSRAM_REGIONx(x=0..3)
475     \param[in]  page_size: CRAM page size
476                 only one parameter can be selected which is shown as below:
477       \arg        EXMC_CRAM_AUTO_SPLIT: the clock is generated only during synchronous access
478       \arg        EXMC_CRAM_PAGE_SIZE_128_BYTES: page size is 128 bytes
479       \arg        EXMC_CRAM_PAGE_SIZE_256_BYTES: page size is 256 bytes
480       \arg        EXMC_CRAM_PAGE_SIZE_512_BYTES: page size is 512 bytes
481       \arg        EXMC_CRAM_PAGE_SIZE_1024_BYTES: page size is 1024 bytes
482     \param[out] none
483     \retval     none
484 */
exmc_norsram_page_size_config(uint32_t exmc_norsram_region,uint32_t page_size)485 void exmc_norsram_page_size_config(uint32_t exmc_norsram_region, uint32_t page_size)
486 {
487     /* reset the bits */
488     EXMC_SNCTL(exmc_norsram_region) &= ~EXMC_SNCTL_CPS;
489 
490     /* set the CPS bits */
491     EXMC_SNCTL(exmc_norsram_region) |= page_size;
492 }
493 
494 /*!
495     \brief      enable or disable the EXMC NAND ECC function
496     \param[in]  exmc_nand_bank: specifie the NAND bank
497                 only one parameter can be selected which is shown as below:
498       \arg        EXMC_BANKx_NAND(x=1,2)
499     \param[in]  newvalue: ENABLE or DISABLE
500     \param[out] none
501     \retval     none
502 */
exmc_nand_ecc_config(uint32_t exmc_nand_bank,ControlStatus newvalue)503 void exmc_nand_ecc_config(uint32_t exmc_nand_bank, ControlStatus newvalue)
504 {
505     if (ENABLE == newvalue){
506         /* enable the selected NAND bank ECC function */
507         EXMC_NPCTL(exmc_nand_bank) |= EXMC_NPCTL_ECCEN;
508     }else{
509         /* disable the selected NAND bank ECC function */
510         EXMC_NPCTL(exmc_nand_bank) &= (~EXMC_NPCTL_ECCEN);
511     }
512 }
513 
514 /*!
515     \brief      get the EXMC ECC value
516     \param[in]  exmc_nand_bank: specifie the NAND bank
517                 only one parameter can be selected which is shown as below:
518       \arg        EXMC_BANKx_NAND(x=1,2)
519     \param[out] none
520     \retval     the error correction code(ECC) value
521 */
exmc_ecc_get(uint32_t exmc_nand_bank)522 uint32_t exmc_ecc_get(uint32_t exmc_nand_bank)
523 {
524     return (EXMC_NECC(exmc_nand_bank));
525 }
526 
527 /*!
528     \brief      enable EXMC interrupt
529     \param[in]  exmc_bank: specifies the NAND bank,PC card bank
530                 only one parameter can be selected which is shown as below:
531       \arg        EXMC_BANK1_NAND: the NAND bank1
532       \arg        EXMC_BANK2_NAND: the NAND bank2
533       \arg        EXMC_BANK3_PCCARD: the PC card bank
534     \param[in]  interrupt: EXMC interrupt flag
535                 only one parameter can be selected which are shown as below:
536       \arg        EXMC_NAND_PCCARD_INT_FLAG_RISE: rising edge interrupt and flag
537       \arg        EXMC_NAND_PCCARD_INT_FLAG_LEVEL: high-level interrupt and flag
538       \arg        EXMC_NAND_PCCARD_INT_FLAG_FALL: falling edge interrupt and flag
539     \param[out] none
540     \retval     none
541 */
exmc_interrupt_enable(uint32_t exmc_bank,uint32_t interrupt)542 void exmc_interrupt_enable(uint32_t exmc_bank,uint32_t interrupt)
543 {
544     /* NAND bank1,bank2 or PC card bank3 */
545     EXMC_NPINTEN(exmc_bank) |= interrupt;
546 }
547 
548 /*!
549     \brief      disable EXMC interrupt
550     \param[in]  exmc_bank: specifies the NAND bank , PC card bank
551                 only one parameter can be selected which is shown as below:
552       \arg        EXMC_BANK1_NAND: the NAND bank1
553       \arg        EXMC_BANK2_NAND: the NAND bank2
554       \arg        EXMC_BANK3_PCCARD: the PC card bank
555     \param[in]  interrupt: EXMC interrupt flag
556                 only one parameter can be selected which are shown as below:
557       \arg        EXMC_NAND_PCCARD_INT_FLAG_RISE: rising edge interrupt and flag
558       \arg        EXMC_NAND_PCCARD_INT_FLAG_LEVEL: high-level interrupt and flag
559       \arg        EXMC_NAND_PCCARD_INT_FLAG_FALL: falling edge interrupt and flag
560     \param[out] none
561     \retval     none
562 */
exmc_interrupt_disable(uint32_t exmc_bank,uint32_t interrupt)563 void exmc_interrupt_disable(uint32_t exmc_bank,uint32_t interrupt)
564 {
565     /* NAND bank1,bank2 or PC card bank3 */
566     EXMC_NPINTEN(exmc_bank) &= (~interrupt);
567 }
568 
569 /*!
570     \brief      get EXMC flag status
571     \param[in]  exmc_bank: specifies the NAND bank , PC card bank
572                 only one parameter can be selected which is shown as below:
573       \arg        EXMC_BANK1_NAND: the NAND bank1
574       \arg        EXMC_BANK2_NAND: the NAND bank2
575       \arg        EXMC_BANK3_PCCARD: the PC Card bank
576     \param[in]  flag: EXMC status and flag
577                 only one parameter can be selected which are shown as below:
578       \arg        EXMC_NAND_PCCARD_FLAG_RISE: interrupt rising edge status
579       \arg        EXMC_NAND_PCCARD_FLAG_LEVEL: interrupt high-level status
580       \arg        EXMC_NAND_PCCARD_FLAG_FALL: interrupt falling edge status
581       \arg        EXMC_NAND_PCCARD_FLAG_FIFOE: FIFO empty flag
582     \param[out] none
583     \retval     FlagStatus: SET or RESET
584 */
exmc_flag_get(uint32_t exmc_bank,uint32_t flag)585 FlagStatus exmc_flag_get(uint32_t exmc_bank,uint32_t flag)
586 {
587     uint32_t status = 0x00000000U;
588 
589     /* NAND bank1,bank2 or PC card bank3 */
590     status = EXMC_NPINTEN(exmc_bank);
591 
592     if ((status & flag) != (uint32_t)flag ){
593         /* flag is reset */
594         return RESET;
595     }else{
596         /* flag is set */
597         return SET;
598     }
599 }
600 
601 /*!
602     \brief      clear EXMC flag status
603     \param[in]  exmc_bank: specifie the NAND bank , PCCARD bank
604                 only one parameter can be selected which is shown as below:
605       \arg        EXMC_BANK1_NAND: the NAND bank1
606       \arg        EXMC_BANK2_NAND: the NAND bank2
607       \arg        EXMC_BANK3_PCCARD: the PC card bank
608     \param[in]  flag: EXMC status and flag
609                 only one parameter can be selected which are shown as below:
610       \arg        EXMC_NAND_PCCARD_FLAG_RISE: interrupt rising edge status
611       \arg        EXMC_NAND_PCCARD_FLAG_LEVEL: interrupt high-level status
612       \arg        EXMC_NAND_PCCARD_FLAG_FALL: interrupt falling edge status
613       \arg        EXMC_NAND_PCCARD_FLAG_FIFOE: FIFO empty flag
614     \param[out] none
615     \retval     none
616 */
exmc_flag_clear(uint32_t exmc_bank,uint32_t flag)617 void exmc_flag_clear(uint32_t exmc_bank,uint32_t flag)
618 {
619     /* NAND bank1,bank2 or PC card bank3 */
620     EXMC_NPINTEN(exmc_bank) &= (~flag);
621 }
622 
623 /*!
624     \brief      get EXMC interrupt flag
625     \param[in]  exmc_bank: specifies the NAND bank , PC card bank
626                 only one parameter can be selected which is shown as below:
627       \arg        EXMC_BANK1_NAND: the NAND bank1
628       \arg        EXMC_BANK2_NAND: the NAND bank2
629       \arg        EXMC_BANK3_PCCARD: the PC card bank
630     \param[in]  interrupt: EXMC interrupt flag
631                 only one parameter can be selected which are shown as below:
632       \arg        EXMC_NAND_PCCARD_INT_FLAG_RISE: rising edge interrupt and flag
633       \arg        EXMC_NAND_PCCARD_INT_FLAG_LEVEL: high-level interrupt and flag
634       \arg        EXMC_NAND_PCCARD_INT_FLAG_FALL: falling edge interrupt and flag
635     \param[out] none
636     \retval     FlagStatus: SET or RESET
637 */
exmc_interrupt_flag_get(uint32_t exmc_bank,uint32_t interrupt)638 FlagStatus exmc_interrupt_flag_get(uint32_t exmc_bank,uint32_t interrupt)
639 {
640     uint32_t status = 0x00000000U,interrupt_enable = 0x00000000U,interrupt_state = 0x00000000U;
641 
642     /* NAND bank1,bank2 or PC card bank3 */
643     status = EXMC_NPINTEN(exmc_bank);
644     interrupt_state = (status & (interrupt >> INTEN_INTS_OFFSET));
645 
646     interrupt_enable = (status & interrupt);
647 
648     if ((interrupt_enable) && (interrupt_state)){
649         /* interrupt flag is set */
650         return SET;
651     }else{
652         /* interrupt flag is reset */
653         return RESET;
654     }
655 }
656 
657 /*!
658     \brief      clear EXMC interrupt flag
659     \param[in]  exmc_bank: specifies the NAND bank , PC card bank
660                 only one parameter can be selected which is shown as below:
661       \arg        EXMC_BANK1_NAND: the NAND bank1
662       \arg        EXMC_BANK2_NAND: the NAND bank2
663       \arg        EXMC_BANK3_PCCARD: the PC card bank
664     \param[in]  interrupt: EXMC interrupt flag
665                 only one parameter can be selected which are shown as below:
666       \arg        EXMC_NAND_PCCARD_INT_FLAG_RISE: rising edge interrupt and flag
667       \arg        EXMC_NAND_PCCARD_INT_FLAG_LEVEL: high-level interrupt and flag
668       \arg        EXMC_NAND_PCCARD_INT_FLAG_FALL: falling edge interrupt and flag
669     \param[out] none
670     \retval     none
671 */
exmc_interrupt_flag_clear(uint32_t exmc_bank,uint32_t interrupt)672 void exmc_interrupt_flag_clear(uint32_t exmc_bank,uint32_t interrupt)
673 {
674     /* NAND bank1,bank2 or PC card bank3 */
675     EXMC_NPINTEN(exmc_bank) &= ~(interrupt >> INTEN_INTS_OFFSET);
676 }
677