1 /*
2  * Copyright (c) 2018 Peter Bigot Consulting, LLC
3  * Copyright (c) 2018 Aapo Vienamo
4  * Copyright (c) 2019 Nordic Semiconductor ASA
5  * Copyright (c) 2019 Vestas Wind Systems A/S
6  * Copyright (c) 2020 ZedBlox Ltd.
7  * Copyright (c) 2021 Laird Connectivity
8  *
9  * SPDX-License-Identifier: Apache-2.0
10  */
11 
12 #include <errno.h>
13 #include <zephyr/kernel.h>
14 #include <zephyr/device.h>
15 #include <zephyr/init.h>
16 #include <zephyr/drivers/gpio.h>
17 #include <zephyr/drivers/i2c.h>
18 #include <zephyr/sys/byteorder.h>
19 #include <zephyr/sys/util.h>
20 
21 #include <zephyr/logging/log.h>
22 LOG_MODULE_REGISTER(pca953x, CONFIG_GPIO_LOG_LEVEL);
23 
24 #include <zephyr/drivers/gpio/gpio_utils.h>
25 
26 /* PCA953X Register addresses */
27 #define PCA953X_INPUT_PORT		0x00
28 #define PCA953X_OUTPUT_PORT		0x01
29 #define PCA953X_CONFIGURATION		0x03
30 
31 /* Number of pins supported by the device */
32 #define NUM_PINS 8
33 
34 /* Max to select all pins supported on the device. */
35 #define ALL_PINS ((uint8_t)BIT_MASK(NUM_PINS))
36 
37 /** Cache of the output configuration and data of the pins. */
38 struct pca953x_pin_state {
39 	uint8_t dir;
40 	uint8_t input;
41 	uint8_t output;
42 };
43 
44 struct pca953x_irq_state {
45 	uint8_t rising;
46 	uint8_t falling;
47 };
48 
49 /** Runtime driver data */
50 struct pca953x_drv_data {
51 	/* gpio_driver_data needs to be first */
52 	struct gpio_driver_data common;
53 	struct pca953x_pin_state pin_state;
54 	struct k_sem lock;
55 	struct gpio_callback gpio_cb;
56 	struct k_work work;
57 	struct pca953x_irq_state irq_state;
58 	const struct device *dev;
59 	/* user ISR cb */
60 	sys_slist_t cb;
61 };
62 
63 /** Configuration data */
64 struct pca953x_config {
65 	/* gpio_driver_config needs to be first */
66 	struct gpio_driver_config common;
67 	struct i2c_dt_spec i2c;
68 	const struct gpio_dt_spec gpio_int;
69 	bool interrupt_enabled;
70 };
71 
72 /**
73  * @brief Gets the state of input pins of the PCA953X I/O Port and
74  * stores in driver data struct.
75  *
76  * @param dev Pointer to the device structure for the driver instance.
77  *
78  * @retval 0 If successful.
79  * @retval Negative value for error code.
80  */
update_input(const struct device * dev)81 static int update_input(const struct device *dev)
82 {
83 	const struct pca953x_config *cfg = dev->config;
84 	struct pca953x_drv_data *drv_data = dev->data;
85 	uint8_t input_states;
86 	int rc = 0;
87 
88 	rc = i2c_reg_read_byte_dt(&cfg->i2c, PCA953X_INPUT_PORT, &input_states);
89 
90 	if (rc == 0) {
91 		drv_data->pin_state.input = input_states;
92 	}
93 	return rc;
94 }
95 
96 /**
97  * @brief Handles interrupt triggered by the interrupt pin of PCA953X I/O Port.
98  *
99  * If nint_gpios is configured in device tree then this will be triggered each
100  * time a gpio configured as an input changes state. The gpio input states are
101  * read in this function which clears the interrupt.
102  *
103  * @param dev Pointer to the device structure for the driver instance.
104  */
gpio_pca953x_handle_interrupt(const struct device * dev)105 static void gpio_pca953x_handle_interrupt(const struct device *dev)
106 {
107 	struct pca953x_drv_data *drv_data = dev->data;
108 	struct pca953x_irq_state *irq_state = &drv_data->irq_state;
109 	int rc;
110 	uint8_t previous_state;
111 	uint8_t current_state;
112 	uint8_t transitioned_pins;
113 	uint8_t interrupt_status = 0;
114 
115 	k_sem_take(&drv_data->lock, K_FOREVER);
116 
117 	/* Any interrupts enabled? */
118 	if (!irq_state->rising && !irq_state->falling) {
119 		rc = -EINVAL;
120 		goto out;
121 	}
122 
123 	/* Store previous input state then read new value */
124 	previous_state = drv_data->pin_state.input;
125 	rc = update_input(dev);
126 	if (rc != 0) {
127 		goto out;
128 	}
129 
130 	/* Find out which input pins have changed state */
131 	current_state = drv_data->pin_state.input;
132 	transitioned_pins = previous_state ^ current_state;
133 
134 	/* Mask gpio transactions with rising/falling edge interrupt config */
135 	interrupt_status = (irq_state->rising & transitioned_pins &
136 			  current_state);
137 	interrupt_status |= (irq_state->falling & transitioned_pins &
138 			   previous_state);
139 
140 out:
141 	k_sem_give(&drv_data->lock);
142 
143 	if ((rc == 0) && (interrupt_status)) {
144 		gpio_fire_callbacks(&drv_data->cb, dev, interrupt_status);
145 	}
146 }
147 
148 /**
149  * @brief Work handler for PCA953X interrupt
150  *
151  * @param work Work struct that contains pointer to interrupt handler function
152  */
gpio_pca953x_work_handler(struct k_work * work)153 static void gpio_pca953x_work_handler(struct k_work *work)
154 {
155 	struct pca953x_drv_data *drv_data =
156 		CONTAINER_OF(work, struct pca953x_drv_data, work);
157 
158 	gpio_pca953x_handle_interrupt(drv_data->dev);
159 }
160 
161 /**
162  * @brief ISR for interrupt pin of PCA953X
163  *
164  * @param dev Pointer to the device structure for the driver instance.
165  * @param gpio_cb Pointer to callback function struct
166  * @param pins Bitmask of pins that triggered interrupt
167  */
gpio_pca953x_init_cb(const struct device * dev,struct gpio_callback * gpio_cb,uint32_t pins)168 static void gpio_pca953x_init_cb(const struct device *dev,
169 				 struct gpio_callback *gpio_cb, uint32_t pins)
170 {
171 	struct pca953x_drv_data *drv_data =
172 		CONTAINER_OF(gpio_cb, struct pca953x_drv_data, gpio_cb);
173 
174 	ARG_UNUSED(pins);
175 
176 	k_work_submit(&drv_data->work);
177 }
178 
gpio_pca953x_config(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)179 static int gpio_pca953x_config(const struct device *dev, gpio_pin_t pin,
180 			       gpio_flags_t flags)
181 {
182 	const struct pca953x_config *cfg = dev->config;
183 	struct pca953x_drv_data *drv_data = dev->data;
184 	struct pca953x_pin_state *pins = &drv_data->pin_state;
185 	int rc = 0;
186 	bool data_first = false;
187 
188 	/* Can't do I2C bus operations from an ISR */
189 	if (k_is_in_isr()) {
190 		return -EWOULDBLOCK;
191 	}
192 
193 	/* Single Ended lines (Open drain and open source) not supported */
194 	if ((flags & GPIO_SINGLE_ENDED) != 0) {
195 		return -ENOTSUP;
196 	}
197 
198 	/* The PCA953X has no internal pull up support */
199 	if (((flags & GPIO_PULL_UP) != 0) || ((flags & GPIO_PULL_DOWN) != 0)) {
200 		return -ENOTSUP;
201 	}
202 
203 	/* Simultaneous input & output mode not supported */
204 	if (((flags & GPIO_INPUT) != 0) && ((flags & GPIO_OUTPUT) != 0)) {
205 		return -ENOTSUP;
206 	}
207 
208 	k_sem_take(&drv_data->lock, K_FOREVER);
209 
210 	/* Ensure either Output or Input is specified */
211 	if ((flags & GPIO_OUTPUT) != 0) {
212 		pins->dir &= ~BIT(pin);
213 		if ((flags & GPIO_OUTPUT_INIT_LOW) != 0) {
214 			pins->output &= ~BIT(pin);
215 			data_first = true;
216 		} else if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0) {
217 			pins->output |= BIT(pin);
218 			data_first = true;
219 		}
220 	} else if ((flags & GPIO_INPUT) != 0) {
221 		pins->dir |= BIT(pin);
222 	} else {
223 		rc = -ENOTSUP;
224 		goto out;
225 	}
226 
227 	/* Set output values */
228 	if (data_first) {
229 		rc = i2c_reg_write_byte_dt(&cfg->i2c, PCA953X_OUTPUT_PORT, pins->output);
230 	}
231 
232 	if (rc == 0) {
233 		/* Set pin directions */
234 		rc = i2c_reg_write_byte_dt(&cfg->i2c, PCA953X_CONFIGURATION, pins->dir);
235 	}
236 
237 	if (rc == 0) {
238 		/* Refresh input status */
239 		rc = update_input(dev);
240 	}
241 
242 out:
243 	k_sem_give(&drv_data->lock);
244 	return rc;
245 }
246 
gpio_pca953x_port_read(const struct device * dev,gpio_port_value_t * value)247 static int gpio_pca953x_port_read(const struct device *dev,
248 				 gpio_port_value_t *value)
249 {
250 	const struct pca953x_config *cfg = dev->config;
251 	struct pca953x_drv_data *drv_data = dev->data;
252 	uint8_t input_pin_data;
253 	int rc = 0;
254 
255 	/* Can't do I2C bus operations from an ISR */
256 	if (k_is_in_isr()) {
257 		return -EWOULDBLOCK;
258 	}
259 
260 	k_sem_take(&drv_data->lock, K_FOREVER);
261 
262 	/* Read Input Register */
263 	rc = i2c_reg_read_byte_dt(&cfg->i2c, PCA953X_INPUT_PORT, &input_pin_data);
264 
265 	LOG_DBG("read %x got %d", input_pin_data, rc);
266 
267 	if (rc == 0) {
268 		drv_data->pin_state.input = input_pin_data;
269 		*value = (gpio_port_value_t)(drv_data->pin_state.input);
270 	}
271 
272 	k_sem_give(&drv_data->lock);
273 	return rc;
274 }
275 
gpio_pca953x_port_write(const struct device * dev,gpio_port_pins_t mask,gpio_port_value_t value,gpio_port_value_t toggle)276 static int gpio_pca953x_port_write(const struct device *dev,
277 				   gpio_port_pins_t mask,
278 				   gpio_port_value_t value,
279 				   gpio_port_value_t toggle)
280 {
281 	const struct pca953x_config *cfg = dev->config;
282 	struct pca953x_drv_data *drv_data = dev->data;
283 	uint8_t *outp = &drv_data->pin_state.output;
284 	int rc;
285 	uint8_t orig_out;
286 	uint8_t out;
287 
288 	/* Can't do I2C bus operations from an ISR */
289 	if (k_is_in_isr()) {
290 		return -EWOULDBLOCK;
291 	}
292 
293 	k_sem_take(&drv_data->lock, K_FOREVER);
294 
295 	orig_out = *outp;
296 	out = ((orig_out & ~mask) | (value & mask)) ^ toggle;
297 
298 	rc = i2c_reg_write_byte_dt(&cfg->i2c, PCA953X_OUTPUT_PORT, out);
299 
300 	if (rc == 0) {
301 		*outp = out;
302 	}
303 
304 	k_sem_give(&drv_data->lock);
305 
306 	LOG_DBG("write %x msk %08x val %08x => %x: %d", orig_out, mask,
307 		value, out, rc);
308 
309 	return rc;
310 }
311 
gpio_pca953x_port_set_masked(const struct device * dev,gpio_port_pins_t mask,gpio_port_value_t value)312 static int gpio_pca953x_port_set_masked(const struct device *dev,
313 					gpio_port_pins_t mask,
314 					gpio_port_value_t value)
315 {
316 	return gpio_pca953x_port_write(dev, mask, value, 0);
317 }
318 
gpio_pca953x_port_set_bits(const struct device * dev,gpio_port_pins_t pins)319 static int gpio_pca953x_port_set_bits(const struct device *dev,
320 				      gpio_port_pins_t pins)
321 {
322 	return gpio_pca953x_port_write(dev, pins, pins, 0);
323 }
324 
gpio_pca953x_port_clear_bits(const struct device * dev,gpio_port_pins_t pins)325 static int gpio_pca953x_port_clear_bits(const struct device *dev,
326 					gpio_port_pins_t pins)
327 {
328 	return gpio_pca953x_port_write(dev, pins, 0, 0);
329 }
330 
gpio_pca953x_port_toggle_bits(const struct device * dev,gpio_port_pins_t pins)331 static int gpio_pca953x_port_toggle_bits(const struct device *dev,
332 					 gpio_port_pins_t pins)
333 {
334 	return gpio_pca953x_port_write(dev, 0, 0, pins);
335 }
336 
gpio_pca953x_pin_interrupt_configure(const struct device * dev,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)337 static int gpio_pca953x_pin_interrupt_configure(const struct device *dev,
338 						gpio_pin_t pin,
339 						enum gpio_int_mode mode,
340 						enum gpio_int_trig trig)
341 {
342 	const struct pca953x_config *cfg = dev->config;
343 	struct pca953x_drv_data *drv_data = dev->data;
344 	struct pca953x_irq_state *irq = &drv_data->irq_state;
345 
346 	if (!cfg->interrupt_enabled) {
347 		return -ENOTSUP;
348 	}
349 	/* Device does not support level-triggered interrupts. */
350 	if (mode == GPIO_INT_MODE_LEVEL) {
351 		return -ENOTSUP;
352 	}
353 
354 	k_sem_take(&drv_data->lock, K_FOREVER);
355 
356 	if (mode == GPIO_INT_MODE_DISABLED) {
357 		irq->falling &= ~BIT(pin);
358 		irq->rising &= ~BIT(pin);
359 	} else { /* GPIO_INT_MODE_EDGE */
360 		if (trig == GPIO_INT_TRIG_BOTH) {
361 			irq->falling |= BIT(pin);
362 			irq->rising |= BIT(pin);
363 		} else if (trig == GPIO_INT_TRIG_LOW) {
364 			irq->falling |= BIT(pin);
365 			irq->rising &= ~BIT(pin);
366 		} else if (trig == GPIO_INT_TRIG_HIGH) {
367 			irq->falling &= ~BIT(pin);
368 			irq->rising |= BIT(pin);
369 		}
370 	}
371 
372 	k_sem_give(&drv_data->lock);
373 
374 	return 0;
375 }
376 
gpio_pca953x_manage_callback(const struct device * dev,struct gpio_callback * callback,bool set)377 static int gpio_pca953x_manage_callback(const struct device *dev,
378 					struct gpio_callback *callback,
379 					bool set)
380 {
381 	struct pca953x_drv_data *data = dev->data;
382 
383 	return gpio_manage_callback(&data->cb, callback, set);
384 }
385 
386 /**
387  * @brief Initialization function of PCA953X
388  *
389  * This sets initial input/ output configuration and output states.
390  * The interrupt is configured if this is enabled.
391  *
392  * @param dev Device struct
393  * @return 0 if successful, failed otherwise.
394  */
gpio_pca953x_init(const struct device * dev)395 static int gpio_pca953x_init(const struct device *dev)
396 {
397 	const struct pca953x_config *cfg = dev->config;
398 	struct pca953x_drv_data *drv_data = dev->data;
399 	int rc = 0;
400 
401 	if (!device_is_ready(cfg->i2c.bus)) {
402 		LOG_ERR("I2C bus device not found");
403 		goto out;
404 	}
405 
406 	/* Do an initial read, this clears the interrupt pin and sets
407 	 * up the initial value of the pin state input data.
408 	 */
409 	rc = update_input(dev);
410 	if (rc) {
411 		goto out;
412 	}
413 
414 	if (cfg->interrupt_enabled) {
415 		if (!device_is_ready(cfg->gpio_int.port)) {
416 			LOG_ERR("Cannot get pointer to gpio interrupt device");
417 			rc = -EINVAL;
418 			goto out;
419 		}
420 
421 		drv_data->dev = dev;
422 
423 		k_work_init(&drv_data->work, gpio_pca953x_work_handler);
424 
425 		rc = gpio_pin_configure_dt(&cfg->gpio_int, GPIO_INPUT);
426 		if (rc) {
427 			goto out;
428 		}
429 
430 		rc = gpio_pin_interrupt_configure_dt(&cfg->gpio_int,
431 						GPIO_INT_EDGE_TO_ACTIVE);
432 		if (rc) {
433 			goto out;
434 		}
435 
436 		gpio_init_callback(&drv_data->gpio_cb,
437 					gpio_pca953x_init_cb,
438 					BIT(cfg->gpio_int.pin));
439 
440 		rc = gpio_add_callback(cfg->gpio_int.port,
441 					&drv_data->gpio_cb);
442 	}
443 out:
444 	if (rc) {
445 		LOG_ERR("%s init failed: %d", dev->name, rc);
446 	} else {
447 		LOG_INF("%s init ok", dev->name);
448 	}
449 	return rc;
450 }
451 
452 static const struct gpio_driver_api api_table = {
453 	.pin_configure = gpio_pca953x_config,
454 	.port_get_raw = gpio_pca953x_port_read,
455 	.port_set_masked_raw = gpio_pca953x_port_set_masked,
456 	.port_set_bits_raw = gpio_pca953x_port_set_bits,
457 	.port_clear_bits_raw = gpio_pca953x_port_clear_bits,
458 	.port_toggle_bits = gpio_pca953x_port_toggle_bits,
459 	.pin_interrupt_configure = gpio_pca953x_pin_interrupt_configure,
460 	.manage_callback = gpio_pca953x_manage_callback,
461 };
462 
463 #define GPIO_PCA953X_INIT(n)							\
464 	static const struct pca953x_config pca953x_cfg_##n = {			\
465 		.i2c = I2C_DT_SPEC_INST_GET(n),					\
466 		.common = {							\
467 			.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n),	\
468 		},								\
469 		.interrupt_enabled = DT_INST_NODE_HAS_PROP(n, nint_gpios),	\
470 		.gpio_int = GPIO_DT_SPEC_INST_GET_OR(n, nint_gpios, {0}),	\
471 	};									\
472 										\
473 	static struct pca953x_drv_data pca953x_drvdata_##n = {			\
474 		.lock = Z_SEM_INITIALIZER(pca953x_drvdata_##n.lock, 1, 1),	\
475 		.pin_state.dir = ALL_PINS,					\
476 		.pin_state.output = ALL_PINS,					\
477 	};									\
478 	DEVICE_DT_INST_DEFINE(n,						\
479 		gpio_pca953x_init,						\
480 		NULL,								\
481 		&pca953x_drvdata_##n,						\
482 		&pca953x_cfg_##n,						\
483 		POST_KERNEL,							\
484 		CONFIG_GPIO_PCA953X_INIT_PRIORITY,				\
485 		&api_table);
486 
487 #define DT_DRV_COMPAT ti_tca9538
488 DT_INST_FOREACH_STATUS_OKAY(GPIO_PCA953X_INIT)
489