1 /*
2 * Copyright (c) 2020-2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
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 "spi_hi35xx.h"
17 #include "device_resource_if.h"
18 #include "dmac_core.h"
19 #include "hdf_base.h"
20 #include "hdf_log.h"
21 #include "los_vm_phys.h"
22 #include "osal_io.h"
23 #include "osal_irq.h"
24 #include "osal_mem.h"
25 #include "osal_sem.h"
26 #include "osal_time.h"
27 #include "spi_core.h"
28 #include "spi_dev.h"
29 #include "platform_dumper.h"
30
31 #define HDF_LOG_TAG spi_hi35xx
32 #define SPI_DUMPER_NAME_LEN 100
33
34 struct Pl022 {
35 struct SpiCntlr *cntlr;
36 struct DListHead deviceList;
37 struct OsalSem sem;
38 volatile unsigned char *phyBase;
39 volatile unsigned char *regBase;
40 uint32_t irqNum;
41 uint32_t busNum;
42 uint32_t numCs;
43 uint32_t curCs;
44 uint32_t speed;
45 uint32_t fifoSize;
46 uint32_t clkRate;
47 uint32_t maxSpeedHz;
48 uint32_t minSpeedHz;
49 uint32_t regCrg;
50 uint32_t clkEnBit;
51 uint32_t clkRstBit;
52 uint32_t regMiscCtrl;
53 uint32_t miscCtrlCsShift;
54 uint32_t miscCtrlCs;
55 uint16_t mode;
56 uint8_t bitsPerWord;
57 uint8_t transferMode;
58 struct PlatformDumper *dumper;
59 char *dumperName;
60 };
61
SpiDumperDump(struct Pl022 * pl022)62 static void SpiDumperDump(struct Pl022 *pl022)
63 {
64 int32_t ret;
65 struct PlatformDumperData datas[] = {
66 {"REG_SPI_CR0", PLATFORM_DUMPER_REGISTERL, (void *)(pl022->regBase + REG_SPI_CR0)},
67 {"REG_SPI_CR1", PLATFORM_DUMPER_REGISTERL, (void *)(pl022->regBase + REG_SPI_CR1)},
68 {"REG_SPI_DR", PLATFORM_DUMPER_REGISTERL, (void *)(pl022->regBase + REG_SPI_DR)},
69 {"REG_SPI_SR", PLATFORM_DUMPER_REGISTERL, (void *)(pl022->regBase + REG_SPI_SR)},
70 {"REG_SPI_CPSR", PLATFORM_DUMPER_REGISTERL, (void *)(pl022->regBase + REG_SPI_CPSR)},
71 {"REG_SPI_IMSC", PLATFORM_DUMPER_REGISTERL, (void *)(pl022->regBase + REG_SPI_IMSC)},
72 {"REG_SPI_RIS", PLATFORM_DUMPER_REGISTERL, (void *)(pl022->regBase + REG_SPI_RIS)},
73 {"REG_SPI_MIS", PLATFORM_DUMPER_REGISTERL, (void *)(pl022->regBase + REG_SPI_MIS)},
74 {"REG_SPI_ICR", PLATFORM_DUMPER_REGISTERL, (void *)(pl022->regBase + REG_SPI_ICR)},
75 };
76
77 if (pl022->dumper == NULL) {
78 return;
79 }
80 ret = PlatformDumperAddDatas(pl022->dumper, datas, sizeof(datas) / sizeof(struct PlatformDumperData));
81 if (ret != HDF_SUCCESS) {
82 return;
83 }
84 (void)PlatformDumperDump(pl022->dumper);
85 (void)PlatformDumperClearDatas(pl022->dumper);
86 }
87
SpiDumperCreate(struct Pl022 * pl022)88 static int32_t SpiDumperCreate(struct Pl022 *pl022)
89 {
90 struct PlatformDumper *dumper = NULL;
91 char *spiName = NULL;
92
93 spiName = (char *)OsalMemCalloc(SPI_DUMPER_NAME_LEN);
94 if (spiName == NULL) {
95 HDF_LOGE("%s: alloc spiName fail", __func__);
96 return HDF_ERR_MALLOC_FAIL;
97 }
98
99 if (snprintf_s(spiName, SPI_DUMPER_NAME_LEN, SPI_DUMPER_NAME_LEN - 1, "%s%u",
100 "spi_dumper_", pl022->busNum) < 0) {
101 HDF_LOGE("%s: snprintf_s spiName fail!", __func__);
102 OsalMemFree(spiName);
103 return HDF_ERR_IO;
104 }
105 dumper = PlatformDumperCreate(spiName);
106 if (dumper == NULL) {
107 HDF_LOGE("%s: create dumper for %s fail!", __func__, spiName);
108 OsalMemFree(spiName);
109 return HDF_ERR_IO;
110 }
111 pl022->dumper = dumper;
112 pl022->dumperName = spiName;
113
114 return HDF_SUCCESS;
115 }
116
SpiDumperDestroy(struct Pl022 * pl022)117 static inline void SpiDumperDestroy(struct Pl022 *pl022)
118 {
119 PlatformDumperDestroy(pl022->dumper);
120 OsalMemFree(pl022->dumperName);
121 }
122
SpiCfgCs(struct Pl022 * pl022,uint32_t cs)123 static int32_t SpiCfgCs(struct Pl022 *pl022, uint32_t cs)
124 {
125 uint32_t value;
126
127 if ((cs + 1) > pl022->numCs) {
128 HDF_LOGE("%s: cs %u is big than pl022 csNum %u", __func__, cs, pl022->numCs);
129 return HDF_FAILURE;
130 }
131 if (pl022->numCs == 1) {
132 return HDF_SUCCESS;
133 }
134 value = OSAL_READL(pl022->regMiscCtrl);
135 value &= ~pl022->miscCtrlCs;
136 value |= (cs << pl022->miscCtrlCsShift);
137 OSAL_WRITEL(value, pl022->regMiscCtrl);
138 return 0;
139 }
140
SpiHwInitCfg(struct Pl022 * pl022)141 static int32_t SpiHwInitCfg(struct Pl022 *pl022)
142 {
143 uint32_t value;
144
145 value = OSAL_READL(pl022->regCrg);
146 value &= ~pl022->clkRstBit;
147 value |= pl022->clkEnBit;
148 OSAL_WRITEL(value, pl022->regCrg); /* open spi clk */
149 return 0;
150 }
151
SpiHwExitCfg(struct Pl022 * pl022)152 static int32_t SpiHwExitCfg(struct Pl022 *pl022)
153 {
154 uint32_t value;
155
156 value = OSAL_READL(pl022->regCrg);
157 value |= pl022->clkRstBit;
158 value &= ~pl022->clkEnBit;
159 OSAL_WRITEL(value, pl022->regCrg); /* close spi clk */
160 return 0;
161 }
162
Pl022Enable(const struct Pl022 * pl022)163 static void Pl022Enable(const struct Pl022 *pl022)
164 {
165 uint32_t value;
166
167 value = OSAL_READL((uintptr_t)(pl022->regBase) + REG_SPI_CR1);
168 value |= SPI_CR1_SSE;
169 OSAL_WRITEL(value, (uintptr_t)(pl022->regBase) + REG_SPI_CR1);
170 }
171
Pl022Disable(const struct Pl022 * pl022)172 static void Pl022Disable(const struct Pl022 *pl022)
173 {
174 uint32_t value;
175
176 value = OSAL_READL((uintptr_t)(pl022->regBase) + REG_SPI_CR1);
177 value &= ~SPI_CR1_SSE;
178 OSAL_WRITEL(value, (uintptr_t)(pl022->regBase) + REG_SPI_CR1);
179 }
180
Pl022ConfigCPSR(const struct Pl022 * pl022,uint32_t cpsdvsr)181 static void Pl022ConfigCPSR(const struct Pl022 *pl022, uint32_t cpsdvsr)
182 {
183 uint32_t value;
184
185 value = OSAL_READL((uintptr_t)(pl022->regBase) + REG_SPI_CPSR);
186 value &= ~SPI_CPSR_CPSDVSR;
187 value |= cpsdvsr << SPI_CPSR_CPSDVSR_SHIFT;
188 OSAL_WRITEL(value, (uintptr_t)(pl022->regBase) + REG_SPI_CPSR);
189 }
190
Pl022ConfigCR0(const struct Pl022 * pl022,uint32_t scr)191 static void Pl022ConfigCR0(const struct Pl022 *pl022, uint32_t scr)
192 {
193 uint32_t tmp;
194 uint32_t value;
195
196 value = OSAL_READL((uintptr_t)(pl022->regBase) + REG_SPI_CR0);
197 value &= ~SPI_CR0_DSS;
198 value |= (pl022->bitsPerWord - 1) << SPI_CR0_DSS_SHIFT;
199 value &= ~SPI_CR0_FRF;
200 value &= ~SPI_CR0_SPO;
201 tmp = (!!(pl022->mode & SPI_CLK_POLARITY)) ? (1 << SPI_CR0_SPO_SHIFT) : 0;
202 value |= tmp;
203 value &= ~SPI_CR0_SPH;
204 tmp = (!!(pl022->mode & SPI_CLK_PHASE)) ? (1 << SPI_CR0_SPH_SHIFT) : 0;
205 value |= tmp;
206 value &= ~SPI_CR0_SCR;
207 value |= (scr << SPI_CR0_SCR_SHIFT);
208 OSAL_WRITEL(value, (uintptr_t)(pl022->regBase) + REG_SPI_CR0);
209 }
210
Pl022ConfigCR1(const struct Pl022 * pl022)211 static void Pl022ConfigCR1(const struct Pl022 *pl022)
212 {
213 uint32_t tmp;
214 uint32_t value;
215
216 value = OSAL_READL((uintptr_t)(pl022->regBase) + REG_SPI_CR1);
217 value &= ~SPI_CR1_LBN;
218 tmp = (!!(pl022->mode & SPI_MODE_LOOP)) ? (1 << SPI_CR1_LBN_SHIFT) : 0;
219 value |= tmp;
220 value &= ~SPI_CR1_MS;
221 value &= ~SPI_CR1_BIG_END;
222 tmp = (!!(pl022->mode & SPI_MODE_LSBFE)) ? (1 << SPI_CR1_BIG_END_SHIFT) : 0;
223 value |= tmp;
224 value &= ~SPI_CR1_ALT;
225 value |= 0x1 << SPI_CR1_ALT_SHIFT;
226 OSAL_WRITEL(value, (uintptr_t)(pl022->regBase) + REG_SPI_CR1);
227 }
228
Pl022ConfigDma(struct Pl022 * pl022)229 static void Pl022ConfigDma(struct Pl022 *pl022)
230 {
231 uint32_t value;
232 if (pl022->transferMode == SPI_DMA_TRANSFER) {
233 OSAL_WRITEL((0x1 << TX_DMA_EN_SHIFT) | (0x1 << RX_DMA_EN_SHIFT),
234 (uintptr_t)(pl022->regBase) + SPI_DMA_CR);
235
236 value = OSAL_READL((uintptr_t)(pl022->regBase) + SPI_TX_FIFO_CR);
237 value &= ~(TX_DMA_BR_SIZE_MASK << TX_DMA_BR_SIZE_SHIFT);
238 OSAL_WRITEL(value, (uintptr_t)(pl022->regBase) + SPI_TX_FIFO_CR);
239
240 value = OSAL_READL((uintptr_t)(pl022->regBase) + SPI_RX_FIFO_CR);
241 value &= ~(RX_DMA_BR_SIZE_MASK << RX_DMA_BR_SIZE_SHIFT);
242 OSAL_WRITEL(value, (uintptr_t)(pl022->regBase) + SPI_RX_FIFO_CR);
243 } else {
244 OSAL_WRITEL(0, (uintptr_t)(pl022->regBase) + SPI_DMA_CR);
245 }
246 }
247
248 #define RX_INT_SIZE_VALUE 0x6
249 #define RX_INT_FIFO_LEVEL (256 - 128)
250 #define RX_INT_WAIT_TIMEOUT 1000 // ms
251
Pl022ConfigIrq(struct Pl022 * pl022)252 static void Pl022ConfigIrq(struct Pl022 *pl022)
253 {
254 unsigned long value;
255
256 if (pl022->transferMode == SPI_INTERRUPT_TRANSFER) {
257 value = OSAL_READL((uintptr_t)(pl022->regBase) + SPI_RX_FIFO_CR);
258 value &= ~(RX_INT_SIZE_MASK << RX_INT_SIZE_SHIFT);
259 value |= ((RX_INT_SIZE_VALUE & RX_INT_SIZE_MASK) << RX_INT_SIZE_SHIFT);
260 OSAL_WRITEL(value, (uintptr_t)(pl022->regBase) + SPI_RX_FIFO_CR);
261 }
262
263 OSAL_WRITEL(SPI_ALL_IRQ_DISABLE, (uintptr_t)(pl022->regBase) + REG_SPI_IMSC);
264 OSAL_WRITEL(SPI_ALL_IRQ_CLEAR, (uintptr_t)(pl022->regBase) + REG_SPI_ICR);
265 }
266
Pl022Config(struct Pl022 * pl022)267 static int32_t Pl022Config(struct Pl022 *pl022)
268 {
269 uint32_t tmp;
270 uint32_t scr;
271 uint32_t cpsdvsr;
272
273 /* Check if we can provide the requested rate */
274 if (pl022->speed > pl022->maxSpeedHz) {
275 HDF_LOGW("%s: invalid speed:%u, use max:%u instead", __func__, pl022->speed, pl022->maxSpeedHz);
276 pl022->speed = pl022->maxSpeedHz;
277 }
278 /* Min possible */
279 if (pl022->speed == 0 || pl022->speed < pl022->minSpeedHz) {
280 HDF_LOGW("%s: invalid speed:%u, use min:%u instead", __func__, pl022->speed, pl022->minSpeedHz);
281 pl022->speed = pl022->minSpeedHz;
282 }
283 /* Check if we can provide the requested bits_per_word */
284 if ((pl022->bitsPerWord < BITS_PER_WORD_MIN) || (pl022->bitsPerWord > BITS_PER_WORD_MAX)) {
285 HDF_LOGE("%s: pl022->bitsPerWord is %hhu not support", __func__, pl022->bitsPerWord);
286 return HDF_FAILURE;
287 }
288 /* compute spi speed, speed=clk/(cpsdvsr*(scr+1)) */
289 tmp = (pl022->clkRate) / (pl022->speed);
290 cpsdvsr = (tmp < CPSDVSR_MIN) ? CPSDVSR_MIN : (tmp <= CPSDVSR_MAX) ? (tmp & (~0x1)) : CPSDVSR_MAX;
291 scr = (tmp < CPSDVSR_MIN) ? 0 : (tmp <= CPSDVSR_MAX);
292
293 /* config SPICPSR register */
294 Pl022ConfigCPSR(pl022, cpsdvsr);
295 /* config SPICR0 register */
296 Pl022ConfigCR0(pl022, scr);
297 /* config SPICR1 register */
298 Pl022ConfigCR1(pl022);
299 /* config irq */
300 Pl022ConfigIrq(pl022);
301 /* config dma */
302 Pl022ConfigDma(pl022);
303 return 0;
304 }
305
Pl022CheckTimeout(const struct Pl022 * pl022)306 static int32_t Pl022CheckTimeout(const struct Pl022 *pl022)
307 {
308 uint32_t tmp = 0;
309 unsigned long value;
310
311 while (1) {
312 value = OSAL_READL((uintptr_t)(pl022->regBase) + REG_SPI_SR);
313 if ((value & SPI_SR_TFE) && (!(value & SPI_SR_BSY))) {
314 break;
315 }
316 if (tmp++ > MAX_WAIT) {
317 HDF_LOGE("%s: spi transfer wait timeout", __func__);
318 return HDF_ERR_TIMEOUT;
319 }
320 OsalUDelay(1);
321 }
322 return HDF_SUCCESS;
323 }
324
Pl022FlushFifo(const struct Pl022 * pl022)325 static int32_t Pl022FlushFifo(const struct Pl022 *pl022)
326 {
327 uint32_t value;
328 uint32_t tmp;
329
330 tmp = Pl022CheckTimeout(pl022);
331 if (tmp) {
332 return tmp;
333 }
334 while (1) {
335 value = OSAL_READL((uintptr_t)(pl022->regBase) + REG_SPI_SR);
336 if (!(value & SPI_SR_RNE)) {
337 break;
338 }
339 if (tmp++ > pl022->fifoSize) {
340 HDF_LOGE("%s: spi transfer check rx fifo wait timeout", __func__);
341 return HDF_ERR_TIMEOUT;
342 }
343 OSAL_READL((uintptr_t)(pl022->regBase) + REG_SPI_DR);
344 }
345 return 0;
346 }
347
348 #define PL022_ONE_BYTE 1
349 #define PL022_TWO_BYTE 2
350
Pl022ToByteWidth(uint8_t bitsPerWord)351 static inline uint8_t Pl022ToByteWidth(uint8_t bitsPerWord)
352 {
353 if (bitsPerWord <= BITS_PER_WORD_EIGHT) {
354 return PL022_ONE_BYTE;
355 } else {
356 return PL022_TWO_BYTE;
357 }
358 }
359
Pl022WriteFifo(const struct Pl022 * pl022,const uint8_t * tx,uint32_t count)360 static void Pl022WriteFifo(const struct Pl022 *pl022, const uint8_t *tx, uint32_t count)
361 {
362 unsigned long value;
363 uint8_t bytes = Pl022ToByteWidth(pl022->bitsPerWord);
364
365 for (value = 0; count >= bytes; count -= bytes) {
366 if (tx != NULL) {
367 value = (bytes == 1) ? *tx : *((uint16_t *)tx);
368 tx += bytes;
369 }
370 OSAL_WRITEL(value, (uintptr_t)(pl022->regBase) + REG_SPI_DR);
371 }
372 }
373
Pl022ReadFifo(const struct Pl022 * pl022,uint8_t * rx,uint32_t count)374 static void Pl022ReadFifo(const struct Pl022 *pl022, uint8_t *rx, uint32_t count)
375 {
376 unsigned long value;
377 uint8_t bytes = Pl022ToByteWidth(pl022->bitsPerWord);
378
379 for (value = 0; count >= bytes; count -= bytes) {
380 value = OSAL_READL((uintptr_t)(pl022->regBase) + REG_SPI_DR);
381 if (rx == NULL) {
382 continue;
383 }
384 if (bytes == 1) {
385 *rx = (uint8_t)value;
386 } else {
387 *((uint16_t *)rx) = (uint16_t)value;
388 }
389 rx += bytes;
390 }
391 }
392
Pl022TxRx(const struct Pl022 * pl022,const struct SpiMsg * msg)393 static int32_t Pl022TxRx(const struct Pl022 *pl022, const struct SpiMsg *msg)
394 {
395 int32_t ret;
396 uint32_t tmpLen;
397 uint32_t len = msg->len;
398 const uint8_t *tx = msg->wbuf;
399 uint8_t *rx = msg->rbuf;
400 uint8_t bytes = Pl022ToByteWidth(pl022->bitsPerWord);
401 uint32_t burstSize = pl022->fifoSize * bytes;
402
403 if (tx == NULL && rx == NULL) {
404 return HDF_ERR_INVALID_PARAM;
405 }
406
407 if (pl022->transferMode == SPI_INTERRUPT_TRANSFER && RX_INT_FIFO_LEVEL < pl022->fifoSize) {
408 burstSize = RX_INT_FIFO_LEVEL * bytes;
409 }
410
411 for (tmpLen = 0, len = msg->len; len > 0; len -= tmpLen) {
412 tmpLen = (len > burstSize) ? burstSize : len;
413 if (pl022->transferMode == SPI_INTERRUPT_TRANSFER && tmpLen == burstSize) {
414 OSAL_WRITEL(SPI_ALL_IRQ_ENABLE, (uintptr_t)(pl022->regBase) + REG_SPI_IMSC);
415 }
416 Pl022WriteFifo(pl022, tx, tmpLen);
417 tx = (tx == NULL) ? NULL : (tx + tmpLen);
418 if (pl022->transferMode == SPI_INTERRUPT_TRANSFER && tmpLen == burstSize) {
419 ret = OsalSemWait((struct OsalSem *)(&pl022->sem), RX_INT_WAIT_TIMEOUT);
420 } else {
421 ret = Pl022CheckTimeout(pl022);
422 }
423
424 if (ret != HDF_SUCCESS) {
425 HDF_LOGE("%s: %s timeout", __func__, (pl022->transferMode == SPI_INTERRUPT_TRANSFER) ?
426 "wait rx fifo int" : "wait tx fifo idle");
427 return ret;
428 }
429
430 Pl022ReadFifo(pl022, rx, tmpLen);
431 rx = (rx == NULL) ? NULL : (rx + tmpLen);
432 }
433 return 0;
434 }
435
Pl022SetCs(struct Pl022 * pl022,uint32_t cs,uint32_t flag)436 static int32_t Pl022SetCs(struct Pl022 *pl022, uint32_t cs, uint32_t flag)
437 {
438 if (SpiCfgCs(pl022, cs)) {
439 return HDF_FAILURE;
440 }
441 if (flag == SPI_CS_ACTIVE) {
442 Pl022Enable(pl022);
443 } else {
444 Pl022Disable(pl022);
445 }
446 return 0;
447 }
448
Pl022FindDeviceByCsNum(const struct Pl022 * pl022,uint32_t cs)449 static struct SpiDev *Pl022FindDeviceByCsNum(const struct Pl022 *pl022, uint32_t cs)
450 {
451 struct SpiDev *dev = NULL;
452 struct SpiDev *tmpDev = NULL;
453
454 if (pl022 == NULL || pl022->numCs <= cs) {
455 return NULL;
456 }
457 DLIST_FOR_EACH_ENTRY_SAFE(dev, tmpDev, &(pl022->deviceList), struct SpiDev, list) {
458 if (dev->csNum == cs) {
459 break;
460 }
461 }
462 return dev;
463 }
464
Pl022SetCfg(struct SpiCntlr * cntlr,struct SpiCfg * cfg)465 static int32_t Pl022SetCfg(struct SpiCntlr *cntlr, struct SpiCfg *cfg)
466 {
467 struct Pl022 *pl022 = NULL;
468 struct SpiDev *dev = NULL;
469
470 if (cntlr == NULL || cntlr->priv == NULL || cfg == NULL) {
471 HDF_LOGE("%s: cntlr priv or cfg is NULL", __func__);
472 return HDF_ERR_INVALID_PARAM;
473 }
474 pl022 = (struct Pl022 *)cntlr->priv;
475 dev = Pl022FindDeviceByCsNum(pl022, cntlr->curCs);
476 if (dev == NULL) {
477 SpiDumperDump(pl022);
478 return HDF_FAILURE;
479 }
480 dev->cfg.mode = cfg->mode;
481 dev->cfg.transferMode = cfg->transferMode;
482 if (cfg->bitsPerWord < BITS_PER_WORD_MIN || cfg->bitsPerWord > BITS_PER_WORD_MAX) {
483 HDF_LOGE("%s: bitsPerWord %hhu not support, use defaule bitsPerWord %d",
484 __func__, cfg->bitsPerWord, BITS_PER_WORD_EIGHT);
485 dev->cfg.bitsPerWord = BITS_PER_WORD_EIGHT;
486 } else {
487 dev->cfg.bitsPerWord = cfg->bitsPerWord;
488 }
489 if (cfg->maxSpeedHz != 0) {
490 dev->cfg.maxSpeedHz = cfg->maxSpeedHz;
491 }
492 return 0;
493 }
494
Pl022GetCfg(struct SpiCntlr * cntlr,struct SpiCfg * cfg)495 static int32_t Pl022GetCfg(struct SpiCntlr *cntlr, struct SpiCfg *cfg)
496 {
497 struct Pl022 *pl022 = NULL;
498 struct SpiDev *dev = NULL;
499
500 if (cntlr == NULL || cntlr->priv == NULL || cfg == NULL) {
501 HDF_LOGE("%s: cntlr priv or cfg is NULL", __func__);
502 return HDF_ERR_INVALID_PARAM;
503 }
504 pl022 = (struct Pl022 *)cntlr->priv;
505 dev = Pl022FindDeviceByCsNum(pl022, cntlr->curCs);
506 if (dev == NULL) {
507 SpiDumperDump(pl022);
508 return HDF_FAILURE;
509 }
510 *cfg = dev->cfg;
511 return HDF_SUCCESS;
512 }
513
514 struct SpiDmaEvent {
515 const struct SpiMsg *spiMsg;
516 struct DmacMsg *dmaMsg;
517 struct OsalSem sem;
518 int32_t retValue;
519 };
520
Pl022DmaCallBack(void * data,int status)521 static void Pl022DmaCallBack(void *data, int status)
522 {
523 struct SpiDmaEvent *xEvent = (struct SpiDmaEvent *)data;
524
525 if (xEvent != NULL) {
526 #ifdef SPI_HI35XX_DEBUG
527 HDF_LOGD("%s: dmamsg transfer %s!", __func__, (status == DMAC_CHN_SUCCESS) ? "Success!" : "Error!");
528 #endif
529 if (status != DMAC_CHN_SUCCESS) {
530 xEvent->retValue = HDF_FAILURE;
531 HDF_LOGE("%s: dma msg transfer failed, status = %d", __func__, status);
532 }
533 (void)OsalSemPost(&xEvent->sem);
534 }
535 }
536
GetDmaCntlr(void)537 static struct DmaCntlr *GetDmaCntlr(void)
538 {
539 static struct DmaCntlr *cntlr = NULL;
540
541 if (cntlr == NULL) {
542 cntlr = (struct DmaCntlr *)DevSvcManagerClntGetService("HDF_PLATFORM_DMAC0");
543 if (cntlr != NULL) {
544 HDF_LOGE("%s: get dmac0 success!", __func__);
545 } else {
546 HDF_LOGE("%s: get dmac0 fail!", __func__);
547 }
548 }
549 return cntlr;
550 }
551
Pl022AllocBufPhy(size_t len)552 static inline uintptr_t Pl022AllocBufPhy(size_t len)
553 {
554 void *tmpBuf = OsalMemCalloc(len);
555 return (tmpBuf == NULL) ? 0 : (uintptr_t)LOS_PaddrQuery(tmpBuf);
556 }
557
Pl022RleaseBufPhy(uintptr_t buf)558 static inline void Pl022RleaseBufPhy(uintptr_t buf)
559 {
560 void *tmpBuf = NULL;
561
562 if (buf != 0) {
563 tmpBuf = LOS_PaddrToKVaddr((paddr_t)buf);
564 OsalMemFree(tmpBuf);
565 }
566 }
567
Pl022TxRxDma(const struct Pl022 * pl022,const struct SpiMsg * msg)568 static int32_t Pl022TxRxDma(const struct Pl022 *pl022, const struct SpiMsg *msg)
569 {
570 int32_t ret;
571 struct SpiDmaEvent rxEvent;
572 struct DmacMsg dmaMsgRx;
573 struct DmacMsg dmaMsgTx;
574 uintptr_t tmpBuf = 0;
575
576 rxEvent.dmaMsg = &dmaMsgRx;
577 rxEvent.spiMsg = msg;
578 rxEvent.retValue = HDF_SUCCESS;
579
580 (void)OsalSemInit(&rxEvent.sem, 0);
581
582 if (msg->rbuf == NULL || msg->wbuf == NULL) {
583 if ((tmpBuf = Pl022AllocBufPhy(msg->len)) == 0) {
584 return HDF_ERR_MALLOC_FAIL;
585 }
586 }
587
588 dmaMsgRx.srcAddr = (uintptr_t)(pl022->phyBase + REG_SPI_DR);
589 dmaMsgRx.destAddr = (msg->rbuf == NULL) ? tmpBuf : (uintptr_t)(LOS_PaddrQuery(msg->rbuf));
590 dmaMsgRx.transLen = msg->len;
591 dmaMsgRx.transType = TRASFER_TYPE_P2M;
592 dmaMsgRx.cb = Pl022DmaCallBack;
593 dmaMsgRx.para = &rxEvent;
594 dmaMsgRx.srcWidth = dmaMsgRx.destWidth = Pl022ToByteWidth(pl022->bitsPerWord);
595
596 dmaMsgTx.srcAddr = (msg->wbuf == NULL) ? tmpBuf : (uintptr_t)(LOS_PaddrQuery(msg->wbuf));
597 dmaMsgTx.destAddr = (uintptr_t)(pl022->phyBase + REG_SPI_DR);
598 dmaMsgTx.transLen = msg->len;
599 dmaMsgTx.transType = TRASFER_TYPE_M2P;
600 dmaMsgTx.cb = NULL;
601 dmaMsgTx.para = NULL;
602 dmaMsgTx.srcWidth = dmaMsgTx.destWidth = dmaMsgRx.srcWidth;
603
604 if ((ret = DmaCntlrTransfer(GetDmaCntlr(), &dmaMsgRx)) != HDF_SUCCESS) {
605 HDF_LOGE("%s: rx dma trans fail : %d", __func__, ret);
606 goto __OUT;
607 }
608 if ((ret = DmaCntlrTransfer(GetDmaCntlr(), &dmaMsgTx)) != HDF_SUCCESS) {
609 HDF_LOGE("%s: tx dma trans fail : %d", __func__, ret);
610 goto __OUT;
611 }
612
613 #ifdef SPI_HI35XX_DEBUG
614 HDF_LOGD("%s: trying to wait dma callback...", __func__);
615 #endif
616 (void)OsalSemWait(&rxEvent.sem, HDF_WAIT_FOREVER);
617 ret = (rxEvent.retValue != HDF_SUCCESS) ? rxEvent.retValue : ret;
618
619 __OUT:
620 (void)OsalSemDestroy(&rxEvent.sem);
621 Pl022RleaseBufPhy(tmpBuf);
622 return ret;
623 }
624
Pl022TransferOneMessage(struct Pl022 * pl022,struct SpiMsg * msg)625 static int32_t Pl022TransferOneMessage(struct Pl022 *pl022, struct SpiMsg *msg)
626 {
627 int32_t ret;
628
629 pl022->speed = (msg->speed) == 0 ? DEFAULT_SPEED : msg->speed;
630
631 ret = Pl022Config(pl022);
632 if (ret != 0) {
633 return ret;
634 }
635 ret = Pl022SetCs(pl022, pl022->curCs, SPI_CS_ACTIVE);
636 if (ret != 0) {
637 return ret;
638 }
639 ret = Pl022FlushFifo(pl022);
640 if (ret != 0) {
641 return ret;
642 }
643 if (pl022->transferMode == SPI_DMA_TRANSFER) {
644 ret = Pl022TxRxDma(pl022, msg);
645 } else {
646 ret = Pl022TxRx(pl022, msg);
647 }
648 if (ret != HDF_SUCCESS || msg->keepCs == 0) {
649 Pl022SetCs(pl022, pl022->curCs, SPI_CS_INACTIVE);
650 }
651 return ret;
652 }
653
Pl022Transfer(struct SpiCntlr * cntlr,struct SpiMsg * msg,uint32_t count)654 static int32_t Pl022Transfer(struct SpiCntlr *cntlr, struct SpiMsg *msg, uint32_t count)
655 {
656 int32_t ret;
657 uint32_t i;
658 struct Pl022 *pl022 = NULL;
659 struct SpiDev *dev = NULL;
660
661 if (cntlr == NULL || cntlr->priv == NULL) {
662 HDF_LOGE("%s: invalid controller", __func__);
663 return HDF_ERR_INVALID_OBJECT;
664 }
665 if (msg == NULL || (msg->rbuf == NULL && msg->wbuf == NULL) || count == 0) {
666 HDF_LOGE("%s: invalid parameter", __func__);
667 return HDF_ERR_INVALID_PARAM;
668 }
669
670 pl022 = (struct Pl022 *)cntlr->priv;
671 dev = Pl022FindDeviceByCsNum(pl022, cntlr->curCs);
672 if (dev == NULL) {
673 HDF_LOGE("%s: invalid dev", __func__);
674 return HDF_ERR_INVALID_OBJECT;
675 }
676 Pl022Disable(pl022);
677 pl022->mode = dev->cfg.mode;
678 pl022->transferMode = dev->cfg.transferMode;
679 pl022->bitsPerWord = dev->cfg.bitsPerWord;
680 pl022->maxSpeedHz = dev->cfg.maxSpeedHz;
681 pl022->curCs = dev->csNum;
682 for (i = 0; i < count; i++) {
683 ret = Pl022TransferOneMessage(pl022, &(msg[i]));
684 if (ret != 0) {
685 HDF_LOGE("%s: transfer error", __func__);
686 SpiDumperDump(pl022);
687 return ret;
688 }
689 }
690
691 return ret;
692 }
693
Pl022Open(struct SpiCntlr * cntlr)694 int32_t Pl022Open(struct SpiCntlr *cntlr)
695 {
696 (void)cntlr;
697 return HDF_SUCCESS;
698 }
699
Pl022Close(struct SpiCntlr * cntlr)700 int32_t Pl022Close(struct SpiCntlr *cntlr)
701 {
702 (void)cntlr;
703 return HDF_SUCCESS;
704 }
705
Pl022Probe(struct Pl022 * pl022)706 static int32_t Pl022Probe(struct Pl022 *pl022)
707 {
708 int32_t ret;
709
710 ret = SpiHwInitCfg(pl022);
711 if (ret != 0) {
712 HDF_LOGE("%s: SpiHwInitCfg error", __func__);
713 return HDF_FAILURE;
714 }
715 ret = Pl022Config(pl022);
716 if (ret != 0) {
717 HDF_LOGE("%s: Pl022Config error", __func__);
718 }
719 return ret;
720 }
721
722 struct SpiCntlrMethod g_method = {
723 .Transfer = Pl022Transfer,
724 .SetCfg = Pl022SetCfg,
725 .GetCfg = Pl022GetCfg,
726 .Open = Pl022Open,
727 .Close = Pl022Close,
728 };
729
Pl022CreatAndInitDevice(struct Pl022 * pl022)730 static int32_t Pl022CreatAndInitDevice(struct Pl022 *pl022)
731 {
732 uint32_t i;
733 struct SpiDev *device = NULL;
734
735 for (i = 0; i < pl022->numCs; i++) {
736 device = (struct SpiDev *)OsalMemCalloc(sizeof(*device));
737 if (device == NULL) {
738 HDF_LOGE("%s: OsalMemCalloc error", __func__);
739 return HDF_FAILURE;
740 }
741 device->cntlr = pl022->cntlr;
742 device->csNum = i;
743 device->cfg.bitsPerWord = pl022->bitsPerWord;
744 device->cfg.transferMode = pl022->transferMode;
745 device->cfg.maxSpeedHz = pl022->maxSpeedHz;
746 device->cfg.mode = pl022->mode;
747 DListHeadInit(&device->list);
748 DListInsertTail(&device->list, &pl022->deviceList);
749 SpiAddDev(device);
750 }
751 return 0;
752 }
753
Pl022Release(struct Pl022 * pl022)754 static void Pl022Release(struct Pl022 *pl022)
755 {
756 struct SpiDev *dev = NULL;
757 struct SpiDev *tmpDev = NULL;
758
759 DLIST_FOR_EACH_ENTRY_SAFE(dev, tmpDev, &(pl022->deviceList), struct SpiDev, list) {
760 SpiRemoveDev(dev);
761 DListRemove(&(dev->list));
762 OsalMemFree(dev);
763 }
764 if (pl022->irqNum != 0) {
765 (void)OsalUnregisterIrq(pl022->irqNum, pl022);
766 }
767 OsalMemFree(pl022);
768 }
769
SpiGetBaseCfgFromHcs(struct DeviceResourceIface * iface,struct Pl022 * pl022,const struct DeviceResourceNode * node)770 static int32_t SpiGetBaseCfgFromHcs(struct DeviceResourceIface *iface,
771 struct Pl022 *pl022, const struct DeviceResourceNode *node)
772 {
773 if (iface->GetUint32(node, "busNum", &pl022->busNum, 0) != HDF_SUCCESS) {
774 HDF_LOGE("%s: read busNum fail", __func__);
775 return HDF_FAILURE;
776 }
777 if (iface->GetUint32(node, "numCs", &pl022->numCs, 0) != HDF_SUCCESS) {
778 HDF_LOGE("%s: read numCs fail", __func__);
779 return HDF_FAILURE;
780 }
781 if (iface->GetUint32(node, "speed", &pl022->speed, 0) != HDF_SUCCESS) {
782 HDF_LOGE("%s: read speed fail", __func__);
783 return HDF_FAILURE;
784 }
785 if (iface->GetUint32(node, "fifoSize", &pl022->fifoSize, 0) != HDF_SUCCESS) {
786 HDF_LOGE("%s: read fifoSize fail", __func__);
787 return HDF_FAILURE;
788 }
789 if (iface->GetUint32(node, "clkRate", &pl022->clkRate, 0) != HDF_SUCCESS) {
790 HDF_LOGE("%s: read clkRate fail", __func__);
791 return HDF_FAILURE;
792 }
793 if (iface->GetUint16(node, "mode", &pl022->mode, 0) != HDF_SUCCESS) {
794 HDF_LOGE("%s: read mode fail", __func__);
795 return HDF_FAILURE;
796 }
797 if (iface->GetUint8(node, "bitsPerWord", &pl022->bitsPerWord, 0) != HDF_SUCCESS) {
798 HDF_LOGE("%s: read bitsPerWord fail", __func__);
799 return HDF_FAILURE;
800 }
801 if (iface->GetUint8(node, "transferMode", &pl022->transferMode, 0) != HDF_SUCCESS) {
802 HDF_LOGE("%s: read comMode fail", __func__);
803 return HDF_FAILURE;
804 }
805 return 0;
806 }
807
SpiGetCfgFromHcs(struct Pl022 * pl022,const struct DeviceResourceNode * node)808 static int32_t SpiGetCfgFromHcs(struct Pl022 *pl022, const struct DeviceResourceNode *node)
809 {
810 uint32_t tmp;
811 struct DeviceResourceIface *iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
812
813 if (iface == NULL || iface->GetUint8 == NULL || iface->GetUint16 == NULL || iface->GetUint32 == NULL) {
814 HDF_LOGE("%s: iface is invalid", __func__);
815 return HDF_FAILURE;
816 }
817 if (SpiGetBaseCfgFromHcs(iface, pl022, node) != HDF_SUCCESS) {
818 HDF_LOGE("%s: SpiGetBaseCfgFromHcs error", __func__);
819 return HDF_FAILURE;
820 }
821 if (iface->GetUint32(node, "regBase", &tmp, 0) != HDF_SUCCESS) {
822 HDF_LOGE("%s: read regBase fail", __func__);
823 return HDF_FAILURE;
824 }
825 pl022->phyBase = (void *)(uintptr_t)(tmp);
826 pl022->regBase = HDF_IO_DEVICE_ADDR(pl022->phyBase);
827
828 if (iface->GetUint32(node, "irqNum", &pl022->irqNum, 0) != HDF_SUCCESS) {
829 HDF_LOGE("%s: read irqNum fail", __func__);
830 return HDF_FAILURE;
831 }
832 if (iface->GetUint32(node, "REG_CRG_SPI", &pl022->regCrg, 0) != HDF_SUCCESS) {
833 HDF_LOGE("%s: read regCrg fail", __func__);
834 return HDF_FAILURE;
835 }
836 pl022->regCrg = HDF_IO_DEVICE_ADDR(pl022->regCrg);
837 if (iface->GetUint32(node, "CRG_SPI_CKEN", &pl022->clkEnBit, 0) != HDF_SUCCESS) {
838 HDF_LOGE("%s: read clkEnBit fail", __func__);
839 return HDF_FAILURE;
840 }
841 if (iface->GetUint32(node, "CRG_SPI_RST", &pl022->clkRstBit, 0) != HDF_SUCCESS) {
842 HDF_LOGE("%s: read clkRstBit fail", __func__);
843 return HDF_FAILURE;
844 }
845 if (iface->GetUint32(node, "REG_MISC_CTRL_SPI", &pl022->regMiscCtrl, 0) != HDF_SUCCESS) {
846 HDF_LOGE("%s: read regMiscCtrl fail", __func__);
847 return HDF_FAILURE;
848 }
849 pl022->regMiscCtrl = HDF_IO_DEVICE_ADDR(pl022->regMiscCtrl);
850 if (iface->GetUint32(node, "MISC_CTRL_SPI_CS", &pl022->miscCtrlCs, 0) != HDF_SUCCESS) {
851 HDF_LOGE("%s: read miscCtrlCs fail", __func__);
852 return HDF_FAILURE;
853 }
854 if (iface->GetUint32(node, "MISC_CTRL_SPI_CS_SHIFT", &pl022->miscCtrlCsShift, 0) != HDF_SUCCESS) {
855 HDF_LOGE("%s: read miscCtrlCsShift fail", __func__);
856 return HDF_FAILURE;
857 }
858 return 0;
859 }
860
Pl022IrqHandleNoShare(uint32_t irq,void * data)861 static uint32_t Pl022IrqHandleNoShare(uint32_t irq, void *data)
862 {
863 unsigned long value;
864 struct Pl022 *pl022 = (struct Pl022 *)data;
865
866 (void)irq;
867 if (pl022 == NULL) {
868 HDF_LOGE("%s: data is NULL!", __func__);
869 return HDF_ERR_INVALID_PARAM;
870 }
871 // check SPI_RX_INTR
872 value = OSAL_READL((uintptr_t)(pl022->regBase) + REG_SPI_MIS);
873 if ((value & SPI_RX_INTR_MASK) != 0) {
874 OSAL_WRITEL(SPI_ALL_IRQ_DISABLE, (uintptr_t)(pl022->regBase) + REG_SPI_IMSC);
875 OSAL_WRITEL(SPI_ALL_IRQ_CLEAR, (uintptr_t)(pl022->regBase) + REG_SPI_ICR);
876 (void)OsalSemPost(&pl022->sem);
877 }
878
879 return HDF_SUCCESS;
880 }
881
Pl022Init(struct SpiCntlr * cntlr,const struct HdfDeviceObject * device)882 static int32_t Pl022Init(struct SpiCntlr *cntlr, const struct HdfDeviceObject *device)
883 {
884 int32_t ret;
885 struct Pl022 *pl022 = NULL;
886
887 if (device->property == NULL) {
888 HDF_LOGE("%s: property is NULL", __func__);
889 return HDF_ERR_INVALID_PARAM;
890 }
891
892 pl022 = (struct Pl022 *)OsalMemCalloc(sizeof(*pl022));
893 if (pl022 == NULL) {
894 HDF_LOGE("%s: OsalMemCalloc error", __func__);
895 return HDF_FAILURE;
896 }
897 ret = SpiGetCfgFromHcs(pl022, device->property);
898 if (ret != HDF_SUCCESS) {
899 HDF_LOGE("%s: SpiGetRegCfgFromHcs error", __func__);
900 OsalMemFree(pl022);
901 return HDF_FAILURE;
902 }
903 pl022->maxSpeedHz = (pl022->clkRate) / ((SCR_MIN + 1) * CPSDVSR_MIN);
904 pl022->minSpeedHz = (pl022->clkRate) / ((SCR_MAX + 1) * CPSDVSR_MAX);
905 DListHeadInit(&pl022->deviceList);
906 pl022->cntlr = cntlr;
907 cntlr->priv = pl022;
908 cntlr->busNum = pl022->busNum;
909 cntlr->method = &g_method;
910 ret = OsalSemInit(&pl022->sem, 0);
911 if (ret != HDF_SUCCESS) {
912 OsalMemFree(pl022);
913 return ret;
914 }
915
916 if (pl022->irqNum != 0) {
917 OSAL_WRITEL(SPI_ALL_IRQ_DISABLE, (uintptr_t)(pl022->regBase) + REG_SPI_IMSC);
918 ret = OsalRegisterIrq(pl022->irqNum, 0, Pl022IrqHandleNoShare, "SPI_HI35XX", pl022);
919 if (ret != HDF_SUCCESS) {
920 OsalMemFree(pl022);
921 (void)OsalSemDestroy(&pl022->sem);
922 return ret;
923 }
924 }
925
926 ret = Pl022CreatAndInitDevice(pl022);
927 if (ret != 0) {
928 Pl022Release(pl022);
929 return ret;
930 }
931 ret = SpiDumperCreate(pl022);
932 if (ret != HDF_SUCCESS) {
933 HDF_LOGE("%s: create dumper failed:%d", __func__, ret);
934 return ret;
935 }
936 SpiDumperDump(pl022);
937 return 0;
938 }
939
Pl022Remove(struct Pl022 * pl022)940 static void Pl022Remove(struct Pl022 *pl022)
941 {
942 if (SpiHwExitCfg(pl022) != 0) {
943 HDF_LOGE("%s: SpiHwExitCfg error", __func__);
944 }
945 Pl022Release(pl022);
946 }
947
HdfSpiDeviceBind(struct HdfDeviceObject * device)948 static int32_t HdfSpiDeviceBind(struct HdfDeviceObject *device)
949 {
950 HDF_LOGI("%s: entry", __func__);
951 if (device == NULL) {
952 return HDF_ERR_INVALID_OBJECT;
953 }
954 return (SpiCntlrCreate(device) == NULL) ? HDF_FAILURE : HDF_SUCCESS;
955 }
956
HdfSpiDeviceInit(struct HdfDeviceObject * device)957 static int32_t HdfSpiDeviceInit(struct HdfDeviceObject *device)
958 {
959 int32_t ret;
960 struct SpiCntlr *cntlr = NULL;
961
962 if (device == NULL) {
963 HDF_LOGE("%s: ptr is null", __func__);
964 return HDF_ERR_INVALID_OBJECT;
965 }
966 cntlr = SpiCntlrFromDevice(device);
967 if (cntlr == NULL) {
968 HDF_LOGE("%s: cntlr is null", __func__);
969 return HDF_FAILURE;
970 }
971
972 ret = Pl022Init(cntlr, device);
973 if (ret != 0) {
974 HDF_LOGE("%s: error init", __func__);
975 return HDF_FAILURE;
976 }
977 ret = Pl022Probe(cntlr->priv);
978 if (ret != 0) {
979 HDF_LOGE("%s: error probe", __func__);
980 }
981 HDF_LOGI("%s: spi device init success.", __func__);
982 return ret;
983 }
984
HdfSpiDeviceRelease(struct HdfDeviceObject * device)985 static void HdfSpiDeviceRelease(struct HdfDeviceObject *device)
986 {
987 struct SpiCntlr *cntlr = NULL;
988
989 HDF_LOGI("%s: entry", __func__);
990 if (device == NULL) {
991 HDF_LOGE("%s: device is null", __func__);
992 return;
993 }
994 cntlr = SpiCntlrFromDevice(device);
995 if (cntlr == NULL) {
996 HDF_LOGE("%s: cntlr is null", __func__);
997 return;
998 }
999 if (cntlr->priv != NULL) {
1000 SpiDumperDestroy((struct Pl022 *)cntlr->priv);
1001 Pl022Remove((struct Pl022 *)cntlr->priv);
1002 }
1003 SpiCntlrDestroy(cntlr);
1004 }
1005
1006 struct HdfDriverEntry g_hdfSpiDevice = {
1007 .moduleVersion = 1,
1008 .moduleName = "HDF_PLATFORM_SPI",
1009 .Bind = HdfSpiDeviceBind,
1010 .Init = HdfSpiDeviceInit,
1011 .Release = HdfSpiDeviceRelease,
1012 };
1013
1014 HDF_INIT(g_hdfSpiDevice);
1015