[processor-sdk/performance-audio-sr.git] / psdk_cust / pdk_k2g_1_0_1_1_eng / packages / ti / board / src / flash / platform_flash / evmc66x_spi.c
1 /*
2 * Copyright (c) 2011-2015, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
34 /**
35 *
36 * \file evmc66x_spi.c
37 *
38 * \brief This file implements SPI driver for the NOR flash
39 *
40 *****************************************************************************/
42 /************************
43 * Include Files
44 ************************/
45 #include "platform_internal.h"
48 static uint32_t data1_reg_val;
49 static uint32_t spi_base_addr [CSL_SPI_CNT] = {CSL_SPI_0_SLV_REGS,
50 CSL_SPI_1_SLV_REGS,
51 CSL_SPI_2_SLV_REGS,
52 CSL_SPI_3_SLV_REGS};
54 static void
55 spi_delay
56 (
57 uint32_t delay
58 )
59 {
60 volatile uint32_t i;
62 for ( i = 0 ; i < delay ; i++ ){ };
63 }
66 /******************************************************************************
67 *
68 * Function: spi_claim
69 *
70 * Description: This function claims the SPI bus in the SPI controller
71 *
72 * Parameters: uint8_t spiportnumber - spi port number
73 * Uint32 cs - Chip Select number for the slave SPI device
74 * Uint32 freq - SPI clock frequency
75 *
76 * Return Value: error status
77 *
78 ******************************************************************************/
79 SPI_STATUS
80 spi_claim
81 (
82 uint8_t spiportnumber,
83 uint32_t cs,
84 uint32_t freq
86 )
87 {
88 uint32_t scalar;
90 PLIBSPILOCK()
92 /* Enable the SPI hardware */
93 SPI_SPIGCR0 = CSL_SPI_SPIGCR0_RESET_IN_RESET;
94 spi_delay (2000);
95 SPI_SPIGCR0 = CSL_SPI_SPIGCR0_RESET_OUT_OF_RESET;
97 /* Set master mode, powered up and not activated */
98 SPI_SPIGCR1 = (CSL_SPI_SPIGCR1_MASTER_MASTER << CSL_SPI_SPIGCR1_MASTER_SHIFT) |
99 (CSL_SPI_SPIGCR1_CLKMOD_INTERNAL << CSL_SPI_SPIGCR1_CLKMOD_SHIFT);
102 /* CS0, CS1, CLK, Slave in and Slave out are functional pins */
103 if (cs == 0) {
104 SPI_SPIPC0 = (CSL_SPI_SPIPC0_SCS0FUN0_SPI << CSL_SPI_SPIPC0_SCS0FUN0_SHIFT) |
105 (CSL_SPI_SPIPC0_CLKFUN_SPI << CSL_SPI_SPIPC0_CLKFUN_SHIFT) |
106 (CSL_SPI_SPIPC0_SIMOFUN_SPI << CSL_SPI_SPIPC0_SIMOFUN_SHIFT) |
107 (CSL_SPI_SPIPC0_SOMIFUN_SPI << CSL_SPI_SPIPC0_SOMIFUN_SHIFT);
108 } else if (cs == 1) {
109 SPI_SPIPC0 = ((CSL_SPI_SPIPC0_SCS0FUN1_SPI << CSL_SPI_SPIPC0_SCS0FUN1_SHIFT) |
110 (CSL_SPI_SPIPC0_CLKFUN_SPI << CSL_SPI_SPIPC0_CLKFUN_SHIFT) |
111 (CSL_SPI_SPIPC0_SIMOFUN_SPI << CSL_SPI_SPIPC0_SIMOFUN_SHIFT) |
112 (CSL_SPI_SPIPC0_SOMIFUN_SPI << CSL_SPI_SPIPC0_SOMIFUN_SHIFT)) & 0xFFFF;
113 }
115 /* setup format */
116 scalar = ((SPI_MODULE_CLK / freq) - 1 ) & 0xFF;
118 if ( cs == 0) {
119 SPI_SPIFMT0 = (8 << CSL_SPI_SPIFMT_CHARLEN_SHIFT) |
120 (scalar << CSL_SPI_SPIFMT_PRESCALE_SHIFT) |
121 (CSL_SPI_SPIFMT_PHASE_DELAY << CSL_SPI_SPIFMT_PHASE_SHIFT) |
122 (CSL_SPI_SPIFMT_POLARITY_LOW << CSL_SPI_SPIFMT_POLARITY_SHIFT) |
123 (CSL_SPI_SPIFMT_SHIFTDIR_MSB << CSL_SPI_SPIFMT_SHIFTDIR_SHIFT);
124 }else if ( cs == 1) {
125 SPI_SPIFMT0 = (16 << CSL_SPI_SPIFMT_CHARLEN_SHIFT) |
126 (scalar << CSL_SPI_SPIFMT_PRESCALE_SHIFT) |
127 (CSL_SPI_SPIFMT_PHASE_DELAY << CSL_SPI_SPIFMT_PHASE_SHIFT) |
128 (CSL_SPI_SPIFMT_POLARITY_LOW << CSL_SPI_SPIFMT_POLARITY_SHIFT) |
129 (CSL_SPI_SPIFMT_SHIFTDIR_MSB << CSL_SPI_SPIFMT_SHIFTDIR_SHIFT);
130 }
132 /* hold cs active at end of transfer until explicitly de-asserted */
133 data1_reg_val = (CSL_SPI_SPIDAT1_CSHOLD_ENABLE << CSL_SPI_SPIDAT1_CSHOLD_SHIFT) |
134 (0x02 << CSL_SPI_SPIDAT1_CSNR_SHIFT);
135 if (cs == 0) {
136 SPI_SPIDAT1 = (CSL_SPI_SPIDAT1_CSHOLD_ENABLE << CSL_SPI_SPIDAT1_CSHOLD_SHIFT) |
137 (0x02 << CSL_SPI_SPIDAT1_CSNR_SHIFT);
138 }
140 /* including a minor delay. No science here. Should be good even with
141 * no delay
142 */
143 if (cs == 0) {
144 SPI_SPIDELAY = (8 << CSL_SPI_SPIDELAY_C2TDELAY_SHIFT) |
145 (8 << CSL_SPI_SPIDELAY_T2CDELAY_SHIFT);
146 /* default chip select register */
147 SPI_SPIDEF = CSL_SPI_SPIDEF_RESETVAL;
148 } else if (cs == 1) {
149 SPI_SPIDELAY = (6 << CSL_SPI_SPIDELAY_C2TDELAY_SHIFT) |
150 (3 << CSL_SPI_SPIDELAY_T2CDELAY_SHIFT);
151 }
153 /* no interrupts */
154 SPI_SPIINT0 = CSL_SPI_SPIINT0_RESETVAL;
155 SPI_SPILVL = CSL_SPI_SPILVL_RESETVAL;
157 /* enable SPI */
158 SPI_SPIGCR1 |= ( CSL_SPI_SPIGCR1_ENABLE_ENABLE << CSL_SPI_SPIGCR1_ENABLE_SHIFT );
160 return SPI_EOK;
161 }
163 /******************************************************************************
164 *
165 * Function: spi_release
166 *
167 * Description: This function releases the bus in SPI controller
168 *
169 * Parameters: uint8_t spiportnumber - spi port number
170 *
171 * Return Value: None
172 *
173 ******************************************************************************/
174 void
175 spi_release
176 (
177 uint8_t spiportnumber
178 )
179 {
180 /* Disable the SPI hardware */
181 SPI_SPIGCR1 = CSL_SPI_SPIGCR1_RESETVAL;
183 PLIBSPIRELEASE()
184 }
186 /******************************************************************************
187 *
188 * Function: spi_xfer
189 *
190 * Description: This function sends and receives 8-bit data serially
191 *
192 * Parameters: uint8_t spiportnumber - spi port number
193 * uint32_t nbytes - Number of bytes of the TX data
194 * uint8_t* data_out - Pointer to the TX data
195 * uint8_t* data_in - Pointer to the RX data
196 * Bool terminate - TRUE: terminate the transfer, release the CS
197 * FALSE: hold the CS
198 *
199 * Return Value: error status
200 *
201 ******************************************************************************/
202 SPI_STATUS
203 spi_xfer
204 (
205 uint8_t spiportnumber,
206 uint32_t nbytes,
207 uint8_t* data_out,
208 uint8_t* data_in,
209 Bool terminate
211 )
212 {
213 uint32_t i, buf_reg;
214 uint8_t* tx_ptr = data_out;
215 uint8_t* rx_ptr = data_in;
218 /* Clear out any pending read data */
219 SPI_SPIBUF;
221 for (i = 0; i < nbytes; i++)
222 {
223 /* Wait untill TX buffer is not full */
224 while( SPI_SPIBUF & CSL_SPI_SPIBUF_TXFULL_MASK );
226 /* Set the TX data to SPIDAT1 */
227 data1_reg_val &= ~0xFFFF;
228 if(tx_ptr)
229 {
230 data1_reg_val |= *tx_ptr & 0xFF;
231 tx_ptr++;
232 }
234 /* Write to SPIDAT1 */
235 if((i == (nbytes -1)) && (terminate))
236 {
237 /* Release the CS at the end of the transfer when terminate flag is TRUE */
238 SPI_SPIDAT1 = data1_reg_val & ~(CSL_SPI_SPIDAT1_CSHOLD_ENABLE << CSL_SPI_SPIDAT1_CSHOLD_SHIFT);
239 } else
240 {
241 SPI_SPIDAT1 = data1_reg_val;
242 }
245 /* Read SPIBUF, wait untill the RX buffer is not empty */
246 while ( SPI_SPIBUF & ( CSL_SPI_SPIBUF_RXEMPTY_MASK ) );
248 /* Read one byte data */
249 buf_reg = SPI_SPIBUF;
250 if(rx_ptr)
251 {
252 *rx_ptr = buf_reg & 0xFF;
253 rx_ptr++;
254 }
255 }
257 return SPI_EOK;
259 }
262 /******************************************************************************
263 *
264 * Function: spi_cmd
265 *
266 * Description: This function sends a single byte command and receives response data
267 *
268 * Parameters: uint8_t spiportnumber - spi port number
269 * uint8_t cmd - Command sent to the NOR flash
270 * uint8_t* response - Pointer to the RX response data
271 * uint32_t len - Lenght of the response in bytes
272 *
273 * Return Value: error status
274 *
275 ******************************************************************************/
276 SPI_STATUS
277 spi_cmd
278 (
279 uint8_t spiportnumber,
280 uint8_t cmd,
281 uint8_t* response,
282 uint32_t len
284 )
285 {
286 Bool flags = FALSE;
287 uint32_t ret;
289 if (len == 0)
290 {
291 flags = TRUE;
292 }
294 /* Send the command byte */
295 ret = spi_xfer(spiportnumber,1, &cmd, NULL, flags);
296 if (ret)
297 {
298 IFPRINT (platform_write("SF: Failed to send command %02x: %d\n", cmd, ret));
299 return ret;
300 }
302 /* Receive the response */
303 if (len)
304 {
305 ret = spi_xfer(spiportnumber,len, NULL, response, TRUE);
306 if (ret)
307 {
308 IFPRINT (platform_write("SF: Failed to read response (%zu bytes): %d\n", len, ret));
309 }
310 }
312 return ret;
313 }
315 /******************************************************************************
316 *
317 * Function: spi_cmd_read
318 *
319 * Description: This function sends a read command and reads data from the flash
320 *
321 * Parameters: uint8_t spiportnumber - spi port number
322 * uint8_t cmd - Command sent to the NOR flash
323 * uint32_t cmd_len - Length of the command in bytes
324 * uint8_t* dat - Pointer to the data read
325 * uint32_t data_len - Lenght of the data read in bytes
326 *
327 * Return Value: error status
328 *
329 ******************************************************************************/
330 SPI_STATUS
331 spi_cmd_read
332 (
333 uint8_t spiportnumber,
334 uint8_t* cmd,
335 uint32_t cmd_len,
336 uint8_t* data,
337 uint32_t data_len
339 )
340 {
341 Bool flags = FALSE;
342 uint32_t ret;
344 if (data_len == 0)
345 {
346 flags = TRUE;
347 }
349 /* Send read command */
350 ret = spi_xfer(spiportnumber,cmd_len, cmd, NULL, flags);
351 if (ret)
352 {
353 IFPRINT (platform_write("SF: Failed to send read command (%zu bytes): %d\n",
354 cmd_len, ret));
355 }
356 else if (data_len != 0)
357 {
358 /* Read data */
359 ret = spi_xfer(spiportnumber,data_len, NULL, data, TRUE);
360 if (ret)
361 {
362 IFPRINT (platform_write("SF: Failed to read %zu bytes of data: %d\n",
363 data_len, ret));
364 }
365 }
367 return ret;
368 }
370 /******************************************************************************
371 *
372 * Function: spi_cmd_write
373 *
374 * Description: This function sends a write command and writes data to the flash
375 *
376 * Parameters: uint8_t spiportnumber - spi port number
377 * uint8_t cmd - Command sent to the NOR flash
378 * uint32_t cmd_len - Length of the command in bytes
379 * uint8_t* dat - Pointer to the data to be written
380 * uint32_t data_len - Lenght of the data in bytes
381 *
382 * Return Value: error status
383 *
384 ******************************************************************************/
385 SPI_STATUS
386 spi_cmd_write
387 (
388 uint8_t spiportnumber,
389 uint8_t* cmd,
390 uint32_t cmd_len,
391 uint8_t* data,
392 uint32_t data_len
394 )
395 {
396 Bool flags = FALSE;
397 uint32_t ret;
399 if (data_len == 0)
400 {
401 flags = TRUE;
402 }
404 /* Send write command */
405 ret = spi_xfer(spiportnumber,cmd_len, cmd, NULL, flags);
406 if (ret)
407 {
408 IFPRINT (platform_write("SF: Failed to send write command (%zu bytes): %d\n",
409 cmd_len, ret));
410 }
411 else if (data_len != 0)
412 {
413 /* Write data */
414 ret = spi_xfer(spiportnumber,data_len, data, NULL, TRUE);
415 if (ret)
416 {
417 IFPRINT (platform_write("SF: Failed to write %zu bytes of data: %d\n",
418 data_len, ret));
419 }
420 }
422 return ret;
423 }
426 /******************************************************************************
427 *
428 * Function: spi_read_word
429 *
430 * Description: This function sends a read command and reads data in 16-bit data format
431 *
432 * Parameters: uint8_t spiportnumber - spi port number
433 * uint16_t* cmd_buf - Pointer to the command sent
434 * uint32_t cmd_len - Length of the command in words
435 * uint16_t* data_buf - Pointer to the data read
436 * uint32_t data_len - Lenght of the data read in words
437 *
438 * Return Value: error status
439 *
440 ******************************************************************************/
441 SPI_STATUS
442 spi_read_word
443 (
444 uint8_t spiportnumber,
445 uint16_t* cmd_buf,
446 uint32_t cmd_len,
447 uint16_t* data_buf,
448 uint32_t data_len
450 )
451 {
452 uint32_t data1_reg;
453 uint16_t* tx_ptr = cmd_buf;
454 uint16_t* rx_ptr = data_buf;
456 /* disable the SPI communication by setting
457 * the SPIGCR1.ENABLE to 0
458 *
459 *
460 * SPIGCR1
461 * ============================================
462 * Bit Field Value Description
463 * 24 ENABLE 0 SPI disable
464 * ============================================
465 */
466 data1_reg = 0x1 << 24;
467 data1_reg = ~data1_reg;
468 SPI_SPIGCR1 &= data1_reg;
470 /*
471 * clean TX data into SPIDAT0
472 *
473 * SPIDAT0
474 * ============================================
475 * Bit Field Value Description
476 * 15-0 TXDATA 0-FFFFh SPI transmit data
477 * ============================================
478 *
479 */
481 SPI_SPIDAT0 = 0;
483 /* 8.
484 * Enable the SPI communication by setting
485 * the SPIGCR1.ENABLE to 1
486 *
487 *
488 * SPIGCR1
489 * ============================================
490 * Bit Field Value Description
491 * 24 ENABLE 1 SPI enable
492 * ============================================
493 */
495 data1_reg = 0x1 << 24;
496 SPI_SPIGCR1 = (SPI_SPIGCR1 | data1_reg);
498 {
499 {
500 SPI_SPIDAT0 = *tx_ptr;
501 spi_delay(10000);
502 }
504 /* Read SPIFLG, wait untill the RX full interrupt */
505 if ( (SPI_SPIFLG & (CSL_SPI_SPIFLG_RXINTFLG_FULL<<CSL_SPI_SPIFLG_RXINTFLG_SHIFT)) ) {
506 /* Read one byte data */
507 *rx_ptr = SPI_SPIBUF & 0xFF;
508 SPI_SPIBUF = 0;
509 }
510 else {
511 return SPI_EFAIL;
512 }
514 }
516 return SPI_EOK;
518 }
520 /******************************************************************************
521 *
522 * Function: spi_write_word
523 *
524 * Description: This function sends a write command and writes data in 16-bit data format
525 *
526 * Parameters: uint8_t spiportnumber - spi port number
527 * uint16_t* cmd_buf - Pointer to the command sent
528 * uint32_t cmd_len - Length of the command in bytes
529 * uint16_t* data_buf - Pointer to the data read
530 * uint32_t data_len - Lenght of the data read in bytes
531 *
532 * Return Value: error status
533 *
534 ******************************************************************************/
535 SPI_STATUS
536 spi_write_word
537 (
538 uint8_t spiportnumber,
539 uint16_t* cmd_buf,
540 uint32_t cmd_len,
541 uint16_t* data_buf,
542 uint32_t data_len
544 )
545 {
546 uint32_t data1_reg;
547 uint16_t* tx_ptr = cmd_buf;
549 /* disable the SPI communication by setting
550 * the SPIGCR1.ENABLE to 0
551 *
552 *
553 * SPIGCR1
554 * ============================================
555 * Bit Field Value Description
556 * 24 ENABLE 0 SPI disable
557 * ============================================
558 */
559 data1_reg = 0x1 << 24;
560 data1_reg = ~data1_reg;
561 SPI_SPIGCR1 &= data1_reg;
563 /*
564 * clean TX data into SPIDAT0
565 *
566 * SPIDAT0
567 * ============================================
568 * Bit Field Value Description
569 * 15-0 TXDATA 0-FFFFh SPI transmit data
570 * ============================================
571 *
572 */
574 SPI_SPIDAT0 = 0;
576 /* 8.
577 * Enable the SPI communication by setting
578 * the SPIGCR1.ENABLE to 1
579 *
580 *
581 * SPIGCR1
582 * ============================================
583 * Bit Field Value Description
584 * 24 ENABLE 1 SPI enable
585 * ============================================
586 */
588 data1_reg = 0x1 << 24;
589 SPI_SPIGCR1 = (SPI_SPIGCR1 | data1_reg);
591 {
592 {
593 SPI_SPIDAT0 = *tx_ptr;
594 spi_delay(10000);
595 }
597 /* Read SPIFLG, wait untill the RX full interrupt */
598 if ( (SPI_SPIFLG & (CSL_SPI_SPIFLG_TXINTFLG_EMPTY<<CSL_SPI_SPIFLG_TXINTFLG_SHIFT)) ) {
599 /* Clear the SPIBUF */
600 SPI_SPIBUF = 0;
601 return SPI_EOK;
602 }
603 else {
604 return SPI_EFAIL;
605 }
607 }
608 }