spiflash.c (6242B)
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 * Arm Processor Subsystem flash utility 8 */ 9 10 #include <sal/core/libc.h> 11 #include <appl/diag/aps/spiflash.h> 12 13 #define ROUND_UP(x,y) ((((uint32)(x)) + ((uint32)(y)) - 1) \ 14 & ~(uint32)((y) - 1)) 15 16 flash_info_t spiflash_info[] = { 17 { "m25p10a", 0x202011, 256, 64*1024, 32*1024, 128*1024 }, 18 { "m25p20", 0x202012, 256, 64*1024, 64*1024, 256*1024 }, 19 { "m25p40", 0x202013, 256, 64*1024, 64*1024, 512*1024 }, 20 { "m25p80", 0x202014, 256, 64*1024, 64*1024, 1024*1024 }, 21 { "m25p16", 0x202015, 256, 64*1024, 64*1024, 2048*1024 }, 22 23 { "s25fl032p", 0x010215, 256, 64*1024, 64*1024, 4096*1024 }, 24 25 { "m45pe10", 0x204011, 256, 256, 64*1024, 128*1024 }, 26 { "m45pe20", 0x204012, 256, 256, 64*1024, 256*1024 }, 27 { "m45pe40", 0x204013, 256, 256, 64*1024, 512*1024 }, 28 { "m45pe80", 0x204014, 256, 256, 64*1024, 1024*1024 }, 29 { "m45pe16", 0x204015, 256, 256, 64*1024, 2048*1024 }, 30 31 { "mx25L0805d/6e", 0xc22014, 256, 4*1024, 64*1024, 1024*1024 }, 32 { "mx25L1605d/6e", 0xc22015, 256, 4*1024, 64*1024, 2048*1024 }, 33 { "mx25L3205d/6e", 0xc22016, 256, 4*1024, 64*1024, 4096*1024 }, 34 { "mx25L6405d/6e", 0xc22017, 256, 4*1024, 64*1024, 8192*1024 }, 35 36 { "w25x40bv", 0xef3013, 256, 4*1024, 64*1024, 512*1024 }, 37 38 { "at45db011d", 0x1f2200, 256, 256, 2*1024, 128*1024 }, 39 { "at45db021d", 0x1f2300, 256, 256, 2*1024, 256*1024 }, 40 { "at45db041d", 0x1f2400, 256, 256, 2*1024, 512*1024 }, 41 { "at45db081d", 0x1f2500, 256, 256, 2*1024, 1024*1024 } 42 }; 43 44 /* @api 45 * spiflash_info_by_name 46 * 47 * @brief 48 * Lookup the SPI flash info based on it's name. 49 * 50 * @param=name - name of the flash 51 * 52 * @returns pointer to the flash_info_t or NULL 53 */ 54 flash_info_t *spiflash_info_by_name(char *name) 55 { 56 int i; 57 58 /* determine the minimum erase size for this flash */ 59 for (i = 0; i < sizeof(spiflash_info)/sizeof(spiflash_info[0]); ++i) { 60 if (!sal_strcmp(name, spiflash_info[i].name)) { 61 return &spiflash_info[i]; 62 } 63 } 64 return NULL; 65 } 66 67 /* @api 68 * spiflash_info_by_rdid 69 * 70 * @brief 71 * Lookup the SPI flash info based on it's RDID. 72 * 73 * @param=rdid - RDID for the flash 74 * 75 * @returns pointer to the flash_info_t or NULL 76 */ 77 flash_info_t *spiflash_info_by_rdid(uint32 rdid) 78 { 79 int i; 80 81 /* determine the minimum erase size for this flash */ 82 for (i = 0; i < sizeof(spiflash_info)/sizeof(spiflash_info[0]); ++i) { 83 if (spiflash_info[i].rdid == rdid) { 84 return &spiflash_info[i]; 85 } 86 } 87 return NULL; 88 } 89 90 /*@api 91 * spiflash_calculate_flash_header 92 * 93 * @brief 94 * Calculates the flash header based on the input parameters 95 * 96 * @param=flash_info - pointer to the flash_info_t for the flash 97 * @param=header - pointer to the flash_header_t to fill in 98 * @param=dmu_config - DMU configuration option to choose 99 * @param=spi_speed - SPI speed to install (0 = no speed change) 100 * @returns 0 - success 101 * @returns !0 - error 102 * 103 * @desc 104 */ 105 106 int spiflash_calculate_header(flash_info_t *flash_info, 107 flash_header_t *header, 108 uint32 dmu_config, 109 uint32 spi_speed) 110 { 111 int i; 112 uint32 page; 113 uint32 arm_pages; 114 uint32 switch_pages; 115 uint32 core_dump_pages; 116 uint32 arm_image_size; 117 uint32 switch_image_size; 118 uint32 core_dump_size; 119 uint32 avb_config_size; 120 uint32 avb_config_pages; 121 122 /* Calculate the avb config size */ 123 avb_config_size = ROUND_UP(FLASH_AVB_CONFIG_SIZE, SPIFLASH_PAGE_SIZE); 124 /* allocate a page for the image header */ 125 avb_config_size += SPIFLASH_PAGE_SIZE; 126 avb_config_pages = avb_config_size / SPIFLASH_PAGE_SIZE; 127 128 /* Calculate the core dump size */ 129 core_dump_size = ROUND_UP(FLASH_CORE_IMAGE_SIZE, SPIFLASH_PAGE_SIZE); 130 /* allocate a page for the image header */ 131 core_dump_size += SPIFLASH_PAGE_SIZE; 132 core_dump_pages = core_dump_size / SPIFLASH_PAGE_SIZE; 133 134 /* Calculate the ARM and switch pages based on the page size */ 135 arm_image_size = ROUND_UP(FLASH_ARM_IMAGE_SIZE, SPIFLASH_PAGE_SIZE); 136 /* allocate a page for the image header */ 137 arm_image_size += SPIFLASH_PAGE_SIZE; 138 arm_pages = arm_image_size / SPIFLASH_PAGE_SIZE; 139 140 switch_image_size = ROUND_UP(FLASH_SWITCH_IMAGE_SIZE, SPIFLASH_PAGE_SIZE); 141 /* allocate a page for the switch configuration header */ 142 switch_image_size += SPIFLASH_PAGE_SIZE; 143 switch_pages = switch_image_size / SPIFLASH_PAGE_SIZE; 144 145 sal_memset(header, 0, sizeof(flash_header_t)); 146 header->magic = FLASH_HEADER_MAGIC; 147 148 /* Program the DMU configuration */ 149 header->dmu_config = dmu_config; 150 151 /* Program the default spi-speed */ 152 header->spi_speed = spi_speed; 153 154 /* build the offsets in pages, starting after the TOC copies */ 155 page = (FLASH_NUM_HEADER_BLOCKS * flash_info->erase_page_size) / SPIFLASH_PAGE_SIZE; 156 for (i = 0; i < FLASH_NUM_IMAGES; ++i) { 157 header->image_offset[i] = page; 158 page += arm_pages; 159 page = ROUND_UP(page, flash_info->erase_page_size / SPIFLASH_PAGE_SIZE); 160 } 161 for (i = 0; i < FLASH_NUM_CONFIGS; ++i) { 162 header->config_offset[i] = page; 163 page += switch_pages; 164 page = ROUND_UP(page, flash_info->erase_page_size / SPIFLASH_PAGE_SIZE); 165 } 166 for (i = 0; i < FLASH_NUM_CORE_DUMPS; ++i) { 167 header->core_dump_offset[i] = page; 168 page += core_dump_pages; 169 page = ROUND_UP(page, flash_info->erase_page_size / SPIFLASH_PAGE_SIZE); 170 } 171 for (i = 0; i < FLASH_NUM_AVB_CONFIGS; ++i) { 172 header->expansion[AVB_CFG_EXP_OFFSET + i].offset = page; 173 page += avb_config_pages; 174 page = ROUND_UP(page, flash_info->erase_page_size / SPIFLASH_PAGE_SIZE); 175 } 176 177 header->expansion[VPD_EXP_OFFSET].offset = page; 178 /* No boot images yet */ 179 for (i = 0; i < FLASH_NUM_BOOT_IMAGES; ++i) { 180 header->boot_image[i] = -1; 181 } 182 183 return 0; 184 } 185