1 /*
2  * Copyright (c) 2019-2021 Antmicro <www.antmicro.com>
3  * Copyright (c) 2021 Raptor Engineering, LLC <sales@raptorengineering.com>
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #define DT_DRV_COMPAT litex_gpio
9 
10 #include <errno.h>
11 #include <zephyr/device.h>
12 #include <zephyr/drivers/gpio.h>
13 #include <zephyr/irq.h>
14 #include <zephyr/types.h>
15 #include <zephyr/sys/util.h>
16 #include <string.h>
17 #include <zephyr/logging/log.h>
18 
19 #include <soc.h>
20 
21 #include <zephyr/drivers/gpio/gpio_utils.h>
22 
23 #define SUPPORTED_FLAGS (GPIO_INPUT | GPIO_OUTPUT | \
24 			GPIO_OUTPUT_INIT_LOW | GPIO_OUTPUT_INIT_HIGH | \
25 			GPIO_ACTIVE_LOW | GPIO_ACTIVE_HIGH)
26 
27 #define GPIO_LOW        0
28 #define GPIO_HIGH       1
29 
30 #define LOG_LEVEL CONFIG_GPIO_LOG_LEVEL
31 LOG_MODULE_REGISTER(gpio_litex);
32 
33 static const char *LITEX_LOG_REG_SIZE_NGPIOS_MISMATCH =
34 	"Cannot handle all of the gpios with the register of given size\n";
35 static const char *LITEX_LOG_CANNOT_CHANGE_DIR =
36 	"Cannot change port direction selected in device tree\n";
37 
38 struct gpio_litex_cfg {
39 	uint32_t reg_addr;
40 	int reg_size;
41 	uint32_t ev_pending_addr;
42 	uint32_t ev_enable_addr;
43 	uint32_t ev_mode_addr;
44 	uint32_t ev_edge_addr;
45 	int nr_gpios;
46 	bool port_is_output;
47 };
48 
49 struct gpio_litex_data {
50 	struct gpio_driver_data common;
51 	const struct device *dev;
52 	sys_slist_t cb;
53 };
54 
55 /* Helper macros for GPIO */
56 
57 #define DEV_GPIO_CFG(dev)						\
58 	((const struct gpio_litex_cfg *)(dev)->config)
59 
60 /* Helper functions for bit / port access */
61 
set_bit(const struct gpio_litex_cfg * config,uint32_t bit,bool val)62 static inline void set_bit(const struct gpio_litex_cfg *config,
63 			   uint32_t bit, bool val)
64 {
65 	int regv, new_regv;
66 
67 	regv = litex_read(config->reg_addr, config->reg_size);
68 	new_regv = (regv & ~BIT(bit)) | (val << bit);
69 	litex_write(config->reg_addr, config->reg_size, new_regv);
70 }
71 
get_bit(const struct gpio_litex_cfg * config,uint32_t bit)72 static inline uint32_t get_bit(const struct gpio_litex_cfg *config, uint32_t bit)
73 {
74 	int regv = litex_read(config->reg_addr, config->reg_size);
75 
76 	return !!(regv & BIT(bit));
77 }
78 
set_port(const struct gpio_litex_cfg * config,uint32_t value)79 static inline void set_port(const struct gpio_litex_cfg *config, uint32_t value)
80 {
81 	litex_write(config->reg_addr, config->reg_size, value);
82 }
83 
get_port(const struct gpio_litex_cfg * config)84 static inline uint32_t get_port(const struct gpio_litex_cfg *config)
85 {
86 	int regv = litex_read(config->reg_addr, config->reg_size);
87 
88 	return (regv & BIT_MASK(config->nr_gpios));
89 }
90 
91 /* Driver functions */
92 
gpio_litex_configure(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)93 static int gpio_litex_configure(const struct device *dev,
94 				gpio_pin_t pin, gpio_flags_t flags)
95 {
96 	const struct gpio_litex_cfg *gpio_config = DEV_GPIO_CFG(dev);
97 
98 	if (flags & ~SUPPORTED_FLAGS) {
99 		return -ENOTSUP;
100 	}
101 
102 	if ((flags & GPIO_OUTPUT) && (flags & GPIO_INPUT)) {
103 		/* Pin cannot be configured as input and output */
104 		return -ENOTSUP;
105 	} else if (!(flags & (GPIO_INPUT | GPIO_OUTPUT))) {
106 		/* Pin has to be configured as input or output */
107 		return -ENOTSUP;
108 	}
109 
110 	if (flags & GPIO_OUTPUT) {
111 		if (!gpio_config->port_is_output) {
112 			LOG_ERR("%s", LITEX_LOG_CANNOT_CHANGE_DIR);
113 			return -EINVAL;
114 		}
115 
116 		if (flags & GPIO_OUTPUT_INIT_HIGH) {
117 			set_bit(gpio_config, pin, GPIO_HIGH);
118 		} else if (flags & GPIO_OUTPUT_INIT_LOW) {
119 			set_bit(gpio_config, pin, GPIO_LOW);
120 		}
121 	} else {
122 		if (gpio_config->port_is_output) {
123 			LOG_ERR("%s", LITEX_LOG_CANNOT_CHANGE_DIR);
124 			return -EINVAL;
125 		}
126 	}
127 
128 	return 0;
129 }
130 
gpio_litex_port_get_raw(const struct device * dev,gpio_port_value_t * value)131 static int gpio_litex_port_get_raw(const struct device *dev,
132 				   gpio_port_value_t *value)
133 {
134 	const struct gpio_litex_cfg *gpio_config = DEV_GPIO_CFG(dev);
135 
136 	*value = get_port(gpio_config);
137 	return 0;
138 }
139 
gpio_litex_port_set_masked_raw(const struct device * dev,gpio_port_pins_t mask,gpio_port_value_t value)140 static int gpio_litex_port_set_masked_raw(const struct device *dev,
141 					  gpio_port_pins_t mask,
142 					  gpio_port_value_t value)
143 {
144 	const struct gpio_litex_cfg *gpio_config = DEV_GPIO_CFG(dev);
145 	uint32_t port_val;
146 
147 	port_val = get_port(gpio_config);
148 	port_val = (port_val & ~mask) | (value & mask);
149 	set_port(gpio_config, port_val);
150 
151 	return 0;
152 }
153 
gpio_litex_port_set_bits_raw(const struct device * dev,gpio_port_pins_t pins)154 static int gpio_litex_port_set_bits_raw(const struct device *dev,
155 					gpio_port_pins_t pins)
156 {
157 	const struct gpio_litex_cfg *gpio_config = DEV_GPIO_CFG(dev);
158 	uint32_t port_val;
159 
160 	port_val = get_port(gpio_config);
161 	port_val |= pins;
162 	set_port(gpio_config, port_val);
163 
164 	return 0;
165 }
166 
gpio_litex_port_clear_bits_raw(const struct device * dev,gpio_port_pins_t pins)167 static int gpio_litex_port_clear_bits_raw(const struct device *dev,
168 					  gpio_port_pins_t pins)
169 {
170 	const struct gpio_litex_cfg *gpio_config = DEV_GPIO_CFG(dev);
171 	uint32_t port_val;
172 
173 	port_val = get_port(gpio_config);
174 	port_val &= ~pins;
175 	set_port(gpio_config, port_val);
176 
177 	return 0;
178 }
179 
gpio_litex_port_toggle_bits(const struct device * dev,gpio_port_pins_t pins)180 static int gpio_litex_port_toggle_bits(const struct device *dev,
181 				       gpio_port_pins_t pins)
182 {
183 	const struct gpio_litex_cfg *gpio_config = DEV_GPIO_CFG(dev);
184 	uint32_t port_val;
185 
186 	port_val = get_port(gpio_config);
187 	port_val ^= pins;
188 	set_port(gpio_config, port_val);
189 
190 	return 0;
191 }
192 
gpio_litex_irq_handler(const struct device * dev)193 static void gpio_litex_irq_handler(const struct device *dev)
194 {
195 	const struct gpio_litex_cfg *gpio_config = DEV_GPIO_CFG(dev);
196 	struct gpio_litex_data *data = dev->data;
197 
198 	uint8_t int_status =
199 		litex_read(gpio_config->ev_pending_addr, gpio_config->reg_size);
200 	uint8_t ev_enabled =
201 		litex_read(gpio_config->ev_enable_addr, gpio_config->reg_size);
202 
203 	/* clear events */
204 	litex_write(gpio_config->ev_pending_addr, gpio_config->reg_size,
205 			int_status);
206 
207 	gpio_fire_callbacks(&data->cb, dev, int_status & ev_enabled);
208 }
209 
gpio_litex_manage_callback(const struct device * dev,struct gpio_callback * callback,bool set)210 static int gpio_litex_manage_callback(const struct device *dev,
211 				      struct gpio_callback *callback, bool set)
212 {
213 	struct gpio_litex_data *data = dev->data;
214 
215 	return gpio_manage_callback(&data->cb, callback, set);
216 }
217 
gpio_litex_pin_interrupt_configure(const struct device * dev,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)218 static int gpio_litex_pin_interrupt_configure(const struct device *dev,
219 					      gpio_pin_t pin,
220 					      enum gpio_int_mode mode,
221 					      enum gpio_int_trig trig)
222 {
223 	const struct gpio_litex_cfg *gpio_config = DEV_GPIO_CFG(dev);
224 
225 	if (gpio_config->port_is_output == true) {
226 		return -ENOTSUP;
227 	}
228 
229 	if (mode == GPIO_INT_MODE_EDGE) {
230 		uint8_t ev_enabled = litex_read(gpio_config->ev_enable_addr,
231 				gpio_config->reg_size);
232 		uint8_t ev_mode = litex_read(gpio_config->ev_mode_addr,
233 				gpio_config->reg_size);
234 		uint8_t ev_edge = litex_read(gpio_config->ev_edge_addr,
235 				gpio_config->reg_size);
236 
237 		litex_write(gpio_config->ev_enable_addr, gpio_config->reg_size,
238 			    ev_enabled | BIT(pin));
239 
240 		if (trig == GPIO_INT_TRIG_HIGH) {
241 			/* Change mode to 'edge' and edge to 'rising' */
242 			litex_write(gpio_config->ev_mode_addr, gpio_config->reg_size,
243 			    ev_mode & ~BIT(pin));
244 			litex_write(gpio_config->ev_edge_addr, gpio_config->reg_size,
245 			    ev_edge & ~BIT(pin));
246 		} else if (trig == GPIO_INT_TRIG_LOW) {
247 			/* Change mode to 'edge' and edge to 'falling' */
248 			litex_write(gpio_config->ev_mode_addr, gpio_config->reg_size,
249 			    ev_mode & ~BIT(pin));
250 			litex_write(gpio_config->ev_edge_addr, gpio_config->reg_size,
251 			    ev_edge | BIT(pin));
252 		} else if (trig == GPIO_INT_TRIG_BOTH) {
253 			/* Change mode to 'change' */
254 			litex_write(gpio_config->ev_mode_addr, gpio_config->reg_size,
255 			    ev_mode | BIT(pin));
256 		}
257 		return 0;
258 	}
259 
260 	if (mode == GPIO_INT_DISABLE) {
261 		uint8_t ev_enabled = litex_read(gpio_config->ev_enable_addr,
262 				gpio_config->reg_size);
263 		litex_write(gpio_config->ev_enable_addr, gpio_config->reg_size,
264 			    ev_enabled & ~BIT(pin));
265 		return 0;
266 	}
267 
268 	return -ENOTSUP;
269 }
270 
271 #ifdef CONFIG_GPIO_GET_DIRECTION
gpio_litex_port_get_direction(const struct device * dev,gpio_port_pins_t map,gpio_port_pins_t * inputs,gpio_port_pins_t * outputs)272 static int gpio_litex_port_get_direction(const struct device *dev, gpio_port_pins_t map,
273 					 gpio_port_pins_t *inputs, gpio_port_pins_t *outputs)
274 {
275 	const struct gpio_litex_cfg *gpio_config = DEV_GPIO_CFG(dev);
276 
277 	map &= gpio_config->port_pin_mask;
278 
279 	if (inputs != NULL) {
280 		*inputs = map & (!gpio_config->port_is_output);
281 	}
282 
283 	if (outputs != NULL) {
284 		*outputs = map & (gpio_config->port_is_output);
285 	}
286 
287 	return 0;
288 }
289 #endif /* CONFIG_GPIO_GET_DIRECTION */
290 
291 static const struct gpio_driver_api gpio_litex_driver_api = {
292 	.pin_configure = gpio_litex_configure,
293 	.port_get_raw = gpio_litex_port_get_raw,
294 	.port_set_masked_raw = gpio_litex_port_set_masked_raw,
295 	.port_set_bits_raw = gpio_litex_port_set_bits_raw,
296 	.port_clear_bits_raw = gpio_litex_port_clear_bits_raw,
297 	.port_toggle_bits = gpio_litex_port_toggle_bits,
298 	.pin_interrupt_configure = gpio_litex_pin_interrupt_configure,
299 	.manage_callback = gpio_litex_manage_callback,
300 #ifdef CONFIG_GPIO_GET_DIRECTION
301 	.port_get_direction = gpio_litex_port_get_direction,
302 #endif /* CONFIG_GPIO_GET_DIRECTION */
303 };
304 
305 /* Device Instantiation */
306 #define GPIO_LITEX_IRQ_INIT(n) \
307 	do { \
308 		IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), \
309 			    gpio_litex_irq_handler, \
310 			    DEVICE_DT_INST_GET(n), 0); \
311 \
312 		irq_enable(DT_INST_IRQN(n)); \
313 	} while (false)
314 
315 #define GPIO_LITEX_INIT(n) \
316 	static int gpio_litex_port_init_##n(const struct device *dev); \
317 \
318 	static const struct gpio_litex_cfg gpio_litex_cfg_##n = { \
319 		.reg_addr = DT_INST_REG_ADDR(n), \
320 		.reg_size = DT_INST_REG_SIZE(n), \
321 		.nr_gpios = DT_INST_PROP(n, ngpios), \
322 		IF_ENABLED(DT_INST_IRQ_HAS_IDX(n, 0), ( \
323 			.ev_mode_addr    = DT_INST_REG_ADDR_BY_NAME(n, irq_mode), \
324 			.ev_edge_addr    = DT_INST_REG_ADDR_BY_NAME(n, irq_edge), \
325 			.ev_pending_addr = DT_INST_REG_ADDR_BY_NAME(n, irq_pend), \
326 			.ev_enable_addr  = DT_INST_REG_ADDR_BY_NAME(n, irq_en), \
327 		)) \
328 		.port_is_output = DT_INST_PROP(n, port_is_output), \
329 	}; \
330 	static struct gpio_litex_data gpio_litex_data_##n; \
331 \
332 	DEVICE_DT_INST_DEFINE(n, \
333 			    gpio_litex_port_init_##n, \
334 			    NULL, \
335 			    &gpio_litex_data_##n, \
336 			    &gpio_litex_cfg_##n, \
337 			    POST_KERNEL, \
338 			    CONFIG_GPIO_INIT_PRIORITY, \
339 			    &gpio_litex_driver_api \
340 			   ); \
341 \
342 	static int gpio_litex_port_init_##n(const struct device *dev) \
343 	{ \
344 		const struct gpio_litex_cfg *gpio_config = DEV_GPIO_CFG(dev); \
345 \
346 		/* Check if gpios fit in declared register space */ \
347 		/* Number of subregisters times size in bits */ \
348 		const int max_gpios_can_fit = DT_INST_REG_SIZE(n) / 4 \
349 					* CONFIG_LITEX_CSR_DATA_WIDTH; \
350 		if (gpio_config->nr_gpios > max_gpios_can_fit) { \
351 			LOG_ERR("%s", LITEX_LOG_REG_SIZE_NGPIOS_MISMATCH); \
352 			return -EINVAL; \
353 		} \
354 \
355 		IF_ENABLED(DT_INST_IRQ_HAS_IDX(n, 0), \
356 			   (GPIO_LITEX_IRQ_INIT(n);)) \
357 		return 0; \
358 	}
359 
360 DT_INST_FOREACH_STATUS_OKAY(GPIO_LITEX_INIT)
361