1 /*
2  * Copyright (c) 2022 Talkweb Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include <stdlib.h>
10 #include <string.h>
11 #include "hal_gpio.h"
12 #include "hal_spi.h"
13 #include "osal_mutex.h"
14 #include "osal_sem.h"
15 #include "spi_core.h"
16 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
17 #include "hcs_macro.h"
18 #include "hdf_config_macro.h"
19 #else
20 #include "device_resource_if.h"
21 #include "hdf_log.h"
22 #endif
23 #include "hdf_base_hal.h"
24 
25 #define BITWORD_EIGHT 8
26 #define BITWORD_SIXTEEN 16
27 #define GPIO_STR_MAX 32
28 #define PER_MS_IN_SEC 1000
29 typedef enum {
30     SPI_WORK_MODE_0, // CPOL = 0; CPHA = 0
31     SPI_WORK_MODE_2, // CPOL = 1; CPHA = 0
32     SPI_WORK_MODE_1, // CPOL = 0; CPHA = 1
33     SPI_WORK_MODE_3, // CPOL = 1; CPHA = 1
34     SPI_WORD_MODE_MAX,
35 } SPI_CLK_MODE;
36 
37 typedef enum {
38     SPI_TRANSFER_DMA,
39     SPI_TRANSFER_NORMAL,
40     SPI_TRANSFER_MAX,
41 } SPI_TRANS_MODE;
42 
43 typedef enum {
44     FULL_DUPLEX = 0,
45     SIMPLE_RX,
46     HALF_RX,
47     HALF_TX,
48     SPI_TRANS_DIR_MAX,
49 } SPI_TRANS_DIR;
50 
51 typedef enum {
52     SPI_SLAVE_MODE = 0,
53     SPI_MASTER_MODE,
54     SPI_MASTER_SLAVE_MAX,
55 } SPI_SLAVE_MASTER;
56 
57 typedef enum {
58     SPI_DATA_WIDTH_8 = 0,
59     SPI_DATA_WIDTH_16,
60     SPI_DATA_WIDTH_MAX,
61 } SPI_DATA_WIDTH;
62 
63 typedef enum {
64     SPI_NSS_SOFT_MODE = 0,
65     SPI_NSS_HARD_INPUT_MODE,
66     SPI_NSS_HARD_OUTPUT_MODE,
67     SPI_NSS_MODE_MAX,
68 } SPI_NSS;
69 
70 typedef enum {
71     BAUD_RATE_DIV2 = 0,
72     BAUD_RATE_DIV4,
73     BAUD_RATE_DIV8,
74     BAUD_RATE_DIV16,
75     BAUD_RATE_DIV32,
76     BAUD_RATE_DIV64,
77     BAUD_RATE_DIV128,
78     BAUD_RATE_DIV256,
79     BAUD_RATE_DIV_MAX,
80 } SPI_BAUD_RATE;
81 
82 typedef enum {
83     SPI_MSB_FIRST = 0,
84     SPI_LSB_FIRST,
85     SPI_MLSB_MAX,
86 } SPI_BYTE_ORDER;
87 
88 typedef enum {
89     CRC_DISABLE = 0,
90     CRC_ENABLE,
91     CRC_STATE_MAX,
92 } CRC_CALULATION;
93 
94 typedef enum {
95     SPI_PORT1 = 1,
96     SPI_PORT2,
97     SPI_PORT3,
98 } SPI_GROUPS;
99 
100 typedef enum {
101     SPI_PROTO_MOTOROLA = 0,
102     SPI_PROTO_TI,
103     SPI_PROTO_MAX,
104 } SPI_PROTO_STANDARD;
105 
106 typedef struct {
107     uint8_t busNum;
108     uint8_t csNum;
109     SPI_TRANS_DIR transDir;
110     SPI_TRANS_MODE transMode;
111 
112     SPI_SLAVE_MASTER smMode;
113     SPI_CLK_MODE clkMode;
114     SPI_DATA_WIDTH dataWidth;
115     SPI_NSS nss;
116 
117     SPI_BAUD_RATE baudRate;
118     SPI_BYTE_ORDER bitOrder;
119     CRC_CALULATION crcEnable;
120     SPI_GROUPS spix;
121 
122     STM32_GPIO_PIN csPin;
123     STM32_GPIO_GROUP csGroup;
124     SPI_PROTO_STANDARD standard;
125     uint8_t dummyByte;
126 
127     uint16_t crcPoly;
128 } SpiResource;
129 
130 #define HCS_UINT8_PARSE_NUM 16
131 static const char *g_parseHcsMap[HCS_UINT8_PARSE_NUM] = {
132     "busNum",
133     "csNum",
134     "transDir",
135     "transMode",
136     "smMode",
137     "clkMode",
138     "dataWidth",
139     "nss",
140     "baudRate",
141     "bitOrder",
142     "crcEnable",
143     "spix",
144     "csPin",
145     "csGpiox",
146     "standard",
147     "dummyByte",
148 };
149 
150 typedef struct {
151     struct OsalSem* sem;
152     struct OsalMutex* mutex;
153     SPI_TypeDef* spix;
154 } SPI_CONTEXT_T;
155 
156 typedef struct {
157     uint32_t spiId;
158     SpiResource resource;
159 } SpiDevice;
160 
161 static uint32_t g_transDirMaps[SPI_TRANS_DIR_MAX] = {
162     LL_SPI_FULL_DUPLEX,
163     LL_SPI_SIMPLEX_RX,
164     LL_SPI_HALF_DUPLEX_RX,
165     LL_SPI_HALF_DUPLEX_TX,
166 };
167 
168 static uint32_t g_nssMaps[SPI_NSS_MODE_MAX] = {
169     LL_SPI_NSS_SOFT,
170     LL_SPI_NSS_HARD_INPUT,
171     LL_SPI_NSS_HARD_OUTPUT,
172 };
173 
174 static uint32_t g_baudMaps[BAUD_RATE_DIV_MAX] = {
175     LL_SPI_BAUDRATEPRESCALER_DIV2,
176     LL_SPI_BAUDRATEPRESCALER_DIV4,
177     LL_SPI_BAUDRATEPRESCALER_DIV8,
178     LL_SPI_BAUDRATEPRESCALER_DIV16,
179     LL_SPI_BAUDRATEPRESCALER_DIV32,
180     LL_SPI_BAUDRATEPRESCALER_DIV64,
181     LL_SPI_BAUDRATEPRESCALER_DIV128,
182     LL_SPI_BAUDRATEPRESCALER_DIV256,
183 };
184 
185 static SPI_TypeDef* g_spiGroupMaps[SPI_PORT3] = {
186     SPI1,
187     SPI2,
188     SPI3,
189 };
190 
EnableSpiClock(uint32_t spiNum)191 static void EnableSpiClock(uint32_t spiNum)
192 {
193     switch (spiNum) {
194         case SPI_PORT1:
195             LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);
196             break;
197         case SPI_PORT2:
198             LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);
199             break;
200         case SPI_PORT3:
201             LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI3);
202             break;
203         default:
204             break;
205     }
206 }
207 
208 static SPI_CONTEXT_T g_spiContext[SPI_PORT3] = {
209     {
210         .sem = {NULL},
211         .mutex = {NULL},
212         .spix = {NULL},
213     },
214     {
215         .sem = {NULL},
216         .mutex = {NULL},
217         .spix = {NULL},
218     },
219     {
220         .sem = {NULL},
221         .mutex = {NULL},
222         .spix = {NULL},
223     },
224 };
225 
HalSpiSend(const SpiDevice * spiDevice,const uint8_t * data,uint16_t size)226 static int32_t HalSpiSend(const SpiDevice *spiDevice, const uint8_t *data, uint16_t size)
227 {
228     uint32_t spiId;
229     SpiResource *resource = NULL;
230 
231     if (spiDevice == NULL || data == NULL || size == 0) {
232         HDF_LOGE("spi input para err\r\n");
233         return HDF_ERR_INVALID_PARAM;
234     }
235 
236     spiId = spiDevice->spiId;
237     resource = &spiDevice->resource;
238     if (resource == NULL) {
239         HDF_LOGE("resource is null\r\n");
240         return HDF_ERR_INVALID_OBJECT;
241     }
242 
243     if (resource->transMode == SPI_TRANSFER_DMA) {
244         return HDF_ERR_INVALID_PARAM; // unsupport now
245     } else {
246         uint8_t readData;
247         while (size--) {
248             readData = LL_SPI_Transmit(g_spiContext[spiId].spix, *data);
249             data++;
250         }
251     }
252 
253     return HDF_SUCCESS;
254 }
255 
HalSpiRecv(const SpiDevice * spiDevice,uint8_t * data,uint16_t size)256 static int32_t HalSpiRecv(const SpiDevice *spiDevice, uint8_t *data, uint16_t size)
257 {
258     uint32_t len = size;
259     uint8_t *cmd = NULL;
260     uint32_t spiId;
261     SpiResource *resource = NULL;
262     if (spiDevice == NULL || data == NULL || size == 0) {
263         HDF_LOGE("spi input para err\r\n");
264         return HDF_ERR_INVALID_PARAM;
265     }
266 
267     spiId = spiDevice->spiId;
268     resource = &spiDevice->resource;
269     if (resource == NULL) {
270         HDF_LOGE("resource is null\r\n");
271         return HDF_ERR_INVALID_OBJECT;
272     }
273     cmd = (uint8_t *)OsalMemAlloc(len);
274     if (cmd == NULL) {
275         HDF_LOGE("%s OsalMemAlloc size %ld error\r\n", __FUNCTION__, len);
276         return HDF_ERR_MALLOC_FAIL;
277     }
278 
279     (void)memset_s(cmd, len, resource->dummyByte, len);
280 
281     if (resource->transMode == SPI_TRANSFER_DMA) {
282         return HDF_ERR_INVALID_PARAM; // unsupport now
283     } else {
284         while (len--) {
285             *data = LL_SPI_Transmit(g_spiContext[spiId].spix, *cmd);
286             data++;
287             cmd++;
288         }
289     }
290 
291     OsalMemFree(cmd);
292     return HDF_SUCCESS;
293 }
294 
HalSpiSendRecv(const SpiDevice * spiDevice,uint8_t * txData,uint16_t txSize,uint8_t * rxData,uint16_t rxSize)295 static int32_t HalSpiSendRecv(const SpiDevice *spiDevice, uint8_t *txData,
296     uint16_t txSize, uint8_t *rxData, uint16_t rxSize)
297 {
298     uint32_t spiId;
299     SpiResource *resource = NULL;
300     if (spiDevice == NULL || txData == NULL || txSize == 0 || rxData == NULL || rxSize == 0) {
301         HDF_LOGE("spi input para err\r\n");
302         return HDF_ERR_INVALID_PARAM;
303     }
304     spiId = spiDevice->spiId;
305     resource = &spiDevice->resource;
306 
307     if (resource->transMode == SPI_TRANSFER_DMA) {
308         return HDF_ERR_INVALID_PARAM; // unsupport now
309     } else {
310         while (rxSize--) {
311             *rxData = LL_SPI_Transmit(g_spiContext[spiId].spix, *txData);
312             rxData++;
313             txData++;
314         }
315     }
316 
317     return HDF_SUCCESS;
318 }
319 
InitSpiInitStruct(LL_SPI_InitTypeDef * spiInitStruct,const SpiResource * resource)320 static void InitSpiInitStruct(LL_SPI_InitTypeDef *spiInitStruct, const SpiResource *resource)
321 {
322     spiInitStruct->TransferDirection = g_transDirMaps[resource->transDir];
323     if (resource->smMode == SPI_SLAVE_MODE) {
324         spiInitStruct->Mode = LL_SPI_MODE_SLAVE;
325     } else {
326         spiInitStruct->Mode = LL_SPI_MODE_MASTER;
327     }
328 
329     if (resource->dataWidth == SPI_DATA_WIDTH_8) {
330         spiInitStruct->DataWidth = LL_SPI_DATAWIDTH_8BIT;
331     } else {
332         spiInitStruct->DataWidth = LL_SPI_DATAWIDTH_16BIT;
333     }
334 
335     switch (resource->clkMode) {
336         case SPI_WORK_MODE_0:
337             spiInitStruct->ClockPolarity = LL_SPI_POLARITY_LOW;
338             spiInitStruct->ClockPhase = LL_SPI_PHASE_1EDGE;
339             break;
340         case SPI_WORK_MODE_1:
341             spiInitStruct->ClockPolarity = LL_SPI_POLARITY_HIGH;
342             spiInitStruct->ClockPhase = LL_SPI_PHASE_1EDGE;
343             break;
344         case SPI_WORK_MODE_2:
345             spiInitStruct->ClockPolarity = LL_SPI_POLARITY_LOW;
346             spiInitStruct->ClockPhase = LL_SPI_PHASE_2EDGE;
347             break;
348         case SPI_WORK_MODE_3:
349             spiInitStruct->ClockPolarity = LL_SPI_POLARITY_HIGH;
350             spiInitStruct->ClockPhase = LL_SPI_PHASE_2EDGE;
351             break;
352         default:
353             spiInitStruct->ClockPolarity = LL_SPI_POLARITY_LOW;
354             spiInitStruct->ClockPhase = LL_SPI_PHASE_1EDGE;
355     }
356 
357     spiInitStruct->NSS = g_nssMaps[resource->nss];
358     spiInitStruct->BaudRate = g_baudMaps[resource->baudRate];
359 
360     if (resource->bitOrder == SPI_MSB_FIRST) {
361         spiInitStruct->BitOrder = LL_SPI_MSB_FIRST;
362     } else {
363         spiInitStruct->BitOrder = LL_SPI_LSB_FIRST;
364     }
365 
366     if (resource->crcEnable == CRC_DISABLE) {
367         spiInitStruct->CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
368     } else {
369         spiInitStruct->CRCCalculation = LL_SPI_CRCCALCULATION_ENABLE;
370     }
371     spiInitStruct->CRCPoly = resource->crcPoly;
372 
373     return;
374 }
375 
InitSpiDevice(const SpiDevice * spiDevice)376 static int32_t InitSpiDevice(const SpiDevice *spiDevice)
377 {
378     uint32_t spiPort;
379     SpiResource *resource = NULL;
380     if (spiDevice == NULL) {
381         HDF_LOGE("%s: invalid parameter\r\n", __func__);
382         return HDF_ERR_INVALID_PARAM;
383     }
384 
385     LL_SPI_InitTypeDef spiInitStruct = {0};
386     resource = &spiDevice->resource;
387     spiPort = spiDevice->spiId;
388     EnableSpiClock(spiPort + 1);
389     InitSpiInitStruct(&spiInitStruct, resource);
390     SPI_TypeDef* spix = g_spiGroupMaps[resource->spix];
391 
392     g_spiContext[spiPort].spix = spix;
393     LL_SPI_Disable(spix);
394     uint8_t ret = LL_SPI_Init(spix, &spiInitStruct);
395     if (ret != 0) {
396         HDF_LOGE("HAL INIT SPI FAILED\r\n");
397         return HDF_FAILURE;
398     }
399     if (resource->standard == SPI_PROTO_MOTOROLA) {
400         LL_SPI_SetStandard(spix, LL_SPI_PROTOCOL_MOTOROLA);
401     } else {
402         LL_SPI_SetStandard(spix, LL_SPI_PROTOCOL_TI);
403     }
404 
405     return HDF_SUCCESS;
406 }
407 
408 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
409 #define SPI_FIND_CONFIG(node, name, resource, spiDevice) \
410     do { \
411         if (strcmp(HCS_PROP(node, match_attr), name) == 0) { \
412             resource->busNum = HCS_PROP(node, busNum); \
413             spiDevice->spiId = resource->busNum; \
414             resource->csNum = HCS_PROP(node, csNum); \
415             resource->transDir = HCS_PROP(node, transDir); \
416             resource->transMode = HCS_PROP(node, transMode); \
417             resource->smMode = HCS_PROP(node, smMode); \
418             resource->dataWidth = HCS_PROP(node, dataWidth); \
419             resource->clkMode = HCS_PROP(node, clkMode); \
420             resource->csNum = HCS_PROP(node, csNum); \
421             resource->nss = HCS_PROP(node, nss); \
422             resource->baudRate = HCS_PROP(node, baudRate); \
423             resource->bitOrder = HCS_PROP(node, bitOrder); \
424             resource->crcEnable = HCS_PROP(node, crcEnable); \
425             resource->crcPoly = HCS_PROP(node, crcPoly); \
426             resource->spix = HCS_PROP(node, spix); \
427             resource->csPin = HCS_PROP(node, csPin); \
428             resource->csGroup = HCS_PROP(node, csGpiox); \
429             resource->standard = HCS_PROP(node, standard); \
430             resource->dummyByte = HCS_PROP(node, dummyByte); \
431             result = HDF_SUCCESS; \
432         } \
433     } while (0)
434 
435 #define PLATFORM_CONFIG HCS_NODE(HCS_ROOT, platform)
436 #define PLATFORM_SPI_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), spi_config)
GetSpiDeviceResource(SpiDevice * spiDevice,const char * deviceMatchAttr)437 static int32_t GetSpiDeviceResource(SpiDevice *spiDevice, const char *deviceMatchAttr)
438 {
439     int32_t result = HDF_FAILURE;
440     SpiResource *resource = NULL;
441     if (spiDevice == NULL || deviceMatchAttr == NULL) {
442         HDF_LOGE("device or deviceMatchAttr is NULL\r\n");
443         return HDF_ERR_INVALID_PARAM;
444     }
445     resource = &spiDevice->resource;
446 #if HCS_NODE_HAS_PROP(PLATFORM_CONFIG, spi_config)
447     HCS_FOREACH_CHILD_VARGS(PLATFORM_SPI_CONFIG, SPI_FIND_CONFIG, deviceMatchAttr, resource, spiDevice);
448 #endif
449     if (result != HDF_SUCCESS) {
450         HDF_LOGE("resourceNode %s is NULL\r\n", deviceMatchAttr);
451     }
452     return result;
453 }
454 #else
GetSpiDeviceResource(SpiDevice * spiDevice,const struct DeviceResourceNode * resourceNode)455 static int32_t GetSpiDeviceResource(SpiDevice *spiDevice, const struct DeviceResourceNode *resourceNode)
456 {
457     struct DeviceResourceIface *dri = NULL;
458     if (spiDevice == NULL || resourceNode == NULL) {
459         HDF_LOGE("%s: PARAM is NULL\r\n", __func__);
460         return HDF_ERR_INVALID_PARAM;
461     }
462     SpiResource *resource = NULL;
463     resource = &spiDevice->resource;
464     if (resource == NULL) {
465         HDF_LOGE("%s: resource is NULL\r\n", __func__);
466         return HDF_ERR_INVALID_OBJECT;
467     }
468     dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); // open HDF
469     if (dri == NULL || dri->GetUint16 == NULL || dri->GetUint8 == NULL || dri->GetUint32 == NULL) {
470         HDF_LOGE("DeviceResourceIface is invalid\r\n");
471         return HDF_ERR_INVALID_PARAM;
472     }
473     uint8_t temp[HCS_UINT8_PARSE_NUM] = {0};
474     for (int i = 0; i < HCS_UINT8_PARSE_NUM; i++) {
475         if (dri->GetUint8(resourceNode, g_parseHcsMap[i], &temp[i], 0) != HDF_SUCCESS) {
476             HDF_LOGE("get config %s failed\r\n", g_parseHcsMap[i]);
477             return HDF_FAILURE;
478         }
479     }
480     int ret = memcpy_s(resource, HCS_UINT8_PARSE_NUM, temp, HCS_UINT8_PARSE_NUM);
481     if (ret != 0) {
482         HDF_LOGE("memcpy failed\r\n");
483         return HDF_FAILURE;
484     }
485     if (dri->GetUint16(resourceNode, "crcPoly", &resource->crcPoly, 0) != HDF_SUCCESS) {
486         HDF_LOGE("get config %s failed\r\n", "crcPoly");
487         return HDF_FAILURE;
488     }
489     spiDevice->spiId = resource->busNum;
490 
491     return HDF_SUCCESS;
492 }
493 #endif
494 
AttachSpiDevice(struct SpiCntlr * spiCntlr,const struct HdfDeviceObject * device)495 static int32_t AttachSpiDevice(struct SpiCntlr *spiCntlr, const struct HdfDeviceObject *device)
496 {
497     int32_t ret;
498     SpiDevice *spiDevice = NULL;
499 
500 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
501     if (spiCntlr == NULL || device == NULL) {
502 #else
503     if (spiCntlr == NULL || device == NULL || device->property == NULL) {
504 #endif
505         HDF_LOGE("%s: property is NULL\r\n", __func__);
506         return HDF_ERR_INVALID_PARAM;
507     }
508 
509     spiDevice = (SpiDevice *)OsalMemAlloc(sizeof(SpiDevice));
510     if (spiDevice == NULL) {
511         HDF_LOGE("%s: OsalMemAlloc spiDevice error\r\n", __func__);
512         return HDF_ERR_MALLOC_FAIL;
513     }
514 
515 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
516     ret = GetSpiDeviceResource(spiDevice, device->deviceMatchAttr);
517 #else
518     ret = GetSpiDeviceResource(spiDevice, device->property);
519 #endif
520     if (ret != HDF_SUCCESS) {
521         (void)OsalMemFree(spiDevice);
522         return HDF_FAILURE;
523     }
524 
525     spiCntlr->priv = spiDevice;
526     spiCntlr->busNum = spiDevice->spiId;
527     InitSpiDevice(spiDevice);
528 
529     return HDF_SUCCESS;
530 }
531 /* SPI Method */
532 static int32_t SpiDevGetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg);
533 static int32_t SpiDevSetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg);
534 static int32_t SpiDevTransfer(struct SpiCntlr *spiCntlr, struct SpiMsg *spiMsg, uint32_t count);
535 static int32_t SpiDevOpen(struct SpiCntlr *spiCntlr);
536 static int32_t SpiDevClose(struct SpiCntlr *spiCntlr);
537 
538 struct SpiCntlrMethod g_twSpiCntlrMethod = {
539     .GetCfg = SpiDevGetCfg,
540     .SetCfg = SpiDevSetCfg,
541     .Transfer = SpiDevTransfer,
542     .Open = SpiDevOpen,
543     .Close = SpiDevClose,
544 };
545 
546 /* HdfDriverEntry method definitions */
547 static int32_t SpiDriverBind(struct HdfDeviceObject *device);
548 static int32_t SpiDriverInit(struct HdfDeviceObject *device);
549 static void SpiDriverRelease(struct HdfDeviceObject *device);
550 
551 /* HdfDriverEntry definitions */
552 struct HdfDriverEntry g_SpiDriverEntry = {
553     .moduleVersion = 1,
554     .moduleName = "ST_SPI_MODULE_HDF",
555     .Bind = SpiDriverBind,
556     .Init = SpiDriverInit,
557     .Release = SpiDriverRelease,
558 };
559 
560 HDF_INIT(g_SpiDriverEntry);
561 
562 static int32_t SpiDriverBind(struct HdfDeviceObject *device)
563 {
564     struct SpiCntlr *spiCntlr = NULL;
565     if (device == NULL) {
566         HDF_LOGE("Sample device object is null!\r\n");
567         return HDF_ERR_INVALID_PARAM;
568     }
569     HDF_LOGI("Enter %s:\r\n", __func__);
570     spiCntlr = SpiCntlrCreate(device);
571     if (spiCntlr == NULL) {
572         HDF_LOGE("SpiCntlrCreate object is null!\r\n");
573         return HDF_FAILURE;
574     }
575 
576     return HDF_SUCCESS;
577 }
578 
579 static int32_t SpiDriverInit(struct HdfDeviceObject *device)
580 {
581     int32_t ret;
582     struct SpiCntlr *spiCntlr = NULL;
583 
584     if (device == NULL) {
585         HDF_LOGE("%s: device is NULL\r\n", __func__);
586         return HDF_ERR_INVALID_PARAM;
587     }
588 
589     HDF_LOGI("Enter %s:", __func__);
590     spiCntlr = SpiCntlrFromDevice(device);
591     if (spiCntlr == NULL) {
592         HDF_LOGE("%s: spiCntlr is NULL", __func__);
593         return HDF_DEV_ERR_NO_DEVICE;
594     }
595 
596     ret = AttachSpiDevice(spiCntlr, device); // SpiCntlr add TWSpiDevice to priv
597     if (ret != HDF_SUCCESS) {
598         HDF_LOGE("%s: attach error\r\n", __func__);
599         return HDF_DEV_ERR_ATTACHDEV_FAIL;
600     }
601 
602     spiCntlr->method = &g_twSpiCntlrMethod; // register callback
603 
604     return ret;
605 }
606 
607 static void SpiDriverRelease(struct HdfDeviceObject *device)
608 {
609     struct SpiCntlr *spiCntlr = NULL;
610     SpiDevice *spiDevice = NULL;
611 
612     HDF_LOGI("Enter %s\r\n", __func__);
613 
614     if (device == NULL) {
615         HDF_LOGE("%s: device is NULL\r\n", __func__);
616         return;
617     }
618 
619     spiCntlr = SpiCntlrFromDevice(device);
620     if (spiCntlr == NULL || spiCntlr->priv == NULL) {
621         HDF_LOGE("%s: spiCntlr is NULL\r\n", __func__);
622         return;
623     }
624 
625     spiDevice = (SpiDevice *)spiCntlr->priv;
626     OsalMemFree(spiDevice);
627 
628     return;
629 }
630 
631 static int32_t SpiDevOpen(struct SpiCntlr *spiCntlr)
632 {
633     HDF_LOGI("Enter %s\r\n", __func__);
634     SpiDevice *spiDevice = NULL;
635 
636     spiDevice = (SpiDevice*)spiCntlr->priv;
637     SPI_TypeDef* spix = g_spiGroupMaps[spiDevice->resource.spix];
638     LL_SPI_Enable(spix);
639 
640     return HDF_SUCCESS;
641 }
642 
643 static int32_t SpiDevClose(struct SpiCntlr *spiCntlr)
644 {
645     SpiDevice *spiDevice = NULL;
646 
647     spiDevice = (SpiDevice*)spiCntlr->priv;
648     SPI_TypeDef* spix = g_spiGroupMaps[spiDevice->resource.spix];
649     LL_SPI_Disable(spix);
650 
651     return HDF_SUCCESS;
652 }
653 
654 static int32_t SpiDevGetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg)
655 {
656     SpiDevice *spiDevice = NULL;
657 
658     if (spiCntlr == NULL || spiCfg == NULL || spiCntlr->priv == NULL) {
659         HDF_LOGE("%s: spiCntlr is NULL\r\n", __func__);
660         return HDF_ERR_INVALID_PARAM;
661     }
662     spiDevice = (SpiDevice *)spiCntlr->priv;
663     spiCfg->maxSpeedHz = spiDevice->resource.baudRate;
664     spiCfg->mode = spiDevice->resource.clkMode;
665     spiCfg->transferMode = spiDevice->resource.transMode;
666 
667     if (spiDevice->resource.dataWidth == SPI_DATA_WIDTH_16) {
668         spiCfg->bitsPerWord = BITWORD_SIXTEEN;
669     } else {
670         spiCfg->bitsPerWord = BITWORD_EIGHT;
671     }
672 
673     return HDF_SUCCESS;
674 }
675 static int32_t SpiDevSetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg)
676 {
677     SpiDevice *spiDevice = NULL;
678 
679     if (spiCntlr == NULL || spiCfg == NULL || spiCntlr->priv == NULL) {
680         HDF_LOGE("%s: spiCntlr is NULL\r\n", __func__);
681         return HDF_ERR_INVALID_PARAM;
682     }
683     spiDevice = (SpiDevice *)spiCntlr->priv;
684     spiDevice->resource.baudRate = spiCfg->maxSpeedHz;
685     spiDevice->resource.clkMode = spiCfg->mode;
686     spiDevice->resource.transMode = spiCfg->transferMode;
687     if (spiCfg->bitsPerWord == BITWORD_EIGHT) {
688         spiDevice->resource.dataWidth  = SPI_DATA_WIDTH_8;
689     } else {
690         spiDevice->resource.dataWidth  = SPI_DATA_WIDTH_16;
691     }
692 
693     return InitSpiDevice(spiDevice);
694 }
695 
696 static int32_t SpiDevTransfer(struct SpiCntlr *spiCntlr, struct SpiMsg *spiMsg, uint32_t count)
697 {
698     SpiDevice *spiDevice = NULL;
699     uint32_t ticks = 0;
700     uint8_t singleCsChange = 0;
701     struct SpiMsg *msg = NULL;
702     if (spiCntlr == NULL || spiCntlr->priv == NULL) {
703         HDF_LOGE("%s: spiCntlr is NULL\r\n", __func__);
704         return HDF_ERR_INVALID_PARAM;
705     }
706 
707     spiDevice = (SpiDevice *)spiCntlr->priv;
708     for (size_t i = 0; i < count; i++) {
709         msg = &spiMsg[i];
710         LL_GPIO_ResetOutputPin(LL_GET_GPIOX(spiDevice->resource.csGroup), LL_GET_HAL_PIN(spiDevice->resource.csPin));
711 
712         if ((msg->rbuf == NULL) && (msg->wbuf != NULL)) {
713             singleCsChange = msg->wbuf[0];
714 
715             if (msg->len == 1) {
716                 goto CS_DOWN;
717             }
718             HalSpiSend(spiDevice, msg->wbuf + 1, msg->len - 1);
719         }
720 
721         if ((msg->rbuf != NULL) && (msg->wbuf == NULL)) {
722             singleCsChange = msg->rbuf[0];
723 
724             if (msg->len == 1) {
725                 goto CS_DOWN;
726             }
727             HalSpiRecv(spiDevice, msg->rbuf + 1, msg->len - 1);
728         }
729 
730         if ((msg->wbuf != NULL) && (msg->rbuf != NULL)) {
731             HalSpiSendRecv(spiDevice, msg->wbuf, msg->len, msg->rbuf, msg->len);
732         }
733 
734         if (msg->keepCs == 0|| singleCsChange) {
735             LL_GPIO_SetOutputPin(LL_GET_GPIOX(spiDevice->resource.csGroup), LL_GET_HAL_PIN(spiDevice->resource.csPin));
736         }
737         if (msg->delayUs > 0) {
738             ticks = (msg->delayUs / PER_MS_IN_SEC);
739             osDelay(ticks);
740         }
741     }
742     return HDF_SUCCESS;
743 CS_DOWN:
744     if (msg->keepCs == 0 || singleCsChange) {
745         LL_GPIO_SetOutputPin(LL_GET_GPIOX(spiDevice->resource.csGroup), LL_GET_HAL_PIN(spiDevice->resource.csPin));
746     }
747     return HDF_SUCCESS;
748 }
749 
750