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", ®BasePhy, 0) != HDF_SUCCESS) {
768 HDF_LOGE("%s: read regBase fail", __func__);
769 return HDF_FAILURE;
770 }
771 if (iface->GetUint32(node, "regSize", ®Size, 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