1 /*
2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include "hardware/gpio.h"
8 #include "hardware/sync.h"
9
10 #include "hardware/structs/io_bank0.h"
11 #include "hardware/irq.h"
12
13 #if LIB_PICO_BINARY_INFO
14 #include "pico/binary_info.h"
15 #endif
16
17 static gpio_irq_callback_t callbacks[NUM_CORES];
18 // a 1 bit means the IRQ is handled by a raw IRQ handler
19 #if NUM_BANK0_GPIOS > 32
20 typedef uint64_t raw_irq_mask_type_t;
21 #else
22 typedef uint32_t raw_irq_mask_type_t;
23 #endif
24
25 static raw_irq_mask_type_t raw_irq_mask[NUM_CORES];
26
27 // Get the raw value from the pin, bypassing any muxing or overrides.
gpio_get_pad(uint gpio)28 int gpio_get_pad(uint gpio) {
29 check_gpio_param(gpio);
30 hw_set_bits(&pads_bank0_hw->io[gpio], PADS_BANK0_GPIO0_IE_BITS);
31 return (io_bank0_hw->io[gpio].status & IO_BANK0_GPIO0_STATUS_INFROMPAD_BITS)
32 >> IO_BANK0_GPIO0_STATUS_INFROMPAD_LSB;
33 }
34
35 /// \tag::gpio_set_function[]
36 // Select function for this GPIO, and ensure input/output are enabled at the pad.
37 // This also clears the input/output/irq override bits.
gpio_set_function(uint gpio,gpio_function_t fn)38 void gpio_set_function(uint gpio, gpio_function_t fn) {
39 check_gpio_param(gpio);
40 invalid_params_if(HARDWARE_GPIO, ((uint32_t)fn << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB) & ~IO_BANK0_GPIO0_CTRL_FUNCSEL_BITS);
41 // Set input enable on, output disable off
42 hw_write_masked(&pads_bank0_hw->io[gpio],
43 PADS_BANK0_GPIO0_IE_BITS,
44 PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS
45 );
46 // Zero all fields apart from fsel; we want this IO to do what the peripheral tells it.
47 // This doesn't affect e.g. pullup/pulldown, as these are in pad controls.
48 io_bank0_hw->io[gpio].ctrl = fn << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
49 #if !PICO_RP2040
50 // Remove pad isolation now that the correct peripheral is in control of the pad
51 hw_clear_bits(&pads_bank0_hw->io[gpio], PADS_BANK0_GPIO0_ISO_BITS);
52 #endif
53 }
54 /// \end::gpio_set_function[]
55
gpio_get_function(uint gpio)56 gpio_function_t gpio_get_function(uint gpio) {
57 check_gpio_param(gpio);
58 return (gpio_function_t) ((io_bank0_hw->io[gpio].ctrl & IO_BANK0_GPIO0_CTRL_FUNCSEL_BITS) >> IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB);
59 }
60
61 // Note that, on RP2040, setting both pulls enables a "bus keep" function,
62 // i.e. weak pull to whatever is current high/low state of GPIO.
gpio_set_pulls(uint gpio,bool up,bool down)63 void gpio_set_pulls(uint gpio, bool up, bool down) {
64 check_gpio_param(gpio);
65 hw_write_masked(
66 &pads_bank0_hw->io[gpio],
67 (bool_to_bit(up) << PADS_BANK0_GPIO0_PUE_LSB) | (bool_to_bit(down) << PADS_BANK0_GPIO0_PDE_LSB),
68 PADS_BANK0_GPIO0_PUE_BITS | PADS_BANK0_GPIO0_PDE_BITS
69 );
70 }
71
72 // Direct override for per-GPIO IRQ signal
gpio_set_irqover(uint gpio,uint value)73 void gpio_set_irqover(uint gpio, uint value) {
74 check_gpio_param(gpio);
75 hw_write_masked(&io_bank0_hw->io[gpio].ctrl,
76 value << IO_BANK0_GPIO0_CTRL_IRQOVER_LSB,
77 IO_BANK0_GPIO0_CTRL_IRQOVER_BITS
78 );
79 }
80
81 // Direct overrides for pad controls
gpio_set_inover(uint gpio,uint value)82 void gpio_set_inover(uint gpio, uint value) {
83 check_gpio_param(gpio);
84 hw_write_masked(&io_bank0_hw->io[gpio].ctrl,
85 value << IO_BANK0_GPIO0_CTRL_INOVER_LSB,
86 IO_BANK0_GPIO0_CTRL_INOVER_BITS
87 );
88 }
89
gpio_set_outover(uint gpio,uint value)90 void gpio_set_outover(uint gpio, uint value) {
91 check_gpio_param(gpio);
92 hw_write_masked(&io_bank0_hw->io[gpio].ctrl,
93 value << IO_BANK0_GPIO0_CTRL_OUTOVER_LSB,
94 IO_BANK0_GPIO0_CTRL_OUTOVER_BITS
95 );
96 }
97
gpio_set_oeover(uint gpio,uint value)98 void gpio_set_oeover(uint gpio, uint value) {
99 check_gpio_param(gpio);
100 hw_write_masked(&io_bank0_hw->io[gpio].ctrl,
101 value << IO_BANK0_GPIO0_CTRL_OEOVER_LSB,
102 IO_BANK0_GPIO0_CTRL_OEOVER_BITS
103 );
104 }
105
gpio_set_input_hysteresis_enabled(uint gpio,bool enabled)106 void gpio_set_input_hysteresis_enabled(uint gpio, bool enabled) {
107 check_gpio_param(gpio);
108 if (enabled)
109 hw_set_bits(&pads_bank0_hw->io[gpio], PADS_BANK0_GPIO0_SCHMITT_BITS);
110 else
111 hw_clear_bits(&pads_bank0_hw->io[gpio], PADS_BANK0_GPIO0_SCHMITT_BITS);
112 }
113
114
gpio_is_input_hysteresis_enabled(uint gpio)115 bool gpio_is_input_hysteresis_enabled(uint gpio) {
116 check_gpio_param(gpio);
117 return (pads_bank0_hw->io[gpio] & PADS_BANK0_GPIO0_SCHMITT_BITS) != 0;
118 }
119
gpio_set_slew_rate(uint gpio,enum gpio_slew_rate slew)120 void gpio_set_slew_rate(uint gpio, enum gpio_slew_rate slew) {
121 check_gpio_param(gpio);
122 hw_write_masked(&pads_bank0_hw->io[gpio],
123 (uint)slew << PADS_BANK0_GPIO0_SLEWFAST_LSB,
124 PADS_BANK0_GPIO0_SLEWFAST_BITS
125 );
126 }
127
gpio_get_slew_rate(uint gpio)128 enum gpio_slew_rate gpio_get_slew_rate(uint gpio) {
129 check_gpio_param(gpio);
130 return (enum gpio_slew_rate)((pads_bank0_hw->io[gpio]
131 & PADS_BANK0_GPIO0_SLEWFAST_BITS)
132 >> PADS_BANK0_GPIO0_SLEWFAST_LSB);
133 }
134
135
136 // Enum encoding should match hardware encoding on RP2040
137 static_assert(PADS_BANK0_GPIO0_DRIVE_VALUE_8MA == GPIO_DRIVE_STRENGTH_8MA, "");
gpio_set_drive_strength(uint gpio,enum gpio_drive_strength drive)138 void gpio_set_drive_strength(uint gpio, enum gpio_drive_strength drive) {
139 check_gpio_param(gpio);
140 hw_write_masked(&pads_bank0_hw->io[gpio],
141 (uint)drive << PADS_BANK0_GPIO0_DRIVE_LSB,
142 PADS_BANK0_GPIO0_DRIVE_BITS
143 );
144 }
145
gpio_get_drive_strength(uint gpio)146 enum gpio_drive_strength gpio_get_drive_strength(uint gpio) {
147 check_gpio_param(gpio);
148 return (enum gpio_drive_strength)((pads_bank0_hw->io[gpio]
149 & PADS_BANK0_GPIO0_DRIVE_BITS)
150 >> PADS_BANK0_GPIO0_DRIVE_LSB);
151 }
152
gpio_default_irq_handler(void)153 static void gpio_default_irq_handler(void) {
154 uint core = get_core_num();
155 gpio_irq_callback_t callback = callbacks[core];
156 io_bank0_irq_ctrl_hw_t *irq_ctrl_base = core ? &io_bank0_hw->proc1_irq_ctrl : &io_bank0_hw->proc0_irq_ctrl;
157 for (uint gpio = 0; gpio < NUM_BANK0_GPIOS; gpio+=8) {
158 uint32_t events8 = irq_ctrl_base->ints[gpio >> 3u];
159 // note we assume events8 is 0 for non-existent GPIO
160 for(uint i=gpio;events8 && i<gpio+8;i++) {
161 uint32_t events = events8 & 0xfu;
162 if (events && !(raw_irq_mask[core] & (1ull << i))) {
163 gpio_acknowledge_irq(i, events);
164 if (callback) {
165 callback(i, events);
166 }
167 }
168 events8 >>= 4;
169 }
170 }
171 }
172
_gpio_set_irq_enabled(uint gpio,uint32_t events,bool enabled,io_bank0_irq_ctrl_hw_t * irq_ctrl_base)173 static void _gpio_set_irq_enabled(uint gpio, uint32_t events, bool enabled, io_bank0_irq_ctrl_hw_t *irq_ctrl_base) {
174 // Clear stale events which might cause immediate spurious handler entry
175 gpio_acknowledge_irq(gpio, events);
176
177 io_rw_32 *en_reg = &irq_ctrl_base->inte[gpio / 8];
178 events <<= 4 * (gpio % 8);
179
180 if (enabled)
181 hw_set_bits(en_reg, events);
182 else
183 hw_clear_bits(en_reg, events);
184 }
185
gpio_set_irq_enabled(uint gpio,uint32_t events,bool enabled)186 void gpio_set_irq_enabled(uint gpio, uint32_t events, bool enabled) {
187 // either this call disables the interrupt
188 // or callback should already be set (raw or using gpio_set_irq_callback)
189 // this protects against enabling the interrupt without callback set
190 /**
191 * Modification on the porting to Zephyr:
192 * The GPIO irq is managed by Zephyr, so there is no need to check it in the SDK.
193 *
194 assert(!enabled
195 || (raw_irq_mask[get_core_num()] & (1ull<<gpio))
196 || callbacks[get_core_num()]);
197 */
198
199 // Separate mask/force/status per-core, so check which core called, and
200 // set the relevant IRQ controls.
201 io_bank0_irq_ctrl_hw_t *irq_ctrl_base = get_core_num() ?
202 &io_bank0_hw->proc1_irq_ctrl : &io_bank0_hw->proc0_irq_ctrl;
203 _gpio_set_irq_enabled(gpio, events, enabled, irq_ctrl_base);
204 }
205
gpio_set_irq_enabled_with_callback(uint gpio,uint32_t events,bool enabled,gpio_irq_callback_t callback)206 void gpio_set_irq_enabled_with_callback(uint gpio, uint32_t events, bool enabled, gpio_irq_callback_t callback) {
207 // first set callback, then enable the interrupt
208 gpio_set_irq_callback(callback);
209 gpio_set_irq_enabled(gpio, events, enabled);
210 if (enabled) irq_set_enabled(IO_IRQ_BANK0, true);
211 }
212
gpio_set_irq_callback(gpio_irq_callback_t callback)213 void gpio_set_irq_callback(gpio_irq_callback_t callback) {
214 uint core = get_core_num();
215 if (callbacks[core]) {
216 if (!callback) {
217 irq_remove_handler(IO_IRQ_BANK0, gpio_default_irq_handler);
218 }
219 callbacks[core] = callback;
220 } else if (callback) {
221 callbacks[core] = callback;
222 irq_add_shared_handler(IO_IRQ_BANK0, gpio_default_irq_handler, GPIO_IRQ_CALLBACK_ORDER_PRIORITY);
223 }
224 }
225
gpio_add_raw_irq_handler_with_order_priority_masked(uint32_t gpio_mask,irq_handler_t handler,uint8_t order_priority)226 void gpio_add_raw_irq_handler_with_order_priority_masked(uint32_t gpio_mask, irq_handler_t handler, uint8_t order_priority) {
227 hard_assert(!(raw_irq_mask[get_core_num()] & gpio_mask)); // should not add multiple handlers for the same event
228 raw_irq_mask[get_core_num()] |= gpio_mask;
229 irq_add_shared_handler(IO_IRQ_BANK0, handler, order_priority);
230 }
231
gpio_add_raw_irq_handler_with_order_priority_masked64(uint64_t gpio_mask,irq_handler_t handler,uint8_t order_priority)232 void gpio_add_raw_irq_handler_with_order_priority_masked64(uint64_t gpio_mask, irq_handler_t handler, uint8_t order_priority) {
233 hard_assert(!(raw_irq_mask[get_core_num()] & gpio_mask)); // should not add multiple handlers for the same event
234 raw_irq_mask[get_core_num()] |= (raw_irq_mask_type_t) gpio_mask;
235 irq_add_shared_handler(IO_IRQ_BANK0, handler, order_priority);
236 }
237
gpio_add_raw_irq_handler_masked(uint32_t gpio_mask,irq_handler_t handler)238 void gpio_add_raw_irq_handler_masked(uint32_t gpio_mask, irq_handler_t handler) {
239 gpio_add_raw_irq_handler_with_order_priority_masked(gpio_mask, handler, GPIO_RAW_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
240 }
241
gpio_add_raw_irq_handler_masked64(uint64_t gpio_mask,irq_handler_t handler)242 void gpio_add_raw_irq_handler_masked64(uint64_t gpio_mask, irq_handler_t handler) {
243 gpio_add_raw_irq_handler_with_order_priority_masked64(gpio_mask, handler, GPIO_RAW_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
244 }
245
gpio_remove_raw_irq_handler_masked(uint32_t gpio_mask,irq_handler_t handler)246 void gpio_remove_raw_irq_handler_masked(uint32_t gpio_mask, irq_handler_t handler) {
247 assert(raw_irq_mask[get_core_num()] & gpio_mask); // should not remove handlers that are not added
248 irq_remove_handler(IO_IRQ_BANK0, handler);
249 raw_irq_mask[get_core_num()] &= ~gpio_mask;
250 }
251
gpio_remove_raw_irq_handler_masked64(uint64_t gpio_mask,irq_handler_t handler)252 void gpio_remove_raw_irq_handler_masked64(uint64_t gpio_mask, irq_handler_t handler) {
253 assert(raw_irq_mask[get_core_num()] & gpio_mask); // should not remove handlers that are not added
254 irq_remove_handler(IO_IRQ_BANK0, handler);
255 raw_irq_mask[get_core_num()] &= (raw_irq_mask_type_t)~gpio_mask;
256 }
257
gpio_set_dormant_irq_enabled(uint gpio,uint32_t events,bool enabled)258 void gpio_set_dormant_irq_enabled(uint gpio, uint32_t events, bool enabled) {
259 check_gpio_param(gpio);
260 io_bank0_irq_ctrl_hw_t *irq_ctrl_base = &io_bank0_hw->dormant_wake_irq_ctrl;
261 _gpio_set_irq_enabled(gpio, events, enabled, irq_ctrl_base);
262 }
263
gpio_acknowledge_irq(uint gpio,uint32_t events)264 void gpio_acknowledge_irq(uint gpio, uint32_t events) {
265 check_gpio_param(gpio);
266 io_bank0_hw->intr[gpio / 8] = events << (4 * (gpio % 8));
267 }
268
269 #define DEBUG_PIN_MASK (((1u << PICO_DEBUG_PIN_COUNT)-1) << PICO_DEBUG_PIN_BASE)
gpio_debug_pins_init(void)270 void gpio_debug_pins_init(void) {
271 gpio_init_mask(DEBUG_PIN_MASK);
272 gpio_set_dir_masked(DEBUG_PIN_MASK, DEBUG_PIN_MASK);
273 #if LIB_PICO_BINARY_INFO
274 bi_decl_if_func_used(bi_pin_mask_with_names(DEBUG_PIN_MASK, "Debug"));
275 #endif
276 }
277
gpio_set_input_enabled(uint gpio,bool enabled)278 void gpio_set_input_enabled(uint gpio, bool enabled) {
279 check_gpio_param(gpio);
280 if (enabled)
281 hw_set_bits(&pads_bank0_hw->io[gpio], PADS_BANK0_GPIO0_IE_BITS);
282 else
283 hw_clear_bits(&pads_bank0_hw->io[gpio], PADS_BANK0_GPIO0_IE_BITS);
284 }
285
gpio_init(uint gpio)286 void gpio_init(uint gpio) {
287 gpio_set_dir(gpio, GPIO_IN);
288 gpio_put(gpio, 0);
289 gpio_set_function(gpio, GPIO_FUNC_SIO);
290 }
291
gpio_deinit(uint gpio)292 void gpio_deinit(uint gpio) {
293 gpio_set_function(gpio, GPIO_FUNC_NULL);
294 }
295
gpio_init_mask(uint gpio_mask)296 void gpio_init_mask(uint gpio_mask) {
297 for(uint i=0;i<NUM_BANK0_GPIOS;i++) {
298 if (gpio_mask & 1) {
299 gpio_init(i);
300 }
301 gpio_mask >>= 1;
302 }
303 }
304
gpio_set_function_masked(uint32_t gpio_mask,gpio_function_t fn)305 void gpio_set_function_masked(uint32_t gpio_mask, gpio_function_t fn) {
306 for (uint i = 0; i < MIN(NUM_BANK0_GPIOS, 32u); i++) {
307 if (gpio_mask & 1u) {
308 gpio_set_function(i, fn);
309 }
310 gpio_mask >>= 1;
311 }
312 }
313
gpio_set_function_masked64(uint64_t gpio_mask,gpio_function_t fn)314 void gpio_set_function_masked64(uint64_t gpio_mask, gpio_function_t fn) {
315 for (uint i = 0; i < MIN(NUM_BANK0_GPIOS, 64u); i++) {
316 if (gpio_mask & 1u) {
317 gpio_set_function(i, fn);
318 }
319 gpio_mask >>= 1;
320 }
321 }
322