1 /*
2  * Copyright (c) 2006-2025 RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2012-01-08     bernard      first version.
9  * 2012-02-03     bernard      add const attribute to the ops.
10  * 2012-05-15     dzzxzz       fixed the return value in attach_device.
11  * 2012-05-18     bernard      Changed SPI message to message list.
12  *                             Added take/release SPI device/bus interface.
13  * 2012-09-28     aozima       fixed rt_spi_release_bus assert error.
14  */
15 
16 #include "drivers/dev_spi.h"
17 
18 #define DBG_TAG    "spi.core"
19 #define DBG_LVL    DBG_INFO
20 #include <rtdbg.h>
21 
22 #ifdef RT_USING_DM
23 #include "dev_spi_dm.h"
24 #endif
25 
26 extern rt_err_t rt_spi_bus_device_init(struct rt_spi_bus *bus, const char *name);
27 extern rt_err_t rt_spidev_device_init(struct rt_spi_device *dev, const char *name);
28 
spi_bus_register(struct rt_spi_bus * bus,const char * name,const struct rt_spi_ops * ops)29 rt_err_t spi_bus_register(struct rt_spi_bus       *bus,
30                           const char              *name,
31                           const struct rt_spi_ops *ops)
32 {
33     rt_err_t result;
34 
35     result = rt_spi_bus_device_init(bus, name);
36     if (result != RT_EOK)
37         return result;
38 
39     /* initialize mutex lock */
40     rt_mutex_init(&(bus->lock), name, RT_IPC_FLAG_PRIO);
41     /* set ops */
42     bus->ops = ops;
43     /* initialize owner */
44     bus->owner = RT_NULL;
45 
46 #ifdef RT_USING_DM
47     if (!bus->slave)
48     {
49         int pin_count = rt_pin_get_named_pin_count(&bus->parent, "cs");
50 
51         if (pin_count > 0)
52         {
53             pin_count = rt_max_t(int, pin_count, bus->num_chipselect);
54 
55             for (int i = 0; i < pin_count; ++i)
56             {
57                 bus->cs_pins[i] = rt_pin_get_named_pin(&bus->parent, "cs", i,
58                                                        RT_NULL, &bus->cs_active_vals[i]);
59             }
60         }
61         else if (pin_count < 0)
62         {
63             result = pin_count;
64 
65             LOG_E("CS PIN find error = %s", rt_strerror(result));
66 
67             rt_device_unregister(&bus->parent);
68             return result;
69         }
70     }
71 
72     spi_bus_scan_devices(bus);
73 #endif
74 
75     return RT_EOK;
76 }
77 
rt_spi_bus_register(struct rt_spi_bus * bus,const char * name,const struct rt_spi_ops * ops)78 rt_err_t rt_spi_bus_register(struct rt_spi_bus       *bus,
79                              const char              *name,
80                              const struct rt_spi_ops *ops)
81 {
82     /* set bus mode */
83     bus->mode = RT_SPI_BUS_MODE_SPI;
84 
85     return spi_bus_register(bus, name, ops);
86 }
87 
rt_spi_bus_attach_device_cspin(struct rt_spi_device * device,const char * name,const char * bus_name,rt_base_t cs_pin,void * user_data)88 rt_err_t rt_spi_bus_attach_device_cspin(struct rt_spi_device *device,
89                                         const char           *name,
90                                         const char           *bus_name,
91                                         rt_base_t            cs_pin,
92                                         void                 *user_data)
93 {
94     rt_err_t result;
95     rt_device_t bus;
96 
97     /* get physical spi bus */
98     bus = rt_device_find(bus_name);
99     if (bus != RT_NULL && bus->type == RT_Device_Class_SPIBUS)
100     {
101         device->bus = (struct rt_spi_bus *)bus;
102 
103         if (device->bus->owner == RT_NULL)
104             device->bus->owner = device;
105 
106         /* initialize spidev device */
107         result = rt_spidev_device_init(device, name);
108         if (result != RT_EOK)
109             return result;
110 
111         if (cs_pin != PIN_NONE)
112         {
113             rt_pin_mode(cs_pin, PIN_MODE_OUTPUT);
114         }
115 
116         rt_memset(&device->config, 0, sizeof(device->config));
117         device->parent.user_data = user_data;
118         device->cs_pin = cs_pin;
119         return RT_EOK;
120     }
121 
122     /* not found the host bus */
123     return -RT_ERROR;
124 }
125 
rt_spi_bus_attach_device(struct rt_spi_device * device,const char * name,const char * bus_name,void * user_data)126 rt_err_t rt_spi_bus_attach_device(struct rt_spi_device *device,
127                                   const char           *name,
128                                   const char           *bus_name,
129                                   void                 *user_data)
130 {
131     return rt_spi_bus_attach_device_cspin(device, name, bus_name, PIN_NONE, user_data);
132 }
133 
rt_spi_bus_configure(struct rt_spi_device * device)134 rt_err_t rt_spi_bus_configure(struct rt_spi_device *device)
135 {
136     rt_err_t result = -RT_ERROR;
137 
138     if (device->bus != RT_NULL)
139     {
140         result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER);
141         if (result == RT_EOK)
142         {
143             if (device->bus->owner == device)
144             {
145                 /* current device is using, re-configure SPI bus */
146                 result = device->bus->ops->configure(device, &device->config);
147                 if (result != RT_EOK)
148                 {
149                     /* configure SPI bus failed */
150                     LOG_E("SPI device %s configuration failed", device->parent.parent.name);
151                 }
152             }
153             else
154             {
155                 /* RT_EBUSY is not an error condition and
156                  * the configuration will take effect once the device has the bus
157                  */
158                 result = -RT_EBUSY;
159             }
160             /* release lock */
161             rt_mutex_release(&(device->bus->lock));
162         }
163     }
164     else
165     {
166         result = RT_EOK;
167     }
168 
169     return result;
170 }
171 
rt_spi_configure(struct rt_spi_device * device,struct rt_spi_configuration * cfg)172 rt_err_t rt_spi_configure(struct rt_spi_device        *device,
173                           struct rt_spi_configuration *cfg)
174 {
175     RT_ASSERT(device != RT_NULL);
176     RT_ASSERT(cfg != RT_NULL);
177 
178     /* reset the CS pin */
179     if (device->cs_pin != PIN_NONE)
180     {
181         rt_err_t result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER);
182         if (result == RT_EOK)
183         {
184             if (cfg->mode & RT_SPI_CS_HIGH)
185             {
186                 rt_pin_write(device->cs_pin, PIN_LOW);
187             }
188             else
189             {
190                 rt_pin_write(device->cs_pin, PIN_HIGH);
191             }
192             rt_mutex_release(&(device->bus->lock));
193         }
194         else
195         {
196             return result;
197         }
198     }
199 
200     /* If the configurations are the same, we don't need to set again. */
201     if (device->config.data_width == cfg->data_width &&
202         device->config.mode       == (cfg->mode & RT_SPI_MODE_MASK) &&
203         device->config.max_hz     == cfg->max_hz)
204     {
205         return RT_EOK;
206     }
207 
208     /* set configuration */
209     device->config.data_width = cfg->data_width;
210     device->config.mode       = cfg->mode & RT_SPI_MODE_MASK;
211     device->config.max_hz     = cfg->max_hz;
212 
213     return rt_spi_bus_configure(device);
214 }
215 
rt_spi_send_then_send(struct rt_spi_device * device,const void * send_buf1,rt_size_t send_length1,const void * send_buf2,rt_size_t send_length2)216 rt_err_t rt_spi_send_then_send(struct rt_spi_device *device,
217                                const void           *send_buf1,
218                                rt_size_t             send_length1,
219                                const void           *send_buf2,
220                                rt_size_t             send_length2)
221 {
222     rt_err_t result;
223     struct rt_spi_message message;
224 
225     RT_ASSERT(device != RT_NULL);
226     RT_ASSERT(device->bus != RT_NULL);
227 
228     result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER);
229     if (result == RT_EOK)
230     {
231         if (device->bus->owner != device)
232         {
233             /* not the same owner as current, re-configure SPI bus */
234             result = device->bus->ops->configure(device, &device->config);
235             if (result == RT_EOK)
236             {
237                 /* set SPI bus owner */
238                 device->bus->owner = device;
239             }
240             else
241             {
242                 /* configure SPI bus failed */
243                 LOG_E("SPI device %s configuration failed", device->parent.parent.name);
244                 goto __exit;
245             }
246         }
247 
248         /* send data1 */
249         message.send_buf   = send_buf1;
250         message.recv_buf   = RT_NULL;
251         message.length     = send_length1;
252         message.cs_take    = 1;
253         message.cs_release = 0;
254         message.next       = RT_NULL;
255 
256         result = device->bus->ops->xfer(device, &message);
257         if (result < 0)
258         {
259             LOG_E("SPI device %s transfer failed", device->parent.parent.name);
260             goto __exit;
261         }
262 
263         /* send data2 */
264         message.send_buf   = send_buf2;
265         message.recv_buf   = RT_NULL;
266         message.length     = send_length2;
267         message.cs_take    = 0;
268         message.cs_release = 1;
269         message.next       = RT_NULL;
270 
271         result = device->bus->ops->xfer(device, &message);
272         if (result < 0)
273         {
274             LOG_E("SPI device %s transfer failed", device->parent.parent.name);
275             goto __exit;
276         }
277 
278         result = RT_EOK;
279     }
280     else
281     {
282         return -RT_EIO;
283     }
284 
285 __exit:
286     rt_mutex_release(&(device->bus->lock));
287 
288     return result;
289 }
290 
rt_spi_send_then_recv(struct rt_spi_device * device,const void * send_buf,rt_size_t send_length,void * recv_buf,rt_size_t recv_length)291 rt_err_t rt_spi_send_then_recv(struct rt_spi_device *device,
292                                const void           *send_buf,
293                                rt_size_t             send_length,
294                                void                 *recv_buf,
295                                rt_size_t             recv_length)
296 {
297     rt_err_t result;
298     struct rt_spi_message message;
299 
300     RT_ASSERT(device != RT_NULL);
301     RT_ASSERT(device->bus != RT_NULL);
302 
303     result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER);
304     if (result == RT_EOK)
305     {
306         if (device->bus->owner != device)
307         {
308             /* not the same owner as current, re-configure SPI bus */
309             result = device->bus->ops->configure(device, &device->config);
310             if (result == RT_EOK)
311             {
312                 /* set SPI bus owner */
313                 device->bus->owner = device;
314             }
315             else
316             {
317                 /* configure SPI bus failed */
318                 LOG_E("SPI device %s configuration failed", device->parent.parent.name);
319                 goto __exit;
320             }
321         }
322 
323         /* send data */
324         message.send_buf   = send_buf;
325         message.recv_buf   = RT_NULL;
326         message.length     = send_length;
327         message.cs_take    = 1;
328         message.cs_release = 0;
329         message.next       = RT_NULL;
330 
331         result = device->bus->ops->xfer(device, &message);
332         if (result < 0)
333         {
334             LOG_E("SPI device %s transfer failed", device->parent.parent.name);
335             goto __exit;
336         }
337 
338         /* recv data */
339         message.send_buf   = RT_NULL;
340         message.recv_buf   = recv_buf;
341         message.length     = recv_length;
342         message.cs_take    = 0;
343         message.cs_release = 1;
344         message.next       = RT_NULL;
345 
346         result = device->bus->ops->xfer(device, &message);
347         if (result < 0)
348         {
349             LOG_E("SPI device %s transfer failed", device->parent.parent.name);
350             goto __exit;
351         }
352 
353         result = RT_EOK;
354     }
355     else
356     {
357         return -RT_EIO;
358     }
359 
360 __exit:
361     rt_mutex_release(&(device->bus->lock));
362 
363     return result;
364 }
365 
rt_spi_transfer(struct rt_spi_device * device,const void * send_buf,void * recv_buf,rt_size_t length)366 rt_ssize_t rt_spi_transfer(struct rt_spi_device *device,
367                            const void           *send_buf,
368                            void                 *recv_buf,
369                            rt_size_t             length)
370 {
371     rt_ssize_t result;
372     struct rt_spi_message message;
373 
374     RT_ASSERT(device != RT_NULL);
375     RT_ASSERT(device->bus != RT_NULL);
376 
377     result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER);
378     if (result == RT_EOK)
379     {
380         if (device->bus->owner != device)
381         {
382             /* not the same owner as current, re-configure SPI bus */
383             result = device->bus->ops->configure(device, &device->config);
384             if (result == RT_EOK)
385             {
386                 /* set SPI bus owner */
387                 device->bus->owner = device;
388             }
389             else
390             {
391                 /* configure SPI bus failed */
392                 LOG_E("SPI device %s configuration failed", device->parent.parent.name);
393                 goto __exit;
394             }
395         }
396 
397         /* initial message */
398         message.send_buf   = send_buf;
399         message.recv_buf   = recv_buf;
400         message.length     = length;
401         message.cs_take    = 1;
402         message.cs_release = 1;
403         message.next       = RT_NULL;
404 
405         /* transfer message */
406         result = device->bus->ops->xfer(device, &message);
407         if (result < 0)
408         {
409             LOG_E("SPI device %s transfer failed", device->parent.parent.name);
410             goto __exit;
411         }
412     }
413     else
414     {
415         return -RT_EIO;
416     }
417 
418 __exit:
419     rt_mutex_release(&(device->bus->lock));
420 
421     return result;
422 }
423 
rt_spi_sendrecv8(struct rt_spi_device * device,rt_uint8_t senddata,rt_uint8_t * recvdata)424 rt_err_t rt_spi_sendrecv8(struct rt_spi_device *device,
425                           rt_uint8_t            senddata,
426                           rt_uint8_t           *recvdata)
427 {
428     rt_ssize_t len = rt_spi_transfer(device, &senddata, recvdata, 1);
429     if (len < 0)
430     {
431         return (rt_err_t)len;
432     }
433     else
434     {
435         return RT_EOK;
436     }
437 }
438 
rt_spi_sendrecv16(struct rt_spi_device * device,rt_uint16_t senddata,rt_uint16_t * recvdata)439 rt_err_t rt_spi_sendrecv16(struct rt_spi_device *device,
440                            rt_uint16_t           senddata,
441                            rt_uint16_t          *recvdata)
442 {
443     rt_ssize_t len;
444     rt_uint16_t tmp;
445 
446     if (device->config.mode & RT_SPI_MSB)
447     {
448         tmp = ((senddata & 0xff00) >> 8) | ((senddata & 0x00ff) << 8);
449         senddata = tmp;
450     }
451 
452     len = rt_spi_transfer(device, &senddata, recvdata, 2);
453     if (len < 0)
454     {
455         return (rt_err_t)len;
456     }
457 
458     if (device->config.mode & RT_SPI_MSB)
459     {
460         tmp = ((*recvdata & 0xff00) >> 8) | ((*recvdata & 0x00ff) << 8);
461         *recvdata = tmp;
462     }
463 
464     return RT_EOK;
465 }
466 
rt_spi_transfer_message(struct rt_spi_device * device,struct rt_spi_message * message)467 struct rt_spi_message *rt_spi_transfer_message(struct rt_spi_device  *device,
468                                                struct rt_spi_message *message)
469 {
470     rt_err_t result;
471     struct rt_spi_message *index;
472 
473     RT_ASSERT(device != RT_NULL);
474 
475     /* get first message */
476     index = message;
477     if (index == RT_NULL)
478         return index;
479 
480     result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER);
481     if (result != RT_EOK)
482     {
483         return index;
484     }
485 
486     /* configure SPI bus */
487     if (device->bus->owner != device)
488     {
489         /* not the same owner as current, re-configure SPI bus */
490         result = device->bus->ops->configure(device, &device->config);
491         if (result == RT_EOK)
492         {
493             /* set SPI bus owner */
494             device->bus->owner = device;
495         }
496         else
497         {
498             /* configure SPI bus failed */
499             goto __exit;
500         }
501     }
502 
503     /* transmit each SPI message */
504     while (index != RT_NULL)
505     {
506         /* transmit SPI message */
507         result = device->bus->ops->xfer(device, index);
508         if (result < 0)
509         {
510             break;
511         }
512 
513         index = index->next;
514     }
515 
516 __exit:
517     /* release bus lock */
518     rt_mutex_release(&(device->bus->lock));
519 
520     return index;
521 }
522 
rt_spi_take_bus(struct rt_spi_device * device)523 rt_err_t rt_spi_take_bus(struct rt_spi_device *device)
524 {
525     rt_err_t result = RT_EOK;
526 
527     RT_ASSERT(device != RT_NULL);
528     RT_ASSERT(device->bus != RT_NULL);
529 
530     result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER);
531     if (result != RT_EOK)
532     {
533         return -RT_EBUSY;
534     }
535 
536     /* configure SPI bus */
537     if (device->bus->owner != device)
538     {
539         /* not the same owner as current, re-configure SPI bus */
540         result = device->bus->ops->configure(device, &device->config);
541         if (result == RT_EOK)
542         {
543             /* set SPI bus owner */
544             device->bus->owner = device;
545         }
546         else
547         {
548             /* configure SPI bus failed */
549             rt_mutex_release(&(device->bus->lock));
550 
551             return result;
552         }
553     }
554 
555     return result;
556 }
557 
rt_spi_release_bus(struct rt_spi_device * device)558 rt_err_t rt_spi_release_bus(struct rt_spi_device *device)
559 {
560     RT_ASSERT(device != RT_NULL);
561     RT_ASSERT(device->bus != RT_NULL);
562     RT_ASSERT(device->bus->owner == device);
563 
564     /* release lock */
565     return rt_mutex_release(&(device->bus->lock));
566 }
567 
rt_spi_take(struct rt_spi_device * device)568 rt_err_t rt_spi_take(struct rt_spi_device *device)
569 {
570     rt_ssize_t result;
571     struct rt_spi_message message;
572 
573     RT_ASSERT(device != RT_NULL);
574     RT_ASSERT(device->bus != RT_NULL);
575 
576     rt_memset(&message, 0, sizeof(message));
577     message.cs_take = 1;
578 
579     result = device->bus->ops->xfer(device, &message);
580     if (result < 0)
581     {
582         return (rt_err_t)result;
583     }
584 
585     return RT_EOK;
586 }
587 
rt_spi_release(struct rt_spi_device * device)588 rt_err_t rt_spi_release(struct rt_spi_device *device)
589 {
590     rt_ssize_t result;
591     struct rt_spi_message message;
592 
593     RT_ASSERT(device != RT_NULL);
594     RT_ASSERT(device->bus != RT_NULL);
595 
596     rt_memset(&message, 0, sizeof(message));
597     message.cs_release = 1;
598 
599     result = device->bus->ops->xfer(device, &message);
600     if (result < 0)
601     {
602         return (rt_err_t)result;
603     }
604 
605     return RT_EOK;
606 }
607