Update copyright year in gdbarch.sh doc/gdb.texinfo and doc/refcard.tex
[binutils-gdb.git] / sim / ppc / hw_eeprom.c
blob3406be93c62d0f47a391113b7f163eaa52465f6c
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/>.
21 #ifndef _HW_EEPROM_C_
22 #define _HW_EEPROM_C_
24 #include "device_table.h"
26 #ifdef HAVE_STRING_H
27 #include <string.h>
28 #else
29 #ifdef HAVE_STRINGS_H
30 #include <strings.h>
31 #endif
32 #endif
35 /* DEVICE
38 eeprom - JEDEC? compatible electricaly erasable programable device
41 DESCRIPTION
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
48 completed.
50 It is based on the AMD 29F040 component.
53 PROPERTIES
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
81 completes.
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
98 is read.
101 device-code = <integer> (required)
103 The one byte value returned when the auto-select device code is
104 read.
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
115 specified file.
118 EXAMPLES
121 Enable tracing of the eeprom:
123 | bash$ psim -t eeprom-device \
126 Configure something very like the Amd Am29F040 - 512byte EEPROM
127 (but a bit faster):
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'
144 BUGS
149 typedef enum {
150 read_reset,
151 write_nr_2,
152 write_nr_3,
153 write_nr_4,
154 write_nr_5,
155 write_nr_6,
156 byte_program,
157 byte_programming,
158 chip_erase,
159 sector_erase,
160 sector_erase_suspend,
161 autoselect,
162 } hw_eeprom_states;
164 static const char *
165 state2a(hw_eeprom_states state)
167 switch (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";
181 return NULL;
184 typedef struct _hw_eeprom_device {
185 /* general */
186 hw_eeprom_states state;
187 unsigned8 *memory;
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;
195 /* initialization */
196 const char *input_file_name;
197 const char *output_file_name;
198 /* for sector and sector programming */
199 hw_eeprom_states sector_state;
200 unsigned8 *sectors;
201 unsigned nr_sectors;
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;
209 } hw_eeprom_device;
211 typedef struct _hw_eeprom_reg_spec {
212 unsigned32 base;
213 unsigned32 size;
214 } hw_eeprom_reg_spec;
216 static void
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);
233 else
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);
241 else
242 memset(eeprom->memory, 0, eeprom->sizeof_memory);
243 if (eeprom->input_file_name != NULL) {
244 int i;
245 FILE *input_file = fopen(eeprom->input_file_name, "r");
246 if (input_file == NULL) {
247 perror("eeprom");
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)
252 break;
254 fclose(input_file);
257 /* timing */
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");
262 /* misc */
263 eeprom->manufacture_code = device_find_integer_property(me, "manufacture-code");
264 eeprom->device_code = device_find_integer_property(me, "device-code");
268 static void
269 invalid_read(device *me,
270 hw_eeprom_states state,
271 unsigned_word address,
272 const char *reason)
274 DTRACE(eeprom, ("Invalid read to 0x%lx while in state %s (%s)\n",
275 (unsigned long)address,
276 state2a(state),
277 reason));
280 static void
281 invalid_write(device *me,
282 hw_eeprom_states state,
283 unsigned_word address,
284 unsigned8 data,
285 const char *reason)
287 DTRACE(eeprom, ("Invalid write of 0x%lx to 0x%lx while in state %s (%s)\n",
288 (unsigned long)data,
289 (unsigned long)address,
290 state2a(state),
291 reason));
294 static void
295 dump_eeprom(device *me,
296 hw_eeprom_device *eeprom)
298 if (eeprom->output_file_name != NULL) {
299 int i;
300 FILE *output_file = fopen(eeprom->output_file_name, "w");
301 if (output_file == NULL) {
302 perror("eeprom");
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)
308 break;
310 fclose(output_file);
315 /* program a single byte of eeprom */
317 static void
318 start_programming_byte(device *me,
319 hw_eeprom_device *eeprom,
320 unsigned_word address,
321 unsigned8 new_byte)
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
330 : 0 0 : 1 : 0
331 : 0 1 : 1 : 1 -- can not set a bit
332 : 1 0 : 0 : 0
333 : 1 1 : 0 : 0 */
334 if (~old_byte & new_byte)
335 invalid_write(me, eeprom->state, address, new_byte, "setting cleared bit");
336 /* : old new : old&new
337 : 0 0 : 0
338 : 0 1 : 0
339 : 1 0 : 0
340 : 1 1 : 1 */
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);
348 static void
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 */
362 static void
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);
373 static void
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 */
385 static void
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);
405 static void
406 finish_erasing_sector(device *me,
407 hw_eeprom_device *eeprom)
409 int sector;
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);
422 /* eeprom reads */
424 static unsigned8
425 toggle(hw_eeprom_device *eeprom,
426 unsigned8 byte)
428 eeprom->toggle_bit = eeprom->toggle_bit ^ 0x40; /* le-bit 6 */
429 return eeprom->toggle_bit ^ byte;
432 static unsigned8
433 read_byte(device *me,
434 hw_eeprom_device *eeprom,
435 unsigned_word address)
437 /* may need multiple iterations of this */
438 while (1) {
439 switch (eeprom->state) {
441 case read_reset:
442 return eeprom->memory[address];
444 case autoselect:
445 if ((address & 0xff) == 0x00)
446 return eeprom->manufacture_code;
447 else if ((address & 0xff) == 0x01)
448 return eeprom->device_code;
449 else
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;
456 continue;
458 else if (address == eeprom->byte_program_address) {
459 return toggle(eeprom, eeprom->memory[address]);
461 else {
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]);
469 case chip_erase:
470 if (device_event_queue_time(me) > eeprom->program_finish_time) {
471 finish_erasing_chip(me, eeprom);
472 eeprom->state = read_reset;
473 continue;
475 else {
476 return toggle(eeprom, eeprom->memory[address]);
479 case sector_erase:
480 if (device_event_queue_time(me) > eeprom->program_finish_time) {
481 finish_erasing_sector(me, eeprom);
482 eeprom->state = read_reset;
483 continue;
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;
493 else {
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];
501 else {
502 invalid_read(me, eeprom->state, address, "sector being erased");
503 return eeprom->memory[address];
506 default:
507 invalid_read(me, eeprom->state, address, "invalid state");
508 return eeprom->memory[address];
512 return 0;
515 static unsigned
516 hw_eeprom_io_read_buffer(device *me,
517 void *dest,
518 int space,
519 unsigned_word addr,
520 unsigned nr_bytes,
521 cpu *processor,
522 unsigned_word cia)
524 hw_eeprom_device *eeprom = (hw_eeprom_device*)device_data(me);
525 int i;
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;
531 return nr_bytes;
535 /* eeprom writes */
537 static void
538 write_byte(device *me,
539 hw_eeprom_device *eeprom,
540 unsigned_word address,
541 unsigned8 data)
543 /* may need multiple transitions to process a write */
544 while (1) {
545 switch (eeprom->state) {
547 case read_reset:
548 if (address == 0x5555 && data == 0xaa)
549 eeprom->state = write_nr_2;
550 else if (data == 0xf0)
551 eeprom->state = read_reset;
552 else {
553 invalid_write(me, eeprom->state, address, data, "unexpected");
554 eeprom->state = read_reset;
556 return;
558 case write_nr_2:
559 if (address == 0x2aaa && data == 0x55)
560 eeprom->state = write_nr_3;
561 else {
562 invalid_write(me, eeprom->state, address, data, "unexpected");
563 eeprom->state = read_reset;
565 return;
567 case write_nr_3:
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;
577 else {
578 invalid_write(me, eeprom->state, address, data, "unexpected");
579 eeprom->state = read_reset;
581 return;
583 case write_nr_4:
584 if (address == 0x5555 && data == 0xaa)
585 eeprom->state = write_nr_5;
586 else {
587 invalid_write(me, eeprom->state, address, data, "unexpected");
588 eeprom->state = read_reset;
590 return;
592 case write_nr_5:
593 if (address == 0x2aaa && data == 0x55)
594 eeprom->state = write_nr_6;
595 else {
596 invalid_write(me, eeprom->state, address, data, "unexpected");
597 eeprom->state = read_reset;
599 return;
601 case write_nr_6:
602 if (address == 0x5555 && data == 0x10) {
603 start_erasing_chip(me, eeprom);
604 eeprom->state = chip_erase;
606 else {
607 start_erasing_sector(me, eeprom, address);
608 eeprom->sector_state = read_reset;
609 eeprom->state = sector_erase;
611 return;
613 case autoselect:
614 if (data == 0xf0)
615 eeprom->state = read_reset;
616 else if (address == 0x5555 && data == 0xaa)
617 eeprom->state = write_nr_2;
618 else {
619 invalid_write(me, eeprom->state, address, data, "unsupported address");
620 eeprom->state = read_reset;
622 return;
624 case byte_program:
625 start_programming_byte(me, eeprom, address, data);
626 eeprom->state = byte_programming;
627 return;
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;
633 continue;
635 /* ignore it */
636 return;
638 case chip_erase:
639 if (device_event_queue_time(me) > eeprom->program_finish_time) {
640 finish_erasing_chip(me, eeprom);
641 eeprom->state = read_reset;
642 continue;
644 /* ignore it */
645 return;
647 case sector_erase:
648 if (device_event_queue_time(me) > eeprom->program_finish_time) {
649 finish_erasing_sector(me, eeprom);
650 eeprom->state = eeprom->sector_state;
651 continue;
653 else if (device_event_queue_time(me) > eeprom->sector_start_time
654 && data == 0xb0) {
655 eeprom->sector_state = read_reset;
656 eeprom->state = sector_erase_suspend;
658 else {
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;
680 else {
681 start_erasing_sector(me, eeprom, address);
682 eeprom->sector_state = read_reset;
685 else {
686 invalid_write(me, eeprom->state, address, data, state2a(eeprom->sector_state));
687 eeprom->state = read_reset;
690 return;
692 case sector_erase_suspend:
693 if (data == 0x30)
694 eeprom->state = sector_erase;
695 else {
696 invalid_write(me, eeprom->state, address, data, "not resume command");
697 eeprom->state = read_reset;
699 return;
705 static unsigned
706 hw_eeprom_io_write_buffer(device *me,
707 const void *source,
708 int space,
709 unsigned_word addr,
710 unsigned nr_bytes,
711 cpu *processor,
712 unsigned_word cia)
714 hw_eeprom_device *eeprom = (hw_eeprom_device*)device_data(me);
715 int i;
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);
721 return nr_bytes;
725 /* An instance of the eeprom */
727 typedef struct _hw_eeprom_instance {
728 unsigned_word pos;
729 hw_eeprom_device *eeprom;
730 device *me;
731 } hw_eeprom_instance;
733 static void
734 hw_eeprom_instance_delete(device_instance *instance)
736 hw_eeprom_instance *data = device_instance_data(instance);
737 free(data);
740 static int
741 hw_eeprom_instance_read(device_instance *instance,
742 void *buf,
743 unsigned_word len)
745 hw_eeprom_instance *data = device_instance_data(instance);
746 int i;
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;
753 return len;
756 static int
757 hw_eeprom_instance_write(device_instance *instance,
758 const void *buf,
759 unsigned_word len)
761 hw_eeprom_instance *data = device_instance_data(instance);
762 int i;
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);
770 return len;
773 static int
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);
782 data->pos = pos_lo;
783 return 0;
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,
795 const char *path,
796 const char *args)
798 hw_eeprom_device *eeprom = device_data(me);
799 hw_eeprom_instance *data = ZALLOC(hw_eeprom_instance);
800 data->eeprom = eeprom;
801 data->me = me;
802 return device_create_instance_from(me, NULL,
803 data,
804 path, args,
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 */
816 { NULL, }, /* DMA */
817 { NULL, }, /* interrupt */
818 { NULL, }, /* unit */
819 hw_eeprom_create_instance,
822 static void *
823 hw_eeprom_create(const char *name,
824 const device_unit *unit_address,
825 const char *args)
827 hw_eeprom_device *eeprom = ZALLOC(hw_eeprom_device);
828 return eeprom;
833 const device_descriptor hw_eeprom_device_descriptor[] = {
834 { "eeprom", hw_eeprom_create, &hw_eeprom_callbacks },
835 { NULL },
838 #endif /* _HW_EEPROM_C_ */