comparison loadtools/flutil.c @ 405:a212b4968b29

fc-loadtool flash: another refactoring: geometry vs. command set
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Tue, 17 Jun 2014 00:33:05 +0000
parents 7602443edf0d
children f2cc551e597f
comparison
equal deleted inserted replaced
404:7daea2476062 405:a212b4968b29
7 #include <stdint.h> 7 #include <stdint.h>
8 #include <stdlib.h> 8 #include <stdlib.h>
9 #include "flash.h" 9 #include "flash.h"
10 10
11 extern struct flash_bank_info flash_bank_info[2]; 11 extern struct flash_bank_info flash_bank_info[2];
12 extern struct flash_cmdset flash_cmdset_amd;
13 extern struct flash_cmdset flash_cmdset_intel;
12 14
13 static int 15 static int
14 cfi_read_byte(bi, off, ret16p) 16 cfi_read_byte(bi, off, ret16p)
15 struct flash_bank_info *bi; 17 struct flash_bank_info *bi;
16 int off; 18 int off;
35 hi &= 0xFF; 37 hi &= 0xFF;
36 *retptr = (hi << 8) | lo; 38 *retptr = (hi << 8) | lo;
37 return(0); 39 return(0);
38 } 40 }
39 41
40 static int
41 cfi_id_return_to_read_mode(bi)
42 struct flash_bank_info *bi;
43 {
44 if (do_w16(bi->base_addr + 0xAAA, 0xF0)) {
45 fprintf(stderr,
46 "unexpected response to w16 when resetting flash to read mode!\n");
47 return(-1);
48 }
49 return(0);
50 }
51
52 flash_get_cfi(bank) 42 flash_get_cfi(bank)
53 { 43 {
54 struct flash_bank_info *bi; 44 struct flash_bank_info *bi;
55 struct cfi_info *cfi; 45 struct flash_geom *geom;
56 struct flash_region_desc *reg; 46 struct flash_region_desc *reg;
57 int nr; 47 int nr;
58 uint16_t rdval; 48 uint16_t rdval, cmdset_id;
59 uint32_t size_check; 49 uint32_t size_check;
60 50
61 bi = flash_bank_info + bank; 51 bi = flash_bank_info + bank;
62 if (bi->cfi) 52 if (bi->geom)
63 return(0); 53 return(0);
64 printf("Performing CFI query\n"); 54 printf("Performing CFI query\n");
65 if (do_w16(bi->base_addr + 0xAA, 0x98)) { 55 if (do_w16(bi->base_addr + 0xAA, 0x98)) {
66 fprintf(stderr, "unexpected response to w16 - aborting\n"); 56 fprintf(stderr, "unexpected response to w16 - aborting\n");
67 return(-1); 57 return(-1);
69 /* if do_r16() returns -1, error msg has already been printed */ 59 /* if do_r16() returns -1, error msg has already been printed */
70 if (cfi_read_byte(bi, 0x10, &rdval) < 0) 60 if (cfi_read_byte(bi, 0x10, &rdval) < 0)
71 return(-1); 61 return(-1);
72 if (rdval != 'Q') { 62 if (rdval != 'Q') {
73 noqry: fprintf(stderr, "error: no QRY response from flash\n"); 63 noqry: fprintf(stderr, "error: no QRY response from flash\n");
74 cfi_id_return_to_read_mode(bi); 64 amd_reset_cmd(bi);
75 return(-1); 65 return(-1);
76 } 66 }
77 if (cfi_read_byte(bi, 0x11, &rdval) < 0) 67 if (cfi_read_byte(bi, 0x11, &rdval) < 0)
78 return(-1); 68 return(-1);
79 if (rdval != 'R') 69 if (rdval != 'R')
80 goto noqry; 70 goto noqry;
81 if (cfi_read_byte(bi, 0x12, &rdval) < 0) 71 if (cfi_read_byte(bi, 0x12, &rdval) < 0)
82 return(-1); 72 return(-1);
83 if (rdval != 'Y') 73 if (rdval != 'Y')
84 goto noqry; 74 goto noqry;
85 cfi = malloc(sizeof(struct cfi_info)); 75 if (cfi_read_twobyte(bi, 0x13, &cmdset_id) < 0)
86 if (!cfi) { 76 return(-1);
87 fprintf(stderr, 77 if (!bi->ops) {
88 "unable to malloc buffer for flash bank %d CFI structure\n", 78 switch (cmdset_id) {
79 case 2:
80 bi->ops = &flash_cmdset_amd;
81 break;
82 #if 0
83 case 3:
84 bi->ops = &flash_cmdset_intel;
85 break;
86 #endif
87 default:
88 fprintf(stderr, "error: command set %04X unsupported\n",
89 cmdset_id);
90 amd_reset_cmd(bi);
91 return(-1);
92 }
93 }
94 geom = malloc(sizeof(struct flash_geom));
95 if (!geom) {
96 fprintf(stderr,
97 "unable to malloc buffer for flash bank %d CFI geometry structure\n",
89 bank); 98 bank);
90 cfi_id_return_to_read_mode(bi); 99 bi->ops->reset_cmd(bi);
91 return(-1); 100 return(-1);
92 } 101 }
93 if (cfi_read_twobyte(bi, 0x13, &cfi->cmdset_style) < 0) { 102 /* total device size */
103 if (cfi_read_byte(bi, 0x27, &rdval) < 0) {
94 free_and_immed_out: 104 free_and_immed_out:
95 free(cfi); 105 free(geom);
96 return(-1); 106 return(-1);
97 } 107 }
98 /* total device size */
99 if (cfi_read_byte(bi, 0x27, &rdval) < 0)
100 goto free_and_immed_out;
101 if (rdval < 20 || rdval > 24) { 108 if (rdval < 20 || rdval > 24) {
102 fprintf(stderr, 109 fprintf(stderr,
103 "error: CFI reports unreasonable device size\n"); 110 "error: CFI reports unreasonable device size\n");
104 free_and_clean_out: 111 free_and_clean_out:
105 free(cfi); 112 free(geom);
106 cfi_id_return_to_read_mode(bi); 113 bi->ops->reset_cmd(bi);
107 return(-1); 114 return(-1);
108 } 115 }
109 cfi->total_size = 1 << rdval; 116 geom->total_size = 1 << rdval;
110 if (cfi->total_size > bi->bank_desc->align_size) { 117 if (geom->total_size > bi->bank_desc->align_size) {
111 fprintf(stderr, 118 fprintf(stderr,
112 "error: CFI device size 0x%lx exceeds configured maximum 0x%lx\n", 119 "error: CFI device size 0x%lx exceeds configured maximum 0x%lx\n",
113 (u_long) cfi->total_size, bi->bank_desc->align_size); 120 (u_long) geom->total_size, bi->bank_desc->align_size);
114 goto free_and_clean_out; 121 goto free_and_clean_out;
115 } 122 }
116 if (cfi_read_byte(bi, 0x2C, &rdval) < 0) 123 if (cfi_read_byte(bi, 0x2C, &rdval) < 0)
117 goto free_and_immed_out; 124 goto free_and_immed_out;
118 if (rdval < 1 || rdval > CFI_MAX_REGIONS) { 125 if (rdval < 1 || rdval > CFI_MAX_REGIONS) {
119 fprintf(stderr, 126 fprintf(stderr,
120 "error: CFI reports unreasonable # of erase regions\n"); 127 "error: CFI reports unreasonable # of erase regions\n");
121 goto free_and_clean_out; 128 goto free_and_clean_out;
122 } 129 }
123 cfi->nregions = rdval; 130 geom->nregions = rdval;
124 cfi->total_sectors = 0; 131 geom->total_sectors = 0;
125 size_check = 0; 132 size_check = 0;
126 for (nr = 0; nr < cfi->nregions; nr++) { 133 for (nr = 0; nr < geom->nregions; nr++) {
127 reg = cfi->regions + nr; 134 reg = geom->regions + nr;
128 if (cfi_read_twobyte(bi, 0x2D + nr*4, &rdval) < 0) 135 if (cfi_read_twobyte(bi, 0x2D + nr*4, &rdval) < 0)
129 goto free_and_immed_out; 136 goto free_and_immed_out;
130 if (rdval > 255) { 137 if (rdval > 255) {
131 fprintf(stderr, 138 fprintf(stderr,
132 "error: CFI reports unreasonable # of sectors in region %d\n", 139 "error: CFI reports unreasonable # of sectors in region %d\n",
133 nr); 140 nr);
134 goto free_and_clean_out; 141 goto free_and_clean_out;
135 } 142 }
136 reg->nsectors = rdval + 1; 143 reg->nsectors = rdval + 1;
137 cfi->total_sectors += reg->nsectors; 144 geom->total_sectors += reg->nsectors;
138 if (cfi_read_twobyte(bi, 0x2F + nr*4, &rdval) < 0) 145 if (cfi_read_twobyte(bi, 0x2F + nr*4, &rdval) < 0)
139 goto free_and_immed_out; 146 goto free_and_immed_out;
140 if (rdval < 0x20 || rdval > 0x400) { 147 if (rdval < 0x20 || rdval > 0x400) {
141 fprintf(stderr, 148 fprintf(stderr,
142 "error: CFI reports unreasonable sector size in region %d\n", 149 "error: CFI reports unreasonable sector size in region %d\n",
144 goto free_and_clean_out; 151 goto free_and_clean_out;
145 } 152 }
146 reg->sector_size = rdval << 8; 153 reg->sector_size = rdval << 8;
147 size_check += reg->sector_size * reg->nsectors; 154 size_check += reg->sector_size * reg->nsectors;
148 } 155 }
149 if (cfi_id_return_to_read_mode(bi) < 0) { 156 if (bi->ops->reset_cmd(bi) < 0) {
150 /* error msg already printed */ 157 /* error msg already printed */
151 free(cfi); 158 free(geom);
152 return(-1); 159 return(-1);
153 } 160 }
154 if (size_check != cfi->total_size) { 161 if (size_check != geom->total_size) {
155 fprintf(stderr, 162 fprintf(stderr,
156 "CFI error: added size of erase regions (%lx) != reported devive size (%lx)\n", 163 "CFI error: added size of erase regions (%lx) != reported devive size (%lx)\n",
157 (u_long) size_check, (u_long) cfi->total_size); 164 (u_long) size_check, (u_long) geom->total_size);
158 free(cfi); 165 free(geom);
159 return(-1); 166 return(-1);
160 } 167 }
161 /* all checks passed */ 168 /* all checks passed */
162 bi->cfi = cfi; 169 bi->geom = geom;
163 printf( 170 printf(
164 "CFI query successful: total size %lx, %u sectors, command set style %04X\n\n", 171 "CFI query successful: total size %lx, %u sectors, command set style %04X\n",
165 (u_long) cfi->total_size, cfi->total_sectors, 172 (u_long) geom->total_size, geom->total_sectors, cmdset_id);
166 cfi->cmdset_style);
167 return(1); 173 return(1);
168 } 174 }
169 175
170 get_flash_sector_table(bank) 176 get_flash_sector_table(bank)
171 { 177 {
172 struct flash_bank_info *bi; 178 struct flash_bank_info *bi;
173 struct cfi_info *cfi; 179 struct flash_geom *geom;
174 struct flash_region_desc *reg; 180 struct flash_region_desc *reg;
175 struct sector_info *sp; 181 struct sector_info *sp;
176 uint32_t offset; 182 uint32_t offset;
177 int nr, i; 183 int nr, i;
178 184
180 if (bi->sectors) 186 if (bi->sectors)
181 return(0); 187 return(0);
182 i = flash_get_cfi(bank); 188 i = flash_get_cfi(bank);
183 if (i < 0) 189 if (i < 0)
184 return(i); 190 return(i);
185 cfi = bi->cfi; 191 geom = bi->geom;
186 sp = (struct sector_info *) malloc(sizeof(struct sector_info) 192 sp = (struct sector_info *) malloc(sizeof(struct sector_info)
187 * (cfi->total_sectors + 1)); 193 * (geom->total_sectors + 1));
188 if (!sp) { 194 if (!sp) {
189 fprintf(stderr, 195 fprintf(stderr,
190 "unable to malloc buffer for flash bank %d sector table\n", 196 "unable to malloc buffer for flash bank %d sector table\n",
191 bank); 197 bank);
192 return(-1); 198 return(-1);
193 } 199 }
194 bi->sectors = sp; 200 bi->sectors = sp;
195 /* now fill it */ 201 /* now fill it */
196 offset = 0; 202 offset = 0;
197 for (nr = 0; nr < cfi->nregions; nr++) { 203 for (nr = 0; nr < geom->nregions; nr++) {
198 reg = cfi->regions + nr; 204 reg = geom->regions + nr;
199 for (i = 0; i < reg->nsectors; i++) { 205 for (i = 0; i < reg->nsectors; i++) {
200 sp->start = offset; 206 sp->start = offset;
201 sp->size = reg->sector_size; 207 sp->size = reg->sector_size;
202 sp++; 208 sp++;
203 offset += reg->sector_size; 209 offset += reg->sector_size;
204 } 210 }
205 } 211 }
206 /* sanity checks */ 212 /* sanity checks */
207 if (sp - bi->sectors != cfi->total_sectors) { 213 if (sp - bi->sectors != geom->total_sectors) {
208 fprintf(stderr, 214 fprintf(stderr,
209 "BUG in get_flash_sector_table(): wrong # of sectors at the end\n"); 215 "BUG in get_flash_sector_table(): wrong # of sectors at the end\n");
210 abort(); 216 abort();
211 } 217 }
212 if (offset != cfi->total_size) { 218 if (offset != geom->total_size) {
213 fprintf(stderr, 219 fprintf(stderr,
214 "BUG in get_flash_sector_table(): wrong offset at the end\n"); 220 "BUG in get_flash_sector_table(): wrong offset at the end\n");
215 abort(); 221 abort();
216 } 222 }
217 /* finish */ 223 /* finish */
231 return(-1); 237 return(-1);
232 } 238 }
233 if (get_flash_sector_table(bank) < 0) 239 if (get_flash_sector_table(bank) < 0)
234 return(-1); 240 return(-1);
235 bi = flash_bank_info + bank; 241 bi = flash_bank_info + bank;
236 printf("%u sectors in flash bank %d:\n", bi->cfi->total_sectors, bank); 242 printf("%u sectors in flash bank %d:\n", bi->geom->total_sectors, bank);
237 printf("Offset Size\n"); 243 printf("Offset Size\n");
238 for (sp = bi->sectors; sp->size; sp++) 244 for (sp = bi->sectors; sp->size; sp++)
239 printf("%08lX %lx\n", (u_long) sp->start, (u_long) sp->size); 245 printf("%08lX %lx\n", (u_long) sp->start, (u_long) sp->size);
240 return(0); 246 return(0);
241 } 247 }