summaryrefslogtreecommitdiffstats
path: root/linux-2.4.x/drivers/mtd/devices/doc2001.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux-2.4.x/drivers/mtd/devices/doc2001.c')
-rw-r--r--linux-2.4.x/drivers/mtd/devices/doc2001.c114
1 files changed, 61 insertions, 53 deletions
diff --git a/linux-2.4.x/drivers/mtd/devices/doc2001.c b/linux-2.4.x/drivers/mtd/devices/doc2001.c
index b34591a..fcb28a6 100644
--- a/linux-2.4.x/drivers/mtd/devices/doc2001.c
+++ b/linux-2.4.x/drivers/mtd/devices/doc2001.c
@@ -4,7 +4,7 @@
* (c) 1999 Machine Vision Holdings, Inc.
* (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
*
- * $Id: doc2001.c,v 1.35 2001/10/02 15:05:13 dwmw2 Exp $
+ * $Id: doc2001.c,v 1.49 2005/11/07 11:14:24 gleixner Exp $
*/
#include <linux/kernel.h>
@@ -19,10 +19,10 @@
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/types.h>
+#include <linux/bitops.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
-#include <linux/mtd/nand_ids.h>
#include <linux/mtd/doc2000.h>
/* #define ECC_DEBUG */
@@ -38,9 +38,11 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf);
static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, u_char *buf, u_char *eccbuf);
+ size_t *retlen, u_char *buf, u_char *eccbuf,
+ struct nand_oobinfo *oobsel);
static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const u_char *buf, u_char *eccbuf);
+ size_t *retlen, const u_char *buf, u_char *eccbuf,
+ struct nand_oobinfo *oobsel);
static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
size_t *retlen, u_char *buf);
static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
@@ -50,7 +52,7 @@ static int doc_erase (struct mtd_info *mtd, struct erase_info *instr);
static struct mtd_info *docmillist = NULL;
/* Perform the required delay cycles by reading from the NOP register */
-static void DoC_Delay(unsigned long docptr, unsigned short cycles)
+static void DoC_Delay(void __iomem * docptr, unsigned short cycles)
{
volatile char dummy;
int i;
@@ -60,7 +62,7 @@ static void DoC_Delay(unsigned long docptr, unsigned short cycles)
}
/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
-static int _DoC_WaitReady(unsigned long docptr)
+static int _DoC_WaitReady(void __iomem * docptr)
{
unsigned short c = 0xffff;
@@ -77,7 +79,7 @@ static int _DoC_WaitReady(unsigned long docptr)
return (c == 0);
}
-static inline int DoC_WaitReady(unsigned long docptr)
+static inline int DoC_WaitReady(void __iomem * docptr)
{
/* This is inline, to optimise the common case, where it's ready instantly */
int ret = 0;
@@ -101,7 +103,7 @@ static inline int DoC_WaitReady(unsigned long docptr)
with the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
-static inline void DoC_Command(unsigned long docptr, unsigned char command,
+static inline void DoC_Command(void __iomem * docptr, unsigned char command,
unsigned char xtraflags)
{
/* Assert the CLE (Command Latch Enable) line to the flash chip */
@@ -121,7 +123,7 @@ static inline void DoC_Command(unsigned long docptr, unsigned char command,
with the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
-static inline void DoC_Address(unsigned long docptr, int numbytes, unsigned long ofs,
+static inline void DoC_Address(void __iomem * docptr, int numbytes, unsigned long ofs,
unsigned char xtraflags1, unsigned char xtraflags2)
{
/* Assert the ALE (Address Latch Enable) line to the flash chip */
@@ -159,7 +161,7 @@ static inline void DoC_Address(unsigned long docptr, int numbytes, unsigned long
}
/* DoC_SelectChip: Select a given flash chip within the current floor */
-static int DoC_SelectChip(unsigned long docptr, int chip)
+static int DoC_SelectChip(void __iomem * docptr, int chip)
{
/* Select the individual flash chip requested */
WriteDOC(chip, docptr, CDSNDeviceSelect);
@@ -170,7 +172,7 @@ static int DoC_SelectChip(unsigned long docptr, int chip)
}
/* DoC_SelectFloor: Select a given floor (bank of flash chips) */
-static int DoC_SelectFloor(unsigned long docptr, int floor)
+static int DoC_SelectFloor(void __iomem * docptr, int floor)
{
/* Select the floor (bank) of chips required */
WriteDOC(floor, docptr, FloorSelect);
@@ -182,7 +184,7 @@ static int DoC_SelectFloor(unsigned long docptr, int floor)
/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */
static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
{
- int mfr, id, i;
+ int mfr, id, i, j;
volatile char dummy;
/* Page in the required floor/chip
@@ -194,10 +196,10 @@ static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
DoC_Command(doc->virtadr, NAND_CMD_RESET, CDSN_CTRL_WP);
DoC_WaitReady(doc->virtadr);
- /* Read the NAND chip ID: 1. Send ReadID command */
+ /* Read the NAND chip ID: 1. Send ReadID command */
DoC_Command(doc->virtadr, NAND_CMD_READID, CDSN_CTRL_WP);
- /* Read the NAND chip ID: 2. Send address byte zero */
+ /* Read the NAND chip ID: 2. Send address byte zero */
DoC_Address(doc->virtadr, 1, 0x00, CDSN_CTRL_WP, 0x00);
/* Read the manufacturer and device id codes of the flash device through
@@ -216,14 +218,18 @@ static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
/* FIXME: to deal with multi-flash on multi-Millennium case more carefully */
for (i = 0; nand_flash_ids[i].name != NULL; i++) {
- if (mfr == nand_flash_ids[i].manufacture_id &&
- id == nand_flash_ids[i].model_id) {
+ if ( id == nand_flash_ids[i].id) {
+ /* Try to identify manufacturer */
+ for (j = 0; nand_manuf_ids[j].id != 0x0; j++) {
+ if (nand_manuf_ids[j].id == mfr)
+ break;
+ }
printk(KERN_INFO "Flash chip found: Manufacturer ID: %2.2X, "
- "Chip ID: %2.2X (%s)\n",
- mfr, id, nand_flash_ids[i].name);
+ "Chip ID: %2.2X (%s:%s)\n",
+ mfr, id, nand_manuf_ids[j].name, nand_flash_ids[i].name);
doc->mfr = mfr;
doc->id = id;
- doc->chipshift = nand_flash_ids[i].chipshift;
+ doc->chipshift = ffs((nand_flash_ids[i].chipsize << 20)) - 1;
break;
}
}
@@ -269,7 +275,7 @@ static void DoC_ScanChips(struct DiskOnChip *this)
return;
}
- /* Fill out the chip array with {floor, chipno} for each
+ /* Fill out the chip array with {floor, chipno} for each
* detected chip in the device. */
for (floor = 0, ret = 0; floor < MAX_FLOORS_MIL; floor++) {
for (chip = 0 ; chip < numchips[floor] ; chip++) {
@@ -303,7 +309,7 @@ static int DoCMil_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2)
tmp2 = ReadDOC(doc2->virtadr, AliasResolution);
if (tmp1 != tmp2)
return 0;
-
+
WriteDOC((tmp1+1) % 0xff, doc1->virtadr, AliasResolution);
tmp2 = ReadDOC(doc2->virtadr, AliasResolution);
if (tmp2 == (tmp1+1) % 0xff)
@@ -329,23 +335,23 @@ static const char im_name[] = "DoCMil_init";
*/
static void DoCMil_init(struct mtd_info *mtd)
{
- struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
+ struct DiskOnChip *this = mtd->priv;
struct DiskOnChip *old = NULL;
/* We must avoid being called twice for the same device. */
if (docmillist)
- old = (struct DiskOnChip *)docmillist->priv;
+ old = docmillist->priv;
while (old) {
if (DoCMil_is_alias(this, old)) {
printk(KERN_NOTICE "Ignoring DiskOnChip Millennium at "
"0x%lX - already configured\n", this->physadr);
- iounmap((void *)this->virtadr);
+ iounmap(this->virtadr);
kfree(mtd);
return;
}
if (old->nextdoc)
- old = (struct DiskOnChip *)old->nextdoc->priv;
+ old = old->nextdoc->priv;
else
old = NULL;
}
@@ -356,14 +362,15 @@ static void DoCMil_init(struct mtd_info *mtd)
mtd->type = MTD_NANDFLASH;
mtd->flags = MTD_CAP_NANDFLASH;
+ mtd->ecctype = MTD_ECC_RS_DiskOnChip;
mtd->size = 0;
- /* FIXME: erase size is not always 8kB */
+ /* FIXME: erase size is not always 8KiB */
mtd->erasesize = 0x2000;
mtd->oobblock = 512;
mtd->oobsize = 16;
- mtd->module = THIS_MODULE;
+ mtd->owner = THIS_MODULE;
mtd->erase = doc_erase;
mtd->point = NULL;
mtd->unpoint = NULL;
@@ -385,7 +392,7 @@ static void DoCMil_init(struct mtd_info *mtd)
if (!this->totlen) {
kfree(mtd);
- iounmap((void *)this->virtadr);
+ iounmap(this->virtadr);
} else {
this->nextdoc = docmillist;
docmillist = mtd;
@@ -399,17 +406,18 @@ static int doc_read (struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf)
{
/* Just a special case of doc_read_ecc */
- return doc_read_ecc(mtd, from, len, retlen, buf, NULL);
+ return doc_read_ecc(mtd, from, len, retlen, buf, NULL, NULL);
}
static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, u_char *buf, u_char *eccbuf)
+ size_t *retlen, u_char *buf, u_char *eccbuf,
+ struct nand_oobinfo *oobsel)
{
int i, ret;
volatile char dummy;
unsigned char syndrome[6];
- struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
- unsigned long docptr = this->virtadr;
+ struct DiskOnChip *this = mtd->priv;
+ void __iomem *docptr = this->virtadr;
struct Nand *mychip = &this->chips[from >> (this->chipshift)];
/* Don't allow read past end of device */
@@ -417,7 +425,7 @@ static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
return -EINVAL;
/* Don't allow a single read to cross a 512-byte block boundary */
- if (from + len > ((from | 0x1ff) + 1))
+ if (from + len > ((from | 0x1ff) + 1))
len = ((from | 0x1ff) + 1) - from;
/* Find the chip which is to be used and select it */
@@ -525,16 +533,17 @@ static int doc_write (struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf)
{
char eccbuf[6];
- return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf);
+ return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, NULL);
}
static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const u_char *buf, u_char *eccbuf)
+ size_t *retlen, const u_char *buf, u_char *eccbuf,
+ struct nand_oobinfo *oobsel)
{
int i,ret = 0;
volatile char dummy;
- struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
- unsigned long docptr = this->virtadr;
+ struct DiskOnChip *this = mtd->priv;
+ void __iomem *docptr = this->virtadr;
struct Nand *mychip = &this->chips[to >> (this->chipshift)];
/* Don't allow write past end of device */
@@ -543,7 +552,7 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
#if 0
/* Don't allow a single write to cross a 512-byte block boundary */
- if (to + len > ( (to | 0x1ff) + 1))
+ if (to + len > ( (to | 0x1ff) + 1))
len = ((to | 0x1ff) + 1) - to;
#else
/* Don't allow writes which aren't exactly one block */
@@ -623,7 +632,7 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
/* write the block status BLOCK_USED (0x5555) at the end of ECC data
FIXME: this is only a hack for programming the IPL area for LinuxBIOS
- and should be replace with proper codes in user space utilities */
+ and should be replace with proper codes in user space utilities */
WriteDOC(0x55, docptr, Mil_CDSN_IO);
WriteDOC(0x55, docptr, Mil_CDSN_IO + 1);
@@ -668,8 +677,8 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
int i;
#endif
volatile char dummy;
- struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
- unsigned long docptr = this->virtadr;
+ struct DiskOnChip *this = mtd->priv;
+ void __iomem *docptr = this->virtadr;
struct Nand *mychip = &this->chips[ofs >> this->chipshift];
/* Find the chip which is to be used and select it */
@@ -720,8 +729,8 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
#endif
volatile char dummy;
int ret = 0;
- struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
- unsigned long docptr = this->virtadr;
+ struct DiskOnChip *this = mtd->priv;
+ void __iomem *docptr = this->virtadr;
struct Nand *mychip = &this->chips[ofs >> this->chipshift];
/* Find the chip which is to be used and select it */
@@ -787,13 +796,13 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
int doc_erase (struct mtd_info *mtd, struct erase_info *instr)
{
volatile char dummy;
- struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
+ struct DiskOnChip *this = mtd->priv;
__u32 ofs = instr->addr;
__u32 len = instr->len;
- unsigned long docptr = this->virtadr;
+ void __iomem *docptr = this->virtadr;
struct Nand *mychip = &this->chips[ofs >> this->chipshift];
- if (len != mtd->erasesize)
+ if (len != mtd->erasesize)
printk(KERN_WARNING "Erase not right size (%x != %x)n",
len, mtd->erasesize);
@@ -836,8 +845,7 @@ int doc_erase (struct mtd_info *mtd, struct erase_info *instr)
instr->state = MTD_ERASE_DONE;
dummy = ReadDOC(docptr, LastDataRead);
- if (instr->callback)
- instr->callback(instr);
+ mtd_erase_callback(instr);
return 0;
}
@@ -848,7 +856,7 @@ int doc_erase (struct mtd_info *mtd, struct erase_info *instr)
*
****************************************************************************/
-int __init init_doc2001(void)
+static int __init init_doc2001(void)
{
inter_module_register(im_name, THIS_MODULE, &DoCMil_init);
return 0;
@@ -860,12 +868,12 @@ static void __exit cleanup_doc2001(void)
struct DiskOnChip *this;
while ((mtd=docmillist)) {
- this = (struct DiskOnChip *)mtd->priv;
+ this = mtd->priv;
docmillist = this->nextdoc;
-
+
del_mtd_device(mtd);
-
- iounmap((void *)this->virtadr);
+
+ iounmap(this->virtadr);
kfree(this->chips);
kfree(mtd);
}