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