• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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