1 /*
2  * Copyright (C) 2018 Shanghai Eastsoft Microelectronics Co., Ltd.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Licensed under the Apache License, Version 2.0 (the License); you may
7  * not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * Change Logs:
19  * Date           Author        Notes
20  * 2019-01-24     wangyq        the first version
21  * 2019-11-01     wangyq        update libraries
22  * 2021-04-20     liuhy         the second version
23  */
24 
25 #include <rtthread.h>
26 #include <rtdevice.h>
27 #include <string.h>
28 #include <rthw.h>
29 #include "board.h"
30 #include "drv_spi.h"
31 
32 
33 #ifdef RT_USING_SPI
34 
35 #define SPITIMEOUT 0x0FFF
36 
spi_configure(struct rt_spi_device * device,struct rt_spi_configuration * cfg)37 rt_err_t spi_configure(struct rt_spi_device *device,
38                        struct rt_spi_configuration *cfg)
39 {
40     spi_handle_t *hspi;
41     hspi = (spi_handle_t *)device->bus->parent.user_data;
42 
43     hspi->init.ss_en    = DISABLE;
44     hspi->init.crc_calc = DISABLE;
45 
46     /* config spi mode */
47     if (cfg->mode & RT_SPI_SLAVE)
48     {
49         hspi->init.mode = SPI_MODE_SLAVER;
50     }
51     else
52     {
53         hspi->init.mode = SPI_MODE_MASTER;
54     }
55     if (cfg->mode & RT_SPI_3WIRE)
56     {
57         hspi->init.dir = SPI_DIRECTION_1LINE;
58     }
59     else
60     {
61         hspi->init.dir = SPI_DIRECTION_2LINES;
62     }
63     if (cfg->data_width == 8)
64     {
65         hspi->init.data_size = SPI_DATA_SIZE_8;
66     }
67     else if (cfg->data_width == 16)
68     {
69         hspi->init.data_size = SPI_DATA_SIZE_16;
70     }
71 
72     if (cfg->mode & RT_SPI_CPHA)
73     {
74         hspi->init.phase = SPI_CPHA_SECOND;
75     }
76     else
77     {
78         hspi->init.phase = SPI_CPHA_FIRST;
79     }
80 
81     if (cfg->mode & RT_SPI_MSB)
82     {
83         hspi->init.first_bit = SPI_FIRSTBIT_MSB;
84     }
85     else
86     {
87         hspi->init.first_bit = SPI_FIRSTBIT_LSB;
88     }
89 
90     if (cfg->mode & RT_SPI_CPOL)
91     {
92         hspi->init.polarity = SPI_CPOL_HIGH;
93     }
94     else
95     {
96         hspi->init.polarity = SPI_CPOL_LOW;
97     }
98 
99     if (cfg->mode & RT_SPI_NO_CS)
100     {
101         hspi->init.ss_en = DISABLE;
102     }
103     else
104     {
105         hspi->init.ss_en = ENABLE;
106     }
107 
108     /* config spi clock */
109     if (cfg->max_hz >= ald_cmu_get_pclk1_clock() / 2)
110     {
111         /* pclk1 max speed 48MHz, spi master max speed 10MHz */
112         if (ald_cmu_get_pclk1_clock() / 2 <= 10000000)
113         {
114             hspi->init.baud = SPI_BAUD_2;
115         }
116         else if (ald_cmu_get_pclk1_clock() / 4 <= 10000000)
117         {
118             hspi->init.baud = SPI_BAUD_4;
119         }
120         else
121         {
122             hspi->init.baud = SPI_BAUD_8;
123         }
124     }
125     else if (cfg->max_hz >= ald_cmu_get_pclk1_clock() / 4)
126     {
127         /* pclk1 max speed 48MHz, spi master max speed 10MHz */
128         if (ald_cmu_get_pclk1_clock() / 4 <= 10000000)
129         {
130             hspi->init.baud = SPI_BAUD_4;
131         }
132         else
133         {
134             hspi->init.baud = SPI_BAUD_8;
135         }
136     }
137     else if (cfg->max_hz >= ald_cmu_get_pclk1_clock() / 8)
138     {
139         hspi->init.baud = SPI_BAUD_8;
140     }
141     else if (cfg->max_hz >= ald_cmu_get_pclk1_clock() / 16)
142     {
143         hspi->init.baud = SPI_BAUD_16;
144     }
145     else if (cfg->max_hz >= ald_cmu_get_pclk1_clock() / 32)
146     {
147         hspi->init.baud = SPI_BAUD_32;
148     }
149     else if (cfg->max_hz >= ald_cmu_get_pclk1_clock() / 64)
150     {
151         hspi->init.baud = SPI_BAUD_64;
152     }
153     else if (cfg->max_hz >= ald_cmu_get_pclk1_clock() / 128)
154     {
155         hspi->init.baud = SPI_BAUD_128;
156     }
157     else
158     {
159         hspi->init.baud = SPI_BAUD_256;
160     }
161     ald_spi_init(hspi);
162     return RT_EOK;
163 }
164 
spixfer(struct rt_spi_device * device,struct rt_spi_message * message)165 static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message)
166 {
167     rt_err_t res;
168     spi_handle_t *hspi;
169     struct es32f0_hw_spi_cs *cs;
170 
171     RT_ASSERT(device != RT_NULL);
172     RT_ASSERT(device->bus != RT_NULL);
173     RT_ASSERT(device->bus->parent.user_data != RT_NULL);
174 
175     hspi = (spi_handle_t *)device->bus->parent.user_data;
176     cs = device->parent.user_data;
177 
178     if (message->cs_take)
179         {
180             rt_pin_write(cs->pin, ES_SPI_CS_LEVEL);
181         }
182 
183     if(message->send_buf != RT_NULL || message->recv_buf != RT_NULL)
184     {
185     /* send & receive */
186     if ((message->send_buf != RT_NULL) && (message->recv_buf != RT_NULL))
187     {
188         res = ald_spi_send_recv(hspi, (rt_uint8_t *)message->send_buf, (rt_uint8_t *)message->recv_buf,
189                                 (rt_int32_t)message->length, SPITIMEOUT);
190     }
191     else
192     {
193         /* only send data */
194         if (message->recv_buf == RT_NULL)
195         {
196             res = ald_spi_send(hspi, (rt_uint8_t *)message->send_buf, (rt_int32_t)message->length, SPITIMEOUT);
197         }
198         /* only receive data */
199         if (message->send_buf == RT_NULL)
200         {
201             res = ald_spi_recv(hspi, (rt_uint8_t *)message->recv_buf, (rt_int32_t)message->length, SPITIMEOUT);
202         }
203     }
204 
205      if (message->cs_release)
206      {
207         rt_pin_write(cs->pin, !ES_SPI_CS_LEVEL);
208      }
209 
210      if (res != RT_EOK)
211          return -RT_ERROR;
212      else
213          return message->length;
214 
215     }
216     else
217     {
218 
219         if (message->cs_release)
220         {
221             rt_pin_write(cs->pin, !ES_SPI_CS_LEVEL);
222         }
223             return RT_EOK;
224     }
225 
226 }
227 
228 const struct rt_spi_ops es32f0_spi_ops =
229 {
230     spi_configure,
231     spixfer,
232 };
233 
234 
es32f0_spi_device_attach(rt_uint32_t pin,const char * bus_name,const char * device_name)235 rt_err_t es32f0_spi_device_attach(rt_uint32_t pin, const char *bus_name, const char *device_name)
236 {
237     int result;
238     /* define spi Instance */
239     struct rt_spi_device *spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
240     RT_ASSERT(spi_device != RT_NULL);
241     struct es32f0_hw_spi_cs *cs_pin = (struct es32f0_hw_spi_cs *)rt_malloc(sizeof(struct es32f0_hw_spi_cs));
242     RT_ASSERT(cs_pin != RT_NULL);
243     cs_pin->pin = pin;
244     rt_pin_mode(pin, PIN_MODE_OUTPUT);
245     rt_pin_write(pin, 1);
246 
247     result = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin);
248 
249 #ifdef BSP_USING_SPI0
250     if(!(strcmp(bus_name,ES_DEVICE_NAME_SPI0_BUS)))SPI_BUS_CONFIG(spi_device->config,0);
251 #endif
252 #ifdef BSP_USING_SPI1
253     if(!(strcmp(bus_name,ES_DEVICE_NAME_SPI1_BUS)))SPI_BUS_CONFIG(spi_device->config,1);
254 #endif
255 
256     return result;
257 }
258 
259 #ifdef BSP_USING_SPI0
260     static struct rt_spi_bus _spi_bus0;
261     static spi_handle_t _spi0;
262 #endif
263 
264 #ifdef BSP_USING_SPI1
265     static struct rt_spi_bus _spi_bus1;
266     static spi_handle_t _spi1;
267 #endif
268 
rt_hw_spi_init(void)269 int rt_hw_spi_init(void)
270 {
271    int result = RT_EOK;
272 
273     struct rt_spi_bus *spi_bus;
274     spi_handle_t *spi;
275     gpio_init_t gpio_instruct;
276 
277         gpio_instruct.odos = GPIO_PUSH_PULL;
278         gpio_instruct.type = GPIO_TYPE_CMOS;
279         gpio_instruct.flt  = GPIO_FILTER_DISABLE;
280         gpio_instruct.odrv = GPIO_OUT_DRIVE_NORMAL;
281 #ifdef BSP_USING_SPI0
282     _spi0.perh = SPI0;
283     spi_bus = &_spi_bus0;
284     spi = &_spi0;
285 
286     /* SPI0 gpio init */
287     gpio_instruct.mode = GPIO_MODE_OUTPUT;
288 
289 #if  defined(ES_SPI0_SCK_GPIO_FUNC)&&defined(ES_SPI0_SCK_GPIO_PORT)&&defined(ES_SPI0_SCK_GPIO_PIN)
290     gpio_instruct.func = ES_SPI0_SCK_GPIO_FUNC;
291     ald_gpio_init(ES_SPI0_SCK_GPIO_PORT, ES_SPI0_SCK_GPIO_PIN, &gpio_instruct);
292 #endif
293 
294 #if  defined(ES_SPI0_MOSI_GPIO_FUNC)&&defined(ES_SPI0_MOSI_GPIO_PORT)&&defined(ES_SPI0_MOSI_GPIO_PIN)
295     gpio_instruct.func = ES_SPI0_MOSI_GPIO_FUNC;
296     ald_gpio_init(ES_SPI0_MOSI_GPIO_PORT, ES_SPI0_MOSI_GPIO_PIN, &gpio_instruct);
297 #endif
298 
299     gpio_instruct.mode = GPIO_MODE_INPUT;
300 
301 #if  defined(ES_SPI0_MISO_GPIO_FUNC)&&defined(ES_SPI0_MISO_GPIO_PORT)&&defined(ES_SPI0_MISO_GPIO_PIN)
302     gpio_instruct.func = ES_SPI0_MISO_GPIO_FUNC;
303     ald_gpio_init(ES_SPI0_MISO_GPIO_PORT, ES_SPI0_MISO_GPIO_PIN, &gpio_instruct);
304 #endif
305 
306     spi_bus->parent.user_data = spi;
307     result = rt_spi_bus_register(spi_bus, ES_DEVICE_NAME_SPI0_BUS, &es32f0_spi_ops);
308     if (result != RT_EOK)
309     {
310         return result;
311     }
312 
313     result = es32f0_spi_device_attach(ES_SPI0_NSS_PIN, ES_DEVICE_NAME_SPI0_BUS, ES_DEVICE_NAME_SPI0_DEV0);
314 
315     if (result != RT_EOK)
316     {
317         return result;
318     }
319 
320 #endif
321 
322 #ifdef BSP_USING_SPI1
323     _spi1.perh = SPI1;
324     spi_bus = &_spi_bus1;
325     spi = &_spi1;
326 
327     /* SPI1 gpio init */
328     gpio_instruct.mode = GPIO_MODE_OUTPUT;
329 
330 #if  defined(ES_SPI1_SCK_GPIO_FUNC)&&defined(ES_SPI1_SCK_GPIO_PORT)&&defined(ES_SPI1_SCK_GPIO_PIN)
331     gpio_instruct.func = ES_SPI1_SCK_GPIO_FUNC;
332     ald_gpio_init(ES_SPI1_SCK_GPIO_PORT, ES_SPI1_SCK_GPIO_PIN, &gpio_instruct);
333 #endif
334 
335 #if  defined(ES_SPI1_MOSI_GPIO_FUNC)&&defined(ES_SPI1_MOSI_GPIO_PORT)&&defined(ES_SPI1_MOSI_GPIO_PIN)
336     gpio_instruct.func = ES_SPI1_MOSI_GPIO_FUNC;
337     ald_gpio_init(ES_SPI1_MOSI_GPIO_PORT, ES_SPI1_MOSI_GPIO_PIN, &gpio_instruct);
338 #endif
339 
340     gpio_instruct.mode = GPIO_MODE_INPUT;
341 
342 #if  defined(ES_SPI1_MISO_GPIO_FUNC)&&defined(ES_SPI1_MISO_GPIO_PORT)&&defined(ES_SPI1_MISO_GPIO_PIN)
343     gpio_instruct.func = ES_SPI1_MISO_GPIO_FUNC;
344     ald_gpio_init(ES_SPI1_MISO_GPIO_PORT, ES_SPI1_MISO_GPIO_PIN, &gpio_instruct);
345 #endif
346 
347     spi_bus->parent.user_data = spi;
348     result = rt_spi_bus_register(spi_bus, ES_DEVICE_NAME_SPI1_BUS, &es32f0_spi_ops);
349     if (result != RT_EOK)
350     {
351         return result;
352     }
353 
354     result = es32f0_spi_device_attach(ES_SPI1_NSS_PIN, ES_DEVICE_NAME_SPI1_BUS, ES_DEVICE_NAME_SPI1_DEV0);
355     if (result != RT_EOK)
356     {
357         return result;
358     }
359 
360 #endif
361 
362     return result;
363 }
364 INIT_BOARD_EXPORT(rt_hw_spi_init);
365 
366 #endif
367