1 /*
2  * Copyright (c) 2021 Nuvoton Technology Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_DRIVERS_GPIO_GPIO_NCT38XX_H_
8 #define ZEPHYR_DRIVERS_GPIO_GPIO_NCT38XX_H_
9 
10 #include <zephyr/device.h>
11 #include <zephyr/drivers/gpio.h>
12 #include <zephyr/drivers/i2c.h>
13 #include <zephyr/kernel.h>
14 
15 /* NCT38XX controller register */
16 #define NCT38XX_REG_ALERT      0x10
17 #define NCT38XX_REG_ALERT_MASK 0x12
18 
19 #define NCT38XX_REG_GPIO_DATA_IN(n)     (0xC0 + ((n) * 8))
20 #define NCT38XX_REG_GPIO_DATA_OUT(n)    (0xC1 + ((n) * 8))
21 #define NCT38XX_REG_GPIO_DIR(n)         (0xC2 + ((n) * 8))
22 #define NCT38XX_REG_GPIO_OD_SEL(n)      (0xC3 + ((n) * 8))
23 #define NCT38XX_REG_GPIO_ALERT_RISE(n)  (0xC4 + ((n) * 8))
24 #define NCT38XX_REG_GPIO_ALERT_FALL(n)  (0xC5 + ((n) * 8))
25 #define NCT38XX_REG_GPIO_ALERT_LEVEL(n) (0xC6 + ((n) * 8))
26 #define NCT38XX_REG_GPIO_ALERT_MASK(n)  (0xC7 + ((n) * 8))
27 #define NCT38XX_REG_MUX_CONTROL         0xD0
28 #define NCT38XX_REG_GPIO_ALERT_STAT(n)  (0xD4 + (n))
29 
30 /* NCT38XX controller register field */
31 #define NCT38XX_REG_ALERT_VENDOR_DEFINDED_ALERT      15
32 #define NCT38XX_REG_ALERT_MASK_VENDOR_DEFINDED_ALERT 15
33 
34 /* Driver config */
35 struct gpio_nct38xx_config {
36 	/* I2C device */
37 	const struct i2c_dt_spec i2c_dev;
38 	/* GPIO ports */
39 	const struct device **sub_gpio_dev;
40 	uint8_t sub_gpio_port_num;
41 	/* Alert handler */
42 	const struct device *alert_dev;
43 };
44 
45 /* Driver data */
46 struct gpio_nct38xx_data {
47 	/* NCT38XX device */
48 	const struct device *dev;
49 };
50 
51 /**
52  * @brief Read a NCT38XX register
53  *
54  * @param dev NCT38XX device
55  * @param reg_addr Register address
56  * @param val A pointer to a buffer for the data to return
57  *
58  * @return 0 if successful, otherwise failed.
59  */
nct38xx_reg_read_byte(const struct device * dev,uint8_t reg_addr,uint8_t * val)60 static inline int nct38xx_reg_read_byte(const struct device *dev, uint8_t reg_addr, uint8_t *val)
61 {
62 	const struct gpio_nct38xx_config *const config =
63 		(const struct gpio_nct38xx_config *)dev->config;
64 	return i2c_reg_read_byte_dt(&config->i2c_dev, reg_addr, val);
65 }
66 
67 /**
68  * @brief Read a sequence of NCT38XX registers
69  *
70  * @param dev NCT38XX device
71  * @param start_addr The register start address
72  * @param buf A pointer to a buffer for the data to return
73  * @param num_bytes Number of data to read
74  *
75  * @return 0 if successful, otherwise failed.
76  */
nct38xx_reg_burst_read(const struct device * dev,uint8_t start_addr,uint8_t * buf,uint32_t num_bytes)77 static inline int nct38xx_reg_burst_read(const struct device *dev, uint8_t start_addr, uint8_t *buf,
78 					 uint32_t num_bytes)
79 {
80 	const struct gpio_nct38xx_config *const config =
81 		(const struct gpio_nct38xx_config *)dev->config;
82 	return i2c_burst_read_dt(&config->i2c_dev, start_addr, buf, num_bytes);
83 }
84 
85 /**
86  * @brief Write a NCT38XX register
87  *
88  * @param dev NCT38XX device
89  * @param reg_addr Register address
90  * @param val Data to write
91  *
92  * @return 0 if successful, otherwise failed.
93  */
nct38xx_reg_write_byte(const struct device * dev,uint8_t reg_addr,uint8_t val)94 static inline int nct38xx_reg_write_byte(const struct device *dev, uint8_t reg_addr, uint8_t val)
95 {
96 	const struct gpio_nct38xx_config *const config =
97 		(const struct gpio_nct38xx_config *)dev->config;
98 	return i2c_reg_write_byte_dt(&config->i2c_dev, reg_addr, val);
99 }
100 
101 /**
102  * @brief Write a sequence of NCT38XX registers
103  *
104  * @param dev NCT38XX device
105  * @param start_addr The register start address
106  * @param buf A pointer to a buffer for the data to write
107  * @param num_bytes Number of data to write
108  *
109  * @return 0 if successful, otherwise failed.
110  */
nct38xx_reg_burst_write(const struct device * dev,uint8_t start_addr,uint8_t * buf,uint32_t num_bytes)111 static inline int nct38xx_reg_burst_write(const struct device *dev, uint8_t start_addr,
112 					  uint8_t *buf, uint32_t num_bytes)
113 {
114 	const struct gpio_nct38xx_config *const config =
115 		(const struct gpio_nct38xx_config *)dev->config;
116 	return i2c_burst_write_dt(&config->i2c_dev, start_addr, buf, num_bytes);
117 }
118 
119 /**
120  * @brief Compare data & write a NCT38XX register
121  *
122  * @param dev NCT38XX device
123  * @param reg_addr Register address
124  * @param reg_val Old register data
125  * @param new_val New register data
126  *
127  * @return 0 if successful, otherwise failed.
128  */
nct38xx_reg_update(const struct device * dev,uint8_t reg_addr,uint8_t reg_val,uint8_t new_val)129 static inline int nct38xx_reg_update(const struct device *dev, uint8_t reg_addr, uint8_t reg_val,
130 				     uint8_t new_val)
131 {
132 	if (reg_val == new_val)
133 		return 0;
134 
135 	return nct38xx_reg_write_byte(dev, reg_addr, new_val);
136 }
137 
138 /**
139  * @brief Dispatch GPIO port ISR
140  *
141  * @param dev GPIO port device
142  * @return 0 if successful, otherwise failed.
143  */
144 int gpio_nct38xx_dispatch_port_isr(const struct device *dev);
145 
146 #endif /* ZEPHYR_DRIVERS_GPIO_GPIO_NCT38XX_H_*/
147