1 /*
2  * Copyright (c) 2024 ENE Technology Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT ene_kb1200_i2c
8 
9 #include <zephyr/kernel.h>
10 #include <zephyr/drivers/i2c.h>
11 #include <zephyr/drivers/pinctrl.h>
12 #include <errno.h>
13 #include <reg/fsmbm.h>
14 
15 struct i2c_kb1200_config {
16 	struct fsmbm_regs *fsmbm;
17 	const struct pinctrl_dev_config *pcfg;
18 };
19 
20 struct i2c_kb1200_data {
21 	struct k_sem mutex;
22 	volatile uint8_t *msg_buf;
23 	volatile uint32_t msg_len;
24 	volatile uint8_t msg_flags;
25 	volatile int state;
26 	volatile uint32_t index;
27 	volatile int err_code;
28 };
29 
30 /* I2C Master local functions */
i2c_kb1200_isr(const struct device * dev)31 static void i2c_kb1200_isr(const struct device *dev)
32 {
33 	const struct i2c_kb1200_config *config = dev->config;
34 	struct i2c_kb1200_data *data = dev->data;
35 
36 	if (data->state == STATE_SENDING) {
37 		if (config->fsmbm->FSMBMPF & FSMBM_BLOCK_FINISH_EVENT) {
38 			/* continue block */
39 			uint32_t remain = data->msg_len - data->index;
40 			uint32_t send_bytes =
41 				remain > FSMBM_BUFFER_SIZE ? FSMBM_BUFFER_SIZE : remain;
42 			memcpy((void *)&config->fsmbm->FSMBMDAT[0],
43 			       (void *)&data->msg_buf[data->index], send_bytes);
44 			data->index += send_bytes;
45 			/* Increase CNT setting let hw can't match counter */
46 			config->fsmbm->FSMBMPRTC_C += send_bytes;
47 			/* If it was the last protocol recover the correct length value*/
48 			if (data->msg_len == data->index) {
49 				config->fsmbm->FSMBMPRTC_C -= 1;
50 			}
51 			config->fsmbm->FSMBMPF = FSMBM_BLOCK_FINISH_EVENT;
52 		} else if (config->fsmbm->FSMBMPF & FSMBM_COMPLETE_EVENT) {
53 			/* complete */
54 			if (((config->fsmbm->FSMBMSTS & FSMBM_STS_MASK) == FSMBM_SMBUS_BUSY) &&
55 			    ((config->fsmbm->FSMBMFRT & ___STOP) == ___NONE)) {
56 				/* while packet finish without STOP, the error message is
57 				 * FSMBM_SMBUS_BUSY
58 				 */
59 				data->err_code = 0;
60 			} else {
61 				data->err_code = config->fsmbm->FSMBMSTS & FSMBM_STS_MASK;
62 			}
63 			data->state = STATE_COMPLETE;
64 			config->fsmbm->FSMBMPF = FSMBM_COMPLETE_EVENT;
65 		} else {
66 			data->err_code = config->fsmbm->FSMBMSTS & FSMBM_STS_MASK;
67 			data->state = STATE_COMPLETE;
68 		}
69 	} else if (data->state == STATE_RECEIVING) {
70 		uint32_t remain = data->msg_len - data->index;
71 		uint32_t receive_bytes = (remain > FSMBM_BUFFER_SIZE) ? FSMBM_BUFFER_SIZE : remain;
72 
73 		memcpy((void *)&data->msg_buf[data->index], (void *)&config->fsmbm->FSMBMDAT[0],
74 		       receive_bytes);
75 		data->index += receive_bytes;
76 		if (config->fsmbm->FSMBMPF & FSMBM_BLOCK_FINISH_EVENT) {
77 			/* continue block */
78 			/* Check next protocl information */
79 			remain = data->msg_len - data->index;
80 			uint32_t NextLen =
81 				(remain > FSMBM_BUFFER_SIZE) ? FSMBM_BUFFER_SIZE : remain;
82 			/* Increase CNT setting let hw can't match counter */
83 			config->fsmbm->FSMBMPRTC_C += NextLen;
84 			/* If it was the last protocol recover the correct length value */
85 			if (data->msg_len == (data->index + NextLen)) {
86 				config->fsmbm->FSMBMPRTC_C -= 1;
87 			}
88 			config->fsmbm->FSMBMPF = FSMBM_BLOCK_FINISH_EVENT;
89 		} else if (config->fsmbm->FSMBMPF & FSMBM_COMPLETE_EVENT) {
90 			/* complete */
91 			if (((config->fsmbm->FSMBMSTS & FSMBM_STS_MASK) == FSMBM_SMBUS_BUSY) &&
92 			    ((config->fsmbm->FSMBMFRT & ___STOP) == ___NONE)) {
93 				/* while packet finish without STOP, the error message is
94 				 * FSMBM_SMBUS_BUSY
95 				 */
96 				data->err_code = 0;
97 			} else {
98 				data->err_code = config->fsmbm->FSMBMSTS & FSMBM_STS_MASK;
99 			}
100 			data->state = STATE_COMPLETE;
101 			config->fsmbm->FSMBMPF = FSMBM_COMPLETE_EVENT;
102 		} else {
103 			data->err_code = config->fsmbm->FSMBMSTS & FSMBM_STS_MASK;
104 			data->state = STATE_COMPLETE;
105 		}
106 	} else if (data->state == STATE_COMPLETE) {
107 		config->fsmbm->FSMBMPF = (FSMBM_COMPLETE_EVENT | FSMBM_BLOCK_FINISH_EVENT);
108 	}
109 }
110 
i2c_kb1200_poll_write(const struct device * dev,struct i2c_msg msg,uint16_t addr)111 static int i2c_kb1200_poll_write(const struct device *dev, struct i2c_msg msg, uint16_t addr)
112 {
113 	const struct i2c_kb1200_config *config = dev->config;
114 	struct i2c_kb1200_data *data = dev->data;
115 	uint8_t send_bytes;
116 
117 	if (msg.flags & I2C_MSG_STOP) {
118 		/* No CMD, No CNT, No PEC, with STOP*/
119 		config->fsmbm->FSMBMFRT = ___STOP;
120 	} else {
121 		/* No CMD, No CNT, No PEC, no STOP*/
122 		config->fsmbm->FSMBMFRT = ___NONE;
123 	}
124 	data->msg_len = msg.len;
125 	data->msg_buf = msg.buf;
126 	data->msg_flags = msg.flags;
127 	data->state = STATE_IDLE;
128 	data->index = 0;
129 	data->err_code = 0;
130 
131 	send_bytes = (msg.len > FSMBM_BUFFER_SIZE) ? FSMBM_BUFFER_SIZE : msg.len;
132 	memcpy((void *)&config->fsmbm->FSMBMDAT[0], (void *)&data->msg_buf[data->index],
133 	       send_bytes);
134 	data->index += send_bytes;
135 	data->state = STATE_SENDING;
136 
137 	config->fsmbm->FSMBMCMD = 0;
138 	config->fsmbm->FSMBMADR = (addr & ~BIT(0)) | FSMBM_WRITE;
139 	config->fsmbm->FSMBMPF = (FSMBM_COMPLETE_EVENT | FSMBM_BLOCK_FINISH_EVENT);
140 	/* If data over bufferSize increase 1 to force continue transmit */
141 	if (msg.len >= (FSMBM_BUFFER_SIZE + 1)) {
142 		config->fsmbm->FSMBMPRTC_C = FSMBM_BUFFER_SIZE + 1;
143 	} else {
144 		config->fsmbm->FSMBMPRTC_C = send_bytes;
145 	}
146 	config->fsmbm->FSMBMIE = (FSMBM_COMPLETE_EVENT | FSMBM_BLOCK_FINISH_EVENT);
147 	config->fsmbm->FSMBMPRTC_P = FLEXIBLE_PROTOCOL;
148 	while (data->state != STATE_COMPLETE) {
149 		;
150 	}
151 	data->state = STATE_IDLE;
152 	if (data->err_code != 0) {
153 		/* reset HW  */
154 		config->fsmbm->FSMBMCFG |= FSMBM_HW_RESET;
155 		return data->err_code;
156 	}
157 	return 0;
158 }
159 
i2c_kb1200_poll_read(const struct device * dev,struct i2c_msg msg,uint16_t addr)160 static int i2c_kb1200_poll_read(const struct device *dev, struct i2c_msg msg, uint16_t addr)
161 {
162 	const struct i2c_kb1200_config *config = dev->config;
163 	struct i2c_kb1200_data *data = dev->data;
164 
165 	if (msg.flags & I2C_MSG_STOP) {
166 		/* No CMD, No CNT, No PEC, with STOP*/
167 		config->fsmbm->FSMBMFRT = ___STOP;
168 	} else {
169 		/* No CMD, No CNT, No PEC, no STOP*/
170 		config->fsmbm->FSMBMFRT = ___NONE;
171 	}
172 	data->msg_len = msg.len;
173 	data->msg_buf = msg.buf;
174 	data->msg_flags = msg.flags;
175 	data->state = STATE_IDLE;
176 	data->index = 0;
177 	data->err_code = 0;
178 	data->state = STATE_RECEIVING;
179 
180 	config->fsmbm->FSMBMCMD = 0;
181 	config->fsmbm->FSMBMADR = (addr & ~BIT(0)) | FSMBM_READ;
182 	config->fsmbm->FSMBMPF = (FSMBM_COMPLETE_EVENT | FSMBM_BLOCK_FINISH_EVENT);
183 	/* If data over bufferSize increase 1 to force continue receive */
184 	if (msg.len >= (FSMBM_BUFFER_SIZE + 1)) {
185 		config->fsmbm->FSMBMPRTC_C = FSMBM_BUFFER_SIZE + 1;
186 	} else {
187 		config->fsmbm->FSMBMPRTC_C = msg.len;
188 	}
189 	config->fsmbm->FSMBMIE = (FSMBM_COMPLETE_EVENT | FSMBM_BLOCK_FINISH_EVENT);
190 	config->fsmbm->FSMBMPRTC_P = FLEXIBLE_PROTOCOL;
191 	while (data->state != STATE_COMPLETE) {
192 		;
193 	}
194 	data->state = STATE_IDLE;
195 	if (data->err_code != 0) {
196 		/* reset HW  */
197 		config->fsmbm->FSMBMCFG |= FSMBM_HW_RESET;
198 		return data->err_code;
199 	}
200 	return 0;
201 }
202 
203 /* I2C Master api functions */
i2c_kb1200_configure(const struct device * dev,uint32_t dev_config)204 static int i2c_kb1200_configure(const struct device *dev, uint32_t dev_config)
205 {
206 	const struct i2c_kb1200_config *config = dev->config;
207 
208 	if (!(dev_config & I2C_MODE_CONTROLLER)) {
209 		return -ENOTSUP;
210 	}
211 
212 	if (dev_config & I2C_ADDR_10_BITS) {
213 		return -ENOTSUP;
214 	}
215 
216 	uint32_t speed = I2C_SPEED_GET(dev_config);
217 
218 	switch (speed) {
219 	case I2C_SPEED_STANDARD:
220 		config->fsmbm->FSMBMCFG = (FSMBM_CLK_100K << FSMBM_CLK_POS);
221 		break;
222 	case I2C_SPEED_FAST:
223 		config->fsmbm->FSMBMCFG = (FSMBM_CLK_400K << FSMBM_CLK_POS);
224 		break;
225 	case I2C_SPEED_FAST_PLUS:
226 		config->fsmbm->FSMBMCFG = (FSMBM_CLK_1M << FSMBM_CLK_POS);
227 		break;
228 	default:
229 		return -EINVAL;
230 	}
231 
232 	config->fsmbm->FSMBMPF = (FSMBM_COMPLETE_EVENT | FSMBM_BLOCK_FINISH_EVENT);
233 	config->fsmbm->FSMBMIE = (FSMBM_COMPLETE_EVENT | FSMBM_BLOCK_FINISH_EVENT);
234 	/* HW reset, Enable FSMBM function, Timeout function*/
235 	config->fsmbm->FSMBMCFG |= FSMBM_HW_RESET | FSMBM_TIMEOUT_ENABLE | FSMBM_FUNCTION_ENABLE;
236 
237 	return 0;
238 }
239 
i2c_kb1200_get_config(const struct device * dev,uint32_t * dev_config)240 static int i2c_kb1200_get_config(const struct device *dev, uint32_t *dev_config)
241 {
242 	const struct i2c_kb1200_config *config = dev->config;
243 
244 	if ((config->fsmbm->FSMBMCFG & FSMBM_FUNCTION_ENABLE) == 0x00) {
245 		printk("Cannot find i2c controller on 0x%p!\n", config->fsmbm);
246 		return -EIO;
247 	}
248 
249 	switch ((config->fsmbm->FSMBMCFG >> FSMBM_CLK_POS) & FSMBM_CLK_MASK) {
250 	case FSMBM_CLK_100K:
251 		*dev_config = I2C_MODE_CONTROLLER | I2C_SPEED_SET(I2C_SPEED_STANDARD);
252 		break;
253 	case FSMBM_CLK_400K:
254 		*dev_config = I2C_MODE_CONTROLLER | I2C_SPEED_SET(I2C_SPEED_FAST);
255 		break;
256 	case FSMBM_CLK_1M:
257 		*dev_config = I2C_MODE_CONTROLLER | I2C_SPEED_SET(I2C_SPEED_FAST_PLUS);
258 		break;
259 	default:
260 		return -ERANGE;
261 	}
262 
263 	return 0;
264 }
265 
i2c_kb1200_transfer(const struct device * dev,struct i2c_msg * msgs,uint8_t num_msgs,uint16_t addr)266 static int i2c_kb1200_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs,
267 			       uint16_t addr)
268 {
269 	struct i2c_kb1200_data *data = dev->data;
270 	int ret;
271 
272 	/* get the mutex */
273 	k_sem_take(&data->mutex, K_FOREVER);
274 	for (int i = 0U; i < num_msgs; i++) {
275 		if ((msgs[i].flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) {
276 			ret = i2c_kb1200_poll_write(dev, msgs[i], addr);
277 			if (ret) {
278 				printk("%s Write error: 0x%X\n", dev->name, ret);
279 				break;
280 			}
281 		} else {
282 			ret = i2c_kb1200_poll_read(dev, msgs[i], addr);
283 			if (ret) {
284 				printk("%s Read error: 0x%X\n", dev->name, ret);
285 				break;
286 			}
287 		}
288 	}
289 	/* release the mutex */
290 	k_sem_give(&data->mutex);
291 
292 	return ret;
293 }
294 
295 /* I2C Master driver registration */
296 static DEVICE_API(i2c, i2c_kb1200_api) = {
297 	.configure = i2c_kb1200_configure,
298 	.get_config = i2c_kb1200_get_config,
299 	.transfer = i2c_kb1200_transfer,
300 #ifdef CONFIG_I2C_RTIO
301 	.iodev_submit = i2c_iodev_submit_fallback,
302 #endif
303 };
304 
305 #define KB1200_FSMBM_DEV(inst) DEVICE_DT_INST_GET(inst),
306 static const struct device *const fsmbm_devices[] = {DT_INST_FOREACH_STATUS_OKAY(KB1200_FSMBM_DEV)};
i2c_kb1200_isr_wrap(void)307 static void i2c_kb1200_isr_wrap(void)
308 {
309 	for (size_t i = 0; i < ARRAY_SIZE(fsmbm_devices); i++) {
310 		const struct device *dev_ = fsmbm_devices[i];
311 		const struct i2c_kb1200_config *config = dev_->config;
312 
313 		if (config->fsmbm->FSMBMIE & config->fsmbm->FSMBMPF) {
314 			i2c_kb1200_isr(dev_);
315 		}
316 	}
317 }
318 
319 static bool init_irq = true;
kb1200_fsmbm_irq_init(void)320 static void kb1200_fsmbm_irq_init(void)
321 {
322 	if (init_irq) {
323 		init_irq = false;
324 		IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), i2c_kb1200_isr_wrap, NULL,
325 			    0);
326 		irq_enable(DT_INST_IRQN(0));
327 	}
328 }
329 
i2c_kb1200_init(const struct device * dev)330 static int i2c_kb1200_init(const struct device *dev)
331 {
332 	int ret;
333 	const struct i2c_kb1200_config *config = dev->config;
334 	struct i2c_kb1200_data *data = dev->data;
335 
336 	ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
337 	if (ret != 0) {
338 		return ret;
339 	}
340 
341 	/* init mutex */
342 	k_sem_init(&data->mutex, 1, 1);
343 	kb1200_fsmbm_irq_init();
344 
345 	return 0;
346 }
347 
348 #define I2C_KB1200_DEVICE(inst)                                                                    \
349 	PINCTRL_DT_INST_DEFINE(inst);                                                              \
350 	static struct i2c_kb1200_data i2c_kb1200_data_##inst;                                      \
351 	static const struct i2c_kb1200_config i2c_kb1200_config_##inst = {                         \
352 		.fsmbm = (struct fsmbm_regs *)DT_INST_REG_ADDR(inst),                              \
353 		.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst),                                      \
354 	};                                                                                         \
355 	I2C_DEVICE_DT_INST_DEFINE(inst, &i2c_kb1200_init, NULL, &i2c_kb1200_data_##inst,           \
356 			      &i2c_kb1200_config_##inst, PRE_KERNEL_1,                             \
357 			      CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &i2c_kb1200_api);
358 
359 DT_INST_FOREACH_STATUS_OKAY(I2C_KB1200_DEVICE)
360