1 /*
2 * Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <stdlib.h>
17 #include <string.h>
18 #include "osal_mutex.h"
19 #include "osal_sem.h"
20 #include "spi_core.h"
21 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
22 #include "hcs_macro.h"
23 #include "hdf_config_macro.h"
24 #else
25 #include "device_resource_if.h"
26 #endif
27 #include "hdf_log.h"
28 #include "osal_mem.h"
29 #include "gpio_types.h"
30 #include "driver/spi_common.h"
31 #include "driver/spi_master.h"
32
33 #ifndef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
34 #error "LOSCFG_DRIVERS_HDF_CONFIG_MACRO"
35 #endif
36
37 typedef struct {
38 uint8_t spi_num;
39 uint8_t miso_pin;
40 uint8_t mosi_pin;
41 uint8_t sck_pin;
42 uint8_t cs_pin;
43 uint8_t mode;
44 uint8_t queue_size;
45 uint8_t dma_chn;
46 uint8_t transferMode;
47 uint8_t bitsPerWord;
48 uint16_t openCnt;
49 uint16_t max_transfer_size;
50 uint32_t speed;
51 spi_device_handle_t spi_handle;
52 } SpiDeviceSt;
53
54 static int32_t SpiDevGetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg);
55 static int32_t SpiDevSetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg);
56 static int32_t SpiDevTransfer(struct SpiCntlr *spiCntlr, struct SpiMsg *spiMsg, uint32_t count);
57 static int32_t SpiDevOpen(struct SpiCntlr *spiCntlr);
58 static int32_t SpiDevClose(struct SpiCntlr *spiCntlr);
59
60 static int32_t SpiDriverBind(struct HdfDeviceObject *device);
61 static int32_t SpiDriverInit(struct HdfDeviceObject *device);
62 static void SpiDriverRelease(struct HdfDeviceObject *device);
63
64 struct SpiCntlrMethod g_twSpiCntlrMethod = {
65 .GetCfg = SpiDevGetCfg,
66 .SetCfg = SpiDevSetCfg,
67 .Transfer = SpiDevTransfer,
68 .Open = SpiDevOpen,
69 .Close = SpiDevClose,
70 };
71
72 struct HdfDriverEntry g_SpiDriverEntry = {
73 .moduleVersion = 1,
74 .moduleName = "ESP32U4_SPI_MODULE_HDF",
75 .Bind = SpiDriverBind,
76 .Init = SpiDriverInit,
77 .Release = SpiDriverRelease,
78 };
79
80 HDF_INIT(g_SpiDriverEntry);
81
82 #define SPI_FIND_CONFIG(node, name, dev) \
83 do { \
84 if (strcmp(HCS_PROP(node, match_attr), name) == 0) { \
85 (dev)->spi_num = HCS_PROP(node, spi_num); \
86 (dev)->miso_pin = HCS_PROP(node, miso_pin); \
87 (dev)->mosi_pin = HCS_PROP(node, mosi_pin); \
88 (dev)->sck_pin = HCS_PROP(node, sck_pin); \
89 (dev)->cs_pin = HCS_PROP(node, cs_pin); \
90 (dev)->speed = HCS_PROP(node, speed); \
91 (dev)->mode = HCS_PROP(node, mode); \
92 (dev)->max_transfer_size = HCS_PROP(node, max_transfer_size); \
93 (dev)->queue_size = HCS_PROP(node, queue_size); \
94 (dev)->dma_chn = HCS_PROP(node, dma_chn); \
95 result = HDF_SUCCESS; \
96 } \
97 } while (0)
98
99 #define PLATFORM_SPI_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), spi_config)
GetSpiDeviceResource(SpiDeviceSt * spiDevice,const char * deviceMatchAttr)100 static int32_t GetSpiDeviceResource(SpiDeviceSt *spiDevice, const char *deviceMatchAttr)
101 {
102 int32_t result = HDF_FAILURE;
103 if (spiDevice == NULL || deviceMatchAttr == NULL) {
104 return HDF_ERR_INVALID_PARAM;
105 }
106 HCS_FOREACH_CHILD_VARGS(PLATFORM_SPI_CONFIG, SPI_FIND_CONFIG, deviceMatchAttr, spiDevice);
107 return result;
108 }
109
AttachSpiDevice(struct SpiCntlr * spiCntlr,struct HdfDeviceObject * device)110 static int32_t AttachSpiDevice(struct SpiCntlr *spiCntlr, struct HdfDeviceObject *device)
111 {
112 int32_t ret;
113 SpiDeviceSt *spiDevice = NULL;
114
115 if (spiCntlr == NULL || device == NULL) {
116 return HDF_ERR_INVALID_PARAM;
117 }
118
119 spiDevice = (SpiDeviceSt *)OsalMemCalloc(sizeof(SpiDeviceSt));
120 if (spiDevice == NULL) {
121 return HDF_ERR_MALLOC_FAIL;
122 }
123
124 ret = GetSpiDeviceResource(spiDevice, device->deviceMatchAttr);
125 if (ret != HDF_SUCCESS) {
126 (void)OsalMemFree(spiDevice);
127 return HDF_FAILURE;
128 }
129
130 spiCntlr->priv = spiDevice;
131 spiCntlr->busNum = spiDevice->spi_num;
132
133 return HDF_SUCCESS;
134 }
135
SpiDriverBind(struct HdfDeviceObject * device)136 static int32_t SpiDriverBind(struct HdfDeviceObject *device)
137 {
138 struct SpiCntlr *spiCntlr = NULL;
139 if (device == NULL) {
140 return HDF_ERR_INVALID_PARAM;
141 }
142 spiCntlr = SpiCntlrCreate(device);
143 if (spiCntlr == NULL) {
144 return HDF_FAILURE;
145 }
146
147 return HDF_SUCCESS;
148 }
149
SpiDriverInit(struct HdfDeviceObject * device)150 static int32_t SpiDriverInit(struct HdfDeviceObject *device)
151 {
152 int32_t ret;
153 struct SpiCntlr *spiCntlr = NULL;
154
155 if (device == NULL) {
156 return HDF_ERR_INVALID_PARAM;
157 }
158
159 spiCntlr = SpiCntlrFromDevice(device);
160 if (spiCntlr == NULL) {
161 return HDF_DEV_ERR_NO_DEVICE;
162 }
163
164 ret = AttachSpiDevice(spiCntlr, device);
165 if (ret != HDF_SUCCESS) {
166 return HDF_DEV_ERR_ATTACHDEV_FAIL;
167 }
168
169 spiCntlr->method = &g_twSpiCntlrMethod;
170
171 return ret;
172 }
173
SpiDriverRelease(struct HdfDeviceObject * device)174 static void SpiDriverRelease(struct HdfDeviceObject *device)
175 {
176 SpiDeviceSt *dev;
177 struct SpiCntlr *spiCntlr = NULL;
178
179 if (device == NULL) {
180 return;
181 }
182
183 spiCntlr = SpiCntlrFromDevice(device);
184 if (spiCntlr == NULL) {
185 return;
186 }
187
188 dev = (SpiDeviceSt *)spiCntlr->priv;
189 if (dev == NULL) {
190 return;
191 }
192 if (dev->openCnt) {
193 dev->openCnt = 1;
194 (void)SpiDevClose(spiCntlr);
195 }
196 OsalMemFree(spiCntlr->priv);
197 spiCntlr->priv = NULL;
198 return;
199 }
SpiDevOpen(struct SpiCntlr * spiCntlr)200 static int32_t SpiDevOpen(struct SpiCntlr *spiCntlr)
201 {
202 esp_err_t err;
203 SpiDeviceSt *dev;
204 if (spiCntlr == NULL) {
205 return HDF_ERR_INVALID_PARAM;
206 }
207 dev = (SpiDeviceSt *)spiCntlr->priv;
208 if (dev == NULL) {
209 return HDF_ERR_INVALID_PARAM;
210 }
211 if (dev->openCnt == 0) {
212 spi_bus_config_t buscfg = {0};
213 buscfg.miso_io_num = dev->miso_pin;
214 buscfg.mosi_io_num = dev->mosi_pin;
215 buscfg.sclk_io_num = dev->sck_pin;
216 buscfg.quadwp_io_num = GPIO_NUM_NC;
217 buscfg.quadhd_io_num = GPIO_NUM_NC;
218 buscfg.max_transfer_sz = dev->max_transfer_size;
219 err = spi_bus_initialize(dev->spi_num, &buscfg, dev->dma_chn);
220 if (err != ESP_OK) {
221 return HDF_ERR_IO;
222 }
223 }
224 if (dev->openCnt == 0) {
225 spi_device_interface_config_t devcfg = {0};
226 devcfg.clock_speed_hz = dev->speed;
227 devcfg.mode = dev->mode;
228 devcfg.spics_io_num = dev->cs_pin;
229 devcfg.queue_size = dev->queue_size;
230 err = spi_bus_add_device(dev->spi_num, &devcfg, &dev->spi_handle);
231 if (err != ESP_OK) {
232 return HDF_ERR_DEVICE_BUSY;
233 }
234 }
235 dev->openCnt++;
236 return HDF_SUCCESS;
237 }
238
SpiDevClose(struct SpiCntlr * spiCntlr)239 static int32_t SpiDevClose(struct SpiCntlr *spiCntlr)
240 {
241 esp_err_t err;
242 SpiDeviceSt *dev;
243 if (spiCntlr == NULL) {
244 return HDF_ERR_INVALID_PARAM;
245 }
246 dev = (SpiDeviceSt *)spiCntlr->priv;
247 if (dev == NULL) {
248 return HDF_ERR_INVALID_PARAM;
249 }
250
251 if (dev->openCnt > 0) {
252 if (--dev->openCnt > 0) {
253 return HDF_SUCCESS;
254 }
255 err = spi_bus_remove_device(dev->spi_handle);
256 if (err != ESP_OK) {
257 return HDF_ERR_DEVICE_BUSY;
258 }
259 dev->spi_handle = NULL;
260
261 err = spi_bus_free(dev->spi_num);
262 if (err != ESP_OK) {
263 return HDF_ERR_IO;
264 }
265 }
266 return HDF_SUCCESS;
267 }
268
SpiDevGetCfg(struct SpiCntlr * spiCntlr,struct SpiCfg * spiCfg)269 static int32_t SpiDevGetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg)
270 {
271 SpiDeviceSt *dev;
272 if (spiCntlr == NULL || spiCfg == NULL) {
273 return HDF_ERR_INVALID_PARAM;
274 }
275 dev = (SpiDeviceSt *)spiCntlr->priv;
276 if (dev == NULL) {
277 return HDF_ERR_INVALID_PARAM;
278 }
279
280 spiCfg->maxSpeedHz = dev->speed;
281 spiCfg->mode = dev->mode;
282 spiCfg->transferMode = dev->transferMode;
283 spiCfg->bitsPerWord = dev->bitsPerWord;
284 return HDF_SUCCESS;
285 }
SpiDevSetCfg(struct SpiCntlr * spiCntlr,struct SpiCfg * spiCfg)286 static int32_t SpiDevSetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg)
287 {
288 SpiDeviceSt *dev;
289 if (spiCntlr == NULL || spiCfg == NULL) {
290 return HDF_ERR_INVALID_PARAM;
291 }
292 dev = (SpiDeviceSt *)spiCntlr->priv;
293 if (dev == NULL) {
294 return HDF_ERR_INVALID_PARAM;
295 }
296
297 dev->speed = spiCfg->maxSpeedHz;
298 dev->mode = spiCfg->mode;
299 dev->transferMode = spiCfg->transferMode;
300 dev->bitsPerWord = spiCfg->bitsPerWord;
301 return HDF_SUCCESS;
302 }
303
SpiDevTransfer(struct SpiCntlr * spiCntlr,struct SpiMsg * spiMsg,uint32_t count)304 static int32_t SpiDevTransfer(struct SpiCntlr *spiCntlr, struct SpiMsg *spiMsg, uint32_t count)
305 {
306 esp_err_t err;
307 SpiDeviceSt *dev;
308 if (spiCntlr == NULL) {
309 return HDF_ERR_INVALID_PARAM;
310 }
311 dev = (SpiDeviceSt *)spiCntlr->priv;
312 if (dev == NULL) {
313 return HDF_ERR_INVALID_PARAM;
314 }
315 for (size_t i = 0; i < count; i++) {
316 struct SpiMsg *msg = &spiMsg[i];
317 spi_transaction_t t = {0};
318 if ((msg->wbuf == NULL) && (msg->rbuf == NULL)) {
319 continue;
320 }
321 t.length = msg->len << '\x3';
322 t.rx_buffer = msg->rbuf;
323 t.tx_buffer = msg->wbuf;
324 err = spi_device_polling_transmit(dev->spi_handle, &t);
325 if (err != ESP_OK) {
326 return HDF_ERR_DEVICE_BUSY;
327 }
328 }
329 return HDF_SUCCESS;
330 }
331