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