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 /* Check if we can provide the requested rate */
209 if (pl022->speed > pl022->maxSpeedHz) {
210 HDF_LOGW("%s: invalid speed:%d, use max:%d instead", __func__, pl022->speed, pl022->maxSpeedHz);
211 pl022->speed = pl022->maxSpeedHz;
212 }
213 /* Min possible */
214 if (pl022->speed == 0 || pl022->speed < pl022->minSpeedHz) {
215 HDF_LOGW("%s: invalid speed:%d, use min:%d instead", __func__, pl022->speed, pl022->minSpeedHz);
216 pl022->speed = pl022->minSpeedHz;
217 }
218 /* Check if we can provide the requested bits_per_word */
219 if ((pl022->bitsPerWord < BITS_PER_WORD_MIN) || (pl022->bitsPerWord > BITS_PER_WORD_MAX)) {
220 HDF_LOGE("%s: pl022->bitsPerWord is %d not support", __func__, pl022->bitsPerWord);
221 return HDF_FAILURE;
222 }
223 /* compute spi speed, speed=clk/(cpsdvsr*(scr+1)) */
224 tmp = (pl022->clkRate) / (pl022->speed);
225 cpsdvsr = (tmp < CPSDVSR_MIN) ? CPSDVSR_MIN : (tmp <= CPSDVSR_MAX) ? (tmp & (~0x1)) : CPSDVSR_MAX;
226 scr = (tmp < CPSDVSR_MIN) ? 0 : (tmp <= CPSDVSR_MAX);
227
228 /* config SPICPSR register */
229 Pl022ConfigCPSR(pl022, cpsdvsr);
230 /* config SPICR0 register */
231 Pl022ConfigCR0(pl022, scr);
232 /* config SPICR1 register */
233 Pl022ConfigCR1(pl022);
234 /* config irq */
235 Pl022ConfigIrq(pl022);
236 /* config dma */
237 Pl022ConfigDma(pl022);
238 return 0;
239 }
240
Pl022CheckTimeout(const struct Pl022 * pl022)241 static int32_t Pl022CheckTimeout(const struct Pl022 *pl022)
242 {
243 uint32_t tmp = 0;
244 unsigned long value;
245
246 while (1) {
247 value = OSAL_READL((uintptr_t)(pl022->regBase) + REG_SPI_SR);
248 if ((value & SPI_SR_TFE) && (!(value & SPI_SR_BSY))) {
249 break;
250 }
251 if (tmp++ > MAX_WAIT) {
252 HDF_LOGE("%s: spi transfer wait timeout", __func__);
253 return HDF_ERR_TIMEOUT;
254 }
255 OsalUDelay(1);
256 }
257 return HDF_SUCCESS;
258 }
259
Pl022FlushFifo(const struct Pl022 * pl022)260 static int32_t Pl022FlushFifo(const struct Pl022 *pl022)
261 {
262 uint32_t value;
263 uint32_t tmp;
264
265 tmp = Pl022CheckTimeout(pl022);
266 if (tmp) {
267 return tmp;
268 }
269 while (1) {
270 value = OSAL_READL((uintptr_t)(pl022->regBase) + REG_SPI_SR);
271 if (!(value & SPI_SR_RNE)) {
272 break;
273 }
274 if (tmp++ > pl022->fifoSize) {
275 HDF_LOGE("%s: spi transfer check rx fifo wait timeout", __func__);
276 return HDF_ERR_TIMEOUT;
277 }
278 OSAL_READL((uintptr_t)(pl022->regBase) + REG_SPI_DR);
279 }
280 return 0;
281 }
282
283 #define PL022_ONE_BYTE 1
284 #define PL022_TWO_BYTE 2
285
Pl022ToByteWidth(uint8_t bitsPerWord)286 static inline uint8_t Pl022ToByteWidth(uint8_t bitsPerWord)
287 {
288 if (bitsPerWord <= BITS_PER_WORD_EIGHT) {
289 return PL022_ONE_BYTE;
290 } else {
291 return PL022_TWO_BYTE;
292 }
293 }
294
Pl022WriteFifo(const struct Pl022 * pl022,const uint8_t * tx,uint32_t count)295 static void Pl022WriteFifo(const struct Pl022 *pl022, const uint8_t *tx, uint32_t count)
296 {
297 unsigned long value;
298 uint8_t bytes = Pl022ToByteWidth(pl022->bitsPerWord);
299
300 for (value = 0; count >= bytes; count -= bytes) {
301 if (tx != NULL) {
302 value = (bytes == 1) ? *tx : *((uint16_t *)tx);
303 tx += bytes;
304 }
305 OSAL_WRITEL(value, (uintptr_t)(pl022->regBase) + REG_SPI_DR);
306 }
307 }
308
Pl022ReadFifo(const struct Pl022 * pl022,uint8_t * rx,uint32_t count)309 static void Pl022ReadFifo(const struct Pl022 *pl022, uint8_t *rx, uint32_t count)
310 {
311 unsigned long value;
312 uint8_t bytes = Pl022ToByteWidth(pl022->bitsPerWord);
313
314 for (value = 0; count >= bytes; count -= bytes) {
315 value = OSAL_READL((uintptr_t)(pl022->regBase) + REG_SPI_DR);
316 if (rx == NULL) {
317 continue;
318 }
319 if (bytes == 1) {
320 *rx = (uint8_t)value;
321 } else {
322 *((uint16_t *)rx) = (uint16_t)value;
323 }
324 rx += bytes;
325 }
326 }
327
Pl022TxRx(const struct Pl022 * pl022,const struct SpiMsg * msg)328 static int32_t Pl022TxRx(const struct Pl022 *pl022, const struct SpiMsg *msg)
329 {
330 int32_t ret;
331 uint32_t tmpLen;
332 uint32_t len = msg->len;
333 const uint8_t *tx = msg->wbuf;
334 uint8_t *rx = msg->rbuf;
335 uint8_t bytes = Pl022ToByteWidth(pl022->bitsPerWord);
336 uint32_t burstSize = pl022->fifoSize * bytes;
337
338 if (tx == NULL && rx == NULL) {
339 return HDF_ERR_INVALID_PARAM;
340 }
341
342 if (pl022->transferMode == SPI_INTERRUPT_TRANSFER && RX_INT_FIFO_LEVEL < pl022->fifoSize) {
343 burstSize = RX_INT_FIFO_LEVEL * bytes;
344 }
345
346 for (tmpLen = 0, len = msg->len; len > 0; len -= tmpLen) {
347 tmpLen = (len > burstSize) ? burstSize : len;
348 if (pl022->transferMode == SPI_INTERRUPT_TRANSFER && tmpLen == burstSize) {
349 OSAL_WRITEL(SPI_ALL_IRQ_ENABLE, (uintptr_t)(pl022->regBase) + REG_SPI_IMSC);
350 }
351 Pl022WriteFifo(pl022, tx, tmpLen);
352 tx = (tx == NULL) ? NULL : (tx + tmpLen);
353 if (pl022->transferMode == SPI_INTERRUPT_TRANSFER && tmpLen == burstSize) {
354 ret = OsalSemWait((struct OsalSem *)(&pl022->sem), RX_INT_WAIT_TIMEOUT);
355 } else {
356 ret = Pl022CheckTimeout(pl022);
357 }
358
359 if (ret != HDF_SUCCESS) {
360 HDF_LOGE("%s: %s timeout", __func__, (pl022->transferMode == SPI_INTERRUPT_TRANSFER) ?
361 "wait rx fifo int" : "wait tx fifo idle");
362 return ret;
363 }
364
365 Pl022ReadFifo(pl022, rx, tmpLen);
366 rx = (rx == NULL) ? NULL : (rx + tmpLen);
367 }
368 return 0;
369 }
370
Pl022SetCs(struct Pl022 * pl022,uint32_t cs,uint32_t flag)371 static int32_t Pl022SetCs(struct Pl022 *pl022, uint32_t cs, uint32_t flag)
372 {
373 if (SpiCfgCs(pl022, cs)) {
374 return HDF_FAILURE;
375 }
376 if (flag == SPI_CS_ACTIVE) {
377 Pl022Enable(pl022);
378 } else {
379 Pl022Disable(pl022);
380 }
381 return 0;
382 }
383
Pl022FindDeviceByCsNum(const struct Pl022 * pl022,uint32_t cs)384 static struct SpiDev *Pl022FindDeviceByCsNum(const struct Pl022 *pl022, uint32_t cs)
385 {
386 struct SpiDev *dev = NULL;
387 struct SpiDev *tmpDev = NULL;
388
389 if (pl022 == NULL || pl022->numCs <= cs) {
390 return NULL;
391 }
392 DLIST_FOR_EACH_ENTRY_SAFE(dev, tmpDev, &(pl022->deviceList), struct SpiDev, list) {
393 if (dev->csNum == cs) {
394 break;
395 }
396 }
397 return dev;
398 }
399
Pl022SetCfg(struct SpiCntlr * cntlr,struct SpiCfg * cfg)400 static int32_t Pl022SetCfg(struct SpiCntlr *cntlr, struct SpiCfg *cfg)
401 {
402 struct Pl022 *pl022 = NULL;
403 struct SpiDev *dev = NULL;
404
405 if (cntlr == NULL || cntlr->priv == NULL || cfg == NULL) {
406 HDF_LOGE("%s: cntlr priv or cfg is NULL", __func__);
407 return HDF_ERR_INVALID_PARAM;
408 }
409 pl022 = (struct Pl022 *)cntlr->priv;
410 dev = Pl022FindDeviceByCsNum(pl022, cntlr->curCs);
411 if (dev == NULL) {
412 return HDF_FAILURE;
413 }
414 dev->cfg.mode = cfg->mode;
415 dev->cfg.transferMode = cfg->transferMode;
416 if (cfg->bitsPerWord < BITS_PER_WORD_MIN || cfg->bitsPerWord > BITS_PER_WORD_MAX) {
417 HDF_LOGE("%s: bitsPerWord %d not support, use defaule bitsPerWord %d",
418 __func__, cfg->bitsPerWord, BITS_PER_WORD_EIGHT);
419 dev->cfg.bitsPerWord = BITS_PER_WORD_EIGHT;
420 } else {
421 dev->cfg.bitsPerWord = cfg->bitsPerWord;
422 }
423 if (cfg->maxSpeedHz != 0) {
424 dev->cfg.maxSpeedHz = cfg->maxSpeedHz;
425 }
426 return 0;
427 }
428
Pl022GetCfg(struct SpiCntlr * cntlr,struct SpiCfg * cfg)429 static int32_t Pl022GetCfg(struct SpiCntlr *cntlr, struct SpiCfg *cfg)
430 {
431 struct Pl022 *pl022 = NULL;
432 struct SpiDev *dev = NULL;
433
434 if (cntlr == NULL || cntlr->priv == NULL || cfg == NULL) {
435 HDF_LOGE("%s: cntlr priv or cfg is NULL", __func__);
436 return HDF_ERR_INVALID_PARAM;
437 }
438 pl022 = (struct Pl022 *)cntlr->priv;
439 dev = Pl022FindDeviceByCsNum(pl022, cntlr->curCs);
440 if (dev == NULL) {
441 return HDF_FAILURE;
442 }
443 *cfg = dev->cfg;
444 return HDF_SUCCESS;
445 }
446
447 struct SpiDmaEvent {
448 const struct SpiMsg *spiMsg;
449 struct DmacMsg *dmaMsg;
450 struct OsalSem sem;
451 int32_t retValue;
452 };
453
Pl022DmaCallBack(void * data,int status)454 static void Pl022DmaCallBack(void *data, int status)
455 {
456 struct SpiDmaEvent *xEvent = (struct SpiDmaEvent *)data;
457
458 if (xEvent != NULL) {
459 #ifdef SPI_HI35XX_DEBUG
460 HDF_LOGD("%s: dmamsg transfer %s!", __func__, (status == DMAC_CHN_SUCCESS) ? "Success!" : "Error!");
461 #endif
462 if (status != DMAC_CHN_SUCCESS) {
463 xEvent->retValue = HDF_FAILURE;
464 HDF_LOGE("%s: dma msg transfer failed, status = %d", __func__, status);
465 }
466 (void)OsalSemPost(&xEvent->sem);
467 }
468 }
469
GetDmaCntlr(void)470 static struct DmaCntlr *GetDmaCntlr(void)
471 {
472 static struct DmaCntlr *cntlr = NULL;
473
474 if (cntlr == NULL) {
475 cntlr = (struct DmaCntlr *)DevSvcManagerClntGetService("HDF_PLATFORM_DMAC0");
476 if (cntlr != NULL) {
477 HDF_LOGE("%s: get dmac0 success!", __func__);
478 } else {
479 HDF_LOGE("%s: get dmac0 fail!", __func__);
480 }
481 }
482 return cntlr;
483 }
484
Pl022AllocBufPhy(size_t len)485 static inline uintptr_t Pl022AllocBufPhy(size_t len)
486 {
487 void *tmpBuf = OsalMemCalloc(len);
488 return (tmpBuf == NULL) ? 0 : (uintptr_t)LOS_PaddrQuery(tmpBuf);
489 }
490
Pl022RleaseBufPhy(uintptr_t buf)491 static inline void Pl022RleaseBufPhy(uintptr_t buf)
492 {
493 void *tmpBuf = NULL;
494
495 if (buf != 0) {
496 tmpBuf = LOS_PaddrToKVaddr((paddr_t)buf);
497 OsalMemFree(tmpBuf);
498 }
499 }
500
Pl022TxRxDma(const struct Pl022 * pl022,const struct SpiMsg * msg)501 static int32_t Pl022TxRxDma(const struct Pl022 *pl022, const struct SpiMsg *msg)
502 {
503 int32_t ret;
504 struct SpiDmaEvent rxEvent;
505 struct DmacMsg dmaMsgRx;
506 struct DmacMsg dmaMsgTx;
507 uintptr_t tmpBuf = 0;
508
509 rxEvent.dmaMsg = &dmaMsgRx;
510 rxEvent.spiMsg = msg;
511 rxEvent.retValue = HDF_SUCCESS;
512
513 (void)OsalSemInit(&rxEvent.sem, 0);
514
515 if (msg->rbuf == NULL || msg->wbuf == NULL) {
516 if ((tmpBuf = Pl022AllocBufPhy(msg->len)) == 0) {
517 return HDF_ERR_MALLOC_FAIL;
518 }
519 }
520
521 dmaMsgRx.srcAddr = (uintptr_t)(pl022->phyBase + REG_SPI_DR);
522 dmaMsgRx.destAddr = (msg->rbuf == NULL) ? tmpBuf : (uintptr_t)(LOS_PaddrQuery(msg->rbuf));
523 dmaMsgRx.transLen = msg->len;
524 dmaMsgRx.transType = TRASFER_TYPE_P2M;
525 dmaMsgRx.cb = Pl022DmaCallBack;
526 dmaMsgRx.para = &rxEvent;
527 dmaMsgRx.srcWidth = dmaMsgRx.destWidth = Pl022ToByteWidth(pl022->bitsPerWord);
528
529 dmaMsgTx.srcAddr = (msg->wbuf == NULL) ? tmpBuf : (uintptr_t)(LOS_PaddrQuery(msg->wbuf));
530 dmaMsgTx.destAddr = (uintptr_t)(pl022->phyBase + REG_SPI_DR);
531 dmaMsgTx.transLen = msg->len;
532 dmaMsgTx.transType = TRASFER_TYPE_M2P;
533 dmaMsgTx.cb = NULL;
534 dmaMsgTx.para = NULL;
535 dmaMsgTx.srcWidth = dmaMsgTx.destWidth = dmaMsgRx.srcWidth;
536
537 if ((ret = DmaCntlrTransfer(GetDmaCntlr(), &dmaMsgRx)) != HDF_SUCCESS) {
538 HDF_LOGE("%s: rx dma trans fail : %d", __func__, ret);
539 goto __OUT;
540 }
541 if ((ret = DmaCntlrTransfer(GetDmaCntlr(), &dmaMsgTx)) != HDF_SUCCESS) {
542 HDF_LOGE("%s: tx dma trans fail : %d", __func__, ret);
543 goto __OUT;
544 }
545
546 #ifdef SPI_HI35XX_DEBUG
547 HDF_LOGD("%s: trying to wait dma callback...", __func__);
548 #endif
549 (void)OsalSemWait(&rxEvent.sem, HDF_WAIT_FOREVER);
550 ret = (rxEvent.retValue != HDF_SUCCESS) ? rxEvent.retValue : ret;
551
552 __OUT:
553 (void)OsalSemDestroy(&rxEvent.sem);
554 Pl022RleaseBufPhy(tmpBuf);
555 return ret;
556 }
557
Pl022TransferOneMessage(struct Pl022 * pl022,struct SpiMsg * msg)558 static int32_t Pl022TransferOneMessage(struct Pl022 *pl022, struct SpiMsg *msg)
559 {
560 int32_t ret;
561
562 pl022->speed = (msg->speed) == 0 ? DEFAULT_SPEED : msg->speed;
563
564 ret = Pl022Config(pl022);
565 if (ret != 0) {
566 return ret;
567 }
568 ret = Pl022SetCs(pl022, pl022->curCs, SPI_CS_ACTIVE);
569 if (ret != 0) {
570 return ret;
571 }
572 ret = Pl022FlushFifo(pl022);
573 if (ret != 0) {
574 return ret;
575 }
576 if (pl022->transferMode == SPI_DMA_TRANSFER) {
577 ret = Pl022TxRxDma(pl022, msg);
578 } else {
579 ret = Pl022TxRx(pl022, msg);
580 }
581 if (ret || msg->csChange) {
582 Pl022SetCs(pl022, pl022->curCs, SPI_CS_INACTIVE);
583 }
584 return ret;
585 }
586
Pl022Transfer(struct SpiCntlr * cntlr,struct SpiMsg * msg,uint32_t count)587 static int32_t Pl022Transfer(struct SpiCntlr *cntlr, struct SpiMsg *msg, uint32_t count)
588 {
589 int32_t ret = HDF_FAILURE;
590 uint32_t i;
591 struct Pl022 *pl022 = NULL;
592 struct SpiDev *dev = NULL;
593
594 if (cntlr == NULL || cntlr->priv == NULL) {
595 HDF_LOGE("%s: invalid controller", __func__);
596 return HDF_ERR_INVALID_OBJECT;
597 }
598 if (msg == NULL || (msg->rbuf == NULL && msg->wbuf == NULL) || count == 0) {
599 HDF_LOGE("%s: invalid parameter", __func__);
600 return HDF_ERR_INVALID_PARAM;
601 }
602
603 pl022 = (struct Pl022 *)cntlr->priv;
604 dev = Pl022FindDeviceByCsNum(pl022, cntlr->curCs);
605 if (dev == NULL) {
606 goto __ERR;
607 }
608 Pl022Disable(pl022);
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