]> git.proxmox.com Git - qemu.git/blame - hw/block/onenand.c
Merge git://github.com/hw-claudio/qemu-aarch64-queue into tcg-next
[qemu.git] / hw / block / onenand.c
CommitLineData
7e7c5e4c
AZ
1/*
2 * OneNAND flash memories emulation.
3 *
4 * Copyright (C) 2008 Nokia Corporation
5 * Written by Andrzej Zaborowski <andrew@openedhand.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 or
10 * (at your option) version 3 of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
fad6cb1a 17 * You should have received a copy of the GNU General Public License along
8167ee88 18 * with this program; if not, see <http://www.gnu.org/licenses/>.
7e7c5e4c
AZ
19 */
20
21#include "qemu-common.h"
83c9f4ca 22#include "hw/hw.h"
0d09e41a 23#include "hw/block/flash.h"
83c9f4ca 24#include "hw/irq.h"
9c17d615 25#include "sysemu/blockdev.h"
022c62cb
PB
26#include "exec/memory.h"
27#include "exec/address-spaces.h"
83c9f4ca 28#include "hw/sysbus.h"
1de7afc9 29#include "qemu/error-report.h"
7e7c5e4c
AZ
30
31/* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */
32#define PAGE_SHIFT 11
33
34/* Fixed */
35#define BLOCK_SHIFT (PAGE_SHIFT + 6)
36
bc24a225 37typedef struct {
500954e3 38 SysBusDevice busdev;
5923ba42
JR
39 struct {
40 uint16_t man;
41 uint16_t dev;
42 uint16_t ver;
43 } id;
7e7c5e4c 44 int shift;
a8170e5e 45 hwaddr base;
7e7c5e4c
AZ
46 qemu_irq intr;
47 qemu_irq rdy;
48 BlockDriverState *bdrv;
49 BlockDriverState *bdrv_cur;
50 uint8_t *image;
51 uint8_t *otp;
52 uint8_t *current;
689a1921
AK
53 MemoryRegion ram;
54 MemoryRegion mapped_ram;
500954e3 55 uint8_t current_direction;
7e7c5e4c
AZ
56 uint8_t *boot[2];
57 uint8_t *data[2][2];
689a1921
AK
58 MemoryRegion iomem;
59 MemoryRegion container;
7e7c5e4c
AZ
60 int cycle;
61 int otpmode;
62
63 uint16_t addr[8];
64 uint16_t unladdr[8];
65 int bufaddr;
66 int count;
67 uint16_t command;
68 uint16_t config[2];
69 uint16_t status;
70 uint16_t intstatus;
71 uint16_t wpstatus;
72
bc24a225 73 ECCState ecc;
7e7c5e4c
AZ
74
75 int density_mask;
76 int secs;
77 int secs_cur;
78 int blocks;
79 uint8_t *blockwp;
bc24a225 80} OneNANDState;
7e7c5e4c
AZ
81
82enum {
83 ONEN_BUF_BLOCK = 0,
84 ONEN_BUF_BLOCK2 = 1,
85 ONEN_BUF_DEST_BLOCK = 2,
86 ONEN_BUF_DEST_PAGE = 3,
87 ONEN_BUF_PAGE = 7,
88};
89
90enum {
91 ONEN_ERR_CMD = 1 << 10,
92 ONEN_ERR_ERASE = 1 << 11,
93 ONEN_ERR_PROG = 1 << 12,
94 ONEN_ERR_LOAD = 1 << 13,
95};
96
97enum {
98 ONEN_INT_RESET = 1 << 4,
99 ONEN_INT_ERASE = 1 << 5,
100 ONEN_INT_PROG = 1 << 6,
101 ONEN_INT_LOAD = 1 << 7,
102 ONEN_INT = 1 << 15,
103};
104
105enum {
106 ONEN_LOCK_LOCKTIGHTEN = 1 << 0,
107 ONEN_LOCK_LOCKED = 1 << 1,
108 ONEN_LOCK_UNLOCKED = 1 << 2,
109};
110
689a1921
AK
111static void onenand_mem_setup(OneNANDState *s)
112{
113 /* XXX: We should use IO_MEM_ROMD but we broke it earlier...
114 * Both 0x0000 ... 0x01ff and 0x8000 ... 0x800f can be used to
115 * write boot commands. Also take note of the BWPS bit. */
2d256e6f
PB
116 memory_region_init(&s->container, OBJECT(s), "onenand",
117 0x10000 << s->shift);
689a1921 118 memory_region_add_subregion(&s->container, 0, &s->iomem);
2d256e6f 119 memory_region_init_alias(&s->mapped_ram, OBJECT(s), "onenand-mapped-ram",
689a1921
AK
120 &s->ram, 0x0200 << s->shift,
121 0xbe00 << s->shift);
122 memory_region_add_subregion_overlap(&s->container,
123 0x0200 << s->shift,
124 &s->mapped_ram,
125 1);
126}
127
500954e3 128static void onenand_intr_update(OneNANDState *s)
7e7c5e4c 129{
500954e3 130 qemu_set_irq(s->intr, ((s->intstatus >> 15) ^ (~s->config[0] >> 6)) & 1);
7e7c5e4c
AZ
131}
132
500954e3 133static void onenand_pre_save(void *opaque)
7e7c5e4c 134{
500954e3
JR
135 OneNANDState *s = opaque;
136 if (s->current == s->otp) {
137 s->current_direction = 1;
138 } else if (s->current == s->image) {
139 s->current_direction = 2;
140 } else {
141 s->current_direction = 0;
142 }
7e7c5e4c
AZ
143}
144
500954e3 145static int onenand_post_load(void *opaque, int version_id)
7e7c5e4c 146{
500954e3
JR
147 OneNANDState *s = opaque;
148 switch (s->current_direction) {
149 case 0:
150 break;
151 case 1:
152 s->current = s->otp;
153 break;
154 case 2:
155 s->current = s->image;
156 break;
157 default:
158 return -1;
159 }
160 onenand_intr_update(s);
161 return 0;
7e7c5e4c
AZ
162}
163
500954e3
JR
164static const VMStateDescription vmstate_onenand = {
165 .name = "onenand",
166 .version_id = 1,
167 .minimum_version_id = 1,
168 .minimum_version_id_old = 1,
169 .pre_save = onenand_pre_save,
170 .post_load = onenand_post_load,
171 .fields = (VMStateField[]) {
172 VMSTATE_UINT8(current_direction, OneNANDState),
173 VMSTATE_INT32(cycle, OneNANDState),
174 VMSTATE_INT32(otpmode, OneNANDState),
175 VMSTATE_UINT16_ARRAY(addr, OneNANDState, 8),
176 VMSTATE_UINT16_ARRAY(unladdr, OneNANDState, 8),
177 VMSTATE_INT32(bufaddr, OneNANDState),
178 VMSTATE_INT32(count, OneNANDState),
179 VMSTATE_UINT16(command, OneNANDState),
180 VMSTATE_UINT16_ARRAY(config, OneNANDState, 2),
181 VMSTATE_UINT16(status, OneNANDState),
182 VMSTATE_UINT16(intstatus, OneNANDState),
183 VMSTATE_UINT16(wpstatus, OneNANDState),
184 VMSTATE_INT32(secs_cur, OneNANDState),
185 VMSTATE_PARTIAL_VBUFFER(blockwp, OneNANDState, blocks),
186 VMSTATE_UINT8(ecc.cp, OneNANDState),
187 VMSTATE_UINT16_ARRAY(ecc.lp, OneNANDState, 2),
188 VMSTATE_UINT16(ecc.count, OneNANDState),
b79269b7
IM
189 VMSTATE_BUFFER_POINTER_UNSAFE(otp, OneNANDState, 0,
190 ((64 + 2) << PAGE_SHIFT)),
500954e3
JR
191 VMSTATE_END_OF_LIST()
192 }
193};
194
7e7c5e4c 195/* Hot reset (Reset OneNAND command) or warm reset (RP pin low) */
bc24a225 196static void onenand_reset(OneNANDState *s, int cold)
7e7c5e4c
AZ
197{
198 memset(&s->addr, 0, sizeof(s->addr));
199 s->command = 0;
200 s->count = 1;
201 s->bufaddr = 0;
202 s->config[0] = 0x40c0;
203 s->config[1] = 0x0000;
204 onenand_intr_update(s);
205 qemu_irq_raise(s->rdy);
206 s->status = 0x0000;
207 s->intstatus = cold ? 0x8080 : 0x8010;
208 s->unladdr[0] = 0;
209 s->unladdr[1] = 0;
210 s->wpstatus = 0x0002;
211 s->cycle = 0;
212 s->otpmode = 0;
213 s->bdrv_cur = s->bdrv;
214 s->current = s->image;
215 s->secs_cur = s->secs;
216
217 if (cold) {
218 /* Lock the whole flash */
219 memset(s->blockwp, ONEN_LOCK_LOCKED, s->blocks);
220
500954e3
JR
221 if (s->bdrv_cur && bdrv_read(s->bdrv_cur, 0, s->boot[0], 8) < 0) {
222 hw_error("%s: Loading the BootRAM failed.\n", __func__);
223 }
7e7c5e4c
AZ
224 }
225}
226
500954e3
JR
227static void onenand_system_reset(DeviceState *dev)
228{
1356b98d 229 onenand_reset(FROM_SYSBUS(OneNANDState, SYS_BUS_DEVICE(dev)), 1);
500954e3
JR
230}
231
bc24a225 232static inline int onenand_load_main(OneNANDState *s, int sec, int secn,
7e7c5e4c
AZ
233 void *dest)
234{
235 if (s->bdrv_cur)
236 return bdrv_read(s->bdrv_cur, sec, dest, secn) < 0;
237 else if (sec + secn > s->secs_cur)
238 return 1;
239
240 memcpy(dest, s->current + (sec << 9), secn << 9);
241
242 return 0;
243}
244
bc24a225 245static inline int onenand_prog_main(OneNANDState *s, int sec, int secn,
7e7c5e4c
AZ
246 void *src)
247{
f1588dd2
JR
248 int result = 0;
249
250 if (secn > 0) {
7c00b9de
JR
251 uint32_t size = (uint32_t)secn * 512;
252 const uint8_t *sp = (const uint8_t *)src;
f1588dd2
JR
253 uint8_t *dp = 0;
254 if (s->bdrv_cur) {
7267c094 255 dp = g_malloc(size);
f1588dd2
JR
256 if (!dp || bdrv_read(s->bdrv_cur, sec, dp, secn) < 0) {
257 result = 1;
258 }
259 } else {
260 if (sec + secn > s->secs_cur) {
261 result = 1;
262 } else {
7c00b9de 263 dp = (uint8_t *)s->current + (sec << 9);
f1588dd2
JR
264 }
265 }
266 if (!result) {
267 uint32_t i;
268 for (i = 0; i < size; i++) {
269 dp[i] &= sp[i];
270 }
271 if (s->bdrv_cur) {
272 result = bdrv_write(s->bdrv_cur, sec, dp, secn) < 0;
273 }
274 }
275 if (dp && s->bdrv_cur) {
7267c094 276 g_free(dp);
f1588dd2
JR
277 }
278 }
7e7c5e4c 279
f1588dd2 280 return result;
7e7c5e4c
AZ
281}
282
bc24a225 283static inline int onenand_load_spare(OneNANDState *s, int sec, int secn,
7e7c5e4c
AZ
284 void *dest)
285{
286 uint8_t buf[512];
287
288 if (s->bdrv_cur) {
289 if (bdrv_read(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0)
290 return 1;
291 memcpy(dest, buf + ((sec & 31) << 4), secn << 4);
292 } else if (sec + secn > s->secs_cur)
293 return 1;
294 else
295 memcpy(dest, s->current + (s->secs_cur << 9) + (sec << 4), secn << 4);
296
297 return 0;
298}
299
bc24a225 300static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn,
7e7c5e4c
AZ
301 void *src)
302{
f1588dd2
JR
303 int result = 0;
304 if (secn > 0) {
7c00b9de 305 const uint8_t *sp = (const uint8_t *)src;
f1588dd2
JR
306 uint8_t *dp = 0, *dpp = 0;
307 if (s->bdrv_cur) {
7267c094 308 dp = g_malloc(512);
f1588dd2 309 if (!dp || bdrv_read(s->bdrv_cur,
7c00b9de
JR
310 s->secs_cur + (sec >> 5),
311 dp, 1) < 0) {
f1588dd2
JR
312 result = 1;
313 } else {
314 dpp = dp + ((sec & 31) << 4);
315 }
316 } else {
317 if (sec + secn > s->secs_cur) {
318 result = 1;
319 } else {
320 dpp = s->current + (s->secs_cur << 9) + (sec << 4);
321 }
322 }
323 if (!result) {
324 uint32_t i;
325 for (i = 0; i < (secn << 4); i++) {
326 dpp[i] &= sp[i];
327 }
328 if (s->bdrv_cur) {
329 result = bdrv_write(s->bdrv_cur, s->secs_cur + (sec >> 5),
7c00b9de 330 dp, 1) < 0;
f1588dd2
JR
331 }
332 }
333 if (dp) {
7267c094 334 g_free(dp);
f1588dd2
JR
335 }
336 }
337 return result;
7e7c5e4c
AZ
338}
339
bc24a225 340static inline int onenand_erase(OneNANDState *s, int sec, int num)
7e7c5e4c 341{
f1588dd2 342 uint8_t *blankbuf, *tmpbuf;
7267c094 343 blankbuf = g_malloc(512);
f1588dd2
JR
344 if (!blankbuf) {
345 return 1;
346 }
7267c094 347 tmpbuf = g_malloc(512);
f1588dd2 348 if (!tmpbuf) {
7267c094 349 g_free(blankbuf);
f1588dd2
JR
350 return 1;
351 }
352 memset(blankbuf, 0xff, 512);
353 for (; num > 0; num--, sec++) {
354 if (s->bdrv_cur) {
355 int erasesec = s->secs_cur + (sec >> 5);
7a608f56 356 if (bdrv_write(s->bdrv_cur, sec, blankbuf, 1) < 0) {
f1588dd2
JR
357 goto fail;
358 }
359 if (bdrv_read(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) {
360 goto fail;
361 }
362 memcpy(tmpbuf + ((sec & 31) << 4), blankbuf, 1 << 4);
363 if (bdrv_write(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) {
364 goto fail;
365 }
366 } else {
367 if (sec + 1 > s->secs_cur) {
368 goto fail;
369 }
370 memcpy(s->current + (sec << 9), blankbuf, 512);
371 memcpy(s->current + (s->secs_cur << 9) + (sec << 4),
372 blankbuf, 1 << 4);
373 }
7e7c5e4c
AZ
374 }
375
7267c094
AL
376 g_free(tmpbuf);
377 g_free(blankbuf);
7e7c5e4c 378 return 0;
f1588dd2
JR
379
380fail:
7267c094
AL
381 g_free(tmpbuf);
382 g_free(blankbuf);
f1588dd2 383 return 1;
7e7c5e4c
AZ
384}
385
82866965 386static void onenand_command(OneNANDState *s)
7e7c5e4c
AZ
387{
388 int b;
389 int sec;
390 void *buf;
391#define SETADDR(block, page) \
392 sec = (s->addr[page] & 3) + \
393 ((((s->addr[page] >> 2) & 0x3f) + \
394 (((s->addr[block] & 0xfff) | \
395 (s->addr[block] >> 15 ? \
396 s->density_mask : 0)) << 6)) << (PAGE_SHIFT - 9));
397#define SETBUF_M() \
398 buf = (s->bufaddr & 8) ? \
399 s->data[(s->bufaddr >> 2) & 1][0] : s->boot[0]; \
400 buf += (s->bufaddr & 3) << 9;
401#define SETBUF_S() \
402 buf = (s->bufaddr & 8) ? \
403 s->data[(s->bufaddr >> 2) & 1][1] : s->boot[1]; \
404 buf += (s->bufaddr & 3) << 4;
405
82866965 406 switch (s->command) {
7e7c5e4c
AZ
407 case 0x00: /* Load single/multiple sector data unit into buffer */
408 SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
409
410 SETBUF_M()
411 if (onenand_load_main(s, sec, s->count, buf))
412 s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD;
413
414#if 0
415 SETBUF_S()
416 if (onenand_load_spare(s, sec, s->count, buf))
417 s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD;
418#endif
419
420 /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
421 * or if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
422 * then we need two split the read/write into two chunks.
423 */
424 s->intstatus |= ONEN_INT | ONEN_INT_LOAD;
425 break;
426 case 0x13: /* Load single/multiple spare sector into buffer */
427 SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
428
429 SETBUF_S()
430 if (onenand_load_spare(s, sec, s->count, buf))
431 s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD;
432
433 /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
434 * or if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
435 * then we need two split the read/write into two chunks.
436 */
437 s->intstatus |= ONEN_INT | ONEN_INT_LOAD;
438 break;
439 case 0x80: /* Program single/multiple sector data unit from buffer */
440 SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
441
442 SETBUF_M()
443 if (onenand_prog_main(s, sec, s->count, buf))
444 s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
445
446#if 0
447 SETBUF_S()
448 if (onenand_prog_spare(s, sec, s->count, buf))
449 s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
450#endif
451
452 /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
453 * or if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
454 * then we need two split the read/write into two chunks.
455 */
456 s->intstatus |= ONEN_INT | ONEN_INT_PROG;
457 break;
458 case 0x1a: /* Program single/multiple spare area sector from buffer */
459 SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
460
461 SETBUF_S()
462 if (onenand_prog_spare(s, sec, s->count, buf))
463 s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
464
465 /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
466 * or if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
467 * then we need two split the read/write into two chunks.
468 */
469 s->intstatus |= ONEN_INT | ONEN_INT_PROG;
470 break;
471 case 0x1b: /* Copy-back program */
472 SETBUF_S()
473
474 SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
475 if (onenand_load_main(s, sec, s->count, buf))
476 s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
477
478 SETADDR(ONEN_BUF_DEST_BLOCK, ONEN_BUF_DEST_PAGE)
479 if (onenand_prog_main(s, sec, s->count, buf))
480 s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
481
482 /* TODO: spare areas */
483
484 s->intstatus |= ONEN_INT | ONEN_INT_PROG;
485 break;
486
487 case 0x23: /* Unlock NAND array block(s) */
488 s->intstatus |= ONEN_INT;
489
490 /* XXX the previous (?) area should be locked automatically */
491 for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) {
492 if (b >= s->blocks) {
493 s->status |= ONEN_ERR_CMD;
494 break;
495 }
496 if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN)
497 break;
498
499 s->wpstatus = s->blockwp[b] = ONEN_LOCK_UNLOCKED;
500 }
501 break;
89588a4b
AZ
502 case 0x27: /* Unlock All NAND array blocks */
503 s->intstatus |= ONEN_INT;
504
505 for (b = 0; b < s->blocks; b ++) {
506 if (b >= s->blocks) {
507 s->status |= ONEN_ERR_CMD;
508 break;
509 }
510 if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN)
511 break;
512
513 s->wpstatus = s->blockwp[b] = ONEN_LOCK_UNLOCKED;
514 }
515 break;
516
7e7c5e4c
AZ
517 case 0x2a: /* Lock NAND array block(s) */
518 s->intstatus |= ONEN_INT;
519
520 for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) {
521 if (b >= s->blocks) {
522 s->status |= ONEN_ERR_CMD;
523 break;
524 }
525 if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN)
526 break;
527
528 s->wpstatus = s->blockwp[b] = ONEN_LOCK_LOCKED;
529 }
530 break;
531 case 0x2c: /* Lock-tight NAND array block(s) */
532 s->intstatus |= ONEN_INT;
533
534 for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) {
535 if (b >= s->blocks) {
536 s->status |= ONEN_ERR_CMD;
537 break;
538 }
539 if (s->blockwp[b] == ONEN_LOCK_UNLOCKED)
540 continue;
541
542 s->wpstatus = s->blockwp[b] = ONEN_LOCK_LOCKTIGHTEN;
543 }
544 break;
545
546 case 0x71: /* Erase-Verify-Read */
547 s->intstatus |= ONEN_INT;
548 break;
549 case 0x95: /* Multi-block erase */
550 qemu_irq_pulse(s->intr);
551 /* Fall through. */
552 case 0x94: /* Block erase */
553 sec = ((s->addr[ONEN_BUF_BLOCK] & 0xfff) |
554 (s->addr[ONEN_BUF_BLOCK] >> 15 ? s->density_mask : 0))
555 << (BLOCK_SHIFT - 9);
556 if (onenand_erase(s, sec, 1 << (BLOCK_SHIFT - 9)))
557 s->status |= ONEN_ERR_CMD | ONEN_ERR_ERASE;
558
559 s->intstatus |= ONEN_INT | ONEN_INT_ERASE;
560 break;
561 case 0xb0: /* Erase suspend */
562 break;
563 case 0x30: /* Erase resume */
564 s->intstatus |= ONEN_INT | ONEN_INT_ERASE;
565 break;
566
567 case 0xf0: /* Reset NAND Flash core */
568 onenand_reset(s, 0);
569 break;
570 case 0xf3: /* Reset OneNAND */
571 onenand_reset(s, 0);
572 break;
573
574 case 0x65: /* OTP Access */
575 s->intstatus |= ONEN_INT;
b9d38e95 576 s->bdrv_cur = NULL;
7e7c5e4c
AZ
577 s->current = s->otp;
578 s->secs_cur = 1 << (BLOCK_SHIFT - 9);
579 s->addr[ONEN_BUF_BLOCK] = 0;
580 s->otpmode = 1;
581 break;
582
583 default:
584 s->status |= ONEN_ERR_CMD;
585 s->intstatus |= ONEN_INT;
586 fprintf(stderr, "%s: unknown OneNAND command %x\n",
82866965 587 __func__, s->command);
7e7c5e4c
AZ
588 }
589
590 onenand_intr_update(s);
591}
592
a8170e5e 593static uint64_t onenand_read(void *opaque, hwaddr addr,
689a1921 594 unsigned size)
7e7c5e4c 595{
bc24a225 596 OneNANDState *s = (OneNANDState *) opaque;
8da3ff18 597 int offset = addr >> s->shift;
7e7c5e4c
AZ
598
599 switch (offset) {
600 case 0x0000 ... 0xc000:
8da3ff18 601 return lduw_le_p(s->boot[0] + addr);
7e7c5e4c
AZ
602
603 case 0xf000: /* Manufacturer ID */
5923ba42 604 return s->id.man;
7e7c5e4c 605 case 0xf001: /* Device ID */
5923ba42 606 return s->id.dev;
7e7c5e4c 607 case 0xf002: /* Version ID */
5923ba42
JR
608 return s->id.ver;
609 /* TODO: get the following values from a real chip! */
7e7c5e4c
AZ
610 case 0xf003: /* Data Buffer size */
611 return 1 << PAGE_SHIFT;
612 case 0xf004: /* Boot Buffer size */
613 return 0x200;
614 case 0xf005: /* Amount of buffers */
615 return 1 | (2 << 8);
616 case 0xf006: /* Technology */
617 return 0;
618
619 case 0xf100 ... 0xf107: /* Start addresses */
620 return s->addr[offset - 0xf100];
621
622 case 0xf200: /* Start buffer */
623 return (s->bufaddr << 8) | ((s->count - 1) & (1 << (PAGE_SHIFT - 10)));
624
625 case 0xf220: /* Command */
626 return s->command;
627 case 0xf221: /* System Configuration 1 */
628 return s->config[0] & 0xffe0;
629 case 0xf222: /* System Configuration 2 */
630 return s->config[1];
631
632 case 0xf240: /* Controller Status */
633 return s->status;
634 case 0xf241: /* Interrupt */
635 return s->intstatus;
636 case 0xf24c: /* Unlock Start Block Address */
637 return s->unladdr[0];
638 case 0xf24d: /* Unlock End Block Address */
639 return s->unladdr[1];
640 case 0xf24e: /* Write Protection Status */
641 return s->wpstatus;
642
643 case 0xff00: /* ECC Status */
644 return 0x00;
645 case 0xff01: /* ECC Result of main area data */
646 case 0xff02: /* ECC Result of spare area data */
647 case 0xff03: /* ECC Result of main area data */
648 case 0xff04: /* ECC Result of spare area data */
2ac71179 649 hw_error("%s: imeplement ECC\n", __FUNCTION__);
7e7c5e4c
AZ
650 return 0x0000;
651 }
652
653 fprintf(stderr, "%s: unknown OneNAND register %x\n",
654 __FUNCTION__, offset);
655 return 0;
656}
657
a8170e5e 658static void onenand_write(void *opaque, hwaddr addr,
689a1921 659 uint64_t value, unsigned size)
7e7c5e4c 660{
bc24a225 661 OneNANDState *s = (OneNANDState *) opaque;
8da3ff18 662 int offset = addr >> s->shift;
7e7c5e4c
AZ
663 int sec;
664
665 switch (offset) {
666 case 0x0000 ... 0x01ff:
667 case 0x8000 ... 0x800f:
668 if (s->cycle) {
669 s->cycle = 0;
670
671 if (value == 0x0000) {
672 SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
673 onenand_load_main(s, sec,
674 1 << (PAGE_SHIFT - 9), s->data[0][0]);
675 s->addr[ONEN_BUF_PAGE] += 4;
676 s->addr[ONEN_BUF_PAGE] &= 0xff;
677 }
678 break;
679 }
680
681 switch (value) {
682 case 0x00f0: /* Reset OneNAND */
683 onenand_reset(s, 0);
684 break;
685
686 case 0x00e0: /* Load Data into Buffer */
687 s->cycle = 1;
688 break;
689
690 case 0x0090: /* Read Identification Data */
691 memset(s->boot[0], 0, 3 << s->shift);
5923ba42
JR
692 s->boot[0][0 << s->shift] = s->id.man & 0xff;
693 s->boot[0][1 << s->shift] = s->id.dev & 0xff;
7e7c5e4c
AZ
694 s->boot[0][2 << s->shift] = s->wpstatus & 0xff;
695 break;
696
697 default:
689a1921 698 fprintf(stderr, "%s: unknown OneNAND boot command %"PRIx64"\n",
7e7c5e4c
AZ
699 __FUNCTION__, value);
700 }
701 break;
702
703 case 0xf100 ... 0xf107: /* Start addresses */
704 s->addr[offset - 0xf100] = value;
705 break;
706
707 case 0xf200: /* Start buffer */
708 s->bufaddr = (value >> 8) & 0xf;
709 if (PAGE_SHIFT == 11)
710 s->count = (value & 3) ?: 4;
711 else if (PAGE_SHIFT == 10)
712 s->count = (value & 1) ?: 2;
713 break;
714
715 case 0xf220: /* Command */
716 if (s->intstatus & (1 << 15))
717 break;
718 s->command = value;
82866965 719 onenand_command(s);
7e7c5e4c
AZ
720 break;
721 case 0xf221: /* System Configuration 1 */
722 s->config[0] = value;
723 onenand_intr_update(s);
724 qemu_set_irq(s->rdy, (s->config[0] >> 7) & 1);
725 break;
726 case 0xf222: /* System Configuration 2 */
727 s->config[1] = value;
728 break;
729
730 case 0xf241: /* Interrupt */
731 s->intstatus &= value;
732 if ((1 << 15) & ~s->intstatus)
733 s->status &= ~(ONEN_ERR_CMD | ONEN_ERR_ERASE |
734 ONEN_ERR_PROG | ONEN_ERR_LOAD);
735 onenand_intr_update(s);
736 break;
737 case 0xf24c: /* Unlock Start Block Address */
738 s->unladdr[0] = value & (s->blocks - 1);
739 /* For some reason we have to set the end address to by default
740 * be same as start because the software forgets to write anything
741 * in there. */
742 s->unladdr[1] = value & (s->blocks - 1);
743 break;
744 case 0xf24d: /* Unlock End Block Address */
745 s->unladdr[1] = value & (s->blocks - 1);
746 break;
747
748 default:
749 fprintf(stderr, "%s: unknown OneNAND register %x\n",
750 __FUNCTION__, offset);
751 }
752}
753
689a1921
AK
754static const MemoryRegionOps onenand_ops = {
755 .read = onenand_read,
756 .write = onenand_write,
757 .endianness = DEVICE_NATIVE_ENDIAN,
7e7c5e4c
AZ
758};
759
500954e3 760static int onenand_initfn(SysBusDevice *dev)
7e7c5e4c 761{
500954e3
JR
762 OneNANDState *s = (OneNANDState *)dev;
763 uint32_t size = 1 << (24 + ((s->id.dev >> 4) & 7));
7e7c5e4c 764 void *ram;
a8170e5e 765 s->base = (hwaddr)-1;
b9d38e95 766 s->rdy = NULL;
7e7c5e4c
AZ
767 s->blocks = size >> BLOCK_SHIFT;
768 s->secs = size >> 9;
7267c094 769 s->blockwp = g_malloc(s->blocks);
500954e3
JR
770 s->density_mask = (s->id.dev & 0x08)
771 ? (1 << (6 + ((s->id.dev >> 4) & 7))) : 0;
2d256e6f 772 memory_region_init_io(&s->iomem, OBJECT(s), &onenand_ops, s, "onenand",
689a1921 773 0x10000 << s->shift);
af5a75f4 774 if (!s->bdrv) {
7267c094 775 s->image = memset(g_malloc(size + (size >> 5)),
500954e3
JR
776 0xff, size + (size >> 5));
777 } else {
a3efecb8
JR
778 if (bdrv_is_read_only(s->bdrv)) {
779 error_report("Can't use a read-only drive");
780 return -1;
781 }
500954e3 782 s->bdrv_cur = s->bdrv;
63efb1d9 783 }
7267c094 784 s->otp = memset(g_malloc((64 + 2) << PAGE_SHIFT),
7e7c5e4c 785 0xff, (64 + 2) << PAGE_SHIFT);
2d256e6f
PB
786 memory_region_init_ram(&s->ram, OBJECT(s), "onenand.ram",
787 0xc000 << s->shift);
c5705a77 788 vmstate_register_ram_global(&s->ram);
689a1921 789 ram = memory_region_get_ram_ptr(&s->ram);
7e7c5e4c
AZ
790 s->boot[0] = ram + (0x0000 << s->shift);
791 s->boot[1] = ram + (0x8000 << s->shift);
792 s->data[0][0] = ram + ((0x0200 + (0 << (PAGE_SHIFT - 1))) << s->shift);
793 s->data[0][1] = ram + ((0x8010 + (0 << (PAGE_SHIFT - 6))) << s->shift);
794 s->data[1][0] = ram + ((0x0200 + (1 << (PAGE_SHIFT - 1))) << s->shift);
795 s->data[1][1] = ram + ((0x8010 + (1 << (PAGE_SHIFT - 6))) << s->shift);
689a1921 796 onenand_mem_setup(s);
500954e3 797 sysbus_init_irq(dev, &s->intr);
750ecd44 798 sysbus_init_mmio(dev, &s->container);
500954e3
JR
799 vmstate_register(&dev->qdev,
800 ((s->shift & 0x7f) << 24)
801 | ((s->id.man & 0xff) << 16)
802 | ((s->id.dev & 0xff) << 8)
803 | (s->id.ver & 0xff),
804 &vmstate_onenand, s);
805 return 0;
806}
7e7c5e4c 807
999e12bb
AL
808static Property onenand_properties[] = {
809 DEFINE_PROP_UINT16("manufacturer_id", OneNANDState, id.man, 0),
810 DEFINE_PROP_UINT16("device_id", OneNANDState, id.dev, 0),
811 DEFINE_PROP_UINT16("version_id", OneNANDState, id.ver, 0),
812 DEFINE_PROP_INT32("shift", OneNANDState, shift, 0),
813 DEFINE_PROP_DRIVE("drive", OneNANDState, bdrv),
814 DEFINE_PROP_END_OF_LIST(),
815};
816
817static void onenand_class_init(ObjectClass *klass, void *data)
818{
39bffca2 819 DeviceClass *dc = DEVICE_CLASS(klass);
999e12bb
AL
820 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
821
822 k->init = onenand_initfn;
39bffca2
AL
823 dc->reset = onenand_system_reset;
824 dc->props = onenand_properties;
999e12bb
AL
825}
826
8c43a6f0 827static const TypeInfo onenand_info = {
39bffca2
AL
828 .name = "onenand",
829 .parent = TYPE_SYS_BUS_DEVICE,
830 .instance_size = sizeof(OneNANDState),
831 .class_init = onenand_class_init,
500954e3 832};
7e7c5e4c 833
83f7d43a 834static void onenand_register_types(void)
500954e3 835{
39bffca2 836 type_register_static(&onenand_info);
7e7c5e4c 837}
c580d92b 838
500954e3 839void *onenand_raw_otp(DeviceState *onenand_device)
c580d92b 840{
1356b98d 841 return FROM_SYSBUS(OneNANDState, SYS_BUS_DEVICE(onenand_device))->otp;
c580d92b 842}
500954e3 843
83f7d43a 844type_init(onenand_register_types)