diff options
Diffstat (limited to 'drivers/mtd/devices')
-rw-r--r-- | drivers/mtd/devices/block2mtd.c | 95 | ||||
-rw-r--r-- | drivers/mtd/devices/doc2000.c | 179 | ||||
-rw-r--r-- | drivers/mtd/devices/doc2001.c | 179 | ||||
-rw-r--r-- | drivers/mtd/devices/doc2001plus.c | 164 | ||||
-rw-r--r-- | drivers/mtd/devices/docprobe.c | 1 | ||||
-rw-r--r-- | drivers/mtd/devices/m25p80.c | 12 | ||||
-rw-r--r-- | drivers/mtd/devices/ms02-nv.c | 1 | ||||
-rw-r--r-- | drivers/mtd/devices/mtd_dataflash.c | 2 | ||||
-rw-r--r-- | drivers/mtd/devices/mtdram.c | 1 | ||||
-rw-r--r-- | drivers/mtd/devices/phram.c | 1 | ||||
-rw-r--r-- | drivers/mtd/devices/pmc551.c | 1154 | ||||
-rw-r--r-- | drivers/mtd/devices/slram.c | 1 |
12 files changed, 872 insertions, 918 deletions
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index 0d98c223c5fc..401c6a294baa 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c @@ -8,7 +8,6 @@ * * Licence: GPL */ -#include <linux/config.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/blkdev.h> @@ -19,6 +18,7 @@ #include <linux/mtd/mtd.h> #include <linux/buffer_head.h> #include <linux/mutex.h> +#include <linux/mount.h> #define VERSION "$Revision: 1.30 $" @@ -237,6 +237,8 @@ static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf, } return 0; } + + static int block2mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { @@ -300,6 +302,19 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) /* Get a handle on the device */ bdev = open_bdev_excl(devname, O_RDWR, NULL); +#ifndef MODULE + if (IS_ERR(bdev)) { + + /* We might not have rootfs mounted at this point. Try + to resolve the device name by other means. */ + + dev_t dev = name_to_dev_t(devname); + if (dev != 0) { + bdev = open_by_devnum(dev, FMODE_WRITE | FMODE_READ); + } + } +#endif + if (IS_ERR(bdev)) { ERROR("error: cannot open device %s", devname); goto devinit_err; @@ -324,6 +339,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK; dev->mtd.erasesize = erase_size; + dev->mtd.writesize = 1; dev->mtd.type = MTD_RAM; dev->mtd.flags = MTD_CAP_RAM; dev->mtd.erase = block2mtd_erase; @@ -393,26 +409,6 @@ static int parse_num(size_t *num, const char *token) } -static int parse_name(char **pname, const char *token, size_t limit) -{ - size_t len; - char *name; - - len = strlen(token) + 1; - if (len > limit) - return -ENOSPC; - - name = kmalloc(len, GFP_KERNEL); - if (!name) - return -ENOMEM; - - strcpy(name, token); - - *pname = name; - return 0; -} - - static inline void kill_final_newline(char *str) { char *newline = strrchr(str, '\n'); @@ -426,9 +422,15 @@ static inline void kill_final_newline(char *str) return 0; \ } while (0) -static int block2mtd_setup(const char *val, struct kernel_param *kp) +#ifndef MODULE +static int block2mtd_init_called = 0; +static __initdata char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */ +#endif + + +static int block2mtd_setup2(const char *val) { - char buf[80+12]; /* 80 for device, 12 for erase size */ + char buf[80 + 12]; /* 80 for device, 12 for erase size */ char *str = buf; char *token[2]; char *name; @@ -450,13 +452,9 @@ static int block2mtd_setup(const char *val, struct kernel_param *kp) if (!token[0]) parse_err("no argument"); - ret = parse_name(&name, token[0], 80); - if (ret == -ENOMEM) - parse_err("out of memory"); - if (ret == -ENOSPC) - parse_err("name too long"); - if (ret) - return 0; + name = token[0]; + if (strlen(name) + 1 > 80) + parse_err("device name too long"); if (token[1]) { ret = parse_num(&erase_size, token[1]); @@ -472,13 +470,48 @@ static int block2mtd_setup(const char *val, struct kernel_param *kp) } +static int block2mtd_setup(const char *val, struct kernel_param *kp) +{ +#ifdef MODULE + return block2mtd_setup2(val); +#else + /* If more parameters are later passed in via + /sys/module/block2mtd/parameters/block2mtd + and block2mtd_init() has already been called, + we can parse the argument now. */ + + if (block2mtd_init_called) + return block2mtd_setup2(val); + + /* During early boot stage, we only save the parameters + here. We must parse them later: if the param passed + from kernel boot command line, block2mtd_setup() is + called so early that it is not possible to resolve + the device (even kmalloc() fails). Deter that work to + block2mtd_setup2(). */ + + strlcpy(block2mtd_paramline, val, sizeof(block2mtd_paramline)); + + return 0; +#endif +} + + module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200); MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\""); static int __init block2mtd_init(void) { + int ret = 0; INFO("version " VERSION); - return 0; + +#ifndef MODULE + if (strlen(block2mtd_paramline)) + ret = block2mtd_setup2(block2mtd_paramline); + block2mtd_init_called = 1; +#endif + + return ret; } diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c index c54e40464d82..603a7951ac9b 100644 --- a/drivers/mtd/devices/doc2000.c +++ b/drivers/mtd/devices/doc2000.c @@ -55,10 +55,6 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); 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, 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, struct nand_oobinfo *oobsel); static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, struct mtd_oob_ops *ops); static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, @@ -615,17 +611,10 @@ EXPORT_SYMBOL_GPL(DoC2k_init); 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, 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, struct nand_oobinfo *oobsel) -{ struct DiskOnChip *this = mtd->priv; void __iomem *docptr = this->virtadr; struct Nand *mychip; - unsigned char syndrome[6]; + unsigned char syndrome[6], eccbuf[6]; volatile char dummy; int i, len256 = 0, ret=0; size_t left = len; @@ -673,15 +662,9 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, DoC_Address(this, ADDR_COLUMN_PAGE, from, CDSN_CTRL_WP, CDSN_CTRL_ECC_IO); - if (eccbuf) { - /* Prime the ECC engine */ - WriteDOC(DOC_ECC_RESET, docptr, ECCConf); - WriteDOC(DOC_ECC_EN, docptr, ECCConf); - } else { - /* disable the ECC engine */ - WriteDOC(DOC_ECC_RESET, docptr, ECCConf); - WriteDOC(DOC_ECC_DIS, docptr, ECCConf); - } + /* Prime the ECC engine */ + WriteDOC(DOC_ECC_RESET, docptr, ECCConf); + WriteDOC(DOC_ECC_EN, docptr, ECCConf); /* treat crossing 256-byte sector for 2M x 8bits devices */ if (this->page256 && from + len > (from | 0xff) + 1) { @@ -698,58 +681,59 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, /* Let the caller know we completed it */ *retlen += len; - if (eccbuf) { - /* Read the ECC data through the DiskOnChip ECC logic */ - /* Note: this will work even with 2M x 8bit devices as */ - /* they have 8 bytes of OOB per 256 page. mf. */ - DoC_ReadBuf(this, eccbuf, 6); - - /* Flush the pipeline */ - if (DoC_is_Millennium(this)) { - dummy = ReadDOC(docptr, ECCConf); - dummy = ReadDOC(docptr, ECCConf); - i = ReadDOC(docptr, ECCConf); - } else { - dummy = ReadDOC(docptr, 2k_ECCStatus); - dummy = ReadDOC(docptr, 2k_ECCStatus); - i = ReadDOC(docptr, 2k_ECCStatus); - } + /* Read the ECC data through the DiskOnChip ECC logic */ + /* Note: this will work even with 2M x 8bit devices as */ + /* they have 8 bytes of OOB per 256 page. mf. */ + DoC_ReadBuf(this, eccbuf, 6); - /* Check the ECC Status */ - if (i & 0x80) { - int nb_errors; - /* There was an ECC error */ + /* Flush the pipeline */ + if (DoC_is_Millennium(this)) { + dummy = ReadDOC(docptr, ECCConf); + dummy = ReadDOC(docptr, ECCConf); + i = ReadDOC(docptr, ECCConf); + } else { + dummy = ReadDOC(docptr, 2k_ECCStatus); + dummy = ReadDOC(docptr, 2k_ECCStatus); + i = ReadDOC(docptr, 2k_ECCStatus); + } + + /* Check the ECC Status */ + if (i & 0x80) { + int nb_errors; + /* There was an ECC error */ #ifdef ECC_DEBUG - printk(KERN_ERR "DiskOnChip ECC Error: Read at %lx\n", (long)from); + printk(KERN_ERR "DiskOnChip ECC Error: Read at %lx\n", (long)from); #endif - /* Read the ECC syndrom through the DiskOnChip ECC logic. - These syndrome will be all ZERO when there is no error */ - for (i = 0; i < 6; i++) { - syndrome[i] = - ReadDOC(docptr, ECCSyndrome0 + i); - } - nb_errors = doc_decode_ecc(buf, syndrome); + /* Read the ECC syndrom through the DiskOnChip ECC + logic. These syndrome will be all ZERO when there + is no error */ + for (i = 0; i < 6; i++) { + syndrome[i] = + ReadDOC(docptr, ECCSyndrome0 + i); + } + nb_errors = doc_decode_ecc(buf, syndrome); #ifdef ECC_DEBUG - printk(KERN_ERR "Errors corrected: %x\n", nb_errors); + printk(KERN_ERR "Errors corrected: %x\n", nb_errors); #endif - if (nb_errors < 0) { - /* We return error, but have actually done the read. Not that - this can be told to user-space, via sys_read(), but at least - MTD-aware stuff can know about it by checking *retlen */ - ret = -EIO; - } + if (nb_errors < 0) { + /* We return error, but have actually done the + read. Not that this can be told to + user-space, via sys_read(), but at least + MTD-aware stuff can know about it by + checking *retlen */ + ret = -EIO; } + } #ifdef PSYCHO_DEBUG - printk(KERN_DEBUG "ECC DATA at %lxB: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", - (long)from, eccbuf[0], eccbuf[1], eccbuf[2], - eccbuf[3], eccbuf[4], eccbuf[5]); + printk(KERN_DEBUG "ECC DATA at %lxB: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", + (long)from, eccbuf[0], eccbuf[1], eccbuf[2], + eccbuf[3], eccbuf[4], eccbuf[5]); #endif - /* disable the ECC engine */ - WriteDOC(DOC_ECC_DIS, docptr , ECCConf); - } + /* disable the ECC engine */ + WriteDOC(DOC_ECC_DIS, docptr , ECCConf); /* according to 11.4.1, we need to wait for the busy line * drop if we read to the end of the page. */ @@ -771,17 +755,10 @@ static int doc_read_ecc(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) { - char eccbuf[6]; - 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, struct nand_oobinfo *oobsel) -{ struct DiskOnChip *this = mtd->priv; int di; /* Yes, DI is a hangover from when I was disassembling the binary driver */ void __iomem *docptr = this->virtadr; + unsigned char eccbuf[6]; volatile char dummy; int len256 = 0; struct Nand *mychip; @@ -835,15 +812,9 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, DoC_Command(this, NAND_CMD_SEQIN, 0); DoC_Address(this, ADDR_COLUMN_PAGE, to, 0, CDSN_CTRL_ECC_IO); - if (eccbuf) { - /* Prime the ECC engine */ - WriteDOC(DOC_ECC_RESET, docptr, ECCConf); - WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf); - } else { - /* disable the ECC engine */ - WriteDOC(DOC_ECC_RESET, docptr, ECCConf); - WriteDOC(DOC_ECC_DIS, docptr, ECCConf); - } + /* Prime the ECC engine */ + WriteDOC(DOC_ECC_RESET, docptr, ECCConf); + WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf); /* treat crossing 256-byte sector for 2M x 8bits devices */ if (this->page256 && to + len > (to | 0xff) + 1) { @@ -873,39 +844,35 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, DoC_WriteBuf(this, &buf[len256], len - len256); - if (eccbuf) { - WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_CE, docptr, - CDSNControl); - - if (DoC_is_Millennium(this)) { - WriteDOC(0, docptr, NOP); - WriteDOC(0, docptr, NOP); - WriteDOC(0, docptr, NOP); - } else { - WriteDOC_(0, docptr, this->ioreg); - WriteDOC_(0, docptr, this->ioreg); - WriteDOC_(0, docptr, this->ioreg); - } + WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_CE, docptr, CDSNControl); - WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_FLASH_IO | CDSN_CTRL_CE, docptr, - CDSNControl); + if (DoC_is_Millennium(this)) { + WriteDOC(0, docptr, NOP); + WriteDOC(0, docptr, NOP); + WriteDOC(0, docptr, NOP); + } else { + WriteDOC_(0, docptr, this->ioreg); + WriteDOC_(0, docptr, this->ioreg); + WriteDOC_(0, docptr, this->ioreg); + } - /* Read the ECC data through the DiskOnChip ECC logic */ - for (di = 0; di < 6; di++) { - eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di); - } + WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_FLASH_IO | CDSN_CTRL_CE, docptr, + CDSNControl); - /* Reset the ECC engine */ - WriteDOC(DOC_ECC_DIS, docptr, ECCConf); + /* Read the ECC data through the DiskOnChip ECC logic */ + for (di = 0; di < 6; di++) { + eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di); + } + + /* Reset the ECC engine */ + WriteDOC(DOC_ECC_DIS, docptr, ECCConf); #ifdef PSYCHO_DEBUG - printk - ("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", - (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], - eccbuf[4], eccbuf[5]); + printk + ("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", + (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], + eccbuf[4], eccbuf[5]); #endif - } - DoC_Command(this, NAND_CMD_PAGEPROG, 0); DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP); diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c index 0cf022a69e65..0e2a9326f717 100644 --- a/drivers/mtd/devices/doc2001.c +++ b/drivers/mtd/devices/doc2001.c @@ -37,12 +37,6 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); 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, - 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, - struct nand_oobinfo *oobsel); static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, struct mtd_oob_ops *ops); static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, @@ -397,17 +391,9 @@ EXPORT_SYMBOL_GPL(DoCMil_init); 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, 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, - struct nand_oobinfo *oobsel) -{ int i, ret; volatile char dummy; - unsigned char syndrome[6]; + unsigned char syndrome[6], eccbuf[6]; struct DiskOnChip *this = mtd->priv; void __iomem *docptr = this->virtadr; struct Nand *mychip = &this->chips[from >> (this->chipshift)]; @@ -437,15 +423,9 @@ static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, DoC_Address(docptr, 3, from, CDSN_CTRL_WP, 0x00); DoC_WaitReady(docptr); - if (eccbuf) { - /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ - WriteDOC (DOC_ECC_RESET, docptr, ECCConf); - WriteDOC (DOC_ECC_EN, docptr, ECCConf); - } else { - /* disable the ECC engine */ - WriteDOC (DOC_ECC_RESET, docptr, ECCConf); - WriteDOC (DOC_ECC_DIS, docptr, ECCConf); - } + /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ + WriteDOC (DOC_ECC_RESET, docptr, ECCConf); + WriteDOC (DOC_ECC_EN, docptr, ECCConf); /* Read the data via the internal pipeline through CDSN IO register, see Pipelined Read Operations 11.3 */ @@ -465,58 +445,56 @@ static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, *retlen = len; ret = 0; - if (eccbuf) { - /* Read the ECC data from Spare Data Area, - see Reed-Solomon EDC/ECC 11.1 */ - dummy = ReadDOC(docptr, ReadPipeInit); + /* Read the ECC data from Spare Data Area, + see Reed-Solomon EDC/ECC 11.1 */ + dummy = ReadDOC(docptr, ReadPipeInit); #ifndef USE_MEMCPY - for (i = 0; i < 5; i++) { - /* N.B. you have to increase the source address in this way or the - ECC logic will not work properly */ - eccbuf[i] = ReadDOC(docptr, Mil_CDSN_IO + i); - } + for (i = 0; i < 5; i++) { + /* N.B. you have to increase the source address in this way or the + ECC logic will not work properly */ + eccbuf[i] = ReadDOC(docptr, Mil_CDSN_IO + i); + } #else - memcpy_fromio(eccbuf, docptr + DoC_Mil_CDSN_IO, 5); + memcpy_fromio(eccbuf, docptr + DoC_Mil_CDSN_IO, 5); #endif - eccbuf[5] = ReadDOC(docptr, LastDataRead); + eccbuf[5] = ReadDOC(docptr, LastDataRead); - /* Flush the pipeline */ - dummy = ReadDOC(docptr, ECCConf); - dummy = ReadDOC(docptr, ECCConf); + /* Flush the pipeline */ + dummy = ReadDOC(docptr, ECCConf); + dummy = ReadDOC(docptr, ECCConf); - /* Check the ECC Status */ - if (ReadDOC(docptr, ECCConf) & 0x80) { - int nb_errors; - /* There was an ECC error */ + /* Check the ECC Status */ + if (ReadDOC(docptr, ECCConf) & 0x80) { + int nb_errors; + /* There was an ECC error */ #ifdef ECC_DEBUG - printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); + printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); #endif - /* Read the ECC syndrom through the DiskOnChip ECC logic. - These syndrome will be all ZERO when there is no error */ - for (i = 0; i < 6; i++) { - syndrome[i] = ReadDOC(docptr, ECCSyndrome0 + i); - } - nb_errors = doc_decode_ecc(buf, syndrome); + /* Read the ECC syndrom through the DiskOnChip ECC logic. + These syndrome will be all ZERO when there is no error */ + for (i = 0; i < 6; i++) { + syndrome[i] = ReadDOC(docptr, ECCSyndrome0 + i); + } + nb_errors = doc_decode_ecc(buf, syndrome); #ifdef ECC_DEBUG - printk("ECC Errors corrected: %x\n", nb_errors); + printk("ECC Errors corrected: %x\n", nb_errors); #endif - if (nb_errors < 0) { - /* We return error, but have actually done the read. Not that - this can be told to user-space, via sys_read(), but at least - MTD-aware stuff can know about it by checking *retlen */ - ret = -EIO; - } + if (nb_errors < 0) { + /* We return error, but have actually done the read. Not that + this can be told to user-space, via sys_read(), but at least + MTD-aware stuff can know about it by checking *retlen */ + ret = -EIO; } + } #ifdef PSYCHO_DEBUG - printk("ECC DATA at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", - (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], - eccbuf[4], eccbuf[5]); + printk("ECC DATA at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", + (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], + eccbuf[4], eccbuf[5]); #endif - /* disable the ECC engine */ - WriteDOC(DOC_ECC_DIS, docptr , ECCConf); - } + /* disable the ECC engine */ + WriteDOC(DOC_ECC_DIS, docptr , ECCConf); return ret; } @@ -524,15 +502,8 @@ static int doc_read_ecc (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) { - char eccbuf[6]; - 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, - struct nand_oobinfo *oobsel) -{ int i,ret = 0; + char eccbuf[6]; volatile char dummy; struct DiskOnChip *this = mtd->priv; void __iomem *docptr = this->virtadr; @@ -573,15 +544,9 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, DoC_Address(docptr, 3, to, 0x00, 0x00); DoC_WaitReady(docptr); - if (eccbuf) { - /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ - WriteDOC (DOC_ECC_RESET, docptr, ECCConf); - WriteDOC (DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf); - } else { - /* disable the ECC engine */ - WriteDOC (DOC_ECC_RESET, docptr, ECCConf); - WriteDOC (DOC_ECC_DIS, docptr, ECCConf); - } + /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ + WriteDOC (DOC_ECC_RESET, docptr, ECCConf); + WriteDOC (DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf); /* Write the data via the internal pipeline through CDSN IO register, see Pipelined Write Operations 11.2 */ @@ -596,46 +561,44 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, #endif WriteDOC(0x00, docptr, WritePipeTerm); - if (eccbuf) { - /* Write ECC data to flash, the ECC info is generated by the DiskOnChip ECC logic - see Reed-Solomon EDC/ECC 11.1 */ - WriteDOC(0, docptr, NOP); - WriteDOC(0, docptr, NOP); - WriteDOC(0, docptr, NOP); + /* Write ECC data to flash, the ECC info is generated by the DiskOnChip ECC logic + see Reed-Solomon EDC/ECC 11.1 */ + WriteDOC(0, docptr, NOP); + WriteDOC(0, docptr, NOP); + WriteDOC(0, docptr, NOP); - /* Read the ECC data through the DiskOnChip ECC logic */ - for (i = 0; i < 6; i++) { - eccbuf[i] = ReadDOC(docptr, ECCSyndrome0 + i); - } + /* Read the ECC data through the DiskOnChip ECC logic */ + for (i = 0; i < 6; i++) { + eccbuf[i] = ReadDOC(docptr, ECCSyndrome0 + i); + } - /* ignore the ECC engine */ - WriteDOC(DOC_ECC_DIS, docptr , ECCConf); + /* ignore the ECC engine */ + WriteDOC(DOC_ECC_DIS, docptr , ECCConf); #ifndef USE_MEMCPY - /* Write the ECC data to flash */ - for (i = 0; i < 6; i++) { - /* N.B. you have to increase the source address in this way or the - ECC logic will not work properly */ - WriteDOC(eccbuf[i], docptr, Mil_CDSN_IO + i); - } + /* Write the ECC data to flash */ + for (i = 0; i < 6; i++) { + /* N.B. you have to increase the source address in this way or the + ECC logic will not work properly */ + WriteDOC(eccbuf[i], docptr, Mil_CDSN_IO + i); + } #else - memcpy_toio(docptr + DoC_Mil_CDSN_IO, eccbuf, 6); + memcpy_toio(docptr + DoC_Mil_CDSN_IO, eccbuf, 6); #endif - /* 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 */ - WriteDOC(0x55, docptr, Mil_CDSN_IO); - WriteDOC(0x55, docptr, Mil_CDSN_IO + 1); + /* 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 */ + WriteDOC(0x55, docptr, Mil_CDSN_IO); + WriteDOC(0x55, docptr, Mil_CDSN_IO + 1); - WriteDOC(0x00, docptr, WritePipeTerm); + WriteDOC(0x00, docptr, WritePipeTerm); #ifdef PSYCHO_DEBUG - printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", - (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], - eccbuf[4], eccbuf[5]); + printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", + (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], + eccbuf[4], eccbuf[5]); #endif - } /* Commit the Page Program command and wait for ready see Software Requirement 11.4 item 1.*/ diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c index 66cb1e50469a..92dbb47f2ac3 100644 --- a/drivers/mtd/devices/doc2001plus.c +++ b/drivers/mtd/devices/doc2001plus.c @@ -41,12 +41,6 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); 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, - 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, - struct nand_oobinfo *oobsel); static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, struct mtd_oob_ops *ops); static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, @@ -595,18 +589,10 @@ static int doc_dumpblk(struct mtd_info *mtd, loff_t from) 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, 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, - struct nand_oobinfo *oobsel) -{ int ret, i; volatile char dummy; loff_t fofs; - unsigned char syndrome[6]; + unsigned char syndrome[6], eccbuf[6]; struct DiskOnChip *this = mtd->priv; void __iomem * docptr = this->virtadr; struct Nand *mychip = &this->chips[from >> (this->chipshift)]; @@ -644,56 +630,51 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, WriteDOC(0, docptr, Mplus_FlashControl); DoC_WaitReady(docptr); - if (eccbuf) { - /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ - WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); - WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf); - } else { - /* disable the ECC engine */ - WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); - } + /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ + WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); + WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf); /* Let the caller know we completed it */ *retlen = len; - ret = 0; + ret = 0; ReadDOC(docptr, Mplus_ReadPipeInit); ReadDOC(docptr, Mplus_ReadPipeInit); - if (eccbuf) { - /* Read the data via the internal pipeline through CDSN IO - register, see Pipelined Read Operations 11.3 */ - MemReadDOC(docptr, buf, len); + /* Read the data via the internal pipeline through CDSN IO + register, see Pipelined Read Operations 11.3 */ + MemReadDOC(docptr, buf, len); - /* Read the ECC data following raw data */ - MemReadDOC(docptr, eccbuf, 4); - eccbuf[4] = ReadDOC(docptr, Mplus_LastDataRead); - eccbuf[5] = ReadDOC(docptr, Mplus_LastDataRead); + /* Read the ECC data following raw data */ + MemReadDOC(docptr, eccbuf, 4); + eccbuf[4] = ReadDOC(docptr, Mplus_LastDataRead); + eccbuf[5] = ReadDOC(docptr, Mplus_LastDataRead); - /* Flush the pipeline */ - dummy = ReadDOC(docptr, Mplus_ECCConf); - dummy = ReadDOC(docptr, Mplus_ECCConf); + /* Flush the pipeline */ + dummy = ReadDOC(docptr, Mplus_ECCConf); + dummy = ReadDOC(docptr, Mplus_ECCConf); - /* Check the ECC Status */ - if (ReadDOC(docptr, Mplus_ECCConf) & 0x80) { - int nb_errors; - /* There was an ECC error */ + /* Check the ECC Status */ + if (ReadDOC(docptr, Mplus_ECCConf) & 0x80) { + int nb_errors; + /* There was an ECC error */ #ifdef ECC_DEBUG - printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); + printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); #endif - /* Read the ECC syndrom through the DiskOnChip ECC logic. - These syndrome will be all ZERO when there is no error */ - for (i = 0; i < 6; i++) - syndrome[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i); + /* Read the ECC syndrom through the DiskOnChip ECC logic. + These syndrome will be all ZERO when there is no error */ + for (i = 0; i < 6; i++) + syndrome[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i); - nb_errors = doc_decode_ecc(buf, syndrome); + nb_errors = doc_decode_ecc(buf, syndrome); #ifdef ECC_DEBUG - printk("ECC Errors corrected: %x\n", nb_errors); + printk("ECC Errors corrected: %x\n", nb_errors); #endif - if (nb_errors < 0) { - /* We return error, but have actually done the read. Not that - this can be told to user-space, via sys_read(), but at least - MTD-aware stuff can know about it by checking *retlen */ + if (nb_errors < 0) { + /* We return error, but have actually done the + read. Not that this can be told to user-space, via + sys_read(), but at least MTD-aware stuff can know + about it by checking *retlen */ #ifdef ECC_DEBUG printk("%s(%d): Millennium Plus ECC error (from=0x%x:\n", __FILE__, __LINE__, (int)from); @@ -707,24 +688,16 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, eccbuf[3], eccbuf[4], eccbuf[5]); #endif ret = -EIO; - } } + } #ifdef PSYCHO_DEBUG - printk("ECC DATA at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", - (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], - eccbuf[4], eccbuf[5]); + printk("ECC DATA at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", + (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], + eccbuf[4], eccbuf[5]); #endif - - /* disable the ECC engine */ - WriteDOC(DOC_ECC_DIS, docptr , Mplus_ECCConf); - } else { - /* Read the data via the internal pipeline through CDSN IO - register, see Pipelined Read Operations 11.3 */ - MemReadDOC(docptr, buf, len-2); - buf[len-2] = ReadDOC(docptr, Mplus_LastDataRead); - buf[len-1] = ReadDOC(docptr, Mplus_LastDataRead); - } + /* disable the ECC engine */ + WriteDOC(DOC_ECC_DIS, docptr , Mplus_ECCConf); /* Disable flash internally */ WriteDOC(0, docptr, Mplus_FlashSelect); @@ -735,17 +708,10 @@ static int doc_read_ecc(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) { - char eccbuf[6]; - 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, - struct nand_oobinfo *oobsel) -{ int i, before, ret = 0; loff_t fto; volatile char dummy; + char eccbuf[6]; struct DiskOnChip *this = mtd->priv; void __iomem * docptr = this->virtadr; struct Nand *mychip = &this->chips[to >> (this->chipshift)]; @@ -795,46 +761,42 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, /* Disable the ECC engine */ WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf); - if (eccbuf) { - if (before) { - /* Write the block status BLOCK_USED (0x5555) */ - WriteDOC(0x55, docptr, Mil_CDSN_IO); - WriteDOC(0x55, docptr, Mil_CDSN_IO); - } - - /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ - WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, Mplus_ECCConf); + if (before) { + /* Write the block status BLOCK_USED (0x5555) */ + WriteDOC(0x55, docptr, Mil_CDSN_IO); + WriteDOC(0x55, docptr, Mil_CDSN_IO); } + /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ + WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, Mplus_ECCConf); + MemWriteDOC(docptr, (unsigned char *) buf, len); - if (eccbuf) { - /* Write ECC data to flash, the ECC info is generated by - the DiskOnChip ECC logic see Reed-Solomon EDC/ECC 11.1 */ - DoC_Delay(docptr, 3); + /* Write ECC data to flash, the ECC info is generated by + the DiskOnChip ECC logic see Reed-Solomon EDC/ECC 11.1 */ + DoC_Delay(docptr, 3); - /* Read the ECC data through the DiskOnChip ECC logic */ - for (i = 0; i < 6; i++) - eccbuf[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i); + /* Read the ECC data through the DiskOnChip ECC logic */ + for (i = 0; i < 6; i++) + eccbuf[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i); - /* disable the ECC engine */ - WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf); + /* disable the ECC engine */ + WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf); - /* Write the ECC data to flash */ - MemWriteDOC(docptr, eccbuf, 6); + /* Write the ECC data to flash */ + MemWriteDOC(docptr, eccbuf, 6); - if (!before) { - /* Write the block status BLOCK_USED (0x5555) */ - WriteDOC(0x55, docptr, Mil_CDSN_IO+6); - WriteDOC(0x55, docptr, Mil_CDSN_IO+7); - } + if (!before) { + /* Write the block status BLOCK_USED (0x5555) */ + WriteDOC(0x55, docptr, Mil_CDSN_IO+6); + WriteDOC(0x55, docptr, Mil_CDSN_IO+7); + } #ifdef PSYCHO_DEBUG - printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", - (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], - eccbuf[4], eccbuf[5]); + printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", + (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], + eccbuf[4], eccbuf[5]); #endif - } WriteDOC(0x00, docptr, Mplus_WritePipeTerm); WriteDOC(0x00, docptr, Mplus_WritePipeTerm); diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c index 593bb033a3fa..78872c3f3760 100644 --- a/drivers/mtd/devices/docprobe.c +++ b/drivers/mtd/devices/docprobe.c @@ -40,7 +40,6 @@ */ #define DOC_SINGLE_DRIVER -#include <linux/config.h> #include <linux/kernel.h> #include <linux/module.h> #include <asm/errno.h> diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index a8466141e914..ef4a731ca5c2 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -406,13 +406,13 @@ struct flash_info { static struct flash_info __devinitdata m25p_data [] = { /* REVISIT: fill in JEDEC ids, for parts that have them */ - { "m25p05", 0x05, 0x0000, 32 * 1024, 2 }, - { "m25p10", 0x10, 0x0000, 32 * 1024, 4 }, - { "m25p20", 0x11, 0x0000, 64 * 1024, 4 }, - { "m25p40", 0x12, 0x0000, 64 * 1024, 8 }, + { "m25p05", 0x05, 0x2010, 32 * 1024, 2 }, + { "m25p10", 0x10, 0x2011, 32 * 1024, 4 }, + { "m25p20", 0x11, 0x2012, 64 * 1024, 4 }, + { "m25p40", 0x12, 0x2013, 64 * 1024, 8 }, { "m25p80", 0x13, 0x0000, 64 * 1024, 16 }, - { "m25p16", 0x14, 0x0000, 64 * 1024, 32 }, - { "m25p32", 0x15, 0x0000, 64 * 1024, 64 }, + { "m25p16", 0x14, 0x2015, 64 * 1024, 32 }, + { "m25p32", 0x15, 0x2016, 64 * 1024, 64 }, { "m25p64", 0x16, 0x2017, 64 * 1024, 128 }, }; diff --git a/drivers/mtd/devices/ms02-nv.c b/drivers/mtd/devices/ms02-nv.c index 4ab7670770e4..08dfb899b272 100644 --- a/drivers/mtd/devices/ms02-nv.c +++ b/drivers/mtd/devices/ms02-nv.c @@ -225,6 +225,7 @@ static int __init ms02nv_init_one(ulong addr) mtd->owner = THIS_MODULE; mtd->read = ms02nv_read; mtd->write = ms02nv_write; + mtd->writesize = 1; ret = -EIO; if (add_mtd_device(mtd)) { diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index a19480d07888..5db716045927 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c @@ -9,7 +9,6 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> @@ -478,6 +477,7 @@ add_dataflash(struct spi_device *spi, char *name, device->name = (pdata && pdata->name) ? pdata->name : priv->name; device->size = nr_pages * pagesize; device->erasesize = pagesize; + device->writesize = pagesize; device->owner = THIS_MODULE; device->type = MTD_DATAFLASH; device->flags = MTD_CAP_NORFLASH; diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c index b4438eacfd80..e427c82d5f4c 100644 --- a/drivers/mtd/devices/mtdram.c +++ b/drivers/mtd/devices/mtdram.c @@ -10,7 +10,6 @@ * */ -#include <linux/config.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/ioport.h> diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c index e09e416667d3..6c7337f9ebbb 100644 --- a/drivers/mtd/devices/phram.c +++ b/drivers/mtd/devices/phram.c @@ -151,6 +151,7 @@ static int register_device(char *name, unsigned long start, unsigned long len) new->mtd.owner = THIS_MODULE; new->mtd.type = MTD_RAM; new->mtd.erasesize = PAGE_SIZE; + new->mtd.writesize = 1; ret = -EAGAIN; if (add_mtd_device(&new->mtd)) { diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c index 666cce1bf60c..354e1657cc26 100644 --- a/drivers/mtd/devices/pmc551.c +++ b/drivers/mtd/devices/pmc551.c @@ -4,85 +4,84 @@ * PMC551 PCI Mezzanine Ram Device * * Author: - * Mark Ferrell <mferrell@mvista.com> - * Copyright 1999,2000 Nortel Networks + * Mark Ferrell <mferrell@mvista.com> + * Copyright 1999,2000 Nortel Networks * * License: - * As part of this driver was derived from the slram.c driver it - * falls under the same license, which is GNU General Public - * License v2 + * As part of this driver was derived from the slram.c driver it + * falls under the same license, which is GNU General Public + * License v2 * * Description: - * This driver is intended to support the PMC551 PCI Ram device - * from Ramix Inc. The PMC551 is a PMC Mezzanine module for - * cPCI embedded systems. The device contains a single SROM - * that initially programs the V370PDC chipset onboard the - * device, and various banks of DRAM/SDRAM onboard. This driver - * implements this PCI Ram device as an MTD (Memory Technology - * Device) so that it can be used to hold a file system, or for - * added swap space in embedded systems. Since the memory on - * this board isn't as fast as main memory we do not try to hook - * it into main memory as that would simply reduce performance - * on the system. Using it as a block device allows us to use - * it as high speed swap or for a high speed disk device of some - * sort. Which becomes very useful on diskless systems in the - * embedded market I might add. + * This driver is intended to support the PMC551 PCI Ram device + * from Ramix Inc. The PMC551 is a PMC Mezzanine module for + * cPCI embedded systems. The device contains a single SROM + * that initially programs the V370PDC chipset onboard the + * device, and various banks of DRAM/SDRAM onboard. This driver + * implements this PCI Ram device as an MTD (Memory Technology + * Device) so that it can be used to hold a file system, or for + * added swap space in embedded systems. Since the memory on + * this board isn't as fast as main memory we do not try to hook + * it into main memory as that would simply reduce performance + * on the system. Using it as a block device allows us to use + * it as high speed swap or for a high speed disk device of some + * sort. Which becomes very useful on diskless systems in the + * embedded market I might add. * * Notes: - * Due to what I assume is more buggy SROM, the 64M PMC551 I - * have available claims that all 4 of it's DRAM banks have 64M - * of ram configured (making a grand total of 256M onboard). - * This is slightly annoying since the BAR0 size reflects the - * aperture size, not the dram size, and the V370PDC supplies no - * other method for memory size discovery. This problem is - * mostly only relevant when compiled as a module, as the - * unloading of the module with an aperture size smaller then - * the ram will cause the driver to detect the onboard memory - * size to be equal to the aperture size when the module is - * reloaded. Soooo, to help, the module supports an msize - * option to allow the specification of the onboard memory, and - * an asize option, to allow the specification of the aperture - * size. The aperture must be equal to or less then the memory - * size, the driver will correct this if you screw it up. This - * problem is not relevant for compiled in drivers as compiled - * in drivers only init once. + * Due to what I assume is more buggy SROM, the 64M PMC551 I + * have available claims that all 4 of it's DRAM banks have 64M + * of ram configured (making a grand total of 256M onboard). + * This is slightly annoying since the BAR0 size reflects the + * aperture size, not the dram size, and the V370PDC supplies no + * other method for memory size discovery. This problem is + * mostly only relevant when compiled as a module, as the + * unloading of the module with an aperture size smaller then + * the ram will cause the driver to detect the onboard memory + * size to be equal to the aperture size when the module is + * reloaded. Soooo, to help, the module supports an msize + * option to allow the specification of the onboard memory, and + * an asize option, to allow the specification of the aperture + * size. The aperture must be equal to or less then the memory + * size, the driver will correct this if you screw it up. This + * problem is not relevant for compiled in drivers as compiled + * in drivers only init once. * * Credits: - * Saeed Karamooz <saeed@ramix.com> of Ramix INC. for the - * initial example code of how to initialize this device and for - * help with questions I had concerning operation of the device. + * Saeed Karamooz <saeed@ramix.com> of Ramix INC. for the + * initial example code of how to initialize this device and for + * help with questions I had concerning operation of the device. * - * Most of the MTD code for this driver was originally written - * for the slram.o module in the MTD drivers package which - * allows the mapping of system memory into an MTD device. - * Since the PMC551 memory module is accessed in the same - * fashion as system memory, the slram.c code became a very nice - * fit to the needs of this driver. All we added was PCI - * detection/initialization to the driver and automatically figure - * out the size via the PCI detection.o, later changes by Corey - * Minyard set up the card to utilize a 1M sliding apature. + * Most of the MTD code for this driver was originally written + * for the slram.o module in the MTD drivers package which + * allows the mapping of system memory into an MTD device. + * Since the PMC551 memory module is accessed in the same + * fashion as system memory, the slram.c code became a very nice + * fit to the needs of this driver. All we added was PCI + * detection/initialization to the driver and automatically figure + * out the size via the PCI detection.o, later changes by Corey + * Minyard set up the card to utilize a 1M sliding apature. * - * Corey Minyard <minyard@nortelnetworks.com> - * * Modified driver to utilize a sliding aperture instead of - * mapping all memory into kernel space which turned out to - * be very wasteful. - * * Located a bug in the SROM's initialization sequence that - * made the memory unusable, added a fix to code to touch up - * the DRAM some. + * Corey Minyard <minyard@nortelnetworks.com> + * * Modified driver to utilize a sliding aperture instead of + * mapping all memory into kernel space which turned out to + * be very wasteful. + * * Located a bug in the SROM's initialization sequence that + * made the memory unusable, added a fix to code to touch up + * the DRAM some. * * Bugs/FIXME's: - * * MUST fix the init function to not spin on a register - * waiting for it to set .. this does not safely handle busted - * devices that never reset the register correctly which will - * cause the system to hang w/ a reboot being the only chance at - * recover. [sort of fixed, could be better] - * * Add I2C handling of the SROM so we can read the SROM's information - * about the aperture size. This should always accurately reflect the - * onboard memory size. - * * Comb the init routine. It's still a bit cludgy on a few things. + * * MUST fix the init function to not spin on a register + * waiting for it to set .. this does not safely handle busted + * devices that never reset the register correctly which will + * cause the system to hang w/ a reboot being the only chance at + * recover. [sort of fixed, could be better] + * * Add I2C handling of the SROM so we can read the SROM's information + * about the aperture size. This should always accurately reflect the + * onboard memory size. + * * Comb the init routine. It's still a bit cludgy on a few things. */ -#include <linux/config.h> #include <linux/kernel.h> #include <linux/module.h> #include <asm/uaccess.h> @@ -100,84 +99,83 @@ #include <asm/system.h> #include <linux/pci.h> -#ifndef CONFIG_PCI -#error Enable PCI in your kernel config -#endif - #include <linux/mtd/mtd.h> #include <linux/mtd/pmc551.h> #include <linux/mtd/compatmac.h> static struct mtd_info *pmc551list; -static int pmc551_erase (struct mtd_info *mtd, struct erase_info *instr) +static int pmc551_erase(struct mtd_info *mtd, struct erase_info *instr) { - struct mypriv *priv = mtd->priv; - u32 soff_hi, soff_lo; /* start address offset hi/lo */ - u32 eoff_hi, eoff_lo; /* end address offset hi/lo */ - unsigned long end; + struct mypriv *priv = mtd->priv; + u32 soff_hi, soff_lo; /* start address offset hi/lo */ + u32 eoff_hi, eoff_lo; /* end address offset hi/lo */ + unsigned long end; u_char *ptr; size_t retlen; #ifdef CONFIG_MTD_PMC551_DEBUG - printk(KERN_DEBUG "pmc551_erase(pos:%ld, len:%ld)\n", (long)instr->addr, (long)instr->len); + printk(KERN_DEBUG "pmc551_erase(pos:%ld, len:%ld)\n", (long)instr->addr, + (long)instr->len); #endif - end = instr->addr + instr->len - 1; + end = instr->addr + instr->len - 1; - /* Is it past the end? */ - if ( end > mtd->size ) { + /* Is it past the end? */ + if (end > mtd->size) { #ifdef CONFIG_MTD_PMC551_DEBUG - printk(KERN_DEBUG "pmc551_erase() out of bounds (%ld > %ld)\n", (long)end, (long)mtd->size); + printk(KERN_DEBUG "pmc551_erase() out of bounds (%ld > %ld)\n", + (long)end, (long)mtd->size); #endif - return -EINVAL; - } - - eoff_hi = end & ~(priv->asize - 1); - soff_hi = instr->addr & ~(priv->asize - 1); - eoff_lo = end & (priv->asize - 1); - soff_lo = instr->addr & (priv->asize - 1); - - pmc551_point (mtd, instr->addr, instr->len, &retlen, &ptr); - - if ( soff_hi == eoff_hi || mtd->size == priv->asize) { - /* The whole thing fits within one access, so just one shot - will do it. */ - memset(ptr, 0xff, instr->len); - } else { - /* We have to do multiple writes to get all the data - written. */ - while (soff_hi != eoff_hi) { + return -EINVAL; + } + + eoff_hi = end & ~(priv->asize - 1); + soff_hi = instr->addr & ~(priv->asize - 1); + eoff_lo = end & (priv->asize - 1); + soff_lo = instr->addr & (priv->asize - 1); + + pmc551_point(mtd, instr->addr, instr->len, &retlen, &ptr); + + if (soff_hi == eoff_hi || mtd->size == priv->asize) { + /* The whole thing fits within one access, so just one shot + will do it. */ + memset(ptr, 0xff, instr->len); + } else { + /* We have to do multiple writes to get all the data + written. */ + while (soff_hi != eoff_hi) { #ifdef CONFIG_MTD_PMC551_DEBUG - printk( KERN_DEBUG "pmc551_erase() soff_hi: %ld, eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi); + printk(KERN_DEBUG "pmc551_erase() soff_hi: %ld, " + "eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi); #endif - memset(ptr, 0xff, priv->asize); - if (soff_hi + priv->asize >= mtd->size) { - goto out; - } - soff_hi += priv->asize; - pmc551_point (mtd,(priv->base_map0|soff_hi), - priv->asize, &retlen, &ptr); - } - memset (ptr, 0xff, eoff_lo); - } - -out: + memset(ptr, 0xff, priv->asize); + if (soff_hi + priv->asize >= mtd->size) { + goto out; + } + soff_hi += priv->asize; + pmc551_point(mtd, (priv->base_map0 | soff_hi), + priv->asize, &retlen, &ptr); + } + memset(ptr, 0xff, eoff_lo); + } + + out: instr->state = MTD_ERASE_DONE; #ifdef CONFIG_MTD_PMC551_DEBUG printk(KERN_DEBUG "pmc551_erase() done\n"); #endif - mtd_erase_callback(instr); - return 0; + mtd_erase_callback(instr); + return 0; } - -static int pmc551_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf) +static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len, + size_t * retlen, u_char ** mtdbuf) { - struct mypriv *priv = mtd->priv; - u32 soff_hi; - u32 soff_lo; + struct mypriv *priv = mtd->priv; + u32 soff_hi; + u32 soff_lo; #ifdef CONFIG_MTD_PMC551_DEBUG printk(KERN_DEBUG "pmc551_point(%ld, %ld)\n", (long)from, (long)len); @@ -185,18 +183,19 @@ static int pmc551_point (struct mtd_info *mtd, loff_t from, size_t len, size_t * if (from + len > mtd->size) { #ifdef CONFIG_MTD_PMC551_DEBUG - printk(KERN_DEBUG "pmc551_point() out of bounds (%ld > %ld)\n", (long)from+len, (long)mtd->size); + printk(KERN_DEBUG "pmc551_point() out of bounds (%ld > %ld)\n", + (long)from + len, (long)mtd->size); #endif return -EINVAL; } - soff_hi = from & ~(priv->asize - 1); - soff_lo = from & (priv->asize - 1); + soff_hi = from & ~(priv->asize - 1); + soff_lo = from & (priv->asize - 1); /* Cheap hack optimization */ - if( priv->curr_map0 != from ) { - pci_write_config_dword ( priv->dev, PMC551_PCI_MEM_MAP0, - (priv->base_map0 | soff_hi) ); + if (priv->curr_map0 != from) { + pci_write_config_dword(priv->dev, PMC551_PCI_MEM_MAP0, + (priv->base_map0 | soff_hi)); priv->curr_map0 = soff_hi; } @@ -205,137 +204,144 @@ static int pmc551_point (struct mtd_info *mtd, loff_t from, size_t len, size_t * return 0; } - -static void pmc551_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) +static void pmc551_unpoint(struct mtd_info *mtd, u_char * addr, loff_t from, + size_t len) { #ifdef CONFIG_MTD_PMC551_DEBUG printk(KERN_DEBUG "pmc551_unpoint()\n"); #endif } - -static int pmc551_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) +static int pmc551_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t * retlen, u_char * buf) { - struct mypriv *priv = mtd->priv; - u32 soff_hi, soff_lo; /* start address offset hi/lo */ - u32 eoff_hi, eoff_lo; /* end address offset hi/lo */ - unsigned long end; + struct mypriv *priv = mtd->priv; + u32 soff_hi, soff_lo; /* start address offset hi/lo */ + u32 eoff_hi, eoff_lo; /* end address offset hi/lo */ + unsigned long end; u_char *ptr; - u_char *copyto = buf; + u_char *copyto = buf; #ifdef CONFIG_MTD_PMC551_DEBUG - printk(KERN_DEBUG "pmc551_read(pos:%ld, len:%ld) asize: %ld\n", (long)from, (long)len, (long)priv->asize); + printk(KERN_DEBUG "pmc551_read(pos:%ld, len:%ld) asize: %ld\n", + (long)from, (long)len, (long)priv->asize); #endif - end = from + len - 1; + end = from + len - 1; - /* Is it past the end? */ - if (end > mtd->size) { + /* Is it past the end? */ + if (end > mtd->size) { #ifdef CONFIG_MTD_PMC551_DEBUG - printk(KERN_DEBUG "pmc551_read() out of bounds (%ld > %ld)\n", (long) end, (long)mtd->size); + printk(KERN_DEBUG "pmc551_read() out of bounds (%ld > %ld)\n", + (long)end, (long)mtd->size); #endif - return -EINVAL; - } - - soff_hi = from & ~(priv->asize - 1); - eoff_hi = end & ~(priv->asize - 1); - soff_lo = from & (priv->asize - 1); - eoff_lo = end & (priv->asize - 1); - - pmc551_point (mtd, from, len, retlen, &ptr); - - if (soff_hi == eoff_hi) { - /* The whole thing fits within one access, so just one shot - will do it. */ - memcpy(copyto, ptr, len); - copyto += len; - } else { - /* We have to do multiple writes to get all the data - written. */ - while (soff_hi != eoff_hi) { + return -EINVAL; + } + + soff_hi = from & ~(priv->asize - 1); + eoff_hi = end & ~(priv->asize - 1); + soff_lo = from & (priv->asize - 1); + eoff_lo = end & (priv->asize - 1); + + pmc551_point(mtd, from, len, retlen, &ptr); + + if (soff_hi == eoff_hi) { + /* The whole thing fits within one access, so just one shot + will do it. */ + memcpy(copyto, ptr, len); + copyto += len; + } else { + /* We have to do multiple writes to get all the data + written. */ + while (soff_hi != eoff_hi) { #ifdef CONFIG_MTD_PMC551_DEBUG - printk( KERN_DEBUG "pmc551_read() soff_hi: %ld, eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi); + printk(KERN_DEBUG "pmc551_read() soff_hi: %ld, " + "eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi); #endif - memcpy(copyto, ptr, priv->asize); - copyto += priv->asize; - if (soff_hi + priv->asize >= mtd->size) { - goto out; - } - soff_hi += priv->asize; - pmc551_point (mtd, soff_hi, priv->asize, retlen, &ptr); - } - memcpy(copyto, ptr, eoff_lo); - copyto += eoff_lo; - } - -out: + memcpy(copyto, ptr, priv->asize); + copyto += priv->asize; + if (soff_hi + priv->asize >= mtd->size) { + goto out; + } + soff_hi += priv->asize; + pmc551_point(mtd, soff_hi, priv->asize, retlen, &ptr); + } + memcpy(copyto, ptr, eoff_lo); + copyto += eoff_lo; + } + + out: #ifdef CONFIG_MTD_PMC551_DEBUG printk(KERN_DEBUG "pmc551_read() done\n"); #endif - *retlen = copyto - buf; - return 0; + *retlen = copyto - buf; + return 0; } -static int pmc551_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) +static int pmc551_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t * retlen, const u_char * buf) { - struct mypriv *priv = mtd->priv; - u32 soff_hi, soff_lo; /* start address offset hi/lo */ - u32 eoff_hi, eoff_lo; /* end address offset hi/lo */ - unsigned long end; + struct mypriv *priv = mtd->priv; + u32 soff_hi, soff_lo; /* start address offset hi/lo */ + u32 eoff_hi, eoff_lo; /* end address offset hi/lo */ + unsigned long end; u_char *ptr; - const u_char *copyfrom = buf; - + const u_char *copyfrom = buf; #ifdef CONFIG_MTD_PMC551_DEBUG - printk(KERN_DEBUG "pmc551_write(pos:%ld, len:%ld) asize:%ld\n", (long)to, (long)len, (long)priv->asize); + printk(KERN_DEBUG "pmc551_write(pos:%ld, len:%ld) asize:%ld\n", + (long)to, (long)len, (long)priv->asize); #endif - end = to + len - 1; - /* Is it past the end? or did the u32 wrap? */ - if (end > mtd->size ) { + end = to + len - 1; + /* Is it past the end? or did the u32 wrap? */ + if (end > mtd->size) { #ifdef CONFIG_MTD_PMC551_DEBUG - printk(KERN_DEBUG "pmc551_write() out of bounds (end: %ld, size: %ld, to: %ld)\n", (long) end, (long)mtd->size, (long)to); + printk(KERN_DEBUG "pmc551_write() out of bounds (end: %ld, " + "size: %ld, to: %ld)\n", (long)end, (long)mtd->size, + (long)to); #endif - return -EINVAL; - } - - soff_hi = to & ~(priv->asize - 1); - eoff_hi = end & ~(priv->asize - 1); - soff_lo = to & (priv->asize - 1); - eoff_lo = end & (priv->asize - 1); - - pmc551_point (mtd, to, len, retlen, &ptr); - - if (soff_hi == eoff_hi) { - /* The whole thing fits within one access, so just one shot - will do it. */ - memcpy(ptr, copyfrom, len); - copyfrom += len; - } else { - /* We have to do multiple writes to get all the data - written. */ - while (soff_hi != eoff_hi) { + return -EINVAL; + } + + soff_hi = to & ~(priv->asize - 1); + eoff_hi = end & ~(priv->asize - 1); + soff_lo = to & (priv->asize - 1); + eoff_lo = end & (priv->asize - 1); + + pmc551_point(mtd, to, len, retlen, &ptr); + + if (soff_hi == eoff_hi) { + /* The whole thing fits within one access, so just one shot + will do it. */ + memcpy(ptr, copyfrom, len); + copyfrom += len; + } else { + /* We have to do multiple writes to get all the data + written. */ + while (soff_hi != eoff_hi) { #ifdef CONFIG_MTD_PMC551_DEBUG - printk( KERN_DEBUG "pmc551_write() soff_hi: %ld, eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi); + printk(KERN_DEBUG "pmc551_write() soff_hi: %ld, " + "eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi); #endif - memcpy(ptr, copyfrom, priv->asize); - copyfrom += priv->asize; - if (soff_hi >= mtd->size) { - goto out; - } - soff_hi += priv->asize; - pmc551_point (mtd, soff_hi, priv->asize, retlen, &ptr); - } - memcpy(ptr, copyfrom, eoff_lo); - copyfrom += eoff_lo; - } - -out: + memcpy(ptr, copyfrom, priv->asize); + copyfrom += priv->asize; + if (soff_hi >= mtd->size) { + goto out; + } + soff_hi += priv->asize; + pmc551_point(mtd, soff_hi, priv->asize, retlen, &ptr); + } + memcpy(ptr, copyfrom, eoff_lo); + copyfrom += eoff_lo; + } + + out: #ifdef CONFIG_MTD_PMC551_DEBUG printk(KERN_DEBUG "pmc551_write() done\n"); #endif - *retlen = copyfrom - buf; - return 0; + *retlen = copyfrom - buf; + return 0; } /* @@ -350,58 +356,58 @@ out: * mechanism * returns the size of the memory region found. */ -static u32 fixup_pmc551 (struct pci_dev *dev) +static u32 fixup_pmc551(struct pci_dev *dev) { #ifdef CONFIG_MTD_PMC551_BUGFIX - u32 dram_data; + u32 dram_data; #endif - u32 size, dcmd, cfg, dtmp; - u16 cmd, tmp, i; + u32 size, dcmd, cfg, dtmp; + u16 cmd, tmp, i; u8 bcmd, counter; - /* Sanity Check */ - if(!dev) { - return -ENODEV; - } + /* Sanity Check */ + if (!dev) { + return -ENODEV; + } /* * Attempt to reset the card * FIXME: Stop Spinning registers */ - counter=0; + counter = 0; /* unlock registers */ - pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, 0xA5 ); + pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, 0xA5); /* read in old data */ - pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd ); + pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd); /* bang the reset line up and down for a few */ - for(i=0;i<10;i++) { - counter=0; + for (i = 0; i < 10; i++) { + counter = 0; bcmd &= ~0x80; - while(counter++ < 100) { + while (counter++ < 100) { pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd); } - counter=0; + counter = 0; bcmd |= 0x80; - while(counter++ < 100) { + while (counter++ < 100) { pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd); } } - bcmd |= (0x40|0x20); + bcmd |= (0x40 | 0x20); pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd); - /* + /* * Take care and turn off the memory on the device while we * tweak the configurations */ - pci_read_config_word(dev, PCI_COMMAND, &cmd); - tmp = cmd & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY); - pci_write_config_word(dev, PCI_COMMAND, tmp); + pci_read_config_word(dev, PCI_COMMAND, &cmd); + tmp = cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY); + pci_write_config_word(dev, PCI_COMMAND, tmp); /* * Disable existing aperture before probing memory size */ pci_read_config_dword(dev, PMC551_PCI_MEM_MAP0, &dcmd); - dtmp=(dcmd|PMC551_PCI_MEM_MAP_ENABLE|PMC551_PCI_MEM_MAP_REG_EN); + dtmp = (dcmd | PMC551_PCI_MEM_MAP_ENABLE | PMC551_PCI_MEM_MAP_REG_EN); pci_write_config_dword(dev, PMC551_PCI_MEM_MAP0, dtmp); /* * Grab old BAR0 config so that we can figure out memory size @@ -412,220 +418,230 @@ static u32 fixup_pmc551 (struct pci_dev *dev) * then write all 1's to the memory space, read back the result into * "size", and then write back all the old config. */ - pci_read_config_dword( dev, PCI_BASE_ADDRESS_0, &cfg ); + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &cfg); #ifndef CONFIG_MTD_PMC551_BUGFIX - pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, ~0 ); - pci_read_config_dword( dev, PCI_BASE_ADDRESS_0, &size ); - size = (size&PCI_BASE_ADDRESS_MEM_MASK); - size &= ~(size-1); - pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg ); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, ~0); + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &size); + size = (size & PCI_BASE_ADDRESS_MEM_MASK); + size &= ~(size - 1); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, cfg); #else - /* - * Get the size of the memory by reading all the DRAM size values - * and adding them up. - * - * KLUDGE ALERT: the boards we are using have invalid column and - * row mux values. We fix them here, but this will break other - * memory configurations. - */ - pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dram_data); - size = PMC551_DRAM_BLK_GET_SIZE(dram_data); - dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); - dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); - pci_write_config_dword(dev, PMC551_DRAM_BLK0, dram_data); - - pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dram_data); - size += PMC551_DRAM_BLK_GET_SIZE(dram_data); - dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); - dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); - pci_write_config_dword(dev, PMC551_DRAM_BLK1, dram_data); - - pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dram_data); - size += PMC551_DRAM_BLK_GET_SIZE(dram_data); - dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); - dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); - pci_write_config_dword(dev, PMC551_DRAM_BLK2, dram_data); - - pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dram_data); - size += PMC551_DRAM_BLK_GET_SIZE(dram_data); - dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); - dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); - pci_write_config_dword(dev, PMC551_DRAM_BLK3, dram_data); - - /* - * Oops .. something went wrong - */ - if( (size &= PCI_BASE_ADDRESS_MEM_MASK) == 0) { - return -ENODEV; - } -#endif /* CONFIG_MTD_PMC551_BUGFIX */ - - if ((cfg&PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) { - return -ENODEV; + /* + * Get the size of the memory by reading all the DRAM size values + * and adding them up. + * + * KLUDGE ALERT: the boards we are using have invalid column and + * row mux values. We fix them here, but this will break other + * memory configurations. + */ + pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dram_data); + size = PMC551_DRAM_BLK_GET_SIZE(dram_data); + dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); + dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); + pci_write_config_dword(dev, PMC551_DRAM_BLK0, dram_data); + + pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dram_data); + size += PMC551_DRAM_BLK_GET_SIZE(dram_data); + dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); + dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); + pci_write_config_dword(dev, PMC551_DRAM_BLK1, dram_data); + + pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dram_data); + size += PMC551_DRAM_BLK_GET_SIZE(dram_data); + dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); + dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); + pci_write_config_dword(dev, PMC551_DRAM_BLK2, dram_data); + + pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dram_data); + size += PMC551_DRAM_BLK_GET_SIZE(dram_data); + dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); + dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); + pci_write_config_dword(dev, PMC551_DRAM_BLK3, dram_data); + + /* + * Oops .. something went wrong + */ + if ((size &= PCI_BASE_ADDRESS_MEM_MASK) == 0) { + return -ENODEV; + } +#endif /* CONFIG_MTD_PMC551_BUGFIX */ + + if ((cfg & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) { + return -ENODEV; } - /* - * Precharge Dram - */ - pci_write_config_word( dev, PMC551_SDRAM_MA, 0x0400 ); - pci_write_config_word( dev, PMC551_SDRAM_CMD, 0x00bf ); - - /* - * Wait until command has gone through - * FIXME: register spinning issue - */ - do { pci_read_config_word( dev, PMC551_SDRAM_CMD, &cmd ); - if(counter++ > 100)break; - } while ( (PCI_COMMAND_IO) & cmd ); - - /* + /* + * Precharge Dram + */ + pci_write_config_word(dev, PMC551_SDRAM_MA, 0x0400); + pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x00bf); + + /* + * Wait until command has gone through + * FIXME: register spinning issue + */ + do { + pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd); + if (counter++ > 100) + break; + } while ((PCI_COMMAND_IO) & cmd); + + /* * Turn on auto refresh * The loop is taken directly from Ramix's example code. I assume that * this must be held high for some duration of time, but I can find no * documentation refrencing the reasons why. - */ - for ( i = 1; i<=8 ; i++) { - pci_write_config_word (dev, PMC551_SDRAM_CMD, 0x0df); - - /* - * Make certain command has gone through - * FIXME: register spinning issue - */ - counter=0; - do { pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd); - if(counter++ > 100)break; - } while ( (PCI_COMMAND_IO) & cmd ); - } - - pci_write_config_word ( dev, PMC551_SDRAM_MA, 0x0020); - pci_write_config_word ( dev, PMC551_SDRAM_CMD, 0x0ff); - - /* - * Wait until command completes - * FIXME: register spinning issue - */ - counter=0; - do { pci_read_config_word ( dev, PMC551_SDRAM_CMD, &cmd); - if(counter++ > 100)break; - } while ( (PCI_COMMAND_IO) & cmd ); - - pci_read_config_dword ( dev, PMC551_DRAM_CFG, &dcmd); - dcmd |= 0x02000000; - pci_write_config_dword ( dev, PMC551_DRAM_CFG, dcmd); - - /* - * Check to make certain fast back-to-back, if not - * then set it so - */ - pci_read_config_word( dev, PCI_STATUS, &cmd); - if((cmd&PCI_COMMAND_FAST_BACK) == 0) { - cmd |= PCI_COMMAND_FAST_BACK; - pci_write_config_word( dev, PCI_STATUS, cmd); - } - - /* - * Check to make certain the DEVSEL is set correctly, this device - * has a tendancy to assert DEVSEL and TRDY when a write is performed - * to the memory when memory is read-only - */ - if((cmd&PCI_STATUS_DEVSEL_MASK) != 0x0) { - cmd &= ~PCI_STATUS_DEVSEL_MASK; - pci_write_config_word( dev, PCI_STATUS, cmd ); - } - /* - * Set to be prefetchable and put everything back based on old cfg. + */ + for (i = 1; i <= 8; i++) { + pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x0df); + + /* + * Make certain command has gone through + * FIXME: register spinning issue + */ + counter = 0; + do { + pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd); + if (counter++ > 100) + break; + } while ((PCI_COMMAND_IO) & cmd); + } + + pci_write_config_word(dev, PMC551_SDRAM_MA, 0x0020); + pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x0ff); + + /* + * Wait until command completes + * FIXME: register spinning issue + */ + counter = 0; + do { + pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd); + if (counter++ > 100) + break; + } while ((PCI_COMMAND_IO) & cmd); + + pci_read_config_dword(dev, PMC551_DRAM_CFG, &dcmd); + dcmd |= 0x02000000; + pci_write_config_dword(dev, PMC551_DRAM_CFG, dcmd); + + /* + * Check to make certain fast back-to-back, if not + * then set it so + */ + pci_read_config_word(dev, PCI_STATUS, &cmd); + if ((cmd & PCI_COMMAND_FAST_BACK) == 0) { + cmd |= PCI_COMMAND_FAST_BACK; + pci_write_config_word(dev, PCI_STATUS, cmd); + } + + /* + * Check to make certain the DEVSEL is set correctly, this device + * has a tendancy to assert DEVSEL and TRDY when a write is performed + * to the memory when memory is read-only + */ + if ((cmd & PCI_STATUS_DEVSEL_MASK) != 0x0) { + cmd &= ~PCI_STATUS_DEVSEL_MASK; + pci_write_config_word(dev, PCI_STATUS, cmd); + } + /* + * Set to be prefetchable and put everything back based on old cfg. * it's possible that the reset of the V370PDC nuked the original * setup - */ + */ + /* + cfg |= PCI_BASE_ADDRESS_MEM_PREFETCH; + pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg ); + */ + /* - cfg |= PCI_BASE_ADDRESS_MEM_PREFETCH; - pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg ); - */ - - /* - * Turn PCI memory and I/O bus access back on - */ - pci_write_config_word( dev, PCI_COMMAND, - PCI_COMMAND_MEMORY | PCI_COMMAND_IO ); + * Turn PCI memory and I/O bus access back on + */ + pci_write_config_word(dev, PCI_COMMAND, + PCI_COMMAND_MEMORY | PCI_COMMAND_IO); #ifdef CONFIG_MTD_PMC551_DEBUG - /* - * Some screen fun - */ - printk(KERN_DEBUG "pmc551: %d%c (0x%x) of %sprefetchable memory at 0x%lx\n", - (size<1024)?size:(size<1048576)?size>>10:size>>20, - (size<1024)?'B':(size<1048576)?'K':'M', - size, ((dcmd&(0x1<<3)) == 0)?"non-":"", - (dev->resource[0].start)&PCI_BASE_ADDRESS_MEM_MASK ); - - /* - * Check to see the state of the memory - */ - pci_read_config_dword( dev, PMC551_DRAM_BLK0, &dcmd ); - printk(KERN_DEBUG "pmc551: DRAM_BLK0 Flags: %s,%s\n" - "pmc551: DRAM_BLK0 Size: %d at %d\n" - "pmc551: DRAM_BLK0 Row MUX: %d, Col MUX: %d\n", - (((0x1<<1)&dcmd) == 0)?"RW":"RO", - (((0x1<<0)&dcmd) == 0)?"Off":"On", - PMC551_DRAM_BLK_GET_SIZE(dcmd), - ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); - - pci_read_config_dword( dev, PMC551_DRAM_BLK1, &dcmd ); - printk(KERN_DEBUG "pmc551: DRAM_BLK1 Flags: %s,%s\n" - "pmc551: DRAM_BLK1 Size: %d at %d\n" - "pmc551: DRAM_BLK1 Row MUX: %d, Col MUX: %d\n", - (((0x1<<1)&dcmd) == 0)?"RW":"RO", - (((0x1<<0)&dcmd) == 0)?"Off":"On", - PMC551_DRAM_BLK_GET_SIZE(dcmd), - ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); - - pci_read_config_dword( dev, PMC551_DRAM_BLK2, &dcmd ); - printk(KERN_DEBUG "pmc551: DRAM_BLK2 Flags: %s,%s\n" - "pmc551: DRAM_BLK2 Size: %d at %d\n" - "pmc551: DRAM_BLK2 Row MUX: %d, Col MUX: %d\n", - (((0x1<<1)&dcmd) == 0)?"RW":"RO", - (((0x1<<0)&dcmd) == 0)?"Off":"On", - PMC551_DRAM_BLK_GET_SIZE(dcmd), - ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); - - pci_read_config_dword( dev, PMC551_DRAM_BLK3, &dcmd ); - printk(KERN_DEBUG "pmc551: DRAM_BLK3 Flags: %s,%s\n" - "pmc551: DRAM_BLK3 Size: %d at %d\n" - "pmc551: DRAM_BLK3 Row MUX: %d, Col MUX: %d\n", - (((0x1<<1)&dcmd) == 0)?"RW":"RO", - (((0x1<<0)&dcmd) == 0)?"Off":"On", - PMC551_DRAM_BLK_GET_SIZE(dcmd), - ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); - - pci_read_config_word( dev, PCI_COMMAND, &cmd ); - printk( KERN_DEBUG "pmc551: Memory Access %s\n", - (((0x1<<1)&cmd) == 0)?"off":"on" ); - printk( KERN_DEBUG "pmc551: I/O Access %s\n", - (((0x1<<0)&cmd) == 0)?"off":"on" ); - - pci_read_config_word( dev, PCI_STATUS, &cmd ); - printk( KERN_DEBUG "pmc551: Devsel %s\n", - ((PCI_STATUS_DEVSEL_MASK&cmd)==0x000)?"Fast": - ((PCI_STATUS_DEVSEL_MASK&cmd)==0x200)?"Medium": - ((PCI_STATUS_DEVSEL_MASK&cmd)==0x400)?"Slow":"Invalid" ); - - printk( KERN_DEBUG "pmc551: %sFast Back-to-Back\n", - ((PCI_COMMAND_FAST_BACK&cmd) == 0)?"Not ":"" ); - - pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd ); - printk( KERN_DEBUG "pmc551: EEPROM is under %s control\n" - "pmc551: System Control Register is %slocked to PCI access\n" - "pmc551: System Control Register is %slocked to EEPROM access\n", - (bcmd&0x1)?"software":"hardware", - (bcmd&0x20)?"":"un", (bcmd&0x40)?"":"un"); + /* + * Some screen fun + */ + printk(KERN_DEBUG "pmc551: %d%c (0x%x) of %sprefetchable memory at " + "0x%llx\n", (size < 1024) ? size : (size < 1048576) ? + size >> 10 : size >> 20, + (size < 1024) ? 'B' : (size < 1048576) ? 'K' : 'M', size, + ((dcmd & (0x1 << 3)) == 0) ? "non-" : "", + (unsigned long long)pci_resource_start(dev, 0)); + + /* + * Check to see the state of the memory + */ + pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dcmd); + printk(KERN_DEBUG "pmc551: DRAM_BLK0 Flags: %s,%s\n" + "pmc551: DRAM_BLK0 Size: %d at %d\n" + "pmc551: DRAM_BLK0 Row MUX: %d, Col MUX: %d\n", + (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO", + (((0x1 << 0) & dcmd) == 0) ? "Off" : "On", + PMC551_DRAM_BLK_GET_SIZE(dcmd), + ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7), + ((dcmd >> 9) & 0xF)); + + pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dcmd); + printk(KERN_DEBUG "pmc551: DRAM_BLK1 Flags: %s,%s\n" + "pmc551: DRAM_BLK1 Size: %d at %d\n" + "pmc551: DRAM_BLK1 Row MUX: %d, Col MUX: %d\n", + (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO", + (((0x1 << 0) & dcmd) == 0) ? "Off" : "On", + PMC551_DRAM_BLK_GET_SIZE(dcmd), + ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7), + ((dcmd >> 9) & 0xF)); + + pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dcmd); + printk(KERN_DEBUG "pmc551: DRAM_BLK2 Flags: %s,%s\n" + "pmc551: DRAM_BLK2 Size: %d at %d\n" + "pmc551: DRAM_BLK2 Row MUX: %d, Col MUX: %d\n", + (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO", + (((0x1 << 0) & dcmd) == 0) ? "Off" : "On", + PMC551_DRAM_BLK_GET_SIZE(dcmd), + ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7), + ((dcmd >> 9) & 0xF)); + + pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dcmd); + printk(KERN_DEBUG "pmc551: DRAM_BLK3 Flags: %s,%s\n" + "pmc551: DRAM_BLK3 Size: %d at %d\n" + "pmc551: DRAM_BLK3 Row MUX: %d, Col MUX: %d\n", + (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO", + (((0x1 << 0) & dcmd) == 0) ? "Off" : "On", + PMC551_DRAM_BLK_GET_SIZE(dcmd), + ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7), + ((dcmd >> 9) & 0xF)); + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + printk(KERN_DEBUG "pmc551: Memory Access %s\n", + (((0x1 << 1) & cmd) == 0) ? "off" : "on"); + printk(KERN_DEBUG "pmc551: I/O Access %s\n", + (((0x1 << 0) & cmd) == 0) ? "off" : "on"); + + pci_read_config_word(dev, PCI_STATUS, &cmd); + printk(KERN_DEBUG "pmc551: Devsel %s\n", + ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x000) ? "Fast" : + ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x200) ? "Medium" : + ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x400) ? "Slow" : "Invalid"); + + printk(KERN_DEBUG "pmc551: %sFast Back-to-Back\n", + ((PCI_COMMAND_FAST_BACK & cmd) == 0) ? "Not " : ""); + + pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd); + printk(KERN_DEBUG "pmc551: EEPROM is under %s control\n" + "pmc551: System Control Register is %slocked to PCI access\n" + "pmc551: System Control Register is %slocked to EEPROM access\n", + (bcmd & 0x1) ? "software" : "hardware", + (bcmd & 0x20) ? "" : "un", (bcmd & 0x40) ? "" : "un"); #endif - return size; + return size; } /* * Kernel version specific module stuffages */ - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Mark Ferrell <mferrell@mvista.com>"); MODULE_DESCRIPTION(PMC551_VERSION); @@ -633,11 +649,11 @@ MODULE_DESCRIPTION(PMC551_VERSION); /* * Stuff these outside the ifdef so as to not bust compiled in driver support */ -static int msize=0; +static int msize = 0; #if defined(CONFIG_MTD_PMC551_APERTURE_SIZE) -static int asize=CONFIG_MTD_PMC551_APERTURE_SIZE +static int asize = CONFIG_MTD_PMC551_APERTURE_SIZE #else -static int asize=0; +static int asize = 0; #endif module_param(msize, int, 0); @@ -650,163 +666,174 @@ MODULE_PARM_DESC(asize, "aperture size, must be <= memsize [1-1024]"); */ static int __init init_pmc551(void) { - struct pci_dev *PCI_Device = NULL; - struct mypriv *priv; - int count, found=0; - struct mtd_info *mtd; - u32 length = 0; - - if(msize) { - msize = (1 << (ffs(msize) - 1))<<20; - if (msize > (1<<30)) { - printk(KERN_NOTICE "pmc551: Invalid memory size [%d]\n", msize); + struct pci_dev *PCI_Device = NULL; + struct mypriv *priv; + int count, found = 0; + struct mtd_info *mtd; + u32 length = 0; + + if (msize) { + msize = (1 << (ffs(msize) - 1)) << 20; + if (msize > (1 << 30)) { + printk(KERN_NOTICE "pmc551: Invalid memory size [%d]\n", + msize); return -EINVAL; } } - if(asize) { - asize = (1 << (ffs(asize) - 1))<<20; - if (asize > (1<<30) ) { - printk(KERN_NOTICE "pmc551: Invalid aperture size [%d]\n", asize); + if (asize) { + asize = (1 << (ffs(asize) - 1)) << 20; + if (asize > (1 << 30)) { + printk(KERN_NOTICE "pmc551: Invalid aperture size " + "[%d]\n", asize); return -EINVAL; } } - printk(KERN_INFO PMC551_VERSION); - - /* - * PCU-bus chipset probe. - */ - for( count = 0; count < MAX_MTD_DEVICES; count++ ) { - - if ((PCI_Device = pci_find_device(PCI_VENDOR_ID_V3_SEMI, - PCI_DEVICE_ID_V3_SEMI_V370PDC, - PCI_Device ) ) == NULL) { - break; - } - - printk(KERN_NOTICE "pmc551: Found PCI V370PDC at 0x%lX\n", - PCI_Device->resource[0].start); - - /* - * The PMC551 device acts VERY weird if you don't init it - * first. i.e. it will not correctly report devsel. If for - * some reason the sdram is in a wrote-protected state the - * device will DEVSEL when it is written to causing problems - * with the oldproc.c driver in - * some kernels (2.2.*) - */ - if((length = fixup_pmc551(PCI_Device)) <= 0) { - printk(KERN_NOTICE "pmc551: Cannot init SDRAM\n"); - break; - } + printk(KERN_INFO PMC551_VERSION); + + /* + * PCU-bus chipset probe. + */ + for (count = 0; count < MAX_MTD_DEVICES; count++) { + + if ((PCI_Device = pci_get_device(PCI_VENDOR_ID_V3_SEMI, + PCI_DEVICE_ID_V3_SEMI_V370PDC, + PCI_Device)) == NULL) { + break; + } + + printk(KERN_NOTICE "pmc551: Found PCI V370PDC at 0x%llx\n", + (unsigned long long)pci_resource_start(PCI_Device, 0)); + + /* + * The PMC551 device acts VERY weird if you don't init it + * first. i.e. it will not correctly report devsel. If for + * some reason the sdram is in a wrote-protected state the + * device will DEVSEL when it is written to causing problems + * with the oldproc.c driver in + * some kernels (2.2.*) + */ + if ((length = fixup_pmc551(PCI_Device)) <= 0) { + printk(KERN_NOTICE "pmc551: Cannot init SDRAM\n"); + break; + } /* * This is needed until the driver is capable of reading the * onboard I2C SROM to discover the "real" memory size. */ - if(msize) { + if (msize) { length = msize; - printk(KERN_NOTICE "pmc551: Using specified memory size 0x%x\n", length); + printk(KERN_NOTICE "pmc551: Using specified memory " + "size 0x%x\n", length); } else { msize = length; } - mtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL); - if (!mtd) { - printk(KERN_NOTICE "pmc551: Cannot allocate new MTD device.\n"); - break; - } - - memset(mtd, 0, sizeof(struct mtd_info)); - - priv = kmalloc (sizeof(struct mypriv), GFP_KERNEL); - if (!priv) { - printk(KERN_NOTICE "pmc551: Cannot allocate new MTD device.\n"); - kfree(mtd); - break; - } - memset(priv, 0, sizeof(*priv)); - mtd->priv = priv; - priv->dev = PCI_Device; - - if(asize > length) { - printk(KERN_NOTICE "pmc551: reducing aperture size to fit %dM\n",length>>20); + mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL); + if (!mtd) { + printk(KERN_NOTICE "pmc551: Cannot allocate new MTD " + "device.\n"); + break; + } + + priv = kzalloc(sizeof(struct mypriv), GFP_KERNEL); + if (!priv) { + printk(KERN_NOTICE "pmc551: Cannot allocate new MTD " + "device.\n"); + kfree(mtd); + break; + } + mtd->priv = priv; + priv->dev = PCI_Device; + + if (asize > length) { + printk(KERN_NOTICE "pmc551: reducing aperture size to " + "fit %dM\n", length >> 20); priv->asize = asize = length; } else if (asize == 0 || asize == length) { - printk(KERN_NOTICE "pmc551: Using existing aperture size %dM\n", length>>20); + printk(KERN_NOTICE "pmc551: Using existing aperture " + "size %dM\n", length >> 20); priv->asize = asize = length; } else { - printk(KERN_NOTICE "pmc551: Using specified aperture size %dM\n", asize>>20); + printk(KERN_NOTICE "pmc551: Using specified aperture " + "size %dM\n", asize >> 20); priv->asize = asize; } - priv->start = ioremap(((PCI_Device->resource[0].start) - & PCI_BASE_ADDRESS_MEM_MASK), - priv->asize); + priv->start = pci_iomap(PCI_Device, 0, priv->asize); if (!priv->start) { printk(KERN_NOTICE "pmc551: Unable to map IO space\n"); - kfree(mtd->priv); - kfree(mtd); + kfree(mtd->priv); + kfree(mtd); break; } - #ifdef CONFIG_MTD_PMC551_DEBUG - printk( KERN_DEBUG "pmc551: setting aperture to %d\n", - ffs(priv->asize>>20)-1); + printk(KERN_DEBUG "pmc551: setting aperture to %d\n", + ffs(priv->asize >> 20) - 1); #endif - priv->base_map0 = ( PMC551_PCI_MEM_MAP_REG_EN - | PMC551_PCI_MEM_MAP_ENABLE - | (ffs(priv->asize>>20)-1)<<4 ); - priv->curr_map0 = priv->base_map0; - pci_write_config_dword ( priv->dev, PMC551_PCI_MEM_MAP0, - priv->curr_map0 ); + priv->base_map0 = (PMC551_PCI_MEM_MAP_REG_EN + | PMC551_PCI_MEM_MAP_ENABLE + | (ffs(priv->asize >> 20) - 1) << 4); + priv->curr_map0 = priv->base_map0; + pci_write_config_dword(priv->dev, PMC551_PCI_MEM_MAP0, + priv->curr_map0); #ifdef CONFIG_MTD_PMC551_DEBUG - printk( KERN_DEBUG "pmc551: aperture set to %d\n", - (priv->base_map0 & 0xF0)>>4 ); + printk(KERN_DEBUG "pmc551: aperture set to %d\n", + (priv->base_map0 & 0xF0) >> 4); #endif - mtd->size = msize; - mtd->flags = MTD_CAP_RAM; - mtd->erase = pmc551_erase; - mtd->read = pmc551_read; - mtd->write = pmc551_write; - mtd->point = pmc551_point; - mtd->unpoint = pmc551_unpoint; - mtd->type = MTD_RAM; - mtd->name = "PMC551 RAM board"; - mtd->erasesize = 0x10000; + mtd->size = msize; + mtd->flags = MTD_CAP_RAM; + mtd->erase = pmc551_erase; + mtd->read = pmc551_read; + mtd->write = pmc551_write; + mtd->point = pmc551_point; + mtd->unpoint = pmc551_unpoint; + mtd->type = MTD_RAM; + mtd->name = "PMC551 RAM board"; + mtd->erasesize = 0x10000; + mtd->writesize = 1; mtd->owner = THIS_MODULE; - if (add_mtd_device(mtd)) { - printk(KERN_NOTICE "pmc551: Failed to register new device\n"); - iounmap(priv->start); - kfree(mtd->priv); - kfree(mtd); - break; - } - printk(KERN_NOTICE "Registered pmc551 memory device.\n"); - printk(KERN_NOTICE "Mapped %dM of memory from 0x%p to 0x%p\n", - priv->asize>>20, - priv->start, - priv->start + priv->asize); - printk(KERN_NOTICE "Total memory is %d%c\n", - (length<1024)?length: - (length<1048576)?length>>10:length>>20, - (length<1024)?'B':(length<1048576)?'K':'M'); + if (add_mtd_device(mtd)) { + printk(KERN_NOTICE "pmc551: Failed to register new " + "device\n"); + pci_iounmap(PCI_Device, priv->start); + kfree(mtd->priv); + kfree(mtd); + break; + } + + /* Keep a reference as the add_mtd_device worked */ + pci_dev_get(PCI_Device); + + printk(KERN_NOTICE "Registered pmc551 memory device.\n"); + printk(KERN_NOTICE "Mapped %dM of memory from 0x%p to 0x%p\n", + priv->asize >> 20, + priv->start, priv->start + priv->asize); + printk(KERN_NOTICE "Total memory is %d%c\n", + (length < 1024) ? length : + (length < 1048576) ? length >> 10 : length >> 20, + (length < 1024) ? 'B' : (length < 1048576) ? 'K' : 'M'); priv->nextpmc551 = pmc551list; pmc551list = mtd; found++; - } + } + + /* Exited early, reference left over */ + if (PCI_Device) + pci_dev_put(PCI_Device); - if( !pmc551list ) { - printk(KERN_NOTICE "pmc551: not detected\n"); - return -ENODEV; - } else { + if (!pmc551list) { + printk(KERN_NOTICE "pmc551: not detected\n"); + return -ENODEV; + } else { printk(KERN_NOTICE "pmc551: %d pmc551 devices loaded\n", found); - return 0; + return 0; } } @@ -815,23 +842,24 @@ static int __init init_pmc551(void) */ static void __exit cleanup_pmc551(void) { - int found=0; - struct mtd_info *mtd; + int found = 0; + struct mtd_info *mtd; struct mypriv *priv; - while((mtd=pmc551list)) { + while ((mtd = pmc551list)) { priv = mtd->priv; pmc551list = priv->nextpmc551; - if(priv->start) { - printk (KERN_DEBUG "pmc551: unmapping %dM starting at 0x%p\n", - priv->asize>>20, priv->start); - iounmap (priv->start); + if (priv->start) { + printk(KERN_DEBUG "pmc551: unmapping %dM starting at " + "0x%p\n", priv->asize >> 20, priv->start); + pci_iounmap(priv->dev, priv->start); } + pci_dev_put(priv->dev); - kfree (mtd->priv); - del_mtd_device (mtd); - kfree (mtd); + kfree(mtd->priv); + del_mtd_device(mtd); + kfree(mtd); found++; } diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c index b3f665e3c38b..542a0c009006 100644 --- a/drivers/mtd/devices/slram.c +++ b/drivers/mtd/devices/slram.c @@ -209,6 +209,7 @@ static int register_device(char *name, unsigned long start, unsigned long length (*curmtd)->mtdinfo->owner = THIS_MODULE; (*curmtd)->mtdinfo->type = MTD_RAM; (*curmtd)->mtdinfo->erasesize = SLRAM_BLK_SZ; + (*curmtd)->mtdinfo->writesize = 1; if (add_mtd_device((*curmtd)->mtdinfo)) { E("slram: Failed to register new device\n"); |