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, ®);
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 ®);
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 ®);
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 ®);
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 ®);
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, ®_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, ®_int8) ||
313 rt1718s_reg_read_byte(dev, RT1718S_REG_RT_MASK8, ®_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