3 * Samsung S3C24XX NAND emulation
5 * Copyright 2006, 2008 Ben Dooks, Daniel Silverstone and Vincent Sanders
7 * Copyright 2010, 2013 Stefan Weil
9 * This file is under the terms of the GNU General Public License Version 2.
12 #include "qemu/osdep.h"
15 #include "exec/address-spaces.h" /* get_system_memory */
26 #define NFCE ((s->nand_reg[NFCONF] & 1<<11) != 0)
28 /* NAND controller state */
29 typedef struct s3c24xx_nand_state_s
{
31 uint32_t nand_reg
[13];
36 static void s3c24xx_nand_write(void *opaque
, hwaddr addr
,
37 uint64_t value
, unsigned size
)
39 S3C24xxNandState
*s
= opaque
;
40 int reg
= (addr
& 0x1f) >> 2;
42 if ((reg
!= NFCONF
) && ((s
->nand_reg
[NFCONF
] & 1<<15) == 0)) {
43 return; /* Ignore the write, the nand is not enabled */
48 s
->nand_reg
[reg
] = value
;
50 nand_setpins(s
->nand
, 0, 0, NFCE
, 1, 0);
54 s
->nand_reg
[reg
] = value
;
55 if (s
->nand
!= NULL
) {
56 nand_setpins(s
->nand
, 1, 0, NFCE
, 1, 0);
57 nand_setio(s
->nand
, value
);
62 s
->nand_reg
[reg
] = value
;
63 if (s
->nand
!= NULL
) {
64 nand_setpins(s
->nand
, 0, 1, NFCE
, 1, 0);
65 nand_setio(s
->nand
, value
);
70 s
->nand_reg
[reg
] = value
;
71 if (s
->nand
!= NULL
) {
72 nand_setpins(s
->nand
, 0, 0, NFCE
, 1, 0);
73 nand_setio(s
->nand
, value
);
78 /* Do nothing because the other registers are read only */
83 static uint64_t s3c24xx_nand_read(void *opaque
, hwaddr addr
,
86 S3C24xxNandState
*s
= opaque
;
87 int reg
= (addr
& 0x1f) >> 2;
89 uint32_t ret
= s
->nand_reg
[reg
];
93 if (s
->nand
!= NULL
) {
94 nand_setpins(s
->nand
, 0, 0, NFCE
, 1, 0);
95 value
= nand_getio(s
->nand
);
97 ret
= s
->nand_reg
[ret
] = value
;
101 if (s
->nand
!= NULL
) {
102 nand_getpins(s
->nand
, &value
);
104 ret
= s
->nand_reg
[reg
] = value
;
107 /* The rest read-back what was written to them */
114 static const MemoryRegionOps s3c24xx_nand_ops
= {
115 .read
= s3c24xx_nand_read
,
116 .write
= s3c24xx_nand_write
,
117 .endianness
= DEVICE_NATIVE_ENDIAN
,
119 .min_access_size
= 1,
124 struct s3c24xx_nand_state_s
*s3c24xx_nand_init(hwaddr base_addr
)
126 S3C24xxNandState
*s
= g_new0(S3C24xxNandState
, 1);
128 memory_region_init_io(&s
->mmio
, OBJECT(s
),
129 &s3c24xx_nand_ops
, s
, "s3c24xx.nand", 0x40);
130 memory_region_add_subregion(get_system_memory(), base_addr
, &s
->mmio
);
136 s3c24xx_nand_attach(S3C24xxNandState
*s
, DeviceState
*nand
)
138 if (s
->nand
!= NULL
) {
139 /* Detach current nand device */
140 /* no cmd, no addr, not enabled, write protected, no 'gnd' */
141 nand_setpins(s
->nand
, 0, 0, 1, 0, 0);