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