[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:
David Woodhouse 2006-05-13 18:07:53 +01:00
parent 6943f8af7d
commit e0c7d76753
17 changed files with 1217 additions and 1292 deletions

View File

@ -38,22 +38,20 @@
*/ */
static struct mtd_info *au1550_mtd = NULL; static struct mtd_info *au1550_mtd = NULL;
static void __iomem *p_nand; static void __iomem *p_nand;
static int nand_width = 1; /* default x8*/ static int nand_width = 1; /* default x8 */
/* /*
* Define partitions for flash device * Define partitions for flash device
*/ */
static const struct mtd_partition partition_info[] = { static const struct mtd_partition partition_info[] = {
{ {
.name = "NAND FS 0", .name = "NAND FS 0",
.offset = 0, .offset = 0,
.size = 8*1024*1024 .size = 8 * 1024 * 1024},
},
{ {
.name = "NAND FS 1", .name = "NAND FS 1",
.offset = MTDPART_OFS_APPEND, .offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL .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; int i;
struct nand_chip *this = mtd->priv; 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); writeb(buf[i], this->IO_ADDR_W);
au_sync(); au_sync();
} }
@ -176,7 +174,7 @@ static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
int i; int i;
struct nand_chip *this = mtd->priv; 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); buf[i] = readb(this->IO_ADDR_R);
au_sync(); au_sync();
} }
@ -195,7 +193,7 @@ static int au_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
int i; int i;
struct nand_chip *this = mtd->priv; 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)) if (buf[i] != readb(this->IO_ADDR_R))
return -EFAULT; return -EFAULT;
au_sync(); 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; u16 *p = (u16 *) buf;
len >>= 1; len >>= 1;
for (i=0; i<len; i++) { for (i = 0; i < len; i++) {
writew(p[i], this->IO_ADDR_W); writew(p[i], this->IO_ADDR_W);
au_sync(); au_sync();
} }
@ -241,7 +239,7 @@ static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
u16 *p = (u16 *) buf; u16 *p = (u16 *) buf;
len >>= 1; len >>= 1;
for (i=0; i<len; i++) { for (i = 0; i < len; i++) {
p[i] = readw(this->IO_ADDR_R); p[i] = readw(this->IO_ADDR_R);
au_sync(); 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; u16 *p = (u16 *) buf;
len >>= 1; len >>= 1;
for (i=0; i<len; i++) { for (i = 0; i < len; i++) {
if (p[i] != readw(this->IO_ADDR_R)) if (p[i] != readw(this->IO_ADDR_R))
return -EFAULT; return -EFAULT;
au_sync(); au_sync();
@ -275,27 +273,35 @@ static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
{ {
register struct nand_chip *this = mtd->priv; 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_SETCLE:
case NAND_CTL_CLRCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; break; 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: case NAND_CTL_CLRALE:
this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; 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 */ * but it works only that way */
udelay(1); udelay(1);
break; break;
case NAND_CTL_SETNCE: case NAND_CTL_SETNCE:
/* assert (force assert) chip enable */ /* assert (force assert) chip enable */
au_writel((1<<(4+NAND_CS)) , MEM_STNDCTL); break; au_writel((1 << (4 + NAND_CS)), MEM_STNDCTL);
break; break;
case NAND_CTL_CLRNCE: case NAND_CTL_CLRNCE:
/* deassert chip enable */ /* deassert chip enable */
au_writel(0, MEM_STNDCTL); break; au_writel(0, MEM_STNDCTL);
break; break;
} }
@ -315,66 +321,63 @@ int au1550_device_ready(struct mtd_info *mtd)
/* /*
* Main initialization routine * Main initialization routine
*/ */
int __init au1xxx_nand_init (void) int __init au1xxx_nand_init(void)
{ {
struct nand_chip *this; struct nand_chip *this;
u16 boot_swapboot = 0; /* default value */ u16 boot_swapboot = 0; /* default value */
int retval; int retval;
u32 mem_staddr; u32 mem_staddr;
u32 nand_phys; u32 nand_phys;
/* Allocate memory for MTD device structure and private data */ /* Allocate memory for MTD device structure and private data */
au1550_mtd = kmalloc (sizeof(struct mtd_info) + au1550_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
sizeof (struct nand_chip), GFP_KERNEL);
if (!au1550_mtd) { if (!au1550_mtd) {
printk ("Unable to allocate NAND MTD dev structure.\n"); printk("Unable to allocate NAND MTD dev structure.\n");
return -ENOMEM; return -ENOMEM;
} }
/* Get pointer to private data */ /* Get pointer to private data */
this = (struct nand_chip *) (&au1550_mtd[1]); this = (struct nand_chip *)(&au1550_mtd[1]);
/* Initialize structures */ /* Initialize structures */
memset((char *) au1550_mtd, 0, sizeof(struct mtd_info)); memset(au1550_mtd, 0, sizeof(struct mtd_info));
memset((char *) this, 0, sizeof(struct nand_chip)); memset(this, 0, sizeof(struct nand_chip));
/* Link the private data with the MTD structure */ /* Link the private data with the MTD structure */
au1550_mtd->priv = this; au1550_mtd->priv = this;
/* disable interrupts */ /* 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 */ /* 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 #ifdef CONFIG_MIPS_PB1550
/* set gpio206 high */ /* 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)) | boot_swapboot = (au_readl(MEM_STSTAT) & (0x7 << 1)) | ((bcsr->status >> 6) & 0x1);
((bcsr->status >> 6) & 0x1);
switch (boot_swapboot) { switch (boot_swapboot) {
case 0: case 0:
case 2: case 2:
case 8: case 8:
case 0xC: case 0xC:
case 0xD: case 0xD:
/* x16 NAND Flash */ /* x16 NAND Flash */
nand_width = 0; nand_width = 0;
break; break;
case 1: case 1:
case 9: case 9:
case 3: case 3:
case 0xE: case 0xE:
case 0xF: case 0xF:
/* x8 NAND Flash */ /* x8 NAND Flash */
nand_width = 1; nand_width = 1;
break; break;
default: default:
printk("Pb1550 NAND: bad boot:swap\n"); printk("Pb1550 NAND: bad boot:swap\n");
retval = -EINVAL; retval = -EINVAL;
goto outmem; goto outmem;
} }
#endif #endif
@ -424,14 +427,13 @@ int __init au1xxx_nand_init (void)
/* make controller and MTD agree */ /* make controller and MTD agree */
if (NAND_CS == 0) if (NAND_CS == 0)
nand_width = au_readl(MEM_STCFG0) & (1<<22); nand_width = au_readl(MEM_STCFG0) & (1 << 22);
if (NAND_CS == 1) if (NAND_CS == 1)
nand_width = au_readl(MEM_STCFG1) & (1<<22); nand_width = au_readl(MEM_STCFG1) & (1 << 22);
if (NAND_CS == 2) if (NAND_CS == 2)
nand_width = au_readl(MEM_STCFG2) & (1<<22); nand_width = au_readl(MEM_STCFG2) & (1 << 22);
if (NAND_CS == 3) 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 */ /* Set address of hardware control function */
this->hwcontrol = au1550_hwcontrol; 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; this->verify_buf = (!nand_width) ? au_verify_buf16 : au_verify_buf;
/* Scan to find existence of the device */ /* Scan to find existence of the device */
if (nand_scan (au1550_mtd, 1)) { if (nand_scan(au1550_mtd, 1)) {
retval = -ENXIO; retval = -ENXIO;
goto outio; goto outio;
} }
@ -465,10 +467,10 @@ int __init au1xxx_nand_init (void)
return 0; return 0;
outio: outio:
iounmap ((void *)p_nand); iounmap((void *)p_nand);
outmem: outmem:
kfree (au1550_mtd); kfree(au1550_mtd);
return retval; return retval;
} }
@ -478,19 +480,20 @@ module_init(au1xxx_nand_init);
* Clean up routine * Clean up routine
*/ */
#ifdef MODULE #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 */ /* Release resources, unregister device */
nand_release (au1550_mtd); nand_release(au1550_mtd);
/* Free the MTD device structure */ /* Free the MTD device structure */
kfree (au1550_mtd); kfree(au1550_mtd);
/* Unmap */ /* Unmap */
iounmap ((void *)p_nand); iounmap((void *)p_nand);
} }
module_exit(au1550_cleanup); module_exit(au1550_cleanup);
#endif #endif

View File

@ -47,7 +47,7 @@ static int autcpu12_io_base = CS89712_VIRT_BASE;
static int autcpu12_fio_pbase = AUTCPU12_PHYS_SMC; static int autcpu12_fio_pbase = AUTCPU12_PHYS_SMC;
static int autcpu12_fio_ctrl = AUTCPU12_SMC_SELECT_OFFSET; static int autcpu12_fio_ctrl = AUTCPU12_SMC_SELECT_OFFSET;
static int autcpu12_pedr = AUTCPU12_SMC_PORT_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 * Define partitions for flash devices
@ -95,10 +95,10 @@ static struct mtd_partition partition_info128k[] = {
/* /*
* hardware specific access to control-lines * hardware specific access to control-lines
*/ */
static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd) 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_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; 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) 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 * Main initialization routine
*/ */
int __init autcpu12_init (void) int __init autcpu12_init(void)
{ {
struct nand_chip *this; struct nand_chip *this;
int err = 0; int err = 0;
/* Allocate memory for MTD device structure and private data */ /* Allocate memory for MTD device structure and private data */
autcpu12_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), autcpu12_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
GFP_KERNEL);
if (!autcpu12_mtd) { 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; err = -ENOMEM;
goto out; goto out;
} }
/* map physical adress */ /* map physical adress */
autcpu12_fio_base = ioremap(autcpu12_fio_pbase,SZ_1K); autcpu12_fio_base = ioremap(autcpu12_fio_pbase, SZ_1K);
if(!autcpu12_fio_base){ if (!autcpu12_fio_base) {
printk("Ioremap autcpu12 SmartMedia Card failed\n"); printk("Ioremap autcpu12 SmartMedia Card failed\n");
err = -EIO; err = -EIO;
goto out_mtd; goto out_mtd;
} }
/* Get pointer to private data */ /* Get pointer to private data */
this = (struct nand_chip *) (&autcpu12_mtd[1]); this = (struct nand_chip *)(&autcpu12_mtd[1]);
/* Initialize structures */ /* Initialize structures */
memset((char *) autcpu12_mtd, 0, sizeof(struct mtd_info)); memset(autcpu12_mtd, 0, sizeof(struct mtd_info));
memset((char *) this, 0, sizeof(struct nand_chip)); memset(this, 0, sizeof(struct nand_chip));
/* Link the private data with the MTD structure */ /* Link the private data with the MTD structure */
autcpu12_mtd->priv = this; autcpu12_mtd->priv = this;
@ -167,35 +166,34 @@ int __init autcpu12_init (void)
/* Enable the following for a flash based bad block table */ /* 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; this->options = NAND_USE_FLASH_BBT;
/* Scan to find existance of the device */ /* Scan to find existance of the device */
if (nand_scan (autcpu12_mtd, 1)) { if (nand_scan(autcpu12_mtd, 1)) {
err = -ENXIO; err = -ENXIO;
goto out_ior; goto out_ior;
} }
/* Register the partitions */ /* 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_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_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_64M: add_mtd_partitions(autcpu12_mtd, partition_info64k, NUM_PARTITIONS64K); break;
case SZ_128M: add_mtd_partitions(autcpu12_mtd, partition_info128k, NUM_PARTITIONS128K); break; case SZ_128M: add_mtd_partitions(autcpu12_mtd, partition_info128k, NUM_PARTITIONS128K); break;
default: { default:
printk ("Unsupported SmartMedia device\n"); printk("Unsupported SmartMedia device\n");
err = -ENXIO; err = -ENXIO;
goto out_ior; goto out_ior;
}
} }
goto out; goto out;
out_ior: out_ior:
iounmap((void *)autcpu12_fio_base); iounmap((void *)autcpu12_fio_base);
out_mtd: out_mtd:
kfree (autcpu12_mtd); kfree(autcpu12_mtd);
out: out:
return err; return err;
} }
@ -205,17 +203,18 @@ module_init(autcpu12_init);
* Clean up routine * Clean up routine
*/ */
#ifdef MODULE #ifdef MODULE
static void __exit autcpu12_cleanup (void) static void __exit autcpu12_cleanup(void)
{ {
/* Release resources, unregister device */ /* Release resources, unregister device */
nand_release (autcpu12_mtd); nand_release(autcpu12_mtd);
/* unmap physical adress */ /* unmap physical adress */
iounmap((void *)autcpu12_fio_base); iounmap((void *)autcpu12_fio_base);
/* Free the MTD device structure */ /* Free the MTD device structure */
kfree (autcpu12_mtd); kfree(autcpu12_mtd);
} }
module_exit(autcpu12_cleanup); module_exit(autcpu12_cleanup);
#endif #endif

View File

