• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
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 "stm32mp1_spi.h"
17 #include "device_resource_if.h"
18 #include "hdf_device_desc.h"
19 #include "hdf_log.h"
20 #include "osal_io.h"
21 #include "osal_mem.h"
22 #include "osal_irq.h"
23 #include "osal_time.h"
24 #include "stm32mp1xx.h"
25 #include "stm32mp1xx_hal_conf.h"
26 #include "spi_dev.h"
27 
28 #define HDF_LOG_TAG stm32mp1_spi
29 
Mp1xxSpiSetPinMux(struct Mp1xxSpiCntlr * stm32mp1)30 static void Mp1xxSpiSetPinMux(struct Mp1xxSpiCntlr *stm32mp1)
31 {
32     uint32_t value;
33     uint32_t i;
34     volatile unsigned char *gpioZBase = NULL;
35     volatile unsigned char *gpioBase = NULL;
36     volatile unsigned char *tempBase = NULL;
37 
38     gpioZBase = OsalIoRemap(MP1XX_AHB5_GPIOZ_BASE, MP1XX_GPIO_REG_SIZE);
39     if (gpioZBase == NULL) {
40         HDF_LOGE("%s: remap regbase failed", __func__);
41         return;
42     }
43     gpioBase = OsalIoRemap(MP1XX_AHB4_GPIO_BASE, MP1XX_GPIO_GROUP_STEP * MP1XX_GPIO_GROUP_NUM);
44     if (gpioBase == NULL) {
45         HDF_LOGE("%s: remap regbase failed", __func__);
46         return;
47     }
48 
49     for (i = 0; i < MP1XX_SPI_PIN_NUM * MP1XX_MEMBER_PER_PIN; i += MP1XX_MEMBER_PER_PIN) {
50         if (stm32mp1->pins[i + PIN_GROUP] == MP1XX_GPIOZ) {
51             tempBase = gpioZBase;
52         } else if (stm32mp1->pins[i + PIN_GROUP] < MP1XX_GPIO_GROUP_NUM) {
53             tempBase = gpioBase + MP1XX_GPIO_GROUP_STEP * stm32mp1->pins[i + PIN_GROUP];
54         }
55         value = OSAL_READL(tempBase);
56         value &= ~(MP1XX_MODER_MASK << (MP1XX_GPIO_MODE_BITS * stm32mp1->pins[i + PIN_NUM]));
57         value |= MP1XX_PIN_AF_MODE << (MP1XX_GPIO_MODE_BITS * stm32mp1->pins[i + PIN_NUM]);
58         OSAL_WRITEL(value, tempBase);
59         if (stm32mp1->pins[i + PIN_NUM] < MP1XX_PIN_NUM_PER_AF_REG) {
60             value = OSAL_READL(tempBase + MP1XX_GPIO_AF_LOW_REG);
61 
62             value &= ~(MP1XX_GPIO_AF_MASK << (MP1XX_GPIO_AF_BITS * stm32mp1->pins[i + PIN_NUM]));
63             value |= stm32mp1->pins[i + PIN_AF] << (MP1XX_GPIO_AF_BITS * stm32mp1->pins[i + PIN_NUM]);
64             OSAL_WRITEL(value, tempBase + MP1XX_GPIO_AF_LOW_REG);
65         } else {
66             value = OSAL_READL(tempBase + MP1XX_GPIO_AF_HIGH_REG);
67             value &= ~(MP1XX_GPIO_AF_MASK <<
68                 (MP1XX_GPIO_AF_BITS * stm32mp1->pins[i + PIN_NUM - MP1XX_PIN_NUM_PER_AF_REG]));
69             value |= stm32mp1->pins[i + PIN_AF] <<
70                 (MP1XX_GPIO_AF_BITS * stm32mp1->pins[i + PIN_NUM - MP1XX_PIN_NUM_PER_AF_REG]);
71             OSAL_WRITEL(value, tempBase + MP1XX_GPIO_AF_HIGH_REG);
72         }
73     }
74     OsalIoUnmap((void *)gpioZBase);
75     OsalIoUnmap((void *)gpioBase);
76 }
77 
Mp1xxSpiCfgCs(struct Mp1xxSpiCntlr * stm32mp1,uint32_t cs)78 static int32_t Mp1xxSpiCfgCs(struct Mp1xxSpiCntlr *stm32mp1, uint32_t cs)
79 {
80     uint32_t value;
81 
82     if ((cs + 1) > stm32mp1->numCs) {
83         HDF_LOGE("%s: cs %d is big than stm32mp1 csNum %d", __func__, cs, stm32mp1->numCs);
84         return HDF_FAILURE;
85     }
86     if (stm32mp1->numCs == 1) {
87         return HDF_SUCCESS;
88     }
89     value = OSAL_READL(stm32mp1->regBase + MP1XX_SPI2S_CR1_OFFSET);
90     value &= ~MP1XX_SPI_CS;
91     value |= (!!cs ? (cs << MP1XX_SPI_CS_SHIFT) : 0);
92     OSAL_WRITEL(value, stm32mp1->regBase + MP1XX_SPI2S_CR1_OFFSET);
93 
94     return HDF_SUCCESS;
95 }
96 
97 /* open spi clk */
Mp1xxSpiHwInitCfg(struct Mp1xxSpiCntlr * stm32mp1)98 static void Mp1xxSpiHwInitCfg(struct Mp1xxSpiCntlr *stm32mp1)
99 {
100     switch (stm32mp1->busNum) {
101         case SPI_1:
102             __HAL_RCC_SPI1_CLK_ENABLE();
103             break;
104         case SPI_2:
105             __HAL_RCC_SPI2_CLK_ENABLE();
106             break;
107         case SPI_3:
108             __HAL_RCC_SPI3_CLK_ENABLE();
109             break;
110         case SPI_4:
111             __HAL_RCC_SPI4_CLK_ENABLE();
112             break;
113         case SPI_5:
114             __HAL_RCC_SPI5_CLK_ENABLE();
115             break;
116         case SPI_6:
117             __HAL_RCC_SPI6_CLK_ENABLE();
118             break;
119         default:
120             break;
121     }
122 }
123 
124 /* close spi clk */
Mp1xxSpiHwExitCfg(struct Mp1xxSpiCntlr * stm32mp1)125 static void Mp1xxSpiHwExitCfg(struct Mp1xxSpiCntlr *stm32mp1)
126 {
127     switch (stm32mp1->busNum) {
128         case SPI_1:
129             __HAL_RCC_SPI1_CLK_DISABLE();
130             break;
131         case SPI_2:
132             __HAL_RCC_SPI2_CLK_DISABLE();
133             break;
134         case SPI_3:
135             __HAL_RCC_SPI3_CLK_DISABLE();
136             break;
137         case SPI_4:
138             __HAL_RCC_SPI4_CLK_DISABLE();
139             break;
140         case SPI_5:
141             __HAL_RCC_SPI5_CLK_DISABLE();
142             break;
143         case SPI_6:
144             __HAL_RCC_SPI6_CLK_DISABLE();
145             break;
146         default:
147             break;
148     }
149 }
150 
Mp1xxSpiEnable(const struct Mp1xxSpiCntlr * stm32mp1)151 static void Mp1xxSpiEnable(const struct Mp1xxSpiCntlr *stm32mp1)
152 {
153     uint32_t value;
154 
155     value = OSAL_READL(stm32mp1->regBase + MP1XX_SPI2S_SR_OFFSET);
156     if ((value & MP1XX_SPI_MODF_MASK) != 0) {
157         value = OSAL_READL(stm32mp1->regBase + MP1XX_SPI2S_CR1_OFFSET);
158         value |= MP1XX_SPI_SSI;
159         OSAL_WRITEL(value, stm32mp1->regBase + MP1XX_SPI2S_CR1_OFFSET);
160         value = MP1XX_SPI_MODF_MASK;
161         OSAL_WRITEL(value, stm32mp1->regBase + MP1XX_SPI2S_IFCR_OFFSET);
162     }
163 
164     value = OSAL_READL(stm32mp1->regBase + MP1XX_SPI2S_CR1_OFFSET);
165     value |= 0x1U;
166     OSAL_WRITEL(value, stm32mp1->regBase + MP1XX_SPI2S_CR1_OFFSET);
167 }
168 
Mp1xxSpiDisable(const struct Mp1xxSpiCntlr * stm32mp1)169 static void Mp1xxSpiDisable(const struct Mp1xxSpiCntlr *stm32mp1)
170 {
171     uint32_t value;
172 
173     value = OSAL_READL(stm32mp1->regBase + MP1XX_SPI2S_CR1_OFFSET);
174     value &= ~0x1U;
175     OSAL_WRITEL(value, stm32mp1->regBase + MP1XX_SPI2S_CR1_OFFSET);
176 }
177 
Mp1xxSpiConfigClk(const struct Mp1xxSpiCntlr * stm32mp1,uint32_t clkDiv)178 static void Mp1xxSpiConfigClk(const struct Mp1xxSpiCntlr *stm32mp1, uint32_t clkDiv)
179 {
180     uint32_t value;
181     uint32_t mbr;
182 
183     clkDiv = clkDiv / MP1XX_SPI_MIN_CLK_DIV;
184     for (mbr = 0; mbr <= MP1XX_SPI_MBR_MAX; mbr++) {
185         if ((clkDiv >> mbr) == 0) {
186             mbr++;
187             HDF_LOGE("%s:mbr=%u", __func__, mbr);
188             break;
189         }
190     }
191 
192     value = OSAL_READL(stm32mp1->regBase + MP1XX_SPI_CFG1_OFFSET);
193     value &= ~MP1XX_SPI_MBR_MASK;
194     OSAL_WRITEL(value, stm32mp1->regBase + MP1XX_SPI_CFG1_OFFSET);
195 }
196 
Mp1xxSpiConfigCfg1(const struct Mp1xxSpiCntlr * stm32mp1)197 static void Mp1xxSpiConfigCfg1(const struct Mp1xxSpiCntlr *stm32mp1)
198 {
199     uint32_t value;
200     uint32_t temp;
201 
202     temp = (stm32mp1->fifoSize > SPI_MAX_LEVEL) ? SPI_MAX_LEVEL : stm32mp1->fifoSize;
203     value = OSAL_READL(stm32mp1->regBase + MP1XX_SPI_CFG1_OFFSET);
204     value &= ~MP1XX_SPI_FTHLV_MASK;
205     value |= temp;
206 
207     value &= ~MP1XX_SPI_DSIZE_MASK;
208     value |= stm32mp1->bitsPerWord - 1;
209     OSAL_WRITEL(value, stm32mp1->regBase + MP1XX_SPI_CFG1_OFFSET);
210 }
211 
Mp1xxSpiConfigCfg2(const struct Mp1xxSpiCntlr * stm32mp1)212 static void Mp1xxSpiConfigCfg2(const struct Mp1xxSpiCntlr *stm32mp1)
213 {
214     uint32_t tmp;
215     uint32_t value;
216 
217     value = OSAL_READL(stm32mp1->regBase + MP1XX_SPI_CFG2_OFFSET);
218     value |= MP1XX_SPI_SSM;
219 
220     tmp = (!!(stm32mp1->mode & SPI_CLK_PHASE)) ? (1 << MP1XX_SPI_CPHA_SHIFT) : 0;
221     value |= tmp;
222 
223     tmp = (!!(stm32mp1->mode & SPI_CLK_POLARITY)) ? (1 << MP1XX_SPI_CPOL_SHIFT) : 0;
224     value |= tmp;
225 
226     tmp = (!!(stm32mp1->mode & SPI_MODE_3WIRE)) ? (MP1XX_SPI_HALF_DUPLEX_MODE << MP1XX_SPI_COMM_SHIFT) : 0;
227     value |= tmp;
228 
229     tmp = (!!(stm32mp1->mode & SPI_MODE_LSBFE)) ? (1 << MP1XX_SPI_LSBFRST_SHIFT) : 0;
230     value |= tmp;
231 
232     value |= MP1XX_SPI_MASTER;
233     value |= MP1XX_SPI_SSOE_MASK;
234     OSAL_WRITEL(value, stm32mp1->regBase + MP1XX_SPI_CFG2_OFFSET);
235 }
236 
Mp1xxSpiConfigFifo(const struct Mp1xxSpiCntlr * stm32mp1)237 static void Mp1xxSpiConfigFifo(const struct Mp1xxSpiCntlr *stm32mp1)
238 {
239     uint32_t value;
240 
241     value = OSAL_READL(stm32mp1->regBase + MP1XX_SPI2S_HWCFGR_OFFSET);
242     /* Tx FIFO size 32 byte */
243     value &= ~MP1XX_SPI_FIFO_MASK;
244     value |= MP1XX_SPI2S_FIFO_SIZE;
245     /* Rx FIFO size 32 byte */
246     value &= ~(MP1XX_SPI_FIFO_MASK << MP1XX_SPI_RXFCFG_SHIFT);
247     value |= MP1XX_SPI2S_FIFO_SIZE << MP1XX_SPI_RXFCFG_SHIFT;
248     OSAL_WRITEL(value, stm32mp1->regBase + MP1XX_SPI2S_HWCFGR_OFFSET);
249 }
250 
251 #define RX_INT_FIFO_LEVEL      (256 - 128)
252 #define RX_INT_WAIT_TIMEOUT    1000 // ms
253 
Mp1xxSpiConfigIrq(struct Mp1xxSpiCntlr * stm32mp1)254 static void Mp1xxSpiConfigIrq(struct Mp1xxSpiCntlr *stm32mp1)
255 {
256     OSAL_WRITEL(SPI_ALL_IRQ_CLEAR, stm32mp1->regBase + MP1XX_SPI2S_IFCR_OFFSET);
257     if (stm32mp1->transferMode == SPI_POLLING_TRANSFER) {
258         OSAL_WRITEL(SPI_ALL_IRQ_DISABLE, stm32mp1->regBase + MP1XX_SPI2S_IER_OFFSET);
259     } else {
260         OSAL_WRITEL(SPI_ALL_IRQ_ENABLE, stm32mp1->regBase + MP1XX_SPI2S_IER_OFFSET);
261     }
262 }
263 
Mp1xxSpiConfig(struct Mp1xxSpiCntlr * stm32mp1)264 static int32_t Mp1xxSpiConfig(struct Mp1xxSpiCntlr *stm32mp1)
265 {
266     uint32_t tmp;
267     uint32_t clkDiv;
268 
269     /* Check if we can provide the requested rate */
270     if (stm32mp1->speed > stm32mp1->maxSpeedHz) {
271         HDF_LOGW("%s: invalid speed:%d, use max:%d instead", __func__, stm32mp1->speed, stm32mp1->maxSpeedHz);
272         stm32mp1->speed = stm32mp1->maxSpeedHz;
273     }
274     /* Min possible */
275     if (stm32mp1->speed == 0 || stm32mp1->speed < stm32mp1->minSpeedHz) {
276         HDF_LOGW("%s: invalid speed:%d, use min:%d instead", __func__, stm32mp1->speed, stm32mp1->minSpeedHz);
277         stm32mp1->speed = stm32mp1->minSpeedHz;
278     }
279 
280     /* Check if we can provide the requested bits_per_word */
281     if ((stm32mp1->bitsPerWord < BITS_PER_WORD_MIN) || (stm32mp1->bitsPerWord > BITS_PER_WORD_MAX)) {
282         HDF_LOGE("%s: stm32mp1->bitsPerWord is %d not support", __func__, stm32mp1->bitsPerWord);
283         return HDF_FAILURE;
284     }
285 
286     tmp = (stm32mp1->clkRate) / (stm32mp1->speed);
287     if (tmp < MP1XX_SPI_MIN_CLK_DIV) {
288         clkDiv = MP1XX_SPI_MIN_CLK_DIV;
289     } else if (tmp > MP1XX_SPI_MAX_CLK_DIV) {
290         clkDiv = MP1XX_SPI_MAX_CLK_DIV;
291     } else {
292         /* Calculate the closest division factor */
293         for (clkDiv = MP1XX_SPI_MIN_CLK_DIV; clkDiv < MP1XX_SPI_MAX_CLK_DIV; clkDiv = clkDiv << 1) {
294             if (clkDiv < tmp && (clkDiv << 1) > tmp) {
295                 clkDiv = (((clkDiv << 1) - tmp) > (tmp - clkDiv)) ? clkDiv : (clkDiv << 1);
296                 break;
297             }
298         }
299         HDF_LOGE("%s:clkDiv=%u", __func__, clkDiv);
300     }
301 
302     Mp1xxSpiDisable(stm32mp1);
303     /* config SPICLK */
304     Mp1xxSpiConfigClk(stm32mp1, clkDiv);
305     /* config SPICFG1 register */
306     Mp1xxSpiConfigCfg1(stm32mp1);
307     /* config SPICFG2 register */
308     Mp1xxSpiConfigCfg2(stm32mp1);
309     /* config irq */
310     Mp1xxSpiConfigIrq(stm32mp1);
311     Mp1xxSpiEnable(stm32mp1);
312 
313     return HDF_SUCCESS;
314 }
315 
Mp1xxSpiCheckTimeout(const struct Mp1xxSpiCntlr * stm32mp1)316 static int32_t Mp1xxSpiCheckTimeout(const struct Mp1xxSpiCntlr *stm32mp1)
317 {
318     uint32_t tmp = 0;
319     unsigned long value;
320 
321     while (1) {
322         value = OSAL_READL(stm32mp1->regBase + MP1XX_SPI2S_SR_OFFSET);
323         if ((value & MP1XX_SPI_SR_RXP_MASK) != 0) {
324             break;
325         }
326         if (tmp++ > MAX_WAIT) {
327             HDF_LOGE("%s: spi transfer wait timeout", __func__);
328             return HDF_ERR_TIMEOUT;
329         }
330         OsalUDelay(1);
331     }
332     OSAL_WRITEL(SPI_ALL_IRQ_CLEAR, stm32mp1->regBase + MP1XX_SPI2S_IFCR_OFFSET);
333 
334     return HDF_SUCCESS;
335 }
336 
Mp1xxSpiFlushFifo(const struct Mp1xxSpiCntlr * stm32mp1)337 static int32_t Mp1xxSpiFlushFifo(const struct Mp1xxSpiCntlr *stm32mp1)
338 {
339     Mp1xxSpiDisable(stm32mp1);
340     OsalMDelay(1);
341     Mp1xxSpiEnable(stm32mp1);
342 
343     return HDF_SUCCESS;
344 }
345 
346 #define MP1XX_ONE_BYTE 1
347 #define MP1XX_TWO_BYTE 2
348 
Mp1xxSpiToByteWidth(uint8_t bitsPerWord)349 static inline uint8_t Mp1xxSpiToByteWidth(uint8_t bitsPerWord)
350 {
351     if (bitsPerWord <= BITS_PER_WORD_EIGHT) {
352         return MP1XX_ONE_BYTE;
353     } else {
354         return MP1XX_TWO_BYTE;
355     }
356 }
357 
Mp1xxSpiWriteFifo(const struct Mp1xxSpiCntlr * stm32mp1,const uint8_t * tx,uint32_t count)358 static void Mp1xxSpiWriteFifo(const struct Mp1xxSpiCntlr *stm32mp1, const uint8_t *tx, uint32_t count)
359 {
360     unsigned long value;
361     uint32_t delay = 0;
362     uint8_t bytes = Mp1xxSpiToByteWidth(stm32mp1->bitsPerWord);
363 
364     for (value = 0; count >= bytes; count -= bytes) {
365         while (1) {
366             value = OSAL_READL(stm32mp1->regBase + MP1XX_SPI2S_SR_OFFSET);
367             if ((value & MP1XX_SPI_SR_TXP_MASK) != 0) {
368                 break;
369             }
370             OsalUDelay(1);
371             delay++;
372             if (delay >= MAX_WAIT) {
373                 HDF_LOGE("%s: write fifo time out", __func__);
374                 break;
375             }
376         }
377         if (tx != NULL) {
378             value = (bytes == MP1XX_ONE_BYTE) ? *tx : *((uint16_t *)tx);
379             tx += bytes;
380         }
381         OSAL_WRITEL(value, stm32mp1->regBase + MP1XX_SPI2S_TXDR_OFFSET);
382     }
383 }
384 
Mp1xxSpiReadFifo(const struct Mp1xxSpiCntlr * stm32mp1,uint8_t * rx,uint32_t count)385 static void Mp1xxSpiReadFifo(const struct Mp1xxSpiCntlr *stm32mp1, uint8_t *rx, uint32_t count)
386 {
387     unsigned long value;
388     uint32_t delay = 0;
389     uint8_t bytes = Mp1xxSpiToByteWidth(stm32mp1->bitsPerWord);
390 
391     while (1) {
392         value = OSAL_READL(stm32mp1->regBase + MP1XX_SPI2S_SR_OFFSET);
393         if ((value & MP1XX_SPI_SR_RXP_MASK) != 0) {
394             break;
395         }
396         OsalUDelay(1);
397         delay++;
398         if (delay >= MAX_WAIT) {
399             HDF_LOGE("%s: read fifo time out", __func__);
400             break;
401         }
402     }
403 
404     for (value = 0; count >= bytes; count -= bytes) {
405         value = OSAL_READL(stm32mp1->regBase + MP1XX_SPI2S_RXDR_OFFSET);
406         if (rx == NULL) {
407             continue;
408         }
409         if (bytes == MP1XX_ONE_BYTE) {
410             *rx = (uint8_t)value;
411         } else {
412             *((uint16_t *)rx) = (uint16_t)value;
413         }
414         rx += bytes;
415     }
416 }
417 
Mp1xxSpiStartTransfer(const struct Mp1xxSpiCntlr * stm32mp1)418 static void Mp1xxSpiStartTransfer(const struct Mp1xxSpiCntlr *stm32mp1)
419 {
420     uint32_t value;
421 
422     value = OSAL_READL(stm32mp1->regBase + MP1XX_SPI2S_CR1_OFFSET);
423     value |= MP1XX_SPI_CSTART_MASK;
424     OSAL_WRITEL(value, stm32mp1->regBase + MP1XX_SPI2S_CR1_OFFSET);
425 }
426 
Mp1xxSpiTxRx(const struct Mp1xxSpiCntlr * stm32mp1,const struct SpiMsg * msg)427 static int32_t Mp1xxSpiTxRx(const struct Mp1xxSpiCntlr *stm32mp1, const struct SpiMsg *msg)
428 {
429     int32_t ret;
430     uint32_t tmpLen;
431     uint32_t len = msg->len;
432     const uint8_t *tx = msg->wbuf;
433     uint8_t *rx = msg->rbuf;
434     uint8_t bytes = Mp1xxSpiToByteWidth(stm32mp1->bitsPerWord);
435     uint32_t burstSize = stm32mp1->fifoSize * bytes;
436 
437     if (tx == NULL && rx == NULL) {
438         return HDF_ERR_INVALID_PARAM;
439     }
440 
441     if (stm32mp1->transferMode != SPI_POLLING_TRANSFER && RX_INT_FIFO_LEVEL < stm32mp1->fifoSize) {
442         burstSize = RX_INT_FIFO_LEVEL * bytes;
443     }
444 
445     for (tmpLen = 0, len = msg->len; len > 0; len -= tmpLen) {
446         tmpLen = (len > burstSize) ? burstSize : len;
447         if (stm32mp1->transferMode != SPI_POLLING_TRANSFER && tmpLen == burstSize) {
448             OSAL_WRITEL(SPI_ALL_IRQ_ENABLE, stm32mp1->regBase + MP1XX_SPI2S_IER_OFFSET);
449         }
450         Mp1xxSpiWriteFifo(stm32mp1, tx, tmpLen);
451         Mp1xxSpiStartTransfer(stm32mp1);
452         tx = (tx == NULL) ? NULL : (tx + tmpLen);
453         if (stm32mp1->transferMode != SPI_POLLING_TRANSFER && tmpLen == burstSize) {
454             ret = OsalSemWait((struct OsalSem *)(&stm32mp1->sem), RX_INT_WAIT_TIMEOUT);
455         } else {
456             ret = Mp1xxSpiCheckTimeout(stm32mp1);
457         }
458 
459         if (ret != HDF_SUCCESS) {
460             HDF_LOGE("%s: %s timeout", __func__, (stm32mp1->transferMode != SPI_POLLING_TRANSFER) ?
461                 "wait rx fifo int" : "wait tx fifo idle");
462 
463             return ret;
464         }
465         Mp1xxSpiReadFifo(stm32mp1, rx, tmpLen);
466         rx = (rx == NULL) ? NULL : (rx + tmpLen);
467     }
468     return HDF_SUCCESS;
469 }
470 
Mp1xxSpiSetCs(struct Mp1xxSpiCntlr * stm32mp1,uint32_t cs,uint32_t flag)471 static int32_t Mp1xxSpiSetCs(struct Mp1xxSpiCntlr *stm32mp1, uint32_t cs, uint32_t flag)
472 {
473     if (Mp1xxSpiCfgCs(stm32mp1, cs)) {
474         return HDF_FAILURE;
475     }
476     if (flag == SPI_CS_ACTIVE) {
477         Mp1xxSpiEnable(stm32mp1);
478     } else {
479         Mp1xxSpiDisable(stm32mp1);
480     }
481     return HDF_SUCCESS;
482 }
483 
Mp1xxSpiFindDeviceByCsNum(const struct Mp1xxSpiCntlr * stm32mp1,uint32_t cs)484 static struct SpiDev *Mp1xxSpiFindDeviceByCsNum(const struct Mp1xxSpiCntlr *stm32mp1, uint32_t cs)
485 {
486     struct SpiDev *dev = NULL;
487     struct SpiDev *tmpDev = NULL;
488 
489     if (stm32mp1 == NULL || stm32mp1->numCs <= cs) {
490         return NULL;
491     }
492     DLIST_FOR_EACH_ENTRY_SAFE(dev, tmpDev, &(stm32mp1->deviceList), struct SpiDev, list)
493     {
494         if (dev->csNum == cs) {
495             break;
496         }
497     }
498     return dev;
499 }
500 
Mp1xxSpiSetCfg(struct SpiCntlr * cntlr,struct SpiCfg * cfg)501 static int32_t Mp1xxSpiSetCfg(struct SpiCntlr *cntlr, struct SpiCfg *cfg)
502 {
503     struct Mp1xxSpiCntlr *stm32mp1 = NULL;
504     struct SpiDev *dev = NULL;
505     int32_t ret;
506 
507     if (cntlr == NULL) {
508         HDF_LOGE("%s: cntlr is NULL", __func__);
509         return HDF_ERR_INVALID_PARAM;
510     }
511     if (cntlr->priv == NULL) {
512         HDF_LOGE("%s: priv is NULL", __func__);
513         return HDF_ERR_INVALID_PARAM;
514     }
515     if (cfg == NULL) {
516         HDF_LOGE("%s: cfg is NULL", __func__);
517         return HDF_ERR_INVALID_PARAM;
518     }
519     stm32mp1 = (struct Mp1xxSpiCntlr *)cntlr->priv;
520     dev = Mp1xxSpiFindDeviceByCsNum(stm32mp1, cntlr->curCs);
521     if (dev == NULL) {
522         return HDF_FAILURE;
523     }
524     dev->cfg.mode = cfg->mode;
525     dev->cfg.transferMode = cfg->transferMode;
526     if (cfg->bitsPerWord < BITS_PER_WORD_MIN || cfg->bitsPerWord > BITS_PER_WORD_MAX) {
527         HDF_LOGE("%s: bitsPerWord %d not support, use defaule bitsPerWord %d",
528             __func__, cfg->bitsPerWord, BITS_PER_WORD_EIGHT);
529         dev->cfg.bitsPerWord = BITS_PER_WORD_EIGHT;
530     } else {
531         dev->cfg.bitsPerWord = cfg->bitsPerWord;
532     }
533     if (cfg->maxSpeedHz != 0) {
534         dev->cfg.maxSpeedHz = cfg->maxSpeedHz;
535     }
536     ret = Mp1xxSpiConfig(stm32mp1);
537     if (ret != HDF_SUCCESS) {
538         return ret;
539     }
540     return HDF_SUCCESS;
541 }
542 
Mp1xxSpiGetCfg(struct SpiCntlr * cntlr,struct SpiCfg * cfg)543 static int32_t Mp1xxSpiGetCfg(struct SpiCntlr *cntlr, struct SpiCfg *cfg)
544 {
545     struct Mp1xxSpiCntlr *stm32mp1 = NULL;
546     struct SpiDev *dev = NULL;
547 
548     if (cntlr == NULL || cntlr->priv == NULL || cfg == NULL) {
549         HDF_LOGE("%s: cntlr priv or cfg is NULL", __func__);
550         return HDF_ERR_INVALID_PARAM;
551     }
552     stm32mp1 = (struct Mp1xxSpiCntlr *)cntlr->priv;
553     dev = Mp1xxSpiFindDeviceByCsNum(stm32mp1, cntlr->curCs);
554     if (dev == NULL) {
555         return HDF_FAILURE;
556     }
557     *cfg = dev->cfg;
558     return HDF_SUCCESS;
559 }
560 
Mp1xxSpiTransferOneMessage(struct Mp1xxSpiCntlr * stm32mp1,struct SpiMsg * msg)561 static int32_t Mp1xxSpiTransferOneMessage(struct Mp1xxSpiCntlr *stm32mp1, struct SpiMsg *msg)
562 {
563     int32_t ret;
564 
565     ret = Mp1xxSpiSetCs(stm32mp1, stm32mp1->curCs, SPI_CS_ACTIVE);
566     if (ret != HDF_SUCCESS) {
567         return ret;
568     }
569     ret = Mp1xxSpiFlushFifo(stm32mp1);
570     if (ret != HDF_SUCCESS) {
571         return ret;
572     }
573 
574     stm32mp1->speed = (msg->speed) == 0 ? DEFAULT_SPEED : msg->speed;
575     ret = Mp1xxSpiConfig(stm32mp1);
576     if (ret != HDF_SUCCESS) {
577         return ret;
578     }
579 
580     ret = Mp1xxSpiTxRx(stm32mp1, msg);
581     if (ret || msg->keepCs == 0) {
582         Mp1xxSpiSetCs(stm32mp1, stm32mp1->curCs, SPI_CS_INACTIVE);
583     }
584     return ret;
585 }
586 
Mp1xxSpiTransfer(struct SpiCntlr * cntlr,struct SpiMsg * msg,uint32_t count)587 static int32_t Mp1xxSpiTransfer(struct SpiCntlr *cntlr, struct SpiMsg *msg, uint32_t count)
588 {
589     int32_t ret;
590     uint32_t i;
591     struct Mp1xxSpiCntlr *stm32mp1 = 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     stm32mp1 = (struct Mp1xxSpiCntlr *)cntlr->priv;
604     dev = Mp1xxSpiFindDeviceByCsNum(stm32mp1, cntlr->curCs);
605     if (dev == NULL) {
606         return HDF_FAILURE;
607     }
608     Mp1xxSpiDisable(stm32mp1);
609     stm32mp1->mode = dev->cfg.mode;
610     stm32mp1->transferMode = dev->cfg.transferMode;
611     stm32mp1->bitsPerWord = dev->cfg.bitsPerWord;
612     stm32mp1->maxSpeedHz = dev->cfg.maxSpeedHz;
613     stm32mp1->curCs = dev->csNum;
614     for (i = 0; i < count; i++) {
615         ret = Mp1xxSpiTransferOneMessage(stm32mp1, &(msg[i]));
616         if (ret != HDF_SUCCESS) {
617             HDF_LOGE("%s: transfer error", __func__);
618             return ret;
619         }
620     }
621 
622     return HDF_SUCCESS;
623 }
624 
Mp1xxSpiOpen(struct SpiCntlr * cntlr)625 int32_t Mp1xxSpiOpen(struct SpiCntlr *cntlr)
626 {
627     (void)cntlr;
628     return HDF_SUCCESS;
629 }
630 
Mp1xxSpiClose(struct SpiCntlr * cntlr)631 int32_t Mp1xxSpiClose(struct SpiCntlr *cntlr)
632 {
633     (void)cntlr;
634     return HDF_SUCCESS;
635 }
636 
Mp1xxSpiProbe(struct Mp1xxSpiCntlr * stm32mp1)637 static int32_t Mp1xxSpiProbe(struct Mp1xxSpiCntlr *stm32mp1)
638 {
639     int32_t ret;
640 
641     Mp1xxSpiSetPinMux(stm32mp1);
642     Mp1xxSpiHwInitCfg(stm32mp1);
643     Mp1xxSpiConfigFifo(stm32mp1);
644 
645     ret = Mp1xxSpiConfig(stm32mp1);
646     if (ret != HDF_SUCCESS) {
647         HDF_LOGE("%s: Mp1xxSpiConfig error", __func__);
648         return ret;
649     }
650 
651     return HDF_SUCCESS;
652 }
653 
654 struct SpiCntlrMethod g_method = {
655     .Transfer = Mp1xxSpiTransfer,
656     .SetCfg = Mp1xxSpiSetCfg,
657     .GetCfg = Mp1xxSpiGetCfg,
658     .Open = Mp1xxSpiOpen,
659     .Close = Mp1xxSpiClose,
660 };
661 
Mp1xxSpiCreatAndInitDevice(struct Mp1xxSpiCntlr * stm32mp1)662 static int32_t Mp1xxSpiCreatAndInitDevice(struct Mp1xxSpiCntlr *stm32mp1)
663 {
664     uint32_t i;
665     struct SpiDev *device = NULL;
666 
667     for (i = 0; i < stm32mp1->numCs; i++) {
668         device = (struct SpiDev *)OsalMemCalloc(sizeof(*device));
669         if (device == NULL) {
670             HDF_LOGE("%s: OsalMemCalloc error", __func__);
671             return HDF_FAILURE;
672         }
673         device->cntlr = stm32mp1->cntlr;
674         device->csNum = i;
675         device->cfg.bitsPerWord = stm32mp1->bitsPerWord;
676         device->cfg.transferMode = stm32mp1->transferMode;
677         device->cfg.maxSpeedHz = stm32mp1->maxSpeedHz;
678         device->cfg.mode = stm32mp1->mode;
679         DListHeadInit(&device->list);
680         DListInsertTail(&device->list, &stm32mp1->deviceList);
681         SpiAddDev(device);
682     }
683     return HDF_SUCCESS;
684 }
685 
Mp1xxSpiRelease(struct Mp1xxSpiCntlr * stm32mp1)686 static void Mp1xxSpiRelease(struct Mp1xxSpiCntlr *stm32mp1)
687 {
688     struct SpiDev *dev = NULL;
689     struct SpiDev *tmpDev = NULL;
690 
691     DLIST_FOR_EACH_ENTRY_SAFE(dev, tmpDev, &(stm32mp1->deviceList), struct SpiDev, list)
692     {
693         SpiRemoveDev(dev);
694         DListRemove(&(dev->list));
695         OsalMemFree(dev);
696     }
697     if (stm32mp1->irqNum != 0) {
698         (void)OsalUnregisterIrq(stm32mp1->irqNum, stm32mp1);
699     }
700     OsalMemFree(stm32mp1);
701 }
702 
SpiGetBaseCfgFromHcs(struct Mp1xxSpiCntlr * stm32mp1,const struct DeviceResourceNode * node)703 static int32_t SpiGetBaseCfgFromHcs(struct Mp1xxSpiCntlr *stm32mp1, const struct DeviceResourceNode *node)
704 {
705     struct DeviceResourceIface *iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
706 
707     if (iface == NULL || iface->GetUint8 == NULL || iface->GetUint16 == NULL || iface->GetUint32 == NULL) {
708         HDF_LOGE("%s: iface is invalid", __func__);
709         return HDF_FAILURE;
710     }
711     if (iface->GetUint32(node, "busNum", &stm32mp1->busNum, 0) != HDF_SUCCESS) {
712         HDF_LOGE("%s: read busNum fail", __func__);
713         return HDF_FAILURE;
714     }
715     if (iface->GetUint32(node, "spi_numCs", &stm32mp1->numCs, 0) != HDF_SUCCESS) {
716         HDF_LOGE("%s: read numCs fail", __func__);
717         return HDF_FAILURE;
718     }
719     if (iface->GetUint32(node, "spi_speed", &stm32mp1->speed, 0) != HDF_SUCCESS) {
720         HDF_LOGE("%s: read speed fail", __func__);
721         return HDF_FAILURE;
722     }
723     if (iface->GetUint32(node, "fifoSize", &stm32mp1->fifoSize, 0) != HDF_SUCCESS) {
724         HDF_LOGE("%s: read fifoSize fail", __func__);
725         return HDF_FAILURE;
726     }
727     if (iface->GetUint32(node, "spi_clkRate", &stm32mp1->clkRate, 0) != HDF_SUCCESS) {
728         HDF_LOGE("%s: read clkRate fail", __func__);
729         return HDF_FAILURE;
730     }
731     if (iface->GetUint16(node, "spi_mode", &stm32mp1->mode, 0) != HDF_SUCCESS) {
732         HDF_LOGE("%s: read mode fail", __func__);
733         return HDF_FAILURE;
734     }
735     if (iface->GetUint8(node, "spi_bitsPerWord", &stm32mp1->bitsPerWord, 0) != HDF_SUCCESS) {
736         HDF_LOGE("%s: read bitsPerWord fail", __func__);
737         return HDF_FAILURE;
738     }
739     if (iface->GetUint8(node, "spi_transferMode", &stm32mp1->transferMode, 0) != HDF_SUCCESS) {
740         HDF_LOGE("%s: read comMode fail", __func__);
741         return HDF_FAILURE;
742     }
743     return HDF_SUCCESS;
744 }
745 
SpiGetRegCfgFromHcs(struct Mp1xxSpiCntlr * stm32mp1,const struct DeviceResourceNode * node)746 static int32_t SpiGetRegCfgFromHcs(struct Mp1xxSpiCntlr *stm32mp1, const struct DeviceResourceNode *node)
747 {
748     uint32_t regBasePhy;
749     uint32_t regSize;
750     int32_t ret;
751     struct DeviceResourceIface *iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
752 
753     if (iface == NULL || iface->GetUint32 == NULL) {
754         HDF_LOGE("%s: face is invalid", __func__);
755         return HDF_FAILURE;
756     }
757     if (iface->GetUint32(node, "busModeSel", &stm32mp1->busModeSel, 0) != HDF_SUCCESS) {
758         HDF_LOGE("%s: read busModeSel fail", __func__);
759         return HDF_FAILURE;
760     }
761 
762     if (stm32mp1->busModeSel != SPI2S_SPI_MODE) {
763         HDF_LOGI("%s: SPI%u is disabled", __func__, stm32mp1->busNum);
764         return HDF_ERR_NOT_SUPPORT;
765     }
766 
767     if (iface->GetUint32(node, "regPBase", &regBasePhy, 0) != HDF_SUCCESS) {
768         HDF_LOGE("%s: read regBase fail", __func__);
769         return HDF_FAILURE;
770     }
771     if (iface->GetUint32(node, "regSize", &regSize, 0) != HDF_SUCCESS) {
772         HDF_LOGE("%s: read regSize fail", __func__);
773         return HDF_FAILURE;
774     }
775     stm32mp1->regBase = OsalIoRemap(regBasePhy, regSize);
776     if (stm32mp1->regBase == NULL) {
777         HDF_LOGE("%s: remap regbase failed", __func__);
778         return HDF_FAILURE;
779     }
780 
781     if (iface->GetUint32(node, "irqNum", &stm32mp1->irqNum, 0) != HDF_SUCCESS) {
782         HDF_LOGE("%s: read irqNum fail", __func__);
783         return HDF_FAILURE;
784     }
785 
786     ret = iface->GetUint8Array(node, "pins", stm32mp1->pins, MP1XX_SPI_PIN_NUM * MP1XX_MEMBER_PER_PIN, 0);
787     if (ret != HDF_SUCCESS) {
788         HDF_LOGE("%s: read pins failed", __func__);
789         return ret;
790     }
791 
792     return HDF_SUCCESS;
793 }
794 
Mp1xxSpiIrqHandleNoShare(uint32_t irq,void * data)795 static uint32_t Mp1xxSpiIrqHandleNoShare(uint32_t irq, void *data)
796 {
797     unsigned long value;
798     struct Mp1xxSpiCntlr *stm32mp1 = (struct Mp1xxSpiCntlr *)data;
799 
800     (void)irq;
801     if (stm32mp1 == NULL) {
802         HDF_LOGE("%s: data is NULL!", __func__);
803         return HDF_ERR_INVALID_PARAM;
804     }
805 
806     value = OSAL_READL(stm32mp1->regBase + MP1XX_SPI2S_SR_OFFSET);
807     if ((value & MP1XX_SPI_MODF_MASK) != 0) {
808         HDF_LOGE("%s: mode fault detected", __func__);
809         return HDF_FAILURE;
810     }
811 
812     OSAL_WRITEL(SPI_ALL_IRQ_CLEAR, stm32mp1->regBase + MP1XX_SPI2S_IFCR_OFFSET);
813     OSAL_WRITEL(SPI_ALL_IRQ_DISABLE, stm32mp1->regBase + MP1XX_SPI2S_IER_OFFSET);
814     (void)OsalSemPost(&stm32mp1->sem);
815     return HDF_SUCCESS;
816 }
817 
Mp1xxSpiInit(struct SpiCntlr * cntlr,const struct HdfDeviceObject * device)818 static int32_t Mp1xxSpiInit(struct SpiCntlr *cntlr, const struct HdfDeviceObject *device)
819 {
820     int32_t ret;
821     struct Mp1xxSpiCntlr *stm32mp1 = NULL;
822 
823     if (device->property == NULL) {
824         HDF_LOGE("%s: property is NULL", __func__);
825         return HDF_ERR_INVALID_PARAM;
826     }
827 
828     stm32mp1 = (struct Mp1xxSpiCntlr *)OsalMemCalloc(sizeof(*stm32mp1));
829     if (stm32mp1 == NULL) {
830         HDF_LOGE("%s: OsalMemCalloc error", __func__);
831         return HDF_FAILURE;
832     }
833 
834     ret = SpiGetRegCfgFromHcs(stm32mp1, device->property);
835     if (ret != HDF_SUCCESS) {
836         HDF_LOGE("%s: SpiGetRegCfgFromHcs error", __func__);
837         OsalMemFree(stm32mp1);
838         return HDF_FAILURE;
839     }
840     ret = SpiGetBaseCfgFromHcs(stm32mp1, device->property);
841     if (ret != HDF_SUCCESS) {
842         HDF_LOGE("%s: SpiGetBaseCfgFromHcs error", __func__);
843         OsalMemFree(stm32mp1);
844         return HDF_FAILURE;
845     }
846     stm32mp1->maxSpeedHz = MP1XX_SPI_MAX_SPEED;
847     stm32mp1->minSpeedHz = stm32mp1->clkRate / MP1XX_SPI_MAX_CLK_DIV;
848     DListHeadInit(&stm32mp1->deviceList);
849     stm32mp1->cntlr = cntlr;
850     cntlr->priv = stm32mp1;
851     cntlr->busNum = stm32mp1->busNum;
852     cntlr->method = &g_method;
853     ret = OsalSemInit(&stm32mp1->sem, 0);
854     if (ret != HDF_SUCCESS) {
855         OsalMemFree(stm32mp1);
856         HDF_LOGE("%s: sem init fail", __func__);
857         return ret;
858     }
859 
860     if (stm32mp1->irqNum != 0) {
861         OSAL_WRITEL(SPI_ALL_IRQ_DISABLE, stm32mp1->regBase + MP1XX_SPI2S_IER_OFFSET);
862         ret = OsalRegisterIrq(stm32mp1->irqNum, 0, Mp1xxSpiIrqHandleNoShare, "SPI_MP1XX", stm32mp1);
863         if (ret != HDF_SUCCESS) {
864             OsalMemFree(stm32mp1);
865             HDF_LOGE("%s: regisiter irq %u fail", __func__, stm32mp1->irqNum);
866             (void)OsalSemDestroy(&stm32mp1->sem);
867             return ret;
868         }
869     }
870 
871     ret = Mp1xxSpiCreatAndInitDevice(stm32mp1);
872     if (ret != HDF_SUCCESS) {
873         Mp1xxSpiRelease(stm32mp1);
874         return ret;
875     }
876     return HDF_SUCCESS;
877 }
878 
Mp1xxSpiRemove(struct Mp1xxSpiCntlr * stm32mp1)879 static inline void Mp1xxSpiRemove(struct Mp1xxSpiCntlr *stm32mp1)
880 {
881     Mp1xxSpiHwExitCfg(stm32mp1);
882     OsalIoUnmap((void *)stm32mp1->regBase);
883     Mp1xxSpiRelease(stm32mp1);
884 }
885 
HdfSpiDeviceBind(struct HdfDeviceObject * device)886 static int32_t HdfSpiDeviceBind(struct HdfDeviceObject *device)
887 {
888     HDF_LOGI("%s: entry", __func__);
889     if (device == NULL) {
890         return HDF_ERR_INVALID_OBJECT;
891     }
892     return (SpiCntlrCreate(device) == NULL) ? HDF_FAILURE : HDF_SUCCESS;
893 }
894 
HdfSpiDeviceInit(struct HdfDeviceObject * device)895 static int32_t HdfSpiDeviceInit(struct HdfDeviceObject *device)
896 {
897     int32_t ret;
898     struct SpiCntlr *cntlr = NULL;
899 
900     HDF_LOGI("%s: entry", __func__);
901     if (device == NULL) {
902         HDF_LOGE("%s: ptr is null", __func__);
903         return HDF_ERR_INVALID_OBJECT;
904     }
905     cntlr = SpiCntlrFromDevice(device);
906     if (cntlr == NULL) {
907         HDF_LOGE("%s: cntlr is null", __func__);
908         return HDF_FAILURE;
909     }
910 
911     ret = Mp1xxSpiInit(cntlr, device);
912     if (ret != HDF_SUCCESS) {
913         HDF_LOGE("%s: error init", __func__);
914         return HDF_FAILURE;
915     }
916 
917     ret = Mp1xxSpiProbe(cntlr->priv);
918     if (ret != HDF_SUCCESS) {
919         HDF_LOGE("%s: error probe", __func__);
920     }
921     return ret;
922 }
923 
HdfSpiDeviceRelease(struct HdfDeviceObject * device)924 static void HdfSpiDeviceRelease(struct HdfDeviceObject *device)
925 {
926     struct SpiCntlr *cntlr = NULL;
927 
928     HDF_LOGI("%s: entry", __func__);
929     if (device == NULL) {
930         HDF_LOGE("%s: device is null", __func__);
931         return;
932     }
933     cntlr = SpiCntlrFromDevice(device);
934     if (cntlr == NULL) {
935         HDF_LOGE("%s: cntlr is null", __func__);
936         return;
937     }
938     if (cntlr->priv != NULL) {
939         Mp1xxSpiRemove((struct Mp1xxSpiCntlr *)cntlr->priv);
940     }
941     SpiCntlrDestroy(cntlr);
942 }
943 
944 struct HdfDriverEntry g_hdfSpiDevice = {
945     .moduleVersion = 1,
946     .moduleName = "stm32mp1_spi_driver",
947     .Bind = HdfSpiDeviceBind,
948     .Init = HdfSpiDeviceInit,
949     .Release = HdfSpiDeviceRelease,
950 };
951 
952 HDF_INIT(g_hdfSpiDevice);
953