]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
a6e34f76 VK |
2 | /* |
3 | * (C) Copyright 2009 | |
f3fcf92d | 4 | * Vipin Kumar, ST Microelectronics, [email protected]. |
a6e34f76 VK |
5 | */ |
6 | ||
7 | #include <common.h> | |
8 | #include <flash.h> | |
c05ed00a | 9 | #include <linux/delay.h> |
a6e34f76 | 10 | #include <linux/err.h> |
f3fcf92d | 11 | #include <linux/mtd/st_smi.h> |
a6e34f76 VK |
12 | |
13 | #include <asm/io.h> | |
14 | #include <asm/arch/hardware.h> | |
a6e34f76 | 15 | |
e856bdcf | 16 | #if defined(CONFIG_MTD_NOR_FLASH) |
a6e34f76 VK |
17 | |
18 | static struct smi_regs *const smicntl = | |
19 | (struct smi_regs * const)CONFIG_SYS_SMI_BASE; | |
20 | static ulong bank_base[CONFIG_SYS_MAX_FLASH_BANKS] = | |
21 | CONFIG_SYS_FLASH_ADDR_BASE; | |
22 | flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; | |
23 | ||
6d6d23c1 AV |
24 | /* data structure to maintain flash ids from different vendors */ |
25 | struct flash_device { | |
26 | char *name; | |
27 | u8 erase_cmd; | |
28 | u32 device_id; | |
29 | u32 pagesize; | |
30 | unsigned long sectorsize; | |
31 | unsigned long size_in_bytes; | |
32 | }; | |
33 | ||
34 | #define FLASH_ID(n, es, id, psize, ssize, size) \ | |
35 | { \ | |
36 | .name = n, \ | |
37 | .erase_cmd = es, \ | |
38 | .device_id = id, \ | |
39 | .pagesize = psize, \ | |
40 | .sectorsize = ssize, \ | |
41 | .size_in_bytes = size \ | |
42 | } | |
43 | ||
44 | /* | |
45 | * List of supported flash devices. | |
46 | * Currently the erase_cmd field is not used in this driver. | |
47 | */ | |
48 | static struct flash_device flash_devices[] = { | |
49 | FLASH_ID("st m25p16" , 0xd8, 0x00152020, 0x100, 0x10000, 0x200000), | |
50 | FLASH_ID("st m25p32" , 0xd8, 0x00162020, 0x100, 0x10000, 0x400000), | |
51 | FLASH_ID("st m25p64" , 0xd8, 0x00172020, 0x100, 0x10000, 0x800000), | |
52 | FLASH_ID("st m25p128" , 0xd8, 0x00182020, 0x100, 0x40000, 0x1000000), | |
53 | FLASH_ID("st m25p05" , 0xd8, 0x00102020, 0x80 , 0x8000 , 0x10000), | |
54 | FLASH_ID("st m25p10" , 0xd8, 0x00112020, 0x80 , 0x8000 , 0x20000), | |
55 | FLASH_ID("st m25p20" , 0xd8, 0x00122020, 0x100, 0x10000, 0x40000), | |
56 | FLASH_ID("st m25p40" , 0xd8, 0x00132020, 0x100, 0x10000, 0x80000), | |
57 | FLASH_ID("st m25p80" , 0xd8, 0x00142020, 0x100, 0x10000, 0x100000), | |
58 | FLASH_ID("st m45pe10" , 0xd8, 0x00114020, 0x100, 0x10000, 0x20000), | |
59 | FLASH_ID("st m45pe20" , 0xd8, 0x00124020, 0x100, 0x10000, 0x40000), | |
60 | FLASH_ID("st m45pe40" , 0xd8, 0x00134020, 0x100, 0x10000, 0x80000), | |
61 | FLASH_ID("st m45pe80" , 0xd8, 0x00144020, 0x100, 0x10000, 0x100000), | |
62 | FLASH_ID("sp s25fl004" , 0xd8, 0x00120201, 0x100, 0x10000, 0x80000), | |
63 | FLASH_ID("sp s25fl008" , 0xd8, 0x00130201, 0x100, 0x10000, 0x100000), | |
64 | FLASH_ID("sp s25fl016" , 0xd8, 0x00140201, 0x100, 0x10000, 0x200000), | |
65 | FLASH_ID("sp s25fl032" , 0xd8, 0x00150201, 0x100, 0x10000, 0x400000), | |
66 | FLASH_ID("sp s25fl064" , 0xd8, 0x00160201, 0x100, 0x10000, 0x800000), | |
67 | FLASH_ID("mac 25l512" , 0xd8, 0x001020C2, 0x010, 0x10000, 0x10000), | |
68 | FLASH_ID("mac 25l1005" , 0xd8, 0x001120C2, 0x010, 0x10000, 0x20000), | |
69 | FLASH_ID("mac 25l2005" , 0xd8, 0x001220C2, 0x010, 0x10000, 0x40000), | |
70 | FLASH_ID("mac 25l4005" , 0xd8, 0x001320C2, 0x010, 0x10000, 0x80000), | |
71 | FLASH_ID("mac 25l4005a" , 0xd8, 0x001320C2, 0x010, 0x10000, 0x80000), | |
72 | FLASH_ID("mac 25l8005" , 0xd8, 0x001420C2, 0x010, 0x10000, 0x100000), | |
73 | FLASH_ID("mac 25l1605" , 0xd8, 0x001520C2, 0x100, 0x10000, 0x200000), | |
74 | FLASH_ID("mac 25l1605a" , 0xd8, 0x001520C2, 0x010, 0x10000, 0x200000), | |
75 | FLASH_ID("mac 25l3205" , 0xd8, 0x001620C2, 0x100, 0x10000, 0x400000), | |
76 | FLASH_ID("mac 25l3205a" , 0xd8, 0x001620C2, 0x100, 0x10000, 0x400000), | |
77 | FLASH_ID("mac 25l6405" , 0xd8, 0x001720C2, 0x100, 0x10000, 0x800000), | |
92640776 | 78 | FLASH_ID("wbd w25q128" , 0xd8, 0x001840EF, 0x100, 0x10000, 0x1000000), |
a6e34f76 VK |
79 | }; |
80 | ||
81 | /* | |
82 | * smi_wait_xfer_finish - Wait until TFF is set in status register | |
83 | * @timeout: timeout in milliseconds | |
84 | * | |
85 | * Wait until TFF is set in status register | |
86 | */ | |
5c16c541 | 87 | static int smi_wait_xfer_finish(int timeout) |
a6e34f76 | 88 | { |
b5992fac AV |
89 | ulong start = get_timer(0); |
90 | ||
91 | while (get_timer(start) < timeout) { | |
a6e34f76 | 92 | if (readl(&smicntl->smi_sr) & TFF) |
5c16c541 | 93 | return 0; |
b5992fac AV |
94 | |
95 | /* Try after 10 ms */ | |
96 | udelay(10); | |
97 | }; | |
5c16c541 AV |
98 | |
99 | return -1; | |
a6e34f76 VK |
100 | } |
101 | ||
102 | /* | |
103 | * smi_read_id - Read flash id | |
104 | * @info: flash_info structure pointer | |
105 | * @banknum: bank number | |
106 | * | |
107 | * Read the flash id present at bank #banknum | |
108 | */ | |
109 | static unsigned int smi_read_id(flash_info_t *info, int banknum) | |
110 | { | |
111 | unsigned int value; | |
112 | ||
113 | writel(readl(&smicntl->smi_cr1) | SW_MODE, &smicntl->smi_cr1); | |
114 | writel(READ_ID, &smicntl->smi_tr); | |
115 | writel((banknum << BANKSEL_SHIFT) | SEND | TX_LEN_1 | RX_LEN_3, | |
116 | &smicntl->smi_cr2); | |
f3fcf92d | 117 | |
5c16c541 AV |
118 | if (smi_wait_xfer_finish(XFER_FINISH_TOUT)) |
119 | return -EIO; | |
a6e34f76 VK |
120 | |
121 | value = (readl(&smicntl->smi_rr) & 0x00FFFFFF); | |
122 | ||
123 | writel(readl(&smicntl->smi_sr) & ~TFF, &smicntl->smi_sr); | |
124 | writel(readl(&smicntl->smi_cr1) & ~SW_MODE, &smicntl->smi_cr1); | |
125 | ||
126 | return value; | |
127 | } | |
128 | ||
129 | /* | |
130 | * flash_get_size - Detect the SMI flash by reading the ID. | |
131 | * @base: Base address of the flash area bank #banknum | |
132 | * @banknum: Bank number | |
133 | * | |
134 | * Detect the SMI flash by reading the ID. Initializes the flash_info structure | |
135 | * with size, sector count etc. | |
136 | */ | |
137 | static ulong flash_get_size(ulong base, int banknum) | |
138 | { | |
139 | flash_info_t *info = &flash_info[banknum]; | |
69fcb55f | 140 | int value; |
a6e34f76 VK |
141 | int i; |
142 | ||
143 | value = smi_read_id(info, banknum); | |
69fcb55f AV |
144 | |
145 | if (value < 0) { | |
146 | printf("Flash id could not be read\n"); | |
147 | return 0; | |
148 | } | |
149 | ||
6d6d23c1 AV |
150 | /* Matches chip-id to entire list of 'serial-nor flash' ids */ |
151 | for (i = 0; i < ARRAY_SIZE(flash_devices); i++) { | |
152 | if (flash_devices[i].device_id == value) { | |
153 | info->size = flash_devices[i].size_in_bytes; | |
154 | info->flash_id = value; | |
155 | info->start[0] = base; | |
156 | info->sector_count = | |
157 | info->size/flash_devices[i].sectorsize; | |
a6e34f76 | 158 | |
6d6d23c1 | 159 | return info->size; |
a6e34f76 VK |
160 | } |
161 | } | |
162 | ||
6d6d23c1 | 163 | return 0; |
a6e34f76 VK |
164 | } |
165 | ||
166 | /* | |
167 | * smi_read_sr - Read status register of SMI | |
168 | * @bank: bank number | |
169 | * | |
170 | * This routine will get the status register of the flash chip present at the | |
171 | * given bank | |
172 | */ | |
69fcb55f | 173 | static int smi_read_sr(int bank) |
a6e34f76 | 174 | { |
a59c7b37 | 175 | u32 ctrlreg1, val; |
a6e34f76 VK |
176 | |
177 | /* store the CTRL REG1 state */ | |
178 | ctrlreg1 = readl(&smicntl->smi_cr1); | |
179 | ||
180 | /* Program SMI in HW Mode */ | |
181 | writel(readl(&smicntl->smi_cr1) & ~(SW_MODE | WB_MODE), | |
182 | &smicntl->smi_cr1); | |
183 | ||
184 | /* Performing a RSR instruction in HW mode */ | |
185 | writel((bank << BANKSEL_SHIFT) | RD_STATUS_REG, &smicntl->smi_cr2); | |
186 | ||
5c16c541 AV |
187 | if (smi_wait_xfer_finish(XFER_FINISH_TOUT)) |
188 | return -1; | |
a6e34f76 | 189 | |
a59c7b37 SH |
190 | val = readl(&smicntl->smi_sr); |
191 | ||
a6e34f76 VK |
192 | /* Restore the CTRL REG1 state */ |
193 | writel(ctrlreg1, &smicntl->smi_cr1); | |
194 | ||
a59c7b37 | 195 | return val; |
a6e34f76 VK |
196 | } |
197 | ||
198 | /* | |
199 | * smi_wait_till_ready - Wait till last operation is over. | |
200 | * @bank: bank number shifted. | |
201 | * @timeout: timeout in milliseconds. | |
202 | * | |
203 | * This routine checks for WIP(write in progress)bit in Status register(SMSR-b0) | |
204 | * The routine checks for #timeout loops, each at interval of 1 milli-second. | |
205 | * If successful the routine returns 0. | |
206 | */ | |
207 | static int smi_wait_till_ready(int bank, int timeout) | |
208 | { | |
69fcb55f | 209 | int sr; |
b5992fac | 210 | ulong start = get_timer(0); |
a6e34f76 VK |
211 | |
212 | /* One chip guarantees max 5 msec wait here after page writes, | |
213 | but potentially three seconds (!) after page erase. */ | |
b5992fac | 214 | while (get_timer(start) < timeout) { |
a6e34f76 | 215 | sr = smi_read_sr(bank); |
a5ad7ccd | 216 | if ((sr >= 0) && (!(sr & WIP_BIT))) |
a6e34f76 VK |
217 | return 0; |
218 | ||
b5992fac AV |
219 | /* Try again after 10 usec */ |
220 | udelay(10); | |
69fcb55f AV |
221 | } while (timeout--); |
222 | ||
a6e34f76 VK |
223 | printf("SMI controller is still in wait, timeout=%d\n", timeout); |
224 | return -EIO; | |
225 | } | |
226 | ||
227 | /* | |
228 | * smi_write_enable - Enable the flash to do write operation | |
229 | * @bank: bank number | |
230 | * | |
231 | * Set write enable latch with Write Enable command. | |
232 | * Returns negative if error occurred. | |
233 | */ | |
234 | static int smi_write_enable(int bank) | |
235 | { | |
236 | u32 ctrlreg1; | |
b5992fac | 237 | u32 start; |
a6e34f76 | 238 | int timeout = WMODE_TOUT; |
69fcb55f | 239 | int sr; |
a6e34f76 VK |
240 | |
241 | /* Store the CTRL REG1 state */ | |
242 | ctrlreg1 = readl(&smicntl->smi_cr1); | |
243 | ||
244 | /* Program SMI in H/W Mode */ | |
245 | writel(readl(&smicntl->smi_cr1) & ~SW_MODE, &smicntl->smi_cr1); | |
246 | ||
247 | /* Give the Flash, Write Enable command */ | |
248 | writel((bank << BANKSEL_SHIFT) | WE, &smicntl->smi_cr2); | |
249 | ||
5c16c541 AV |
250 | if (smi_wait_xfer_finish(XFER_FINISH_TOUT)) |
251 | return -1; | |
a6e34f76 VK |
252 | |
253 | /* Restore the CTRL REG1 state */ | |
254 | writel(ctrlreg1, &smicntl->smi_cr1); | |
255 | ||
b5992fac AV |
256 | start = get_timer(0); |
257 | while (get_timer(start) < timeout) { | |
69fcb55f | 258 | sr = smi_read_sr(bank); |
a5ad7ccd | 259 | if ((sr >= 0) && (sr & (1 << (bank + WM_SHIFT)))) |
69fcb55f | 260 | return 0; |
a6e34f76 | 261 | |
b5992fac AV |
262 | /* Try again after 10 usec */ |
263 | udelay(10); | |
264 | }; | |
a6e34f76 VK |
265 | |
266 | return -1; | |
267 | } | |
268 | ||
269 | /* | |
270 | * smi_init - SMI initialization routine | |
271 | * | |
272 | * SMI initialization routine. Sets SMI control register1. | |
273 | */ | |
f3fcf92d | 274 | void smi_init(void) |
a6e34f76 VK |
275 | { |
276 | /* Setting the fast mode values. SMI working at 166/4 = 41.5 MHz */ | |
277 | writel(HOLD1 | FAST_MODE | BANK_EN | DSEL_TIME | PRESCAL4, | |
278 | &smicntl->smi_cr1); | |
279 | } | |
280 | ||
281 | /* | |
282 | * smi_sector_erase - Erase flash sector | |
283 | * @info: flash_info structure pointer | |
284 | * @sector: sector number | |
285 | * | |
286 | * Set write enable latch with Write Enable command. | |
287 | * Returns negative if error occurred. | |
288 | */ | |
289 | static int smi_sector_erase(flash_info_t *info, unsigned int sector) | |
290 | { | |
291 | int bank; | |
292 | unsigned int sect_add; | |
293 | unsigned int instruction; | |
294 | ||
295 | switch (info->start[0]) { | |
296 | case SMIBANK0_BASE: | |
297 | bank = BANK0; | |
298 | break; | |
299 | case SMIBANK1_BASE: | |
300 | bank = BANK1; | |
301 | break; | |
302 | case SMIBANK2_BASE: | |
303 | bank = BANK2; | |
304 | break; | |
305 | case SMIBANK3_BASE: | |
306 | bank = BANK3; | |
307 | break; | |
308 | default: | |
309 | return -1; | |
310 | } | |
311 | ||
312 | sect_add = sector * (info->size / info->sector_count); | |
313 | instruction = ((sect_add >> 8) & 0x0000FF00) | SECTOR_ERASE; | |
314 | ||
315 | writel(readl(&smicntl->smi_sr) & ~(ERF1 | ERF2), &smicntl->smi_sr); | |
316 | ||
ae3e0cc9 AV |
317 | /* Wait until finished previous write command. */ |
318 | if (smi_wait_till_ready(bank, CONFIG_SYS_FLASH_ERASE_TOUT)) | |
319 | return -EBUSY; | |
a6e34f76 | 320 | |
ae3e0cc9 AV |
321 | /* Send write enable, before erase commands. */ |
322 | if (smi_write_enable(bank)) | |
323 | return -EIO; | |
a6e34f76 | 324 | |
ae3e0cc9 AV |
325 | /* Put SMI in SW mode */ |
326 | writel(readl(&smicntl->smi_cr1) | SW_MODE, &smicntl->smi_cr1); | |
a6e34f76 | 327 | |
ae3e0cc9 AV |
328 | /* Send Sector Erase command in SW Mode */ |
329 | writel(instruction, &smicntl->smi_tr); | |
330 | writel((bank << BANKSEL_SHIFT) | SEND | TX_LEN_4, | |
a6e34f76 | 331 | &smicntl->smi_cr2); |
ae3e0cc9 AV |
332 | if (smi_wait_xfer_finish(XFER_FINISH_TOUT)) |
333 | return -EIO; | |
a6e34f76 | 334 | |
ae3e0cc9 AV |
335 | if (smi_wait_till_ready(bank, CONFIG_SYS_FLASH_ERASE_TOUT)) |
336 | return -EBUSY; | |
a6e34f76 | 337 | |
ae3e0cc9 AV |
338 | /* Put SMI in HW mode */ |
339 | writel(readl(&smicntl->smi_cr1) & ~SW_MODE, | |
a6e34f76 VK |
340 | &smicntl->smi_cr1); |
341 | ||
ae3e0cc9 | 342 | return 0; |
a6e34f76 VK |
343 | } |
344 | ||
345 | /* | |
346 | * smi_write - Write to SMI flash | |
347 | * @src_addr: source buffer | |
348 | * @dst_addr: destination buffer | |
185b3b76 | 349 | * @length: length to write in bytes |
a6e34f76 VK |
350 | * @bank: bank base address |
351 | * | |
352 | * Write to SMI flash | |
353 | */ | |
354 | static int smi_write(unsigned int *src_addr, unsigned int *dst_addr, | |
355 | unsigned int length, ulong bank_addr) | |
356 | { | |
185b3b76 SR |
357 | u8 *src_addr8 = (u8 *)src_addr; |
358 | u8 *dst_addr8 = (u8 *)dst_addr; | |
a6e34f76 | 359 | int banknum; |
185b3b76 | 360 | int i; |
a6e34f76 VK |
361 | |
362 | switch (bank_addr) { | |
363 | case SMIBANK0_BASE: | |
364 | banknum = BANK0; | |
a6e34f76 VK |
365 | break; |
366 | case SMIBANK1_BASE: | |
367 | banknum = BANK1; | |
a6e34f76 VK |
368 | break; |
369 | case SMIBANK2_BASE: | |
370 | banknum = BANK2; | |
a6e34f76 VK |
371 | break; |
372 | case SMIBANK3_BASE: | |
373 | banknum = BANK3; | |
a6e34f76 VK |
374 | break; |
375 | default: | |
376 | return -1; | |
377 | } | |
378 | ||
379 | if (smi_wait_till_ready(banknum, CONFIG_SYS_FLASH_WRITE_TOUT)) | |
380 | return -EBUSY; | |
381 | ||
382 | /* Set SMI in Hardware Mode */ | |
383 | writel(readl(&smicntl->smi_cr1) & ~SW_MODE, &smicntl->smi_cr1); | |
384 | ||
385 | if (smi_write_enable(banknum)) | |
386 | return -EIO; | |
387 | ||
388 | /* Perform the write command */ | |
185b3b76 | 389 | for (i = 0; i < length; i += 4) { |
a6e34f76 VK |
390 | if (((ulong) (dst_addr) % SFLASH_PAGE_SIZE) == 0) { |
391 | if (smi_wait_till_ready(banknum, | |
392 | CONFIG_SYS_FLASH_WRITE_TOUT)) | |
393 | return -EBUSY; | |
394 | ||
395 | if (smi_write_enable(banknum)) | |
396 | return -EIO; | |
397 | } | |
398 | ||
185b3b76 SR |
399 | if (length < 4) { |
400 | int k; | |
401 | ||
402 | /* | |
403 | * Handle special case, where length < 4 (redundant env) | |
404 | */ | |
405 | for (k = 0; k < length; k++) | |
406 | *dst_addr8++ = *src_addr8++; | |
407 | } else { | |
408 | /* Normal 32bit write */ | |
409 | *dst_addr++ = *src_addr++; | |
410 | } | |
a6e34f76 VK |
411 | |
412 | if ((readl(&smicntl->smi_sr) & (ERF1 | ERF2))) | |
413 | return -EIO; | |
414 | } | |
415 | ||
416 | if (smi_wait_till_ready(banknum, CONFIG_SYS_FLASH_WRITE_TOUT)) | |
417 | return -EBUSY; | |
418 | ||
419 | writel(readl(&smicntl->smi_sr) & ~(WCF), &smicntl->smi_sr); | |
420 | ||
421 | return 0; | |
422 | } | |
423 | ||
424 | /* | |
425 | * write_buff - Write to SMI flash | |
426 | * @info: flash info structure | |
427 | * @src: source buffer | |
428 | * @dest_addr: destination buffer | |
429 | * @length: length to write in words | |
430 | * | |
431 | * Write to SMI flash | |
432 | */ | |
433 | int write_buff(flash_info_t *info, uchar *src, ulong dest_addr, ulong length) | |
434 | { | |
435 | return smi_write((unsigned int *)src, (unsigned int *)dest_addr, | |
185b3b76 | 436 | length, info->start[0]); |
a6e34f76 VK |
437 | } |
438 | ||
439 | /* | |
440 | * flash_init - SMI flash initialization | |
441 | * | |
442 | * SMI flash initialization | |
443 | */ | |
444 | unsigned long flash_init(void) | |
445 | { | |
446 | unsigned long size = 0; | |
447 | int i, j; | |
448 | ||
449 | smi_init(); | |
450 | ||
451 | for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) { | |
452 | flash_info[i].flash_id = FLASH_UNKNOWN; | |
453 | size += flash_info[i].size = flash_get_size(bank_base[i], i); | |
454 | } | |
455 | ||
456 | for (j = 0; j < CONFIG_SYS_MAX_FLASH_BANKS; j++) { | |
457 | for (i = 1; i < flash_info[j].sector_count; i++) | |
458 | flash_info[j].start[i] = | |
459 | flash_info[j].start[i - 1] + | |
460 | flash_info->size / flash_info->sector_count; | |
461 | ||
462 | } | |
463 | ||
464 | return size; | |
465 | } | |
466 | ||
467 | /* | |
468 | * flash_print_info - Print SMI flash information | |
469 | * | |
470 | * Print SMI flash information | |
471 | */ | |
472 | void flash_print_info(flash_info_t *info) | |
473 | { | |
474 | int i; | |
475 | if (info->flash_id == FLASH_UNKNOWN) { | |
476 | puts("missing or unknown FLASH type\n"); | |
477 | return; | |
478 | } | |
cf9026de AV |
479 | |
480 | if (info->size >= 0x100000) | |
481 | printf(" Size: %ld MB in %d Sectors\n", | |
482 | info->size >> 20, info->sector_count); | |
483 | else | |
484 | printf(" Size: %ld KB in %d Sectors\n", | |
485 | info->size >> 10, info->sector_count); | |
a6e34f76 VK |
486 | |
487 | puts(" Sector Start Addresses:"); | |
488 | for (i = 0; i < info->sector_count; ++i) { | |
489 | #ifdef CONFIG_SYS_FLASH_EMPTY_INFO | |
490 | int size; | |
491 | int erased; | |
492 | u32 *flash; | |
493 | ||
494 | /* | |
495 | * Check if whole sector is erased | |
496 | */ | |
497 | size = (info->size) / (info->sector_count); | |
498 | flash = (u32 *) info->start[i]; | |
499 | size = size / sizeof(int); | |
500 | ||
501 | while ((size--) && (*flash++ == ~0)) | |
502 | ; | |
503 | ||
504 | size++; | |
505 | if (size) | |
506 | erased = 0; | |
507 | else | |
508 | erased = 1; | |
509 | ||
510 | if ((i % 5) == 0) | |
511 | printf("\n"); | |
512 | ||
513 | printf(" %08lX%s%s", | |
514 | info->start[i], | |
515 | erased ? " E" : " ", info->protect[i] ? "RO " : " "); | |
516 | #else | |
517 | if ((i % 5) == 0) | |
518 | printf("\n "); | |
519 | printf(" %08lX%s", | |
520 | info->start[i], info->protect[i] ? " (RO) " : " "); | |
521 | #endif | |
522 | } | |
523 | putc('\n'); | |
524 | return; | |
525 | } | |
526 | ||
527 | /* | |
528 | * flash_erase - Erase SMI flash | |
529 | * | |
530 | * Erase SMI flash | |
531 | */ | |
532 | int flash_erase(flash_info_t *info, int s_first, int s_last) | |
533 | { | |
534 | int rcode = 0; | |
535 | int prot = 0; | |
536 | flash_sect_t sect; | |
537 | ||
a6e34f76 VK |
538 | if ((s_first < 0) || (s_first > s_last)) { |
539 | puts("- no sectors to erase\n"); | |
540 | return 1; | |
541 | } | |
542 | ||
543 | for (sect = s_first; sect <= s_last; ++sect) { | |
544 | if (info->protect[sect]) | |
545 | prot++; | |
546 | } | |
547 | if (prot) { | |
548 | printf("- Warning: %d protected sectors will not be erased!\n", | |
549 | prot); | |
550 | } else { | |
551 | putc('\n'); | |
552 | } | |
553 | ||
554 | for (sect = s_first; sect <= s_last; sect++) { | |
555 | if (info->protect[sect] == 0) { | |
556 | if (smi_sector_erase(info, sect)) | |
557 | rcode = 1; | |
558 | else | |
559 | putc('.'); | |
560 | } | |
561 | } | |
562 | puts(" done\n"); | |
563 | return rcode; | |
564 | } | |
565 | #endif |