1 /*
2  * Copyright (C) 2015-2021 Alibaba Group Holding Limited
3  */
4 
5 #include <poll.h>
6 
7 #include <aos/driver/i2c.h>
8 #include <vfsdev/i2c_dev.h>
9 #include <devicevfs/devicevfs.h>
10 
11 #ifdef CONFIG_I2C_NUM
12 #define PLATFORM_I2C_NUM CONFIG_I2C_NUM
13 #else
14 #define PLATFORM_I2C_NUM 4
15 #endif
16 
17 #if (PLATFORM_I2C_NUM > 0)
18 // I2C device node will be named with "/dev/i2c<x>", where <x> is i2c port id
19 #define I2C_DEV_NAME_FORMAT "i2c%d"
20 
21 typedef struct vfs_i2c {
22     unsigned port;
23 } vfs_i2c_t;
24 
25 /**
26  * allocate memory for copy i2c_config_t
27  * @param dst pointer to destinatin struct
28  * @param src pointer to source struct
29  * @return 0 for success; negative for failure
30  */
_copy_i2c_control_arg(io_i2c_control_u * dst,io_i2c_control_u * src)31 static int _copy_i2c_control_arg (io_i2c_control_u *dst, io_i2c_control_u *src) {
32     if (!dst || !src) {
33         return -EINVAL;
34     }
35     aos_ipc_copy(dst, src, sizeof(io_i2c_control_u));
36 
37     return 0;
38 }
39 
40 /**
41  * allocate memory for copy io_i2c_data_t, data field in io_i2c_data_t is also included
42  * @param dst pointer to destinatin struct
43  * @param src pointer to source struct
44  * @return 0 for success; negative for failure
45  */
_alloc_i2c_data_arg(io_i2c_data_t * dst,io_i2c_data_t * src)46 static int _alloc_i2c_data_arg (io_i2c_data_t *dst, io_i2c_data_t *src) {
47     if (!dst || !src) {
48         return -EINVAL;
49     }
50 
51     aos_ipc_copy(dst, src, sizeof(io_i2c_data_t));
52     if (!dst->data || !dst->length) {
53         return -EINVAL;
54     }
55 
56     dst->data = malloc(dst->length);
57     if (!dst->data)
58         return -ENOMEM;
59 
60     return 0;
61 }
62 
63 /**
64  * copy io_i2c_data_t's data field
65  * @param dst pointer to destinatin struct
66  * @param src pointer to source struct
67  * @return 0 for success; negative for failure
68  */
_copy_i2c_data_field(io_i2c_data_t * dst,io_i2c_data_t * src)69 static int _copy_i2c_data_field (io_i2c_data_t *dst, io_i2c_data_t *src) {
70     io_i2c_data_t tmp;
71     unsigned char *data = NULL;
72 
73     if (!dst || !src) {
74         return -EINVAL;
75     }
76     tmp.data = NULL;
77 
78     aos_ipc_copy(&tmp, dst, sizeof(io_i2c_data_t));
79 
80     data = tmp.data;
81     if (!data || !tmp.length || !src->data || !src->length || (tmp.length != src->length)) {
82         ddkc_err("invalid arg, dst[data:%p, length:%d], src[data:%p, length:%d]",
83                  data, tmp.length, src->data, src->length);
84         return -EINVAL;
85     }
86 
87     aos_ipc_copy(data, src->data, src->length);
88 
89     return 0;
90 }
91 
92 /**
93  * copy io_i2c_data_t's content, data included
94  * @param dst pointer to destinatin struct
95  * @param src pointer to source struct
96  * @return 0 for success; negative for failure
97  */
_copy_i2c_data_arg(io_i2c_data_t * dst,io_i2c_data_t * src)98 static int _copy_i2c_data_arg (io_i2c_data_t *dst, io_i2c_data_t *src) {
99     unsigned char *data = NULL;
100 
101     if (!dst || !src) {
102         return -1;
103     }
104 
105     aos_ipc_copy(dst, src, sizeof(io_i2c_data_t));
106 
107     data = dst->data;
108     if (!data || !dst->length)
109         return 0;
110 
111     dst->data = malloc(dst->length);
112     if (!dst->data)
113         return -ENOMEM;
114 
115     aos_ipc_copy(dst->data, data, dst->length);
116 
117     return 0;
118 }
119 
_free_i2c_data_arg(io_i2c_data_t * dst)120 static int _free_i2c_data_arg (io_i2c_data_t *dst) {
121     if (!dst || !dst->data)
122         return -EINVAL;
123 
124     free(dst->data);
125 
126     return 0;
127 }
128 
i2c_device_ioctl(file_t * f,int cmd,unsigned long arg)129 int i2c_device_ioctl (file_t *f, int cmd, unsigned long arg) {
130     int ret = 0;
131     io_i2c_data_t *d = NULL;
132     io_i2c_control_u *c = NULL;
133     vfs_i2c_t *vd = (vfs_i2c_t *)f->node->i_arg;
134     i2c_dev_handle_t slave = (i2c_dev_handle_t)f->f_arg;
135 
136     // VFS make sure ioctl on the same fd is sequenced, so big-lock is not necessary
137     ddkc_dbg("cmd:0x%x, arg:0x%lx\r\n", cmd, arg);
138 
139     switch (cmd) {
140         case IOC_I2C_SET_FREQ:
141             ddkc_dbg("IOC_I2C_SET_FREQ\r\n");
142             c = (io_i2c_control_u *)arg;
143             ret = aos_i2c_clk_set(slave, c->freq);
144             if (ret) {
145                 ddkc_err("set clock to i2c%d failed, ret:%d\r\n", c->freq, ret);
146             }
147             break;
148 
149         case IOC_I2C_SET_CONFIG:
150             ddkc_dbg("IOC_I2C_SET_CONFIG\r\n");
151 
152             c = (io_i2c_control_u *)arg;
153             if (!c->c.role) {
154                 ret = -EINVAL;
155                 ddkc_err("i2c%d only support master mode\r\n", c->freq);
156             }
157 
158             ret = aos_i2c_slave_addr_set(slave, c->c.addr);
159             if (ret) {
160                 ddkc_err("set slave address:0x%x to i2c%d failed, ret:%d\r\n", c->c.addr, ret);
161             }
162 
163             ret += aos_i2c_addr_width_set(slave, c->c.addr_width ? I2C_SLAVE_ADDR_WIDTH_10BIT : I2C_SLAVE_ADDR_WIDTH_7BIT);
164             if (ret) {
165                 ddkc_err("set slave address:0x%x to i2c%d failed, ret:%d\r\n", c->c.addr, ret);
166             }
167             break;
168 
169         case IOC_I2C_MASTER_RX:
170             ddkc_dbg("IOC_I2C_MASTER_RX\r\n");
171 
172             d = (io_i2c_data_t *)arg;
173 
174             ret = aos_i2c_slave_addr_set(slave, d->addr);
175             if (ret) {
176                 ddkc_err("set slave address:0x%x to i2c%d failed, ret:%d\r\n", c->c.addr, ret);
177                 return ret;
178             }
179 
180             ret = aos_i2c_master_recv(slave, d->data, d->length, d->timeout);
181             if (ret != d->length) {
182                 ddkc_err("i2c%d rx failed, tx_buffer:%p, d->length:%d, d->timeout:%d, ret:%d\n",
183                     vd->port, d->data, d->length, d->timeout, ret);
184                     ret = -EIO;
185             } else {
186                 ddkc_dbg("i2c%d rx succeed, tx_buffer:%p, d->length:%d, d->timeout:%d\n",
187                     vd->port, d->data, d->length, d->timeout);
188                     ret = 0;
189             }
190             break;
191         case IOC_I2C_MASTER_TX:
192             ddkc_dbg("IOC_I2C_MASTER_TX\r\n");
193 
194             d = (io_i2c_data_t *)arg;
195 
196             ret = aos_i2c_slave_addr_set(slave, d->addr);
197             if (ret) {
198                 ddkc_err("set slave address:0x%x to i2c%d failed, ret:%d\r\n", c->c.addr, ret);
199                 return ret;
200             }
201 
202             ret = aos_i2c_master_send(slave, d->data, d->length, d->timeout);
203             if (ret != d->length) {
204                 ddkc_err("i2c%d tx failed, tx_buffer:%p, d->length:%d, d->timeout:%d, ret:%d\n",
205                     vd->port, d->data, d->length, d->timeout, ret);
206                     ret = -EIO;
207             } else {
208                 ddkc_dbg("i2c%d tx succeed, tx_buffer:%p, d->length:%d, d->timeout:%d\n",
209                     vd->port, d->data, d->length, d->timeout);
210                     ret = 0;
211             }
212             break;
213         case IOC_I2C_SLAVE_RX:
214             ddkc_dbg("IOC_I2C_SLAVE_RX\r\n");
215             ddkc_err("i2c slave operation is not supported\r\n");
216             ret = -ENOTSUP;
217             break;
218         case IOC_I2C_SLAVE_TX:
219             ddkc_dbg("IOC_I2C_SLAVE_TX\r\n");
220             ddkc_err("i2c slave operation is not supported\r\n");
221             ret = -ENOTSUP;
222             break;
223         case IOC_I2C_MEM_RX:
224             ddkc_dbg("IOC_I2C_MEM_RX\r\n");
225             d = (io_i2c_data_t *)arg;
226 
227             ret = aos_i2c_slave_addr_set(slave, d->addr);
228             if (ret) {
229                 ddkc_err("set slave address:0x%x to i2c%d failed, ret:%d\r\n", c->c.addr, ret);
230                 return ret;
231             }
232 
233             ret = aos_i2c_mem_read(slave, d->maddr, d->mlength, d->data, d->length, d->timeout);
234             if (ret != d->length) {
235                 ddkc_err("i2c%d memory rx failed, mem_addr:0x%x, addr_len:%d, tx_buffer:%p, d->length:%d, d->timeout:%d, ret:%d\n",
236                     vd->port, d->maddr, d->mlength, d->data, d->length, d->timeout, ret);
237                     ret = -EIO;
238             } else {
239                 ddkc_dbg("i2c%d memory rx succeed, mem_addr:0x%x, addr_len:%d, tx_buffer:%p, d->length:%d, d->timeout:%d\n",
240                     vd->port, d->maddr, d->mlength, d->data, d->length, d->timeout);
241                     ret = 0;
242             }
243             break;
244         case IOC_I2C_MEM_TX:
245             ddkc_dbg("IOC_I2C_MEM_TX\r\n");
246             d = (io_i2c_data_t *)arg;
247 
248             ret = aos_i2c_slave_addr_set(slave, d->addr);
249             if (ret) {
250                 ddkc_err("set slave address:0x%x to i2c%d failed, ret:%d\r\n", c->c.addr, ret);
251                 return ret;
252             }
253 
254             ret = aos_i2c_mem_write(slave, d->maddr, d->mlength, d->data, d->length, d->timeout);
255             if (ret != d->length) {
256                 ddkc_err("i2c%d memory tx failed, mem_addr:0x%x, addr_len:%d, tx_buffer:%p, d->length:%d, d->timeout:%d, ret:%d\n",
257                     vd->port, d->maddr, d->mlength, d->data, d->length, d->timeout, ret);
258                     ret = -EIO;
259             } else {
260                 ddkc_dbg("i2c%d memory tx succeed, mem_addr:0x%x, addr_len:%d, tx_buffer:%p, d->length:%d, d->timeout:%d\n",
261                     vd->port, d->maddr, d->mlength, d->data, d->length, d->timeout);
262                     ret = 0;
263             }
264             break;
265         default:
266             ddkc_err("invalid cmd:%d\r\n", cmd);
267             break;
268     }
269 
270     return ret;
271 }
272 
i2c_device_open(inode_t * node,file_t * f)273 int i2c_device_open (inode_t *node, file_t *f) {
274     vfs_i2c_t *vd = (vfs_i2c_t *)node->i_arg;
275     i2c_dev_handle_t slave = NULL;
276     i2c_slave_config_t config;
277 
278     config.addr = 0x0; // set to 0x0 by default
279     config.addr_width = I2C_SLAVE_ADDR_WIDTH_7BIT; // set to 7-bit address mode by default
280     config.clk = I2C_BUS_CLK_100K; // set to 100k by default
281 
282     slave = aos_i2c_open(vd->port, &config);
283     if (!slave) {
284         printf("i2c%d open failed\r\n", vd->port);
285         return -1;
286     }
287 
288     f->f_arg = slave;
289 
290     ddkc_dbg("device:%s open success\r\n", node->i_name);
291 
292     return 0;
293 }
294 
i2c_device_close(file_t * f)295 int i2c_device_close (file_t *f) {
296     int ret = -1;
297     vfs_i2c_t *vd = (vfs_i2c_t *)f->node->i_arg;
298     i2c_dev_handle_t slave = (i2c_dev_handle_t)f->f_arg;
299 
300     if (slave) {
301         ret = aos_i2c_close(slave);
302         if (ret) {
303             printf("i2c%d close failed, ret:%d\r\n", vd->port, ret);
304         }
305         f->f_arg = NULL;
306     } else {
307         ddkc_warn("invalid f_arg:%x\r\n", slave);
308     };
309 
310     ddkc_dbg("device:%s close success\r\n", f->node->i_name);
311 
312     return 0;
313 }
314 
315 
316 /************************** device ****************************/
317 
318 
319 subsys_file_ops_t i2c_device_fops = {
320     .open = i2c_device_open,
321     .close = i2c_device_close,
322     .read = NULL,
323     .write = NULL,
324     .ioctl = i2c_device_ioctl,
325     .poll = NULL,
326 };
327 
i2c_device_init(struct u_platform_device * pdev)328 int i2c_device_init (struct u_platform_device *pdev) {
329     // make sure 0 is returned if init operation success
330     // or aos_dev_reg procedure will break and no device node will be registered
331     ddkc_dbg("%s\r\n", __func__);
332     return 0;
333 }
334 
i2c_device_deinit(struct u_platform_device * pdev)335 int i2c_device_deinit (struct u_platform_device *pdev) {
336     ddkc_dbg("%s\r\n", __func__);
337     return 0;
338 }
339 
i2c_device_pm(struct u_platform_device * pdev,u_pm_ops_t state)340 int i2c_device_pm (struct u_platform_device *pdev, u_pm_ops_t state) {
341     ddkc_dbg("%s\r\n", __func__);
342     return 0;
343 }
344 
345 struct subsys_drv i2c_device_drv = {
346     .drv_name = "i2c",
347     .init = i2c_device_init,
348     .deinit = i2c_device_deinit,
349     .pm = i2c_device_pm,
350 };
351 
352 struct subsys_dev *g_i2c_device_array[PLATFORM_I2C_NUM];
353 
354 
vfs_i2c_drv_init(void)355 int vfs_i2c_drv_init (void) {
356     int i = 0;
357     int j = 0;
358     int ret = 0;
359     int node_name_len = 0;
360     struct subsys_dev **ppsdev = NULL;
361 
362     ddkc_dbg("i2c vfs driver init starts\r\n");
363 
364     node_name_len = strlen(I2C_DEV_NAME_FORMAT) + 1;
365     ddkc_dbg("node_name_len:%d\r\n", node_name_len);
366 
367     memset(g_i2c_device_array, 0, sizeof(g_i2c_device_array));
368     ppsdev = g_i2c_device_array;
369 
370     for (i = 0; i < PLATFORM_I2C_NUM; i++) {
371         vfs_i2c_t *vd = malloc(sizeof(vfs_i2c_t));
372 
373         *ppsdev = malloc(sizeof(struct subsys_dev) + node_name_len);
374         if (!(*ppsdev) || !vd) {
375             ddkc_info("malloc failed, *ppsdev:%p, vd:%p\r\n", *ppsdev, vd);
376 
377             if (*ppsdev) {
378                 free(*ppsdev);
379                 *ppsdev = NULL;
380             }
381 
382             if (vd)
383                 free(vd);
384 
385             goto err;
386         }
387 
388         memset(*ppsdev, 0, sizeof(struct subsys_dev) + node_name_len);
389         memset(vd, 0, sizeof(*vd));
390         // vfs_i2c_t's port should be remained during the whole driver life
391         vd->port = i;
392 
393         (*ppsdev)->node_name = (char *)((*ppsdev) + 1);
394         snprintf((*ppsdev)->node_name, node_name_len, I2C_DEV_NAME_FORMAT, i);
395         ddkc_dbg("*ppsdev:%p, node_name:%s, (*ppsdev) + 1:%p, sizeof(struct subsys_dev):%d\r\n",
396                 *ppsdev, (*ppsdev)->node_name, (*ppsdev) + 1, sizeof(struct subsys_dev));
397         (*ppsdev)->permission = 0;
398         // please refer to definitions in enum SUBSYS_BUS_TYPE
399         (*ppsdev)->type = BUS_TYPE_PLATFORM;
400         // user_data will be passed to open operation via node->i_arg
401         (*ppsdev)->user_data = vd;
402 
403         ret = aos_dev_reg(*ppsdev, &i2c_device_fops, &i2c_device_drv);
404         if (ret) {
405             ddkc_err("aos_dev_reg for i2c%d failed, ret:%d\r\n", i, ret);
406 
407             free(vd);
408             free(*ppsdev);
409             *ppsdev = NULL;
410 
411             goto err;
412         }
413 
414         ppsdev++;
415     }
416 
417     ddkc_dbg("i2c vfs driver init finish, ret:%d\r\n", ret);
418     return 0;
419 
420 err:
421     ppsdev = g_i2c_device_array;
422     for (j = 0; j < i; j++) {
423         // shall uninstall i2c devices who are already registered
424 
425         if (*ppsdev) {
426             aos_dev_unreg(*ppsdev);
427 
428             ddkc_info("free memory for i2c%d\r\n", i);
429 
430             if ((*ppsdev)->user_data)
431                 free((*ppsdev)->user_data);
432 
433             free(*ppsdev);
434             *ppsdev = NULL;
435         }
436         ppsdev++;
437     }
438     ddkc_err("i2c vfs driver init failed, ret:%d\r\n", ret);
439 
440     return ret;
441 }
442 
443 VFS_DRIVER_ENTRY(vfs_i2c_drv_init)
444 
445 
446 #endif
447