forked from Minki/linux
[MTD NAND] Indent all of drivers/mtd/nand/*.c.
It was just too painful to deal with. Signed-off-by: David Woodhouse <dwmw2@infradead.org>
This commit is contained in:
parent
6943f8af7d
commit
e0c7d76753
@ -38,22 +38,20 @@
|
||||
*/
|
||||
static struct mtd_info *au1550_mtd = NULL;
|
||||
static void __iomem *p_nand;
|
||||
static int nand_width = 1; /* default x8*/
|
||||
static int nand_width = 1; /* default x8 */
|
||||
|
||||
/*
|
||||
* Define partitions for flash device
|
||||
*/
|
||||
static const struct mtd_partition partition_info[] = {
|
||||
{
|
||||
.name = "NAND FS 0",
|
||||
.offset = 0,
|
||||
.size = 8*1024*1024
|
||||
},
|
||||
.name = "NAND FS 0",
|
||||
.offset = 0,
|
||||
.size = 8 * 1024 * 1024},
|
||||
{
|
||||
.name = "NAND FS 1",
|
||||
.offset = MTDPART_OFS_APPEND,
|
||||
.size = MTDPART_SIZ_FULL
|
||||
}
|
||||
.name = "NAND FS 1",
|
||||
.offset = MTDPART_OFS_APPEND,
|
||||
.size = MTDPART_SIZ_FULL}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -157,7 +155,7 @@ static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
|
||||
int i;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
|
||||
for (i=0; i<len; i++) {
|
||||
for (i = 0; i < len; i++) {
|
||||
writeb(buf[i], this->IO_ADDR_W);
|
||||
au_sync();
|
||||
}
|
||||
@ -176,7 +174,7 @@ static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
|
||||
int i;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
|
||||
for (i=0; i<len; i++) {
|
||||
for (i = 0; i < len; i++) {
|
||||
buf[i] = readb(this->IO_ADDR_R);
|
||||
au_sync();
|
||||
}
|
||||
@ -195,7 +193,7 @@ static int au_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
|
||||
int i;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
|
||||
for (i=0; i<len; i++) {
|
||||
for (i = 0; i < len; i++) {
|
||||
if (buf[i] != readb(this->IO_ADDR_R))
|
||||
return -EFAULT;
|
||||
au_sync();
|
||||
@ -219,7 +217,7 @@ static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
|
||||
u16 *p = (u16 *) buf;
|
||||
len >>= 1;
|
||||
|
||||
for (i=0; i<len; i++) {
|
||||
for (i = 0; i < len; i++) {
|
||||
writew(p[i], this->IO_ADDR_W);
|
||||
au_sync();
|
||||
}
|
||||
@ -241,7 +239,7 @@ static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
|
||||
u16 *p = (u16 *) buf;
|
||||
len >>= 1;
|
||||
|
||||
for (i=0; i<len; i++) {
|
||||
for (i = 0; i < len; i++) {
|
||||
p[i] = readw(this->IO_ADDR_R);
|
||||
au_sync();
|
||||
}
|
||||
@ -262,7 +260,7 @@ static int au_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len)
|
||||
u16 *p = (u16 *) buf;
|
||||
len >>= 1;
|
||||
|
||||
for (i=0; i<len; i++) {
|
||||
for (i = 0; i < len; i++) {
|
||||
if (p[i] != readw(this->IO_ADDR_R))
|
||||
return -EFAULT;
|
||||
au_sync();
|
||||
@ -275,27 +273,35 @@ static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
{
|
||||
register struct nand_chip *this = mtd->priv;
|
||||
|
||||
switch(cmd){
|
||||
switch (cmd) {
|
||||
|
||||
case NAND_CTL_SETCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_CMD; break;
|
||||
case NAND_CTL_CLRCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; break;
|
||||
case NAND_CTL_SETCLE:
|
||||
this->IO_ADDR_W = p_nand + MEM_STNAND_CMD;
|
||||
break;
|
||||
|
||||
case NAND_CTL_CLRCLE:
|
||||
this->IO_ADDR_W = p_nand + MEM_STNAND_DATA;
|
||||
break;
|
||||
|
||||
case NAND_CTL_SETALE:
|
||||
this->IO_ADDR_W = p_nand + MEM_STNAND_ADDR;
|
||||
break;
|
||||
|
||||
case NAND_CTL_SETALE: this->IO_ADDR_W = p_nand + MEM_STNAND_ADDR; break;
|
||||
case NAND_CTL_CLRALE:
|
||||
this->IO_ADDR_W = p_nand + MEM_STNAND_DATA;
|
||||
/* FIXME: Nobody knows why this is neccecary,
|
||||
/* FIXME: Nobody knows why this is necessary,
|
||||
* but it works only that way */
|
||||
udelay(1);
|
||||
break;
|
||||
|
||||
case NAND_CTL_SETNCE:
|
||||
/* assert (force assert) chip enable */
|
||||
au_writel((1<<(4+NAND_CS)) , MEM_STNDCTL); break;
|
||||
au_writel((1 << (4 + NAND_CS)), MEM_STNDCTL);
|
||||
break;
|
||||
|
||||
case NAND_CTL_CLRNCE:
|
||||
/* deassert chip enable */
|
||||
au_writel(0, MEM_STNDCTL); break;
|
||||
/* deassert chip enable */
|
||||
au_writel(0, MEM_STNDCTL);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -315,66 +321,63 @@ int au1550_device_ready(struct mtd_info *mtd)
|
||||
/*
|
||||
* Main initialization routine
|
||||
*/
|
||||
int __init au1xxx_nand_init (void)
|
||||
int __init au1xxx_nand_init(void)
|
||||
{
|
||||
struct nand_chip *this;
|
||||
u16 boot_swapboot = 0; /* default value */
|
||||
u16 boot_swapboot = 0; /* default value */
|
||||
int retval;
|
||||
u32 mem_staddr;
|
||||
u32 nand_phys;
|
||||
|
||||
/* Allocate memory for MTD device structure and private data */
|
||||
au1550_mtd = kmalloc (sizeof(struct mtd_info) +
|
||||
sizeof (struct nand_chip), GFP_KERNEL);
|
||||
au1550_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
|
||||
if (!au1550_mtd) {
|
||||
printk ("Unable to allocate NAND MTD dev structure.\n");
|
||||
printk("Unable to allocate NAND MTD dev structure.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Get pointer to private data */
|
||||
this = (struct nand_chip *) (&au1550_mtd[1]);
|
||||
this = (struct nand_chip *)(&au1550_mtd[1]);
|
||||
|
||||
/* Initialize structures */
|
||||
memset((char *) au1550_mtd, 0, sizeof(struct mtd_info));
|
||||
memset((char *) this, 0, sizeof(struct nand_chip));
|
||||
memset(au1550_mtd, 0, sizeof(struct mtd_info));
|
||||
memset(this, 0, sizeof(struct nand_chip));
|
||||
|
||||
/* Link the private data with the MTD structure */
|
||||
au1550_mtd->priv = this;
|
||||
|
||||
|
||||
/* disable interrupts */
|
||||
au_writel(au_readl(MEM_STNDCTL) & ~(1<<8), MEM_STNDCTL);
|
||||
au_writel(au_readl(MEM_STNDCTL) & ~(1 << 8), MEM_STNDCTL);
|
||||
|
||||
/* disable NAND boot */
|
||||
au_writel(au_readl(MEM_STNDCTL) & ~(1<<0), MEM_STNDCTL);
|
||||
au_writel(au_readl(MEM_STNDCTL) & ~(1 << 0), MEM_STNDCTL);
|
||||
|
||||
#ifdef CONFIG_MIPS_PB1550
|
||||
/* set gpio206 high */
|
||||
au_writel(au_readl(GPIO2_DIR) & ~(1<<6), GPIO2_DIR);
|
||||
au_writel(au_readl(GPIO2_DIR) & ~(1 << 6), GPIO2_DIR);
|
||||
|
||||
boot_swapboot = (au_readl(MEM_STSTAT) & (0x7<<1)) |
|
||||
((bcsr->status >> 6) & 0x1);
|
||||
boot_swapboot = (au_readl(MEM_STSTAT) & (0x7 << 1)) | ((bcsr->status >> 6) & 0x1);
|
||||
switch (boot_swapboot) {
|
||||
case 0:
|
||||
case 2:
|
||||
case 8:
|
||||
case 0xC:
|
||||
case 0xD:
|
||||
/* x16 NAND Flash */
|
||||
nand_width = 0;
|
||||
break;
|
||||
case 1:
|
||||
case 9:
|
||||
case 3:
|
||||
case 0xE:
|
||||
case 0xF:
|
||||
/* x8 NAND Flash */
|
||||
nand_width = 1;
|
||||
break;
|
||||
default:
|
||||
printk("Pb1550 NAND: bad boot:swap\n");
|
||||
retval = -EINVAL;
|
||||
goto outmem;
|
||||
case 0:
|
||||
case 2:
|
||||
case 8:
|
||||
case 0xC:
|
||||
case 0xD:
|
||||
/* x16 NAND Flash */
|
||||
nand_width = 0;
|
||||
break;
|
||||
case 1:
|
||||
case 9:
|
||||
case 3:
|
||||
case 0xE:
|
||||
case 0xF:
|
||||
/* x8 NAND Flash */
|
||||
nand_width = 1;
|
||||
break;
|
||||
default:
|
||||
printk("Pb1550 NAND: bad boot:swap\n");
|
||||
retval = -EINVAL;
|
||||
goto outmem;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -424,14 +427,13 @@ int __init au1xxx_nand_init (void)
|
||||
|
||||
/* make controller and MTD agree */
|
||||
if (NAND_CS == 0)
|
||||
nand_width = au_readl(MEM_STCFG0) & (1<<22);
|
||||
nand_width = au_readl(MEM_STCFG0) & (1 << 22);
|
||||
if (NAND_CS == 1)
|
||||
nand_width = au_readl(MEM_STCFG1) & (1<<22);
|
||||
nand_width = au_readl(MEM_STCFG1) & (1 << 22);
|
||||
if (NAND_CS == 2)
|
||||
nand_width = au_readl(MEM_STCFG2) & (1<<22);
|
||||
nand_width = au_readl(MEM_STCFG2) & (1 << 22);
|
||||
if (NAND_CS == 3)
|
||||
nand_width = au_readl(MEM_STCFG3) & (1<<22);
|
||||
|
||||
nand_width = au_readl(MEM_STCFG3) & (1 << 22);
|
||||
|
||||
/* Set address of hardware control function */
|
||||
this->hwcontrol = au1550_hwcontrol;
|
||||
@ -454,7 +456,7 @@ int __init au1xxx_nand_init (void)
|
||||
this->verify_buf = (!nand_width) ? au_verify_buf16 : au_verify_buf;
|
||||
|
||||
/* Scan to find existence of the device */
|
||||
if (nand_scan (au1550_mtd, 1)) {
|
||||
if (nand_scan(au1550_mtd, 1)) {
|
||||
retval = -ENXIO;
|
||||
goto outio;
|
||||
}
|
||||
@ -465,10 +467,10 @@ int __init au1xxx_nand_init (void)
|
||||
return 0;
|
||||
|
||||
outio:
|
||||
iounmap ((void *)p_nand);
|
||||
iounmap((void *)p_nand);
|
||||
|
||||
outmem:
|
||||
kfree (au1550_mtd);
|
||||
kfree(au1550_mtd);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -478,19 +480,20 @@ module_init(au1xxx_nand_init);
|
||||
* Clean up routine
|
||||
*/
|
||||
#ifdef MODULE
|
||||
static void __exit au1550_cleanup (void)
|
||||
static void __exit au1550_cleanup(void)
|
||||
{
|
||||
struct nand_chip *this = (struct nand_chip *) &au1550_mtd[1];
|
||||
struct nand_chip *this = (struct nand_chip *)&au1550_mtd[1];
|
||||
|
||||
/* Release resources, unregister device */
|
||||
nand_release (au1550_mtd);
|
||||
nand_release(au1550_mtd);
|
||||
|
||||
/* Free the MTD device structure */
|
||||
kfree (au1550_mtd);
|
||||
kfree(au1550_mtd);
|
||||
|
||||
/* Unmap */
|
||||
iounmap ((void *)p_nand);
|
||||
iounmap((void *)p_nand);
|
||||
}
|
||||
|
||||
module_exit(au1550_cleanup);
|
||||
#endif
|
||||
|
||||
|
@ -47,7 +47,7 @@ static int autcpu12_io_base = CS89712_VIRT_BASE;
|
||||
static int autcpu12_fio_pbase = AUTCPU12_PHYS_SMC;
|
||||
static int autcpu12_fio_ctrl = AUTCPU12_SMC_SELECT_OFFSET;
|
||||
static int autcpu12_pedr = AUTCPU12_SMC_PORT_OFFSET;
|
||||
static void __iomem * autcpu12_fio_base;
|
||||
static void __iomem *autcpu12_fio_base;
|
||||
|
||||
/*
|
||||
* Define partitions for flash devices
|
||||
@ -95,10 +95,10 @@ static struct mtd_partition partition_info128k[] = {
|
||||
/*
|
||||
* hardware specific access to control-lines
|
||||
*/
|
||||
|
||||
static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
{
|
||||
|
||||
switch(cmd){
|
||||
switch (cmd) {
|
||||
|
||||
case NAND_CTL_SETCLE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) |= AUTCPU12_SMC_CLE; break;
|
||||
case NAND_CTL_CLRCLE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) &= ~AUTCPU12_SMC_CLE; break;
|
||||
@ -117,41 +117,40 @@ static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
int autcpu12_device_ready(struct mtd_info *mtd)
|
||||
{
|
||||
|
||||
return ( (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) & AUTCPU12_SMC_RDY) ? 1 : 0;
|
||||
return ((*(volatile unsigned char *)(autcpu12_io_base + autcpu12_pedr)) & AUTCPU12_SMC_RDY) ? 1 : 0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Main initialization routine
|
||||
*/
|
||||
int __init autcpu12_init (void)
|
||||
int __init autcpu12_init(void)
|
||||
{
|
||||
struct nand_chip *this;
|
||||
int err = 0;
|
||||
|
||||
/* Allocate memory for MTD device structure and private data */
|
||||
autcpu12_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
|
||||
GFP_KERNEL);
|
||||
autcpu12_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
|
||||
if (!autcpu12_mtd) {
|
||||
printk ("Unable to allocate AUTCPU12 NAND MTD device structure.\n");
|
||||
printk("Unable to allocate AUTCPU12 NAND MTD device structure.\n");
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* map physical adress */
|
||||
autcpu12_fio_base = ioremap(autcpu12_fio_pbase,SZ_1K);
|
||||
if(!autcpu12_fio_base){
|
||||
autcpu12_fio_base = ioremap(autcpu12_fio_pbase, SZ_1K);
|
||||
if (!autcpu12_fio_base) {
|
||||
printk("Ioremap autcpu12 SmartMedia Card failed\n");
|
||||
err = -EIO;
|
||||
goto out_mtd;
|
||||
}
|
||||
|
||||
/* Get pointer to private data */
|
||||
this = (struct nand_chip *) (&autcpu12_mtd[1]);
|
||||
this = (struct nand_chip *)(&autcpu12_mtd[1]);
|
||||
|
||||
/* Initialize structures */
|
||||
memset((char *) autcpu12_mtd, 0, sizeof(struct mtd_info));
|
||||
memset((char *) this, 0, sizeof(struct nand_chip));
|
||||
memset(autcpu12_mtd, 0, sizeof(struct mtd_info));
|
||||
memset(this, 0, sizeof(struct nand_chip));
|
||||
|
||||
/* Link the private data with the MTD structure */
|
||||
autcpu12_mtd->priv = this;
|
||||
@ -167,35 +166,34 @@ int __init autcpu12_init (void)
|
||||
|
||||
/* Enable the following for a flash based bad block table */
|
||||
/*
|
||||
this->options = NAND_USE_FLASH_BBT;
|
||||
*/
|
||||
this->options = NAND_USE_FLASH_BBT;
|
||||
*/
|
||||
this->options = NAND_USE_FLASH_BBT;
|
||||
|
||||
/* Scan to find existance of the device */
|
||||
if (nand_scan (autcpu12_mtd, 1)) {
|
||||
if (nand_scan(autcpu12_mtd, 1)) {
|
||||
err = -ENXIO;
|
||||
goto out_ior;
|
||||
}
|
||||
|
||||
/* Register the partitions */
|
||||
switch(autcpu12_mtd->size){
|
||||
switch (autcpu12_mtd->size) {
|
||||
case SZ_16M: add_mtd_partitions(autcpu12_mtd, partition_info16k, NUM_PARTITIONS16K); break;
|
||||
case SZ_32M: add_mtd_partitions(autcpu12_mtd, partition_info32k, NUM_PARTITIONS32K); break;
|
||||
case SZ_64M: add_mtd_partitions(autcpu12_mtd, partition_info64k, NUM_PARTITIONS64K); break;
|
||||
case SZ_128M: add_mtd_partitions(autcpu12_mtd, partition_info128k, NUM_PARTITIONS128K); break;
|
||||
default: {
|
||||
printk ("Unsupported SmartMedia device\n");
|
||||
default:
|
||||
printk("Unsupported SmartMedia device\n");
|
||||
err = -ENXIO;
|
||||
goto out_ior;
|
||||
}
|
||||
}
|
||||
goto out;
|
||||
|
||||
out_ior:
|
||||
out_ior:
|
||||
iounmap((void *)autcpu12_fio_base);
|
||||
out_mtd:
|
||||
kfree (autcpu12_mtd);
|
||||
out:
|
||||
out_mtd:
|
||||
kfree(autcpu12_mtd);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -205,17 +203,18 @@ module_init(autcpu12_init);
|
||||
* Clean up routine
|
||||
*/
|
||||
#ifdef MODULE
|
||||
static void __exit autcpu12_cleanup (void)
|
||||
static void __exit autcpu12_cleanup(void)
|
||||
{
|
||||
/* Release resources, unregister device */
|
||||
nand_release (autcpu12_mtd);
|
||||
nand_release(autcpu12_mtd);
|
||||
|
||||
/* unmap physical adress */
|
||||
iounmap((void *)autcpu12_fio_base);
|
||||
|
||||
/* Free the MTD device structure */
|
||||
kfree (autcpu12_mtd);
|
||||
kfree(autcpu12_mtd);
|
||||
}
|
||||
|
||||
module_exit(autcpu12_cleanup);
|
||||
#endif
|
||||
|
||||
|
@ -50,7 +50,7 @@
|
||||
|
||||
/* Pin function selection MSR (IDE vs. flash on the IDE pins) */
|
||||
#define MSR_DIVIL_BALL_OPTS 0x51400015
|
||||
#define PIN_OPT_IDE (1<<0) /* 0 for flash, 1 for IDE */
|
||||
#define PIN_OPT_IDE (1<<0) /* 0 for flash, 1 for IDE */
|
||||
|
||||
/* Registers within the NAND flash controller BAR -- memory mapped */
|
||||
#define MM_NAND_DATA 0x00 /* 0 to 0x7ff, in fact */
|
||||
@ -128,7 +128,7 @@ static void cs553x_write_byte(struct mtd_info *mtd, u_char byte)
|
||||
udelay(1);
|
||||
i--;
|
||||
}
|
||||
writeb(byte, this->IO_ADDR_W+0x801);
|
||||
writeb(byte, this->IO_ADDR_W + 0x801);
|
||||
}
|
||||
|
||||
static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
@ -137,7 +137,7 @@ static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
void __iomem *mmio_base = this->IO_ADDR_R;
|
||||
unsigned char ctl;
|
||||
|
||||
switch(cmd) {
|
||||
switch (cmd) {
|
||||
case NAND_CTL_SETCLE:
|
||||
ctl = CS_NAND_CTL_CLE;
|
||||
break;
|
||||
@ -160,17 +160,15 @@ static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
writeb(ctl, mmio_base + MM_NAND_CTL);
|
||||
}
|
||||
|
||||
|
||||
static int cs553x_device_ready(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
void __iomem *mmio_base = this->IO_ADDR_R;
|
||||
unsigned char foo = readb(mmio_base + MM_NAND_STS);
|
||||
|
||||
return (foo & CS_NAND_STS_FLASH_RDY) && !(foo & CS_NAND_CTLR_BUSY);
|
||||
return (foo & CS_NAND_STS_FLASH_RDY) && !(foo & CS_NAND_CTLR_BUSY);
|
||||
}
|
||||
|
||||
|
||||
static void cs_enable_hwecc(struct mtd_info *mtd, int mode)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
@ -209,7 +207,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
|
||||
}
|
||||
|
||||
/* Allocate memory for MTD device structure and private data */
|
||||
new_mtd = kmalloc(sizeof(struct mtd_info) + sizeof (struct nand_chip), GFP_KERNEL);
|
||||
new_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
|
||||
if (!new_mtd) {
|
||||
printk(KERN_WARNING "Unable to allocate CS553X NAND MTD device structure.\n");
|
||||
err = -ENOMEM;
|
||||
@ -217,7 +215,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
|
||||
}
|
||||
|
||||
/* Get pointer to private data */
|
||||
this = (struct nand_chip *) (&new_mtd[1]);
|
||||
this = (struct nand_chip *)(&new_mtd[1]);
|
||||
|
||||
/* Initialize structures */
|
||||
memset(new_mtd, 0, sizeof(struct mtd_info));
|
||||
@ -286,16 +284,16 @@ int __init cs553x_init(void)
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
for (i=0; i<NR_CS553X_CONTROLLERS; i++) {
|
||||
rdmsrl(MSR_DIVIL_LBAR_FLSH0+i, val);
|
||||
for (i = 0; i < NR_CS553X_CONTROLLERS; i++) {
|
||||
rdmsrl(MSR_DIVIL_LBAR_FLSH0 + i, val);
|
||||
|
||||
if ((val & (FLSH_LBAR_EN|FLSH_NOR_NAND)) == (FLSH_LBAR_EN|FLSH_NOR_NAND))
|
||||
err = cs553x_init_one(i, !!(val & FLSH_MEM_IO), val & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
|
||||
/* Register all devices together here. This means we can easily hack it to
|
||||
do mtdconcat etc. if we want to. */
|
||||
for (i=0; i<NR_CS553X_CONTROLLERS; i++) {
|
||||
for (i = 0; i < NR_CS553X_CONTROLLERS; i++) {
|
||||
if (cs553x_mtd[i]) {
|
||||
add_mtd_device(cs553x_mtd[i]);
|
||||
|
||||
@ -306,13 +304,14 @@ int __init cs553x_init(void)
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
module_init(cs553x_init);
|
||||
|
||||
static void __exit cs553x_cleanup (void)
|
||||
static void __exit cs553x_cleanup(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<NR_CS553X_CONTROLLERS; i++) {
|
||||
for (i = 0; i < NR_CS553X_CONTROLLERS; i++) {
|
||||
struct mtd_info *mtd = cs553x_mtd[i];
|
||||
struct nand_chip *this;
|
||||
void __iomem *mmio_base;
|
||||
@ -324,7 +323,7 @@ static void __exit cs553x_cleanup (void)
|
||||
mmio_base = this->IO_ADDR_R;
|
||||
|
||||
/* Release resources, unregister device */
|
||||
nand_release (cs553x_mtd[i]);
|
||||
nand_release(cs553x_mtd[i]);
|
||||
cs553x_mtd[i] = NULL;
|
||||
|
||||
/* unmap physical adress */
|
||||
@ -334,6 +333,7 @@ static void __exit cs553x_cleanup (void)
|
||||
kfree(mtd);
|
||||
}
|
||||
}
|
||||
|
||||
module_exit(cs553x_cleanup);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -25,7 +25,7 @@
|
||||
#include <linux/mtd/nand.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/hardware.h> /* for CLPS7111_VIRT_BASE */
|
||||
#include <asm/arch/hardware.h> /* for CLPS7111_VIRT_BASE */
|
||||
#include <asm/sizes.h>
|
||||
#include <asm/hardware/clps7111.h>
|
||||
|
||||
@ -54,29 +54,29 @@ static struct mtd_info *ep7312_mtd = NULL;
|
||||
*/
|
||||
|
||||
static unsigned long ep7312_fio_pbase = EP7312_FIO_PBASE;
|
||||
static void __iomem * ep7312_pxdr = (void __iomem *) EP7312_PXDR;
|
||||
static void __iomem * ep7312_pxddr = (void __iomem *) EP7312_PXDDR;
|
||||
static void __iomem *ep7312_pxdr = (void __iomem *)EP7312_PXDR;
|
||||
static void __iomem *ep7312_pxddr = (void __iomem *)EP7312_PXDDR;
|
||||
|
||||
#ifdef CONFIG_MTD_PARTITIONS
|
||||
/*
|
||||
* Define static partitions for flash device
|
||||
*/
|
||||
static struct mtd_partition partition_info[] = {
|
||||
{ .name = "EP7312 Nand Flash",
|
||||
.offset = 0,
|
||||
.size = 8*1024*1024 }
|
||||
{.name = "EP7312 Nand Flash",
|
||||
.offset = 0,
|
||||
.size = 8 * 1024 * 1024}
|
||||
};
|
||||
|
||||
#define NUM_PARTITIONS 1
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* hardware specific access to control-lines
|
||||
*/
|
||||
static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
{
|
||||
switch(cmd) {
|
||||
switch (cmd) {
|
||||
|
||||
case NAND_CTL_SETCLE:
|
||||
clps_writeb(clps_readb(ep7312_pxdr) | 0x10, ep7312_pxdr);
|
||||
@ -108,6 +108,7 @@ static int ep7312_device_ready(struct mtd_info *mtd)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MTD_PARTITIONS
|
||||
const char *part_probes[] = { "cmdlinepart", NULL };
|
||||
#endif
|
||||
@ -115,18 +116,16 @@ const char *part_probes[] = { "cmdlinepart", NULL };
|
||||
/*
|
||||
* Main initialization routine
|
||||
*/
|
||||
static int __init ep7312_init (void)
|
||||
static int __init ep7312_init(void)
|
||||
{
|
||||
struct nand_chip *this;
|
||||
const char *part_type = 0;
|
||||
int mtd_parts_nb = 0;
|
||||
struct mtd_partition *mtd_parts = 0;
|
||||
void __iomem * ep7312_fio_base;
|
||||
void __iomem *ep7312_fio_base;
|
||||
|
||||
/* Allocate memory for MTD device structure and private data */
|
||||
ep7312_mtd = kmalloc(sizeof(struct mtd_info) +
|
||||
sizeof(struct nand_chip),
|
||||
GFP_KERNEL);
|
||||
ep7312_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
|
||||
if (!ep7312_mtd) {
|
||||
printk("Unable to allocate EDB7312 NAND MTD device structure.\n");
|
||||
return -ENOMEM;
|
||||
@ -134,18 +133,18 @@ static int __init ep7312_init (void)
|
||||
|
||||
/* map physical adress */
|
||||
ep7312_fio_base = ioremap(ep7312_fio_pbase, SZ_1K);
|
||||
if(!ep7312_fio_base) {
|
||||
if (!ep7312_fio_base) {
|
||||
printk("ioremap EDB7312 NAND flash failed\n");
|
||||
kfree(ep7312_mtd);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Get pointer to private data */
|
||||
this = (struct nand_chip *) (&ep7312_mtd[1]);
|
||||
this = (struct nand_chip *)(&ep7312_mtd[1]);
|
||||
|
||||
/* Initialize structures */
|
||||
memset((char *) ep7312_mtd, 0, sizeof(struct mtd_info));
|
||||
memset((char *) this, 0, sizeof(struct nand_chip));
|
||||
memset(ep7312_mtd, 0, sizeof(struct mtd_info));
|
||||
memset(this, 0, sizeof(struct nand_chip));
|
||||
|
||||
/* Link the private data with the MTD structure */
|
||||
ep7312_mtd->priv = this;
|
||||
@ -165,16 +164,14 @@ static int __init ep7312_init (void)
|
||||
this->chip_delay = 15;
|
||||
|
||||
/* Scan to find existence of the device */
|
||||
if (nand_scan (ep7312_mtd, 1)) {
|
||||
if (nand_scan(ep7312_mtd, 1)) {
|
||||
iounmap((void *)ep7312_fio_base);
|
||||
kfree (ep7312_mtd);
|
||||
kfree(ep7312_mtd);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MTD_PARTITIONS
|
||||
ep7312_mtd->name = "edb7312-nand";
|
||||
mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes,
|
||||
&mtd_parts, 0);
|
||||
mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes, &mtd_parts, 0);
|
||||
if (mtd_parts_nb > 0)
|
||||
part_type = "command line";
|
||||
else
|
||||
@ -193,24 +190,26 @@ static int __init ep7312_init (void)
|
||||
/* Return happy */
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_init(ep7312_init);
|
||||
|
||||
/*
|
||||
* Clean up routine
|
||||
*/
|
||||
static void __exit ep7312_cleanup (void)
|
||||
static void __exit ep7312_cleanup(void)
|
||||
{
|
||||
struct nand_chip *this = (struct nand_chip *) &ep7312_mtd[1];
|
||||
struct nand_chip *this = (struct nand_chip *)&ep7312_mtd[1];
|
||||
|
||||
/* Release resources, unregister device */
|
||||
nand_release (ap7312_mtd);
|
||||
nand_release(ap7312_mtd);
|
||||
|
||||
/* Free internal data buffer */
|
||||
kfree (this->data_buf);
|
||||
kfree(this->data_buf);
|
||||
|
||||
/* Free the MTD device structure */
|
||||
kfree (ep7312_mtd);
|
||||
kfree(ep7312_mtd);
|
||||
}
|
||||
|
||||
module_exit(ep7312_cleanup);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include <linux/mtd/nand.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/hardware.h> /* for CLPS7111_VIRT_BASE */
|
||||
#include <asm/arch/hardware.h> /* for CLPS7111_VIRT_BASE */
|
||||
#include <asm/sizes.h>
|
||||
#include <asm/arch/h1900-gpio.h>
|
||||
#include <asm/arch/ipaq.h>
|
||||
@ -45,23 +45,23 @@ static struct mtd_info *h1910_nand_mtd = NULL;
|
||||
* Define static partitions for flash device
|
||||
*/
|
||||
static struct mtd_partition partition_info[] = {
|
||||
{ name: "h1910 NAND Flash",
|
||||
offset: 0,
|
||||
size: 16*1024*1024 }
|
||||
{name:"h1910 NAND Flash",
|
||||
offset:0,
|
||||
size:16 * 1024 * 1024}
|
||||
};
|
||||
|
||||
#define NUM_PARTITIONS 1
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* hardware specific access to control-lines
|
||||
*/
|
||||
static void h1910_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
{
|
||||
struct nand_chip* this = (struct nand_chip *) (mtd->priv);
|
||||
struct nand_chip *this = (struct nand_chip *)(mtd->priv);
|
||||
|
||||
switch(cmd) {
|
||||
switch (cmd) {
|
||||
|
||||
case NAND_CTL_SETCLE:
|
||||
this->IO_ADDR_R |= (1 << 2);
|
||||
@ -101,7 +101,7 @@ static int h1910_device_ready(struct mtd_info *mtd)
|
||||
/*
|
||||
* Main initialization routine
|
||||
*/
|
||||
static int __init h1910_init (void)
|
||||
static int __init h1910_init(void)
|
||||
{
|
||||
struct nand_chip *this;
|
||||
const char *part_type = 0;
|
||||
@ -119,21 +119,19 @@ static int __init h1910_init (void)
|
||||
}
|
||||
|
||||
/* Allocate memory for MTD device structure and private data */
|
||||
h1910_nand_mtd = kmalloc(sizeof(struct mtd_info) +
|
||||
sizeof(struct nand_chip),
|
||||
GFP_KERNEL);
|
||||
h1910_nand_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
|
||||
if (!h1910_nand_mtd) {
|
||||
printk("Unable to allocate h1910 NAND MTD device structure.\n");
|
||||
iounmap ((void *) nandaddr);
|
||||
iounmap((void *)nandaddr);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Get pointer to private data */
|
||||
this = (struct nand_chip *) (&h1910_nand_mtd[1]);
|
||||
this = (struct nand_chip *)(&h1910_nand_mtd[1]);
|
||||
|
||||
/* Initialize structures */
|
||||
memset((char *) h1910_nand_mtd, 0, sizeof(struct mtd_info));
|
||||
memset((char *) this, 0, sizeof(struct nand_chip));
|
||||
memset(h1910_nand_mtd, 0, sizeof(struct mtd_info));
|
||||
memset(this, 0, sizeof(struct nand_chip));
|
||||
|
||||
/* Link the private data with the MTD structure */
|
||||
h1910_nand_mtd->priv = this;
|
||||
@ -154,23 +152,20 @@ static int __init h1910_init (void)
|
||||
this->options = NAND_NO_AUTOINCR;
|
||||
|
||||
/* Scan to find existence of the device */
|
||||
if (nand_scan (h1910_nand_mtd, 1)) {
|
||||
if (nand_scan(h1910_nand_mtd, 1)) {
|
||||
printk(KERN_NOTICE "No NAND device - returning -ENXIO\n");
|
||||
kfree (h1910_nand_mtd);
|
||||
iounmap ((void *) nandaddr);
|
||||
kfree(h1910_nand_mtd);
|
||||
iounmap((void *)nandaddr);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MTD_CMDLINE_PARTS
|
||||
mtd_parts_nb = parse_cmdline_partitions(h1910_nand_mtd, &mtd_parts,
|
||||
"h1910-nand");
|
||||
mtd_parts_nb = parse_cmdline_partitions(h1910_nand_mtd, &mtd_parts, "h1910-nand");
|
||||
if (mtd_parts_nb > 0)
|
||||
part_type = "command line";
|
||||
part_type = "command line";
|
||||
else
|
||||
mtd_parts_nb = 0;
|
||||
mtd_parts_nb = 0;
|
||||
#endif
|
||||
if (mtd_parts_nb == 0)
|
||||
{
|
||||
if (mtd_parts_nb == 0) {
|
||||
mtd_parts = partition_info;
|
||||
mtd_parts_nb = NUM_PARTITIONS;
|
||||
part_type = "static";
|
||||
@ -183,24 +178,26 @@ static int __init h1910_init (void)
|
||||
/* Return happy */
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_init(h1910_init);
|
||||
|
||||
/*
|
||||
* Clean up routine
|
||||
*/
|
||||
static void __exit h1910_cleanup (void)
|
||||
static void __exit h1910_cleanup(void)
|
||||
{
|
||||
struct nand_chip *this = (struct nand_chip *) &h1910_nand_mtd[1];
|
||||
struct nand_chip *this = (struct nand_chip *)&h1910_nand_mtd[1];
|
||||
|
||||
/* Release resources, unregister device */
|
||||
nand_release (h1910_nand_mtd);
|
||||
nand_release(h1910_nand_mtd);
|
||||
|
||||
/* Release io resource */
|
||||
iounmap ((void *) this->IO_ADDR_W);
|
||||
iounmap((void *)this->IO_ADDR_W);
|
||||
|
||||
/* Free the MTD device structure */
|
||||
kfree (h1910_nand_mtd);
|
||||
kfree(h1910_nand_mtd);
|
||||
}
|
||||
|
||||
module_exit(h1910_cleanup);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -48,7 +48,7 @@
|
||||
*
|
||||
* Following assumptions are made:
|
||||
* - bbts start at a page boundary, if autolocated on a block boundary
|
||||
* - the space neccecary for a bbt in FLASH does not exceed a block boundary
|
||||
* - the space necessary for a bbt in FLASH does not exceed a block boundary
|
||||
*
|
||||
*/
|
||||
|
||||
@ -75,7 +75,7 @@
|
||||
* pattern area contain 0xff
|
||||
*
|
||||
*/
|
||||
static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
|
||||
static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
|
||||
{
|
||||
int i, end = 0;
|
||||
uint8_t *p = buf;
|
||||
@ -116,7 +116,7 @@ static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_des
|
||||
* no optional empty check
|
||||
*
|
||||
*/
|
||||
static int check_short_pattern (uint8_t *buf, struct nand_bbt_descr *td)
|
||||
static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)
|
||||
{
|
||||
int i;
|
||||
uint8_t *p = buf;
|
||||
@ -142,8 +142,8 @@ static int check_short_pattern (uint8_t *buf, struct nand_bbt_descr *td)
|
||||
* Read the bad block table starting from page.
|
||||
*
|
||||
*/
|
||||
static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num,
|
||||
int bits, int offs, int reserved_block_code)
|
||||
static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
|
||||
int bits, int offs, int reserved_block_code)
|
||||
{
|
||||
int res, i, j, act = 0;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
@ -152,17 +152,17 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num,
|
||||
uint8_t msk = (uint8_t) ((1 << bits) - 1);
|
||||
|
||||
totlen = (num * bits) >> 3;
|
||||
from = ((loff_t)page) << this->page_shift;
|
||||
from = ((loff_t) page) << this->page_shift;
|
||||
|
||||
while (totlen) {
|
||||
len = min (totlen, (size_t) (1 << this->bbt_erase_shift));
|
||||
res = mtd->read_ecc (mtd, from, len, &retlen, buf, NULL, this->autooob);
|
||||
len = min(totlen, (size_t) (1 << this->bbt_erase_shift));
|
||||
res = mtd->read_ecc(mtd, from, len, &retlen, buf, NULL, this->autooob);
|
||||
if (res < 0) {
|
||||
if (retlen != len) {
|
||||
printk (KERN_INFO "nand_bbt: Error reading bad block table\n");
|
||||
printk(KERN_INFO "nand_bbt: Error reading bad block table\n");
|
||||
return res;
|
||||
}
|
||||
printk (KERN_WARNING "nand_bbt: ECC error while reading bad block table\n");
|
||||
printk(KERN_WARNING "nand_bbt: ECC error while reading bad block table\n");
|
||||
}
|
||||
|
||||
/* Analyse data */
|
||||
@ -172,17 +172,16 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num,
|
||||
uint8_t tmp = (dat >> j) & msk;
|
||||
if (tmp == msk)
|
||||
continue;
|
||||
if (reserved_block_code &&
|
||||
(tmp == reserved_block_code)) {
|
||||
printk (KERN_DEBUG "nand_read_bbt: Reserved block at 0x%08x\n",
|
||||
((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
|
||||
if (reserved_block_code && (tmp == reserved_block_code)) {
|
||||
printk(KERN_DEBUG "nand_read_bbt: Reserved block at 0x%08x\n",
|
||||
((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
|
||||
this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06);
|
||||
continue;
|
||||
}
|
||||
/* Leave it for now, if its matured we can move this
|
||||
* message to MTD_DEBUG_LEVEL0 */
|
||||
printk (KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n",
|
||||
((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
|
||||
printk(KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n",
|
||||
((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
|
||||
/* Factory marked bad or worn out ? */
|
||||
if (tmp == 0)
|
||||
this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06);
|
||||
@ -207,7 +206,7 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num,
|
||||
* Read the bad block table for all chips starting at a given page
|
||||
* We assume that the bbt bits are in consecutive order.
|
||||
*/
|
||||
static int read_abs_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip)
|
||||
static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
int res = 0, i;
|
||||
@ -242,23 +241,22 @@ static int read_abs_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des
|
||||
* We assume that the bbt bits are in consecutive order.
|
||||
*
|
||||
*/
|
||||
static int read_abs_bbts (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td,
|
||||
struct nand_bbt_descr *md)
|
||||
static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, struct nand_bbt_descr *md)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
|
||||
/* Read the primary version, if available */
|
||||
if (td->options & NAND_BBT_VERSION) {
|
||||
nand_read_raw (mtd, buf, td->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize);
|
||||
nand_read_raw(mtd, buf, td->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize);
|
||||
td->version[0] = buf[mtd->oobblock + td->veroffs];
|
||||
printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", td->pages[0], td->version[0]);
|
||||
printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", td->pages[0], td->version[0]);
|
||||
}
|
||||
|
||||
/* Read the mirror version, if available */
|
||||
if (md && (md->options & NAND_BBT_VERSION)) {
|
||||
nand_read_raw (mtd, buf, md->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize);
|
||||
nand_read_raw(mtd, buf, md->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize);
|
||||
md->version[0] = buf[mtd->oobblock + md->veroffs];
|
||||
printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", md->pages[0], md->version[0]);
|
||||
printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", md->pages[0], md->version[0]);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@ -275,7 +273,7 @@ static int read_abs_bbts (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_de
|
||||
* Create a bad block table by scanning the device
|
||||
* for the given good/bad block identify pattern
|
||||
*/
|
||||
static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip)
|
||||
static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
int i, j, numblocks, len, scanlen;
|
||||
@ -283,7 +281,7 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
|
||||
loff_t from;
|
||||
size_t readlen, ooblen;
|
||||
|
||||
printk (KERN_INFO "Scanning device for bad blocks\n");
|
||||
printk(KERN_INFO "Scanning device for bad blocks\n");
|
||||
|
||||
if (bd->options & NAND_BBT_SCANALLPAGES)
|
||||
len = 1 << (this->bbt_erase_shift - this->page_shift);
|
||||
@ -300,7 +298,7 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
|
||||
readlen = bd->len;
|
||||
} else {
|
||||
/* Full page content should be read */
|
||||
scanlen = mtd->oobblock + mtd->oobsize;
|
||||
scanlen = mtd->oobblock + mtd->oobsize;
|
||||
readlen = len * mtd->oobblock;
|
||||
ooblen = len * mtd->oobsize;
|
||||
}
|
||||
@ -313,8 +311,8 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
|
||||
from = 0;
|
||||
} else {
|
||||
if (chip >= this->numchips) {
|
||||
printk (KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n",
|
||||
chip + 1, this->numchips);
|
||||
printk(KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n",
|
||||
chip + 1, this->numchips);
|
||||
return -EINVAL;
|
||||
}
|
||||
numblocks = this->chipsize >> (this->bbt_erase_shift - 1);
|
||||
@ -327,7 +325,7 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
|
||||
int ret;
|
||||
|
||||
if (bd->options & NAND_BBT_SCANEMPTY)
|
||||
if ((ret = nand_read_raw (mtd, buf, from, readlen, ooblen)))
|
||||
if ((ret = nand_read_raw(mtd, buf, from, readlen, ooblen)))
|
||||
return ret;
|
||||
|
||||
for (j = 0; j < len; j++) {
|
||||
@ -336,22 +334,21 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
|
||||
|
||||
/* Read the full oob until read_oob is fixed to
|
||||
* handle single byte reads for 16 bit buswidth */
|
||||
ret = mtd->read_oob(mtd, from + j * mtd->oobblock,
|
||||
mtd->oobsize, &retlen, buf);
|
||||
ret = mtd->read_oob(mtd, from + j * mtd->oobblock, mtd->oobsize, &retlen, buf);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (check_short_pattern (buf, bd)) {
|
||||
if (check_short_pattern(buf, bd)) {
|
||||
this->bbt[i >> 3] |= 0x03 << (i & 0x6);
|
||||
printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
|
||||
i >> 1, (unsigned int) from);
|
||||
printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
|
||||
i >> 1, (unsigned int)from);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (check_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {
|
||||
if (check_pattern(&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {
|
||||
this->bbt[i >> 3] |= 0x03 << (i & 0x6);
|
||||
printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
|
||||
i >> 1, (unsigned int) from);
|
||||
printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
|
||||
i >> 1, (unsigned int)from);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -374,12 +371,12 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
|
||||
* block.
|
||||
* If the option NAND_BBT_PERCHIP is given, each chip is searched
|
||||
* for a bbt, which contains the bad block information of this chip.
|
||||
* This is neccecary to provide support for certain DOC devices.
|
||||
* This is necessary to provide support for certain DOC devices.
|
||||
*
|
||||
* The bbt ident pattern resides in the oob area of the first page
|
||||
* in a block.
|
||||
*/
|
||||
static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
|
||||
static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
int i, chips;
|
||||
@ -389,7 +386,7 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
|
||||
|
||||
/* Search direction top -> down ? */
|
||||
if (td->options & NAND_BBT_LASTBLOCK) {
|
||||
startblock = (mtd->size >> this->bbt_erase_shift) -1;
|
||||
startblock = (mtd->size >> this->bbt_erase_shift) - 1;
|
||||
dir = -1;
|
||||
} else {
|
||||
startblock = 0;
|
||||
@ -417,7 +414,7 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
|
||||
for (block = 0; block < td->maxblocks; block++) {
|
||||
int actblock = startblock + dir * block;
|
||||
/* Read first page */
|
||||
nand_read_raw (mtd, buf, actblock << this->bbt_erase_shift, mtd->oobblock, mtd->oobsize);
|
||||
nand_read_raw(mtd, buf, actblock << this->bbt_erase_shift, mtd->oobblock, mtd->oobsize);
|
||||
if (!check_pattern(buf, scanlen, mtd->oobblock, td)) {
|
||||
td->pages[i] = actblock << (this->bbt_erase_shift - this->page_shift);
|
||||
if (td->options & NAND_BBT_VERSION) {
|
||||
@ -431,9 +428,10 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
|
||||
/* Check, if we found a bbt for each requested chip */
|
||||
for (i = 0; i < chips; i++) {
|
||||
if (td->pages[i] == -1)
|
||||
printk (KERN_WARNING "Bad block table not found for chip %d\n", i);
|
||||
printk(KERN_WARNING "Bad block table not found for chip %d\n", i);
|
||||
else
|
||||
printk (KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i], td->version[i]);
|
||||
printk(KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i],
|
||||
td->version[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -447,21 +445,19 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
|
||||
*
|
||||
* Search and read the bad block table(s)
|
||||
*/
|
||||
static int search_read_bbts (struct mtd_info *mtd, uint8_t *buf,
|
||||
struct nand_bbt_descr *td, struct nand_bbt_descr *md)
|
||||
static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt_descr *td, struct nand_bbt_descr *md)
|
||||
{
|
||||
/* Search the primary table */
|
||||
search_bbt (mtd, buf, td);
|
||||
search_bbt(mtd, buf, td);
|
||||
|
||||
/* Search the mirror table */
|
||||
if (md)
|
||||
search_bbt (mtd, buf, md);
|
||||
search_bbt(mtd, buf, md);
|
||||
|
||||
/* Force result check */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* write_bbt - [GENERIC] (Re)write the bad block table
|
||||
*
|
||||
@ -474,8 +470,8 @@ static int search_read_bbts (struct mtd_info *mtd, uint8_t *buf,
|
||||
* (Re)write the bad block table
|
||||
*
|
||||
*/
|
||||
static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
|
||||
struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chipsel)
|
||||
static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
|
||||
struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chipsel)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_oobinfo oobinfo;
|
||||
@ -492,7 +488,7 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
|
||||
rcode = 0xff;
|
||||
/* Write bad block table per chip rather than per device ? */
|
||||
if (td->options & NAND_BBT_PERCHIP) {
|
||||
numblocks = (int) (this->chipsize >> this->bbt_erase_shift);
|
||||
numblocks = (int)(this->chipsize >> this->bbt_erase_shift);
|
||||
/* Full device write or specific chip ? */
|
||||
if (chipsel == -1) {
|
||||
nrchips = this->numchips;
|
||||
@ -501,7 +497,7 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
|
||||
chip = chipsel;
|
||||
}
|
||||
} else {
|
||||
numblocks = (int) (mtd->size >> this->bbt_erase_shift);
|
||||
numblocks = (int)(mtd->size >> this->bbt_erase_shift);
|
||||
nrchips = 1;
|
||||
}
|
||||
|
||||
@ -540,9 +536,9 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
|
||||
if (!md || md->pages[chip] != page)
|
||||
goto write;
|
||||
}
|
||||
printk (KERN_ERR "No space left to write bad block table\n");
|
||||
printk(KERN_ERR "No space left to write bad block table\n");
|
||||
return -ENOSPC;
|
||||
write:
|
||||
write:
|
||||
|
||||
/* Set up shift count and masks for the flash table */
|
||||
bits = td->options & NAND_BBT_NRBITS_MSK;
|
||||
@ -558,7 +554,7 @@ write:
|
||||
|
||||
to = ((loff_t) page) << this->page_shift;
|
||||
|
||||
memcpy (&oobinfo, this->autooob, sizeof(oobinfo));
|
||||
memcpy(&oobinfo, this->autooob, sizeof(oobinfo));
|
||||
oobinfo.useecc = MTD_NANDECC_PLACEONLY;
|
||||
|
||||
/* Must we save the block contents ? */
|
||||
@ -566,22 +562,23 @@ write:
|
||||
/* Make it block aligned */
|
||||
to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1));
|
||||
len = 1 << this->bbt_erase_shift;
|
||||
res = mtd->read_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo);
|
||||
res = mtd->read_ecc(mtd, to, len, &retlen, buf, &buf[len], &oobinfo);
|
||||
if (res < 0) {
|
||||
if (retlen != len) {
|
||||
printk (KERN_INFO "nand_bbt: Error reading block for writing the bad block table\n");
|
||||
printk(KERN_INFO
|
||||
"nand_bbt: Error reading block for writing the bad block table\n");
|
||||
return res;
|
||||
}
|
||||
printk (KERN_WARNING "nand_bbt: ECC error while reading block for writing bad block table\n");
|
||||
printk(KERN_WARNING "nand_bbt: ECC error while reading block for writing bad block table\n");
|
||||
}
|
||||
/* Calc the byte offset in the buffer */
|
||||
pageoffs = page - (int)(to >> this->page_shift);
|
||||
offs = pageoffs << this->page_shift;
|
||||
/* Preset the bbt area with 0xff */
|
||||
memset (&buf[offs], 0xff, (size_t)(numblocks >> sft));
|
||||
memset(&buf[offs], 0xff, (size_t) (numblocks >> sft));
|
||||
/* Preset the bbt's oob area with 0xff */
|
||||
memset (&buf[len + pageoffs * mtd->oobsize], 0xff,
|
||||
((len >> this->page_shift) - pageoffs) * mtd->oobsize);
|
||||
memset(&buf[len + pageoffs * mtd->oobsize], 0xff,
|
||||
((len >> this->page_shift) - pageoffs) * mtd->oobsize);
|
||||
if (td->options & NAND_BBT_VERSION) {
|
||||
buf[len + (pageoffs * mtd->oobsize) + td->veroffs] = td->version[chip];
|
||||
}
|
||||
@ -589,22 +586,22 @@ write:
|
||||
/* Calc length */
|
||||
len = (size_t) (numblocks >> sft);
|
||||
/* Make it page aligned ! */
|
||||
len = (len + (mtd->oobblock-1)) & ~(mtd->oobblock-1);
|
||||
len = (len + (mtd->oobblock - 1)) & ~(mtd->oobblock - 1);
|
||||
/* Preset the buffer with 0xff */
|
||||
memset (buf, 0xff, len + (len >> this->page_shift) * mtd->oobsize);
|
||||
memset(buf, 0xff, len + (len >> this->page_shift) * mtd->oobsize);
|
||||
offs = 0;
|
||||
/* Pattern is located in oob area of first page */
|
||||
memcpy (&buf[len + td->offs], td->pattern, td->len);
|
||||
memcpy(&buf[len + td->offs], td->pattern, td->len);
|
||||
if (td->options & NAND_BBT_VERSION) {
|
||||
buf[len + td->veroffs] = td->version[chip];
|
||||
}
|
||||
}
|
||||
|
||||
/* walk through the memory table */
|
||||
for (i = 0; i < numblocks; ) {
|
||||
for (i = 0; i < numblocks;) {
|
||||
uint8_t dat;
|
||||
dat = this->bbt[bbtoffs + (i >> 2)];
|
||||
for (j = 0; j < 4; j++ , i++) {
|
||||
for (j = 0; j < 4; j++, i++) {
|
||||
int sftcnt = (i << (3 - sft)) & sftmsk;
|
||||
/* Do not store the reserved bbt blocks ! */
|
||||
buf[offs + (i >> sft)] &= ~(msk[dat & 0x03] << sftcnt);
|
||||
@ -612,23 +609,23 @@ write:
|
||||
}
|
||||
}
|
||||
|
||||
memset (&einfo, 0, sizeof (einfo));
|
||||
memset(&einfo, 0, sizeof(einfo));
|
||||
einfo.mtd = mtd;
|
||||
einfo.addr = (unsigned long) to;
|
||||
einfo.addr = (unsigned long)to;
|
||||
einfo.len = 1 << this->bbt_erase_shift;
|
||||
res = nand_erase_nand (mtd, &einfo, 1);
|
||||
res = nand_erase_nand(mtd, &einfo, 1);
|
||||
if (res < 0) {
|
||||
printk (KERN_WARNING "nand_bbt: Error during block erase: %d\n", res);
|
||||
printk(KERN_WARNING "nand_bbt: Error during block erase: %d\n", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
res = mtd->write_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo);
|
||||
res = mtd->write_ecc(mtd, to, len, &retlen, buf, &buf[len], &oobinfo);
|
||||
if (res < 0) {
|
||||
printk (KERN_WARNING "nand_bbt: Error while writing bad block table %d\n", res);
|
||||
printk(KERN_WARNING "nand_bbt: Error while writing bad block table %d\n", res);
|
||||
return res;
|
||||
}
|
||||
printk (KERN_DEBUG "Bad block table written to 0x%08x, version 0x%02X\n",
|
||||
(unsigned int) to, td->version[chip]);
|
||||
printk(KERN_DEBUG "Bad block table written to 0x%08x, version 0x%02X\n",
|
||||
(unsigned int)to, td->version[chip]);
|
||||
|
||||
/* Mark it as used */
|
||||
td->pages[chip] = page;
|
||||
@ -644,27 +641,27 @@ write:
|
||||
* The function creates a memory based bbt by scanning the device
|
||||
* for manufacturer / software marked good / bad blocks
|
||||
*/
|
||||
static inline int nand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
||||
static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
|
||||
bd->options &= ~NAND_BBT_SCANEMPTY;
|
||||
return create_bbt (mtd, this->data_buf, bd, -1);
|
||||
return create_bbt(mtd, this->data_buf, bd, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* check_create - [GENERIC] create and write bbt(s) if neccecary
|
||||
* check_create - [GENERIC] create and write bbt(s) if necessary
|
||||
* @mtd: MTD device structure
|
||||
* @buf: temporary buffer
|
||||
* @bd: descriptor for the good/bad block search pattern
|
||||
*
|
||||
* The function checks the results of the previous call to read_bbt
|
||||
* and creates / updates the bbt(s) if neccecary
|
||||
* Creation is neccecary if no bbt was found for the chip/device
|
||||
* Update is neccecary if one of the tables is missing or the
|
||||
* and creates / updates the bbt(s) if necessary
|
||||
* Creation is necessary if no bbt was found for the chip/device
|
||||
* Update is necessary if one of the tables is missing or the
|
||||
* version nr. of one table is less than the other
|
||||
*/
|
||||
static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)
|
||||
static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)
|
||||
{
|
||||
int i, chips, writeops, chipsel, res;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
@ -732,35 +729,35 @@ static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des
|
||||
rd = td;
|
||||
goto writecheck;
|
||||
}
|
||||
create:
|
||||
create:
|
||||
/* Create the bad block table by scanning the device ? */
|
||||
if (!(td->options & NAND_BBT_CREATE))
|
||||
continue;
|
||||
|
||||
/* Create the table in memory by scanning the chip(s) */
|
||||
create_bbt (mtd, buf, bd, chipsel);
|
||||
create_bbt(mtd, buf, bd, chipsel);
|
||||
|
||||
td->version[i] = 1;
|
||||
if (md)
|
||||
md->version[i] = 1;
|
||||
writecheck:
|
||||
writecheck:
|
||||
/* read back first ? */
|
||||
if (rd)
|
||||
read_abs_bbt (mtd, buf, rd, chipsel);
|
||||
read_abs_bbt(mtd, buf, rd, chipsel);
|
||||
/* If they weren't versioned, read both. */
|
||||
if (rd2)
|
||||
read_abs_bbt (mtd, buf, rd2, chipsel);
|
||||
read_abs_bbt(mtd, buf, rd2, chipsel);
|
||||
|
||||
/* Write the bad block table to the device ? */
|
||||
if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
|
||||
res = write_bbt (mtd, buf, td, md, chipsel);
|
||||
res = write_bbt(mtd, buf, td, md, chipsel);
|
||||
if (res < 0)
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Write the mirror bad block table to the device ? */
|
||||
if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
|
||||
res = write_bbt (mtd, buf, md, td, chipsel);
|
||||
res = write_bbt(mtd, buf, md, td, chipsel);
|
||||
if (res < 0)
|
||||
return res;
|
||||
}
|
||||
@ -777,7 +774,7 @@ writecheck:
|
||||
* accidental erasures / writes. The regions are identified by
|
||||
* the mark 0x02.
|
||||
*/
|
||||
static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td)
|
||||
static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
int i, j, chips, block, nrblocks, update;
|
||||
@ -795,7 +792,8 @@ static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td)
|
||||
for (i = 0; i < chips; i++) {
|
||||
if ((td->options & NAND_BBT_ABSPAGE) ||
|
||||
!(td->options & NAND_BBT_WRITE)) {
|
||||
if (td->pages[i] == -1) continue;
|
||||
if (td->pages[i] == -1)
|
||||
continue;
|
||||
block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift);
|
||||
block <<= 1;
|
||||
oldval = this->bbt[(block >> 3)];
|
||||
@ -815,7 +813,8 @@ static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td)
|
||||
oldval = this->bbt[(block >> 3)];
|
||||
newval = oldval | (0x2 << (block & 0x06));
|
||||
this->bbt[(block >> 3)] = newval;
|
||||
if (oldval != newval) update = 1;
|
||||
if (oldval != newval)
|
||||
update = 1;
|
||||
block += 2;
|
||||
}
|
||||
/* If we want reserved blocks to be recorded to flash, and some
|
||||
@ -840,7 +839,7 @@ static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td)
|
||||
* by calling the nand_free_bbt function.
|
||||
*
|
||||
*/
|
||||
int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
||||
int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
int len, res = 0;
|
||||
@ -850,21 +849,21 @@ int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
||||
|
||||
len = mtd->size >> (this->bbt_erase_shift + 2);
|
||||
/* Allocate memory (2bit per block) */
|
||||
this->bbt = kmalloc (len, GFP_KERNEL);
|
||||
this->bbt = kmalloc(len, GFP_KERNEL);
|
||||
if (!this->bbt) {
|
||||
printk (KERN_ERR "nand_scan_bbt: Out of memory\n");
|
||||
printk(KERN_ERR "nand_scan_bbt: Out of memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
/* Clear the memory bad block table */
|
||||
memset (this->bbt, 0x00, len);
|
||||
memset(this->bbt, 0x00, len);
|
||||
|
||||
/* If no primary table decriptor is given, scan the device
|
||||
* to build a memory based bad block table
|
||||
*/
|
||||
if (!td) {
|
||||
if ((res = nand_memory_bbt(mtd, bd))) {
|
||||
printk (KERN_ERR "nand_bbt: Can't scan flash and build the RAM-based BBT\n");
|
||||
kfree (this->bbt);
|
||||
printk(KERN_ERR "nand_bbt: Can't scan flash and build the RAM-based BBT\n");
|
||||
kfree(this->bbt);
|
||||
this->bbt = NULL;
|
||||
}
|
||||
return res;
|
||||
@ -875,33 +874,32 @@ int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
||||
len += (len >> this->page_shift) * mtd->oobsize;
|
||||
buf = vmalloc(len);
|
||||
if (!buf) {
|
||||
printk (KERN_ERR "nand_bbt: Out of memory\n");
|
||||
kfree (this->bbt);
|
||||
printk(KERN_ERR "nand_bbt: Out of memory\n");
|
||||
kfree(this->bbt);
|
||||
this->bbt = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Is the bbt at a given page ? */
|
||||
if (td->options & NAND_BBT_ABSPAGE) {
|
||||
res = read_abs_bbts (mtd, buf, td, md);
|
||||
res = read_abs_bbts(mtd, buf, td, md);
|
||||
} else {
|
||||
/* Search the bad block table using a pattern in oob */
|
||||
res = search_read_bbts (mtd, buf, td, md);
|
||||
res = search_read_bbts(mtd, buf, td, md);
|
||||
}
|
||||
|
||||
if (res)
|
||||
res = check_create (mtd, buf, bd);
|
||||
res = check_create(mtd, buf, bd);
|
||||
|
||||
/* Prevent the bbt regions from erasing / writing */
|
||||
mark_bbt_region (mtd, td);
|
||||
mark_bbt_region(mtd, td);
|
||||
if (md)
|
||||
mark_bbt_region (mtd, md);
|
||||
mark_bbt_region(mtd, md);
|
||||
|
||||
vfree (buf);
|
||||
vfree(buf);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* nand_update_bbt - [NAND Interface] update bad block table(s)
|
||||
* @mtd: MTD device structure
|
||||
@ -909,7 +907,7 @@ int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
|
||||
*
|
||||
* The function updates the bad block table(s)
|
||||
*/
|
||||
int nand_update_bbt (struct mtd_info *mtd, loff_t offs)
|
||||
int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
int len, res = 0, writeops = 0;
|
||||
@ -925,9 +923,9 @@ int nand_update_bbt (struct mtd_info *mtd, loff_t offs)
|
||||
/* Allocate a temporary buffer for one eraseblock incl. oob */
|
||||
len = (1 << this->bbt_erase_shift);
|
||||
len += (len >> this->page_shift) * mtd->oobsize;
|
||||
buf = kmalloc (len, GFP_KERNEL);
|
||||
buf = kmalloc(len, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
printk (KERN_ERR "nand_update_bbt: Out of memory\n");
|
||||
printk(KERN_ERR "nand_update_bbt: Out of memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -935,7 +933,7 @@ int nand_update_bbt (struct mtd_info *mtd, loff_t offs)
|
||||
|
||||
/* Do we have a bbt per chip ? */
|
||||
if (td->options & NAND_BBT_PERCHIP) {
|
||||
chip = (int) (offs >> this->chip_shift);
|
||||
chip = (int)(offs >> this->chip_shift);
|
||||
chipsel = chip;
|
||||
} else {
|
||||
chip = 0;
|
||||
@ -948,17 +946,17 @@ int nand_update_bbt (struct mtd_info *mtd, loff_t offs)
|
||||
|
||||
/* Write the bad block table to the device ? */
|
||||
if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
|
||||
res = write_bbt (mtd, buf, td, md, chipsel);
|
||||
res = write_bbt(mtd, buf, td, md, chipsel);
|
||||
if (res < 0)
|
||||
goto out;
|
||||
}
|
||||
/* Write the mirror bad block table to the device ? */
|
||||
if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
|
||||
res = write_bbt (mtd, buf, md, td, chipsel);
|
||||
res = write_bbt(mtd, buf, md, td, chipsel);
|
||||
}
|
||||
|
||||
out:
|
||||
kfree (buf);
|
||||
out:
|
||||
kfree(buf);
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -1036,7 +1034,7 @@ static struct nand_bbt_descr bbt_mirror_descr = {
|
||||
* support for the device and calls the nand_scan_bbt function
|
||||
*
|
||||
*/
|
||||
int nand_default_bbt (struct mtd_info *mtd)
|
||||
int nand_default_bbt(struct mtd_info *mtd)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
|
||||
@ -1046,7 +1044,7 @@ int nand_default_bbt (struct mtd_info *mtd)
|
||||
* of the good / bad information, so we _must_ store
|
||||
* this information in a good / bad table during
|
||||
* startup
|
||||
*/
|
||||
*/
|
||||
if (this->options & NAND_IS_AND) {
|
||||
/* Use the default pattern descriptors */
|
||||
if (!this->bbt_td) {
|
||||
@ -1054,10 +1052,9 @@ int nand_default_bbt (struct mtd_info *mtd)
|
||||
this->bbt_md = &bbt_mirror_descr;
|
||||
}
|
||||
this->options |= NAND_USE_FLASH_BBT;
|
||||
return nand_scan_bbt (mtd, &agand_flashbased);
|
||||
return nand_scan_bbt(mtd, &agand_flashbased);
|
||||
}
|
||||
|
||||
|
||||
/* Is a flash based bad block table requested ? */
|
||||
if (this->options & NAND_USE_FLASH_BBT) {
|
||||
/* Use the default pattern descriptors */
|
||||
@ -1066,18 +1063,17 @@ int nand_default_bbt (struct mtd_info *mtd)
|
||||
this->bbt_md = &bbt_mirror_descr;
|
||||
}
|
||||
if (!this->badblock_pattern) {
|
||||
this->badblock_pattern = (mtd->oobblock > 512) ?
|
||||
&largepage_flashbased : &smallpage_flashbased;
|
||||
this->badblock_pattern = (mtd->oobblock > 512) ? &largepage_flashbased : &smallpage_flashbased;
|
||||
}
|
||||
} else {
|
||||
this->bbt_td = NULL;
|
||||
this->bbt_md = NULL;
|
||||
if (!this->badblock_pattern) {
|
||||
this->badblock_pattern = (mtd->oobblock > 512) ?
|
||||
&largepage_memorybased : &smallpage_memorybased;
|
||||
&largepage_memorybased : &smallpage_memorybased;
|
||||
}
|
||||
}
|
||||
return nand_scan_bbt (mtd, this->badblock_pattern);
|
||||
return nand_scan_bbt(mtd, this->badblock_pattern);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1087,26 +1083,29 @@ int nand_default_bbt (struct mtd_info *mtd)
|
||||
* @allowbbt: allow access to bad block table region
|
||||
*
|
||||
*/
|
||||
int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt)
|
||||
int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
int block;
|
||||
uint8_t res;
|
||||
uint8_t res;
|
||||
|
||||
/* Get block number * 2 */
|
||||
block = (int) (offs >> (this->bbt_erase_shift - 1));
|
||||
block = (int)(offs >> (this->bbt_erase_shift - 1));
|
||||
res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03;
|
||||
|
||||
DEBUG (MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n",
|
||||
(unsigned int)offs, block >> 1, res);
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n",
|
||||
(unsigned int)offs, block >> 1, res);
|
||||
|
||||
switch ((int)res) {
|
||||
case 0x00: return 0;
|
||||
case 0x01: return 1;
|
||||
case 0x02: return allowbbt ? 0 : 1;
|
||||
case 0x00:
|
||||
return 0;
|
||||
case 0x01:
|
||||
return 1;
|
||||
case 0x02:
|
||||
return allowbbt ? 0 : 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL (nand_scan_bbt);
|
||||
EXPORT_SYMBOL (nand_default_bbt);
|
||||
EXPORT_SYMBOL(nand_scan_bbt);
|
||||
EXPORT_SYMBOL(nand_default_bbt);
|
||||
|
@ -62,7 +62,6 @@ static const u_char nand_ecc_precalc_table[] = {
|
||||
0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* nand_trans_result - [GENERIC] create non-inverted ECC
|
||||
* @reg2: line parity reg 2
|
||||
@ -71,8 +70,7 @@ static const u_char nand_ecc_precalc_table[] = {
|
||||
*
|
||||
* Creates non-inverted ECC code from line parity
|
||||
*/
|
||||
static void nand_trans_result(u_char reg2, u_char reg3,
|
||||
u_char *ecc_code)
|
||||
static void nand_trans_result(u_char reg2, u_char reg3, u_char *ecc_code)
|
||||
{
|
||||
u_char a, b, i, tmp1, tmp2;
|
||||
|
||||
@ -82,10 +80,10 @@ static void nand_trans_result(u_char reg2, u_char reg3,
|
||||
|
||||
/* Calculate first ECC byte */
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (reg3 & a) /* LP15,13,11,9 --> ecc_code[0] */
|
||||
if (reg3 & a) /* LP15,13,11,9 --> ecc_code[0] */
|
||||
tmp1 |= b;
|
||||
b >>= 1;
|
||||
if (reg2 & a) /* LP14,12,10,8 --> ecc_code[0] */
|
||||
if (reg2 & a) /* LP14,12,10,8 --> ecc_code[0] */
|
||||
tmp1 |= b;
|
||||
b >>= 1;
|
||||
a >>= 1;
|
||||
@ -94,10 +92,10 @@ static void nand_trans_result(u_char reg2, u_char reg3,
|
||||
/* Calculate second ECC byte */
|
||||
b = 0x80;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (reg3 & a) /* LP7,5,3,1 --> ecc_code[1] */
|
||||
if (reg3 & a) /* LP7,5,3,1 --> ecc_code[1] */
|
||||
tmp2 |= b;
|
||||
b >>= 1;
|
||||
if (reg2 & a) /* LP6,4,2,0 --> ecc_code[1] */
|
||||
if (reg2 & a) /* LP6,4,2,0 --> ecc_code[1] */
|
||||
tmp2 |= b;
|
||||
b >>= 1;
|
||||
a >>= 1;
|
||||
@ -124,7 +122,7 @@ int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code
|
||||
ecc_code[0] = ecc_code[1] = ecc_code[2] = 0;
|
||||
|
||||
/* Build up column parity */
|
||||
for(j = 0; j < 256; j++) {
|
||||
for (j = 0; j < 256; j++) {
|
||||
|
||||
/* Get CP0 - CP5 from table */
|
||||
idx = nand_ecc_precalc_table[dat[j]];
|
||||
@ -168,8 +166,7 @@ int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_cha
|
||||
if ((d1 | d2 | d3) == 0) {
|
||||
/* No errors */
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
a = (d1 ^ (d1 >> 1)) & 0x55;
|
||||
b = (d2 ^ (d2 >> 1)) & 0x55;
|
||||
c = (d3 ^ (d3 >> 1)) & 0x54;
|
||||
@ -179,14 +176,14 @@ int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_cha
|
||||
c = 0x80;
|
||||
add = 0;
|
||||
a = 0x80;
|
||||
for (i=0; i<4; i++) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (d1 & c)
|
||||
add |= a;
|
||||
c >>= 2;
|
||||
a >>= 1;
|
||||
}
|
||||
c = 0x80;
|
||||
for (i=0; i<4; i++) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (d2 & c)
|
||||
add |= a;
|
||||
c >>= 2;
|
||||
@ -195,7 +192,7 @@ int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_cha
|
||||
bit = 0;
|
||||
b = 0x04;
|
||||
c = 0x80;
|
||||
for (i=0; i<3; i++) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (d3 & c)
|
||||
bit |= b;
|
||||
c >>= 2;
|
||||
@ -206,8 +203,7 @@ int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_cha
|
||||
a ^= (b << bit);
|
||||
dat[add] = a;
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
i = 0;
|
||||
while (d1) {
|
||||
if (d1 & 0x01)
|
||||
@ -230,8 +226,7 @@ int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_cha
|
||||
read_ecc[1] = calc_ecc[1];
|
||||
read_ecc[2] = calc_ecc[2];
|
||||
return 2;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* Uncorrectable Error */
|
||||
return -1;
|
||||
}
|
||||
|
@ -125,13 +125,13 @@ struct nand_manufacturers nand_manuf_ids[] = {
|
||||
{NAND_MFR_NATIONAL, "National"},
|
||||
{NAND_MFR_RENESAS, "Renesas"},
|
||||
{NAND_MFR_STMICRO, "ST Micro"},
|
||||
{NAND_MFR_HYNIX, "Hynix"},
|
||||
{NAND_MFR_HYNIX, "Hynix"},
|
||||
{0x0, "Unknown"}
|
||||
};
|
||||
|
||||
EXPORT_SYMBOL (nand_manuf_ids);
|
||||
EXPORT_SYMBOL (nand_flash_ids);
|
||||
EXPORT_SYMBOL(nand_manuf_ids);
|
||||
EXPORT_SYMBOL(nand_flash_ids);
|
||||
|
||||
MODULE_LICENSE ("GPL");
|
||||
MODULE_AUTHOR ("Thomas Gleixner <tglx@linutronix.de>");
|
||||
MODULE_DESCRIPTION ("Nand device & manufacturer ID's");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
|
||||
MODULE_DESCRIPTION("Nand device & manufacturer IDs");
|
||||
|
@ -58,21 +58,21 @@
|
||||
/*
|
||||
* MTD structure for PPChameleonEVB board
|
||||
*/
|
||||
static struct mtd_info *ppchameleon_mtd = NULL;
|
||||
static struct mtd_info *ppchameleon_mtd = NULL;
|
||||
static struct mtd_info *ppchameleonevb_mtd = NULL;
|
||||
|
||||
/*
|
||||
* Module stuff
|
||||
*/
|
||||
static unsigned long ppchameleon_fio_pbase = CFG_NAND0_PADDR;
|
||||
static unsigned long ppchameleon_fio_pbase = CFG_NAND0_PADDR;
|
||||
static unsigned long ppchameleonevb_fio_pbase = CFG_NAND1_PADDR;
|
||||
|
||||
#ifdef MODULE
|
||||
module_param(ppchameleon_fio_pbase, ulong, 0);
|
||||
module_param(ppchameleonevb_fio_pbase, ulong, 0);
|
||||
#else
|
||||
__setup("ppchameleon_fio_pbase=",ppchameleon_fio_pbase);
|
||||
__setup("ppchameleonevb_fio_pbase=",ppchameleonevb_fio_pbase);
|
||||
__setup("ppchameleon_fio_pbase=", ppchameleon_fio_pbase);
|
||||
__setup("ppchameleonevb_fio_pbase=", ppchameleonevb_fio_pbase);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MTD_PARTITIONS
|
||||
@ -80,80 +80,80 @@ __setup("ppchameleonevb_fio_pbase=",ppchameleonevb_fio_pbase);
|
||||
* Define static partitions for flash devices
|
||||
*/
|
||||
static struct mtd_partition partition_info_hi[] = {
|
||||
{ name: "PPChameleon HI Nand Flash",
|
||||
offset: 0,
|
||||
size: 128*1024*1024 }
|
||||
{ .name = "PPChameleon HI Nand Flash",
|
||||
offset = 0,
|
||||
.size = 128 * 1024 * 1024
|
||||
}
|
||||
};
|
||||
|
||||
static struct mtd_partition partition_info_me[] = {
|
||||
{ name: "PPChameleon ME Nand Flash",
|
||||
offset: 0,
|
||||
size: 32*1024*1024 }
|
||||
{ .name = "PPChameleon ME Nand Flash",
|
||||
.offset = 0,
|
||||
.size = 32 * 1024 * 1024
|
||||
}
|
||||
};
|
||||
|
||||
static struct mtd_partition partition_info_evb[] = {
|
||||
{ name: "PPChameleonEVB Nand Flash",
|
||||
offset: 0,
|
||||
size: 32*1024*1024 }
|
||||
{ .name = "PPChameleonEVB Nand Flash",
|
||||
.offset = 0,
|
||||
.size = 32 * 1024 * 1024
|
||||
}
|
||||
};
|
||||
|
||||
#define NUM_PARTITIONS 1
|
||||
|
||||
extern int parse_cmdline_partitions(struct mtd_info *master,
|
||||
struct mtd_partition **pparts,
|
||||
const char *mtd_id);
|
||||
extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, const char *mtd_id);
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* hardware specific access to control-lines
|
||||
*/
|
||||
static void ppchameleon_hwcontrol(struct mtd_info *mtdinfo, int cmd)
|
||||
{
|
||||
switch(cmd) {
|
||||
switch (cmd) {
|
||||
|
||||
case NAND_CTL_SETCLE:
|
||||
MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND0_PADDR);
|
||||
MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND0_PADDR);
|
||||
break;
|
||||
case NAND_CTL_CLRCLE:
|
||||
MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND0_PADDR);
|
||||
MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND0_PADDR);
|
||||
break;
|
||||
case NAND_CTL_SETALE:
|
||||
MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND0_PADDR);
|
||||
MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND0_PADDR);
|
||||
break;
|
||||
case NAND_CTL_CLRALE:
|
||||
MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND0_PADDR);
|
||||
MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND0_PADDR);
|
||||
break;
|
||||
case NAND_CTL_SETNCE:
|
||||
MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND0_PADDR);
|
||||
MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND0_PADDR);
|
||||
break;
|
||||
case NAND_CTL_CLRNCE:
|
||||
MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND0_PADDR);
|
||||
MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND0_PADDR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd)
|
||||
{
|
||||
switch(cmd) {
|
||||
switch (cmd) {
|
||||
|
||||
case NAND_CTL_SETCLE:
|
||||
MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND1_PADDR);
|
||||
MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND1_PADDR);
|
||||
break;
|
||||
case NAND_CTL_CLRCLE:
|
||||
MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND1_PADDR);
|
||||
MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND1_PADDR);
|
||||
break;
|
||||
case NAND_CTL_SETALE:
|
||||
MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND1_PADDR);
|
||||
MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND1_PADDR);
|
||||
break;
|
||||
case NAND_CTL_CLRALE:
|
||||
MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND1_PADDR);
|
||||
MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND1_PADDR);
|
||||
break;
|
||||
case NAND_CTL_SETNCE:
|
||||
MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND1_PADDR);
|
||||
MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND1_PADDR);
|
||||
break;
|
||||
case NAND_CTL_CLRNCE:
|
||||
MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND1_PADDR);
|
||||
MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND1_PADDR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -164,15 +164,15 @@ static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd)
|
||||
*/
|
||||
static int ppchameleon_device_ready(struct mtd_info *minfo)
|
||||
{
|
||||
if (in_be32((volatile unsigned*)GPIO0_IR) & NAND_RB_GPIO_PIN)
|
||||
if (in_be32((volatile unsigned *)GPIO0_IR) & NAND_RB_GPIO_PIN)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ppchameleonevb_device_ready(struct mtd_info *minfo)
|
||||
{
|
||||
if (in_be32((volatile unsigned*)GPIO0_IR) & NAND_EVB_RB_GPIO_PIN)
|
||||
return 1;
|
||||
if (in_be32((volatile unsigned *)GPIO0_IR) & NAND_EVB_RB_GPIO_PIN)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@ -185,7 +185,7 @@ const char *part_probes_evb[] = { "cmdlinepart", NULL };
|
||||
/*
|
||||
* Main initialization routine
|
||||
*/
|
||||
static int __init ppchameleonevb_init (void)
|
||||
static int __init ppchameleonevb_init(void)
|
||||
{
|
||||
struct nand_chip *this;
|
||||
const char *part_type = 0;
|
||||
@ -194,13 +194,11 @@ static int __init ppchameleonevb_init (void)
|
||||
void __iomem *ppchameleon_fio_base;
|
||||
void __iomem *ppchameleonevb_fio_base;
|
||||
|
||||
|
||||
/*********************************
|
||||
* Processor module NAND (if any) *
|
||||
*********************************/
|
||||
/* Allocate memory for MTD device structure and private data */
|
||||
ppchameleon_mtd = kmalloc(sizeof(struct mtd_info) +
|
||||
sizeof(struct nand_chip), GFP_KERNEL);
|
||||
ppchameleon_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
|
||||
if (!ppchameleon_mtd) {
|
||||
printk("Unable to allocate PPChameleon NAND MTD device structure.\n");
|
||||
return -ENOMEM;
|
||||
@ -208,43 +206,45 @@ static int __init ppchameleonevb_init (void)
|
||||
|
||||
/* map physical address */
|
||||
ppchameleon_fio_base = ioremap(ppchameleon_fio_pbase, SZ_4M);
|
||||
if(!ppchameleon_fio_base) {
|
||||
if (!ppchameleon_fio_base) {
|
||||
printk("ioremap PPChameleon NAND flash failed\n");
|
||||
kfree(ppchameleon_mtd);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Get pointer to private data */
|
||||
this = (struct nand_chip *) (&ppchameleon_mtd[1]);
|
||||
this = (struct nand_chip *)(&ppchameleon_mtd[1]);
|
||||
|
||||
/* Initialize structures */
|
||||
memset((char *) ppchameleon_mtd, 0, sizeof(struct mtd_info));
|
||||
memset((char *) this, 0, sizeof(struct nand_chip));
|
||||
memset(ppchameleon_mtd, 0, sizeof(struct mtd_info));
|
||||
memset(this, 0, sizeof(struct nand_chip));
|
||||
|
||||
/* Link the private data with the MTD structure */
|
||||
ppchameleon_mtd->priv = this;
|
||||
|
||||
/* Initialize GPIOs */
|
||||
/* Initialize GPIOs */
|
||||
/* Pin mapping for NAND chip */
|
||||
/*
|
||||
CE GPIO_01
|
||||
CLE GPIO_02
|
||||
ALE GPIO_03
|
||||
R/B GPIO_04
|
||||
*/
|
||||
CE GPIO_01
|
||||
CLE GPIO_02
|
||||
ALE GPIO_03
|
||||
R/B GPIO_04
|
||||
*/
|
||||
/* output select */
|
||||
out_be32((volatile unsigned*)GPIO0_OSRH, in_be32((volatile unsigned*)GPIO0_OSRH) & 0xC0FFFFFF);
|
||||
out_be32((volatile unsigned *)GPIO0_OSRH, in_be32((volatile unsigned *)GPIO0_OSRH) & 0xC0FFFFFF);
|
||||
/* three-state select */
|
||||
out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xC0FFFFFF);
|
||||
out_be32((volatile unsigned *)GPIO0_TSRH, in_be32((volatile unsigned *)GPIO0_TSRH) & 0xC0FFFFFF);
|
||||
/* enable output driver */
|
||||
out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) | NAND_nCE_GPIO_PIN | NAND_CLE_GPIO_PIN | NAND_ALE_GPIO_PIN);
|
||||
out_be32((volatile unsigned *)GPIO0_TCR,
|
||||
in_be32((volatile unsigned *)GPIO0_TCR) | NAND_nCE_GPIO_PIN | NAND_CLE_GPIO_PIN | NAND_ALE_GPIO_PIN);
|
||||
#ifdef USE_READY_BUSY_PIN
|
||||
/* three-state select */
|
||||
out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xFF3FFFFF);
|
||||
out_be32((volatile unsigned *)GPIO0_TSRH, in_be32((volatile unsigned *)GPIO0_TSRH) & 0xFF3FFFFF);
|
||||
/* high-impedecence */
|
||||
out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) & (~NAND_RB_GPIO_PIN));
|
||||
out_be32((volatile unsigned *)GPIO0_TCR, in_be32((volatile unsigned *)GPIO0_TCR) & (~NAND_RB_GPIO_PIN));
|
||||
/* input select */
|
||||
out_be32((volatile unsigned*)GPIO0_ISR1H, (in_be32((volatile unsigned*)GPIO0_ISR1H) & 0xFF3FFFFF) | 0x00400000);
|
||||
out_be32((volatile unsigned *)GPIO0_ISR1H,
|
||||
(in_be32((volatile unsigned *)GPIO0_ISR1H) & 0xFF3FFFFF) | 0x00400000);
|
||||
#endif
|
||||
|
||||
/* insert callbacks */
|
||||
@ -259,12 +259,11 @@ static int __init ppchameleonevb_init (void)
|
||||
this->eccmode = NAND_ECC_SOFT;
|
||||
|
||||
/* Scan to find existence of the device (it could not be mounted) */
|
||||
if (nand_scan (ppchameleon_mtd, 1)) {
|
||||
if (nand_scan(ppchameleon_mtd, 1)) {
|
||||
iounmap((void *)ppchameleon_fio_base);
|
||||
kfree (ppchameleon_mtd);
|
||||
kfree(ppchameleon_mtd);
|
||||
goto nand_evb_init;
|
||||
}
|
||||
|
||||
#ifndef USE_READY_BUSY_PIN
|
||||
/* Adjust delay if necessary */
|
||||
if (ppchameleon_mtd->size == NAND_SMALL_SIZE)
|
||||
@ -275,12 +274,11 @@ static int __init ppchameleonevb_init (void)
|
||||
ppchameleon_mtd->name = "ppchameleon-nand";
|
||||
mtd_parts_nb = parse_mtd_partitions(ppchameleon_mtd, part_probes, &mtd_parts, 0);
|
||||
if (mtd_parts_nb > 0)
|
||||
part_type = "command line";
|
||||
part_type = "command line";
|
||||
else
|
||||
mtd_parts_nb = 0;
|
||||
mtd_parts_nb = 0;
|
||||
#endif
|
||||
if (mtd_parts_nb == 0)
|
||||
{
|
||||
if (mtd_parts_nb == 0) {
|
||||
if (ppchameleon_mtd->size == NAND_SMALL_SIZE)
|
||||
mtd_parts = partition_info_me;
|
||||
else
|
||||
@ -293,13 +291,12 @@ static int __init ppchameleonevb_init (void)
|
||||
printk(KERN_NOTICE "Using %s partition definition\n", part_type);
|
||||
add_mtd_partitions(ppchameleon_mtd, mtd_parts, mtd_parts_nb);
|
||||
|
||||
nand_evb_init:
|
||||
nand_evb_init:
|
||||
/****************************
|
||||
* EVB NAND (always present) *
|
||||
****************************/
|
||||
/* Allocate memory for MTD device structure and private data */
|
||||
ppchameleonevb_mtd = kmalloc(sizeof(struct mtd_info) +
|
||||
sizeof(struct nand_chip), GFP_KERNEL);
|
||||
ppchameleonevb_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
|
||||
if (!ppchameleonevb_mtd) {
|
||||
printk("Unable to allocate PPChameleonEVB NAND MTD device structure.\n");
|
||||
return -ENOMEM;
|
||||
@ -307,46 +304,47 @@ nand_evb_init:
|
||||
|
||||
/* map physical address */
|
||||
ppchameleonevb_fio_base = ioremap(ppchameleonevb_fio_pbase, SZ_4M);
|
||||
if(!ppchameleonevb_fio_base) {
|
||||
if (!ppchameleonevb_fio_base) {
|
||||
printk("ioremap PPChameleonEVB NAND flash failed\n");
|
||||
kfree(ppchameleonevb_mtd);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Get pointer to private data */
|
||||
this = (struct nand_chip *) (&ppchameleonevb_mtd[1]);
|
||||
this = (struct nand_chip *)(&ppchameleonevb_mtd[1]);
|
||||
|
||||
/* Initialize structures */
|
||||
memset((char *) ppchameleonevb_mtd, 0, sizeof(struct mtd_info));
|
||||
memset((char *) this, 0, sizeof(struct nand_chip));
|
||||
memset(ppchameleonevb_mtd, 0, sizeof(struct mtd_info));
|
||||
memset(this, 0, sizeof(struct nand_chip));
|
||||
|
||||
/* Link the private data with the MTD structure */
|
||||
ppchameleonevb_mtd->priv = this;
|
||||
|
||||
/* Initialize GPIOs */
|
||||
/* Initialize GPIOs */
|
||||
/* Pin mapping for NAND chip */
|
||||
/*
|
||||
CE GPIO_14
|
||||
CLE GPIO_15
|
||||
ALE GPIO_16
|
||||
R/B GPIO_31
|
||||
*/
|
||||
CE GPIO_14
|
||||
CLE GPIO_15
|
||||
ALE GPIO_16
|
||||
R/B GPIO_31
|
||||
*/
|
||||
/* output select */
|
||||
out_be32((volatile unsigned*)GPIO0_OSRH, in_be32((volatile unsigned*)GPIO0_OSRH) & 0xFFFFFFF0);
|
||||
out_be32((volatile unsigned*)GPIO0_OSRL, in_be32((volatile unsigned*)GPIO0_OSRL) & 0x3FFFFFFF);
|
||||
out_be32((volatile unsigned *)GPIO0_OSRH, in_be32((volatile unsigned *)GPIO0_OSRH) & 0xFFFFFFF0);
|
||||
out_be32((volatile unsigned *)GPIO0_OSRL, in_be32((volatile unsigned *)GPIO0_OSRL) & 0x3FFFFFFF);
|
||||
/* three-state select */
|
||||
out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xFFFFFFF0);
|
||||
out_be32((volatile unsigned*)GPIO0_TSRL, in_be32((volatile unsigned*)GPIO0_TSRL) & 0x3FFFFFFF);
|
||||
out_be32((volatile unsigned *)GPIO0_TSRH, in_be32((volatile unsigned *)GPIO0_TSRH) & 0xFFFFFFF0);
|
||||
out_be32((volatile unsigned *)GPIO0_TSRL, in_be32((volatile unsigned *)GPIO0_TSRL) & 0x3FFFFFFF);
|
||||
/* enable output driver */
|
||||
out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) | NAND_EVB_nCE_GPIO_PIN |
|
||||
out_be32((volatile unsigned *)GPIO0_TCR, in_be32((volatile unsigned *)GPIO0_TCR) | NAND_EVB_nCE_GPIO_PIN |
|
||||
NAND_EVB_CLE_GPIO_PIN | NAND_EVB_ALE_GPIO_PIN);
|
||||
#ifdef USE_READY_BUSY_PIN
|
||||
/* three-state select */
|
||||
out_be32((volatile unsigned*)GPIO0_TSRL, in_be32((volatile unsigned*)GPIO0_TSRL) & 0xFFFFFFFC);
|
||||
out_be32((volatile unsigned *)GPIO0_TSRL, in_be32((volatile unsigned *)GPIO0_TSRL) & 0xFFFFFFFC);
|
||||
/* high-impedecence */
|
||||
out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) & (~NAND_EVB_RB_GPIO_PIN));
|
||||
out_be32((volatile unsigned *)GPIO0_TCR, in_be32((volatile unsigned *)GPIO0_TCR) & (~NAND_EVB_RB_GPIO_PIN));
|
||||
/* input select */
|
||||
out_be32((volatile unsigned*)GPIO0_ISR1L, (in_be32((volatile unsigned*)GPIO0_ISR1L) & 0xFFFFFFFC) | 0x00000001);
|
||||
out_be32((volatile unsigned *)GPIO0_ISR1L,
|
||||
(in_be32((volatile unsigned *)GPIO0_ISR1L) & 0xFFFFFFFC) | 0x00000001);
|
||||
#endif
|
||||
|
||||
/* insert callbacks */
|
||||
@ -362,22 +360,20 @@ nand_evb_init:
|
||||
this->eccmode = NAND_ECC_SOFT;
|
||||
|
||||
/* Scan to find existence of the device */
|
||||
if (nand_scan (ppchameleonevb_mtd, 1)) {
|
||||
if (nand_scan(ppchameleonevb_mtd, 1)) {
|
||||
iounmap((void *)ppchameleonevb_fio_base);
|
||||
kfree (ppchameleonevb_mtd);
|
||||
kfree(ppchameleonevb_mtd);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MTD_PARTITIONS
|
||||
ppchameleonevb_mtd->name = NAND_EVB_MTD_NAME;
|
||||
mtd_parts_nb = parse_mtd_partitions(ppchameleonevb_mtd, part_probes_evb, &mtd_parts, 0);
|
||||
if (mtd_parts_nb > 0)
|
||||
part_type = "command line";
|
||||
part_type = "command line";
|
||||
else
|
||||
mtd_parts_nb = 0;
|
||||
mtd_parts_nb = 0;
|
||||
#endif
|
||||
if (mtd_parts_nb == 0)
|
||||
{
|
||||
if (mtd_parts_nb == 0) {
|
||||
mtd_parts = partition_info_evb;
|
||||
mtd_parts_nb = NUM_PARTITIONS;
|
||||
part_type = "static";
|
||||
@ -390,18 +386,19 @@ nand_evb_init:
|
||||
/* Return happy */
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_init(ppchameleonevb_init);
|
||||
|
||||
/*
|
||||
* Clean up routine
|
||||
*/
|
||||
static void __exit ppchameleonevb_cleanup (void)
|
||||
static void __exit ppchameleonevb_cleanup(void)
|
||||
{
|
||||
struct nand_chip *this;
|
||||
|
||||
/* Release resources, unregister device(s) */
|
||||
nand_release (ppchameleon_mtd);
|
||||
nand_release (ppchameleonevb_mtd);
|
||||
nand_release(ppchameleon_mtd);
|
||||
nand_release(ppchameleonevb_mtd);
|
||||
|
||||
/* Release iomaps */
|
||||
this = (struct nand_chip *) &ppchameleon_mtd[1];
|
||||
|
@ -97,12 +97,12 @@ static struct mtd_info *rtc_from4_mtd = NULL;
|
||||
static void __iomem *rtc_from4_fio_base = (void *)P2SEGADDR(RTC_FROM4_FIO_BASE);
|
||||
|
||||
static const struct mtd_partition partition_info[] = {
|
||||
{
|
||||
.name = "Renesas flash partition 1",
|
||||
.offset = 0,
|
||||
.size = MTDPART_SIZ_FULL
|
||||
},
|
||||
{
|
||||
.name = "Renesas flash partition 1",
|
||||
.offset = 0,
|
||||
.size = MTDPART_SIZ_FULL},
|
||||
};
|
||||
|
||||
#define NUM_PARTITIONS 1
|
||||
|
||||
/*
|
||||
@ -111,8 +111,8 @@ static const struct mtd_partition partition_info[] = {
|
||||
* NAND_BBT_CREATE and/or NAND_BBT_WRITE
|
||||
*
|
||||
*/
|
||||
static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
|
||||
static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
|
||||
static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
|
||||
static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
|
||||
|
||||
static struct nand_bbt_descr rtc_from4_bbt_main_descr = {
|
||||
.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
|
||||
@ -134,8 +134,6 @@ static struct nand_bbt_descr rtc_from4_bbt_mirror_descr = {
|
||||
.pattern = mirror_pattern
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef RTC_FROM4_HWECC
|
||||
|
||||
/* the Reed Solomon control structure */
|
||||
@ -148,11 +146,11 @@ static struct nand_oobinfo rtc_from4_nand_oobinfo = {
|
||||
.useecc = MTD_NANDECC_AUTOPLACE,
|
||||
.eccbytes = 32,
|
||||
.eccpos = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23,
|
||||
24, 25, 26, 27, 28, 29, 30, 31},
|
||||
.oobfree = { {32, 32} }
|
||||
0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23,
|
||||
24, 25, 26, 27, 28, 29, 30, 31},
|
||||
.oobfree = {{32, 32}}
|
||||
};
|
||||
|
||||
/* Aargh. I missed the reversed bit order, when I
|
||||
@ -162,44 +160,42 @@ static struct nand_oobinfo rtc_from4_nand_oobinfo = {
|
||||
* of the ecc byte which we get from the FPGA
|
||||
*/
|
||||
static uint8_t revbits[256] = {
|
||||
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
|
||||
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
|
||||
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
|
||||
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
|
||||
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
|
||||
0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
|
||||
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
|
||||
0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
|
||||
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
|
||||
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
|
||||
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
|
||||
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
|
||||
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
|
||||
0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
|
||||
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
|
||||
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
|
||||
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
|
||||
0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
|
||||
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
|
||||
0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
|
||||
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
|
||||
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
|
||||
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
|
||||
0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
|
||||
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
|
||||
0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
|
||||
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
|
||||
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
|
||||
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
|
||||
0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
|
||||
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
|
||||
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
|
||||
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
|
||||
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
|
||||
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
|
||||
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
|
||||
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
|
||||
0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
|
||||
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
|
||||
0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
|
||||
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
|
||||
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
|
||||
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
|
||||
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
|
||||
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
|
||||
0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
|
||||
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
|
||||
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
|
||||
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
|
||||
0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
|
||||
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
|
||||
0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
|
||||
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
|
||||
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
|
||||
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
|
||||
0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
|
||||
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
|
||||
0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
|
||||
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
|
||||
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
|
||||
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
|
||||
0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
|
||||
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
|
||||
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* rtc_from4_hwcontrol - hardware specific access to control-lines
|
||||
* @mtd: MTD device structure
|
||||
@ -214,9 +210,9 @@ static uint8_t revbits[256] = {
|
||||
*/
|
||||
static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
{
|
||||
struct nand_chip* this = (struct nand_chip *) (mtd->priv);
|
||||
struct nand_chip *this = (struct nand_chip *)(mtd->priv);
|
||||
|
||||
switch(cmd) {
|
||||
switch (cmd) {
|
||||
|
||||
case NAND_CTL_SETCLE:
|
||||
this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_CLE);
|
||||
@ -240,7 +236,6 @@ static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* rtc_from4_nand_select_chip - hardware specific chip select
|
||||
* @mtd: MTD device structure
|
||||
@ -252,26 +247,25 @@ static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
*/
|
||||
static void rtc_from4_nand_select_chip(struct mtd_info *mtd, int chip)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
|
||||
this->IO_ADDR_R = (void __iomem *)((unsigned long)this->IO_ADDR_R & ~RTC_FROM4_NAND_ADDR_MASK);
|
||||
this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_NAND_ADDR_MASK);
|
||||
|
||||
switch(chip) {
|
||||
switch (chip) {
|
||||
|
||||
case 0: /* select slot 3 chip */
|
||||
case 0: /* select slot 3 chip */
|
||||
this->IO_ADDR_R = (void __iomem *)((unsigned long)this->IO_ADDR_R | RTC_FROM4_NAND_ADDR_SLOT3);
|
||||
this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_NAND_ADDR_SLOT3);
|
||||
break;
|
||||
case 1: /* select slot 4 chip */
|
||||
break;
|
||||
case 1: /* select slot 4 chip */
|
||||
this->IO_ADDR_R = (void __iomem *)((unsigned long)this->IO_ADDR_R | RTC_FROM4_NAND_ADDR_SLOT4);
|
||||
this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_NAND_ADDR_SLOT4);
|
||||
break;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* rtc_from4_nand_device_ready - hardware specific ready/busy check
|
||||
* @mtd: MTD device structure
|
||||
@ -290,7 +284,6 @@ static int rtc_from4_nand_device_ready(struct mtd_info *mtd)
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* deplete - code to perform device recovery in case there was a power loss
|
||||
* @mtd: MTD device structure
|
||||
@ -306,24 +299,23 @@ static int rtc_from4_nand_device_ready(struct mtd_info *mtd)
|
||||
*/
|
||||
static void deplete(struct mtd_info *mtd, int chip)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
|
||||
/* wait until device is ready */
|
||||
while (!this->dev_ready(mtd));
|
||||
/* wait until device is ready */
|
||||
while (!this->dev_ready(mtd)) ;
|
||||
|
||||
this->select_chip(mtd, chip);
|
||||
|
||||
/* Send the commands for device recovery, phase 1 */
|
||||
this->cmdfunc (mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0000);
|
||||
this->cmdfunc (mtd, NAND_CMD_DEPLETE2, -1, -1);
|
||||
this->cmdfunc(mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0000);
|
||||
this->cmdfunc(mtd, NAND_CMD_DEPLETE2, -1, -1);
|
||||
|
||||
/* Send the commands for device recovery, phase 2 */
|
||||
this->cmdfunc (mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0004);
|
||||
this->cmdfunc (mtd, NAND_CMD_DEPLETE2, -1, -1);
|
||||
this->cmdfunc(mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0004);
|
||||
this->cmdfunc(mtd, NAND_CMD_DEPLETE2, -1, -1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
#ifdef RTC_FROM4_HWECC
|
||||
/*
|
||||
* rtc_from4_enable_hwecc - hardware specific hardware ECC enable function
|
||||
@ -335,39 +327,35 @@ static void deplete(struct mtd_info *mtd, int chip)
|
||||
*/
|
||||
static void rtc_from4_enable_hwecc(struct mtd_info *mtd, int mode)
|
||||
{
|
||||
volatile unsigned short * rs_ecc_ctl = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC_CTL);
|
||||
volatile unsigned short *rs_ecc_ctl = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC_CTL);
|
||||
unsigned short status;
|
||||
|
||||
switch (mode) {
|
||||
case NAND_ECC_READ :
|
||||
status = RTC_FROM4_RS_ECC_CTL_CLR
|
||||
| RTC_FROM4_RS_ECC_CTL_FD_E;
|
||||
case NAND_ECC_READ:
|
||||
status = RTC_FROM4_RS_ECC_CTL_CLR | RTC_FROM4_RS_ECC_CTL_FD_E;
|
||||
|
||||
*rs_ecc_ctl = status;
|
||||
break;
|
||||
|
||||
case NAND_ECC_READSYN :
|
||||
status = 0x00;
|
||||
case NAND_ECC_READSYN:
|
||||
status = 0x00;
|
||||
|
||||
*rs_ecc_ctl = status;
|
||||
break;
|
||||
|
||||
case NAND_ECC_WRITE :
|
||||
status = RTC_FROM4_RS_ECC_CTL_CLR
|
||||
| RTC_FROM4_RS_ECC_CTL_GEN
|
||||
| RTC_FROM4_RS_ECC_CTL_FD_E;
|
||||
case NAND_ECC_WRITE:
|
||||
status = RTC_FROM4_RS_ECC_CTL_CLR | RTC_FROM4_RS_ECC_CTL_GEN | RTC_FROM4_RS_ECC_CTL_FD_E;
|
||||
|
||||
*rs_ecc_ctl = status;
|
||||
break;
|
||||
|
||||
default:
|
||||
default:
|
||||
BUG();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* rtc_from4_calculate_ecc - hardware specific code to read ECC code
|
||||
* @mtd: MTD device structure
|
||||
@ -383,7 +371,7 @@ static void rtc_from4_enable_hwecc(struct mtd_info *mtd, int mode)
|
||||
*/
|
||||
static void rtc_from4_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
|
||||
{
|
||||
volatile unsigned short * rs_eccn = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECCN);
|
||||
volatile unsigned short *rs_eccn = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECCN);
|
||||
unsigned short value;
|
||||
int i;
|
||||
|
||||
@ -395,7 +383,6 @@ static void rtc_from4_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_c
|
||||
ecc_code[7] |= 0x0f; /* set the last four bits (not used) */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* rtc_from4_correct_data - hardware specific code to correct data using ECC code
|
||||
* @mtd: MTD device structure
|
||||
@ -414,7 +401,7 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha
|
||||
unsigned short status;
|
||||
uint16_t par[6], syn[6];
|
||||
uint8_t ecc[8];
|
||||
volatile unsigned short *rs_ecc;
|
||||
volatile unsigned short *rs_ecc;
|
||||
|
||||
status = *((volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC_CHK));
|
||||
|
||||
@ -424,23 +411,18 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha
|
||||
|
||||
/* Read the syndrom pattern from the FPGA and correct the bitorder */
|
||||
rs_ecc = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC);
|
||||
for (i = 0; i < 8; i++) {
|
||||
ecc[i] = revbits[(*rs_ecc) & 0xFF];
|
||||
rs_ecc++;
|
||||
}
|
||||
for (i = 0; i < 8; i++) {
|
||||
ecc[i] = revbits[(*rs_ecc) & 0xFF];
|
||||
rs_ecc++;
|
||||
}
|
||||
|
||||
/* convert into 6 10bit syndrome fields */
|
||||
par[5] = rs_decoder->index_of[(((uint16_t)ecc[0] >> 0) & 0x0ff) |
|
||||
(((uint16_t)ecc[1] << 8) & 0x300)];
|
||||
par[4] = rs_decoder->index_of[(((uint16_t)ecc[1] >> 2) & 0x03f) |
|
||||
(((uint16_t)ecc[2] << 6) & 0x3c0)];
|
||||
par[3] = rs_decoder->index_of[(((uint16_t)ecc[2] >> 4) & 0x00f) |
|
||||
(((uint16_t)ecc[3] << 4) & 0x3f0)];
|
||||
par[2] = rs_decoder->index_of[(((uint16_t)ecc[3] >> 6) & 0x003) |
|
||||
(((uint16_t)ecc[4] << 2) & 0x3fc)];
|
||||
par[1] = rs_decoder->index_of[(((uint16_t)ecc[5] >> 0) & 0x0ff) |
|
||||
(((uint16_t)ecc[6] << 8) & 0x300)];
|
||||
par[0] = (((uint16_t)ecc[6] >> 2) & 0x03f) | (((uint16_t)ecc[7] << 6) & 0x3c0);
|
||||
par[5] = rs_decoder->index_of[(((uint16_t) ecc[0] >> 0) & 0x0ff) | (((uint16_t) ecc[1] << 8) & 0x300)];
|
||||
par[4] = rs_decoder->index_of[(((uint16_t) ecc[1] >> 2) & 0x03f) | (((uint16_t) ecc[2] << 6) & 0x3c0)];
|
||||
par[3] = rs_decoder->index_of[(((uint16_t) ecc[2] >> 4) & 0x00f) | (((uint16_t) ecc[3] << 4) & 0x3f0)];
|
||||
par[2] = rs_decoder->index_of[(((uint16_t) ecc[3] >> 6) & 0x003) | (((uint16_t) ecc[4] << 2) & 0x3fc)];
|
||||
par[1] = rs_decoder->index_of[(((uint16_t) ecc[5] >> 0) & 0x0ff) | (((uint16_t) ecc[6] << 8) & 0x300)];
|
||||
par[0] = (((uint16_t) ecc[6] >> 2) & 0x03f) | (((uint16_t) ecc[7] << 6) & 0x3c0);
|
||||
|
||||
/* Convert to computable syndrome */
|
||||
for (i = 0; i < 6; i++) {
|
||||
@ -453,16 +435,14 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha
|
||||
syn[i] = rs_decoder->index_of[syn[i]];
|
||||
}
|
||||
|
||||
/* Let the library code do its magic.*/
|
||||
res = decode_rs8(rs_decoder, (uint8_t *)buf, par, 512, syn, 0, NULL, 0xff, NULL);
|
||||
/* Let the library code do its magic. */
|
||||
res = decode_rs8(rs_decoder, (uint8_t *) buf, par, 512, syn, 0, NULL, 0xff, NULL);
|
||||
if (res > 0) {
|
||||
DEBUG (MTD_DEBUG_LEVEL0, "rtc_from4_correct_data: "
|
||||
"ECC corrected %d errors on read\n", res);
|
||||
DEBUG(MTD_DEBUG_LEVEL0, "rtc_from4_correct_data: " "ECC corrected %d errors on read\n", res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* rtc_from4_errstat - perform additional error status checks
|
||||
* @mtd: MTD device structure
|
||||
@ -480,44 +460,44 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha
|
||||
*/
|
||||
static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page)
|
||||
{
|
||||
int er_stat=0;
|
||||
int rtn, retlen;
|
||||
size_t len;
|
||||
int er_stat = 0;
|
||||
int rtn, retlen;
|
||||
size_t len;
|
||||
uint8_t *buf;
|
||||
int i;
|
||||
int i;
|
||||
|
||||
this->cmdfunc (mtd, NAND_CMD_STATUS_CLEAR, -1, -1);
|
||||
this->cmdfunc(mtd, NAND_CMD_STATUS_CLEAR, -1, -1);
|
||||
|
||||
if (state == FL_ERASING) {
|
||||
for (i=0; i<4; i++) {
|
||||
if (status & 1<<(i+1)) {
|
||||
this->cmdfunc (mtd, (NAND_CMD_STATUS_ERROR + i + 1), -1, -1);
|
||||
if (state == FL_ERASING) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (status & 1 << (i + 1)) {
|
||||
this->cmdfunc(mtd, (NAND_CMD_STATUS_ERROR + i + 1), -1, -1);
|
||||
rtn = this->read_byte(mtd);
|
||||
this->cmdfunc (mtd, NAND_CMD_STATUS_RESET, -1, -1);
|
||||
this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1);
|
||||
if (!(rtn & ERR_STAT_ECC_AVAILABLE)) {
|
||||
er_stat |= 1<<(i+1); /* err_ecc_not_avail */
|
||||
er_stat |= 1 << (i + 1); /* err_ecc_not_avail */
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (state == FL_WRITING) {
|
||||
/* single bank write logic */
|
||||
this->cmdfunc (mtd, NAND_CMD_STATUS_ERROR, -1, -1);
|
||||
this->cmdfunc(mtd, NAND_CMD_STATUS_ERROR, -1, -1);
|
||||
rtn = this->read_byte(mtd);
|
||||
this->cmdfunc (mtd, NAND_CMD_STATUS_RESET, -1, -1);
|
||||
this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1);
|
||||
if (!(rtn & ERR_STAT_ECC_AVAILABLE)) {
|
||||
er_stat |= 1<<1; /* err_ecc_not_avail */
|
||||
er_stat |= 1 << 1; /* err_ecc_not_avail */
|
||||
} else {
|
||||
len = mtd->oobblock;
|
||||
buf = kmalloc (len, GFP_KERNEL);
|
||||
buf = kmalloc(len, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
printk (KERN_ERR "rtc_from4_errstat: Out of memory!\n");
|
||||
er_stat = 1; /* if we can't check, assume failed */
|
||||
printk(KERN_ERR "rtc_from4_errstat: Out of memory!\n");
|
||||
er_stat = 1; /* if we can't check, assume failed */
|
||||
} else {
|
||||
/* recovery read */
|
||||
/* page read */
|
||||
rtn = nand_do_read_ecc (mtd, page, len, &retlen, buf, NULL, this->autooob, 1);
|
||||
rtn = nand_do_read_ecc(mtd, page, len, &retlen, buf, NULL, this->autooob, 1);
|
||||
if (rtn) { /* if read failed or > 1-bit error corrected */
|
||||
er_stat |= 1<<1; /* ECC read failed */
|
||||
er_stat |= 1 << 1; /* ECC read failed */
|
||||
}
|
||||
kfree(buf);
|
||||
}
|
||||
@ -525,7 +505,7 @@ static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, int s
|
||||
}
|
||||
|
||||
rtn = status;
|
||||
if (er_stat == 0) { /* if ECC is available */
|
||||
if (er_stat == 0) { /* if ECC is available */
|
||||
rtn = (status & ~NAND_STATUS_FAIL); /* clear the error bit */
|
||||
}
|
||||
|
||||
@ -533,30 +513,28 @@ static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, int s
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Main initialization routine
|
||||
*/
|
||||
int __init rtc_from4_init (void)
|
||||
int __init rtc_from4_init(void)
|
||||
{
|
||||
struct nand_chip *this;
|
||||
unsigned short bcr1, bcr2, wcr2;
|
||||
int i;
|
||||
|
||||
/* Allocate memory for MTD device structure and private data */
|
||||
rtc_from4_mtd = kmalloc(sizeof(struct mtd_info) + sizeof (struct nand_chip),
|
||||
GFP_KERNEL);
|
||||
rtc_from4_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
|
||||
if (!rtc_from4_mtd) {
|
||||
printk ("Unable to allocate Renesas NAND MTD device structure.\n");
|
||||
printk("Unable to allocate Renesas NAND MTD device structure.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Get pointer to private data */
|
||||
this = (struct nand_chip *) (&rtc_from4_mtd[1]);
|
||||
this = (struct nand_chip *)(&rtc_from4_mtd[1]);
|
||||
|
||||
/* Initialize structures */
|
||||
memset((char *) rtc_from4_mtd, 0, sizeof(struct mtd_info));
|
||||
memset((char *) this, 0, sizeof(struct nand_chip));
|
||||
memset(rtc_from4_mtd, 0, sizeof(struct mtd_info));
|
||||
memset(this, 0, sizeof(struct nand_chip));
|
||||
|
||||
/* Link the private data with the MTD structure */
|
||||
rtc_from4_mtd->priv = this;
|
||||
@ -582,7 +560,7 @@ int __init rtc_from4_init (void)
|
||||
/* Set address of hardware control function */
|
||||
this->hwcontrol = rtc_from4_hwcontrol;
|
||||
/* Set address of chip select function */
|
||||
this->select_chip = rtc_from4_nand_select_chip;
|
||||
this->select_chip = rtc_from4_nand_select_chip;
|
||||
/* command delay time (in us) */
|
||||
this->chip_delay = 100;
|
||||
/* return the status of the Ready/Busy line */
|
||||
@ -591,7 +569,7 @@ int __init rtc_from4_init (void)
|
||||
#ifdef RTC_FROM4_HWECC
|
||||
printk(KERN_INFO "rtc_from4_init: using hardware ECC detection.\n");
|
||||
|
||||
this->eccmode = NAND_ECC_HW8_512;
|
||||
this->eccmode = NAND_ECC_HW8_512;
|
||||
this->options |= NAND_HWECC_SYNDROME;
|
||||
/* return the status of extra status and ECC checks */
|
||||
this->errstat = rtc_from4_errstat;
|
||||
@ -617,7 +595,7 @@ int __init rtc_from4_init (void)
|
||||
}
|
||||
|
||||
/* Perform 'device recovery' for each chip in case there was a power loss. */
|
||||
for (i=0; i < this->numchips; i++) {
|
||||
for (i = 0; i < this->numchips; i++) {
|
||||
deplete(rtc_from4_mtd, i);
|
||||
}
|
||||
|
||||
@ -643,7 +621,7 @@ int __init rtc_from4_init (void)
|
||||
*/
|
||||
rs_decoder = init_rs(10, 0x409, 0, 1, 6);
|
||||
if (!rs_decoder) {
|
||||
printk (KERN_ERR "Could not create a RS decoder\n");
|
||||
printk(KERN_ERR "Could not create a RS decoder\n");
|
||||
nand_release(rtc_from4_mtd);
|
||||
kfree(rtc_from4_mtd);
|
||||
return -ENOMEM;
|
||||
@ -652,20 +630,20 @@ int __init rtc_from4_init (void)
|
||||
/* Return happy */
|
||||
return 0;
|
||||
}
|
||||
module_init(rtc_from4_init);
|
||||
|
||||
module_init(rtc_from4_init);
|
||||
|
||||
/*
|
||||
* Clean up routine
|
||||
*/
|
||||
#ifdef MODULE
|
||||
static void __exit rtc_from4_cleanup (void)
|
||||
static void __exit rtc_from4_cleanup(void)
|
||||
{
|
||||
/* Release resource, unregister partitions */
|
||||
nand_release(rtc_from4_mtd);
|
||||
|
||||
/* Free the MTD device structure */
|
||||
kfree (rtc_from4_mtd);
|
||||
kfree(rtc_from4_mtd);
|
||||
|
||||
#ifdef RTC_FROM4_HWECC
|
||||
/* Free the reed solomon resources */
|
||||
@ -674,10 +652,10 @@ static void __exit rtc_from4_cleanup (void)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
module_exit(rtc_from4_cleanup);
|
||||
#endif
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("d.marlin <dmarlin@redhat.com");
|
||||
MODULE_DESCRIPTION("Board-specific glue layer for AG-AND flash on Renesas FROM_BOARD4");
|
||||
|
||||
|
@ -77,10 +77,10 @@ static int hardware_ecc = 0;
|
||||
*/
|
||||
|
||||
static struct nand_oobinfo nand_hw_eccoob = {
|
||||
.useecc = MTD_NANDECC_AUTOPLACE,
|
||||
.eccbytes = 3,
|
||||
.eccpos = {0, 1, 2 },
|
||||
.oobfree = { {8, 8} }
|
||||
.useecc = MTD_NANDECC_AUTOPLACE,
|
||||
.eccbytes = 3,
|
||||
.eccpos = {0, 1, 2},
|
||||
.oobfree = {{8, 8}}
|
||||
};
|
||||
|
||||
/* controller and mtd information */
|
||||
@ -149,8 +149,7 @@ static int s3c2410_nand_calc_rate(int wanted, unsigned long clk, int max)
|
||||
pr_debug("result %d from %ld, %d\n", result, clk, wanted);
|
||||
|
||||
if (result > max) {
|
||||
printk("%d ns is too big for current clock rate %ld\n",
|
||||
wanted, clk);
|
||||
printk("%d ns is too big for current clock rate %ld\n", wanted, clk);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -164,8 +163,7 @@ static int s3c2410_nand_calc_rate(int wanted, unsigned long clk, int max)
|
||||
|
||||
/* controller setup */
|
||||
|
||||
static int s3c2410_nand_inithw(struct s3c2410_nand_info *info,
|
||||
struct platform_device *pdev)
|
||||
static int s3c2410_nand_inithw(struct s3c2410_nand_info *info, struct platform_device *pdev)
|
||||
{
|
||||
struct s3c2410_platform_nand *plat = to_nand_plat(pdev);
|
||||
unsigned long clkrate = clk_get_rate(info->clk);
|
||||
@ -177,7 +175,7 @@ static int s3c2410_nand_inithw(struct s3c2410_nand_info *info,
|
||||
clkrate /= 1000; /* turn clock into kHz for ease of use */
|
||||
|
||||
if (plat != NULL) {
|
||||
tacls = s3c2410_nand_calc_rate(plat->tacls, clkrate, 4);
|
||||
tacls = s3c2410_nand_calc_rate(plat->tacls, clkrate, 4);
|
||||
twrph0 = s3c2410_nand_calc_rate(plat->twrph0, clkrate, 8);
|
||||
twrph1 = s3c2410_nand_calc_rate(plat->twrph1, clkrate, 8);
|
||||
} else {
|
||||
@ -193,19 +191,17 @@ static int s3c2410_nand_inithw(struct s3c2410_nand_info *info,
|
||||
}
|
||||
|
||||
printk(KERN_INFO PFX "Tacls=%d, %dns Twrph0=%d %dns, Twrph1=%d %dns\n",
|
||||
tacls, to_ns(tacls, clkrate),
|
||||
twrph0, to_ns(twrph0, clkrate),
|
||||
twrph1, to_ns(twrph1, clkrate));
|
||||
tacls, to_ns(tacls, clkrate), twrph0, to_ns(twrph0, clkrate), twrph1, to_ns(twrph1, clkrate));
|
||||
|
||||
if (!info->is_s3c2440) {
|
||||
cfg = S3C2410_NFCONF_EN;
|
||||
cfg |= S3C2410_NFCONF_TACLS(tacls-1);
|
||||
cfg |= S3C2410_NFCONF_TWRPH0(twrph0-1);
|
||||
cfg |= S3C2410_NFCONF_TWRPH1(twrph1-1);
|
||||
cfg = S3C2410_NFCONF_EN;
|
||||
cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
|
||||
cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
|
||||
cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
|
||||
} else {
|
||||
cfg = S3C2440_NFCONF_TACLS(tacls-1);
|
||||
cfg |= S3C2440_NFCONF_TWRPH0(twrph0-1);
|
||||
cfg |= S3C2440_NFCONF_TWRPH1(twrph1-1);
|
||||
cfg = S3C2440_NFCONF_TACLS(tacls - 1);
|
||||
cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
|
||||
cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
|
||||
}
|
||||
|
||||
pr_debug(PFX "NF_CONF is 0x%lx\n", cfg);
|
||||
@ -229,7 +225,7 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
|
||||
info = nmtd->info;
|
||||
|
||||
bit = (info->is_s3c2440) ? S3C2440_NFCONT_nFCE : S3C2410_NFCONF_nFCE;
|
||||
reg = info->regs+((info->is_s3c2440) ? S3C2440_NFCONT:S3C2410_NFCONF);
|
||||
reg = info->regs + ((info->is_s3c2440) ? S3C2440_NFCONT : S3C2410_NFCONF);
|
||||
|
||||
cur = readl(reg);
|
||||
|
||||
@ -243,7 +239,7 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
|
||||
|
||||
if (info->platform != NULL) {
|
||||
if (info->platform->select_chip != NULL)
|
||||
(info->platform->select_chip)(nmtd->set, chip);
|
||||
(info->platform->select_chip) (nmtd->set, chip);
|
||||
}
|
||||
|
||||
cur &= ~bit;
|
||||
@ -330,22 +326,16 @@ static int s3c2410_nand_devready(struct mtd_info *mtd)
|
||||
return readb(info->regs + S3C2410_NFSTAT) & S3C2410_NFSTAT_BUSY;
|
||||
}
|
||||
|
||||
|
||||
/* ECC handling functions */
|
||||
|
||||
static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
|
||||
u_char *read_ecc, u_char *calc_ecc)
|
||||
static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
|
||||
{
|
||||
pr_debug("s3c2410_nand_correct_data(%p,%p,%p,%p)\n",
|
||||
mtd, dat, read_ecc, calc_ecc);
|
||||
pr_debug("s3c2410_nand_correct_data(%p,%p,%p,%p)\n", mtd, dat, read_ecc, calc_ecc);
|
||||
|
||||
pr_debug("eccs: read %02x,%02x,%02x vs calc %02x,%02x,%02x\n",
|
||||
read_ecc[0], read_ecc[1], read_ecc[2],
|
||||
calc_ecc[0], calc_ecc[1], calc_ecc[2]);
|
||||
read_ecc[0], read_ecc[1], read_ecc[2], calc_ecc[0], calc_ecc[1], calc_ecc[2]);
|
||||
|
||||
if (read_ecc[0] == calc_ecc[0] &&
|
||||
read_ecc[1] == calc_ecc[1] &&
|
||||
read_ecc[2] == calc_ecc[2])
|
||||
if (read_ecc[0] == calc_ecc[0] && read_ecc[1] == calc_ecc[1] && read_ecc[2] == calc_ecc[2])
|
||||
return 0;
|
||||
|
||||
/* we curently have no method for correcting the error */
|
||||
@ -378,8 +368,7 @@ static void s3c2440_nand_enable_hwecc(struct mtd_info *mtd, int mode)
|
||||
writel(ctrl | S3C2440_NFCONT_INITECC, info->regs + S3C2440_NFCONT);
|
||||
}
|
||||
|
||||
static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd,
|
||||
const u_char *dat, u_char *ecc_code)
|
||||
static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
|
||||
{
|
||||
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
|
||||
|
||||
@ -387,15 +376,12 @@ static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd,
|
||||
ecc_code[1] = readb(info->regs + S3C2410_NFECC + 1);
|
||||
ecc_code[2] = readb(info->regs + S3C2410_NFECC + 2);
|
||||
|
||||
pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n",
|
||||
ecc_code[0], ecc_code[1], ecc_code[2]);
|
||||
pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n", ecc_code[0], ecc_code[1], ecc_code[2]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd,
|
||||
const u_char *dat, u_char *ecc_code)
|
||||
static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
|
||||
{
|
||||
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
|
||||
unsigned long ecc = readl(info->regs + S3C2440_NFMECC0);
|
||||
@ -404,13 +390,11 @@ static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd,
|
||||
ecc_code[1] = ecc >> 8;
|
||||
ecc_code[2] = ecc >> 16;
|
||||
|
||||
pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n",
|
||||
ecc_code[0], ecc_code[1], ecc_code[2]);
|
||||
pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n", ecc_code[0], ecc_code[1], ecc_code[2]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* over-ride the standard functions for a little more speed. We can
|
||||
* use read/write block to move the data buffers to/from the controller
|
||||
*/
|
||||
@ -421,8 +405,7 @@ static void s3c2410_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
|
||||
readsb(this->IO_ADDR_R, buf, len);
|
||||
}
|
||||
|
||||
static void s3c2410_nand_write_buf(struct mtd_info *mtd,
|
||||
const u_char *buf, int len)
|
||||
static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
writesb(this->IO_ADDR_W, buf, len);
|
||||
@ -488,9 +471,7 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
|
||||
return add_mtd_device(&mtd->mtd);
|
||||
|
||||
if (set->nr_partitions > 0 && set->partitions != NULL) {
|
||||
return add_mtd_partitions(&mtd->mtd,
|
||||
set->partitions,
|
||||
set->nr_partitions);
|
||||
return add_mtd_partitions(&mtd->mtd, set->partitions, set->nr_partitions);
|
||||
}
|
||||
|
||||
return add_mtd_device(&mtd->mtd);
|
||||
@ -654,13 +635,11 @@ static int s3c24xx_nand_probe(struct platform_device *pdev, int is_s3c2440)
|
||||
nmtd = info->mtds;
|
||||
|
||||
for (setno = 0; setno < nr_sets; setno++, nmtd++) {
|
||||
pr_debug("initialising set %d (%p, info %p)\n",
|
||||
setno, nmtd, info);
|
||||
pr_debug("initialising set %d (%p, info %p)\n", setno, nmtd, info);
|
||||
|
||||
s3c2410_nand_init_chip(info, nmtd, sets);
|
||||
|
||||
nmtd->scan_res = nand_scan(&nmtd->mtd,
|
||||
(sets) ? sets->nr_chips : 1);
|
||||
nmtd->scan_res = nand_scan(&nmtd->mtd, (sets) ? sets->nr_chips : 1);
|
||||
|
||||
if (nmtd->scan_res == 0) {
|
||||
s3c2410_nand_add_partition(info, nmtd, sets);
|
||||
|
@ -46,7 +46,6 @@ static int sharpsl_phys_base = 0x0C000000;
|
||||
#define FLCLE (1 << 1)
|
||||
#define FLCE0 (1 << 0)
|
||||
|
||||
|
||||
/*
|
||||
* MTD structure for SharpSL
|
||||
*/
|
||||
@ -60,27 +59,26 @@ static struct mtd_info *sharpsl_mtd = NULL;
|
||||
static int nr_partitions;
|
||||
static struct mtd_partition sharpsl_nand_default_partition_info[] = {
|
||||
{
|
||||
.name = "System Area",
|
||||
.offset = 0,
|
||||
.size = 7 * 1024 * 1024,
|
||||
},
|
||||
.name = "System Area",
|
||||
.offset = 0,
|
||||
.size = 7 * 1024 * 1024,
|
||||
},
|
||||
{
|
||||
.name = "Root Filesystem",
|
||||
.offset = 7 * 1024 * 1024,
|
||||
.size = 30 * 1024 * 1024,
|
||||
},
|
||||
.name = "Root Filesystem",
|
||||
.offset = 7 * 1024 * 1024,
|
||||
.size = 30 * 1024 * 1024,
|
||||
},
|
||||
{
|
||||
.name = "Home Filesystem",
|
||||
.offset = MTDPART_OFS_APPEND ,
|
||||
.size = MTDPART_SIZ_FULL ,
|
||||
},
|
||||
.name = "Home Filesystem",
|
||||
.offset = MTDPART_OFS_APPEND,
|
||||
.size = MTDPART_SIZ_FULL,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* hardware specific access to control-lines
|
||||
*/
|
||||
static void
|
||||
sharpsl_nand_hwcontrol(struct mtd_info* mtd, int cmd)
|
||||
static void sharpsl_nand_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
{
|
||||
switch (cmd) {
|
||||
case NAND_CTL_SETCLE:
|
||||
@ -98,10 +96,10 @@ sharpsl_nand_hwcontrol(struct mtd_info* mtd, int cmd)
|
||||
break;
|
||||
|
||||
case NAND_CTL_SETNCE:
|
||||
writeb(readb(FLASHCTL) & ~(FLCE0|FLCE1), FLASHCTL);
|
||||
writeb(readb(FLASHCTL) & ~(FLCE0 | FLCE1), FLASHCTL);
|
||||
break;
|
||||
case NAND_CTL_CLRNCE:
|
||||
writeb(readb(FLASHCTL) | (FLCE0|FLCE1), FLASHCTL);
|
||||
writeb(readb(FLASHCTL) | (FLCE0 | FLCE1), FLASHCTL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -126,27 +124,23 @@ static struct nand_oobinfo akita_oobinfo = {
|
||||
.useecc = MTD_NANDECC_AUTOPLACE,
|
||||
.eccbytes = 24,
|
||||
.eccpos = {
|
||||
0x5, 0x1, 0x2, 0x3, 0x6, 0x7, 0x15, 0x11,
|
||||
0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23,
|
||||
0x26, 0x27, 0x35, 0x31, 0x32, 0x33, 0x36, 0x37},
|
||||
.oobfree = { {0x08, 0x09} }
|
||||
0x5, 0x1, 0x2, 0x3, 0x6, 0x7, 0x15, 0x11,
|
||||
0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23,
|
||||
0x26, 0x27, 0x35, 0x31, 0x32, 0x33, 0x36, 0x37},
|
||||
.oobfree = {{0x08, 0x09}}
|
||||
};
|
||||
|
||||
static int
|
||||
sharpsl_nand_dev_ready(struct mtd_info* mtd)
|
||||
static int sharpsl_nand_dev_ready(struct mtd_info *mtd)
|
||||
{
|
||||
return !((readb(FLASHCTL) & FLRYBY) == 0);
|
||||
}
|
||||
|
||||
static void
|
||||
sharpsl_nand_enable_hwecc(struct mtd_info* mtd, int mode)
|
||||
static void sharpsl_nand_enable_hwecc(struct mtd_info *mtd, int mode)
|
||||
{
|
||||
writeb(0 ,ECCCLRR);
|
||||
writeb(0, ECCCLRR);
|
||||
}
|
||||
|
||||
static int
|
||||
sharpsl_nand_calculate_ecc(struct mtd_info* mtd, const u_char* dat,
|
||||
u_char* ecc_code)
|
||||
static int sharpsl_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat, u_char * ecc_code)
|
||||
{
|
||||
ecc_code[0] = ~readb(ECCLPUB);
|
||||
ecc_code[1] = ~readb(ECCLPLB);
|
||||
@ -154,44 +148,40 @@ sharpsl_nand_calculate_ecc(struct mtd_info* mtd, const u_char* dat,
|
||||
return readb(ECCCNTR) != 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_MTD_PARTITIONS
|
||||
const char *part_probes[] = { "cmdlinepart", NULL };
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Main initialization routine
|
||||
*/
|
||||
int __init
|
||||
sharpsl_nand_init(void)
|
||||
int __init sharpsl_nand_init(void)
|
||||
{
|
||||
struct nand_chip *this;
|
||||
struct mtd_partition* sharpsl_partition_info;
|
||||
struct mtd_partition *sharpsl_partition_info;
|
||||
int err = 0;
|
||||
|
||||
/* Allocate memory for MTD device structure and private data */
|
||||
sharpsl_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip),
|
||||
GFP_KERNEL);
|
||||
sharpsl_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
|
||||
if (!sharpsl_mtd) {
|
||||
printk ("Unable to allocate SharpSL NAND MTD device structure.\n");
|
||||
printk("Unable to allocate SharpSL NAND MTD device structure.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* map physical adress */
|
||||
sharpsl_io_base = ioremap(sharpsl_phys_base, 0x1000);
|
||||
if(!sharpsl_io_base){
|
||||
if (!sharpsl_io_base) {
|
||||
printk("ioremap to access Sharp SL NAND chip failed\n");
|
||||
kfree(sharpsl_mtd);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Get pointer to private data */
|
||||
this = (struct nand_chip *) (&sharpsl_mtd[1]);
|
||||
this = (struct nand_chip *)(&sharpsl_mtd[1]);
|
||||
|
||||
/* Initialize structures */
|
||||
memset((char *) sharpsl_mtd, 0, sizeof(struct mtd_info));
|
||||
memset((char *) this, 0, sizeof(struct nand_chip));
|
||||
memset(sharpsl_mtd, 0, sizeof(struct mtd_info));
|
||||
memset(this, 0, sizeof(struct nand_chip));
|
||||
|
||||
/* Link the private data with the MTD structure */
|
||||
sharpsl_mtd->priv = this;
|
||||
@ -221,7 +211,7 @@ sharpsl_nand_init(void)
|
||||
this->correct_data = nand_correct_data;
|
||||
|
||||
/* Scan to find existence of the device */
|
||||
err=nand_scan(sharpsl_mtd,1);
|
||||
err = nand_scan(sharpsl_mtd, 1);
|
||||
if (err) {
|
||||
iounmap(sharpsl_io_base);
|
||||
kfree(sharpsl_mtd);
|
||||
@ -230,24 +220,23 @@ sharpsl_nand_init(void)
|
||||
|
||||
/* Register the partitions */
|
||||
sharpsl_mtd->name = "sharpsl-nand";
|
||||
nr_partitions = parse_mtd_partitions(sharpsl_mtd, part_probes,
|
||||
&sharpsl_partition_info, 0);
|
||||
nr_partitions = parse_mtd_partitions(sharpsl_mtd, part_probes, &sharpsl_partition_info, 0);
|
||||
|
||||
if (nr_partitions <= 0) {
|
||||
nr_partitions = DEFAULT_NUM_PARTITIONS;
|
||||
sharpsl_partition_info = sharpsl_nand_default_partition_info;
|
||||
if (machine_is_poodle()) {
|
||||
sharpsl_partition_info[1].size=22 * 1024 * 1024;
|
||||
sharpsl_partition_info[1].size = 22 * 1024 * 1024;
|
||||
} else if (machine_is_corgi() || machine_is_shepherd()) {
|
||||
sharpsl_partition_info[1].size=25 * 1024 * 1024;
|
||||
sharpsl_partition_info[1].size = 25 * 1024 * 1024;
|
||||
} else if (machine_is_husky()) {
|
||||
sharpsl_partition_info[1].size=53 * 1024 * 1024;
|
||||
sharpsl_partition_info[1].size = 53 * 1024 * 1024;
|
||||
} else if (machine_is_spitz()) {
|
||||
sharpsl_partition_info[1].size=5 * 1024 * 1024;
|
||||
sharpsl_partition_info[1].size = 5 * 1024 * 1024;
|
||||
} else if (machine_is_akita()) {
|
||||
sharpsl_partition_info[1].size=58 * 1024 * 1024;
|
||||
sharpsl_partition_info[1].size = 58 * 1024 * 1024;
|
||||
} else if (machine_is_borzoi()) {
|
||||
sharpsl_partition_info[1].size=32 * 1024 * 1024;
|
||||
sharpsl_partition_info[1].size = 32 * 1024 * 1024;
|
||||
}
|
||||
}
|
||||
|
||||
@ -261,6 +250,7 @@ sharpsl_nand_init(void)
|
||||
/* Return happy */
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_init(sharpsl_nand_init);
|
||||
|
||||
/*
|
||||
@ -269,7 +259,7 @@ module_init(sharpsl_nand_init);
|
||||
#ifdef MODULE
|
||||
static void __exit sharpsl_nand_cleanup(void)
|
||||
{
|
||||
struct nand_chip *this = (struct nand_chip *) &sharpsl_mtd[1];
|
||||
struct nand_chip *this = (struct nand_chip *)&sharpsl_mtd[1];
|
||||
|
||||
/* Release resources, unregister device */
|
||||
nand_release(sharpsl_mtd);
|
||||
@ -279,6 +269,7 @@ static void __exit sharpsl_nand_cleanup(void)
|
||||
/* Free the MTD device structure */
|
||||
kfree(sharpsl_mtd);
|
||||
}
|
||||
|
||||
module_exit(sharpsl_nand_cleanup);
|
||||
#endif
|
||||
|
||||
|
@ -39,16 +39,16 @@ static struct mtd_info *spia_mtd = NULL;
|
||||
*/
|
||||
#define SPIA_IO_BASE 0xd0000000 /* Start of EP7212 IO address space */
|
||||
#define SPIA_FIO_BASE 0xf0000000 /* Address where flash is mapped */
|
||||
#define SPIA_PEDR 0x0080 /*
|
||||
* IO offset to Port E data register
|
||||
* where the CLE, ALE and NCE pins
|
||||
* are wired to.
|
||||
*/
|
||||
#define SPIA_PEDDR 0x00c0 /*
|
||||
* IO offset to Port E data direction
|
||||
* register so we can control the IO
|
||||
* lines.
|
||||
*/
|
||||
#define SPIA_PEDR 0x0080 /*
|
||||
* IO offset to Port E data register
|
||||
* where the CLE, ALE and NCE pins
|
||||
* are wired to.
|
||||
*/
|
||||
#define SPIA_PEDDR 0x00c0 /*
|
||||
* IO offset to Port E data direction
|
||||
* register so we can control the IO
|
||||
* lines.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Module stuff
|
||||
@ -69,25 +69,23 @@ module_param(spia_peddr, int, 0);
|
||||
*/
|
||||
static const struct mtd_partition partition_info[] = {
|
||||
{
|
||||
.name = "SPIA flash partition 1",
|
||||
.offset = 0,
|
||||
.size = 2*1024*1024
|
||||
},
|
||||
.name = "SPIA flash partition 1",
|
||||
.offset = 0,
|
||||
.size = 2 * 1024 * 1024},
|
||||
{
|
||||
.name = "SPIA flash partition 2",
|
||||
.offset = 2*1024*1024,
|
||||
.size = 6*1024*1024
|
||||
}
|
||||
.name = "SPIA flash partition 2",
|
||||
.offset = 2 * 1024 * 1024,
|
||||
.size = 6 * 1024 * 1024}
|
||||
};
|
||||
#define NUM_PARTITIONS 2
|
||||
|
||||
#define NUM_PARTITIONS 2
|
||||
|
||||
/*
|
||||
* hardware specific access to control-lines
|
||||
*/
|
||||
static void spia_hwcontrol(struct mtd_info *mtd, int cmd){
|
||||
|
||||
switch(cmd){
|
||||
static void spia_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
{
|
||||
switch (cmd) {
|
||||
|
||||
case NAND_CTL_SETCLE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) |= 0x01; break;
|
||||
case NAND_CTL_CLRCLE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) &= ~0x01; break;
|
||||
@ -97,30 +95,29 @@ static void spia_hwcontrol(struct mtd_info *mtd, int cmd){
|
||||
|
||||
case NAND_CTL_SETNCE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) &= ~0x04; break;
|
||||
case NAND_CTL_CLRNCE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) |= 0x04; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Main initialization routine
|
||||
*/
|
||||
int __init spia_init (void)
|
||||
int __init spia_init(void)
|
||||
{
|
||||
struct nand_chip *this;
|
||||
|
||||
/* Allocate memory for MTD device structure and private data */
|
||||
spia_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
|
||||
GFP_KERNEL);
|
||||
spia_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
|
||||
if (!spia_mtd) {
|
||||
printk ("Unable to allocate SPIA NAND MTD device structure.\n");
|
||||
printk("Unable to allocate SPIA NAND MTD device structure.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Get pointer to private data */
|
||||
this = (struct nand_chip *) (&spia_mtd[1]);
|
||||
this = (struct nand_chip *)(&spia_mtd[1]);
|
||||
|
||||
/* Initialize structures */
|
||||
memset((char *) spia_mtd, 0, sizeof(struct mtd_info));
|
||||
memset((char *) this, 0, sizeof(struct nand_chip));
|
||||
memset(spia_mtd, 0, sizeof(struct mtd_info));
|
||||
memset(this, 0, sizeof(struct nand_chip));
|
||||
|
||||
/* Link the private data with the MTD structure */
|
||||
spia_mtd->priv = this;
|
||||
@ -129,19 +126,19 @@ int __init spia_init (void)
|
||||
* Set GPIO Port E control register so that the pins are configured
|
||||
* to be outputs for controlling the NAND flash.
|
||||
*/
|
||||
(*(volatile unsigned char *) (spia_io_base + spia_peddr)) = 0x07;
|
||||
(*(volatile unsigned char *)(spia_io_base + spia_peddr)) = 0x07;
|
||||
|
||||
/* Set address of NAND IO lines */
|
||||
this->IO_ADDR_R = (void __iomem *) spia_fio_base;
|
||||
this->IO_ADDR_W = (void __iomem *) spia_fio_base;
|
||||
this->IO_ADDR_R = (void __iomem *)spia_fio_base;
|
||||
this->IO_ADDR_W = (void __iomem *)spia_fio_base;
|
||||
/* Set address of hardware control function */
|
||||
this->hwcontrol = spia_hwcontrol;
|
||||
/* 15 us command delay time */
|
||||
this->chip_delay = 15;
|
||||
|
||||
/* Scan to find existence of the device */
|
||||
if (nand_scan (spia_mtd, 1)) {
|
||||
kfree (spia_mtd);
|
||||
if (nand_scan(spia_mtd, 1)) {
|
||||
kfree(spia_mtd);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
@ -151,20 +148,22 @@ int __init spia_init (void)
|
||||
/* Return happy */
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_init(spia_init);
|
||||
|
||||
/*
|
||||
* Clean up routine
|
||||
*/
|
||||
#ifdef MODULE
|
||||
static void __exit spia_cleanup (void)
|
||||
static void __exit spia_cleanup(void)
|
||||
{
|
||||
/* Release resources, unregister device */
|
||||
nand_release (spia_mtd);
|
||||
nand_release(spia_mtd);
|
||||
|
||||
/* Free the MTD device structure */
|
||||
kfree (spia_mtd);
|
||||
kfree(spia_mtd);
|
||||
}
|
||||
|
||||
module_exit(spia_cleanup);
|
||||
#endif
|
||||
|
||||
|
@ -48,7 +48,7 @@ static unsigned long toto_io_base = OMAP_FLASH_1_BASE;
|
||||
|
||||
#define T_NAND_CTL_CLRALE(iob) gpiosetout(NAND_ALE, 0)
|
||||
#define T_NAND_CTL_SETALE(iob) gpiosetout(NAND_ALE, NAND_ALE)
|
||||
#ifdef CONFIG_NAND_WORKAROUND /* "some" dev boards busted, blue wired to rts2 :( */
|
||||
#ifdef CONFIG_NAND_WORKAROUND /* "some" dev boards busted, blue wired to rts2 :( */
|
||||
#define T_NAND_CTL_CLRCLE(iob) gpiosetout(NAND_CLE, 0); rts2setout(2, 2)
|
||||
#define T_NAND_CTL_SETCLE(iob) gpiosetout(NAND_CLE, NAND_CLE); rts2setout(2, 0)
|
||||
#else
|
||||
@ -98,9 +98,8 @@ static struct mtd_partition partition_info32M[] = {
|
||||
static void toto_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
{
|
||||
|
||||
udelay(1); /* hopefully enough time for tc make proceding write to clear */
|
||||
switch(cmd){
|
||||
|
||||
udelay(1); /* hopefully enough time for tc make proceding write to clear */
|
||||
switch (cmd) {
|
||||
case NAND_CTL_SETCLE: T_NAND_CTL_SETCLE(cmd); break;
|
||||
case NAND_CTL_CLRCLE: T_NAND_CTL_CLRCLE(cmd); break;
|
||||
|
||||
@ -110,32 +109,31 @@ static void toto_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
case NAND_CTL_SETNCE: T_NAND_CTL_SETNCE(cmd); break;
|
||||
case NAND_CTL_CLRNCE: T_NAND_CTL_CLRNCE(cmd); break;
|
||||
}
|
||||
udelay(1); /* allow time to ensure gpio state to over take memory write */
|
||||
udelay(1); /* allow time to ensure gpio state to over take memory write */
|
||||
}
|
||||
|
||||
/*
|
||||
* Main initialization routine
|
||||
*/
|
||||
int __init toto_init (void)
|
||||
int __init toto_init(void)
|
||||
{
|
||||
struct nand_chip *this;
|
||||
int err = 0;
|
||||
|
||||
/* Allocate memory for MTD device structure and private data */
|
||||
toto_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
|
||||
GFP_KERNEL);
|
||||
toto_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
|
||||
if (!toto_mtd) {
|
||||
printk (KERN_WARNING "Unable to allocate toto NAND MTD device structure.\n");
|
||||
printk(KERN_WARNING "Unable to allocate toto NAND MTD device structure.\n");
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Get pointer to private data */
|
||||
this = (struct nand_chip *) (&toto_mtd[1]);
|
||||
this = (struct nand_chip *)(&toto_mtd[1]);
|
||||
|
||||
/* Initialize structures */
|
||||
memset((char *) toto_mtd, 0, sizeof(struct mtd_info));
|
||||
memset((char *) this, 0, sizeof(struct nand_chip));
|
||||
memset(toto_mtd, 0, sizeof(struct mtd_info));
|
||||
memset(this, 0, sizeof(struct nand_chip));
|
||||
|
||||
/* Link the private data with the MTD structure */
|
||||
toto_mtd->priv = this;
|
||||
@ -149,33 +147,37 @@ int __init toto_init (void)
|
||||
this->chip_delay = 30;
|
||||
this->eccmode = NAND_ECC_SOFT;
|
||||
|
||||
/* Scan to find existance of the device */
|
||||
if (nand_scan (toto_mtd, 1)) {
|
||||
/* Scan to find existance of the device */
|
||||
if (nand_scan(toto_mtd, 1)) {
|
||||
err = -ENXIO;
|
||||
goto out_mtd;
|
||||
}
|
||||
|
||||
/* Register the partitions */
|
||||
switch(toto_mtd->size){
|
||||
case SZ_64M: add_mtd_partitions(toto_mtd, partition_info64M, NUM_PARTITIONS64M); break;
|
||||
case SZ_32M: add_mtd_partitions(toto_mtd, partition_info32M, NUM_PARTITIONS32M); break;
|
||||
default: {
|
||||
printk (KERN_WARNING "Unsupported Nand device\n");
|
||||
switch (toto_mtd->size) {
|
||||
case SZ_64M:
|
||||
add_mtd_partitions(toto_mtd, partition_info64M, NUM_PARTITIONS64M);
|
||||
break;
|
||||
case SZ_32M:
|
||||
add_mtd_partitions(toto_mtd, partition_info32M, NUM_PARTITIONS32M);
|
||||
break;
|
||||
default:{
|
||||
printk(KERN_WARNING "Unsupported Nand device\n");
|
||||
err = -ENXIO;
|
||||
goto out_buf;
|
||||
}
|
||||
}
|
||||
|
||||
gpioreserve(NAND_MASK); /* claim our gpios */
|
||||
archflashwp(0,0); /* open up flash for writing */
|
||||
gpioreserve(NAND_MASK); /* claim our gpios */
|
||||
archflashwp(0, 0); /* open up flash for writing */
|
||||
|
||||
goto out;
|
||||
|
||||
out_buf:
|
||||
kfree (this->data_buf);
|
||||
out_mtd:
|
||||
kfree (toto_mtd);
|
||||
out:
|
||||
out_buf:
|
||||
kfree(this->data_buf);
|
||||
out_mtd:
|
||||
kfree(toto_mtd);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -184,20 +186,21 @@ module_init(toto_init);
|
||||
/*
|
||||
* Clean up routine
|
||||
*/
|
||||
static void __exit toto_cleanup (void)
|
||||
static void __exit toto_cleanup(void)
|
||||
{
|
||||
/* Release resources, unregister device */
|
||||
nand_release (toto_mtd);
|
||||
nand_release(toto_mtd);
|
||||
|
||||
/* Free the MTD device structure */
|
||||
kfree (toto_mtd);
|
||||
kfree(toto_mtd);
|
||||
|
||||
/* stop flash writes */
|
||||
archflashwp(0,1);
|
||||
archflashwp(0, 1);
|
||||
|
||||
/* release gpios to system */
|
||||
gpiorelease(NAND_MASK);
|
||||
gpiorelease(NAND_MASK);
|
||||
}
|
||||
|
||||
module_exit(toto_cleanup);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -88,7 +88,7 @@ static void ts7250_hwcontrol(struct mtd_info *mtd, int cmd)
|
||||
{
|
||||
unsigned long ctrl = TS72XX_NAND_CONTROL_VIRT_BASE;
|
||||
|
||||
switch(cmd) {
|
||||
switch (cmd) {
|
||||
case NAND_CTL_SETCLE:
|
||||
__raw_writeb(__raw_readb(ctrl) | 0x2, ctrl);
|
||||
break;
|
||||
@ -132,8 +132,7 @@ static int __init ts7250_init(void)
|
||||
return -ENXIO;
|
||||
|
||||
/* Allocate memory for MTD device structure and private data */
|
||||
ts7250_mtd = kmalloc(sizeof(struct mtd_info) +
|
||||
sizeof(struct nand_chip), GFP_KERNEL);
|
||||
ts7250_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
|
||||
if (!ts7250_mtd) {
|
||||
printk("Unable to allocate TS7250 NAND MTD device structure.\n");
|
||||
return -ENOMEM;
|
||||
@ -163,11 +162,9 @@ static int __init ts7250_init(void)
|
||||
kfree(ts7250_mtd);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MTD_PARTITIONS
|
||||
ts7250_mtd->name = "ts7250-nand";
|
||||
mtd_parts_nb = parse_mtd_partitions(ts7250_mtd, part_probes,
|
||||
&mtd_parts, 0);
|
||||
mtd_parts_nb = parse_mtd_partitions(ts7250_mtd, part_probes, &mtd_parts, 0);
|
||||
if (mtd_parts_nb > 0)
|
||||
part_type = "command line";
|
||||
else
|
||||
@ -188,6 +185,7 @@ static int __init ts7250_init(void)
|
||||
/* Return happy */
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_init(ts7250_init);
|
||||
|
||||
/*
|
||||
@ -201,6 +199,7 @@ static void __exit ts7250_cleanup(void)
|
||||
/* Free the MTD device structure */
|
||||
kfree(ts7250_mtd);
|
||||
}
|
||||
|
||||
module_exit(ts7250_cleanup);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
Loading…
Reference in New Issue
Block a user