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