1 /*!
2     \file    gd32e50x_exmc.c
3     \brief   EXMC driver
4 
5     \version 2020-03-10, V1.0.0, firmware for GD32E50x
6     \version 2020-08-26, V1.1.0, firmware for GD32E50x
7     \version 2021-03-23, V1.2.0, firmware for GD32E50x
8 */
9 
10 /*
11     Copyright (c) 2021, 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 "gd32e50x_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                     asyn_access_mode: EXMC_ACCESS_MODE_A,EXMC_ACCESS_MODE_B,EXMC_ACCESS_MODE_C,EXMC_ACCESS_MODE_D
170                     syn_data_latency: EXMC_DATALAT_n_CLK,(n=2,..,17)
171                     syn_clk_division: EXMC_SYN_CLOCK_RATIO_DISABLE, EXMC_SYN_CLOCK_RATIO_n_CLK,(n=2,..,16)
172                     bus_latency: 1,..,16
173                     asyn_data_setuptime: 2,..,256
174                     asyn_address_holdtime: 2,..,16
175                     asyn_address_setuptime: 1,..,16
176                   write_timing: struct exmc_norsram_timing_parameter_struct set the time
177                     asyn_access_mode: EXMC_ACCESS_MODE_A,EXMC_ACCESS_MODE_B,EXMC_ACCESS_MODE_C,EXMC_ACCESS_MODE_D
178                     syn_data_latency: EXMC_DATALAT_n_CLK,(n=2,..,17)
179                     syn_clk_division: EXMC_SYN_CLOCK_RATIO_DISABLE, EXMC_SYN_CLOCK_RATIO_n_CLK,(n=2,..,16)
180                     bus_latency: 1,..,16
181                     asyn_data_setuptime: 2,..,256
182                     asyn_address_holdtime: 2,..,16
183                     asyn_address_setuptime: 1,..,16
184     \param[out] none
185     \retval     none
186 */
exmc_norsram_init(exmc_norsram_parameter_struct * exmc_norsram_init_struct)187 void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct)
188 {
189     uint32_t snctl = 0x00000000U,sntcfg = 0x00000000U,snwtcfg = 0x00000000U;
190 
191     /* get the register value */
192     snctl = EXMC_SNCTL(exmc_norsram_init_struct->norsram_region);
193 
194     /* clear relative bits */
195     snctl &= ((uint32_t)~(EXMC_SNCTL_NRMUX | EXMC_SNCTL_NRTP | EXMC_SNCTL_NRW | EXMC_SNCTL_SBRSTEN |
196                           EXMC_SNCTL_NREN | EXMC_SNCTL_NRWTPOL | EXMC_SNCTL_WRAPEN | EXMC_SNCTL_NRWTCFG |
197                           EXMC_SNCTL_WREN | EXMC_SNCTL_NRWTEN | EXMC_SNCTL_EXMODEN | EXMC_SNCTL_ASYNCWAIT |
198                           EXMC_SNCTL_SYNCWR ));
199 
200     snctl |= (uint32_t)(exmc_norsram_init_struct->address_data_mux << SNCTL_NRMUX_OFFSET) |
201                         exmc_norsram_init_struct->memory_type |
202                         exmc_norsram_init_struct->databus_width |
203                        (exmc_norsram_init_struct->burst_mode << SNCTL_SBRSTEN_OFFSET) |
204                         exmc_norsram_init_struct->nwait_polarity |
205                        (exmc_norsram_init_struct->wrap_burst_mode << SNCTL_WRAPEN_OFFSET) |
206                         exmc_norsram_init_struct->nwait_config |
207                        (exmc_norsram_init_struct->memory_write << SNCTL_WREN_OFFSET) |
208                        (exmc_norsram_init_struct->nwait_signal << SNCTL_NRWTEN_OFFSET) |
209                        (exmc_norsram_init_struct->extended_mode << SNCTL_EXMODEN_OFFSET) |
210                        (exmc_norsram_init_struct->asyn_wait << SNCTL_ASYNCWAIT_OFFSET) |
211                         exmc_norsram_init_struct->write_mode;
212 
213     sntcfg = (uint32_t)((exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime - 1U ) & EXMC_SNTCFG_ASET )|
214                        (((exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime - 1U ) << SNTCFG_AHLD_OFFSET ) & EXMC_SNTCFG_AHLD ) |
215                        (((exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime - 1U ) << SNTCFG_DSET_OFFSET ) & EXMC_SNTCFG_DSET ) |
216                        (((exmc_norsram_init_struct->read_write_timing->bus_latency - 1U ) << SNTCFG_BUSLAT_OFFSET ) & EXMC_SNTCFG_BUSLAT )|
217                        exmc_norsram_init_struct->read_write_timing->syn_clk_division |
218                        exmc_norsram_init_struct->read_write_timing->syn_data_latency |
219                        exmc_norsram_init_struct->read_write_timing->asyn_access_mode;
220 
221     /* nor flash access enable */
222     if(EXMC_MEMORY_TYPE_NOR == exmc_norsram_init_struct->memory_type){
223         snctl |= (uint32_t)EXMC_SNCTL_NREN;
224     }
225 
226     /* extended mode configure */
227     if(ENABLE == exmc_norsram_init_struct->extended_mode){
228         snwtcfg = (uint32_t)((exmc_norsram_init_struct->write_timing->asyn_address_setuptime - 1U) & EXMC_SNWTCFG_WASET ) |
229                            (((exmc_norsram_init_struct->write_timing->asyn_address_holdtime -1U ) << SNWTCFG_WAHLD_OFFSET ) & EXMC_SNWTCFG_WAHLD )|
230                            (((exmc_norsram_init_struct->write_timing->asyn_data_setuptime -1U ) << SNWTCFG_WDSET_OFFSET ) & EXMC_SNWTCFG_WDSET )|
231                            (((exmc_norsram_init_struct->write_timing->bus_latency - 1U ) << SNWTCFG_WBUSLAT_OFFSET ) & EXMC_SNWTCFG_WBUSLAT ) |
232                             exmc_norsram_init_struct->write_timing->asyn_access_mode;
233     }else{
234         snwtcfg = BANK0_SNWTCFG_RESET;
235     }
236 
237     /* configure the registers */
238     EXMC_SNCTL(exmc_norsram_init_struct->norsram_region) = snctl;
239     EXMC_SNTCFG(exmc_norsram_init_struct->norsram_region) = sntcfg;
240     EXMC_SNWTCFG(exmc_norsram_init_struct->norsram_region) = snwtcfg;
241 }
242 
243 /*!
244     \brief      enable EXMC NOR/PSRAM bank region
245     \param[in]  exmc_norsram_region: specifie the region of NOR/PSRAM bank
246                 only one parameter can be selected which is shown as below:
247       \arg        EXMC_BANK0_NORSRAM_REGIONx(x=0..3)
248     \param[out] none
249     \retval     none
250 */
exmc_norsram_enable(uint32_t exmc_norsram_region)251 void exmc_norsram_enable(uint32_t exmc_norsram_region)
252 {
253     EXMC_SNCTL(exmc_norsram_region) |= (uint32_t)EXMC_SNCTL_NRBKEN;
254 }
255 
256 /*!
257     \brief      disable EXMC NOR/PSRAM bank region
258     \param[in]  exmc_norsram_region: specifie the region of NOR/PSRAM Bank
259                 only one parameter can be selected which is shown as below:
260       \arg        EXMC_BANK0_NORSRAM_REGIONx(x=0..3)
261     \param[out] none
262     \retval     none
263 */
exmc_norsram_disable(uint32_t exmc_norsram_region)264 void exmc_norsram_disable(uint32_t exmc_norsram_region)
265 {
266     EXMC_SNCTL(exmc_norsram_region) &= ~(uint32_t)EXMC_SNCTL_NRBKEN;
267 }
268 
269 /*!
270     \brief      configure CRAM page size
271     \param[in]  exmc_norsram_region: specifie the region of NOR/PSRAM bank
272                 only one parameter can be selected which is shown as below:
273       \arg        EXMC_BANK0_NORSRAM_REGIONx(x=0..3)
274     \param[in]  page_size: CRAM page size
275                 only one parameter can be selected which is shown as below:
276       \arg        EXMC_CRAM_AUTO_SPLIT: the clock is generated only during synchronous access
277       \arg        EXMC_CRAM_PAGE_SIZE_128_BYTES: page size is 128 bytes
278       \arg        EXMC_CRAM_PAGE_SIZE_256_BYTES: page size is 256 bytes
279       \arg        EXMC_CRAM_PAGE_SIZE_512_BYTES: page size is 512 bytes
280       \arg        EXMC_CRAM_PAGE_SIZE_1024_BYTES: page size is 1024 bytes
281     \param[out] none
282     \retval     none
283 */
exmc_norsram_page_size_config(uint32_t exmc_norsram_region,uint32_t page_size)284 void exmc_norsram_page_size_config(uint32_t exmc_norsram_region, uint32_t page_size)
285 {
286     /* reset the bits */
287     EXMC_SNCTL(exmc_norsram_region) &= ~EXMC_SNCTL_CPS;
288 
289     /* set the CPS bits */
290     EXMC_SNCTL(exmc_norsram_region) |= page_size;
291 }
292 
293 /*!
294     \brief      deinitialize EXMC NAND bank
295     \param[in]  exmc_nand_bank: select the bank of NAND
296                 only one parameter can be selected which is shown as below:
297       \arg        EXMC_BANKx_NAND(x=1..2)
298     \param[out] none
299     \retval     none
300 */
exmc_nand_deinit(uint32_t exmc_nand_bank)301 void exmc_nand_deinit(uint32_t exmc_nand_bank)
302 {
303     /* EXMC_BANK1_NAND or EXMC_BANK2_NAND */
304     EXMC_NPCTL(exmc_nand_bank) = BANK1_2_NPCTL_RESET;
305     EXMC_NPINTEN(exmc_nand_bank) = BANK1_2_NPINTEN_RESET;
306     EXMC_NPCTCFG(exmc_nand_bank) = BANK1_2_NPCTCFG_RESET;
307     EXMC_NPATCFG(exmc_nand_bank) = BANK1_2_NPATCFG_RESET;
308 }
309 
310 /*!
311     \brief      initialize exmc_nand_parameter_struct with the default values
312     \param[in]  none
313     \param[out] the initialized struct exmc_nand_parameter_struct pointer
314     \retval     none
315 */
exmc_nand_struct_para_init(exmc_nand_parameter_struct * exmc_nand_init_struct)316 void exmc_nand_struct_para_init(exmc_nand_parameter_struct* exmc_nand_init_struct)
317 {
318     /* configure the structure with default values */
319     exmc_nand_init_struct->nand_bank = EXMC_BANK1_NAND;
320     exmc_nand_init_struct->wait_feature = DISABLE;
321     exmc_nand_init_struct->databus_width = EXMC_NAND_DATABUS_WIDTH_8B;
322     exmc_nand_init_struct->ecc_logic = DISABLE;
323     exmc_nand_init_struct->ecc_size = EXMC_ECC_SIZE_256BYTES;
324     exmc_nand_init_struct->ctr_latency = 0x0U;
325     exmc_nand_init_struct->atr_latency = 0x0U;
326     exmc_nand_init_struct->common_space_timing->setuptime = 0xFCU;
327     exmc_nand_init_struct->common_space_timing->waittime = 0xFCU;
328     exmc_nand_init_struct->common_space_timing->holdtime = 0xFCU;
329     exmc_nand_init_struct->common_space_timing->databus_hiztime = 0xFCU;
330     exmc_nand_init_struct->attribute_space_timing->setuptime = 0xFCU;
331     exmc_nand_init_struct->attribute_space_timing->waittime = 0xFCU;
332     exmc_nand_init_struct->attribute_space_timing->holdtime = 0xFCU;
333     exmc_nand_init_struct->attribute_space_timing->databus_hiztime = 0xFCU;
334 }
335 
336 /*!
337     \brief      initialize EXMC NAND bank
338     \param[in]  exmc_nand_parameter_struct: configure the EXMC NAND parameter
339                   nand_bank: EXMC_BANK1_NAND,EXMC_BANK2_NAND
340                   ecc_size: EXMC_ECC_SIZE_xBYTES,x=256,512,1024,2048,4096
341                   atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16
342                   ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16
343                   ecc_logic: ENABLE or DISABLE
344                   databus_width: EXMC_NAND_DATABUS_WIDTH_8B,EXMC_NAND_DATABUS_WIDTH_16B
345                   wait_feature: ENABLE or DISABLE
346                   common_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time
347                     databus_hiztime: 1,..,255
348                     holdtime: 1,..,254
349                     waittime: 2,..,255
350                     setuptime: 1,..,255
351                   attribute_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time
352                     databus_hiztime: 1,..,255
353                     holdtime: 1,..,254
354                     waittime: 2,..,255
355                     setuptime: 1,..,255
356     \param[out] none
357     \retval     none
358 */
exmc_nand_init(exmc_nand_parameter_struct * exmc_nand_init_struct)359 void exmc_nand_init(exmc_nand_parameter_struct* exmc_nand_init_struct)
360 {
361     uint32_t npctl = 0x00000000U, npctcfg = 0x00000000U, npatcfg = 0x00000000U;
362 
363     npctl = (uint32_t)(exmc_nand_init_struct->wait_feature << NPCTL_NDWTEN_OFFSET)|
364                        EXMC_NPCTL_NDTP |
365                        exmc_nand_init_struct->databus_width |
366                       (exmc_nand_init_struct->ecc_logic << NPCTL_ECCEN_OFFSET)|
367                        exmc_nand_init_struct->ecc_size |
368                        exmc_nand_init_struct->ctr_latency |
369                        exmc_nand_init_struct->atr_latency;
370 
371     npctcfg = (uint32_t)((exmc_nand_init_struct->common_space_timing->setuptime - 1U) & EXMC_NPCTCFG_COMSET ) |
372                         (((exmc_nand_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) & EXMC_NPCTCFG_COMWAIT ) |
373                         ((exmc_nand_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET) & EXMC_NPCTCFG_COMHLD ) |
374                         (((exmc_nand_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET) & EXMC_NPCTCFG_COMHIZ );
375 
376     npatcfg = (uint32_t)((exmc_nand_init_struct->attribute_space_timing->setuptime - 1U) & EXMC_NPATCFG_ATTSET ) |
377                         (((exmc_nand_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_ATTWAIT_OFFSET) & EXMC_NPATCFG_ATTWAIT ) |
378                         ((exmc_nand_init_struct->attribute_space_timing->holdtime << NPATCFG_ATTHLD_OFFSET) & EXMC_NPATCFG_ATTHLD ) |
379                         (((exmc_nand_init_struct->attribute_space_timing->databus_hiztime -1U) << NPATCFG_ATTHIZ_OFFSET) & EXMC_NPATCFG_ATTHIZ );
380 
381     /* EXMC_BANK1_NAND or EXMC_BANK2_NAND initialize */
382     EXMC_NPCTL(exmc_nand_init_struct->nand_bank) = npctl;
383     EXMC_NPCTCFG(exmc_nand_init_struct->nand_bank) = npctcfg;
384     EXMC_NPATCFG(exmc_nand_init_struct->nand_bank) = npatcfg;
385 }
386 
387 /*!
388     \brief      enable NAND bank
389     \param[in]  exmc_nand_bank: specifie the NAND bank
390                 only one parameter can be selected which is shown as below:
391       \arg        EXMC_BANKx_NAND(x=1,2)
392     \param[out] none
393     \retval     none
394 */
exmc_nand_enable(uint32_t exmc_nand_bank)395 void exmc_nand_enable(uint32_t exmc_nand_bank)
396 {
397     EXMC_NPCTL(exmc_nand_bank) |= EXMC_NPCTL_NDBKEN;
398 }
399 
400 /*!
401     \brief      disable NAND bank
402     \param[in]  exmc_nand_bank: specifie the NAND bank
403                 only one parameter can be selected which is shown as below:
404       \arg        EXMC_BANKx_NAND(x=1,2)
405     \param[out] none
406     \retval     none
407 */
exmc_nand_disable(uint32_t exmc_nand_bank)408 void exmc_nand_disable(uint32_t exmc_nand_bank)
409 {
410     EXMC_NPCTL(exmc_nand_bank) &= (~EXMC_NPCTL_NDBKEN);
411 }
412 
413 /*!
414     \brief      enable or disable the EXMC NAND ECC function
415     \param[in]  exmc_nand_bank: specifie the NAND bank
416                 only one parameter can be selected which is shown as below:
417       \arg        EXMC_BANKx_NAND(x=1,2)
418     \param[in]  newvalue: ENABLE or DISABLE
419     \param[out] none
420     \retval     none
421 */
exmc_nand_ecc_config(uint32_t exmc_nand_bank,ControlStatus newvalue)422 void exmc_nand_ecc_config(uint32_t exmc_nand_bank, ControlStatus newvalue)
423 {
424     if (ENABLE == newvalue){
425         /* enable the selected NAND bank ECC function */
426         EXMC_NPCTL(exmc_nand_bank) |= EXMC_NPCTL_ECCEN;
427     }else{
428         /* disable the selected NAND bank ECC function */
429         EXMC_NPCTL(exmc_nand_bank) &= (~EXMC_NPCTL_ECCEN);
430     }
431 }
432 
433 /*!
434     \brief      get the EXMC ECC value
435     \param[in]  exmc_nand_bank: specifie the NAND bank
436                 only one parameter can be selected which is shown as below:
437       \arg        EXMC_BANKx_NAND(x=1,2)
438     \param[out] none
439     \retval     the error correction code(ECC) value
440 */
exmc_ecc_get(uint32_t exmc_nand_bank)441 uint32_t exmc_ecc_get(uint32_t exmc_nand_bank)
442 {
443     return (EXMC_NECC(exmc_nand_bank));
444 }
445 
446 /*!
447     \brief      deinitialize EXMC PC card bank
448     \param[in]  none
449     \param[out] none
450     \retval     none
451 */
exmc_pccard_deinit(void)452 void exmc_pccard_deinit(void)
453 {
454     /* EXMC_BANK3_PCCARD */
455     EXMC_NPCTL3 = BANK3_NPCTL_RESET;
456     EXMC_NPINTEN3 = BANK3_NPINTEN_RESET;
457     EXMC_NPCTCFG3 = BANK3_NPCTCFG_RESET;
458     EXMC_NPATCFG3 = BANK3_NPATCFG_RESET;
459     EXMC_PIOTCFG3 = BANK3_PIOTCFG3_RESET;
460 }
461 
462 /*!
463     \brief      initialize exmc_pccard_parameter_struct parameter with the default values
464     \param[in]  none
465     \param[out] the initialized struct exmc_pccard_parameter_struct pointer
466     \retval     none
467 */
exmc_pccard_struct_para_init(exmc_pccard_parameter_struct * exmc_pccard_init_struct)468 void exmc_pccard_struct_para_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct)
469 {
470     /* configure the structure with default values */
471     exmc_pccard_init_struct->wait_feature = DISABLE;
472     exmc_pccard_init_struct->ctr_latency = 0x0U;
473     exmc_pccard_init_struct->atr_latency = 0x0U;
474     exmc_pccard_init_struct->common_space_timing->setuptime = 0xFCU;
475     exmc_pccard_init_struct->common_space_timing->waittime = 0xFCU;
476     exmc_pccard_init_struct->common_space_timing->holdtime = 0xFCU;
477     exmc_pccard_init_struct->common_space_timing->databus_hiztime = 0xFCU;
478     exmc_pccard_init_struct->attribute_space_timing->setuptime = 0xFCU;
479     exmc_pccard_init_struct->attribute_space_timing->waittime = 0xFCU;
480     exmc_pccard_init_struct->attribute_space_timing->holdtime = 0xFCU;
481     exmc_pccard_init_struct->attribute_space_timing->databus_hiztime = 0xFCU;
482     exmc_pccard_init_struct->io_space_timing->setuptime = 0xFCU;
483     exmc_pccard_init_struct->io_space_timing->waittime = 0xFCU;
484     exmc_pccard_init_struct->io_space_timing->holdtime = 0xFCU;
485     exmc_pccard_init_struct->io_space_timing->databus_hiztime = 0xFCU;
486 }
487 
488 /*!
489     \brief      initialize EXMC PC card bank
490     \param[in]  exmc_pccard_parameter_struct: configure the EXMC NAND parameter
491                   atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16
492                   ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16
493                   wait_feature: ENABLE or DISABLE
494                   common_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time
495                     databus_hiztime: 1,..,255
496                     holdtime: 1,..,254
497                     waittime: 2,..,255
498                     setuptime: 1,..,255
499                   attribute_space_timing: struct exmc_nand_pccard_timing_parameter_struct set the time
500                     databus_hiztime: 1,..,255
501                     holdtime: 1,..,254
502                     waittime: 2,..,255
503                     setuptime: 1,..,255
504                   io_space_timing: exmc_nand_pccard_timing_parameter_struct set the time
505                     databus_hiztime: 0,..,255
506                     holdtime: 1,..,255
507                     waittime: 2,..,256
508                     setuptime: 1,..,256
509     \param[out] none
510     \retval     none
511 */
exmc_pccard_init(exmc_pccard_parameter_struct * exmc_pccard_init_struct)512 void exmc_pccard_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct)
513 {
514     /* configure the EXMC bank3 PC card control register */
515     EXMC_NPCTL3 = (uint32_t)(exmc_pccard_init_struct->wait_feature << NPCTL_NDWTEN_OFFSET) |
516                              EXMC_NAND_DATABUS_WIDTH_16B |
517                              exmc_pccard_init_struct->ctr_latency |
518                              exmc_pccard_init_struct->atr_latency ;
519 
520     /* configure the EXMC bank3 PC card common space timing configuration register */
521     EXMC_NPCTCFG3 = (uint32_t)((exmc_pccard_init_struct->common_space_timing->setuptime - 1U)& EXMC_NPCTCFG_COMSET ) |
522                               (((exmc_pccard_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) & EXMC_NPCTCFG_COMWAIT ) |
523                               ((exmc_pccard_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET) & EXMC_NPCTCFG_COMHLD ) |
524                               (((exmc_pccard_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET) & EXMC_NPCTCFG_COMHIZ );
525 
526     /* configure the EXMC bank3 PC card attribute space timing configuration register */
527     EXMC_NPATCFG3 = (uint32_t)((exmc_pccard_init_struct->attribute_space_timing->setuptime - 1U) & EXMC_NPATCFG_ATTSET ) |
528                               (((exmc_pccard_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_ATTWAIT_OFFSET) & EXMC_NPATCFG_ATTWAIT ) |
529                               ((exmc_pccard_init_struct->attribute_space_timing->holdtime << NPATCFG_ATTHLD_OFFSET) & EXMC_NPATCFG_ATTHLD )|
530                               (((exmc_pccard_init_struct->attribute_space_timing->databus_hiztime -1U) << NPATCFG_ATTHIZ_OFFSET) & EXMC_NPATCFG_ATTHIZ );
531 
532     /* configure the EXMC bank3 PC card io space timing configuration register */
533     EXMC_PIOTCFG3 = (uint32_t)((exmc_pccard_init_struct->io_space_timing->setuptime - 1U) & EXMC_PIOTCFG3_IOSET ) |
534                               (((exmc_pccard_init_struct->io_space_timing->waittime - 1U) << PIOTCFG_IOWAIT_OFFSET) & EXMC_PIOTCFG3_IOWAIT ) |
535                               ((exmc_pccard_init_struct->io_space_timing->holdtime << PIOTCFG_IOHLD_OFFSET) & EXMC_PIOTCFG3_IOHLD )|
536                               ((exmc_pccard_init_struct->io_space_timing->databus_hiztime << PIOTCFG_IOHIZ_OFFSET) & EXMC_PIOTCFG3_IOHIZ );
537 }
538 
539 /*!
540     \brief      enable PC Card Bank
541     \param[in]  none
542     \param[out] none
543     \retval     none
544 */
exmc_pccard_enable(void)545 void exmc_pccard_enable(void)
546 {
547     EXMC_NPCTL3 |= EXMC_NPCTL_NDBKEN;
548 }
549 
550 /*!
551     \brief      disable PC Card Bank
552     \param[in]  none
553     \param[out] none
554     \retval     none
555 */
exmc_pccard_disable(void)556 void exmc_pccard_disable(void)
557 {
558    EXMC_NPCTL3 &= (~EXMC_NPCTL_NDBKEN);
559 }
560 
561 /*!
562     \brief      enable EXMC interrupt
563     \param[in]  exmc_bank: specifies the NAND bank,PC card bank
564                 only one parameter can be selected which is shown as below:
565       \arg        EXMC_BANK1_NAND: the NAND bank1
566       \arg        EXMC_BANK2_NAND: the NAND bank2
567       \arg        EXMC_BANK3_PCCARD: the PC card bank
568     \param[in]  interrupt: EXMC interrupt flag
569                 only one parameter can be selected which are shown as below:
570       \arg        EXMC_NAND_PCCARD_INT_FLAG_RISE: rising edge interrupt and corresponding flag
571       \arg        EXMC_NAND_PCCARD_INT_FLAG_LEVEL: high-level interrupt and corresponding flag
572       \arg        EXMC_NAND_PCCARD_INT_FLAG_FALL: falling edge interrupt and corresponding flag
573     \param[out] none
574     \retval     none
575 */
exmc_interrupt_enable(uint32_t exmc_bank,uint32_t interrupt)576 void exmc_interrupt_enable(uint32_t exmc_bank,uint32_t interrupt)
577 {
578     /* NAND bank1,bank2 or PC card bank3 */
579     EXMC_NPINTEN(exmc_bank) |= interrupt;
580 }
581 
582 /*!
583     \brief      disable EXMC interrupt
584     \param[in]  exmc_bank: specifies the NAND bank , PC card bank
585                 only one parameter can be selected which is shown as below:
586       \arg        EXMC_BANK1_NAND: the NAND bank1
587       \arg        EXMC_BANK2_NAND: the NAND bank2
588       \arg        EXMC_BANK3_PCCARD: the PC card bank
589     \param[in]  interrupt: EXMC interrupt flag
590                 only one parameter can be selected which are shown as below:
591       \arg        EXMC_NAND_PCCARD_INT_FLAG_RISE: rising edge interrupt and corresponding flag
592       \arg        EXMC_NAND_PCCARD_INT_FLAG_LEVEL: high-level interrupt and corresponding flag
593       \arg        EXMC_NAND_PCCARD_INT_FLAG_FALL: falling edge interrupt and corresponding flag
594     \param[out] none
595     \retval     none
596 */
exmc_interrupt_disable(uint32_t exmc_bank,uint32_t interrupt)597 void exmc_interrupt_disable(uint32_t exmc_bank,uint32_t interrupt)
598 {
599     /* NAND bank1,bank2 or PC card bank3 */
600     EXMC_NPINTEN(exmc_bank) &= (~interrupt);
601 }
602 
603 /*!
604     \brief      get EXMC flag status
605     \param[in]  exmc_bank: specifies the NAND bank , PC card bank
606                 only one parameter can be selected which is shown as below:
607       \arg        EXMC_BANK1_NAND: the NAND bank1
608       \arg        EXMC_BANK2_NAND: the NAND bank2
609       \arg        EXMC_BANK3_PCCARD: the PC Card bank
610     \param[in]  flag: EXMC status and flag
611                 only one parameter can be selected which are shown as below:
612       \arg        EXMC_NAND_PCCARD_FLAG_RISE: interrupt rising edge status
613       \arg        EXMC_NAND_PCCARD_FLAG_LEVEL: interrupt high-level status
614       \arg        EXMC_NAND_PCCARD_FLAG_FALL: interrupt falling edge status
615       \arg        EXMC_NAND_PCCARD_FLAG_FIFOE: FIFO empty flag
616     \param[out] none
617     \retval     FlagStatus: SET or RESET
618 */
exmc_flag_get(uint32_t exmc_bank,uint32_t flag)619 FlagStatus exmc_flag_get(uint32_t exmc_bank,uint32_t flag)
620 {
621     uint32_t status = 0x00000000U;
622 
623     /* NAND bank1,bank2 or PC card bank3 */
624     status = EXMC_NPINTEN(exmc_bank);
625 
626     if ((status & flag) != (uint32_t)flag ){
627         /* flag is reset */
628         return RESET;
629     }else{
630         /* flag is set */
631         return SET;
632     }
633 }
634 
635 /*!
636     \brief      clear EXMC flag status
637     \param[in]  exmc_bank: specifie the NAND bank , PCCARD bank
638                 only one parameter can be selected which is shown as below:
639       \arg        EXMC_BANK1_NAND: the NAND bank1
640       \arg        EXMC_BANK2_NAND: the NAND bank2
641       \arg        EXMC_BANK3_PCCARD: the PC card bank
642     \param[in]  flag: EXMC status and flag
643                 only one parameter can be selected which are shown as below:
644       \arg        EXMC_NAND_PCCARD_FLAG_RISE: interrupt rising edge status
645       \arg        EXMC_NAND_PCCARD_FLAG_LEVEL: interrupt high-level status
646       \arg        EXMC_NAND_PCCARD_FLAG_FALL: interrupt falling edge status
647       \arg        EXMC_NAND_PCCARD_FLAG_FIFOE: FIFO empty flag
648     \param[out] none
649     \retval     none
650 */
exmc_flag_clear(uint32_t exmc_bank,uint32_t flag)651 void exmc_flag_clear(uint32_t exmc_bank,uint32_t flag)
652 {
653     /* NAND bank1,bank2 or PC card bank3 */
654     EXMC_NPINTEN(exmc_bank) &= (~flag);
655 }
656 
657 /*!
658     \brief      get 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 corresponding flag
667       \arg        EXMC_NAND_PCCARD_INT_FLAG_LEVEL: high-level interrupt and corresponding flag
668       \arg        EXMC_NAND_PCCARD_INT_FLAG_FALL: falling edge interrupt and corresponding flag
669     \param[out] none
670     \retval     FlagStatus: SET or RESET
671 */
exmc_interrupt_flag_get(uint32_t exmc_bank,uint32_t interrupt)672 FlagStatus exmc_interrupt_flag_get(uint32_t exmc_bank,uint32_t interrupt)
673 {
674     uint32_t status = 0x00000000U,interrupt_enable = 0x00000000U,interrupt_state = 0x00000000U;
675 
676     /* NAND bank1,bank2 or PC card bank3 */
677     status = EXMC_NPINTEN(exmc_bank);
678     interrupt_state = (status & (interrupt >> INTEN_INTS_OFFSET));
679 
680     interrupt_enable = (status & interrupt);
681 
682     if ((interrupt_enable) && (interrupt_state)){
683         /* interrupt flag is set */
684         return SET;
685     }else{
686         /* interrupt flag is reset */
687         return RESET;
688     }
689 }
690 
691 /*!
692     \brief      clear EXMC interrupt flag
693     \param[in]  exmc_bank: specifies the NAND bank , PC card bank
694                 only one parameter can be selected which is shown as below:
695       \arg        EXMC_BANK1_NAND: the NAND bank1
696       \arg        EXMC_BANK2_NAND: the NAND bank2
697       \arg        EXMC_BANK3_PCCARD: the PC card bank
698     \param[in]  interrupt: EXMC interrupt flag
699                 only one parameter can be selected which are shown as below:
700       \arg        EXMC_NAND_PCCARD_INT_FLAG_RISE: rising edge interrupt and corresponding flag
701       \arg        EXMC_NAND_PCCARD_INT_FLAG_LEVEL: high-level interrupt and corresponding flag
702       \arg        EXMC_NAND_PCCARD_INT_FLAG_FALL: falling edge interrupt and corresponding flag
703     \param[out] none
704     \retval     none
705 */
exmc_interrupt_flag_clear(uint32_t exmc_bank,uint32_t interrupt)706 void exmc_interrupt_flag_clear(uint32_t exmc_bank,uint32_t interrupt)
707 {
708     /* NAND bank1,bank2 or PC card bank3 */
709     EXMC_NPINTEN(exmc_bank) &= ~(interrupt >> INTEN_INTS_OFFSET);
710 }
711