openssl: replace ocf-crypto-headers with a header file from cryptodev-linux
[openwrt/openwrt.git] / target / linux / generic / files / crypto / ocf / kirkwood / mvHal / mv_hal / spi / mvSpi.c
1 /*******************************************************************************
2 Copyright (C) Marvell International Ltd. and its affiliates
3
4 This software file (the "File") is owned and distributed by Marvell
5 International Ltd. and/or its affiliates ("Marvell") under the following
6 alternative licensing terms. Once you have made an election to distribute the
7 File under one of the following license alternatives, please (i) delete this
8 introductory statement regarding license alternatives, (ii) delete the two
9 license alternatives that you have not elected to use and (iii) preserve the
10 Marvell copyright notice above.
11
12 ********************************************************************************
13 Marvell Commercial License Option
14
15 If you received this File from Marvell and you have entered into a commercial
16 license agreement (a "Commercial License") with Marvell, the File is licensed
17 to you under the terms of the applicable Commercial License.
18
19 ********************************************************************************
20 Marvell GPL License Option
21
22 If you received this File from Marvell, you may opt to use, redistribute and/or
23 modify this File in accordance with the terms and conditions of the General
24 Public License Version 2, June 1991 (the "GPL License"), a copy of which is
25 available along with the File in the license.txt file or by writing to the Free
26 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
27 on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
28
29 THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
30 WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
31 DISCLAIMED. The GPL License provides additional details about this warranty
32 disclaimer.
33 ********************************************************************************
34 Marvell BSD License Option
35
36 If you received this File from Marvell, you may opt to use, redistribute and/or
37 modify this File under the following licensing terms.
38 Redistribution and use in source and binary forms, with or without modification,
39 are permitted provided that the following conditions are met:
40
41 * Redistributions of source code must retain the above copyright notice,
42 this list of conditions and the following disclaimer.
43
44 * Redistributions in binary form must reproduce the above copyright
45 notice, this list of conditions and the following disclaimer in the
46 documentation and/or other materials provided with the distribution.
47
48 * Neither the name of Marvell nor the names of its contributors may be
49 used to endorse or promote products derived from this software without
50 specific prior written permission.
51
52 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
53 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
54 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
55 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
56 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
57 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
58 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
59 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
60 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
61 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62
63 *******************************************************************************/
64
65 #include "spi/mvSpi.h"
66 #include "spi/mvSpiSpec.h"
67
68 #include "ctrlEnv/mvCtrlEnvLib.h"
69
70 /* #define MV_DEBUG */
71 #ifdef MV_DEBUG
72 #define DB(x) x
73 #define mvOsPrintf printf
74 #else
75 #define DB(x)
76 #endif
77
78
79 /*******************************************************************************
80 * mvSpi16bitDataTxRx - Transmt and receive data
81 *
82 * DESCRIPTION:
83 * Tx data and block waiting for data to be transmitted
84 *
85 ********************************************************************************/
86 static MV_STATUS mvSpi16bitDataTxRx (MV_U16 txData, MV_U16 * pRxData)
87 {
88 MV_U32 i;
89 MV_BOOL ready = MV_FALSE;
90
91 /* First clear the bit in the interrupt cause register */
92 MV_REG_WRITE(MV_SPI_INT_CAUSE_REG, 0x0);
93
94 /* Transmit data */
95 MV_REG_WRITE(MV_SPI_DATA_OUT_REG, MV_16BIT_LE(txData));
96
97 /* wait with timeout for memory ready */
98 for (i=0; i<MV_SPI_WAIT_RDY_MAX_LOOP; i++)
99 {
100 if (MV_REG_READ(MV_SPI_INT_CAUSE_REG))
101 {
102 ready = MV_TRUE;
103 break;
104 }
105 #ifdef MV_SPI_SLEEP_ON_WAIT
106 mvOsSleep(1);
107 #endif /* MV_SPI_SLEEP_ON_WAIT */
108 }
109
110 if (!ready)
111 return MV_TIMEOUT;
112
113 /* check that the RX data is needed */
114 if (pRxData)
115 {
116 if ((MV_U32)pRxData & 0x1) /* check if address is not alligned to 16bit */
117 {
118 #if defined(MV_CPU_LE)
119 /* perform the data write to the buffer in two stages with 8bit each */
120 MV_U8 * bptr = (MV_U8*)pRxData;
121 MV_U16 data = MV_16BIT_LE(MV_REG_READ(MV_SPI_DATA_IN_REG));
122 *bptr = (data & 0xFF);
123 ++bptr;
124 *bptr = ((data >> 8) & 0xFF);
125
126 #elif defined(MV_CPU_BE)
127
128 /* perform the data write to the buffer in two stages with 8bit each */
129 MV_U8 * bptr = (MV_U8 *)pRxData;
130 MV_U16 data = MV_16BIT_LE(MV_REG_READ(MV_SPI_DATA_IN_REG));
131 *bptr = ((data >> 8) & 0xFF);
132 ++bptr;
133 *bptr = (data & 0xFF);
134
135 #else
136 #error "CPU endianess isn't defined!\n"
137 #endif
138
139 }
140 else
141 *pRxData = MV_16BIT_LE(MV_REG_READ(MV_SPI_DATA_IN_REG));
142 }
143
144 return MV_OK;
145 }
146
147
148 /*******************************************************************************
149 * mvSpi8bitDataTxRx - Transmt and receive data (8bits)
150 *
151 * DESCRIPTION:
152 * Tx data and block waiting for data to be transmitted
153 *
154 ********************************************************************************/
155 static MV_STATUS mvSpi8bitDataTxRx (MV_U8 txData, MV_U8 * pRxData)
156 {
157 MV_U32 i;
158 MV_BOOL ready = MV_FALSE;
159
160 /* First clear the bit in the interrupt cause register */
161 MV_REG_WRITE(MV_SPI_INT_CAUSE_REG, 0x0);
162
163 /* Transmit data */
164 MV_REG_WRITE(MV_SPI_DATA_OUT_REG, txData);
165
166 /* wait with timeout for memory ready */
167 for (i=0; i<MV_SPI_WAIT_RDY_MAX_LOOP; i++)
168 {
169 if (MV_REG_READ(MV_SPI_INT_CAUSE_REG))
170 {
171 ready = MV_TRUE;
172 break;
173 }
174 #ifdef MV_SPI_SLEEP_ON_WAIT
175 mvOsSleep(1);
176 #endif /* MV_SPI_SLEEP_ON_WAIT */
177 }
178
179 if (!ready)
180 return MV_TIMEOUT;
181
182 /* check that the RX data is needed */
183 if (pRxData)
184 *pRxData = MV_REG_READ(MV_SPI_DATA_IN_REG);
185
186 return MV_OK;
187 }
188
189 /*
190 #####################################################################################
191 #####################################################################################
192 */
193
194 /*******************************************************************************
195 * mvSpiInit - Initialize the SPI controller
196 *
197 * DESCRIPTION:
198 * Perform the neccessary initialization in order to be able to send an
199 * receive over the SPI interface.
200 *
201 * INPUT:
202 * serialBaudRate: Baud rate (SPI clock frequency)
203 * use16BitMode: Whether to use 2bytes (MV_TRUE) or 1bytes (MV_FALSE)
204 *
205 * OUTPUT:
206 * None.
207 *
208 * RETURN:
209 * Success or Error code.
210 *
211 *
212 *******************************************************************************/
213 MV_STATUS mvSpiInit (MV_U32 serialBaudRate)
214 {
215 MV_STATUS ret;
216
217 /* Set the serial clock */
218 if ((ret = mvSpiBaudRateSet(serialBaudRate)) != MV_OK)
219 return ret;
220
221 /* For devices in which the SPI is muxed on the MPP with other interfaces*/
222 mvMPPConfigToSPI();
223
224 /* Configure the default SPI mode to be 16bit */
225 MV_REG_BIT_SET(MV_SPI_IF_CONFIG_REG, MV_SPI_BYTE_LENGTH_MASK);
226
227 /* Fix ac timing on SPI in 6183, 6183L and 78x00 only */
228 if ( (mvCtrlModelGet() == MV_6183_DEV_ID) ||
229 (mvCtrlModelGet() == MV_6183L_DEV_ID) ||
230 (mvCtrlModelGet() == MV_78100_DEV_ID) ||
231 (mvCtrlModelGet() == MV_78200_DEV_ID) ||
232 (mvCtrlModelGet() == MV_76100_DEV_ID))
233 MV_REG_BIT_SET(MV_SPI_IF_CONFIG_REG, BIT14);
234
235 /* Verify that the CS is deasserted */
236 mvSpiCsDeassert();
237
238 return MV_OK;
239 }
240
241 /*******************************************************************************
242 * mvSpiBaudRateSet - Set the Frequency of the SPI clock
243 *
244 * DESCRIPTION:
245 * Set the Prescale bits to adapt to the requested baud rate (the clock
246 * used for thr SPI).
247 *
248 * INPUT:
249 * serialBaudRate: Baud rate (SPI clock frequency)
250 *
251 * OUTPUT:
252 * None.
253 *
254 * RETURN:
255 * Success or Error code.
256 *
257 *
258 *******************************************************************************/
259 MV_STATUS mvSpiBaudRateSet (MV_U32 serialBaudRate)
260 {
261 MV_U8 i;
262 /* MV_U8 preScale[32] = {1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
263 2, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30};
264 */
265 MV_U8 preScale[14] = { 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30};
266 MV_U8 bestPrescaleIndx = 100;
267 MV_U32 minBaudOffset = 0xFFFFFFFF;
268 MV_U32 cpuClk = mvBoardTclkGet(); /*mvCpuPclkGet();*/
269 MV_U32 tempReg;
270
271 /* Find the best prescale configuration - less or equal */
272 for (i=0; i<14; i++)
273 {
274 /* check for higher - irrelevent */
275 if ((cpuClk / preScale[i]) > serialBaudRate)
276 continue;
277
278 /* check for exact fit */
279 if ((cpuClk / preScale[i]) == serialBaudRate)
280 {
281 bestPrescaleIndx = i;
282 break;
283 }
284
285 /* check if this is better than the previous one */
286 if ((serialBaudRate - (cpuClk / preScale[i])) < minBaudOffset)
287 {
288 minBaudOffset = (serialBaudRate - (cpuClk / preScale[i]));
289 bestPrescaleIndx = i;
290 }
291 }
292
293 if (bestPrescaleIndx > 14)
294 {
295 mvOsPrintf("%s ERROR: SPI baud rate prescale error!\n", __FUNCTION__);
296 return MV_OUT_OF_RANGE;
297 }
298
299 /* configure the Prescale */
300 tempReg = MV_REG_READ(MV_SPI_IF_CONFIG_REG);
301 tempReg = ((tempReg & ~MV_SPI_CLK_PRESCALE_MASK) | (bestPrescaleIndx + 0x12));
302 MV_REG_WRITE(MV_SPI_IF_CONFIG_REG, tempReg);
303
304 return MV_OK;
305 }
306
307 /*******************************************************************************
308 * mvSpiCsAssert - Assert the Chip Select pin indicating a new transfer
309 *
310 * DESCRIPTION:
311 * Assert The chip select - used to select an external SPI device
312 *
313 * INPUT:
314 * None.
315 *
316 * OUTPUT:
317 * None.
318 *
319 * RETURN:
320 * Success or Error code.
321 *
322 ********************************************************************************/
323 MV_VOID mvSpiCsAssert(MV_VOID)
324 {
325 /* For devices in which the SPI is muxed on the MPP with other interfaces*/
326 mvMPPConfigToSPI();
327 mvOsUDelay(1);
328 MV_REG_BIT_SET(MV_SPI_IF_CTRL_REG, MV_SPI_CS_ENABLE_MASK);
329 }
330
331 /*******************************************************************************
332 * mvSpiCsDeassert - DeAssert the Chip Select pin indicating the end of a
333 * SPI transfer sequence
334 *
335 * DESCRIPTION:
336 * DeAssert the chip select pin
337 *
338 * INPUT:
339 * None.
340 *
341 * OUTPUT:
342 * None.
343 *
344 * RETURN:
345 * Success or Error code.
346 *
347 ********************************************************************************/
348 MV_VOID mvSpiCsDeassert(MV_VOID)
349 {
350 MV_REG_BIT_RESET(MV_SPI_IF_CTRL_REG, MV_SPI_CS_ENABLE_MASK);
351
352 /* For devices in which the SPI is muxed on the MPP with other interfaces*/
353 mvMPPConfigToDefault();
354 }
355
356 /*******************************************************************************
357 * mvSpiRead - Read a buffer over the SPI interface
358 *
359 * DESCRIPTION:
360 * Receive (read) a buffer over the SPI interface in 16bit chunks. If the
361 * buffer size is odd, then the last chunk will be 8bits. Chip select is not
362 * handled at this level.
363 *
364 * INPUT:
365 * pRxBuff: Pointer to the buffer to hold the received data
366 * buffSize: length of the pRxBuff
367 *
368 * OUTPUT:
369 * pRxBuff: Pointer to the buffer with the received data
370 *
371 * RETURN:
372 * Success or Error code.
373 *
374 *
375 *******************************************************************************/
376 MV_STATUS mvSpiRead (MV_U8* pRxBuff, MV_U32 buffSize)
377 {
378 MV_STATUS ret;
379 MV_U32 bytesLeft = buffSize;
380 MV_U16* rxPtr = (MV_U16*)pRxBuff;
381
382 /* check for null parameters */
383 if (pRxBuff == NULL)
384 {
385 mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
386 return MV_BAD_PARAM;
387 }
388
389 /* Check that the buffer pointer and the buffer size are 16bit aligned */
390 if ((((MV_U32)buffSize & 1) == 0) && (((MV_U32)pRxBuff & 1) == 0))
391 {
392 /* Verify that the SPI mode is in 16bit mode */
393 MV_REG_BIT_SET(MV_SPI_IF_CONFIG_REG, MV_SPI_BYTE_LENGTH_MASK);
394
395 /* TX/RX as long we have complete 16bit chunks */
396 while (bytesLeft >= MV_SPI_16_BIT_CHUNK_SIZE)
397 {
398 /* Transmitted and wait for the transfer to be completed */
399 if ((ret = mvSpi16bitDataTxRx(MV_SPI_DUMMY_WRITE_16BITS, rxPtr)) != MV_OK)
400 return ret;
401
402 /* increment the pointers */
403 rxPtr++;
404 bytesLeft -= MV_SPI_16_BIT_CHUNK_SIZE;
405 }
406
407 }
408 else
409 {
410 /* Verify that the SPI mode is in 8bit mode */
411 MV_REG_BIT_RESET(MV_SPI_IF_CONFIG_REG, MV_SPI_BYTE_LENGTH_MASK);
412
413 /* TX/RX in 8bit chanks */
414 while (bytesLeft > 0)
415 {
416 /* Transmitted and wait for the transfer to be completed */
417 if ((ret = mvSpi8bitDataTxRx(MV_SPI_DUMMY_WRITE_8BITS, pRxBuff)) != MV_OK)
418 return ret;
419 /* increment the pointers */
420 pRxBuff++;
421 bytesLeft--;
422 }
423 }
424
425 return MV_OK;
426 }
427
428 /*******************************************************************************
429 * mvSpiWrite - Transmit a buffer over the SPI interface
430 *
431 * DESCRIPTION:
432 * Transmit a buffer over the SPI interface in 16bit chunks. If the
433 * buffer size is odd, then the last chunk will be 8bits. No chip select
434 * action is taken.
435 *
436 * INPUT:
437 * pTxBuff: Pointer to the buffer holding the TX data
438 * buffSize: length of the pTxBuff
439 *
440 * OUTPUT:
441 * None.
442 *
443 * RETURN:
444 * Success or Error code.
445 *
446 *
447 *******************************************************************************/
448 MV_STATUS mvSpiWrite(MV_U8* pTxBuff, MV_U32 buffSize)
449 {
450 MV_STATUS ret;
451 MV_U32 bytesLeft = buffSize;
452 MV_U16* txPtr = (MV_U16*)pTxBuff;
453
454 /* check for null parameters */
455 if (pTxBuff == NULL)
456 {
457 mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
458 return MV_BAD_PARAM;
459 }
460
461 /* Check that the buffer pointer and the buffer size are 16bit aligned */
462 if ((((MV_U32)buffSize & 1) == 0) && (((MV_U32)pTxBuff & 1) == 0))
463 {
464 /* Verify that the SPI mode is in 16bit mode */
465 MV_REG_BIT_SET(MV_SPI_IF_CONFIG_REG, MV_SPI_BYTE_LENGTH_MASK);
466
467 /* TX/RX as long we have complete 16bit chunks */
468 while (bytesLeft >= MV_SPI_16_BIT_CHUNK_SIZE)
469 {
470 /* Transmitted and wait for the transfer to be completed */
471 if ((ret = mvSpi16bitDataTxRx(*txPtr, NULL)) != MV_OK)
472 return ret;
473
474 /* increment the pointers */
475 txPtr++;
476 bytesLeft -= MV_SPI_16_BIT_CHUNK_SIZE;
477 }
478 }
479 else
480 {
481
482 /* Verify that the SPI mode is in 8bit mode */
483 MV_REG_BIT_RESET(MV_SPI_IF_CONFIG_REG, MV_SPI_BYTE_LENGTH_MASK);
484
485 /* TX/RX in 8bit chanks */
486 while (bytesLeft > 0)
487 {
488 /* Transmitted and wait for the transfer to be completed */
489 if ((ret = mvSpi8bitDataTxRx(*pTxBuff, NULL)) != MV_OK)
490 return ret;
491
492 /* increment the pointers */
493 pTxBuff++;
494 bytesLeft--;
495 }
496 }
497
498 return MV_OK;
499 }
500
501
502 /*******************************************************************************
503 * mvSpiReadWrite - Read and Write a buffer simultanuosely
504 *
505 * DESCRIPTION:
506 * Transmit and receive a buffer over the SPI in 16bit chunks. If the
507 * buffer size is odd, then the last chunk will be 8bits. The SPI chip
508 * select is not handled implicitely.
509 *
510 * INPUT:
511 * pRxBuff: Pointer to the buffer to write the RX info in
512 * pTxBuff: Pointer to the buffer holding the TX info
513 * buffSize: length of both the pTxBuff and pRxBuff
514 *
515 * OUTPUT:
516 * pRxBuff: Pointer of the buffer holding the RX data
517 *
518 * RETURN:
519 * Success or Error code.
520 *
521 *
522 *******************************************************************************/
523 MV_STATUS mvSpiReadWrite(MV_U8* pRxBuff, MV_U8* pTxBuff, MV_U32 buffSize)
524 {
525 MV_STATUS ret;
526 MV_U32 bytesLeft = buffSize;
527 MV_U16* txPtr = (MV_U16*)pTxBuff;
528 MV_U16* rxPtr = (MV_U16*)pRxBuff;
529
530 /* check for null parameters */
531 if ((pRxBuff == NULL) || (pTxBuff == NULL))
532 {
533 mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
534 return MV_BAD_PARAM;
535 }
536
537 /* Check that the buffer pointer and the buffer size are 16bit aligned */
538 if ((((MV_U32)buffSize & 1) == 0) && (((MV_U32)pTxBuff & 1) == 0) && (((MV_U32)pRxBuff & 1) == 0))
539 {
540 /* Verify that the SPI mode is in 16bit mode */
541 MV_REG_BIT_SET(MV_SPI_IF_CONFIG_REG, MV_SPI_BYTE_LENGTH_MASK);
542
543 /* TX/RX as long we have complete 16bit chunks */
544 while (bytesLeft >= MV_SPI_16_BIT_CHUNK_SIZE)
545 {
546 /* Transmitted and wait for the transfer to be completed */
547 if ((ret = mvSpi16bitDataTxRx(*txPtr, rxPtr)) != MV_OK)
548 return ret;
549
550 /* increment the pointers */
551 txPtr++;
552 rxPtr++;
553 bytesLeft -= MV_SPI_16_BIT_CHUNK_SIZE;
554 }
555 }
556 else
557 {
558 /* Verify that the SPI mode is in 8bit mode */
559 MV_REG_BIT_RESET(MV_SPI_IF_CONFIG_REG, MV_SPI_BYTE_LENGTH_MASK);
560
561 /* TX/RX in 8bit chanks */
562 while (bytesLeft > 0)
563 {
564 /* Transmitted and wait for the transfer to be completed */
565 if ( (ret = mvSpi8bitDataTxRx(*pTxBuff, pRxBuff) ) != MV_OK)
566 return ret;
567 pRxBuff++;
568 pTxBuff++;
569 bytesLeft--;
570 }
571 }
572
573 return MV_OK;
574 }
575
576