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