1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2019-03-18 ZYH first version
9 */
10
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include <spi.h>
14
15 #ifdef RT_USING_SPI
16 #include "drv_spi.h"
17 #include <drv_io_config.h>
18 #include <drivers/dev_spi.h>
19 #include "dmalock.h"
20 #include <sysctl.h>
21 #include <gpiohs.h>
22 #include <string.h>
23 #include "utils.h"
24
25 #define DRV_SPI_DEVICE(spi_bus) (struct drv_spi_bus *)(spi_bus)
26
27 #define MAX_CLOCK (40000000UL)
28
29 struct drv_spi_bus
30 {
31 struct rt_spi_bus parent;
32 spi_device_num_t spi_instance;
33 dmac_channel_number_t dma_send_channel;
34 dmac_channel_number_t dma_recv_channel;
35 struct rt_completion dma_completion;
36 };
37
38 struct drv_cs
39 {
40 int cs_index;
41 int cs_pin;
42 };
43
44 static volatile spi_t *const spi_instance[4] =
45 {
46 (volatile spi_t *)SPI0_BASE_ADDR,
47 (volatile spi_t *)SPI1_BASE_ADDR,
48 (volatile spi_t *)SPI_SLAVE_BASE_ADDR,
49 (volatile spi_t *)SPI3_BASE_ADDR
50 };
51
drv_spi_configure(struct rt_spi_device * device,struct rt_spi_configuration * configuration)52 static rt_err_t drv_spi_configure(struct rt_spi_device *device,
53 struct rt_spi_configuration *configuration)
54 {
55 rt_err_t ret = RT_EOK;
56 int freq = 0;
57 struct drv_spi_bus *bus = DRV_SPI_DEVICE(device->bus);
58 struct drv_cs * cs = (struct drv_cs *)device->parent.user_data;
59 RT_ASSERT(bus != RT_NULL);
60
61 gpiohs_set_drive_mode(cs->cs_pin, GPIO_DM_OUTPUT);
62 gpiohs_set_pin(cs->cs_pin, GPIO_PV_HIGH);
63
64 #ifdef BSP_USING_SPI1_AS_QSPI
65 /* Todo:QSPI*/
66 #else
67 spi_init(bus->spi_instance, configuration->mode & RT_SPI_MODE_3, SPI_FF_STANDARD, configuration->data_width, 0);
68 #endif
69 freq = spi_set_clk_rate(bus->spi_instance, configuration->max_hz > MAX_CLOCK ? MAX_CLOCK : configuration->max_hz);
70 rt_kprintf("set spi freq %d\n", freq);
71 return ret;
72 }
73
74
__spi_set_tmod(uint8_t spi_num,uint32_t tmod)75 void __spi_set_tmod(uint8_t spi_num, uint32_t tmod)
76 {
77 RT_ASSERT(spi_num < SPI_DEVICE_MAX);
78 volatile spi_t *spi_handle = spi[spi_num];
79 uint8_t tmod_offset = 0;
80 switch(spi_num)
81 {
82 case 0:
83 case 1:
84 case 2:
85 tmod_offset = 8;
86 break;
87 case 3:
88 default:
89 tmod_offset = 10;
90 break;
91 }
92 set_bit(&spi_handle->ctrlr0, 3 << tmod_offset, tmod << tmod_offset);
93 }
dma_irq_callback(void * ctx)94 int dma_irq_callback(void *ctx)
95 {
96 struct rt_completion * cmp = ctx;
97 if(cmp)
98 {
99 rt_completion_done(cmp);
100 }
101 }
102
drv_spi_xfer(struct rt_spi_device * device,struct rt_spi_message * message)103 static rt_uint32_t drv_spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
104 {
105 struct drv_spi_bus *bus = DRV_SPI_DEVICE(device->bus);
106 struct drv_cs * cs = (struct drv_cs *)device->parent.user_data;
107 struct rt_spi_configuration *cfg = &device->config;
108 uint32_t * tx_buff = RT_NULL;
109 uint32_t * rx_buff = RT_NULL;
110 int i;
111 rt_ubase_t dummy = 0xFFFFFFFFU;
112 if(cfg->data_width != 8)
113 {
114 return 0;
115 }
116
117 RT_ASSERT(bus != RT_NULL);
118
119 if(message->cs_take)
120 {
121 gpiohs_set_pin(cs->cs_pin, GPIO_PV_LOW);
122 }
123 if(message->length)
124 {
125 bus->dma_send_channel = DMAC_CHANNEL_MAX;
126 bus->dma_recv_channel = DMAC_CHANNEL_MAX;
127
128 rt_completion_init(&bus->dma_completion);
129 if(message->recv_buf)
130 {
131 dmalock_sync_take(&bus->dma_recv_channel, RT_WAITING_FOREVER);
132 sysctl_dma_select(bus->dma_recv_channel, SYSCTL_DMA_SELECT_SSI0_RX_REQ + bus->spi_instance * 2);
133 rx_buff = rt_calloc(message->length * 4, 1);
134 if(!rx_buff)
135 {
136 goto transfer_done;
137 }
138 }
139
140 if(message->send_buf)
141 {
142 dmalock_sync_take(&bus->dma_send_channel, RT_WAITING_FOREVER);
143 sysctl_dma_select(bus->dma_send_channel, SYSCTL_DMA_SELECT_SSI0_TX_REQ + bus->spi_instance * 2);
144 tx_buff = rt_malloc(message->length * 4);
145 if(!tx_buff)
146 {
147 goto transfer_done;
148 }
149 for(i = 0; i < message->length; i++)
150 {
151 tx_buff[i] = ((uint8_t *)message->send_buf)[i];
152 }
153 }
154
155 if(message->send_buf && message->recv_buf)
156 {
157 dmac_irq_register(bus->dma_recv_channel, dma_irq_callback, &bus->dma_completion, 1);
158 __spi_set_tmod(bus->spi_instance, SPI_TMOD_TRANS_RECV);
159 spi_instance[bus->spi_instance]->dmacr = 0x3;
160 spi_instance[bus->spi_instance]->ssienr = 0x01;
161 dmac_set_single_mode(bus->dma_recv_channel, (void *)(&spi_instance[bus->spi_instance]->dr[0]), rx_buff, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
162 DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, message->length);
163 dmac_set_single_mode(bus->dma_send_channel, tx_buff, (void *)(&spi_instance[bus->spi_instance]->dr[0]), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE,
164 DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, message->length);
165 }
166 else if(message->send_buf)
167 {
168 dmac_irq_register(bus->dma_send_channel, dma_irq_callback, &bus->dma_completion, 1);
169 __spi_set_tmod(bus->spi_instance, SPI_TMOD_TRANS);
170 spi_instance[bus->spi_instance]->dmacr = 0x2;
171 spi_instance[bus->spi_instance]->ssienr = 0x01;
172 dmac_set_single_mode(bus->dma_send_channel, tx_buff, (void *)(&spi_instance[bus->spi_instance]->dr[0]), DMAC_ADDR_INCREMENT, DMAC_ADDR_NOCHANGE,
173 DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, message->length);
174 }
175 else if(message->recv_buf)
176 {
177 dmac_irq_register(bus->dma_recv_channel, dma_irq_callback, &bus->dma_completion, 1);
178 __spi_set_tmod(bus->spi_instance, SPI_TMOD_RECV);
179 spi_instance[bus->spi_instance]->ctrlr1 = message->length - 1;
180 spi_instance[bus->spi_instance]->dmacr = 0x1;
181 spi_instance[bus->spi_instance]->ssienr = 0x01;
182 spi_instance[bus->spi_instance]->dr[0] = 0xFF;
183 dmac_set_single_mode(bus->dma_recv_channel, (void *)(&spi_instance[bus->spi_instance]->dr[0]), rx_buff, DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
184 DMAC_MSIZE_1, DMAC_TRANS_WIDTH_32, message->length);
185 }
186 else
187 {
188 goto transfer_done;
189 }
190 spi_instance[bus->spi_instance]->ser = 1U << cs->cs_index;
191
192 rt_completion_wait(&bus->dma_completion, RT_WAITING_FOREVER);
193 if(message->recv_buf)
194 dmac_irq_unregister(bus->dma_recv_channel);
195 else
196 dmac_irq_unregister(bus->dma_send_channel);
197
198 // wait until all data has been transmitted
199 while ((spi_instance[bus->spi_instance]->sr & 0x05) != 0x04)
200 ;
201 spi_instance[bus->spi_instance]->ser = 0x00;
202 spi_instance[bus->spi_instance]->ssienr = 0x00;
203
204 if(message->recv_buf)
205 {
206 for(i = 0; i < message->length; i++)
207 {
208 ((uint8_t *)message->recv_buf)[i] = (uint8_t)rx_buff[i];
209 }
210 }
211
212 transfer_done:
213 dmalock_release(bus->dma_send_channel);
214 dmalock_release(bus->dma_recv_channel);
215 if(tx_buff)
216 {
217 rt_free(tx_buff);
218 }
219 if(rx_buff)
220 {
221 rt_free(rx_buff);
222 }
223 }
224
225 if(message->cs_release)
226 {
227 gpiohs_set_pin(cs->cs_pin, GPIO_PV_HIGH);
228 }
229
230 return message->length;
231 }
232
233 const static struct rt_spi_ops drv_spi_ops =
234 {
235 drv_spi_configure,
236 drv_spi_xfer
237 };
238
rt_hw_spi_init(void)239 int rt_hw_spi_init(void)
240 {
241 rt_err_t ret = RT_EOK;
242
243 #ifdef BSP_USING_SPI1
244 {
245 static struct drv_spi_bus spi_bus1;
246 spi_bus1.spi_instance = SPI_DEVICE_1;
247 ret = rt_spi_bus_register(&spi_bus1.parent, "spi1", &drv_spi_ops);
248
249 #ifdef BSP_SPI1_USING_SS0
250 {
251 static struct rt_spi_device spi_device10;
252 static struct drv_cs cs10 =
253 {
254 .cs_index = SPI_CHIP_SELECT_0,
255 .cs_pin = SPI1_CS0_PIN
256 };
257
258 rt_spi_bus_attach_device(&spi_device10, "spi10", "spi1", (void *)&cs10);
259 }
260 #endif
261
262 #ifdef BSP_SPI1_USING_SS1
263 {
264 static struct rt_spi_device spi_device11;
265 static struct drv_cs cs11 =
266 {
267 .cs_index = SPI_CHIP_SELECT_1,
268 .cs_pin = SPI1_CS1_PIN
269 };
270 rt_spi_bus_attach_device(&spi_device11, "spi11", "spi1", (void *)&cs11);
271 }
272 #endif
273
274 #ifdef BSP_SPI1_USING_SS2
275 {
276 static struct rt_spi_device spi_device12;
277 static struct drv_cs cs12 =
278 {
279 .cs_index = SPI_CHIP_SELECT_2,
280 .cs_pin = SPI1_CS2_PIN
281 };
282 rt_spi_bus_attach_device(&spi_device12, "spi12", "spi1", (void *)&cs12);
283 }
284 #endif
285
286 #ifdef BSP_SPI1_USING_SS3
287 {
288 static struct rt_spi_device spi_device13;
289 static struct drv_cs cs13 =
290 {
291 .cs_index = SPI_CHIP_SELECT_2,
292 .cs_pin = SPI1_CS2_PIN
293 };
294 rt_spi_bus_attach_device(&spi_device13, "spi13", "spi1", (void *)&cs13);
295 }
296 #endif
297 }
298 #endif
299 return ret;
300 }
301 INIT_DEVICE_EXPORT(rt_hw_spi_init);
302 #endif
303