140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * YAFFS: Yet another FFS. A NAND-flash specific file system.
340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Copyright (C) 2002 Aleph One Ltd.
540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *   for Toby Churchill Ltd and Brightstar Engineering
640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Created by Charles Manning <charles@aleph1.co.uk>
840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * This program is free software; you can redistribute it and/or modify
1040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * it under the terms of the GNU General Public License version 2 as
1140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * published by the Free Software Foundation.
1240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
1340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *
1440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *  This version hacked for emulating 2kpage NAND for YAFFS2 testing.
1540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
1640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
1740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include <linux/config.h>
1840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include <linux/kernel.h>
1940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include <linux/module.h>
2040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include <linux/version.h>
2140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include <linux/slab.h>
2240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include <linux/init.h>
2340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include <linux/list.h>
2440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include <linux/fs.h>
2540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include <linux/proc_fs.h>
2640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include <linux/pagemap.h>
2740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include <linux/mtd/mtd.h>
2840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include <linux/interrupt.h>
2940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include <linux/string.h>
3040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
3140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include <linux/locks.h>
3240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
3340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
3440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include <asm/uaccess.h>
3540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include <linux/mtd/mtd.h>
3640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include <linux/mtd/partitions.h>
3740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include <linux/mtd/nand.h>
3840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "../yaffs_nandemul2k.h"
3940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
4040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define ALLOCATE(x) kmalloc(x,GFP_KERNEL)
4140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define FREE(x)     kfree(x)
4240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
4340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
4440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
4540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
4640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
4740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define NAND_SHIFT      (11)   // Shifter for 2k
4840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define PAGE_DATA_SIZE  (1 << NAND_SHIFT)
4940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define PAGE_SPARE_SIZE (64)
5040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define BLK_SHIFT	6
5140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define PAGES_PER_BLOCK (1 << BLK_SHIFT)	// = 64
5240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
5340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
5440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define EM_SIZE_IN_MEG 4
5540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define EM_SIZE_IN_BYTES (EM_SIZE_IN_MEG * (1<<20))
5640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
5740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define PAGE_TOTAL_SIZE (PAGE_DATA_SIZE+PAGE_SPARE_SIZE)
5840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
5940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define BLOCK_TOTAL_SIZE (PAGES_PER_BLOCK * PAGE_TOTAL_SIZE)
6040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
6140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#define BLOCKS_PER_MEG ((1<<20)/(PAGES_PER_BLOCK * PAGE_DATA_SIZE))
6240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
6340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
6440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic struct mtd_info nandemul2k_mtd;
6540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
6640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projecttypedef struct
6740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
6840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u8 data[PAGE_TOTAL_SIZE]; // Data + spare
6940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int empty;      // is this empty?
7040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} nandemul_Page;
7140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
7240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
7340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projecttypedef struct
7440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
7540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nandemul_Page *page[PAGES_PER_BLOCK];
7640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int damaged;
7740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} nandemul_Block;
7840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
7940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
8040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
8140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projecttypedef struct
8240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
8340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nandemul_Block**block;
8440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nBlocks;
8540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} nandemul_Device;
8640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
8740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic nandemul_Device ned;
8840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
8940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int sizeInMB = EM_SIZE_IN_MEG;
9040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
9140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
9240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void nandemul_yield(int n)
9340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
9440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef __KERNEL__
9540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(n > 0) schedule_timeout(n);
9640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
9740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
9840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
9940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
10040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
10140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void nandemul2k_Read(void *buffer, int page, int start, int nBytes)
10240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
10340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int pg = page%PAGES_PER_BLOCK;
10440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int blk = page/PAGES_PER_BLOCK;
10540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(buffer && nBytes > 0)
10640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
10740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		memcpy(buffer,&ned.block[blk]->page[pg]->data[start],nBytes);
10840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
10940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
11040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
11140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
11240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void nandemul2k_Program(const void *buffer, int page, int start, int nBytes)
11340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
11440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int pg = page%PAGES_PER_BLOCK;
11540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int blk = page/PAGES_PER_BLOCK;
11640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u8 *p;
11740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	__u8 *b = (__u8 *)buffer;
11840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
11940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	p = &ned.block[blk]->page[pg]->data[start];
12040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
12140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	while(buffer && nBytes>0)
12240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
12340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		*p = *p & *b;
12440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		p++;
12540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		b++;
12640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		nBytes--;
12740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
12840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
12940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
13040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void nandemul2k_DoErase(int blockNumber)
13140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
13240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i;
13340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
13440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nandemul_Block *blk;
13540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
13640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(blockNumber < 0 || blockNumber >= ned.nBlocks)
13740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
13840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return;
13940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
14040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
14140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	blk = ned.block[blockNumber];
14240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
14340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for(i = 0; i < PAGES_PER_BLOCK; i++)
14440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
14540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		memset(blk->page[i],0xff,sizeof(nandemul_Page));
14640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		blk->page[i]->empty = 1;
14740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
14840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nandemul_yield(2);
14940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
15040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
15140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
15240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nandemul2k_CalcNBlocks(void)
15340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
15440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return EM_SIZE_IN_MEG * BLOCKS_PER_MEG;
15540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
15640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
15740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
15840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
15940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int  CheckInit(void)
16040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
16140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	static int initialised = 0;
16240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
16340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i,j;
16440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
16540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int fail = 0;
16640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nBlocks;
16740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
16840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nAllocated = 0;
16940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
17040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(initialised)
17140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
17240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return 0;
17340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
17440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
17540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
17640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	ned.nBlocks = nBlocks = nandemul2k_CalcNBlocks();
17740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
17840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
17940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	ned.block = ALLOCATE(sizeof(nandemul_Block*) * nBlocks );
18040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
18140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(!ned.block) return ENOMEM;
18240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
18340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
18440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
18540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
18640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
18740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for(i=fail=0; i <nBlocks; i++)
18840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
18940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
19040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		nandemul_Block *blk;
19140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
19240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if(!(blk = ned.block[i] = ALLOCATE(sizeof(nandemul_Block))))
19340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		{
19440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		 fail = 1;
19540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
19640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		else
19740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		{
19840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			for(j = 0; j < PAGES_PER_BLOCK; j++)
19940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			{
20040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				if((blk->page[j] = ALLOCATE(sizeof(nandemul_Page))) == 0)
20140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				{
20240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project					fail = 1;
20340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				}
20440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			}
20540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			nandemul2k_DoErase(i);
20640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			ned.block[i]->damaged = 0;
20740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			nAllocated++;
20840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
20940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
21040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
21140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if(fail)
21240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
21340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		//Todo thump pages
21440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
21540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for(i = 0; i < nAllocated; i++)
21640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		{
21740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			FREE(ned.block[i]);
21840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
21940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		FREE(ned.block);
22040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
22140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return ENOMEM;
22240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
22340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
22440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	ned.nBlocks = nBlocks;
22540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
22640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	initialised = 1;
22740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
22840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return 1;
22940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
23040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
23140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
23240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
23340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void nandemul2k_CleanUp(void)
23440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
23540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i,j;
23640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
23740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for(i = 0; i < ned.nBlocks; i++)
23840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
23940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		for(j = 0; j < PAGES_PER_BLOCK; j++)
24040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		{
24140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   FREE(ned.block[i]->page[j]);
24240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
24340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		FREE(ned.block[i]);
24440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
24540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
24640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	FREE(ned.block);
24740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	ned.block = 0;
24840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
24940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
25040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint nandemul2k_GetBytesPerChunk(void) { return PAGE_DATA_SIZE;}
25140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
25240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint nandemul2k_GetChunksPerBlock(void) { return PAGES_PER_BLOCK; }
25340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint nandemul2k_GetNumberOfBlocks(void) {return nandemul2k_CalcNBlocks();}
25440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
25540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
25640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
25740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nandemul2k_ReadId(__u8 *vendorId, __u8 *deviceId)
25840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
25940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	*vendorId = 'Y';
26040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	*deviceId = '2';
26140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
26240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return 1;
26340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
26440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
26540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
26640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nandemul2k_ReadStatus(__u8 *status)
26740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
26840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		*status = 0;
26940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return 1;
27040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
27140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
27240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
27340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef CONFIG_MTD_NAND_ECC
27440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include <linux/mtd/nand_ecc.h>
27540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
27640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
27740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
27840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * NAND low-level MTD interface functions
27940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
28040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nand_read (struct mtd_info *mtd, loff_t from, size_t len,
28140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			size_t *retlen, u_char *buf);
28240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
28340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				size_t *retlen, u_char *buf, u_char *oob_buf, struct nand_oobinfo *dummy);
28440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len,
28540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				size_t *retlen, u_char *buf);
28640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nand_write (struct mtd_info *mtd, loff_t to, size_t len,
28740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			size_t *retlen, const u_char *buf);
28840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
28940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				size_t *retlen, const u_char *buf,
29040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				u_char *oob_buf, struct nand_oobinfo *dummy);
29140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len,
29240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				size_t *retlen, const u_char *buf);
29340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,7))
29440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nand_writev (struct mtd_info *mtd, const struct kvec *vecs,
29540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				unsigned long count, loff_t to, size_t *retlen);
29640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#else
29740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nand_writev (struct mtd_info *mtd, const struct iovec *vecs,
29840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				unsigned long count, loff_t to, size_t *retlen);
29940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
30040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nand_erase (struct mtd_info *mtd, struct erase_info *instr);
30140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void nand_sync (struct mtd_info *mtd);
30240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
30340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
30440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
30540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
30640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * NAND read
30740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
30840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nand_read (struct mtd_info *mtd, loff_t from, size_t len,
30940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			size_t *retlen, u_char *buf)
31040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
31140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return nand_read_ecc (mtd, from, len, retlen, buf, NULL,NULL);
31240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
31340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
31440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
31540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
31640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * NAND read with ECC
31740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
31840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
31940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				size_t *retlen, u_char *buf, u_char *oob_buf,struct nand_oobinfo *oobsel)
32040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
32140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int 	start, page;
32240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int n = len;
32340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nToCopy;
32440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
32540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
32640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
32740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Do not allow reads past end of device */
32840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if ((from + len) > mtd->size) {
32940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		*retlen = 0;
33040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return -EINVAL;
33140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
33240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
33340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
33440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Initialize return value */
33540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	*retlen = 0;
33640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
33740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	while(n > 0)
33840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
33940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
34040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* First we calculate the starting page */
34140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		page = from >> NAND_SHIFT;
34240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
34340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Get raw starting column */
34440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
34540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		start = from & (mtd->oobblock-1);
34640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
34740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		// OK now check for the curveball where the start and end are in
34840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		// the same page
34940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if((start + n) < mtd->oobblock)
35040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		{
35140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			nToCopy = n;
35240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
35340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		else
35440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		{
35540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			nToCopy =  mtd->oobblock - start;
35640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
35740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
35840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		nandemul2k_Read(buf, page, start, nToCopy);
35940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		nandemul2k_Read(oob_buf,page,PAGE_DATA_SIZE,PAGE_SPARE_SIZE);
36040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
36140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		n -= nToCopy;
36240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		from += nToCopy;
36340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		buf += nToCopy;
36440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if(oob_buf) oob_buf += PAGE_SPARE_SIZE;
36540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		*retlen += nToCopy;
36640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
36740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
36840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
36940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
37040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return 0;
37140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
37240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
37340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
37440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * NAND read out-of-band
37540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
37640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len,
37740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				size_t *retlen, u_char *buf)
37840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
37940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int col, page;
38040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
38140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(0,("nand_read_oob: from = 0x%08x, buf = 0x%08x, len = %i\n", (unsigned int) from, (unsigned int) buf,
38240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		(int) len));
38340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
38440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Shift to get page */
38540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	page = ((int) from) >> NAND_SHIFT;
38640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
38740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Mask to get column */
38840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	col = from & 0x0f;
38940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
39040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Initialize return length value */
39140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	*retlen = 0;
39240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
39340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Do not allow reads past end of device */
39440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if ((from + len) > mtd->size) {
39540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(0,
39640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			("nand_read_oob: Attempt read beyond end of device\n"));
39740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		*retlen = 0;
39840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return -EINVAL;
39940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
40040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
40140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nandemul2k_Read(buf,page,PAGE_DATA_SIZE + col,len);
40240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
40340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Return happy */
40440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	*retlen = len;
40540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return 0;
40640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
40740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
40840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
40940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * NAND write
41040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
41140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nand_write (struct mtd_info *mtd, loff_t to, size_t len,
41240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			size_t *retlen, const u_char *buf)
41340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
41440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return nand_write_ecc (mtd, to, len, retlen, buf, NULL,NULL);
41540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
41640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
41740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
41840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * NAND write with ECC
41940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
42040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
42140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				size_t *retlen, const u_char *buf,
42240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				u_char *oob_buf, struct nand_oobinfo *dummy)
42340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
42440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
42540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int 	start, page;
42640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int n = len;
42740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int nToCopy;
42840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
42940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
43040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
43140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Do not allow reads past end of device */
43240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if ((to + len) > mtd->size) {
43340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		*retlen = 0;
43440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return -EINVAL;
43540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
43640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
43740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
43840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Initialize return value */
43940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	*retlen = 0;
44040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
44140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	while(n > 0)
44240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
44340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
44440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* First we calculate the starting page */
44540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		page = to >> NAND_SHIFT;
44640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
44740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		/* Get raw starting column */
44840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
44940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		start = to & (mtd->oobblock - 1);
45040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
45140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		// OK now check for the curveball where the start and end are in
45240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		// the same page
45340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if((start + n) < mtd->oobblock)
45440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		{
45540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			nToCopy = n;
45640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
45740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		else
45840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		{
45940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			nToCopy =  mtd->oobblock - start;
46040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		}
46140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
46240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		nandemul2k_Program(buf, page, start, nToCopy);
46340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		nandemul2k_Program(oob_buf, page, PAGE_DATA_SIZE, PAGE_SPARE_SIZE);
46440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
46540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		n -= nToCopy;
46640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		to += nToCopy;
46740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		buf += nToCopy;
46840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		if(oob_buf) oob_buf += PAGE_SPARE_SIZE;
46940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		*retlen += nToCopy;
47040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
47140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
47240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
47340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
47440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return 0;
47540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
47640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
47740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
47840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * NAND write out-of-band
47940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
48040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len,
48140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				size_t *retlen, const u_char *buf)
48240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
48340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int col, page;
48440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
48540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
48640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(0,(
48740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		"nand_read_oob: to = 0x%08x, len = %i\n", (unsigned int) to,
48840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		(int) len));
48940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
49040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Shift to get page */
49140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	page = ((int) to) >> NAND_SHIFT;
49240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
49340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Mask to get column */
49440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	col = to & 0x0f;
49540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
49640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Initialize return length value */
49740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	*retlen = 0;
49840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
49940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Do not allow reads past end of device */
50040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if ((to + len) > mtd->size) {
50140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(0,(
50240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		   "nand_read_oob: Attempt read beyond end of device\n"));
50340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		*retlen = 0;
50440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return -EINVAL;
50540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
50640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
50740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nandemul2k_Program(buf,page,512 + col,len);
50840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
50940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Return happy */
51040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	*retlen = len;
51140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return 0;
51240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
51340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
51440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
51540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
51640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * NAND write with iovec
51740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
51840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,7))
51940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nand_writev (struct mtd_info *mtd, const struct kvec *vecs,
52040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				unsigned long count, loff_t to, size_t *retlen)
52140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#else
52240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nand_writev (struct mtd_info *mtd, const struct iovec *vecs,
52340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project				unsigned long count, loff_t to, size_t *retlen)
52440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
52540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
52640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return -EINVAL;
52740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
52840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
52940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
53040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * NAND erase a block
53140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
53240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nand_erase (struct mtd_info *mtd, struct erase_info *instr)
53340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
53440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	int i, nBlocks,block;
53540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
53640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(0,(
53740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		"nand_erase: start = 0x%08x, len = %i\n",
53840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		(unsigned int) instr->addr, (unsigned int) instr->len));
53940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
54040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Start address must align on block boundary */
54140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (instr->addr & (mtd->erasesize - 1)) {
54240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(0,(
54340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			"nand_erase: Unaligned address\n"));
54440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return -EINVAL;
54540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
54640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
54740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Length must align on block boundary */
54840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if (instr->len & (mtd->erasesize - 1)) {
54940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(0,(
55040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			"nand_erase: Length not block aligned\n"));
55140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return -EINVAL;
55240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
55340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
55440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Do not allow erase past end of device */
55540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	if ((instr->len + instr->addr) > mtd->size) {
55640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		T(0,(
55740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project			"nand_erase: Erase past end of device\n"));
55840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		return -EINVAL;
55940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
56040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
56140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nBlocks = instr->len >> (NAND_SHIFT + BLK_SHIFT);
56240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	block = instr->addr >> (NAND_SHIFT + BLK_SHIFT);
56340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
56440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	for(i = 0; i < nBlocks; i++)
56540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{
56640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		nandemul2k_DoErase(block);
56740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project		block++;
56840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	}
56940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
57040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
57140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
57240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return 0;
57340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
57440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
57540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
57640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
57740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
57840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nand_block_isbad(struct mtd_info *mtd, loff_t ofs)
57940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
58040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return 0;
58140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
58240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
58340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
58440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
58540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return 0;
58640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
58740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
58840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
58940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
59040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * NAND sync
59140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
59240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void nand_sync (struct mtd_info *mtd)
59340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
59440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	T(0,("nand_sync: called\n"));
59540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
59640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
59740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
59840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
59940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Scan for the NAND device
60040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
60140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nandemul2k_scan (struct mtd_info *mtd,int nchips)
60240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
60340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->oobblock = PAGE_DATA_SIZE;
60440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->oobsize =  PAGE_SPARE_SIZE;
60540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->erasesize = PAGE_DATA_SIZE * PAGES_PER_BLOCK;
60640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->size = sizeInMB * 1024*1024;
60740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
60840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
60940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
61040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Fill in remaining MTD driver data */
61140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->type = MTD_NANDFLASH;
61240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->flags = MTD_CAP_NANDFLASH;
61340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->owner = THIS_MODULE;
61440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->ecctype = MTD_ECC_NONE;
61540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->erase = nand_erase;
61640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->point = NULL;
61740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->unpoint = NULL;
61840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->read = nand_read;
61940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->write = nand_write;
62040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->read_ecc = nand_read_ecc;
62140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->write_ecc = nand_write_ecc;
62240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->read_oob = nand_read_oob;
62340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->write_oob = nand_write_oob;
62440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->block_isbad = nand_block_isbad;
62540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->block_markbad = nand_block_markbad;
62640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->readv = NULL;
62740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->writev = nand_writev;
62840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->sync = nand_sync;
62940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->lock = NULL;
63040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->unlock = NULL;
63140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->suspend = NULL;
63240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->resume = NULL;
63340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
63440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	mtd->name = "NANDemul2k";
63540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
63640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Return happy */
63740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return 0;
63840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
63940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
64040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#if 0
64140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef MODULE
64240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source ProjectMODULE_PARM(sizeInMB, "i");
64340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
64440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project__setup("sizeInMB=",sizeInMB);
64540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
64640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
64740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
64840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
64940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Define partitions for flash devices
65040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
65140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
65240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic struct mtd_partition nandemul2k_partition[] =
65340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
65440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	{ .name		= "NANDemul partition 1",
65540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	  .offset	= 0,
65640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	  .size		= 0 },
65740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project};
65840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
65940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int nPartitions = sizeof(nandemul2k_partition)/sizeof(nandemul2k_partition[0]);
66040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
66140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
66240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Main initialization routine
66340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
66440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint __init nandemul2k_init (void)
66540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
66640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
66740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	// Do the nand init
66840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
66940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	CheckInit();
67040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
67140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nandemul2k_scan(&nandemul2k_mtd,1);
67240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
67340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	// Build the partition table
67440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
67540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nandemul2k_partition[0].size = sizeInMB * 1024 * 1024;
67640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
67740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	// Register the partition
67840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	add_mtd_partitions(&nandemul2k_mtd,nandemul2k_partition,nPartitions);
67940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
68040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	return 0;
68140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
68240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
68340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
68440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectmodule_init(nandemul2k_init);
68540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
68640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/*
68740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Clean up routine
68840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */
68940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#ifdef MODULE
69040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void __exit nandemul2k_cleanup (void)
69140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{
69240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
69340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	nandemul2k_CleanUp();
69440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
69540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Unregister partitions */
69640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	del_mtd_partitions(&nandemul2k_mtd);
69740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
69840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	/* Unregister the device */
69940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project	del_mtd_device (&nandemul2k_mtd);
70040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
70140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project}
70240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectmodule_exit(nandemul2k_cleanup);
70340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#endif
70440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
70540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source ProjectMODULE_LICENSE("GPL");
70640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source ProjectMODULE_AUTHOR("Charles Manning <manningc@aleph1.co.uk>");
70740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source ProjectMODULE_DESCRIPTION("2k Page/128k Block NAND emulated in RAM");
70840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
70940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
71040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
71140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project
712