1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#ifndef NAND_IO
20
21#include "qemu/osdep.h"
22#include "hw/hw.h"
23#include "hw/block/flash.h"
24#include "sysemu/block-backend.h"
25#include "hw/qdev.h"
26#include "qapi/error.h"
27#include "qemu/error-report.h"
28
29#ifndef NAND_ERR_DEBUG
30#define NAND_ERR_DEBUG 1
31#endif
32
33#define DB_PRINT_L(...) do { \
34 if (NAND_ERR_DEBUG) { \
35 qemu_log_mask(DEV_LOG_NAND, ": %s: ", __func__); \
36 qemu_log_mask(DEV_LOG_NAND, ## __VA_ARGS__); \
37 } \
38} while (0);
39
40# define NAND_CMD_READ0 0x00
41# define NAND_CMD_READ1 0x01
42# define NAND_CMD_READ2 0x50
43# define NAND_CMD_LPREAD2 0x30
44# define NAND_CMD_NOSERIALREAD2 0x35
45# define NAND_CMD_RANDOMREAD1 0x05
46# define NAND_CMD_RANDOMREAD2 0xe0
47# define NAND_CMD_READID 0x90
48# define NAND_CMD_RESET 0xff
49# define NAND_CMD_PAGEPROGRAM1 0x80
50# define NAND_CMD_PAGEPROGRAM2 0x10
51# define NAND_CMD_CACHEPROGRAM2 0x15
52# define NAND_CMD_BLOCKERASE1 0x60
53# define NAND_CMD_BLOCKERASE2 0xd0
54# define NAND_CMD_READSTATUS 0x70
55# define NAND_CMD_COPYBACKPRG1 0x85
56# define NAND_CMD_READ_PARAMETER_PAGE 0xec
57
58# define NAND_IOSTATUS_ERROR (1 << 0)
59# define NAND_IOSTATUS_PLANE0 (1 << 1)
60# define NAND_IOSTATUS_PLANE1 (1 << 2)
61# define NAND_IOSTATUS_PLANE2 (1 << 3)
62# define NAND_IOSTATUS_PLANE3 (1 << 4)
63# define NAND_IOSTATUS_READY (1 << 6)
64# define NAND_IOSTATUS_UNPROTCT (1 << 7)
65
66# define MAX_PAGE 0x800
67# define MAX_OOB 0x40
68# define MAX_PARM_PAGE_SIZE 256
69# define MAX_EXT_PARM_PAGE_SIZE 48
70
71# define NUM_PARAMETER_PAGES_OFFSET 14
72typedef struct NANDFlashState NANDFlashState;
73struct NANDFlashState {
74 DeviceState parent_obj;
75
76 uint8_t manf_id, chip_id;
77 uint8_t buswidth;
78 int size, pages;
79 int page_shift, oob_shift, erase_shift, addr_shift;
80 uint8_t *storage;
81 BlockBackend *blk;
82 int mem_oob;
83
84 uint8_t cle, ale, ce, wp, gnd;
85
86 uint8_t io[MAX_PAGE + MAX_OOB + 0x400];
87 uint8_t *ioaddr;
88 int iolen;
89
90 uint32_t cmd;
91 uint64_t addr;
92 int addrlen;
93 int status;
94 int offset;
95
96 void (*blk_write)(NANDFlashState *s);
97 void (*blk_erase)(NANDFlashState *s);
98 void (*blk_load)(NANDFlashState *s, uint64_t addr, int offset);
99
100 uint32_t ioaddr_vmstate;
101};
102
103#define TYPE_NAND "nand"
104
105#define NAND(obj) \
106 OBJECT_CHECK(NANDFlashState, (obj), TYPE_NAND)
107
108static void mem_and(uint8_t *dest, const uint8_t *src, size_t n)
109{
110
111 int i;
112 for (i = 0; i < n; i++) {
113 dest[i] &= src[i];
114 }
115}
116
117# define NAND_NO_AUTOINCR 0x00000001
118# define NAND_BUSWIDTH_16 0x00000002
119# define NAND_NO_PADDING 0x00000004
120# define NAND_CACHEPRG 0x00000008
121# define NAND_COPYBACK 0x00000010
122# define NAND_IS_AND 0x00000020
123# define NAND_4PAGE_ARRAY 0x00000040
124# define NAND_NO_READRDY 0x00000100
125# define NAND_SAMSUNG_LP (NAND_NO_PADDING | NAND_COPYBACK)
126
127# define NAND_IO
128
129# define PAGE(addr) ((addr) >> ADDR_SHIFT)
130# define PAGE_START(page) (PAGE(page) * (PAGE_SIZE + OOB_SIZE))
131# define PAGE_MASK ((1 << ADDR_SHIFT) - 1)
132# define OOB_SHIFT (PAGE_SHIFT - 5)
133# define OOB_SIZE (1 << OOB_SHIFT)
134# define SECTOR(addr) ((addr) >> (9 + ADDR_SHIFT - PAGE_SHIFT))
135# define SECTOR_OFFSET(addr) ((addr) & ((511 >> PAGE_SHIFT) << 8))
136
137# define PAGE_SIZE 256
138# define PAGE_SHIFT 8
139# define PAGE_SECTORS 1
140# define ADDR_SHIFT 8
141# include "nand.c"
142# define PAGE_SIZE 512
143# define PAGE_SHIFT 9
144# define PAGE_SECTORS 1
145# define ADDR_SHIFT 8
146# include "nand.c"
147# define PAGE_SIZE 2048
148# define PAGE_SHIFT 11
149# define PAGE_SECTORS 4
150# define ADDR_SHIFT 16
151# include "nand.c"
152
153
154static const struct {
155 int size;
156 int width;
157 int page_shift;
158 int erase_shift;
159 uint32_t options;
160 uint32_t oob_size;
161 uint8_t param_page[MAX_PARM_PAGE_SIZE + MAX_EXT_PARM_PAGE_SIZE];
162} nand_flash_ids[0x100] = {
163 [0 ... 0xff] = { 0 },
164
165 [0x44] = { 4096, 8, 14, 8, NAND_SAMSUNG_LP, 1216,
166 .param_page = {
167 0x4F, 0x4E, 0x46, 0x49, 0x7E, 0x00, 0xF8, 0x1D,
168 0xFF, 0x0F, 0x0F, 0x00, 0x03, 0x00, 0x03, 0x00,
169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
170 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
171 0x4D, 0x49, 0x43, 0x52, 0x4F, 0x4E, 0x20, 0x20,
172 0x20, 0x20, 0x20, 0x20, 0x4D, 0x54, 0x32, 0x39,
173 0x46, 0x33, 0x32, 0x47, 0x30, 0x38, 0x41, 0x42,
174 0x43, 0x44, 0x42, 0x4A, 0x34, 0x20, 0x20, 0x20,
175 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
176 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
177 0x00, 0x40, 0x00, 0x00, 0xC0, 0x04, 0x00, 0x00,
178 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
179 0x18, 0x04, 0x00, 0x00, 0x01, 0x23, 0x01, 0x31,
180 0x00, 0x06, 0x04, 0x01, 0x00, 0x00, 0x02, 0x00,
181 0xFF, 0x01, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00,
182 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
183 0x05, 0x3F, 0x00, 0x00, 0x00, 0x94, 0x02, 0x40,
184 0x1F, 0x2D, 0x00, 0xC8, 0x00, 0x3F, 0x7F, 0x02,
185 0x28, 0x00, 0x2D, 0x00, 0x28, 0x00, 0x05, 0x07,
186 0x2D, 0x00, 0x46, 0x00, 0x00, 0x00, 0x1F, 0xFF,
187 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
188 0x00, 0x00, 0x04, 0x10, 0x01, 0x81, 0x04, 0x02,
189 0x02, 0x01, 0x1E, 0x90, 0x0A, 0x00, 0x00, 0x00,
190 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
191 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
192 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
193 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
194 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
195 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
196 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x63, 0x8A,
199 0xBD, 0x70, 0x45, 0x50, 0x50, 0x53, 0x00, 0x00,
200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
201 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
203 0x18, 0x0A, 0x64, 0x00, 0x05, 0x03, 0x00, 0x00,
204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
205 }
206 },
207
208 [0x6e] = { 1, 8, 8, 4, 0 },
209 [0x64] = { 2, 8, 8, 4, 0 },
210 [0x6b] = { 4, 8, 9, 4, 0 },
211 [0xe8] = { 1, 8, 8, 4, 0 },
212 [0xec] = { 1, 8, 8, 4, 0 },
213 [0xea] = { 2, 8, 8, 4, 0 },
214 [0xd5] = { 4, 8, 9, 4, 0 },
215 [0xe3] = { 4, 8, 9, 4, 0 },
216 [0xe5] = { 4, 8, 9, 4, 0 },
217 [0xd6] = { 8, 8, 9, 4, 0 },
218
219 [0x39] = { 8, 8, 9, 4, 0 },
220 [0xe6] = { 8, 8, 9, 4, 0 },
221 [0x49] = { 8, 16, 9, 4, NAND_BUSWIDTH_16 },
222 [0x59] = { 8, 16, 9, 4, NAND_BUSWIDTH_16 },
223
224 [0x33] = { 16, 8, 9, 5, 0 },
225 [0x73] = { 16, 8, 9, 5, 0 },
226 [0x43] = { 16, 16, 9, 5, NAND_BUSWIDTH_16 },
227 [0x53] = { 16, 16, 9, 5, NAND_BUSWIDTH_16 },
228
229 [0x35] = { 32, 8, 9, 5, 0 },
230 [0x75] = { 32, 8, 9, 5, 0 },
231 [0x45] = { 32, 16, 9, 5, NAND_BUSWIDTH_16 },
232 [0x55] = { 32, 16, 9, 5, NAND_BUSWIDTH_16 },
233
234 [0x36] = { 64, 8, 9, 5, 0 },
235 [0x76] = { 64, 8, 9, 5, 0 },
236 [0x46] = { 64, 16, 9, 5, NAND_BUSWIDTH_16 },
237 [0x56] = { 64, 16, 9, 5, NAND_BUSWIDTH_16 },
238
239 [0x78] = { 128, 8, 9, 5, 0 },
240 [0x39] = { 128, 8, 9, 5, 0 },
241 [0x79] = { 128, 8, 9, 5, 0 },
242 [0x72] = { 128, 16, 9, 5, NAND_BUSWIDTH_16 },
243 [0x49] = { 128, 16, 9, 5, NAND_BUSWIDTH_16 },
244 [0x74] = { 128, 16, 9, 5, NAND_BUSWIDTH_16 },
245 [0x59] = { 128, 16, 9, 5, NAND_BUSWIDTH_16 },
246
247 [0x71] = { 256, 8, 9, 5, 0 },
248
249
250
251
252
253# define LP_OPTIONS (NAND_SAMSUNG_LP | NAND_NO_READRDY | NAND_NO_AUTOINCR)
254# define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16)
255
256
257 [0xa2] = { 64, 8, 0, 0, LP_OPTIONS },
258 [0xf2] = { 64, 8, 0, 0, LP_OPTIONS },
259 [0xb2] = { 64, 16, 0, 0, LP_OPTIONS16 },
260 [0xc2] = { 64, 16, 0, 0, LP_OPTIONS16 },
261
262
263
264 [0xa1] = { 128, 8, 0, 0, LP_OPTIONS, 64,
265 .param_page = {
266 0x4F, 0x4E, 0x46, 0x49, 0x02, 0x00, 0x1, 0x0,
267 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
268 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
269 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
270 0x4D, 0x49, 0x43, 0x52, 0x4F, 0x4E, 0x20, 0x20,
271 0x20, 0x20, 0x20, 0x20, 0x4D, 0x54, 0x32, 0x39,
272 0x46, 0x31, 0x47, 0x30, 0x38, 0x41, 0x42, 0x42,
273 0x44, 0x41, 0x33, 0x57, 0x20, 0x20, 0x20, 0x20,
274 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
275 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
276 0x00, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0x20,
277 0x00, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x00,
278 0x00, 0x04, 0x00, 0x00, 0x01, 0x22, 0x01, 0x14,
279 0x00, 0x01, 0x05, 0x01, 0x00, 0x00, 0x04, 0x00,
280 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
281 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
282 0x0A, 0x1F, 0x00, 0x1F, 0x00, 0x58, 0x02, 0xB8,
283 0x0B, 0x19, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00,
284 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
285 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
286 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
287 0x00, 0x02, 0x04, 0x80, 0x01, 0x81, 0x04, 0x01,
288 0x02, 0x01, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
289 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
290 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
291 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
292 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
293 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
294 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
295 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
296 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
297 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x09,
298 },
299 },
300 [0xf1] = { 128, 8, 0, 0, LP_OPTIONS },
301 [0xb1] = { 128, 16, 0, 0, LP_OPTIONS16 },
302 [0xc1] = { 128, 16, 0, 0, LP_OPTIONS16 },
303
304
305 [0xaa] = {
306 256, 8, 0, 0, LP_OPTIONS,
307 .param_page = {
308 0x4F, 0x4E, 0x46, 0x49, 0x02, 0x00, 0x00, 0x00,
309 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
310 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
311 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
312 0x4D, 0x49, 0x43, 0x52, 0x4F, 0x4E, 0x20, 0x20,
313 0x20, 0x20, 0x20, 0x20, 0x4D, 0x54, 0x32, 0x39,
314 0x46, 0x32, 0x47, 0x30, 0x38, 0x41, 0x42, 0x42,
315 0x45, 0x41, 0x48, 0x43, 0x20, 0x20, 0x20, 0x20,
316 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
318 0x00, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02,
319 0x00, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x00,
320 0x00, 0x08, 0x00, 0x00, 0x01, 0x23, 0x01, 0x28,
321 0x00, 0x01, 0x05, 0x01, 0x00, 0x00, 0x04, 0x00,
322 0x04, 0x01, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
323 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
324 0x0A, 0x1F, 0x00, 0x1F, 0x00, 0x58, 0x02, 0xB8,
325 0x0B, 0x19, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00,
326 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
327 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
328 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
329 0x00, 0x02, 0x04, 0x80, 0x01, 0x81, 0x04, 0x01,
330 0x02, 0x01, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
331 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
333 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
335 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
336 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
337 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
338 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
339 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x1E
340 }
341 },
342 [0xda] = { 256, 8, 0, 0, LP_OPTIONS },
343 [0xba] = { 256, 16, 0, 0, LP_OPTIONS16 },
344 [0xca] = { 256, 16, 0, 0, LP_OPTIONS16 },
345
346
347 [0xac] = { 512, 8, 0, 0, LP_OPTIONS },
348 [0xdc] = { 512, 8, 0, 0, LP_OPTIONS },
349 [0xbc] = { 512, 16, 0, 0, LP_OPTIONS16 },
350 [0xcc] = { 512, 16, 0, 0, LP_OPTIONS16 },
351
352
353 [0xa3] = { 1024, 8, 0, 0, LP_OPTIONS },
354 [0xd3] = { 1024, 8, 0, 0, LP_OPTIONS },
355 [0xb3] = { 1024, 16, 0, 0, LP_OPTIONS16 },
356 [0xc3] = { 1024, 16, 0, 0, LP_OPTIONS16 },
357
358
359 [0xa5] = { 2048, 8, 0, 0, LP_OPTIONS },
360 [0xd5] = { 2048, 8, 0, 0, LP_OPTIONS },
361 [0xb5] = { 2048, 16, 0, 0, LP_OPTIONS16 },
362 [0xc5] = { 2048, 16, 0, 0, LP_OPTIONS16 },
363};
364
365static void nand_reset(DeviceState *dev)
366{
367 NANDFlashState *s = NAND(dev);
368 s->cmd = NAND_CMD_READ0;
369 s->addr = 0;
370 s->addrlen = 0;
371 s->iolen = 0;
372 s->offset = 0;
373 s->status &= NAND_IOSTATUS_UNPROTCT;
374 s->status |= NAND_IOSTATUS_READY;
375}
376
377static inline void nand_pushio_byte(NANDFlashState *s, uint8_t value)
378{
379 s->ioaddr[s->iolen++] = value;
380 for (value = s->buswidth; --value;) {
381 s->ioaddr[s->iolen++] = 0;
382 }
383}
384
385static void nand_command(NANDFlashState *s)
386{
387 int i, j;
388 unsigned int offset;
389 switch (s->cmd) {
390 case NAND_CMD_READ0:
391 s->iolen = 0;
392 break;
393
394 case NAND_CMD_READID:
395 s->ioaddr = s->io;
396 s->iolen = 0;
397 nand_pushio_byte(s, s->manf_id);
398 nand_pushio_byte(s, s->chip_id);
399 nand_pushio_byte(s, 'Q');
400 if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
401
402
403
404 nand_pushio_byte(s, (s->buswidth == 2) ? 0x55 : 0x15);
405 } else {
406 nand_pushio_byte(s, 0xc0);
407 }
408 break;
409 case NAND_CMD_READ_PARAMETER_PAGE:
410 s->ioaddr = s->io;
411 s->iolen = 0;
412 int num_parameter_pages = \
413 nand_flash_ids[s->chip_id].param_page[NUM_PARAMETER_PAGES_OFFSET];
414
415
416 if (!num_parameter_pages) {
417 num_parameter_pages = 3;
418 }
419
420
421 for (j = 0; j < num_parameter_pages; ++j) {
422 for (i = 0; i < MAX_PARM_PAGE_SIZE; ++i) {
423 nand_pushio_byte(s, nand_flash_ids[s->chip_id].param_page[i]);
424 }
425 }
426
427
428 for (j = 0; j < num_parameter_pages; ++j) {
429 for (i = MAX_PARM_PAGE_SIZE; \
430 i < (MAX_PARM_PAGE_SIZE + MAX_EXT_PARM_PAGE_SIZE); ++i) {
431 nand_pushio_byte(s, nand_flash_ids[s->chip_id].param_page[i]);
432 }
433 }
434 break;
435
436 case NAND_CMD_RANDOMREAD2:
437 case NAND_CMD_NOSERIALREAD2:
438 if (!(nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP))
439 break;
440 offset = s->addr & ((1 << s->addr_shift) - 1);
441 s->blk_load(s, s->addr, offset);
442 if (s->gnd)
443 s->iolen = (1 << s->page_shift) - offset;
444 else
445 s->iolen = (1 << s->page_shift) + (1 << s->oob_shift) - offset;
446 break;
447
448 case NAND_CMD_RESET:
449 nand_reset(DEVICE(s));
450 break;
451
452 case NAND_CMD_PAGEPROGRAM1:
453 s->ioaddr = s->io;
454 s->iolen = 0;
455 break;
456
457 case NAND_CMD_PAGEPROGRAM2:
458 if (s->wp) {
459 s->blk_write(s);
460 }
461 break;
462
463 case NAND_CMD_BLOCKERASE1:
464 break;
465
466 case NAND_CMD_BLOCKERASE2:
467 s->addr &= (1ull << s->addrlen * 8) - 1;
468 s->addr <<= nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP ?
469 16 : 8;
470
471 if (s->wp) {
472 s->blk_erase(s);
473 }
474 break;
475
476 case NAND_CMD_READSTATUS:
477 s->ioaddr = s->io;
478 s->iolen = 0;
479 nand_pushio_byte(s, s->status);
480 break;
481
482 default:
483 printf("%s: Unknown NAND command 0x%02x\n", __FUNCTION__, s->cmd);
484 }
485}
486
487static void nand_pre_save(void *opaque)
488{
489 NANDFlashState *s = NAND(opaque);
490
491 s->ioaddr_vmstate = s->ioaddr - s->io;
492}
493
494static int nand_post_load(void *opaque, int version_id)
495{
496 NANDFlashState *s = NAND(opaque);
497
498 if (s->ioaddr_vmstate > sizeof(s->io)) {
499 return -EINVAL;
500 }
501 s->ioaddr = s->io + s->ioaddr_vmstate;
502
503 return 0;
504}
505
506static const VMStateDescription vmstate_nand = {
507 .name = "nand",
508 .version_id = 1,
509 .minimum_version_id = 1,
510 .pre_save = nand_pre_save,
511 .post_load = nand_post_load,
512 .fields = (VMStateField[]) {
513 VMSTATE_UINT8(cle, NANDFlashState),
514 VMSTATE_UINT8(ale, NANDFlashState),
515 VMSTATE_UINT8(ce, NANDFlashState),
516 VMSTATE_UINT8(wp, NANDFlashState),
517 VMSTATE_UINT8(gnd, NANDFlashState),
518 VMSTATE_BUFFER(io, NANDFlashState),
519 VMSTATE_UINT32(ioaddr_vmstate, NANDFlashState),
520 VMSTATE_INT32(iolen, NANDFlashState),
521 VMSTATE_UINT32(cmd, NANDFlashState),
522 VMSTATE_UINT64(addr, NANDFlashState),
523 VMSTATE_INT32(addrlen, NANDFlashState),
524 VMSTATE_INT32(status, NANDFlashState),
525 VMSTATE_INT32(offset, NANDFlashState),
526
527 VMSTATE_END_OF_LIST()
528 }
529};
530
531static void nand_realize(DeviceState *dev, Error **errp)
532{
533 int pagesize;
534 NANDFlashState *s = NAND(dev);
535
536 s->buswidth = nand_flash_ids[s->chip_id].width >> 3;
537 s->size = nand_flash_ids[s->chip_id].size << 20;
538 if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
539 s->page_shift = 11;
540 s->erase_shift = 6;
541 } else {
542 s->page_shift = nand_flash_ids[s->chip_id].page_shift;
543 s->erase_shift = nand_flash_ids[s->chip_id].erase_shift;
544 }
545
546 switch (1 << s->page_shift) {
547 case 256:
548 nand_init_256(s);
549 break;
550 case 512:
551 nand_init_512(s);
552 break;
553 case 2048:
554 nand_init_2048(s);
555 break;
556 default:
557 error_setg(errp, "Unsupported NAND block size %#x",
558 1 << s->page_shift);
559 return;
560 }
561
562 pagesize = 1 << s->oob_shift;
563 s->mem_oob = 1;
564 if (s->blk) {
565 if (blk_is_read_only(s->blk)) {
566 error_setg(errp, "Can't use a read-only drive");
567 return;
568 }
569 if (blk_getlength(s->blk) >=
570 (s->pages << s->page_shift) + (s->pages << s->oob_shift)) {
571 pagesize = 0;
572 s->mem_oob = 0;
573 }
574 } else {
575 pagesize += 1 << s->page_shift;
576 }
577 if (pagesize) {
578 s->storage = (uint8_t *) memset(g_malloc(s->pages * pagesize),
579 0xff, s->pages * pagesize);
580 }
581
582 s->ioaddr = s->io;
583}
584
585static Property nand_properties[] = {
586 DEFINE_PROP_UINT8("manufacturer_id", NANDFlashState, manf_id, 0),
587 DEFINE_PROP_UINT8("chip_id", NANDFlashState, chip_id, 0),
588 DEFINE_PROP_DRIVE("drive", NANDFlashState, blk),
589 DEFINE_PROP_END_OF_LIST(),
590};
591
592static void nand_class_init(ObjectClass *klass, void *data)
593{
594 DeviceClass *dc = DEVICE_CLASS(klass);
595
596 dc->realize = nand_realize;
597 dc->reset = nand_reset;
598 dc->vmsd = &vmstate_nand;
599 dc->props = nand_properties;
600}
601
602static const TypeInfo nand_info = {
603 .name = TYPE_NAND,
604 .parent = TYPE_DEVICE,
605 .instance_size = sizeof(NANDFlashState),
606 .class_init = nand_class_init,
607};
608
609static void nand_register_types(void)
610{
611 type_register_static(&nand_info);
612}
613
614
615
616
617
618
619
620void nand_setpins(DeviceState *dev, uint8_t cle, uint8_t ale,
621 uint8_t ce, uint8_t wp, uint8_t gnd)
622{
623 NANDFlashState *s = NAND(dev);
624
625 s->cle = cle;
626 s->ale = ale;
627 s->ce = ce;
628 s->wp = wp;
629 s->gnd = gnd;
630 if (wp) {
631 s->status |= NAND_IOSTATUS_UNPROTCT;
632 } else {
633 s->status &= ~NAND_IOSTATUS_UNPROTCT;
634 }
635}
636
637void nand_getpins(DeviceState *dev, int *rb)
638{
639 *rb = 1;
640}
641
642void nand_setio(DeviceState *dev, uint32_t value)
643{
644 int i;
645 NANDFlashState *s = NAND(dev);
646
647 if (!s->ce && s->cle) {
648 if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
649 if (s->cmd == NAND_CMD_READ0 && value == NAND_CMD_LPREAD2)
650 return;
651 if (value == NAND_CMD_RANDOMREAD1) {
652 s->addr &= ~((1 << s->addr_shift) - 1);
653 s->addrlen = 0;
654 return;
655 }
656 }
657 if (value == NAND_CMD_READ0) {
658 s->offset = 0;
659 } else if (value == NAND_CMD_READ1) {
660 s->offset = 0x100;
661 value = NAND_CMD_READ0;
662 } else if (value == NAND_CMD_READ2) {
663 s->offset = 1 << s->page_shift;
664 value = NAND_CMD_READ0;
665 }
666
667 s->cmd = value;
668
669 if (s->cmd == NAND_CMD_READSTATUS ||
670 s->cmd == NAND_CMD_PAGEPROGRAM2 ||
671 s->cmd == NAND_CMD_BLOCKERASE1 ||
672 s->cmd == NAND_CMD_BLOCKERASE2 ||
673 s->cmd == NAND_CMD_NOSERIALREAD2 ||
674 s->cmd == NAND_CMD_RANDOMREAD2 ||
675 s->cmd == NAND_CMD_RESET) {
676 nand_command(s);
677 }
678
679 if (s->cmd != NAND_CMD_RANDOMREAD2) {
680 s->addrlen = 0;
681 }
682 }
683
684 if (s->ale) {
685 unsigned int shift = s->addrlen * 8;
686 uint64_t mask = ~(0xffull << shift);
687 uint64_t v = (uint64_t)value << shift;
688
689 s->addr = (s->addr & mask) | v;
690 s->addrlen ++;
691
692 switch (s->addrlen) {
693 case 1:
694 if (s->cmd == NAND_CMD_READID) {
695 nand_command(s);
696 }
697 break;
698 case 2:
699 s->addr <<= (s->buswidth - 1);
700 break;
701 case 3:
702 if (!(nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) &&
703 (s->cmd == NAND_CMD_READ0 ||
704 s->cmd == NAND_CMD_PAGEPROGRAM1)) {
705 nand_command(s);
706 }
707 break;
708 case 4:
709 if ((nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) &&
710 nand_flash_ids[s->chip_id].size < 256 &&
711 (s->cmd == NAND_CMD_READ0 ||
712 s->cmd == NAND_CMD_PAGEPROGRAM1)) {
713 nand_command(s);
714 }
715 break;
716 case 5:
717 if ((nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) &&
718 nand_flash_ids[s->chip_id].size >= 256 &&
719 (s->cmd == NAND_CMD_READ0 ||
720 s->cmd == NAND_CMD_PAGEPROGRAM1)) {
721 nand_command(s);
722 }
723 break;
724 default:
725 break;
726 }
727 }
728
729 if (!s->cle && !s->ale && s->cmd == NAND_CMD_PAGEPROGRAM1) {
730 if (s->iolen < (1 << s->page_shift) + (1 << s->oob_shift)) {
731 for (i = s->buswidth; i--; value >>= 8) {
732 s->io[s->iolen ++] = (uint8_t) (value & 0xff);
733 }
734 }
735 } else if (!s->cle && !s->ale && s->cmd == NAND_CMD_COPYBACKPRG1) {
736 if ((s->addr & ((1 << s->addr_shift) - 1)) <
737 (1 << s->page_shift) + (1 << s->oob_shift)) {
738 for (i = s->buswidth; i--; s->addr++, value >>= 8) {
739 s->io[s->iolen + (s->addr & ((1 << s->addr_shift) - 1))] =
740 (uint8_t) (value & 0xff);
741 }
742 }
743 }
744}
745
746uint32_t nand_getio(DeviceState *dev)
747{
748 int offset;
749 uint32_t x = 0;
750 NANDFlashState *s = NAND(dev);
751
752
753 if (!s->iolen && s->cmd == NAND_CMD_READ0) {
754 offset = (int) (s->addr & ((1 << s->addr_shift) - 1)) + s->offset;
755 s->offset = 0;
756
757 s->blk_load(s, s->addr, offset);
758 if (s->gnd)
759 s->iolen = (1 << s->page_shift) - offset;
760 else
761 s->iolen = (1 << s->page_shift) + (1 << s->oob_shift) - offset;
762 }
763
764 if (s->ce || s->iolen <= 0) {
765 return 0;
766 }
767
768 for (offset = s->buswidth; offset--;) {
769 x |= s->ioaddr[offset] << (offset << 3);
770 }
771
772
773
774 if (s->cmd != NAND_CMD_READSTATUS) {
775 s->addr += s->buswidth;
776 s->ioaddr += s->buswidth;
777 s->iolen -= s->buswidth;
778 }
779 return x;
780}
781
782uint32_t nand_getbuswidth(DeviceState *dev)
783{
784 NANDFlashState *s = (NANDFlashState *) dev;
785 return s->buswidth << 3;
786}
787
788DeviceState *nand_init(BlockBackend *blk, int manf_id, int chip_id)
789{
790 DeviceState *dev;
791
792 if (nand_flash_ids[chip_id].size == 0) {
793 hw_error("%s: Unsupported NAND chip ID.\n", __FUNCTION__);
794 }
795 dev = DEVICE(object_new(TYPE_NAND));
796 qdev_prop_set_uint8(dev, "manufacturer_id", manf_id);
797 qdev_prop_set_uint8(dev, "chip_id", chip_id);
798 if (blk) {
799 qdev_prop_set_drive(dev, "drive", blk, &error_fatal);
800 }
801
802 qdev_init_nofail(dev);
803 return dev;
804}
805
806type_init(nand_register_types)
807
808#else
809
810
811static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
812{
813 uint64_t off, page, sector, soff;
814 uint8_t iobuf[(PAGE_SECTORS + 2) * 0x200];
815 if (PAGE(s->addr) >= s->pages)
816 return;
817
818 if (!s->blk) {
819 mem_and(s->storage + PAGE_START(s->addr) + (s->addr & PAGE_MASK) +
820 s->offset, s->io, s->iolen);
821 } else if (s->mem_oob) {
822 sector = SECTOR(s->addr);
823 off = (s->addr & PAGE_MASK) + s->offset;
824 soff = SECTOR_OFFSET(s->addr);
825 if (blk_pread(s->blk, sector << BDRV_SECTOR_BITS, iobuf,
826 PAGE_SECTORS << BDRV_SECTOR_BITS) < 0) {
827 printf("%s: read error in sector %" PRIu64 "\n", __func__, sector);
828 return;
829 }
830
831 mem_and(iobuf + (soff | off), s->io, MIN(s->iolen, PAGE_SIZE - off));
832 if (off + s->iolen > PAGE_SIZE) {
833 page = PAGE(s->addr);
834 mem_and(s->storage + (page << OOB_SHIFT), s->io + PAGE_SIZE - off,
835 MIN(OOB_SIZE, off + s->iolen - PAGE_SIZE));
836 }
837
838 if (blk_pwrite(s->blk, sector << BDRV_SECTOR_BITS, iobuf,
839 PAGE_SECTORS << BDRV_SECTOR_BITS, 0) < 0) {
840 printf("%s: write error in sector %" PRIu64 "\n", __func__, sector);
841 }
842 } else {
843 off = PAGE_START(s->addr) + (s->addr & PAGE_MASK) + s->offset;
844 sector = off >> 9;
845 soff = off & 0x1ff;
846 if (blk_pread(s->blk, sector << BDRV_SECTOR_BITS, iobuf,
847 (PAGE_SECTORS + 2) << BDRV_SECTOR_BITS) < 0) {
848 printf("%s: read error in sector %" PRIu64 "\n", __func__, sector);
849 return;
850 }
851
852 mem_and(iobuf + soff, s->io, s->iolen);
853
854 if (blk_pwrite(s->blk, sector << BDRV_SECTOR_BITS, iobuf,
855 (PAGE_SECTORS + 2) << BDRV_SECTOR_BITS, 0) < 0) {
856 printf("%s: write error in sector %" PRIu64 "\n", __func__, sector);
857 }
858 }
859 s->offset = 0;
860}
861
862
863static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s)
864{
865 uint64_t i, page, addr;
866 uint8_t iobuf[0x200] = { [0 ... 0x1ff] = 0xff, };
867 addr = s->addr & ~((1 << (ADDR_SHIFT + s->erase_shift)) - 1);
868
869 if (PAGE(addr) >= s->pages) {
870 return;
871 }
872
873 if (!s->blk) {
874 memset(s->storage + PAGE_START(addr),
875 0xff, (PAGE_SIZE + OOB_SIZE) << s->erase_shift);
876 } else if (s->mem_oob) {
877 memset(s->storage + (PAGE(addr) << OOB_SHIFT),
878 0xff, OOB_SIZE << s->erase_shift);
879 i = SECTOR(addr);
880 page = SECTOR(addr + (1 << (ADDR_SHIFT + s->erase_shift)));
881 for (; i < page; i ++)
882 if (blk_pwrite(s->blk, i << BDRV_SECTOR_BITS, iobuf,
883 BDRV_SECTOR_SIZE, 0) < 0) {
884 printf("%s: write error in sector %" PRIu64 "\n", __func__, i);
885 }
886 } else {
887 addr = PAGE_START(addr);
888 page = addr >> 9;
889 if (blk_pread(s->blk, page << BDRV_SECTOR_BITS, iobuf,
890 BDRV_SECTOR_SIZE) < 0) {
891 printf("%s: read error in sector %" PRIu64 "\n", __func__, page);
892 }
893 memset(iobuf + (addr & 0x1ff), 0xff, (~addr & 0x1ff) + 1);
894 if (blk_pwrite(s->blk, page << BDRV_SECTOR_BITS, iobuf,
895 BDRV_SECTOR_SIZE, 0) < 0) {
896 printf("%s: write error in sector %" PRIu64 "\n", __func__, page);
897 }
898
899 memset(iobuf, 0xff, 0x200);
900 i = (addr & ~0x1ff) + 0x200;
901 for (addr += ((PAGE_SIZE + OOB_SIZE) << s->erase_shift) - 0x200;
902 i < addr; i += 0x200) {
903 if (blk_pwrite(s->blk, i, iobuf, BDRV_SECTOR_SIZE, 0) < 0) {
904 printf("%s: write error in sector %" PRIu64 "\n",
905 __func__, i >> 9);
906 }
907 }
908
909 page = i >> 9;
910 if (blk_pread(s->blk, page << BDRV_SECTOR_BITS, iobuf,
911 BDRV_SECTOR_SIZE) < 0) {
912 printf("%s: read error in sector %" PRIu64 "\n", __func__, page);
913 }
914 memset(iobuf, 0xff, ((addr - 1) & 0x1ff) + 1);
915 if (blk_pwrite(s->blk, page << BDRV_SECTOR_BITS, iobuf,
916 BDRV_SECTOR_SIZE, 0) < 0) {
917 printf("%s: write error in sector %" PRIu64 "\n", __func__, page);
918 }
919 }
920}
921
922static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s,
923 uint64_t addr, int offset)
924{
925 if (PAGE(addr) >= s->pages) {
926 return;
927 }
928
929 if (s->blk) {
930 if (s->mem_oob) {
931 if (blk_pread(s->blk, SECTOR(addr) << BDRV_SECTOR_BITS, s->io,
932 PAGE_SECTORS << BDRV_SECTOR_BITS) < 0) {
933 printf("%s: read error in sector %" PRIu64 "\n",
934 __func__, SECTOR(addr));
935 }
936 memcpy(s->io + SECTOR_OFFSET(s->addr) + PAGE_SIZE,
937 s->storage + (PAGE(s->addr) << OOB_SHIFT),
938 OOB_SIZE);
939 s->ioaddr = s->io + SECTOR_OFFSET(s->addr) + offset;
940 } else {
941 if (blk_pread(s->blk, PAGE_START(addr), s->io,
942 (PAGE_SECTORS + 2) << BDRV_SECTOR_BITS) < 0) {
943 printf("%s: read error in sector %" PRIu64 "\n",
944 __func__, PAGE_START(addr) >> 9);
945 }
946 s->ioaddr = s->io + (PAGE_START(addr) & 0x1ff) + offset;
947 }
948 } else {
949 memcpy(s->io, s->storage + PAGE_START(s->addr) +
950 offset, PAGE_SIZE + OOB_SIZE - offset);
951 s->ioaddr = s->io;
952 }
953}
954
955static void glue(nand_init_, PAGE_SIZE)(NANDFlashState *s)
956{
957 s->oob_shift = PAGE_SHIFT - 5;
958 s->pages = s->size >> PAGE_SHIFT;
959 s->addr_shift = ADDR_SHIFT;
960
961 s->blk_erase = glue(nand_blk_erase_, PAGE_SIZE);
962 s->blk_write = glue(nand_blk_write_, PAGE_SIZE);
963 s->blk_load = glue(nand_blk_load_, PAGE_SIZE);
964}
965
966# undef PAGE_SIZE
967# undef PAGE_SHIFT
968# undef PAGE_SECTORS
969# undef ADDR_SHIFT
970#endif
971