1 /*!
2     \file    gd32e10x_exmc.c
3     \brief   EXMC driver
4 
5     \version 2017-12-26, V1.0.0, firmware for GD32E10x
6     \version 2020-09-30, V1.1.0, firmware for GD32E10x
7     \version 2020-12-31, V1.2.0, firmware for GD32E10x
8     \version 2022-06-30, V1.3.0, firmware for GD32E10x
9 */
10 
11 /*
12     Copyright (c) 2022, GigaDevice Semiconductor Inc.
13 
14     Redistribution and use in source and binary forms, with or without modification,
15 are permitted provided that the following conditions are met:
16 
17     1. Redistributions of source code must retain the above copyright notice, this
18        list of conditions and the following disclaimer.
19     2. Redistributions in binary form must reproduce the above copyright notice,
20        this list of conditions and the following disclaimer in the documentation
21        and/or other materials provided with the distribution.
22     3. Neither the name of the copyright holder nor the names of its contributors
23        may be used to endorse or promote products derived from this software without
24        specific prior written permission.
25 
26     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
30 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
35 OF SUCH DAMAGE.
36 */
37 
38 #include "gd32e10x_exmc.h"
39 
40 /* EXMC bank0 register reset value */
41 #define BANK0_SNCTL_RESET                 ((uint32_t)0x000030DBU)
42 #define BANK0_SNTCFG_RESET                ((uint32_t)0x0FFFFFFFU)
43 #define BANK0_SNWTCFG_RESET               ((uint32_t)0x0FFFFFFFU)
44 
45 /* EXMC register bit offset */
46 #define SNCTL_NRMUX_OFFSET                ((uint32_t)1U)
47 #define SNCTL_SBRSTEN_OFFSET              ((uint32_t)8U)
48 #define SNCTL_WRAPEN_OFFSET               ((uint32_t)10U)
49 #define SNCTL_WREN_OFFSET                 ((uint32_t)12U)
50 #define SNCTL_NRWTEN_OFFSET               ((uint32_t)13U)
51 #define SNCTL_EXMODEN_OFFSET              ((uint32_t)14U)
52 #define SNCTL_ASYNCWAIT_OFFSET            ((uint32_t)15U)
53 
54 #define SNTCFG_AHLD_OFFSET                ((uint32_t)4U)
55 #define SNTCFG_DSET_OFFSET                ((uint32_t)8U)
56 #define SNTCFG_BUSLAT_OFFSET              ((uint32_t)16U)
57 
58 #define SNWTCFG_WAHLD_OFFSET              ((uint32_t)4U)
59 #define SNWTCFG_WDSET_OFFSET              ((uint32_t)8U)
60 #define SNWTCFG_WBUSLAT_OFFSET            ((uint32_t)16U)
61 
62 /*!
63     \brief      deinitialize EXMC NOR/SRAM bank
64     \param[in]  none
65     \param[out] none
66     \retval     none
67 */
exmc_norsram_deinit(void)68 void exmc_norsram_deinit(void)
69 {
70     /* reset the registers */
71     EXMC_SNCTL = BANK0_SNCTL_RESET;
72 
73     EXMC_SNTCFG = BANK0_SNTCFG_RESET;
74     EXMC_SNWTCFG = BANK0_SNWTCFG_RESET;
75 }
76 
77 /*!
78     \brief      initialize the struct exmc_norsram_parameter_struct
79     \param[in]  none
80     \param[out] exmc_norsram_init_struct: the initialized struct exmc_norsram_parameter_struct pointer
81     \retval     none
82 */
exmc_norsram_struct_para_init(exmc_norsram_parameter_struct * exmc_norsram_init_struct)83 void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct)
84 {
85     /* configure the structure with default value */
86     exmc_norsram_init_struct->address_data_mux = ENABLE;
87     exmc_norsram_init_struct->memory_type = EXMC_MEMORY_TYPE_NOR;
88     exmc_norsram_init_struct->databus_width = EXMC_NOR_DATABUS_WIDTH_16B;
89     exmc_norsram_init_struct->burst_mode = DISABLE;
90     exmc_norsram_init_struct->nwait_polarity = EXMC_NWAIT_POLARITY_LOW;
91     exmc_norsram_init_struct->wrap_burst_mode = DISABLE;
92     exmc_norsram_init_struct->nwait_config = EXMC_NWAIT_CONFIG_BEFORE;
93     exmc_norsram_init_struct->memory_write = ENABLE;
94     exmc_norsram_init_struct->nwait_signal = ENABLE;
95     exmc_norsram_init_struct->extended_mode = DISABLE;
96     exmc_norsram_init_struct->asyn_wait = DISABLE;
97     exmc_norsram_init_struct->write_mode = EXMC_ASYN_WRITE;
98 
99     /* read/write timing configure */
100     exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime = 0xFU;
101     exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime = 0xFU;
102     exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime = 0xFFU;
103     exmc_norsram_init_struct->read_write_timing->bus_latency = 0xFU;
104     exmc_norsram_init_struct->read_write_timing->syn_clk_division = EXMC_SYN_CLOCK_RATIO_16_CLK;
105     exmc_norsram_init_struct->read_write_timing->syn_data_latency = EXMC_DATALAT_17_CLK;
106     exmc_norsram_init_struct->read_write_timing->asyn_access_mode = EXMC_ACCESS_MODE_A;
107 
108     /* write timing configure, when extended mode is used */
109     exmc_norsram_init_struct->write_timing->asyn_address_setuptime = 0xFU;
110     exmc_norsram_init_struct->write_timing->asyn_address_holdtime = 0xFU;
111     exmc_norsram_init_struct->write_timing->asyn_data_setuptime = 0xFFU;
112     exmc_norsram_init_struct->write_timing->bus_latency = 0xFU;
113     exmc_norsram_init_struct->write_timing->asyn_access_mode = EXMC_ACCESS_MODE_A;
114 }
115 
116 /*!
117     \brief      initialize EXMC NOR/SRAM bank
118     \param[in]  exmc_norsram_parameter_struct: configure the EXMC NOR/SRAM parameter
119                   write_mode: EXMC_ASYN_WRITE,EXMC_SYN_WRITE
120                   extended_mode: ENABLE or DISABLE
121                   asyn_wait: ENABLE or DISABLE
122                   nwait_signal: ENABLE or DISABLE
123                   memory_write: ENABLE or DISABLE
124                   nwait_config: EXMC_NWAIT_CONFIG_BEFORE,EXMC_NWAIT_CONFIG_DURING
125                   wrap_burst_mode: ENABLE or DISABLE
126                   nwait_polarity: EXMC_NWAIT_POLARITY_LOW,EXMC_NWAIT_POLARITY_HIGH
127                   burst_mode: ENABLE or DISABLE
128                   databus_width: EXMC_NOR_DATABUS_WIDTH_8B,EXMC_NOR_DATABUS_WIDTH_16B
129                   memory_type: EXMC_MEMORY_TYPE_SRAM,EXMC_MEMORY_TYPE_PSRAM,EXMC_MEMORY_TYPE_NOR
130                   address_data_mux: ENABLE or DISABLE
131                   read_write_timing: struct exmc_norsram_timing_parameter_struct set the time
132                   write_timing: struct exmc_norsram_timing_parameter_struct set the time
133     \param[out] none
134     \retval     none
135 */
exmc_norsram_init(exmc_norsram_parameter_struct * exmc_norsram_init_struct)136 void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct)
137 {
138     uint32_t snctl = 0x00000000U, sntcfg = 0x00000000U, snwtcfg = 0x00000000U;
139 
140     /* get the register value */
141     snctl = EXMC_SNCTL;
142 
143     /* clear relative bits */
144     snctl &= ((uint32_t)~(EXMC_SNCTL_NRMUX | EXMC_SNCTL_NRTP | EXMC_SNCTL_NRW | EXMC_SNCTL_SBRSTEN |
145                           EXMC_SNCTL_NREN | EXMC_SNCTL_NRWTPOL | EXMC_SNCTL_WRAPEN | EXMC_SNCTL_NRWTCFG |
146                           EXMC_SNCTL_WREN | EXMC_SNCTL_NRWTEN | EXMC_SNCTL_EXMODEN | EXMC_SNCTL_ASYNCWAIT |
147                           EXMC_SNCTL_SYNCWR ));
148 
149     snctl |= (uint32_t)(exmc_norsram_init_struct->address_data_mux << SNCTL_NRMUX_OFFSET) |
150                         exmc_norsram_init_struct->memory_type |
151                         exmc_norsram_init_struct->databus_width |
152                        (exmc_norsram_init_struct->burst_mode << SNCTL_SBRSTEN_OFFSET) |
153                         exmc_norsram_init_struct->nwait_polarity |
154                        (exmc_norsram_init_struct->wrap_burst_mode << SNCTL_WRAPEN_OFFSET) |
155                         exmc_norsram_init_struct->nwait_config |
156                        (exmc_norsram_init_struct->memory_write << SNCTL_WREN_OFFSET) |
157                        (exmc_norsram_init_struct->nwait_signal << SNCTL_NRWTEN_OFFSET) |
158                        (exmc_norsram_init_struct->extended_mode << SNCTL_EXMODEN_OFFSET) |
159                        (exmc_norsram_init_struct->asyn_wait << SNCTL_ASYNCWAIT_OFFSET) |
160                         exmc_norsram_init_struct->write_mode;
161 
162     sntcfg = (uint32_t)((exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime - 1U ) & EXMC_SNTCFG_ASET )|
163                        (((exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime - 1U ) << SNTCFG_AHLD_OFFSET ) & EXMC_SNTCFG_AHLD ) |
164                        (((exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime - 1U ) << SNTCFG_DSET_OFFSET ) & EXMC_SNTCFG_DSET ) |
165                        (((exmc_norsram_init_struct->read_write_timing->bus_latency - 1U ) << SNTCFG_BUSLAT_OFFSET ) & EXMC_SNTCFG_BUSLAT )|
166                        exmc_norsram_init_struct->read_write_timing->syn_clk_division |
167                        exmc_norsram_init_struct->read_write_timing->syn_data_latency |
168                        exmc_norsram_init_struct->read_write_timing->asyn_access_mode;
169 
170     /* nor flash access enable */
171     if(EXMC_MEMORY_TYPE_NOR == exmc_norsram_init_struct->memory_type){
172         snctl |= (uint32_t)EXMC_SNCTL_NREN;
173     }
174 
175     /* extended mode configure */
176     if(ENABLE == exmc_norsram_init_struct->extended_mode){
177         snwtcfg = (uint32_t)((exmc_norsram_init_struct->write_timing->asyn_address_setuptime - 1U) & EXMC_SNWTCFG_WASET ) |
178                            (((exmc_norsram_init_struct->write_timing->asyn_address_holdtime -1U ) << SNWTCFG_WAHLD_OFFSET ) & EXMC_SNWTCFG_WAHLD )|
179                            (((exmc_norsram_init_struct->write_timing->asyn_data_setuptime -1U ) << SNWTCFG_WDSET_OFFSET ) & EXMC_SNWTCFG_WDSET )|
180                            (((exmc_norsram_init_struct->write_timing->bus_latency - 1U ) << SNWTCFG_WBUSLAT_OFFSET ) & EXMC_SNWTCFG_WBUSLAT ) |
181                             exmc_norsram_init_struct->write_timing->asyn_access_mode;
182     }else{
183         snwtcfg = BANK0_SNWTCFG_RESET;
184     }
185 
186     /* configure the registers */
187     EXMC_SNCTL = snctl;
188     EXMC_SNTCFG = sntcfg;
189     EXMC_SNWTCFG = snwtcfg;
190 }
191 
192 /*!
193     \brief      enable EXMC NOR/PSRAM bank
194     \param[in]  none
195     \param[out] none
196     \retval     none
197 */
exmc_norsram_enable(void)198 void exmc_norsram_enable(void)
199 {
200     EXMC_SNCTL |= (uint32_t)EXMC_SNCTL_NRBKEN;
201 }
202 
203 /*!
204     \brief      disable EXMC NOR/PSRAM bank
205     \param[in]  none
206     \param[out] none
207     \retval     none
208 */
exmc_norsram_disable(void)209 void exmc_norsram_disable(void)
210 {
211     EXMC_SNCTL &= ~(uint32_t)EXMC_SNCTL_NRBKEN;
212 }
213 
214 /*!
215     \brief      configure CRAM page size
216     \param[in]  page_size: CRAM page size
217                 only one parameter can be selected which is shown as below:
218       \arg        EXMC_CRAM_AUTO_SPLIT: the clock is generated only during synchronous access
219       \arg        EXMC_CRAM_PAGE_SIZE_128_BYTES: page size is 128 bytes
220       \arg        EXMC_CRAM_PAGE_SIZE_256_BYTES: page size is 256 bytes
221       \arg        EXMC_CRAM_PAGE_SIZE_512_BYTES: page size is 512 bytes
222       \arg        EXMC_CRAM_PAGE_SIZE_1024_BYTES: page size is 1024 bytes
223     \param[out] none
224     \retval     none
225 */
exmc_norsram_page_size_config(uint32_t page_size)226 void exmc_norsram_page_size_config(uint32_t page_size)
227 {
228     /* reset the bits */
229     EXMC_SNCTL &= ~EXMC_SNCTL_CPS;
230     /* set the CPS bits */
231     EXMC_SNCTL |= page_size;
232 }
233