2 * TC58128 NAND EEPROM emulation
4 * Copyright (c) 2005 Samuel Tardieu
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * SPDX-License-Identifier: MIT
27 #include "qemu/osdep.h"
28 #include "qemu/units.h"
29 #include "hw/sh4/sh.h"
30 #include "hw/loader.h"
31 #include "sysemu/qtest.h"
32 #include "qemu/error-report.h"
42 #define RDY(n) ((n) == 0 ? RDY1 : RDY2)
44 typedef enum { WAIT
, READ1
, READ2
, READ3
} state_t
;
47 uint8_t *flash_contents
;
50 uint8_t address_cycle
;
53 static tc58128_dev tc58128_devs
[2];
55 #define FLASH_SIZE (16 * MiB)
57 static void init_dev(tc58128_dev
* dev
, const char *filename
)
62 dev
->flash_contents
= g_malloc(FLASH_SIZE
);
63 memset(dev
->flash_contents
, 0xff, FLASH_SIZE
);
65 /* Load flash image skipping the first block */
66 ret
= load_image_size(filename
, dev
->flash_contents
+ 528 * 32,
67 FLASH_SIZE
- 528 * 32);
69 if (!qtest_enabled()) {
70 error_report("Could not load flash image %s", filename
);
74 /* Build first block with number of blocks */
75 blocks
= DIV_ROUND_UP(ret
, 528 * 32);
76 dev
->flash_contents
[0] = blocks
& 0xff;
77 dev
->flash_contents
[1] = (blocks
>> 8) & 0xff;
78 dev
->flash_contents
[2] = (blocks
>> 16) & 0xff;
79 dev
->flash_contents
[3] = (blocks
>> 24) & 0xff;
80 fprintf(stderr
, "loaded %d bytes for %s into flash\n", ret
,
86 static void handle_command(tc58128_dev
* dev
, uint8_t command
)
90 fprintf(stderr
, "reset flash device\n");
94 fprintf(stderr
, "read mode 1\n");
96 dev
->address_cycle
= 0;
99 fprintf(stderr
, "read mode 2\n");
101 dev
->address_cycle
= 0;
104 fprintf(stderr
, "read mode 3\n");
106 dev
->address_cycle
= 0;
109 fprintf(stderr
, "unknown flash command 0x%02x\n", command
);
114 static void handle_address(tc58128_dev
* dev
, uint8_t data
)
116 switch (dev
->state
) {
120 switch (dev
->address_cycle
) {
123 if (dev
->state
== READ2
)
124 dev
->address
|= 0x100;
125 else if (dev
->state
== READ3
)
126 dev
->address
|= 0x200;
129 dev
->address
+= data
* 528 * 0x100;
132 dev
->address
+= data
* 528;
133 fprintf(stderr
, "address pointer in flash: 0x%08x\n",
140 dev
->address_cycle
++;
147 static uint8_t handle_read(tc58128_dev
* dev
)
150 if (dev
->address
% 0x100000 == 0)
151 fprintf(stderr
, "reading flash at address 0x%08x\n", dev
->address
);
153 return dev
->flash_contents
[dev
->address
++];
156 /* We never mark the device as busy, so interrupts cannot be triggered
159 static int tc58128_cb(uint16_t porta
, uint16_t portb
,
160 uint16_t * periph_pdtra
, uint16_t * periph_portadir
,
161 uint16_t * periph_pdtrb
, uint16_t * periph_portbdir
)
165 if ((porta
& CE1
) == 0)
167 else if ((porta
& CE2
) == 0)
170 return 0; /* No device selected */
172 if ((porta
& RE
) && (porta
& WE
)) {
173 /* Nothing to do, assert ready and return to input state */
174 *periph_portadir
&= 0xff00;
175 *periph_portadir
|= RDY(dev
);
176 *periph_pdtra
|= RDY(dev
);
182 assert((porta
& WE
) == 0);
183 handle_command(&tc58128_devs
[dev
], porta
& 0x00ff);
184 } else if (porta
& ALE
) {
185 assert((porta
& WE
) == 0);
186 handle_address(&tc58128_devs
[dev
], porta
& 0x00ff);
187 } else if ((porta
& RE
) == 0) {
188 *periph_portadir
|= 0x00ff;
189 *periph_pdtra
&= 0xff00;
190 *periph_pdtra
|= handle_read(&tc58128_devs
[dev
]);
197 static sh7750_io_device tc58128
= {
198 RE
| WE
, /* Port A triggers */
199 0, /* Port B triggers */
200 tc58128_cb
/* Callback */
203 int tc58128_init(struct SH7750State
*s
, const char *zone1
, const char *zone2
)
205 init_dev(&tc58128_devs
[0], zone1
);
206 init_dev(&tc58128_devs
[1], zone2
);
207 return sh7750_register_io_device(s
, &tc58128
);