xref: /nrf52832-nimble/rt-thread/components/drivers/spi/qspi_core.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
1 /*
2  * Copyright (c) 2006-2018, 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/spi.h>
12 
13 rt_err_t rt_qspi_configure(struct rt_qspi_device *device, struct rt_qspi_configuration *cfg)
14 {
15     RT_ASSERT(device != RT_NULL);
16     RT_ASSERT(cfg != RT_NULL);
17 
18     struct rt_qspi_device *qspi_device = (struct rt_qspi_device *)device;
19     rt_err_t result = RT_EOK;
20 
21     /* copy configuration items */
22     qspi_device->config.parent.mode = cfg->parent.mode;
23     qspi_device->config.parent.max_hz = cfg->parent.max_hz;
24     qspi_device->config.parent.data_width = cfg->parent.data_width;
25     qspi_device->config.parent.reserved = cfg->parent.reserved;
26     qspi_device->config.medium_size = cfg->medium_size;
27     qspi_device->config.ddr_mode = cfg->ddr_mode;
28     qspi_device->config.qspi_dl_width = cfg->qspi_dl_width;
29 
30     result = rt_spi_configure(&device->parent, &cfg->parent);
31 
32     return result;
33 }
34 
35 rt_err_t rt_qspi_bus_register(struct rt_spi_bus *bus, const char *name, const struct rt_spi_ops *ops)
36 {
37     rt_err_t result = RT_EOK;
38 
39     result = rt_spi_bus_register(bus, name, ops);
40     if(result == RT_EOK)
41     {
42         /* set SPI bus to qspi modes */
43         bus->mode = RT_SPI_BUS_MODE_QSPI;
44     }
45 
46     return result;
47 }
48 
49 rt_size_t rt_qspi_transfer_message(struct rt_qspi_device  *device, struct rt_qspi_message *message)
50 {
51     rt_err_t result;
52 
53     RT_ASSERT(device != RT_NULL);
54     RT_ASSERT(message != RT_NULL);
55 
56     result = rt_mutex_take(&(device->parent.bus->lock), RT_WAITING_FOREVER);
57     if (result != RT_EOK)
58     {
59         rt_set_errno(-RT_EBUSY);
60 
61         return 0;
62     }
63 
64     /* reset errno */
65     rt_set_errno(RT_EOK);
66 
67     /* configure SPI bus */
68     if (device->parent.bus->owner != &device->parent)
69     {
70         /* not the same owner as current, re-configure SPI bus */
71         result = device->parent.bus->ops->configure(&device->parent, &device->parent.config);
72         if (result == RT_EOK)
73         {
74             /* set SPI bus owner */
75             device->parent.bus->owner = &device->parent;
76         }
77         else
78         {
79             /* configure SPI bus failed */
80             rt_set_errno(-RT_EIO);
81             goto __exit;
82         }
83     }
84 
85     /* transmit each SPI message */
86 
87     result = device->parent.bus->ops->xfer(&device->parent, &message->parent);
88     if (result == 0)
89     {
90         rt_set_errno(-RT_EIO);
91     }
92 
93 __exit:
94     /* release bus lock */
95     rt_mutex_release(&(device->parent.bus->lock));
96 
97     return result;
98 }
99 
100 rt_err_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)
101 {
102     RT_ASSERT(send_buf);
103     RT_ASSERT(recv_buf);
104     RT_ASSERT(send_length != 0);
105 
106     struct rt_qspi_message message;
107     unsigned char *ptr = (unsigned char *)send_buf;
108     rt_size_t count = 0;
109     rt_err_t result = 0;
110 
111     message.instruction.content = ptr[0];
112     message.instruction.qspi_lines = 1;
113     count++;
114 
115     /* get address */
116     if (send_length > 1)
117     {
118         if (device->config.medium_size > 0x1000000 && send_length >= 5)
119         {
120             /* medium size greater than 16Mb, address size is 4 Byte */
121             message.address.content = (ptr[1] << 24) | (ptr[2] << 16) | (ptr[3] << 8) | (ptr[4]);
122             message.address.size = 32;
123             count += 4;
124         }
125         else if (send_length >= 4)
126         {
127             /* address size is 3 Byte */
128             message.address.content = (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
129             message.address.size = 24;
130             count += 3;
131         }
132         else
133         {
134             return -RT_ERROR;
135         }
136         message.address.qspi_lines = 1;
137     }
138     else
139     {
140         /* no address stage */
141         message.address.content = 0 ;
142         message.address.qspi_lines = 0;
143         message.address.size = 0;
144     }
145 
146     message.alternate_bytes.content = 0;
147     message.alternate_bytes.size = 0;
148     message.alternate_bytes.qspi_lines = 0;
149 
150     /* set dummy cycles */
151     if (count != send_length)
152     {
153         message.dummy_cycles = (send_length - count) * 8;
154 
155     }
156     else
157     {
158         message.dummy_cycles = 0;
159     }
160 
161     /* set recv buf and recv size */
162     message.parent.recv_buf = recv_buf;
163     message.parent.send_buf = RT_NULL;
164     message.parent.length = recv_length;
165     message.parent.cs_take = 1;
166     message.parent.cs_release = 1;
167 
168     message.qspi_data_lines = 1;
169 
170     result = rt_qspi_transfer_message(device, &message);
171     if (result == 0)
172     {
173         result = -RT_EIO;
174     }
175     else
176     {
177         result = recv_length;
178     }
179 
180     return result;
181 }
182 
183 rt_err_t rt_qspi_send(struct rt_qspi_device *device, const void *send_buf, rt_size_t length)
184 {
185     RT_ASSERT(send_buf);
186     RT_ASSERT(length != 0);
187 
188     struct rt_qspi_message message;
189     char *ptr = (char *)send_buf;
190     rt_size_t  count = 0;
191     rt_err_t result = 0;
192 
193     message.instruction.content = ptr[0];
194     message.instruction.qspi_lines = 1;
195     count++;
196 
197     /* get address */
198     if (length > 1)
199     {
200         if (device->config.medium_size > 0x1000000 && length >= 5)
201         {
202             /* medium size greater than 16Mb, address size is 4 Byte */
203             message.address.content = (ptr[1] << 24) | (ptr[2] << 16) | (ptr[3] << 8) | (ptr[4]);
204             message.address.size = 32;
205             message.address.qspi_lines = 1;
206             count += 4;
207         }
208         else if (length >= 4)
209         {
210             /* address size is 3 Byte */
211             message.address.content = (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
212             message.address.size = 24;
213             message.address.qspi_lines = 1;
214             count += 3;
215         }
216         else
217         {
218             return -RT_ERROR;
219         }
220 
221     }
222     else
223     {
224         /* no address stage */
225         message.address.content = 0 ;
226         message.address.qspi_lines = 0;
227         message.address.size = 0;
228     }
229 
230     message.alternate_bytes.content = 0;
231     message.alternate_bytes.size = 0;
232     message.alternate_bytes.qspi_lines = 0;
233 
234     message.dummy_cycles = 0;
235 
236     /* determine if there is data to send */
237     if (length - count > 0)
238     {
239         message.qspi_data_lines = 1;
240     }
241     else
242     {
243         message.qspi_data_lines = 0;
244 
245     }
246 
247     /* set send buf and send size */
248     message.parent.send_buf = ptr + count;
249     message.parent.recv_buf = RT_NULL;
250     message.parent.length = length - count;
251     message.parent.cs_take = 1;
252     message.parent.cs_release = 1;
253 
254     result = rt_qspi_transfer_message(device, &message);
255     if (result == 0)
256     {
257         result = -RT_EIO;
258     }
259     else
260     {
261         result = length;
262     }
263 
264     return result;
265 }
266