1 /*
2  * Copyright (c) 2021 Titouan Christophe
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT st_stmpe1600
8 
9 /**
10  * @file Driver for STMPE1600 I2C-based GPIO driver.
11  */
12 #include <errno.h>
13 
14 #include <zephyr/kernel.h>
15 #include <zephyr/device.h>
16 #include <zephyr/init.h>
17 #include <zephyr/sys/byteorder.h>
18 #include <zephyr/sys/util.h>
19 #include <zephyr/drivers/gpio.h>
20 #include <zephyr/drivers/i2c.h>
21 
22 #include <zephyr/drivers/gpio/gpio_utils.h>
23 
24 #define LOG_LEVEL CONFIG_GPIO_LOG_LEVEL
25 #include <zephyr/logging/log.h>
26 LOG_MODULE_REGISTER(stmpe1600);
27 
28 /* Register definitions */
29 #define REG_CHIP_ID_LSB 0x00    /* const 0x00 */
30 #define REG_CHIP_ID_MSB 0x01    /* const 0x16 */
31 #define REG_VERSION_ID  0x02    /* Revision number (const 0x01) */
32 #define REG_SYS_CTRL    0x03    /* Reset and interrupt control */
33 #define REG_IEGPIOR_LSB 0x08    /* GPIO interrupt enable register */
34 #define REG_IEGPIOR_MSB 0x09
35 #define REG_ISGPIOR_LSB 0x0A    /* GPIO interrupt status register */
36 #define REG_ISGPIOR_MSB 0x0B
37 #define REG_GPMR_LSB    0x10    /* GPIO monitor pin state register */
38 #define REG_GPMR_MSB    0x11
39 #define REG_GPSR_LSB    0x12    /* GPIO set pin state register */
40 #define REG_GPSR_MSB    0x13
41 #define REG_GPDR_LSB    0x14    /* GPIO set pin direction register */
42 #define REG_GPDR_MSB    0x15
43 #define REG_GPPIR_LSB   0x16    /* GPIO polarity inversion register */
44 #define REG_GPPIR_MSB   0x17
45 
46 
47 /** Configuration data */
48 struct stmpe1600_config {
49 	/* gpio_driver_config needs to be first */
50 	struct gpio_driver_config common;
51 
52 	/** Master I2C DT specification */
53 	struct i2c_dt_spec i2c;
54 };
55 
56 /** Runtime driver data */
57 struct stmpe1600_drvdata {
58 	/* gpio_driver_data needs to be first */
59 	struct gpio_driver_data common;
60 
61 	/** Driver lock */
62 	struct k_sem lock;
63 
64 	/* Registers cache */
65 	uint16_t GPSR;
66 	uint16_t GPDR;
67 };
68 
write_reg16(const struct stmpe1600_config * const config,uint8_t reg,uint16_t value)69 static int write_reg16(const struct stmpe1600_config * const config, uint8_t reg, uint16_t value)
70 {
71 	uint8_t buf[3];
72 	int ret;
73 
74 	LOG_DBG("STMPE1600[0x%02X]: write REG[0x%02X..0x%02X] = %04x",
75 		config->i2c.addr, reg, reg + 1, value);
76 
77 	buf[0] = reg;
78 	sys_put_le16(value, &buf[1]);
79 
80 	ret = i2c_write_dt(&config->i2c, buf, sizeof(buf));
81 
82 	if (ret != 0) {
83 		LOG_ERR("STMPE1600[0x%02X]: write error REG[0x%02X..0x%02X]: %d",
84 			config->i2c.addr, reg, reg + 1, ret);
85 	}
86 	return ret;
87 }
88 
read_reg16(const struct stmpe1600_config * const config,uint8_t reg,uint16_t * value)89 static int read_reg16(const struct stmpe1600_config * const config, uint8_t reg, uint16_t *value)
90 {
91 	uint16_t transfer_data;
92 	int ret;
93 
94 	LOG_DBG("STMPE1600[0x%02X]: read REG[0x%02X..0x%02X]",
95 		  config->i2c.addr, reg, reg + 1);
96 
97 	ret = i2c_burst_read_dt(&config->i2c, reg, (uint8_t *)&transfer_data,
98 				sizeof(transfer_data));
99 
100 	if (ret != 0) {
101 		LOG_ERR("STMPE1600[0x%02X]: read error REG[0x%02X..0x%02X]: %d",
102 			config->i2c.addr, reg, reg + 1, ret);
103 	} else {
104 		*value = sys_le16_to_cpu(transfer_data);
105 		LOG_DBG("STMPE1600[0x%02X]: read REG[0x%02X..0x%02X] => %04x",
106 			config->i2c.addr, reg, reg + 1, *value);
107 	}
108 	return ret;
109 }
110 
set_pin_dir(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)111 static int set_pin_dir(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags)
112 {
113 	struct stmpe1600_drvdata *const drvdata = (struct stmpe1600_drvdata *const) dev->data;
114 	bool set_state = false;
115 	uint16_t GPDR = drvdata->GPDR;
116 	uint16_t GPSR = drvdata->GPSR;
117 	int ret;
118 
119 	if ((flags & GPIO_OUTPUT) != 0U) {
120 		GPDR |= BIT(pin);
121 		if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0U) {
122 			GPSR |= BIT(pin);
123 			set_state = true;
124 		} else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0U) {
125 			GPSR &= ~BIT(pin);
126 			set_state = true;
127 		}
128 	} else {
129 		GPDR &= ~BIT(pin);
130 	}
131 
132 	if (set_state) {
133 		ret = write_reg16(dev->config, REG_GPSR_LSB, GPSR);
134 		if (ret != 0) {
135 			return ret;
136 		}
137 		drvdata->GPSR = GPSR;
138 	}
139 
140 	ret = write_reg16(dev->config, REG_GPDR_LSB, GPDR);
141 	if (ret == 0) {
142 		drvdata->GPDR = GPDR;
143 	}
144 	return ret;
145 }
146 
stmpe1600_configure(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)147 static int stmpe1600_configure(const struct device *dev,
148 			       gpio_pin_t pin, gpio_flags_t flags)
149 {
150 	const struct stmpe1600_config *const config = dev->config;
151 	struct stmpe1600_drvdata *const drvdata = (struct stmpe1600_drvdata *const) dev->data;
152 	int ret;
153 
154 	/* No support for disconnected pin */
155 	if ((flags & (GPIO_INPUT | GPIO_OUTPUT)) == GPIO_DISCONNECTED) {
156 		return -ENOTSUP;
157 	}
158 
159 	/* STMPE1600 does not support any of these modes */
160 	if ((flags & (GPIO_SINGLE_ENDED | GPIO_PULL_UP | GPIO_PULL_DOWN)) != 0) {
161 		return -ENOTSUP;
162 	}
163 
164 	if (k_is_in_isr()) {
165 		return -EWOULDBLOCK;
166 	}
167 
168 	k_sem_take(&drvdata->lock, K_FOREVER);
169 
170 	ret = set_pin_dir(dev, pin, flags);
171 	if (ret != 0) {
172 		LOG_ERR("STMPE1600[0x%X]: error setting pin direction (%d)",
173 			config->i2c.addr, ret);
174 	}
175 
176 	k_sem_give(&drvdata->lock);
177 	return ret;
178 }
179 
stmpe1600_port_get_raw(const struct device * dev,uint32_t * value)180 static int stmpe1600_port_get_raw(const struct device *dev, uint32_t *value)
181 {
182 	struct stmpe1600_drvdata *const drvdata = (struct stmpe1600_drvdata *const) dev->data;
183 	uint16_t reg_value;
184 	int ret;
185 
186 	if (k_is_in_isr()) {
187 		return -EWOULDBLOCK;
188 	}
189 
190 	k_sem_take(&drvdata->lock, K_FOREVER);
191 	ret = read_reg16(dev->config, REG_GPMR_LSB, &reg_value);
192 	k_sem_give(&drvdata->lock);
193 
194 	if (ret == 0) {
195 		*value = reg_value;
196 	}
197 
198 	return ret;
199 }
200 
stmpe1600_port_set_masked_raw(const struct device * dev,uint32_t mask,uint32_t value)201 static int stmpe1600_port_set_masked_raw(const struct device *dev,
202 					 uint32_t mask, uint32_t value)
203 {
204 	struct stmpe1600_drvdata *const drvdata = dev->data;
205 	uint16_t GPSR;
206 	int ret;
207 
208 	if (k_is_in_isr()) {
209 		return -EWOULDBLOCK;
210 	}
211 
212 	k_sem_take(&drvdata->lock, K_FOREVER);
213 	GPSR = (drvdata->GPSR & ~mask) | (mask & value);
214 	ret = write_reg16(dev->config, REG_GPSR_LSB, GPSR);
215 	if (ret == 0) {
216 		drvdata->GPSR = GPSR;
217 	}
218 	k_sem_give(&drvdata->lock);
219 
220 	return ret;
221 }
222 
stmpe1600_port_set_bits_raw(const struct device * dev,uint32_t mask)223 static int stmpe1600_port_set_bits_raw(const struct device *dev, uint32_t mask)
224 {
225 	return stmpe1600_port_set_masked_raw(dev, mask, mask);
226 }
227 
stmpe1600_port_clear_bits_raw(const struct device * dev,uint32_t mask)228 static int stmpe1600_port_clear_bits_raw(const struct device *dev, uint32_t mask)
229 {
230 	return stmpe1600_port_set_masked_raw(dev, mask, 0);
231 }
232 
stmpe1600_port_toggle_bits(const struct device * dev,uint32_t mask)233 static int stmpe1600_port_toggle_bits(const struct device *dev, uint32_t mask)
234 {
235 	struct stmpe1600_drvdata *const drvdata = dev->data;
236 	uint16_t GPSR;
237 	int ret;
238 
239 	if (k_is_in_isr()) {
240 		return -EWOULDBLOCK;
241 	}
242 	k_sem_take(&drvdata->lock, K_FOREVER);
243 	GPSR = drvdata->GPSR ^ mask;
244 	ret = write_reg16(dev->config, REG_GPSR_LSB, GPSR);
245 	if (ret == 0) {
246 		drvdata->GPSR = GPSR;
247 	}
248 	k_sem_give(&drvdata->lock);
249 	return ret;
250 }
251 
stmpe1600_init(const struct device * dev)252 static int stmpe1600_init(const struct device *dev)
253 {
254 	const struct stmpe1600_config *const config = dev->config;
255 	struct stmpe1600_drvdata *const drvdata = (struct stmpe1600_drvdata *const) dev->data;
256 	uint16_t chip_id;
257 	int ret;
258 
259 	LOG_DBG("STMPE1600[0x%02X] init", config->i2c.addr);
260 
261 	k_sem_init(&drvdata->lock, 1, 1);
262 
263 	ret = read_reg16(dev->config, REG_CHIP_ID_LSB, &chip_id);
264 	if (ret != 0) {
265 		LOG_ERR("STMPE1600[0x%02X]: Unable to read Chip ID", config->i2c.addr);
266 		return ret;
267 	}
268 
269 	if (chip_id != 0x1600) {
270 		LOG_ERR("STMPE1600[0x%02X]: Invalid Chip ID", config->i2c.addr);
271 		return -EINVAL;
272 	}
273 
274 	ret = read_reg16(dev->config, REG_GPSR_LSB, &drvdata->GPSR);
275 	if (ret != 0) {
276 		LOG_ERR("STMPE1600[0x%02X]: Unable to read GPSR", config->i2c.addr);
277 		return ret;
278 	}
279 
280 	ret = read_reg16(dev->config, REG_GPDR_LSB, &drvdata->GPDR);
281 	if (ret != 0) {
282 		LOG_ERR("STMPE1600[0x%02X]: Unable to read GPDR", config->i2c.addr);
283 	}
284 
285 	return ret;
286 }
287 
288 static const struct gpio_driver_api stmpe1600_drv_api = {
289 	.pin_configure = stmpe1600_configure,
290 	.port_get_raw = stmpe1600_port_get_raw,
291 	.port_set_masked_raw = stmpe1600_port_set_masked_raw,
292 	.port_set_bits_raw = stmpe1600_port_set_bits_raw,
293 	.port_clear_bits_raw = stmpe1600_port_clear_bits_raw,
294 	.port_toggle_bits = stmpe1600_port_toggle_bits,
295 };
296 
297 #define STMPE1600_INIT(inst)					     \
298 	static struct stmpe1600_config stmpe1600_##inst##_config = { \
299 		.common = { .port_pin_mask = 0xffff },		     \
300 		.i2c = I2C_DT_SPEC_INST_GET(inst),		     \
301 	};							     \
302 								     \
303 	static struct stmpe1600_drvdata stmpe1600_##inst##_drvdata;  \
304 								     \
305 	DEVICE_DT_INST_DEFINE(inst, stmpe1600_init, NULL,	     \
306 			      &stmpe1600_##inst##_drvdata,	     \
307 			      &stmpe1600_##inst##_config,	     \
308 			      POST_KERNEL,			     \
309 			      CONFIG_GPIO_STMPE1600_INIT_PRIORITY,   \
310 			      &stmpe1600_drv_api);
311 
312 DT_INST_FOREACH_STATUS_OKAY(STMPE1600_INIT)
313