• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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