1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "swspi.h"
18 
19 #include <assert.h>
20 #include <lib/spi/srv/dev.h>
21 #include <stdint.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <trusty/time.h>
25 #include <uapi/err.h>
26 
27 #define TLOG_TAG "swspi-drv"
28 #include <trusty_log.h>
29 
spi_is_bus_shared(struct spi_dev_ctx * dev)30 bool spi_is_bus_shared(struct spi_dev_ctx* dev) {
31     return dev->bus->num_devs > 1;
32 }
33 
spi_dev_seq_active(struct spi_dev_ctx * dev)34 static inline bool spi_dev_seq_active(struct spi_dev_ctx* dev) {
35     return dev->cmds;
36 }
37 
spi_req_exec_set_clk(struct spi_dev_ctx * dev,void * priv)38 static void spi_req_exec_set_clk(struct spi_dev_ctx* dev, void* priv) {
39     /* Not a real device. No clock to configure */
40 }
41 
spi_req_set_clk(struct spi_dev_ctx * dev,uint64_t * clk_hz)42 int spi_req_set_clk(struct spi_dev_ctx* dev, uint64_t* clk_hz) {
43     assert(dev);
44     assert(clk_hz);
45 
46     dev->cmds[dev->curr_cmd].exec = spi_req_exec_set_clk;
47     dev->curr_cmd++;
48     return NO_ERROR;
49 }
50 
spi_req_exec_cs_assert(struct spi_dev_ctx * dev,void * priv)51 static void spi_req_exec_cs_assert(struct spi_dev_ctx* dev, void* priv) {
52     assert(dev->bus->owner == NULL);
53     /* become bus owner */
54     dev->bus->owner = dev;
55 }
56 
spi_req_cs_assert(struct spi_dev_ctx * dev)57 int spi_req_cs_assert(struct spi_dev_ctx* dev) {
58     assert(spi_dev_seq_active(dev));
59     assert(dev->curr_cmd < dev->num_cmds);
60 
61     dev->cmds[dev->curr_cmd].exec = spi_req_exec_cs_assert;
62     dev->curr_cmd++;
63     return NO_ERROR;
64 }
65 
spi_req_exec_cs_deassert(struct spi_dev_ctx * dev,void * priv)66 static void spi_req_exec_cs_deassert(struct spi_dev_ctx* dev, void* priv) {
67     assert(dev->bus->owner == dev);
68     /* release the bus */
69     dev->bus->owner = NULL;
70 }
71 
spi_req_cs_deassert(struct spi_dev_ctx * dev)72 int spi_req_cs_deassert(struct spi_dev_ctx* dev) {
73     assert(spi_dev_seq_active(dev));
74     assert(dev->curr_cmd < dev->num_cmds);
75 
76     dev->cmds[dev->curr_cmd].exec = spi_req_exec_cs_deassert;
77     dev->curr_cmd++;
78     return NO_ERROR;
79 }
80 
81 /* calculate an 8-bit digest of a buffer */
digest(uint8_t * buf,size_t sz)82 static uint8_t digest(uint8_t* buf, size_t sz) {
83     uint8_t digest = 0;
84 
85     for (size_t i = 0; i < sz; i++) {
86         /* rotate right one bit */
87         digest = digest >> 1 | (digest & 0x1) << 7;
88         digest ^= buf[i];
89     }
90     return digest;
91 }
92 
93 /* fill buffer with predefined pattern */
rand_buf(uint8_t * buf,size_t sz,uint8_t seed)94 static void rand_buf(uint8_t* buf, size_t sz, uint8_t seed) {
95     /* seed RNG */
96     srand(seed);
97 
98     for (size_t i = 0; i < sz; i++) {
99         buf[i] = rand() % 0xff;
100     }
101 }
102 
103 struct spi_req_xfer_args {
104     void* tx;
105     void* rx;
106     size_t len;
107 };
108 
109 /*
110  * This device calculates an 8-bit digest of TX buffer, seeds rand() with that
111  * digest, fills RX with random bytes, and sends it back to us. If it's a
112  * receive-only transfer, i.e. no TX buffer, use seed 0.
113  */
spi_req_exec_xfer(struct spi_dev_ctx * dev,void * priv)114 static void spi_req_exec_xfer(struct spi_dev_ctx* dev, void* priv) {
115     struct spi_req_xfer_args* args = (struct spi_req_xfer_args*)priv;
116     void* tx = args->tx;
117     void* rx = args->rx;
118     size_t len = args->len;
119     uint8_t seed = 0;
120 
121     if (dev->loopback) {
122         if (rx) {
123             if (tx) {
124                 memcpy(rx, tx, len);
125             } else {
126                 memset(rx, 0, len);
127             }
128         }
129         return;
130     }
131 
132     if (tx) {
133         seed = digest(tx, len);
134     }
135 
136     if (rx) {
137         rand_buf(rx, len, seed);
138     }
139 }
140 
spi_req_xfer(struct spi_dev_ctx * dev,void * tx,void * rx,size_t len)141 int spi_req_xfer(struct spi_dev_ctx* dev, void* tx, void* rx, size_t len) {
142     assert(spi_dev_seq_active(dev));
143     assert(dev->curr_cmd < dev->num_cmds);
144 
145     struct spi_req_xfer_args* args = malloc(sizeof(*args));
146     if (!args) {
147         TLOGE("failed to allocate memory for arguments for xfer requests\n");
148         return ERR_NO_MEMORY;
149     }
150     args->tx = tx;
151     args->rx = rx;
152     args->len = len;
153 
154     dev->cmds[dev->curr_cmd].exec = spi_req_exec_xfer;
155     dev->cmds[dev->curr_cmd].priv = args;
156     dev->curr_cmd++;
157     return NO_ERROR;
158 }
159 
spi_req_exec_delay(struct spi_dev_ctx * dev,void * priv)160 static void spi_req_exec_delay(struct spi_dev_ctx* dev, void* priv) {
161     uint64_t delay_ns = *((uint64_t*)priv);
162     trusty_nanosleep(0, 0, delay_ns);
163 }
164 
spi_req_delay(struct spi_dev_ctx * dev,uint64_t delay_ns)165 int spi_req_delay(struct spi_dev_ctx* dev, uint64_t delay_ns) {
166     assert(dev);
167 
168     uint64_t* arg = malloc(sizeof(*arg));
169     if (!arg) {
170         TLOGE("failed to allocate memory for delay argument\n");
171         return ERR_NO_MEMORY;
172     }
173     *arg = delay_ns;
174 
175     dev->cmds[dev->curr_cmd].exec = spi_req_exec_delay;
176     dev->cmds[dev->curr_cmd].priv = arg;
177     dev->curr_cmd++;
178     return NO_ERROR;
179 }
180 
spi_seq_begin(struct spi_dev_ctx * dev,size_t num_cmds)181 int spi_seq_begin(struct spi_dev_ctx* dev, size_t num_cmds) {
182     assert(!spi_dev_seq_active(dev));
183 
184     /* allocate SPI sequence represented by an array of &struct spi_seq_entry */
185     dev->cmds = calloc(num_cmds, sizeof(struct spi_seq_entry));
186     if (!dev->cmds) {
187         TLOGE("failed to allocate memory for SPI sequence\n");
188         return ERR_NO_MEMORY;
189     }
190 
191     dev->num_cmds = num_cmds;
192     return NO_ERROR;
193 }
194 
spi_seq_free(struct spi_dev_ctx * dev)195 static void spi_seq_free(struct spi_dev_ctx* dev) {
196     for (size_t i = 0; i < dev->num_cmds; i++) {
197         void* priv = dev->cmds[i].priv;
198         if (priv) {
199             free(priv);
200         }
201     }
202     free(dev->cmds);
203     dev->cmds = NULL;
204     dev->num_cmds = 0;
205     dev->curr_cmd = 0;
206 }
207 
spi_seq_commit(struct spi_dev_ctx * dev)208 int spi_seq_commit(struct spi_dev_ctx* dev) {
209     void* priv;
210     size_t i;
211 
212     assert(spi_dev_seq_active(dev));
213     assert(dev->curr_cmd == dev->num_cmds);
214 
215     /* iterate through SPI sequence and execute each SPI request */
216     for (i = 0; i < dev->num_cmds; i++) {
217         priv = dev->cmds[i].priv;
218         dev->cmds[i].exec(dev, priv);
219     }
220 
221     spi_seq_free(dev);
222     return NO_ERROR;
223 }
224 
spi_seq_abort(struct spi_dev_ctx * dev)225 void spi_seq_abort(struct spi_dev_ctx* dev) {
226     assert(spi_dev_seq_active(dev));
227     spi_seq_free(dev);
228 }
229