2 * Copyright © 2020 Keith Packard <keithp@keithp.com>
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.
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.
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.
21 static uint8_t ao_spi_mutex;
22 static uint8_t ao_spi_pin_config;
24 #define AO_DMA_SPI1_RX_INDEX STM_DMA_INDEX(2)
25 #define AO_DMA_SPI1_RX_CSELR STM_DMA_CSELR_C2S_SPI1_RX
26 #define AO_DMA_SPI1_TX_INDEX STM_DMA_INDEX(3)
27 #define AO_DMA_SPI1_TX_CSELR STM_DMA_CSELR_C3S_SPI1_TX
30 static uint8_t spi_dev_null;
33 ao_spi_set_dma_mosi(uint8_t id, const void *data, uint16_t len, uint32_t minc)
36 struct stm_spi *stm_spi = &stm_spi1;
38 ao_dma_set_transfer(AO_DMA_SPI1_TX_INDEX,
42 (0 << STM_DMA_CCR_MEM2MEM) |
43 (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
44 (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
45 (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
46 (minc << STM_DMA_CCR_MINC) |
47 (0 << STM_DMA_CCR_PINC) |
48 (0 << STM_DMA_CCR_CIRC) |
49 (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
53 ao_spi_set_dma_miso(uint8_t id, void *data, uint16_t len, uint32_t minc)
56 uint8_t miso_dma_index = STM_DMA_INDEX(2);
57 struct stm_spi *stm_spi = &stm_spi1;
59 ao_dma_set_transfer(miso_dma_index,
63 (0 << STM_DMA_CCR_MEM2MEM) |
64 (STM_DMA_CCR_PL_HIGH << STM_DMA_CCR_PL) |
65 (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
66 (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
67 (minc << STM_DMA_CCR_MINC) |
68 (0 << STM_DMA_CCR_PINC) |
69 (0 << STM_DMA_CCR_CIRC) |
70 (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
74 ao_spi_run(uint8_t id, uint8_t which, uint16_t len)
77 uint8_t mosi_dma_index = STM_DMA_INDEX(3);
78 uint8_t miso_dma_index = STM_DMA_INDEX(2);
79 struct stm_spi *stm_spi = &stm_spi1;
81 stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
82 (0 << STM_SPI_CR2_RXNEIE) |
83 (0 << STM_SPI_CR2_ERRIE) |
84 (0 << STM_SPI_CR2_SSOE) |
85 (1 << STM_SPI_CR2_TXDMAEN) |
86 (1 << STM_SPI_CR2_RXDMAEN));
88 ao_dma_start(miso_dma_index);
89 ao_dma_start(mosi_dma_index);
92 while (!ao_dma_done[miso_dma_index])
93 ao_sleep(&ao_dma_done[miso_dma_index]);
96 while ((stm_spi->sr & (1 << STM_SPI_SR_TXE)) == 0);
97 while (stm_spi->sr & (1 << STM_SPI_SR_BSY));
101 ao_dma_done_transfer(mosi_dma_index);
102 ao_dma_done_transfer(miso_dma_index);
107 ao_spi_send(const void *block, uint16_t len, uint8_t spi_index)
111 /* Set up the transmit DMA to deliver data */
112 ao_spi_set_dma_mosi(id, block, len, 1);
114 /* Set up the receive DMA -- when this is done, we know the SPI unit
115 * is idle. Without this, we'd have to poll waiting for the BSY bit to
118 ao_spi_set_dma_miso(id, &spi_dev_null, len, 0);
120 ao_spi_run(id, 1, len);
122 const uint8_t *bytes = block;
123 struct stm_spi *stm_spi = &stm_spi1;
126 while ((stm_spi->sr & (1 << STM_SPI_SR_TXE)) == 0);
127 stm_spi->dr = *bytes++;
128 while ((stm_spi->sr & (1 << STM_SPI_SR_RXNE)) == 0);
136 ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index)
138 uint8_t id = AO_SPI_INDEX(spi_index);
140 /* Set up the transmit DMA to deliver data */
141 ao_spi_set_dma_mosi(id, &value, len, 0);
143 /* Set up the receive DMA -- when this is done, we know the SPI unit
144 * is idle. Without this, we'd have to poll waiting for the BSY bit to
147 ao_spi_set_dma_miso(id, &spi_dev_null, len, 0);
149 ao_spi_run(id, 3, len);
153 ao_spi_start_bytes(uint8_t spi_index)
156 struct stm_spi *stm_spi = &stm_spi1;
158 stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
159 (0 << STM_SPI_CR2_RXNEIE) |
160 (0 << STM_SPI_CR2_ERRIE) |
161 (0 << STM_SPI_CR2_SSOE) |
162 (0 << STM_SPI_CR2_TXDMAEN) |
163 (0 << STM_SPI_CR2_RXDMAEN));
167 ao_spi_stop_bytes(uint8_t spi_index)
170 struct stm_spi *stm_spi = &stm_spi1;
172 while ((stm_spi->sr & (1 << STM_SPI_SR_TXE)) == 0)
174 while (stm_spi->sr & (1 << STM_SPI_SR_BSY))
176 /* Clear the OVR flag */
183 ao_spi_send_sync(const void *block, uint16_t len, uint8_t spi_index)
186 const uint8_t *b = block;
187 struct stm_spi *stm_spi = &stm_spi1;
189 stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
190 (0 << STM_SPI_CR2_RXNEIE) |
191 (0 << STM_SPI_CR2_ERRIE) |
192 (0 << STM_SPI_CR2_SSOE) |
193 (0 << STM_SPI_CR2_TXDMAEN) |
194 (0 << STM_SPI_CR2_RXDMAEN));
196 while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE)));
199 while ((stm_spi->sr & (1 << STM_SPI_SR_TXE)) == 0)
201 while (stm_spi->sr & (1 << STM_SPI_SR_BSY))
203 /* Clear the OVR flag */
210 ao_spi_recv(void *block, uint16_t len, uint8_t spi_index)
217 /* Set up transmit DMA to make the SPI hardware actually run */
218 ao_spi_set_dma_mosi(id, &spi_dev_null, len, 0);
220 /* Set up the receive DMA to capture data */
221 ao_spi_set_dma_miso(id, block, len, 1);
223 ao_spi_run(id, 9, len);
225 uint8_t *bytes = block;
226 struct stm_spi *stm_spi = &stm_spi1;
229 while ((stm_spi->sr & (1 << STM_SPI_SR_TXE)) == 0);
231 while ((stm_spi->sr & (1 << STM_SPI_SR_RXNE)) == 0);
232 *bytes++ = stm_spi->dr;
239 ao_spi_duplex(const void *out, void *in, uint16_t len, uint8_t spi_index)
241 uint8_t id = AO_SPI_INDEX(spi_index);
243 /* Set up transmit DMA to send data */
244 ao_spi_set_dma_mosi(id, out, len, 1);
246 /* Set up the receive DMA to capture data */
247 ao_spi_set_dma_miso(id, in, len, 1);
249 ao_spi_run(id, 11, len);
254 ao_spi_disable_pin_config(uint8_t spi_pin_config)
256 /* Disable current config
258 switch (spi_pin_config) {
259 case AO_SPI_1_PA5_PA6_PA7:
260 stm_gpio_set(&stm_gpioa, 5, 1);
261 stm_moder_set(&stm_gpioa, 5, STM_MODER_OUTPUT);
262 stm_moder_set(&stm_gpioa, 6, STM_MODER_INPUT);
263 stm_moder_set(&stm_gpioa, 7, STM_MODER_OUTPUT);
265 case AO_SPI_1_PA12_PA13_PA14:
266 stm_gpio_set(&stm_gpioa, 13, 1);
267 stm_moder_set(&stm_gpioa, 13, STM_MODER_OUTPUT); /* clk */
268 stm_moder_set(&stm_gpioa, 12, STM_MODER_OUTPUT); /* mosi */
269 stm_moder_set(&stm_gpioa, 14, STM_MODER_INPUT); /* miso */
271 case AO_SPI_1_PB3_PB4_PB5:
272 stm_gpio_set(&stm_gpiob, 3, 1);
273 stm_moder_set(&stm_gpiob, 3, STM_MODER_OUTPUT);
274 stm_moder_set(&stm_gpiob, 4, STM_MODER_INPUT);
275 stm_moder_set(&stm_gpiob, 5, STM_MODER_OUTPUT);
281 ao_spi_enable_pin_config(uint8_t spi_pin_config)
285 switch (spi_pin_config) {
286 case AO_SPI_1_PA5_PA6_PA7:
287 stm_afr_set(&stm_gpioa, 5, STM_AFR_AF0);
288 stm_afr_set(&stm_gpioa, 6, STM_AFR_AF0);
289 stm_afr_set(&stm_gpioa, 7, STM_AFR_AF0);
291 case AO_SPI_1_PA12_PA13_PA14:
292 stm_afr_set(&stm_gpioe, 12, STM_AFR_AF0); /* yes, AF0 */
293 stm_afr_set(&stm_gpioe, 13, STM_AFR_AF5);
294 stm_afr_set(&stm_gpioe, 14, STM_AFR_AF5);
296 case AO_SPI_1_PB3_PB4_PB5:
297 stm_afr_set(&stm_gpiob, 3, STM_AFR_AF0);
298 stm_afr_set(&stm_gpiob, 4, STM_AFR_AF0);
299 stm_afr_set(&stm_gpiob, 5, STM_AFR_AF0);
305 ao_spi_config(uint8_t spi_index, uint32_t speed)
307 uint8_t spi_pin_config = AO_SPI_PIN_CONFIG(spi_index);
308 struct stm_spi *stm_spi = &stm_spi1;
310 if (spi_pin_config != ao_spi_pin_config) {
312 /* Disable old config
314 ao_spi_disable_pin_config(ao_spi_pin_config);
318 ao_spi_enable_pin_config(spi_pin_config);
320 /* Remember current config
322 ao_spi_pin_config = spi_pin_config;
325 /* Turn the SPI transceiver on and set the mode */
326 stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) | /* Three wire mode */
327 (0 << STM_SPI_CR1_BIDIOE) |
328 (0 << STM_SPI_CR1_CRCEN) | /* CRC disabled */
329 (0 << STM_SPI_CR1_CRCNEXT) |
330 (0 << STM_SPI_CR1_DFF) |
331 (0 << STM_SPI_CR1_RXONLY) |
332 (1 << STM_SPI_CR1_SSM) | /* Software SS handling */
333 (1 << STM_SPI_CR1_SSI) | /* ... */
334 (0 << STM_SPI_CR1_LSBFIRST) | /* Big endian */
335 (1 << STM_SPI_CR1_SPE) | /* Enable SPI unit */
336 (speed << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */
337 (1 << STM_SPI_CR1_MSTR) |
338 (AO_SPI_CPOL(spi_index) << STM_SPI_CR1_CPOL) | /* Format */
339 (AO_SPI_CPHA(spi_index) << STM_SPI_CR1_CPHA));
344 ao_spi_try_get(uint8_t spi_index, uint32_t speed, uint8_t task_id)
346 uint8_t id = AO_SPI_INDEX(spi_index);
348 if (!ao_mutex_try(&ao_spi_mutex[id], task_id))
350 ao_spi_config(spi_index, speed);
356 ao_spi_get(uint8_t spi_index, uint32_t speed)
360 ao_mutex_get(&ao_spi_mutex);
361 ao_spi_config(spi_index, speed);
365 ao_spi_put(uint8_t spi_index)
368 struct stm_spi *stm_spi = &stm_spi1;
371 ao_mutex_put(&ao_spi_mutex);
375 ao_spi_channel_init(uint8_t spi_index)
378 struct stm_spi *stm_spi = &stm_spi1;
380 ao_spi_disable_pin_config(AO_SPI_PIN_CONFIG(spi_index));
383 stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
384 (0 << STM_SPI_CR2_RXNEIE) |
385 (0 << STM_SPI_CR2_ERRIE) |
386 (0 << STM_SPI_CR2_SSOE) |
387 (0 << STM_SPI_CR2_TXDMAEN) |
388 (0 << STM_SPI_CR2_RXDMAEN));
390 /* Clear any pending data and error flags */
397 ao_spi_dump_cmd(void)
401 for (s = 0; s < 64; s++) {
402 int i = (spi_task_index + s) & 63;
403 if (spi_tasks[i].which) {
405 const char *name = "(none)";
406 for (t = 0; t < ao_num_tasks; t++)
407 if (ao_tasks[t]->task_id == spi_tasks[i].task) {
408 name = ao_tasks[t]->name;
411 printf("%2d: %5d task %2d which %2d len %5d %s\n",
420 for (s = 0; s < STM_NUM_SPI; s++) {
421 struct stm_spi *spi = ao_spi_stm_info[s].stm_spi;
423 printf("%1d: mutex %2d index %3d miso dma %3d mosi dma %3d",
424 s, ao_spi_mutex[s], ao_spi_index[s],
425 ao_spi_stm_info[s].miso_dma_index,
426 ao_spi_stm_info[s].mosi_dma_index);
427 printf(" cr1 %04x cr2 %02x sr %03x\n",
428 spi->cr1, spi->cr2, spi->sr);
433 static const struct ao_cmds ao_spi_cmds[] = {
434 { ao_spi_dump_cmd, "S\0Dump SPI status" },
443 # if SPI_1_PA5_PA6_PA7
444 ao_enable_port(&stm_gpioa);
445 stm_ospeedr_set(&stm_gpioa, 5, SPI_1_OSPEEDR);
446 stm_ospeedr_set(&stm_gpioa, 6, SPI_1_OSPEEDR);
447 stm_ospeedr_set(&stm_gpioa, 7, SPI_1_OSPEEDR);
449 # if SPI_1_PB3_PB4_PB5
450 ao_enable_port(&stm_gpiob);
451 stm_ospeedr_set(&stm_gpiob, 3, SPI_1_OSPEEDR);
452 stm_ospeedr_set(&stm_gpiob, 4, SPI_1_OSPEEDR);
453 stm_ospeedr_set(&stm_gpiob, 5, SPI_1_OSPEEDR);
455 # if SPI_1_PE13_PE14_PE15
456 ao_enable_port(&stm_gpioe);
457 stm_ospeedr_set(&stm_gpioe, 13, SPI_1_OSPEEDR);
458 stm_ospeedr_set(&stm_gpioe, 14, SPI_1_OSPEEDR);
459 stm_ospeedr_set(&stm_gpioe, 15, SPI_1_OSPEEDR);
461 stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN);
462 ao_spi_pin_config = AO_SPI_CONFIG_NONE;
463 ao_spi_channel_init(0);
465 ao_dma_alloc(AO_DMA_SPI1_RX_INDEX, AO_DMA_SPI1_RX_CSELR);
466 ao_dma_alloc(AO_DMA_SPI1_TX_INDEX, AO_DMA_SPI1_TX_CSELR);
471 # if SPI_2_PB13_PB14_PB15
472 ao_enable_port(&stm_gpiob);
473 stm_ospeedr_set(&stm_gpiob, 13, SPI_2_OSPEEDR);
474 stm_ospeedr_set(&stm_gpiob, 14, SPI_2_OSPEEDR);
475 stm_ospeedr_set(&stm_gpiob, 15, SPI_2_OSPEEDR);
476 # define HAS_SPI_2_CONFIG 1
478 # if SPI_2_PD1_PD3_PD4
479 ao_enable_port(&stm_gpiod);
480 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN);
481 stm_ospeedr_set(&stm_gpiod, 1, SPI_2_OSPEEDR);
482 stm_ospeedr_set(&stm_gpiod, 3, SPI_2_OSPEEDR);
483 stm_ospeedr_set(&stm_gpiod, 4, SPI_2_OSPEEDR);
484 # define HAS_SPI_2_CONFIG 1
486 # ifndef HAS_SPI_2_CONFIG 1
487 #error "no config for SPI2"
489 stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN);
490 ao_spi_pin_config[1] = AO_SPI_CONFIG_NONE;
491 ao_spi_channel_init(1);
492 ao_dma_alloc(AO_DMA_SPI2_RX_INDEX, AO_DMA_SPI2_RX_CSELR);
493 ao_dma_alloc(AO_DMA_SPI2_TX_INDEX, AO_DMA_SPI2_TX_CSELR);
496 ao_cmd_register(&ao_spi_cmds[0]);