1 /*******************************************************************************
2 * Copyright 2019-2020 Microchip FPGA Embedded Systems Solutions.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 *
24 *
25 * PolarFire SoC Microprocessor Subsystem GPIO bare metal software driver
26 * public API.
27 *
28 * This driver is based on SmartFusion2 MSS GPIO driver v2.1.102
29 *
30 */
31
32 /*=========================================================================*//**
33 @mainpage PolarFire SoC MSS GPIO Bare Metal Driver
34
35 ==============================================================================
36 Introduction
37 ==============================================================================
38 The PolarFire SoC Microprocessor Subsystem (MSS) includes three blocks of
39 general purpose input/outputs (GPIO). The GPIO0, GPIO1 and GPIO2 blocks have
40 14, 24 and 32 GPIO ports respectively. This software driver provides a set of
41 functions for controlling the MSS GPIO blocks as part of a bare metal system
42 where no operating system is available. This driver can be adapted for use as
43 part of an operating system but the implementation of the adaptation layer
44 between this driver and the operating system's driver model is outside the
45 scope of this driver.
46
47 ==============================================================================
48 Hardware Flow Dependencies
49 ==============================================================================
50 The configuration of all features of the MSS GPIO peripherals is covered by
51 this driver with the exception of the PolarFire SoC IOMUX configuration.
52 PolarFire SoC allows multiple non-concurrent uses of some external pins
53 through IOMUX configuration. This feature allows optimization of external pin
54 usage by assigning external pins for use by either the microprocessor
55 subsystem or the FPGA fabric. The MSS GPIO signals are routed through
56 IOMUXs to the PolarFire SoC device external pins. The MSS GPIO serial
57 signals may also be routed through IOMUXs to the PolarFire SoC FPGA fabric.
58 For more information on IOMUX, refer to the IOMUX section of the PolarFire SoC
59 Microprocessor Subsystem (MSS) User's Guide.
60
61 The IOMUXs are configured using the PolarFire SoC MSS configurator tool. You
62 must ensure that the MSS GPIO peripherals are enabled and configured in the
63 PolarFire SoC MSS configurator if you wish to use them. For more information
64 on IOMUXs, refer to the IOMUX section of the PolarFire SoC microprocessor
65 Subsystem (MSS) User's Guide.
66
67 On PolarFire SoC an AXI switch forms a bus matrix interconnect among multiple
68 masters and multiple slaves. Five RISC-V CPUs connect to the Master ports
69 M10 to M14 of the AXI switch. By default, all the APB peripherals are
70 accessible on AXI-Slave 5 of the AXI switch via the AXI to AHB and AHB to APB
71 bridges (referred as main APB bus). However, to support logical separation in
72 the Asymmetric Multi-Processing (AMP) mode of operation, the APB peripherals
73 can alternatively be accessed on the AXI-Slave 6 via the AXI to AHB and AHB to
74 APB bridges (referred as the AMP APB bus).
75
76 Application must make sure that the desired GPIO instance is appropriately
77 configured on one of the APB bus described above by configuring the PolarFire
78 SoC system registers (SYSREG) as per the application need and that the
79 appropriate data structures are provided to this driver as parameter to the
80 functions provided by this driver.
81
82 The base address and register addresses are defined in this driver as
83 constants. The interrupt number assignment for the MSS GPIO peripherals are
84 defined as constants in the MPFS HAL. You must ensure that the latest MPFS HAL
85 is included in the project settings of the SoftConsole tool chain and that it
86 is generated into your project.
87
88 ==============================================================================
89 Theory of Operation
90 ==============================================================================
91 The MSS GPIO driver functions are grouped into the following categories:
92 - Initialization
93 - Configuration
94 - Reading and setting GPIO state
95 - Interrupt control
96
97 --------------------------------
98 Initialization
99 --------------------------------
100 The MSS GPIO driver is initialized through a call to the MSS_GPIO_init()
101 function. The MSS_GPIO_init() function must be called before any other MSS
102 GPIO driver functions can be called.
103
104 --------------------------------
105 Configuration
106 --------------------------------
107 Each GPIO port is individually configured through a call to the
108 MSS_GPIO_config() function. Configuration includes deciding if a GPIO port
109 will be used as an input, an output or both. GPIO ports configured as inputs
110 can be further configured to generate interrupts based on the input's state.
111 Interrupts can be level or edge sensitive. The MSS_GPIO_config_byte() function
112 can be used to configure eight consecutive GPIO ports identically. The
113 MSS_GPIO_config_byte() function can be used to configure all available GPIO
114 ports identically.
115
116 --------------------------------
117 Reading and Setting GPIO State
118 --------------------------------
119 The state of the GPIO ports can be read and set using the following functions:
120 - MSS_GPIO_get_inputs()
121 - MSS_GPIO_get_outputs()
122 - MSS_GPIO_set_outputs()
123 - MSS_GPIO_set_output()
124 - MSS_GPIO_drive_inout()
125
126 --------------------------------
127 Interrupt Control
128 --------------------------------
129 Interrupts generated by GPIO ports configured as inputs are controlled using
130 the following functions:
131 - MSS_GPIO_enable_irq()
132 - MSS_GPIO_disable_irq()
133 - MSS_GPIO_clear_irq()
134 - MSS_GPIO_get_irq()
135 - MSS_GPIO_enable_nondirect_irq()
136 - MSS_GPIO_disable_nondirect_irq()
137
138 The GPIO interrupts are multiplexed. Total GPIO interrupt inputs on PLIC are
139 41.
140
141 41 = (14 from GPIO0 + 24 from GPIO1 + 3 non direct interrupts)
142 GPIO2 interrupts are not available by default. Setting the corresponding bit
143 in GPIO_INTERRUPT_FAB_CR(31:0) system register will enable GPIO2(31:0)
144 corresponding interrupt on PLIC. e.g. If GPIO_INTERRUPT_FAB_CR bit0 is set
145 then GPIO2 bit0 interrupt is available on the direct input pin on the PLIC.
146 In this case GPIO0 bit 0 interrupt will not be available on the direct input
147 pin on the PLIC however, the GPIO0 non-direct input will be asserted as OR of
148 all the GPIO0 interrupts which don't have a direct interrupt input on PLIC are
149 connected to corresponding non-direct input pin. The table below explains all
150 the GPIO direct and non-direct interrupt connectivity options.
151
152 | PLIC | GPIO_INTERRUPT_FAB_CR = 0 | GPIO_INTERRUPT_FAB_CR = 1 |
153 |------|---------------------------|---------------------------|
154 | 0 | GPIO0 bit 0 | GPIO2 bit 0 |
155 | 1 | GPIO0 bit 1 | GPIO2 bit 1 |
156 | ... | ... | ... |
157 | 12 | GPIO0 bit 12 | GPIO2 bit 12 |
158 | 13 | GPIO0 bit 13 | GPIO2 bit 13 |
159 | 14 | GPIO1 bit 0 | GPIO2 bit 14 |
160 | 15 | GPIO1 bit 1 | GPIO2 bit 15 |
161 | ... | ... | ... |
162 | 30 | GPIO1 bit 16 | GPIO2 bit 30 |
163 | 31 | GPIO1 bit 17 | GPIO2 bit 31 |
164
165
166 | PLIC | Interrupt source |
167 |------|----------------------------------------------------------------------|
168 | 32 | GPIO1 bit 18 |
169 | 33 | GPIO1 bit 19 |
170 | 34 | GPIO1 bit 20 |
171 | 35 | GPIO1 bit 21 |
172 | 36 | GPIO1 bit 22 |
173 | 37 | GPIO1 bit 23 |
174 | 38 | OR of all GPIO0 interrupts who don't have a direct connection enabled|
175 | 39 | OR of all GPIO1 interrupts who don't have a direct connection enabled|
176 | 40 | OR of all GPIO2 interrupts who don't have a direct connection enabled|
177
178
179 NOTE: GPIO_INTERRUPT_FAB_CR controls the multiplexing in above table. It is
180 your responsibility to set up the GPIO_INTERRUPT_FAB_CR bits in application
181 code. you must make sure that you are using the valid combination of
182 GPIO0/1/2 interrupt per above table.
183
184 *//*=========================================================================*/
185 #ifndef MSS_GPIO_H_
186 #define MSS_GPIO_H_
187
188 #ifdef __cplusplus
189 extern "C" {
190 #endif
191
192 #include <stdint.h>
193
194 /*-------------------------------------------------------------------------*//**
195 The mss_gpio_id_t enumeration is used to identify individual GPIO ports as an
196 argument to functions:
197 - MSS_GPIO_config()
198 - MSS_GPIO_set_output() and MSS_GPIO_drive_inout()
199 - MSS_GPIO_enable_irq(), MSS_GPIO_disable_irq() and MSS_GPIO_clear_irq()
200
201 Note that the GPIO0, GPIO1 and GPIO2 blocks have 14, 24 and 32 GPIO ports
202 respectively.
203 */
204 typedef enum mss_gpio_id
205 {
206 MSS_GPIO_0 = 0,
207 MSS_GPIO_1 = 1,
208 MSS_GPIO_2 = 2,
209 MSS_GPIO_3 = 3,
210 MSS_GPIO_4 = 4,
211 MSS_GPIO_5 = 5,
212 MSS_GPIO_6 = 6,
213 MSS_GPIO_7 = 7,
214 MSS_GPIO_8 = 8,
215 MSS_GPIO_9 = 9,
216 MSS_GPIO_10 = 10,
217 MSS_GPIO_11 = 11,
218 MSS_GPIO_12 = 12,
219 MSS_GPIO_13 = 13,
220 MSS_GPIO_14 = 14,
221 MSS_GPIO_15 = 15,
222 MSS_GPIO_16 = 16,
223 MSS_GPIO_17 = 17,
224 MSS_GPIO_18 = 18,
225 MSS_GPIO_19 = 19,
226 MSS_GPIO_20 = 20,
227 MSS_GPIO_21 = 21,
228 MSS_GPIO_22 = 22,
229 MSS_GPIO_23 = 23,
230 MSS_GPIO_24 = 24,
231 MSS_GPIO_25 = 25,
232 MSS_GPIO_26 = 26,
233 MSS_GPIO_27 = 27,
234 MSS_GPIO_28 = 28,
235 MSS_GPIO_29 = 29,
236 MSS_GPIO_30 = 30,
237 MSS_GPIO_31 = 31
238 } mss_gpio_id_t;
239
240 /*-------------------------------------------------------------------------*//**
241 The mss_gpio_inout_state_t enumeration is used to specify the output state of
242 an INOUT GPIO port as an argument to the MSS_GPIO_drive_inout() function.
243 */
244 typedef enum mss_gpio_inout_state
245 {
246 MSS_GPIO_DRIVE_LOW = 0,
247 MSS_GPIO_DRIVE_HIGH,
248 MSS_GPIO_HIGH_Z
249 } mss_gpio_inout_state_t;
250
251 /*-------------------------------------------------------------------------*//**
252 The mss_gpio_byte_num_t enumeration is used to specify the set of the 8
253 consecutive GPIO ports that are to be configured as an argument to the
254 MSS_GPIO_config_byte() function.
255 */
256 typedef enum mss_gpio_byte_num
257 {
258 MSS_GPIO_BYTE_0 = 0,
259 MSS_GPIO_BYTE_1,
260 MSS_GPIO_BYTE_2,
261 MSS_GPIO_BYTE_3,
262 MSS_GPIO_BYTE_INVALID,
263 } mss_gpio_byte_num_t;
264
265 /*-------------------------------------------------------------------------*//**
266 GPIO Instance Identification
267 ============================
268 These constants are provided for the application use. These constants must be
269 passed as a first parameter of all the APIs provided by this driver. The
270 GPIO0_LO, GPIO1_LO, GPIO2_LO represent the GPIO0, GPIO1 and GPIO2 hardware
271 blocks when they are connected on the main APB bus. The GPIO0_HI, GPIO1_HI,
272 GPIO2_HI represent the GPIO0, GPIO1 and GPIO2 hardware blocks when they are
273 connected on the AMP APB bus.
274
275 | Constant | Description |
276 |----------|---------------------------------------|
277 | GPIO0_LO | GPIO0 block connected on main APB bus |
278 | GPIO1_LO | GPIO1 block connected on main APB bus |
279 | GPIO2_LO | GPIO2 block connected on main APB bus |
280 | GPIO0_HI | GPIO0 block connected on AMP APB bus |
281 | GPIO1_HI | GPIO1 block connected on AMP APB bus |
282 | GPIO2_HI | GPIO2 block connected on AMP APB bus |
283
284 */
285 #define GPIO0_LO ((GPIO_TypeDef*)0x20120000UL)
286 #define GPIO1_LO ((GPIO_TypeDef*)0x20121000UL)
287 #define GPIO2_LO ((GPIO_TypeDef*)0x20122000UL)
288 #define GPIO0_HI ((GPIO_TypeDef*)0x28120000UL)
289 #define GPIO1_HI ((GPIO_TypeDef*)0x28121000UL)
290 #define GPIO2_HI ((GPIO_TypeDef*)0x28122000UL)
291
292 /*-------------------------------------------------------------------------*//**
293 GPIO Port Masks
294 ===============
295 These constant definitions are used as an argument to the
296 MSS_GPIO_set_outputs() function to identify GPIO ports. A logical OR of these
297 constants can be used to specify multiple GPIO ports.
298 These definitions can also be used to identify GPIO ports through logical
299 operations on the return value of the MSS_GPIO_get_inputs() function.
300
301 | Constant | Description |
302 |------------------|-----------------------|
303 | MSS_GPIO_0_MASK | GPIO port 0-bit mask |
304 | MSS_GPIO_1_MASK | GPIO port 1-bit mask |
305 | MSS_GPIO_2_MASK | GPIO port 2-bit mask |
306 | MSS_GPIO_3_MASK | GPIO port 3-bit mask |
307 | MSS_GPIO_4_MASK | GPIO port 4-bit mask |
308 | MSS_GPIO_5_MASK | GPIO port 5-bit mask |
309 | MSS_GPIO_6_MASK | GPIO port 6-bit mask |
310 | MSS_GPIO_7_MASK | GPIO port 7-bit mask |
311 | MSS_GPIO_8_MASK | GPIO port 8-bit mask |
312 | MSS_GPIO_9_MASK | GPIO port 9-bit mask |
313 | MSS_GPIO_10_MASK | GPIO port 10-bit mask |
314 | MSS_GPIO_11_MASK | GPIO port 11-bit mask |
315 | MSS_GPIO_12_MASK | GPIO port 12-bit mask |
316 | MSS_GPIO_13_MASK | GPIO port 13-bit mask |
317 | MSS_GPIO_14_MASK | GPIO port 14-bit mask |
318 | MSS_GPIO_15_MASK | GPIO port 15-bit mask |
319 | MSS_GPIO_16_MASK | GPIO port 16-bit mask |
320 | MSS_GPIO_17_MASK | GPIO port 17-bit mask |
321 | MSS_GPIO_18_MASK | GPIO port 18-bit mask |
322 | MSS_GPIO_19_MASK | GPIO port 19-bit mask |
323 | MSS_GPIO_20_MASK | GPIO port 20-bit mask |
324 | MSS_GPIO_21_MASK | GPIO port 21-bit mask |
325 | MSS_GPIO_22_MASK | GPIO port 22-bit mask |
326 | MSS_GPIO_23_MASK | GPIO port 23-bit mask |
327 | MSS_GPIO_24_MASK | GPIO port 24-bit mask |
328 | MSS_GPIO_25_MASK | GPIO port 25-bit mask |
329 | MSS_GPIO_26_MASK | GPIO port 26-bit mask |
330 | MSS_GPIO_27_MASK | GPIO port 27-bit mask |
331 | MSS_GPIO_28_MASK | GPIO port 28-bit mask |
332 | MSS_GPIO_29_MASK | GPIO port 29-bit mask |
333 | MSS_GPIO_30_MASK | GPIO port 30-bit mask |
334 | MSS_GPIO_31_MASK | GPIO port 31-bit mask |
335
336 */
337 #define MSS_GPIO_0_MASK 0x00000001UL
338 #define MSS_GPIO_1_MASK 0x00000002UL
339 #define MSS_GPIO_2_MASK 0x00000004UL
340 #define MSS_GPIO_3_MASK 0x00000008UL
341 #define MSS_GPIO_4_MASK 0x00000010UL
342 #define MSS_GPIO_5_MASK 0x00000020UL
343 #define MSS_GPIO_6_MASK 0x00000040UL
344 #define MSS_GPIO_7_MASK 0x00000080UL
345 #define MSS_GPIO_8_MASK 0x00000100UL
346 #define MSS_GPIO_9_MASK 0x00000200UL
347 #define MSS_GPIO_10_MASK 0x00000400UL
348 #define MSS_GPIO_11_MASK 0x00000800UL
349 #define MSS_GPIO_12_MASK 0x00001000UL
350 #define MSS_GPIO_13_MASK 0x00002000UL
351 #define MSS_GPIO_14_MASK 0x00004000UL
352 #define MSS_GPIO_15_MASK 0x00008000UL
353 #define MSS_GPIO_16_MASK 0x00010000UL
354 #define MSS_GPIO_17_MASK 0x00020000UL
355 #define MSS_GPIO_18_MASK 0x00040000UL
356 #define MSS_GPIO_19_MASK 0x00080000UL
357 #define MSS_GPIO_20_MASK 0x00100000UL
358 #define MSS_GPIO_21_MASK 0x00200000UL
359 #define MSS_GPIO_22_MASK 0x00400000UL
360 #define MSS_GPIO_23_MASK 0x00800000UL
361 #define MSS_GPIO_24_MASK 0x01000000UL
362 #define MSS_GPIO_25_MASK 0x02000000UL
363 #define MSS_GPIO_26_MASK 0x04000000UL
364 #define MSS_GPIO_27_MASK 0x08000000UL
365 #define MSS_GPIO_28_MASK 0x10000000UL
366 #define MSS_GPIO_29_MASK 0x20000000UL
367 #define MSS_GPIO_30_MASK 0x40000000UL
368 #define MSS_GPIO_31_MASK 0x80000000UL
369
370 /*-------------------------------------------------------------------------*//**
371 GPIO Port I/O Mode
372 ==================
373 These constant definitions are used as an argument to the MSS_GPIO_config()
374 function to specify the I/O mode of each GPIO port.
375
376 | Constant | Description |
377 |----------------------|----------------------------|
378 | MSS_GPIO_INPUT_MODE | Input port only |
379 | MSS_GPIO_OUTPUT_MODE | Output port only |
380 | MSS_GPIO_INOUT_MODE | Both input and output port |
381
382 */
383 #define MSS_GPIO_INPUT_MODE 0x0000000002UL
384 #define MSS_GPIO_OUTPUT_MODE 0x0000000005UL
385 #define MSS_GPIO_INOUT_MODE 0x0000000003UL
386
387 /*-------------------------------------------------------------------------*//**
388 GPIO Interrupt Mode
389 ===================
390 These constant definitions are used as an argument to the MSS_GPIO_config()
391 function to specify the interrupt mode of each GPIO port.
392
393 | Constant | Description |
394 |----------------------------|-----------------------------------------------------|
395 | MSS_GPIO_IRQ_LEVEL_HIGH | Interrupt on GPIO input level High |
396 | MSS_GPIO_IRQ_LEVEL_LOW | Interrupt on GPIO input level Low |
397 | MSS_GPIO_IRQ_EDGE_POSITIVE | Interrupt on GPIO input positive edge |
398 | MSS_GPIO_IRQ_EDGE_NEGATIVE | Interrupt on GPIO input negative edge |
399 | MSS_GPIO_IRQ_EDGE_BOTH | Interrupt on GPIO input positive and negative edges |
400
401 */
402 #define MSS_GPIO_IRQ_LEVEL_HIGH 0x0000000000UL
403 #define MSS_GPIO_IRQ_LEVEL_LOW 0x0000000020UL
404 #define MSS_GPIO_IRQ_EDGE_POSITIVE 0x0000000040UL
405 #define MSS_GPIO_IRQ_EDGE_NEGATIVE 0x0000000060UL
406 #define MSS_GPIO_IRQ_EDGE_BOTH 0x0000000080UL
407
408 /*------------------------Private data structures-----------------------------*/
409 /*----------------------------------- GPIO -----------------------------------*/
410 /*----------------------------------------------------------------------------*/
411 typedef struct
412 {
413 volatile uint32_t GPIO_CFG[32];
414 volatile uint32_t GPIO_IRQ;
415 volatile const uint32_t GPIO_IN;
416 volatile uint32_t GPIO_OUT;
417 volatile uint32_t GPIO_CFG_ALL;
418 volatile uint32_t GPIO_CFG_BYTE[4];
419 volatile uint32_t GPIO_CLR_BITS;
420 volatile uint32_t GPIO_SET_BITS;
421
422 } GPIO_TypeDef;
423
424 /*--------------------------------Public APIs---------------------------------*/
425
426 /*-------------------------------------------------------------------------*//**
427 The MSS_GPIO_init() function initializes the PolarFire SoC MSS GPIO block. It
428 resets the MSS GPIO hardware block and it also clears any pending MSS GPIO
429 interrupts in the interrupt controller. When the function exits,
430 it takes the MSS GPIO block out of reset.
431
432 @param gpio
433 The gpio parameter specifies the GPIO block that needs to be configured
434
435 @return
436 This function does not return a value.
437
438 Example:
439 @code
440 #include "mss_gpio.h"
441 int main(void)
442 {
443 MSS_GPIO_init(GPIO0_LO);
444 MSS_GPIO_config(GPIO0_LO, MSS_GPIO_4, MSS_GPIO_INPUT_MODE |
445 MSS_GPIO_IRQ_EDGE_POSITIVE );
446 return (0u);
447 }
448 @endcode
449 */
450 void MSS_GPIO_init
451 (
452 GPIO_TypeDef * gpio
453 );
454
455 /*-------------------------------------------------------------------------*//**
456 The MSS_GPIO_config() function is used to configure an individual GPIO port.
457
458 @param gpio
459 The gpio parameter specifies the GPIO block that needs to be configured
460
461 @param port_id
462 The port_id parameter identifies the GPIO port to be configured. An
463 enumeration item of the form MSS_GPIO_n, where n is the number of the GPIO
464 port, is used to identify the GPIO port. For example, MSS_GPIO_0 identifies
465 the first GPIO port and MSS_GPIO_31 is the last one.
466
467 @param config
468 The config parameter specifies the configuration to be applied to the GPIO
469 port identified by the port_id parameter. It is a logical OR of the required
470 I/O mode and the required interrupt mode. The interrupt mode is not relevant
471 if the GPIO is configured as an output only.
472 These I/O mode constants are allowed:
473 - MSS_GPIO_INPUT_MODE
474 - MSS_GPIO_OUTPUT_MODE
475 - MSS_GPIO_INOUT_MODE
476 These interrupt mode constants are allowed:
477 - MSS_GPIO_IRQ_LEVEL_HIGH
478 - MSS_GPIO_IRQ_LEVEL_LOW
479 - MSS_GPIO_IRQ_EDGE_POSITIVE
480 - MSS_GPIO_IRQ_EDGE_NEGATIVE
481 - MSS_GPIO_IRQ_EDGE_BOTH
482
483 @return
484 This function does not return any value.
485
486 Example:
487 The following call will configure GPIO 4 on GPIO0 hardware block on main APB
488 bus as an input generating interrupts on a Low to High transition of the input
489 @code
490 #include "mss_gpio.h"
491 int main(void)
492 {
493 MSS_GPIO_init(GPIO0_LO);
494 MSS_GPIO_config(GPIO0_LO, MSS_GPIO_4, MSS_GPIO_INPUT_MODE |
495 MSS_GPIO_IRQ_EDGE_POSITIVE );
496 return (0u);
497 }
498 @endcode
499 */
500 void MSS_GPIO_config
501 (
502 GPIO_TypeDef * gpio,
503 mss_gpio_id_t port_id,
504 uint32_t config
505 );
506
507 /*-------------------------------------------------------------------------*//**
508 The MSS_GPIO_set_outputs() function is used to set the state of all GPIO ports
509 configured as outputs.
510
511 @param gpio
512 The gpio parameter specifies the GPIO block that needs to be configured
513
514 @param value
515 The value parameter specifies the state of the GPIO ports configured as
516 outputs. It is a bit mask of the form (MSS_GPIO_n_MASK | MSS_GPIO_m_MASK)
517 where n and m are numbers identifying GPIOs. For example, (MSS_GPIO_0_MASK |
518 MSS_GPIO_1_MASK | MSS_GPIO_2_MASK ) specifies that the first, second and
519 third GPIO outputs must be set High and all other GPIO outputs set Low. The
520 driver provides 32 mask constants, MSS_GPIO_0_MASK to MSS_GPIO_31_MASK
521 inclusive, for this purpose.
522
523 @return
524 This function does not return any value.
525
526 Example 1:
527 Set GPIOs outputs 0 and 8 high and all other GPIO outputs low.
528 @code
529 #include "mss_gpio.h"
530 int main(void)
531 {
532 MSS_GPIO_init(GPIO0_LO);
533 MSS_GPIO_config(GPIO0_LO, MSS_GPIO_4, MSS_GPIO_INPUT_MODE |
534 MSS_GPIO_IRQ_EDGE_POSITIVE );
535 MSS_GPIO_set_outputs(GPIO0_LO, MSS_GPIO_0_MASK | MSS_GPIO_8_MASK );
536 return (0u);
537 }
538
539 @endcode
540
541 Example 2:
542 Set GPIOs outputs 2 and 4 low without affecting other GPIO outputs.
543 @code
544 #include "mss_gpio.h"
545 int main(void)
546 {
547 uint32_t gpio_outputs;
548 MSS_GPIO_init(GPIO0_LO);
549 MSS_GPIO_config(GPIO0_LO, MSS_GPIO_4, MSS_GPIO_INPUT_MODE |
550 MSS_GPIO_IRQ_EDGE_POSITIVE );
551
552 gpio_outputs = MSS_GPIO_get_outputs();
553 gpio_outputs &= ~( MSS_GPIO_2_MASK | MSS_GPIO_4_MASK );
554 MSS_GPIO_set_outputs(GPIO0_LO, gpio_outputs );
555
556 return (0u);
557 }
558
559 @endcode
560
561 @see MSS_GPIO_get_outputs()
562 */
563 static inline void
MSS_GPIO_set_outputs(GPIO_TypeDef * gpio,uint32_t value)564 MSS_GPIO_set_outputs
565 (
566 GPIO_TypeDef * gpio,
567 uint32_t value
568 )
569 {
570 gpio->GPIO_OUT = value;
571 }
572
573 /*-------------------------------------------------------------------------*//**
574 The MSS_GPIO_config_all() function is used to configure all the ports of the
575 GPIO block. This function will apply the same configuration values to all the
576 GPIO ports.
577
578 @param gpio
579 The gpio parameter specifies the GPIO block that needs to be configured
580
581 @param config
582 The config parameter specifies the configuration to be applied to the all
583 the GPIO ports. It is a logical OR of the required I/O mode and the required
584 interrupt mode. The interrupt mode is not relevant if the GPIO is configured
585 as an output only.
586 These I/O mode constants are allowed:
587 - MSS_GPIO_INPUT_MODE
588 - MSS_GPIO_OUTPUT_MODE
589 - MSS_GPIO_INOUT_MODE
590 These interrupt mode constants are allowed:
591 - MSS_GPIO_IRQ_LEVEL_HIGH
592 - MSS_GPIO_IRQ_LEVEL_LOW
593 - MSS_GPIO_IRQ_EDGE_POSITIVE
594 - MSS_GPIO_IRQ_EDGE_NEGATIVE
595 - MSS_GPIO_IRQ_EDGE_BOTH
596
597 @return
598 This function does not return any value.
599
600 Example:
601 @code
602 #include "mss_gpio.h"
603 int main(void)
604 {
605 MSS_GPIO_init(GPIO0_LO);
606 MSS_GPIO_config_all(GPIO0_LO, MSS_GPIO_INPUT_MODE |
607 MSS_GPIO_IRQ_EDGE_POSITIVE );
608 return (0u);
609 }
610 @endcode
611 */
612 void MSS_GPIO_config_all
613 (
614 GPIO_TypeDef * gpio,
615 uint32_t config
616 );
617
618 /*-------------------------------------------------------------------------*//**
619 The MSS_GPIO_config_byte() function is used to byte wise (consecutive 8 ports)
620 configure the gpio ports.
621
622 @param gpio
623 The gpio parameter specifies the GPIO block that needs to be configured.
624
625 @param byte_num
626 The byte_num parameter specifies the byte (consecutive 8 ports) which needs
627 to be configured. The value 0 indicates the bunch from gpio port0 to gpio
628 port7. Value of 3 indicates the bunch from gpio port25 to gpio port31.
629 When you use this function, you must make sure that the gpio ports that
630 you are trying to configure do exist for that GPIO hardware block.
631 GPIO0 has 14 ports.GPIO1 has 24 ports.GPIO3 has 32 ports.
632
633 @param config
634 The config parameter specifies the configuration to be applied to the GPIO
635 byte identified by the byte_num parameter. It is a logical OR of the
636 required I/O mode and the required interrupt mode. The interrupt mode is not
637 relevant if the GPIO is configured as an output only.
638 These I/O mode constants are allowed:
639 - MSS_GPIO_INPUT_MODE
640 - MSS_GPIO_OUTPUT_MODE
641 - MSS_GPIO_INOUT_MODE
642 These interrupt mode constants are allowed:
643 - MSS_GPIO_IRQ_LEVEL_HIGH
644 - MSS_GPIO_IRQ_LEVEL_LOW
645 - MSS_GPIO_IRQ_EDGE_POSITIVE
646 - MSS_GPIO_IRQ_EDGE_NEGATIVE
647 - MSS_GPIO_IRQ_EDGE_BOTH
648
649 @return
650 This function does not return any value.
651
652 Example:
653 @code
654 #include "mss_gpio.h"
655 int main(void)
656 {
657 MSS_GPIO_init(GPIO0_LO);
658 MSS_GPIO_config_byte(GPIO0_LO, MSS_GPIO_BYTE_1, MSS_GPIO_INPUT_MODE |
659 MSS_GPIO_IRQ_EDGE_POSITIVE );
660 return (0u);
661 }
662 @endcode
663 */
664 void MSS_GPIO_config_byte
665 (
666 GPIO_TypeDef * gpio,
667 mss_gpio_byte_num_t byte_num,
668 uint32_t config
669 );
670
671 /*-------------------------------------------------------------------------*//**
672 The MSS_GPIO_set_output() function is used to set the state of a single GPIO
673 port configured as an output.
674
675 @param gpio
676 The gpio parameter specifies the GPIO block that needs to be configured
677
678 @param port_id
679 The port_id parameter identifies the GPIO port that is to have its output
680 set. An enumeration item of the form MSS_GPIO_n, where n is the number of
681 the GPIO port, is used to identify the GPIO port. For example, MSS_GPIO_0
682 identifies the first GPIO port and MSS_GPIO_31 is the last one.
683
684 @param value
685 The value parameter specifies the desired state for the GPIO output. A value
686 of 0 will set the output Low and a value of 1 will set the output High.
687
688 @return
689 This function does not return a value.
690
691 Example:
692 The following call will set GPIO output 12 High, leaving all other GPIO
693 outputs unaffected:
694 @code
695 #include "mss_gpio.h"
696 int main(void)
697 {
698 MSS_GPIO_init(GPIO0_LO);
699 MSS_GPIO_config_all(GPIO0_LO, MSS_GPIO_INOUT_MODE);
700 MSS_GPIO_set_output(GPIO0_LO, MSS_GPIO_13, 1);
701 return (0u);
702 }
703 @endcode
704 */
705 void MSS_GPIO_set_output
706 (
707 GPIO_TypeDef * gpio,
708 mss_gpio_id_t port_id,
709 uint8_t value
710 );
711
712 /*-------------------------------------------------------------------------*//**
713 The MSS_GPIO_get_inputs() function is used to read the current state all GPIO
714 ports configured as inputs.
715
716 @param gpio
717 The gpio parameter specifies the GPIO block that needs to be configured
718
719 @return
720 This function returns a 32-bit unsigned integer where each bit represents
721 the state of a GPIO input. The least significant bit represents the state of
722 GPIO input 0 and the most significant bit the state of GPIO input 31.
723
724 Example:
725 Read and assign the current state of the GPIO outputs to a variable.
726 @code
727 #include "mss_gpio.h"
728 int main(void)
729 {
730 uint32_t gpio_inputs;
731 MSS_GPIO_init(GPIO0_LO);
732 MSS_GPIO_config_all(GPIO0_LO, MSS_GPIO_INOUT_MODE);
733 gpio_inputs = MSS_GPIO_get_inputs(GPIO0_LO);
734 return (0u);
735 }
736 @endcode
737 */
738 static inline uint32_t
MSS_GPIO_get_inputs(GPIO_TypeDef const * gpio)739 MSS_GPIO_get_inputs( GPIO_TypeDef const * gpio )
740 {
741 return gpio->GPIO_IN;
742 }
743
744 /*-------------------------------------------------------------------------*//**
745 The MSS_GPIO_enable_nondirect_irq() function is used to enable the non-direct
746 interrupt input at the PLIC.
747
748 @param gpio
749 The gpio parameter specifies the GPIO block that needs to be configured
750
751 @return
752 This function does not return any value.
753
754 Example:
755 Read and assign the current state of the GPIO outputs to a variable.
756 @code
757 #include "mss_gpio.h"
758 int main(void)
759 {
760 uint32_t gpio_inputs;
761 MSS_GPIO_init(GPIO0_LO);
762 MSS_GPIO_config_all(GPIO0_LO, MSS_GPIO_INOUT_MODE |
763 MSS_GPIO_IRQ_EDGE_POSITIVE);
764 MSS_GPIO_enable_nondirect_irq(GPIO1_LO);
765 return (0u);
766 }
767
768 @endcode
769 */
770 void
771 MSS_GPIO_enable_nondirect_irq
772 (
773 GPIO_TypeDef const * gpio
774 );
775
776 /*-------------------------------------------------------------------------*//**
777 The MSS_GPIO_disable_nondirect_irq() function is used to disable the
778 non-direct interrupt input at the PLIC.
779
780 @param gpio
781 The gpio parameter specifies the GPIO block that needs to be configured
782
783 @return
784 This function does not return any value.
785
786 Example:
787 @code
788 #include "mss_gpio.h"
789 int main(void)
790 {
791 uint32_t gpio_inputs;
792 MSS_GPIO_init(GPIO0_LO);
793 MSS_GPIO_config_all(GPIO0_LO, MSS_GPIO_INOUT_MODE |
794 MSS_GPIO_IRQ_EDGE_POSITIVE);
795 MSS_GPIO_disable_nondirect_irq(GPIO1_LO);
796 return (0u);
797 }
798 @endcode
799 */
800 void
801 MSS_GPIO_disable_nondirect_irq
802 (
803 GPIO_TypeDef const * gpio
804 );
805
806 /*-------------------------------------------------------------------------*//**
807 The MSS_GPIO_get_outputs() function is used to read the current state of all
808 GPIO ports configured as outputs.
809
810 @param gpio
811 The gpio parameter specifies the GPIO block that needs to be configured
812
813 @return
814 This function returns a 32-bit unsigned integer where each bit represents
815 the state of a GPIO output. The least significant bit represents the state
816 of GPIO output 0 and the most significant bit the state of GPIO output 31.
817
818 Example:
819 Read and assign the current state of the GPIO outputs to a variable.
820 @code
821 #include "mss_gpio.h"
822 int main(void)
823 {
824 uint32_t gpio_outputs;
825 MSS_GPIO_init(GPIO0_LO);
826 MSS_GPIO_config(GPIO0_LO, MSS_GPIO_4, MSS_GPIO_INPUT_MODE |
827 MSS_GPIO_IRQ_EDGE_POSITIVE );
828
829 gpio_outputs = MSS_GPIO_get_outputs();
830 gpio_outputs &= ~( MSS_GPIO_2_MASK | MSS_GPIO_4_MASK );
831 MSS_GPIO_set_outputs( gpio_outputs );
832
833 return (0u);
834 }
835 @endcode
836 */
837 static inline uint32_t
MSS_GPIO_get_outputs(GPIO_TypeDef const * gpio)838 MSS_GPIO_get_outputs( GPIO_TypeDef const * gpio )
839 {
840 return gpio->GPIO_OUT;
841 }
842
843 /*-------------------------------------------------------------------------*//**
844 The MSS_GPIO_get_irq() function is used to read the current value of the IRQ
845 register. The GPIO interrupts are multiplexed. The GPIO interrupts which are
846 not available on the direct GPIO interrupt line on the PLIC are ORed and
847 routed to the non-direct interrupt line on the PLIC for the corresponding
848 GPIO hardware block. When the non-direct interrupt is asserted, this function
849 can be used to determine which exact GPIO bit(s) caused the interrupt.
850
851 @param gpio
852 The gpio parameter specifies the GPIO block that needs to be configured
853
854 @return
855 This function returns a 32-bit unsigned integer value of the IRQ register.
856
857 Example:
858 In the non-direct interrupt ISR, read the IRQ register to know which are
859 the GPIO port causing the interrupt.
860
861 @code
862 uint8_t gpio2_non_direct_plic_IRQHandler(void)
863 {
864 uint32_t intr_num = 0;
865 intr_num = MSS_GPIO_get_irq(GPIO2_LO);
866
867 for(int cnt=0; cnt<32; cnt++)
868 {
869 if (1u == (intr_num & 0x00000001U))
870 {
871 MSS_GPIO_clear_irq(GPIO0_LO, (mss_gpio_id_t)cnt);
872 }
873
874 intr_num >>= 1u;
875 }
876
877 return EXT_IRQ_KEEP_ENABLED;
878 }
879 @endcode
880 */
881 static inline uint32_t
MSS_GPIO_get_irq(GPIO_TypeDef const * gpio)882 MSS_GPIO_get_irq( GPIO_TypeDef const * gpio )
883 {
884 return gpio->GPIO_IRQ;
885 }
886
887 /*-------------------------------------------------------------------------*//**
888 The MSS_GPIO_drive_inout() function is used to set the output state of a
889 single GPIO port configured as an INOUT. An INOUT GPIO can be in one of three
890 states:
891 - High
892 - Low
893 - High impedance
894
895 An INOUT output would typically be used where several devices can drive the
896 state of a shared signal line. The High and Low states are equivalent to the
897 High and Low states of a GPIO configured as an output. The High impedance
898 state is used to prevent the GPIO from driving its output state onto the
899 signal line, while at the same time allowing the input state of the GPIO to
900 be read.
901
902 @param gpio
903 The gpio parameter specifies the GPIO block that needs to be configured
904
905 @param port_id
906 The port_id parameter identifies the GPIO port for which you want to change
907 the output state. An enumeration item of the form MSS_GPIO_n, where n is the
908 number of the GPIO port, is used to identify the GPIO port. For example,
909 MSS_GPIO_0 identifies the first GPIO port and MSS_GPIO_31 is the last one.
910
911 @param inout_state
912 The inout_state parameter specifies the state of the GPIO port identified by
913 the port_id parameter. Allowed values of type mss_gpio_inout_state_t are as
914 follows:
915 - MSS_GPIO_DRIVE_HIGH
916 - MSS_GPIO_DRIVE_LOW
917 - MSS_GPIO_HIGH_Z (High impedance)
918
919 @return
920 This function does not return a value.
921
922 Example:
923 The call to MSS_GPIO_drive_inout() below will set the GPIO 7 output to the
924 high impedance state.
925 @code
926 #include "mss_gpio.h"
927 int main(void)
928 {
929 uint32_t gpio_inputs;
930 MSS_GPIO_init(GPIO0_LO);
931 MSS_GPIO_config_all(GPIO0_LO, MSS_GPIO_INOUT_MODE |
932 MSS_GPIO_IRQ_EDGE_POSITIVE);
933 MSS_GPIO_drive_inout(GPIO0_LO, MSS_GPIO_7, MSS_GPIO_HIGH_Z);
934 return (0u);
935 }
936 @endcode
937 */
938 void MSS_GPIO_drive_inout
939 (
940 GPIO_TypeDef * gpio,
941 mss_gpio_id_t port_id,
942 mss_gpio_inout_state_t inout_state
943 );
944
945 /*-------------------------------------------------------------------------*//**
946 The MSS_GPIO_enable_irq() function is used to enable interrupt generation for
947 the specified GPIO input. Interrupts are generated based on the state of the
948 GPIO input and the interrupt mode configured for it by MSS_GPIO_config(). This
949 function enables the corresponding GPIO direct interrupt on the PLIC as well.
950
951 @param gpio
952 The gpio parameter specifies the GPIO block that needs to be configured
953
954 @param port_id
955 The port_id parameter identifies the GPIO port for which you want to enable
956 interrupt generation. An enumeration item of the form MSS_GPIO_n, where n is
957 the number of the GPIO port, is used to identify the GPIO port. For example,
958 MSS_GPIO_0 identifies the first GPIO port and MSS_GPIO_31 is the last one in
959 GPIO2 block.
960
961 @return
962 This function does not return a value.
963
964 Example:
965 The call to MSS_GPIO_enable_irq() below will allow GPIO 8 to generate
966 interrupts.
967 @code
968 #include "mss_gpio.h"
969 int main(void)
970 {
971 uint32_t gpio_inputs;
972 MSS_GPIO_init(GPIO0_LO);
973 MSS_GPIO_config_all(GPIO0_LO, MSS_GPIO_INOUT_MODE |
974 MSS_GPIO_IRQ_EDGE_POSITIVE);
975 MSS_GPIO_enable_irq(GPIO0_LO, MSS_GPIO_8);
976 return (0u);
977 }
978
979 @endcode
980 */
981 void MSS_GPIO_enable_irq
982 (
983 GPIO_TypeDef * gpio,
984 mss_gpio_id_t port_id
985 );
986
987 /*-------------------------------------------------------------------------*//**
988 The MSS_GPIO_disable_irq() function is used to disable interrupt generation
989 for the specified GPIO input. This function disables the corresponding GPIO
990 direct interrupt on the PLIC as well.
991
992 @param gpio
993 The gpio parameter specifies the GPIO block that needs to be configured
994
995 @param port_id
996 The port_id parameter identifies the GPIO port for which you want to disable
997 interrupt generation. An enumeration item of the form MSS_GPIO_n, where n is
998 the number of the GPIO port, is used to identify the GPIO port. For example,
999 MSS_GPIO_0 identifies the first GPIO port and MSS_GPIO_31 is the last one.
1000
1001 @return
1002 This function does not return a value.
1003
1004 Example:
1005 The call to MSS_GPIO_disable_irq() below will prevent GPIO 8 from generating
1006 interrupts.
1007 @code
1008 MSS_GPIO_disable_irq( MSS_GPIO_8 );
1009 @endcode
1010 */
1011 void MSS_GPIO_disable_irq
1012 (
1013 GPIO_TypeDef * gpio,
1014 mss_gpio_id_t port_id
1015 );
1016
1017 /*-------------------------------------------------------------------------*//**
1018 The MSS_GPIO_clear_irq() function is used to clear a pending interrupt from
1019 the specified GPIO input.
1020
1021 Note: The MSS_GPIO_clear_irq() function must be called as part of any GPIO
1022 interrupt service routine (ISR) in order to prevent the same interrupt
1023 event retriggering a call to the GPIO ISR.
1024
1025 @param gpio
1026 The gpio parameter specifies the GPIO block that needs to be configured
1027
1028 @param port_id
1029 The port_id parameter identifies the GPIO port for which you want to clear
1030 the interrupt. An enumeration item of the form MSS_GPIO_n, where n is the
1031 number of the GPIO port, is used to identify the GPIO port. For example,
1032 MSS_GPIO_0 identifies the first GPIO port and MSS_GPIO_31 is the last one.
1033
1034 @return
1035 This function does not return a value.
1036
1037 Example:
1038 The example below demonstrates the use of the MSS_GPIO_clear_irq() function
1039 as part of the GPIO 9 interrupt service routine.
1040
1041 @code
1042 uint8_t gpio2_non_direct_plic_IRQHandler(void)
1043 {
1044 uint32_t intr_num = 0;
1045 intr_num = MSS_GPIO_get_irq(GPIO2_LO);
1046
1047 for(int cnt=0; cnt<32; cnt++)
1048 {
1049 if (1u == (intr_num & 0x00000001U))
1050 {
1051 MSS_GPIO_clear_irq(GPIO0_LO, (mss_gpio_id_t)cnt);
1052 }
1053
1054 intr_num >>= 1u;
1055 }
1056
1057 return EXT_IRQ_KEEP_ENABLED;
1058 }
1059 @endcode
1060 */
1061 void MSS_GPIO_clear_irq
1062 (
1063 GPIO_TypeDef * gpio,
1064 mss_gpio_id_t port_id
1065 );
1066
1067 #ifdef __cplusplus
1068 }
1069 #endif
1070
1071 #endif /* MSS_GPIO_H_ */
1072