qspi_flash_test.c (8854B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 */ 7 8 #include <appl/diag/test.h> 9 #include <appl/diag/system.h> 10 #include <sal/appl/io.h> 11 #include <sal/compiler.h> 12 #include <sal/core/thread.h> 13 #include <sal/core/libc.h> 14 #include <shared/bsl.h> 15 #include "testlist.h" 16 #include <soc/drv.h> 17 #include <soc/mem.h> 18 #include <soc/error.h> 19 #include <soc/soc_flash.h> 20 21 #ifdef BCM_CMICX_SUPPORT 22 23 # define SPI_SPEED 62500000 /* BSPI */ 24 # define SPI_MODE 3 /* (CPOL|CPHA) */ 25 26 #define SWAP_ENDIAN(x) ( \ 27 (((x) << 24) & 0xff000000) | \ 28 (((x) << 8) & 0x00ff0000) | \ 29 (((x) >> 8) & 0x0000ff00) | \ 30 (((x) >> 24) & 0x000000ff)) 31 32 soc_flash_conf_t testflash; 33 34 char *qspi_flash_magic_str = "QSPI_FLASH"; 35 36 /* initialize the test */ 37 int qspi_flash_test_init(int u, args_t *a, void *p) 38 { 39 unsigned int speed = SPI_SPEED; 40 unsigned int mode = SPI_MODE; 41 soc_mem_test_t *parm = p; 42 int rv = SOC_E_NONE; 43 cli_out("qspi_flash_test_init...\n"); 44 parm->userdata = qspi_flash_magic_str; 45 rv = soc_flash_init(u, speed, mode, &testflash); 46 if (SOC_FAILURE(rv)) { 47 cli_out("Error: QSPI flash init failed, speed = %u, mode =%u\n", speed, mode); 48 } 49 return rv; 50 } 51 52 static void fill_pattern(uint32 *buf, uint32 bufsize, uint32 pattern) 53 { 54 int i; 55 int size = bufsize/4; /* Number of words to fill */ 56 57 for(i = 0; i < size; i++) { 58 buf[i] = pattern; 59 } 60 return; 61 } 62 63 /* run the test */ 64 int qspi_flash_test_run(int u, args_t *a, void *p) 65 { 66 int rv = SOC_E_NONE; 67 uint32 *wbuf = NULL; 68 uint32 *rbuf = NULL; 69 uint32 *sbuf = NULL; 70 uint32 numsect = testflash.nr_sectors; 71 uint32 sector, offset=0; 72 uint32 startsect, endsect; 73 soc_mem_test_t *parm = p; 74 75 if(parm->index_end) { 76 /* Boundary check */ 77 if((parm->index_start >= testflash.size) || 78 (parm->index_end >= testflash.size) || 79 (parm->index_end < parm->index_start)) { 80 cli_out("IndexStart and IndexEnd not in flash boundaries 0 and 0x%zx\n", testflash.size); 81 return(SOC_E_PARAM); 82 } 83 startsect = parm->index_start/testflash.sector_size; 84 endsect = parm->index_end/testflash.sector_size; 85 } 86 else { /* default - test last 16 sectors */ 87 startsect = numsect - 16; 88 endsect = numsect - 1; 89 } 90 91 cli_out("Max sectors in flash: %d, sectsize: 0x%zx\n", numsect, testflash.sector_size); 92 cli_out("Testing sectors: %d to %d\n", startsect, endsect); 93 94 wbuf = sal_alloc(testflash.sector_size, "FLASH_W"); 95 if (!wbuf) { 96 cli_out("sal_alloc failed\n"); 97 rv = SOC_E_MEMORY; 98 goto cleanup; 99 } 100 101 rbuf = sal_alloc(testflash.sector_size, "FLASH_R"); 102 if (!rbuf) { 103 cli_out("sal_alloc failed\n"); 104 rv = SOC_E_MEMORY; 105 goto cleanup; 106 } 107 108 sbuf = sal_alloc(testflash.sector_size, "FLASH_S"); 109 if (!sbuf) { 110 cli_out("sal_alloc failed\n"); 111 rv = SOC_E_MEMORY; 112 goto cleanup; 113 } 114 115 /* To retain original content, we are going to test sectors 116 only. We are not goig to erase whole flash, 117 instead, erase sector wise, and recover that sector with 118 original data after testing the sector */ 119 120 /* Test last 16 sectors to reduce the test time */ 121 for(sector = startsect; sector <= endsect; sector++) { 122 offset = sector * testflash.sector_size; 123 cli_out("Testing sector: %d, offset=0x%08x, size: 0x%08zx\n", sector, offset, 124 testflash.sector_size); 125 /* Save sector data */ 126 rv = soc_flash_read(u, offset, testflash.sector_size, sbuf); 127 if(rv != SOC_E_NONE) { 128 cli_out("Flash read failed, sector: %d, size: 0x%08zx\n", sector, 129 testflash.sector_size); 130 goto cleanup; 131 } 132 133 /* Sector erase and blank check */ 134 fill_pattern(wbuf, testflash.sector_size, 0); 135 136 rv = soc_flash_erase(u,offset, testflash.sector_size); 137 if(rv != SOC_E_NONE) { 138 cli_out("Flash erase failed, sector: %d, size: 0x%08zx\n", sector, 139 testflash.sector_size); 140 goto cleanup; 141 } 142 143 rv = soc_flash_write(u, offset, testflash.sector_size, wbuf); 144 if(rv != SOC_E_NONE) { 145 cli_out("Flash write failed, sector: %d, size: 0x%08zx\n", sector, 146 testflash.sector_size); 147 goto restore; 148 } 149 150 rv = soc_flash_read(u, offset, testflash.sector_size, rbuf); 151 if(rv != SOC_E_NONE) { 152 cli_out("Flash read failed, sector: %d, size: 0x%08zx\n", sector, 153 testflash.sector_size); 154 goto restore; 155 } 156 157 rv = sal_memcmp(wbuf, rbuf,testflash.sector_size); 158 if(rv != 0) { 159 cli_out("Data integrity failed, sector: %d, size: 0x%08zx\n", sector, 160 testflash.sector_size); 161 goto restore; 162 } 163 164 /* Walking 0 and 1 pattern */ 165 fill_pattern(wbuf, testflash.sector_size, 0x55555555); 166 rv = soc_flash_erase(u,offset, testflash.sector_size); 167 if(rv != SOC_E_NONE) { 168 cli_out("Flash erase failed, sector: %d, size: 0x%08zx\n", sector, 169 testflash.sector_size); 170 goto restore; 171 } 172 rv = soc_flash_write(u, offset, testflash.sector_size, wbuf); 173 if(rv != SOC_E_NONE) { 174 cli_out("Flash write failed, sector: %d, size: 0x%08zx\n", sector, 175 testflash.sector_size); 176 goto restore; 177 } 178 179 rv = soc_flash_read(u, offset, testflash.sector_size, rbuf); 180 if(rv != SOC_E_NONE) { 181 cli_out("Flash read failed, sector: %d, size: 0x%08zx\n", sector, 182 testflash.sector_size); 183 goto restore; 184 } 185 186 rv = sal_memcmp(wbuf, rbuf,testflash.sector_size); 187 if(rv != 0) { 188 cli_out("Data integrity failed with walking 0s and 1s, sector: %d, size: 0x%08zx\n", sector, 189 testflash.sector_size); 190 goto restore; 191 } 192 193 194 /* Walking 1 and 0 pattern */ 195 fill_pattern(wbuf, testflash.sector_size, 0xAAAAAAAA); 196 rv = soc_flash_erase(u,offset, testflash.sector_size); 197 if(rv != SOC_E_NONE) { 198 cli_out("Flash erase failed, sector: %d, size: 0x%08zx\n", sector, 199 testflash.sector_size); 200 goto restore; 201 } 202 rv = soc_flash_write(u, offset, testflash.sector_size, wbuf); 203 if(rv != SOC_E_NONE) { 204 cli_out("Flash write failed, sector: %d, size: 0x%08zx\n", sector, 205 testflash.sector_size); 206 goto restore; 207 } 208 209 rv = soc_flash_read(u, offset, testflash.sector_size, rbuf); 210 if(rv != SOC_E_NONE) { 211 cli_out("Flash read failed, sector: %d, size: 0x%08zx\n", sector, 212 testflash.sector_size); 213 goto restore; 214 } 215 216 rv = sal_memcmp(wbuf, rbuf,testflash.sector_size); 217 if(rv != 0) { 218 cli_out("Data integrity failed with walking 1s and 0s, sector: %d, size: 0x%08zx\n", sector, 219 testflash.sector_size); 220 goto restore; 221 } 222 223 restore: 224 rv = soc_flash_erase(u,offset, testflash.sector_size); 225 if(rv != SOC_E_NONE) { 226 cli_out("Flash erase failed, sector: %d, size: 0x%08zx\n", sector, 227 testflash.sector_size); 228 goto cleanup; 229 } 230 231 rv = soc_flash_write(u, offset, testflash.sector_size, sbuf); 232 if(rv != SOC_E_NONE) { 233 cli_out("Fatal: Flash restore failed, sector: %d, size: 0x%08zx\n", sector, 234 testflash.sector_size); 235 goto cleanup; 236 } 237 } /* End for */ 238 cleanup: 239 if(wbuf) sal_free(wbuf); 240 if(rbuf) sal_free(rbuf); 241 if(sbuf) sal_free(sbuf); 242 243 return rv; 244 } 245 246 247 /* end the test */ 248 int qspi_flash_test_done(int u, void *p) 249 { 250 soc_mem_test_t *parm = p; 251 parm->userdata = NULL; 252 253 cli_out("QSPI flash test Done, please power cycle the system\n"); 254 return 0; 255 } 256 257 #endif /* BCM_CMICX_SUPPORT */