1 /*
2  * Copyright 2022 Google LLC
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT richtek_rt1718s_gpio_port
8 
9 /**
10  * @file Driver for RS1718S TCPC chip GPIOs.
11  */
12 
13 #include "gpio_rt1718s.h"
14 
15 #include <zephyr/drivers/gpio.h>
16 #include <zephyr/drivers/gpio/gpio_utils.h>
17 #include <zephyr/logging/log.h>
18 LOG_MODULE_DECLARE(gpio_rt1718s_port, CONFIG_GPIO_LOG_LEVEL);
19 
20 /* Driver config */
21 struct gpio_rt1718s_port_config {
22 	/* gpio_driver_config needs to be first */
23 	struct gpio_driver_config common;
24 	/* RT1718S chip device */
25 	const struct device *rt1718s_dev;
26 };
27 
28 /* Driver data */
29 struct gpio_rt1718s_port_data {
30 	/* gpio_driver_data needs to be first */
31 	struct gpio_driver_data common;
32 	/* GPIO callback list */
33 	sys_slist_t cb_list_gpio;
34 	/* lock GPIO registers access */
35 	struct k_sem lock;
36 };
37 
38 /* GPIO api functions */
gpio_rt1718s_pin_config(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)39 static int gpio_rt1718s_pin_config(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags)
40 {
41 	const struct gpio_rt1718s_port_config *const config = dev->config;
42 	struct gpio_rt1718s_port_data *const data = dev->data;
43 	uint8_t new_reg = 0;
44 	int ret = 0;
45 
46 	/* Don't support simultaneous in/out mode */
47 	if ((flags & GPIO_INPUT) && (flags & GPIO_OUTPUT)) {
48 		return -ENOTSUP;
49 	}
50 
51 	/* Don't support "open source" mode */
52 	if ((flags & GPIO_SINGLE_ENDED) && !(flags & GPIO_LINE_OPEN_DRAIN)) {
53 		return -ENOTSUP;
54 	}
55 
56 	/* RT1718S has 3 GPIOs so check range */
57 	if (pin >= RT1718S_GPIO_NUM) {
58 		return -EINVAL;
59 	}
60 
61 	/* Configure pin as input. */
62 	if (flags & GPIO_INPUT) {
63 		/* Do not set RT1718S_REG_GPIO_CTRL_OE bit for input */
64 		/* Set pull-high/low input */
65 		if (flags & GPIO_PULL_UP) {
66 			new_reg |= RT1718S_REG_GPIO_CTRL_PU;
67 		}
68 		if (flags & GPIO_PULL_DOWN) {
69 			new_reg |= RT1718S_REG_GPIO_CTRL_PD;
70 		}
71 	} else if (flags & GPIO_OUTPUT) {
72 		/* Set GPIO as output */
73 		new_reg |= RT1718S_REG_GPIO_CTRL_OE;
74 
75 		/* Set push-pull or open-drain */
76 		if (!(flags & GPIO_SINGLE_ENDED)) {
77 			new_reg |= RT1718S_REG_GPIO_CTRL_OD_N;
78 		}
79 
80 		/* Set init state */
81 		if (flags & GPIO_OUTPUT_INIT_HIGH) {
82 			new_reg |= RT1718S_REG_GPIO_CTRL_O;
83 		}
84 	}
85 
86 	k_sem_take(&data->lock, K_FOREVER);
87 	ret = rt1718s_reg_write_byte(config->rt1718s_dev, RT1718S_REG_GPIO_CTRL(pin), new_reg);
88 	k_sem_give(&data->lock);
89 
90 	return ret;
91 }
92 
gpio_rt1718s_port_get_raw(const struct device * dev,gpio_port_value_t * value)93 static int gpio_rt1718s_port_get_raw(const struct device *dev, gpio_port_value_t *value)
94 {
95 	const struct gpio_rt1718s_port_config *const config = dev->config;
96 	uint8_t reg;
97 	int ret;
98 
99 	ret = rt1718s_reg_read_byte(config->rt1718s_dev, RT1718S_REG_RT_ST8, &reg);
100 	*value = reg & (RT1718S_REG_RT_ST8_GPIO1_I | RT1718S_REG_RT_ST8_GPIO2_I |
101 			RT1718S_REG_RT_ST8_GPIO3_I);
102 
103 	return ret;
104 }
105 
gpio_rt1718s_port_set_masked_raw(const struct device * dev,gpio_port_pins_t mask,gpio_port_value_t value)106 static int gpio_rt1718s_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask,
107 					    gpio_port_value_t value)
108 {
109 	const struct gpio_rt1718s_port_config *const config = dev->config;
110 	struct gpio_rt1718s_port_data *const data = dev->data;
111 	uint8_t new_reg, reg;
112 	int ret = 0;
113 
114 	k_sem_take(&data->lock, K_FOREVER);
115 
116 	for (int pin = 0; pin < RT1718S_GPIO_NUM; pin++) {
117 		if (mask & BIT(pin)) {
118 			ret = rt1718s_reg_read_byte(config->rt1718s_dev, RT1718S_REG_GPIO_CTRL(pin),
119 						    &reg);
120 			if (ret < 0) {
121 				break;
122 			}
123 
124 			if (value & BIT(pin)) {
125 				new_reg = reg | RT1718S_REG_GPIO_CTRL_O;
126 			} else {
127 				new_reg = reg & ~RT1718S_REG_GPIO_CTRL_O;
128 			}
129 			ret = rt1718s_reg_update(config->rt1718s_dev, RT1718S_REG_GPIO_CTRL(pin),
130 						 reg, new_reg);
131 		}
132 	}
133 
134 	k_sem_give(&data->lock);
135 
136 	return ret;
137 }
138 
gpio_rt1718s_port_set_bits_raw(const struct device * dev,gpio_port_pins_t mask)139 static int gpio_rt1718s_port_set_bits_raw(const struct device *dev, gpio_port_pins_t mask)
140 {
141 	const struct gpio_rt1718s_port_config *const config = dev->config;
142 	struct gpio_rt1718s_port_data *const data = dev->data;
143 	uint8_t new_reg, reg;
144 	int ret = 0;
145 
146 	k_sem_take(&data->lock, K_FOREVER);
147 
148 	for (int pin = 0; pin < RT1718S_GPIO_NUM; pin++) {
149 		if (mask & BIT(pin)) {
150 			ret = rt1718s_reg_read_byte(config->rt1718s_dev, RT1718S_REG_GPIO_CTRL(pin),
151 						    &reg);
152 			if (ret < 0) {
153 				break;
154 			}
155 			new_reg = reg | RT1718S_REG_GPIO_CTRL_O;
156 			ret = rt1718s_reg_update(config->rt1718s_dev, RT1718S_REG_GPIO_CTRL(pin),
157 						 reg, new_reg);
158 		}
159 	}
160 
161 	k_sem_give(&data->lock);
162 
163 	return ret;
164 }
165 
gpio_rt1718s_port_clear_bits_raw(const struct device * dev,gpio_port_pins_t mask)166 static int gpio_rt1718s_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t mask)
167 {
168 	const struct gpio_rt1718s_port_config *const config = dev->config;
169 	struct gpio_rt1718s_port_data *const data = dev->data;
170 	uint8_t new_reg, reg;
171 	int ret = 0;
172 
173 	k_sem_take(&data->lock, K_FOREVER);
174 
175 	for (int pin = 0; pin < RT1718S_GPIO_NUM; pin++) {
176 		if (mask & BIT(pin)) {
177 			ret = rt1718s_reg_read_byte(config->rt1718s_dev, RT1718S_REG_GPIO_CTRL(pin),
178 						    &reg);
179 			if (ret < 0) {
180 				break;
181 			}
182 			new_reg = reg & ~RT1718S_REG_GPIO_CTRL_O;
183 			ret = rt1718s_reg_update(config->rt1718s_dev, RT1718S_REG_GPIO_CTRL(pin),
184 						 reg, new_reg);
185 		}
186 	}
187 
188 	k_sem_give(&data->lock);
189 
190 	return ret;
191 }
192 
gpio_rt1718s_port_toggle_bits(const struct device * dev,gpio_port_pins_t mask)193 static int gpio_rt1718s_port_toggle_bits(const struct device *dev, gpio_port_pins_t mask)
194 {
195 	const struct gpio_rt1718s_port_config *const config = dev->config;
196 	struct gpio_rt1718s_port_data *const data = dev->data;
197 	uint8_t new_reg, reg;
198 	int ret = 0;
199 
200 	k_sem_take(&data->lock, K_FOREVER);
201 
202 	for (int pin = 0; pin < RT1718S_GPIO_NUM; pin++) {
203 		if (mask & BIT(pin)) {
204 			ret = rt1718s_reg_read_byte(config->rt1718s_dev, RT1718S_REG_GPIO_CTRL(pin),
205 						    &reg);
206 			if (ret < 0) {
207 				break;
208 			}
209 			new_reg = reg ^ RT1718S_REG_GPIO_CTRL_O;
210 			ret = rt1718s_reg_update(config->rt1718s_dev, RT1718S_REG_GPIO_CTRL(pin),
211 						 reg, new_reg);
212 		}
213 	}
214 
215 	k_sem_give(&data->lock);
216 
217 	return ret;
218 }
219 
gpio_rt1718s_pin_interrupt_configure(const struct device * dev,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)220 static int gpio_rt1718s_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin,
221 						enum gpio_int_mode mode, enum gpio_int_trig trig)
222 {
223 	const struct gpio_rt1718s_port_config *const config = dev->config;
224 	struct gpio_rt1718s_port_data *const data = dev->data;
225 	struct rt1718s_data *const data_rt1718s = config->rt1718s_dev->data;
226 	uint8_t reg_int8, reg_mask8, new_reg_mask8 = 0;
227 	uint8_t mask_rise = BIT(pin), mask_fall = BIT(4 + pin);
228 	uint16_t alert_mask;
229 	int ret;
230 
231 	/* Check passed arguments */
232 	if (mode == GPIO_INT_MODE_LEVEL || pin >= RT1718S_GPIO_NUM) {
233 		return -ENOTSUP;
234 	}
235 
236 	k_sem_take(&data->lock, K_FOREVER);
237 	k_sem_take(&data_rt1718s->lock_tcpci, K_FOREVER);
238 
239 	ret = rt1718s_reg_read_byte(config->rt1718s_dev, RT1718S_REG_RT_MASK8, &reg_mask8);
240 	if (ret < 0) {
241 		goto done;
242 	}
243 
244 	/* Disable GPIO interrupt */
245 	if (mode == GPIO_INT_MODE_DISABLED) {
246 		new_reg_mask8 = reg_mask8 & ~(mask_rise | mask_fall);
247 	} else if (mode == GPIO_INT_MODE_EDGE) {
248 		switch (trig) {
249 		case GPIO_INT_TRIG_BOTH:
250 			new_reg_mask8 = reg_mask8 | mask_rise | mask_fall;
251 			break;
252 		case GPIO_INT_TRIG_HIGH:
253 			new_reg_mask8 = (reg_mask8 | mask_rise) & ~mask_fall;
254 			break;
255 		case GPIO_INT_TRIG_LOW:
256 			new_reg_mask8 = (reg_mask8 | mask_fall) & ~mask_rise;
257 			break;
258 		}
259 
260 		ret = rt1718s_reg_burst_read(config->rt1718s_dev, RT1718S_REG_ALERT_MASK,
261 					     (uint8_t *)&alert_mask, sizeof(alert_mask));
262 		if (ret) {
263 			goto done;
264 		}
265 
266 		/* Enable Vendor Defined Alert for GPIO interrupts */
267 		if (!(alert_mask & RT1718S_REG_ALERT_MASK_VENDOR_DEFINED_ALERT)) {
268 			alert_mask |= RT1718S_REG_ALERT_MASK_VENDOR_DEFINED_ALERT;
269 			ret = rt1718s_reg_burst_write(config->rt1718s_dev, RT1718S_REG_ALERT_MASK,
270 						      (uint8_t *)&alert_mask, sizeof(alert_mask));
271 
272 			if (ret) {
273 				goto done;
274 			}
275 		}
276 
277 		/* Clear pending interrupts, which were trigger before enabling the pin
278 		 * interrupt by user.
279 		 */
280 		reg_int8 = mask_rise | mask_fall;
281 		rt1718s_reg_write_byte(config->rt1718s_dev, RT1718S_REG_RT_INT8, reg_int8);
282 	}
283 
284 	/* MASK8 handles 3 GPIOs interrupts, both edges */
285 	ret = rt1718s_reg_update(config->rt1718s_dev, RT1718S_REG_RT_MASK8, reg_mask8,
286 				 new_reg_mask8);
287 
288 done:
289 	k_sem_give(&data_rt1718s->lock_tcpci);
290 	k_sem_give(&data->lock);
291 
292 	return ret;
293 }
294 
gpio_rt1718s_manage_callback(const struct device * dev,struct gpio_callback * callback,bool set)295 static int gpio_rt1718s_manage_callback(const struct device *dev, struct gpio_callback *callback,
296 					bool set)
297 {
298 	struct gpio_rt1718s_port_data *const data = dev->data;
299 
300 	return gpio_manage_callback(&data->cb_list_gpio, callback, set);
301 }
302 
rt1718s_gpio_alert_handler(const struct device * dev)303 void rt1718s_gpio_alert_handler(const struct device *dev)
304 {
305 	const struct rt1718s_config *const config = dev->config;
306 	struct gpio_rt1718s_port_data *const data_port = config->gpio_port_dev->data;
307 	uint8_t reg_int8, reg_mask8;
308 
309 	k_sem_take(&data_port->lock, K_FOREVER);
310 
311 	/* Get mask and state of GPIO interrupts */
312 	if (rt1718s_reg_read_byte(dev, RT1718S_REG_RT_INT8, &reg_int8) ||
313 	    rt1718s_reg_read_byte(dev, RT1718S_REG_RT_MASK8, &reg_mask8)) {
314 		k_sem_give(&data_port->lock);
315 		LOG_ERR("i2c access failed");
316 		return;
317 	}
318 
319 	reg_int8 &= reg_mask8;
320 	/* Clear the interrupts */
321 	if (reg_int8) {
322 		if (rt1718s_reg_write_byte(dev, RT1718S_REG_RT_INT8, reg_int8)) {
323 			k_sem_give(&data_port->lock);
324 			LOG_ERR("i2c access failed");
325 			return;
326 		}
327 	}
328 
329 	k_sem_give(&data_port->lock);
330 
331 	if (reg_int8 & RT1718S_GPIO_INT_MASK)
332 		/* Call the GPIO callbacks for rising *or* falling edge */
333 		gpio_fire_callbacks(&data_port->cb_list_gpio, config->gpio_port_dev,
334 				    (reg_int8 & 0x7) | ((reg_int8 >> 4) & 0x7));
335 }
336 
337 static const struct gpio_driver_api gpio_rt1718s_driver = {
338 	.pin_configure = gpio_rt1718s_pin_config,
339 	.port_get_raw = gpio_rt1718s_port_get_raw,
340 	.port_set_masked_raw = gpio_rt1718s_port_set_masked_raw,
341 	.port_set_bits_raw = gpio_rt1718s_port_set_bits_raw,
342 	.port_clear_bits_raw = gpio_rt1718s_port_clear_bits_raw,
343 	.port_toggle_bits = gpio_rt1718s_port_toggle_bits,
344 	.pin_interrupt_configure = gpio_rt1718s_pin_interrupt_configure,
345 	.manage_callback = gpio_rt1718s_manage_callback,
346 };
347 
gpio_rt1718s_port_init(const struct device * dev)348 static int gpio_rt1718s_port_init(const struct device *dev)
349 {
350 	const struct gpio_rt1718s_port_config *const config = dev->config;
351 	struct gpio_rt1718s_port_data *const data = dev->data;
352 
353 	if (!device_is_ready(config->rt1718s_dev)) {
354 		LOG_ERR("%s is not ready", config->rt1718s_dev->name);
355 		return -ENODEV;
356 	}
357 
358 	k_sem_init(&data->lock, 1, 1);
359 
360 	return 0;
361 }
362 
363 /* RT1718S GPIO port driver must be initialized after RT1718S chip driver */
364 BUILD_ASSERT(CONFIG_GPIO_RT1718S_PORT_INIT_PRIORITY > CONFIG_RT1718S_INIT_PRIORITY);
365 
366 #define GPIO_RT1718S_PORT_DEVICE_INSTANCE(inst)                                                    \
367 	static const struct gpio_rt1718s_port_config gpio_rt1718s_port_cfg_##inst = {              \
368 		.common = {.port_pin_mask = 0x7},                                                  \
369 		.rt1718s_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)),                                \
370 	};                                                                                         \
371 	static struct gpio_rt1718s_port_data gpio_rt1718s_port_data_##inst;                        \
372 	DEVICE_DT_INST_DEFINE(inst, gpio_rt1718s_port_init, NULL, &gpio_rt1718s_port_data_##inst,  \
373 			      &gpio_rt1718s_port_cfg_##inst, POST_KERNEL,                          \
374 			      CONFIG_GPIO_RT1718S_PORT_INIT_PRIORITY, &gpio_rt1718s_driver);
375 
376 DT_INST_FOREACH_STATUS_OKAY(GPIO_RT1718S_PORT_DEVICE_INSTANCE)
377