disable cfi_write_words(). Broken for spansion, fallback
[fw/openocd] / src / flash / cfi.c
1 /***************************************************************************\r
2  *   Copyright (C) 2005, 2007 by Dominic Rath                              *\r
3  *   Dominic.Rath@gmx.de                                                   *\r
4  *                                                                         *\r
5  *   This program is free software; you can redistribute it and/or modify  *\r
6  *   it under the terms of the GNU General Public License as published by  *\r
7  *   the Free Software Foundation; either version 2 of the License, or     *\r
8  *   (at your option) any later version.                                   *\r
9  *                                                                         *\r
10  *   This program is distributed in the hope that it will be useful,       *\r
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *\r
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *\r
13  *   GNU General Public License for more details.                          *\r
14  *                                                                         *\r
15  *   You should have received a copy of the GNU General Public License     *\r
16  *   along with this program; if not, write to the                         *\r
17  *   Free Software Foundation, Inc.,                                       *\r
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *\r
19  ***************************************************************************/\r
20 #ifdef HAVE_CONFIG_H\r
21 #include "config.h"\r
22 #endif\r
23 \r
24 #include "replacements.h"\r
25 \r
26 #include "cfi.h"\r
27 \r
28 #include "flash.h"\r
29 #include "target.h"\r
30 #include "log.h"\r
31 #include "armv4_5.h"\r
32 #include "algorithm.h"\r
33 #include "binarybuffer.h"\r
34 #include "types.h"\r
35 \r
36 #include <stdlib.h>\r
37 #include <string.h>\r
38 #include <unistd.h>\r
39 \r
40 int cfi_register_commands(struct command_context_s *cmd_ctx);\r
41 int cfi_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);\r
42 int cfi_erase(struct flash_bank_s *bank, int first, int last);\r
43 int cfi_protect(struct flash_bank_s *bank, int set, int first, int last);\r
44 int cfi_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);\r
45 int cfi_probe(struct flash_bank_s *bank);\r
46 int cfi_auto_probe(struct flash_bank_s *bank);\r
47 int cfi_erase_check(struct flash_bank_s *bank);\r
48 int cfi_protect_check(struct flash_bank_s *bank);\r
49 int cfi_info(struct flash_bank_s *bank, char *buf, int buf_size);\r
50 \r
51 int cfi_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
52 \r
53 #define CFI_MAX_BUS_WIDTH       4\r
54 #define CFI_MAX_CHIP_WIDTH      4\r
55 \r
56 /* defines internal maximum size for code fragment in cfi_intel_write_block() */\r
57 #define CFI_MAX_INTEL_CODESIZE 256\r
58 \r
59 flash_driver_t cfi_flash =\r
60 {\r
61         .name = "cfi",\r
62         .register_commands = cfi_register_commands,\r
63         .flash_bank_command = cfi_flash_bank_command,\r
64         .erase = cfi_erase,\r
65         .protect = cfi_protect,\r
66         .write = cfi_write,\r
67         .probe = cfi_probe,\r
68         .auto_probe = cfi_auto_probe,\r
69         .erase_check = cfi_erase_check,\r
70         .protect_check = cfi_protect_check,\r
71         .info = cfi_info\r
72 };\r
73 \r
74 cfi_unlock_addresses_t cfi_unlock_addresses[] =\r
75 {\r
76         [CFI_UNLOCK_555_2AA] = { .unlock1 = 0x555, .unlock2 = 0x2aa },\r
77         [CFI_UNLOCK_5555_2AAA] = { .unlock1 = 0x5555, .unlock2 = 0x2aaa },\r
78 };\r
79 \r
80 /* CFI fixups foward declarations */\r
81 void cfi_fixup_non_cfi(flash_bank_t *flash, void *param);\r
82 void cfi_fixup_0002_erase_regions(flash_bank_t *flash, void *param);\r
83 void cfi_fixup_0002_unlock_addresses(flash_bank_t *flash, void *param);\r
84 void cfi_fixup_atmel_reversed_erase_regions(flash_bank_t *flash, void *param);\r
85 \r
86 /* fixup after identifying JEDEC manufactuer and ID */\r
87 cfi_fixup_t cfi_jedec_fixups[] = {\r
88         {CFI_MFR_SST, 0x00D4, cfi_fixup_non_cfi, NULL},\r
89         {CFI_MFR_SST, 0x00D5, cfi_fixup_non_cfi, NULL},\r
90         {CFI_MFR_SST, 0x00D6, cfi_fixup_non_cfi, NULL},\r
91         {CFI_MFR_SST, 0x00D7, cfi_fixup_non_cfi, NULL},\r
92         {CFI_MFR_SST, 0x2780, cfi_fixup_non_cfi, NULL},\r
93         {CFI_MFR_ST, 0x00D5, cfi_fixup_non_cfi, NULL},\r
94         {CFI_MFR_ST, 0x00D6, cfi_fixup_non_cfi, NULL},\r
95         {CFI_MFR_AMD, 0x2223, cfi_fixup_non_cfi, NULL},\r
96         {CFI_MFR_AMD, 0x22ab, cfi_fixup_non_cfi, NULL},\r
97         {0, 0, NULL, NULL}\r
98 };\r
99 \r
100 /* fixup after reading cmdset 0002 primary query table */\r
101 cfi_fixup_t cfi_0002_fixups[] = {\r
102         {CFI_MFR_SST, 0x00D4, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},\r
103         {CFI_MFR_SST, 0x00D5, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},\r
104         {CFI_MFR_SST, 0x00D6, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},\r
105         {CFI_MFR_SST, 0x00D7, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},\r
106         {CFI_MFR_SST, 0x2780, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},\r
107         {CFI_MFR_ATMEL, 0x00C8, cfi_fixup_atmel_reversed_erase_regions, NULL},\r
108         {CFI_MFR_ANY, CFI_ID_ANY, cfi_fixup_0002_erase_regions, NULL},\r
109         {0, 0, NULL, NULL}\r
110 };\r
111 \r
112 /* fixup after reading cmdset 0001 primary query table */\r
113 cfi_fixup_t cfi_0001_fixups[] = {\r
114         {0, 0, NULL, NULL}\r
115 };\r
116 \r
117 void cfi_fixup(flash_bank_t *bank, cfi_fixup_t *fixups)\r
118 {\r
119         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
120         cfi_fixup_t *f;\r
121 \r
122         for (f = fixups; f->fixup; f++)\r
123         {\r
124                 if (((f->mfr == CFI_MFR_ANY) || (f->mfr == cfi_info->manufacturer)) &&\r
125                         ((f->id  == CFI_ID_ANY)  || (f->id  == cfi_info->device_id)))\r
126                 {\r
127                         f->fixup(bank, f->param);\r
128                 }\r
129         }\r
130 }\r
131 \r
132 inline u32 flash_address(flash_bank_t *bank, int sector, u32 offset)\r
133 {\r
134         /* while the sector list isn't built, only accesses to sector 0 work */\r
135         if (sector == 0)\r
136                 return bank->base + offset * bank->bus_width;\r
137         else\r
138         {\r
139                 if (!bank->sectors)\r
140                 {\r
141                         ERROR("BUG: sector list not yet built");\r
142                         exit(-1);\r
143                 }\r
144                 return bank->base + bank->sectors[sector].offset + offset * bank->bus_width;\r
145         }\r
146 \r
147 }\r
148 \r
149 void cfi_command(flash_bank_t *bank, u8 cmd, u8 *cmd_buf)\r
150 {\r
151         int i;\r
152 \r
153         /* clear whole buffer, to ensure bits that exceed the bus_width\r
154          * are set to zero\r
155          */\r
156         for (i = 0; i < CFI_MAX_BUS_WIDTH; i++)\r
157                 cmd_buf[i] = 0;\r
158 \r
159         if (bank->target->endianness == TARGET_LITTLE_ENDIAN)\r
160         {\r
161                 for (i = bank->bus_width; i > 0; i--)\r
162                 {\r
163                         *cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;\r
164                 }\r
165         }\r
166         else\r
167         {\r
168                 for (i = 1; i <= bank->bus_width; i++)\r
169                 {\r
170                         *cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;\r
171                 }\r
172         }\r
173 }\r
174 \r
175 /* read unsigned 8-bit value from the bank\r
176  * flash banks are expected to be made of similar chips\r
177  * the query result should be the same for all\r
178  */\r
179 u8 cfi_query_u8(flash_bank_t *bank, int sector, u32 offset)\r
180 {\r
181         target_t *target = bank->target;\r
182         u8 data[CFI_MAX_BUS_WIDTH];\r
183 \r
184         target->type->read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 1, data);\r
185 \r
186         if (bank->target->endianness == TARGET_LITTLE_ENDIAN)\r
187                 return data[0];\r
188         else\r
189                 return data[bank->bus_width - 1];\r
190 }\r
191 \r
192 /* read unsigned 8-bit value from the bank\r
193  * in case of a bank made of multiple chips,\r
194  * the individual values are ORed\r
195  */\r
196 u8 cfi_get_u8(flash_bank_t *bank, int sector, u32 offset)\r
197 {\r
198         target_t *target = bank->target;\r
199         u8 data[CFI_MAX_BUS_WIDTH];\r
200         int i;\r
201 \r
202         target->type->read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 1, data);\r
203 \r
204         if (bank->target->endianness == TARGET_LITTLE_ENDIAN)\r
205         {\r
206                 for (i = 0; i < bank->bus_width / bank->chip_width; i++)\r
207                         data[0] |= data[i];\r
208 \r
209                 return data[0];\r
210         }\r
211         else\r
212         {\r
213                 u8 value = 0;\r
214                 for (i = 0; i < bank->bus_width / bank->chip_width; i++)\r
215                         value |= data[bank->bus_width - 1 - i];\r
216 \r
217                 return value;\r
218         }\r
219 }\r
220 \r
221 u16 cfi_query_u16(flash_bank_t *bank, int sector, u32 offset)\r
222 {\r
223         target_t *target = bank->target;\r
224         u8 data[CFI_MAX_BUS_WIDTH * 2];\r
225 \r
226         target->type->read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 2, data);\r
227 \r
228         if (bank->target->endianness == TARGET_LITTLE_ENDIAN)\r
229                 return data[0] | data[bank->bus_width] << 8;\r
230         else\r
231                 return data[bank->bus_width - 1] | data[(2 * bank->bus_width) - 1] << 8;\r
232 }\r
233 \r
234 u32 cfi_query_u32(flash_bank_t *bank, int sector, u32 offset)\r
235 {\r
236         target_t *target = bank->target;\r
237         u8 data[CFI_MAX_BUS_WIDTH * 4];\r
238 \r
239         target->type->read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 4, data);\r
240 \r
241         if (bank->target->endianness == TARGET_LITTLE_ENDIAN)\r
242                 return data[0] | data[bank->bus_width] << 8 | data[bank->bus_width * 2] << 16 | data[bank->bus_width * 3] << 24;\r
243         else\r
244                 return data[bank->bus_width - 1] | data[(2* bank->bus_width) - 1] << 8 |\r
245                                 data[(3 * bank->bus_width) - 1] << 16 | data[(4 * bank->bus_width) - 1] << 24;\r
246 }\r
247 \r
248 void cfi_intel_clear_status_register(flash_bank_t *bank)\r
249 {\r
250         target_t *target = bank->target;\r
251         u8 command[8];\r
252 \r
253         if (target->state != TARGET_HALTED)\r
254         {\r
255                 ERROR("BUG: attempted to clear status register while target wasn't halted");\r
256                 exit(-1);\r
257         }\r
258 \r
259         cfi_command(bank, 0x50, command);\r
260         target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
261 }\r
262 \r
263 u8 cfi_intel_wait_status_busy(flash_bank_t *bank, int timeout)\r
264 {\r
265         u8 status;\r
266 \r
267         while ((!((status = cfi_get_u8(bank, 0, 0x0)) & 0x80)) && (timeout-- > 0))\r
268         {\r
269                 DEBUG("status: 0x%x", status);\r
270                 usleep(1000);\r
271         }\r
272 \r
273         /* mask out bit 0 (reserved) */\r
274         status = status & 0xfe;\r
275 \r
276         DEBUG("status: 0x%x", status);\r
277 \r
278         if ((status & 0x80) != 0x80)\r
279         {\r
280                 ERROR("timeout while waiting for WSM to become ready");\r
281         }\r
282         else if (status != 0x80)\r
283         {\r
284                 ERROR("status register: 0x%x", status);\r
285                 if (status & 0x2)\r
286                         ERROR("Block Lock-Bit Detected, Operation Abort");\r
287                 if (status & 0x4)\r
288                         ERROR("Program suspended");\r
289                 if (status & 0x8)\r
290                         ERROR("Low Programming Voltage Detected, Operation Aborted");\r
291                 if (status & 0x10)\r
292                         ERROR("Program Error / Error in Setting Lock-Bit");\r
293                 if (status & 0x20)\r
294                         ERROR("Error in Block Erasure or Clear Lock-Bits");\r
295                 if (status & 0x40)\r
296                         ERROR("Block Erase Suspended");\r
297 \r
298                 cfi_intel_clear_status_register(bank);\r
299         }\r
300 \r
301         return status;\r
302 }\r
303 \r
304 int cfi_spansion_wait_status_busy(flash_bank_t *bank, int timeout)\r
305 {\r
306         u8 status, oldstatus;\r
307 \r
308         oldstatus = cfi_get_u8(bank, 0, 0x0);\r
309 \r
310         do {\r
311                 status = cfi_get_u8(bank, 0, 0x0);\r
312                 if ((status ^ oldstatus) & 0x40) {\r
313                         if (status & 0x20) {\r
314                                 oldstatus = cfi_get_u8(bank, 0, 0x0);\r
315                                 status = cfi_get_u8(bank, 0, 0x0);\r
316                                 if ((status ^ oldstatus) & 0x40) {\r
317                                         ERROR("dq5 timeout, status: 0x%x", status);\r
318                                         return(ERROR_FLASH_OPERATION_FAILED);\r
319                                 } else {\r
320                                         DEBUG("status: 0x%x", status);\r
321                                         return(ERROR_OK);\r
322                                 }\r
323                         }\r
324                 } else {\r
325                         DEBUG("status: 0x%x", status);\r
326                         return(ERROR_OK);\r
327                 }\r
328 \r
329                 oldstatus = status;\r
330                 usleep(1000);\r
331         } while (timeout-- > 0);\r
332 \r
333         ERROR("timeout, status: 0x%x", status);\r
334 \r
335         return(ERROR_FLASH_BUSY);\r
336 }\r
337 \r
338 int cfi_read_intel_pri_ext(flash_bank_t *bank)\r
339 {\r
340         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
341         cfi_intel_pri_ext_t *pri_ext = malloc(sizeof(cfi_intel_pri_ext_t));\r
342         target_t *target = bank->target;\r
343         u8 command[8];\r
344 \r
345         cfi_info->pri_ext = pri_ext;\r
346 \r
347         pri_ext->pri[0] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0);\r
348         pri_ext->pri[1] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 1);\r
349         pri_ext->pri[2] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 2);\r
350 \r
351         if ((pri_ext->pri[0] != 'P') || (pri_ext->pri[1] != 'R') || (pri_ext->pri[2] != 'I'))\r
352         {\r
353                 cfi_command(bank, 0xf0, command);\r
354                 target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
355                 cfi_command(bank, 0xff, command);\r
356                 target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
357                 return ERROR_FLASH_BANK_INVALID;\r
358         }\r
359 \r
360         pri_ext->major_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 3);\r
361         pri_ext->minor_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 4);\r
362 \r
363         DEBUG("pri: '%c%c%c', version: %c.%c", pri_ext->pri[0], pri_ext->pri[1], pri_ext->pri[2], pri_ext->major_version, pri_ext->minor_version);\r
364 \r
365         pri_ext->feature_support = cfi_query_u32(bank, 0, cfi_info->pri_addr + 5);\r
366         pri_ext->suspend_cmd_support = cfi_query_u8(bank, 0, cfi_info->pri_addr + 9);\r
367         pri_ext->blk_status_reg_mask = cfi_query_u16(bank, 0, cfi_info->pri_addr + 0xa);\r
368 \r
369         DEBUG("feature_support: 0x%x, suspend_cmd_support: 0x%x, blk_status_reg_mask: 0x%x", pri_ext->feature_support, pri_ext->suspend_cmd_support, pri_ext->blk_status_reg_mask);\r
370 \r
371         pri_ext->vcc_optimal = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0xc);\r
372         pri_ext->vpp_optimal = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0xd);\r
373 \r
374         DEBUG("Vcc opt: %1.1x.%1.1x, Vpp opt: %1.1x.%1.1x",\r
375                   (pri_ext->vcc_optimal & 0xf0) >> 4, pri_ext->vcc_optimal & 0x0f,\r
376                   (pri_ext->vpp_optimal & 0xf0) >> 4, pri_ext->vpp_optimal & 0x0f);\r
377 \r
378         pri_ext->num_protection_fields = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0xe);\r
379         if (pri_ext->num_protection_fields != 1)\r
380         {\r
381                 WARNING("expected one protection register field, but found %i", pri_ext->num_protection_fields);\r
382         }\r
383 \r
384         pri_ext->prot_reg_addr = cfi_query_u16(bank, 0, cfi_info->pri_addr + 0xf);\r
385         pri_ext->fact_prot_reg_size = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0x11);\r
386         pri_ext->user_prot_reg_size = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0x12);\r
387 \r
388         DEBUG("protection_fields: %i, prot_reg_addr: 0x%x, factory pre-programmed: %i, user programmable: %i", pri_ext->num_protection_fields, pri_ext->prot_reg_addr, 1 << pri_ext->fact_prot_reg_size, 1 << pri_ext->user_prot_reg_size);\r
389 \r
390         return ERROR_OK;\r
391 }\r
392 \r
393 int cfi_read_spansion_pri_ext(flash_bank_t *bank)\r
394 {\r
395         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
396         cfi_spansion_pri_ext_t *pri_ext = malloc(sizeof(cfi_spansion_pri_ext_t));\r
397         target_t *target = bank->target;\r
398         u8 command[8];\r
399 \r
400         cfi_info->pri_ext = pri_ext;\r
401 \r
402         pri_ext->pri[0] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0);\r
403         pri_ext->pri[1] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 1);\r
404         pri_ext->pri[2] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 2);\r
405 \r
406         if ((pri_ext->pri[0] != 'P') || (pri_ext->pri[1] != 'R') || (pri_ext->pri[2] != 'I'))\r
407         {\r
408                 cfi_command(bank, 0xf0, command);\r
409                 target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
410                 return ERROR_FLASH_BANK_INVALID;\r
411         }\r
412 \r
413         pri_ext->major_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 3);\r
414         pri_ext->minor_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 4);\r
415 \r
416         DEBUG("pri: '%c%c%c', version: %c.%c", pri_ext->pri[0], pri_ext->pri[1], pri_ext->pri[2], pri_ext->major_version, pri_ext->minor_version);\r
417 \r
418         pri_ext->SiliconRevision = cfi_query_u8(bank, 0, cfi_info->pri_addr + 5);\r
419         pri_ext->EraseSuspend    = cfi_query_u8(bank, 0, cfi_info->pri_addr + 6);\r
420         pri_ext->BlkProt         = cfi_query_u8(bank, 0, cfi_info->pri_addr + 7);\r
421         pri_ext->TmpBlkUnprotect = cfi_query_u8(bank, 0, cfi_info->pri_addr + 8);\r
422         pri_ext->BlkProtUnprot   = cfi_query_u8(bank, 0, cfi_info->pri_addr + 9);\r
423         pri_ext->SimultaneousOps = cfi_query_u8(bank, 0, cfi_info->pri_addr + 10);\r
424         pri_ext->BurstMode       = cfi_query_u8(bank, 0, cfi_info->pri_addr + 11);\r
425         pri_ext->PageMode        = cfi_query_u8(bank, 0, cfi_info->pri_addr + 12);\r
426         pri_ext->VppMin          = cfi_query_u8(bank, 0, cfi_info->pri_addr + 13);\r
427         pri_ext->VppMax          = cfi_query_u8(bank, 0, cfi_info->pri_addr + 14);\r
428         pri_ext->TopBottom       = cfi_query_u8(bank, 0, cfi_info->pri_addr + 15);\r
429 \r
430         DEBUG("Silicon Revision: 0x%x, Erase Suspend: 0x%x, Block protect: 0x%x", pri_ext->SiliconRevision,\r
431               pri_ext->EraseSuspend, pri_ext->BlkProt);\r
432 \r
433         DEBUG("Temporary Unprotect: 0x%x, Block Protect Scheme: 0x%x, Simultaneous Ops: 0x%x", pri_ext->TmpBlkUnprotect,\r
434               pri_ext->BlkProtUnprot, pri_ext->SimultaneousOps);\r
435 \r
436         DEBUG("Burst Mode: 0x%x, Page Mode: 0x%x, ", pri_ext->BurstMode, pri_ext->PageMode);\r
437 \r
438 \r
439         DEBUG("Vpp min: %2.2d.%1.1d, Vpp max: %2.2d.%1.1x",\r
440                   (pri_ext->VppMin & 0xf0) >> 4, pri_ext->VppMin & 0x0f,\r
441                   (pri_ext->VppMax & 0xf0) >> 4, pri_ext->VppMax & 0x0f);\r
442 \r
443         DEBUG("WP# protection 0x%x", pri_ext->TopBottom);\r
444 \r
445         /* default values for implementation specific workarounds */\r
446         pri_ext->_unlock1 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock1;\r
447         pri_ext->_unlock2 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock2;\r
448         pri_ext->_reversed_geometry = 0;\r
449 \r
450         return ERROR_OK;\r
451 }\r
452 \r
453 int cfi_read_atmel_pri_ext(flash_bank_t *bank)\r
454 {\r
455         cfi_atmel_pri_ext_t atmel_pri_ext;\r
456         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
457         cfi_spansion_pri_ext_t *pri_ext = malloc(sizeof(cfi_spansion_pri_ext_t));\r
458         target_t *target = bank->target;\r
459         u8 command[8];\r
460 \r
461         /* ATMEL devices use the same CFI primary command set (0x2) as AMD/Spansion,\r
462          * but a different primary extended query table.\r
463          * We read the atmel table, and prepare a valid AMD/Spansion query table.\r
464          */\r
465 \r
466         memset(pri_ext, 0, sizeof(cfi_spansion_pri_ext_t));\r
467 \r
468         cfi_info->pri_ext = pri_ext;\r
469 \r
470         atmel_pri_ext.pri[0] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0);\r
471         atmel_pri_ext.pri[1] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 1);\r
472         atmel_pri_ext.pri[2] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 2);\r
473 \r
474         if ((atmel_pri_ext.pri[0] != 'P') || (atmel_pri_ext.pri[1] != 'R') || (atmel_pri_ext.pri[2] != 'I'))\r
475         {\r
476                 cfi_command(bank, 0xf0, command);\r
477                 target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
478                 return ERROR_FLASH_BANK_INVALID;\r
479         }\r
480 \r
481         pri_ext->pri[0] = atmel_pri_ext.pri[0];\r
482         pri_ext->pri[1] = atmel_pri_ext.pri[1];\r
483         pri_ext->pri[2] = atmel_pri_ext.pri[2];\r
484 \r
485         atmel_pri_ext.major_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 3);\r
486         atmel_pri_ext.minor_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 4);\r
487 \r
488         DEBUG("pri: '%c%c%c', version: %c.%c", atmel_pri_ext.pri[0], atmel_pri_ext.pri[1], atmel_pri_ext.pri[2], atmel_pri_ext.major_version, atmel_pri_ext.minor_version);\r
489 \r
490         pri_ext->major_version = atmel_pri_ext.major_version;\r
491         pri_ext->minor_version = atmel_pri_ext.minor_version;\r
492 \r
493         atmel_pri_ext.features = cfi_query_u8(bank, 0, cfi_info->pri_addr + 5);\r
494         atmel_pri_ext.bottom_boot = cfi_query_u8(bank, 0, cfi_info->pri_addr + 6);\r
495         atmel_pri_ext.burst_mode = cfi_query_u8(bank, 0, cfi_info->pri_addr + 7);\r
496         atmel_pri_ext.page_mode = cfi_query_u8(bank, 0, cfi_info->pri_addr + 8);\r
497 \r
498         DEBUG("features: 0x%2.2x, bottom_boot: 0x%2.2x, burst_mode: 0x%2.2x, page_mode: 0x%2.2x",\r
499                 atmel_pri_ext.features, atmel_pri_ext.bottom_boot, atmel_pri_ext.burst_mode, atmel_pri_ext.page_mode);\r
500 \r
501         if (atmel_pri_ext.features & 0x02)\r
502                 pri_ext->EraseSuspend = 2;\r
503 \r
504         if (atmel_pri_ext.bottom_boot)\r
505                 pri_ext->TopBottom = 2;\r
506         else\r
507                 pri_ext->TopBottom = 3;\r
508 \r
509         pri_ext->_unlock1 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock1;\r
510         pri_ext->_unlock2 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock2;\r
511 \r
512         return ERROR_OK;\r
513 }\r
514 \r
515 int cfi_read_0002_pri_ext(flash_bank_t *bank)\r
516 {\r
517         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
518 \r
519         if (cfi_info->manufacturer == CFI_MFR_ATMEL)\r
520         {\r
521                 return cfi_read_atmel_pri_ext(bank);\r
522         }\r
523         else\r
524         {\r
525                 return cfi_read_spansion_pri_ext(bank);\r
526         }\r
527 }\r
528 \r
529 int cfi_spansion_info(struct flash_bank_s *bank, char *buf, int buf_size)\r
530 {\r
531         int printed;\r
532         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
533         cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;\r
534 \r
535         printed = snprintf(buf, buf_size, "\nSpansion primary algorithm extend information:\n");\r
536         buf += printed;\r
537         buf_size -= printed;\r
538 \r
539         printed = snprintf(buf, buf_size, "pri: '%c%c%c', version: %c.%c\n", pri_ext->pri[0],\r
540                            pri_ext->pri[1], pri_ext->pri[2],\r
541                            pri_ext->major_version, pri_ext->minor_version);\r
542         buf += printed;\r
543         buf_size -= printed;\r
544 \r
545         printed = snprintf(buf, buf_size, "Silicon Rev.: 0x%x, Address Sensitive unlock: 0x%x\n",\r
546                            (pri_ext->SiliconRevision) >> 2,\r
547                            (pri_ext->SiliconRevision) & 0x03);\r
548         buf += printed;\r
549         buf_size -= printed;\r
550 \r
551         printed = snprintf(buf, buf_size, "Erase Suspend: 0x%x, Sector Protect: 0x%x\n",\r
552                            pri_ext->EraseSuspend,\r
553                            pri_ext->BlkProt);\r
554         buf += printed;\r
555         buf_size -= printed;\r
556 \r
557         printed = snprintf(buf, buf_size, "VppMin: %2.2d.%1.1x, VppMax: %2.2d.%1.1x\n",\r
558                 (pri_ext->VppMin & 0xf0) >> 4, pri_ext->VppMin & 0x0f,\r
559                 (pri_ext->VppMax & 0xf0) >> 4, pri_ext->VppMax & 0x0f);\r
560 \r
561         return ERROR_OK;\r
562 }\r
563 \r
564 int cfi_intel_info(struct flash_bank_s *bank, char *buf, int buf_size)\r
565 {\r
566         int printed;\r
567         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
568         cfi_intel_pri_ext_t *pri_ext = cfi_info->pri_ext;\r
569 \r
570         printed = snprintf(buf, buf_size, "\nintel primary algorithm extend information:\n");\r
571         buf += printed;\r
572         buf_size -= printed;\r
573 \r
574         printed = snprintf(buf, buf_size, "pri: '%c%c%c', version: %c.%c\n", pri_ext->pri[0], pri_ext->pri[1], pri_ext->pri[2], pri_ext->major_version, pri_ext->minor_version);\r
575         buf += printed;\r
576         buf_size -= printed;\r
577 \r
578         printed = snprintf(buf, buf_size, "feature_support: 0x%x, suspend_cmd_support: 0x%x, blk_status_reg_mask: 0x%x\n", pri_ext->feature_support, pri_ext->suspend_cmd_support, pri_ext->blk_status_reg_mask);\r
579         buf += printed;\r
580         buf_size -= printed;\r
581 \r
582         printed = snprintf(buf, buf_size, "Vcc opt: %1.1x.%1.1x, Vpp opt: %1.1x.%1.1x\n",\r
583                 (pri_ext->vcc_optimal & 0xf0) >> 4, pri_ext->vcc_optimal & 0x0f,\r
584                 (pri_ext->vpp_optimal & 0xf0) >> 4, pri_ext->vpp_optimal & 0x0f);\r
585         buf += printed;\r
586         buf_size -= printed;\r
587 \r
588         printed = snprintf(buf, buf_size, "protection_fields: %i, prot_reg_addr: 0x%x, factory pre-programmed: %i, user programmable: %i\n", pri_ext->num_protection_fields, pri_ext->prot_reg_addr, 1 << pri_ext->fact_prot_reg_size, 1 << pri_ext->user_prot_reg_size);\r
589 \r
590         return ERROR_OK;\r
591 }\r
592 \r
593 int cfi_register_commands(struct command_context_s *cmd_ctx)\r
594 {\r
595         /*command_t *cfi_cmd = */\r
596         register_command(cmd_ctx, NULL, "cfi", NULL, COMMAND_ANY, "flash bank cfi <base> <size> <chip_width> <bus_width> <targetNum> [jedec_probe/x16_as_x8]");\r
597         /*\r
598         register_command(cmd_ctx, cfi_cmd, "part_id", cfi_handle_part_id_command, COMMAND_EXEC,\r
599                                          "print part id of cfi flash bank <num>");\r
600         */\r
601         return ERROR_OK;\r
602 }\r
603 \r
604 /* flash_bank cfi <base> <size> <chip_width> <bus_width> <target#> [options]\r
605  */\r
606 int cfi_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)\r
607 {\r
608         cfi_flash_bank_t *cfi_info;\r
609         int i;\r
610 \r
611         if (argc < 6)\r
612         {\r
613                 WARNING("incomplete flash_bank cfi configuration");\r
614                 return ERROR_FLASH_BANK_INVALID;\r
615         }\r
616 \r
617         if ((strtoul(args[4], NULL, 0) > CFI_MAX_CHIP_WIDTH)\r
618                 || (strtoul(args[3], NULL, 0) > CFI_MAX_BUS_WIDTH))\r
619         {\r
620                 ERROR("chip and bus width have to specified in bytes");\r
621                 return ERROR_FLASH_BANK_INVALID;\r
622         }\r
623 \r
624         cfi_info = malloc(sizeof(cfi_flash_bank_t));\r
625         cfi_info->probed = 0;\r
626         bank->driver_priv = cfi_info;\r
627 \r
628         cfi_info->write_algorithm = NULL;\r
629         cfi_info->erase_check_algorithm = NULL;\r
630 \r
631         cfi_info->x16_as_x8 = 0;\r
632         cfi_info->jedec_probe = 0;\r
633         cfi_info->not_cfi = 0;\r
634 \r
635         for (i = 6; i < argc; i++)\r
636         {\r
637                 if (strcmp(args[i], "x16_as_x8") == 0)\r
638                 {\r
639                         cfi_info->x16_as_x8 = 1;\r
640                 }\r
641                 else if (strcmp(args[i], "jedec_probe") == 0)\r
642                 {\r
643                         cfi_info->jedec_probe = 1;\r
644                 }\r
645         }\r
646 \r
647         cfi_info->write_algorithm = NULL;\r
648 \r
649         /* bank wasn't probed yet */\r
650         cfi_info->qry[0] = -1;\r
651 \r
652         return ERROR_OK;\r
653 }\r
654 \r
655 int cfi_intel_erase(struct flash_bank_s *bank, int first, int last)\r
656 {\r
657         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
658         target_t *target = bank->target;\r
659         u8 command[8];\r
660         int i;\r
661 \r
662         cfi_intel_clear_status_register(bank);\r
663 \r
664         for (i = first; i <= last; i++)\r
665         {\r
666                 cfi_command(bank, 0x20, command);\r
667                 target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);\r
668 \r
669                 cfi_command(bank, 0xd0, command);\r
670                 target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);\r
671 \r
672                 if (cfi_intel_wait_status_busy(bank, 1000 * (1 << cfi_info->block_erase_timeout_typ)) == 0x80)\r
673                         bank->sectors[i].is_erased = 1;\r
674                 else\r
675                 {\r
676                         cfi_command(bank, 0xff, command);\r
677                         target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
678 \r
679                         ERROR("couldn't erase block %i of flash bank at base 0x%x", i, bank->base);\r
680                         return ERROR_FLASH_OPERATION_FAILED;\r
681                 }\r
682         }\r
683 \r
684         cfi_command(bank, 0xff, command);\r
685         target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
686 \r
687         return ERROR_OK;\r
688 }\r
689 \r
690 int cfi_spansion_erase(struct flash_bank_s *bank, int first, int last)\r
691 {\r
692         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
693         cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;\r
694         target_t *target = bank->target;\r
695         u8 command[8];\r
696         int i;\r
697 \r
698         for (i = first; i <= last; i++)\r
699         {\r
700                 cfi_command(bank, 0xaa, command);\r
701                 target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);\r
702 \r
703                 cfi_command(bank, 0x55, command);\r
704                 target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock2), bank->bus_width, 1, command);\r
705 \r
706                 cfi_command(bank, 0x80, command);\r
707                 target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);\r
708 \r
709                 cfi_command(bank, 0xaa, command);\r
710                 target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);\r
711 \r
712                 cfi_command(bank, 0x55, command);\r
713                 target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock2), bank->bus_width, 1, command);\r
714 \r
715                 cfi_command(bank, 0x30, command);\r
716                 target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);\r
717 \r
718                 if (cfi_spansion_wait_status_busy(bank, 1000 * (1 << cfi_info->block_erase_timeout_typ)) == ERROR_OK)\r
719                         bank->sectors[i].is_erased = 1;\r
720                 else\r
721                 {\r
722                         cfi_command(bank, 0xf0, command);\r
723                         target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
724 \r
725                         ERROR("couldn't erase block %i of flash bank at base 0x%x", i, bank->base);\r
726                         return ERROR_FLASH_OPERATION_FAILED;\r
727                 }\r
728         }\r
729 \r
730         cfi_command(bank, 0xf0, command);\r
731         target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
732 \r
733         return ERROR_OK;\r
734 }\r
735 \r
736 int cfi_erase(struct flash_bank_s *bank, int first, int last)\r
737 {\r
738         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
739 \r
740         if (bank->target->state != TARGET_HALTED)\r
741         {\r
742                 return ERROR_TARGET_NOT_HALTED;\r
743         }\r
744 \r
745         if ((first < 0) || (last < first) || (last >= bank->num_sectors))\r
746         {\r
747                 return ERROR_FLASH_SECTOR_INVALID;\r
748         }\r
749 \r
750         if (cfi_info->qry[0] != 'Q')\r
751                 return ERROR_FLASH_BANK_NOT_PROBED;\r
752 \r
753         switch(cfi_info->pri_id)\r
754         {\r
755                 case 1:\r
756                 case 3:\r
757                         return cfi_intel_erase(bank, first, last);\r
758                         break;\r
759                 case 2:\r
760                         return cfi_spansion_erase(bank, first, last);\r
761                         break;\r
762                 default:\r
763                         ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);\r
764                         break;\r
765         }\r
766 \r
767         return ERROR_OK;\r
768 }\r
769 \r
770 int cfi_intel_protect(struct flash_bank_s *bank, int set, int first, int last)\r
771 {\r
772         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
773         cfi_intel_pri_ext_t *pri_ext = cfi_info->pri_ext;\r
774         target_t *target = bank->target;\r
775         u8 command[8];\r
776         int retry = 0;\r
777         int i;\r
778 \r
779         /* if the device supports neither legacy lock/unlock (bit 3) nor\r
780          * instant individual block locking (bit 5).\r
781          */\r
782         if (!(pri_ext->feature_support & 0x28))\r
783                 return ERROR_FLASH_OPERATION_FAILED;\r
784 \r
785         cfi_intel_clear_status_register(bank);\r
786 \r
787         for (i = first; i <= last; i++)\r
788         {\r
789                 cfi_command(bank, 0x60, command);\r
790                 DEBUG("address: 0x%4.4x, command: 0x%4.4x", flash_address(bank, i, 0x0), target_buffer_get_u32(target, command));\r
791                 target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);\r
792                 if (set)\r
793                 {\r
794                         cfi_command(bank, 0x01, command);\r
795                         DEBUG("address: 0x%4.4x, command: 0x%4.4x", flash_address(bank, i, 0x0), target_buffer_get_u32(target, command));\r
796                         target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);\r
797                         bank->sectors[i].is_protected = 1;\r
798                 }\r
799                 else\r
800                 {\r
801                         cfi_command(bank, 0xd0, command);\r
802                         DEBUG("address: 0x%4.4x, command: 0x%4.4x", flash_address(bank, i, 0x0), target_buffer_get_u32(target, command));\r
803                         target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);\r
804                         bank->sectors[i].is_protected = 0;\r
805                 }\r
806 \r
807                 /* instant individual block locking doesn't require reading of the status register */\r
808                 if (!(pri_ext->feature_support & 0x20))\r
809                 {\r
810                         /* Clear lock bits operation may take up to 1.4s */\r
811                         cfi_intel_wait_status_busy(bank, 1400);\r
812                 }\r
813                 else\r
814                 {\r
815                         u8 block_status;\r
816                         /* read block lock bit, to verify status */\r
817                         cfi_command(bank, 0x90, command);\r
818                         target->type->write_memory(target, flash_address(bank, 0, 0x55), bank->bus_width, 1, command);\r
819                         block_status = cfi_get_u8(bank, i, 0x2);\r
820 \r
821                         if ((block_status & 0x1) != set)\r
822                         {\r
823                                 ERROR("couldn't change block lock status (set = %i, block_status = 0x%2.2x)", set, block_status);\r
824                                 cfi_command(bank, 0x70, command);\r
825                                 target->type->write_memory(target, flash_address(bank, 0, 0x55), bank->bus_width, 1, command);\r
826                                 cfi_intel_wait_status_busy(bank, 10);\r
827 \r
828                                 if (retry > 10)\r
829                                         return ERROR_FLASH_OPERATION_FAILED;\r
830                                 else\r
831                                 {\r
832                                         i--;\r
833                                         retry++;\r
834                                 }\r
835                         }\r
836                 }\r
837         }\r
838 \r
839         /* if the device doesn't support individual block lock bits set/clear,\r
840          * all blocks have been unlocked in parallel, so we set those that should be protected\r
841          */\r
842         if ((!set) && (!(pri_ext->feature_support & 0x20)))\r
843         {\r
844                 for (i = 0; i < bank->num_sectors; i++)\r
845                 {\r
846                         if (bank->sectors[i].is_protected == 1)\r
847                         {\r
848                                 cfi_intel_clear_status_register(bank);\r
849 \r
850                                 cfi_command(bank, 0x60, command);\r
851                                 target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);\r
852 \r
853                                 cfi_command(bank, 0x01, command);\r
854                                 target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);\r
855 \r
856                                 cfi_intel_wait_status_busy(bank, 100);\r
857                         }\r
858                 }\r
859         }\r
860 \r
861         cfi_command(bank, 0xff, command);\r
862         target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
863 \r
864         return ERROR_OK;\r
865 }\r
866 \r
867 int cfi_protect(struct flash_bank_s *bank, int set, int first, int last)\r
868 {\r
869         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
870 \r
871         if (bank->target->state != TARGET_HALTED)\r
872         {\r
873                 return ERROR_TARGET_NOT_HALTED;\r
874         }\r
875 \r
876         if ((first < 0) || (last < first) || (last >= bank->num_sectors))\r
877         {\r
878                 return ERROR_FLASH_SECTOR_INVALID;\r
879         }\r
880 \r
881         if (cfi_info->qry[0] != 'Q')\r
882                 return ERROR_FLASH_BANK_NOT_PROBED;\r
883 \r
884         switch(cfi_info->pri_id)\r
885         {\r
886                 case 1:\r
887                 case 3:\r
888                         cfi_intel_protect(bank, set, first, last);\r
889                         break;\r
890                 default:\r
891                         ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);\r
892                         break;\r
893         }\r
894 \r
895         return ERROR_OK;\r
896 }\r
897 \r
898 /* FIXME Replace this by a simple memcpy() - still unsure about sideeffects */\r
899 static void cfi_add_byte(struct flash_bank_s *bank, u8 *word, u8 byte)\r
900 {\r
901         //target_t *target = bank->target;\r
902 \r
903         int i;\r
904 \r
905         // NOTE:\r
906         // The data to flash must not be changed in endian! We write a bytestrem in\r
907         // target byte order already. Only the control and status byte lane of the flash\r
908         // WSM is interpreted by the CPU in different ways, when read a u16 or u32\r
909         // word (data seems to be in the upper or lower byte lane for u16 accesses).\r
910 \r
911         //if (target->endianness == TARGET_LITTLE_ENDIAN)\r
912         //{\r
913                 /* shift bytes */\r
914                 for (i = 0; i < bank->bus_width - 1; i++)\r
915                         word[i] = word[i + 1];\r
916                 word[bank->bus_width - 1] = byte;\r
917         //}\r
918         //else\r
919         //{\r
920         //      /* shift bytes */\r
921         //      for (i = bank->bus_width - 1; i > 0; i--)\r
922         //              word[i] = word[i - 1];\r
923         //      word[0] = byte;\r
924         //}\r
925 }\r
926 \r
927 /* Convert code image to target endian */\r
928 /* FIXME create general block conversion fcts in target.c?) */ static\r
929 void cfi_fix_code_endian(target_t *target, u32 *dest, const u32 *src, u32 count)\r
930 {\r
931         u32 i;\r
932         for (i=0; i< count; i++)\r
933         {\r
934                 target_buffer_set_u32(target, (u8*)dest, *src);\r
935                 dest++;\r
936                 src++;\r
937         }\r
938 }\r
939 \r
940 int cfi_intel_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u32 count)\r
941 {\r
942         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
943         target_t *target = bank->target;\r
944         reg_param_t reg_params[7];\r
945         armv4_5_algorithm_t armv4_5_info;\r
946         working_area_t *source;\r
947         u32 buffer_size = 32768;\r
948         u8 write_command_buf[CFI_MAX_BUS_WIDTH];\r
949         u8 busy_pattern_buf[CFI_MAX_BUS_WIDTH];\r
950         u8 error_pattern_buf[CFI_MAX_BUS_WIDTH];\r
951         u32 write_command_val, busy_pattern_val, error_pattern_val;\r
952 \r
953         /* algorithm register usage:\r
954          * r0: source address (in RAM)\r
955          * r1: target address (in Flash)\r
956          * r2: count\r
957          * r3: flash write command\r
958          * r4: status byte (returned to host)\r
959          * r5: busy test pattern\r
960          * r6: error test pattern\r
961          */\r
962 \r
963         static const u32 word_32_code[] = {\r
964                 0xe4904004,   /* loop:  ldr r4, [r0], #4 */\r
965                 0xe5813000,   /*                str r3, [r1] */\r
966                 0xe5814000,   /*                str r4, [r1] */\r
967                 0xe5914000,   /* busy:  ldr r4, [r1] */\r
968                 0xe0047005,   /*                and r7, r4, r5 */\r
969                 0xe1570005,   /*                cmp r7, r5 */\r
970                 0x1afffffb,   /*                bne busy */\r
971                 0xe1140006,   /*                tst r4, r6 */\r
972                 0x1a000003,   /*                bne done */\r
973                 0xe2522001,   /*                subs r2, r2, #1 */\r
974                 0x0a000001,   /*                beq done */\r
975                 0xe2811004,   /*                add r1, r1 #4 */\r
976                 0xeafffff2,   /*                b loop */\r
977                 0xeafffffe    /* done:  b -2 */\r
978         };\r
979 \r
980         static const u32 word_16_code[] = {\r
981                 0xe0d040b2,   /* loop:  ldrh r4, [r0], #2 */\r
982                 0xe1c130b0,   /*                strh r3, [r1] */\r
983                 0xe1c140b0,   /*                strh r4, [r1] */\r
984                 0xe1d140b0,   /* busy   ldrh r4, [r1] */\r
985                 0xe0047005,   /*                and r7, r4, r5 */\r
986                 0xe1570005,   /*                cmp r7, r5 */\r
987                 0x1afffffb,   /*                bne busy */\r
988                 0xe1140006,   /*                tst r4, r6 */\r
989                 0x1a000003,   /*                bne done */\r
990                 0xe2522001,   /*                subs r2, r2, #1 */\r
991                 0x0a000001,   /*                beq done */\r
992                 0xe2811002,   /*                add r1, r1 #2 */\r
993                 0xeafffff2,   /*                b loop */\r
994                 0xeafffffe    /* done:  b -2 */\r
995         };\r
996 \r
997         static const u32 word_8_code[] = {\r
998                 0xe4d04001,   /* loop:  ldrb r4, [r0], #1 */\r
999                 0xe5c13000,   /*                strb r3, [r1] */\r
1000                 0xe5c14000,   /*                strb r4, [r1] */\r
1001                 0xe5d14000,   /* busy   ldrb r4, [r1] */\r
1002                 0xe0047005,   /*                and r7, r4, r5 */\r
1003                 0xe1570005,   /*                cmp r7, r5 */\r
1004                 0x1afffffb,   /*                bne busy */\r
1005                 0xe1140006,   /*                tst r4, r6 */\r
1006                 0x1a000003,   /*                bne done */\r
1007                 0xe2522001,   /*                subs r2, r2, #1 */\r
1008                 0x0a000001,   /*                beq done */\r
1009                 0xe2811001,   /*                add r1, r1 #1 */\r
1010                 0xeafffff2,   /*                b loop */\r
1011                 0xeafffffe    /* done:  b -2 */\r
1012         };\r
1013         u32 target_code[CFI_MAX_INTEL_CODESIZE];\r
1014         const u32 *target_code_src;\r
1015         int target_code_size;\r
1016         int retval = ERROR_OK;\r
1017 \r
1018 \r
1019         cfi_intel_clear_status_register(bank);\r
1020 \r
1021         armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;\r
1022         armv4_5_info.core_mode = ARMV4_5_MODE_SVC;\r
1023         armv4_5_info.core_state = ARMV4_5_STATE_ARM;\r
1024 \r
1025         /* If we are setting up the write_algorith, we need target_code_src */\r
1026         /* if not we only need target_code_size.                                                                                                                */\r
1027         /*                                                                                                                                                                                                                                                                      */\r
1028         /* However, we don't want to create multiple code paths, so we                  */\r
1029         /* do the unecessary evaluation of target_code_src, which the                   */\r
1030         /* compiler will probably nicely optimize away if not needed                            */\r
1031 \r
1032         /* prepare algorithm code for target endian */\r
1033         switch (bank->bus_width)\r
1034         {\r
1035         case 1 :\r
1036                 target_code_src = word_8_code;\r
1037                 target_code_size = sizeof(word_8_code);\r
1038                 break;\r
1039         case 2 :\r
1040                 target_code_src = word_16_code;\r
1041                 target_code_size = sizeof(word_16_code);\r
1042                 break;\r
1043         case 4 :\r
1044                 target_code_src = word_32_code;\r
1045                 target_code_size = sizeof(word_32_code);\r
1046                 break;\r
1047         default:\r
1048                 ERROR("Unsupported bank buswidth %d, can't do block memory writes", bank->bus_width);\r
1049                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;\r
1050         }\r
1051 \r
1052         /* flash write code */\r
1053         if (!cfi_info->write_algorithm)\r
1054         {\r
1055                 if ( target_code_size > sizeof(target_code) )\r
1056                 {\r
1057                         WARNING("Internal error - target code buffer to small. Increase CFI_MAX_INTEL_CODESIZE and recompile.");\r
1058                         return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;\r
1059                 }\r
1060                 cfi_fix_code_endian(target, target_code, target_code_src, target_code_size);\r
1061 \r
1062                 /* Get memory for block write handler */\r
1063                 retval = target_alloc_working_area(target, target_code_size, &cfi_info->write_algorithm);\r
1064                 if (retval != ERROR_OK)\r
1065                 {\r
1066                         WARNING("No working area available, can't do block memory writes");\r
1067                         return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;\r
1068                 };\r
1069 \r
1070                 /* write algorithm code to working area */\r
1071                 retval = target_write_buffer(target, cfi_info->write_algorithm->address, target_code_size, (u8*)target_code);\r
1072                 if (retval != ERROR_OK)\r
1073                 {\r
1074                         ERROR("Unable to write block write code to target");\r
1075                         goto cleanup;\r
1076                 }\r
1077         }\r
1078 \r
1079         /* Get a workspace buffer for the data to flash starting with 32k size.\r
1080            Half size until buffer would be smaller 256 Bytem then fail back */\r
1081         /* FIXME Why 256 bytes, why not 32 bytes (smallest flash write page */\r
1082         while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)\r
1083         {\r
1084                 buffer_size /= 2;\r
1085                 if (buffer_size <= 256)\r
1086                 {\r
1087                         WARNING("no large enough working area available, can't do block memory writes");\r
1088                         retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;\r
1089                         goto cleanup;\r
1090                 }\r
1091         };\r
1092 \r
1093         /* setup algo registers */\r
1094         init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);\r
1095         init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);\r
1096         init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);\r
1097         init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);\r
1098         init_reg_param(&reg_params[4], "r4", 32, PARAM_IN);\r
1099         init_reg_param(&reg_params[5], "r5", 32, PARAM_OUT);\r
1100         init_reg_param(&reg_params[6], "r6", 32, PARAM_OUT);\r
1101 \r
1102         /* prepare command and status register patterns */\r
1103         cfi_command(bank, 0x40, write_command_buf);\r
1104         cfi_command(bank, 0x80, busy_pattern_buf);\r
1105         cfi_command(bank, 0x7e, error_pattern_buf);\r
1106 \r
1107         switch (bank->bus_width)\r
1108         {\r
1109         case 1 :\r
1110                 write_command_val = write_command_buf[0];\r
1111                 busy_pattern_val = busy_pattern_buf[0];\r
1112                 error_pattern_val = error_pattern_buf[0];\r
1113                 break;\r
1114         case 2 :\r
1115                 write_command_val = target_buffer_get_u16(target, write_command_buf);\r
1116                 busy_pattern_val = target_buffer_get_u16(target, busy_pattern_buf);\r
1117                 error_pattern_val = target_buffer_get_u16(target, error_pattern_buf);\r
1118                 break;\r
1119         case 4 :\r
1120                 write_command_val = target_buffer_get_u32(target, write_command_buf);\r
1121                 busy_pattern_val = target_buffer_get_u32(target, busy_pattern_buf);\r
1122                 error_pattern_val = target_buffer_get_u32(target, error_pattern_buf);\r
1123                 break;\r
1124         default :\r
1125                 ERROR("Unsupported bank buswidth %d, can't do block memory writes", bank->bus_width);\r
1126                 retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;\r
1127                 goto cleanup;\r
1128         }\r
1129 \r
1130         INFO("Using target buffer at 0x%08x and of size 0x%04x", source->address, buffer_size );\r
1131 \r
1132         /* Programming main loop */\r
1133         while (count > 0)\r
1134         {\r
1135                 u32 thisrun_count = (count > buffer_size) ? buffer_size : count;\r
1136                 u32 wsm_error;\r
1137 \r
1138                 target_write_buffer(target, source->address, thisrun_count, buffer);\r
1139 \r
1140                 buf_set_u32(reg_params[0].value, 0, 32, source->address);\r
1141                 buf_set_u32(reg_params[1].value, 0, 32, address);\r
1142                 buf_set_u32(reg_params[2].value, 0, 32, thisrun_count / bank->bus_width);\r
1143 \r
1144                 buf_set_u32(reg_params[3].value, 0, 32, write_command_val);\r
1145                 buf_set_u32(reg_params[5].value, 0, 32, busy_pattern_val);\r
1146                 buf_set_u32(reg_params[6].value, 0, 32, error_pattern_val);\r
1147 \r
1148                 INFO("Write 0x%04x bytes to flash at 0x%08x", thisrun_count, address );\r
1149 \r
1150                 /* Execute algorithm, assume breakpoint for last instruction */\r
1151                 retval = target->type->run_algorithm(target, 0, NULL, 7, reg_params,\r
1152                         cfi_info->write_algorithm->address,\r
1153                         cfi_info->write_algorithm->address + target_code_size - sizeof(u32),\r
1154                         10000, /* 10s should be enough for max. 32k of data */\r
1155                         &armv4_5_info);\r
1156 \r
1157                 /* On failure try a fall back to direct word writes */\r
1158                 if (retval != ERROR_OK)\r
1159                 {\r
1160                         cfi_intel_clear_status_register(bank);\r
1161                         ERROR("Execution of flash algorythm failed. Can't fall back. Please report.");\r
1162                         retval = ERROR_FLASH_OPERATION_FAILED;\r
1163                         //retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;\r
1164                         // FIXME To allow fall back or recovery, we must save the actual status\r
1165                         //       somewhere, so that a higher level code can start recovery.\r
1166                         goto cleanup;\r
1167                 }\r
1168 \r
1169                 /* Check return value from algo code */\r
1170                 wsm_error = buf_get_u32(reg_params[4].value, 0, 32) & error_pattern_val;\r
1171                 if (wsm_error)\r
1172                 {\r
1173                         /* read status register (outputs debug inforation) */\r
1174                         cfi_intel_wait_status_busy(bank, 100);\r
1175                         cfi_intel_clear_status_register(bank);\r
1176                         retval = ERROR_FLASH_OPERATION_FAILED;\r
1177                         goto cleanup;\r
1178                 }\r
1179 \r
1180                 buffer += thisrun_count;\r
1181                 address += thisrun_count;\r
1182                 count -= thisrun_count;\r
1183         }\r
1184 \r
1185         /* free up resources */\r
1186 cleanup:\r
1187         if (source)\r
1188                 target_free_working_area(target, source);\r
1189 \r
1190         if (cfi_info->write_algorithm)\r
1191         {\r
1192                 target_free_working_area(target, cfi_info->write_algorithm);\r
1193                 cfi_info->write_algorithm = NULL;\r
1194         }\r
1195 \r
1196         destroy_reg_param(&reg_params[0]);\r
1197         destroy_reg_param(&reg_params[1]);\r
1198         destroy_reg_param(&reg_params[2]);\r
1199         destroy_reg_param(&reg_params[3]);\r
1200         destroy_reg_param(&reg_params[4]);\r
1201         destroy_reg_param(&reg_params[5]);\r
1202         destroy_reg_param(&reg_params[6]);\r
1203 \r
1204         return retval;\r
1205 }\r
1206 \r
1207 int cfi_spansion_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u32 count)\r
1208 {\r
1209         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
1210         cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;\r
1211         target_t *target = bank->target;\r
1212         reg_param_t reg_params[10];\r
1213         armv4_5_algorithm_t armv4_5_info;\r
1214         working_area_t *source;\r
1215         u32 buffer_size = 32768;\r
1216         u8 write_command[CFI_MAX_BUS_WIDTH];\r
1217         u32 status;\r
1218         int i;\r
1219         int retval;\r
1220         int exit_code = ERROR_OK;\r
1221 \r
1222         /* input parameters - */\r
1223         /*      R0 = source address */\r
1224         /*      R1 = destination address */\r
1225         /*      R2 = number of writes */\r
1226         /*      R3 = flash write command */\r
1227         /*      R4 = constant to mask DQ7 bits (also used for Dq5 with shift) */\r
1228         /* output parameters - */\r
1229         /*      R5 = 0x80 ok 0x00 bad */\r
1230         /* temp registers - */\r
1231         /*      R6 = value read from flash to test status */\r
1232         /*      R7 = holding register */\r
1233         /* unlock registers - */\r
1234         /*  R8 = unlock1_addr */\r
1235         /*  R9 = unlock1_cmd */\r
1236         /*  R10 = unlock2_addr */\r
1237         /*  R11 = unlock2_cmd */\r
1238 \r
1239         u32 word_32_code[] = {\r
1240                                                 /* 00008100 <sp_32_code>:               */\r
1241                 0xe4905004,             /* ldr  r5, [r0], #4                    */\r
1242                 0xe5889000,     /* str  r9, [r8]                                */\r
1243                 0xe58ab000,     /* str  r11, [r10]                              */\r
1244                 0xe5883000,     /* str  r3, [r8]                                */\r
1245                 0xe5815000,     /* str  r5, [r1]                                */\r
1246                 0xe1a00000,     /* nop                                                  */\r
1247                                                 /*                                                              */\r
1248                                                 /* 00008110 <sp_32_busy>:               */\r
1249                 0xe5916000,     /* ldr  r6, [r1]                                */\r
1250                 0xe0257006,     /* eor  r7, r5, r6                              */\r
1251                 0xe0147007,     /* ands r7, r4, r7                              */\r
1252                 0x0a000007,     /* beq  8140 <sp_32_cont> ; b if DQ7 == Data7 */\r
1253                 0xe0166124,     /* ands r6, r6, r4, lsr #2              */\r
1254                 0x0afffff9,     /* beq  8110 <sp_32_busy> ;     b if DQ5 low */\r
1255                 0xe5916000,     /* ldr  r6, [r1]                                */\r
1256                 0xe0257006,     /* eor  r7, r5, r6                              */\r
1257                 0xe0147007,     /* ands r7, r4, r7                              */\r
1258                 0x0a000001,     /* beq  8140 <sp_32_cont> ; b if DQ7 == Data7 */\r
1259                 0xe3a05000,     /* mov  r5, #0  ; 0x0 - return 0x00, error */\r
1260                 0x1a000004,     /* bne  8154 <sp_32_done>               */\r
1261                                                 /*                                                              */\r
1262                                 /* 00008140 <sp_32_cont>:                               */\r
1263                 0xe2522001,     /* subs r2, r2, #1      ; 0x1           */\r
1264                 0x03a05080,     /* moveq        r5, #128        ; 0x80  */\r
1265                 0x0a000001,     /* beq  8154 <sp_32_done>               */\r
1266                 0xe2811004,     /* add  r1, r1, #4      ; 0x4           */\r
1267                 0xeaffffe8,     /* b    8100 <sp_32_code>               */\r
1268                                                 /*                                                              */\r
1269                                                 /* 00008154 <sp_32_done>:               */\r
1270                 0xeafffffe              /* b    8154 <sp_32_done>               */\r
1271                 };\r
1272 \r
1273                 u32 word_16_code[] = {\r
1274                                 /* 00008158 <sp_16_code>:              */\r
1275                 0xe0d050b2,     /* ldrh r5, [r0], #2               */\r
1276                 0xe1c890b0,     /* strh r9, [r8]                                */\r
1277                 0xe1cab0b0,     /* strh r11, [r10]                              */\r
1278                 0xe1c830b0,     /* strh r3, [r8]                                */\r
1279                 0xe1c150b0,     /* strh r5, [r1]                       */\r
1280                 0xe1a00000,     /* nop                  (mov r0,r0)    */\r
1281                                 /*                                     */\r
1282                                 /* 00008168 <sp_16_busy>:              */\r
1283                 0xe1d160b0,     /* ldrh r6, [r1]                       */\r
1284                 0xe0257006,     /* eor  r7, r5, r6                     */\r
1285                 0xe0147007,     /* ands r7, r4, r7                     */\r
1286                 0x0a000007,     /* beq  8198 <sp_16_cont>              */\r
1287                 0xe0166124,     /* ands r6, r6, r4, lsr #2             */\r
1288                 0x0afffff9,     /* beq  8168 <sp_16_busy>              */\r
1289                 0xe1d160b0,     /* ldrh r6, [r1]                       */\r
1290                 0xe0257006,     /* eor  r7, r5, r6                     */\r
1291                 0xe0147007,     /* ands r7, r4, r7                     */\r
1292                 0x0a000001,     /* beq  8198 <sp_16_cont>              */\r
1293                 0xe3a05000,     /* mov  r5, #0  ; 0x0                  */\r
1294                 0x1a000004,     /* bne  81ac <sp_16_done>              */\r
1295                                 /*                                     */\r
1296                                 /* 00008198 <sp_16_cont>:              */\r
1297                 0xe2522001,     /* subs r2, r2, #1      ; 0x1          */\r
1298                 0x03a05080,     /* moveq        r5, #128        ; 0x80 */\r
1299                 0x0a000001,     /* beq  81ac <sp_16_done>              */\r
1300                 0xe2811002,     /* add  r1, r1, #2      ; 0x2          */\r
1301                 0xeaffffe8,     /* b    8158 <sp_16_code>              */\r
1302                                 /*                                     */\r
1303                                 /* 000081ac <sp_16_done>:              */\r
1304                 0xeafffffe      /* b    81ac <sp_16_done>              */\r
1305                 };\r
1306 \r
1307                 u32 word_8_code[] = {\r
1308                                 /* 000081b0 <sp_16_code_end>:          */\r
1309                 0xe4d05001,     /* ldrb r5, [r0], #1                   */\r
1310                 0xe5c89000,     /* strb r9, [r8]                                */\r
1311                 0xe5cab000,     /* strb r11, [r10]                              */\r
1312                 0xe5c83000,     /* strb r3, [r8]                                */\r
1313                 0xe5c15000,     /* strb r5, [r1]                       */\r
1314                 0xe1a00000,     /* nop                  (mov r0,r0)    */\r
1315                                 /*                                     */\r
1316                                 /* 000081c0 <sp_8_busy>:               */\r
1317                 0xe5d16000,     /* ldrb r6, [r1]                       */\r
1318                 0xe0257006,     /* eor  r7, r5, r6                     */\r
1319                 0xe0147007,     /* ands r7, r4, r7                     */\r
1320                 0x0a000007,     /* beq  81f0 <sp_8_cont>               */\r
1321                 0xe0166124,     /* ands r6, r6, r4, lsr #2             */\r
1322                 0x0afffff9,     /* beq  81c0 <sp_8_busy>               */\r
1323                 0xe5d16000,     /* ldrb r6, [r1]                       */\r
1324                 0xe0257006,     /* eor  r7, r5, r6                     */\r
1325                 0xe0147007,     /* ands r7, r4, r7                     */\r
1326                 0x0a000001,     /* beq  81f0 <sp_8_cont>               */\r
1327                 0xe3a05000,     /* mov  r5, #0  ; 0x0                  */\r
1328                 0x1a000004,     /* bne  8204 <sp_8_done>               */\r
1329                                 /*                                     */\r
1330                                 /* 000081f0 <sp_8_cont>:               */\r
1331                 0xe2522001,     /* subs r2, r2, #1      ; 0x1          */\r
1332                 0x03a05080,     /* moveq        r5, #128        ; 0x80 */\r
1333                 0x0a000001,     /* beq  8204 <sp_8_done>               */\r
1334                 0xe2811001,     /* add  r1, r1, #1      ; 0x1          */\r
1335                 0xeaffffe8,     /* b    81b0 <sp_16_code_end>          */\r
1336                                 /*                                     */\r
1337                                 /* 00008204 <sp_8_done>:               */\r
1338                 0xeafffffe      /* b    8204 <sp_8_done>               */\r
1339         };\r
1340 \r
1341         armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;\r
1342         armv4_5_info.core_mode = ARMV4_5_MODE_SVC;\r
1343         armv4_5_info.core_state = ARMV4_5_STATE_ARM;\r
1344 \r
1345         /* flash write code */\r
1346         if (!cfi_info->write_algorithm)\r
1347         {\r
1348                 u8 *code_p;\r
1349 \r
1350                 /* convert bus-width dependent algorithm code to correct endiannes */\r
1351                 if (bank->bus_width == 1)\r
1352                 {\r
1353                         code_p = malloc(24 * 4);\r
1354 \r
1355                         for (i = 0; i < 24; i++)\r
1356                                 target_buffer_set_u32(target, code_p + (i*4), word_8_code[i]);\r
1357                 }\r
1358                 else if (bank->bus_width == 2)\r
1359                 {\r
1360                         code_p = malloc(24 * 4);\r
1361 \r
1362                         for (i = 0; i < 24; i++)\r
1363                                 target_buffer_set_u32(target, code_p + (i*4), word_16_code[i]);\r
1364                 }\r
1365                 else if (bank->bus_width == 4)\r
1366                 {\r
1367                         code_p = malloc(24 * 4);\r
1368 \r
1369                         for (i = 0; i < 24; i++)\r
1370                                 target_buffer_set_u32(target, code_p + (i*4), word_32_code[i]);\r
1371                 }\r
1372                 else\r
1373                 {\r
1374                         return ERROR_FLASH_OPERATION_FAILED;\r
1375                 }\r
1376 \r
1377                 /* allocate working area */\r
1378                 if (target_alloc_working_area(target, 24 * 4,\r
1379                         &cfi_info->write_algorithm) != ERROR_OK)\r
1380                 {\r
1381                         WARNING("no working area available, can't do block memory writes");\r
1382                         return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;\r
1383                 }\r
1384 \r
1385                 /* write algorithm code to working area */\r
1386                 target_write_buffer(target, cfi_info->write_algorithm->address, 24 * 4, code_p);\r
1387 \r
1388                 free(code_p);\r
1389         }\r
1390 \r
1391         while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)\r
1392         {\r
1393                 buffer_size /= 2;\r
1394                 if (buffer_size <= 256)\r
1395                 {\r
1396                         /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */\r
1397                         if (cfi_info->write_algorithm)\r
1398                                 target_free_working_area(target, cfi_info->write_algorithm);\r
1399 \r
1400                         WARNING("not enough working area available, can't do block memory writes");\r
1401                         return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;\r
1402                 }\r
1403         };\r
1404 \r
1405         init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);\r
1406         init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);\r
1407         init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);\r
1408         init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);\r
1409         init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT);\r
1410         init_reg_param(&reg_params[5], "r5", 32, PARAM_IN);\r
1411         init_reg_param(&reg_params[6], "r8", 32, PARAM_OUT);\r
1412         init_reg_param(&reg_params[7], "r9", 32, PARAM_OUT);\r
1413         init_reg_param(&reg_params[8], "r10", 32, PARAM_OUT);\r
1414         init_reg_param(&reg_params[9], "r11", 32, PARAM_OUT);\r
1415 \r
1416         while (count > 0)\r
1417         {\r
1418                 u32 thisrun_count = (count > buffer_size) ? buffer_size : count;\r
1419 \r
1420                 target_write_buffer(target, source->address, thisrun_count, buffer);\r
1421 \r
1422                 buf_set_u32(reg_params[0].value, 0, 32, source->address);\r
1423                 buf_set_u32(reg_params[1].value, 0, 32, address);\r
1424                 buf_set_u32(reg_params[2].value, 0, 32, thisrun_count / bank->bus_width);\r
1425                 cfi_command(bank, 0xA0, write_command);\r
1426                 buf_set_u32(reg_params[3].value, 0, 32, buf_get_u32(write_command, 0, 32));\r
1427                 cfi_command(bank, 0x80, write_command);\r
1428                 buf_set_u32(reg_params[4].value, 0, 32, buf_get_u32(write_command, 0, 32));\r
1429                 buf_set_u32(reg_params[6].value, 0, 32, flash_address(bank, 0, pri_ext->_unlock1));\r
1430                 buf_set_u32(reg_params[7].value, 0, 32, 0xaa);\r
1431                 buf_set_u32(reg_params[8].value, 0, 32, flash_address(bank, 0, pri_ext->_unlock2));\r
1432                 buf_set_u32(reg_params[9].value, 0, 32, 0x55);\r
1433 \r
1434                 retval = target->type->run_algorithm(target, 0, NULL, 10, reg_params,\r
1435                                                      cfi_info->write_algorithm->address,\r
1436                                                      cfi_info->write_algorithm->address + ((24 * 4) - 4),\r
1437                                                      10000, &armv4_5_info);\r
1438 \r
1439                 status = buf_get_u32(reg_params[5].value, 0, 32);\r
1440 \r
1441                 if ((retval != ERROR_OK) || status != 0x80)\r
1442                 {\r
1443                         DEBUG("status: 0x%x", status);\r
1444                         exit_code = ERROR_FLASH_OPERATION_FAILED;\r
1445                         break;\r
1446                 }\r
1447 \r
1448                 buffer += thisrun_count;\r
1449                 address += thisrun_count;\r
1450                 count -= thisrun_count;\r
1451         }\r
1452 \r
1453         target_free_working_area(target, source);\r
1454 \r
1455         destroy_reg_param(&reg_params[0]);\r
1456         destroy_reg_param(&reg_params[1]);\r
1457         destroy_reg_param(&reg_params[2]);\r
1458         destroy_reg_param(&reg_params[3]);\r
1459         destroy_reg_param(&reg_params[4]);\r
1460         destroy_reg_param(&reg_params[5]);\r
1461         destroy_reg_param(&reg_params[6]);\r
1462         destroy_reg_param(&reg_params[7]);\r
1463         destroy_reg_param(&reg_params[8]);\r
1464         destroy_reg_param(&reg_params[9]);\r
1465 \r
1466         return exit_code;\r
1467 }\r
1468 \r
1469 int cfi_intel_write_word(struct flash_bank_s *bank, u8 *word, u32 address)\r
1470 {\r
1471         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
1472         target_t *target = bank->target;\r
1473         u8 command[8];\r
1474 \r
1475         cfi_intel_clear_status_register(bank);\r
1476         cfi_command(bank, 0x40, command);\r
1477         target->type->write_memory(target, address, bank->bus_width, 1, command);\r
1478 \r
1479         target->type->write_memory(target, address, bank->bus_width, 1, word);\r
1480 \r
1481         if (cfi_intel_wait_status_busy(bank, 1000 * (1 << cfi_info->word_write_timeout_max)) != 0x80)\r
1482         {\r
1483                 cfi_command(bank, 0xff, command);\r
1484                 target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
1485 \r
1486                 ERROR("couldn't write word at base 0x%x, address %x", bank->base, address);\r
1487                 return ERROR_FLASH_OPERATION_FAILED;\r
1488         }\r
1489 \r
1490         return ERROR_OK;\r
1491 }\r
1492 \r
1493 int cfi_intel_write_words(struct flash_bank_s *bank, u8 *word, u32 wordcount, u32 address)\r
1494 {\r
1495         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
1496         target_t *target = bank->target;\r
1497         u8 command[8];\r
1498 \r
1499         /* Calculate buffer size and boundary mask */\r
1500         u32 buffersize = 1UL << cfi_info->max_buf_write_size;\r
1501         u32 buffermask = buffersize-1;\r
1502         u32 bufferwsize;\r
1503 \r
1504         /* Check for valid range */\r
1505         if (address & buffermask)\r
1506         {\r
1507                 ERROR("Write address at base 0x%x, address %x not aligned to 2^%d boundary", bank->base, address, cfi_info->max_buf_write_size);\r
1508                 return ERROR_FLASH_OPERATION_FAILED;\r
1509         }\r
1510         switch(bank->chip_width)\r
1511         {\r
1512         case 4 : bufferwsize = buffersize / 4; break;\r
1513         case 2 : bufferwsize = buffersize / 2; break;\r
1514         case 1 : bufferwsize = buffersize; break;\r
1515         default:\r
1516                 ERROR("Unsupported chip width %d", bank->chip_width);\r
1517                 return ERROR_FLASH_OPERATION_FAILED;\r
1518         }\r
1519 \r
1520         /* Check for valid size */\r
1521         if (wordcount > bufferwsize)\r
1522         {\r
1523                 ERROR("Number of data words %d exceeds available buffersize %d", wordcount, buffersize);\r
1524                 return ERROR_FLASH_OPERATION_FAILED;\r
1525         }\r
1526 \r
1527         /* Write to flash buffer */\r
1528         cfi_intel_clear_status_register(bank);\r
1529 \r
1530         /* Initiate buffer operation _*/\r
1531         cfi_command(bank, 0xE8, command);\r
1532         target->type->write_memory(target, address, bank->bus_width, 1, command);\r
1533         if (cfi_intel_wait_status_busy(bank, 1000 * (1 << cfi_info->buf_write_timeout_max)) != 0x80)\r
1534         {\r
1535                 cfi_command(bank, 0xff, command);\r
1536                 target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
1537 \r
1538                 ERROR("couldn't start buffer write operation at base 0x%x, address %x", bank->base, address);\r
1539                 return ERROR_FLASH_OPERATION_FAILED;\r
1540         }\r
1541 \r
1542         /* Write buffer wordcount-1 and data words */\r
1543         cfi_command(bank, bufferwsize-1, command);\r
1544         target->type->write_memory(target, address, bank->bus_width, 1, command);\r
1545 \r
1546         target->type->write_memory(target, address, bank->bus_width, bufferwsize, word);\r
1547 \r
1548         /* Commit write operation */\r
1549         cfi_command(bank, 0xd0, command);\r
1550         target->type->write_memory(target, address, bank->bus_width, 1, command);\r
1551         if (cfi_intel_wait_status_busy(bank, 1000 * (1 << cfi_info->buf_write_timeout_max)) != 0x80)\r
1552         {\r
1553                 cfi_command(bank, 0xff, command);\r
1554                 target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
1555 \r
1556                 ERROR("Buffer write at base 0x%x, address %x failed.", bank->base, address);\r
1557                 return ERROR_FLASH_OPERATION_FAILED;\r
1558         }\r
1559 \r
1560         return ERROR_OK;\r
1561 }\r
1562 \r
1563 int cfi_spansion_write_word(struct flash_bank_s *bank, u8 *word, u32 address)\r
1564 {\r
1565         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
1566         cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;\r
1567         target_t *target = bank->target;\r
1568         u8 command[8];\r
1569 \r
1570         cfi_command(bank, 0xaa, command);\r
1571         target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);\r
1572 \r
1573         cfi_command(bank, 0x55, command);\r
1574         target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock2), bank->bus_width, 1, command);\r
1575 \r
1576         cfi_command(bank, 0xa0, command);\r
1577         target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);\r
1578 \r
1579         target->type->write_memory(target, address, bank->bus_width, 1, word);\r
1580 \r
1581         if (cfi_spansion_wait_status_busy(bank, 1000 * (1 << cfi_info->word_write_timeout_max)) != ERROR_OK)\r
1582         {\r
1583                 cfi_command(bank, 0xf0, command);\r
1584                 target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
1585 \r
1586                 ERROR("couldn't write word at base 0x%x, address %x", bank->base, address);\r
1587                 return ERROR_FLASH_OPERATION_FAILED;\r
1588         }\r
1589 \r
1590         return ERROR_OK;\r
1591 }\r
1592 \r
1593 int cfi_write_word(struct flash_bank_s *bank, u8 *word, u32 address)\r
1594 {\r
1595         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
1596 \r
1597         switch(cfi_info->pri_id)\r
1598         {\r
1599                 case 1:\r
1600                 case 3:\r
1601                         return cfi_intel_write_word(bank, word, address);\r
1602                         break;\r
1603                 case 2:\r
1604                         return cfi_spansion_write_word(bank, word, address);\r
1605                         break;\r
1606                 default:\r
1607                         ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);\r
1608                         break;\r
1609         }\r
1610 \r
1611         return ERROR_FLASH_OPERATION_FAILED;\r
1612 }\r
1613 \r
1614 int cfi_write_words(struct flash_bank_s *bank, u8 *word, u32 wordcount, u32 address)\r
1615 {\r
1616         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
1617 \r
1618         switch(cfi_info->pri_id)\r
1619         {\r
1620                 case 1:\r
1621                 case 3:\r
1622                         return cfi_intel_write_words(bank, word, wordcount, address);\r
1623                         break;\r
1624                 case 2:\r
1625                         //return cfi_spansion_write_words(bank, word, address);\r
1626                         ERROR("cfi primary command set %i unimplemented - FIXME", cfi_info->pri_id);\r
1627                         break;\r
1628                 default:\r
1629                         ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);\r
1630                         break;\r
1631         }\r
1632 \r
1633         return ERROR_FLASH_OPERATION_FAILED;\r
1634 }\r
1635 \r
1636 int cfi_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)\r
1637 {\r
1638         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
1639         target_t *target = bank->target;\r
1640         u32 address = bank->base + offset;      /* address of first byte to be programmed */\r
1641         u32 write_p, copy_p;\r
1642         int align;      /* number of unaligned bytes */\r
1643         int blk_count; /* number of bus_width bytes for block copy */\r
1644         u8 current_word[CFI_MAX_BUS_WIDTH * 4]; /* word (bus_width size) currently being programmed */\r
1645         int i;\r
1646         int retval;\r
1647 \r
1648         if (bank->target->state != TARGET_HALTED)\r
1649         {\r
1650                 return ERROR_TARGET_NOT_HALTED;\r
1651         }\r
1652 \r
1653         if (offset + count > bank->size)\r
1654                 return ERROR_FLASH_DST_OUT_OF_BANK;\r
1655 \r
1656         if (cfi_info->qry[0] != 'Q')\r
1657                 return ERROR_FLASH_BANK_NOT_PROBED;\r
1658 \r
1659         /* start at the first byte of the first word (bus_width size) */\r
1660         write_p = address & ~(bank->bus_width - 1);\r
1661         if ((align = address - write_p) != 0)\r
1662         {\r
1663                 INFO("Fixup %d unaligned head bytes", align );\r
1664 \r
1665                 for (i = 0; i < bank->bus_width; i++)\r
1666                         current_word[i] = 0;\r
1667                 copy_p = write_p;\r
1668 \r
1669                 /* copy bytes before the first write address */\r
1670                 for (i = 0; i < align; ++i, ++copy_p)\r
1671                 {\r
1672                         u8 byte;\r
1673                         target->type->read_memory(target, copy_p, 1, 1, &byte);\r
1674                         cfi_add_byte(bank, current_word, byte);\r
1675                 }\r
1676 \r
1677                 /* add bytes from the buffer */\r
1678                 for (; (i < bank->bus_width) && (count > 0); i++)\r
1679                 {\r
1680                         cfi_add_byte(bank, current_word, *buffer++);\r
1681                         count--;\r
1682                         copy_p++;\r
1683                 }\r
1684 \r
1685                 /* if the buffer is already finished, copy bytes after the last write address */\r
1686                 for (; (count == 0) && (i < bank->bus_width); ++i, ++copy_p)\r
1687                 {\r
1688                         u8 byte;\r
1689                         target->type->read_memory(target, copy_p, 1, 1, &byte);\r
1690                         cfi_add_byte(bank, current_word, byte);\r
1691                 }\r
1692 \r
1693                 retval = cfi_write_word(bank, current_word, write_p);\r
1694                 if (retval != ERROR_OK)\r
1695                         return retval;\r
1696                 write_p = copy_p;\r
1697         }\r
1698 \r
1699         /* handle blocks of bus_size aligned bytes */\r
1700         blk_count = count & ~(bank->bus_width - 1); /* round down, leave tail bytes */\r
1701         switch(cfi_info->pri_id)\r
1702         {\r
1703                 /* try block writes (fails without working area) */\r
1704                 case 1:\r
1705                 case 3:\r
1706                         retval = cfi_intel_write_block(bank, buffer, write_p, blk_count);\r
1707                         break;\r
1708                 case 2:\r
1709                         retval = cfi_spansion_write_block(bank, buffer, write_p, blk_count);\r
1710                         break;\r
1711                 default:\r
1712                         ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);\r
1713                         retval = ERROR_FLASH_OPERATION_FAILED;\r
1714                         break;\r
1715         }\r
1716         if (retval == ERROR_OK)\r
1717         {\r
1718                 /* Increment pointers and decrease count on succesful block write */\r
1719                 buffer += blk_count;\r
1720                 write_p += blk_count;\r
1721                 count -= blk_count;\r
1722         }\r
1723         else\r
1724         {\r
1725                 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)\r
1726                 {\r
1727                         u32 buffersize = 1UL << cfi_info->max_buf_write_size;\r
1728                         u32 buffermask = buffersize-1;\r
1729                         u32 bufferwsize;\r
1730 \r
1731                         switch(bank->chip_width)\r
1732                         {\r
1733                         case 4 : bufferwsize = buffersize / 4; break;\r
1734                         case 2 : bufferwsize = buffersize / 2; break;\r
1735                         case 1 : bufferwsize = buffersize; break;\r
1736                         default:\r
1737                                 ERROR("Unsupported chip width %d", bank->chip_width);\r
1738                                 return ERROR_FLASH_OPERATION_FAILED;\r
1739                         }\r
1740 \r
1741                         /* fall back to memory writes */\r
1742                         while (count > bank->bus_width)\r
1743                         {\r
1744                                 if ((write_p & 0xff) == 0)\r
1745                                 {\r
1746                                         INFO("Programming at %08x, count %08x bytes remaining", write_p, count);\r
1747                                 }\r
1748 #if 0\r
1749                                 /* NB! this is broken for spansion! */\r
1750                                 if ((count > bufferwsize) && !(write_p & buffermask))\r
1751                                 {\r
1752                                         retval = cfi_write_words(bank, buffer, bufferwsize, write_p);\r
1753                                         if (retval != ERROR_OK)\r
1754                                                 return retval;\r
1755 \r
1756                                         buffer += buffersize;\r
1757                                         write_p += buffersize;\r
1758                                         count -= buffersize;\r
1759                                 }\r
1760                                 else\r
1761 #endif\r
1762                                 {\r
1763                                         for (i = 0; i < bank->bus_width; i++)\r
1764                                                 current_word[i] = 0;\r
1765 \r
1766                                         for (i = 0; i < bank->bus_width; i++)\r
1767                                         {\r
1768                                                 cfi_add_byte(bank, current_word, *buffer++);\r
1769                                         }\r
1770 \r
1771                                         retval = cfi_write_word(bank, current_word, write_p);\r
1772                                         if (retval != ERROR_OK)\r
1773                                                 return retval;\r
1774 \r
1775                                         write_p += bank->bus_width;\r
1776                                         count -= bank->bus_width;\r
1777                                 }\r
1778                         }\r
1779                 }\r
1780                 else\r
1781                         return retval;\r
1782         }\r
1783 \r
1784         /* return to read array mode, so we can read from flash again for padding */\r
1785         cfi_command(bank, 0xf0, current_word);\r
1786         target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, current_word);\r
1787         cfi_command(bank, 0xff, current_word);\r
1788         target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, current_word);\r
1789 \r
1790         /* handle unaligned tail bytes */\r
1791         if (count > 0)\r
1792         {\r
1793                 INFO("Fixup %d unaligned tail bytes", count );\r
1794 \r
1795                 copy_p = write_p;\r
1796                 for (i = 0; i < bank->bus_width; i++)\r
1797                         current_word[i] = 0;\r
1798 \r
1799                 for (i = 0; (i < bank->bus_width) && (count > 0); ++i, ++copy_p)\r
1800                 {\r
1801                         cfi_add_byte(bank, current_word, *buffer++);\r
1802                         count--;\r
1803                 }\r
1804                 for (; i < bank->bus_width; ++i, ++copy_p)\r
1805                 {\r
1806                         u8 byte;\r
1807                         target->type->read_memory(target, copy_p, 1, 1, &byte);\r
1808                         cfi_add_byte(bank, current_word, byte);\r
1809                 }\r
1810                 retval = cfi_write_word(bank, current_word, write_p);\r
1811                 if (retval != ERROR_OK)\r
1812                         return retval;\r
1813         }\r
1814 \r
1815         /* return to read array mode */\r
1816         cfi_command(bank, 0xf0, current_word);\r
1817         target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, current_word);\r
1818         cfi_command(bank, 0xff, current_word);\r
1819         target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, current_word);\r
1820 \r
1821         return ERROR_OK;\r
1822 }\r
1823 \r
1824 void cfi_fixup_atmel_reversed_erase_regions(flash_bank_t *bank, void *param)\r
1825 {\r
1826         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
1827         cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;\r
1828 \r
1829         pri_ext->_reversed_geometry = 1;\r
1830 }\r
1831 \r
1832 void cfi_fixup_0002_erase_regions(flash_bank_t *bank, void *param)\r
1833 {\r
1834         int i;\r
1835         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
1836         cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;\r
1837 \r
1838         if ((pri_ext->_reversed_geometry) || (pri_ext->TopBottom == 3))\r
1839         {\r
1840                 DEBUG("swapping reversed erase region information on cmdset 0002 device");\r
1841 \r
1842                 for (i = 0; i < cfi_info->num_erase_regions / 2; i++)\r
1843                 {\r
1844                         int j = (cfi_info->num_erase_regions - 1) - i;\r
1845                         u32 swap;\r
1846 \r
1847                         swap = cfi_info->erase_region_info[i];\r
1848                         cfi_info->erase_region_info[i] = cfi_info->erase_region_info[j];\r
1849                         cfi_info->erase_region_info[j] = swap;\r
1850                 }\r
1851         }\r
1852 }\r
1853 \r
1854 void cfi_fixup_0002_unlock_addresses(flash_bank_t *bank, void *param)\r
1855 {\r
1856         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
1857         cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;\r
1858         cfi_unlock_addresses_t *unlock_addresses = param;\r
1859 \r
1860         pri_ext->_unlock1 = unlock_addresses->unlock1;\r
1861         pri_ext->_unlock2 = unlock_addresses->unlock2;\r
1862 }\r
1863 \r
1864 int cfi_probe(struct flash_bank_s *bank)\r
1865 {\r
1866         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
1867         target_t *target = bank->target;\r
1868         u8 command[8];\r
1869         int num_sectors = 0;\r
1870         int i;\r
1871         int sector = 0;\r
1872         u32 offset = 0;\r
1873         u32 unlock1 = 0x555;\r
1874         u32 unlock2 = 0x2aa;\r
1875 \r
1876         cfi_info->probed = 0;\r
1877 \r
1878         /* JEDEC standard JESD21C uses 0x5555 and 0x2aaa as unlock addresses,\r
1879          * while CFI compatible AMD/Spansion flashes use 0x555 and 0x2aa\r
1880          */\r
1881         if (cfi_info->jedec_probe)\r
1882         {\r
1883                 unlock1 = 0x5555;\r
1884                 unlock2 = 0x2aaa;\r
1885         }\r
1886 \r
1887         /* switch to read identifier codes mode ("AUTOSELECT") */\r
1888         cfi_command(bank, 0xaa, command);\r
1889         target->type->write_memory(target, flash_address(bank, 0, unlock1), bank->bus_width, 1, command);\r
1890         cfi_command(bank, 0x55, command);\r
1891         target->type->write_memory(target, flash_address(bank, 0, unlock2), bank->bus_width, 1, command);\r
1892         cfi_command(bank, 0x90, command);\r
1893         target->type->write_memory(target, flash_address(bank, 0, unlock1), bank->bus_width, 1, command);\r
1894 \r
1895         if (bank->chip_width == 1)\r
1896         {\r
1897                 u8 manufacturer, device_id;\r
1898                 target_read_u8(target, bank->base + 0x0, &manufacturer);\r
1899                 target_read_u8(target, bank->base + 0x1, &device_id);\r
1900                 cfi_info->manufacturer = manufacturer;\r
1901                 cfi_info->device_id = device_id;\r
1902         }\r
1903         else if (bank->chip_width == 2)\r
1904         {\r
1905                 target_read_u16(target, bank->base + 0x0, &cfi_info->manufacturer);\r
1906                 target_read_u16(target, bank->base + 0x2, &cfi_info->device_id);\r
1907         }\r
1908 \r
1909         /* switch back to read array mode */\r
1910         cfi_command(bank, 0xf0, command);\r
1911         target->type->write_memory(target, flash_address(bank, 0, 0x00), bank->bus_width, 1, command);\r
1912         cfi_command(bank, 0xff, command);\r
1913         target->type->write_memory(target, flash_address(bank, 0, 0x00), bank->bus_width, 1, command);\r
1914 \r
1915         cfi_fixup(bank, cfi_jedec_fixups);\r
1916 \r
1917         /* query only if this is a CFI compatible flash,\r
1918          * otherwise the relevant info has already been filled in\r
1919          */\r
1920         if (cfi_info->not_cfi == 0)\r
1921         {\r
1922                 /* enter CFI query mode\r
1923                  * according to JEDEC Standard No. 68.01,\r
1924                  * a single bus sequence with address = 0x55, data = 0x98 should put\r
1925                  * the device into CFI query mode.\r
1926                  *\r
1927                  * SST flashes clearly violate this, and we will consider them incompatbile for now\r
1928                  */\r
1929                 cfi_command(bank, 0x98, command);\r
1930                 target->type->write_memory(target, flash_address(bank, 0, 0x55), bank->bus_width, 1, command);\r
1931 \r
1932                 cfi_info->qry[0] = cfi_query_u8(bank, 0, 0x10);\r
1933                 cfi_info->qry[1] = cfi_query_u8(bank, 0, 0x11);\r
1934                 cfi_info->qry[2] = cfi_query_u8(bank, 0, 0x12);\r
1935 \r
1936                 DEBUG("CFI qry returned: 0x%2.2x 0x%2.2x 0x%2.2x", cfi_info->qry[0], cfi_info->qry[1], cfi_info->qry[2]);\r
1937 \r
1938                 if ((cfi_info->qry[0] != 'Q') || (cfi_info->qry[1] != 'R') || (cfi_info->qry[2] != 'Y'))\r
1939                 {\r
1940                         cfi_command(bank, 0xf0, command);\r
1941                         target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
1942                         cfi_command(bank, 0xff, command);\r
1943                         target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
1944                         return ERROR_FLASH_BANK_INVALID;\r
1945                 }\r
1946 \r
1947                 cfi_info->pri_id = cfi_query_u16(bank, 0, 0x13);\r
1948                 cfi_info->pri_addr = cfi_query_u16(bank, 0, 0x15);\r
1949                 cfi_info->alt_id = cfi_query_u16(bank, 0, 0x17);\r
1950                 cfi_info->alt_addr = cfi_query_u16(bank, 0, 0x19);\r
1951 \r
1952                 DEBUG("qry: '%c%c%c', pri_id: 0x%4.4x, pri_addr: 0x%4.4x, alt_id: 0x%4.4x, alt_addr: 0x%4.4x", cfi_info->qry[0], cfi_info->qry[1], cfi_info->qry[2], cfi_info->pri_id, cfi_info->pri_addr, cfi_info->alt_id, cfi_info->alt_addr);\r
1953 \r
1954                 cfi_info->vcc_min = cfi_query_u8(bank, 0, 0x1b);\r
1955                 cfi_info->vcc_max = cfi_query_u8(bank, 0, 0x1c);\r
1956                 cfi_info->vpp_min = cfi_query_u8(bank, 0, 0x1d);\r
1957                 cfi_info->vpp_max = cfi_query_u8(bank, 0, 0x1e);\r
1958                 cfi_info->word_write_timeout_typ = cfi_query_u8(bank, 0, 0x1f);\r
1959                 cfi_info->buf_write_timeout_typ = cfi_query_u8(bank, 0, 0x20);\r
1960                 cfi_info->block_erase_timeout_typ = cfi_query_u8(bank, 0, 0x21);\r
1961                 cfi_info->chip_erase_timeout_typ = cfi_query_u8(bank, 0, 0x22);\r
1962                 cfi_info->word_write_timeout_max = cfi_query_u8(bank, 0, 0x23);\r
1963                 cfi_info->buf_write_timeout_max = cfi_query_u8(bank, 0, 0x24);\r
1964                 cfi_info->block_erase_timeout_max = cfi_query_u8(bank, 0, 0x25);\r
1965                 cfi_info->chip_erase_timeout_max = cfi_query_u8(bank, 0, 0x26);\r
1966 \r
1967                 DEBUG("Vcc min: %1.1x.%1.1x, Vcc max: %1.1x.%1.1x, Vpp min: %1.1x.%1.1x, Vpp max: %1.1x.%1.1x",\r
1968                         (cfi_info->vcc_min & 0xf0) >> 4, cfi_info->vcc_min & 0x0f,\r
1969                         (cfi_info->vcc_max & 0xf0) >> 4, cfi_info->vcc_max & 0x0f,\r
1970                         (cfi_info->vpp_min & 0xf0) >> 4, cfi_info->vpp_min & 0x0f,\r
1971                         (cfi_info->vpp_max & 0xf0) >> 4, cfi_info->vpp_max & 0x0f);\r
1972                 DEBUG("typ. word write timeout: %u, typ. buf write timeout: %u, typ. block erase timeout: %u, typ. chip erase timeout: %u", 1 << cfi_info->word_write_timeout_typ, 1 << cfi_info->buf_write_timeout_typ,\r
1973                         1 << cfi_info->block_erase_timeout_typ, 1 << cfi_info->chip_erase_timeout_typ);\r
1974                 DEBUG("max. word write timeout: %u, max. buf write timeout: %u, max. block erase timeout: %u, max. chip erase timeout: %u", (1 << cfi_info->word_write_timeout_max) * (1 << cfi_info->word_write_timeout_typ),\r
1975                         (1 << cfi_info->buf_write_timeout_max) * (1 << cfi_info->buf_write_timeout_typ),\r
1976                         (1 << cfi_info->block_erase_timeout_max) * (1 << cfi_info->block_erase_timeout_typ),\r
1977                         (1 << cfi_info->chip_erase_timeout_max) * (1 << cfi_info->chip_erase_timeout_typ));\r
1978 \r
1979                 cfi_info->dev_size = cfi_query_u8(bank, 0, 0x27);\r
1980                 cfi_info->interface_desc = cfi_query_u16(bank, 0, 0x28);\r
1981                 cfi_info->max_buf_write_size = cfi_query_u16(bank, 0, 0x2a);\r
1982                 cfi_info->num_erase_regions = cfi_query_u8(bank, 0, 0x2c);\r
1983 \r
1984                 DEBUG("size: 0x%x, interface desc: %i, max buffer write size: %x", 1 << cfi_info->dev_size, cfi_info->interface_desc, (1 << cfi_info->max_buf_write_size));\r
1985 \r
1986                 if (((1 << cfi_info->dev_size) * bank->bus_width / bank->chip_width) != bank->size)\r
1987                 {\r
1988                         WARNING("configuration specifies 0x%x size, but a 0x%x size flash was found", bank->size, 1 << cfi_info->dev_size);\r
1989                 }\r
1990 \r
1991                 if (cfi_info->num_erase_regions)\r
1992                 {\r
1993                         cfi_info->erase_region_info = malloc(4 * cfi_info->num_erase_regions);\r
1994                         for (i = 0; i < cfi_info->num_erase_regions; i++)\r
1995                         {\r
1996                                 cfi_info->erase_region_info[i] = cfi_query_u32(bank, 0, 0x2d + (4 * i));\r
1997                                 DEBUG("erase region[%i]: %i blocks of size 0x%x", i, (cfi_info->erase_region_info[i] & 0xffff) + 1, (cfi_info->erase_region_info[i] >> 16) * 256);\r
1998                         }\r
1999                 }\r
2000                 else\r
2001                 {\r
2002                         cfi_info->erase_region_info = NULL;\r
2003                 }\r
2004 \r
2005                 /* We need to read the primary algorithm extended query table before calculating\r
2006                  * the sector layout to be able to apply fixups\r
2007                  */\r
2008                 switch(cfi_info->pri_id)\r
2009                 {\r
2010                         /* Intel command set (standard and extended) */\r
2011                         case 0x0001:\r
2012                         case 0x0003:\r
2013                                 cfi_read_intel_pri_ext(bank);\r
2014                                 break;\r
2015                         /* AMD/Spansion, Atmel, ... command set */\r
2016                         case 0x0002:\r
2017                                 cfi_read_0002_pri_ext(bank);\r
2018                                 break;\r
2019                         default:\r
2020                                 ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);\r
2021                                 break;\r
2022                 }\r
2023 \r
2024                 /* return to read array mode\r
2025                  * we use both reset commands, as some Intel flashes fail to recognize the 0xF0 command\r
2026                  */\r
2027                 cfi_command(bank, 0xf0, command);\r
2028                 target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
2029                 cfi_command(bank, 0xff, command);\r
2030                 target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
2031         }\r
2032 \r
2033         /* apply fixups depending on the primary command set */\r
2034         switch(cfi_info->pri_id)\r
2035         {\r
2036                 /* Intel command set (standard and extended) */\r
2037                 case 0x0001:\r
2038                 case 0x0003:\r
2039                         cfi_fixup(bank, cfi_0001_fixups);\r
2040                         break;\r
2041                 /* AMD/Spansion, Atmel, ... command set */\r
2042                 case 0x0002:\r
2043                         cfi_fixup(bank, cfi_0002_fixups);\r
2044                         break;\r
2045                 default:\r
2046                         ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);\r
2047                         break;\r
2048         }\r
2049 \r
2050         if (cfi_info->num_erase_regions == 0)\r
2051         {\r
2052                 /* a device might have only one erase block, spanning the whole device */\r
2053                 bank->num_sectors = 1;\r
2054                 bank->sectors = malloc(sizeof(flash_sector_t));\r
2055 \r
2056                 bank->sectors[sector].offset = 0x0;\r
2057                 bank->sectors[sector].size = bank->size;\r
2058                 bank->sectors[sector].is_erased = -1;\r
2059                 bank->sectors[sector].is_protected = -1;\r
2060         }\r
2061         else\r
2062         {\r
2063                 for (i = 0; i < cfi_info->num_erase_regions; i++)\r
2064                 {\r
2065                         num_sectors += (cfi_info->erase_region_info[i] & 0xffff) + 1;\r
2066                 }\r
2067 \r
2068                 bank->num_sectors = num_sectors;\r
2069                 bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors);\r
2070 \r
2071                 for (i = 0; i < cfi_info->num_erase_regions; i++)\r
2072                 {\r
2073                         int j;\r
2074                         for (j = 0; j < (cfi_info->erase_region_info[i] & 0xffff) + 1; j++)\r
2075                         {\r
2076                                 bank->sectors[sector].offset = offset;\r
2077                                 bank->sectors[sector].size = ((cfi_info->erase_region_info[i] >> 16) * 256) * bank->bus_width / bank->chip_width;\r
2078                                 offset += bank->sectors[sector].size;\r
2079                                 bank->sectors[sector].is_erased = -1;\r
2080                                 bank->sectors[sector].is_protected = -1;\r
2081                                 sector++;\r
2082                         }\r
2083                 }\r
2084         }\r
2085         \r
2086         cfi_info->probed = 1;\r
2087 \r
2088         return ERROR_OK;\r
2089 }\r
2090 \r
2091 int cfi_auto_probe(struct flash_bank_s *bank)\r
2092 {\r
2093         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
2094         if (cfi_info->probed)\r
2095                 return ERROR_OK;\r
2096         return cfi_probe(bank);\r
2097 }\r
2098 \r
2099 int cfi_erase_check(struct flash_bank_s *bank)\r
2100 {\r
2101         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
2102         target_t *target = bank->target;\r
2103         int i;\r
2104         int retval;\r
2105 \r
2106         if (!cfi_info->erase_check_algorithm)\r
2107         {\r
2108                 u32 erase_check_code[] =\r
2109                 {\r
2110                         0xe4d03001,     /* ldrb r3, [r0], #1    */\r
2111                         0xe0022003, /* and r2, r2, r3           */\r
2112                         0xe2511001, /* subs r1, r1, #1          */\r
2113                         0x1afffffb,     /* b -4                                 */\r
2114                         0xeafffffe      /* b 0                                  */\r
2115                 };\r
2116 \r
2117                 /* make sure we have a working area */\r
2118                 if (target_alloc_working_area(target, 20, &cfi_info->erase_check_algorithm) != ERROR_OK)\r
2119                 {\r
2120                         WARNING("no working area available, falling back to slow memory reads");\r
2121                 }\r
2122                 else\r
2123                 {\r
2124                         u8 erase_check_code_buf[5 * 4];\r
2125 \r
2126                         for (i = 0; i < 5; i++)\r
2127                                 target_buffer_set_u32(target, erase_check_code_buf + (i*4), erase_check_code[i]);\r
2128 \r
2129                         /* write algorithm code to working area */\r
2130                         target->type->write_memory(target, cfi_info->erase_check_algorithm->address, 4, 5, erase_check_code_buf);\r
2131                 }\r
2132         }\r
2133 \r
2134         if (!cfi_info->erase_check_algorithm)\r
2135         {\r
2136                 u32 *buffer = malloc(4096);\r
2137 \r
2138                 for (i = 0; i < bank->num_sectors; i++)\r
2139                 {\r
2140                         u32 address = bank->base + bank->sectors[i].offset;\r
2141                         u32 size = bank->sectors[i].size;\r
2142                         u32 check = 0xffffffffU;\r
2143                         int erased = 1;\r
2144 \r
2145                         while (size > 0)\r
2146                         {\r
2147                                 u32 thisrun_size = (size > 4096) ? 4096 : size;\r
2148                                 int j;\r
2149 \r
2150                                 target->type->read_memory(target, address, 4, thisrun_size / 4, (u8*)buffer);\r
2151 \r
2152                                 for (j = 0; j < thisrun_size / 4; j++)\r
2153                                         check &= buffer[j];\r
2154 \r
2155                                 if (check != 0xffffffff)\r
2156                                 {\r
2157                                         erased = 0;\r
2158                                         break;\r
2159                                 }\r
2160 \r
2161                                 size -= thisrun_size;\r
2162                                 address += thisrun_size;\r
2163                         }\r
2164 \r
2165                         bank->sectors[i].is_erased = erased;\r
2166                 }\r
2167 \r
2168                 free(buffer);\r
2169         }\r
2170         else\r
2171         {\r
2172                 for (i = 0; i < bank->num_sectors; i++)\r
2173                 {\r
2174                         u32 address = bank->base + bank->sectors[i].offset;\r
2175                         u32 size = bank->sectors[i].size;\r
2176 \r
2177                         reg_param_t reg_params[3];\r
2178                         armv4_5_algorithm_t armv4_5_info;\r
2179 \r
2180                         armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;\r
2181                         armv4_5_info.core_mode = ARMV4_5_MODE_SVC;\r
2182                         armv4_5_info.core_state = ARMV4_5_STATE_ARM;\r
2183 \r
2184                         init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);\r
2185                         buf_set_u32(reg_params[0].value, 0, 32, address);\r
2186 \r
2187                         init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);\r
2188                         buf_set_u32(reg_params[1].value, 0, 32, size);\r
2189 \r
2190                         init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);\r
2191                         buf_set_u32(reg_params[2].value, 0, 32, 0xff);\r
2192 \r
2193                         if ((retval = target->type->run_algorithm(target, 0, NULL, 3, reg_params, cfi_info->erase_check_algorithm->address, cfi_info->erase_check_algorithm->address + 0x10, 10000, &armv4_5_info)) != ERROR_OK)\r
2194                                 return ERROR_FLASH_OPERATION_FAILED;\r
2195 \r
2196                         if (buf_get_u32(reg_params[2].value, 0, 32) == 0xff)\r
2197                                 bank->sectors[i].is_erased = 1;\r
2198                         else\r
2199                                 bank->sectors[i].is_erased = 0;\r
2200 \r
2201                         destroy_reg_param(&reg_params[0]);\r
2202                         destroy_reg_param(&reg_params[1]);\r
2203                         destroy_reg_param(&reg_params[2]);\r
2204                 }\r
2205         }\r
2206 \r
2207         return ERROR_OK;\r
2208 }\r
2209 \r
2210 int cfi_intel_protect_check(struct flash_bank_s *bank)\r
2211 {\r
2212         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
2213         cfi_intel_pri_ext_t *pri_ext = cfi_info->pri_ext;\r
2214         target_t *target = bank->target;\r
2215         u8 command[CFI_MAX_BUS_WIDTH];\r
2216         int i;\r
2217 \r
2218         /* check if block lock bits are supported on this device */\r
2219         if (!(pri_ext->blk_status_reg_mask & 0x1))\r
2220                 return ERROR_FLASH_OPERATION_FAILED;\r
2221 \r
2222         cfi_command(bank, 0x90, command);\r
2223         target->type->write_memory(target, flash_address(bank, 0, 0x55), bank->bus_width, 1, command);\r
2224 \r
2225         for (i = 0; i < bank->num_sectors; i++)\r
2226         {\r
2227                 u8 block_status = cfi_get_u8(bank, i, 0x2);\r
2228 \r
2229                 if (block_status & 1)\r
2230                         bank->sectors[i].is_protected = 1;\r
2231                 else\r
2232                         bank->sectors[i].is_protected = 0;\r
2233         }\r
2234 \r
2235         cfi_command(bank, 0xff, command);\r
2236         target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
2237 \r
2238         return ERROR_OK;\r
2239 }\r
2240 \r
2241 int cfi_spansion_protect_check(struct flash_bank_s *bank)\r
2242 {\r
2243         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
2244         cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;\r
2245         target_t *target = bank->target;\r
2246         u8 command[8];\r
2247         int i;\r
2248 \r
2249         cfi_command(bank, 0xaa, command);\r
2250         target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);\r
2251 \r
2252         cfi_command(bank, 0x55, command);\r
2253         target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock2), bank->bus_width, 1, command);\r
2254 \r
2255         cfi_command(bank, 0x90, command);\r
2256         target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);\r
2257 \r
2258         for (i = 0; i < bank->num_sectors; i++)\r
2259         {\r
2260                 u8 block_status = cfi_get_u8(bank, i, 0x2);\r
2261 \r
2262                 if (block_status & 1)\r
2263                         bank->sectors[i].is_protected = 1;\r
2264                 else\r
2265                         bank->sectors[i].is_protected = 0;\r
2266         }\r
2267 \r
2268         cfi_command(bank, 0xf0, command);\r
2269         target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
2270 \r
2271         return ERROR_OK;\r
2272 }\r
2273 \r
2274 int cfi_protect_check(struct flash_bank_s *bank)\r
2275 {\r
2276         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
2277 \r
2278         if (cfi_info->qry[0] != 'Q')\r
2279                 return ERROR_FLASH_BANK_NOT_PROBED;\r
2280 \r
2281         switch(cfi_info->pri_id)\r
2282         {\r
2283                 case 1:\r
2284                 case 3:\r
2285                         return cfi_intel_protect_check(bank);\r
2286                         break;\r
2287                 case 2:\r
2288                         return cfi_spansion_protect_check(bank);\r
2289                         break;\r
2290                 default:\r
2291                         ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);\r
2292                         break;\r
2293         }\r
2294 \r
2295         return ERROR_OK;\r
2296 }\r
2297 \r
2298 int cfi_info(struct flash_bank_s *bank, char *buf, int buf_size)\r
2299 {\r
2300         int printed;\r
2301         cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
2302 \r
2303         if (cfi_info->qry[0] == (char)-1)\r
2304         {\r
2305                 printed = snprintf(buf, buf_size, "\ncfi flash bank not probed yet\n");\r
2306                 return ERROR_OK;\r
2307         }\r
2308 \r
2309         printed = snprintf(buf, buf_size, "\ncfi information:\n");\r
2310         buf += printed;\r
2311         buf_size -= printed;\r
2312 \r
2313         printed = snprintf(buf, buf_size, "\nmfr: 0x%4.4x, id:0x%4.4x\n",\r
2314                 cfi_info->manufacturer, cfi_info->device_id);\r
2315         buf += printed;\r
2316         buf_size -= printed;\r
2317 \r
2318         printed = snprintf(buf, buf_size, "qry: '%c%c%c', pri_id: 0x%4.4x, pri_addr: 0x%4.4x, alt_id: 0x%4.4x, alt_addr: 0x%4.4x\n", cfi_info->qry[0], cfi_info->qry[1], cfi_info->qry[2], cfi_info->pri_id, cfi_info->pri_addr, cfi_info->alt_id, cfi_info->alt_addr);\r
2319         buf += printed;\r
2320         buf_size -= printed;\r
2321 \r
2322         printed = snprintf(buf, buf_size, "Vcc min: %1.1x.%1.1x, Vcc max: %1.1x.%1.1x, Vpp min: %1.1x.%1.1x, Vpp max: %1.1x.%1.1x\n", (cfi_info->vcc_min & 0xf0) >> 4, cfi_info->vcc_min & 0x0f,\r
2323         (cfi_info->vcc_max & 0xf0) >> 4, cfi_info->vcc_max & 0x0f,\r
2324         (cfi_info->vpp_min & 0xf0) >> 4, cfi_info->vpp_min & 0x0f,\r
2325         (cfi_info->vpp_max & 0xf0) >> 4, cfi_info->vpp_max & 0x0f);\r
2326         buf += printed;\r
2327         buf_size -= printed;\r
2328 \r
2329         printed = snprintf(buf, buf_size, "typ. word write timeout: %u, typ. buf write timeout: %u, typ. block erase timeout: %u, typ. chip erase timeout: %u\n", 1 << cfi_info->word_write_timeout_typ, 1 << cfi_info->buf_write_timeout_typ,\r
2330                   1 << cfi_info->block_erase_timeout_typ, 1 << cfi_info->chip_erase_timeout_typ);\r
2331         buf += printed;\r
2332         buf_size -= printed;\r
2333 \r
2334         printed = snprintf(buf, buf_size, "max. word write timeout: %u, max. buf write timeout: %u, max. block erase timeout: %u, max. chip erase timeout: %u\n", (1 << cfi_info->word_write_timeout_max) * (1 << cfi_info->word_write_timeout_typ),\r
2335                   (1 << cfi_info->buf_write_timeout_max) * (1 << cfi_info->buf_write_timeout_typ),\r
2336                   (1 << cfi_info->block_erase_timeout_max) * (1 << cfi_info->block_erase_timeout_typ),\r
2337                   (1 << cfi_info->chip_erase_timeout_max) * (1 << cfi_info->chip_erase_timeout_typ));\r
2338         buf += printed;\r
2339         buf_size -= printed;\r
2340 \r
2341         printed = snprintf(buf, buf_size, "size: 0x%x, interface desc: %i, max buffer write size: %x\n", 1 << cfi_info->dev_size, cfi_info->interface_desc, cfi_info->max_buf_write_size);\r
2342         buf += printed;\r
2343         buf_size -= printed;\r
2344 \r
2345         switch(cfi_info->pri_id)\r
2346         {\r
2347                 case 1:\r
2348                 case 3:\r
2349                         cfi_intel_info(bank, buf, buf_size);\r
2350                         break;\r
2351                 case 2:\r
2352                         cfi_spansion_info(bank, buf, buf_size);\r
2353                         break;\r
2354                 default:\r
2355                         ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);\r
2356                         break;\r
2357         }\r
2358 \r
2359         return ERROR_OK;\r
2360 }\r