1 //*****************************************************************************
2 //
3 //! @file am_hal_gpio.c
4 //!
5 //! @brief Functions for Interfacing with the GPIO module
6 //!
7 //! @addtogroup gpio3p GPIO - GPIO Functions
8 //! @ingroup apollo3p_hal
9 //! @{
10 //
11 //*****************************************************************************
12 
13 //*****************************************************************************
14 //
15 // Copyright (c) 2024, Ambiq Micro, Inc.
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are met:
20 //
21 // 1. Redistributions of source code must retain the above copyright notice,
22 // this list of conditions and the following disclaimer.
23 //
24 // 2. Redistributions in binary form must reproduce the above copyright
25 // notice, this list of conditions and the following disclaimer in the
26 // documentation and/or other materials provided with the distribution.
27 //
28 // 3. Neither the name of the copyright holder nor the names of its
29 // contributors may be used to endorse or promote products derived from this
30 // software without specific prior written permission.
31 //
32 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
33 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
36 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
37 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
40 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 // POSSIBILITY OF SUCH DAMAGE.
43 //
44 // This is part of revision release_sdk_3_2_0-dd5f40c14b of the AmbiqSuite Development Package.
45 //
46 //*****************************************************************************
47 
48 #include <stdint.h>
49 #include <stdbool.h>
50 #include "am_mcu_apollo.h"
51 
52 //*****************************************************************************
53 //! Local defines.
54 //*****************************************************************************
55 //
56 // Generally define GPIO PADREG and GPIOCFG bitfields
57 //
58 #define PADREG_FLD_76_S         6
59 #define PADREG_FLD_FNSEL_S      3
60 #define PADREG_FLD_DRVSTR_S     2
61 #define PADREG_FLD_INPEN_S      1
62 #define PADREG_FLD_PULLUP_S     0
63 
64 #define GPIOCFG_FLD_INTD_S      3
65 #define GPIOCFG_FLD_OUTCFG_S    1
66 #define GPIOCFG_FLD_INCFG_S     0
67 
68 //*****************************************************************************
69 //
70 // Globals
71 //
72 //*****************************************************************************
73 //*****************************************************************************
74 //  Define some common GPIO configurations.
75 //*****************************************************************************
76 const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_DEFAULT =
77 {
78     .uFuncSel       = 3,
79     .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA,
80     .eGPOutcfg      = AM_HAL_GPIO_PIN_OUTCFG_DISABLE
81 };
82 
83 const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_DISABLE =
84 {
85     .uFuncSel       = 3,
86     .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA,
87     .eGPOutcfg      = AM_HAL_GPIO_PIN_OUTCFG_DISABLE
88 };
89 
90 const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_TRISTATE =
91 {
92     .uFuncSel       = 3,
93     .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA,
94     .eGPOutcfg      = AM_HAL_GPIO_PIN_OUTCFG_TRISTATE
95 };
96 
97 const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT =
98 {
99     .uFuncSel       = 3,
100     .eGPOutcfg      = AM_HAL_GPIO_PIN_OUTCFG_DISABLE,
101     .eGPInput       = AM_HAL_GPIO_PIN_INPUT_ENABLE,
102     .eGPRdZero      = AM_HAL_GPIO_PIN_RDZERO_READPIN
103 };
104 
105 //
106 // Input with various pullups (weak, 1.5K, 6K, 12K, 24K)
107 // The 1.5K - 24K pullup values are valid for select I2C enabled pads.
108 // For Apollo3 these pins are 0-1,5-6,8-9,25,27,39-40,42-43,48-49.
109 // The "weak" value is used for almost every other pad except pin 20.
110 //
111 const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT_PULLUP =
112 {
113     .uFuncSel       = 3,
114     .eGPOutcfg      = AM_HAL_GPIO_PIN_OUTCFG_DISABLE,
115     .eGPInput       = AM_HAL_GPIO_PIN_INPUT_ENABLE,
116     .eGPRdZero      = AM_HAL_GPIO_PIN_RDZERO_READPIN,
117     .ePullup        = AM_HAL_GPIO_PIN_PULLUP_WEAK
118 };
119 
120 const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT_PULLUP_1_5 =
121 {
122     .uFuncSel       = 3,
123     .eGPOutcfg      = AM_HAL_GPIO_PIN_OUTCFG_DISABLE,
124     .eGPInput       = AM_HAL_GPIO_PIN_INPUT_ENABLE,
125     .eGPRdZero      = AM_HAL_GPIO_PIN_RDZERO_READPIN,
126     .ePullup        = AM_HAL_GPIO_PIN_PULLUP_1_5K
127 };
128 
129 const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT_PULLUP_6 =
130 {
131     .uFuncSel       = 3,
132     .eGPOutcfg      = AM_HAL_GPIO_PIN_OUTCFG_DISABLE,
133     .eGPInput       = AM_HAL_GPIO_PIN_INPUT_ENABLE,
134     .eGPRdZero      = AM_HAL_GPIO_PIN_RDZERO_READPIN,
135     .ePullup        = AM_HAL_GPIO_PIN_PULLUP_6K
136 };
137 
138 const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT_PULLUP_12 =
139 {
140     .uFuncSel       = 3,
141     .eGPOutcfg      = AM_HAL_GPIO_PIN_OUTCFG_DISABLE,
142     .eGPInput       = AM_HAL_GPIO_PIN_INPUT_ENABLE,
143     .eGPRdZero      = AM_HAL_GPIO_PIN_RDZERO_READPIN,
144     .ePullup        = AM_HAL_GPIO_PIN_PULLUP_12K
145 };
146 
147 const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT_PULLUP_24 =
148 {
149     .uFuncSel       = 3,
150     .eGPOutcfg      = AM_HAL_GPIO_PIN_OUTCFG_DISABLE,
151     .eGPInput       = AM_HAL_GPIO_PIN_INPUT_ENABLE,
152     .eGPRdZero      = AM_HAL_GPIO_PIN_RDZERO_READPIN,
153     .ePullup        = AM_HAL_GPIO_PIN_PULLUP_24K
154 };
155 
156 //
157 // Variations of output (drive strengths, read, etc)
158 //
159 const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_OUTPUT =
160 {
161     .uFuncSel       = 3,
162     .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA,
163     .eGPOutcfg      = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL
164 };
165 
166 const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_OUTPUT_4 =
167 {
168     .uFuncSel       = 3,
169     .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_4MA,
170     .eGPOutcfg      = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL
171 };
172 
173 const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_OUTPUT_8 =
174 {
175     .uFuncSel       = 3,
176     .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_8MA,
177     .eGPOutcfg      = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL
178 };
179 
180 const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_OUTPUT_12 =
181 {
182     .uFuncSel       = 3,
183     .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA,
184     .eGPOutcfg      = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL
185 };
186 
187 const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_OUTPUT_WITH_READ =
188 {
189     .uFuncSel       = 3,
190     .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA,
191     .eGPOutcfg      = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL,
192     .eGPInput       = AM_HAL_GPIO_PIN_INPUT_ENABLE,
193     .eGPRdZero      = AM_HAL_GPIO_PIN_RDZERO_READPIN
194 };
195 
196 //*****************************************************************************
197 //
198 //  g_ui8Inpen[]
199 //  This lookup table determines whether the INPEN bit is required based on
200 //  the pin number and FNSEL.
201 //
202 //*****************************************************************************
203 static const uint8_t
204 g_ui8Inpen[AM_HAL_GPIO_MAX_PADS] =
205 {
206     //0     1     2     3     4     5     6     7     8     9
207     0x23, 0x23, 0x27, 0x62, 0xA1, 0x03, 0x87, 0x10, 0x03, 0x53, // Pins 0-9
208     0x00, 0xE1, 0x51, 0x81, 0x41, 0x55, 0x05, 0xC4, 0x80, 0x40, // Pins 10-19
209     0x01, 0xB1, 0x40, 0x41, 0x14, 0x31, 0xA0, 0x31, 0x00, 0xF1, // Pins 20-29
210     0x80, 0x11, 0x91, 0x21, 0xC1, 0x11, 0xE5, 0x11, 0x45, 0x30, // Pins 30-39
211     0x37, 0x00, 0x30, 0x31, 0x00, 0x71, 0x00, 0x40, 0x30, 0x31, // Pins 40-49
212     0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // Pins 50-59
213     0x01, 0xA0, 0x50, 0xA0, 0x01, 0x01, 0x01, 0x01, 0x01, 0xA0, // Pins 60-69
214     0xA0, 0xA0, 0xA0, 0x50                                      // Pins 70-73
215 };
216 
217 //*****************************************************************************
218 //
219 //  g_ui8Bit76Capabilities[]
220 //  This lookup table specifies capabilities of each pad for PADREG bits 7:6.
221 //
222 //*****************************************************************************
223 #define CAP_PUP     0x01    // PULLUP
224 #define CAP_PDN     0x08    // PULLDOWN (pin 20 only)
225 #define CAP_VDD     0x02    // VDD PWR (power source)
226 #define CAP_VSS     0x04    // VSS PWR (ground sink)
227 #define CAP_RSV     0x80    // bits 7:6 are reserved for this pin
228 static const uint8_t
229 g_ui8Bit76Capabilities[AM_HAL_GPIO_MAX_PADS] =
230 {
231     //0        1        2        3        4        5        6        7        8        9
232     CAP_PUP, CAP_PUP, CAP_RSV, CAP_VDD, CAP_RSV, CAP_PUP, CAP_PUP, CAP_RSV, CAP_PUP, CAP_PUP,   // Pins 0-9
233     CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV,   // Pins 10-19
234     CAP_PDN, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_PUP, CAP_RSV, CAP_PUP, CAP_RSV, CAP_RSV,   // Pins 20-29
235     CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_VDD, CAP_VSS, CAP_RSV, CAP_PUP,   // Pins 30-39
236     CAP_PUP, CAP_VSS, CAP_PUP, CAP_PUP, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_PUP, CAP_PUP,   // Pins 40-49
237     CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV,   // Pins 50-59
238     CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV,   // Pins 60-69
239     CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV                                                          // Pins 70-73
240 };
241 
242 //*****************************************************************************
243 //
244 // g_ui8nCEpins[]
245 // This lookup table lists the nCE funcsel value as a function of the pin.
246 //  Almost every pad has a nCE function.  Every one of those nCE functions
247 // can select a polarity (active low or high) via the INTD field.
248 // All non-nCE functions use INCFG and INTD to select interrupt transition types.
249 // A lookup will return 0-7 if the pin supports nCE, and 8 if it does not.
250 //
251 // The truth table summarizes behavior.  For the purposes of this table, assume
252 //  "A" is the funcsel that selects nCE (and thus polarity is needed) for the
253 //  given pad.  Then "!A" is any other funcsel and selects interrupt transition.
254 //
255 //  funcsel     INCFG       INTD        Behavior
256 //    !A        0           0           Interrupt on L->H transition.
257 //    !A        0           1           Interrupt on H->L transition.
258 //    !A        1           0           No interrupts.
259 //    !A        1           1           Interrupt either direction.
260 //     A        x           0           nCE polarity active low.
261 //     A        x           1           nCE polarity active high.
262 //
263 //*****************************************************************************
264 static const uint8_t
265 g_ui8nCEpins[AM_HAL_GPIO_MAX_PADS] =
266 {
267     // 0     1     2     3     4     5     6     7     8     9
268     0x07, 0x07, 0x07, 0x02, 0x02, 0x08, 0x08, 0x00, 0x02, 0x02,     // Pads 0-9
269     0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,     // Pads 10-19
270     0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,     // Pads 20-29
271     0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08,     // Pads 30-39
272     0x08, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,     // Pads 40-49
273     0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,     // Pads 50-59
274     0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,     // Pads 60-69
275     0x01, 0x01, 0x01, 0x01                                          // Pads 70-73
276 };
277 
278 //*****************************************************************************
279 //
280 // g_ui8NCEtable[]
281 // This lookup table lists all available NCEs. It basically reproduces the
282 //  "NCE Encoding Table" from the datasheet.
283 //
284 // The format of this table is:
285 //  [7:7] IOM=1, MSPI=0
286 //  [6:4] NCE number (0-3)
287 //  [3:0] IOM number (0-5) or MSPI number (0-2)
288 //  Every 4 bytes (1 word) of the table represent an index to the next GPIO pin.
289 //
290 //*****************************************************************************
291 //
292 // In NCETBL entries, either IOM or MSPI should be 0.
293 //
294 #define NCETBL(IOM, NUM, NCE)      ((IOM << 7) | (NCE << 4) | (NUM << 0))
295 
296 static const uint8_t
297 g_ui8NCEtable[AM_HAL_GPIO_MAX_PADS][4] =
298 {
299      // 0       1       2       3    = OUTCFG
300     {NCETBL(1, 3, 2), NCETBL(1, 4, 2), NCETBL(0, 2, 1), NCETBL(0, 1, 0)},   // NCE0
301     {NCETBL(1, 0, 2), NCETBL(1, 1, 2), NCETBL(1, 2, 2), NCETBL(1, 4, 2)},   // NCE1
302     {NCETBL(1, 3, 3), NCETBL(0, 2, 0), NCETBL(1, 5, 3), NCETBL(1, 2, 1)},   // NCE2
303     {NCETBL(1, 3, 0), NCETBL(1, 4, 0), NCETBL(1, 5, 0), NCETBL(1, 2, 0)},   // NCE3
304     {NCETBL(1, 3, 1), NCETBL(1, 4, 1), NCETBL(0, 1, 0), NCETBL(1, 1, 1)},   // NCE4
305     {0xFF,            0xFF,            0xFF,            0xFF},              // NCE5
306     {0xFF,            0xFF,            0xFF,            0xFF},              // NCE6
307     {NCETBL(0, 1, 0), NCETBL(0, 2, 1), NCETBL(1, 5, 1), NCETBL(0, 0, 0)},   // NCE7
308     {NCETBL(1, 3, 0), NCETBL(1, 4, 0), NCETBL(0, 2, 0), NCETBL(1, 0, 0)},   // NCE8
309     {NCETBL(0, 1, 0), NCETBL(1, 4, 3), NCETBL(1, 5, 3), NCETBL(1, 2, 3)},   // NCE9
310     {NCETBL(1, 3, 2), NCETBL(1, 4, 2), NCETBL(0, 1, 1), NCETBL(0, 0, 0)},   // NCE10
311     {NCETBL(1, 0, 0), NCETBL(1, 1, 0), NCETBL(1, 2, 0), NCETBL(1, 3, 0)},   // NCE11
312     {NCETBL(1, 3, 0), NCETBL(0, 2, 0), NCETBL(1, 5, 0), NCETBL(0, 0, 1)},   // NCE12
313     {NCETBL(1, 3, 1), NCETBL(1, 4, 1), NCETBL(1, 5, 1), NCETBL(1, 0, 1)},   // NCE13
314     {NCETBL(1, 0, 2), NCETBL(0, 2, 1), NCETBL(1, 2, 2), NCETBL(1, 4, 2)},   // NCE14
315     {NCETBL(0, 1, 0), NCETBL(1, 1, 3), NCETBL(1, 2, 3), NCETBL(0, 0, 0)},   // NCE15
316     {NCETBL(1, 0, 0), NCETBL(0, 2, 0), NCETBL(1, 2, 3), NCETBL(1, 5, 0)},   // NCE16
317     {NCETBL(1, 0, 1), NCETBL(1, 1, 1), NCETBL(0, 2, 0), NCETBL(1, 4, 1)},   // NCE17
318     {NCETBL(0, 2, 0), NCETBL(1, 1, 2), NCETBL(1, 2, 2), NCETBL(1, 3, 2)},   // NCE18
319     {NCETBL(1, 0, 3), NCETBL(0, 1, 1), NCETBL(1, 3, 3), NCETBL(0, 0, 0)},   // NCE19
320     {NCETBL(0, 2, 1), NCETBL(0, 0, 0), NCETBL(1, 5, 1), NCETBL(1, 2, 1)},   // NCE20
321     {NCETBL(1, 3, 2), NCETBL(1, 4, 2), NCETBL(0, 2, 0), NCETBL(0, 1, 0)},   // NCE21
322     {NCETBL(1, 3, 3), NCETBL(1, 4, 3), NCETBL(1, 5, 3), NCETBL(0, 2, 0)},   // NCE22
323     {NCETBL(1, 0, 0), NCETBL(1, 1, 0), NCETBL(1, 2, 0), NCETBL(1, 4, 0)},   // NCE23
324     {NCETBL(1, 0, 1), NCETBL(0, 1, 0), NCETBL(1, 2, 1), NCETBL(1, 5, 1)},   // NCE24
325     {NCETBL(1, 3, 2), NCETBL(0, 1, 0), NCETBL(1, 5, 2), NCETBL(1, 0, 2)},   // NCE25
326     {NCETBL(1, 3, 3), NCETBL(1, 4, 3), NCETBL(1, 5, 3), NCETBL(1, 1, 3)},   // NCE26
327     {NCETBL(0, 2, 0), NCETBL(1, 4, 0), NCETBL(0, 0, 0), NCETBL(1, 1, 0)},   // NCE27
328     {NCETBL(1, 3, 1), NCETBL(1, 4, 1), NCETBL(1, 5, 1), NCETBL(0, 0, 0)},   // NCE28
329     {NCETBL(1, 3, 2), NCETBL(0, 2, 1), NCETBL(1, 5, 2), NCETBL(1, 1, 2)},   // NCE29
330     {NCETBL(0, 0, 0), NCETBL(1, 4, 3), NCETBL(0, 2, 0), NCETBL(1, 0, 3)},   // NCE30
331     {NCETBL(0, 1, 0), NCETBL(0, 2, 0), NCETBL(1, 2, 0), NCETBL(1, 4, 0)},   // NCE31
332     {NCETBL(1, 0, 1), NCETBL(1, 1, 3), NCETBL(0, 1, 0), NCETBL(0, 0, 1)},   // NCE32
333     {NCETBL(1, 0, 2), NCETBL(0, 1, 1), NCETBL(1, 2, 1), NCETBL(1, 5, 2)},   // NCE33
334     {NCETBL(1, 0, 3), NCETBL(0, 2, 0), NCETBL(1, 2, 3), NCETBL(0, 1, 1)},   // NCE34
335     {NCETBL(0, 1, 0), NCETBL(1, 1, 0), NCETBL(1, 2, 0), NCETBL(0, 2, 0)},   // NCE35
336     {NCETBL(1, 3, 1), NCETBL(1, 4, 1), NCETBL(1, 5, 1), NCETBL(0, 0, 1)},   // NCE36
337     {NCETBL(1, 3, 1), NCETBL(1, 4, 2), NCETBL(1, 5, 2), NCETBL(0, 0, 0)},   // NCE37
338     {NCETBL(1, 0, 3), NCETBL(1, 1, 3), NCETBL(0, 2, 1), NCETBL(1, 5, 3)},   // NCE38
339     {0xFF,            0xFF,            0xFF,            0xFF},              // NCE39
340     {0xFF,            0xFF,            0xFF,            0xFF},              // NCE40
341     {NCETBL(0, 2, 0), NCETBL(1, 1, 1), NCETBL(0, 1, 1), NCETBL(0, 0, 1)},   // NCE41
342     {NCETBL(1, 0, 0), NCETBL(0, 1, 0), NCETBL(1, 2, 0), NCETBL(1, 5, 0)},   // NCE42
343     {NCETBL(1, 0, 1), NCETBL(1, 1, 1), NCETBL(0, 2, 0), NCETBL(0, 0, 1)},   // NCE43
344     {NCETBL(1, 0, 2), NCETBL(0, 0, 0), NCETBL(1, 2, 2), NCETBL(1, 5, 2)},   // NCE44
345     {NCETBL(1, 3, 3), NCETBL(1, 4, 3), NCETBL(1, 5, 0), NCETBL(1, 1, 3)},   // NCE45
346     {NCETBL(1, 3, 0), NCETBL(0, 1, 0), NCETBL(0, 2, 0), NCETBL(0, 0, 1)},   // NCE46
347     {NCETBL(0, 1, 1), NCETBL(1, 1, 0), NCETBL(1, 2, 1), NCETBL(1, 3, 1)},   // NCE47
348     {NCETBL(0, 1, 0), NCETBL(1, 1, 2), NCETBL(1, 2, 2), NCETBL(0, 2, 1)},   // NCE48
349     {NCETBL(1, 0, 3), NCETBL(0, 1, 1), NCETBL(1, 2, 3), NCETBL(1, 1, 0)},   // NCE49
350     {NCETBL(0, 1, 0), NCETBL(0, 2, 0), NCETBL(1, 2, 3), NCETBL(1, 0, 0)},   // NCE50
351     {NCETBL(1, 4, 2), NCETBL(1, 1, 1), NCETBL(1, 2, 1), NCETBL(1, 0, 0)},   // NCE51
352     {NCETBL(1, 0, 1), NCETBL(1, 1, 2), NCETBL(0, 0, 0), NCETBL(1, 2, 1)},   // NCE52
353     {NCETBL(1, 0, 2), NCETBL(1, 1, 3), NCETBL(0, 2, 0), NCETBL(1, 2, 0)},   // NCE53
354     {NCETBL(0, 2, 0), NCETBL(1, 4, 0), NCETBL(1, 5, 0), NCETBL(1, 3, 0)},   // NCE54
355     {NCETBL(1, 3, 0), NCETBL(0, 0, 0), NCETBL(1, 5, 1), NCETBL(1, 4, 0)},   // NCE55
356     {NCETBL(1, 3, 2), NCETBL(1, 4, 3), NCETBL(1, 5, 2), NCETBL(0, 0, 1)},   // NCE56
357     {NCETBL(0, 0, 0), NCETBL(1, 4, 3), NCETBL(1, 5, 3), NCETBL(1, 0, 1)},   // NCE57
358     {NCETBL(1, 3, 3), NCETBL(1, 1, 0), NCETBL(0, 0, 0), NCETBL(1, 5, 3)},   // NCE58
359     {NCETBL(0, 1, 1), NCETBL(1, 1, 1), NCETBL(1, 2, 1), NCETBL(0, 0, 0)},   // NCE59
360     {NCETBL(0, 0, 1), NCETBL(1, 1, 2), NCETBL(1, 2, 2), NCETBL(1, 0, 3)},   // NCE60
361     {NCETBL(0, 0, 0), NCETBL(1, 1, 3), NCETBL(0, 2, 0), NCETBL(0, 1, 0)},   // NCE61
362     {NCETBL(0, 0, 1), NCETBL(1, 4, 0), NCETBL(1, 5, 0), NCETBL(0, 1, 1)},   // NCE62
363     {NCETBL(0, 1, 0), NCETBL(1, 4, 1), NCETBL(0, 2, 0), NCETBL(0, 0, 0)},   // NCE63
364     {NCETBL(1, 0, 0), NCETBL(1, 4, 2), NCETBL(1, 5, 2), NCETBL(0, 0, 1)},   // NCE64
365     {NCETBL(1, 0, 1), NCETBL(0, 0, 0), NCETBL(1, 5, 2), NCETBL(1, 3, 1)},   // NCE65
366     {NCETBL(0, 1, 0), NCETBL(1, 1, 0), NCETBL(1, 2, 0), NCETBL(1, 4, 1)},   // NCE66
367     {NCETBL(1, 0, 3), NCETBL(1, 1, 1), NCETBL(1, 2, 3), NCETBL(1, 5, 1)},   // NCE67
368     {NCETBL(1, 3, 0), NCETBL(0, 0, 0), NCETBL(1, 2, 2), NCETBL(1, 0, 2)},   // NCE68
369     {NCETBL(1, 3, 1), NCETBL(1, 1, 3), NCETBL(0, 0, 0), NCETBL(0, 1, 0)},   // NCE69
370     {NCETBL(1, 3, 2), NCETBL(0, 2, 0), NCETBL(1, 5, 0), NCETBL(0, 1, 1)},   // NCE70
371     {NCETBL(1, 3, 3), NCETBL(1, 4, 1), NCETBL(1, 0, 3), NCETBL(1, 1, 2)},   // NCE71
372     {NCETBL(0, 0, 0), NCETBL(0, 2, 0), NCETBL(0, 1, 0), NCETBL(1, 2, 2)},   // NCE72
373     {NCETBL(0, 1, 0), NCETBL(1, 4, 3), NCETBL(1, 5, 3), NCETBL(0, 2, 0)},   // NCE73
374 };
375 
376 //*****************************************************************************
377 //
378 // Array of function pointers for handling GPIO interrupts.
379 //
380 //*****************************************************************************
381 static am_hal_gpio_handler_t gpio_ppfnHandlers[AM_HAL_GPIO_MAX_PADS];
382 static void                  *gpio_pHandlerCtxt[AM_HAL_GPIO_MAX_PADS];
383 
384 //*****************************************************************************
385 //
386 // Helper functions
387 //  popcount()   - Determine how many bits are set in the given bitmasks.
388 //  pincfg_equ() - compare 2 am_hal_gpio_pincfg_t structures for equality.
389 //
390 //*****************************************************************************
391 //*****************************************************************************
392 // @brief compare 32bit values at two pointers
393 //
394 // @param cfg1
395 // @param cfg2
396 // @return true
397 // @return false
398 //*****************************************************************************
399 static bool
pincfg_equ(void * cfg1,void * cfg2)400 pincfg_equ(void *cfg1, void *cfg2)
401 {
402     uint32_t ui32A, ui32B;
403 
404     //
405     // We're assuming that am_hal_gpio_pincfg_t boils down to a uint32_t,
406     // which is its intent.
407     //
408     ui32A = *((uint32_t*)cfg1);
409     ui32B = *((uint32_t*)cfg2);
410 
411     return ui32A == ui32B ? true : false;
412 
413 } // pincfg_equ()
414 
415 //*****************************************************************************
416 // @brief Count the number of set bits in the given bitmasks
417 //
418 // @param pui32bitmask
419 // @param i32numbits
420 // @return uint32_t
421 //*****************************************************************************
422 static uint32_t
popcount(uint32_t * pui32bitmask,int32_t i32numbits)423 popcount(uint32_t *pui32bitmask, int32_t i32numbits)
424 {
425     uint32_t uCnt = 0;
426     uint32_t ui32bm;
427 
428     // Count the number of set bits in the given bitmasks.
429     uCnt = 0;
430     while ( i32numbits > 0 )
431     {
432         ui32bm  = *pui32bitmask++;
433         ui32bm &= (((uint32_t)1 << i32numbits) - 1);
434 
435         //
436         // This loop will efficiently determine the number of set bits in ui32bm
437         //
438         while ( ui32bm )
439         {
440             ui32bm &= (ui32bm - 1);
441             uCnt++;
442         }
443         i32numbits -= 32;
444     }
445     return uCnt;
446 } // popcount()
447 
448 //*****************************************************************************
449 //
450 // Return the current configuration of a pin.
451 //
452 //*****************************************************************************
am_hal_gpio_pinconfig_get(uint32_t ui32GpioNum,am_hal_gpio_pincfg_t * psGpioCfg)453 uint32_t am_hal_gpio_pinconfig_get(uint32_t ui32GpioNum, am_hal_gpio_pincfg_t *psGpioCfg)
454 {
455     uint32_t ui32GPCfgAddr, ui32PadregAddr, ui32AltpadAddr;
456     uint32_t ui32GPCfgMask, ui32PadMask;
457     uint32_t ui32GPCfgShft, ui32PadShft;
458     uint32_t ui32GPCfgVal, ui32PadVal, ui32AltVal;
459 
460     if (ui32GpioNum >= AM_HAL_GPIO_MAX_PADS) {
461         return AM_HAL_STATUS_OUT_OF_RANGE;
462     }
463 
464     if (psGpioCfg == (am_hal_gpio_pincfg_t *)0x0) {
465         return AM_HAL_STATUS_INVALID_ARG;
466     }
467 
468     ui32GPCfgAddr = AM_REGADDR(GPIO, CFGA) + ((ui32GpioNum >> 1) & ~0x3);
469     ui32PadregAddr = AM_REGADDR(GPIO, PADREGA) + (ui32GpioNum & ~0x3);
470     ui32AltpadAddr = AM_REGADDR(GPIO, ALTPADCFGA) + (ui32GpioNum & ~0x3);
471     ui32GPCfgShft = ((ui32GpioNum & 0x7) << 2);
472     ui32PadShft = ((ui32GpioNum & 0x3) << 3);
473     ui32GPCfgMask = (uint32_t)0xF << ui32GPCfgShft;
474     ui32PadMask = (uint32_t)0xFF << ui32PadShft;
475 
476     ui32GPCfgVal = (AM_REGVAL(ui32GPCfgAddr) & ui32GPCfgMask) >> ui32GPCfgShft;
477     ui32PadVal = (AM_REGVAL(ui32PadregAddr) & ui32PadMask) >> ui32PadShft;
478     ui32AltVal = (AM_REGVAL(ui32AltpadAddr) & ui32PadMask) >> ui32PadShft;
479 
480     psGpioCfg->eGPOutcfg =
481         (ui32GPCfgVal & GPIO_CFGA_GPIO0OUTCFG_Msk) >> GPIO_CFGA_GPIO0OUTCFG_Pos;
482     psGpioCfg->eGPInput =
483         (ui32PadVal & GPIO_PADREGA_PAD0INPEN_Msk) >> GPIO_PADREGA_PAD0INPEN_Pos;
484 
485     if ((ui32PadVal & GPIO_PADREGA_PAD0PULL_Msk) >> GPIO_PADREGA_PAD0PULL_Pos) {
486         if ((ui32PadVal & GPIO_PADREGA_PAD0RSEL_Msk) >> GPIO_PADREGA_PAD0RSEL_Pos) {
487             psGpioCfg->ePullup = AM_HAL_GPIO_PIN_PULLUP_1_5K +
488                          ((ui32PadVal & GPIO_PADREGA_PAD0RSEL_Msk) >>
489                           GPIO_PADREGA_PAD0RSEL_Pos);
490         } else if (ui32GpioNum != 20) {
491             psGpioCfg->ePullup = AM_HAL_GPIO_PIN_PULLUP_WEAK;
492         } else {
493             psGpioCfg->ePullup = AM_HAL_GPIO_PIN_PULLDOWN;
494         }
495     } else {
496         psGpioCfg->ePullup = AM_HAL_GPIO_PIN_PULLUP_NONE;
497     }
498 
499     psGpioCfg->uFuncSel =
500         (ui32PadVal & GPIO_PADREGA_PAD0FNCSEL_Msk) >> GPIO_PADREGA_PAD0FNCSEL_Pos;
501     psGpioCfg->eCEpol = (ui32GPCfgVal & GPIO_CFGA_GPIO0INTD_Msk) >> GPIO_CFGA_GPIO0INTD_Pos;
502     psGpioCfg->eIntDir =
503         (((ui32GPCfgVal & GPIO_CFGA_GPIO0INCFG_Msk) >> GPIO_CFGA_GPIO0INCFG_Pos) << 1) |
504         psGpioCfg->eCEpol;
505     psGpioCfg->eDriveStrength =
506         (((ui32AltVal & GPIO_ALTPADCFGA_PAD0_DS1_Msk) >> GPIO_ALTPADCFGA_PAD0_DS1_Pos)
507          << 1) |
508         ((ui32PadVal & GPIO_PADREGA_PAD0STRNG_Msk) >> GPIO_PADREGA_PAD0STRNG_Pos);
509     psGpioCfg->eGPRdZero =
510         (ui32GPCfgVal & GPIO_CFGA_GPIO0INCFG_Msk) >> GPIO_CFGA_GPIO0INCFG_Pos;
511 
512     return AM_HAL_STATUS_SUCCESS;
513 }// am_hal_gpio_pinconfig_get()
514 
515 //*****************************************************************************
516 //
517 // @brief Configure an Apollo3 pin.
518 //
519 // @param ui32Pin    - pin number to be configured.
520 // @param bfGpioCfg - Contains multiple descriptor fields.
521 //
522 // This function configures a pin according to the parameters in ui32Config.
523 // All parameters are validated, and the given pin is configured according
524 // to the designated parameters.
525 //
526 // @return Status.
527 //
528 //*****************************************************************************
529 uint32_t
am_hal_gpio_pinconfig(uint32_t ui32Pin,am_hal_gpio_pincfg_t bfGpioCfg)530 am_hal_gpio_pinconfig(uint32_t ui32Pin, am_hal_gpio_pincfg_t bfGpioCfg)
531 
532 {
533     uint32_t ui32Padreg, ui32AltPadCfg, ui32GPCfg;
534     uint32_t ui32Funcsel, ui32PowerSw;
535     bool bClearEnable = false;
536 
537 #ifndef AM_HAL_DISABLE_API_VALIDATION
538     if ( ui32Pin >= AM_HAL_GPIO_MAX_PADS )
539     {
540         return AM_HAL_STATUS_INVALID_ARG;
541     }
542 #endif // AM_HAL_DISABLE_API_VALIDATION
543 
544     //
545     // Initialize the PADREG accumulator variables.
546     //
547     ui32GPCfg = ui32Padreg = ui32AltPadCfg = 0;
548 
549     //
550     // Get the requested function and/or power switch.
551     //
552     ui32Funcsel = bfGpioCfg.uFuncSel;
553     ui32PowerSw = bfGpioCfg.ePowerSw;
554 
555     ui32Padreg |= ui32Funcsel << PADREG_FLD_FNSEL_S;
556 
557     //
558     // Check for invalid configuration requests.
559     //
560     if ( bfGpioCfg.ePullup != AM_HAL_GPIO_PIN_PULLUP_NONE )
561     {
562         //
563         // This setting is needed for all pullup settings including
564         // AM_HAL_GPIO_PIN_PULLUP_WEAK and AM_HAL_GPIO_PIN_PULLDOWN.
565         //
566         ui32Padreg |= (0x1 << PADREG_FLD_PULLUP_S);
567 
568         //
569         // Check for specific pullup or pulldown settings.
570         //
571         if ( (bfGpioCfg.ePullup >= AM_HAL_GPIO_PIN_PULLUP_1_5K) &&
572              (bfGpioCfg.ePullup <= AM_HAL_GPIO_PIN_PULLUP_24K) )
573         {
574             ui32Padreg |= ((bfGpioCfg.ePullup - AM_HAL_GPIO_PIN_PULLUP_1_5K) <<
575                            PADREG_FLD_76_S);
576 #ifndef AM_HAL_DISABLE_API_VALIDATION
577             if ( !(g_ui8Bit76Capabilities[ui32Pin] & CAP_PUP) )
578             {
579                 return AM_HAL_GPIO_ERR_PULLUP;
580             }
581         }
582         else if ( bfGpioCfg.ePullup == AM_HAL_GPIO_PIN_PULLDOWN )
583         {
584             if ( ui32Pin != 20 )
585             {
586                 return AM_HAL_GPIO_ERR_PULLDOWN;
587             }
588         }
589         else if ( bfGpioCfg.ePullup == AM_HAL_GPIO_PIN_PULLUP_WEAK )
590         {
591             //
592             // All pads except 20 support a weak pullup, for which we only need
593             // to set PADnPULL and clear 7:6 (already done at this point).
594             //
595             if ( ui32Pin == 20 )
596             {
597                 return AM_HAL_GPIO_ERR_PULLUP;
598             }
599 #endif // AM_HAL_DISABLE_API_VALIDATION
600         }
601     }
602 
603     //
604     // Check if requesting a power switch pin
605     //
606     if ( ui32PowerSw != AM_HAL_GPIO_PIN_POWERSW_NONE )
607     {
608         if ( (ui32PowerSw == AM_HAL_GPIO_PIN_POWERSW_VDD)  &&
609              (g_ui8Bit76Capabilities[ui32Pin] & CAP_VDD) )
610         {
611             ui32Padreg |= 0x1 << PADREG_FLD_76_S;
612         }
613         else if ( (ui32PowerSw == AM_HAL_GPIO_PIN_POWERSW_VSS)  &&
614                   (g_ui8Bit76Capabilities[ui32Pin] & CAP_VSS) )
615         {
616             ui32Padreg |= 0x2 << PADREG_FLD_76_S;
617         }
618         else
619         {
620             return AM_HAL_GPIO_ERR_PWRSW;
621         }
622     }
623 
624     //
625     // Depending on the selected pin and FNSEL, determine if INPEN needs to be set.
626     //
627     ui32Padreg |= (g_ui8Inpen[ui32Pin] & (1 << ui32Funcsel)) ? (1 << PADREG_FLD_INPEN_S) : 0;
628 
629     //
630     // Configure ui32GpCfg based on whether nCE requested.
631     //
632     if ( g_ui8nCEpins[ui32Pin] == ui32Funcsel )
633     {
634         uint32_t ui32Outcfg;
635         uint8_t ui8CEtbl;
636 
637         //
638         // User is configuring a nCE. Verify the requested settings and set the
639         // polarity and OUTCFG values (INCFG is not used here and should be 0).
640         // Valid uNCE values are 0-3 (uNCE is a 2-bit field).
641         // Valid uIOMnum are 0-5 (0-5 for IOMs, 0-2 for MSPI).
642         //
643 #ifndef AM_HAL_DISABLE_API_VALIDATION
644         //
645         // Optionally validate the settings.
646         //
647         if ( bfGpioCfg.uNCE >= 4 )
648         {
649             return AM_HAL_GPIO_ERR_INVCE;   // Invalid CE specified
650         }
651 
652         if ( (bfGpioCfg.bIomMSPIn)  &&
653              (bfGpioCfg.uIOMnum >= AM_REG_IOM_NUM_MODULES) )
654         {
655             return AM_HAL_GPIO_ERR_INVCE;   // Invalid CE specified
656         }
657         else if ( (!bfGpioCfg.bIomMSPIn)  &&
658                   (bfGpioCfg.uIOMnum >= AM_REG_MSPI_NUM_MODULES) )
659         {
660             return AM_HAL_GPIO_ERR_INVCE;   // Invalid CE specified
661         }
662 #endif // AM_HAL_DISABLE_API_VALIDATION
663 
664         //
665         // Construct the entry we expect to find in the table. We can determine
666         // the OUTCFG value by looking for that value in the pin row.
667         //
668         ui8CEtbl = NCETBL(bfGpioCfg.bIomMSPIn, bfGpioCfg.uIOMnum, bfGpioCfg.uNCE);
669 
670         //
671         // Now search the NCE table for a match.
672         //
673         for ( ui32Outcfg = 0; ui32Outcfg < 4; ui32Outcfg++ )
674         {
675             if ( g_ui8NCEtable[ui32Pin][ui32Outcfg] == ui8CEtbl )
676             {
677                 break;
678             }
679         }
680 
681 #ifndef AM_HAL_DISABLE_API_VALIDATION
682         if ( ui32Outcfg >= 4 )
683         {
684             return AM_HAL_GPIO_ERR_INVCEPIN;
685         }
686 #endif // AM_HAL_DISABLE_API_VALIDATION
687 
688         ui32GPCfg |= (ui32Outcfg       << GPIOCFG_FLD_OUTCFG_S) |
689                      (bfGpioCfg.eCEpol << GPIOCFG_FLD_INTD_S)   |
690                      (0                << GPIOCFG_FLD_INCFG_S);
691     }
692     else
693     {
694         //
695         // It's not nCE, it's one of the other funcsels.
696         // Start by setting the value of the requested GPIO input.
697         //
698         ui32Padreg |= (bfGpioCfg.eGPInput << PADREG_FLD_INPEN_S);
699 
700         //
701         // Map the requested interrupt direction settings into the Apollo3
702         //  GPIOCFG register field, which is a 4-bit field:
703         //  [INTD(1):OUTCFG(2):INCFG(1)].
704         // Bit0 of eIntDir maps to GPIOCFG.INTD  (b3).
705         // Bit1 of eIntDir maps to GPIOCFG.INCFG (b0).
706         //
707         ui32GPCfg |= (bfGpioCfg.eGPOutcfg << GPIOCFG_FLD_OUTCFG_S)              |
708                      (((bfGpioCfg.eIntDir >> 0) & 0x1) << GPIOCFG_FLD_INTD_S)   |
709                      (((bfGpioCfg.eIntDir >> 1) & 0x1) << GPIOCFG_FLD_INCFG_S);
710 
711         if ( (bfGpioCfg.eGPOutcfg == AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL) ||
712              pincfg_equ(&bfGpioCfg, (void*)&g_AM_HAL_GPIO_DISABLE) )
713         {
714             //
715             // For pushpull configurations, we must be sure to clear the ENABLE
716             // bit.  In pushpull, these bits turn on FAST GPIO.  For regular
717             // GPIO, they must be clear.
718             //
719             bClearEnable = true;
720         }
721 
722         //
723         // There is some overlap between eGPRdZero and eIntDir as both settings
724         //  utilize the overloaded INCFG bit.
725         // Therefore the two fields should be used in a mutually exclusive
726         //  manner. For flexibility however they are not disallowed because
727         //  their functionality is dependent on FUNCSEL and whether interrupts
728         //  are used.
729         //
730         // In the vein of mutual exclusion, eGPRdZero is primarily intended for
731         //  use when GPIO interrupts are not in use and can be used when no
732         //  eIntDir setting is provided.
733         // If eIntDir is provided, eGPRdZero is ignored and can only be
734         //  achieved via the AM_HAL_GPIO_PIN_INTDIR_NONE setting.
735         //
736         if ( bfGpioCfg.eIntDir == AM_HAL_GPIO_PIN_INTDIR_NONE )
737         {
738             ui32GPCfg &= ~(1 << GPIOCFG_FLD_INCFG_S);
739             ui32GPCfg |= (bfGpioCfg.eGPRdZero << GPIOCFG_FLD_INCFG_S);
740         }
741     }
742 
743     switch ( bfGpioCfg.eDriveStrength )
744     {
745         // DRIVESTRENGTH is a 2-bit field.
746         //  bit0 maps to bit2 of a PADREG field.
747         //  bit1 maps to bit0 of an ALTPADCFG field.
748         case AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA:
749             ui32Padreg    |= (0 << PADREG_FLD_DRVSTR_S);
750             ui32AltPadCfg |= (0 << 0);
751             break;
752         case AM_HAL_GPIO_PIN_DRIVESTRENGTH_4MA:
753             ui32Padreg    |= (1 << PADREG_FLD_DRVSTR_S);
754             ui32AltPadCfg |= (0 << 0);
755             break;
756         case AM_HAL_GPIO_PIN_DRIVESTRENGTH_8MA:
757             ui32Padreg    |= (0 << PADREG_FLD_DRVSTR_S);
758             ui32AltPadCfg |= (1 << 0);
759             break;
760         case AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA:
761             ui32Padreg    |= (1 << PADREG_FLD_DRVSTR_S);
762             ui32AltPadCfg |= (1 << 0);
763             break;
764     }
765 
766     //
767     // At this point, the 3 configuration variables, ui32GPCfg, ui32Padreg,
768     //  and ui32AltPadCfg values are set (at bit position 0) and ready to write
769     //  to their respective register bitfields.
770     //
771     uint32_t ui32GPCfgAddr, ui32PadregAddr, ui32AltpadAddr;
772     uint32_t ui32GPCfgClearMask, ui32PadClearMask;
773     uint32_t ui32GPCfgShft, ui32PadShft;
774 
775     ui32GPCfgAddr       = AM_REGADDR(GPIO, CFGA)       + ((ui32Pin >> 1) & ~0x3);
776     ui32PadregAddr      = AM_REGADDR(GPIO, PADREGA)    + (ui32Pin & ~0x3);
777     ui32AltpadAddr      = AM_REGADDR(GPIO, ALTPADCFGA) + (ui32Pin & ~0x3);
778 
779     ui32GPCfgShft       = ((ui32Pin & 0x7) << 2);
780     ui32PadShft         = ((ui32Pin & 0x3) << 3);
781     ui32GPCfgClearMask  = ~((uint32_t)0xF  << ui32GPCfgShft);
782     ui32PadClearMask    = ~((uint32_t)0xFF << ui32PadShft);
783 
784     //
785     // Get the new values into their rightful bit positions.
786     //
787     ui32Padreg    <<= ui32PadShft;
788     ui32AltPadCfg <<= ui32PadShft;
789     ui32GPCfg     <<= ui32GPCfgShft;
790 
791     AM_CRITICAL_BEGIN
792 
793     if ( bClearEnable )
794     {
795         //
796         // We're configuring a mode that requires clearing the Enable bit.
797         //
798         am_hal_gpio_output_tristate_disable(ui32Pin);
799     }
800 
801     GPIO->PADKEY = GPIO_PADKEY_PADKEY_Key;
802 
803     AM_REGVAL(ui32PadregAddr)  = (AM_REGVAL(ui32PadregAddr) & ui32PadClearMask)   | ui32Padreg;
804     AM_REGVAL(ui32GPCfgAddr)   = (AM_REGVAL(ui32GPCfgAddr)  & ui32GPCfgClearMask) | ui32GPCfg;
805     AM_REGVAL(ui32AltpadAddr)  = (AM_REGVAL(ui32AltpadAddr) & ui32PadClearMask)   | ui32AltPadCfg;
806 
807     GPIO->PADKEY = 0;
808 
809     AM_CRITICAL_END
810 
811     return AM_HAL_STATUS_SUCCESS;
812 
813 } // am_hal_gpio_pinconfig()
814 
815 //*****************************************************************************
816 //
817 // @brief Configure specified pins for FAST GPIO operation.
818 //
819 // @param psPinMask - a mask specifying up to 8 pins to be configured and
820 //               used for FAST GPIO (only bits 0-49 are valid).
821 // @param bfGpioCfg   - The GPIO configuration (same as am_hal_gpio_pinconfig()).
822 //               All of the pins specified by ui64PinMask will be set to this
823 //               configuration.
824 // @param ui32Masks   - If provided, an array to receive 2 32-bit values of the
825 //               SET and CLEAR masks that are used for the BBSETCLEAR reg.
826 //               Two 32-bit wds are placed for each pin indicated by the mask.
827 //               The 2 32-bit values will be placed at incremental indexes.
828 //               For example, say pin numbers 5 and 19 are indicated in the
829 //               mask, and an array pointer is provided in ui32Masks.  This
830 //               array must be allocated by the caller to be at least 4 words.
831 //               ui32Masks[0] = the set   mask used for pin 5.
832 //               ui32Masks[1] = the clear mask used for pin 5.
833 //               ui32Masks[2] = the set   mask used for pin 19.
834 //               ui32Masks[3] = the clear mask used for pin 19.
835 //               It is recommended that this array be allocated to 16 uint32_t.
836 //
837 // @return       Standard System Status
838 //
839 //*****************************************************************************
840 uint32_t
am_hal_gpio_fast_pinconfig(am_hal_gpio_mask_t * psPinMask,am_hal_gpio_pincfg_t bfGpioCfg,uint32_t ui32Masks[])841 am_hal_gpio_fast_pinconfig(am_hal_gpio_mask_t *psPinMask,
842                            am_hal_gpio_pincfg_t bfGpioCfg,
843                            uint32_t ui32Masks[])
844 {
845     uint32_t ux, ui32pinnum, ui32retval, ui32Mask, ui32PinMask;
846     uint32_t ui32WdIdx;
847 
848 #ifndef AM_HAL_DISABLE_API_VALIDATION
849     if ( psPinMask->U.Msk[AM_HAL_GPIO_NUMWORDS - 1] &
850          ~(((uint32_t)1 << (AM_HAL_GPIO_MAX_PADS - 64)) - 1)                    ||
851          (popcount((uint32_t*)&psPinMask->U.Msk[0], AM_HAL_GPIO_MAX_PADS) > 8)  ||
852          (bfGpioCfg.eGPOutcfg == AM_HAL_GPIO_PIN_OUTCFG_TRISTATE) )
853     {
854         return AM_HAL_STATUS_INVALID_ARG;
855     }
856 #endif // AM_HAL_DISABLE_API_VALIDATION
857 
858     //
859     // Roll through the pin mask and configure any designated pins per the
860     // bfGpioCfg parameter, and enable for Fast GPIO.
861     //
862     ux = 0;
863     ui32pinnum = 0;
864     ui32WdIdx = 0;
865     while ( ui32pinnum < AM_HAL_GPIO_MAX_PADS )
866     {
867         ui32PinMask = psPinMask->U.Msk[ui32WdIdx++];
868         ui32Mask = 0;
869 
870         while ( ui32PinMask )
871         {
872             if ( ui32PinMask & 0x1 )
873             {
874                 //
875                 // It is assumed that the caller will have disabled Fast GPIO and
876                 // initialized the pin value before calling this function. Therefore
877                 // no value initialization is done before the pin configuration, nor
878                 // is the am_hal_gpio_fastgpio_disable() called here.
879                 //
880                 // Configure the pin.
881                 //
882                 ui32retval = am_hal_gpio_pinconfig(ui32pinnum, bfGpioCfg);
883                 if ( ui32retval )
884                 {
885                     return ui32retval;
886                 }
887 
888                 ui32Mask |= 1 << (ui32pinnum & 0x7);
889 
890                 //
891                 // Enable the FAST GPIO for this pin
892                 //
893                 am_hal_gpio_fastgpio_enable(ui32pinnum);
894 
895                 if ( ui32Masks )
896                 {
897                     ui32Masks[ux + 0] = _VAL2FLD(APBDMA_BBSETCLEAR_SET,   ui32Mask);
898                     ui32Masks[ux + 1] = _VAL2FLD(APBDMA_BBSETCLEAR_CLEAR, ui32Mask);
899                 }
900                 ux += 2;    // Get next indexes
901             }
902             ui32pinnum++;
903             ui32PinMask >>= 1;
904         }
905         ui32pinnum &= ~31;
906         ui32pinnum += 32;
907     }
908 
909     return AM_HAL_STATUS_SUCCESS;
910 
911 } // am_hal_gpio_fast_pinconfig()
912 
913 //*****************************************************************************
914 //
915 // @brief Read GPIO.
916 //
917 // @param ui32Pin    - pin number to be read.
918 // @param eReadType  - State type to read.  One of:
919 //     AM_HAL_GPIO_INPUT_READ
920 //     AM_HAL_GPIO_OUTPUT_READ
921 //     AM_HAL_GPIO_ENABLE_READ
922 // @param pui32ReadState - Pointer to the value to contain the read state.
923 //        When reading the value of a bit, will be either 0 or 1.
924 //
925 // This function reads a pin state as given by ui32Type.
926 //
927 // @return Status.
928 //
929 // @note This function is intended for use only when the pin is configured as GPIO.
930 //
931 //*****************************************************************************
932 uint32_t
am_hal_gpio_state_read(uint32_t ui32Pin,am_hal_gpio_read_type_e eReadType,uint32_t * pui32ReadState)933 am_hal_gpio_state_read(uint32_t ui32Pin,
934                        am_hal_gpio_read_type_e eReadType,
935                        uint32_t *pui32ReadState)
936 {
937     uint32_t ui32ReadValue = 0xFFFFFFFF;
938     uint32_t ui32BaseAddr, ui32Shift;
939 
940 #ifndef AM_HAL_DISABLE_API_VALIDATION
941     if ( pui32ReadState == NULL )
942     {
943         return AM_HAL_STATUS_INVALID_ARG;
944     }
945 
946     if ( ui32Pin >= AM_HAL_GPIO_MAX_PADS )
947     {
948         *pui32ReadState = ui32ReadValue;
949         return AM_HAL_STATUS_OUT_OF_RANGE;
950     }
951 
952 #if 0   // By default, disable this additional validation check as it is very time consuming.
953     //
954     // Validate that the pin is configured for GPIO. Return error if not.
955     //
956     uint32_t ui32Regval, ui32PadShft, ui32FncselMsk;
957     ui32Regval    = AM_REGVAL( AM_REGADDR(GPIO, PADREGA) + (ui32Pin & ~0x3) );
958     ui32PadShft   = ((ui32Pin & 0x3) << 3);
959     ui32FncselMsk = (uint32_t)0x38 << ui32PadShft;
960     if ( (ui32Regval & ui32FncselMsk) != (0x3 << (ui32PadShft + 3)) )
961     {
962         return AM_HAL_STATUS_INVALID_ARG;
963     }
964 #endif
965 #endif // AM_HAL_DISABLE_API_VALIDATION
966 
967     //
968     // Compute base address + offset of 0 or 4.
969     //
970     ui32BaseAddr = ((ui32Pin & 0x60) >> 3);   // 0, 4, or 8
971     ui32Shift    = ui32Pin & 0x1F;
972 
973     switch ( eReadType )
974     {
975         case AM_HAL_GPIO_INPUT_READ:
976             //
977             // Assumes eIntDir != AM_HAL_GPIO_PIN_INTDIR_NONE   &&
978             //         eIntDir != AM_HAL_GPIO_PIN_INTDIR_BOTH
979             // If either of those configs are set, returns 0.
980             //
981             ui32ReadValue = AM_REGVAL(AM_REGADDR(GPIO, RDA) + ui32BaseAddr);
982             ui32ReadValue = (ui32ReadValue >> ui32Shift) & 0x01;
983             break;
984         case AM_HAL_GPIO_OUTPUT_READ:
985             ui32ReadValue = AM_REGVAL(AM_REGADDR(GPIO, WTA) + ui32BaseAddr);
986             ui32ReadValue = (ui32ReadValue >> ui32Shift) & 0x01;
987             break;
988         case AM_HAL_GPIO_ENABLE_READ:
989             ui32ReadValue = AM_REGVAL(AM_REGADDR(GPIO, ENA) + ui32BaseAddr);
990             ui32ReadValue = (ui32ReadValue >> ui32Shift) & 0x01;
991             break;
992         default:
993             return AM_HAL_STATUS_INVALID_ARG;
994     }
995 
996     *pui32ReadState = ui32ReadValue;
997 
998     return AM_HAL_STATUS_SUCCESS;
999 } // am_hal_gpio_state_read()
1000 
1001 //*****************************************************************************
1002 //
1003 // @brief Write GPIO.
1004 //
1005 // @param ui32Pin    - pin number to be written.
1006 //
1007 // @param eWriteType   - State type to write.  One of:
1008 //     AM_HAL_GPIO_OUTPUT_SET              - Write a one to a GPIO.
1009 //     AM_HAL_GPIO_OUTPUT_CLEAR            - Write a zero to a GPIO.
1010 //     AM_HAL_GPIO_OUTPUT_TOGGLE           - Toggle the GPIO value.
1011 //     The following two apply when output is set for TriState (OUTCFG==3).
1012 //     AM_HAL_GPIO_OUTPUT_TRISTATE_ENABLE  - Enable  a tri-state GPIO.
1013 //     AM_HAL_GPIO_OUTPUT_TRISTATE_DISABLE - Disable a tri-state GPIO.
1014 //
1015 // This function writes a GPIO value.
1016 //
1017 // @return Status.
1018 //
1019 // This function is intended for use only when the pin is configured as GPIO.
1020 //
1021 //*****************************************************************************
1022 uint32_t
am_hal_gpio_state_write(uint32_t ui32Pin,am_hal_gpio_write_type_e eWriteType)1023 am_hal_gpio_state_write(uint32_t ui32Pin, am_hal_gpio_write_type_e eWriteType)
1024 {
1025     uint32_t ui32Mask, ui32Off;
1026     uint32_t ui32Return = AM_HAL_STATUS_SUCCESS;
1027 
1028 #ifndef AM_HAL_DISABLE_API_VALIDATION
1029     if ( ui32Pin >= AM_HAL_GPIO_MAX_PADS )
1030     {
1031         return AM_HAL_STATUS_OUT_OF_RANGE;
1032     }
1033 
1034     if ( eWriteType > AM_HAL_GPIO_OUTPUT_TRISTATE_TOGGLE )
1035     {
1036         return AM_HAL_STATUS_INVALID_ARG;
1037     }
1038 
1039 #if 0   // By default, disable this additional validation check as it is very time consuming.
1040     //
1041     // Validate that the pin is configured for GPIO. Return error if not.
1042     //
1043     uint32_t ui32Regval, ui32PadShft, ui32FncselMsk;
1044     ui32Regval    = AM_REGVAL( AM_REGADDR(GPIO, PADREGA) + (ui32Pin & ~0x3) );
1045     ui32PadShft   = ((ui32Pin & 0x3) << 3);
1046     ui32FncselMsk = (uint32_t)0x38 << ui32PadShft;
1047     if ( (ui32Regval & ui32FncselMsk) != (0x3 << (ui32PadShft + 3)) )
1048     {
1049         return AM_HAL_STATUS_INVALID_ARG;
1050     }
1051 #endif
1052 #endif // AM_HAL_DISABLE_API_VALIDATION
1053 
1054     ui32Mask = (uint32_t)0x1 << (ui32Pin % 32);
1055     ui32Off  = (ui32Pin & 0x60) >> 3;   // 0, 4 or 8
1056 
1057     AM_CRITICAL_BEGIN;
1058     switch ( eWriteType )
1059     {
1060         case AM_HAL_GPIO_OUTPUT_SET:                // Write a one to a GPIO.
1061             AM_REGVAL(AM_REGADDR(GPIO, WTSA) + ui32Off) = ui32Mask;
1062             break;
1063         case AM_HAL_GPIO_OUTPUT_CLEAR:              // Write a zero to a GPIO.
1064             AM_REGVAL(AM_REGADDR(GPIO, WTCA) + ui32Off) = ui32Mask;
1065             break;
1066         case AM_HAL_GPIO_OUTPUT_TOGGLE:             // Toggle the GPIO value.
1067             AM_REGVAL(AM_REGADDR(GPIO, WTA) + ui32Off) ^= ui32Mask;
1068             break;
1069         case AM_HAL_GPIO_OUTPUT_TRISTATE_ENABLE:    // Enable  a tri-state GPIO.
1070             AM_REGVAL(AM_REGADDR(GPIO, ENSA) + ui32Off) = ui32Mask;
1071             break;
1072         case AM_HAL_GPIO_OUTPUT_TRISTATE_DISABLE:   // Disable a tri-state GPIO.
1073             AM_REGVAL(AM_REGADDR(GPIO, ENCA) + ui32Off) = ui32Mask;
1074             break;
1075         case AM_HAL_GPIO_OUTPUT_TRISTATE_TOGGLE:   // Toggle a tri-state GPIO.
1076             AM_REGVAL(AM_REGADDR(GPIO, ENCA) + ui32Off) ^= ui32Mask;
1077             break;
1078         default:
1079             // Type values were validated on entry.
1080             // We can't return from here because we're in a critical section.
1081             ui32Return = AM_HAL_STATUS_INVALID_ARG;
1082             break;
1083     }
1084 
1085     AM_CRITICAL_END;
1086 
1087     return ui32Return;
1088 } // am_hal_gpio_state_write()
1089 
1090 //*****************************************************************************
1091 //
1092 // Enable GPIO interrupts.
1093 //
1094 //*****************************************************************************
1095 uint32_t
am_hal_gpio_interrupt_enable(am_hal_gpio_mask_t * pGpioIntMask)1096 am_hal_gpio_interrupt_enable(am_hal_gpio_mask_t *pGpioIntMask)
1097 {
1098 #ifndef AM_HAL_DISABLE_API_VALIDATION
1099     if ( pGpioIntMask->U.Msk[AM_HAL_GPIO_MAX_PADS / 32] &
1100          ~(((uint32_t)1 << (AM_HAL_GPIO_MAX_PADS % 32)) - 1) )
1101     {
1102         return AM_HAL_STATUS_OUT_OF_RANGE;
1103     }
1104 #endif // AM_HAL_DISABLE_API_VALIDATION
1105 
1106     //
1107     // Enable the interrupts.
1108     //
1109     AM_CRITICAL_BEGIN
1110 
1111     DIAG_SUPPRESS_VOLATILE_ORDER()
1112     GPIO->INT0EN |= pGpioIntMask->U.Msk[0];
1113     GPIO->INT1EN |= pGpioIntMask->U.Msk[1];
1114     GPIO->INT2EN |= pGpioIntMask->U.Msk[2];
1115     DIAG_DEFAULT_VOLATILE_ORDER()
1116 
1117     AM_CRITICAL_END
1118 
1119     //
1120     // Return the status.
1121     //
1122     return AM_HAL_STATUS_SUCCESS;
1123 
1124 } // am_hal_gpio_interrupt_enable()
1125 
1126 //*****************************************************************************
1127 //
1128 // Disable GPIO interrupts.
1129 //
1130 //*****************************************************************************
1131 uint32_t
am_hal_gpio_interrupt_disable(am_hal_gpio_mask_t * pGpioIntMask)1132 am_hal_gpio_interrupt_disable(am_hal_gpio_mask_t *pGpioIntMask)
1133 {
1134 #ifndef AM_HAL_DISABLE_API_VALIDATION
1135 
1136     if ( !pGpioIntMask )
1137     {
1138         return AM_HAL_STATUS_INVALID_ARG;
1139     }
1140 
1141     if ( pGpioIntMask->U.Msk[AM_HAL_GPIO_MAX_PADS / 32] &
1142          ~(((uint32_t)1 << (AM_HAL_GPIO_MAX_PADS % 32)) - 1) )
1143     {
1144         return AM_HAL_STATUS_OUT_OF_RANGE;
1145     }
1146 #endif // AM_HAL_DISABLE_API_VALIDATION
1147 
1148     //
1149     // Disable the interrupts.
1150     //
1151     AM_CRITICAL_BEGIN
1152 
1153     DIAG_SUPPRESS_VOLATILE_ORDER()
1154     GPIO->INT0EN &= ~pGpioIntMask->U.Msk[0];
1155     GPIO->INT1EN &= ~pGpioIntMask->U.Msk[1];
1156     GPIO->INT2EN &= ~pGpioIntMask->U.Msk[2];
1157     DIAG_DEFAULT_VOLATILE_ORDER()
1158 
1159     AM_CRITICAL_END
1160 
1161     //
1162     // Return the status.
1163     //
1164     return AM_HAL_STATUS_SUCCESS;
1165 
1166 } // am_hal_gpio_interrupt_disable()
1167 
1168 //*****************************************************************************
1169 //
1170 // Clear GPIO interrupts.
1171 //
1172 //*****************************************************************************
1173 uint32_t
am_hal_gpio_interrupt_clear(am_hal_gpio_mask_t * pGpioIntMask)1174 am_hal_gpio_interrupt_clear(am_hal_gpio_mask_t *pGpioIntMask)
1175 {
1176 #ifndef AM_HAL_DISABLE_API_VALIDATION
1177     if ( !pGpioIntMask )
1178     {
1179         return AM_HAL_STATUS_INVALID_ARG;
1180     }
1181 
1182     if ( pGpioIntMask->U.Msk[AM_HAL_GPIO_MAX_PADS / 32] &
1183          ~(((uint32_t)1 << (AM_HAL_GPIO_MAX_PADS % 32)) - 1) )
1184     {
1185         return AM_HAL_STATUS_OUT_OF_RANGE;
1186     }
1187 #endif // AM_HAL_DISABLE_API_VALIDATION
1188 
1189     //
1190     // Clear the interrupts.
1191     //
1192     AM_CRITICAL_BEGIN
1193 
1194     DIAG_SUPPRESS_VOLATILE_ORDER()
1195     GPIO->INT0CLR |= pGpioIntMask->U.Msk[0];
1196     GPIO->INT1CLR |= pGpioIntMask->U.Msk[1];
1197     GPIO->INT2CLR |= pGpioIntMask->U.Msk[2];
1198     DIAG_DEFAULT_VOLATILE_ORDER()
1199 
1200     AM_CRITICAL_END
1201 
1202     //
1203     // Return the status.
1204     //
1205     return AM_HAL_STATUS_SUCCESS;
1206 
1207 } // am_hal_gpio_interrupt_clear()
1208 
1209 //*****************************************************************************
1210 //
1211 // Get GPIO interrupt status.
1212 //
1213 //*****************************************************************************
1214 uint32_t
am_hal_gpio_interrupt_status_get(bool bEnabledOnly,am_hal_gpio_mask_t * pGpioIntMask)1215 am_hal_gpio_interrupt_status_get(bool bEnabledOnly,
1216                                  am_hal_gpio_mask_t *pGpioIntMask)
1217 {
1218     volatile uint32_t ui32Mask[3];
1219 
1220 #ifndef AM_HAL_DISABLE_API_VALIDATION
1221     if ( !pGpioIntMask )
1222     {
1223         return AM_HAL_STATUS_INVALID_ARG;
1224     }
1225 
1226     if ( pGpioIntMask->U.Msk[AM_HAL_GPIO_MAX_PADS / 32] &
1227          ~(((uint32_t)1 << (AM_HAL_GPIO_MAX_PADS % 32)) - 1) )
1228     {
1229         return AM_HAL_STATUS_OUT_OF_RANGE;
1230     }
1231 #endif // AM_HAL_DISABLE_API_VALIDATION
1232 
1233     //
1234     // Initialize mask variable outside critical section
1235     //
1236     ui32Mask[0] = 0xFFFFFFFF;
1237     ui32Mask[1] = 0xFFFFFFFF;
1238     ui32Mask[2] = 0xFFFFFFFF;
1239 
1240     //
1241     // Combine upper or lower GPIO words into one 64 bit return value.
1242     //
1243     AM_CRITICAL_BEGIN
1244 
1245     DIAG_SUPPRESS_VOLATILE_ORDER()
1246     if ( bEnabledOnly )
1247     {
1248         ui32Mask[0] = GPIO->INT0EN;
1249         ui32Mask[1] = GPIO->INT1EN;
1250         ui32Mask[2] = GPIO->INT2EN;
1251     }
1252 
1253     pGpioIntMask->U.Msk[0] = GPIO->INT0STAT & ui32Mask[0];
1254     pGpioIntMask->U.Msk[1] = GPIO->INT1STAT & ui32Mask[1];
1255     pGpioIntMask->U.Msk[2] = GPIO->INT2STAT & ui32Mask[2];
1256     DIAG_DEFAULT_VOLATILE_ORDER()
1257 
1258     AM_CRITICAL_END
1259 
1260     //
1261     // Return the status.
1262     //
1263     return AM_HAL_STATUS_SUCCESS;
1264 
1265 } // am_hal_gpio_interrupt_status_get()
1266 
1267 //*****************************************************************************
1268 //
1269 // GPIO interrupt service routine registration.
1270 //
1271 //*****************************************************************************
1272 uint32_t
am_hal_gpio_interrupt_register(uint32_t ui32GPIONumber,am_hal_gpio_handler_t pfnHandler)1273 am_hal_gpio_interrupt_register(uint32_t ui32GPIONumber,
1274                                am_hal_gpio_handler_t pfnHandler)
1275 {
1276 #ifndef AM_HAL_DISABLE_API_VALIDATION
1277     //
1278     // Check parameters
1279     //
1280     if ( ui32GPIONumber >= AM_HAL_GPIO_MAX_PADS )
1281     {
1282         return AM_HAL_STATUS_OUT_OF_RANGE;
1283     }
1284 
1285     if ( pfnHandler == NULL )
1286     {
1287         return AM_HAL_STATUS_INVALID_ARG;
1288     }
1289 #endif // AM_HAL_DISABLE_API_VALIDATION
1290 
1291     //
1292     // Store the handler function pointer.
1293     //
1294     gpio_ppfnHandlers[ui32GPIONumber] = pfnHandler;
1295 
1296     //
1297     // Return the status.
1298     //
1299     return AM_HAL_STATUS_SUCCESS;
1300 
1301 } // am_hal_gpio_interrupt_register()
1302 
1303 //*****************************************************************************
1304 //
1305 // @brief Advanced GPIO interrupt service routine registration.
1306 //
1307 // @param ui32GPIONumber - GPIO number (0-73) to be registered.
1308 // @param pfnHandler - Function pointer to the callback.
1309 // @param pCtxt      - context for the callback.
1310 //
1311 // @return Status.
1312 //         Fails if pfnHandler is NULL or ui32GPIONumber > 73.
1313 //
1314 //*****************************************************************************
1315 uint32_t
am_hal_gpio_interrupt_register_adv(uint32_t ui32GPIONumber,am_hal_gpio_handler_adv_t pfnHandler,void * pCtxt)1316 am_hal_gpio_interrupt_register_adv(uint32_t ui32GPIONumber,
1317                                    am_hal_gpio_handler_adv_t pfnHandler, void *pCtxt)
1318 {
1319 #ifndef AM_HAL_DISABLE_API_VALIDATION
1320     //
1321     // Check parameters
1322     //
1323     if ( ui32GPIONumber >= AM_HAL_GPIO_MAX_PADS )
1324     {
1325         return AM_HAL_STATUS_OUT_OF_RANGE;
1326     }
1327 
1328     if ( pfnHandler == NULL )
1329     {
1330         return AM_HAL_STATUS_INVALID_ARG;
1331     }
1332 #endif // AM_HAL_DISABLE_API_VALIDATION
1333 
1334     //
1335     // Store the handler function pointer.
1336     //
1337     gpio_ppfnHandlers[ui32GPIONumber] = (am_hal_gpio_handler_t)((uint32_t)pfnHandler & ~0x1);
1338     gpio_pHandlerCtxt[ui32GPIONumber] = pCtxt;
1339 
1340     //
1341     // Return the status.
1342     //
1343     return AM_HAL_STATUS_SUCCESS;
1344 
1345 } // am_hal_gpio_interrupt_register_adv()
1346 
1347 //*****************************************************************************
1348 //
1349 // GPIO interrupt service routine.
1350 //
1351 //*****************************************************************************
1352 uint32_t
am_hal_gpio_interrupt_service(am_hal_gpio_mask_t * pGpioIntMaskStatus)1353 am_hal_gpio_interrupt_service(am_hal_gpio_mask_t *pGpioIntMaskStatus)
1354 {
1355     uint32_t ui32RetStatus = AM_HAL_STATUS_SUCCESS;
1356     uint32_t ui32Status, ui32FFS, ui32Idx;
1357     am_hal_gpio_handler_t pfnHandler;
1358     uint32_t *pui32Status;
1359 
1360 #ifndef AM_HAL_DISABLE_API_VALIDATION
1361     if ( !pGpioIntMaskStatus )
1362     {
1363         return AM_HAL_STATUS_INVALID_ARG;
1364     }
1365 
1366     if ( pGpioIntMaskStatus->U.Msk[AM_HAL_GPIO_MAX_PADS / 32] &
1367          ~(((uint32_t)1 << (AM_HAL_GPIO_MAX_PADS % 32)) - 1) )
1368     {
1369         return AM_HAL_STATUS_OUT_OF_RANGE;
1370     }
1371 #endif // AM_HAL_DISABLE_API_VALIDATION
1372 
1373     //
1374     // Convert the mask status structure to an uint32_t pointer.
1375     //
1376     pui32Status = (uint32_t*)pGpioIntMaskStatus;
1377 
1378     //
1379     // Handle interrupts.
1380     //
1381     uint32_t ui32regcnt = AM_HAL_GPIO_NUMWORDS;
1382     ui32Idx = 0;
1383     while ( ui32regcnt )
1384     {
1385         //
1386         // Get next status word from the caller.
1387         //
1388         ui32Status = *pui32Status++;
1389 
1390         while ( ui32Status )
1391         {
1392             //
1393             // We need to FFS (Find First Set).  We can easily zero-base FFS
1394             // since we know that at least 1 bit is set in ui32Status.
1395             // FFS(x) = 31 - clz(x & -x).       // Zero-based version of FFS.
1396             //
1397             ui32FFS = ui32Status & (uint32_t)(-(int32_t)ui32Status);
1398             ui32FFS = 31 - AM_ASM_CLZ(ui32FFS);
1399 
1400             //
1401             // Turn off the bit we picked in the working copy
1402             //
1403             ui32Status &= ~(0x00000001 << ui32FFS);
1404 
1405             //
1406             // Check the bit handler table to see if there is an interrupt handler
1407             // registered for this particular bit.
1408             //
1409             pfnHandler = gpio_ppfnHandlers[ui32Idx + ui32FFS];
1410             if ( pfnHandler )
1411             {
1412                 //
1413                 // If we found an interrupt handler routine, call it now.
1414                 //
1415                 if ((uint32_t)pfnHandler & 0x1)
1416                 {
1417                     pfnHandler();
1418                 }
1419                 else
1420                 {
1421                     am_hal_gpio_handler_adv_t padvHandler = (am_hal_gpio_handler_adv_t)((uint32_t)pfnHandler | 0x1);
1422                     padvHandler(gpio_pHandlerCtxt[ui32Idx + ui32FFS]);
1423                 }
1424             }
1425             else
1426             {
1427                 //
1428                 // No handler was registered for the GPIO that interrupted.
1429                 // Return an error.
1430                 //
1431                 ui32RetStatus = AM_HAL_STATUS_INVALID_OPERATION;
1432             }
1433         }
1434         --ui32regcnt;
1435         ui32Idx += 32;
1436     }
1437 
1438     //
1439     // Return the status.
1440     //
1441     return ui32RetStatus;
1442 
1443 } // am_hal_gpio_interrupt_service()
1444 
1445 //*****************************************************************************
1446 //
1447 //  am_hal_gpio_isinput()
1448 //
1449 //  Determine whether a pad is configured with input enable.
1450 //  Returns true if input enable is set, false otherwise.
1451 //
1452 //*****************************************************************************
am_hal_gpio_isinput(uint32_t ui32Pin)1453 bool am_hal_gpio_isinput(uint32_t ui32Pin)
1454 {
1455     uint32_t ui32Regval, ui32PadShft, ui32InpenMsk;
1456     ui32Regval    = AM_REGVAL( AM_REGADDR(GPIO, PADREGA) + (ui32Pin & ~0x3) );
1457     ui32PadShft   = ((ui32Pin & 0x3) << 3);
1458     ui32InpenMsk = (uint32_t)0x02 << ui32PadShft;
1459 
1460     return (ui32Regval & ui32InpenMsk) ? true : false;
1461 } // am_hal_gpio_isinput()
1462 
1463 //*****************************************************************************
1464 //  am_hal_gpio_isgpio()
1465 //
1466 //  Determine whether the GPIO is configured as input or output.
1467 //
1468 //  Return values:
1469 //      0: Pin is not configured as GPIO.
1470 //      1: Pin is configured as GPIO input.
1471 //      2: Pin is configured as GPIO output.
1472 //*****************************************************************************
am_hal_gpio_isgpio(uint32_t ui32Pin)1473 uint32_t am_hal_gpio_isgpio(uint32_t ui32Pin)
1474 {
1475     uint32_t ui32Padval, ui32Cfgval;
1476 
1477     //
1478     // Check PADREGx field for this pin.
1479     // [5:3] is FNCSEL (must be 0x18 for GPIO), [1:1] is INPEN.
1480     //
1481     ui32Padval   = AM_REGVAL( AM_REGADDR(GPIO, PADREGA) + (ui32Pin & ~0x3) );
1482     ui32Padval >>= ((ui32Pin & 0x3) << 3);
1483     if ( (ui32Padval & 0x38) != 0x18 )
1484     {
1485         //
1486         // Not configured as GPIO
1487         //
1488         return 0;
1489     }
1490 
1491     //
1492     // Determine if an input or an output.
1493     //
1494     ui32Cfgval = AM_REGVAL( AM_REGADDR(GPIO, CFGA) + ((ui32Pin >> 1) & ~0x3) );
1495     ui32Cfgval >>= ((ui32Pin & 0x7) * 4);
1496     if ( (ui32Padval & 0x02) )
1497     {
1498         //
1499         // INPEN is set, so probably a GPIO input.
1500         // However, GPIO outputs can also be set to read the pin state,
1501         // which requires INPEN be set.
1502         //
1503         return (ui32Cfgval & 0x6) == 0 ? 1 : 2;
1504     }
1505     else
1506     {
1507         return 2;
1508     }
1509 } // am_hal_gpio_isgpio()
1510 
1511 //*****************************************************************************
1512 //
1513 // End Doxygen group.
1514 //! @}
1515 //
1516 //*****************************************************************************
1517