@ -50,7 +50,7 @@
/* Pin function selection MSR (IDE vs. flash on the IDE pins) */ /* Pin function selection MSR (IDE vs. flash on the IDE pins) */
#define MSR_DIVIL_BALL_OPTS 0x51400015 #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 */ /* Registers within the NAND flash controller BAR -- memory mapped */
#define MM_NAND_DATA 0x00 /* 0 to 0x7ff, in fact */ #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); udelay(1);
i--; 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) 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; void __iomem *mmio_base = this->IO_ADDR_R;
unsigned char ctl; unsigned char ctl;
switch(cmd) { switch (cmd) {
case NAND_CTL_SETCLE: case NAND_CTL_SETCLE:
ctl = CS_NAND_CTL_CLE; ctl = CS_NAND_CTL_CLE;
break; break;
@ -160,17 +160,15 @@ static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd)
writeb(ctl, mmio_base + MM_NAND_CTL); writeb(ctl, mmio_base + MM_NAND_CTL);
} }
static int cs553x_device_ready(struct mtd_info *mtd) static int cs553x_device_ready(struct mtd_info *mtd)
{ {
struct nand_chip *this = mtd->priv; struct nand_chip *this = mtd->priv;
void __iomem *mmio_base = this->IO_ADDR_R; void __iomem *mmio_base = this->IO_ADDR_R;
unsigned char foo = readb(mmio_base + MM_NAND_STS); 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) static void cs_enable_hwecc(struct mtd_info *mtd, int mode)
{ {
struct nand_chip *this = mtd->priv; 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 */ /* 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) { if (!new_mtd) {
printk(KERN_WARNING "Unable to allocate CS553X NAND MTD device structure.\n"); printk(KERN_WARNING "Unable to allocate CS553X NAND MTD device structure.\n");
err = -ENOMEM; err = -ENOMEM;
@ -217,7 +215,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
} }
/* Get pointer to private data */ /* Get pointer to private data */
this = (struct nand_chip *) (&new_mtd[1]); this = (struct nand_chip *)(&new_mtd[1]);
/* Initialize structures */ /* Initialize structures */
memset(new_mtd, 0, sizeof(struct mtd_info)); memset(new_mtd, 0, sizeof(struct mtd_info));
@ -286,16 +284,16 @@ int __init cs553x_init(void)
return -ENXIO; return -ENXIO;
} }
for (i=0; i<NR_CS553X_CONTROLLERS; i++) { for (i = 0; i < NR_CS553X_CONTROLLERS; i++) {
rdmsrl(MSR_DIVIL_LBAR_FLSH0+i, val); rdmsrl(MSR_DIVIL_LBAR_FLSH0 + i, val);
if ((val & (FLSH_LBAR_EN|FLSH_NOR_NAND)) == (FLSH_LBAR_EN|FLSH_NOR_NAND)) 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); err = cs553x_init_one(i, !!(val & FLSH_MEM_IO), val & 0xFFFFFFFF);
} }
/* Register all devices together here. This means we can easily hack it to /* Register all devices together here. This means we can easily hack it to
do mtdconcat etc. if we want 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]) { if (cs553x_mtd[i]) {
add_mtd_device(cs553x_mtd[i]); add_mtd_device(cs553x_mtd[i]);
@ -306,13 +304,14 @@ int __init cs553x_init(void)
return err; return err;
} }
module_init(cs553x_init); module_init(cs553x_init);
static void __exit cs553x_cleanup (void) static void __exit cs553x_cleanup(void)
{ {
int i; 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 mtd_info *mtd = cs553x_mtd[i];
struct nand_chip *this; struct nand_chip *this;
void __iomem *mmio_base; void __iomem *mmio_base;
@ -324,7 +323,7 @@ static void __exit cs553x_cleanup (void)
mmio_base = this->IO_ADDR_R; mmio_base = this->IO_ADDR_R;
/* Release resources, unregister device */ /* Release resources, unregister device */
nand_release (cs553x_mtd[i]); nand_release(cs553x_mtd[i]);
cs553x_mtd[i] = NULL; cs553x_mtd[i] = NULL;
/* unmap physical adress */ /* unmap physical adress */
@ -334,6 +333,7 @@ static void __exit cs553x_cleanup (void)
kfree(mtd); kfree(mtd);
} }
} }
module_exit(cs553x_cleanup); module_exit(cs553x_cleanup);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,7 @@
#include <linux/mtd/nand.h> #include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h> #include <linux/mtd/partitions.h>
#include <asm/io.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/sizes.h>
#include <asm/hardware/clps7111.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 unsigned long ep7312_fio_pbase = EP7312_FIO_PBASE;
static void __iomem * ep7312_pxdr = (void __iomem *) EP7312_PXDR; static void __iomem *ep7312_pxdr = (void __iomem *)EP7312_PXDR;
static void __iomem * ep7312_pxddr = (void __iomem *) EP7312_PXDDR; static void __iomem *ep7312_pxddr = (void __iomem *)EP7312_PXDDR;
#ifdef CONFIG_MTD_PARTITIONS #ifdef CONFIG_MTD_PARTITIONS
/* /*
* Define static partitions for flash device * Define static partitions for flash device
*/ */
static struct mtd_partition partition_info[] = { static struct mtd_partition partition_info[] = {
{ .name = "EP7312 Nand Flash", {.name = "EP7312 Nand Flash",
.offset = 0, .offset = 0,
.size = 8*1024*1024 } .size = 8 * 1024 * 1024}
}; };
#define NUM_PARTITIONS 1 #define NUM_PARTITIONS 1
#endif #endif
/* /*
* hardware specific access to control-lines * hardware specific access to control-lines
*/ */
static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd) static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd)
{ {
switch(cmd) { switch (cmd) {
case NAND_CTL_SETCLE: case NAND_CTL_SETCLE:
clps_writeb(clps_readb(ep7312_pxdr) | 0x10, ep7312_pxdr); clps_writeb(clps_readb(ep7312_pxdr) | 0x10, ep7312_pxdr);
@ -108,6 +108,7 @@ static int ep7312_device_ready(struct mtd_info *mtd)
{ {
return 1; return 1;
} }
#ifdef CONFIG_MTD_PARTITIONS #ifdef CONFIG_MTD_PARTITIONS
const char *part_probes[] = { "cmdlinepart", NULL }; const char *part_probes[] = { "cmdlinepart", NULL };
#endif #endif
@ -115,18 +116,16 @@ const char *part_probes[] = { "cmdlinepart", NULL };
/* /*
* Main initialization routine * Main initialization routine
*/ */
static int __init ep7312_init (void) static int __init ep7312_init(void)
{ {
struct nand_chip *this; struct nand_chip *this;
const char *part_type = 0; const char *part_type = 0;
int mtd_parts_nb = 0; int mtd_parts_nb = 0;
struct mtd_partition *mtd_parts = 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 */ /* Allocate memory for MTD device structure and private data */
ep7312_mtd = kmalloc(sizeof(struct mtd_info) + ep7312_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
sizeof(struct nand_chip),
GFP_KERNEL);
if (!ep7312_mtd) { if (!ep7312_mtd) {
printk("Unable to allocate EDB7312 NAND MTD device structure.\n"); printk("Unable to allocate EDB7312 NAND MTD device structure.\n");
return -ENOMEM; return -ENOMEM;
@ -134,18 +133,18 @@ static int __init ep7312_init (void)
/* map physical adress */ /* map physical adress */
ep7312_fio_base = ioremap(ep7312_fio_pbase, SZ_1K); ep7312_fio_base = ioremap(ep7312_fio_pbase, SZ_1K);
if(!ep7312_fio_base) { if (!ep7312_fio_base) {
printk("ioremap EDB7312 NAND flash failed\n"); printk("ioremap EDB7312 NAND flash failed\n");
kfree(ep7312_mtd); kfree(ep7312_mtd);
return -EIO; return -EIO;
} }
/* Get pointer to private data */ /* Get pointer to private data */
this = (struct nand_chip *) (&ep7312_mtd[1]); this = (struct nand_chip *)(&ep7312_mtd[1]);
/* Initialize structures */ /* Initialize structures */
memset((char *) ep7312_mtd, 0, sizeof(struct mtd_info)); memset(ep7312_mtd, 0, sizeof(struct mtd_info));
memset((char *) this, 0, sizeof(struct nand_chip)); memset(this, 0, sizeof(struct nand_chip));
/* Link the private data with the MTD structure */ /* Link the private data with the MTD structure */
ep7312_mtd->priv = this; ep7312_mtd->priv = this;
@ -165,16 +164,14 @@ static int __init ep7312_init (void)
this->chip_delay = 15; this->chip_delay = 15;
/* Scan to find existence of the device */ /* Scan to find existence of the device */
if (nand_scan (ep7312_mtd, 1)) { if (nand_scan(ep7312_mtd, 1)) {
iounmap((void *)ep7312_fio_base); iounmap((void *)ep7312_fio_base);
kfree (ep7312_mtd); kfree(ep7312_mtd);
return -ENXIO; return -ENXIO;
} }
#ifdef CONFIG_MTD_PARTITIONS #ifdef CONFIG_MTD_PARTITIONS
ep7312_mtd->name = "edb7312-nand"; ep7312_mtd->name = "edb7312-nand";
mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes, mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes, &mtd_parts, 0);
&mtd_parts, 0);
if (mtd_parts_nb > 0) if (mtd_parts_nb > 0)
part_type = "command line"; part_type = "command line";
else else
@ -193,24 +190,26 @@ static int __init ep7312_init (void)
/* Return happy */ /* Return happy */
return 0; return 0;
} }
module_init(ep7312_init); module_init(ep7312_init);
/* /*
* Clean up routine * 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 */ /* Release resources, unregister device */
nand_release (ap7312_mtd); nand_release(ap7312_mtd);
/* Free internal data buffer */ /* Free internal data buffer */
kfree (this->data_buf); kfree(this->data_buf);
/* Free the MTD device structure */ /* Free the MTD device structure */
kfree (ep7312_mtd); kfree(ep7312_mtd);
} }
module_exit(ep7312_cleanup); module_exit(ep7312_cleanup);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

View File

@ -26,7 +26,7 @@
#include <linux/mtd/nand.h> #include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h> #include <linux/mtd/partitions.h>
#include <asm/io.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/sizes.h>
#include <asm/arch/h1900-gpio.h> #include <asm/arch/h1900-gpio.h>
#include <asm/arch/ipaq.h> #include <asm/arch/ipaq.h>
@ -45,23 +45,23 @@ static struct mtd_info *h1910_nand_mtd = NULL;
* Define static partitions for flash device * Define static partitions for flash device
*/ */
static struct mtd_partition partition_info[] = { static struct mtd_partition partition_info[] = {
{ name: "h1910 NAND Flash", {name:"h1910 NAND Flash",
offset: 0, offset:0,
size: 16*1024*1024 } size:16 * 1024 * 1024}
}; };
#define NUM_PARTITIONS 1 #define NUM_PARTITIONS 1
#endif #endif
/* /*
* hardware specific access to control-lines * hardware specific access to control-lines
*/ */
static void h1910_hwcontrol(struct mtd_info *mtd, int cmd) 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: case NAND_CTL_SETCLE:
this->IO_ADDR_R |= (1 << 2); this->IO_ADDR_R |= (1 << 2);
@ -101,7 +101,7 @@ static int h1910_device_ready(struct mtd_info *mtd)
/* /*
* Main initialization routine * Main initialization routine
*/ */
static int __init h1910_init (void) static int __init h1910_init(void)
{ {
struct nand_chip *this; struct nand_chip *this;
const char *part_type = 0; const char *part_type = 0;
@ -119,21 +119,19 @@ static int __init h1910_init (void)
} }
/* Allocate memory for MTD device structure and private data */ /* Allocate memory for MTD device structure and private data */
h1910_nand_mtd = kmalloc(sizeof(struct mtd_info) + h1910_nand_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
sizeof(struct nand_chip),
GFP_KERNEL);
if (!h1910_nand_mtd) { if (!h1910_nand_mtd) {
printk("Unable to allocate h1910 NAND MTD device structure.\n"); printk("Unable to allocate h1910 NAND MTD device structure.\n");
iounmap ((void *) nandaddr); iounmap((void *)nandaddr);
return -ENOMEM; return -ENOMEM;
} }
/* Get pointer to private data */ /* Get pointer to private data */
this = (struct nand_chip *) (&h1910_nand_mtd[1]); this = (struct nand_chip *)(&h1910_nand_mtd[1]);
/* Initialize structures */ /* Initialize structures */
memset((char *) h1910_nand_mtd, 0, sizeof(struct mtd_info)); memset(h1910_nand_mtd, 0, sizeof(struct mtd_info));
memset((char *) this, 0, sizeof(struct nand_chip)); memset(this, 0, sizeof(struct nand_chip));
/* Link the private data with the MTD structure */ /* Link the private data with the MTD structure */
h1910_nand_mtd->priv = this; h1910_nand_mtd->priv = this;
@ -154,23 +152,20 @@ static int __init h1910_init (void)
this->options = NAND_NO_AUTOINCR; this->options = NAND_NO_AUTOINCR;
/* Scan to find existence of the device */ /* 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"); printk(KERN_NOTICE "No NAND device - returning -ENXIO\n");
kfree (h1910_nand_mtd); kfree(h1910_nand_mtd);
iounmap ((void *) nandaddr); iounmap((void *)nandaddr);
return -ENXIO; return -ENXIO;
} }
#ifdef CONFIG_MTD_CMDLINE_PARTS #ifdef CONFIG_MTD_CMDLINE_PARTS
mtd_parts_nb = parse_cmdline_partitions(h1910_nand_mtd, &mtd_parts, mtd_parts_nb = parse_cmdline_partitions(h1910_nand_mtd, &mtd_parts, "h1910-nand");
"h1910-nand");
if (mtd_parts_nb > 0) if (mtd_parts_nb > 0)
part_type = "command line"; part_type = "command line";
else else
mtd_parts_nb = 0; mtd_parts_nb = 0;
#endif #endif
if (mtd_parts_nb == 0) if (mtd_parts_nb == 0) {
{
mtd_parts = partition_info; mtd_parts = partition_info;
mtd_parts_nb = NUM_PARTITIONS; mtd_parts_nb = NUM_PARTITIONS;
part_type = "static"; part_type = "static";
@ -183,24 +178,26 @@ static int __init h1910_init (void)
/* Return happy */ /* Return happy */
return 0; return 0;
} }
module_init(h1910_init); module_init(h1910_init);
/* /*
* Clean up routine * 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 */ /* Release resources, unregister device */
nand_release (h1910_nand_mtd); nand_release(h1910_nand_mtd);
/* Release io resource */ /* Release io resource */
iounmap ((void *) this->IO_ADDR_W); iounmap((void *)this->IO_ADDR_W);
/* Free the MTD device structure */ /* Free the MTD device structure */
kfree (h1910_nand_mtd); kfree(h1910_nand_mtd);
} }
module_exit(h1910_cleanup); module_exit(h1910_cleanup);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

File diff suppressed because it is too large Load Diff

View File

