1 /*******************************************************************************
2  * (c) Copyright 2008-2015 Microsemi SoC Products Group.  All rights reserved.
3  *
4  *  SmartFusion2 Microcontroller Subsystem GPIO bare metal software driver public
5  *  API.
6  *
7  * SVN $Revision: 7748 $
8  * SVN $Date: 2015-09-04 11:36:30 +0530 (Fri, 04 Sep 2015) $
9  */
10 
11 /*=========================================================================*//**
12   @mainpage SmartFusion2 MSS GPIO Bare Metal Driver.
13 
14   @section intro_sec Introduction
15   The SmartFusion2 Microcontroller Subsystem (MSS) includes a block of 32 general
16   purpose input/outputs (GPIO).
17   This software driver provides a set of functions for controlling the MSS GPIO
18   block as part of a bare metal system where no operating system is available.
19   This driver can be adapted for use as part of an operating system but the
20   implementation of the adaptation layer between this driver and the operating
21   system's driver model is outside the scope of this driver.
22 
23   @section hw_dependencies Hardware Flow Dependencies
24   The configuration of all features of the MSS GPIOs is covered by this driver
25   with the exception of the SmartFusion2 IOMUX configuration. SmartFusion2
26   allows multiple non-concurrent uses of some external pins through IOMUX
27   configuration. This feature allows optimization of external pin usage by
28   assigning external pins for use by either the microcontroller subsystem or the
29   FPGA fabric. The MSS GPIOs share SmartFusion2 device external pins with the
30   FPGA fabric and with other MSS peripherals via an IOMUX. The MSS GPIO ports
31   can alternatively be routed to the FPGA fabric through an IOMUX.
32   The IOMUXs are configured using the SmartFusion2 MSS configurator tool. You
33   must ensure that the MSS GPIOs are enabled and configured in the SmartFusion2
34   MSS configurator if you wish to use them. For more information on IOMUXs,
35   refer to the IOMUX section of the SmartFusion2 Microcontroller Subsystem (MSS)
36   User’s Guide.
37   The base address, register addresses and interrupt number assignment for the
38   MSS GPIO block are defined as constants in the SmartFusion2 CMSIS HAL. You
39   must ensure that the latest SmartFusion2 CMSIS HAL is included in the project
40   settings of the software tool chain used to build your project and that it is
41   generated into your project.
42 
43   @section theory_op Theory of Operation
44   The MSS GPIO driver functions are grouped into the following categories:
45     - Initialization
46     - Configuration
47     - Reading and setting GPIO state
48     - Interrupt control
49 
50   Initialization
51   The MSS GPIO driver is initialized through a call to the MSS_GPIO_init()
52   function. The MSS_GPIO_init() function must be called before any other MSS
53   GPIO driver functions can be called.
54 
55   Configuration
56   Each GPIO port is individually configured through a call to the
57   MSS_GPIO_config() function. Configuration includes deciding if a GPIO port
58   will be used as an input, an output or both. GPIO ports configured as inputs
59   can be further configured to generate interrupts based on the input's state.
60   Interrupts can be level or edge sensitive.
61 
62   Reading and Setting GPIO State
63   The state of the GPIO ports can be read and set using the following functions:
64     - MSS_GPIO_get_inputs()
65     - MSS_GPIO_get_outputs()
66     - MSS_GPIO_set_outputs()
67     - MSS_GPIO_set_output()
68     - MSS_GPIO_drive_inout()
69 
70   Interrupt Control
71   Interrupts generated by GPIO ports configured as inputs are controlled using
72   the following functions:
73     - MSS_GPIO_enable_irq()
74     - MSS_GPIO_disable_irq()
75     - MSS_GPIO_clear_irq()
76 
77  *//*=========================================================================*/
78 #ifndef MSS_GPIO_H_
79 #define MSS_GPIO_H_
80 
81 #ifdef __cplusplus
82 extern "C" {
83 #endif
84 
85 #include "../../CMSIS/m2sxxx.h"
86 
87 /*-------------------------------------------------------------------------*//**
88   The mss_gpio_id_t enumeration is used to identify individual GPIO ports as an
89   argument to functions:
90     - MSS_GPIO_config()
91     - MSS_GPIO_set_output() and MSS_GPIO_drive_inout()
92     - MSS_GPIO_enable_irq(), MSS_GPIO_disable_irq() and MSS_GPIO_clear_irq()
93  */
94 typedef enum __mss_gpio_id_t
95 {
96     MSS_GPIO_0 = 0,
97     MSS_GPIO_1 = 1,
98     MSS_GPIO_2 = 2,
99     MSS_GPIO_3 = 3,
100     MSS_GPIO_4 = 4,
101     MSS_GPIO_5 = 5,
102     MSS_GPIO_6 = 6,
103     MSS_GPIO_7 = 7,
104     MSS_GPIO_8 = 8,
105     MSS_GPIO_9 = 9,
106     MSS_GPIO_10 = 10,
107     MSS_GPIO_11 = 11,
108     MSS_GPIO_12 = 12,
109     MSS_GPIO_13 = 13,
110     MSS_GPIO_14 = 14,
111     MSS_GPIO_15 = 15,
112     MSS_GPIO_16 = 16,
113     MSS_GPIO_17 = 17,
114     MSS_GPIO_18 = 18,
115     MSS_GPIO_19 = 19,
116     MSS_GPIO_20 = 20,
117     MSS_GPIO_21 = 21,
118     MSS_GPIO_22 = 22,
119     MSS_GPIO_23 = 23,
120     MSS_GPIO_24 = 24,
121     MSS_GPIO_25 = 25,
122     MSS_GPIO_26 = 26,
123     MSS_GPIO_27 = 27,
124     MSS_GPIO_28 = 28,
125     MSS_GPIO_29 = 29,
126     MSS_GPIO_30 = 30,
127     MSS_GPIO_31 = 31
128 } mss_gpio_id_t;
129 
130 /*-------------------------------------------------------------------------*//**
131   These constant definitions are used as an argument to the
132   MSS_GPIO_set_outputs() function to identify GPIO ports. A logical OR of these
133   constants can be used to specify multiple GPIO ports.
134   These definitions can also be used to identify GPIO ports through logical
135   operations on the return value of the MSS_GPIO_get_inputs() function.
136  */
137 #define MSS_GPIO_0_MASK         0x00000001uL
138 #define MSS_GPIO_1_MASK         0x00000002uL
139 #define MSS_GPIO_2_MASK         0x00000004uL
140 #define MSS_GPIO_3_MASK         0x00000008uL
141 #define MSS_GPIO_4_MASK         0x00000010uL
142 #define MSS_GPIO_5_MASK         0x00000020uL
143 #define MSS_GPIO_6_MASK         0x00000040uL
144 #define MSS_GPIO_7_MASK         0x00000080uL
145 #define MSS_GPIO_8_MASK         0x00000100uL
146 #define MSS_GPIO_9_MASK         0x00000200uL
147 #define MSS_GPIO_10_MASK        0x00000400uL
148 #define MSS_GPIO_11_MASK        0x00000800uL
149 #define MSS_GPIO_12_MASK        0x00001000uL
150 #define MSS_GPIO_13_MASK        0x00002000uL
151 #define MSS_GPIO_14_MASK        0x00004000uL
152 #define MSS_GPIO_15_MASK        0x00008000uL
153 #define MSS_GPIO_16_MASK        0x00010000uL
154 #define MSS_GPIO_17_MASK        0x00020000uL
155 #define MSS_GPIO_18_MASK        0x00040000uL
156 #define MSS_GPIO_19_MASK        0x00080000uL
157 #define MSS_GPIO_20_MASK        0x00100000uL
158 #define MSS_GPIO_21_MASK        0x00200000uL
159 #define MSS_GPIO_22_MASK        0x00400000uL
160 #define MSS_GPIO_23_MASK        0x00800000uL
161 #define MSS_GPIO_24_MASK        0x01000000uL
162 #define MSS_GPIO_25_MASK        0x02000000uL
163 #define MSS_GPIO_26_MASK        0x04000000uL
164 #define MSS_GPIO_27_MASK        0x08000000uL
165 #define MSS_GPIO_28_MASK        0x10000000uL
166 #define MSS_GPIO_29_MASK        0x20000000uL
167 #define MSS_GPIO_30_MASK        0x40000000uL
168 #define MSS_GPIO_31_MASK        0x80000000uL
169 
170 /*-------------------------------------------------------------------------*//**
171   These constant definitions are used as an argument to the MSS_GPIO_config()
172   function to specify the I/O mode of each GPIO port.
173  */
174 #define MSS_GPIO_INPUT_MODE              0x0000000002uL
175 #define MSS_GPIO_OUTPUT_MODE             0x0000000005uL
176 #define MSS_GPIO_INOUT_MODE              0x0000000003uL
177 
178 /*-------------------------------------------------------------------------*//**
179   These constant definitions are used as an argument to the MSS_GPIO_config()
180   function to specify the interrupt mode of each GPIO port.
181  */
182 #define MSS_GPIO_IRQ_LEVEL_HIGH           0x0000000000uL
183 #define MSS_GPIO_IRQ_LEVEL_LOW            0x0000000020uL
184 #define MSS_GPIO_IRQ_EDGE_POSITIVE        0x0000000040uL
185 #define MSS_GPIO_IRQ_EDGE_NEGATIVE        0x0000000060uL
186 #define MSS_GPIO_IRQ_EDGE_BOTH            0x0000000080uL
187 
188 /*-------------------------------------------------------------------------*//**
189   The mss_gpio_inout_state_t enumeration is used to specify the output state of
190   an INOUT GPIO port as an argument to the MSS_GPIO_drive_inout() function.
191  */
192 typedef enum mss_gpio_inout_state
193 {
194     MSS_GPIO_DRIVE_LOW = 0,
195     MSS_GPIO_DRIVE_HIGH,
196     MSS_GPIO_HIGH_Z
197 } mss_gpio_inout_state_t;
198 
199 /*-------------------------------------------------------------------------*//**
200   The MSS_GPIO_init() function initializes the SmartFusion2 MSS GPIO block. It
201   resets the MSS GPIO hardware block and it also clears any pending MSS GPIO
202   interrupts in the ARM Cortex-M3 interrupt controller. When the function exits,
203   it takes the MSS GPIO block out of reset.
204 
205    @param
206     This function has no parameters.
207 
208    @return
209     This function does not return a value.
210  */
211 void MSS_GPIO_init( void );
212 
213 /*-------------------------------------------------------------------------*//**
214   The MSS_GPIO_config() function is used to configure an individual GPIO port.
215 
216   @param port_id
217     The port_id parameter identifies the GPIO port to be configured. An
218     enumeration item of the form MSS_GPIO_n, where n is the number of the GPIO
219     port, is used to identify the GPIO port. For example, MSS_GPIO_0 identifies
220     the first GPIO port and MSS_GPIO_31 is the last one.
221 
222   @param config
223     The config parameter specifies the configuration to be applied to the GPIO
224     port identified by the port_id parameter. It is a logical OR of the required
225     I/O mode and the required interrupt mode. The interrupt mode is not relevant
226     if the GPIO is configured as an output only.
227        These I/O mode constants are allowed:
228            - MSS_GPIO_INPUT_MODE
229            - MSS_GPIO_OUTPUT_MODE
230            - MSS_GPIO_INOUT_MODE
231        These interrupt mode constants are allowed:
232            - MSS_GPIO_IRQ_LEVEL_HIGH
233            - MSS_GPIO_IRQ_LEVEL_LOW
234            - MSS_GPIO_IRQ_EDGE_POSITIVE
235            - MSS_GPIO_IRQ_EDGE_NEGATIVE
236            - MSS_GPIO_IRQ_EDGE_BOTH
237 
238    @return
239     none.
240 
241   Example:
242   The following call will configure GPIO 4 as an input generating interrupts on
243   a Low to High transition of the input:
244   @code
245   MSS_GPIO_config( MSS_GPIO_4, MSS_GPIO_INPUT_MODE | MSS_GPIO_IRQ_EDGE_POSITIVE );
246   @endcode
247  */
248 void MSS_GPIO_config
249 (
250     mss_gpio_id_t port_id,
251     uint32_t config
252 );
253 
254 /*-------------------------------------------------------------------------*//**
255   The MSS_GPIO_set_outputs() function is used to set the state of all GPIO ports
256   configured as outputs.
257 
258   @param value
259     The value parameter specifies the state of the GPIO ports configured as
260     outputs. It is a bit mask of the form (MSS_GPIO_n_MASK | MSS_GPIO_m_MASK)
261     where n and m are numbers identifying GPIOs. For example, (MSS_GPIO_0_MASK |
262     MSS_GPIO_1_MASK | MSS_GPIO_2_MASK ) specifies that the first, second and
263     third GPIO outputs must be set High and all other GPIO outputs set Low. The
264     driver provides 32 mask constants, MSS_GPIO_0_MASK to MSS_GPIO_31_MASK
265     inclusive, for this purpose.
266 
267   @return
268     none.
269 
270   Example 1:
271     Set GPIOs outputs 0 and 8 high and all other GPIO outputs low.
272     @code
273         MSS_GPIO_set_outputs( MSS_GPIO_0_MASK | MSS_GPIO_8_MASK );
274     @endcode
275 
276   Example 2:
277     Set GPIOs outputs 2 and 4 low without affecting other GPIO outputs.
278     @code
279         uint32_t gpio_outputs;
280         gpio_outputs = MSS_GPIO_get_outputs();
281         gpio_outputs &= ~( MSS_GPIO_2_MASK | MSS_GPIO_4_MASK );
282         MSS_GPIO_set_outputs(  gpio_outputs );
283     @endcode
284 
285   @see MSS_GPIO_get_outputs()
286  */
287 static __INLINE void
MSS_GPIO_set_outputs(uint32_t value)288 MSS_GPIO_set_outputs
289 (
290    uint32_t value
291 )
292 {
293     GPIO->GPIO_OUT = value;
294 }
295 
296 /*-------------------------------------------------------------------------*//**
297   The MSS_GPIO_set_output() function is used to set the state of a single GPIO
298   port configured as an output.
299   Note: Using bit-band writes might be a better option than this function for
300         performance critical applications where the application code is not
301         intended to be ported to a processor other than the ARM Cortex-M3 in
302         SmartFusion2. The bit-band write equivalent to this function would be:
303             GPIO_BITBAND->GPIO_OUT[port_id] = (uint32_t)value;
304 
305   @param port_id
306     The port_id parameter identifies the GPIO port that is to have its output
307     set. An enumeration item of the form MSS_GPIO_n, where n is the number of
308     the GPIO port, is used to identify the GPIO port. For example, MSS_GPIO_0
309     identifies the first GPIO port and MSS_GPIO_31 is the last one.
310 
311   @param value
312     The value parameter specifies the desired state for the GPIO output. A value
313     of 0 will set the output Low and a value of 1 will set the output High.
314 
315   @return
316     This function does not return a value.
317 
318   Example:
319   The following call will set GPIO output 12 High, leaving all other GPIO
320   outputs unaffected:
321   @code
322     _GPIO_set_output(MSS_GPIO_12, 1);
323   @endcode
324  */
325 void MSS_GPIO_set_output
326 (
327     mss_gpio_id_t       port_id,
328     uint8_t             value
329 );
330 
331 /*-------------------------------------------------------------------------*//**
332   The MSS_GPIO_get_inputs() function is used to read the current state all GPIO
333   ports configured as inputs.
334 
335   @return
336     This function returns a 32-bit unsigned integer where each bit represents
337     the state of a GPIO input. The least significant bit represents the state of
338     GPIO input 0 and the most significant bit the state of GPIO input 31.
339 
340   Example:
341     Read and assign the current state of the GPIO outputs to a variable.
342     @code
343         uint32_t gpio_inputs;
344         gpio_inputs = MSS_GPIO_get_inputs();
345     @endcode
346  */
347 static __INLINE uint32_t
MSS_GPIO_get_inputs(void)348 MSS_GPIO_get_inputs( void )
349 {
350     return GPIO->GPIO_IN;
351 }
352 
353 /*-------------------------------------------------------------------------*//**
354   The MSS_GPIO_get_outputs() function is used to read the current state all GPIO
355   ports configured as outputs.
356 
357   @return
358      This function returns a 32-bit unsigned integer where each bit represents
359      the state of a GPIO output. The least significant bit represents the state
360      of GPIO output 0 and the most significant bit the state of GPIO output 31.
361 
362   Example:
363     Read and assign the current state of the GPIO outputs to a variable.
364     @code
365         uint32_t gpio_outputs;
366         gpio_outputs = MSS_GPIO_get_outputs();
367     @endcode
368  */
369 static __INLINE uint32_t
MSS_GPIO_get_outputs(void)370 MSS_GPIO_get_outputs( void )
371 {
372     return GPIO->GPIO_OUT;
373 }
374 
375 /*-------------------------------------------------------------------------*//**
376   The MSS_GPIO_drive_inout() function is used to set the output state of a
377   single GPIO port configured as an INOUT. An INOUT GPIO can be in one of three
378   states:
379     - High
380     - Low
381     - High impedance
382   An INOUT output would typically be used where several devices can drive the
383   state of a shared signal line. The High and Low states are equivalent to the
384   High and Low states of a GPIO configured as an output. The High impedance
385   state is used to prevent the GPIO from driving its output state onto the
386   signal line, while at the same time allowing the input state of the GPIO to
387   be read.
388 
389   @param port_id
390     The port_id parameter identifies the GPIO port for which you want to change
391     the output state. An enumeration item of the form MSS_GPIO_n, where n is the
392     number of the GPIO port, is used to identify the GPIO port. For example,
393     MSS_GPIO_0 identifies the first GPIO port and MSS_GPIO_31 is the last one.
394 
395   @param inout_state
396     The inout_state parameter specifies the state of the GPIO port identified by
397     the port_id parameter. Allowed values of type mss_gpio_inout_state_t are as
398     follows:
399         - MSS_GPIO_DRIVE_HIGH
400         - MSS_GPIO_DRIVE_LOW
401         - MSS_GPIO_HIGH_Z  (High impedance)
402 
403   @return
404     This function does not return a value.
405 
406   Example:
407     The call to MSS_GPIO_drive_inout() below will set the GPIO 7 output to the
408     high impedance state.
409     @code
410     MSS_GPIO_drive_inout( MSS_GPIO_7, MSS_GPIO_HIGH_Z );
411     @endcode
412  */
413 void MSS_GPIO_drive_inout
414 (
415     mss_gpio_id_t           port_id,
416     mss_gpio_inout_state_t  inout_state
417 );
418 
419 /*-------------------------------------------------------------------------*//**
420   The MSS_GPIO_enable_irq() function is used to enable interrupt generation for
421   the specified GPIO input. Interrupts are generated based on the state of the
422   GPIO input and the interrupt mode configured for it by MSS_GPIO_config().
423 
424   @param port_id
425     The port_id parameter identifies the GPIO port for which you want to enable
426     interrupt generation. An enumeration item of the form MSS_GPIO_n, where n is
427     the number of the GPIO port, is used to identify the GPIO port. For example,
428     MSS_GPIO_0 identifies the first GPIO port and MSS_GPIO_31 is the last one.
429 
430   @return
431     This function does not return a value.
432 
433   Example:
434     The call to MSS_GPIO_enable_irq() below will allow GPIO 8 to generate
435     interrupts.
436     @code
437     MSS_GPIO_enable_irq( MSS_GPIO_8 );
438     @endcode
439  */
440 void MSS_GPIO_enable_irq
441 (
442     mss_gpio_id_t port_id
443 );
444 
445 /*-------------------------------------------------------------------------*//**
446   The MSS_GPIO_disable_irq() function is used to disable interrupt generation
447   for the specified GPIO input.
448 
449   @param port_id
450     The port_id parameter identifies the GPIO port for which you want to disable
451     interrupt generation. An enumeration item of the form MSS_GPIO_n, where n is
452     the number of the GPIO port, is used to identify the GPIO port. For example,
453     MSS_GPIO_0 identifies the first GPIO port and MSS_GPIO_31 is the last one.
454 
455   @return
456     This function does not return a value.
457 
458   Example:
459     The call to MSS_GPIO_disable_irq() below will prevent GPIO 8 from generating
460     interrupts.
461     @code
462     MSS_GPIO_disable_irq( MSS_GPIO_8 );
463     @endcode
464  */
465 void MSS_GPIO_disable_irq
466 (
467     mss_gpio_id_t port_id
468 );
469 
470 /*-------------------------------------------------------------------------*//**
471   The MSS_GPIO_clear_irq() function is used to clear a pending interrupt from
472   the specified GPIO input.
473   Note: The MSS_GPIO_clear_irq() function must be called as part of any GPIO
474         interrupt service routine (ISR) in order to prevent the same interrupt
475         event retriggering a call to the GPIO ISR.
476 
477   @param port_id
478     The port_id parameter identifies the GPIO port for which you want to clear
479     the interrupt. An enumeration item of the form MSS_GPIO_n, where n is the
480     number of the GPIO port, is used to identify the GPIO port. For example,
481     MSS_GPIO_0 identifies the first GPIO port and MSS_GPIO_31 is the last one.
482 
483   @return
484     none.
485 
486   Example:
487     The example below demonstrates the use of the MSS_GPIO_clear_irq() function
488     as part of the GPIO 9 interrupt service routine.
489     @code
490     void GPIO9_IRQHandler( void )
491     {
492         do_interrupt_processing();
493 
494         MSS_GPIO_clear_irq( MSS_GPIO_9 );
495     }
496     @endcode
497  */
498 void MSS_GPIO_clear_irq
499 (
500     mss_gpio_id_t port_id
501 );
502 
503 #ifdef __cplusplus
504 }
505 #endif
506 
507 #endif /* MSS_GPIO_H_ */
508