1 /*
2 * Copyright (c) 2024 ITE Corporation. All Rights Reserved.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT ite_it8801_gpio
8
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/gpio.h>
11 #include <zephyr/drivers/gpio/gpio_utils.h>
12 #include <zephyr/drivers/i2c.h>
13 #include <zephyr/drivers/mfd/mfd_ite_it8801.h>
14 #include <zephyr/spinlock.h>
15
16 #include <zephyr/logging/log.h>
17 LOG_MODULE_REGISTER(gpio_ite_it8801, CONFIG_GPIO_LOG_LEVEL);
18
19 struct gpio_it8801_config {
20 /* gpio_driver_config needs to be first */
21 struct gpio_driver_config common;
22 /* IT8801 controller dev */
23 const struct device *mfd;
24 /* I2C device for the MFD parent */
25 const struct i2c_dt_spec i2c_dev;
26 /* GPIO input pin status register */
27 uint8_t reg_ipsr;
28 /* GPIO set output value register */
29 uint8_t reg_sovr;
30 /* GPIO control register */
31 uint8_t reg_gpcr;
32 /* GPIO interrupt status register */
33 uint8_t reg_gpisr;
34 /* GPIO interrupt enable register */
35 uint8_t reg_gpier;
36 uint8_t pin_mask;
37 };
38
39 struct gpio_it8801_data {
40 struct gpio_driver_data common;
41 struct it8801_mfd_callback it8801_gpio_callback;
42 sys_slist_t callbacks;
43 };
44
ioex_check_is_not_valid(const struct device * dev,gpio_pin_t pin)45 static int ioex_check_is_not_valid(const struct device *dev, gpio_pin_t pin)
46 {
47 const struct gpio_it8801_config *config = dev->config;
48
49 if (BIT(pin) & ~(config->pin_mask)) {
50 LOG_ERR("GPIO port%d-%d is not support", config->reg_ipsr, pin);
51 return -ENOTSUP;
52 }
53
54 return 0;
55 }
56
gpio_it8801_configure(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)57 static int gpio_it8801_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags)
58 {
59 const struct gpio_it8801_config *config = dev->config;
60 int ret;
61 uint8_t reg_gpcr = config->reg_gpcr + pin;
62 uint8_t mask = BIT(pin);
63 uint8_t new_value, control;
64
65 /* Don't support "open source" mode */
66 if (((flags & GPIO_SINGLE_ENDED) != 0) && ((flags & GPIO_LINE_OPEN_DRAIN) == 0)) {
67 return -ENOTSUP;
68 }
69
70 if (ioex_check_is_not_valid(dev, pin)) {
71 return -ENOTSUP;
72 }
73
74 ret = i2c_reg_read_byte_dt(&config->i2c_dev, reg_gpcr, &control);
75 if (ret) {
76 LOG_ERR("Failed to read control value (ret %d)", ret);
77 return ret;
78 }
79
80 if (flags == GPIO_DISCONNECTED) {
81 control &= ~(IT8801_GPIODIR | IT8801_GPIOPDE | IT8801_GPIOPUE);
82
83 goto write_and_return;
84 }
85
86 /* If output, set level before changing type to an output. */
87 if (flags & GPIO_OUTPUT) {
88 if (flags & GPIO_OUTPUT_INIT_HIGH) {
89 new_value = mask;
90 } else if (flags & GPIO_OUTPUT_INIT_LOW) {
91 new_value = 0;
92 } else {
93 new_value = 0;
94 }
95 ret = i2c_reg_update_byte_dt(&config->i2c_dev, config->reg_sovr, mask, new_value);
96 if (ret) {
97 LOG_ERR("Failed to set output value (ret %d)", ret);
98 return ret;
99 }
100 /* Set output */
101 control |= IT8801_GPIODIR;
102 /* Select open drain 0:push-pull 1:open-drain */
103 if (flags & GPIO_OPEN_DRAIN) {
104 control |= IT8801_GPIOIOT_OD;
105 } else {
106 control &= ~IT8801_GPIOIOT_OD;
107 }
108 } else {
109 /* Set input */
110 control &= ~IT8801_GPIODIR;
111 }
112
113 /* Handle pullup / pulldown */
114 if (flags & GPIO_PULL_UP) {
115 control = (control | IT8801_GPIOPUE) & ~IT8801_GPIOPDE;
116 } else if (flags & GPIO_PULL_DOWN) {
117 control = (control | IT8801_GPIOPDE) & ~IT8801_GPIOPUE;
118 } else {
119 /* No pull up/down */
120 control &= ~(IT8801_GPIOPUE | IT8801_GPIOPDE);
121 }
122
123 write_and_return:
124 /* Set GPIO control */
125 ret = i2c_reg_write_byte_dt(&config->i2c_dev, reg_gpcr, control);
126 if (ret) {
127 LOG_ERR("Failed to set control value (ret %d)", ret);
128 return ret;
129 }
130
131 return 0;
132 }
133
134 #ifdef CONFIG_GPIO_GET_CONFIG
gpio_it8801_get_config(const struct device * dev,gpio_pin_t pin,gpio_flags_t * out_flags)135 static int gpio_it8801_get_config(const struct device *dev, gpio_pin_t pin, gpio_flags_t *out_flags)
136 {
137 const struct gpio_it8801_config *config = dev->config;
138 gpio_flags_t flags = 0;
139 int ret;
140 uint8_t reg_gpcr = config->reg_gpcr + pin;
141 uint8_t mask = BIT(pin);
142 uint8_t control, value;
143
144 if (ioex_check_is_not_valid(dev, pin)) {
145 return -ENOTSUP;
146 }
147
148 ret = i2c_reg_read_byte_dt(&config->i2c_dev, reg_gpcr, &control);
149 if (ret) {
150 LOG_ERR("Failed to read control value (ret %d)", ret);
151 return ret;
152 }
153
154 /* Get GPIO direction */
155 if (control & IT8801_GPIODIR) {
156 flags |= GPIO_OUTPUT;
157
158 /* Get GPIO type, 0:push-pull 1:open-drain */
159 if (control & IT8801_GPIOIOT_OD) {
160 flags |= GPIO_OPEN_DRAIN;
161 }
162
163 ret = i2c_reg_read_byte_dt(&config->i2c_dev, config->reg_ipsr, &value);
164 if (ret) {
165 LOG_ERR("Failed to read pin status (ret %d)", ret);
166 return ret;
167 }
168
169 /* Get GPIO output level */
170 if (value & mask) {
171 flags |= GPIO_OUTPUT_HIGH;
172 } else {
173 flags |= GPIO_OUTPUT_LOW;
174 }
175 } else {
176 flags |= GPIO_INPUT;
177 }
178
179 /* pullup / pulldown */
180 if (control & IT8801_GPIOPUE) {
181 flags |= GPIO_PULL_UP;
182 } else if (control & IT8801_GPIOPDE) {
183 flags |= GPIO_PULL_DOWN;
184 }
185
186 *out_flags = flags;
187
188 return 0;
189 }
190 #endif
191
gpio_it8801_port_get_raw(const struct device * dev,gpio_port_value_t * value)192 static int gpio_it8801_port_get_raw(const struct device *dev, gpio_port_value_t *value)
193 {
194 const struct gpio_it8801_config *config = dev->config;
195 int ret;
196 uint8_t val;
197
198 /* Get raw bits of GPIO mirror register */
199 ret = i2c_reg_read_byte_dt(&config->i2c_dev, config->reg_ipsr, &val);
200 if (ret) {
201 LOG_ERR("Failed to get port mask (ret %d)", ret);
202 return ret;
203 }
204
205 *value = val;
206
207 return 0;
208 }
209
gpio_it8801_port_set_masked_raw(const struct device * dev,gpio_port_pins_t mask,gpio_port_value_t value)210 static int gpio_it8801_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask,
211 gpio_port_value_t value)
212 {
213 const struct gpio_it8801_config *config = dev->config;
214 int ret;
215
216 ret = i2c_reg_update_byte_dt(&config->i2c_dev, config->reg_sovr, mask, value);
217 if (ret) {
218 LOG_ERR("Failed to set port mask (ret %d)", ret);
219 return ret;
220 }
221
222 return 0;
223 }
224
gpio_it8801_port_set_bits_raw(const struct device * dev,gpio_port_pins_t pins)225 static int gpio_it8801_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins)
226 {
227 const struct gpio_it8801_config *config = dev->config;
228 int ret;
229
230 /* Set raw bits of GPIO data register */
231 ret = i2c_reg_update_byte_dt(&config->i2c_dev, config->reg_sovr, pins, pins);
232 if (ret) {
233 LOG_ERR("Failed to set bits raw (ret %d)", ret);
234 return ret;
235 }
236
237 return 0;
238 }
239
gpio_it8801_port_clear_bits_raw(const struct device * dev,gpio_port_pins_t pins)240 static int gpio_it8801_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins)
241 {
242 const struct gpio_it8801_config *config = dev->config;
243 int ret;
244
245 /* Clear raw bits of GPIO data register */
246 ret = i2c_reg_update_byte_dt(&config->i2c_dev, config->reg_sovr, pins, 0);
247 if (ret) {
248 LOG_ERR("Failed to clear bits raw (ret %d)", ret);
249 return ret;
250 }
251
252 return 0;
253 }
254
gpio_it8801_port_toggle_bits(const struct device * dev,gpio_port_pins_t pins)255 static int gpio_it8801_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins)
256 {
257 const struct gpio_it8801_config *config = dev->config;
258 int ret;
259 uint8_t val, new_val;
260
261 ret = i2c_reg_read_byte_dt(&config->i2c_dev, config->reg_sovr, &val);
262 if (ret) {
263 return ret;
264 }
265 /* Toggle raw bits of GPIO data register */
266 new_val = val ^ pins;
267 if (new_val != val) {
268 ret = i2c_reg_write_byte_dt(&config->i2c_dev, config->reg_sovr, new_val);
269 if (ret) {
270 LOG_ERR("Failed to write toggle value (ret %d)", ret);
271 return ret;
272 }
273 }
274
275 return 0;
276 }
277
gpio_it8801_manage_callback(const struct device * dev,struct gpio_callback * callback,bool set)278 static int gpio_it8801_manage_callback(const struct device *dev, struct gpio_callback *callback,
279 bool set)
280 {
281 struct gpio_it8801_data *data = dev->data;
282 int ret;
283
284 ret = gpio_manage_callback(&data->callbacks, callback, set);
285
286 return ret;
287 }
288
it8801_gpio_alert_handler(const struct device * dev)289 static void it8801_gpio_alert_handler(const struct device *dev)
290 {
291 const struct gpio_it8801_config *config = dev->config;
292 struct gpio_it8801_data *data = dev->data;
293 int ret;
294 uint8_t isr_val, ier_val;
295
296 ret = i2c_reg_read_byte_dt(&config->i2c_dev, config->reg_gpisr, &isr_val);
297 if (ret) {
298 LOG_ERR("Failed to read GPIO interrupt status (ret %d)", ret);
299 return;
300 }
301
302 ret = i2c_reg_read_byte_dt(&config->i2c_dev, config->reg_gpier, &ier_val);
303 if (ret) {
304 LOG_ERR("Failed to read GPIO interrupt pin set (ret %d)", ret);
305 return;
306 }
307
308 if (isr_val & ier_val) {
309 /* Clear pending interrupt */
310 ret = i2c_reg_write_byte_dt(&config->i2c_dev, config->reg_gpisr, isr_val);
311 if (ret) {
312 LOG_ERR("Failed to clear GPIO interrupt (ret %d)", ret);
313 return;
314 }
315
316 gpio_fire_callbacks(&data->callbacks, dev, isr_val);
317 }
318 }
319
gpio_it8801_pin_interrupt_configure(const struct device * dev,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)320 static int gpio_it8801_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin,
321 enum gpio_int_mode mode, enum gpio_int_trig trig)
322 {
323 const struct gpio_it8801_config *config = dev->config;
324 struct gpio_it8801_data *data = dev->data;
325 int ret;
326 uint8_t reg_gpcr = config->reg_gpcr + pin;
327 uint8_t control;
328 uint8_t mask = BIT(pin);
329
330 if (ioex_check_is_not_valid(dev, pin)) {
331 return -ENOTSUP;
332 }
333
334 /* Disable irq before configuring it */
335 ret = i2c_reg_update_byte_dt(&config->i2c_dev, config->reg_gpier, mask, 0);
336 if (ret) {
337 LOG_ERR("Failed to disable irq (ret %d)", ret);
338 return ret;
339 }
340
341 if (mode == GPIO_INT_MODE_DISABLED) {
342 return ret;
343 }
344
345 /* Set input pin */
346 ret = i2c_reg_update_byte_dt(&config->i2c_dev, reg_gpcr, IT8801_GPIODIR, 0);
347 if (ret) {
348 LOG_ERR("Failed to set input pin (ret %d)", ret);
349 return ret;
350 }
351
352 /* Clear trigger type */
353 ret = i2c_reg_update_byte_dt(&config->i2c_dev, reg_gpcr, GENMASK(4, 3), 0);
354 if (ret) {
355 LOG_ERR("Failed to clear trigger type (ret %d)", ret);
356 return ret;
357 }
358
359 ret = i2c_reg_read_byte_dt(&config->i2c_dev, reg_gpcr, &control);
360 if (ret) {
361 LOG_ERR("Failed to read gpio control (ret %d)", ret);
362 return ret;
363 }
364
365 if (mode == GPIO_INT_MODE_EDGE) {
366 /* Set edge trigger */
367 if ((trig & GPIO_INT_TRIG_BOTH) == GPIO_INT_TRIG_BOTH) {
368 control |= IT8801_GPIOIOT_INT_FALL | IT8801_GPIOIOT_INT_RISE;
369 } else if (trig & GPIO_INT_TRIG_LOW) {
370 control |= IT8801_GPIOIOT_INT_FALL;
371 } else if (trig & GPIO_INT_TRIG_HIGH) {
372 control |= IT8801_GPIOIOT_INT_RISE;
373 } else {
374 LOG_ERR("Invalid interrupt trigger type %d", trig);
375 return -EINVAL;
376 }
377 } else if (mode == GPIO_INT_MODE_LEVEL) {
378 /* Set level trigger */
379 if (trig & GPIO_INT_TRIG_LOW) {
380 control &= ~IT8801_GPIOPOL;
381 } else {
382 control |= IT8801_GPIOPOL;
383 }
384 }
385
386 /* Set control value */
387 ret = i2c_reg_write_byte_dt(&config->i2c_dev, reg_gpcr, control);
388 if (ret) {
389 LOG_ERR("Failed to write trigger state (ret %d)", ret);
390 return ret;
391 }
392
393 /* Clear pending interrupt */
394 ret = i2c_reg_update_byte_dt(&config->i2c_dev, config->reg_gpisr, mask, mask);
395 if (ret) {
396 LOG_ERR("Failed to clear pending interrupt (ret %d)", ret);
397 return ret;
398 }
399
400 /* Enable GPIO interrupt */
401 ret = i2c_reg_update_byte_dt(&config->i2c_dev, config->reg_gpier, mask, mask);
402 if (ret) {
403 LOG_ERR("Failed to enable interrupt (ret %d)", ret);
404 return ret;
405 }
406
407 /* Gather GPIO interrupt enable */
408 ret = i2c_reg_write_byte_dt(&config->i2c_dev, IT8801_REG_GIECR, IT8801_REG_MASK_GGPIOIE);
409
410 /* Register the interrupt of IT8801 MFD callback function */
411 data->it8801_gpio_callback.cb = it8801_gpio_alert_handler;
412 data->it8801_gpio_callback.dev = dev;
413 mfd_it8801_register_interrupt_callback(config->mfd, &data->it8801_gpio_callback);
414
415 return ret;
416 }
417
418 static DEVICE_API(gpio, gpio_it8801_driver_api) = {
419 .pin_configure = gpio_it8801_configure,
420 #ifdef CONFIG_GPIO_GET_CONFIG
421 .pin_get_config = gpio_it8801_get_config,
422 #endif
423 .port_get_raw = gpio_it8801_port_get_raw,
424 .port_set_masked_raw = gpio_it8801_port_set_masked_raw,
425 .port_set_bits_raw = gpio_it8801_port_set_bits_raw,
426 .port_clear_bits_raw = gpio_it8801_port_clear_bits_raw,
427 .port_toggle_bits = gpio_it8801_port_toggle_bits,
428 .pin_interrupt_configure = gpio_it8801_pin_interrupt_configure,
429 .manage_callback = gpio_it8801_manage_callback,
430 };
431
gpio_it8801_init(const struct device * dev)432 static int gpio_it8801_init(const struct device *dev)
433 {
434 const struct gpio_it8801_config *config = dev->config;
435
436 /* Verify multi-function parent is ready */
437 if (!device_is_ready(config->mfd)) {
438 LOG_ERR("(gpio)%s is not ready", config->mfd->name);
439 return -ENODEV;
440 }
441
442 return 0;
443 }
444
445 #define GPIO_IT8801_DEVICE_INST(inst) \
446 static struct gpio_it8801_data gpio_it8801_data_##inst; \
447 static const struct gpio_it8801_config gpio_it8801_cfg_##inst = { \
448 .common = {.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(inst)}, \
449 .mfd = DEVICE_DT_GET(DT_INST_PARENT(inst)), \
450 .i2c_dev = I2C_DT_SPEC_GET(DT_INST_PARENT(inst)), \
451 .reg_ipsr = DT_INST_REG_ADDR_BY_IDX(inst, 0), \
452 .reg_sovr = DT_INST_REG_ADDR_BY_IDX(inst, 1), \
453 .reg_gpcr = DT_INST_REG_ADDR_BY_IDX(inst, 2), \
454 .reg_gpisr = DT_INST_REG_ADDR_BY_IDX(inst, 3), \
455 .reg_gpier = DT_INST_REG_ADDR_BY_IDX(inst, 4), \
456 .pin_mask = DT_INST_PROP(inst, pin_mask), \
457 }; \
458 DEVICE_DT_INST_DEFINE(inst, gpio_it8801_init, NULL, &gpio_it8801_data_##inst, \
459 &gpio_it8801_cfg_##inst, POST_KERNEL, CONFIG_MFD_INIT_PRIORITY, \
460 &gpio_it8801_driver_api);
461
462 DT_INST_FOREACH_STATUS_OKAY(GPIO_IT8801_DEVICE_INST)
463