@ -48,7 +48,7 @@
* *
* Following assumptions are made: * Following assumptions are made:
* - bbts start at a page boundary, if autolocated on a block boundary * - 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 * 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; int i, end = 0;
uint8_t *p = buf; 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 * 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; int i;
uint8_t *p = buf; 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. * Read the bad block table starting from page.
* *
*/ */
static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num, static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
int bits, int offs, int reserved_block_code) int bits, int offs, int reserved_block_code)
{ {
int res, i, j, act = 0; int res, i, j, act = 0;
struct nand_chip *this = mtd->priv; 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); uint8_t msk = (uint8_t) ((1 << bits) - 1);
totlen = (num * bits) >> 3; totlen = (num * bits) >> 3;
from = ((loff_t)page) << this->page_shift; from = ((loff_t) page) << this->page_shift;
while (totlen) { while (totlen) {
len = min (totlen, (size_t) (1 << this->bbt_erase_shift)); len = min(totlen, (size_t) (1 << this->bbt_erase_shift));
res = mtd->read_ecc (mtd, from, len, &retlen, buf, NULL, this->autooob); res = mtd->read_ecc(mtd, from, len, &retlen, buf, NULL, this->autooob);
if (res < 0) { if (res < 0) {
if (retlen != len) { 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; 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 */ /* 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; uint8_t tmp = (dat >> j) & msk;
if (tmp == msk) if (tmp == msk)
continue; continue;
if (reserved_block_code && if (reserved_block_code && (tmp == reserved_block_code)) {
(tmp == reserved_block_code)) { printk(KERN_DEBUG "nand_read_bbt: Reserved block at 0x%08x\n",
printk (KERN_DEBUG "nand_read_bbt: Reserved block at 0x%08x\n", ((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06); this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06);
continue; continue;
} }
/* Leave it for now, if its matured we can move this /* Leave it for now, if its matured we can move this
* message to MTD_DEBUG_LEVEL0 */ * message to MTD_DEBUG_LEVEL0 */
printk (KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n", printk(KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n",
((offs << 2) + (act >> 1)) << this->bbt_erase_shift); ((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
/* Factory marked bad or worn out ? */ /* Factory marked bad or worn out ? */
if (tmp == 0) if (tmp == 0)
this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06); 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 * Read the bad block table for all chips starting at a given page
* We assume that the bbt bits are in consecutive order. * 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; struct nand_chip *this = mtd->priv;
int res = 0, i; 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. * 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, static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, struct nand_bbt_descr *md)
struct nand_bbt_descr *md)
{ {
struct nand_chip *this = mtd->priv; struct nand_chip *this = mtd->priv;
/* Read the primary version, if available */ /* Read the primary version, if available */
if (td->options & NAND_BBT_VERSION) { 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]; 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 */ /* Read the mirror version, if available */
if (md && (md->options & NAND_BBT_VERSION)) { 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]; 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; 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 * Create a bad block table by scanning the device
* for the given good/bad block identify pattern * 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; struct nand_chip *this = mtd->priv;
int i, j, numblocks, len, scanlen; 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; loff_t from;
size_t readlen, ooblen; 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) if (bd->options & NAND_BBT_SCANALLPAGES)
len = 1 << (this->bbt_erase_shift - this->page_shift); 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; readlen = bd->len;
} else { } else {
/* Full page content should be read */ /* Full page content should be read */
scanlen = mtd->oobblock + mtd->oobsize; scanlen = mtd->oobblock + mtd->oobsize;
readlen = len * mtd->oobblock; readlen = len * mtd->oobblock;
ooblen = len * mtd->oobsize; 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; from = 0;
} else { } else {
if (chip >= this->numchips) { if (chip >= this->numchips) {
printk (KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n", printk(KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n",
chip + 1, this->numchips); chip + 1, this->numchips);
return -EINVAL; return -EINVAL;
} }
numblocks = this->chipsize >> (this->bbt_erase_shift - 1); 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; int ret;
if (bd->options & NAND_BBT_SCANEMPTY) 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; return ret;
for (j = 0; j < len; j++) { 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 /* Read the full oob until read_oob is fixed to
* handle single byte reads for 16 bit buswidth */ * handle single byte reads for 16 bit buswidth */
ret = mtd->read_oob(mtd, from + j * mtd->oobblock, ret = mtd->read_oob(mtd, from + j * mtd->oobblock, mtd->oobsize, &retlen, buf);
mtd->oobsize, &retlen, buf);
if (ret) if (ret)
return ret; return ret;
if (check_short_pattern (buf, bd)) { if (check_short_pattern(buf, bd)) {
this->bbt[i >> 3] |= 0x03 << (i & 0x6); this->bbt[i >> 3] |= 0x03 << (i & 0x6);
printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
i >> 1, (unsigned int) from); i >> 1, (unsigned int)from);
break; break;
} }
} else { } 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); this->bbt[i >> 3] |= 0x03 << (i & 0x6);
printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
i >> 1, (unsigned int) from); i >> 1, (unsigned int)from);
break; break;
} }
} }
@ -374,12 +371,12 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
* block. * block.
* If the option NAND_BBT_PERCHIP is given, each chip is searched * If the option NAND_BBT_PERCHIP is given, each chip is searched
* for a bbt, which contains the bad block information of this chip. * 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 * The bbt ident pattern resides in the oob area of the first page
* in a block. * 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; struct nand_chip *this = mtd->priv;
int i, chips; 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 ? */ /* Search direction top -> down ? */
if (td->options & NAND_BBT_LASTBLOCK) { if (td->options & NAND_BBT_LASTBLOCK) {
startblock = (mtd->size >> this->bbt_erase_shift) -1; startblock = (mtd->size >> this->bbt_erase_shift) - 1;
dir = -1; dir = -1;
} else { } else {
startblock = 0; 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++) { for (block = 0; block < td->maxblocks; block++) {
int actblock = startblock + dir * block; int actblock = startblock + dir * block;
/* Read first page */ /* 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)) { if (!check_pattern(buf, scanlen, mtd->oobblock, td)) {
td->pages[i] = actblock << (this->bbt_erase_shift - this->page_shift); td->pages[i] = actblock << (this->bbt_erase_shift - this->page_shift);
if (td->options & NAND_BBT_VERSION) { 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 */ /* Check, if we found a bbt for each requested chip */
for (i = 0; i < chips; i++) { for (i = 0; i < chips; i++) {
if (td->pages[i] == -1) 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 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; 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) * Search and read the bad block table(s)
*/ */
static int search_read_bbts (struct mtd_info *mtd, uint8_t *buf, static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt_descr *td, struct nand_bbt_descr *md)
struct nand_bbt_descr *td, struct nand_bbt_descr *md)
{ {
/* Search the primary table */ /* Search the primary table */
search_bbt (mtd, buf, td); search_bbt(mtd, buf, td);
/* Search the mirror table */ /* Search the mirror table */
if (md) if (md)
search_bbt (mtd, buf, md); search_bbt(mtd, buf, md);
/* Force result check */ /* Force result check */
return 1; return 1;
} }
/** /**
* write_bbt - [GENERIC] (Re)write the bad block table * 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 * (Re)write the bad block table
* *
*/ */
static int write_bbt (struct mtd_info *mtd, uint8_t *buf, 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_bbt_descr *td, struct nand_bbt_descr *md, int chipsel)
{ {
struct nand_chip *this = mtd->priv; struct nand_chip *this = mtd->priv;
struct nand_oobinfo oobinfo; struct nand_oobinfo oobinfo;
@ -492,7 +488,7 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
rcode = 0xff; rcode = 0xff;
/* Write bad block table per chip rather than per device ? */ /* Write bad block table per chip rather than per device ? */
if (td->options & NAND_BBT_PERCHIP) { 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 ? */ /* Full device write or specific chip ? */
if (chipsel == -1) { if (chipsel == -1) {
nrchips = this->numchips; nrchips = this->numchips;
@ -501,7 +497,7 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
chip = chipsel; chip = chipsel;
} }
} else { } else {
numblocks = (int) (mtd->size >> this->bbt_erase_shift); numblocks = (int)(mtd->size >> this->bbt_erase_shift);
nrchips = 1; nrchips = 1;
} }
@ -540,9 +536,9 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
if (!md || md->pages[chip] != page) if (!md || md->pages[chip] != page)
goto write; 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; return -ENOSPC;
write: write:
/* Set up shift count and masks for the flash table */ /* Set up shift count and masks for the flash table */
bits = td->options & NAND_BBT_NRBITS_MSK; bits = td->options & NAND_BBT_NRBITS_MSK;
@ -558,7 +554,7 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
to = ((loff_t) page) << this->page_shift; to = ((loff_t) page) << this->page_shift;
memcpy (&oobinfo, this->autooob, sizeof(oobinfo)); memcpy(&oobinfo, this->autooob, sizeof(oobinfo));
oobinfo.useecc = MTD_NANDECC_PLACEONLY; oobinfo.useecc = MTD_NANDECC_PLACEONLY;
/* Must we save the block contents ? */ /* Must we save the block contents ? */
@ -566,22 +562,23 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
/* Make it block aligned */ /* Make it block aligned */
to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1)); to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1));
len = 1 << this->bbt_erase_shift; 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 (res < 0) {
if (retlen != len) { 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; 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 */ /* Calc the byte offset in the buffer */
pageoffs = page - (int)(to >> this->page_shift); pageoffs = page - (int)(to >> this->page_shift);
offs = pageoffs << this->page_shift; offs = pageoffs << this->page_shift;
/* Preset the bbt area with 0xff */ /* 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 */ /* Preset the bbt's oob area with 0xff */
memset (&buf[len + pageoffs * mtd->oobsize], 0xff, memset(&buf[len + pageoffs * mtd->oobsize], 0xff,
((len >> this->page_shift) - pageoffs) * mtd->oobsize); ((len >> this->page_shift) - pageoffs) * mtd->oobsize);
if (td->options & NAND_BBT_VERSION) { if (td->options & NAND_BBT_VERSION) {
buf[len + (pageoffs * mtd->oobsize) + td->veroffs] = td->version[chip]; buf[len + (pageoffs * mtd->oobsize) + td->veroffs] = td->version[chip];
} }
@ -589,22 +586,22 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
/* Calc length */ /* Calc length */
len = (size_t) (numblocks >> sft); len = (size_t) (numblocks >> sft);
/* Make it page aligned ! */ /* 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 */ /* 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; offs = 0;
/* Pattern is located in oob area of first page */ /* 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) { if (td->options & NAND_BBT_VERSION) {
buf[len + td->veroffs] = td->version[chip]; buf[len + td->veroffs] = td->version[chip];
} }
} }
/* walk through the memory table */ /* walk through the memory table */
for (i = 0; i < numblocks; ) { for (i = 0; i < numblocks;) {
uint8_t dat; uint8_t dat;
dat = this->bbt[bbtoffs + (i >> 2)]; 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; int sftcnt = (i << (3 - sft)) & sftmsk;
/* Do not store the reserved bbt blocks ! */ /* Do not store the reserved bbt blocks ! */
buf[offs + (i >> sft)] &= ~(msk[dat & 0x03] << sftcnt); buf[offs + (i >> sft)] &= ~(msk[dat & 0x03] << sftcnt);
@ -612,23 +609,23 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
} }
} }
memset (&einfo, 0, sizeof (einfo)); memset(&einfo, 0, sizeof(einfo));
einfo.mtd = mtd; einfo.mtd = mtd;
einfo.addr = (unsigned long) to; einfo.addr = (unsigned long)to;
einfo.len = 1 << this->bbt_erase_shift; einfo.len = 1 << this->bbt_erase_shift;
res = nand_erase_nand (mtd, &einfo, 1); res = nand_erase_nand(mtd, &einfo, 1);
if (res < 0) { 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; 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) { 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; return res;
} }
printk (KERN_DEBUG "Bad block table written to 0x%08x, version 0x%02X\n", printk(KERN_DEBUG "Bad block table written to 0x%08x, version 0x%02X\n",
(unsigned int) to, td->version[chip]); (unsigned int)to, td->version[chip]);
/* Mark it as used */ /* Mark it as used */
td->pages[chip] = page; td->pages[chip] = page;
@ -644,27 +641,27 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
* The function creates a memory based bbt by scanning the device * The function creates a memory based bbt by scanning the device
* for manufacturer / software marked good / bad blocks * 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; struct nand_chip *this = mtd->priv;
bd->options &= ~NAND_BBT_SCANEMPTY; 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 * @mtd: MTD device structure
* @buf: temporary buffer * @buf: temporary buffer
* @bd: descriptor for the good/bad block search pattern * @bd: descriptor for the good/bad block search pattern
* *
* The function checks the results of the previous call to read_bbt * The function checks the results of the previous call to read_bbt
* and creates / updates the bbt(s) if neccecary * and creates / updates the bbt(s) if necessary
* Creation is neccecary if no bbt was found for the chip/device * Creation is necessary if no bbt was found for the chip/device
* Update is neccecary if one of the tables is missing or the * Update is necessary if one of the tables is missing or the
* version nr. of one table is less than the other * 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; int i, chips, writeops, chipsel, res;
struct nand_chip *this = mtd->priv; 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; rd = td;
goto writecheck; goto writecheck;
} }
create: create:
/* Create the bad block table by scanning the device ? */ /* Create the bad block table by scanning the device ? */
if (!(td->options & NAND_BBT_CREATE)) if (!(td->options & NAND_BBT_CREATE))
continue; continue;
/* Create the table in memory by scanning the chip(s) */ /* 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; td->version[i] = 1;
if (md) if (md)
md->version[i] = 1; md->version[i] = 1;
writecheck: writecheck:
/* read back first ? */ /* read back first ? */
if (rd) if (rd)
read_abs_bbt (mtd, buf, rd, chipsel); read_abs_bbt(mtd, buf, rd, chipsel);
/* If they weren't versioned, read both. */ /* If they weren't versioned, read both. */
if (rd2) if (rd2)
read_abs_bbt (mtd, buf, rd2, chipsel); read_abs_bbt(mtd, buf, rd2, chipsel);
/* Write the bad block table to the device ? */ /* Write the bad block table to the device ? */
if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) { 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) if (res < 0)
return res; return res;
} }
/* Write the mirror bad block table to the device ? */ /* Write the mirror bad block table to the device ? */
if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) { 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) if (res < 0)
return res; return res;
} }
@ -777,7 +774,7 @@ static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des
* accidental erasures / writes. The regions are identified by * accidental erasures / writes. The regions are identified by
* the mark 0x02. * 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; struct nand_chip *this = mtd->priv;
int i, j, chips, block, nrblocks, update; 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++) { for (i = 0; i < chips; i++) {
if ((td->options & NAND_BBT_ABSPAGE) || if ((td->options & NAND_BBT_ABSPAGE) ||
!(td->options & NAND_BBT_WRITE)) { !(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 = td->pages[i] >> (this->bbt_erase_shift - this->page_shift);
block <<= 1; block <<= 1;
oldval = this->bbt[(block >> 3)]; 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)]; oldval = this->bbt[(block >> 3)];
newval = oldval | (0x2 << (block & 0x06)); newval = oldval | (0x2 << (block & 0x06));
this->bbt[(block >> 3)] = newval; this->bbt[(block >> 3)] = newval;
if (oldval != newval) update = 1; if (oldval != newval)
update = 1;
block += 2; block += 2;
} }
/* If we want reserved blocks to be recorded to flash, and some /* 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. * 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; struct nand_chip *this = mtd->priv;
int len, res = 0; 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); len = mtd->size >> (this->bbt_erase_shift + 2);
/* Allocate memory (2bit per block) */ /* Allocate memory (2bit per block) */
this->bbt = kmalloc (len, GFP_KERNEL); this->bbt = kmalloc(len, GFP_KERNEL);
if (!this->bbt) { 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; return -ENOMEM;
} }
/* Clear the memory bad block table */ /* 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 /* If no primary table decriptor is given, scan the device
* to build a memory based bad block table * to build a memory based bad block table
*/ */
if (!td) { if (!td) {
if ((res = nand_memory_bbt(mtd, bd))) { if ((res = nand_memory_bbt(mtd, bd))) {
printk (KERN_ERR "nand_bbt: Can't scan flash and build the RAM-based BBT\n"); printk(KERN_ERR "nand_bbt: Can't scan flash and build the RAM-based BBT\n");
kfree (this->bbt); kfree(this->bbt);
this->bbt = NULL; this->bbt = NULL;
} }
return res; 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; len += (len >> this->page_shift) * mtd->oobsize;
buf = vmalloc(len); buf = vmalloc(len);
if (!buf) { if (!buf) {
printk (KERN_ERR "nand_bbt: Out of memory\n"); printk(KERN_ERR "nand_bbt: Out of memory\n");
kfree (this->bbt); kfree(this->bbt);
this->bbt = NULL; this->bbt = NULL;
return -ENOMEM; return -ENOMEM;
} }
/* Is the bbt at a given page ? */ /* Is the bbt at a given page ? */
if (td->options & NAND_BBT_ABSPAGE) { if (td->options & NAND_BBT_ABSPAGE) {
res = read_abs_bbts (mtd, buf, td, md); res = read_abs_bbts(mtd, buf, td, md);
} else { } else {
/* Search the bad block table using a pattern in oob */ /* 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) if (res)
res = check_create (mtd, buf, bd); res = check_create(mtd, buf, bd);
/* Prevent the bbt regions from erasing / writing */ /* Prevent the bbt regions from erasing / writing */
mark_bbt_region (mtd, td); mark_bbt_region(mtd, td);
if (md) if (md)
mark_bbt_region (mtd, md); mark_bbt_region(mtd, md);
vfree (buf); vfree(buf);
return res; return res;
} }
/** /**
* nand_update_bbt - [NAND Interface] update bad block table(s) * nand_update_bbt - [NAND Interface] update bad block table(s)
* @mtd: MTD device structure * @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) * 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; struct nand_chip *this = mtd->priv;
int len, res = 0, writeops = 0; 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 */ /* Allocate a temporary buffer for one eraseblock incl. oob */
len = (1 << this->bbt_erase_shift); len = (1 << this->bbt_erase_shift);
len += (len >> this->page_shift) * mtd->oobsize; len += (len >> this->page_shift) * mtd->oobsize;
buf = kmalloc (len, GFP_KERNEL); buf = kmalloc(len, GFP_KERNEL);
if (!buf) { if (!buf) {
printk (KERN_ERR "nand_update_bbt: Out of memory\n"); printk(KERN_ERR "nand_update_bbt: Out of memory\n");
return -ENOMEM; return -ENOMEM;
} }
@ -935,7 +933,7 @@ int nand_update_bbt (struct mtd_info *mtd, loff_t offs)
/* Do we have a bbt per chip ? */ /* Do we have a bbt per chip ? */
if (td->options & NAND_BBT_PERCHIP) { if (td->options & NAND_BBT_PERCHIP) {
chip = (int) (offs >> this->chip_shift); chip = (int)(offs >> this->chip_shift);
chipsel = chip; chipsel = chip;
} else { } else {
chip = 0; 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 ? */ /* Write the bad block table to the device ? */
if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) { 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) if (res < 0)
goto out; goto out;
} }
/* Write the mirror bad block table to the device ? */ /* Write the mirror bad block table to the device ? */
if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) { 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: out:
kfree (buf); kfree(buf);
return res; 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 * 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; 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 * of the good / bad information, so we _must_ store
* this information in a good / bad table during * this information in a good / bad table during
* startup * startup
*/ */
if (this->options & NAND_IS_AND) { if (this->options & NAND_IS_AND) {
/* Use the default pattern descriptors */ /* Use the default pattern descriptors */
if (!this->bbt_td) { if (!this->bbt_td) {
@ -1054,10 +1052,9 @@ int nand_default_bbt (struct mtd_info *mtd)
this->bbt_md = &bbt_mirror_descr; this->bbt_md = &bbt_mirror_descr;
} }
this->options |= NAND_USE_FLASH_BBT; 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 ? */ /* Is a flash based bad block table requested ? */
if (this->options & NAND_USE_FLASH_BBT) { if (this->options & NAND_USE_FLASH_BBT) {
/* Use the default pattern descriptors */ /* Use the default pattern descriptors */
@ -1066,18 +1063,17 @@ int nand_default_bbt (struct mtd_info *mtd)
this->bbt_md = &bbt_mirror_descr; this->bbt_md = &bbt_mirror_descr;
} }
if (!this->badblock_pattern) { if (!this->badblock_pattern) {
this->badblock_pattern = (mtd->oobblock > 512) ? this->badblock_pattern = (mtd->oobblock > 512) ? &largepage_flashbased : &smallpage_flashbased;
&largepage_flashbased : &smallpage_flashbased;
} }
} else { } else {
this->bbt_td = NULL; this->bbt_td = NULL;
this->bbt_md = NULL; this->bbt_md = NULL;
if (!this->badblock_pattern) { if (!this->badblock_pattern) {
this->badblock_pattern = (mtd->oobblock > 512) ? 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 * @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; struct nand_chip *this = mtd->priv;
int block; int block;
uint8_t res; uint8_t res;
/* Get block number * 2 */ /* 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; 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", DEBUG(MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n",
(unsigned int)offs, block >> 1, res); (unsigned int)offs, block >> 1, res);
switch ((int)res) { switch ((int)res) {
case 0x00: return 0; case 0x00:
case 0x01: return 1; return 0;
case 0x02: return allowbbt ? 0 : 1; case 0x01:
return 1;
case 0x02:
return allowbbt ? 0 : 1;
} }
return 1; return 1;
} }
EXPORT_SYMBOL (nand_scan_bbt); EXPORT_SYMBOL(nand_scan_bbt);
EXPORT_SYMBOL (nand_default_bbt); EXPORT_SYMBOL(nand_default_bbt);

View File

@ -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 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
}; };
/** /**
* nand_trans_result - [GENERIC] create non-inverted ECC * nand_trans_result - [GENERIC] create non-inverted ECC
* @reg2: line parity reg 2 * @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 * Creates non-inverted ECC code from line parity
*/ */
static void nand_trans_result(u_char reg2, u_char reg3, static void nand_trans_result(u_char reg2, u_char reg3, u_char *ecc_code)
u_char *ecc_code)
{ {
u_char a, b, i, tmp1, tmp2; 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 */ /* Calculate first ECC byte */
for (i = 0; i < 4; i++) { 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; tmp1 |= b;
b >>= 1; b >>= 1;
if (reg2 & a) /* LP14,12,10,8 --> ecc_code[0] */ if (reg2 & a) /* LP14,12,10,8 --> ecc_code[0] */
tmp1 |= b; tmp1 |= b;
b >>= 1; b >>= 1;
a >>= 1; a >>= 1;
@ -94,10 +92,10 @@ static void nand_trans_result(u_char reg2, u_char reg3,
/* Calculate second ECC byte */ /* Calculate second ECC byte */
b = 0x80; b = 0x80;
for (i = 0; i < 4; i++) { 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; tmp2 |= b;
b >>= 1; b >>= 1;
if (reg2 & a) /* LP6,4,2,0 --> ecc_code[1] */ if (reg2 & a) /* LP6,4,2,0 --> ecc_code[1] */
tmp2 |= b; tmp2 |= b;
b >>= 1; b >>= 1;
a >>= 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; ecc_code[0] = ecc_code[1] = ecc_code[2] = 0;
/* Build up column parity */ /* Build up column parity */
for(j = 0; j < 256; j++) { for (j = 0; j < 256; j++) {
/* Get CP0 - CP5 from table */ /* Get CP0 - CP5 from table */
idx = nand_ecc_precalc_table[dat[j]]; 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) { if ((d1 | d2 | d3) == 0) {
/* No errors */ /* No errors */
return 0; return 0;
} } else {
else {
a = (d1 ^ (d1 >> 1)) & 0x55; a = (d1 ^ (d1 >> 1)) & 0x55;
b = (d2 ^ (d2 >> 1)) & 0x55; b = (d2 ^ (d2 >> 1)) & 0x55;
c = (d3 ^ (d3 >> 1)) & 0x54; 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; c = 0x80;
add = 0; add = 0;
a = 0x80; a = 0x80;
for (i=0; i<4; i++) { for (i = 0; i < 4; i++) {
if (d1 & c) if (d1 & c)
add |= a; add |= a;
c >>= 2; c >>= 2;
a >>= 1; a >>= 1;
} }
c = 0x80; c = 0x80;
for (i=0; i<4; i++) { for (i = 0; i < 4; i++) {
if (d2 & c) if (d2 & c)
add |= a; add |= a;
c >>= 2; 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; bit = 0;
b = 0x04; b = 0x04;
c = 0x80; c = 0x80;
for (i=0; i<3; i++) { for (i = 0; i < 3; i++) {
if (d3 & c) if (d3 & c)
bit |= b; bit |= b;
c >>= 2; 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); a ^= (b << bit);
dat[add] = a; dat[add] = a;
return 1; return 1;
} } else {
else {
i = 0; i = 0;
while (d1) { while (d1) {
if (d1 & 0x01) 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[1] = calc_ecc[1];
read_ecc[2] = calc_ecc[2]; read_ecc[2] = calc_ecc[2];
return 2; return 2;
} } else {
else {
/* Uncorrectable Error */ /* Uncorrectable Error */
return -1; return -1;
} }

View File

@ -125,13 +125,13 @@ struct nand_manufacturers nand_manuf_ids[] = {
{NAND_MFR_NATIONAL, "National"}, {NAND_MFR_NATIONAL, "National"},
{NAND_MFR_RENESAS, "Renesas"}, {NAND_MFR_RENESAS, "Renesas"},
{NAND_MFR_STMICRO, "ST Micro"}, {NAND_MFR_STMICRO, "ST Micro"},
{NAND_MFR_HYNIX, "Hynix"}, {NAND_MFR_HYNIX, "Hynix"},
{0x0, "Unknown"} {0x0, "Unknown"}
}; };
EXPORT_SYMBOL (nand_manuf_ids); EXPORT_SYMBOL(nand_manuf_ids);
EXPORT_SYMBOL (nand_flash_ids); EXPORT_SYMBOL(nand_flash_ids);
MODULE_LICENSE ("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR ("Thomas Gleixner <tglx@linutronix.de>"); MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
MODULE_DESCRIPTION ("Nand device & manufacturer ID's"); MODULE_DESCRIPTION("Nand device & manufacturer IDs");

View File

@ -58,21 +58,21 @@
/* /*
* MTD structure for PPChameleonEVB board * 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; static struct mtd_info *ppchameleonevb_mtd = NULL;
/* /*
* Module stuff * 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; static unsigned long ppchameleonevb_fio_pbase = CFG_NAND1_PADDR;
#ifdef MODULE #ifdef MODULE
module_param(ppchameleon_fio_pbase, ulong, 0); module_param(ppchameleon_fio_pbase, ulong, 0);
module_param(ppchameleonevb_fio_pbase, ulong, 0); module_param(ppchameleonevb_fio_pbase, ulong, 0);
#else #else
__setup("ppchameleon_fio_pbase=",ppchameleon_fio_pbase); __setup("ppchameleon_fio_pbase=", ppchameleon_fio_pbase);
__setup("ppchameleonevb_fio_pbase=",ppchameleonevb_fio_pbase); __setup("ppchameleonevb_fio_pbase=", ppchameleonevb_fio_pbase);
#endif #endif
#ifdef CONFIG_MTD_PARTITIONS #ifdef CONFIG_MTD_PARTITIONS
@ -80,80 +80,80 @@ __setup("ppchameleonevb_fio_pbase=",ppchameleonevb_fio_pbase);
* Define static partitions for flash devices * Define static partitions for flash devices
*/ */
static struct mtd_partition partition_info_hi[] = { static struct mtd_partition partition_info_hi[] = {
{ name: "PPChameleon HI Nand Flash", { .name = "PPChameleon HI Nand Flash",
offset: 0, offset = 0,
size: 128*1024*1024 } .size = 128 * 1024 * 1024
}
}; };
static struct mtd_partition partition_info_me[] = { static struct mtd_partition partition_info_me[] = {
{ name: "PPChameleon ME Nand Flash", { .name = "PPChameleon ME Nand Flash",
offset: 0, .offset = 0,
size: 32*1024*1024 } .size = 32 * 1024 * 1024
}
}; };
static struct mtd_partition partition_info_evb[] = { static struct mtd_partition partition_info_evb[] = {
{ name: "PPChameleonEVB Nand Flash", { .name = "PPChameleonEVB Nand Flash",
offset: 0, .offset = 0,
size: 32*1024*1024 } .size = 32 * 1024 * 1024
}
}; };
#define NUM_PARTITIONS 1 #define NUM_PARTITIONS 1
extern int parse_cmdline_partitions(struct mtd_info *master, extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, const char *mtd_id);
struct mtd_partition **pparts,
const char *mtd_id);
#endif #endif
/* /*
* hardware specific access to control-lines * hardware specific access to control-lines
*/ */
static void ppchameleon_hwcontrol(struct mtd_info *mtdinfo, int cmd) static void ppchameleon_hwcontrol(struct mtd_info *mtdinfo, int cmd)
{ {
switch(cmd) { switch (cmd) {
case NAND_CTL_SETCLE: case NAND_CTL_SETCLE:
MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND0_PADDR); MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND0_PADDR);
break; break;
case NAND_CTL_CLRCLE: case NAND_CTL_CLRCLE:
MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND0_PADDR); MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND0_PADDR);
break; break;
case NAND_CTL_SETALE: case NAND_CTL_SETALE:
MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND0_PADDR); MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND0_PADDR);
break; break;
case NAND_CTL_CLRALE: case NAND_CTL_CLRALE:
MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND0_PADDR); MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND0_PADDR);
break; break;
case NAND_CTL_SETNCE: case NAND_CTL_SETNCE:
MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND0_PADDR); MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND0_PADDR);
break; break;
case NAND_CTL_CLRNCE: case NAND_CTL_CLRNCE:
MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND0_PADDR); MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND0_PADDR);
break; break;
} }
} }
static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd) static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd)
{ {
switch(cmd) { switch (cmd) {
case NAND_CTL_SETCLE: case NAND_CTL_SETCLE:
MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND1_PADDR); MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND1_PADDR);
break; break;
case NAND_CTL_CLRCLE: case NAND_CTL_CLRCLE:
MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND1_PADDR); MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND1_PADDR);
break; break;
case NAND_CTL_SETALE: case NAND_CTL_SETALE:
MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND1_PADDR); MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND1_PADDR);
break; break;
case NAND_CTL_CLRALE: case NAND_CTL_CLRALE:
MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND1_PADDR); MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND1_PADDR);
break; break;
case NAND_CTL_SETNCE: case NAND_CTL_SETNCE:
MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND1_PADDR); MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND1_PADDR);
break; break;
case NAND_CTL_CLRNCE: case NAND_CTL_CLRNCE:
MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND1_PADDR); MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND1_PADDR);
break; break;
} }
} }
@ -164,15 +164,15 @@ static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd)
*/ */
static int ppchameleon_device_ready(struct mtd_info *minfo) 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 1;
return 0; return 0;
} }
static int ppchameleonevb_device_ready(struct mtd_info *minfo) static int ppchameleonevb_device_ready(struct mtd_info *minfo)
{ {
if (in_be32((volatile unsigned*)GPIO0_IR) & NAND_EVB_RB_GPIO_PIN) if (in_be32((volatile unsigned *)GPIO0_IR) & NAND_EVB_RB_GPIO_PIN)
return 1; return 1;
return 0; return 0;
} }
#endif #endif
@ -185,7 +185,7 @@ const char *part_probes_evb[] = { "cmdlinepart", NULL };
/* /*
* Main initialization routine * Main initialization routine
*/ */
static int __init ppchameleonevb_init (void) static int __init ppchameleonevb_init(void)
{ {
struct nand_chip *this; struct nand_chip *this;
const char *part_type = 0; const char *part_type = 0;
@ -194,13 +194,11 @@ static int __init ppchameleonevb_init (void)
void __iomem *ppchameleon_fio_base; void __iomem *ppchameleon_fio_base;
void __iomem *ppchameleonevb_fio_base; void __iomem *ppchameleonevb_fio_base;
/********************************* /*********************************
* Processor module NAND (if any) * * Processor module NAND (if any) *
*********************************/ *********************************/
/* Allocate memory for MTD device structure and private data */ /* Allocate memory for MTD device structure and private data */
ppchameleon_mtd = kmalloc(sizeof(struct mtd_info) + ppchameleon_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
sizeof(struct nand_chip), GFP_KERNEL);
if (!ppchameleon_mtd) { if (!ppchameleon_mtd) {
printk("Unable to allocate PPChameleon NAND MTD device structure.\n"); printk("Unable to allocate PPChameleon NAND MTD device structure.\n");
return -ENOMEM; return -ENOMEM;
@ -208,43 +206,45 @@ static int __init ppchameleonevb_init (void)
/* map physical address */ /* map physical address */
ppchameleon_fio_base = ioremap(ppchameleon_fio_pbase, SZ_4M); ppchameleon_fio_base = ioremap(ppchameleon_fio_pbase, SZ_4M);
if(!ppchameleon_fio_base) { if (!ppchameleon_fio_base) {
printk("ioremap PPChameleon NAND flash failed\n"); printk("ioremap PPChameleon NAND flash failed\n");
kfree(ppchameleon_mtd); kfree(ppchameleon_mtd);
return -EIO; return -EIO;
} }
/* Get pointer to private data */ /* Get pointer to private data */
this = (struct nand_chip *) (&ppchameleon_mtd[1]); this = (struct nand_chip *)(&ppchameleon_mtd[1]);
/* Initialize structures */ /* Initialize structures */
memset((char *) ppchameleon_mtd, 0, sizeof(struct mtd_info)); memset(ppchameleon_mtd, 0, sizeof(struct mtd_info));
memset((char *) this, 0, sizeof(struct nand_chip)); memset(this, 0, sizeof(struct nand_chip));
/* Link the private data with the MTD structure */ /* Link the private data with the MTD structure */
ppchameleon_mtd->priv = this; ppchameleon_mtd->priv = this;
/* Initialize GPIOs */ /* Initialize GPIOs */
/* Pin mapping for NAND chip */ /* Pin mapping for NAND chip */
/* /*
CE GPIO_01 CE GPIO_01
CLE GPIO_02 CLE GPIO_02
ALE GPIO_03 ALE GPIO_03
R/B GPIO_04 R/B GPIO_04
*/ */
/* output select */ /* 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 */ /* 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 */ /* 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 #ifdef USE_READY_BUSY_PIN
/* three-state select */ /* 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 */ /* 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 */ /* 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 #endif
/* insert callbacks */ /* insert callbacks */
@ -259,12 +259,11 @@ static int __init ppchameleonevb_init (void)
this->eccmode = NAND_ECC_SOFT; this->eccmode = NAND_ECC_SOFT;
/* Scan to find existence of the device (it could not be mounted) */ /* 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); iounmap((void *)ppchameleon_fio_base);
kfree (ppchameleon_mtd); kfree(ppchameleon_mtd);
goto nand_evb_init; goto nand_evb_init;
} }
#ifndef USE_READY_BUSY_PIN #ifndef USE_READY_BUSY_PIN
/* Adjust delay if necessary */ /* Adjust delay if necessary */
if (ppchameleon_mtd->size == NAND_SMALL_SIZE) if (ppchameleon_mtd->size == NAND_SMALL_SIZE)
@ -275,12 +274,11 @@ static int __init ppchameleonevb_init (void)
ppchameleon_mtd->name = "ppchameleon-nand"; ppchameleon_mtd->name = "ppchameleon-nand";
mtd_parts_nb = parse_mtd_partitions(ppchameleon_mtd, part_probes, &mtd_parts, 0); mtd_parts_nb = parse_mtd_partitions(ppchameleon_mtd, part_probes, &mtd_parts, 0);
if (mtd_parts_nb > 0) if (mtd_parts_nb > 0)
part_type = "command line"; part_type = "command line";
else else
mtd_parts_nb = 0; mtd_parts_nb = 0;
#endif #endif
if (mtd_parts_nb == 0) if (mtd_parts_nb == 0) {
{
if (ppchameleon_mtd->size == NAND_SMALL_SIZE) if (ppchameleon_mtd->size == NAND_SMALL_SIZE)
mtd_parts = partition_info_me; mtd_parts = partition_info_me;
else else
@ -293,13 +291,12 @@ static int __init ppchameleonevb_init (void)
printk(KERN_NOTICE "Using %s partition definition\n", part_type); printk(KERN_NOTICE "Using %s partition definition\n", part_type);
add_mtd_partitions(ppchameleon_mtd, mtd_parts, mtd_parts_nb); add_mtd_partitions(ppchameleon_mtd, mtd_parts, mtd_parts_nb);
nand_evb_init: nand_evb_init:
/**************************** /****************************
* EVB NAND (always present) * * EVB NAND (always present) *
****************************/ ****************************/
/* Allocate memory for MTD device structure and private data */ /* Allocate memory for MTD device structure and private data */
ppchameleonevb_mtd = kmalloc(sizeof(struct mtd_info) + ppchameleonevb_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
sizeof(struct nand_chip), GFP_KERNEL);
if (!ppchameleonevb_mtd) { if (!ppchameleonevb_mtd) {
printk("Unable to allocate PPChameleonEVB NAND MTD device structure.\n"); printk("Unable to allocate PPChameleonEVB NAND MTD device structure.\n");
return -ENOMEM; return -ENOMEM;
@ -307,46 +304,47 @@ static int __init ppchameleonevb_init (void)
/* map physical address */ /* map physical address */
ppchameleonevb_fio_base = ioremap(ppchameleonevb_fio_pbase, SZ_4M); ppchameleonevb_fio_base = ioremap(ppchameleonevb_fio_pbase, SZ_4M);
if(!ppchameleonevb_fio_base) { if (!ppchameleonevb_fio_base) {
printk("ioremap PPChameleonEVB NAND flash failed\n"); printk("ioremap PPChameleonEVB NAND flash failed\n");
kfree(ppchameleonevb_mtd); kfree(ppchameleonevb_mtd);
return -EIO; return -EIO;
} }
/* Get pointer to private data */ /* Get pointer to private data */
this = (struct nand_chip *) (&ppchameleonevb_mtd[1]); this = (struct nand_chip *)(&ppchameleonevb_mtd[1]);
/* Initialize structures */ /* Initialize structures */
memset((char *) ppchameleonevb_mtd, 0, sizeof(struct mtd_info)); memset(ppchameleonevb_mtd, 0, sizeof(struct mtd_info));
memset((char *) this, 0, sizeof(struct nand_chip)); memset(this, 0, sizeof(struct nand_chip));
/* Link the private data with the MTD structure */ /* Link the private data with the MTD structure */
ppchameleonevb_mtd->priv = this; ppchameleonevb_mtd->priv = this;
/* Initialize GPIOs */ /* Initialize GPIOs */
/* Pin mapping for NAND chip */ /* Pin mapping for NAND chip */
/* /*
CE GPIO_14 CE GPIO_14
CLE GPIO_15 CLE GPIO_15
ALE GPIO_16 ALE GPIO_16
R/B GPIO_31 R/B GPIO_31
*/ */
/* output select */ /* output select */
out_be32((volatile unsigned*)GPIO0_OSRH, in_be32((volatile unsigned*)GPIO0_OSRH) & 0xFFFFFFF0); 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_OSRL, in_be32((volatile unsigned *)GPIO0_OSRL) & 0x3FFFFFFF);
/* three-state select */ /* three-state select */
out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xFFFFFFF0); 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_TSRL, in_be32((volatile unsigned *)GPIO0_TSRL) & 0x3FFFFFFF);
/* enable output driver */ /* 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); NAND_EVB_CLE_GPIO_PIN | NAND_EVB_ALE_GPIO_PIN);
#ifdef USE_READY_BUSY_PIN #ifdef USE_READY_BUSY_PIN
/* three-state select */ /* 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 */ /* 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 */ /* 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 #endif
/* insert callbacks */ /* insert callbacks */
@ -362,22 +360,20 @@ static int __init ppchameleonevb_init (void)
this->eccmode = NAND_ECC_SOFT; this->eccmode = NAND_ECC_SOFT;
/* Scan to find existence of the device */ /* Scan to find existence of the device */
if (nand_scan (ppchameleonevb_mtd, 1)) { if (nand_scan(ppchameleonevb_mtd, 1)) {
iounmap((void *)ppchameleonevb_fio_base); iounmap((void *)ppchameleonevb_fio_base);
kfree (ppchameleonevb_mtd); kfree(ppchameleonevb_mtd);
return -ENXIO; return -ENXIO;
} }
#ifdef CONFIG_MTD_PARTITIONS #ifdef CONFIG_MTD_PARTITIONS
ppchameleonevb_mtd->name = NAND_EVB_MTD_NAME; ppchameleonevb_mtd->name = NAND_EVB_MTD_NAME;
mtd_parts_nb = parse_mtd_partitions(ppchameleonevb_mtd, part_probes_evb, &mtd_parts, 0); mtd_parts_nb = parse_mtd_partitions(ppchameleonevb_mtd, part_probes_evb, &mtd_parts, 0);
if (mtd_parts_nb > 0) if (mtd_parts_nb > 0)
part_type = "command line"; part_type = "command line";
else else
mtd_parts_nb = 0; mtd_parts_nb = 0;
#endif #endif
if (mtd_parts_nb == 0) if (mtd_parts_nb == 0) {
{
mtd_parts = partition_info_evb; mtd_parts = partition_info_evb;
mtd_parts_nb = NUM_PARTITIONS; mtd_parts_nb = NUM_PARTITIONS;
part_type = "static"; part_type = "static";
@ -390,18 +386,19 @@ static int __init ppchameleonevb_init (void)
/* Return happy */ /* Return happy */
return 0; return 0;
} }
module_init(ppchameleonevb_init); module_init(ppchameleonevb_init);
/* /*
* Clean up routine * Clean up routine
*/ */
static void __exit ppchameleonevb_cleanup (void) static void __exit ppchameleonevb_cleanup(void)
{ {
struct nand_chip *this; struct nand_chip *this;
/* Release resources, unregister device(s) */ /* Release resources, unregister device(s) */
nand_release (ppchameleon_mtd); nand_release(ppchameleon_mtd);
nand_release (ppchameleonevb_mtd); nand_release(ppchameleonevb_mtd);
/* Release iomaps */ /* Release iomaps */
this = (struct nand_chip *) &ppchameleon_mtd[1]; this = (struct nand_chip *) &ppchameleon_mtd[1];

View File

@ -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 void __iomem *rtc_from4_fio_base = (void *)P2SEGADDR(RTC_FROM4_FIO_BASE);
static const struct mtd_partition partition_info[] = { static const struct mtd_partition partition_info[] = {
{ {
.name = "Renesas flash partition 1", .name = "Renesas flash partition 1",
.offset = 0, .offset = 0,
.size = MTDPART_SIZ_FULL .size = MTDPART_SIZ_FULL},
},
}; };
#define NUM_PARTITIONS 1 #define NUM_PARTITIONS 1
/* /*
@ -111,8 +111,8 @@ static const struct mtd_partition partition_info[] = {
* NAND_BBT_CREATE and/or NAND_BBT_WRITE * NAND_BBT_CREATE and/or NAND_BBT_WRITE
* *
*/ */
static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' }; static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' }; static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
static struct nand_bbt_descr rtc_from4_bbt_main_descr = { static struct nand_bbt_descr rtc_from4_bbt_main_descr = {
.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE .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 .pattern = mirror_pattern
}; };
#ifdef RTC_FROM4_HWECC #ifdef RTC_FROM4_HWECC
/* the Reed Solomon control structure */ /* the Reed Solomon control structure */
@ -148,11 +146,11 @@ static struct nand_oobinfo rtc_from4_nand_oobinfo = {
.useecc = MTD_NANDECC_AUTOPLACE, .useecc = MTD_NANDECC_AUTOPLACE,
.eccbytes = 32, .eccbytes = 32,
.eccpos = { .eccpos = {
0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31}, 24, 25, 26, 27, 28, 29, 30, 31},
.oobfree = { {32, 32} } .oobfree = {{32, 32}}
}; };
/* Aargh. I missed the reversed bit order, when I /* 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 * of the ecc byte which we get from the FPGA
*/ */
static uint8_t revbits[256] = { static uint8_t revbits[256] = {
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
}; };
#endif #endif
/* /*
* rtc_from4_hwcontrol - hardware specific access to control-lines * rtc_from4_hwcontrol - hardware specific access to control-lines
* @mtd: MTD device structure * @mtd: MTD device structure
@ -214,9 +210,9 @@ static uint8_t revbits[256] = {
*/ */
static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd) 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: case NAND_CTL_SETCLE:
this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_CLE); 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 * rtc_from4_nand_select_chip - hardware specific chip select
* @mtd: MTD device structure * @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) 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_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); 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_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); this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_NAND_ADDR_SLOT3);
break; break;
case 1: /* select slot 4 chip */ 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_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); 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 * rtc_from4_nand_device_ready - hardware specific ready/busy check
* @mtd: MTD device structure * @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 * deplete - code to perform device recovery in case there was a power loss
* @mtd: MTD device structure * @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) 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 */ /* wait until device is ready */
while (!this->dev_ready(mtd)); while (!this->dev_ready(mtd)) ;
this->select_chip(mtd, chip); this->select_chip(mtd, chip);
/* Send the commands for device recovery, phase 1 */ /* Send the commands for device recovery, phase 1 */
this->cmdfunc (mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0000); this->cmdfunc(mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0000);
this->cmdfunc (mtd, NAND_CMD_DEPLETE2, -1, -1); this->cmdfunc(mtd, NAND_CMD_DEPLETE2, -1, -1);
/* Send the commands for device recovery, phase 2 */ /* Send the commands for device recovery, phase 2 */
this->cmdfunc (mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0004); this->cmdfunc(mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0004);
this->cmdfunc (mtd, NAND_CMD_DEPLETE2, -1, -1); this->cmdfunc(mtd, NAND_CMD_DEPLETE2, -1, -1);
} }
#ifdef RTC_FROM4_HWECC #ifdef RTC_FROM4_HWECC
/* /*
* rtc_from4_enable_hwecc - hardware specific hardware ECC enable function * 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) 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; unsigned short status;
switch (mode) { switch (mode) {
case NAND_ECC_READ : case NAND_ECC_READ:
status = RTC_FROM4_RS_ECC_CTL_CLR status = RTC_FROM4_RS_ECC_CTL_CLR | RTC_FROM4_RS_ECC_CTL_FD_E;
| RTC_FROM4_RS_ECC_CTL_FD_E;
*rs_ecc_ctl = status; *rs_ecc_ctl = status;
break; break;
case NAND_ECC_READSYN : case NAND_ECC_READSYN:
status = 0x00; status = 0x00;
*rs_ecc_ctl = status; *rs_ecc_ctl = status;
break; break;
case NAND_ECC_WRITE : case NAND_ECC_WRITE:
status = RTC_FROM4_RS_ECC_CTL_CLR status = RTC_FROM4_RS_ECC_CTL_CLR | RTC_FROM4_RS_ECC_CTL_GEN | RTC_FROM4_RS_ECC_CTL_FD_E;
| RTC_FROM4_RS_ECC_CTL_GEN
| RTC_FROM4_RS_ECC_CTL_FD_E;
*rs_ecc_ctl = status; *rs_ecc_ctl = status;
break; break;
default: default:
BUG(); BUG();
break; break;
} }
} }
/* /*
* rtc_from4_calculate_ecc - hardware specific code to read ECC code * rtc_from4_calculate_ecc - hardware specific code to read ECC code
* @mtd: MTD device structure * @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) 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; unsigned short value;
int i; 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) */ ecc_code[7] |= 0x0f; /* set the last four bits (not used) */
} }
/* /*
* rtc_from4_correct_data - hardware specific code to correct data using ECC code * rtc_from4_correct_data - hardware specific code to correct data using ECC code
* @mtd: MTD device structure * @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; unsigned short status;
uint16_t par[6], syn[6]; uint16_t par[6], syn[6];
uint8_t ecc[8]; 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)); 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 */ /* Read the syndrom pattern from the FPGA and correct the bitorder */
rs_ecc = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC); rs_ecc = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC);
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
ecc[i] = revbits[(*rs_ecc) & 0xFF]; ecc[i] = revbits[(*rs_ecc) & 0xFF];
rs_ecc++; rs_ecc++;
} }
/* convert into 6 10bit syndrome fields */ /* convert into 6 10bit syndrome fields */
par[5] = rs_decoder->index_of[(((uint16_t)ecc[0] >> 0) & 0x0ff) | par[5] = rs_decoder->index_of[(((uint16_t) ecc[0] >> 0) & 0x0ff) | (((uint16_t) ecc[1] << 8) & 0x300)];
(((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[4] = rs_decoder->index_of[(((uint16_t)ecc[1] >> 2) & 0x03f) | par[3] = rs_decoder->index_of[(((uint16_t) ecc[2] >> 4) & 0x00f) | (((uint16_t) ecc[3] << 4) & 0x3f0)];
(((uint16_t)ecc[2] << 6) & 0x3c0)]; par[2] = rs_decoder->index_of[(((uint16_t) ecc[3] >> 6) & 0x003) | (((uint16_t) ecc[4] << 2) & 0x3fc)];
par[3] = rs_decoder->index_of[(((uint16_t)ecc[2] >> 4) & 0x00f) | par[1] = rs_decoder->index_of[(((uint16_t) ecc[5] >> 0) & 0x0ff) | (((uint16_t) ecc[6] << 8) & 0x300)];
(((uint16_t)ecc[3] << 4) & 0x3f0)]; par[0] = (((uint16_t) ecc[6] >> 2) & 0x03f) | (((uint16_t) ecc[7] << 6) & 0x3c0);
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 */ /* Convert to computable syndrome */
for (i = 0; i < 6; i++) { 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]]; syn[i] = rs_decoder->index_of[syn[i]];
} }
/* Let the library code do its magic.*/ /* Let the library code do its magic. */
res = decode_rs8(rs_decoder, (uint8_t *)buf, par, 512, syn, 0, NULL, 0xff, NULL); res = decode_rs8(rs_decoder, (uint8_t *) buf, par, 512, syn, 0, NULL, 0xff, NULL);
if (res > 0) { if (res > 0) {
DEBUG (MTD_DEBUG_LEVEL0, "rtc_from4_correct_data: " DEBUG(MTD_DEBUG_LEVEL0, "rtc_from4_correct_data: " "ECC corrected %d errors on read\n", res);
"ECC corrected %d errors on read\n", res);
} }
return res; return res;
} }
/** /**
* rtc_from4_errstat - perform additional error status checks * rtc_from4_errstat - perform additional error status checks
* @mtd: MTD device structure * @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) static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page)
{ {
int er_stat=0; int er_stat = 0;
int rtn, retlen; int rtn, retlen;
size_t len; size_t len;
uint8_t *buf; 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) { if (state == FL_ERASING) {
for (i=0; i<4; i++) { for (i = 0; i < 4; i++) {
if (status & 1<<(i+1)) { if (status & 1 << (i + 1)) {
this->cmdfunc (mtd, (NAND_CMD_STATUS_ERROR + i + 1), -1, -1); this->cmdfunc(mtd, (NAND_CMD_STATUS_ERROR + i + 1), -1, -1);
rtn = this->read_byte(mtd); 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)) { 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) { } else if (state == FL_WRITING) {
/* single bank write logic */ /* 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); 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)) { if (!(rtn & ERR_STAT_ECC_AVAILABLE)) {
er_stat |= 1<<1; /* err_ecc_not_avail */ er_stat |= 1 << 1; /* err_ecc_not_avail */
} else { } else {
len = mtd->oobblock; len = mtd->oobblock;
buf = kmalloc (len, GFP_KERNEL); buf = kmalloc(len, GFP_KERNEL);
if (!buf) { if (!buf) {
printk (KERN_ERR "rtc_from4_errstat: Out of memory!\n"); printk(KERN_ERR "rtc_from4_errstat: Out of memory!\n");
er_stat = 1; /* if we can't check, assume failed */ er_stat = 1; /* if we can't check, assume failed */
} else { } else {
/* recovery read */ /* recovery read */
/* page 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 */ 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); kfree(buf);
} }
@ -525,7 +505,7 @@ static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, int s
} }
rtn = status; 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 */ 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 #endif
/* /*
* Main initialization routine * Main initialization routine
*/ */
int __init rtc_from4_init (void) int __init rtc_from4_init(void)
{ {
struct nand_chip *this; struct nand_chip *this;
unsigned short bcr1, bcr2, wcr2; unsigned short bcr1, bcr2, wcr2;
int i; int i;
/* Allocate memory for MTD device structure and private data */ /* Allocate memory for MTD device structure and private data */
rtc_from4_mtd = kmalloc(sizeof(struct mtd_info) + sizeof (struct nand_chip), rtc_from4_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
GFP_KERNEL);
if (!rtc_from4_mtd) { 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; return -ENOMEM;
} }
/* Get pointer to private data */ /* Get pointer to private data */
this = (struct nand_chip *) (&rtc_from4_mtd[1]); this = (struct nand_chip *)(&rtc_from4_mtd[1]);
/* Initialize structures */ /* Initialize structures */
memset((char *) rtc_from4_mtd, 0, sizeof(struct mtd_info)); memset(rtc_from4_mtd, 0, sizeof(struct mtd_info));
memset((char *) this, 0, sizeof(struct nand_chip)); memset(this, 0, sizeof(struct nand_chip));
/* Link the private data with the MTD structure */ /* Link the private data with the MTD structure */
rtc_from4_mtd->priv = this; rtc_from4_mtd->priv = this;
@ -582,7 +560,7 @@ int __init rtc_from4_init (void)
/* Set address of hardware control function */ /* Set address of hardware control function */
this->hwcontrol = rtc_from4_hwcontrol; this->hwcontrol = rtc_from4_hwcontrol;
/* Set address of chip select function */ /* 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) */ /* command delay time (in us) */
this->chip_delay = 100; this->chip_delay = 100;
/* return the status of the Ready/Busy line */ /* return the status of the Ready/Busy line */
@ -591,7 +569,7 @@ int __init rtc_from4_init (void)
#ifdef RTC_FROM4_HWECC #ifdef RTC_FROM4_HWECC
printk(KERN_INFO "rtc_from4_init: using hardware ECC detection.\n"); 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; this->options |= NAND_HWECC_SYNDROME;
/* return the status of extra status and ECC checks */ /* return the status of extra status and ECC checks */
this->errstat = rtc_from4_errstat; 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. */ /* 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); deplete(rtc_from4_mtd, i);
} }
@ -643,7 +621,7 @@ int __init rtc_from4_init (void)
*/ */
rs_decoder = init_rs(10, 0x409, 0, 1, 6); rs_decoder = init_rs(10, 0x409, 0, 1, 6);
if (!rs_decoder) { 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); nand_release(rtc_from4_mtd);
kfree(rtc_from4_mtd); kfree(rtc_from4_mtd);
return -ENOMEM; return -ENOMEM;
@ -652,20 +630,20 @@ int __init rtc_from4_init (void)
/* Return happy */ /* Return happy */
return 0; return 0;
} }
module_init(rtc_from4_init);
module_init(rtc_from4_init);
/* /*
* Clean up routine * Clean up routine
*/ */
#ifdef MODULE #ifdef MODULE
static void __exit rtc_from4_cleanup (void) static void __exit rtc_from4_cleanup(void)
{ {
/* Release resource, unregister partitions */ /* Release resource, unregister partitions */
nand_release(rtc_from4_mtd); nand_release(rtc_from4_mtd);
/* Free the MTD device structure */ /* Free the MTD device structure */
kfree (rtc_from4_mtd); kfree(rtc_from4_mtd);
#ifdef RTC_FROM4_HWECC #ifdef RTC_FROM4_HWECC
/* Free the reed solomon resources */ /* Free the reed solomon resources */
@ -674,10 +652,10 @@ static void __exit rtc_from4_cleanup (void)
} }
#endif #endif
} }
module_exit(rtc_from4_cleanup); module_exit(rtc_from4_cleanup);
#endif #endif
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("d.marlin <dmarlin@redhat.com"); MODULE_AUTHOR("d.marlin <dmarlin@redhat.com");
MODULE_DESCRIPTION("Board-specific glue layer for AG-AND flash on Renesas FROM_BOARD4"); MODULE_DESCRIPTION("Board-specific glue layer for AG-AND flash on Renesas FROM_BOARD4");

