]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/blob - rpp/src/drv/spi.c
fb3b1e89712a084e4fe29028be7888bfdc61541a
[pes-rpp/rpp-lib.git] / rpp / src / drv / spi.c
1 /* Copyright (C) 2012-2013, 2015 Czech Technical University in Prague
2  *
3  * This document contains proprietary information belonging to Czech
4  * Technical University in Prague. Passing on and copying of this
5  * document, and communication of its contents is not permitted
6  * without prior written authorization.
7  *
8  * File : spi.c
9  */
10
11 #include "drv/spi.h"
12 #include "drv/spi_tms570.h"
13
14 static boolean_t spi_initialized = FALSE;
15
16 int spi_init()
17 {
18         if (spi_initialized == TRUE)
19                 return FAILURE;
20         spi_initialized = TRUE;
21
22         spi_tms570_init();
23         return SUCCESS;
24 }
25
26 static int spi_transfer_callback(struct spi_drv *ifc, int code, struct spi_msg *msg)
27 {
28         if (msg->private)
29                 msg->private = 0;
30         return 0;
31 }
32
33 /*
34  * Send SPI message asynchronously
35  *
36  * This function is thread safe.
37  */
38 int spi_msg_rq_ins(spi_msg_t *msg)
39 {
40         spi_isr_lock_level_t saveif;
41         spi_drv_t *ifc = spi_tms570_get_iface(msg->dev);
42
43         spi_isr_lock(saveif);
44         spi_rq_queue_insert(ifc, msg);
45         spi_isr_unlock(saveif);
46         ifc->ctrl_fnc(ifc, SPI_CTRL_WAKE_RQ, NULL);
47         return 0;
48 }
49
50 /*
51  * Send SPI message synchronously
52  *
53  * This function is thread safe.
54  */
55 int spi_transfer(enum spi_device dev, int rq_len, const void *tx_buf, void *rx_buf)
56 {
57         spi_msg_t msg;
58
59         msg.flags = 0;
60         //msg.ifc = NULL;
61         spi_rq_queue_init_detached(&msg);
62         msg.dev = dev;
63         msg.rq_len = rq_len;
64         msg.tx_buf = tx_buf;
65         msg.rx_buf = rx_buf;
66         msg.callback = spi_transfer_callback;
67         msg.private = 1;
68
69         if (spi_msg_rq_ins(&msg) < 0)
70                 return -1;
71
72         /* Wait for the request completion */
73         while (msg.private)
74                 __memory_barrier();
75
76
77         if (msg.flags & (SPI_MSG_FAIL | SPI_MSG_ABORT))
78                 return -1;
79
80         return msg.rq_len;
81 }
82
83 #define MIN(a,b) ((a) < (b) ? (a) : (b))
84
85 int8_t port_spi_set(const struct port_desc *port, void *values, size_t size)
86 {
87         uint8_t rx[4];
88
89         assert(port->numchn == 1);
90         assert(size == port->bpch/8);
91         assert(size <= sizeof(rx));
92
93         spi_transfer(port->cfg.spi.dev, size, values, rx);
94
95         memcpy(values, rx, MIN(size, port->numchn * port->bpch/8));
96         return SUCCESS;
97 }