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