View File

@ -77,10 +77,10 @@ static int hardware_ecc = 0;
*/ */
static struct nand_oobinfo nand_hw_eccoob = { static struct nand_oobinfo nand_hw_eccoob = {
.useecc = MTD_NANDECC_AUTOPLACE, .useecc = MTD_NANDECC_AUTOPLACE,
.eccbytes = 3, .eccbytes = 3,
.eccpos = {0, 1, 2 }, .eccpos = {0, 1, 2},
.oobfree = { {8, 8} } .oobfree = {{8, 8}}
}; };
/* controller and mtd information */ /* 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); pr_debug("result %d from %ld, %d\n", result, clk, wanted);
if (result > max) { if (result > max) {
printk("%d ns is too big for current clock rate %ld\n", printk("%d ns is too big for current clock rate %ld\n", wanted, clk);
wanted, clk);
return -1; return -1;
} }
@ -164,8 +163,7 @@ static int s3c2410_nand_calc_rate(int wanted, unsigned long clk, int max)
/* controller setup */ /* controller setup */
static int s3c2410_nand_inithw(struct s3c2410_nand_info *info, static int s3c2410_nand_inithw(struct s3c2410_nand_info *info, struct platform_device *pdev)
struct platform_device *pdev)
{ {
struct s3c2410_platform_nand *plat = to_nand_plat(pdev); struct s3c2410_platform_nand *plat = to_nand_plat(pdev);
unsigned long clkrate = clk_get_rate(info->clk); 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 */ clkrate /= 1000; /* turn clock into kHz for ease of use */
if (plat != NULL) { 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); twrph0 = s3c2410_nand_calc_rate(plat->twrph0, clkrate, 8);
twrph1 = s3c2410_nand_calc_rate(plat->twrph1, clkrate, 8); twrph1 = s3c2410_nand_calc_rate(plat->twrph1, clkrate, 8);
} else { } 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", printk(KERN_INFO PFX "Tacls=%d, %dns Twrph0=%d %dns, Twrph1=%d %dns\n",
tacls, to_ns(tacls, clkrate), tacls, to_ns(tacls, clkrate), twrph0, to_ns(twrph0, clkrate), twrph1, to_ns(twrph1, clkrate));
twrph0, to_ns(twrph0, clkrate),
twrph1, to_ns(twrph1, clkrate));
if (!info->is_s3c2440) { if (!info->is_s3c2440) {
cfg = S3C2410_NFCONF_EN; cfg = S3C2410_NFCONF_EN;
cfg |= S3C2410_NFCONF_TACLS(tacls-1); cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
cfg |= S3C2410_NFCONF_TWRPH0(twrph0-1); cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
cfg |= S3C2410_NFCONF_TWRPH1(twrph1-1); cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
} else { } else {
cfg = S3C2440_NFCONF_TACLS(tacls-1); cfg = S3C2440_NFCONF_TACLS(tacls - 1);
cfg |= S3C2440_NFCONF_TWRPH0(twrph0-1); cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
cfg |= S3C2440_NFCONF_TWRPH1(twrph1-1); cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
} }
pr_debug(PFX "NF_CONF is 0x%lx\n", cfg); 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; info = nmtd->info;
bit = (info->is_s3c2440) ? S3C2440_NFCONT_nFCE : S3C2410_NFCONF_nFCE; 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); 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 != NULL) {
if (info->platform->select_chip != NULL) if (info->platform->select_chip != NULL)
(info->platform->select_chip)(nmtd->set, chip); (info->platform->select_chip) (nmtd->set, chip);
} }
cur &= ~bit; cur &= ~bit;
@ -330,22 +326,16 @@ static int s3c2410_nand_devready(struct mtd_info *mtd)
return readb(info->regs + S3C2410_NFSTAT) & S3C2410_NFSTAT_BUSY; return readb(info->regs + S3C2410_NFSTAT) & S3C2410_NFSTAT_BUSY;
} }
/* ECC handling functions */ /* ECC handling functions */
static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat, static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
u_char *read_ecc, u_char *calc_ecc)
{ {
pr_debug("s3c2410_nand_correct_data(%p,%p,%p,%p)\n", pr_debug("s3c2410_nand_correct_data(%p,%p,%p,%p)\n", mtd, dat, read_ecc, calc_ecc);
mtd, dat, read_ecc, calc_ecc);
pr_debug("eccs: read %02x,%02x,%02x vs calc %02x,%02x,%02x\n", pr_debug("eccs: read %02x,%02x,%02x vs calc %02x,%02x,%02x\n",
read_ecc[0], read_ecc[1], read_ecc[2], read_ecc[0], read_ecc[1], read_ecc[2], calc_ecc[0], calc_ecc[1], calc_ecc[2]);
calc_ecc[0], calc_ecc[1], calc_ecc[2]);
if (read_ecc[0] == calc_ecc[0] && if (read_ecc[0] == calc_ecc[0] && read_ecc[1] == calc_ecc[1] && read_ecc[2] == calc_ecc[2])
read_ecc[1] == calc_ecc[1] &&
read_ecc[2] == calc_ecc[2])
return 0; return 0;
/* we curently have no method for correcting the error */ /* 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); writel(ctrl | S3C2440_NFCONT_INITECC, info->regs + S3C2440_NFCONT);
} }
static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
const u_char *dat, u_char *ecc_code)
{ {
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); 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[1] = readb(info->regs + S3C2410_NFECC + 1);
ecc_code[2] = readb(info->regs + S3C2410_NFECC + 2); ecc_code[2] = readb(info->regs + S3C2410_NFECC + 2);
pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n", pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n", ecc_code[0], ecc_code[1], ecc_code[2]);
ecc_code[0], ecc_code[1], ecc_code[2]);
return 0; 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); struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
unsigned long ecc = readl(info->regs + S3C2440_NFMECC0); 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[1] = ecc >> 8;
ecc_code[2] = ecc >> 16; ecc_code[2] = ecc >> 16;
pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n", pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n", ecc_code[0], ecc_code[1], ecc_code[2]);
ecc_code[0], ecc_code[1], ecc_code[2]);
return 0; return 0;
} }
/* over-ride the standard functions for a little more speed. We can /* 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 * 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); readsb(this->IO_ADDR_R, buf, len);
} }
static void s3c2410_nand_write_buf(struct mtd_info *mtd, static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
const u_char *buf, int len)
{ {
struct nand_chip *this = mtd->priv; struct nand_chip *this = mtd->priv;
writesb(this->IO_ADDR_W, buf, len); 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); return add_mtd_device(&mtd->mtd);
if (set->nr_partitions > 0 && set->partitions != NULL) { if (set->nr_partitions > 0 && set->partitions != NULL) {
return add_mtd_partitions(&mtd->mtd, return add_mtd_partitions(&mtd->mtd, set->partitions, set->nr_partitions);
set->partitions,
set->nr_partitions);
} }
return add_mtd_device(&mtd->mtd); 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; nmtd = info->mtds;
for (setno = 0; setno < nr_sets; setno++, nmtd++) { for (setno = 0; setno < nr_sets; setno++, nmtd++) {
pr_debug("initialising set %d (%p, info %p)\n", pr_debug("initialising set %d (%p, info %p)\n", setno, nmtd, info);
setno, nmtd, info);
s3c2410_nand_init_chip(info, nmtd, sets); s3c2410_nand_init_chip(info, nmtd, sets);
nmtd->scan_res = nand_scan(&nmtd->mtd, nmtd->scan_res = nand_scan(&nmtd->mtd, (sets) ? sets->nr_chips : 1);
(sets) ? sets->nr_chips : 1);
if (nmtd->scan_res == 0) { if (nmtd->scan_res == 0) {
s3c2410_nand_add_partition(info, nmtd, sets); s3c2410_nand_add_partition(info, nmtd, sets);

View File

@ -46,7 +46,6 @@ static int sharpsl_phys_base = 0x0C000000;
#define FLCLE (1 << 1) #define FLCLE (1 << 1)
#define FLCE0 (1 << 0) #define FLCE0 (1 << 0)
/* /*
* MTD structure for SharpSL * MTD structure for SharpSL
*/ */
@ -60,27 +59,26 @@ static struct mtd_info *sharpsl_mtd = NULL;
static int nr_partitions; static int nr_partitions;
static struct mtd_partition sharpsl_nand_default_partition_info[] = { static struct mtd_partition sharpsl_nand_default_partition_info[] = {
{ {
.name = "System Area", .name = "System Area",
.offset = 0, .offset = 0,
.size = 7 * 1024 * 1024, .size = 7 * 1024 * 1024,
}, },
{ {
.name = "Root Filesystem", .name = "Root Filesystem",
.offset = 7 * 1024 * 1024, .offset = 7 * 1024 * 1024,
.size = 30 * 1024 * 1024, .size = 30 * 1024 * 1024,
}, },
{ {
.name = "Home Filesystem", .name = "Home Filesystem",
.offset = MTDPART_OFS_APPEND , .offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL , .size = MTDPART_SIZ_FULL,
}, },
}; };
/* /*
* hardware specific access to control-lines * hardware specific access to control-lines
*/ */
static void static void sharpsl_nand_hwcontrol(struct mtd_info *mtd, int cmd)
sharpsl_nand_hwcontrol(struct mtd_info* mtd, int cmd)
{ {
switch (cmd) { switch (cmd) {
case NAND_CTL_SETCLE: case NAND_CTL_SETCLE:
@ -98,10 +96,10 @@ sharpsl_nand_hwcontrol(struct mtd_info* mtd, int cmd)
break; break;
case NAND_CTL_SETNCE: case NAND_CTL_SETNCE:
writeb(readb(FLASHCTL) & ~(FLCE0|FLCE1), FLASHCTL); writeb(readb(FLASHCTL) & ~(FLCE0 | FLCE1), FLASHCTL);
break; break;
case NAND_CTL_CLRNCE: case NAND_CTL_CLRNCE:
writeb(readb(FLASHCTL) | (FLCE0|FLCE1), FLASHCTL); writeb(readb(FLASHCTL) | (FLCE0 | FLCE1), FLASHCTL);
break; break;
} }
} }
@ -126,27 +124,23 @@ static struct nand_oobinfo akita_oobinfo = {
.useecc = MTD_NANDECC_AUTOPLACE, .useecc = MTD_NANDECC_AUTOPLACE,
.eccbytes = 24, .eccbytes = 24,
.eccpos = { .eccpos = {
0x5, 0x1, 0x2, 0x3, 0x6, 0x7, 0x15, 0x11, 0x5, 0x1, 0x2, 0x3, 0x6, 0x7, 0x15, 0x11,
0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23, 0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23,
0x26, 0x27, 0x35, 0x31, 0x32, 0x33, 0x36, 0x37}, 0x26, 0x27, 0x35, 0x31, 0x32, 0x33, 0x36, 0x37},
.oobfree = { {0x08, 0x09} } .oobfree = {{0x08, 0x09}}
}; };
static int static int sharpsl_nand_dev_ready(struct mtd_info *mtd)
sharpsl_nand_dev_ready(struct mtd_info* mtd)
{ {
return !((readb(FLASHCTL) & FLRYBY) == 0); return !((readb(FLASHCTL) & FLRYBY) == 0);
} }
static void static void sharpsl_nand_enable_hwecc(struct mtd_info *mtd, int mode)
sharpsl_nand_enable_hwecc(struct mtd_info* mtd, int mode)
{ {
writeb(0 ,ECCCLRR); writeb(0, ECCCLRR);
} }
static int static int sharpsl_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat, u_char * ecc_code)
sharpsl_nand_calculate_ecc(struct mtd_info* mtd, const u_char* dat,
u_char* ecc_code)
{ {
ecc_code[0] = ~readb(ECCLPUB); ecc_code[0] = ~readb(ECCLPUB);
ecc_code[1] = ~readb(ECCLPLB); 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; return readb(ECCCNTR) != 0;
} }
#ifdef CONFIG_MTD_PARTITIONS #ifdef CONFIG_MTD_PARTITIONS
const char *part_probes[] = { "cmdlinepart", NULL }; const char *part_probes[] = { "cmdlinepart", NULL };
#endif #endif
/* /*
* Main initialization routine * Main initialization routine
*/ */
int __init int __init sharpsl_nand_init(void)
sharpsl_nand_init(void)
{ {
struct nand_chip *this; struct nand_chip *this;
struct mtd_partition* sharpsl_partition_info; struct mtd_partition *sharpsl_partition_info;
int err = 0; int err = 0;
/* Allocate memory for MTD device structure and private data */ /* Allocate memory for MTD device structure and private data */
sharpsl_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), sharpsl_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
GFP_KERNEL);
if (!sharpsl_mtd) { 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; return -ENOMEM;
} }
/* map physical adress */ /* map physical adress */
sharpsl_io_base = ioremap(sharpsl_phys_base, 0x1000); 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"); printk("ioremap to access Sharp SL NAND chip failed\n");
kfree(sharpsl_mtd); kfree(sharpsl_mtd);
return -EIO; return -EIO;
} }
/* Get pointer to private data */ /* Get pointer to private data */
this = (struct nand_chip *) (&sharpsl_mtd[1]); this = (struct nand_chip *)(&sharpsl_mtd[1]);
/* Initialize structures */ /* Initialize structures */
memset((char *) sharpsl_mtd, 0, sizeof(struct mtd_info)); memset(sharpsl_mtd, 0, sizeof(struct mtd_info));
memset((char *) this, 0, sizeof(struct nand_chip)); memset(this, 0, sizeof(struct nand_chip));
/* Link the private data with the MTD structure */ /* Link the private data with the MTD structure */
sharpsl_mtd->priv = this; sharpsl_mtd->priv = this;
@ -221,7 +211,7 @@ sharpsl_nand_init(void)
this->correct_data = nand_correct_data; this->correct_data = nand_correct_data;
/* Scan to find existence of the device */ /* Scan to find existence of the device */
err=nand_scan(sharpsl_mtd,1); err = nand_scan(sharpsl_mtd, 1);
if (err) { if (err) {
iounmap(sharpsl_io_base); iounmap(sharpsl_io_base);
kfree(sharpsl_mtd); kfree(sharpsl_mtd);
@ -230,24 +220,23 @@ sharpsl_nand_init(void)
/* Register the partitions */ /* Register the partitions */
sharpsl_mtd->name = "sharpsl-nand"; sharpsl_mtd->name = "sharpsl-nand";
nr_partitions = parse_mtd_partitions(sharpsl_mtd, part_probes, nr_partitions = parse_mtd_partitions(sharpsl_mtd, part_probes, &sharpsl_partition_info, 0);
&sharpsl_partition_info, 0);
if (nr_partitions <= 0) { if (nr_partitions <= 0) {
nr_partitions = DEFAULT_NUM_PARTITIONS; nr_partitions = DEFAULT_NUM_PARTITIONS;
sharpsl_partition_info = sharpsl_nand_default_partition_info; sharpsl_partition_info = sharpsl_nand_default_partition_info;
if (machine_is_poodle()) { 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()) { } 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()) { } 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()) { } 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()) { } 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()) { } 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 happy */
return 0; return 0;
} }
module_init(sharpsl_nand_init); module_init(sharpsl_nand_init);
/* /*
@ -269,7 +259,7 @@ module_init(sharpsl_nand_init);
#ifdef MODULE #ifdef MODULE
static void __exit sharpsl_nand_cleanup(void) 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 */ /* Release resources, unregister device */
nand_release(sharpsl_mtd); nand_release(sharpsl_mtd);
@ -279,6 +269,7 @@ static void __exit sharpsl_nand_cleanup(void)
/* Free the MTD device structure */ /* Free the MTD device structure */
kfree(sharpsl_mtd); kfree(sharpsl_mtd);
} }
module_exit(sharpsl_nand_cleanup); module_exit(sharpsl_nand_cleanup);
#endif #endif

