[processor-sdk/performance-audio-sr.git] / psdk_cust / pdk_k2g_1_0_1_1_eng / packages / ti / boot / writer / qspi_flash / src / qspiflashwriter.c
1 /*
2 * Copyright (c) 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 * FILE PURPOSE: QSPI Flash writer utility
36 **************************************************************************************
37 * FILE NAME: qspiflashwriter.c
38 *
39 * DESCRIPTION: A simple flash writer using platform lib APIs to program the
40 * QSPI flash with an image that the ibl can read.
41 *
42 ***************************************************************************************/
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <string.h>
46 #include "platform.h"
47 #include "types.h"
49 /* QSPI flash writer utility version */
50 char version[] = "01.00.00.00";
52 /* The input file name is hard coded */
53 char *input_file = "qspi_flash_writer_input.txt";
55 uint32_t swap_byte = 0;
57 /* Parameters defined in the input_file */
58 #define FILE_NAME "file_name"
59 #define START_ADDR "start_addr"
61 /* Memory address to store the write data */
62 #define WRITE_DATA_ADDRESS 0x80000000
63 #define QSPI_FLASH_SIZE (64 * 1024 * 1024)
65 /******************************************************************************
66 * Structure: QSPI_FLASH_WRITER_INFO_T
67 *
68 * QSPI Flash writer control data. This structure should be
69 * filled in by the user before running
70 ******************************************************************************/
71 #define MAX_LINE_LENGTH 40
72 typedef struct QSPI_FLASH_WRITER_INFO_tag
73 {
74 char file_name[MAX_LINE_LENGTH]; /* CCS format data file name */
75 uint32_t filesize; /* Number of bytes to be written into the device */
76 uint32_t blockSizeBytes; /* The size of each sector */
77 uint32_t deviceTotalBytes; /* Total number of bytes available in the device */
78 uint32_t startAddr; /* Start address to write */
79 uint32_t writeBytes; /* Number of bytes to be written into the device */
80 uint8_t *writeData; /* Address to store the write data */
81 uint8_t *readData; /* Address to store the read data */
83 } QSPI_FLASH_WRITER_INFO_T;
85 QSPI_FLASH_WRITER_INFO_T qspiFlashWriterInfo;
87 /* OSAL functions for Platform Library */
88 uint8_t *Osal_platformMalloc (uint32_t num_bytes, uint32_t alignment)
89 {
90 return malloc(num_bytes);
91 }
93 void Osal_platformFree (uint8_t *dataPtr, uint32_t num_bytes)
94 {
95 /* Free up the memory */
96 if (dataPtr)
97 {
98 free(dataPtr);
99 }
100 }
102 void Osal_platformSpiCsEnter(void)
103 {
104 return;
105 }
107 void Osal_platformSpiCsExit (void)
108 {
109 return;
110 }
112 /******************************************************************************
113 * Function: print_platform_errno
114 ******************************************************************************/
115 void
116 print_platform_errno
117 (
118 void
119 )
120 {
121 printf ("Returned platform error number is %d\n", platform_errno);
122 }
124 /******************************************************************************
125 * Function: formBlock
126 *
127 * Form a block of data to write to the QSPI flash. The block is
128 * created as a byte stream from the 4 byte stream in which
129 * the MSB is always sent first.
130 ******************************************************************************/
131 void
132 formBlock
133 (
134 uint32_t *data,
135 uint32_t blockSize,
136 uint8_t *scratch
137 )
138 {
139 uint32_t i, j;
141 /* Convert the data to a byte stream */
142 for (i = j = 0; j < blockSize; i++, j+=4)
143 {
144 scratch[j+0] = (data[i] >> 24) & 0xff;
145 scratch[j+1] = (data[i] >> 16) & 0xff;
146 scratch[j+2] = (data[i] >> 8) & 0xff;
147 scratch[j+3] = (data[i] >> 0) & 0xff;
148 }
149 }
151 /******************************************************************************
152 * Function: write_qspi_flash
153 *
154 * Write the image to flash.
155 * Returns TRUE if the image is written successfully
156 * FALSE if the image write fails
157 ******************************************************************************/
158 Bool
159 write_qspi_flash
160 (
161 PLATFORM_DEVICE_info *p_device
162 )
163 {
164 uint32_t wPos, wLen;
165 uint32_t block, start_block;
166 uint8_t *scrach_block;
168 if (swap_byte)
169 {
170 scrach_block = malloc(qspiFlashWriterInfo.blockSizeBytes);
171 if (scrach_block == NULL)
172 {
173 printf ("Can not allocate scratch block memory!\n");
174 return (FALSE);
175 }
176 }
178 start_block = qspiFlashWriterInfo.startAddr / qspiFlashWriterInfo.blockSizeBytes;
180 for (block = start_block, wPos = 0; wPos < qspiFlashWriterInfo.filesize; block++, wPos += qspiFlashWriterInfo.blockSizeBytes)
181 {
182 printf ("Erasing sector %d \n", block);
183 if (platform_device_erase_block (p_device->handle, block))
184 {
185 printf ("platform_device_erase_block sector # %d failed!\n", start_block);
186 print_platform_errno();
187 if (swap_byte) free (scrach_block);
188 return (FALSE);
189 }
190 }
191 /* Program the QSPI flash */
192 for (block = start_block, wPos = 0; wPos < qspiFlashWriterInfo.writeBytes; block++, wPos += qspiFlashWriterInfo.blockSizeBytes)
193 {
194 printf ("Flashing sector %d (%d bytes of %d)\n", block, wPos, qspiFlashWriterInfo.writeBytes);
196 wLen = qspiFlashWriterInfo.blockSizeBytes;
197 if ((qspiFlashWriterInfo.filesize - wPos) < qspiFlashWriterInfo.blockSizeBytes)
198 {
199 wLen = (qspiFlashWriterInfo.filesize - wPos);
200 }
202 if (swap_byte)
203 {
204 formBlock((uint32_t *)(&qspiFlashWriterInfo.writeData[wPos]), wLen, scrach_block);
205 }
206 else
207 {
208 scrach_block = &qspiFlashWriterInfo.writeData[wPos];
209 }
211 if (platform_device_write(p_device->handle,
212 (block * qspiFlashWriterInfo.blockSizeBytes),
213 scrach_block,
214 wLen) != Platform_EOK)
215 {
216 printf ("platform_device_write sector # %d failed!\n", block);
217 print_platform_errno();
218 if (swap_byte) free (scrach_block);
219 return (FALSE);
220 }
221 }
223 if (swap_byte) free (scrach_block);
224 return (TRUE);
225 }
227 /******************************************************************************
228 * Function: flash_verify
229 *
230 * Read back the data file that was just flashed.
231 * Returns TRUE if the image verified correctly.
232 * FALSE if the image verification failed
233 ******************************************************************************/
234 Bool
235 flash_verify
236 (
237 PLATFORM_DEVICE_info *p_device
238 )
239 {
240 uint32_t rPos, rLen;
241 uint32_t i, j;
242 uint32_t block, start_block;
243 uint8_t *scrach_block;
244 uint32_t *read_data_w;
246 if (swap_byte)
247 {
248 scrach_block = malloc(qspiFlashWriterInfo.blockSizeBytes);
249 if (scrach_block == NULL)
250 {
251 printf ("Can not allocate scratch block memory!\n");
252 return (FALSE);
253 }
254 }
256 start_block = qspiFlashWriterInfo.startAddr / qspiFlashWriterInfo.blockSizeBytes;
258 for (block = start_block, rPos = 0; rPos < qspiFlashWriterInfo.writeBytes; block++, rPos += qspiFlashWriterInfo.blockSizeBytes)
259 {
260 printf ("Reading and verifying sector %d (%d bytes of %d)\n", block, rPos, qspiFlashWriterInfo.writeBytes);
262 if (!swap_byte)
263 {
264 scrach_block = &qspiFlashWriterInfo.readData[rPos];
266 }
268 /* Read a sector of data */
269 if(platform_device_read(p_device->handle,
270 (block * qspiFlashWriterInfo.blockSizeBytes),
271 scrach_block,
272 qspiFlashWriterInfo.blockSizeBytes) != Platform_EOK)
273 {
274 printf ("Failure in sector %d\n", block);
275 print_platform_errno();
276 if (swap_byte) free (scrach_block);
277 return (FALSE);
278 }
280 /* Convert the packed data */
281 if (swap_byte)
282 {
283 read_data_w = (uint32_t *)(&qspiFlashWriterInfo.readData[rPos]);
284 for (i = 0, j = 0; i < qspiFlashWriterInfo.blockSizeBytes; i += 4)
285 {
286 read_data_w[j++] = (scrach_block[i+0] << 24) |
287 (scrach_block[i+1] << 16) |
288 (scrach_block[i+2] << 8) |
289 scrach_block[i+3];
290 }
291 }
293 /* Read the data from the file */
294 rLen = qspiFlashWriterInfo.blockSizeBytes;
295 if ((qspiFlashWriterInfo.writeBytes - rPos) < qspiFlashWriterInfo.blockSizeBytes)
296 {
297 rLen = (qspiFlashWriterInfo.writeBytes - rPos);
298 }
300 for (i = rPos; i < rLen; i++)
301 {
302 if (qspiFlashWriterInfo.readData[i] != qspiFlashWriterInfo.writeData[i])
303 {
304 printf ("Failure in sector %d, at byte %d, (at byte %d in the data file) expected 0x%08x, read 0x%08x\n",
305 block, i, rPos, qspiFlashWriterInfo.writeData[i], qspiFlashWriterInfo.readData[i]);
306 if (swap_byte) free (scrach_block);
307 return (FALSE);
308 }
309 }
311 }
313 if (swap_byte) free (scrach_block);
314 return (TRUE);
315 }
317 /******************************************************************************
318 * Function: parse_input_file
319 ******************************************************************************/
320 static Bool
321 parse_input_file
322 (
323 FILE* fp
324 )
325 {
326 char line[MAX_LINE_LENGTH];
327 char tokens[] = " :=;\n\r";
328 char *key, *data;
330 memset(line, 0, MAX_LINE_LENGTH);
332 fgets(line, MAX_LINE_LENGTH, fp);
333 key = (char *)strtok(line, tokens);
334 data = (char *)strtok(NULL, tokens);
336 if(strlen(data) == 0)
337 {
338 return FALSE;
339 }
341 if(strcmp(key, FILE_NAME) != 0)
342 {
343 return FALSE;
344 }
346 strcpy (qspiFlashWriterInfo.file_name, data);
348 fgets(line, MAX_LINE_LENGTH, fp);
349 key = (char *)strtok(line, tokens);
350 data = (char *)strtok(NULL, tokens);
352 if(strlen(data) == 0)
353 {
354 return FALSE;
355 }
357 if(strcmp(key, START_ADDR) != 0)
358 {
359 return FALSE;
360 }
362 qspiFlashWriterInfo.startAddr = (uint32_t)atoi(data);
364 return TRUE;
365 }
367 /******************************************************************************
368 * Function: find_file_length
369 ******************************************************************************/
370 static Bool
371 find_file_length
372 (
373 FILE* fp
374 )
375 {
376 char line[MAX_LINE_LENGTH];
377 char *pEnd;
378 char *ext;
379 uint32_t data_len, write_addr;
381 memset(line, 0, MAX_LINE_LENGTH);
383 ext = strrchr(qspiFlashWriterInfo.file_name, '.');
386 if (ext && (strcmp(ext, ".dat") == 0))
387 {
388 fgets(line, MAX_LINE_LENGTH, fp);
390 /* Read the write address from the CCS header */
391 strtoul (line,&pEnd,16);
392 strtoul (pEnd,&pEnd,16);
393 write_addr = strtoul (pEnd,&pEnd,16);
394 strtoul (pEnd,&pEnd,16);
396 /* Read the data length */
397 data_len = (strtoul (pEnd,NULL,16)) * 4;
398 }
399 else
400 {
401 /* find the data length by seeking to the end and getting position */
402 fseek(fp, 0, SEEK_END);
403 data_len = ftell(fp);
404 fseek(fp, 0, SEEK_SET);
405 }
406 printf ("The contents of file %s of length %d will be written to QSPI flash of size 0x%x.\n", qspiFlashWriterInfo.file_name, data_len, QSPI_FLASH_SIZE);
407 if (data_len > (qspiFlashWriterInfo.deviceTotalBytes - qspiFlashWriterInfo.startAddr))
408 {
409 printf ("The data file is too big to fit into the device.\n");
410 return FALSE;
411 }
413 qspiFlashWriterInfo.writeBytes = data_len;
414 if (write_addr != WRITE_DATA_ADDRESS)
415 write_addr = WRITE_DATA_ADDRESS;
416 memset((void *)write_addr, 0xFF, qspiFlashWriterInfo.blockSizeBytes);
417 qspiFlashWriterInfo.filesize= fread((void *)write_addr, 1, data_len, fp);
418 printf ("The contents of file %s read is of length %d.\n", qspiFlashWriterInfo.file_name, qspiFlashWriterInfo.filesize);
419 qspiFlashWriterInfo.writeData = (uint8_t *)write_addr;
420 qspiFlashWriterInfo.readData = (uint8_t *)(write_addr + qspiFlashWriterInfo.deviceTotalBytes);
422 return TRUE;
423 }
425 /******************************************************************************
426 * Function: main
427 ******************************************************************************/
428 void main ()
429 {
430 FILE *fp;
431 platform_init_flags init_flags;
432 platform_init_config init_config;
433 PLATFORM_DEVICE_info *p_device;
434 Bool ret;
436 printf("QSPI Flash Writer Utility Version %s\n\n", version);
438 fp = fopen(input_file, "r");
439 if (fp == NULL)
440 {
441 printf("Error in opening %s input file\n", input_file);
442 return;
443 }
445 ret = parse_input_file(fp);
446 fclose (fp);
448 if (ret == FALSE)
449 {
450 printf("Error in parsing %s input file\n", input_file);
451 return;
452 }
454 /* Initialize main Platform lib */
455 memset(&init_config, 0, sizeof(platform_init_config));
456 memset(&init_flags, 1, sizeof(platform_init_flags));
457 init_flags.pll = 0;
458 init_flags.ddr = 0;
459 init_flags.phy = 0;
460 if (platform_init(&init_flags, &init_config) != Platform_EOK)
461 {
462 printf ("Platform init failed!\n");
463 print_platform_errno();
464 return;
465 }
467 p_device = platform_device_open(PLATFORM_DEVID_QSPIFLASH_S25FL512S, 0);
468 if (p_device == NULL)
469 {
470 printf ("QSPI Flash device open failed!\n");
471 print_platform_errno();
472 return;
473 }
474 qspiFlashWriterInfo.deviceTotalBytes = p_device->block_count * p_device->page_count * p_device->page_size;
475 qspiFlashWriterInfo.blockSizeBytes = p_device->page_count * p_device->page_size;
477 if ((qspiFlashWriterInfo.startAddr % qspiFlashWriterInfo.blockSizeBytes) != 0)
478 {
479 printf ("The start programming address 0x%8x set in %s is not at the beginning of a block, block size = 0x%4x\n",
480 qspiFlashWriterInfo.startAddr,
481 qspiFlashWriterInfo.file_name,
482 qspiFlashWriterInfo.blockSizeBytes);
483 return;
484 }
486 /* Open and find the length of the data file */
487 fp = fopen (qspiFlashWriterInfo.file_name, "rb");
488 if (fp == NULL)
489 {
490 printf ("Failed to open file %s\n", qspiFlashWriterInfo.file_name);
491 platform_device_close(p_device->handle);
492 return;
493 }
495 /* Parse the CCS format file */
496 ret = find_file_length(fp);
497 fclose (fp);
499 qspiFlashWriterInfo.writeBytes += qspiFlashWriterInfo.blockSizeBytes - 1;
500 qspiFlashWriterInfo.writeBytes -= qspiFlashWriterInfo.writeBytes % qspiFlashWriterInfo.blockSizeBytes;
502 if (ret == FALSE)
503 {
504 printf("Error in parsing CCS file %s\n", qspiFlashWriterInfo.file_name);
505 platform_device_close(p_device->handle);
506 return;
507 }
509 /* Write the flash */
510 if (write_qspi_flash (p_device) == FALSE)
511 {
512 printf ("QSPI Flash write failed\n");
513 platform_device_close(p_device->handle);
514 return;
515 }
517 /* verify the flash */
518 if(flash_verify (p_device) == FALSE)
519 {
520 printf ("QSPI Flash read verify failed\n");
521 platform_device_close(p_device->handle);
522 return;
523 }
526 printf ("QSPI Flash programming completed successfully\n");
528 platform_device_close(p_device->handle);
530 return;
531 }