1 /*
2 * $Id$
3 *
4 * Copyright (C) 2002 ETC s.r.o.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 *
21 * Written by Marcel Telka <marcel@telka.sk>, 2002.
22 * Changed by August Hörandl, 2003
23 *
24 * Documentation:
25 * [1] Advanced Micro Devices, "Common Flash Memory Interface Specification Release 2.0",
26 * December 1, 2001
27 * [2] Intel Corporation, "Intel PXA250 and PXA210 Application Processors
28 * Developer's Manual", February 2002, Order Number: 278522-001
29 * [3] Intel Corporation, "Common Flash Interface (CFI) and Command Sets
30 * Application Note 646", April 2000, Order Number: 292204-004
31 * [4] Advanced Micro Devices, "Common Flash Memory Interface Publication 100 Vendor & Device
32 * ID Code Assignments", December 1, 2001, Volume Number: 96.1
33 * [5] Micron Technology, Inc. "Q-Flash Memory MT28F123J3, MT28F640J3, MT28F320J3",
34 * MT28F640J3.fm - Rev. N 3/05 EN
35 *
36 */
37
38 #include <sysdep.h>
39
40 #include <stdint.h>
41 #include <stdlib.h>
42 #include <string.h>
43
44 #include <urjtag/error.h>
45 #include <urjtag/log.h>
46 #include <urjtag/flash.h>
47 #include <urjtag/bus.h>
48
49 #include "flash.h"
50
51 #include "cfi.h"
52 #include "intel.h"
53 #include "mic.h"
54
55 /* autodetect, we can handle this chip */
56 static int
intel_flash_autodetect32(urj_flash_cfi_array_t * cfi_array)57 intel_flash_autodetect32 (urj_flash_cfi_array_t *cfi_array)
58 {
59 urj_bus_area_t area;
60
61 if (URJ_BUS_AREA (cfi_array->bus, cfi_array->address,
62 &area) != URJ_STATUS_OK)
63 return 0;
64
65 return ((cfi_array->cfi_chips[0]->cfi.identification_string.pri_id_code
66 == CFI_VENDOR_MITSUBISHI_SCS)
67 || (cfi_array->cfi_chips[0]->cfi.identification_string.pri_id_code
68 == CFI_VENDOR_MITSUBISHI_ECS)
69 || (cfi_array->cfi_chips[0]->cfi.identification_string.pri_id_code
70 == CFI_VENDOR_INTEL_ECS)
71 || (cfi_array->cfi_chips[0]->cfi.identification_string.pri_id_code
72 == CFI_VENDOR_INTEL_SCS))
73 && (area.width == 32);
74 }
75
76 static int
intel_flash_autodetect(urj_flash_cfi_array_t * cfi_array)77 intel_flash_autodetect (urj_flash_cfi_array_t *cfi_array)
78 {
79 urj_bus_area_t area;
80
81 if (URJ_BUS_AREA (cfi_array->bus, cfi_array->address,
82 &area) != URJ_STATUS_OK)
83 return 0;
84
85 return ((cfi_array->cfi_chips[0]->cfi.identification_string.pri_id_code
86 == CFI_VENDOR_MITSUBISHI_SCS)
87 || (cfi_array->cfi_chips[0]->cfi.identification_string.pri_id_code
88 == CFI_VENDOR_MITSUBISHI_ECS)
89 || (cfi_array->cfi_chips[0]->cfi.identification_string.pri_id_code
90 == CFI_VENDOR_INTEL_ECS)
91 || (cfi_array->cfi_chips[0]->cfi.identification_string.pri_id_code
92 == CFI_VENDOR_INTEL_SCS))
93 && (area.width == 16);
94 }
95
96 static int
intel_flash_autodetect8(urj_flash_cfi_array_t * cfi_array)97 intel_flash_autodetect8 (urj_flash_cfi_array_t *cfi_array)
98 {
99 urj_bus_area_t area;
100
101 if (URJ_BUS_AREA (cfi_array->bus, cfi_array->address,
102 &area) != URJ_STATUS_OK)
103 return 0;
104
105 return ((cfi_array->cfi_chips[0]->cfi.identification_string.pri_id_code
106 == CFI_VENDOR_MITSUBISHI_SCS)
107 || (cfi_array->cfi_chips[0]->cfi.identification_string.pri_id_code
108 == CFI_VENDOR_MITSUBISHI_ECS)
109 || (cfi_array->cfi_chips[0]->cfi.identification_string.pri_id_code
110 == CFI_VENDOR_INTEL_ECS)
111 || (cfi_array->cfi_chips[0]->cfi.identification_string.pri_id_code
112 == CFI_VENDOR_INTEL_SCS))
113 && (area.width == 8);
114 }
115
116 static void
_intel_flash_print_info(urj_log_level_t ll,urj_flash_cfi_array_t * cfi_array,int o)117 _intel_flash_print_info (urj_log_level_t ll, urj_flash_cfi_array_t *cfi_array,
118 int o)
119 {
120 uint32_t mid, cid;
121 urj_bus_t *bus = cfi_array->bus;
122
123 mid = (URJ_BUS_READ (bus, cfi_array->address + (0x00 << o)) & 0xFF);
124 switch (mid)
125 {
126 case STD_MIC_INTEL:
127 urj_log (ll, _("Manufacturer: %s\n"), STD_MICN_INTEL);
128 break;
129 case STD_MIC_MITSUBISHI:
130 urj_log (ll, _("Manufacturer: %s\n"), STD_MICN_MITSUBISHI);
131 break;
132 case STD_MIC_MICRON_TECHNOLOGY:
133 urj_log (ll, _("Manufacturer: %s\n"), STD_MICN_MICRON_TECHNOLOGY);
134 break;
135 default:
136 urj_log (ll, _("Unknown manufacturer (0x%04lX)!\n"),
137 (long unsigned) mid);
138 break;
139 }
140
141 urj_log (ll, _("Chip: "));
142 cid = (URJ_BUS_READ (bus, cfi_array->address + (0x01 << o)) & 0xFFFF);
143 switch (cid)
144 {
145 case 0x0016:
146 urj_log (ll, "28F320J3A\n");
147 break;
148 case 0x0017:
149 urj_log (ll, "28F640J3A\n");
150 break;
151 case 0x0018:
152 urj_log (ll, "28F128J3A\n");
153 break;
154 case 0x001D:
155 urj_log (ll, "28F256J3A\n");
156 break;
157 case 0x8801:
158 urj_log (ll, "28F640K3\n");
159 break;
160 case 0x8802:
161 urj_log (ll, "28F128K3\n");
162 break;
163 case 0x8803:
164 urj_log (ll, "28F256K3\n");
165 break;
166 case 0x8805:
167 urj_log (ll, "28F640K18\n");
168 break;
169 case 0x8806:
170 urj_log (ll, "28F128K18\n");
171 break;
172 case 0x8807:
173 urj_log (ll, "28F256K18\n");
174 break;
175 case 0x880B:
176 urj_log (ll, "GE28F640L18T\n");
177 break;
178 case 0x880C:
179 urj_log (ll, "GE28F128L18T\n");
180 break;
181 case 0x880D:
182 urj_log (ll, "GE28F256L18T\n");
183 break;
184 case 0x880E:
185 urj_log (ll, "GE28F640L18B\n");
186 break;
187 case 0x880F:
188 urj_log (ll, "GE28F128L18B\n");
189 break;
190 case 0x8810:
191 urj_log (ll, "GE28F256L18B\n");
192 break;
193 case 0x891F:
194 urj_log (ll, "28F256P33\n");
195 break;
196 default:
197 urj_log (ll, _("Unknown (0x%02lX)!\n"), (long unsigned) cid);
198 break;
199 }
200
201 /* Read Array */
202 URJ_BUS_WRITE (bus, cfi_array->address + (0 << o), 0x00FF00FF);
203 }
204
205 static void
intel_flash_print_info(urj_log_level_t ll,urj_flash_cfi_array_t * cfi_array)206 intel_flash_print_info (urj_log_level_t ll, urj_flash_cfi_array_t *cfi_array)
207 {
208 int o = 1;
209 urj_bus_t *bus = cfi_array->bus;
210
211 /* Intel Primary Algorithm Extended Query Table - see Table 5. in [3] */
212 /* TODO */
213
214 /* Clear Status Register */
215 URJ_BUS_WRITE (bus, cfi_array->address + (0 << o), 0x0050);
216
217 /* Read Identifier Command */
218 URJ_BUS_WRITE (bus, cfi_array->address + (0 << 0), 0x0090);
219
220 _intel_flash_print_info (ll, cfi_array, o);
221 }
222
223 static void
intel_flash_print_info32(urj_log_level_t ll,urj_flash_cfi_array_t * cfi_array)224 intel_flash_print_info32 (urj_log_level_t ll, urj_flash_cfi_array_t *cfi_array)
225 {
226 int o = 2;
227 urj_bus_t *bus = cfi_array->bus;
228 /* Intel Primary Algorithm Extended Query Table - see Table 5. in [3] */
229 /* TODO */
230
231 /* Clear Status Register */
232 URJ_BUS_WRITE (bus, cfi_array->address + (0 << o), 0x00500050);
233
234 /* Read Identifier Command */
235 URJ_BUS_WRITE (bus, cfi_array->address + (0 << 0), 0x00900090);
236
237 _intel_flash_print_info (ll, cfi_array, o);
238 }
239
240 static int
intel_flash_erase_block(urj_flash_cfi_array_t * cfi_array,uint32_t adr)241 intel_flash_erase_block (urj_flash_cfi_array_t *cfi_array, uint32_t adr)
242 {
243 uint16_t sr;
244 urj_bus_t *bus = cfi_array->bus;
245
246 URJ_BUS_WRITE (bus, cfi_array->address,
247 CFI_INTEL_CMD_CLEAR_STATUS_REGISTER);
248 URJ_BUS_WRITE (bus, adr, CFI_INTEL_CMD_BLOCK_ERASE);
249 URJ_BUS_WRITE (bus, adr, CFI_INTEL_CMD_CONFIRM);
250
251 while (!((sr = URJ_BUS_READ (bus, cfi_array->address) & 0xFE) & CFI_INTEL_SR_READY)); /* TODO: add timeout */
252
253 switch (sr & ~CFI_INTEL_SR_READY)
254 {
255 case 0:
256 return URJ_STATUS_OK;
257 case CFI_INTEL_SR_ERASE_ERROR | CFI_INTEL_SR_PROGRAM_ERROR:
258 urj_error_set (URJ_ERROR_FLASH_ERASE, _("invalid command seq"));
259 return URJ_STATUS_FAIL;
260 case CFI_INTEL_SR_ERASE_ERROR | CFI_INTEL_SR_VPEN_ERROR:
261 urj_error_set (URJ_ERROR_FLASH_ERASE, _("low vpen"));
262 return URJ_STATUS_FAIL;
263 case CFI_INTEL_SR_ERASE_ERROR | CFI_INTEL_SR_BLOCK_LOCKED:
264 urj_error_set (URJ_ERROR_FLASH_ERASE, _("block locked"));
265 return URJ_STATUS_FAIL;
266 default:
267 break;
268 }
269
270 urj_error_set (URJ_ERROR_FLASH, "unknown error");
271 return URJ_STATUS_FAIL;
272 }
273
274 static int
intel_flash_unlock_block(urj_flash_cfi_array_t * cfi_array,uint32_t adr)275 intel_flash_unlock_block (urj_flash_cfi_array_t *cfi_array, uint32_t adr)
276 {
277 uint16_t sr;
278 urj_bus_t *bus = cfi_array->bus;
279
280 URJ_BUS_WRITE (bus, cfi_array->address,
281 CFI_INTEL_CMD_CLEAR_STATUS_REGISTER);
282 URJ_BUS_WRITE (bus, adr, CFI_INTEL_CMD_LOCK_SETUP);
283 URJ_BUS_WRITE (bus, adr, CFI_INTEL_CMD_UNLOCK_BLOCK);
284
285 while (!((sr = URJ_BUS_READ (bus, cfi_array->address) & 0xFE) & CFI_INTEL_SR_READY)); /* TODO: add timeout */
286
287 if (sr != CFI_INTEL_SR_READY)
288 {
289 urj_error_set (URJ_ERROR_FLASH_UNLOCK,
290 _("unknown error while unlocking block"));
291 return URJ_STATUS_FAIL;
292 }
293
294 return URJ_STATUS_OK;
295 }
296
297 static int
intel_flash_lock_block(urj_flash_cfi_array_t * cfi_array,uint32_t adr)298 intel_flash_lock_block (urj_flash_cfi_array_t *cfi_array, uint32_t adr)
299 {
300 uint16_t sr;
301 urj_bus_t *bus = cfi_array->bus;
302
303 URJ_BUS_WRITE (bus, cfi_array->address,
304 CFI_INTEL_CMD_CLEAR_STATUS_REGISTER);
305 URJ_BUS_WRITE (bus, adr, CFI_INTEL_CMD_LOCK_SETUP);
306 URJ_BUS_WRITE (bus, adr, CFI_INTEL_CMD_LOCK_BLOCK);
307
308 while (!((sr = URJ_BUS_READ (bus, cfi_array->address) & 0xFE) & CFI_INTEL_SR_READY)); /* TODO: add timeout */
309
310 if (sr != CFI_INTEL_SR_READY)
311 {
312 urj_error_set (URJ_ERROR_FLASH_LOCK,
313 _("unknown error while locking block"));
314 return URJ_STATUS_FAIL;
315 }
316
317 URJ_BUS_WRITE (bus, adr + 0x02, CFI_INTEL_CMD_READ_IDENTIFIER);
318
319 sr = URJ_BUS_READ (bus, cfi_array->address & 0x01);
320 if (!sr)
321 {
322 urj_error_set (URJ_ERROR_FLASH_LOCK,
323 _("locking block failed"));
324 return URJ_STATUS_FAIL;
325 }
326
327 return URJ_STATUS_OK;
328 }
329
330 static int
intel_flash_program_single(urj_flash_cfi_array_t * cfi_array,uint32_t adr,uint32_t data)331 intel_flash_program_single (urj_flash_cfi_array_t *cfi_array,
332 uint32_t adr, uint32_t data)
333 {
334 uint16_t sr;
335 urj_bus_t *bus = cfi_array->bus;
336
337 URJ_BUS_WRITE (bus, cfi_array->address,
338 CFI_INTEL_CMD_CLEAR_STATUS_REGISTER);
339 URJ_BUS_WRITE (bus, adr, CFI_INTEL_CMD_PROGRAM1);
340 URJ_BUS_WRITE (bus, adr, data);
341
342 while (!((sr = URJ_BUS_READ (bus, cfi_array->address) & 0xFE) & CFI_INTEL_SR_READY)); /* TODO: add timeout */
343
344 if (sr != CFI_INTEL_SR_READY)
345 {
346 urj_error_set (URJ_ERROR_FLASH_PROGRAM,
347 _("unknown error while programming"));
348 return URJ_STATUS_FAIL;
349 }
350
351 return URJ_STATUS_OK;
352 }
353
354 static int
intel_flash_program_buffer(urj_flash_cfi_array_t * cfi_array,uint32_t adr,uint32_t * buffer,int count)355 intel_flash_program_buffer (urj_flash_cfi_array_t *cfi_array,
356 uint32_t adr, uint32_t *buffer, int count)
357 {
358 /* NOTE: Write-to-buffer programming operation according to [5], Figure 9 */
359 uint16_t sr;
360 urj_bus_t *bus = cfi_array->bus;
361 urj_flash_cfi_chip_t *cfi_chip = cfi_array->cfi_chips[0];
362 int wb_bytes = cfi_chip->cfi.device_geometry.max_bytes_write;
363 int chip_width = cfi_chip->width;
364 int offset = 0;
365
366 while (count > 0)
367 {
368 int wcount, idx;
369 uint32_t block_adr = adr;
370
371 /* determine length of next multi-byte write */
372 wcount = wb_bytes - (adr % wb_bytes);
373 wcount /= chip_width;
374 if (wcount > count)
375 wcount = count;
376
377 /* issue command WRITE_TO_BUFFER */
378 URJ_BUS_WRITE (bus, cfi_array->address,
379 CFI_INTEL_CMD_CLEAR_STATUS_REGISTER);
380 /* poll XSR7 == 1 */
381 do {
382 URJ_BUS_WRITE (bus, adr, CFI_INTEL_CMD_WRITE_TO_BUFFER);
383 } while (!((sr = URJ_BUS_READ (bus, cfi_array->address) & 0xFE) & CFI_INTEL_SR_READY)); /* TODO: add timeout */
384
385 /* write count value (number of upcoming writes - 1) */
386 URJ_BUS_WRITE (bus, adr, wcount - 1);
387
388 /* write payload to buffer */
389 for (idx = 0; idx < wcount; idx++)
390 {
391 URJ_BUS_WRITE (bus, adr, buffer[offset + idx]);
392 adr += cfi_array->bus_width;
393 }
394 offset += wcount;
395
396 /* issue command WRITE_CONFIRM */
397 URJ_BUS_WRITE (bus, block_adr, CFI_INTEL_CMD_WRITE_CONFIRM);
398
399 count -= wcount;
400 }
401
402 /* poll SR7 == 1 */
403 while (!((sr = URJ_BUS_READ (bus, cfi_array->address) & 0xFE) & CFI_INTEL_SR_READY)); /* TODO: add timeout */
404 if (sr != CFI_INTEL_SR_READY)
405 {
406 urj_error_set (URJ_ERROR_FLASH_PROGRAM,
407 _("unknown error while programming"));
408 return URJ_STATUS_FAIL;
409 }
410
411 return URJ_STATUS_OK;
412 }
413
414 static int
intel_flash_program(urj_flash_cfi_array_t * cfi_array,uint32_t adr,uint32_t * buffer,int count)415 intel_flash_program (urj_flash_cfi_array_t *cfi_array,
416 uint32_t adr, uint32_t *buffer, int count)
417 {
418 urj_flash_cfi_query_structure_t *cfi = &(cfi_array->cfi_chips[0]->cfi);
419 int max_bytes_write = cfi->device_geometry.max_bytes_write;
420
421 #ifndef FLASH_MULTI_BYTE
422 max_bytes_write = 1;
423 #endif
424
425 /* multi-byte writes supported? */
426 if (max_bytes_write > 1)
427 return intel_flash_program_buffer (cfi_array, adr, buffer, count);
428
429 else
430 {
431 /* unroll buffer to single writes */
432 int idx;
433
434 for (idx = 0; idx < count; idx++)
435 {
436 int status = intel_flash_program_single (cfi_array, adr,
437 buffer[idx]);
438 if (status != URJ_STATUS_OK)
439 return status;
440 adr += cfi_array->bus_width;
441 }
442 }
443
444 return URJ_STATUS_OK;
445 }
446
447 static int
intel_flash_erase_block32(urj_flash_cfi_array_t * cfi_array,uint32_t adr)448 intel_flash_erase_block32 (urj_flash_cfi_array_t *cfi_array, uint32_t adr)
449 {
450 uint32_t sr;
451 urj_bus_t *bus = cfi_array->bus;
452
453 URJ_BUS_WRITE (bus, cfi_array->address,
454 (CFI_INTEL_CMD_CLEAR_STATUS_REGISTER << 16) |
455 CFI_INTEL_CMD_CLEAR_STATUS_REGISTER);
456 URJ_BUS_WRITE (bus, adr,
457 (CFI_INTEL_CMD_BLOCK_ERASE << 16) |
458 CFI_INTEL_CMD_BLOCK_ERASE);
459 URJ_BUS_WRITE (bus, adr,
460 (CFI_INTEL_CMD_CONFIRM << 16) | CFI_INTEL_CMD_CONFIRM);
461
462 while (((sr = URJ_BUS_READ (bus, cfi_array->address) & 0x00FE00FE) & ((CFI_INTEL_SR_READY << 16) | CFI_INTEL_SR_READY)) != ((CFI_INTEL_SR_READY << 16) | CFI_INTEL_SR_READY)); /* TODO: add timeout */
463
464 if (sr != ((CFI_INTEL_SR_READY << 16) | CFI_INTEL_SR_READY))
465 {
466 urj_error_set (URJ_ERROR_FLASH_ERASE, "sr = 0x%08lX",
467 (long unsigned) sr);
468 return URJ_STATUS_FAIL;
469 }
470
471 return URJ_STATUS_OK;
472 }
473
474 static int
intel_flash_unlock_block32(urj_flash_cfi_array_t * cfi_array,uint32_t adr)475 intel_flash_unlock_block32 (urj_flash_cfi_array_t *cfi_array,
476 uint32_t adr)
477 {
478 uint32_t sr;
479 urj_bus_t *bus = cfi_array->bus;
480
481 URJ_BUS_WRITE (bus, cfi_array->address,
482 (CFI_INTEL_CMD_CLEAR_STATUS_REGISTER << 16) |
483 CFI_INTEL_CMD_CLEAR_STATUS_REGISTER);
484 URJ_BUS_WRITE (bus, adr,
485 (CFI_INTEL_CMD_LOCK_SETUP << 16) |
486 CFI_INTEL_CMD_LOCK_SETUP);
487 URJ_BUS_WRITE (bus, adr,
488 (CFI_INTEL_CMD_UNLOCK_BLOCK << 16) |
489 CFI_INTEL_CMD_UNLOCK_BLOCK);
490
491 while (((sr = URJ_BUS_READ (bus, cfi_array->address) & 0x00FE00FE) & ((CFI_INTEL_SR_READY << 16) | CFI_INTEL_SR_READY)) != ((CFI_INTEL_SR_READY << 16) | CFI_INTEL_SR_READY)); /* TODO: add timeout */
492
493 if (sr != ((CFI_INTEL_SR_READY << 16) | CFI_INTEL_SR_READY))
494 {
495 urj_error_set (URJ_ERROR_FLASH_UNLOCK, "sr = 0x%08lX",
496 (long unsigned) sr);
497 return URJ_STATUS_FAIL;
498 }
499
500 return URJ_STATUS_OK;
501 }
502
503 static int
intel_flash_lock_block32(urj_flash_cfi_array_t * cfi_array,uint32_t adr)504 intel_flash_lock_block32 (urj_flash_cfi_array_t *cfi_array,
505 uint32_t adr)
506 {
507 urj_log (URJ_LOG_LEVEL_NORMAL, "flash_lock_block32 0x%08lX IGNORE\n",
508 (long unsigned) adr);
509 return URJ_STATUS_OK;
510 }
511
512 static int
intel_flash_program32_single(urj_flash_cfi_array_t * cfi_array,uint32_t adr,uint32_t data)513 intel_flash_program32_single (urj_flash_cfi_array_t *cfi_array,
514 uint32_t adr, uint32_t data)
515 {
516 uint32_t sr;
517 urj_bus_t *bus = cfi_array->bus;
518
519 URJ_BUS_WRITE (bus, cfi_array->address,
520 (CFI_INTEL_CMD_CLEAR_STATUS_REGISTER << 16) |
521 CFI_INTEL_CMD_CLEAR_STATUS_REGISTER);
522 URJ_BUS_WRITE (bus, adr,
523 (CFI_INTEL_CMD_PROGRAM1 << 16) | CFI_INTEL_CMD_PROGRAM1);
524 URJ_BUS_WRITE (bus, adr, data);
525
526 while (((sr = URJ_BUS_READ (bus, cfi_array->address) & 0x00FE00FE) & ((CFI_INTEL_SR_READY << 16) | CFI_INTEL_SR_READY)) != ((CFI_INTEL_SR_READY << 16) | CFI_INTEL_SR_READY)); /* TODO: add timeout */
527
528 if (sr != ((CFI_INTEL_SR_READY << 16) | CFI_INTEL_SR_READY))
529 {
530 urj_error_set (URJ_ERROR_FLASH_PROGRAM, "sr = 0x%08lX",
531 (long unsigned) sr);
532 return URJ_STATUS_FAIL;
533 }
534
535 return URJ_STATUS_OK;
536 }
537
538 static int
intel_flash_program32(urj_flash_cfi_array_t * cfi_array,uint32_t adr,uint32_t * buffer,int count)539 intel_flash_program32 (urj_flash_cfi_array_t *cfi_array,
540 uint32_t adr, uint32_t *buffer, int count)
541 {
542 /* Single byte programming is forced for 32 bit (2x16) flash configuration.
543 a) lack of testing capbilities for 2x16 multi-byte write operation
544 b) no implementation of intel_flash_program32_buffer() available
545 Closing these issues will enable multi-byte for 2x16 as well. */
546 int idx;
547
548 /* unroll buffer to single writes */
549 for (idx = 0; idx < count; idx++)
550 {
551 int status = intel_flash_program32_single (cfi_array, adr, buffer[idx]);
552 if (status != URJ_STATUS_OK)
553 return status;
554 adr += cfi_array->bus_width;
555 }
556
557 return URJ_STATUS_OK;
558 }
559
560 static void
intel_flash_readarray32(urj_flash_cfi_array_t * cfi_array)561 intel_flash_readarray32 (urj_flash_cfi_array_t *cfi_array)
562 {
563 /* Read Array */
564 URJ_BUS_WRITE (cfi_array->bus, cfi_array->address, 0x00FF00FF);
565 }
566
567 static void
intel_flash_readarray(urj_flash_cfi_array_t * cfi_array)568 intel_flash_readarray (urj_flash_cfi_array_t *cfi_array)
569 {
570 /* Read Array */
571 URJ_BUS_WRITE (cfi_array->bus, cfi_array->address, 0x00FF00FF);
572 }
573
574 const urj_flash_driver_t urj_flash_intel_32_flash_driver = {
575 N_("Intel Standard Command Set"),
576 N_("supported: 28Fxxxx, 2 x 16 bit"),
577 4, /* buswidth */
578 intel_flash_autodetect32,
579 intel_flash_print_info32,
580 intel_flash_erase_block32,
581 intel_flash_lock_block32,
582 intel_flash_unlock_block32,
583 intel_flash_program32,
584 intel_flash_readarray32,
585 };
586
587 const urj_flash_driver_t urj_flash_intel_16_flash_driver = {
588 N_("Intel Standard Command Set"),
589 N_("supported: 28Fxxxx, 1 x 16 bit"),
590 2, /* buswidth */
591 intel_flash_autodetect,
592 intel_flash_print_info,
593 intel_flash_erase_block,
594 intel_flash_lock_block,
595 intel_flash_unlock_block,
596 intel_flash_program,
597 intel_flash_readarray,
598 };
599
600 const urj_flash_driver_t urj_flash_intel_8_flash_driver = {
601 N_("Intel Standard Command Set"),
602 N_("supported: 28Fxxxx, 1 x 8 bit"),
603 1, /* buswidth */
604 intel_flash_autodetect8,
605 intel_flash_print_info,
606 intel_flash_erase_block,
607 intel_flash_lock_block,
608 intel_flash_unlock_block,
609 intel_flash_program,
610 intel_flash_readarray,
611 };
612