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