1 /*
2  * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "hardware/resets.h"
8 #include "hardware/clocks.h"
9 #include "hardware/spi.h"
10 
spi_reset(spi_inst_t * spi)11 static inline void spi_reset(spi_inst_t *spi) {
12     invalid_params_if(HARDWARE_SPI, spi != spi0 && spi != spi1);
13     reset_block_num(spi == spi0 ? RESET_SPI0 : RESET_SPI1);
14 }
15 
spi_unreset(spi_inst_t * spi)16 static inline void spi_unreset(spi_inst_t *spi) {
17     invalid_params_if(HARDWARE_SPI, spi != spi0 && spi != spi1);
18     unreset_block_num_wait_blocking(spi == spi0 ? RESET_SPI0 : RESET_SPI1);
19 }
20 
spi_init(spi_inst_t * spi,uint baudrate)21 uint spi_init(spi_inst_t *spi, uint baudrate) {
22     spi_reset(spi);
23     spi_unreset(spi);
24 
25     uint baud = spi_set_baudrate(spi, baudrate);
26     spi_set_format(spi, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
27     // Always enable DREQ signals -- harmless if DMA is not listening
28     hw_set_bits(&spi_get_hw(spi)->dmacr, SPI_SSPDMACR_TXDMAE_BITS | SPI_SSPDMACR_RXDMAE_BITS);
29 
30     // Finally enable the SPI
31     hw_set_bits(&spi_get_hw(spi)->cr1, SPI_SSPCR1_SSE_BITS);
32 
33     return baud;
34 }
35 
spi_deinit(spi_inst_t * spi)36 void spi_deinit(spi_inst_t *spi) {
37     hw_clear_bits(&spi_get_hw(spi)->cr1, SPI_SSPCR1_SSE_BITS);
38     hw_clear_bits(&spi_get_hw(spi)->dmacr, SPI_SSPDMACR_TXDMAE_BITS | SPI_SSPDMACR_RXDMAE_BITS);
39     spi_reset(spi);
40 }
41 
spi_set_baudrate(spi_inst_t * spi,uint baudrate)42 uint spi_set_baudrate(spi_inst_t *spi, uint baudrate) {
43     uint freq_in = clock_get_hz(clk_peri);
44     uint prescale, postdiv;
45     invalid_params_if(HARDWARE_SPI, baudrate > freq_in);
46 
47     // Disable the SPI
48     uint32_t enable_mask = spi_get_hw(spi)->cr1 & SPI_SSPCR1_SSE_BITS;
49     hw_clear_bits(&spi_get_hw(spi)->cr1, SPI_SSPCR1_SSE_BITS);
50 
51     // Find smallest prescale value which puts output frequency in range of
52     // post-divide. Prescale is an even number from 2 to 254 inclusive.
53     for (prescale = 2; prescale <= 254; prescale += 2) {
54         if (freq_in < prescale * 256 * (uint64_t) baudrate)
55             break;
56     }
57     invalid_params_if(HARDWARE_SPI, prescale > 254); // Frequency too low
58 
59     // Find largest post-divide which makes output <= baudrate. Post-divide is
60     // an integer in the range 1 to 256 inclusive.
61     for (postdiv = 256; postdiv > 1; --postdiv) {
62         if (freq_in / (prescale * (postdiv - 1)) > baudrate)
63             break;
64     }
65 
66     spi_get_hw(spi)->cpsr = prescale;
67     hw_write_masked(&spi_get_hw(spi)->cr0, (postdiv - 1) << SPI_SSPCR0_SCR_LSB, SPI_SSPCR0_SCR_BITS);
68 
69     // Re-enable the SPI
70     hw_set_bits(&spi_get_hw(spi)->cr1, enable_mask);
71 
72     // Return the frequency we were able to achieve
73     return freq_in / (prescale * postdiv);
74 }
75 
spi_get_baudrate(const spi_inst_t * spi)76 uint spi_get_baudrate(const spi_inst_t *spi) {
77     uint prescale = spi_get_const_hw(spi)->cpsr;
78     uint postdiv = ((spi_get_const_hw(spi)->cr0  & SPI_SSPCR0_SCR_BITS) >> SPI_SSPCR0_SCR_LSB) + 1;
79     return clock_get_hz(clk_peri) / (prescale * postdiv);
80 }
81 
82 // Write len bytes from src to SPI. Simultaneously read len bytes from SPI to dst.
83 // Note this function is guaranteed to exit in a known amount of time (bits sent * time per bit)
__not_in_flash_func(spi_write_read_blocking)84 int __not_in_flash_func(spi_write_read_blocking)(spi_inst_t *spi, const uint8_t *src, uint8_t *dst, size_t len) {
85     invalid_params_if(HARDWARE_SPI, 0 > (int)len);
86 
87     // Never have more transfers in flight than will fit into the RX FIFO,
88     // else FIFO will overflow if this code is heavily interrupted.
89     const size_t fifo_depth = 8;
90     size_t rx_remaining = len, tx_remaining = len;
91 
92     while (rx_remaining || tx_remaining) {
93         if (tx_remaining && spi_is_writable(spi) && rx_remaining < tx_remaining + fifo_depth) {
94             spi_get_hw(spi)->dr = (uint32_t) *src++;
95             --tx_remaining;
96         }
97         if (rx_remaining && spi_is_readable(spi)) {
98             *dst++ = (uint8_t) spi_get_hw(spi)->dr;
99             --rx_remaining;
100         }
101     }
102 
103     return (int)len;
104 }
105 
106 // Write len bytes directly from src to the SPI, and discard any data received back
__not_in_flash_func(spi_write_blocking)107 int __not_in_flash_func(spi_write_blocking)(spi_inst_t *spi, const uint8_t *src, size_t len) {
108     invalid_params_if(HARDWARE_SPI, 0 > (int)len);
109     // Write to TX FIFO whilst ignoring RX, then clean up afterward. When RX
110     // is full, PL022 inhibits RX pushes, and sets a sticky flag on
111     // push-on-full, but continues shifting. Safe if SSPIMSC_RORIM is not set.
112     for (size_t i = 0; i < len; ++i) {
113         while (!spi_is_writable(spi))
114             tight_loop_contents();
115         spi_get_hw(spi)->dr = (uint32_t)src[i];
116     }
117     // Drain RX FIFO, then wait for shifting to finish (which may be *after*
118     // TX FIFO drains), then drain RX FIFO again
119     while (spi_is_readable(spi))
120         (void)spi_get_hw(spi)->dr;
121     while (spi_get_hw(spi)->sr & SPI_SSPSR_BSY_BITS)
122         tight_loop_contents();
123     while (spi_is_readable(spi))
124         (void)spi_get_hw(spi)->dr;
125 
126     // Don't leave overrun flag set
127     spi_get_hw(spi)->icr = SPI_SSPICR_RORIC_BITS;
128 
129     return (int)len;
130 }
131 
132 // Read len bytes directly from the SPI to dst.
133 // repeated_tx_data is output repeatedly on SO as data is read in from SI.
134 // Generally this can be 0, but some devices require a specific value here,
135 // e.g. SD cards expect 0xff
__not_in_flash_func(spi_read_blocking)136 int __not_in_flash_func(spi_read_blocking)(spi_inst_t *spi, uint8_t repeated_tx_data, uint8_t *dst, size_t len) {
137     invalid_params_if(HARDWARE_SPI, 0 > (int)len);
138     const size_t fifo_depth = 8;
139     size_t rx_remaining = len, tx_remaining = len;
140 
141     while (rx_remaining || tx_remaining) {
142         if (tx_remaining && spi_is_writable(spi) && rx_remaining < tx_remaining + fifo_depth) {
143             spi_get_hw(spi)->dr = (uint32_t) repeated_tx_data;
144             --tx_remaining;
145         }
146         if (rx_remaining && spi_is_readable(spi)) {
147             *dst++ = (uint8_t) spi_get_hw(spi)->dr;
148             --rx_remaining;
149         }
150     }
151 
152     return (int)len;
153 }
154 
155 // Write len halfwords from src to SPI. Simultaneously read len halfwords from SPI to dst.
__not_in_flash_func(spi_write16_read16_blocking)156 int __not_in_flash_func(spi_write16_read16_blocking)(spi_inst_t *spi, const uint16_t *src, uint16_t *dst, size_t len) {
157     invalid_params_if(HARDWARE_SPI, 0 > (int)len);
158     // Never have more transfers in flight than will fit into the RX FIFO,
159     // else FIFO will overflow if this code is heavily interrupted.
160     const size_t fifo_depth = 8;
161     size_t rx_remaining = len, tx_remaining = len;
162 
163     while (rx_remaining || tx_remaining) {
164         if (tx_remaining && spi_is_writable(spi) && rx_remaining < tx_remaining + fifo_depth) {
165             spi_get_hw(spi)->dr = (uint32_t) *src++;
166             --tx_remaining;
167         }
168         if (rx_remaining && spi_is_readable(spi)) {
169             *dst++ = (uint16_t) spi_get_hw(spi)->dr;
170             --rx_remaining;
171         }
172     }
173 
174     return (int)len;
175 }
176 
177 // Write len bytes directly from src to the SPI, and discard any data received back
__not_in_flash_func(spi_write16_blocking)178 int __not_in_flash_func(spi_write16_blocking)(spi_inst_t *spi, const uint16_t *src, size_t len) {
179     invalid_params_if(HARDWARE_SPI, 0 > (int)len);
180     // Deliberately overflow FIFO, then clean up afterward, to minimise amount
181     // of APB polling required per halfword
182     for (size_t i = 0; i < len; ++i) {
183         while (!spi_is_writable(spi))
184             tight_loop_contents();
185         spi_get_hw(spi)->dr = (uint32_t)src[i];
186     }
187 
188     while (spi_is_readable(spi))
189         (void)spi_get_hw(spi)->dr;
190     while (spi_get_hw(spi)->sr & SPI_SSPSR_BSY_BITS)
191         tight_loop_contents();
192     while (spi_is_readable(spi))
193         (void)spi_get_hw(spi)->dr;
194 
195     // Don't leave overrun flag set
196     spi_get_hw(spi)->icr = SPI_SSPICR_RORIC_BITS;
197 
198     return (int)len;
199 }
200 
201 // Read len halfwords directly from the SPI to dst.
202 // repeated_tx_data is output repeatedly on SO as data is read in from SI.
__not_in_flash_func(spi_read16_blocking)203 int __not_in_flash_func(spi_read16_blocking)(spi_inst_t *spi, uint16_t repeated_tx_data, uint16_t *dst, size_t len) {
204     invalid_params_if(HARDWARE_SPI, 0 > (int)len);
205     const size_t fifo_depth = 8;
206     size_t rx_remaining = len, tx_remaining = len;
207 
208     while (rx_remaining || tx_remaining) {
209         if (tx_remaining && spi_is_writable(spi) && rx_remaining < tx_remaining + fifo_depth) {
210             spi_get_hw(spi)->dr = (uint32_t) repeated_tx_data;
211             --tx_remaining;
212         }
213         if (rx_remaining && spi_is_readable(spi)) {
214             *dst++ = (uint16_t) spi_get_hw(spi)->dr;
215             --rx_remaining;
216         }
217     }
218 
219     return (int)len;
220 }
221