View File

@ -39,16 +39,16 @@ static struct mtd_info *spia_mtd = NULL;
*/ */
#define SPIA_IO_BASE 0xd0000000 /* Start of EP7212 IO address space */ #define SPIA_IO_BASE 0xd0000000 /* Start of EP7212 IO address space */
#define SPIA_FIO_BASE 0xf0000000 /* Address where flash is mapped */ #define SPIA_FIO_BASE 0xf0000000 /* Address where flash is mapped */
#define SPIA_PEDR 0x0080 /* #define SPIA_PEDR 0x0080 /*
* IO offset to Port E data register * IO offset to Port E data register
* where the CLE, ALE and NCE pins * where the CLE, ALE and NCE pins
* are wired to. * are wired to.
*/ */
#define SPIA_PEDDR 0x00c0 /* #define SPIA_PEDDR 0x00c0 /*
* IO offset to Port E data direction * IO offset to Port E data direction
* register so we can control the IO * register so we can control the IO
* lines. * lines.
*/ */
/* /*
* Module stuff * Module stuff
@ -69,25 +69,23 @@ module_param(spia_peddr, int, 0);
*/ */
static const struct mtd_partition partition_info[] = { static const struct mtd_partition partition_info[] = {
{ {
.name = "SPIA flash partition 1", .name = "SPIA flash partition 1",
.offset = 0, .offset = 0,
.size = 2*1024*1024 .size = 2 * 1024 * 1024},
},
{ {
.name = "SPIA flash partition 2", .name = "SPIA flash partition 2",
.offset = 2*1024*1024, .offset = 2 * 1024 * 1024,
.size = 6*1024*1024 .size = 6 * 1024 * 1024}
}
}; };
#define NUM_PARTITIONS 2
#define NUM_PARTITIONS 2
/* /*
* hardware specific access to control-lines * hardware specific access to control-lines
*/ */
static void spia_hwcontrol(struct mtd_info *mtd, int cmd){ static void spia_hwcontrol(struct mtd_info *mtd, int cmd)
{
switch(cmd){ switch (cmd) {
case NAND_CTL_SETCLE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) |= 0x01; break; 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; 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_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; case NAND_CTL_CLRNCE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) |= 0x04; break;
} }
} }
/* /*
* Main initialization routine * Main initialization routine
*/ */
int __init spia_init (void) int __init spia_init(void)
{ {
struct nand_chip *this; struct nand_chip *this;
/* Allocate memory for MTD device structure and private data */ /* Allocate memory for MTD device structure and private data */
spia_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), spia_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
GFP_KERNEL);
if (!spia_mtd) { 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; return -ENOMEM;
} }
/* Get pointer to private data */ /* Get pointer to private data */
this = (struct nand_chip *) (&spia_mtd[1]); this = (struct nand_chip *)(&spia_mtd[1]);
/* Initialize structures */ /* Initialize structures */
memset((char *) spia_mtd, 0, sizeof(struct mtd_info)); memset(spia_mtd, 0, sizeof(struct mtd_info));
memset((char *) this, 0, sizeof(struct nand_chip)); memset(this, 0, sizeof(struct nand_chip));
/* Link the private data with the MTD structure */ /* Link the private data with the MTD structure */
spia_mtd->priv = this; 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 * Set GPIO Port E control register so that the pins are configured
* to be outputs for controlling the NAND flash. * 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 */ /* Set address of NAND IO lines */
this->IO_ADDR_R = (void __iomem *) spia_fio_base; this->IO_ADDR_R = (void __iomem *)spia_fio_base;
this->IO_ADDR_W = (void __iomem *) spia_fio_base; this->IO_ADDR_W = (void __iomem *)spia_fio_base;
/* Set address of hardware control function */ /* Set address of hardware control function */
this->hwcontrol = spia_hwcontrol; this->hwcontrol = spia_hwcontrol;
/* 15 us command delay time */ /* 15 us command delay time */
this->chip_delay = 15; this->chip_delay = 15;
/* Scan to find existence of the device */ /* Scan to find existence of the device */
if (nand_scan (spia_mtd, 1)) { if (nand_scan(spia_mtd, 1)) {
kfree (spia_mtd); kfree(spia_mtd);
return -ENXIO; return -ENXIO;
} }
@ -151,20 +148,22 @@ int __init spia_init (void)
/* Return happy */ /* Return happy */
return 0; return 0;
} }
module_init(spia_init); module_init(spia_init);
/* /*
* Clean up routine * Clean up routine
*/ */
#ifdef MODULE #ifdef MODULE
static void __exit spia_cleanup (void) static void __exit spia_cleanup(void)
{ {
/* Release resources, unregister device */ /* Release resources, unregister device */
nand_release (spia_mtd); nand_release(spia_mtd);
/* Free the MTD device structure */ /* Free the MTD device structure */
kfree (spia_mtd); kfree(spia_mtd);
} }
module_exit(spia_cleanup); module_exit(spia_cleanup);
#endif #endif

