1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2018-11-16     zylx      first version.
9  */
10 
11 #include "drivers/dev_spi.h"
12 
13 extern rt_err_t spi_bus_register(struct rt_spi_bus       *bus,
14                                  const char              *name,
15                                  const struct rt_spi_ops *ops);
16 
rt_qspi_configure(struct rt_qspi_device * device,struct rt_qspi_configuration * cfg)17 rt_err_t rt_qspi_configure(struct rt_qspi_device *device, struct rt_qspi_configuration *cfg)
18 {
19     RT_ASSERT(device != RT_NULL);
20     RT_ASSERT(cfg != RT_NULL);
21 
22     /* reset the CS pin */
23     if (device->parent.cs_pin != PIN_NONE)
24     {
25         rt_err_t result = rt_mutex_take(&(device->parent.bus->lock), RT_WAITING_FOREVER);
26         if (result == RT_EOK)
27         {
28             if (cfg->parent.mode & RT_SPI_CS_HIGH)
29             {
30                 rt_pin_write(device->parent.cs_pin, PIN_LOW);
31             }
32             else
33             {
34                 rt_pin_write(device->parent.cs_pin, PIN_HIGH);
35             }
36             rt_mutex_release(&(device->parent.bus->lock));
37         }
38         else
39         {
40             return result;
41         }
42     }
43 
44     /* If the configurations are the same, we don't need to set again. */
45     if (device->config.medium_size       == cfg->medium_size &&
46         device->config.ddr_mode          == cfg->ddr_mode &&
47         device->config.qspi_dl_width     == cfg->qspi_dl_width &&
48         device->config.parent.data_width == cfg->parent.data_width &&
49         device->config.parent.mode       == (cfg->parent.mode & RT_SPI_MODE_MASK) &&
50         device->config.parent.max_hz     == cfg->parent.max_hz)
51     {
52         return RT_EOK;
53     }
54 
55     /* copy configuration items */
56     device->config.parent.mode = cfg->parent.mode;
57     device->config.parent.max_hz = cfg->parent.max_hz;
58     device->config.parent.data_width = cfg->parent.data_width;
59 #ifdef RT_USING_DM
60     device->config.parent.data_width_tx = cfg->parent.data_width_tx;
61     device->config.parent.data_width_rx = cfg->parent.data_width_rx;
62 #else
63     device->config.parent.reserved = cfg->parent.reserved;
64 #endif
65     device->config.medium_size = cfg->medium_size;
66     device->config.ddr_mode = cfg->ddr_mode;
67     device->config.qspi_dl_width = cfg->qspi_dl_width;
68 
69     return rt_spi_bus_configure(&device->parent);
70 }
71 
rt_qspi_bus_register(struct rt_spi_bus * bus,const char * name,const struct rt_spi_ops * ops)72 rt_err_t rt_qspi_bus_register(struct rt_spi_bus *bus, const char *name, const struct rt_spi_ops *ops)
73 {
74     /* set SPI bus to qspi modes */
75     bus->mode = RT_SPI_BUS_MODE_QSPI;
76 
77     return spi_bus_register(bus, name, ops);
78 }
79 
rt_qspi_transfer_message(struct rt_qspi_device * device,struct rt_qspi_message * message)80 rt_ssize_t rt_qspi_transfer_message(struct rt_qspi_device  *device, struct rt_qspi_message *message)
81 {
82     rt_ssize_t result;
83 
84     RT_ASSERT(device != RT_NULL);
85     RT_ASSERT(message != RT_NULL);
86 
87     result = rt_mutex_take(&(device->parent.bus->lock), RT_WAITING_FOREVER);
88     if (result != RT_EOK)
89     {
90         rt_set_errno(-RT_EBUSY);
91 
92         return 0;
93     }
94 
95     /* reset errno */
96     rt_set_errno(RT_EOK);
97 
98     /* configure SPI bus */
99     if (device->parent.bus->owner != &device->parent)
100     {
101         /* not the same owner as current, re-configure SPI bus */
102         result = device->parent.bus->ops->configure(&device->parent, &device->parent.config);
103         if (result == RT_EOK)
104         {
105             /* set SPI bus owner */
106             device->parent.bus->owner = &device->parent;
107         }
108         else
109         {
110             /* configure SPI bus failed */
111             rt_set_errno(-RT_EIO);
112             goto __exit;
113         }
114     }
115 
116     /* transmit each SPI message */
117 
118     result = device->parent.bus->ops->xfer(&device->parent, &message->parent);
119     if (result == 0)
120     {
121         rt_set_errno(-RT_EIO);
122     }
123 
124 __exit:
125     /* release bus lock */
126     rt_mutex_release(&(device->parent.bus->lock));
127 
128     return result;
129 }
130 
rt_qspi_send_then_recv(struct rt_qspi_device * device,const void * send_buf,rt_size_t send_length,void * recv_buf,rt_size_t recv_length)131 rt_ssize_t rt_qspi_send_then_recv(struct rt_qspi_device *device, const void *send_buf, rt_size_t send_length, void *recv_buf, rt_size_t recv_length)
132 {
133     RT_ASSERT(send_buf);
134     RT_ASSERT(recv_buf);
135     RT_ASSERT(send_length != 0);
136 
137     struct rt_qspi_message message;
138     unsigned char *ptr = (unsigned char *)send_buf;
139     rt_size_t count = 0;
140     rt_ssize_t result = 0;
141 
142     message.instruction.content = ptr[0];
143     message.instruction.qspi_lines = 1;
144     count++;
145 
146     /* get address */
147     if (send_length > 1)
148     {
149         if (device->config.medium_size > 0x1000000 && send_length >= 5)
150         {
151             /* medium size greater than 16Mb, address size is 4 Byte */
152             message.address.content = (ptr[1] << 24) | (ptr[2] << 16) | (ptr[3] << 8) | (ptr[4]);
153             message.address.size = 32;
154             count += 4;
155         }
156         else if (send_length >= 4)
157         {
158             /* address size is 3 Byte */
159             message.address.content = (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
160             message.address.size = 24;
161             count += 3;
162         }
163         else
164         {
165             return -RT_ERROR;
166         }
167         message.address.qspi_lines = 1;
168     }
169     else
170     {
171         /* no address stage */
172         message.address.content = 0 ;
173         message.address.qspi_lines = 0;
174         message.address.size = 0;
175     }
176 
177     message.alternate_bytes.content = 0;
178     message.alternate_bytes.size = 0;
179     message.alternate_bytes.qspi_lines = 0;
180 
181     /* set dummy cycles */
182     if (count != send_length)
183     {
184         message.dummy_cycles = (send_length - count) * 8;
185 
186     }
187     else
188     {
189         message.dummy_cycles = 0;
190     }
191 
192     /* set recv buf and recv size */
193     message.parent.recv_buf = recv_buf;
194     message.parent.send_buf = RT_NULL;
195     message.parent.length = recv_length;
196     message.parent.cs_take = 1;
197     message.parent.cs_release = 1;
198 
199     message.qspi_data_lines = 1;
200     /* set next */
201     /* Ensure correct QSPI message chaining by setting next pointer to NULL, preventing unintended data transmission issues.*/
202     message.parent.next = RT_NULL;
203 
204     result = rt_qspi_transfer_message(device, &message);
205     if (result == 0)
206     {
207         result = -RT_EIO;
208     }
209     else if (result > 0)
210     {
211         result = recv_length;
212     }
213 
214     return result;
215 }
216 
rt_qspi_send(struct rt_qspi_device * device,const void * send_buf,rt_size_t length)217 rt_ssize_t rt_qspi_send(struct rt_qspi_device *device, const void *send_buf, rt_size_t length)
218 {
219     RT_ASSERT(send_buf);
220     RT_ASSERT(length != 0);
221 
222     struct rt_qspi_message message;
223     unsigned char *ptr = (unsigned char *)send_buf;
224     rt_size_t  count = 0;
225     rt_ssize_t result = 0;
226 
227     message.instruction.content = ptr[0];
228     message.instruction.qspi_lines = 1;
229     count++;
230 
231     /* get address */
232     if (length > 1)
233     {
234         if (device->config.medium_size > 0x1000000 && length >= 5)
235         {
236             /* medium size greater than 16Mb, address size is 4 Byte */
237             message.address.content = (ptr[1] << 24) | (ptr[2] << 16) | (ptr[3] << 8) | (ptr[4]);
238             message.address.size = 32;
239             message.address.qspi_lines = 1;
240             count += 4;
241         }
242         else if (length >= 4)
243         {
244             /* address size is 3 Byte */
245             message.address.content = (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
246             message.address.size = 24;
247             message.address.qspi_lines = 1;
248             count += 3;
249         }
250         else
251         {
252             return -RT_ERROR;
253         }
254 
255     }
256     else
257     {
258         /* no address stage */
259         message.address.content = 0 ;
260         message.address.qspi_lines = 0;
261         message.address.size = 0;
262     }
263 
264     message.alternate_bytes.content = 0;
265     message.alternate_bytes.size = 0;
266     message.alternate_bytes.qspi_lines = 0;
267 
268     message.dummy_cycles = 0;
269 
270     /* determine if there is data to send */
271     if (length - count > 0)
272     {
273         message.qspi_data_lines = 1;
274     }
275     else
276     {
277         message.qspi_data_lines = 0;
278     }
279 
280     /* set send buf and send size */
281     message.parent.send_buf = ptr + count;
282     message.parent.recv_buf = RT_NULL;
283     message.parent.length = length - count;
284     message.parent.cs_take = 1;
285     message.parent.cs_release = 1;
286     /* set next */
287     /* Ensure correct QSPI message chaining by setting next pointer to NULL, preventing unintended data transmission issues.*/
288     message.parent.next = RT_NULL;
289 
290     result = rt_qspi_transfer_message(device, &message);
291     if (result == 0)
292     {
293         result = -RT_EIO;
294     }
295     else if (result > 0)
296     {
297         result = length;
298     }
299 
300     return result;
301 }
302