1 /*******************************************************************************
2 * (c) Copyright 2008-2015 Microsemi SoC Products Group. All rights reserved.
3 *
4 * SmartFusion2 microcontroller subsystem GPIO bare metal driver implementation.
5 *
6 * SVN $Revision: 7749 $
7 * SVN $Date: 2015-09-04 14:32:09 +0530 (Fri, 04 Sep 2015) $
8 */
9 #include "mss_gpio.h"
10 #include "../../CMSIS/mss_assert.h"
11
12 #ifdef __cplusplus
13 extern "C" {
14 #endif
15
16 /*-------------------------------------------------------------------------*//**
17 * Defines.
18 */
19 #define GPIO_INT_ENABLE_MASK ((uint32_t)0x00000008uL)
20 #define OUTPUT_BUFFER_ENABLE_MASK 0x00000004u
21
22 #define NB_OF_GPIO ((uint32_t)32)
23
24 /*-------------------------------------------------------------------------*//**
25 * Lookup table of GPIO configuration registers address indexed on GPIO ID.
26 */
27 static uint32_t volatile * const g_config_reg_lut[NB_OF_GPIO] =
28 {
29 &(GPIO->GPIO_0_CFG),
30 &(GPIO->GPIO_1_CFG),
31 &(GPIO->GPIO_2_CFG),
32 &(GPIO->GPIO_3_CFG),
33 &(GPIO->GPIO_4_CFG),
34 &(GPIO->GPIO_5_CFG),
35 &(GPIO->GPIO_6_CFG),
36 &(GPIO->GPIO_7_CFG),
37 &(GPIO->GPIO_8_CFG),
38 &(GPIO->GPIO_9_CFG),
39 &(GPIO->GPIO_10_CFG),
40 &(GPIO->GPIO_11_CFG),
41 &(GPIO->GPIO_12_CFG),
42 &(GPIO->GPIO_13_CFG),
43 &(GPIO->GPIO_14_CFG),
44 &(GPIO->GPIO_15_CFG),
45 &(GPIO->GPIO_16_CFG),
46 &(GPIO->GPIO_17_CFG),
47 &(GPIO->GPIO_18_CFG),
48 &(GPIO->GPIO_19_CFG),
49 &(GPIO->GPIO_20_CFG),
50 &(GPIO->GPIO_21_CFG),
51 &(GPIO->GPIO_22_CFG),
52 &(GPIO->GPIO_23_CFG),
53 &(GPIO->GPIO_24_CFG),
54 &(GPIO->GPIO_25_CFG),
55 &(GPIO->GPIO_26_CFG),
56 &(GPIO->GPIO_27_CFG),
57 &(GPIO->GPIO_28_CFG),
58 &(GPIO->GPIO_29_CFG),
59 &(GPIO->GPIO_30_CFG),
60 &(GPIO->GPIO_31_CFG)
61 };
62
63 /*-------------------------------------------------------------------------*//**
64 * Lookup table of Cortex-M3 GPIO interrupt number indexed on GPIO ID.
65 */
66 static const IRQn_Type g_gpio_irqn_lut[NB_OF_GPIO] =
67 {
68 GPIO0_IRQn,
69 GPIO1_IRQn,
70 GPIO2_IRQn,
71 GPIO3_IRQn,
72 GPIO4_IRQn,
73 GPIO5_IRQn,
74 GPIO6_IRQn,
75 GPIO7_IRQn,
76 GPIO8_IRQn,
77 GPIO9_IRQn,
78 GPIO10_IRQn,
79 GPIO11_IRQn,
80 GPIO12_IRQn,
81 GPIO13_IRQn,
82 GPIO14_IRQn,
83 GPIO15_IRQn,
84 GPIO16_IRQn,
85 GPIO17_IRQn,
86 GPIO18_IRQn,
87 GPIO19_IRQn,
88 GPIO20_IRQn,
89 GPIO21_IRQn,
90 GPIO22_IRQn,
91 GPIO23_IRQn,
92 GPIO24_IRQn,
93 GPIO25_IRQn,
94 GPIO26_IRQn,
95 GPIO27_IRQn,
96 GPIO28_IRQn,
97 GPIO29_IRQn,
98 GPIO30_IRQn,
99 GPIO31_IRQn
100 };
101
102 /*-------------------------------------------------------------------------*//**
103 * MSS_GPIO_init
104 * See "mss_gpio.h" for details of how to use this function.
105 */
MSS_GPIO_init(void)106 void MSS_GPIO_init( void )
107 {
108 uint32_t inc;
109
110 /* reset MSS GPIO hardware */
111 SYSREG->SOFT_RST_CR |= SYSREG_GPIO_SOFTRESET_MASK;
112 SYSREG->SOFT_RST_CR |= (SYSREG_GPIO_7_0_SOFTRESET_MASK |
113 SYSREG_GPIO_15_8_SOFTRESET_MASK |
114 SYSREG_GPIO_23_16_SOFTRESET_MASK |
115 SYSREG_GPIO_31_24_SOFTRESET_MASK);
116
117 /* Clear any previously pended MSS GPIO interrupt */
118 for(inc = 0U; inc < NB_OF_GPIO; ++inc)
119 {
120 NVIC_DisableIRQ(g_gpio_irqn_lut[inc]);
121 NVIC_ClearPendingIRQ(g_gpio_irqn_lut[inc]);
122 }
123 /* Take MSS GPIO hardware out of reset. */
124 SYSREG->SOFT_RST_CR &= ~(SYSREG_GPIO_7_0_SOFTRESET_MASK |
125 SYSREG_GPIO_15_8_SOFTRESET_MASK |
126 SYSREG_GPIO_23_16_SOFTRESET_MASK |
127 SYSREG_GPIO_31_24_SOFTRESET_MASK);
128 SYSREG->SOFT_RST_CR &= ~SYSREG_GPIO_SOFTRESET_MASK;
129 }
130
131 /*-------------------------------------------------------------------------*//**
132 * MSS_GPIO_config
133 * See "mss_gpio.h" for details of how to use this function.
134 */
MSS_GPIO_config(mss_gpio_id_t port_id,uint32_t config)135 void MSS_GPIO_config
136 (
137 mss_gpio_id_t port_id,
138 uint32_t config
139 )
140 {
141 uint32_t gpio_idx = (uint32_t)port_id;
142
143 ASSERT(gpio_idx < NB_OF_GPIO);
144
145 if(gpio_idx < NB_OF_GPIO)
146 {
147 *(g_config_reg_lut[gpio_idx]) = config;
148 }
149 }
150
151 /*-------------------------------------------------------------------------*//**
152 * MSS_GPIO_set_output
153 * See "mss_gpio.h" for details of how to use this function.
154 */
MSS_GPIO_set_output(mss_gpio_id_t port_id,uint8_t value)155 void MSS_GPIO_set_output
156 (
157 mss_gpio_id_t port_id,
158 uint8_t value
159 )
160 {
161 uint32_t gpio_setting;
162 uint32_t gpio_idx = (uint32_t)port_id;
163
164 ASSERT(gpio_idx < NB_OF_GPIO);
165
166 if(gpio_idx < NB_OF_GPIO)
167 {
168 gpio_setting = GPIO->GPIO_OUT;
169 gpio_setting &= ~((uint32_t)0x01u << gpio_idx);
170 gpio_setting |= ((uint32_t)value & 0x01u) << gpio_idx;
171 GPIO->GPIO_OUT = gpio_setting;
172 }
173 }
174
175 /*-------------------------------------------------------------------------*//**
176 * MSS_GPIO_drive_inout
177 * See "mss_gpio.h" for details of how to use this function.
178 */
MSS_GPIO_drive_inout(mss_gpio_id_t port_id,mss_gpio_inout_state_t inout_state)179 void MSS_GPIO_drive_inout
180 (
181 mss_gpio_id_t port_id,
182 mss_gpio_inout_state_t inout_state
183 )
184 {
185 uint32_t outputs_state;
186 uint32_t config;
187 uint32_t gpio_idx = (uint32_t)port_id;
188
189 ASSERT(gpio_idx < NB_OF_GPIO);
190
191 if(gpio_idx < NB_OF_GPIO)
192 {
193 switch(inout_state)
194 {
195 case MSS_GPIO_DRIVE_HIGH:
196 /* Set output high */
197 outputs_state = GPIO->GPIO_OUT;
198 outputs_state |= (uint32_t)1 << gpio_idx;
199 GPIO->GPIO_OUT = outputs_state;
200 /* Enable output buffer */
201 config = *(g_config_reg_lut[gpio_idx]);
202 config |= OUTPUT_BUFFER_ENABLE_MASK;
203 *(g_config_reg_lut[gpio_idx]) = config;
204 break;
205
206 case MSS_GPIO_DRIVE_LOW:
207 /* Set output low */
208 outputs_state = GPIO->GPIO_OUT;
209 outputs_state &= ~((uint32_t)((uint32_t)1 << gpio_idx));
210 GPIO->GPIO_OUT = outputs_state;
211 /* Enable output buffer */
212 config = *(g_config_reg_lut[gpio_idx]);
213 config |= OUTPUT_BUFFER_ENABLE_MASK;
214 *(g_config_reg_lut[gpio_idx]) = config;
215 break;
216
217 case MSS_GPIO_HIGH_Z:
218 /* Disable output buffer */
219 config = *(g_config_reg_lut[gpio_idx]);
220 config &= ~OUTPUT_BUFFER_ENABLE_MASK;
221 *(g_config_reg_lut[gpio_idx]) = config;
222 break;
223
224 default:
225 ASSERT(0);
226 break;
227 }
228 }
229 }
230
231 /*-------------------------------------------------------------------------*//**
232 * MSS_GPIO_enable_irq
233 * See "mss_gpio.h" for details of how to use this function.
234 */
MSS_GPIO_enable_irq(mss_gpio_id_t port_id)235 void MSS_GPIO_enable_irq
236 (
237 mss_gpio_id_t port_id
238 )
239 {
240 uint32_t cfg_value;
241 uint32_t gpio_idx = (uint32_t)port_id;
242
243 ASSERT(gpio_idx < NB_OF_GPIO);
244
245 if(gpio_idx < NB_OF_GPIO)
246 {
247 cfg_value = *(g_config_reg_lut[gpio_idx]);
248 *(g_config_reg_lut[gpio_idx]) = (cfg_value | GPIO_INT_ENABLE_MASK);
249 NVIC_EnableIRQ(g_gpio_irqn_lut[gpio_idx]);
250 }
251 }
252
253 /*-------------------------------------------------------------------------*//**
254 * MSS_GPIO_disable_irq
255 * See "mss_gpio.h" for details of how to use this function.
256 */
MSS_GPIO_disable_irq(mss_gpio_id_t port_id)257 void MSS_GPIO_disable_irq
258 (
259 mss_gpio_id_t port_id
260 )
261 {
262 uint32_t cfg_value;
263 uint32_t gpio_idx = (uint32_t)port_id;
264
265 ASSERT(gpio_idx < NB_OF_GPIO);
266
267 if(gpio_idx < NB_OF_GPIO)
268 {
269 cfg_value = *(g_config_reg_lut[gpio_idx]);
270 *(g_config_reg_lut[gpio_idx]) = (cfg_value & ~GPIO_INT_ENABLE_MASK);
271 }
272 }
273
274 /*-------------------------------------------------------------------------*//**
275 * MSS_GPIO_clear_irq
276 * See "mss_gpio.h" for details of how to use this function.
277 */
MSS_GPIO_clear_irq(mss_gpio_id_t port_id)278 void MSS_GPIO_clear_irq
279 (
280 mss_gpio_id_t port_id
281 )
282 {
283 uint32_t gpio_idx = (uint32_t)port_id;
284
285 ASSERT(gpio_idx < NB_OF_GPIO);
286
287 if(gpio_idx < NB_OF_GPIO)
288 {
289 GPIO->GPIO_IRQ = ((uint32_t)1) << gpio_idx;
290 }
291 __ASM volatile ("dsb");
292
293 }
294
295 #ifdef __cplusplus
296 }
297 #endif
298
299