• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Shenzhen Kaihong 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 "hdf_device_desc.h"
17 #include "hdf_log.h"
18 #include "spi_core.h"
19 #include "gd32f4xx_spi.h"
20 #include "spi_if.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 
28 #define BITWORD_EIGHT 8
29 #define BITWORD_SIXTEEN 16
30 #define PER_MS_IN_SEC 1000
31 #define SPI_CLK 100000000
32 #define WAIT_TIME_MAX 10000
33 #define SPICFG_MODE 0x0000
34 #define SPI_SOFT 0
35 
36 #define GPIO_REG_BASE 0x40020000
37 #define GPIO_REG_STEP 0x00000400
38 #define GPIO_BIT_PER_GROUP 16
39 
40 typedef enum {
41     BAUD_RATE_DIV2 = 2,
42     BAUD_RATE_DIV4 = 4,
43     BAUD_RATE_DIV8 = 8,
44     BAUD_RATE_DIV16 = 16,
45     BAUD_RATE_DIV32 = 32,
46     BAUD_RATE_DIV64 = 64,
47     BAUD_RATE_DIV128 = 128,
48     BAUD_RATE_DIV256 = 256,
49 } SPI_BAUD_RATE;
50 
51 typedef enum {
52     SPI_PORT1 = 0,
53     SPI_PORT2,
54     SPI_PORT3,
55     SPI_PORT4,
56     SPI_PORT5,
57     SPI_PORT6,
58     SPI_PORT_MAX,
59 } SPI_GROUPS;
60 
61 typedef struct {
62     uint32_t speed;
63     uint8_t num;
64     uint8_t csPin;
65     uint8_t dataSize;
66     uint8_t misoPin;
67     uint8_t mosiPin;
68     uint8_t clkPin;
69     uint8_t csSoft;
70     uint8_t transMode;
71     uint8_t mode;
72     uint8_t afPin;
73     uint8_t enableQuad;
74 } SpiResource;
75 
76 typedef struct {
77     uint32_t spiId;
78     SpiResource resource;
79 } SpiDevice;
80 
81 static uint32_t g_spiGroupMaps[SPI_PORT_MAX] = {
82     SPI0, SPI1, SPI2, SPI3, SPI4, SPI5,
83 };
84 
85 static uint32_t g_rcuSpiGroupMaps[SPI_PORT_MAX] = {
86     RCU_SPI0, RCU_SPI1, RCU_SPI2, RCU_SPI3, RCU_SPI4, RCU_SPI5,
87 };
88 
ToGpioPeriph(uint16_t local)89 static inline uint32_t ToGpioPeriph(uint16_t local)
90 {
91     uint32_t gpioPeriph = 0;
92 
93     gpioPeriph = GPIO_REG_BASE + (local / GPIO_BIT_PER_GROUP) * GPIO_REG_STEP;
94 
95     return gpioPeriph;
96 }
97 
ToGpioPin(uint16_t local)98 static inline uint32_t ToGpioPin(uint16_t local)
99 {
100     uint32_t pinNum = 0;
101 
102     pinNum = local % GPIO_BIT_PER_GROUP;
103 
104     return (BIT(pinNum));
105 }
106 
ToGpioRcuPeriphNum(uint16_t local)107 static inline rcu_periph_enum ToGpioRcuPeriphNum(uint16_t local)
108 {
109     rcu_periph_enum rcuPeriph;
110 
111     rcuPeriph = (rcu_periph_enum)(RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, local / GPIO_BIT_PER_GROUP));
112 
113     return rcuPeriph;
114 }
115 
EnableSpiClock(uint32_t spiNum)116 static void EnableSpiClock(uint32_t spiNum)
117 {
118     switch (spiNum) {
119         case SPI_PORT1:
120             spi_enable(SPI0);
121         case SPI_PORT2:
122             spi_enable(SPI1);
123         case SPI_PORT3:
124             spi_enable(SPI2);
125         case SPI_PORT4:
126             spi_enable(SPI3);
127         case SPI_PORT5:
128             spi_enable(SPI4);
129         case SPI_PORT6:
130             spi_enable(SPI5);
131         default:
132             break;
133     }
134 }
135 
InitSpiRcu(const SpiResource * resource)136 static void InitSpiRcu(const SpiResource *resource)
137 {
138     rcu_periph_clock_enable(ToGpioRcuPeriphNum(resource->csPin));
139     rcu_periph_clock_enable(g_rcuSpiGroupMaps[resource->csPin % GPIO_BIT_PER_GROUP]);
140 }
141 
InitSpiGpio(const SpiResource * resource)142 static void InitSpiGpio(const SpiResource *resource)
143 {
144     gpio_af_set(ToGpioPeriph(resource->misoPin), AF(resource->afPin), ToGpioPin(resource->misoPin));
145     gpio_af_set(ToGpioPeriph(resource->mosiPin), AF(resource->afPin), ToGpioPin(resource->mosiPin));
146     gpio_af_set(ToGpioPeriph(resource->clkPin), AF(resource->afPin), ToGpioPin(resource->clkPin));
147 
148     if (resource->enableQuad == TRUE) {
149         gpio_af_set(GPIOG, AF(resource->afPin), GPIO_PIN_10);
150         gpio_af_set(GPIOG, AF(resource->afPin), GPIO_PIN_11);
151     }
152 
153     gpio_mode_set(ToGpioPeriph(resource->misoPin), GPIO_MODE_AF, GPIO_PUPD_NONE, ToGpioPin(resource->misoPin));
154     gpio_mode_set(ToGpioPeriph(resource->mosiPin), GPIO_MODE_AF, GPIO_PUPD_NONE, ToGpioPin(resource->mosiPin));
155     gpio_mode_set(ToGpioPeriph(resource->clkPin), GPIO_MODE_AF, GPIO_PUPD_NONE, ToGpioPin(resource->clkPin));
156     if (resource->enableQuad == TRUE) {
157         gpio_output_options_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
158         gpio_output_options_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
159     }
160 
161     gpio_output_options_set(ToGpioPeriph(resource->misoPin), GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ,
162                             ToGpioPin(resource->misoPin));
163     gpio_output_options_set(ToGpioPeriph(resource->mosiPin), GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ,
164                             ToGpioPin(resource->mosiPin));
165     gpio_output_options_set(ToGpioPeriph(resource->clkPin), GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ,
166                             ToGpioPin(resource->clkPin));
167     if (resource->enableQuad == TRUE) {
168         gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ, GPIO_PIN_10);
169         gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ, GPIO_PIN_11);
170     }
171 
172     gpio_mode_set(ToGpioPeriph(resource->csPin), GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, ToGpioPin(resource->csPin));
173     gpio_output_options_set(ToGpioPeriph(resource->csPin), GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,
174                             ToGpioPin(resource->csPin));
175 }
176 
SpiSendRecv(const SpiDevice * spiDevice,uint8_t * txData,uint8_t * rxData,uint16_t len)177 static int32_t SpiSendRecv(const SpiDevice *spiDevice, uint8_t *txData, uint8_t *rxData, uint16_t len)
178 {
179     uint32_t spiId;
180     uint32_t time = 0;
181     SpiResource *resource = NULL;
182     if (spiDevice == NULL || len == 0) {
183         HDF_LOGE("spi input para err");
184         return HDF_ERR_INVALID_PARAM;
185     }
186     spiId = spiDevice->spiId;
187     resource = &spiDevice->resource;
188 
189     if ((resource->transMode == SPI_INTERRUPT_TRANSFER) || (resource->transMode == SPI_DMA_TRANSFER)) {
190         HDF_LOGE("%s: transfer mode is not support!", __func__);
191         return HDF_ERR_INVALID_PARAM;
192     } else if (resource->transMode != SPI_POLLING_TRANSFER) {
193         HDF_LOGE("%s: error transfer mode!", __func__);
194     }
195 
196     while (len--) {
197         if (txData != NULL) {
198             time = 0;
199             while ((RESET == spi_i2s_flag_get(g_spiGroupMaps[spiId], SPI_FLAG_TBE)) && (time <= WAIT_TIME_MAX)) {
200                 time++;
201             }
202             if (time > WAIT_TIME_MAX) {
203                 return HDF_FAILURE;
204             }
205             spi_i2s_data_transmit(g_spiGroupMaps[spiId], *txData);
206             txData++;
207         }
208 
209         if (rxData != NULL) {
210             time = 0;
211             while ((RESET == spi_i2s_flag_get(g_spiGroupMaps[spiId], SPI_FLAG_RBNE)) && (time <= WAIT_TIME_MAX)) {
212                 time++;
213             }
214             if (time > WAIT_TIME_MAX) {
215                 return HDF_FAILURE;
216             }
217             *rxData = spi_i2s_data_receive(g_spiGroupMaps[spiId]);
218             rxData++;
219         }
220     }
221 
222     return HDF_SUCCESS;
223 }
SpiClkInit(spi_parameter_struct * spi,const SpiResource * resource)224 static void SpiClkInit(spi_parameter_struct *spi, const SpiResource *resource)
225 {
226     if (SPI_CLK / resource->speed <= BAUD_RATE_DIV2) {
227         spi->prescale = SPI_PSC_2;
228     } else if (SPI_CLK / resource->speed <= BAUD_RATE_DIV4) {
229         spi->prescale = SPI_PSC_4;
230     } else if (SPI_CLK / resource->speed <= BAUD_RATE_DIV8) {
231         spi->prescale = SPI_PSC_8;
232     } else if (SPI_CLK / resource->speed <= BAUD_RATE_DIV16) {
233         spi->prescale = SPI_PSC_16;
234     } else if (SPI_CLK / resource->speed <= BAUD_RATE_DIV32) {
235         spi->prescale = SPI_PSC_32;
236     } else if (SPI_CLK / resource->speed <= BAUD_RATE_DIV64) {
237         spi->prescale = SPI_PSC_64;
238     } else if (SPI_CLK / resource->speed <= BAUD_RATE_DIV128) {
239         spi->prescale = SPI_PSC_128;
240     } else if (SPI_CLK / resource->speed > BAUD_RATE_DIV128) {
241         spi->prescale = SPI_PSC_256;
242     }
243 }
SpiStructInit(spi_parameter_struct * spi,const SpiResource * resource)244 static void SpiStructInit(spi_parameter_struct *spi, const SpiResource *resource)
245 {
246     uint32_t temp = 0;
247     spi->device_mode = SPI_MASTER;
248     spi->trans_mode = SPI_TRANSMODE_FULLDUPLEX;
249     if (resource->dataSize == BITWORD_EIGHT) {
250         spi->frame_size = SPI_FRAMESIZE_8BIT;
251     } else {
252         spi->frame_size = SPI_FRAMESIZE_16BIT;
253     }
254     temp = (resource->mode & (SPI_CLK_PHASE | SPI_CLK_POLARITY));
255     switch (temp) {
256         case (SPI_CLK_PHASE | SPI_CLK_POLARITY):
257             spi->clock_polarity_phase = SPI_CK_PL_HIGH_PH_2EDGE;
258             break;
259         case SPI_CLK_PHASE:
260             spi->clock_polarity_phase = SPI_CK_PL_LOW_PH_2EDGE;
261             break;
262         case SPI_CLK_POLARITY:
263             spi->clock_polarity_phase = SPI_CK_PL_HIGH_PH_1EDGE;
264             break;
265         default:
266             spi->clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
267             break;
268     }
269     if (resource->mode & SPI_MODE_LSBFE) {
270         spi->endian = SPI_ENDIAN_LSB;
271     } else {
272         spi->endian = SPI_ENDIAN_MSB;
273     }
274     if (resource->csSoft == SPI_SOFT) {
275         spi->nss = SPI_NSS_SOFT;
276     } else {
277         spi->nss = SPI_NSS_HARD;
278     }
279     SpiClkInit(spi, resource);
280     return;
281 }
282 
InitSpiDevice(const SpiDevice * spiDevice)283 static int32_t InitSpiDevice(const SpiDevice *spiDevice)
284 {
285     SpiResource *resource = NULL;
286     spi_parameter_struct spiInitStruct = {0};
287     uint32_t spix;
288 
289     if (spiDevice == NULL) {
290         HDF_LOGE("%s: invalid parameter", __func__);
291         return HDF_ERR_INVALID_PARAM;
292     }
293 
294     resource = &spiDevice->resource;
295     spix = g_spiGroupMaps[resource->num];
296 
297     SpiStructInit(&spiInitStruct, resource);
298     spi_init(spix, &spiInitStruct);
299 
300     if (resource->enableQuad == TRUE) {
301         /* quad wire SPI_IO2 and SPI_IO3 pin output enable */
302         spi_quad_io23_output_enable(spix);
303     }
304 
305     spi_enable(spix);
306 
307     return HDF_SUCCESS;
308 }
309 
310 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
311 #define SPI_FIND_CONFIG(node, name, resource, spiDevice)                                                               \
312     do {                                                                                                               \
313         if (strcmp(HCS_PROP(node, match_attr), name) == 0) {                                                           \
314             resource->speed = HCS_PROP(node, speed);                                                                   \
315             resource->num = HCS_PROP(node, num);                                                                       \
316             resource->csPin = HCS_PROP(node, csPin);                                                                   \
317             resource->dataSize = HCS_PROP(node, dataSize);                                                             \
318             resource->clkPin = HCS_PROP(node, clkPin);                                                                 \
319             resource->mosiPin = HCS_PROP(node, mosiPin);                                                               \
320             resource->misoPin = HCS_PROP(node, misoPin);                                                               \
321             resource->afPin = HCS_PROP(node, afPin);                                                                   \
322             resource->enableQuad = HCS_PROP(node, enableQuad);                                                         \
323             resource->csSoft = HCS_PROP(node, csSoft);                                                                 \
324             resource->transMode = HCS_PROP(node, transMode);                                                           \
325             resource->mode = HCS_PROP(node, mode);                                                                     \
326             spiDevice->spiId = resource->num;                                                                          \
327             result = HDF_SUCCESS;                                                                                      \
328         }                                                                                                              \
329     } while (0)
330 
331 #define PLATFORM_CONFIG HCS_NODE(HCS_ROOT, platform)
332 #define PLATFORM_SPI_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), spi_config)
GetSpiDeviceResource(SpiDevice * spiDevice,const char * deviceMatchAttr)333 static int32_t GetSpiDeviceResource(SpiDevice *spiDevice, const char *deviceMatchAttr)
334 {
335     int32_t result = HDF_FAILURE;
336     SpiResource *resource = NULL;
337     if (spiDevice == NULL || deviceMatchAttr == NULL) {
338         HDF_LOGE("device or deviceMatchAttr is NULL");
339         return HDF_ERR_INVALID_PARAM;
340     }
341     resource = &spiDevice->resource;
342 #if HCS_NODE_HAS_PROP(PLATFORM_CONFIG, spi_config)
343     HCS_FOREACH_CHILD_VARGS(PLATFORM_SPI_CONFIG, SPI_FIND_CONFIG, deviceMatchAttr, resource, spiDevice);
344 #endif
345     if (result != HDF_SUCCESS) {
346         HDF_LOGE("resourceNode %s is NULL", deviceMatchAttr);
347     }
348     return result;
349 }
350 #else
GetSpiDeviceResource(SpiDevice * spiDevice,const struct DeviceResourceNode * resourceNode)351 static int32_t GetSpiDeviceResource(SpiDevice *spiDevice, const struct DeviceResourceNode *resourceNode)
352 {
353     struct DeviceResourceIface *dri = NULL;
354     SpiResource *resource = NULL;
355 
356     if (spiDevice == NULL || resourceNode == NULL) {
357         HDF_LOGE("%s: PARAM is NULL", __func__);
358         return HDF_ERR_INVALID_PARAM;
359     }
360 
361     resource = &spiDevice->resource;
362     if (resource == NULL) {
363         HDF_LOGE("%s: resource is NULL", __func__);
364         return HDF_ERR_INVALID_OBJECT;
365     }
366 
367     dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
368     if (dri == NULL || dri->GetUint16 == NULL || dri->GetUint8 == NULL || dri->GetUint32 == NULL) {
369         HDF_LOGE("DeviceResourceIface is invalid");
370         return HDF_ERR_INVALID_PARAM;
371     }
372 
373     if (dri->GetUint8(resourceNode, "num", &resource->num, 0) != HDF_SUCCESS) {
374         HDF_LOGE("get config num failed");
375         return HDF_FAILURE;
376     }
377     if (dri->GetUint8(resourceNode, "csPin", &resource->csPin, 0) != HDF_SUCCESS) {
378         HDF_LOGE("get config csPin failed");
379         return HDF_FAILURE;
380     }
381     if (dri->GetUint32(resourceNode, "speed", &resource->speed, 0) != HDF_SUCCESS) {
382         HDF_LOGE("get config speed failed");
383         return HDF_FAILURE;
384     }
385     if (dri->GetUint32(resourceNode, "dataSize", &resource->dataSize, 0) != HDF_SUCCESS) {
386         HDF_LOGE("get config dataSize failed");
387         return HDF_FAILURE;
388     }
389     if (dri->GetUint32(resourceNode, "clkPin", &resource->clkPin, 0) != HDF_SUCCESS) {
390         HDF_LOGE("get config spiClkPin failed");
391         return HDF_FAILURE;
392     }
393     if (dri->GetUint32(resourceNode, "mosiPin", &resource->mosiPin, 0) != HDF_SUCCESS) {
394         HDF_LOGE("get config spiMosiPin failed");
395         return HDF_FAILURE;
396     }
397     if (dri->GetUint32(resourceNode, "misoPin", &resource->misoPin, 0) != HDF_SUCCESS) {
398         HDF_LOGE("get config spiMisoPin failed");
399         return HDF_FAILURE;
400     }
401     if (dri->GetUint32(resourceNode, "csSoft", &resource->csSoft, 0) != HDF_SUCCESS) {
402         HDF_LOGE("get config spiCsSoft failed");
403         return HDF_FAILURE;
404     }
405     if (dri->GetUint32(resourceNode, "transMode", &resource->transMode, 0) != HDF_SUCCESS) {
406         HDF_LOGE("get config transMode failed");
407         return HDF_FAILURE;
408     }
409     if (dri->GetUint32(resourceNode, "mode", &resource->mode, 0) != HDF_SUCCESS) {
410         HDF_LOGE("get config mode failed");
411         return HDF_FAILURE;
412     }
413     if (dri->GetUint32(resourceNode, "afPin", &resource->afPin, 0) != HDF_SUCCESS) {
414         HDF_LOGE("get config afPin failed");
415         return HDF_FAILURE;
416     }
417     if (dri->GetUint32(resourceNode, "enableQuad", &resource->enableQuad, 0) != HDF_SUCCESS) {
418         HDF_LOGE("get config enableQuad failed");
419         return HDF_FAILURE;
420     }
421 
422     spiDevice->spiId = resource->num;
423 
424     return HDF_SUCCESS;
425 }
426 #endif
427 
AttachSpiDevice(struct SpiCntlr * spiCntlr,const struct HdfDeviceObject * device)428 static int32_t AttachSpiDevice(struct SpiCntlr *spiCntlr, const struct HdfDeviceObject *device)
429 {
430     int32_t ret;
431     SpiDevice *spiDevice = NULL;
432 
433 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
434     if (spiCntlr == NULL || device == NULL) {
435 #else
436     if (spiCntlr == NULL || device == NULL || device->property == NULL) {
437 #endif
438         HDF_LOGE("%s: param is NULL", __func__);
439         return HDF_ERR_INVALID_PARAM;
440     }
441 
442     spiDevice = (struct SpiDevice *)OsalMemAlloc(sizeof(*spiDevice));
443     if (spiDevice == NULL) {
444         HDF_LOGE("%s: OsalMemAlloc spiDevice error", __func__);
445         return HDF_ERR_MALLOC_FAIL;
446     }
447 
448 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
449     ret = GetSpiDeviceResource(spiDevice, device->deviceMatchAttr);
450 #else
451     ret = GetSpiDeviceResource(spiDevice, device->property);
452 #endif
453     if (ret != HDF_SUCCESS) {
454         (void)OsalMemFree(spiDevice);
455         return HDF_FAILURE;
456     }
457 
458     spiCntlr->priv = spiDevice;
459     spiCntlr->busNum = spiDevice->spiId;
460 
461     InitSpiRcu(&spiDevice->resource);
462     InitSpiGpio(&spiDevice->resource);
463     InitSpiDevice(spiDevice);
464 
465     return HDF_SUCCESS;
466 }
467 
468 static int32_t SpiDevOpen(struct SpiCntlr *spiCntlr)
469 {
470     HDF_LOGI("Enter %s", __func__);
471     if (spiCntlr == NULL) {
472         HDF_LOGE("spiCntlr is NULL");
473         return HDF_ERR_INVALID_PARAM;
474     }
475     SpiDevice *spiDevice = NULL;
476     spiDevice = (SpiDevice *)spiCntlr->priv;
477     uint32_t spix = g_spiGroupMaps[spiDevice->resource.num];
478     spi_enable(spix);
479 
480     return HDF_SUCCESS;
481 }
482 
483 static int32_t SpiDevClose(struct SpiCntlr *spiCntlr)
484 {
485     HDF_LOGI("Enter %s", __func__);
486     if (spiCntlr == NULL) {
487         HDF_LOGE("spiCntlr is NULL");
488         return HDF_ERR_INVALID_PARAM;
489     }
490     SpiDevice *spiDevice = NULL;
491     spiDevice = (SpiDevice *)spiCntlr->priv;
492     uint32_t spix = g_spiGroupMaps[spiDevice->resource.num];
493     spi_disable(spix);
494 
495     return HDF_SUCCESS;
496 }
497 
498 static int32_t SpiDevGetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg)
499 {
500     SpiDevice *spiDevice = NULL;
501     if (spiCntlr == NULL || spiCfg == NULL || spiCntlr->priv == NULL) {
502         HDF_LOGE("%s: spiCntlr is NULL", __func__);
503         return HDF_ERR_INVALID_PARAM;
504     }
505     spiDevice = (SpiDevice *)spiCntlr->priv;
506     if (spiDevice == NULL) {
507         return HDF_DEV_ERR_NO_DEVICE;
508     }
509 
510     spiCfg->maxSpeedHz = spiDevice->resource.speed;
511     spiCfg->mode = spiDevice->resource.mode;
512     spiCfg->transferMode = spiDevice->resource.transMode;
513     spiCfg->bitsPerWord = spiDevice->resource.dataSize;
514 
515     return HDF_SUCCESS;
516 }
517 
518 static int32_t SpiDevSetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg)
519 {
520     SpiDevice *spiDevice = NULL;
521     if (spiCntlr == NULL || spiCfg == NULL || spiCntlr->priv == NULL) {
522         HDF_LOGE("%s: spiCntlr is NULL", __func__);
523         return HDF_ERR_INVALID_PARAM;
524     }
525     spiDevice = (SpiDevice *)spiCntlr->priv;
526     if (spiDevice == NULL) {
527         HDF_LOGE("%s: spiDevice is NULL", __func__);
528         return HDF_DEV_ERR_NO_DEVICE;
529     }
530 
531     if ((spiDevice->resource.speed == spiCfg->maxSpeedHz) && (spiDevice->resource.dataSize == spiCfg->bitsPerWord) &&
532         (spiDevice->resource.transMode == spiCfg->transferMode) && (spiDevice->resource.mode == spiCfg->mode)) {
533         return HDF_SUCCESS;
534     }
535 
536     spiDevice->resource.speed = spiCfg->maxSpeedHz;
537     spiDevice->resource.dataSize = spiCfg->bitsPerWord;
538     spiDevice->resource.transMode = spiCfg->transferMode;
539     spiDevice->resource.mode = spiCfg->mode;
540 
541     return InitSpiDevice(spiDevice);
542 }
543 
544 static int32_t SpiDevTransfer(struct SpiCntlr *spiCntlr, struct SpiMsg *spiMsg, uint32_t count)
545 {
546     SpiDevice *spiDevice = NULL;
547     uint32_t ticks = 0;
548     int32_t ret = 0;
549     uint8_t singleCsChange = 0;
550     struct SpiMsg *msg = NULL;
551     msg = (struct SpiMsg *)OsalMemAlloc(sizeof(*msg));
552     if (spiCntlr == NULL || spiCntlr->priv == NULL) {
553         HDF_LOGE("%s: spiCntlr is NULL", __func__);
554         return HDF_ERR_INVALID_PARAM;
555     }
556     spiDevice = (SpiDevice *)spiCntlr->priv;
557     InitSpiDevice(spiDevice);
558 
559     for (size_t i = 0; i < count; i++) {
560         msg = &spiMsg[i];
561         gpio_bit_reset(ToGpioPeriph((spiDevice->resource).csPin), ToGpioPin((spiDevice->resource).csPin));
562 
563         ret = SpiSendRecv(spiDevice, msg->wbuf, msg->rbuf, msg->len);
564         if (ret != HDF_SUCCESS) {
565             HDF_LOGE("%s: SpiSendRecv failed: ret is %x", __func__, ret);
566         }
567 
568         if (msg->keepCs == 0 || singleCsChange) {
569             gpio_bit_reset(ToGpioPeriph((spiDevice->resource).csPin), ToGpioPin((spiDevice->resource).csPin));
570         }
571         if (msg->delayUs > 0) {
572             ticks = (msg->delayUs / PER_MS_IN_SEC);
573             osDelay(ticks);
574         }
575     }
576 
577     HDF_LOGD("%s success\n", __func__);
578     return HDF_SUCCESS;
579 }
580 
581 struct SpiCntlrMethod g_method = {
582     .Transfer = SpiDevTransfer,
583     .SetCfg = SpiDevSetCfg,
584     .GetCfg = SpiDevGetCfg,
585     .Open = SpiDevOpen,
586     .Close = SpiDevClose,
587 };
588 
589 static int32_t SpiDriverBind(struct HdfDeviceObject *device)
590 {
591     struct SpiCntrl *spiCntlr = NULL;
592 
593     HDF_LOGI("%s: Enter ", __func__);
594 
595     if (device == NULL) {
596         HDF_LOGE("device object is null!");
597         return HDF_ERR_INVALID_PARAM;
598     }
599 
600     spiCntlr = SpiCntlrCreate(device);
601     if (spiCntlr == NULL) {
602         HDF_LOGE("SpiCntrlCreate object failed!");
603         return HDF_FAILURE;
604     }
605     HDF_LOGI("%s spi bind success\n", __func__);
606 
607     return HDF_SUCCESS;
608 }
609 
610 static int32_t SpiDriverInit(struct HdfDeviceObject *device)
611 {
612     int32_t ret;
613     struct SpiCntlr *spiCntlr = NULL;
614 
615     if (device == NULL) {
616         HDF_LOGE("device object is null!");
617         return HDF_ERR_INVALID_PARAM;
618     }
619     HDF_LOGI("%s: Enter", __func__);
620 
621     spiCntlr = SpiCntlrFromDevice(device);
622     if (spiCntlr == NULL) {
623         HDF_LOGE("%s: spiCntlr is NULL", __func__);
624         return HDF_DEV_ERR_NO_DEVICE;
625     }
626 
627     ret = AttachSpiDevice(spiCntlr, device);
628     if (ret != HDF_SUCCESS) {
629         HDF_LOGE("%s: attach error", __func__);
630         return HDF_DEV_ERR_ATTACHDEV_FAIL;
631     }
632 
633     spiCntlr->method = &g_method;
634     HDF_LOGI("%s spi%d init success\n", __func__, spiCntlr->busNum);
635 
636     return HDF_SUCCESS;
637 }
638 
639 static void SpiDriverRelease(struct HdfDeviceObject *device)
640 {
641     struct SpiCntlr *spiCntlr = NULL;
642     SpiDevice *spiDevice = NULL;
643     if (device == NULL) {
644         HDF_LOGE("%s: device is NULL", __func__);
645         return;
646     }
647 
648     spiCntlr = SpiCntlrFromDevice(device);
649     if (spiCntlr == NULL || spiCntlr->priv == NULL) {
650         HDF_LOGE("%s: spiCntlr is NULL", __func__);
651         return;
652     }
653 
654     spiDevice = (SpiDevice *)spiCntlr->priv;
655     OsalMemFree(spiDevice);
656 
657     HDF_LOGD("%s success", __func__);
658 }
659 
660 struct HdfDriverEntry g_hdfSpiDevice = {
661     .moduleVersion = 1,
662     .moduleName = "GD_SPI_MODULE_HDF",
663     .Bind = SpiDriverBind,
664     .Init = SpiDriverInit,
665     .Release = SpiDriverRelease,
666 };
667 HDF_INIT(g_hdfSpiDevice);