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