1 /*!
2     \file    gd32vf103_exmc.c
3     \brief   EXMC driver
4 
5     \version 2019-06-05, V1.0.0, firmware for GD32VF103
6     \version 2020-08-04, V1.1.0, firmware for GD32VF103
7 */
8 
9 /*
10     Copyright (c) 2020, GigaDevice Semiconductor Inc.
11 
12     Redistribution and use in source and binary forms, with or without modification,
13 are permitted provided that the following conditions are met:
14 
15     1. Redistributions of source code must retain the above copyright notice, this
16        list of conditions and the following disclaimer.
17     2. Redistributions in binary form must reproduce the above copyright notice,
18        this list of conditions and the following disclaimer in the documentation
19        and/or other materials provided with the distribution.
20     3. Neither the name of the copyright holder nor the names of its contributors
21        may be used to endorse or promote products derived from this software without
22        specific prior written permission.
23 
24     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
33 OF SUCH DAMAGE.
34 */
35 
36 #include "gd32vf103_exmc.h"
37 
38 /* EXMC bank0 register reset value */
39 #define BANK0_SNCTL0_REGION_RESET         ((uint32_t)0x000030DAU)
40 #define BANK0_SNTCFG_RESET                ((uint32_t)0x0FFFFFFFU)
41 
42 /* EXMC register bit offset */
43 #define SNCTL_NRMUX_OFFSET                ((uint32_t)1U)
44 #define SNCTL_WREN_OFFSET                 ((uint32_t)12U)
45 #define SNCTL_NRWTEN_OFFSET               ((uint32_t)13U)
46 #define SNCTL_ASYNCWAIT_OFFSET            ((uint32_t)15U)
47 
48 #define SNTCFG_AHLD_OFFSET                ((uint32_t)4U)
49 #define SNTCFG_DSET_OFFSET                ((uint32_t)8U)
50 #define SNTCFG_BUSLAT_OFFSET              ((uint32_t)16U)
51 
52 /*!
53     \brief      deinitialize EXMC NOR/SRAM region
54     \param[in]  norsram_region: select the region of bank0
55       \arg        EXMC_BANK0_NORSRAM_REGIONx(x=0)
56     \param[out] none
57     \retval     none
58 */
exmc_norsram_deinit(uint32_t norsram_region)59 void exmc_norsram_deinit(uint32_t norsram_region)
60 {
61     /* reset the registers */
62     if(EXMC_BANK0_NORSRAM_REGION0 == norsram_region){
63         EXMC_SNCTL(norsram_region) = BANK0_SNCTL0_REGION_RESET;
64     }
65 
66     EXMC_SNTCFG(norsram_region) = BANK0_SNTCFG_RESET;
67 }
68 
69 /*!
70     \brief      initialize the structure exmc_norsram_parameter_struct
71     \param[in]  none
72     \param[out] exmc_norsram_init_struct: the initialized structure exmc_norsram_parameter_struct pointer
73     \retval     none
74 */
exmc_norsram_struct_para_init(exmc_norsram_parameter_struct * exmc_norsram_init_struct)75 void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct)
76 {
77     /* configure the structure with default value */
78     exmc_norsram_init_struct->norsram_region = EXMC_BANK0_NORSRAM_REGION0;
79     exmc_norsram_init_struct->address_data_mux = ENABLE;
80     exmc_norsram_init_struct->memory_type = EXMC_MEMORY_TYPE_SRAM;
81     exmc_norsram_init_struct->databus_width = EXMC_NOR_DATABUS_WIDTH_16B;
82     exmc_norsram_init_struct->nwait_polarity = EXMC_NWAIT_POLARITY_LOW;
83     exmc_norsram_init_struct->memory_write = ENABLE;
84     exmc_norsram_init_struct->nwait_signal = ENABLE;
85     exmc_norsram_init_struct->asyn_wait = DISABLE;
86 
87     /* read/write timing configure */
88     exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime = 0xFU;
89     exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime = 0xFU;
90     exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime = 0xFFU;
91     exmc_norsram_init_struct->read_write_timing->bus_latency = 0xFU;
92 }
93 
94 /*!
95     \brief      initialize EXMC NOR/SRAM region
96     \param[in]  exmc_norsram_parameter_struct: configure the EXMC NOR/SRAM parameter
97                   norsram_region: EXMC_BANK0_NORSRAM_REGIONx,x=0
98                   asyn_wait: ENABLE or DISABLE
99                   nwait_signal: ENABLE or DISABLE
100                   memory_write: ENABLE or DISABLE
101                   nwait_polarity: EXMC_NWAIT_POLARITY_LOW,EXMC_NWAIT_POLARITY_HIGH
102                   databus_width: EXMC_NOR_DATABUS_WIDTH_8B,EXMC_NOR_DATABUS_WIDTH_16B
103                   memory_type: EXMC_MEMORY_TYPE_SRAM,EXMC_MEMORY_TYPE_PSRAM,EXMC_MEMORY_TYPE_NOR
104                   address_data_mux: ENABLE
105                   read_write_timing: structure exmc_norsram_timing_parameter_struct set the time
106     \param[out] none
107     \retval     none
108 */
exmc_norsram_init(exmc_norsram_parameter_struct * exmc_norsram_init_struct)109 void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct)
110 {
111     uint32_t snctl = 0x00000000U, sntcfg = 0x00000000U;
112 
113     /* get the register value */
114     snctl = EXMC_SNCTL(exmc_norsram_init_struct->norsram_region);
115 
116     /* clear relative bits */
117     snctl &= ((uint32_t)~(EXMC_SNCTL_NREN | EXMC_SNCTL_NRTP | EXMC_SNCTL_NRW | EXMC_SNCTL_NRWTPOL |
118                           EXMC_SNCTL_WREN | EXMC_SNCTL_NRWTEN | EXMC_SNCTL_ASYNCWAIT | EXMC_SNCTL_NRMUX));
119 
120     snctl |= (uint32_t)((uint32_t)exmc_norsram_init_struct->address_data_mux << SNCTL_NRMUX_OFFSET) |
121                         exmc_norsram_init_struct->memory_type |
122                         exmc_norsram_init_struct->databus_width |
123                         exmc_norsram_init_struct->nwait_polarity |
124                        ((uint32_t)exmc_norsram_init_struct->memory_write << SNCTL_WREN_OFFSET) |
125                        ((uint32_t)exmc_norsram_init_struct->nwait_signal << SNCTL_NRWTEN_OFFSET) |
126                        ((uint32_t)exmc_norsram_init_struct->asyn_wait << SNCTL_ASYNCWAIT_OFFSET);
127 
128     sntcfg = (uint32_t)((exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime - 1U ) & EXMC_SNTCFG_ASET )|
129                        (((exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime - 1U ) << SNTCFG_AHLD_OFFSET ) & EXMC_SNTCFG_AHLD ) |
130                        (((exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime - 1U ) << SNTCFG_DSET_OFFSET ) & EXMC_SNTCFG_DSET ) |
131                        (((exmc_norsram_init_struct->read_write_timing->bus_latency - 1U ) << SNTCFG_BUSLAT_OFFSET ) & EXMC_SNTCFG_BUSLAT );
132 
133     /* nor flash access enable */
134     if(EXMC_MEMORY_TYPE_NOR == exmc_norsram_init_struct->memory_type){
135         snctl |= (uint32_t)EXMC_SNCTL_NREN;
136     }
137 
138     /* configure the registers */
139     EXMC_SNCTL(exmc_norsram_init_struct->norsram_region) = snctl;
140     EXMC_SNTCFG(exmc_norsram_init_struct->norsram_region) = sntcfg;
141 }
142 
143 /*!
144     \brief      enable EXMC NOR/PSRAM bank region
145     \param[in]  norsram_region: specify the region of NOR/PSRAM bank
146       \arg        EXMC_BANK0_NORSRAM_REGIONx(x=0)
147     \param[out] none
148     \retval     none
149 */
exmc_norsram_enable(uint32_t norsram_region)150 void exmc_norsram_enable(uint32_t norsram_region)
151 {
152     EXMC_SNCTL(norsram_region) |= (uint32_t)EXMC_SNCTL_NRBKEN;
153 }
154 
155 /*!
156     \brief      disable EXMC NOR/PSRAM bank region
157     \param[in]  norsram_region: specify the region of NOR/PSRAM bank
158       \arg        EXMC_BANK0_NORSRAM_REGIONx(x=0)
159     \param[out] none
160     \retval     none
161 */
exmc_norsram_disable(uint32_t norsram_region)162 void exmc_norsram_disable(uint32_t norsram_region)
163 {
164     EXMC_SNCTL(norsram_region) &= ~(uint32_t)EXMC_SNCTL_NRBKEN;
165 }
166