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_REGISTER(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 		default:
259 			ret = -EINVAL;
260 			goto done;
261 		}
262 
263 		ret = rt1718s_reg_burst_read(config->rt1718s_dev, RT1718S_REG_ALERT_MASK,
264 					     (uint8_t *)&alert_mask, sizeof(alert_mask));
265 		if (ret) {
266 			goto done;
267 		}
268 
269 		/* Enable Vendor Defined Alert for GPIO interrupts */
270 		if (!(alert_mask & RT1718S_REG_ALERT_MASK_VENDOR_DEFINED_ALERT)) {
271 			alert_mask |= RT1718S_REG_ALERT_MASK_VENDOR_DEFINED_ALERT;
272 			ret = rt1718s_reg_burst_write(config->rt1718s_dev, RT1718S_REG_ALERT_MASK,
273 						      (uint8_t *)&alert_mask, sizeof(alert_mask));
274 
275 			if (ret) {
276 				goto done;
277 			}
278 		}
279 
280 		/* Clear pending interrupts, which were trigger before enabling the pin
281 		 * interrupt by user.
282 		 */
283 		reg_int8 = mask_rise | mask_fall;
284 		rt1718s_reg_write_byte(config->rt1718s_dev, RT1718S_REG_RT_INT8, reg_int8);
285 	}
286 
287 	/* MASK8 handles 3 GPIOs interrupts, both edges */
288 	ret = rt1718s_reg_update(config->rt1718s_dev, RT1718S_REG_RT_MASK8, reg_mask8,
289 				 new_reg_mask8);
290 
291 done:
292 	k_sem_give(&data_rt1718s->lock_tcpci);
293 	k_sem_give(&data->lock);
294 
295 	return ret;
296 }
297 
gpio_rt1718s_manage_callback(const struct device * dev,struct gpio_callback * callback,bool set)298 static int gpio_rt1718s_manage_callback(const struct device *dev, struct gpio_callback *callback,
299 					bool set)
300 {
301 	struct gpio_rt1718s_port_data *const data = dev->data;
302 
303 	return gpio_manage_callback(&data->cb_list_gpio, callback, set);
304 }
305 
rt1718s_gpio_alert_handler(const struct device * dev)306 void rt1718s_gpio_alert_handler(const struct device *dev)
307 {
308 	const struct rt1718s_config *const config = dev->config;
309 	struct gpio_rt1718s_port_data *const data_port = config->gpio_port_dev->data;
310 	uint8_t reg_int8, reg_mask8;
311 
312 	k_sem_take(&data_port->lock, K_FOREVER);
313 
314 	/* Get mask and state of GPIO interrupts */
315 	if (rt1718s_reg_read_byte(dev, RT1718S_REG_RT_INT8, &reg_int8) ||
316 	    rt1718s_reg_read_byte(dev, RT1718S_REG_RT_MASK8, &reg_mask8)) {
317 		k_sem_give(&data_port->lock);
318 		LOG_ERR("i2c access failed");
319 		return;
320 	}
321 
322 	reg_int8 &= reg_mask8;
323 	/* Clear the interrupts */
324 	if (reg_int8) {
325 		if (rt1718s_reg_write_byte(dev, RT1718S_REG_RT_INT8, reg_int8)) {
326 			k_sem_give(&data_port->lock);
327 			LOG_ERR("i2c access failed");
328 			return;
329 		}
330 	}
331 
332 	k_sem_give(&data_port->lock);
333 
334 	if (reg_int8 & RT1718S_GPIO_INT_MASK) {
335 		/* Call the GPIO callbacks for rising *or* falling edge */
336 		gpio_fire_callbacks(&data_port->cb_list_gpio, config->gpio_port_dev,
337 				    (reg_int8 & 0x7) | ((reg_int8 >> 4) & 0x7));
338 	}
339 }
340 
341 static DEVICE_API(gpio, gpio_rt1718s_driver) = {
342 	.pin_configure = gpio_rt1718s_pin_config,
343 	.port_get_raw = gpio_rt1718s_port_get_raw,
344 	.port_set_masked_raw = gpio_rt1718s_port_set_masked_raw,
345 	.port_set_bits_raw = gpio_rt1718s_port_set_bits_raw,
346 	.port_clear_bits_raw = gpio_rt1718s_port_clear_bits_raw,
347 	.port_toggle_bits = gpio_rt1718s_port_toggle_bits,
348 	.pin_interrupt_configure = gpio_rt1718s_pin_interrupt_configure,
349 	.manage_callback = gpio_rt1718s_manage_callback,
350 };
351 
gpio_rt1718s_port_init(const struct device * dev)352 static int gpio_rt1718s_port_init(const struct device *dev)
353 {
354 	const struct gpio_rt1718s_port_config *const config = dev->config;
355 	struct gpio_rt1718s_port_data *const data = dev->data;
356 
357 	if (!device_is_ready(config->rt1718s_dev)) {
358 		LOG_ERR("%s is not ready", config->rt1718s_dev->name);
359 		return -ENODEV;
360 	}
361 
362 	k_sem_init(&data->lock, 1, 1);
363 
364 	return 0;
365 }
366 
367 /* RT1718S GPIO port driver must be initialized after RT1718S chip driver */
368 BUILD_ASSERT(CONFIG_GPIO_RT1718S_PORT_INIT_PRIORITY > CONFIG_RT1718S_INIT_PRIORITY);
369 
370 #define GPIO_RT1718S_PORT_DEVICE_INSTANCE(inst)                                                    \
371 	static const struct gpio_rt1718s_port_config gpio_rt1718s_port_cfg_##inst = {              \
372 		.common = {.port_pin_mask = 0x7},                                                  \
373 		.rt1718s_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)),                                \
374 	};                                                                                         \
375 	static struct gpio_rt1718s_port_data gpio_rt1718s_port_data_##inst;                        \
376 	DEVICE_DT_INST_DEFINE(inst, gpio_rt1718s_port_init, NULL, &gpio_rt1718s_port_data_##inst,  \
377 			      &gpio_rt1718s_port_cfg_##inst, POST_KERNEL,                          \
378 			      CONFIG_GPIO_RT1718S_PORT_INIT_PRIORITY, &gpio_rt1718s_driver);
379 
380 DT_INST_FOREACH_STATUS_OKAY(GPIO_RT1718S_PORT_DEVICE_INSTANCE)
381