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