1 /*
2 * Copyright (c) 2016-2017 Piotr Mienkowski
3 * Copyright (c) 2020 Gerson Fernando Budke <nandojve@gmail.com>
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /** @file
8 * @brief Atmel SAM MCU family General Purpose Input Output (GPIO)
9 * module HAL driver.
10 */
11
12 #ifndef _ATMEL_SAM_SOC_GPIO_H_
13 #define _ATMEL_SAM_SOC_GPIO_H_
14
15 #include <zephyr/types.h>
16 #include <soc.h>
17
18 /*
19 * Pin flags/attributes
20 */
21
22 /* TODO: replace hard coded pin attribute values with defines provided
23 * in gpio.h, once the official API is clean.
24 */
25
26 #define SOC_GPIO_DEFAULT (0)
27
28 #define SOC_GPIO_FLAGS_POS (0)
29 #define SOC_GPIO_FLAGS_MASK (7 << SOC_GPIO_FLAGS_POS)
30 #define SOC_GPIO_PULLUP_POS (0)
31 #define SOC_GPIO_PULLUP (1 << SOC_GPIO_PULLUP_POS)
32 #define SOC_GPIO_PULLDOWN_POS (1)
33 #define SOC_GPIO_PULLDOWN (1 << SOC_GPIO_PULLDOWN_POS)
34 #define SOC_GPIO_OPENDRAIN_POS (2)
35 #define SOC_GPIO_OPENDRAIN (1 << SOC_GPIO_OPENDRAIN_POS)
36
37 /* Bit field: SOC_GPIO_IN_FILTER */
38 #define SOC_GPIO_IN_FILTER_POS (3)
39 #define SOC_GPIO_IN_FILTER_MASK (3 << SOC_GPIO_IN_FILTER_POS)
40 #define SOC_GPIO_IN_FILTER_NONE (0 << SOC_GPIO_IN_FILTER_POS)
41 #define SOC_GPIO_IN_FILTER_DEBOUNCE (1 << SOC_GPIO_IN_FILTER_POS)
42 #define SOC_GPIO_IN_FILTER_DEGLITCH (2 << SOC_GPIO_IN_FILTER_POS)
43
44 #define SOC_GPIO_INT_ENABLE (1 << 5)
45
46 /* Bit field: SOC_GPIO_INT_TRIG */
47 #define SOC_GPIO_INT_TRIG_POS (6)
48 #define SOC_GPIO_INT_TRIG_MASK (3 << SOC_GPIO_INT_TRIG_POS)
49 /** Interrupt is triggered by a level detection event. */
50 #define SOC_GPIO_INT_TRIG_LEVEL (0 << SOC_GPIO_INT_TRIG_POS)
51 /** Interrupt is triggered by an edge detection event. */
52 #define SOC_GPIO_INT_TRIG_EDGE (1 << SOC_GPIO_INT_TRIG_POS)
53 /** Interrupt is triggered by any edge detection event. */
54 #define SOC_GPIO_INT_TRIG_DOUBLE_EDGE (2 << SOC_GPIO_INT_TRIG_POS)
55
56 /** Interrupt is triggered by a high level / rising edge detection event */
57 #define SOC_GPIO_INT_ACTIVE_HIGH (1 << 8)
58
59 /* Bit field: SOC_GPIO_FUNC */
60 #define SOC_GPIO_FUNC_POS (16)
61 #define SOC_GPIO_FUNC_MASK (15 << SOC_GPIO_FUNC_POS)
62 /** Connect pin to peripheral A. */
63 #define SOC_GPIO_FUNC_A (0 << SOC_GPIO_FUNC_POS)
64 /** Connect pin to peripheral B. */
65 #define SOC_GPIO_FUNC_B (1 << SOC_GPIO_FUNC_POS)
66 /** Connect pin to peripheral C. */
67 #define SOC_GPIO_FUNC_C (2 << SOC_GPIO_FUNC_POS)
68 /** Connect pin to peripheral D. */
69 #define SOC_GPIO_FUNC_D (3 << SOC_GPIO_FUNC_POS)
70 /** Connect pin to peripheral E. */
71 #define SOC_GPIO_FUNC_E (4 << SOC_GPIO_FUNC_POS)
72 /** Connect pin to peripheral F. */
73 #define SOC_GPIO_FUNC_F (5 << SOC_GPIO_FUNC_POS)
74 /** Connect pin to peripheral G. */
75 #define SOC_GPIO_FUNC_G (6 << SOC_GPIO_FUNC_POS)
76 /** Connect pin to peripheral H. */
77 #define SOC_GPIO_FUNC_H (7 << SOC_GPIO_FUNC_POS)
78 /** Configure pin as input. */
79 #define SOC_GPIO_FUNC_IN (8 << SOC_GPIO_FUNC_POS)
80 /** Configure pin as output and set it initial value to 0. */
81 #define SOC_GPIO_FUNC_OUT_0 (9 << SOC_GPIO_FUNC_POS)
82 /** Configure pin as output and set it initial value to 1. */
83 #define SOC_GPIO_FUNC_OUT_1 (10 << SOC_GPIO_FUNC_POS)
84
85 struct soc_gpio_pin {
86 uint32_t mask; /** pin(s) bit mask */
87 #ifdef ID_GPIO
88 Gpio *regs; /** pointer to registers of the GPIO controller */
89 #else
90 Pio *regs; /** pointer to registers of the PIO controller */
91 #endif
92 uint8_t periph_id; /** peripheral ID of the PIO controller */
93 uint32_t flags; /** pin flags/attributes */
94 };
95
96 /**
97 * @brief Configure GPIO pin(s).
98 *
99 * Configure one or several pins belonging to the same GPIO port.
100 * Example scenarios:
101 * - configure pin(s) as input with debounce filter enabled.
102 * - connect pin(s) to a peripheral B and enable pull-up.
103 * - configure pin(s) as open drain output.
104 * All pins are configured in the same way.
105 *
106 * @remark The function will enable the GPIO module's clock only if
107 * any of its pins is configured as an input. This is typically what
108 * a user wants. A pin will function correctly without clock enabled
109 * when configured as an output or connected to a peripheral.
110 * In some cases, e.g. when a pin is configured as an output with
111 * a pull-up and user wants to read pin's input value it is necessary
112 * to enable GPIO module's clock separately.
113 *
114 * @param pin pin's configuration data such as pin mask, pin attributes, etc.
115 */
116 void soc_gpio_configure(const struct soc_gpio_pin *pin);
117
118 /**
119 * @brief Configure a list of GPIO pin(s).
120 *
121 * Configure an arbitrary amount of pins in an arbitrary way. Each
122 * configuration entry is a single item in an array passed as an
123 * argument to the function.
124 *
125 * @param pins an array where each item contains pin's configuration data.
126 * @param size size of the pin list.
127 */
128 void soc_gpio_list_configure(const struct soc_gpio_pin pins[],
129 unsigned int size);
130
131 /**
132 * @brief Set pin(s) high.
133 *
134 * Set pin(s) defined in the mask parameter to high. The pin(s) have to be
135 * configured as output by the configure function. The flags field which
136 * is part of pin struct is ignored.
137 *
138 * @param pin pointer to a pin instance describing one or more pins.
139 */
soc_gpio_set(const struct soc_gpio_pin * pin)140 static inline void soc_gpio_set(const struct soc_gpio_pin *pin)
141 {
142 #ifdef ID_GPIO
143 pin->regs->OVRS = pin->mask;
144 #else
145 pin->regs->PIO_SODR = pin->mask;
146 #endif
147 }
148
149 /**
150 * @brief Set pin(s) low.
151 *
152 * Set pin(s) defined in the mask field to low. The pin(s) have to be
153 * configured as output by the configure function. The flags field which
154 * is part of pin struct is ignored.
155 *
156 * @param pin pointer to a pin instance describing one or more pins.
157 */
soc_gpio_clear(const struct soc_gpio_pin * pin)158 static inline void soc_gpio_clear(const struct soc_gpio_pin *pin)
159 {
160 #ifdef ID_GPIO
161 pin->regs->OVRC = pin->mask;
162 #else
163 pin->regs->PIO_CODR = pin->mask;
164 #endif
165 }
166
167 /**
168 * @brief Get pin(s) value.
169 *
170 * Get value of the pin(s) defined in the mask field.
171 *
172 * @param pin pointer to a pin instance describing one or more pins.
173 * @return pin(s) value. To assess value of a specific pin the pin's bit
174 * field has to be read.
175 */
soc_gpio_get(const struct soc_gpio_pin * pin)176 static inline uint32_t soc_gpio_get(const struct soc_gpio_pin *pin)
177 {
178 #ifdef ID_GPIO
179 return pin->regs->PVR & pin->mask;
180 #else
181 return pin->regs->PIO_PDSR & pin->mask;
182 #endif
183 }
184
185 /**
186 * @brief Set the length of the debounce window.
187 *
188 * The debouncing filter automatically rejects a pulse with a duration of less
189 * than 1/2 programmable divided slow clock period tdiv_slck, while a pulse with
190 * a duration of one or more tdiv_slck cycles is accepted. For pulse durations
191 * between 1/2 selected clock cycle and one tdiv_slck clock cycle, the pulse may
192 * or may not be taken into account, depending on the precise timing of its
193 * occurrence.
194 *
195 * tdiv_slck = ((div + 1) x 2) x tslck
196 * where tslck is the slow clock, typically 32.768 kHz.
197 *
198 * Setting the length of the debounce window is only meaningful if the pin is
199 * configured as input and the debounce pin option is enabled.
200 *
201 * @param pin pointer to a pin instance describing one or more pins.
202 * @param div slow clock divider, valid values: from 0 to 2^14 - 1
203 */
soc_gpio_debounce_length_set(const struct soc_gpio_pin * pin,uint32_t div)204 static inline void soc_gpio_debounce_length_set(const struct soc_gpio_pin *pin,
205 uint32_t div)
206 {
207 #ifdef ID_GPIO
208 if (div) {
209 pin->regs->STERS = pin->mask;
210 } else {
211 pin->regs->STERC = pin->mask;
212 }
213 #else
214 pin->regs->PIO_SCDR = PIO_SCDR_DIV(div);
215 #endif
216 }
217
218 #endif /* _ATMEL_SAM_SOC_GPIO_H_ */
219