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