2 * Copyright © 2010 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; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20 /* Default pin usage for existing Altus Metrum devices */
23 #define SPI_CONST 0xff
27 * USART0 SPI config alt 1
34 * USART0 SPI config alt 2
41 * USART1 SPI config alt 1
48 * USART1 SPI config alt 2
56 * Chip select is the responsibility of the caller in master mode
60 #define SPI_BUF_0 &U0DBUFXADDR
61 #define SPI_CSR_0 U0CSR
62 #define SPI_BAUD_0 U0BAUD
63 #define SPI_GCR_0 U0GCR
64 #define SPI_CFG_MASK_0 PERCFG_U0CFG_ALT_MASK
65 #define SPI_DMA_TX_0 DMA_CFG0_TRIGGER_UTX0
66 #define SPI_DMA_RX_0 DMA_CFG0_TRIGGER_URX0
69 #define SPI_CFG_0 PERCFG_U0CFG_ALT_1
70 #define SPI_SEL_0 P0SEL
71 #define SPI_BITS_0 (1 << 3) | (1 << 2) | (1 << 5)
72 #define SPI_CSS_BIT_0 (1 << 4)
76 #define SPI_CFG_0 PERCFG_U0CFG_ALT_2
77 #define SPI_SEL_0 P1SEL
78 #define SPI_PRI_0 P2SEL_PRI3P1_USART0
79 #define SPI_BITS_0 (1 << 5) | (1 << 4) | (1 << 3)
80 #define SPI_CSS_BIT_0 (1 << 2)
86 #define SPI_BUF_1 &U1DBUFXADDR
87 #define SPI_CSR_1 U1CSR
88 #define SPI_BAUD_1 U1BAUD
89 #define SPI_GCR_1 U1GCR
90 #define SPI_CFG_MASK_1 PERCFG_U1CFG_ALT_MASK
91 #define SPI_DMA_TX_1 DMA_CFG0_TRIGGER_UTX1
92 #define SPI_DMA_RX_1 DMA_CFG0_TRIGGER_URX1
95 #define SPI_CFG_1 PERCFG_U1CFG_ALT_1
96 #define SPI_SEL_1 P0SEL
97 #define SPI_BITS_1 (1 << 4) | (1 << 5) | (1 << 3)
98 #define SPI_CSS_BIT_1 (1 << 2)
102 #define SPI_CFG_1 PERCFG_U1CFG_ALT_2
103 #define SPI_SEL_1 P1SEL
104 #define SPI_PRI_1 P2SEL_PRI3P1_USART1
105 #define SPI_BITS_1 (1 << 6) | (1 << 7) | (1 << 5)
106 #define SPI_CSS_BIT_1 (1 << 4)
113 #define SPI_BUF(bus) ((bus) ? SPI_BUF_1 : SPI_BUF_0)
114 #define SPI_CSR(bus) ((bus) ? SPI_CSR_1 : SPI_CSR_0)
115 #define SPI_BAUD(bus) ((bus) ? SPI_BAUD_1 : SPI_BAUD_0)
116 #define SPI_GCR(bus) ((bus) ? SPI_GCR_1 : SPI_GCR_0)
117 #define SPI_CFG_MASK(bus) ((bus) ? SPI_CFG_MASK_1 : SPI_CFG_MASK_0)
118 #define SPI_DMA_TX(bus) ((bus) ? SPI_DMA_TX_1 : SPI_DMA_TX_0)
119 #define SPI_DMA_RX(bus) ((bus) ? SPI_DMA_RX_1 : SPI_DMA_RX_0)
120 #define SPI_CFG(bus) ((bus) ? SPI_CFG_1 : SPI_CFG_0)
121 #define SPI_SEL(bus) ((bus) ? SPI_SEL_1 : SPI_SEL_0)
122 #define SPI_BITS(bus) ((bus) ? SPI_BITS_1 : SPI_BITS_0)
123 #define SPI_CSS_BIT(bus) ((bus) ? SPI_CSS_BIT_1 : SPI_CSS_BIT_0)
128 #define SPI_BUF(bus) SPI_BUF_0
129 #define SPI_CSR(bus) SPI_CSR_0
130 #define SPI_BAUD(bus) SPI_BAUD_0
131 #define SPI_GCR(bus) SPI_GCR_0
132 #define SPI_CFG_MASK(bus) SPI_CFG_MASK_0
133 #define SPI_DMA_TX(bus) SPI_DMA_TX_0
134 #define SPI_DMA_RX(bus) SPI_DMA_RX_0
135 #define SPI_CFG(bus) SPI_CFG_0
136 #define SPI_SEL(bus) SPI_SEL_0
137 #define SPI_BITS(bus) SPI_BITS_0
138 #define SPI_CSS_BIT(bus) SPI_CSS_BIT_0
141 #define SPI_BUF(bus) SPI_BUF_1
142 #define SPI_CSR(bus) SPI_CSR_1
143 #define SPI_BAUD(bus) SPI_BAUD_1
144 #define SPI_GCR(bus) SPI_GCR_1
145 #define SPI_CFG_MASK(bus) SPI_CFG_MASK_1
146 #define SPI_DMA_TX(bus) SPI_DMA_TX_1
147 #define SPI_DMA_RX(bus) SPI_DMA_RX_1
148 #define SPI_CFG(bus) SPI_CFG_1
149 #define SPI_SEL(bus) SPI_SEL_1
150 #define SPI_BITS(bus) SPI_BITS_1
151 #define SPI_CSS_BIT(bus) SPI_CSS_BIT_1
154 #endif /* MULTI_SPI */
157 #define CSS(bus) SPI_CSS_BIT(bus)
158 #define UxCSR_DIRECTION UxCSR_SLAVE
161 #define UxCSR_DIRECTION UxCSR_MASTER
164 /* Shared mutex to protect SPI bus, must cover the entire
165 * operation, from CS low to CS high. This means that any SPI
166 * user must protect the SPI bus with this mutex
168 __xdata uint8_t ao_spi_mutex[N_SPI];
169 __xdata uint8_t ao_spi_dma_in_done[N_SPI];
170 __xdata uint8_t ao_spi_dma_out_done[N_SPI];
172 uint8_t ao_spi_dma_out_id[N_SPI];
173 uint8_t ao_spi_dma_in_id[N_SPI];
175 static __xdata uint8_t ao_spi_const;
178 /* Send bytes over SPI.
180 * This sets up two DMA engines, one writing the data and another reading
181 * bytes coming back. We use the bytes coming back to tell when the transfer
182 * is complete, as the transmit register is double buffered and hence signals
183 * completion one byte before the transfer is actually complete
187 ao_spi_send(void __xdata *block, uint16_t len, uint8_t bus) __reentrant
190 ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant
194 ao_dma_set_transfer(ao_spi_dma_in_id[bus],
198 DMA_CFG0_WORDSIZE_8 |
199 DMA_CFG0_TMODE_SINGLE |
203 DMA_CFG1_PRIORITY_NORMAL);
204 ao_dma_set_transfer(ao_spi_dma_out_id[bus],
208 DMA_CFG0_WORDSIZE_8 |
209 DMA_CFG0_TMODE_SINGLE |
213 DMA_CFG1_PRIORITY_NORMAL);
215 ao_dma_start(ao_spi_dma_in_id[bus]);
216 ao_dma_start(ao_spi_dma_out_id[bus]);
217 ao_dma_trigger(ao_spi_dma_out_id[bus]);
219 __critical while (!ao_spi_dma_in_done[bus])
220 ao_sleep(&ao_spi_dma_in_done[bus]);
227 ao_spi_send_wait(void)
229 __critical while (!ao_spi_dma_in_done[0])
230 ao_sleep(&ao_spi_dma_in_done[0]);
234 /* Receive bytes over SPI.
236 * This sets up tow DMA engines, one reading the data and another
237 * writing constant values to the SPI transmitter as that is what
238 * clocks the data coming in.
242 ao_spi_recv(void __xdata *block, uint16_t len, uint8_t bus) __reentrant
245 ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant
249 ao_dma_set_transfer(ao_spi_dma_in_id[bus],
253 DMA_CFG0_WORDSIZE_8 |
254 DMA_CFG0_TMODE_SINGLE |
258 DMA_CFG1_PRIORITY_NORMAL);
260 ao_spi_const = SPI_CONST;
263 ao_dma_set_transfer(ao_spi_dma_out_id[bus],
267 DMA_CFG0_WORDSIZE_8 |
268 DMA_CFG0_TMODE_SINGLE |
272 DMA_CFG1_PRIORITY_NORMAL);
275 ao_dma_start(ao_spi_dma_in_id[bus]);
277 ao_dma_start(ao_spi_dma_out_id[bus]);
278 ao_dma_trigger(ao_spi_dma_out_id[bus]);
279 __critical while (!ao_spi_dma_in_done[bus])
280 ao_sleep(&ao_spi_dma_in_done[bus]);
286 ao_spi_recv_wait(void)
288 __critical while (!ao_spi_dma_in_done[0])
289 ao_sleep(&ao_spi_dma_in_done[0]);
295 * SPI master/slave mode
297 /* Set the baud rate and signal parameters
299 * The cc1111 is limited to a 24/8 MHz SPI clock.
300 * Every peripheral I've ever seen goes faster than that,
301 * so set the clock to 3MHz (BAUD_E 17, BAUD_M 0)
303 #define SPI_INIT(bus,o) do { \
304 /* Set up the USART pin assignment */ \
305 PERCFG = (PERCFG & ~SPI_CFG_MASK(bus)) | SPI_CFG(bus); \
307 /* Make the SPI pins be controlled by the USART peripheral */ \
308 SPI_SEL(bus) |= SPI_BITS(bus) | CSS(bus); \
309 SPI_CSR(bus) = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_DIRECTION); \
311 SPI_GCR(bus) = (UxGCR_CPOL_NEGATIVE | \
312 UxGCR_CPHA_FIRST_EDGE | \
314 (17 << UxGCR_BAUD_E_SHIFT)); \
315 /* Set up OUT DMA */ \
316 ao_spi_dma_out_id[o] = ao_dma_alloc(&ao_spi_dma_out_done[o]); \
318 /* Set up IN DMA */ \
319 ao_spi_dma_in_id[o] = ao_dma_alloc(&ao_spi_dma_in_done[o]); \
325 /* Ensure that SPI USART takes precidence over the other USART
326 * for pins that they share
329 P2SEL = (P2SEL & ~P2SEL_PRI3P1_MASK) | SPI_PRI;
336 SPI_INIT(1, MULTI_SPI);