FreeCalypso > hg > freecalypso-sw
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 } |