1 /*
2 * Copyright (c) 2021-2022 Bestechnic (Shanghai) Co., Ltd. All rights reserved.
3 *
4 * This file 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 "spi_bes.h"
10 #include <stdlib.h>
11 #include <string.h>
12 #include "spi_core.h"
13 #include "hal_cache.h"
14 #include "hal_trace.h"
15 #include "hdf_log.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 #endif
22
23 #define SPI_DMA_MAX 4095
24 #define DEC_NUM 10
25 #define GROUP_PIN_NUM 8
26 #define TIMEOUT 1000
27 #define SPI_PIN_0 0
28 #define SPI_PIN_1 1
29 #define SPI_PIN_2 2
30 #define SPI_PIN_3 3
31 #define DRIVER_LEVEL 3
32 #define MAX_SPI_NUMBER 2
33 #define MAX_SPI_SPEED 26000000
34 static void Spi0DmaIrq(int error);
35 static void Spi1DmaIrq(int error);
36
37 static struct SPI_CTX_OBJ_T spiCtx[MAX_SPI_NUMBER] = {
38 {
39 .spiPinCS0 = 0,
40 #if defined (LOSCFG_SOC_SERIES_BES2700)
41 .spiFunDI0 = HAL_IOMUX_FUNC_SYS_SPI_DI0,
42 .spiFunCLK = HAL_IOMUX_FUNC_SYS_SPI_CLK,
43 .spiFunCS0 = HAL_IOMUX_FUNC_SYS_SPI_CS0,
44 .spiFunDIO = HAL_IOMUX_FUNC_SYS_SPI_DIO,
45 #elif defined (LOSCFG_SOC_SERIES_BES2600)
46 .spiFunDI0 = HAL_IOMUX_FUNC_SPI_DI0,
47 .spiFunCLK = HAL_IOMUX_FUNC_SPI_CLK,
48 .spiFunCS0 = HAL_IOMUX_FUNC_SPI_CS0,
49 .spiFunDIO = HAL_IOMUX_FUNC_SPI_DIO,
50 #endif
51 .sem = { NULL },
52 .mutex = { NULL },
53 .SpiOpen = hal_spi_open,
54 .SpiDmaSend = hal_spi_dma_send,
55 .SpiDmaRecv = hal_spi_dma_recv,
56 .SpiSend = hal_spi_send,
57 .SpiRecv = hal_spi_recv,
58 .SpiDmaIrq = Spi0DmaIrq,
59 .SpiClose = hal_spi_close
60 },
61 {
62 .spiPinCS0 = 0,
63 #if defined (LOSCFG_SOC_SERIES_BES2700)
64 .spiFunDI0 = HAL_IOMUX_FUNC_SYS_SPILCD_DI0,
65 .spiFunCLK = HAL_IOMUX_FUNC_SYS_SPILCD_CLK,
66 .spiFunCS0 = HAL_IOMUX_FUNC_SYS_SPILCD_CS0,
67 .spiFunDIO = HAL_IOMUX_FUNC_SYS_SPILCD_DIO,
68 #elif defined (LOSCFG_SOC_SERIES_BES2600)
69 .spiFunDI0 = HAL_IOMUX_FUNC_SPILCD_DI0,
70 .spiFunCLK = HAL_IOMUX_FUNC_SPILCD_CLK,
71 .spiFunCS0 = HAL_IOMUX_FUNC_SPILCD_CS0,
72 .spiFunDIO = HAL_IOMUX_FUNC_SPILCD_DIO,
73 #endif
74 .sem = { NULL },
75 .mutex = { NULL },
76 .SpiOpen = hal_spilcd_open,
77 .SpiDmaSend = hal_spilcd_dma_send,
78 .SpiDmaRecv = hal_spilcd_dma_recv,
79 .SpiSend = hal_spilcd_send,
80 .SpiRecv = hal_spilcd_recv,
81 .SpiDmaIrq = Spi1DmaIrq,
82 .SpiClose = hal_spilcd_close
83 }
84 };
85
86 static struct HAL_IOMUX_PIN_FUNCTION_MAP pinMuxSpi[] = {
87 {0, 0, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_NOPULL },
88 {0, 0, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_NOPULL },
89 {0, 0, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_NOPULL },
90 {0, 0, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_NOPULL },
91 };
92
Spi0DmaIrq(int error)93 void Spi0DmaIrq(int error)
94 {
95 (void)error;
96 if (HDF_SUCCESS != OsalSemPost(&spiCtx[0].sem)) {
97 HDF_LOGE("spi0dmairq OsalSemPost failed!\r\n");
98 return;
99 }
100 }
101
Spi1DmaIrq(int error)102 void Spi1DmaIrq(int error)
103 {
104 (void)error;
105 if (HDF_SUCCESS != OsalSemPost(&spiCtx[1].sem)) {
106 HDF_LOGE("spi1dmairq OsalSemPost failed!\r\n");
107 return;
108 }
109 }
110
SpiIomuxInit(struct SpiDevice * spiDevice)111 static void SpiIomuxInit(struct SpiDevice *spiDevice)
112 {
113 struct HAL_SPI_CFG_T *spiDevCfg = NULL;
114 struct SpiResource *resource = NULL;
115 uint32_t spiPort;
116 HDF_LOGI("%s: Enter\r\n", __func__);
117
118 if (spiDevice == NULL) {
119 HDF_LOGE("%s: invalid parameter\r\n", __func__);
120 return;
121 }
122
123 resource = &spiDevice->resource;
124 if (resource == NULL) {
125 HDF_LOGE("resource is null\r\n");
126 return;
127 }
128 spiDevCfg = &spiDevice->spiDevCfg;
129 if (spiDevCfg == NULL) {
130 HDF_LOGE("resource is null\r\n");
131 return;
132 }
133 spiDevCfg->rate = resource->speed;
134
135 spiPort = spiDevice->spiId;
136
137 pinMuxSpi[SPI_PIN_0].pin = resource->spiMisoPin;
138 pinMuxSpi[SPI_PIN_1].pin = resource->spiClkPin;
139 pinMuxSpi[SPI_PIN_2].pin = resource->spiCsPin;
140 pinMuxSpi[SPI_PIN_3].pin = resource->spiMosiPin;
141
142 spiCtx[spiPort].spiPinCS0 = resource->spiCsPin;
143
144 pinMuxSpi[SPI_PIN_0].function = spiCtx[spiPort].spiFunDI0;
145 pinMuxSpi[SPI_PIN_1].function = spiCtx[spiPort].spiFunCLK;
146
147 if (resource->spiCsSoft) {
148 spiCtx[spiPort].spiFunCS0 = HAL_IOMUX_FUNC_AS_GPIO;
149 }
150
151 pinMuxSpi[SPI_PIN_2].function = spiCtx[spiPort].spiFunCS0;
152 pinMuxSpi[SPI_PIN_3].function = spiCtx[spiPort].spiFunDIO;
153
154 hal_iomux_set_io_drv(pinMuxSpi[SPI_PIN_0].pin, DRIVER_LEVEL);
155 hal_iomux_set_io_drv(pinMuxSpi[SPI_PIN_1].pin, DRIVER_LEVEL);
156 hal_iomux_set_io_drv(pinMuxSpi[SPI_PIN_2].pin, DRIVER_LEVEL);
157 hal_iomux_set_io_drv(pinMuxSpi[SPI_PIN_3].pin, DRIVER_LEVEL);
158
159 hal_iomux_init(pinMuxSpi, ARRAY_SIZE(pinMuxSpi));
160 }
161
SpiDevCfgInit(struct HAL_SPI_CFG_T * spiDevCfg,const struct SpiResource * resource)162 static int32_t SpiDevCfgInit(struct HAL_SPI_CFG_T *spiDevCfg, const struct SpiResource *resource)
163 {
164 if (spiDevCfg == NULL || resource == NULL) {
165 HDF_LOGE("spi input para err\r\n");
166 return HDF_ERR_INVALID_PARAM;
167 }
168 switch (resource->mode) {
169 case SPI_WORK_MODE_0:
170 spiDevCfg->clk_delay_half = false;
171 spiDevCfg->clk_polarity = false;
172 break;
173 case SPI_WORK_MODE_1:
174 spiDevCfg->clk_delay_half = true;
175 spiDevCfg->clk_polarity = false;
176 break;
177 case SPI_WORK_MODE_2:
178 spiDevCfg->clk_delay_half = false;
179 spiDevCfg->clk_polarity = true;
180 break;
181 case SPI_WORK_MODE_3:
182 spiDevCfg->clk_delay_half = true;
183 spiDevCfg->clk_polarity = true;
184 break;
185 default:
186 spiDevCfg->clk_delay_half = true;
187 spiDevCfg->clk_polarity = true;
188 }
189 spiDevCfg->slave = 0;
190 if (resource->transmode == SPI_TRANSFER_DMA) {
191 spiDevCfg->dma_rx = true;
192 spiDevCfg->dma_tx = true;
193 } else {
194 spiDevCfg->dma_rx = false;
195 spiDevCfg->dma_tx = false;
196 }
197 spiDevCfg->cs = 0;
198 spiDevCfg->rx_bits = resource->dataSize;
199 spiDevCfg->tx_bits = resource->dataSize;
200 spiDevCfg->rx_frame_bits = 0;
201 return HDF_SUCCESS;
202 }
203 /**
204 * Spi send
205 *
206 * @param[in] spiId the spi bus id
207 * @param[in] data spi send data
208 * @param[in] size spi send data size
209 * @param[in] timeOut timeOut in milisecond, set this value to HAL_WAIT_FOREVER
210 * if you want to wait forever
211 *
212 * @return 0 : on success, EIO : if the SPI device could not be initialised
213 */
214
215 #ifdef HalSpiSend
216 #undef HalSpiSend
217 #endif
HalSpiSend(const struct SpiDevice * spiDevice,const uint8_t * data,uint16_t size,uint32_t timeOut)218 static int32_t HalSpiSend(const struct SpiDevice *spiDevice, const uint8_t *data, uint16_t size, uint32_t timeOut)
219 {
220 int32_t ret;
221 uint32_t spiId;
222 uint32_t len = size;
223 struct SpiResource *resource = NULL;
224 int32_t status = HDF_FAILURE;
225
226 if (spiDevice == NULL || data == NULL || size == 0) {
227 HDF_LOGE("spi input para err\r\n");
228 return HDF_ERR_INVALID_PARAM;
229 }
230
231 spiId = spiDevice->spiId;
232 resource = &spiDevice->resource;
233 if (resource == NULL) {
234 HDF_LOGE("resource is null\r\n");
235 return HDF_ERR_INVALID_OBJECT;
236 }
237 status = OsalMutexLock(&spiCtx[spiId].mutex);
238 if (HDF_SUCCESS != status) {
239 HDF_LOGE("%s spi_mutex wait error = 0x%X!\r\n", __func__, status);
240 return HDF_ERR_TIMEOUT;
241 }
242 #ifdef LOSCFG_SOC_SERIES_BES2700
243 hal_cache_sync_all(HAL_CACHE_ID_D_CACHE);
244 #endif
245 if (resource->transmode == SPI_TRANSFER_DMA) {
246 ret = spiCtx[spiId].SpiDmaSend(data, len, spiCtx[spiId].SpiDmaIrq);
247 if (OsalSemWait(&spiCtx[spiId].sem, timeOut) != HDF_SUCCESS) {
248 HDF_LOGE("spi dma send timeOut\r\n");
249 goto OUT;
250 }
251 } else {
252 ret = spiCtx[spiId].SpiSend(data, len);
253 }
254
255 if (ret != 0) {
256 HDF_LOGE("spi tail send fail %ld, size %ld\r\n", ret, len);
257 goto OUT;
258 }
259 OUT:
260 OsalMutexUnlock(&spiCtx[spiId].mutex);
261 return ret;
262 }
263
264 #ifdef HalSpiRecv
265 #undef HalSpiRecv
266 #endif
267
268 /**
269 * SpiRecv
270 *
271 * @param[in] spiId the spi bus id
272 * @param[out] data spi recv data
273 * @param[in] size spi recv data size
274 * @param[in] timeOut timeOut in milisecond, set this value to HAL_WAIT_FOREVER
275 * if you want to wait forever
276 *
277 * @return 0 : on success, EIO : if the SPI device could not be initialised
278 */
HalSpiRecv(const struct SpiDevice * spiDevice,uint8_t * data,uint16_t size,uint32_t timeOut)279 static int32_t HalSpiRecv(const struct SpiDevice *spiDevice, uint8_t *data, uint16_t size, uint32_t timeOut)
280 {
281 int32_t ret;
282 int32_t len = (int32_t)size;
283 uint32_t remainder;
284 int32_t status = HDF_FAILURE;
285 uint8_t *cmd = NULL;
286 uint32_t spiId;
287 struct SpiResource *resource = NULL;
288
289 if (spiDevice == NULL || data == NULL || size == 0) {
290 HDF_LOGE("spi input para err\r\n");
291 return HDF_ERR_INVALID_PARAM;
292 }
293
294 spiId = spiDevice->spiId;
295 resource = &spiDevice->resource;
296 if (resource == NULL) {
297 HDF_LOGE("resource is null\r\n");
298 return HDF_ERR_INVALID_OBJECT;
299 }
300 cmd = (uint8_t *)0x20020000; // 0x20020000 : non secure sram base. tx buf is useless, use sram instead of malloc.
301
302 status = OsalMutexLock(&spiCtx[spiId].mutex);
303 if (HDF_SUCCESS != status) {
304 HDF_LOGE("%s spi_mutex wait error = 0x%X!\r\n", __func__, status);
305 return HDF_ERR_TIMEOUT;
306 }
307 #ifdef LOSCFG_SOC_SERIES_BES2700
308 hal_cache_sync_all(HAL_CACHE_ID_D_CACHE);
309 #endif
310 do {
311 remainder = len <= SPI_DMA_MAX ? len : SPI_DMA_MAX;
312 if (resource->transmode == SPI_TRANSFER_DMA) {
313 ret = spiCtx[spiId].SpiDmaRecv(cmd, data, remainder, spiCtx[spiId].SpiDmaIrq);
314 if (OsalSemWait(&spiCtx[spiId].sem, timeOut) <= 0) {
315 HDF_LOGE("SPI Read timeOut!\r\n");
316 goto OUT;
317 }
318 } else {
319 ret = spiCtx[spiId].SpiRecv(cmd, data, remainder);
320 }
321
322 len -= remainder;
323 data += remainder;
324
325 if (ret != 0) {
326 HDF_LOGE("spi tail fail %ld, size %ld\r\n", ret, len);
327 goto OUT;
328 }
329 } while (len != 0);
330 OUT:
331 OsalMutexUnlock(&spiCtx[spiId].mutex);
332 return ret;
333 }
334
335 #ifdef HalSpiSendRecv
336 #undef HalSpiSendRecv
337 #endif
HalSpiSendRecv(const struct SpiDevice * spiDevice,uint8_t * txData,uint16_t txSize,uint8_t * rxData,uint16_t rxSize)338 static int32_t HalSpiSendRecv(const struct SpiDevice *spiDevice, uint8_t *txData, uint16_t txSize, uint8_t *rxData,
339 uint16_t rxSize)
340 {
341 int32_t ret;
342 int32_t status;
343 uint32_t spiId;
344 struct SpiResource *resource = NULL;
345
346 if (spiDevice == NULL || txData == NULL || txSize == 0 || rxData == NULL || rxSize == 0) {
347 HDF_LOGE("spi input para err\r\n");
348 return HDF_ERR_INVALID_PARAM;
349 }
350 spiId = spiDevice->spiId;
351 resource = &spiDevice->resource;
352 status = OsalMutexLock(&spiCtx[spiId].mutex);
353 if (HDF_SUCCESS != status) {
354 HDF_LOGE("%s OsalMutexLock error = 0x%X!\r\n", __func__, status);
355 return HDF_ERR_TIMEOUT;
356 }
357 #ifdef LOSCFG_SOC_SERIES_BES2700
358 hal_cache_sync_all(HAL_CACHE_ID_D_CACHE);
359 #endif
360 if (resource->transmode == SPI_TRANSFER_DMA) {
361 ret = spiCtx[spiId].SpiDmaRecv(txData, rxData, rxSize, spiCtx[spiId].SpiDmaIrq);
362 if (OsalSemWait(&spiCtx[spiId].sem, TIMEOUT) <= 0) {
363 HDF_LOGE("%s:SPI Read timeOut!\r\n", __func__);
364 goto OUT;
365 }
366 } else {
367 ret = spiCtx[spiId].SpiRecv(txData, rxData, rxSize);
368 }
369 if (ret != 0) {
370 HDF_LOGE("spi dma tail fail %d\r\n", ret);
371 }
372 OUT:
373 OsalMutexUnlock(&spiCtx[spiId].mutex);
374 return ret;
375 }
376
InitSpiDevice(struct SpiDevice * spiDevice)377 static int32_t InitSpiDevice(struct SpiDevice *spiDevice)
378 {
379 uint32_t spiPort;
380 int32_t ret;
381 struct HAL_SPI_CFG_T *spiDevCfg = NULL;
382 struct SpiResource *resource = NULL;
383
384 if (spiDevice == NULL) {
385 HDF_LOGE("%s: invalid parameter\r\n", __func__);
386 return HDF_ERR_INVALID_PARAM;
387 }
388
389 resource = &spiDevice->resource;
390 spiDevCfg = &spiDevice->spiDevCfg;
391 spiPort = spiDevice->spiId;
392
393 SpiIomuxInit(spiDevice);
394 ret = SpiDevCfgInit(spiDevCfg, resource);
395 if (ret != HDF_SUCCESS) {
396 HDF_LOGE("%s: SPI config init failed\r\n", __func__);
397 return HDF_FAILURE;
398 }
399 /* spi open move to hdf open api */
400 /* if cs use as gpio ,pull up at first */
401 if (spiCtx[spiPort].spiFunCS0 == HAL_IOMUX_FUNC_AS_GPIO) {
402 hal_gpio_pin_set_dir(spiCtx[spiPort].spiPinCS0, HAL_GPIO_DIR_OUT, 1);
403 }
404
405 if (&spiCtx[spiPort].sem == NULL) {
406 if (OsalSemInit(&spiCtx[spiPort].sem, 0) != HDF_SUCCESS) {
407 HDF_LOGE("spiDmaSemaphore create failed!\r\n");
408 return HDF_FAILURE;
409 }
410 }
411
412 if (&spiCtx[spiPort].mutex == NULL) {
413 if (OsalMutexInit(&spiCtx[spiPort].mutex) != HDF_SUCCESS) {
414 HDF_LOGE("spi Mutex create failed!\r\n");
415 return HDF_FAILURE;
416 }
417 }
418 return HDF_SUCCESS;
419 }
420
421 /* get spi config from hcs file */
422 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
423 #define SPI_FIND_CONFIG(node, name, resource) \
424 do { \
425 if (strcmp(HCS_PROP(node, match_attr), name) == 0) { \
426 resource->num = HCS_PROP(node, busNum); \
427 resource->speed = HCS_PROP(node, speed); \
428 resource->transmode = HCS_PROP(node, transmode); \
429 resource->spiCsSoft = HCS_PROP(node, spiCsSoft); \
430 resource->mode = HCS_PROP(node, mode); \
431 resource->dataSize = HCS_PROP(node, dataSize); \
432 resource->csNum = HCS_PROP(node, csNum); \
433 tempPin = HCS_PROP(node, spiClkPin); \
434 resource->spiClkPin = ((tempPin / DEC_NUM) * GROUP_PIN_NUM) + (tempPin % DEC_NUM); \
435 tempPin = HCS_PROP(node, spiMosiPin); \
436 resource->spiMosiPin = ((tempPin / DEC_NUM) * GROUP_PIN_NUM) + (tempPin % DEC_NUM); \
437 tempPin = HCS_PROP(node, spiMisoPin); \
438 resource->spiMisoPin = ((tempPin / DEC_NUM) * GROUP_PIN_NUM) + (tempPin % DEC_NUM); \
439 tempPin = HCS_PROP(node, spiCsPin); \
440 resource->spiCsPin = ((tempPin / DEC_NUM) * GROUP_PIN_NUM) + (tempPin % DEC_NUM); \
441 result = HDF_SUCCESS; \
442 break; \
443 } \
444 } while (0)
445
446 #define PLATFORM_SPI_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), spi_config)
GetSpiDeviceResource(struct SpiDevice * spiDevice,const char * deviceMatchAttr)447 static int32_t GetSpiDeviceResource(struct SpiDevice *spiDevice, const char *deviceMatchAttr)
448 {
449 int32_t result = HDF_FAILURE;
450 struct SpiResource *resource = NULL;
451
452 if (spiDevice == NULL || deviceMatchAttr == NULL) {
453 HDF_LOGE("device or deviceMatchAttr is NULL\r\n");
454 return HDF_ERR_INVALID_PARAM;
455 }
456 resource = &spiDevice->resource;
457 #if HCS_NODE_EXISTS(PLATFORM_SPI_CONFIG)
458 HCS_FOREACH_CHILD_VARGS(PLATFORM_SPI_CONFIG, SPI_FIND_CONFIG, deviceMatchAttr, resource);
459 #endif
460 spiDevice->spiId = resource->num;
461 if (result != HDF_SUCCESS) {
462 HDF_LOGE("resourceNode %s is NULL\r\n", deviceMatchAttr);
463 }
464
465 return result;
466 }
467 #else
GetSpiDeviceResource(struct SpiDevice * spiDevice,const struct DeviceResourceNode * resourceNode)468 static int32_t GetSpiDeviceResource(struct SpiDevice *spiDevice, const struct DeviceResourceNode *resourceNode)
469 {
470 uint32_t relPin;
471 struct SpiResource *resource = NULL;
472 struct DeviceResourceIface *dri = NULL;
473
474 if (spiDevice == NULL || resourceNode == NULL) {
475 HDF_LOGE("%s: PARAM is NULL\r\n", __func__);
476 return HDF_ERR_INVALID_PARAM;
477 }
478 resource = &spiDevice->resource;
479 if (resource == NULL) {
480 HDF_LOGE("%s: resource is NULL\r\n", __func__);
481 return HDF_ERR_INVALID_OBJECT;
482 }
483 dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); // open HDF
484 if (dri == NULL || dri->GetUint32 == NULL) {
485 HDF_LOGE("DeviceResourceIface is invalid\r\n");
486 return HDF_ERR_INVALID_PARAM;
487 }
488
489 if (dri->GetUint32(resourceNode, "busNum", &resource->num, 0) != HDF_SUCCESS) {
490 HDF_LOGE("spi config read num fail\r\n");
491 return HDF_FAILURE;
492 }
493
494 spiDevice->spiId = resource->num;
495 if (dri->GetUint32(resourceNode, "speed", &resource->speed, 0) != HDF_SUCCESS) {
496 HDF_LOGE("spi config read base fail\r\n");
497 return HDF_FAILURE;
498 }
499
500 if (dri->GetUint32(resourceNode, "transmode", &resource->transmode, 0) != HDF_SUCCESS) {
501 HDF_LOGE("spi config read transmode fail\r\n");
502 return HDF_FAILURE;
503 }
504
505 if (dri->GetUint32(resourceNode, "spiCsSoft", &resource->spiCsSoft, 0) != HDF_SUCCESS) {
506 HDF_LOGE("spi config read spiCsSoft fail\r\n");
507 return HDF_FAILURE;
508 }
509
510 if (dri->GetUint32(resourceNode, "mode", &resource->mode, 0) != HDF_SUCCESS) {
511 HDF_LOGE("spi config read mode fail\r\n");
512 return HDF_FAILURE;
513 }
514
515 if (dri->GetUint32(resourceNode, "dataSize", &resource->dataSize, 0) != HDF_SUCCESS) {
516 HDF_LOGE("spi config read dataSize fail\r\n");
517 return HDF_FAILURE;
518 }
519
520 if (dri->GetUint32(resourceNode, "csNum", &resource->csNum, 0) != HDF_SUCCESS) {
521 HDF_LOGE("spi config read csNum fail\r\n");
522 return HDF_FAILURE;
523 }
524
525 if (dri->GetUint32(resourceNode, "spiClkPin", &resource->spiClkPin, 0) != HDF_SUCCESS) {
526 HDF_LOGE("spi config read spiClkPin fail\r\n");
527 return HDF_FAILURE;
528 }
529
530 relPin = (resource->spiClkPin / DEC_NUM) * GROUP_PIN_NUM + (resource->spiClkPin % DEC_NUM);
531 resource->spiClkPin = relPin;
532
533 if (dri->GetUint32(resourceNode, "spiMosiPin", &resource->spiMosiPin, 0) != HDF_SUCCESS) {
534 HDF_LOGE("spi config read spiMosiPin fail\r\n");
535 return HDF_FAILURE;
536 }
537
538 relPin = (resource->spiMosiPin / DEC_NUM) * GROUP_PIN_NUM + (resource->spiMosiPin % DEC_NUM);
539 resource->spiMosiPin = relPin;
540 if (dri->GetUint32(resourceNode, "spiMisoPin", &resource->spiMisoPin, 0) != HDF_SUCCESS) {
541 HDF_LOGE("spi config read spiMisoPin fail\r\n");
542 return HDF_FAILURE;
543 }
544
545 relPin = ((resource->spiMisoPin / DEC_NUM) * GROUP_PIN_NUM) + (resource->spiMisoPin % DEC_NUM);
546 resource->spiMisoPin = relPin;
547
548 if (dri->GetUint32(resourceNode, "spiCsPin", &resource->spiCsPin, 0) != HDF_SUCCESS) {
549 HDF_LOGE("spi config read spiCsPin fail\r\n");
550 return HDF_FAILURE;
551 }
552
553 relPin = ((resource->spiCsPin / DEC_NUM) * GROUP_PIN_NUM) + (resource->spiCsPin % DEC_NUM);
554 resource->spiCsPin = relPin;
555
556 return HDF_SUCCESS;
557 }
558 #endif
559
AttachSpiDevice(struct SpiCntlr * spiCntlr,const struct HdfDeviceObject * device)560 static int32_t AttachSpiDevice(struct SpiCntlr *spiCntlr, const struct HdfDeviceObject *device)
561 {
562 int32_t ret;
563 struct SpiDevice *spiDevice = NULL;
564 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
565 if (spiCntlr == NULL || device == NULL) {
566 #else
567 if (spiCntlr == NULL || device == NULL || device->property == NULL) {
568 #endif
569 HDF_LOGE("%s: property is NULL\r\n", __func__);
570 return HDF_ERR_INVALID_PARAM;
571 }
572
573 spiDevice = (struct SpiDevice *)OsalMemAlloc(sizeof(struct SpiDevice));
574 if (spiDevice == NULL) {
575 HDF_LOGE("%s: OsalMemAlloc spiDevice error\r\n", __func__);
576 return HDF_ERR_MALLOC_FAIL;
577 }
578 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
579 ret = GetSpiDeviceResource(spiDevice, device->deviceMatchAttr);
580 #else
581 ret = GetSpiDeviceResource(spiDevice, device->property);
582 #endif
583 if (ret != HDF_SUCCESS) {
584 (void)OsalMemFree(spiDevice);
585 return HDF_FAILURE;
586 }
587
588 spiCntlr->priv = spiDevice;
589 spiCntlr->busNum = spiDevice->spiId;
590 return InitSpiDevice(spiDevice);
591 }
592 /* SPI Method */
593 static int32_t SpiDevGetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg);
594 static int32_t SpiDevSetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg);
595 static int32_t SpiDevTransfer(struct SpiCntlr *spiCntlr, struct SpiMsg *spiMsg, uint32_t count);
596 static int32_t SpiDevOpen(struct SpiCntlr *spiCntlr);
597 static int32_t SpiDevClose(struct SpiCntlr *spiCntlr);
598
599 struct SpiCntlrMethod g_SpiCntlrMethod = {
600 .GetCfg = SpiDevGetCfg,
601 .SetCfg = SpiDevSetCfg,
602 .Transfer = SpiDevTransfer,
603 .Open = SpiDevOpen,
604 .Close = SpiDevClose,
605 };
606
607 /* HdfDriverEntry method definitions */
608 static int32_t SpiDriverBind(struct HdfDeviceObject *device);
609 static int32_t SpiDriverInit(struct HdfDeviceObject *device);
610 static void SpiDriverRelease(struct HdfDeviceObject *device);
611
612 /* HdfDriverEntry definitions */
613 struct HdfDriverEntry g_SpiDriverEntry = {
614 .moduleVersion = 1,
615 .moduleName = "BES_SPI_MODULE_HDF",
616 .Bind = SpiDriverBind,
617 .Init = SpiDriverInit,
618 .Release = SpiDriverRelease,
619 };
620
621 HDF_INIT(g_SpiDriverEntry);
622
623 static int32_t SpiDriverBind(struct HdfDeviceObject *device)
624 {
625 struct SpiCntlr *spiCntlr = NULL;
626
627 if (device == NULL) {
628 HDF_LOGE("Sample device object is null!\r\n");
629 return HDF_ERR_INVALID_PARAM;
630 }
631 HDF_LOGI("Enter %s:\r\n", __func__);
632 spiCntlr = (struct SpiCntlr *)OsalMemAlloc(sizeof(struct SpiCntlr));
633 if (spiCntlr == NULL) {
634 HDF_LOGE("%s: host is NULL\r\n", __func__);
635 return HDF_FAILURE;
636 }
637 device->service = &spiCntlr->service;
638 spiCntlr->device = device;
639 spiCntlr->priv = NULL;
640 return HDF_SUCCESS;
641 }
642
643 static int32_t SpiDriverInit(struct HdfDeviceObject *device)
644 {
645 int32_t ret;
646 struct SpiCntlr *spiCntlr = NULL;
647
648 if (device == NULL) {
649 HDF_LOGE("%s: device is NULL\r\n", __func__);
650 return HDF_ERR_INVALID_PARAM;
651 }
652
653 HDF_LOGI("Enter %s:", __func__);
654 spiCntlr = SpiCntlrFromDevice(device);
655 if (spiCntlr == NULL) {
656 HDF_LOGE("%s: spiCntlr is NULL", __func__);
657 return HDF_DEV_ERR_NO_DEVICE;
658 }
659
660 ret = AttachSpiDevice(spiCntlr, device); // SpiCntlr add SpiDevice to priv
661 if (ret != HDF_SUCCESS) {
662 HDF_LOGE("%s: attach error\r\n", __func__);
663 return HDF_DEV_ERR_ATTACHDEV_FAIL;
664 }
665
666 spiCntlr->method = &g_SpiCntlrMethod; // register callback
667
668 return ret;
669 }
670
671 static void SpiDriverRelease(struct HdfDeviceObject *device)
672 {
673 struct SpiCntlr *spiCntlr = NULL;
674 struct SpiDevice *spiDevice = NULL;
675
676 HDF_LOGI("Enter %s\r\n", __func__);
677
678 if (device == NULL) {
679 HDF_LOGE("%s: device is NULL\r\n", __func__);
680 return;
681 }
682
683 spiCntlr = SpiCntlrFromDevice(device);
684 if (spiCntlr == NULL || spiCntlr->priv == NULL) {
685 HDF_LOGE("%s: spiCntlr is NULL\r\n", __func__);
686 return;
687 }
688
689 spiDevice = (struct SpiDevice *)spiCntlr->priv;
690 OsalMemFree(spiDevice);
691 return;
692 }
693
694 static int32_t SpiDevOpen(struct SpiCntlr *spiCntlr)
695 {
696 HDF_LOGI("Enter %s\r\n", __func__);
697 int ret;
698 uint32_t spiPort;
699 struct SpiDevice *spiDevice = NULL;
700 struct HAL_SPI_CFG_T *spiDevCfg = NULL;
701
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 spiDevice = (struct SpiDevice *)spiCntlr->priv;
707 spiPort = spiDevice->spiId;
708 spiDevCfg = &spiDevice->spiDevCfg;
709 if (spiDevCfg == NULL) {
710 HDF_LOGE("spi %u config is NULL\r\n", spiPort);
711 return HDF_DEV_ERR_NO_DEVICE;
712 }
713 ret = spiCtx[spiPort].SpiOpen(spiDevCfg);
714 if (ret != 0) {
715 HDF_LOGE("spi %u open error %d\r\n", spiPort, ret);
716 return HDF_FAILURE;
717 }
718 return HDF_SUCCESS;
719 }
720
721 static int32_t SpiDevClose(struct SpiCntlr *spiCntlr)
722 {
723 int ret;
724 uint32_t spiPort;
725 struct SpiDevice *spiDevice = NULL;
726 struct HAL_SPI_CFG_T *spiDevCfg = NULL;
727
728 if (spiCntlr == NULL || spiCntlr->priv == NULL) {
729 HDF_LOGE("%s: spiCntlr is NULL\r\n", __func__);
730 return HDF_ERR_INVALID_PARAM;
731 }
732 spiDevice = (struct SpiDevice *)spiCntlr->priv;
733 spiPort = spiDevice->spiId;
734 spiDevCfg = &spiDevice->spiDevCfg;
735 if (spiDevCfg == NULL) {
736 HDF_LOGE("spi %u config is NULL\r\n", spiPort);
737 return HDF_DEV_ERR_NO_DEVICE;
738 }
739 ret = spiCtx[spiPort].SpiClose(spiDevCfg->cs);
740 if (ret != 0) {
741 HDF_LOGE("spi %ld open error %d\r\n", spiPort, ret);
742 return HDF_FAILURE;
743 }
744 return HDF_SUCCESS;
745 }
746
747 static int32_t SpiDevGetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg)
748 {
749 struct SpiDevice *spiDevice = NULL;
750
751 if (spiCntlr == NULL || spiCfg == NULL || spiCntlr->priv == NULL) {
752 HDF_LOGE("%s: spiCntlr is NULL\r\n", __func__);
753 return HDF_ERR_INVALID_PARAM;
754 }
755 spiDevice = (struct SpiDevice *)spiCntlr->priv;
756 spiCfg->maxSpeedHz = spiDevice->resource.speed;
757 spiCfg->mode = spiDevice->resource.mode;
758 spiCfg->transferMode = spiDevice->resource.transmode;
759 spiCfg->bitsPerWord = spiDevice->resource.dataSize;
760
761 return HDF_SUCCESS;
762 }
763
764 static int32_t SpiDevSetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg)
765 {
766 struct SpiDevice *spiDevice = NULL;
767 struct HAL_SPI_CFG_T *spiDevCfg = NULL;
768
769 if (spiCntlr == NULL || spiCfg == NULL || spiCntlr->priv == NULL) {
770 HDF_LOGE("%s: spiCntlr is NULL\r\n", __func__);
771 return HDF_ERR_INVALID_PARAM;
772 }
773 spiDevice = (struct SpiDevice *)spiCntlr->priv;
774 spiDevCfg = &spiDevice->spiDevCfg;
775 if (spiDevCfg == NULL) {
776 return HDF_ERR_INVALID_OBJECT;
777 }
778 spiDevice->resource.speed = spiCfg->maxSpeedHz;
779 spiDevice->resource.mode = spiCfg->mode;
780 spiDevice->resource.transmode = spiCfg->transferMode;
781 spiDevice->resource.dataSize = spiCfg->bitsPerWord;
782 spiDevCfg->rate = spiCfg->maxSpeedHz;
783 return InitSpiDevice(spiDevice);
784 }
785
786 static int32_t SpiDevTransfer(struct SpiCntlr *spiCntlr, struct SpiMsg *spiMsg, uint32_t count)
787 {
788 uint32_t spiId;
789 struct SpiDevice *spiDevice = NULL;
790 struct SpiMsg *msg = NULL;
791 int32_t ret;
792
793 if (spiCntlr == NULL || spiCntlr->priv == NULL) {
794 HDF_LOGE("%s: spiCntlr is NULL\r\n", __func__);
795 return HDF_ERR_INVALID_PARAM;
796 }
797 spiDevice = (struct SpiDevice *)spiCntlr->priv;
798 spiId = spiDevice->spiId;
799 for (size_t i = 0; i < count; i++) {
800 msg = &spiMsg[i];
801 /* pull down cs at first */
802 if (spiDevice->resource.spiCsSoft) {
803 hal_gpio_pin_set_dir(spiCtx[spiId].spiPinCS0, HAL_GPIO_DIR_OUT, 0);
804 }
805
806 if ((msg->wbuf != NULL) && (msg->rbuf == NULL)) {
807 ret = HalSpiSend(spiDevice, msg->wbuf, msg->len, TIMEOUT);
808 }
809 if ((msg->rbuf != NULL) && (msg->wbuf == NULL)) {
810 ret = HalSpiRecv(spiDevice, msg->rbuf, msg->len, TIMEOUT);
811 }
812 if ((msg->wbuf != NULL) && (msg->rbuf != NULL)) {
813 ret = HalSpiSendRecv(spiDevice, msg->wbuf, msg->len, msg->rbuf, msg->len);
814 }
815
816 /* pull pull up cs at the end */
817 if (msg->keepCs == 0) {
818 hal_gpio_pin_set_dir(spiCtx[spiId].spiPinCS0, HAL_GPIO_DIR_OUT, 1);
819 }
820 if (ret < 0) {
821 HDF_LOGE("%s send error!\r\n", __func__);
822 }
823 DelayUs(msg->delayUs);
824 }
825 return HDF_SUCCESS;
826 }
827