1 /*******************************************************************************
2 * Copyright 2019-2020 Microchip FPGA Embedded Systems Solutions.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * PolarFire SoC microprocessor subsystem GPIO bare metal driver implementation.
7 *
8 * This driver is based on SmartFusion2 MSS GPIO driver v2.1.102
9 *
10 */
11
12 #include "mpfs_hal/mss_hal.h"
13 #include "mss_gpio.h"
14
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18
19 /*-------------------------------------------------------------------------*//**
20 * Defines.
21 */
22 #define GPIO_INT_ENABLE_MASK ((uint32_t)0x00000008)
23 #define OUTPUT_BUFFER_ENABLE_MASK ((uint32_t)0x00000004)
24
25 /*These constants define the number of GPIO bits available on each GPIO
26 * hardware block*/
27 #define NB_OF_GPIO_GPIO0 ((uint32_t)14)
28 #define NB_OF_GPIO_GPIO1 ((uint32_t)24)
29 #define NB_OF_GPIO_GPIO2 ((uint32_t)32)
30
31 /*This constant indicates the total number of GPIO interrupt inputs at the PLIC
32 * (includes the direct and non-direct GPIO interrupts)*/
33 #define NB_OF_GPIO_INTR ((uint32_t)41)
34
35 /*-------------------------------------------------------------------------*//**
36 * Lookup table of GPIO interrupt number indexed on GPIO ID.
37 * The GPIO interrupts are multiplexed. Total GPIO interrupts are 41.
38 * 41 = (14 from GPIO0 + 24 from GPIO1 + 3 non direct interrupts)
39 * GPIO2 interrupts are not available by default. Setting the corresponding bit
40 * in GPIO_INTERRUPT_FAB_CR(31:0) will enable GPIO2(31:0) corresponding
41 * interrupt on PLIC.
42 *
43 * PLIC GPIO_INTERRUPT_FAB_CR
44 0 1
45 0 GPIO0 bit 0 GPIO2 bit 0
46 1 GPIO0 bit 1 GPIO2 bit 1
47 .
48 .
49 12 GPIO0 bit 12 GPIO2 bit 12
50 13 GPIO0 bit 13 GPIO2 bit 13
51 14 GPIO1 bit 0 GPIO2 bit 14
52 15 GPIO1 bit 1 GPIO2 bit 15
53 .
54 .
55 .
56 30 GPIO1 bit 16 GPIO2 bit 30
57 31 GPIO1 bit 17 GPIO2 bit 31
58 32 GPIO1 bit 18
59 33 GPIO1 bit 19
60 34 GPIO1 bit 20
61 35 GPIO1 bit 21
62 36 GPIO1 bit 22
63 37 GPIO1 bit 23
64 38 Or of all GPIO0 interrupts who do not have a direct connection enabled
65 39 Or of all GPIO1 interrupts who do not have a direct connection enabled
66 40 Or of all GPIO2 interrupts who do not have a direct connection enabled
67 *
68 */
69 static const PLIC_IRQn_Type g_gpio_irqn_lut[NB_OF_GPIO_INTR] =
70 {
71 GPIO0_BIT0_or_GPIO2_BIT0_PLIC_0,
72 GPIO0_BIT1_or_GPIO2_BIT1_PLIC_1,
73 GPIO0_BIT2_or_GPIO2_BIT2_PLIC_2,
74 GPIO0_BIT3_or_GPIO2_BIT3_PLIC_3,
75 GPIO0_BIT4_or_GPIO2_BIT4_PLIC_4,
76 GPIO0_BIT5_or_GPIO2_BIT5_PLIC_5,
77 GPIO0_BIT6_or_GPIO2_BIT6_PLIC_6,
78 GPIO0_BIT7_or_GPIO2_BIT7_PLIC_7,
79 GPIO0_BIT8_or_GPIO2_BIT8_PLIC_8,
80 GPIO0_BIT9_or_GPIO2_BIT9_PLIC_9,
81 GPIO0_BIT10_or_GPIO2_BIT10_PLIC_10,
82 GPIO0_BIT11_or_GPIO2_BIT11_PLIC_11,
83 GPIO0_BIT12_or_GPIO2_BIT12_PLIC_12,
84 GPIO0_BIT13_or_GPIO2_BIT13_PLIC_13,
85
86 GPIO1_BIT0_or_GPIO2_BIT14_PLIC_14,
87 GPIO1_BIT1_or_GPIO2_BIT15_PLIC_15,
88 GPIO1_BIT2_or_GPIO2_BIT16_PLIC_16,
89 GPIO1_BIT3_or_GPIO2_BIT17_PLIC_17,
90 GPIO1_BIT4_or_GPIO2_BIT18_PLIC_18,
91 GPIO1_BIT5_or_GPIO2_BIT19_PLIC_19,
92 GPIO1_BIT6_or_GPIO2_BIT20_PLIC_20,
93 GPIO1_BIT7_or_GPIO2_BIT21_PLIC_21,
94 GPIO1_BIT8_or_GPIO2_BIT22_PLIC_22,
95 GPIO1_BIT9_or_GPIO2_BIT23_PLIC_23,
96 GPIO1_BIT10_or_GPIO2_BIT24_PLIC_24,
97 GPIO1_BIT11_or_GPIO2_BIT25_PLIC_25,
98 GPIO1_BIT12_or_GPIO2_BIT26_PLIC_26,
99 GPIO1_BIT13_or_GPIO2_BIT27_PLIC_27,
100 GPIO1_BIT14_or_GPIO2_BIT28_PLIC_28,
101 GPIO1_BIT15_or_GPIO2_BIT29_PLIC_29,
102 GPIO1_BIT16_or_GPIO2_BIT30_PLIC_30,
103 GPIO1_BIT17_or_GPIO2_BIT31_PLIC_31,
104
105 GPIO1_BIT18_PLIC_32,
106 GPIO1_BIT19_PLIC_33,
107 GPIO1_BIT20_PLIC_34,
108 GPIO1_BIT21_PLIC_35,
109 GPIO1_BIT22_PLIC_36,
110 GPIO1_BIT23_PLIC_37,
111
112 GPIO0_NON_DIRECT_PLIC,
113 GPIO1_NON_DIRECT_PLIC,
114 GPIO2_NON_DIRECT_PLIC
115 };
116
117 /*-------------------------------------------------------------------------*//**
118 * Local functions
119 */
120 static uint8_t gpio_number_validate(GPIO_TypeDef const * gpio, mss_gpio_id_t gpio_idx);
121
122 /*-------------------------------------------------------------------------*//**
123 * MSS_GPIO_init
124 * See "mss_gpio.h" for details of how to use this function.
125 */
126 void
MSS_GPIO_init(GPIO_TypeDef * gpio)127 MSS_GPIO_init
128 (
129 GPIO_TypeDef * gpio
130 )
131 {
132 /* clear all pending interrupts*/
133 gpio->GPIO_IRQ = 0xFFFFFFFFU;
134 }
135
136 /*-------------------------------------------------------------------------*//**
137 * MSS_GPIO_config
138 * See "mss_gpio.h" for details of how to use this function.
139 */
MSS_GPIO_config(GPIO_TypeDef * gpio,mss_gpio_id_t port_id,uint32_t config)140 void MSS_GPIO_config
141 (
142 GPIO_TypeDef * gpio,
143 mss_gpio_id_t port_id,
144 uint32_t config
145 )
146 {
147 if (0U == gpio_number_validate(gpio, port_id))
148 {
149 gpio->GPIO_CFG[port_id] = config;
150 }
151 else
152 {
153 ASSERT(0); /*LDRA warning*/
154 }
155 }
156
157 /*-------------------------------------------------------------------------*//**
158 * MSS_GPIO_config_byte
159 * See "mss_gpio.h" for details of how to use this function.
160 */
MSS_GPIO_config_byte(GPIO_TypeDef * gpio,mss_gpio_byte_num_t byte_num,uint32_t config)161 void MSS_GPIO_config_byte
162 (
163 GPIO_TypeDef * gpio,
164 mss_gpio_byte_num_t byte_num,
165 uint32_t config
166 )
167 {
168 if (((GPIO0_LO == gpio) || (GPIO0_HI == gpio)) &&
169 (byte_num >= MSS_GPIO_BYTE_1))
170 {
171 ASSERT(0);
172 }
173 else if (((GPIO1_LO == gpio) || (GPIO1_HI == gpio)) &&
174 (byte_num > MSS_GPIO_BYTE_2))
175 {
176 ASSERT(0);
177 }
178 else if (((GPIO2_LO == gpio) || (GPIO2_HI == gpio)) &&
179 (byte_num > MSS_GPIO_BYTE_3))
180 {
181 ASSERT(0);
182 }
183 else
184 {
185 gpio->GPIO_CFG_BYTE[byte_num] = config;
186 }
187 }
188
189 /*-------------------------------------------------------------------------*//**
190 * MSS_GPIO_config_all
191 * See "mss_gpio.h" for details of how to use this function.
192 */
MSS_GPIO_config_all(GPIO_TypeDef * gpio,uint32_t config)193 void MSS_GPIO_config_all
194 (
195 GPIO_TypeDef * gpio,
196 uint32_t config
197 )
198 {
199 gpio->GPIO_CFG_ALL = config;
200 }
201
202 /*-------------------------------------------------------------------------*//**
203 * MSS_GPIO_set_output
204 * See "mss_gpio.h" for details of how to use this function.
205 */
MSS_GPIO_set_output(GPIO_TypeDef * gpio,mss_gpio_id_t port_id,uint8_t value)206 void MSS_GPIO_set_output
207 (
208 GPIO_TypeDef * gpio,
209 mss_gpio_id_t port_id,
210 uint8_t value
211 )
212 {
213 uint32_t gpio_setting;
214
215 if (0U == gpio_number_validate(gpio, port_id))
216 {
217 /* Setting the bit in GPIO_SET_BITS (offset 0xA4) sets the corresponding
218 * output port.
219 * Setting the bit in GPIO_CLR_BITS (offset 0xA0) clears the
220 * corresponding output port.*/
221
222 if (value > 0u)
223 {
224 gpio->GPIO_SET_BITS = ((uint32_t)0x01 << port_id);
225 }
226 else
227 {
228 gpio->GPIO_CLR_BITS = ((uint32_t)0x01 << port_id);
229 }
230 }
231 else
232 {
233 ASSERT(0); /*LDRA warning*/
234 }
235 }
236
237 /*-------------------------------------------------------------------------*//**
238 * MSS_GPIO_drive_inout
239 * See "mss_gpio.h" for details of how to use this function.
240 */
MSS_GPIO_drive_inout(GPIO_TypeDef * gpio,mss_gpio_id_t port_id,mss_gpio_inout_state_t inout_state)241 void MSS_GPIO_drive_inout
242 (
243 GPIO_TypeDef * gpio,
244 mss_gpio_id_t port_id,
245 mss_gpio_inout_state_t inout_state
246 )
247 {
248 uint32_t outputs_state;
249 uint32_t config;
250
251 if (0U == gpio_number_validate(gpio, port_id))
252 {
253 switch (inout_state)
254 {
255 case MSS_GPIO_DRIVE_HIGH:
256 /* Set output high */
257 gpio->GPIO_SET_BITS = ((uint32_t)1 << port_id);
258
259 /* Enable output buffer */
260 config = gpio->GPIO_CFG[port_id];
261 config |= OUTPUT_BUFFER_ENABLE_MASK;
262 gpio->GPIO_CFG[port_id] = config;
263 break;
264
265 case MSS_GPIO_DRIVE_LOW:
266 /* Set output low */
267 gpio->GPIO_CLR_BITS = (uint32_t)1 << port_id;
268 /* Enable output buffer */
269 config = gpio->GPIO_CFG[port_id];
270 config |= OUTPUT_BUFFER_ENABLE_MASK;
271 gpio->GPIO_CFG[port_id] = config;
272 break;
273
274 case MSS_GPIO_HIGH_Z:
275 /* Disable output buffer */
276 config = gpio->GPIO_CFG[port_id];
277 config &= ~OUTPUT_BUFFER_ENABLE_MASK;
278 gpio->GPIO_CFG[port_id] = config;
279 break;
280
281 default:
282 ASSERT(0);
283 break;
284 }
285 }
286 else
287 {
288 ASSERT(0); /*LDRA warning*/
289 }
290 }
291
292 /*-------------------------------------------------------------------------*//**
293 * MSS_GPIO_enable_irq
294 * See "mss_gpio.h" for details of how to use this function.
295 */
MSS_GPIO_enable_irq(GPIO_TypeDef * gpio,mss_gpio_id_t port_id)296 void MSS_GPIO_enable_irq
297 (
298 GPIO_TypeDef * gpio,
299 mss_gpio_id_t port_id
300 )
301 {
302 uint32_t cfg_value;
303
304 if (0U == gpio_number_validate(gpio, port_id))
305 {
306 cfg_value = gpio->GPIO_CFG[(uint8_t)port_id];
307 gpio->GPIO_CFG[(uint8_t)port_id] = (cfg_value | GPIO_INT_ENABLE_MASK);
308
309 if ((GPIO0_LO == gpio) || (GPIO0_HI == gpio))
310 {
311 PLIC_EnableIRQ(g_gpio_irqn_lut[port_id]);
312 }
313 else if ((GPIO1_LO == gpio) || (GPIO1_HI == gpio))
314 {
315 PLIC_EnableIRQ(g_gpio_irqn_lut[port_id +
316 GPIO1_BIT0_or_GPIO2_BIT14_PLIC_14]);
317 }
318 else if ((GPIO2_LO == gpio) || (GPIO2_HI == gpio))
319 {
320 PLIC_EnableIRQ(g_gpio_irqn_lut[port_id]);
321 }
322 else
323 {
324 ASSERT(0); /*LDRA warning*/
325 }
326 }
327 else
328 {
329 ASSERT(0); /*LDRA warning*/
330 }
331 }
332
333 /*-------------------------------------------------------------------------*//**
334 * MSS_GPIO_disable_irq
335 * See "mss_gpio.h" for details of how to use this function.
336 */
337
MSS_GPIO_disable_irq(GPIO_TypeDef * gpio,mss_gpio_id_t port_id)338 void MSS_GPIO_disable_irq
339 (
340 GPIO_TypeDef * gpio,
341 mss_gpio_id_t port_id
342 )
343 {
344 uint32_t cfg_value;
345
346 if (0U == gpio_number_validate(gpio, port_id))
347 {
348 cfg_value = gpio->GPIO_CFG[(uint8_t)port_id];
349 gpio->GPIO_CFG[(uint8_t)port_id] = (cfg_value & (~GPIO_INT_ENABLE_MASK));
350
351 if ((GPIO0_LO == gpio) || (GPIO0_HI == gpio))
352 {
353 PLIC_DisableIRQ(g_gpio_irqn_lut[port_id]);
354 }
355 else if ((GPIO1_LO == gpio) || (GPIO1_HI == gpio))
356 {
357 PLIC_DisableIRQ(g_gpio_irqn_lut[port_id +
358 GPIO1_BIT0_or_GPIO2_BIT14_PLIC_14]);
359 }
360 else if ((GPIO2_LO == gpio) || (GPIO2_HI == gpio))
361 {
362 PLIC_DisableIRQ(GPIO2_NON_DIRECT_PLIC);
363 }
364 else
365 {
366 ASSERT(0); /*LDRA warning*/
367 }
368 }
369 else
370 {
371 ASSERT(0); /*LDRA warning*/
372 }
373 }
374
375 /*-------------------------------------------------------------------------*//**
376 * MSS_GPIO_enable_nondirect_irq
377 * See "mss_gpio.h" for details of how to use this function.
378 */
379 void
MSS_GPIO_enable_nondirect_irq(GPIO_TypeDef const * gpio)380 MSS_GPIO_enable_nondirect_irq
381 (
382 GPIO_TypeDef const * gpio
383 )
384 {
385 if ((GPIO0_LO == gpio) || (GPIO0_HI == gpio))
386 {
387 PLIC_EnableIRQ(GPIO0_NON_DIRECT_PLIC);
388 }
389 else if ((GPIO1_LO == gpio) || (GPIO1_HI == gpio))
390 {
391 PLIC_EnableIRQ(GPIO1_NON_DIRECT_PLIC);
392 }
393 else if ((GPIO2_LO == gpio) || (GPIO2_HI == gpio))
394 {
395 PLIC_EnableIRQ(GPIO2_NON_DIRECT_PLIC);
396 }
397 else
398 {
399 ASSERT(0); /*LDRA warning*/
400 }
401 }
402
403 /*-------------------------------------------------------------------------*//**
404 * MSS_GPIO_disable_nondirect_irq
405 * See "mss_gpio.h" for details of how to use this function.
406 */
407 void
MSS_GPIO_disable_nondirect_irq(GPIO_TypeDef const * gpio)408 MSS_GPIO_disable_nondirect_irq
409 (
410 GPIO_TypeDef const * gpio
411 )
412 {
413 if ((GPIO0_LO == gpio) || (GPIO0_HI == gpio))
414 {
415 PLIC_DisableIRQ(GPIO0_NON_DIRECT_PLIC);
416 }
417 else if ((GPIO1_LO == gpio) || (GPIO1_HI == gpio))
418 {
419 PLIC_DisableIRQ(GPIO1_NON_DIRECT_PLIC);
420 }
421 else if ((GPIO2_LO == gpio) || (GPIO2_HI == gpio))
422 {
423 PLIC_DisableIRQ(GPIO2_NON_DIRECT_PLIC);
424 }
425 else
426 {
427 ASSERT(0); /*LDRA warning*/
428 }
429 }
430
431 /*-------------------------------------------------------------------------*//**
432 * MSS_GPIO_clear_irq
433 * See "mss_gpio.h" for details of how to use this function.
434 */
MSS_GPIO_clear_irq(GPIO_TypeDef * gpio,mss_gpio_id_t port_id)435 void MSS_GPIO_clear_irq
436 (
437 GPIO_TypeDef * gpio,
438 mss_gpio_id_t port_id
439 )
440 {
441 if (0U == gpio_number_validate(gpio, port_id))
442 {
443 gpio->GPIO_IRQ = ((uint32_t)1) << port_id;
444 __asm("fence");
445 }
446 else
447 {
448 ASSERT(0); /*LDRA warning*/
449 }
450 }
451
gpio_number_validate(GPIO_TypeDef const * gpio,mss_gpio_id_t gpio_idx)452 static uint8_t gpio_number_validate(GPIO_TypeDef const * gpio, mss_gpio_id_t gpio_idx)
453 {
454 uint8_t ret;
455
456 if (((GPIO0_LO == gpio) || (GPIO0_HI == gpio)) &&
457 (gpio_idx >= NB_OF_GPIO_GPIO0))
458 {
459 ret = 1u;
460 }
461 else if (((GPIO1_LO == gpio) || (GPIO1_HI == gpio)) &&
462 (gpio_idx >= NB_OF_GPIO_GPIO1))
463 {
464 ret = 1u;
465 }
466 else if (((GPIO2_LO == gpio) || (GPIO2_HI == gpio)) &&
467 (gpio_idx >= NB_OF_GPIO_GPIO2))
468 {
469 ret = 1u;
470 }
471 else
472 {
473 ret = 0u;
474 }
475
476 return ret;
477 }
478
479 #ifdef __cplusplus
480 }
481 #endif
482