1 /*
2  * Copyright (C) 2015-2021 Alibaba Group Holding Limited
3  */
4 
5 #include <poll.h>
6 
7 #include <aos/hal/spi.h>
8 #include <vfsdev/spi_dev.h>
9 #include <devicevfs/devicevfs.h>
10 
11 #ifdef CONFIG_SPI_NUM
12 #define PLATFORM_SPI_NUM CONFIG_SPI_NUM
13 #else
14 #define PLATFORM_SPI_NUM 4
15 #endif
16 
17 #if (PLATFORM_SPI_NUM > 0)
18 
19 // SPI device node will be named with "/dev/spi<x>", where <x> is spi port id
20 #define SPI_DEV_NAME_FORMAT "spi%d"
21 #define DEFAULT_SPI_FREQ 1000000
22 /* used to notify user on poll events */
23 typedef struct spi_poll_notify {
24     bool flag;
25     struct mutex mutex;
26     poll_notify_t notify;
27     struct pollfd *fd;
28     void *arg;
29 } spi_poll_notify_t;
30 
31 static spi_poll_notify_t g_spi_notify[PLATFORM_SPI_NUM];
32 
hal_spi_recv_cb_reg(spi_dev_t * spi,spi_rx_cb cb)33 __weak int hal_spi_recv_cb_reg(spi_dev_t *spi, spi_rx_cb cb) {
34     ddkc_dbg("%s, spi:%p, cb:%p\r\n", __func__, spi, cb);
35     return 0;
36 }
37 
spi_device_read(file_t * f,void * buffer,size_t size)38 ssize_t spi_device_read (file_t *f, void *buffer, size_t size) {
39 
40     spi_dev_t *spi = (spi_dev_t *)f->node->i_arg;
41     spi_poll_notify_t *spi_poll = NULL;
42 
43     if (!spi || !buffer || !size) {
44         ddkc_dbg("invalid spi:%p, buffer:%p or size:%d\r\n", spi, buffer, size);
45         return -EINVAL;
46     }
47     spi_poll = &g_spi_notify[spi->port];
48     if (spi_poll->flag) {
49         mutex_lock(&spi_poll->mutex);
50         spi_poll->flag = false;
51         mutex_unlock(&spi_poll->mutex);
52     }
53     return hal_spi_recv(spi, buffer, size, 0);
54 }
55 
spi_device_write(file_t * f,const void * buffer,size_t size)56 ssize_t spi_device_write (file_t *f, const void *buffer, size_t size) {
57     spi_dev_t *spi = (spi_dev_t *)f->node->i_arg;
58 
59     if (!spi || !buffer || !size) {
60         ddkc_err("invalid spi:%p, buffer:%p or size:%d\r\n", spi, buffer, size);
61         return -EINVAL;
62     }
63     return hal_spi_send(spi, buffer, size, 1000);
64 }
65 
_arg_to_role(unsigned long arg)66 static spi_role_e _arg_to_role (unsigned long arg) {
67     spi_role_e role = 0;
68     int control = arg & SPI_SLAVE;
69 
70     switch (control) {
71         case SPI_SLAVE:
72             role = SPI_ROLE_SLAVE;
73             break;
74         case SPI_MASTER:
75             role = SPI_ROLE_MASTER;
76             break;
77 
78         default:
79             role = SPI_ROLE_MASTER;
80             break;
81     }
82 
83     return role;
84 }
85 
_arg_to_firstbit(unsigned long arg)86 static spi_firstbit_e _arg_to_firstbit (unsigned long arg) {
87     spi_firstbit_e  firstbit = 0;
88     int control = arg & SPI_LSB;
89 
90     switch (control) {
91         case SPI_LSB:
92             firstbit = SPI_FIRSTBIT_LSB;
93             break;
94         case SPI_MSB:
95             firstbit = SPI_FIRSTBIT_MSB;
96             break;
97 
98         default:
99             firstbit = SPI_FIRSTBIT_MSB;
100             break;
101     }
102 
103     return firstbit;
104 }
105 
_arg_to_work_mode(unsigned long arg)106 static spi_work_mode_e _arg_to_work_mode (unsigned long arg) {
107     spi_work_mode_e mode = 0;
108     int control = arg & (SPI_CPOL|SPI_CPHA);
109 
110     switch (control) {
111         case SPI_MODE_0:
112             mode = SPI_WORK_MODE_0;
113             break;
114         case SPI_MODE_1:
115             mode = SPI_WORK_MODE_1;
116             break;
117         case SPI_MODE_2:
118             mode = SPI_WORK_MODE_2;
119             break;
120         case SPI_MODE_3:
121             mode = SPI_WORK_MODE_3;
122             break;
123     }
124 
125     return mode;
126 }
127 
_arg_to_tranmode(unsigned long arg)128 static spi_transfer_mode_e _arg_to_tranmode (unsigned long arg) {
129     spi_transfer_mode_e mode = 0;
130     int control = arg & SPI_TRANSFER_MODE_MASK;
131 
132     switch (control) {
133         case SPI_TRANSFER_DMA_MODE:
134             mode = (spi_transfer_mode_e)SPI_TRANSFER_DMA;
135             break;
136         case SPI_TRANSFER_NORMAL_MODE:
137             mode = (spi_transfer_mode_e)SPI_TRANSFER_NORMAL;
138             break;
139 
140         default:
141             mode = (spi_transfer_mode_e)SPI_TRANSFER_NORMAL;
142             break;
143     }
144 
145     return mode;
146 }
147 
_arg_to_datasize(unsigned long arg)148 static spi_data_size_e _arg_to_datasize (unsigned long arg) {
149     spi_data_size_e datasize = 0;
150     int control = arg & SPI_DATA_SIZE_MASK;
151 
152     switch (control) {
153         case SPI_DATA_4BIT:
154             datasize = SPI_DATA_SIZE_4BIT;
155             break;
156         case SPI_DATA_5BIT:
157             datasize = SPI_DATA_SIZE_5BIT;
158             break;
159         case SPI_DATA_6BIT:
160             datasize = SPI_DATA_SIZE_6BIT;
161             break;
162         case SPI_DATA_7BIT:
163             datasize = SPI_DATA_SIZE_7BIT;
164             break;
165         case SPI_DATA_8BIT:
166             datasize = SPI_DATA_SIZE_8BIT;
167             break;
168         case SPI_DATA_9BIT:
169             datasize = SPI_DATA_SIZE_9BIT;
170             break;
171         case SPI_DATA_10BIT:
172             datasize = SPI_DATA_SIZE_10BIT;
173             break;
174         case SPI_DATA_11BIT:
175             datasize = SPI_DATA_SIZE_11BIT;
176             break;
177         case SPI_DATA_12BIT:
178             datasize = SPI_DATA_SIZE_12BIT;
179             break;
180         case SPI_DATA_13BIT:
181             datasize = SPI_DATA_SIZE_13BIT;
182             break;
183         case SPI_DATA_14BIT:
184             datasize = SPI_DATA_SIZE_14BIT;
185             break;
186         case SPI_DATA_15BIT:
187             datasize = SPI_DATA_SIZE_15BIT;
188             break;
189         case SPI_DATA_16BIT:
190             datasize = SPI_DATA_SIZE_16BIT;
191             break;
192 
193         default:
194             datasize = SPI_DATA_SIZE_8BIT;
195             break;
196     }
197 
198     return datasize;
199 }
200 
_arg_to_cs(int arg)201 static spi_cs_e _arg_to_cs (int arg) {
202     spi_cs_e cs = 0;
203     int control = arg & SPI_NO_CS;
204 
205     switch (control) {
206         case SPI_NO_CS:
207             cs = SPI_CS_DIS;
208             break;
209 
210         default:
211             cs = SPI_CS_EN;
212             break;
213     }
214 
215     return cs;
216 }
217 
spi_device_ioctl(file_t * f,int cmd,unsigned long arg)218 int spi_device_ioctl (file_t *f, int cmd, unsigned long arg) {
219     int ret = -1;
220     spi_config_t *config = NULL;
221     spi_dev_t *spi = (spi_dev_t *)f->node->i_arg;
222 	ioc_spi_transfer_t *tranptr;
223 
224     if (!spi) {
225         ddkc_dbg("spi is NULL,invalid and ignore\r\n");
226         return -EINVAL;
227     }
228 
229     config = &spi->config;
230 
231     ddkc_dbg("i_name:%s, spi:%p, cmd:%d, arg:0x%lx\r\n", f->node->i_name, spi, cmd, arg);
232 
233     switch (cmd) {
234         case IOC_SPI_SET_CFLAG:
235             ret = hal_spi_finalize(spi);
236             if (ret) {
237                 ddkc_warn("hal_spi_finalize failed, ret:%d\r\n", ret);
238                 break;
239             }
240 
241             config->role = _arg_to_role(arg);
242             config->firstbit = _arg_to_firstbit(arg);
243             config->mode = _arg_to_work_mode(arg);
244             config->t_mode = _arg_to_tranmode(arg);
245             config->data_size = _arg_to_datasize(arg);
246             config->cs = _arg_to_cs(arg);
247             ddkc_info("role:%d, firstbit:%d, mode:%d, t_mode:%d, data_size:%d, cs:%d\r\n",
248                       config->role, config->firstbit, config->mode, config->t_mode, config->data_size, config->cs);
249 
250             ret = hal_spi_init(spi);
251             if (ret) {
252                 ddkc_warn("hal_spi_init failed, ret:%d\r\n", ret);
253             }
254             break;
255         case IOC_SPI_SET_FREQ:
256             ret = hal_spi_finalize(spi);
257             if (ret) {
258                 ddkc_warn("hal_spi_finalize failed, ret:%d\r\n", ret);
259                 break;
260             }
261             config->freq = arg;
262             ret = hal_spi_init(spi);
263             if (ret) {
264                 ddkc_warn("hal_spi_init failed, ret:%d\r\n", ret);
265             }
266 
267             break;
268         case IOC_SPI_SEND_RECV:
269             tranptr = (ioc_spi_transfer_t *)arg;
270             if(NULL == tranptr){
271                 ddkc_warn("tranptr is null, ret:%d\r\n", ret);
272                 break;
273             }
274             ret = hal_spi_send_recv(spi,tranptr->tx_buf,tranptr->rx_buf,tranptr->rx_size,0);
275             if (ret) {
276                 ddkc_warn("hal_spi_send_recv failed, ret:%d\r\n", ret);
277             }
278 
279             break;
280         case IOC_SPI_SEND_AND_RECV:
281             tranptr = (ioc_spi_transfer_t *)arg;
282             if(NULL == tranptr){
283                 ddkc_warn("tranptr is null, ret:%d\r\n", ret);
284                 break;
285             }
286             ret = hal_spi_send_and_recv(spi,tranptr->tx_buf,tranptr->tx_size,tranptr->rx_buf,tranptr->rx_size,0);
287             if (ret) {
288                 ddkc_warn("hal_spi_send_and_recv failed, ret:%d\r\n", ret);
289             }
290 
291             break;
292         case IOC_SPI_SEND_AND_SEND:
293             tranptr = (ioc_spi_transfer_t *)arg;
294             if(NULL == tranptr){
295                 ddkc_warn("tranptr is null, ret:%d\r\n", ret);
296                 break;
297             }
298             ret = hal_spi_send_and_send(spi,tranptr->tx_buf,tranptr->tx_size,tranptr->rx_buf,tranptr->rx_size,0);
299             if (ret) {
300                 ddkc_warn("hal_spi_send_and_send failed, ret:%d\r\n", ret);
301             }
302             break;
303 
304         case IOC_SPI_SET_SERIAL_LEN:
305             ret = hal_spi_finalize(spi);
306             if (ret) {
307                 ddkc_warn("hal_spi_finalize failed, ret:%d\r\n", ret);
308                 break;
309             }
310             config->serial_len = arg;
311             ret = hal_spi_init(spi);
312             if (ret) {
313                 ddkc_warn("hal_spi_init failed, ret:%d\r\n", ret);
314             }
315 
316             break;
317 
318         default:
319             break;
320     }
321 
322     return ret;
323 }
324 
spi_device_open(inode_t * node,file_t * f)325 int spi_device_open (inode_t *node, file_t *f) {
326     int ret = -1;
327     spi_dev_t *spi = (spi_dev_t *)node->i_arg;
328 
329     ddkc_dbg("%s - node:%p, i_name:%s, spi:%p\r\n", __func__, node, node->i_name, spi);
330     if (!spi) {
331         ddkc_dbg("spi is NULL,invalid and ignore\r\n");
332         return -EINVAL;
333     }
334 
335     //TODO: check whether it is for console, special operation needed for console
336     /* open spi with default parameter */
337     ret = hal_spi_init(spi);
338     if (ret) {
339         ddkc_err("hal_spi_init failed, ret:%d\r\n", ret);
340         return ret;
341     }
342 
343     hal_spi_recv_cb_reg(spi, NULL);
344     //spi->priv = f;
345 
346     return 0;
347 }
348 
spi_device_close(file_t * f)349 int spi_device_close (file_t *f) {
350     int ret = 0;
351 
352     ddkc_dbg("%s\r\n", __func__);
353     spi_dev_t *spi = (spi_dev_t *)f->node->i_arg;
354 
355     //TODO: check whether it is for console, special operation needed for console
356     if (!spi) {
357         ddkc_dbg("f->node->i_arg is NULL, invalid and ignore\r\n");
358         return -EINVAL;
359     }
360 
361     hal_spi_recv_cb_reg(spi, NULL);
362     /* open spi with default parameter */
363     ret = hal_spi_finalize(spi);
364     if (ret) {
365         ddkc_err("hal_spi_finalize failed, ret:%d\r\n", ret);
366         return ret;
367     }
368 
369     return 0;
370 }
371 
spi_rx_notify(spi_dev_t * spi)372 int spi_rx_notify (spi_dev_t *spi) {
373     struct pollfd *fd = NULL;
374     spi_poll_notify_t *spi_poll = NULL;
375 
376     if (!spi) {
377         ddkc_err("spi should not be NULL in %s\r\n", __func__);
378         return -1;
379     }
380     ddkc_dbg("enter %s\r\n", __func__);
381     //fp = (file_t *)spi->priv;
382 
383     spi_poll = &g_spi_notify[spi->port];
384 
385     if (spi_poll->notify) {
386         mutex_lock(&spi_poll->mutex);
387         spi_poll->flag = true;
388 
389         fd = (struct pollfd *)spi_poll->fd;
390         fd->revents |= POLLIN;
391         /* add POLLOUT by default */
392         fd->revents |= POLLOUT;
393 
394         (*(spi_poll->notify)) (fd, spi_poll->arg);
395 
396         spi_poll->notify = NULL;
397         spi_poll->fd = NULL;
398         spi_poll->arg = NULL;
399 
400         hal_spi_recv_cb_reg(spi, NULL);
401 
402         mutex_unlock(&spi_poll->mutex);
403 
404     } else {
405         ddkc_err("!!!impossible case happened!!! spi_poll->notify is NULL\r\n");
406     }
407 
408 
409     return 0;
410 }
411 
spi_device_poll(file_t * f,int flag,poll_notify_t notify,void * fd,void * arg)412 int spi_device_poll (file_t *f, int flag, poll_notify_t notify, void *fd, void *arg) {
413     spi_poll_notify_t *spi_poll = NULL;
414     spi_dev_t *spi = (spi_dev_t *)f->node->i_arg;
415 
416     //TODO: check whether it is for console, special operation needed for console
417     if (!spi) {
418         ddkc_dbg("f->node->i_arg is NULL, invalid and ignore\r\n");
419         return -EINVAL;
420     }
421     ddkc_dbg("enter %s, fd:%p, arg:%p, notify:%p\r\n", __func__, fd, arg, notify);
422 
423     spi_poll = &g_spi_notify[spi->port];
424 
425     if (!fd) {
426         mutex_lock(&spi_poll->mutex);
427         hal_spi_recv_cb_reg(spi, NULL);
428         spi_poll->notify = NULL;
429         spi_poll->fd = NULL;
430         spi_poll->arg = NULL;
431         mutex_unlock(&spi_poll->mutex);
432         return 0;
433     }
434 
435     if (!spi_poll->flag) {
436         mutex_lock(&spi_poll->mutex);
437 
438         spi_poll->notify = notify;
439         spi_poll->fd = (struct pollfd *)fd;
440         spi_poll->arg = arg;
441 
442         hal_spi_recv_cb_reg(spi, spi_rx_notify);
443         ((struct pollfd *)fd)->revents &= ~POLLIN;
444 
445         mutex_unlock(&spi_poll->mutex);
446     } else {
447         ddkc_warn("spi_poll->flag is true, notify user directly\r\n");
448         ((struct pollfd *)fd)->events |= POLLIN;
449         (*notify)(fd, arg);
450     }
451 
452     // add POLLOUT to events by default
453     ((struct pollfd *)fd)->events |= POLLOUT;
454 
455     return 0;
456 }
457 
458 /************************** device ****************************/
459 
460 
461 subsys_file_ops_t spi_device_fops = {
462     .open = spi_device_open,
463     .close = spi_device_close,
464     .read = spi_device_read,
465     .write = spi_device_write,
466     .ioctl = spi_device_ioctl,
467     .poll = spi_device_poll,
468     .lseek = NULL,
469 };
470 
spi_device_init(struct u_platform_device * pdev)471 int spi_device_init (struct u_platform_device *pdev) {
472     // make sure 0 is returned if init operation success
473     // or aos_dev_reg procedure will break and no device node will be registered
474     ddkc_dbg("%s\r\n", __func__);
475     return 0;
476 }
477 
spi_device_deinit(struct u_platform_device * pdev)478 int spi_device_deinit (struct u_platform_device *pdev) {
479     ddkc_dbg("%s\r\n", __func__);
480     return 0;
481 }
482 
spi_device_pm(struct u_platform_device * pdev,u_pm_ops_t state)483 int spi_device_pm (struct u_platform_device *pdev, u_pm_ops_t state) {
484     ddkc_dbg("%s\r\n", __func__);
485     return 0;
486 }
487 
488 struct subsys_drv spi_device_drv = {
489     .drv_name = "spi",
490     .init = spi_device_init,
491     .deinit = spi_device_deinit,
492     .pm = spi_device_pm,
493 };
494 
495 struct subsys_dev *g_spi_device_array[PLATFORM_SPI_NUM];
496 
497 static spi_dev_t g_def_setting = {
498         .port = 0,
499         .config = {
500             .role = SPI_ROLE_MASTER,
501             .firstbit = SPI_FIRSTBIT_MSB,
502             .mode = SPI_WORK_MODE_0,
503             .t_mode = SPI_TRANSFER_NORMAL,
504             .freq = DEFAULT_SPI_FREQ,
505             .serial_len = DEFAULT_SPI_SERAIL_LEN,
506             .data_size = SPI_DATA_SIZE_8BIT,
507             .cs = SPI_CS_EN,
508         },
509         .priv = NULL,
510     };
511 
vfs_spi_drv_init(void)512 int vfs_spi_drv_init (void) {
513     int i = 0;
514     int j = 0;
515     int ret = 0;
516     int node_name_len = 0;
517     struct subsys_dev **ppsdev = NULL;
518 
519     ddkc_info("spi vfs driver init starts\r\n");
520 
521     node_name_len = strlen(SPI_DEV_NAME_FORMAT) + 1;
522 
523     memset(g_spi_notify, 0, sizeof(g_spi_notify));
524     memset(g_spi_device_array, 0, sizeof(g_spi_device_array));
525     ppsdev = g_spi_device_array;
526 
527     for (i = 0; i < PLATFORM_SPI_NUM; i++) {
528         spi_dev_t *spi_dev = malloc(sizeof(*spi_dev));
529 
530         *ppsdev = malloc(sizeof(struct subsys_dev) + node_name_len);
531 
532         if (!spi_dev || !(*ppsdev)) {
533             ddkc_info("malloc for spi_dev:%p or subsys_dev:%p failed, \r\n", spi_dev, *ppsdev);
534             if (spi_dev) {
535                 free(spi_dev);
536             }
537             if (*ppsdev) {
538                 free(*ppsdev);
539                 *ppsdev = NULL;
540             }
541 
542             goto err;
543         }
544 
545         memset(*ppsdev, 0, sizeof(struct subsys_dev) + node_name_len);
546 
547         (*ppsdev)->node_name = (char *)((*ppsdev) + 1);
548         snprintf((*ppsdev)->node_name, node_name_len, SPI_DEV_NAME_FORMAT, i);
549         ddkc_dbg("*ppsdev:%p, node_name:%s, (*ppsdev) + 1:%p, sizeof(struct subsys_dev):%d\r\n",
550                 *ppsdev, (*ppsdev)->node_name, (*ppsdev) + 1, sizeof(struct subsys_dev));
551         (*ppsdev)->permission = 0;
552         // please refer to definitions in enum SUBSYS_BUS_TYPE
553         (*ppsdev)->type = BUS_TYPE_PLATFORM;
554         memcpy(spi_dev, &g_def_setting, sizeof(*spi_dev));
555         spi_dev->port = i;
556         // user_data will be passed to open operation via node->i_arg
557         (*ppsdev)->user_data = spi_dev;
558 
559         mutex_init(&g_spi_notify[i].mutex);
560         ret = aos_dev_reg(*ppsdev, &spi_device_fops, &spi_device_drv);
561         if (ret) {
562             ddkc_err("aos_dev_reg for pwm%d failed, ret:%d\r\n", i, ret);
563 
564             free(spi_dev);
565             free(*ppsdev);
566             *ppsdev = NULL;
567 
568             goto err;
569         }
570 
571         ppsdev++;
572     }
573 
574     ddkc_info("spi vfs driver init finish, ret:%d\r\n", ret);
575 
576     return 0;
577 
578 err:
579     ppsdev = g_spi_device_array;
580 
581     for (j = 0; j < i; j++) {
582         if (*ppsdev) {
583             aos_dev_unreg(*ppsdev);
584 
585             ddkc_info("free memory for spi%d\r\n", j);
586 
587             if ((*ppsdev)->user_data)
588                 free((*ppsdev)->user_data);
589             free(*ppsdev);
590 
591             *ppsdev = NULL;
592         }
593         ppsdev++;
594     }
595     ddkc_err("spi vfs driver init failed, ret:%d\r\n", ret);
596 
597     return ret;
598 }
599 
600 //FIXME: not implement for pangu now.
601 #ifndef CONFIG_CHIP_PANGU
602 VFS_DRIVER_ENTRY(vfs_spi_drv_init)
603 #endif
604 
605 #endif
606