1 /*
2  * Xilinx Processor System MIO / EMIO GPIO controller driver
3  * GPIO bank module
4  *
5  * Copyright (c) 2022, Weidmueller Interface GmbH & Co. KG
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include <zephyr/arch/cpu.h>
10 #include <zephyr/device.h>
11 #include <zephyr/devicetree.h>
12 
13 #include <zephyr/drivers/gpio.h>
14 #include <zephyr/drivers/gpio/gpio_utils.h>
15 #include "gpio_xlnx_ps_bank.h"
16 
17 #define LOG_MODULE_NAME gpio_xlnx_ps_bank
18 #define LOG_LEVEL CONFIG_GPIO_LOG_LEVEL
19 #include <zephyr/logging/log.h>
20 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
21 
22 #define DT_DRV_COMPAT xlnx_ps_gpio_bank
23 
24 /**
25  * @brief GPIO bank pin configuration function
26  *
27  * Configures an individual pin within a MIO / EMIO GPIO pin bank.
28  * The following flags specified by the GPIO subsystem are NOT
29  * supported by the PS GPIO controller:
30  *
31  * - Pull up
32  * - Pull down
33  * - Open drain
34  * - Open source.
35  *
36  * @param dev Pointer to the GPIO bank's device.
37  * @param pin Index of the pin within the bank to be configured
38  *            (decimal index of the pin).
39  * @param flags Flags specifying the pin's configuration.
40  *
41  * @retval 0 if the device initialization completed successfully,
42  *         -EINVAL if the specified pin index is out of range,
43  *         -ENOTSUP if the pin configuration data contains a flag
44  *         that is not supported by the controller.
45  */
gpio_xlnx_ps_pin_configure(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)46 static int gpio_xlnx_ps_pin_configure(const struct device *dev,
47 				      gpio_pin_t pin,
48 				      gpio_flags_t flags)
49 {
50 	const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = dev->config;
51 	uint32_t pin_mask = BIT(pin);
52 	uint32_t bank_data;
53 	uint32_t dirm_data;
54 	uint32_t oen_data;
55 
56 	/* Validity of the specified pin index is checked in drivers/gpio.h */
57 
58 	/* Check for config flags not supported by the controller */
59 	if (flags & (GPIO_PULL_UP | GPIO_PULL_DOWN | GPIO_SINGLE_ENDED)) {
60 		return -ENOTSUP;
61 	}
62 
63 	/* Read the data direction & output enable registers */
64 	dirm_data = sys_read32(GPIO_XLNX_PS_BANK_DIRM_REG);
65 	oen_data = sys_read32(GPIO_XLNX_PS_BANK_OEN_REG);
66 
67 	if (flags & GPIO_OUTPUT) {
68 		dirm_data |= pin_mask;
69 		oen_data |= pin_mask;
70 
71 		/*
72 		 * Setting of an initial value (see below) requires the
73 		 * direction register to be written *BEFORE* the data
74 		 * register, otherwise, the value will not be applied!
75 		 * The output enable bit can be set after the initial
76 		 * value has been written.
77 		 */
78 		sys_write32(dirm_data, GPIO_XLNX_PS_BANK_DIRM_REG);
79 
80 		/*
81 		 * If the current pin is to be configured as an output
82 		 * pin, it is up to the caller to specify whether the
83 		 * output's initial value shall be high or low.
84 		 * -> Write the initial output value into the data register.
85 		 */
86 		bank_data = sys_read32(GPIO_XLNX_PS_BANK_DATA_REG);
87 		if (flags & GPIO_OUTPUT_INIT_HIGH) {
88 			bank_data |= pin_mask;
89 		} else if (flags & GPIO_OUTPUT_INIT_LOW) {
90 			bank_data &= ~pin_mask;
91 		}
92 		sys_write32(bank_data, GPIO_XLNX_PS_BANK_DATA_REG);
93 
94 		/* Set the pin's output enable bit */
95 		sys_write32(oen_data, GPIO_XLNX_PS_BANK_OEN_REG);
96 	} else {
97 		dirm_data &= ~pin_mask;
98 		oen_data &= ~pin_mask;
99 
100 		/*
101 		 * Disable the output first in case of an O -> I
102 		 * transition, then change the pin's direction.
103 		 */
104 		sys_write32(oen_data, GPIO_XLNX_PS_BANK_OEN_REG);
105 		sys_write32(dirm_data, GPIO_XLNX_PS_BANK_DIRM_REG);
106 	}
107 
108 	return 0;
109 }
110 
111 /**
112  * @brief Reads the current bit mask of the entire GPIO pin bank.
113  *
114  * Reads the current bit mask of the entire bank from the
115  * read-only data register. This includes the current values
116  * of not just all input pins, but both the input and output
117  * pins within the bank.
118  *
119  * @param dev   Pointer to the GPIO bank's device.
120  * @param value Pointer to a variable of type gpio_port_value_t
121  *              to which the current bit mask read from the bank's
122  *              RO data register will be written to.
123  *
124  * @retval 0 if the read operation completed successfully,
125  *         -EINVAL if the pointer to the output variable is NULL.
126  */
gpio_xlnx_ps_bank_get(const struct device * dev,gpio_port_value_t * value)127 static int gpio_xlnx_ps_bank_get(const struct device *dev,
128 				 gpio_port_value_t *value)
129 {
130 	const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = dev->config;
131 
132 	*value = sys_read32(GPIO_XLNX_PS_BANK_DATA_REG);
133 	return 0;
134 }
135 
136 /**
137  * @brief Masked write of a bit mask for the entire GPIO pin bank.
138  *
139  * Performs a masked write operation on the data register of
140  * the current GPIO pin bank. The mask is applied twice:
141  * first, it is applied to the current contents of the bank's
142  * RO data register, clearing any bits that are zeroes in the
143  * mask (will not have any effect on input pins). Second, it
144  * is applied to the data word to be written into the current
145  * bank's data register. The masked data word read from the
146  * RO data register and the masked data word provided by the
147  * caller ar then OR'ed and written to the bank's data register.
148  *
149  * @param dev   Pointer to the GPIO bank's device.
150  * @param mask  Mask to be applied to both the current contents
151  *              of the data register and the data word provided
152  *              by the caller.
153  * @param value Value to be written to the current bank's data
154  *              register.
155  *
156  * @retval Always 0.
157  */
gpio_xlnx_ps_bank_set_masked(const struct device * dev,gpio_port_pins_t mask,gpio_port_value_t value)158 static int gpio_xlnx_ps_bank_set_masked(const struct device *dev,
159 					gpio_port_pins_t mask,
160 					gpio_port_value_t value)
161 {
162 	const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = dev->config;
163 	uint32_t bank_data;
164 
165 	bank_data = sys_read32(GPIO_XLNX_PS_BANK_DATA_REG);
166 	bank_data = (bank_data & ~mask) | (value & mask);
167 	sys_write32(bank_data, GPIO_XLNX_PS_BANK_DATA_REG);
168 
169 	return 0;
170 }
171 
172 /**
173  * @brief Sets bits in the data register of the GPIO pin bank.
174  *
175  * Sets bits in the data register of the current GPIO pin bank
176  * as a read-modify-write operation. All bits set in the bit
177  * mask provided by the caller are OR'ed into the current data
178  * word of the bank. This operation has no effect on the values
179  * associated with pins configured as inputs.
180  *
181  * @param dev   Pointer to the GPIO bank's device.
182  * @param pins  Bit mask specifying which bits shall be set in
183  *              the data word of the current GPIO pin bank.
184  *
185  * @retval Always 0.
186  */
gpio_xlnx_ps_bank_set_bits(const struct device * dev,gpio_port_pins_t pins)187 static int gpio_xlnx_ps_bank_set_bits(const struct device *dev,
188 				      gpio_port_pins_t pins)
189 {
190 	const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = dev->config;
191 	uint32_t bank_data;
192 
193 	bank_data = sys_read32(GPIO_XLNX_PS_BANK_DATA_REG);
194 	bank_data |= pins;
195 	sys_write32(bank_data, GPIO_XLNX_PS_BANK_DATA_REG);
196 
197 	return 0;
198 }
199 
200 /**
201  * @brief Clears bits in the data register of the GPIO pin bank.
202  *
203  * Clears bits in the data register of the current GPIO pin bank
204  * as a read-modify-write operation. All bits set in the bit
205  * mask provided by the caller are NAND'ed into the current data
206  * word of the bank. This operation has no effect on the values
207  * associated with pins configured as inputs.
208  *
209  * @param dev   Pointer to the GPIO bank's device.
210  * @param pins  Bit mask specifying which bits shall be cleared
211  *              in the data word of the current GPIO pin bank.
212  *
213  * @retval Always 0.
214  */
gpio_xlnx_ps_bank_clear_bits(const struct device * dev,gpio_port_pins_t pins)215 static int gpio_xlnx_ps_bank_clear_bits(const struct device *dev,
216 					gpio_port_pins_t pins)
217 {
218 	const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = dev->config;
219 	uint32_t bank_data;
220 
221 	bank_data = sys_read32(GPIO_XLNX_PS_BANK_DATA_REG);
222 	bank_data &= ~pins;
223 	sys_write32(bank_data, GPIO_XLNX_PS_BANK_DATA_REG);
224 
225 	return 0;
226 }
227 
228 /**
229  * @brief Toggles bits in the data register of the GPIO pin bank.
230  *
231  * Toggles bits in the data register of the current GPIO pin bank
232  * as a read-modify-write operation. All bits set in the bit
233  * mask provided by the caller are XOR'ed into the current data
234  * word of the bank. This operation has no effect on the values
235  * associated with pins configured as inputs.
236  *
237  * @param dev   Pointer to the GPIO bank's device.
238  * @param pins  Bit mask specifying which bits shall be toggled
239  *              in the data word of the current GPIO pin bank.
240  *
241  * @retval Always 0.
242  */
gpio_xlnx_ps_bank_toggle_bits(const struct device * dev,gpio_port_pins_t pins)243 static int gpio_xlnx_ps_bank_toggle_bits(const struct device *dev,
244 					 gpio_port_pins_t pins)
245 {
246 	const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = dev->config;
247 	uint32_t bank_data;
248 
249 	bank_data = sys_read32(GPIO_XLNX_PS_BANK_DATA_REG);
250 	bank_data ^= pins;
251 	sys_write32(bank_data, GPIO_XLNX_PS_BANK_DATA_REG);
252 
253 	return 0;
254 }
255 
256 /**
257  * @brief Configures the interrupt behaviour of a pin within the
258  *        current GPIO bank.
259  *
260  * Configures the interrupt behaviour of a pin within the current
261  * GPIO bank. If a pin is to be configured to trigger an interrupt,
262  * the following modes are supported:
263  *
264  * - edge or level triggered,
265  * - rising edge / high level or falling edge / low level,
266  * - in edge mode only: trigger on both rising and falling edge.
267  *
268  * @param dev  Pointer to the GPIO bank's device.
269  * @param pin  Index of the pin within the bank to be configured
270  *             (decimal index of the pin).
271  * @param mode Mode configuration: edge, level or interrupt disabled.
272  * @param trig Trigger condition configuration: high/low level or
273  *             rising/falling/both edge(s).
274  *
275  * @retval 0 if the interrupt configuration completed successfully,
276  *         -EINVAL if the specified pin index is out of range,
277  *         -ENOTSUP if the interrupt configuration data contains an
278  *         invalid combination of configuration flags.
279  */
gpio_xlnx_ps_bank_pin_irq_configure(const struct device * dev,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)280 static int gpio_xlnx_ps_bank_pin_irq_configure(const struct device *dev,
281 					       gpio_pin_t pin,
282 					       enum gpio_int_mode mode,
283 					       enum gpio_int_trig trig)
284 {
285 	const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = dev->config;
286 	uint32_t pin_mask = BIT(pin);
287 	uint32_t int_type_data;
288 	uint32_t int_polarity_data;
289 	uint32_t int_any_data;
290 
291 	/* Validity of the specified pin index is checked in drivers/gpio.h */
292 
293 	/* Disable the specified pin's interrupt before (re-)configuring it */
294 	sys_write32(pin_mask, GPIO_XLNX_PS_BANK_INT_DIS_REG);
295 
296 	int_type_data = sys_read32(GPIO_XLNX_PS_BANK_INT_TYPE_REG);
297 	int_polarity_data = sys_read32(GPIO_XLNX_PS_BANK_INT_POLARITY_REG);
298 	int_any_data = sys_read32(GPIO_XLNX_PS_BANK_INT_ANY_REG);
299 
300 	if (mode != GPIO_INT_MODE_DISABLED) {
301 
302 		if (mode == GPIO_INT_MODE_LEVEL) {
303 			int_type_data &= ~pin_mask;
304 		} else if (mode == GPIO_INT_MODE_EDGE) {
305 			int_type_data |= pin_mask;
306 		} else {
307 			return -EINVAL;
308 		}
309 
310 		if (trig == GPIO_INT_TRIG_LOW) {
311 			int_any_data &= ~pin_mask;
312 			int_polarity_data &= ~pin_mask;
313 		} else if (trig == GPIO_INT_TRIG_HIGH) {
314 			int_any_data &= ~pin_mask;
315 			int_polarity_data |= pin_mask;
316 		} else if (trig == GPIO_INT_TRIG_BOTH) {
317 			if (mode == GPIO_INT_MODE_LEVEL) {
318 				return -EINVAL;
319 			}
320 			int_any_data |= pin_mask;
321 		}
322 
323 	} else { /* mode == GPIO_INT_MODE_DISABLED */
324 		int_any_data &= ~pin_mask;
325 		int_polarity_data &= ~pin_mask;
326 		int_type_data &= ~pin_mask;
327 	}
328 
329 	sys_write32(int_any_data, GPIO_XLNX_PS_BANK_INT_ANY_REG);
330 	sys_write32(int_polarity_data, GPIO_XLNX_PS_BANK_INT_POLARITY_REG);
331 	sys_write32(int_type_data, GPIO_XLNX_PS_BANK_INT_TYPE_REG);
332 
333 	if (mode != GPIO_INT_MODE_DISABLED) {
334 		/* Clear potential stale pending bit before enabling interrupt */
335 		sys_write32(pin_mask, GPIO_XLNX_PS_BANK_INT_STAT_REG);
336 		sys_write32(pin_mask, GPIO_XLNX_PS_BANK_INT_EN_REG);
337 	}
338 
339 	return 0;
340 }
341 
342 /**
343  * @brief Returns the interrupt status of the current GPIO bank.
344  *
345  * Returns the interrupt status of the current GPIO bank, in the
346  * form of a bit mask where each pin with a pending interrupt is
347  * indicated. This information can either be used by the PM sub-
348  * system or the parent controller device driver, which manages
349  * the interrupt line of the entire PS GPIO controller, regardless
350  * of how many bank sub-devices exist. As the current status is
351  * read, it is automatically cleared. Callback triggering is handled
352  * by the parent controller device.
353  *
354  * @param dev  Pointer to the GPIO bank's device.
355  *
356  * @retval A bit mask indicating for which pins within the bank
357  *         an interrupt is pending.
358  */
gpio_xlnx_ps_bank_get_int_status(const struct device * dev)359 static uint32_t gpio_xlnx_ps_bank_get_int_status(const struct device *dev)
360 {
361 	const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = dev->config;
362 	uint32_t int_status;
363 
364 	int_status = sys_read32(GPIO_XLNX_PS_BANK_INT_STAT_REG);
365 	if (int_status != 0) {
366 		sys_write32(int_status, GPIO_XLNX_PS_BANK_INT_STAT_REG);
367 	}
368 
369 	return int_status;
370 }
371 
372 /**
373  * @brief Callback management re-direction function.
374  *
375  * Re-directs any callback management calls relating to the current
376  * GPIO bank to the GPIO sub-system. Comp. documentation of the
377  * underlying sub-system's #gpio_manage_callback function.
378  *
379  * @param dev      Pointer to the GPIO bank's device.
380  * @param callback Pointer to a GPIO callback struct.
381  * @param set      Callback set flag.
382  *
383  * @retval A bit mask indicating for which pins within the bank
384  *         an interrupt is pending.
385  */
gpio_xlnx_ps_bank_manage_callback(const struct device * dev,struct gpio_callback * callback,bool set)386 static int gpio_xlnx_ps_bank_manage_callback(const struct device *dev,
387 					     struct gpio_callback *callback,
388 					     bool set)
389 {
390 	struct gpio_xlnx_ps_bank_dev_data *dev_data = dev->data;
391 
392 	return gpio_manage_callback(&dev_data->callbacks, callback, set);
393 }
394 
395 /* GPIO bank device driver API */
396 static const struct gpio_driver_api gpio_xlnx_ps_bank_apis = {
397 	.pin_configure = gpio_xlnx_ps_pin_configure,
398 	.port_get_raw = gpio_xlnx_ps_bank_get,
399 	.port_set_masked_raw = gpio_xlnx_ps_bank_set_masked,
400 	.port_set_bits_raw = gpio_xlnx_ps_bank_set_bits,
401 	.port_clear_bits_raw = gpio_xlnx_ps_bank_clear_bits,
402 	.port_toggle_bits = gpio_xlnx_ps_bank_toggle_bits,
403 	.pin_interrupt_configure = gpio_xlnx_ps_bank_pin_irq_configure,
404 	.manage_callback = gpio_xlnx_ps_bank_manage_callback,
405 	.get_pending_int = gpio_xlnx_ps_bank_get_int_status
406 };
407 
408 /**
409  * @brief Initialize a MIO / EMIO GPIO bank sub-device
410  *
411  * Initialize a MIO / EMIO GPIO bank sub-device, which is a child
412  * of the parent Xilinx PS GPIO controller device driver. This ini-
413  * tialization function sets up a defined initial state for each
414  * GPIO bank.
415  *
416  * @param dev Pointer to the GPIO bank's device.
417  *
418  * @retval Always 0.
419  */
gpio_xlnx_ps_bank_init(const struct device * dev)420 static int gpio_xlnx_ps_bank_init(const struct device *dev)
421 {
422 	const struct gpio_xlnx_ps_bank_dev_cfg *dev_conf = dev->config;
423 
424 	sys_write32(~0x0, GPIO_XLNX_PS_BANK_INT_DIS_REG);  /* Disable all interrupts */
425 	sys_write32(~0x0, GPIO_XLNX_PS_BANK_INT_STAT_REG); /* Clear all interrupts */
426 	sys_write32(0x0, GPIO_XLNX_PS_BANK_OEN_REG);       /* All outputs disabled */
427 	sys_write32(0x0, GPIO_XLNX_PS_BANK_DIRM_REG);      /* All pins input */
428 	sys_write32(0x0, GPIO_XLNX_PS_BANK_DATA_REG);      /* Zero data register */
429 
430 	return 0;
431 }
432 
433 /* MIO / EMIO bank device definition macros */
434 #define GPIO_XLNX_PS_BANK_INIT(idx)\
435 static const struct gpio_xlnx_ps_bank_dev_cfg gpio_xlnx_ps_bank##idx##_cfg = {\
436 	.common = {\
437 		.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(idx),\
438 	},\
439 	.base_addr = DT_REG_ADDR(DT_PARENT(DT_INST(idx, DT_DRV_COMPAT))),\
440 	.bank_index = idx,\
441 };\
442 static struct gpio_xlnx_ps_bank_dev_data gpio_xlnx_ps_bank##idx##_data;\
443 DEVICE_DT_INST_DEFINE(idx, gpio_xlnx_ps_bank_init, NULL,\
444 	&gpio_xlnx_ps_bank##idx##_data, &gpio_xlnx_ps_bank##idx##_cfg,\
445 	PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, &gpio_xlnx_ps_bank_apis);
446 
447 /* Register & initialize all MIO / EMIO GPIO banks specified in the device tree. */
448 DT_INST_FOREACH_STATUS_OKAY(GPIO_XLNX_PS_BANK_INIT);
449