altos/stm: Make ao_spi_duplex out pointer const
[fw/altos] / src / stm / ao_spi_stm.c
1 /*
2  * Copyright © 2012 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 #include <ao.h>
20
21 struct ao_spi_stm_info {
22         uint8_t miso_dma_index;
23         uint8_t mosi_dma_index;
24         struct stm_spi *stm_spi;
25 };
26
27 static uint8_t          ao_spi_mutex[STM_NUM_SPI];
28 static uint8_t          ao_spi_index[STM_NUM_SPI];
29
30 static const struct ao_spi_stm_info ao_spi_stm_info[STM_NUM_SPI] = {
31         {
32                 .miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_RX),
33                 .mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_TX),
34                 &stm_spi1
35         },
36         {
37                 .miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_RX),
38                 .mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_TX),
39                 &stm_spi2
40         }
41 };
42
43 static uint8_t  spi_dev_null;
44
45 #if DEBUG
46 static struct {
47         uint8_t task;
48         uint8_t which;
49         AO_TICK_TYPE tick;
50         uint16_t len;
51 } spi_tasks[64];
52 static uint8_t  spi_task_index;
53
54 static void
55 validate_spi(struct stm_spi *stm_spi, int which, uint16_t len)
56 {
57         uint32_t        sr = stm_spi->sr;
58
59         if (stm_spi != &stm_spi2)
60                 return;
61         spi_tasks[spi_task_index].task = ao_cur_task ? ao_cur_task->task_id : 0;
62         spi_tasks[spi_task_index].which = which;
63         spi_tasks[spi_task_index].tick = ao_time();
64         spi_tasks[spi_task_index].len = len;
65         spi_task_index = (spi_task_index + 1) & (63);
66         if (sr & (1 << STM_SPI_SR_FRE))
67                 ao_panic(0x40 | 1);
68         if (sr & (1 << STM_SPI_SR_BSY))
69                 ao_panic(0x40 | 2);
70         if (sr & (1 << STM_SPI_SR_OVR))
71                 ao_panic(0x40 | 3);
72         if (sr & (1 << STM_SPI_SR_MODF))
73                 ao_panic(0x40 | 4);
74         if (sr & (1 << STM_SPI_SR_UDR))
75                 ao_panic(0x40 | 5);
76         if ((sr & (1 << STM_SPI_SR_TXE)) == 0)
77                 ao_panic(0x40 | 6);
78         if (sr & (1 << STM_SPI_SR_RXNE))
79                 ao_panic(0x40 | 7);
80         if (which != 5 && which != 6 && which != 13)
81                 if (ao_cur_task->task_id != ao_spi_mutex[1])
82                         ao_panic(0x40 | 8);
83 }
84 #else
85 #define validate_spi(stm_spi, which, len) do { (void) (which); (void) (len); } while (0)
86 #endif
87
88 static void
89 ao_spi_run(uint8_t id, uint8_t which, uint16_t len)
90 {
91         struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
92         uint8_t mosi_dma_index = ao_spi_stm_info[id].mosi_dma_index;
93         uint8_t miso_dma_index = ao_spi_stm_info[id].miso_dma_index;
94
95         validate_spi(stm_spi, which, len);
96
97         stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
98                         (0 << STM_SPI_CR2_RXNEIE) |
99                         (0 << STM_SPI_CR2_ERRIE) |
100                         (0 << STM_SPI_CR2_SSOE) |
101                         (1 << STM_SPI_CR2_TXDMAEN) |
102                         (1 << STM_SPI_CR2_RXDMAEN));
103
104         ao_dma_start(miso_dma_index);
105         ao_dma_start(mosi_dma_index);
106
107         ao_arch_critical(
108                 while (!ao_dma_done[miso_dma_index])
109                         ao_sleep(&ao_dma_done[miso_dma_index]);
110                 );
111
112         while ((stm_spi->sr & (1 << STM_SPI_SR_TXE)) == 0);
113         while (stm_spi->sr & (1 << STM_SPI_SR_BSY));
114
115         validate_spi(stm_spi, which+1, len);
116
117         stm_spi->cr2 = 0;
118
119         ao_dma_done_transfer(mosi_dma_index);
120         ao_dma_done_transfer(miso_dma_index);
121 }
122
123 void
124 ao_spi_send(const void *block, uint16_t len, uint8_t spi_index)
125 {
126         uint8_t id = AO_SPI_INDEX(spi_index);
127         struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
128         uint8_t mosi_dma_index = ao_spi_stm_info[id].mosi_dma_index;
129         uint8_t miso_dma_index = ao_spi_stm_info[id].miso_dma_index;
130
131         /* Set up the transmit DMA to deliver data */
132         ao_dma_set_transfer(mosi_dma_index,
133                             &stm_spi->dr,
134                             (void *) block,
135                             len,
136                             (0 << STM_DMA_CCR_MEM2MEM) |
137                             (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
138                             (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
139                             (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
140                             (1 << STM_DMA_CCR_MINC) |
141                             (0 << STM_DMA_CCR_PINC) |
142                             (0 << STM_DMA_CCR_CIRC) |
143                             (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
144
145         /* Set up the receive DMA -- when this is done, we know the SPI unit
146          * is idle. Without this, we'd have to poll waiting for the BSY bit to
147          * be cleared
148          */
149         ao_dma_set_transfer(miso_dma_index,
150                             &stm_spi->dr,
151                             &spi_dev_null,
152                             len,
153                             (0 << STM_DMA_CCR_MEM2MEM) |
154                             (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
155                             (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
156                             (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
157                             (0 << STM_DMA_CCR_MINC) |
158                             (0 << STM_DMA_CCR_PINC) |
159                             (0 << STM_DMA_CCR_CIRC) |
160                             (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
161
162         ao_spi_run(id, 1, len);
163 }
164
165 void
166 ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index)
167 {
168         uint8_t id = AO_SPI_INDEX(spi_index);
169         struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
170         uint8_t mosi_dma_index = ao_spi_stm_info[id].mosi_dma_index;
171         uint8_t miso_dma_index = ao_spi_stm_info[id].miso_dma_index;
172
173         /* Set up the transmit DMA to deliver data */
174         ao_dma_set_transfer(mosi_dma_index,
175                             &stm_spi->dr,
176                             &value,
177                             len,
178                             (0 << STM_DMA_CCR_MEM2MEM) |
179                             (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
180                             (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
181                             (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
182                             (0 << STM_DMA_CCR_MINC) |
183                             (0 << STM_DMA_CCR_PINC) |
184                             (0 << STM_DMA_CCR_CIRC) |
185                             (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
186
187         /* Set up the receive DMA -- when this is done, we know the SPI unit
188          * is idle. Without this, we'd have to poll waiting for the BSY bit to
189          * be cleared
190          */
191         ao_dma_set_transfer(miso_dma_index,
192                             &stm_spi->dr,
193                             &spi_dev_null,
194                             len,
195                             (0 << STM_DMA_CCR_MEM2MEM) |
196                             (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
197                             (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
198                             (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
199                             (0 << STM_DMA_CCR_MINC) |
200                             (0 << STM_DMA_CCR_PINC) |
201                             (0 << STM_DMA_CCR_CIRC) |
202                             (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
203
204         ao_spi_run(id, 3, len);
205 }
206
207 void
208 ao_spi_start_bytes(uint8_t spi_index)
209 {
210         uint8_t         id = AO_SPI_INDEX(spi_index);
211         struct stm_spi  *stm_spi = ao_spi_stm_info[id].stm_spi;
212
213         stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
214                         (0 << STM_SPI_CR2_RXNEIE) |
215                         (0 << STM_SPI_CR2_ERRIE) |
216                         (0 << STM_SPI_CR2_SSOE) |
217                         (0 << STM_SPI_CR2_TXDMAEN) |
218                         (0 << STM_SPI_CR2_RXDMAEN));
219         validate_spi(stm_spi, 5, 0xffff);
220 }
221
222 void
223 ao_spi_stop_bytes(uint8_t spi_index)
224 {
225         uint8_t         id = AO_SPI_INDEX(spi_index);
226         struct stm_spi  *stm_spi = ao_spi_stm_info[id].stm_spi;
227
228         while ((stm_spi->sr & (1 << STM_SPI_SR_TXE)) == 0)
229                 ;
230         while (stm_spi->sr & (1 << STM_SPI_SR_BSY))
231                 ;
232         /* Clear the OVR flag */
233         (void) stm_spi->dr;
234         (void) stm_spi->sr;
235         validate_spi(stm_spi, 6, 0xffff);
236         stm_spi->cr2 = 0;
237 }
238
239 void
240 ao_spi_send_sync(const void *block, uint16_t len, uint8_t spi_index)
241 {
242         uint8_t         id = AO_SPI_INDEX(spi_index);
243         const uint8_t   *b = block;
244         struct stm_spi  *stm_spi = ao_spi_stm_info[id].stm_spi;
245
246         stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
247                         (0 << STM_SPI_CR2_RXNEIE) |
248                         (0 << STM_SPI_CR2_ERRIE) |
249                         (0 << STM_SPI_CR2_SSOE) |
250                         (0 << STM_SPI_CR2_TXDMAEN) |
251                         (0 << STM_SPI_CR2_RXDMAEN));
252         validate_spi(stm_spi, 7, len);
253         while (len--) {
254                 while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE)));
255                 stm_spi->dr = *b++;
256         }
257         while ((stm_spi->sr & (1 << STM_SPI_SR_TXE)) == 0)
258                 ;
259         while (stm_spi->sr & (1 << STM_SPI_SR_BSY))
260                 ;
261         /* Clear the OVR flag */
262         (void) stm_spi->dr;
263         (void) stm_spi->sr;
264         validate_spi(stm_spi, 8, len);
265 }
266
267 void
268 ao_spi_recv(void *block, uint16_t len, uint8_t spi_index)
269 {
270         uint8_t         id = AO_SPI_INDEX(spi_index);
271         struct stm_spi  *stm_spi = ao_spi_stm_info[id].stm_spi;
272         uint8_t         mosi_dma_index = ao_spi_stm_info[id].mosi_dma_index;
273         uint8_t         miso_dma_index = ao_spi_stm_info[id].miso_dma_index;
274
275         spi_dev_null = 0xff;
276
277         /* Set up transmit DMA to make the SPI hardware actually run */
278         ao_dma_set_transfer(mosi_dma_index,
279                             &stm_spi->dr,
280                             &spi_dev_null,
281                             len,
282                             (0 << STM_DMA_CCR_MEM2MEM) |
283                             (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
284                             (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
285                             (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
286                             (0 << STM_DMA_CCR_MINC) |
287                             (0 << STM_DMA_CCR_PINC) |
288                             (0 << STM_DMA_CCR_CIRC) |
289                             (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
290
291         /* Set up the receive DMA to capture data */
292         ao_dma_set_transfer(miso_dma_index,
293                             &stm_spi->dr,
294                             block,
295                             len,
296                             (0 << STM_DMA_CCR_MEM2MEM) |
297                             (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
298                             (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
299                             (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
300                             (1 << STM_DMA_CCR_MINC) |
301                             (0 << STM_DMA_CCR_PINC) |
302                             (0 << STM_DMA_CCR_CIRC) |
303                             (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
304
305         ao_spi_run(id, 9, len);
306 }
307
308 void
309 ao_spi_duplex(const void *out, void *in, uint16_t len, uint8_t spi_index)
310 {
311         uint8_t         id = AO_SPI_INDEX(spi_index);
312         struct stm_spi  *stm_spi = ao_spi_stm_info[id].stm_spi;
313         uint8_t         mosi_dma_index = ao_spi_stm_info[id].mosi_dma_index;
314         uint8_t         miso_dma_index = ao_spi_stm_info[id].miso_dma_index;
315
316         /* Set up transmit DMA to send data */
317         ao_dma_set_transfer(mosi_dma_index,
318                             &stm_spi->dr,
319                             out,
320                             len,
321                             (0 << STM_DMA_CCR_MEM2MEM) |
322                             (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
323                             (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
324                             (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
325                             (1 << STM_DMA_CCR_MINC) |
326                             (0 << STM_DMA_CCR_PINC) |
327                             (0 << STM_DMA_CCR_CIRC) |
328                             (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
329
330         /* Set up the receive DMA to capture data */
331         ao_dma_set_transfer(miso_dma_index,
332                             &stm_spi->dr,
333                             in,
334                             len,
335                             (0 << STM_DMA_CCR_MEM2MEM) |
336                             (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
337                             (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
338                             (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
339                             (1 << STM_DMA_CCR_MINC) |
340                             (0 << STM_DMA_CCR_PINC) |
341                             (0 << STM_DMA_CCR_CIRC) |
342                             (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
343         ao_spi_run(id, 11, len);
344 }
345
346 static void
347 ao_spi_disable_index(uint8_t spi_index)
348 {
349         /* Disable current config
350          */
351         switch (spi_index) {
352         case AO_SPI_1_PA5_PA6_PA7:
353                 stm_gpio_set(&stm_gpioa, 5, 1);
354                 stm_moder_set(&stm_gpioa, 5, STM_MODER_OUTPUT);
355                 stm_moder_set(&stm_gpioa, 6, STM_MODER_INPUT);
356                 stm_moder_set(&stm_gpioa, 7, STM_MODER_OUTPUT);
357                 break;
358         case AO_SPI_1_PB3_PB4_PB5:
359                 stm_gpio_set(&stm_gpiob, 3, 1);
360                 stm_moder_set(&stm_gpiob, 3, STM_MODER_OUTPUT);
361                 stm_moder_set(&stm_gpiob, 4, STM_MODER_INPUT);
362                 stm_moder_set(&stm_gpiob, 5, STM_MODER_OUTPUT);
363                 break;
364         case AO_SPI_1_PE13_PE14_PE15:
365                 stm_gpio_set(&stm_gpioe, 13, 1);
366                 stm_moder_set(&stm_gpioe, 13, STM_MODER_OUTPUT);
367                 stm_moder_set(&stm_gpioe, 14, STM_MODER_INPUT);
368                 stm_moder_set(&stm_gpioe, 15, STM_MODER_OUTPUT);
369                 break;
370         case AO_SPI_2_PB13_PB14_PB15:
371                 stm_gpio_set(&stm_gpiob, 13, 1);
372                 stm_moder_set(&stm_gpiob, 13, STM_MODER_OUTPUT);
373                 stm_moder_set(&stm_gpiob, 14, STM_MODER_INPUT);
374                 stm_moder_set(&stm_gpiob, 15, STM_MODER_OUTPUT);
375                 break;
376         case AO_SPI_2_PD1_PD3_PD4:
377                 stm_gpio_set(&stm_gpiod, 1, 1);
378                 stm_moder_set(&stm_gpiod, 1, STM_MODER_OUTPUT);
379                 stm_moder_set(&stm_gpiod, 3, STM_MODER_INPUT);
380                 stm_moder_set(&stm_gpiod, 4, STM_MODER_OUTPUT);
381                 break;
382         }
383 }
384
385 static void
386 ao_spi_enable_index(uint8_t spi_index)
387 {
388         /* Enable new config
389          */
390         switch (spi_index) {
391         case AO_SPI_1_PA5_PA6_PA7:
392                 stm_afr_set(&stm_gpioa, 5, STM_AFR_AF5);
393                 stm_afr_set(&stm_gpioa, 6, STM_AFR_AF5);
394                 stm_afr_set(&stm_gpioa, 7, STM_AFR_AF5);
395                 break;
396         case AO_SPI_1_PB3_PB4_PB5:
397                 stm_afr_set(&stm_gpiob, 3, STM_AFR_AF5);
398                 stm_afr_set(&stm_gpiob, 4, STM_AFR_AF5);
399                 stm_afr_set(&stm_gpiob, 5, STM_AFR_AF5);
400                 break;
401         case AO_SPI_1_PE13_PE14_PE15:
402                 stm_afr_set(&stm_gpioe, 13, STM_AFR_AF5);
403                 stm_afr_set(&stm_gpioe, 14, STM_AFR_AF5);
404                 stm_afr_set(&stm_gpioe, 15, STM_AFR_AF5);
405                 break;
406         case AO_SPI_2_PB13_PB14_PB15:
407                 stm_afr_set(&stm_gpiob, 13, STM_AFR_AF5);
408                 stm_afr_set(&stm_gpiob, 14, STM_AFR_AF5);
409                 stm_afr_set(&stm_gpiob, 15, STM_AFR_AF5);
410                 break;
411         case AO_SPI_2_PD1_PD3_PD4:
412                 stm_afr_set(&stm_gpiod, 1, STM_AFR_AF5);
413                 stm_afr_set(&stm_gpiod, 3, STM_AFR_AF5);
414                 stm_afr_set(&stm_gpiod, 4, STM_AFR_AF5);
415                 break;
416         }
417 }
418
419 static void
420 ao_spi_config(uint8_t spi_index, uint32_t speed)
421 {
422         uint8_t         id = AO_SPI_INDEX(spi_index);
423         struct stm_spi  *stm_spi = ao_spi_stm_info[id].stm_spi;
424
425         if (spi_index != ao_spi_index[id]) {
426
427                 /* Disable old config
428                  */
429                 ao_spi_disable_index(ao_spi_index[id]);
430
431                 /* Enable new config
432                  */
433                 ao_spi_enable_index(spi_index);
434
435                 /* Remember current config
436                  */
437                 ao_spi_index[id] = spi_index;
438         }
439         stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) |           /* Three wire mode */
440                         (0 << STM_SPI_CR1_BIDIOE) |
441                         (0 << STM_SPI_CR1_CRCEN) |              /* CRC disabled */
442                         (0 << STM_SPI_CR1_CRCNEXT) |
443                         (0 << STM_SPI_CR1_DFF) |
444                         (0 << STM_SPI_CR1_RXONLY) |
445                         (1 << STM_SPI_CR1_SSM) |                /* Software SS handling */
446                         (1 << STM_SPI_CR1_SSI) |                /*  ... */
447                         (0 << STM_SPI_CR1_LSBFIRST) |           /* Big endian */
448                         (1 << STM_SPI_CR1_SPE) |                /* Enable SPI unit */
449                         (speed << STM_SPI_CR1_BR) |             /* baud rate to pclk/4 */
450                         (1 << STM_SPI_CR1_MSTR) |
451                         (0 << STM_SPI_CR1_CPOL) |               /* Format 0 */
452                         (0 << STM_SPI_CR1_CPHA));
453         validate_spi(stm_spi, 13, 0);
454 }
455
456 uint8_t
457 ao_spi_try_get(uint8_t spi_index, uint32_t speed, uint8_t task_id)
458 {
459         uint8_t         id = AO_SPI_INDEX(spi_index);
460
461         if (!ao_mutex_try(&ao_spi_mutex[id], task_id))
462                 return 0;
463         ao_spi_config(spi_index, speed);
464         return 1;
465 }
466
467 void
468 ao_spi_get(uint8_t spi_index, uint32_t speed)
469 {
470         uint8_t         id = AO_SPI_INDEX(spi_index);
471
472         ao_mutex_get(&ao_spi_mutex[id]);
473         ao_spi_config(spi_index, speed);
474 }
475
476 void
477 ao_spi_put(uint8_t spi_index)
478 {
479         uint8_t         id = AO_SPI_INDEX(spi_index);
480         struct stm_spi  *stm_spi = ao_spi_stm_info[id].stm_spi;
481
482         stm_spi->cr1 = 0;
483         ao_mutex_put(&ao_spi_mutex[id]);
484 }
485
486 static void
487 ao_spi_channel_init(uint8_t spi_index)
488 {
489         uint8_t         id = AO_SPI_INDEX(spi_index);
490         struct stm_spi  *stm_spi = ao_spi_stm_info[id].stm_spi;
491
492         ao_spi_disable_index(spi_index);
493
494         stm_spi->cr1 = 0;
495         stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
496                         (0 << STM_SPI_CR2_RXNEIE) |
497                         (0 << STM_SPI_CR2_ERRIE) |
498                         (0 << STM_SPI_CR2_SSOE) |
499                         (0 << STM_SPI_CR2_TXDMAEN) |
500                         (0 << STM_SPI_CR2_RXDMAEN));
501
502         /* Clear any pending data and error flags */
503         (void) stm_spi->dr;
504         (void) stm_spi->sr;
505 }
506
507 #if DEBUG
508 void
509 ao_spi_dump_cmd(void)
510 {
511         int s;
512
513         for (s = 0; s < 64; s++) {
514                 int i = (spi_task_index + s) & 63;
515                 if (spi_tasks[i].which) {
516                         int t;
517                         const char *name = "(none)";
518                         for (t = 0; t < ao_num_tasks; t++)
519                                 if (ao_tasks[t]->task_id == spi_tasks[i].task) {
520                                         name = ao_tasks[t]->name;
521                                         break;
522                                 }
523                         printf("%2d: %5d task %2d which %2d len %5d %s\n",
524                                s,
525                                spi_tasks[i].tick,
526                                spi_tasks[i].task,
527                                spi_tasks[i].which,
528                                spi_tasks[i].len,
529                                name);
530                 }
531         }
532         for (s = 0; s < STM_NUM_SPI; s++) {
533                 struct stm_spi *spi = ao_spi_stm_info[s].stm_spi;
534
535                 printf("%1d: mutex %2d index %3d miso dma %3d mosi dma %3d",
536                        s, ao_spi_mutex[s], ao_spi_index[s],
537                        ao_spi_stm_info[s].miso_dma_index,
538                        ao_spi_stm_info[s].mosi_dma_index);
539                 printf(" cr1 %04x cr2 %02x sr %03x\n",
540                        spi->cr1, spi->cr2, spi->sr);
541         }
542
543 }
544
545 static const struct ao_cmds ao_spi_cmds[] = {
546         { ao_spi_dump_cmd,      "S\0Dump SPI status" },
547         { 0, NULL }
548 };
549 #endif
550
551 void
552 ao_spi_init(void)
553 {
554 #if HAS_SPI_1
555 # if SPI_1_PA5_PA6_PA7
556         stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN);
557         stm_ospeedr_set(&stm_gpioa, 5, SPI_1_OSPEEDR);
558         stm_ospeedr_set(&stm_gpioa, 6, SPI_1_OSPEEDR);
559         stm_ospeedr_set(&stm_gpioa, 7, SPI_1_OSPEEDR);
560 # endif
561 # if SPI_1_PB3_PB4_PB5
562         stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN);
563         stm_ospeedr_set(&stm_gpiob, 3, SPI_1_OSPEEDR);
564         stm_ospeedr_set(&stm_gpiob, 4, SPI_1_OSPEEDR);
565         stm_ospeedr_set(&stm_gpiob, 5, SPI_1_OSPEEDR);
566 # endif
567 # if SPI_1_PE13_PE14_PE15
568         stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOEEN);
569         stm_ospeedr_set(&stm_gpioe, 13, SPI_1_OSPEEDR);
570         stm_ospeedr_set(&stm_gpioe, 14, SPI_1_OSPEEDR);
571         stm_ospeedr_set(&stm_gpioe, 15, SPI_1_OSPEEDR);
572 # endif
573         stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN);
574         ao_spi_index[0] = AO_SPI_CONFIG_NONE;
575         ao_spi_channel_init(0);
576 #endif
577
578 #if HAS_SPI_2
579 # if SPI_2_PB13_PB14_PB15
580         stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN);
581         stm_ospeedr_set(&stm_gpiob, 13, SPI_2_OSPEEDR);
582         stm_ospeedr_set(&stm_gpiob, 14, SPI_2_OSPEEDR);
583         stm_ospeedr_set(&stm_gpiob, 15, SPI_2_OSPEEDR);
584 # endif
585 # if SPI_2_PD1_PD3_PD4
586         stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN);
587         stm_ospeedr_set(&stm_gpiod, 1, SPI_2_OSPEEDR);
588         stm_ospeedr_set(&stm_gpiod, 3, SPI_2_OSPEEDR);
589         stm_ospeedr_set(&stm_gpiod, 4, SPI_2_OSPEEDR);
590 # endif
591         stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN);
592         ao_spi_index[1] = AO_SPI_CONFIG_NONE;
593         ao_spi_channel_init(1);
594 #endif
595 #if DEBUG
596         ao_cmd_register(&ao_spi_cmds[0]);
597 #endif
598 }