* config/sh/tm-sh.h (BELIEVE_PCC_PROMOTION): Define, so that
[deliverable/binutils-gdb.git] / sim / ppc / hw_eeprom.c
1 /* This file is part of the program psim.
2
3 Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
4
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 2 of the License, or
8 (at your option) any later version.
9
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.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20
21
22 #ifndef _HW_EEPROM_C_
23 #define _HW_EEPROM_C_
24
25 #ifndef STATIC_INLINE_HW_EEPROM
26 #define STATIC_INLINE_HW_EEPROM STATIC_INLINE
27 #endif
28
29 #include "device_table.h"
30
31 #ifdef HAVE_STRING_H
32 #include <string.h>
33 #else
34 #ifdef HAVE_STRINGS_H
35 #include <strings.h>
36 #endif
37 #endif
38
39 /* EEPROM - electricaly erasable programable memory
40
41 Description:
42
43 This device implements a small byte addressable EEPROM.
44 Programming is performed using the same write sequences as used by
45 modern EEPROM components. Writes occure in real time, the device
46 returning a progress value until the programing has been completed.
47
48 Properties:
49
50 reg = <address> <size>. Determine where the device lives in the
51 parents address space.
52
53 nr-sectors = <integer>. When erasing an entire sector is cleared
54 at a time. This specifies the number of sectors in the EEPROM
55 component.
56
57 byte-write-delay = <integer>. Number of clock ticks before the
58 programming of a single byte completes.
59
60 sector-start-delay = <integer>. When erasing sectors, the number
61 of clock ticks after the sector has been specified and the actual
62 erase process commences.
63
64 erase-delay = <intger>. Number of clock ticks before an erase
65 program completes. */
66
67 typedef enum {
68 read_reset,
69 write_nr_2,
70 write_nr_3,
71 write_nr_4,
72 write_nr_5,
73 write_nr_6,
74 byte_program,
75 byte_programming,
76 chip_erase, chip_erasing,
77 sector_erase, sector_erasing,
78 sector_erase_suspend,
79 sector_erase_resume,
80 } eeprom_states;
81
82 typedef struct _eeprom_device {
83 unsigned8 *memory;
84 unsigned sizeof_memory;
85 unsigned sector_size;
86 unsigned nr_sectors;
87 unsigned byte_write_delay;
88 unsigned sector_start_delay;
89 unsigned erase_delay;
90 signed64 programme_start_time;
91 unsigned program_byte_address;
92 eeprom_states state;
93 } eeprom_device;
94
95 static void *
96 eeprom_create(const char *name,
97 const device_unit *unit_address,
98 const char *args,
99 device *parent)
100 {
101 eeprom_device *eeprom = ZALLOC(eeprom_device);
102 return eeprom;
103 }
104
105 typedef struct _eeprom_reg_spec {
106 unsigned32 base;
107 unsigned32 size;
108 } eeprom_reg_spec;
109
110 static void
111 eeprom_init_address(device *me,
112 psim *system)
113 {
114 eeprom_device *eeprom = (eeprom_device*)device_data(me);
115 const device_property *reg = device_find_array_property(me, "reg");
116 const eeprom_reg_spec *spec = reg->array;
117 int nr_entries = reg->sizeof_array / sizeof(*spec);
118
119 if ((reg->sizeof_array % sizeof(*spec)) != 0)
120 error("devices/%s reg property of incorrect size\n", device_name(me));
121 if (nr_entries > 1)
122 error("devices/%s reg property contains multiple specs\n",
123 device_name(me));
124
125 /* initialize the eeprom */
126 if (eeprom->memory == NULL) {
127 eeprom->sizeof_memory = BE2H_4(spec->size);
128 eeprom->memory = zalloc(eeprom->sizeof_memory);
129 }
130 else
131 memset(eeprom->memory, eeprom->sizeof_memory, 0);
132
133 /* figure out the sectors in the eeprom */
134 eeprom->nr_sectors = device_find_integer_property(me, "nr-sectors");
135 eeprom->sector_size = eeprom->sizeof_memory / eeprom->nr_sectors;
136 if (eeprom->sector_size * eeprom->nr_sectors != eeprom->sizeof_memory)
137 error("device/%s nr-sectors does not evenly divide eeprom\n",
138 device_name(me));
139
140 /* timing */
141 eeprom->byte_write_delay = device_find_integer_property(me, "byte-write-delay");
142 eeprom->sector_start_delay = device_find_integer_property(me, "sector-start-delay");
143 eeprom->erase_delay = device_find_integer_property(me, "erase-delay");
144
145 device_attach_address(device_parent(me),
146 device_name(me),
147 attach_callback,
148 0 /*address space*/,
149 BE2H_4(spec->base),
150 eeprom->sizeof_memory,
151 access_read_write_exec,
152 me);
153 }
154
155
156 static unsigned
157 eeprom_io_read_buffer(device *me,
158 void *dest,
159 int space,
160 unsigned_word addr,
161 unsigned nr_bytes,
162 cpu *processor,
163 unsigned_word cia)
164 {
165 eeprom_device *eeprom = (eeprom_device*)device_data(me);
166 int i;
167 for (i = 0; i < nr_bytes; i++) {
168 unsigned_word address = (addr + nr_bytes) % eeprom->sizeof_memory;
169 eeprom->memory[address] = eeprom_io_read_byte(address);
170 }
171 return nr_bytes;
172 }
173
174 static void
175 eeprom_io_write_byte()
176 {
177 switch (state) {
178 case read_reset:
179 if (address == 0x5555 && data = 0xaa)
180 state = first_write;
181 else
182 state = read_reset;
183 break;
184 case first_write:
185 if (address == 0x2aaa && data == 0x55)
186 state = second_write;
187 else
188 state = read_reset; /* issue warning */
189 break;
190 case second_write:
191 if (address == 0x5555 && data == 0xf0)
192 state = read_reset;
193 else if (address == 0x5555 && data == 0x90)
194 state = auto_select;
195 else if (address == 0x5555 && data == 0xa0)
196 state = byte_program;
197 else if (address == 0x5555 && data == 0x80)
198 state = third_write;
199 else
200 state = read_reset;
201 break;
202 case fourth_write:
203 if (address == 0x5555 && data == 0xaa)
204 state = fith_write;
205 else
206 state = read_reset;
207 break;
208 case fith_write:
209 if (address == 0x2aaa && data == 0x55)
210 state = sixth_write;
211 else
212 state = read_reset;
213 break;
214 case sixth_write:
215 if (address == 0x5555 && data == 0x10)
216 state = chip_erase;
217 else
218 sector_erase();
219 break;
220 case auto_select:
221 if (data == 0xf0)
222 state = read_reset;
223 else if (address == 0x5555 && data == 0xaa)
224 state = second_write;
225 else
226 state = read_reset; /* issue warning */
227 break;
228 case sector_erase:
229 if (data == 0xb0)
230 state = sector_erase_suspend;
231 else
232 state = sector_erase; /* ignore */
233 break;
234 case sector_erase_suspend:
235 if (data == 0x30)
236 state = sector_erase;
237 else
238 state = sector_erase_suspend; /* ignore */
239 break;
240 case byte_program:
241 /* perform the byte program */
242 program_address = address;
243 program_start = some_time();
244 toggle = 0;
245 /* but only make things `0' and never 1 */
246 byte[address] = data;
247 state = byte_programming;
248 break;
249 case byte_programming:
250 if (finished)
251 state = read_reset;
252 else
253 state = byte_programming;
254 break;
255 }
256 }
257
258 static unsigned
259 eeprom_io_write_buffer(device *me,
260 const void *source,
261 int space,
262 unsigned_word addr,
263 unsigned nr_bytes,
264 cpu *processor,
265 unsigned_word cia)
266 {
267 eeprom_device *eeprom = (eeprom_device*)device_data(me);
268 int i;
269 for (i = 0; i < nr_bytes; i++) {
270 unsigned_word address = (addr + nr_bytes) % eeprom->sizeof_memory;
271 eeprom_io_read_byte(address, eeprom->memory[address]);
272 }
273 return nr_bytes;
274 }
275
276
277
278 static device_callbacks const eeprom_callbacks = {
279 { eeprom_init_address, },
280 { NULL, }, /* address */
281 { eeprom_io_read_buffer, eeprom_io_write_buffer }, /* IO */
282 };
283
284 const device_descriptor eeprom_device_descriptor[] = {
285 { "eeprom", eeprom_create, &eeprom_callbacks },
286 { NULL },
287 };
288
289 #endif /* _HW_EEPROM_C_ */
This page took 0.033876 seconds and 4 git commands to generate.