Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

stm32h7: simplify generic SPI driver

Supporting large transfers (>64k) isn't really needed;
the main use case right now is interfacing with an LCD
controller.

Change-Id: I901e5ddb1b4efa9aa650b3e5074537ba785c6d41

authored by

Aidan MacDonald and committed by
Solomon Peachy
8d279aa4 09a31fff

+15 -80
+2 -1
firmware/target/arm/stm32/echoplayer/lcd-echoplayer.c
··· 24 24 #include "spi-stm32h7.h" 25 25 #include "gpio-stm32h7.h" 26 26 #include "regs/stm32h743/rcc.h" 27 + #include "regs/stm32h743/spi.h" 27 28 28 29 struct stm_spi_config spi_cfg = { 29 - .num = STM_SPI5, 30 + .instance = ITA_SPI5, 30 31 .mode = STM_SPIMODE_HALF_DUPLEX, 31 32 .proto = STM_SPIPROTO_MOTOROLA, 32 33 .frame_bits = 9,
+11 -66
firmware/target/arm/stm32/spi-stm32h7.c
··· 20 20 ****************************************************************************/ 21 21 #include "spi-stm32h7.h" 22 22 #include "regs/stm32h743/spi.h" 23 + #include "panic.h" 23 24 24 25 /* 25 26 * Align the max transfer size to ensure it will always be a multiple 26 27 * of 32 bits. This is necessary because an unaligned TSIZE will cause 27 - * some data written to the FIFO to be ignored -- this is OK and the 28 - * intended behavior when it happens at the end of the transfer. But 29 - * we don't want this to happen when TSER > 0 when we're still in the 30 - * middle of the transfer, as it will throw away valid data. 28 + * some data written to the FIFO to be ignored. 31 29 */ 32 30 #define TSIZE_MAX \ 33 - ALIGN_DOWN(reg_vreadf(BM_SPI_CR2_TSIZE, SPI_CR2, TSIZE), sizeof(uint32_t)) 34 - 35 - static struct stm_spi *spi_map[STM_SPI_COUNT]; 36 - static const uint32_t spi_addr[STM_SPI_COUNT] INITDATA_ATTR = { 37 - [STM_SPI1] = ITA_SPI1, 38 - [STM_SPI2] = ITA_SPI2, 39 - [STM_SPI3] = ITA_SPI3, 40 - [STM_SPI4] = ITA_SPI4, 41 - [STM_SPI5] = ITA_SPI5, 42 - [STM_SPI6] = ITA_SPI6, 43 - }; 31 + ALIGN_DOWN(BM_SPI_CR2_TSIZE >> BP_SPI_CR2_TSIZE, sizeof(uint32_t)) 44 32 45 33 static void stm_spi_set_cs(struct stm_spi *spi, bool enable) 46 34 { ··· 53 41 static void stm_spi_enable(struct stm_spi *spi, bool hd_tx, size_t size) 54 42 { 55 43 size_t tsize = size / spi->frame_size; 56 - size_t tser = 0; 57 - size_t left = 0; 58 - 59 44 if (tsize > TSIZE_MAX) 60 - { 61 - tser = tsize - TSIZE_MAX; 62 - tsize = TSIZE_MAX; 63 - 64 - if (tser > TSIZE_MAX) 65 - { 66 - left = tser - TSIZE_MAX; 67 - tser = TSIZE_MAX; 68 - } 69 - } 70 - 71 - /* 72 - * Save number of bytes left for next TSER load, tracked 73 - * separately from the overall transfer size because the 74 - * timing of the SPI_SR.TSERF interrupt isn't clear. We'll 75 - * decrement this by TSIZE_MAX whenever we load TSER in the 76 - * middle of a transfer. 77 - */ 78 - spi->tser_left = left; 45 + panicf("%s: tsize > TSIZE_MAX", __func__); 79 46 80 47 /* TSIZE must be programmed before setting SPE. */ 81 - reg_assignlf(spi->regs, SPI_CR2, TSIZE(tsize), TSER(tser)); 48 + reg_assignlf(spi->regs, SPI_CR2, TSIZE(tsize), TSER(0)); 82 49 reg_writelf(spi->regs, SPI_CR1, HDDIR(hd_tx), SPE(1)); 83 50 } 84 51 ··· 144 111 { 145 112 uint32_t ftlevel; 146 113 147 - spi->regs = spi_addr[config->num]; 114 + spi->regs = config->instance; 148 115 spi->mode = config->mode; 149 116 spi->set_cs = config->set_cs; 150 117 ··· 170 137 * So we can double the threshold setting for SPI1-3. 171 138 * (Maximum allowable threshold is 1/2 the FIFO size.) 172 139 */ 173 - if (config->num <= STM_SPI3) 140 + if (config->instance == ITA_SPI1 || 141 + config->instance == ITA_SPI2 || 142 + config->instance == ITA_SPI3) 143 + { 174 144 ftlevel *= 2; 145 + } 175 146 176 147 /* TODO: allow setting MBR here */ 177 148 reg_writelf(spi->regs, SPI_CFG1, ··· 199 170 IOSWP(config->swap_mosi_miso), 200 171 MIDI(0), 201 172 MSSI(0)); 202 - 203 - spi_map[config->num] = spi; 204 173 } 205 174 206 175 int stm_spi_xfer(struct stm_spi *spi, size_t size, ··· 238 207 { 239 208 uint32_t sr = reg_readl(spi->regs, SPI_SR); 240 209 241 - /* 242 - * Handle continuation of large transfers 243 - * 244 - * TODO - something is not right with this code 245 - */ 246 - if (spi->tser_left > 0 && reg_vreadf(sr, SPI_SR, TSERF)) 247 - { 248 - if (spi->tser_left < TSIZE_MAX) 249 - { 250 - reg_writelf(spi->regs, SPI_CR2, TSER(spi->tser_left)); 251 - spi->tser_left = 0; 252 - } 253 - else 254 - { 255 - reg_writelf(spi->regs, SPI_CR2, TSER(TSIZE_MAX)); 256 - spi->tser_left -= TSIZE_MAX; 257 - } 258 - } 259 - 260 210 /* Handle FIFO write */ 261 211 if (size_tx > 0 && reg_vreadf(sr, SPI_SR, TXP)) 262 212 { ··· 295 245 stm_spi_set_cs(spi, false); 296 246 return 0; 297 247 } 298 - 299 - void spi_irq_handler(void) 300 - { 301 - while (1); 302 - }
+2 -13
firmware/target/arm/stm32/spi-stm32h7.h
··· 26 26 27 27 struct stm_spi; 28 28 29 - enum stm_spi_num 30 - { 31 - STM_SPI1, 32 - STM_SPI2, 33 - STM_SPI3, 34 - STM_SPI4, 35 - STM_SPI5, 36 - STM_SPI6, 37 - STM_SPI_COUNT, 38 - }; 39 - 40 29 /* Must match the SPI_CFG2.COMM register */ 41 30 enum stm_spi_mode 42 31 { ··· 57 46 58 47 struct stm_spi_config 59 48 { 60 - enum stm_spi_num num; 49 + /* Peripheral instance base address; one of ITA_SPIx */ 50 + uint32_t instance; 61 51 enum stm_spi_mode mode; 62 52 enum stm_spi_protocol proto; 63 53 stm_spi_set_cs_t set_cs; ··· 77 67 enum stm_spi_mode mode; 78 68 stm_spi_set_cs_t set_cs; 79 69 uint32_t frame_size; 80 - size_t tser_left; 81 70 }; 82 71 83 72 void stm_spi_init(struct stm_spi *spi,