1 /* This file is part of the program psim.
3 Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, see <http://www.gnu.org/licenses/>.
24 #include "device_table.h"
38 eeprom - JEDEC? compatible electricaly erasable programable device
44 This device implements a small byte addressable EEPROM.
45 Programming is performed using the same write sequences as used by
46 standard modern EEPROM components. Writes occure in real time, the
47 device returning a progress value until the programing has been
50 It is based on the AMD 29F040 component.
56 reg = <address> <size> (required)
58 Determine where the device lives in the parents address space.
61 nr-sectors = <integer> (required)
63 When erasing an entire sector is cleared at a time. This specifies
64 the number of sectors in the EEPROM component.
67 sector-size = <integer> (required)
69 The number of bytes in a sector. When erasing, memory chunks of
70 this size are cleared.
72 NOTE: The product nr-sectors * sector-size does not need to map the
73 size specified in the reg property. If the specified size is
74 smaller part of the eeprom will not be accessible while if it is
75 larger the addresses will wrap.
78 byte-write-delay = <integer> (required)
80 Number of clock ticks before the programming of a single byte
84 sector-start-delay = <integer> (required)
86 When erasing sectors, the number of clock ticks after the sector
87 has been specified that the actual erase process commences.
90 erase-delay = <intger> (required)
92 Number of clock ticks before an erase program completes
95 manufacture-code = <integer> (required)
97 The one byte value returned when the auto-select manufacturer code
101 device-code = <integer> (required)
103 The one byte value returned when the auto-select device code is
107 input-file = <file-name> (optional)
109 Initialize the eeprom using the specified binary file.
112 output-file = <file-name> (optional)
114 When ever the eeprom is updated, save the modified image into the
121 Enable tracing of the eeprom:
123 | bash$ psim -t eeprom-device \
126 Configure something very like the Amd Am29F040 - 512byte EEPROM
129 | -o '/eeprom@0xfff00000/reg 0xfff00000 0x80000' \
130 | -o '/eeprom@0xfff00000/nr-sectors 8' \
131 | -o '/eeprom@0xfff00000/sector-size 0x10000' \
132 | -o '/eeprom@0xfff00000/byte-write-delay 1000' \
133 | -o '/eeprom@0xfff00000/sector-start-delay 100' \
134 | -o '/eeprom@0xfff00000/erase-delay 1000' \
135 | -o '/eeprom@0xfff00000/manufacture-code 0x01' \
136 | -o '/eeprom@0xfff00000/device-code 0xa4' \
139 Initialize the eeprom from the file <</dev/zero>>:
141 | -o '/eeprom@0xfff00000/input-file /dev/zero'
160 sector_erase_suspend
,
165 state2a(hw_eeprom_states state
)
168 case read_reset
: return "read_reset";
169 case write_nr_2
: return "write_nr_2";
170 case write_nr_3
: return "write_nr_3";
171 case write_nr_4
: return "write_nr_4";
172 case write_nr_5
: return "write_nr_5";
173 case write_nr_6
: return "write_nr_6";
174 case byte_program
: return "byte_program";
175 case byte_programming
: return "byte_programming";
176 case chip_erase
: return "chip_erase";
177 case sector_erase
: return "sector_erase";
178 case sector_erase_suspend
: return "sector_erase_suspend";
179 case autoselect
: return "autoselect";
184 typedef struct _hw_eeprom_device
{
186 hw_eeprom_states state
;
188 unsigned sizeof_memory
;
189 unsigned erase_delay
;
190 signed64 program_start_time
;
191 signed64 program_finish_time
;
192 unsigned8 manufacture_code
;
193 unsigned8 device_code
;
194 unsigned8 toggle_bit
;
196 const char *input_file_name
;
197 const char *output_file_name
;
198 /* for sector and sector programming */
199 hw_eeprom_states sector_state
;
202 unsigned sizeof_sector
;
203 unsigned sector_start_delay
;
204 unsigned sector_start_time
;
205 /* byte and byte programming */
206 unsigned byte_write_delay
;
207 unsigned_word byte_program_address
;
208 unsigned8 byte_program_byte
;
211 typedef struct _hw_eeprom_reg_spec
{
214 } hw_eeprom_reg_spec
;
217 hw_eeprom_init_data(device
*me
)
219 hw_eeprom_device
*eeprom
= (hw_eeprom_device
*)device_data(me
);
221 /* have we any input or output files */
222 if (device_find_property(me
, "input-file") != NULL
)
223 eeprom
->input_file_name
= device_find_string_property(me
, "input-file");
224 if (device_find_property(me
, "output-file") != NULL
)
225 eeprom
->input_file_name
= device_find_string_property(me
, "output-file");
227 /* figure out the sectors in the eeprom */
228 if (eeprom
->sectors
== NULL
) {
229 eeprom
->nr_sectors
= device_find_integer_property(me
, "nr-sectors");
230 eeprom
->sizeof_sector
= device_find_integer_property(me
, "sector-size");
231 eeprom
->sectors
= zalloc(eeprom
->nr_sectors
);
234 memset(eeprom
->sectors
, 0, eeprom
->nr_sectors
);
236 /* initialize the eeprom */
237 if (eeprom
->memory
== NULL
) {
238 eeprom
->sizeof_memory
= eeprom
->sizeof_sector
* eeprom
->nr_sectors
;
239 eeprom
->memory
= zalloc(eeprom
->sizeof_memory
);
242 memset(eeprom
->memory
, 0, eeprom
->sizeof_memory
);
243 if (eeprom
->input_file_name
!= NULL
) {
245 FILE *input_file
= fopen(eeprom
->input_file_name
, "r");
246 if (input_file
== NULL
) {
248 device_error(me
, "Failed to open input file %s\n", eeprom
->input_file_name
);
250 for (i
= 0; i
< eeprom
->sizeof_memory
; i
++) {
251 if (fread(&eeprom
->memory
[i
], 1, 1, input_file
) != 1)
258 eeprom
->byte_write_delay
= device_find_integer_property(me
, "byte-write-delay");
259 eeprom
->sector_start_delay
= device_find_integer_property(me
, "sector-start-delay");
260 eeprom
->erase_delay
= device_find_integer_property(me
, "erase-delay");
263 eeprom
->manufacture_code
= device_find_integer_property(me
, "manufacture-code");
264 eeprom
->device_code
= device_find_integer_property(me
, "device-code");
269 invalid_read(device
*me
,
270 hw_eeprom_states state
,
271 unsigned_word address
,
274 DTRACE(eeprom
, ("Invalid read to 0x%lx while in state %s (%s)\n",
275 (unsigned long)address
,
281 invalid_write(device
*me
,
282 hw_eeprom_states state
,
283 unsigned_word address
,
287 DTRACE(eeprom
, ("Invalid write of 0x%lx to 0x%lx while in state %s (%s)\n",
289 (unsigned long)address
,
295 dump_eeprom(device
*me
,
296 hw_eeprom_device
*eeprom
)
298 if (eeprom
->output_file_name
!= NULL
) {
300 FILE *output_file
= fopen(eeprom
->output_file_name
, "w");
301 if (output_file
== NULL
) {
303 device_error(me
, "Failed to open output file %s\n",
304 eeprom
->output_file_name
);
306 for (i
= 0; i
< eeprom
->sizeof_memory
; i
++) {
307 if (fwrite(&eeprom
->memory
[i
], 1, 1, output_file
) != 1)
315 /* program a single byte of eeprom */
318 start_programming_byte(device
*me
,
319 hw_eeprom_device
*eeprom
,
320 unsigned_word address
,
323 unsigned8 old_byte
= eeprom
->memory
[address
];
324 DTRACE(eeprom
, ("start-programing-byte - address 0x%lx, new 0x%lx, old 0x%lx\n",
325 (unsigned long)address
,
326 (unsigned long)new_byte
,
327 (unsigned long)old_byte
));
328 eeprom
->byte_program_address
= address
;
329 /* : old new : ~old : new&~old
331 : 0 1 : 1 : 1 -- can not set a bit
334 if (~old_byte
& new_byte
)
335 invalid_write(me
, eeprom
->state
, address
, new_byte
, "setting cleared bit");
336 /* : old new : old&new
341 eeprom
->byte_program_byte
= new_byte
& old_byte
;
342 eeprom
->memory
[address
] = ~new_byte
& ~0x24; /* LE-bits 5:3 zero */
343 eeprom
->program_start_time
= device_event_queue_time(me
);
344 eeprom
->program_finish_time
= (eeprom
->program_start_time
345 + eeprom
->byte_write_delay
);
349 finish_programming_byte(device
*me
,
350 hw_eeprom_device
*eeprom
)
352 DTRACE(eeprom
, ("finish-programming-byte - address 0x%lx, byte 0x%lx\n",
353 (unsigned long)eeprom
->byte_program_address
,
354 (unsigned long)eeprom
->byte_program_byte
));
355 eeprom
->memory
[eeprom
->byte_program_address
] = eeprom
->byte_program_byte
;
356 dump_eeprom(me
, eeprom
);
360 /* erase the eeprom completly */
363 start_erasing_chip(device
*me
,
364 hw_eeprom_device
*eeprom
)
366 DTRACE(eeprom
, ("start-erasing-chip\n"));
367 memset(eeprom
->memory
, 0, eeprom
->sizeof_memory
);
368 eeprom
->program_start_time
= device_event_queue_time(me
);
369 eeprom
->program_finish_time
= (eeprom
->program_start_time
370 + eeprom
->erase_delay
);
374 finish_erasing_chip(device
*me
,
375 hw_eeprom_device
*eeprom
)
377 DTRACE(eeprom
, ("finish-erasing-chip\n"));
378 memset(eeprom
->memory
, 0xff, eeprom
->sizeof_memory
);
379 dump_eeprom(me
, eeprom
);
383 /* erase a single sector of the eeprom */
386 start_erasing_sector(device
*me
,
387 hw_eeprom_device
*eeprom
,
388 unsigned_word address
)
390 int sector
= address
/ eeprom
->sizeof_sector
;
391 DTRACE(eeprom
, ("start-erasing-sector - address 0x%lx, sector %d\n",
392 (unsigned long)address
, sector
));
393 ASSERT(sector
< eeprom
->nr_sectors
);
394 eeprom
->sectors
[sector
] = 1;
395 memset(eeprom
->memory
+ sector
* eeprom
->sizeof_sector
,
396 0x4, eeprom
->sizeof_sector
);
397 eeprom
->program_start_time
= device_event_queue_time(me
);
398 eeprom
->sector_start_time
= (eeprom
->program_start_time
399 + eeprom
->sector_start_delay
);
400 eeprom
->program_finish_time
= (eeprom
->sector_start_time
401 + eeprom
->erase_delay
);
406 finish_erasing_sector(device
*me
,
407 hw_eeprom_device
*eeprom
)
410 DTRACE(eeprom
, ("finish-erasing-sector\n"));
411 for (sector
= 0; sector
< eeprom
->nr_sectors
; sector
++) {
412 if (eeprom
->sectors
[sector
]) {
413 eeprom
->sectors
[sector
] = 0;
414 memset(eeprom
->memory
+ sector
* eeprom
->sizeof_sector
,
415 0xff, eeprom
->sizeof_sector
);
418 dump_eeprom(me
, eeprom
);
425 toggle(hw_eeprom_device
*eeprom
,
428 eeprom
->toggle_bit
= eeprom
->toggle_bit
^ 0x40; /* le-bit 6 */
429 return eeprom
->toggle_bit
^ byte
;
433 read_byte(device
*me
,
434 hw_eeprom_device
*eeprom
,
435 unsigned_word address
)
437 /* may need multiple iterations of this */
439 switch (eeprom
->state
) {
442 return eeprom
->memory
[address
];
445 if ((address
& 0xff) == 0x00)
446 return eeprom
->manufacture_code
;
447 else if ((address
& 0xff) == 0x01)
448 return eeprom
->device_code
;
450 return 0; /* not certain about this */
452 case byte_programming
:
453 if (device_event_queue_time(me
) > eeprom
->program_finish_time
) {
454 finish_programming_byte(me
, eeprom
);
455 eeprom
->state
= read_reset
;
458 else if (address
== eeprom
->byte_program_address
) {
459 return toggle(eeprom
, eeprom
->memory
[address
]);
462 /* trash that memory location */
463 invalid_read(me
, eeprom
->state
, address
, "not byte program address");
464 eeprom
->memory
[address
] = (eeprom
->memory
[address
]
465 & eeprom
->byte_program_byte
);
466 return toggle(eeprom
, eeprom
->memory
[eeprom
->byte_program_address
]);
470 if (device_event_queue_time(me
) > eeprom
->program_finish_time
) {
471 finish_erasing_chip(me
, eeprom
);
472 eeprom
->state
= read_reset
;
476 return toggle(eeprom
, eeprom
->memory
[address
]);
480 if (device_event_queue_time(me
) > eeprom
->program_finish_time
) {
481 finish_erasing_sector(me
, eeprom
);
482 eeprom
->state
= read_reset
;
485 else if (!eeprom
->sectors
[address
/ eeprom
->sizeof_sector
]) {
486 /* read to wrong sector */
487 invalid_read(me
, eeprom
->state
, address
, "sector not being erased");
488 return toggle(eeprom
, eeprom
->memory
[address
]) & ~0x8;
490 else if (device_event_queue_time(me
) > eeprom
->sector_start_time
) {
491 return toggle(eeprom
, eeprom
->memory
[address
]) | 0x8;
494 return toggle(eeprom
, eeprom
->memory
[address
]) & ~0x8;
497 case sector_erase_suspend
:
498 if (!eeprom
->sectors
[address
/ eeprom
->sizeof_sector
]) {
499 return eeprom
->memory
[address
];
502 invalid_read(me
, eeprom
->state
, address
, "sector being erased");
503 return eeprom
->memory
[address
];
507 invalid_read(me
, eeprom
->state
, address
, "invalid state");
508 return eeprom
->memory
[address
];
516 hw_eeprom_io_read_buffer(device
*me
,
524 hw_eeprom_device
*eeprom
= (hw_eeprom_device
*)device_data(me
);
526 for (i
= 0; i
< nr_bytes
; i
++) {
527 unsigned_word address
= (addr
+ i
) % eeprom
->sizeof_memory
;
528 unsigned8 byte
= read_byte(me
, eeprom
, address
);
529 ((unsigned8
*)dest
)[i
] = byte
;
538 write_byte(device
*me
,
539 hw_eeprom_device
*eeprom
,
540 unsigned_word address
,
543 /* may need multiple transitions to process a write */
545 switch (eeprom
->state
) {
548 if (address
== 0x5555 && data
== 0xaa)
549 eeprom
->state
= write_nr_2
;
550 else if (data
== 0xf0)
551 eeprom
->state
= read_reset
;
553 invalid_write(me
, eeprom
->state
, address
, data
, "unexpected");
554 eeprom
->state
= read_reset
;
559 if (address
== 0x2aaa && data
== 0x55)
560 eeprom
->state
= write_nr_3
;
562 invalid_write(me
, eeprom
->state
, address
, data
, "unexpected");
563 eeprom
->state
= read_reset
;
568 if (address
== 0x5555 && data
== 0xf0)
569 eeprom
->state
= read_reset
;
570 else if (address
== 0x5555 && data
== 0x90)
571 eeprom
->state
= autoselect
;
572 else if (address
== 0x5555 && data
== 0xa0) {
573 eeprom
->state
= byte_program
;
575 else if (address
== 0x5555 && data
== 0x80)
576 eeprom
->state
= write_nr_4
;
578 invalid_write(me
, eeprom
->state
, address
, data
, "unexpected");
579 eeprom
->state
= read_reset
;
584 if (address
== 0x5555 && data
== 0xaa)
585 eeprom
->state
= write_nr_5
;
587 invalid_write(me
, eeprom
->state
, address
, data
, "unexpected");
588 eeprom
->state
= read_reset
;
593 if (address
== 0x2aaa && data
== 0x55)
594 eeprom
->state
= write_nr_6
;
596 invalid_write(me
, eeprom
->state
, address
, data
, "unexpected");
597 eeprom
->state
= read_reset
;
602 if (address
== 0x5555 && data
== 0x10) {
603 start_erasing_chip(me
, eeprom
);
604 eeprom
->state
= chip_erase
;
607 start_erasing_sector(me
, eeprom
, address
);
608 eeprom
->sector_state
= read_reset
;
609 eeprom
->state
= sector_erase
;
615 eeprom
->state
= read_reset
;
616 else if (address
== 0x5555 && data
== 0xaa)
617 eeprom
->state
= write_nr_2
;
619 invalid_write(me
, eeprom
->state
, address
, data
, "unsupported address");
620 eeprom
->state
= read_reset
;
625 start_programming_byte(me
, eeprom
, address
, data
);
626 eeprom
->state
= byte_programming
;
629 case byte_programming
:
630 if (device_event_queue_time(me
) > eeprom
->program_finish_time
) {
631 finish_programming_byte(me
, eeprom
);
632 eeprom
->state
= read_reset
;
639 if (device_event_queue_time(me
) > eeprom
->program_finish_time
) {
640 finish_erasing_chip(me
, eeprom
);
641 eeprom
->state
= read_reset
;
648 if (device_event_queue_time(me
) > eeprom
->program_finish_time
) {
649 finish_erasing_sector(me
, eeprom
);
650 eeprom
->state
= eeprom
->sector_state
;
653 else if (device_event_queue_time(me
) > eeprom
->sector_start_time
655 eeprom
->sector_state
= read_reset
;
656 eeprom
->state
= sector_erase_suspend
;
659 if (eeprom
->sector_state
== read_reset
660 && address
== 0x5555 && data
== 0xaa)
661 eeprom
->sector_state
= write_nr_2
;
662 else if (eeprom
->sector_state
== write_nr_2
663 && address
== 0x2aaa && data
== 0x55)
664 eeprom
->sector_state
= write_nr_3
;
665 else if (eeprom
->sector_state
== write_nr_3
666 && address
== 0x5555 && data
== 0x80)
667 eeprom
->sector_state
= write_nr_4
;
668 else if (eeprom
->sector_state
== write_nr_4
669 && address
== 0x5555 && data
== 0xaa)
670 eeprom
->sector_state
= write_nr_5
;
671 else if (eeprom
->sector_state
== write_nr_5
672 && address
== 0x2aaa && data
== 0x55)
673 eeprom
->sector_state
= write_nr_6
;
674 else if (eeprom
->sector_state
== write_nr_6
675 && address
!= 0x5555 && data
== 0x30) {
676 if (device_event_queue_time(me
) > eeprom
->sector_start_time
) {
677 DTRACE(eeprom
, ("sector erase command after window closed\n"));
678 eeprom
->sector_state
= read_reset
;
681 start_erasing_sector(me
, eeprom
, address
);
682 eeprom
->sector_state
= read_reset
;
686 invalid_write(me
, eeprom
->state
, address
, data
, state2a(eeprom
->sector_state
));
687 eeprom
->state
= read_reset
;
692 case sector_erase_suspend
:
694 eeprom
->state
= sector_erase
;
696 invalid_write(me
, eeprom
->state
, address
, data
, "not resume command");
697 eeprom
->state
= read_reset
;
706 hw_eeprom_io_write_buffer(device
*me
,
714 hw_eeprom_device
*eeprom
= (hw_eeprom_device
*)device_data(me
);
716 for (i
= 0; i
< nr_bytes
; i
++) {
717 unsigned_word address
= (addr
+ i
) % eeprom
->sizeof_memory
;
718 unsigned8 byte
= ((unsigned8
*)source
)[i
];
719 write_byte(me
, eeprom
, address
, byte
);
725 /* An instance of the eeprom */
727 typedef struct _hw_eeprom_instance
{
729 hw_eeprom_device
*eeprom
;
731 } hw_eeprom_instance
;
734 hw_eeprom_instance_delete(device_instance
*instance
)
736 hw_eeprom_instance
*data
= device_instance_data(instance
);
741 hw_eeprom_instance_read(device_instance
*instance
,
745 hw_eeprom_instance
*data
= device_instance_data(instance
);
747 if (data
->eeprom
->state
!= read_reset
)
748 DITRACE(eeprom
, ("eeprom not idle during instance read\n"));
749 for (i
= 0; i
< len
; i
++) {
750 ((unsigned8
*)buf
)[i
] = data
->eeprom
->memory
[data
->pos
];
751 data
->pos
= (data
->pos
+ 1) % data
->eeprom
->sizeof_memory
;
757 hw_eeprom_instance_write(device_instance
*instance
,
761 hw_eeprom_instance
*data
= device_instance_data(instance
);
763 if (data
->eeprom
->state
!= read_reset
)
764 DITRACE(eeprom
, ("eeprom not idle during instance write\n"));
765 for (i
= 0; i
< len
; i
++) {
766 data
->eeprom
->memory
[data
->pos
] = ((unsigned8
*)buf
)[i
];
767 data
->pos
= (data
->pos
+ 1) % data
->eeprom
->sizeof_memory
;
769 dump_eeprom(data
->me
, data
->eeprom
);
774 hw_eeprom_instance_seek(device_instance
*instance
,
775 unsigned_word pos_hi
,
776 unsigned_word pos_lo
)
778 hw_eeprom_instance
*data
= device_instance_data(instance
);
779 if (pos_lo
>= data
->eeprom
->sizeof_memory
)
780 device_error(data
->me
, "seek value 0x%lx out of range\n",
781 (unsigned long)pos_lo
);
786 static const device_instance_callbacks hw_eeprom_instance_callbacks
= {
787 hw_eeprom_instance_delete
,
788 hw_eeprom_instance_read
,
789 hw_eeprom_instance_write
,
790 hw_eeprom_instance_seek
,
793 static device_instance
*
794 hw_eeprom_create_instance(device
*me
,
798 hw_eeprom_device
*eeprom
= device_data(me
);
799 hw_eeprom_instance
*data
= ZALLOC(hw_eeprom_instance
);
800 data
->eeprom
= eeprom
;
802 return device_create_instance_from(me
, NULL
,
805 &hw_eeprom_instance_callbacks
);
810 static device_callbacks
const hw_eeprom_callbacks
= {
811 { generic_device_init_address
,
812 hw_eeprom_init_data
},
813 { NULL
, }, /* address */
814 { hw_eeprom_io_read_buffer
,
815 hw_eeprom_io_write_buffer
}, /* IO */
817 { NULL
, }, /* interrupt */
818 { NULL
, }, /* unit */
819 hw_eeprom_create_instance
,
823 hw_eeprom_create(const char *name
,
824 const device_unit
*unit_address
,
827 hw_eeprom_device
*eeprom
= ZALLOC(hw_eeprom_device
);
833 const device_descriptor hw_eeprom_device_descriptor
[] = {
834 { "eeprom", hw_eeprom_create
, &hw_eeprom_callbacks
},
838 #endif /* _HW_EEPROM_C_ */