View File

@ -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_CLRALE(iob) gpiosetout(NAND_ALE, 0)
#define T_NAND_CTL_SETALE(iob) gpiosetout(NAND_ALE, NAND_ALE) #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_CLRCLE(iob) gpiosetout(NAND_CLE, 0); rts2setout(2, 2)
#define T_NAND_CTL_SETCLE(iob) gpiosetout(NAND_CLE, NAND_CLE); rts2setout(2, 0) #define T_NAND_CTL_SETCLE(iob) gpiosetout(NAND_CLE, NAND_CLE); rts2setout(2, 0)
#else #else
@ -98,9 +98,8 @@ static struct mtd_partition partition_info32M[] = {
static void toto_hwcontrol(struct mtd_info *mtd, int cmd) static void toto_hwcontrol(struct mtd_info *mtd, int cmd)
{ {
udelay(1); /* hopefully enough time for tc make proceding write to clear */ udelay(1); /* hopefully enough time for tc make proceding write to clear */
switch(cmd){ switch (cmd) {
case NAND_CTL_SETCLE: T_NAND_CTL_SETCLE(cmd); break; case NAND_CTL_SETCLE: T_NAND_CTL_SETCLE(cmd); break;
case NAND_CTL_CLRCLE: T_NAND_CTL_CLRCLE(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_SETNCE: T_NAND_CTL_SETNCE(cmd); break;
case NAND_CTL_CLRNCE: T_NAND_CTL_CLRNCE(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 * Main initialization routine
*/ */
int __init toto_init (void) int __init toto_init(void)
{ {
struct nand_chip *this; struct nand_chip *this;
int err = 0; int err = 0;
/* Allocate memory for MTD device structure and private data */ /* Allocate memory for MTD device structure and private data */
toto_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), toto_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
GFP_KERNEL);
if (!toto_mtd) { 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; err = -ENOMEM;
goto out; goto out;
} }
/* Get pointer to private data */ /* Get pointer to private data */
this = (struct nand_chip *) (&toto_mtd[1]); this = (struct nand_chip *)(&toto_mtd[1]);
/* Initialize structures */ /* Initialize structures */
memset((char *) toto_mtd, 0, sizeof(struct mtd_info)); memset(toto_mtd, 0, sizeof(struct mtd_info));
memset((char *) this, 0, sizeof(struct nand_chip)); memset(this, 0, sizeof(struct nand_chip));
/* Link the private data with the MTD structure */ /* Link the private data with the MTD structure */
toto_mtd->priv = this; toto_mtd->priv = this;
@ -149,33 +147,37 @@ int __init toto_init (void)
this->chip_delay = 30; this->chip_delay = 30;
this->eccmode = NAND_ECC_SOFT; this->eccmode = NAND_ECC_SOFT;
/* Scan to find existance of the device */ /* Scan to find existance of the device */
if (nand_scan (toto_mtd, 1)) { if (nand_scan(toto_mtd, 1)) {
err = -ENXIO; err = -ENXIO;
goto out_mtd; goto out_mtd;
} }
/* Register the partitions */ /* Register the partitions */
switch(toto_mtd->size){ switch (toto_mtd->size) {
case SZ_64M: add_mtd_partitions(toto_mtd, partition_info64M, NUM_PARTITIONS64M); break; case SZ_64M:
case SZ_32M: add_mtd_partitions(toto_mtd, partition_info32M, NUM_PARTITIONS32M); break; add_mtd_partitions(toto_mtd, partition_info64M, NUM_PARTITIONS64M);
default: { break;
printk (KERN_WARNING "Unsupported Nand device\n"); case SZ_32M:
add_mtd_partitions(toto_mtd, partition_info32M, NUM_PARTITIONS32M);
break;
default:{
printk(KERN_WARNING "Unsupported Nand device\n");
err = -ENXIO; err = -ENXIO;
goto out_buf; goto out_buf;
} }
} }
gpioreserve(NAND_MASK); /* claim our gpios */ gpioreserve(NAND_MASK); /* claim our gpios */
archflashwp(0,0); /* open up flash for writing */ archflashwp(0, 0); /* open up flash for writing */
goto out; goto out;
out_buf: out_buf:
kfree (this->data_buf); kfree(this->data_buf);
out_mtd: out_mtd:
kfree (toto_mtd); kfree(toto_mtd);
out: out:
return err; return err;
} }
@ -184,20 +186,21 @@ module_init(toto_init);
/* /*
* Clean up routine * Clean up routine
*/ */
static void __exit toto_cleanup (void) static void __exit toto_cleanup(void)
{ {
/* Release resources, unregister device */ /* Release resources, unregister device */
nand_release (toto_mtd); nand_release(toto_mtd);
/* Free the MTD device structure */ /* Free the MTD device structure */
kfree (toto_mtd); kfree(toto_mtd);
/* stop flash writes */ /* stop flash writes */
archflashwp(0,1); archflashwp(0, 1);
/* release gpios to system */ /* release gpios to system */
gpiorelease(NAND_MASK); gpiorelease(NAND_MASK);
} }
module_exit(toto_cleanup); module_exit(toto_cleanup);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

View File

@ -88,7 +88,7 @@ static void ts7250_hwcontrol(struct mtd_info *mtd, int cmd)
{ {
unsigned long ctrl = TS72XX_NAND_CONTROL_VIRT_BASE; unsigned long ctrl = TS72XX_NAND_CONTROL_VIRT_BASE;
switch(cmd) { switch (cmd) {
case NAND_CTL_SETCLE: case NAND_CTL_SETCLE:
__raw_writeb(__raw_readb(ctrl) | 0x2, ctrl); __raw_writeb(__raw_readb(ctrl) | 0x2, ctrl);
break; break;
@ -132,8 +132,7 @@ static int __init ts7250_init(void)
return -ENXIO; return -ENXIO;
/* Allocate memory for MTD device structure and private data */ /* Allocate memory for MTD device structure and private data */
ts7250_mtd = kmalloc(sizeof(struct mtd_info) + ts7250_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
sizeof(struct nand_chip), GFP_KERNEL);
if (!ts7250_mtd) { if (!ts7250_mtd) {
printk("Unable to allocate TS7250 NAND MTD device structure.\n"); printk("Unable to allocate TS7250 NAND MTD device structure.\n");
return -ENOMEM; return -ENOMEM;
@ -163,11 +162,9 @@ static int __init ts7250_init(void)
kfree(ts7250_mtd); kfree(ts7250_mtd);
return -ENXIO; return -ENXIO;
} }
#ifdef CONFIG_MTD_PARTITIONS #ifdef CONFIG_MTD_PARTITIONS
ts7250_mtd->name = "ts7250-nand"; ts7250_mtd->name = "ts7250-nand";
mtd_parts_nb = parse_mtd_partitions(ts7250_mtd, part_probes, mtd_parts_nb = parse_mtd_partitions(ts7250_mtd, part_probes, &mtd_parts, 0);
&mtd_parts, 0);
if (mtd_parts_nb > 0) if (mtd_parts_nb > 0)
part_type = "command line"; part_type = "command line";
else else
@ -188,6 +185,7 @@ static int __init ts7250_init(void)
/* Return happy */ /* Return happy */
return 0; return 0;
} }
module_init(ts7250_init); module_init(ts7250_init);
/* /*
@ -201,6 +199,7 @@ static void __exit ts7250_cleanup(void)
/* Free the MTD device structure */ /* Free the MTD device structure */
kfree(ts7250_mtd); kfree(ts7250_mtd);
} }
module_exit(ts7250_cleanup); module_exit(ts7250_cleanup);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");