change debug_out format of addr to JZ_FMT_plx
[qemu/qemu-JZ.git] / hw / nand_bpage.c
blob9b1d4505dd4a596dfeb9b989f1826f9929fc1f9a
1 /*
2 * Big page NAND flash memory emulation. based on 256M/16 bit flash datasheet from micro(MT29F2G16ABC)
4 * Copyright (C) 2008 yajin(yajin@vm-kernel.org)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 or
9 * (at your option) version 3 of the License.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
19 * MA 02111-1307 USA
22 #include "hw.h"
23 #include "flash.h"
24 #include "block.h"
25 #include "sysemu.h"
28 #define MAX_PAGE 0x800
29 #define MAX_OOB 0x40
30 #define PAGE_MASK (0xffff)
31 #define BUS_WIDTH_16 2
32 #define BUS_WIDTH_8 1
34 //#define DEBUG
36 struct nand_flash_info_s
38 uint8_t manf_id,chip_id;
39 uint32_t size;;
40 int bus_width;
41 int page_shift;
42 int oob_shift;
43 int block_shift;
46 struct nand_flash_info_s nand_flash_info[2] =
48 {0x2c, 0xba, 256,2, 11, 6, 6},
49 {0Xec, 0xd3, 1024,1, 11, 6, 6}
53 struct nand_bflash_s
55 BlockDriverState *bdrv;
56 uint8_t manf_id, chip_id;
57 uint32_t size, pages;
58 uint32_t page_size, page_shift;
59 uint32_t oob_size, oob_shift;
60 uint32_t page_oob_size;
61 uint32_t page_sectors; /*sector = 512 bytes */
62 uint32_t block_shift, block_pages; /*how many pages in a block */
63 uint32_t bus_width; /*bytes */
65 //uint8_t *internal_buf;
66 uint8_t io[MAX_PAGE + MAX_OOB + 0x400];
67 uint8_t *ioaddr;
68 int iolen;
71 uint32 addr_low, addr_high;
72 uint32 addr_cycle;
74 uint32 cmd, status;
75 #ifdef DEBUG
76 FILE *fp;
77 #endif
81 #ifdef DEBUG
82 static void debug_init(struct nand_bflash_s *s)
84 s->fp=fopen("nandflash_debug.txt","w+");
85 if (s->fp==NULL)
87 fprintf(stderr,"can not open nandflash_debug.txt \n");
88 exit(-1);
92 static void debug_out(struct nand_bflash_s *s,const char* format, ...)
94 va_list ap;
95 if (s->fp)
97 va_start(ap, format);
98 vfprintf(s->fp, format, ap);
99 fflush(s->fp);
100 va_end(ap);
104 #else
105 static void debug_init(struct nand_bflash_s *s)
109 static void debug_out(struct nand_bflash_s *s,const char* format, ...)
114 #endif
116 static inline uint32_t get_page_number(struct nand_bflash_s *s,
117 uint32_t addr_low, uint32 addr_high)
119 return (addr_high << 16) + ((addr_low >> 16) & PAGE_MASK);
124 /* Program a single page */
125 static void nand_blk_write(struct nand_bflash_s *s)
127 uint32_t page_number, off, sector, soff;
128 uint8_t *iobuf=NULL;
130 if (!iobuf)
131 iobuf = qemu_mallocz((s->page_sectors + 2) * 0x200);
132 if (!iobuf)
134 fprintf(stderr, "can not alloc io buffer size 0x%x \n",
135 (s->page_sectors + 2) * 0x200);
136 cpu_abort(cpu_single_env, "%s: can not alloc io buffer size 0x%x \n",
137 __FUNCTION__, (s->page_sectors + 2) * 0x200);
140 page_number = get_page_number(s, s->addr_low, s->addr_high);
142 debug_out(s,"nand_blk_write page number %x s->addr_low %x s->addr_high %x\n",page_number,s->addr_low,s->addr_high);
144 if (page_number >= s->pages)
145 return;
147 off = page_number * s->page_oob_size + (s->addr_low & PAGE_MASK);
148 sector = off >> 9;
149 soff = off & 0x1ff;
150 if (bdrv_read(s->bdrv, sector, iobuf, s->page_sectors + 2) == -1)
152 printf("%s: read error in sector %i\n", __FUNCTION__, sector);
153 return;
156 memcpy(iobuf + soff, s->io, s->iolen);
158 if (bdrv_write(s->bdrv, sector, iobuf, s->page_sectors + 2) == -1)
159 printf("%s: write error in sector %i\n", __FUNCTION__, sector);
161 //qemu_free(iobuf);
165 static void nandb_blk_load(struct nand_bflash_s *s)
167 uint32_t page_number, offset;
168 offset = s->addr_low & PAGE_MASK;
170 page_number = get_page_number(s, s->addr_low, s->addr_high);
171 debug_out(s,"nandb_blk_load page number %x s->addr_low %x s->addr_high %x\n",page_number,s->addr_low,s->addr_high);
172 if (page_number >= s->pages)
173 return;
175 if (bdrv_read(s->bdrv, (page_number * s->page_oob_size + offset) >> 9,
176 s->io, (s->page_sectors + 2)) == -1)
177 printf("%s: read error in sector %i\n",
178 __FUNCTION__, page_number * s->page_oob_size);
179 s->ioaddr = s->io + ((page_number * s->page_oob_size + offset) & 0x1ff);
183 /* Erase a single block */
184 static void nandb_blk_erase(struct nand_bflash_s *s)
186 uint32_t page_number, sector, addr, i;
188 uint8_t iobuf[0x200];
190 memset(iobuf,0xff,sizeof(iobuf));
191 s->addr_low = s->addr_low & ~((1 << (16 + s->block_shift)) - 1);
192 page_number = get_page_number(s, s->addr_low, s->addr_high);
193 debug_out(s,"nandb_blk_erase page number %x s->addr_low %x s->addr_high %x\n",page_number,s->addr_low,s->addr_high);
194 if (page_number >= s->pages)
195 return;
197 addr = page_number * s->page_oob_size;
199 sector = addr >> 9;
200 if (bdrv_read(s->bdrv, sector, iobuf, 1) == -1)
201 printf("%s: read error in sector %i\n", __FUNCTION__, sector);
202 memset(iobuf + (addr & 0x1ff), 0xff, (~addr & 0x1ff) + 1);
203 if (bdrv_write(s->bdrv, sector, iobuf, 1) == -1)
204 printf("%s: write error in sector %i\n", __FUNCTION__, sector);
206 memset(iobuf, 0xff, 0x200);
207 i = (addr & ~0x1ff) + 0x200;
208 for (addr += (s->page_oob_size*s->block_pages - 0x200); i < addr; i += 0x200)
209 if (bdrv_write(s->bdrv, i >> 9, iobuf, 1) == -1)
210 printf("%s: write error in sector %i\n", __FUNCTION__, i >> 9);
212 sector = i >> 9;
213 if (bdrv_read(s->bdrv, sector, iobuf, 1) == -1)
214 printf("%s: read error in sector %i\n", __FUNCTION__, sector);
215 memset(iobuf, 0xff, ((addr - 1) & 0x1ff) + 1);
216 if (bdrv_write(s->bdrv, sector, iobuf, 1) == -1)
217 printf("%s: write error in sector %i\n", __FUNCTION__, sector);
220 static void nandb_next_page(struct nand_bflash_s *s)
222 if ((s->addr_low + 0x10000) < s->addr_low)
223 s->addr_high++;
224 s->addr_low += 0x10000;
227 void nandb_write_command(struct nand_bflash_s *s, uint16_t value)
229 int id_index[5] = { 0, 1, 2, 3,4};
231 debug_out(s,"nandb_write_command %x\n",value);
233 switch (value)
235 case 0x00:
236 case 0x05:
237 s->iolen = 0;
238 s->addr_cycle = 0;
239 break;
240 case 0x60:
241 /*earse only need 3 addrss cycle.Its address is block address*/
242 s->addr_low &= ~PAGE_MASK;
243 s->addr_high =0;
244 s->addr_cycle = 2;
245 break;
246 case 0x30:
247 case 0xe0:
248 s->iolen = s->page_oob_size - (s->addr_low & PAGE_MASK);
249 nandb_blk_load(s);
250 break;
251 case 0x31:
252 case 0x3f:
253 nandb_next_page(s);
254 s->iolen = s->page_oob_size - (s->addr_low & PAGE_MASK);
255 nandb_blk_load(s);
256 break;
257 case 0x90:
258 s->iolen = 5 * s->bus_width;
259 memset(s->io, 0x0, s->iolen);
260 if (s->bus_width == BUS_WIDTH_16)
262 id_index[0] = 0;
263 id_index[1] = 2;
264 id_index[2] = 4;
265 id_index[3] = 6;
266 id_index[4] = 6;
268 s->io[id_index[0]] = s->manf_id;
269 s->io[id_index[1]] = s->chip_id;
270 s->io[id_index[2]] = 'Q'; /* Don't-care byte (often 0xa5) */
271 if ((s->manf_id == NAND_MFR_MICRON) && (s->chip_id == 0xba))
272 s->io[id_index[3]] = 0x55;
273 if ((s->manf_id == NAND_MFR_SAMSUNG) && (s->chip_id == 0xd3))
275 s->io[id_index[3]] = 0x95;
276 s->io[id_index[4]] = 0x48;
278 s->ioaddr = s->io;
279 s->addr_cycle = 0;
280 break;
281 case 0x70:
282 if ((s->manf_id == NAND_MFR_MICRON) && (s->chip_id == 0xba))
284 s->status |= 0x60; /*flash is ready */
285 s->status |= 0x80; /*not protect */
287 if ((s->manf_id == NAND_MFR_SAMSUNG) && (s->chip_id == 0xd3))
289 s->status |= 0x40; /*flash is ready */
290 s->status |= 0x80; /*not protect */
292 s->io[0] = s->status;
293 s->ioaddr = s->io;
294 s->iolen = 1;
295 break;
296 case 0xd0:
297 nandb_blk_erase(s);
298 break;
299 case 0x80:
300 case 0x85:
301 s->addr_cycle = 0;
302 s->ioaddr = s->io;
303 s->iolen = 0;
304 break;
305 case 0x10:
306 nand_blk_write(s);
307 break;
308 case 0xff:
309 s->addr_cycle =0;
310 s->iolen=0;
311 s->addr_low =0;
312 s->addr_high =0;
313 s->ioaddr = NULL;
314 break;
315 default:
316 fprintf(stderr, "unknown nand command 0x%x \n", value);
317 exit(-1);
319 s->cmd = value;
322 void nandb_write_address(struct nand_bflash_s *s, uint16_t value)
324 uint32_t mask;
325 uint32_t colum_addr;
326 //if (s->cmd==0x60)
327 debug_out(s,"value %x addr_cycle %x \n",value,s->addr_cycle);
328 if (s->addr_cycle < 5)
330 if (s->addr_cycle < 4)
332 mask = ~(0xff << (s->addr_cycle * 8));
333 s->addr_low &= mask;
334 s->addr_low |= value << (s->addr_cycle * 8);
336 else
338 mask = ~(0xff << ((s->addr_cycle-4) * 8));
339 s->addr_high &= mask;
340 s->addr_high |= value << ((s->addr_cycle-4) * 8);
343 else
345 fprintf(stderr,"%s wrong addr cycle\n",__FUNCTION__);
346 exit(-1);
348 if ((s->addr_cycle==1)&&(s->bus_width!=1))
350 colum_addr = s->addr_low & PAGE_MASK;
351 colum_addr *= s->bus_width;
352 s->addr_low &= ~PAGE_MASK;
353 s->addr_low += colum_addr;
355 s->addr_cycle++;
359 uint8_t nandb_read_data8(struct nand_bflash_s *s)
361 uint8_t ret;
362 if ((s->iolen==0)&&(s->cmd==0x31))
364 nandb_next_page(s);
365 s->iolen = s->page_oob_size - (s->addr_low & PAGE_MASK);
366 nandb_blk_load(s);
368 if (s->iolen <= 0)
370 fprintf(stderr,"iolen <0 \n");
371 exit(-1);
373 if (s->cmd!=0x70)
374 s->iolen -=1 ;
375 ret = *((uint8_t *)s->ioaddr);
376 if (s->cmd!=0x70)
377 s->ioaddr += 1;
379 //debug_out(s," %x ",ret);
380 return ret;
383 void nandb_write_data8(struct nand_bflash_s *s, uint8_t value)
385 if ((s->cmd == 0x80) )
387 if (s->iolen < s->page_oob_size)
389 s->io[s->iolen ++] = value&0xff;
394 uint16_t nandb_read_data16(struct nand_bflash_s *s)
396 uint16_t ret;
397 if ((s->iolen==0)&&(s->cmd==0x31))
399 nandb_next_page(s);
400 s->iolen = s->page_oob_size - (s->addr_low & PAGE_MASK);
401 nandb_blk_load(s);
403 if (s->iolen <= 0)
405 fprintf(stderr,"iolen <0 \n");
406 exit(-1);
408 if (s->cmd!=0x70)
409 s->iolen -=2 ;
410 ret = *((uint16_t *)s->ioaddr);
411 if (s->cmd!=0x70)
412 s->ioaddr += 2;
413 return ret;
416 void nandb_write_data16(struct nand_bflash_s *s, uint16_t value)
418 if ((s->cmd == 0x80) )
420 if (s->iolen < s->page_oob_size)
422 s->io[s->iolen ++] = value&0xff;
423 s->io[s->iolen ++] = (value>>8)&0xff;
428 struct nand_bflash_s *nandb_init(int manf_id, int chip_id)
430 //int pagesize;
431 struct nand_bflash_s *s;
432 int index;
433 int i;
435 s = (struct nand_bflash_s *) qemu_mallocz(sizeof(struct nand_bflash_s));
436 for (i = 0; i < sizeof(nand_flash_info); i++)
438 if ((nand_flash_info[i].manf_id == manf_id)
439 && (nand_flash_info[i].chip_id == chip_id))
441 s->manf_id = manf_id;
442 s->chip_id = chip_id;
443 s->page_shift = nand_flash_info[i].page_shift;
444 s->oob_shift = nand_flash_info[i].oob_shift;
445 s->bus_width = nand_flash_info[i].bus_width;
446 s->page_size = 1 << s->page_shift;
447 s->oob_size = 1 << s->oob_shift;
448 s->block_shift = nand_flash_info[i].block_shift;
449 s->block_pages = 1 << s->block_shift;
450 s->page_oob_size = s->page_size + s->oob_size;
451 s->page_sectors = 1 << (s->page_shift - 9);
452 /*TODO: size overflow */
453 s->size = nand_flash_info[i].size << 20;
454 s->pages = (s->size / s->page_size);
456 break;
460 if (i >= sizeof(nand_flash_info))
462 fprintf(stderr, "%s: Unsupported NAND chip ID.\n",
463 __FUNCTION__);
464 exit(-1);
468 index = drive_get_index(IF_MTD, 0, 0);
469 if (index != -1)
470 s->bdrv = drives_table[index].bdrv;
471 else
473 fprintf(stderr, "%s: Please use -mtdblock to specify flash image.\n",
474 __FUNCTION__);
475 exit(-1);
478 if (bdrv_getlength(s->bdrv) != (s->pages*s->page_oob_size))
480 fprintf(stderr, "%s: Invalid flash image size.\n",
481 __FUNCTION__);
482 exit(-1);
486 debug_init(s);
487 return s;