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