• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 <errno.h>
18 #include <heap.h>
19 #include <string.h>
20 
21 #include <cpu.h>
22 #include <spi.h>
23 #include <spi_priv.h>
24 #include <timer.h>
25 
26 #define INFO_PRINT(fmt, ...) do { \
27         osLog(LOG_INFO, "%s " fmt, "[spi]", ##__VA_ARGS__); \
28     } while (0);
29 
30 #define ERROR_PRINT(fmt, ...) do { \
31         osLog(LOG_ERROR, "%s " fmt, "[spi] ERROR:", ##__VA_ARGS__); \
32     } while (0);
33 
34 struct SpiDeviceState {
35     struct SpiDevice dev;
36 
37     const struct SpiPacket *packets;
38     size_t n;
39     size_t currentBuf;
40     struct SpiMode mode;
41     uint16_t tid;
42 
43     SpiCbkF rxTxCallback;
44     void *rxTxCookie;
45 
46     SpiCbkF finishCallback;
47     void *finishCookie;
48 
49     int err;
50 };
51 #define SPI_DEVICE_TO_STATE(p) ((struct SpiDeviceState *)p)
52 
53 static void spiMasterNext(struct SpiDeviceState *state);
54 static void spiMasterStop(struct SpiDeviceState *state);
55 static void spiMasterDone(struct SpiDeviceState *state, int err);
56 
57 static void spiSlaveNext(struct SpiDeviceState *state);
58 static void spiSlaveIdle(struct SpiDeviceState *state, int err);
59 static void spiSlaveDone(struct SpiDeviceState *state);
60 
spiMasterStart(struct SpiDeviceState * state,spi_cs_t cs,const struct SpiMode * mode)61 static int spiMasterStart(struct SpiDeviceState *state,
62         spi_cs_t cs, const struct SpiMode *mode)
63 {
64     struct SpiDevice *dev = &state->dev;
65 
66     if (dev->ops->masterStartAsync)
67         return dev->ops->masterStartAsync(dev, cs, mode);
68 
69     if (dev->ops->masterStartSync) {
70         int err = dev->ops->masterStartSync(dev, cs, mode);
71         if (err < 0)
72             return err;
73     }
74 
75     return dev->ops->masterRxTx(dev, state->packets[0].rxBuf,
76             state->packets[0].txBuf, state->packets[0].size, mode);
77 }
78 
spi_masterStartAsync_done(struct SpiDevice * dev,int err)79 void spi_masterStartAsync_done(struct SpiDevice *dev, int err)
80 {
81     struct SpiDeviceState *state = SPI_DEVICE_TO_STATE(dev);
82     if (err)
83         spiMasterDone(state, err);
84     else
85         spiMasterNext(state);
86 }
87 
spiDelayCallback(uint32_t timerId,void * data)88 static void spiDelayCallback(uint32_t timerId, void *data)
89 {
90     spiMasterNext((struct SpiDeviceState *)data);
91 }
92 
spiMasterNext(struct SpiDeviceState * state)93 static void spiMasterNext(struct SpiDeviceState *state)
94 {
95     struct SpiDevice *dev = &state->dev;
96 
97     if (state->currentBuf == state->n) {
98         spiMasterStop(state);
99         return;
100     }
101 
102     size_t i = state->currentBuf;
103     void *rxBuf = state->packets[i].rxBuf;
104     const void *txBuf = state->packets[i].txBuf;
105     size_t size = state->packets[i].size;
106     const struct SpiMode *mode = &state->mode;
107 
108     int err = dev->ops->masterRxTx(dev, rxBuf, txBuf, size, mode);
109     if (err)
110         spiMasterDone(state, err);
111 }
112 
spiMasterRxTxDone(struct SpiDevice * dev,int err)113 void spiMasterRxTxDone(struct SpiDevice *dev, int err)
114 {
115     struct SpiDeviceState *state = SPI_DEVICE_TO_STATE(dev);
116     if (err) {
117         spiMasterDone(state, err);
118     } else {
119         size_t i = state->currentBuf++;
120 
121         if (state->packets[i].delay > 0) {
122             if (!timTimerSet(state->packets[i].delay, 0, 50, spiDelayCallback, state, true)) {
123                 ERROR_PRINT("Cannot do delayed spi, timer depleted\n");
124                 spiMasterDone(state, -ENOMEM); // should be out of timer; out of mem is close enough
125             }
126         } else {
127             spiMasterNext(state);
128         }
129     }
130 }
131 
spiMasterStop(struct SpiDeviceState * state)132 static void spiMasterStop(struct SpiDeviceState *state)
133 {
134     struct SpiDevice *dev = &state->dev;
135 
136     if (dev->ops->masterStopSync) {
137         int err = dev->ops->masterStopSync(dev);
138         spiMasterDone(state, err);
139     } else if (dev->ops->masterStopAsync) {
140         int err = dev->ops->masterStopAsync(dev);
141         if (err < 0)
142             spiMasterDone(state, err);
143     } else {
144         spiMasterDone(state, 0);
145     }
146 }
147 
spiMasterStopAsyncDone(struct SpiDevice * dev,int err)148 void spiMasterStopAsyncDone(struct SpiDevice *dev, int err)
149 {
150     struct SpiDeviceState *state = SPI_DEVICE_TO_STATE(dev);
151     spiMasterDone(state, err);
152 }
153 
spiMasterDone(struct SpiDeviceState * state,int err)154 static void spiMasterDone(struct SpiDeviceState *state, int err)
155 {
156     SpiCbkF callback = state->rxTxCallback;
157     void *cookie = state->rxTxCookie;
158 
159     uint16_t oldTid = osSetCurrentTid(state->tid);
160     callback(cookie, err);
161     osSetCurrentTid(oldTid);
162 }
163 
spiSlaveStart(struct SpiDeviceState * state,const struct SpiMode * mode)164 static int spiSlaveStart(struct SpiDeviceState *state,
165         const struct SpiMode *mode)
166 {
167     struct SpiDevice *dev = &state->dev;
168 
169     if (dev->ops->slaveStartAsync)
170         return dev->ops->slaveStartAsync(dev, mode);
171 
172     if (dev->ops->slaveStartSync) {
173         int err = dev->ops->slaveStartSync(dev, mode);
174         if (err < 0)
175             return err;
176     }
177 
178     return dev->ops->slaveIdle(dev, mode);
179 }
180 
spiSlaveStartAsyncDone(struct SpiDevice * dev,int err)181 void spiSlaveStartAsyncDone(struct SpiDevice *dev, int err)
182 {
183     struct SpiDeviceState *state = SPI_DEVICE_TO_STATE(dev);
184 
185     if (err)
186         state->err = err;
187     else
188         state->err = dev->ops->slaveIdle(dev, &state->mode);
189 }
190 
spiSlaveRxTxDone(struct SpiDevice * dev,int err)191 void spiSlaveRxTxDone(struct SpiDevice *dev, int err)
192 {
193     struct SpiDeviceState *state = SPI_DEVICE_TO_STATE(dev);
194 
195     if (err) {
196         spiSlaveIdle(state, err);
197     } else {
198         state->currentBuf++;
199         spiSlaveNext(state);
200     }
201 }
202 
spiSlaveCsInactive(struct SpiDevice * dev)203 void spiSlaveCsInactive(struct SpiDevice *dev)
204 {
205     struct SpiDeviceState *state = SPI_DEVICE_TO_STATE(dev);
206 
207     dev->ops->slaveSetCsInterrupt(dev, false);
208 
209     if (!state->finishCallback) {
210         osLog(LOG_WARN, "%s called without callback\n", __func__);
211         return;
212     }
213 
214     SpiCbkF callback = state->finishCallback;
215     void *cookie = state->finishCookie;
216     state->finishCallback = NULL;
217     state->finishCookie = NULL;
218 
219     uint16_t oldTid = osSetCurrentTid(state->tid);
220     callback(cookie, 0);
221     osSetCurrentTid(oldTid);
222 }
223 
spiSlaveNext(struct SpiDeviceState * state)224 static void spiSlaveNext(struct SpiDeviceState *state)
225 {
226     struct SpiDevice *dev = &state->dev;
227 
228     if (state->currentBuf == state->n) {
229         spiSlaveIdle(state, 0);
230         return;
231     }
232 
233     size_t i = state->currentBuf;
234     void *rxBuf = state->packets[i].rxBuf;
235     const void *txBuf = state->packets[i].txBuf;
236     size_t size = state->packets[i].size;
237     const struct SpiMode *mode = &state->mode;
238 
239     int err = dev->ops->slaveRxTx(dev, rxBuf, txBuf, size, mode);
240     if (err)
241         spiSlaveIdle(state, err);
242 }
243 
spiSlaveIdle(struct SpiDeviceState * state,int err)244 static void spiSlaveIdle(struct SpiDeviceState *state, int err)
245 {
246     struct SpiDevice *dev = &state->dev;
247     SpiCbkF callback = state->rxTxCallback;
248     void *cookie = state->rxTxCookie;
249 
250     if (!err)
251         err = dev->ops->slaveIdle(dev, &state->mode);
252 
253     uint16_t oldTid = osSetCurrentTid(state->tid);
254     callback(cookie, err);
255     osSetCurrentTid(oldTid);
256 }
257 
spiSlaveStopAsyncDone(struct SpiDevice * dev,int err)258 void spiSlaveStopAsyncDone(struct SpiDevice *dev, int err)
259 {
260     struct SpiDeviceState *state = SPI_DEVICE_TO_STATE(dev);
261     spiSlaveDone(state);
262 }
263 
spiSlaveDone(struct SpiDeviceState * state)264 static void spiSlaveDone(struct SpiDeviceState *state)
265 {
266     struct SpiDevice *dev = &state->dev;
267 
268     if (dev->ops->release)
269         dev->ops->release(dev);
270     heapFree(state);
271 }
272 
spiSetupRxTx(struct SpiDeviceState * state,const struct SpiPacket packets[],size_t n,SpiCbkF callback,void * cookie)273 static int spiSetupRxTx(struct SpiDeviceState *state,
274         const struct SpiPacket packets[], size_t n,
275         SpiCbkF callback, void *cookie)
276 {
277     state->packets = packets;
278     state->n = n;
279     state->currentBuf = 0;
280     state->rxTxCallback = callback;
281     state->rxTxCookie = cookie;
282     state->tid = osGetCurrentTid();
283 
284     return 0;
285 }
286 
spiMasterRequest(uint8_t busId,struct SpiDevice ** dev_out)287 int spiMasterRequest(uint8_t busId, struct SpiDevice **dev_out)
288 {
289     int ret = 0;
290 
291     struct SpiDeviceState *state = heapAlloc(sizeof(*state));
292     if (!state)
293         return -ENOMEM;
294     struct SpiDevice *dev = &state->dev;
295 
296     ret = spiRequest(dev, busId);
297     if (ret < 0)
298         goto err_request;
299 
300     if (!dev->ops->masterRxTx) {
301         ret = -EOPNOTSUPP;
302         goto err_opsupp;
303     }
304 
305     *dev_out = dev;
306     return 0;
307 
308 err_opsupp:
309     if (dev->ops->release)
310         dev->ops->release(dev);
311 err_request:
312     heapFree(state);
313     return ret;
314 }
315 
spiMasterRxTx(struct SpiDevice * dev,spi_cs_t cs,const struct SpiPacket packets[],size_t n,const struct SpiMode * mode,SpiCbkF callback,void * cookie)316 int spiMasterRxTx(struct SpiDevice *dev, spi_cs_t cs,
317         const struct SpiPacket packets[], size_t n,
318         const struct SpiMode *mode, SpiCbkF callback,
319         void *cookie)
320 {
321     struct SpiDeviceState *state = SPI_DEVICE_TO_STATE(dev);
322     int ret = 0;
323 
324     if (!n)
325         return -EINVAL;
326 
327     ret = spiSetupRxTx(state, packets, n, callback, cookie);
328     if (ret < 0)
329         return ret;
330 
331     state->mode = *mode;
332 
333     return spiMasterStart(state, cs, mode);
334 }
335 
spiMasterRelease(struct SpiDevice * dev)336 int spiMasterRelease(struct SpiDevice *dev)
337 {
338     struct SpiDeviceState *state = SPI_DEVICE_TO_STATE(dev);
339 
340     if (dev->ops->release) {
341         int ret = dev->ops->release(dev);
342         if (ret < 0)
343             return ret;
344     }
345 
346     heapFree(state);
347     return 0;
348 }
349 
spiSlaveRequest(uint8_t busId,const struct SpiMode * mode,struct SpiDevice ** dev_out)350 int spiSlaveRequest(uint8_t busId, const struct SpiMode *mode,
351         struct SpiDevice **dev_out)
352 {
353     int ret = 0;
354 
355     struct SpiDeviceState *state = heapAlloc(sizeof(*state));
356     if (!state)
357         return -ENOMEM;
358     struct SpiDevice *dev = &state->dev;
359 
360     ret = spiRequest(dev, busId);
361     if (ret < 0)
362         goto err_request;
363 
364     if (!dev->ops->slaveIdle || !dev->ops->slaveRxTx) {
365         ret = -EOPNOTSUPP;
366         goto err_opsupp;
367     }
368 
369     state->mode = *mode;
370     state->err = 0;
371 
372     ret = spiSlaveStart(state, mode);
373     if (ret < 0)
374         goto err_opsupp;
375 
376     *dev_out = dev;
377     return 0;
378 
379 err_opsupp:
380     if (dev->ops->release)
381         dev->ops->release(dev);
382 err_request:
383     heapFree(state);
384     return ret;
385 }
386 
spiSlaveRxTx(struct SpiDevice * dev,const struct SpiPacket packets[],size_t n,SpiCbkF callback,void * cookie)387 int spiSlaveRxTx(struct SpiDevice *dev,
388         const struct SpiPacket packets[], size_t n,
389         SpiCbkF callback, void *cookie)
390 {
391     struct SpiDeviceState *state = SPI_DEVICE_TO_STATE(dev);
392 
393     if (!n)
394         return -EINVAL;
395 
396     if (state->err)
397         return state->err;
398 
399     int ret = spiSetupRxTx(state, packets, n, callback, cookie);
400     if (ret < 0)
401         return ret;
402 
403     return dev->ops->slaveRxTx(dev, state->packets[0].rxBuf,
404             state->packets[0].txBuf, state->packets[0].size, &state->mode);
405 }
406 
spiSlaveWaitForInactive(struct SpiDevice * dev,SpiCbkF callback,void * cookie)407 int spiSlaveWaitForInactive(struct SpiDevice *dev, SpiCbkF callback,
408         void *cookie)
409 {
410     struct SpiDeviceState *state = SPI_DEVICE_TO_STATE(dev);
411 
412     if (!dev->ops->slaveSetCsInterrupt || !dev->ops->slaveCsIsActive)
413         return -EOPNOTSUPP;
414 
415     state->finishCallback = callback;
416     state->finishCookie = cookie;
417 
418     uint64_t flags = cpuIntsOff();
419     dev->ops->slaveSetCsInterrupt(dev, true);
420 
421     /* CS may already be inactive before enabling the interrupt.  In this case
422      * roll back and fire the callback immediately.
423      *
424      * Interrupts must be off while checking for this.  Otherwise there is a
425      * (very unlikely) race where the CS interrupt fires between calling
426      * slaveSetCsInterrupt(true) and the rollback
427      * slaveSetCsInterrupt(false), causing the event to be handled twice.
428      *
429      * Likewise the check must come after enabling the interrupt.  Otherwise
430      * there is an (also unlikely) race where CS goes inactive between reading
431      * CS and enabling the interrupt, causing the event to be lost.
432      */
433 
434     bool cs = dev->ops->slaveCsIsActive(dev);
435     if (!cs) {
436         dev->ops->slaveSetCsInterrupt(dev, false);
437         cpuIntsRestore(flags);
438 
439         state->finishCallback = NULL;
440         state->finishCookie = NULL;
441         callback(cookie, 0);
442         return 0;
443     }
444 
445     cpuIntsRestore(flags);
446     return 0;
447 }
448 
spiSlaveRelease(struct SpiDevice * dev)449 int spiSlaveRelease(struct SpiDevice *dev)
450 {
451     struct SpiDeviceState *state = SPI_DEVICE_TO_STATE(dev);
452     int ret;
453 
454     if (dev->ops->slaveStopSync) {
455         ret = dev->ops->slaveStopSync(dev);
456         if (ret < 0)
457             return ret;
458     } else if (dev->ops->slaveStopAsync) {
459         return dev->ops->slaveStopAsync(dev);
460     }
461 
462     spiSlaveDone(state);
463     return 0;
464 }
465