1 /*
2 * Copyright (c) 2006-2020, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2020-05-28 hqfang first implementation.
9 */
10
11 #include "drv_spi.h"
12
13 #ifdef RT_USING_SPI
14
15 #if !defined(BSP_USING_SPI0) && !defined(BSP_USING_SPI1) && !defined(BSP_USING_SPI2)
16 #error "Please define at least one BSP_USING_SPIx"
17 /* this driver can be disabled at menuconfig -> Hardware Drivers Config -> On-chip Peripheral Drivers -> Enable SPI */
18 #endif
19
20 static struct gd32_spi_config spi_config[] =
21 {
22 #ifdef BSP_USING_SPI0
23 {
24 "spi0",
25 SPI0,
26 },
27 #endif
28 #ifdef BSP_USING_SPI1
29 {
30 "spi1",
31 SPI1,
32 },
33 #endif
34 #ifdef BSP_USING_SPI2
35 {
36 "spi2",
37 SPI2,
38 },
39 #endif
40 };
41
42 static struct gd32_spi spi_obj[sizeof(spi_config) / sizeof(spi_config[0])] = {0};
43
gd32_spi_init(rt_uint32_t spi_periph,struct rt_spi_configuration * cfg)44 static rt_err_t gd32_spi_init(rt_uint32_t spi_periph, struct rt_spi_configuration *cfg)
45 {
46 spi_parameter_struct spicfg;
47 uint32_t apbfreq;
48 uint32_t scale;
49
50 RT_ASSERT(cfg != RT_NULL);
51
52 spi_struct_para_init(&spicfg);
53
54 if (cfg->data_width != 8 && cfg->data_width != 16)
55 {
56 return (-RT_EINVAL);
57 }
58
59 switch (spi_periph)
60 {
61 case SPI0:
62 apbfreq = rcu_clock_freq_get(CK_APB2);
63 break;
64 default:
65 apbfreq = rcu_clock_freq_get(CK_APB1);
66 break;
67 }
68
69 scale = apbfreq / cfg->max_hz;
70 if (scale <= 2)
71 {
72 spicfg.prescale = SPI_PSC_2;
73 }
74 else if (scale <= 4)
75 {
76 spicfg.prescale = SPI_PSC_4;
77 }
78 else if (scale <= 8)
79 {
80 spicfg.prescale = SPI_PSC_8;
81 }
82 else if (scale <= 16)
83 {
84 spicfg.prescale = SPI_PSC_16;
85 }
86 else if (scale <= 32)
87 {
88 spicfg.prescale = SPI_PSC_32;
89 }
90 else if (scale <= 64)
91 {
92 spicfg.prescale = SPI_PSC_64;
93 }
94 else if (scale <= 128)
95 {
96 spicfg.prescale = SPI_PSC_128;
97 }
98 else if (scale <= 256)
99 {
100 spicfg.prescale = SPI_PSC_256;
101 }
102 else
103 {
104 spicfg.prescale = SPI_PSC_256;
105 }
106
107 if (cfg->data_width == 8)
108 {
109 spicfg.frame_size = SPI_FRAMESIZE_8BIT;
110 }
111 else
112 {
113 spicfg.frame_size = SPI_FRAMESIZE_16BIT;
114 }
115
116 if (cfg->mode & RT_SPI_MSB)
117 {
118 spicfg.endian = SPI_ENDIAN_MSB;
119 }
120 else
121 {
122 spicfg.endian = SPI_ENDIAN_LSB;
123 }
124
125 spicfg.clock_polarity_phase = 0;
126 if (cfg->mode & RT_SPI_CPHA)
127 {
128 spicfg.clock_polarity_phase |= SPI_CTL0_CKPH;
129 }
130 if (cfg->mode & RT_SPI_CPOL)
131 {
132 spicfg.clock_polarity_phase |= SPI_CTL0_CKPL;
133 }
134
135 if (cfg->mode & RT_SPI_SLAVE)
136 {
137 spicfg.device_mode = SPI_SLAVE;
138 }
139 else
140 {
141 spicfg.device_mode = SPI_MASTER;
142 }
143 spicfg.nss = SPI_NSS_SOFT;
144 spicfg.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
145
146 spi_init(spi_periph, &spicfg);
147 /* set crc polynomial */
148 spi_crc_polynomial_set(spi_periph, 7);
149
150 return RT_EOK;
151 }
152
gd32_spi_configure(struct rt_spi_device * device,struct rt_spi_configuration * cfg)153 static rt_err_t gd32_spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *cfg)
154 {
155 rt_err_t ret = RT_EOK;
156 RT_ASSERT(device != RT_NULL);
157
158 struct gd32_spi *spi_obj = (struct gd32_spi *)(device->bus->parent.user_data);
159 struct gd32_spi_config *spi_cfg = (struct gd32_spi_config *)(spi_obj->config);
160
161 ret = gd32_spi_init(spi_cfg->spi_periph, cfg);
162 /* enable SPI */
163 spi_enable(spi_cfg->spi_periph);
164
165 return ret;
166 }
167
168 /**
169 * Attach the spi device to SPI bus, this function must be used after initialization.
170 */
rt_hw_spi_device_attach(const char * bus_name,const char * device_name,rt_uint32_t pin)171 rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint32_t pin)
172 {
173 rt_err_t ret = RT_EOK;
174
175 struct rt_spi_device *spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
176 RT_ASSERT(spi_device != RT_NULL);
177
178 struct gd32_spi_cs *cs_pin = (struct gd32_spi_cs *)rt_malloc(sizeof(struct gd32_spi_cs));
179 RT_ASSERT(cs_pin != RT_NULL);
180
181 cs_pin->pin = pin;
182 rt_pin_mode(pin, PIN_MODE_OUTPUT);
183 rt_pin_write(pin, PIN_HIGH);
184
185 ret = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin);
186
187 return ret;
188 }
189
gd32_spi_transmit(rt_uint32_t spi_periph,const void * send_buf,void * recv_buf,rt_size_t length)190 rt_size_t gd32_spi_transmit(rt_uint32_t spi_periph, const void *send_buf, void *recv_buf, rt_size_t length)
191 {
192 uint8_t *send_buf_8b = (uint8_t *)send_buf;
193 uint8_t *recv_buf_8b = (uint8_t *)recv_buf;
194 uint8_t sndbyte = 0xFF, rcvbyte;
195 rt_size_t idx = 0;
196
197 while (idx < length)
198 {
199 while (RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_TBE));
200 if (send_buf_8b)
201 {
202 sndbyte = send_buf_8b[idx];
203 }
204 spi_i2s_data_transmit(spi_periph, sndbyte);
205 while (RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_RBNE));
206 rcvbyte = spi_i2s_data_receive(spi_periph);
207 if (recv_buf_8b)
208 {
209 recv_buf_8b[idx] = rcvbyte;
210 }
211 idx ++;
212 }
213
214 return length;
215 }
216
gd32_spi_xfer(struct rt_spi_device * device,struct rt_spi_message * message)217 static rt_uint32_t gd32_spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
218 {
219 rt_uint32_t total_length = 0;
220 rt_err_t ret = RT_EOK;
221
222 RT_ASSERT(device != RT_NULL);
223
224 struct gd32_spi *spi_obj = (struct gd32_spi *)(device->bus->parent.user_data);
225 struct gd32_spi_config *spi_cfg = (struct gd32_spi_config *)(spi_obj->config);
226 RT_ASSERT(spi_cfg != RT_NULL);
227 struct gd32_spi_cs *cs = (struct gd32_spi_cs *)(device->parent.user_data);
228
229 if (message && message->cs_take)
230 {
231 rt_pin_write(cs->pin, PIN_LOW);
232 }
233 if (message && message->length)
234 {
235
236 total_length += gd32_spi_transmit(spi_cfg->spi_periph, message->send_buf, \
237 message->recv_buf, message->length);
238 }
239 if (message && message->cs_release)
240 {
241 rt_pin_write(cs->pin, PIN_HIGH);
242 }
243 return total_length;
244 }
245
246 static const struct rt_spi_ops spi_ops =
247 {
248 gd32_spi_configure,
249 gd32_spi_xfer
250 };
251
rt_hw_spi_init(void)252 int rt_hw_spi_init(void)
253 {
254 rt_size_t obj_num;
255 int index;
256 rt_err_t result = 0;
257
258 #ifdef BSP_USING_SPI0
259 rcu_periph_clock_enable(RCU_SPI0);
260 #endif
261 #ifdef BSP_USING_SPI1
262 rcu_periph_clock_enable(RCU_SPI1);
263 #endif
264 #ifdef BSP_USING_SPI2
265 rcu_periph_clock_enable(RCU_SPI2);
266 #endif
267
268 obj_num = sizeof(spi_obj) / sizeof(struct gd32_spi);
269 for (index = 0; index < obj_num; index++)
270 {
271 /* init spi object */
272 spi_obj[index].config = &spi_config[index];
273 spi_obj[index].bus.parent.user_data = &spi_obj[index];
274
275 /* register spi device */
276 result = rt_spi_bus_register(&spi_obj[index].bus,
277 spi_obj[index].config->name,
278 &spi_ops);
279 RT_ASSERT(result == RT_EOK);
280 }
281
282 return 0;
283 }
284 INIT_DEVICE_EXPORT(rt_hw_spi_init);
285
286 #endif
287 /* end of spi driver */
288