aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/devices/doc2000.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/devices/doc2000.c')
-rw-r--r--drivers/mtd/devices/doc2000.c129
1 files changed, 29 insertions, 100 deletions
diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c
index 23e7a5c7d2c1..c54e40464d82 100644
--- a/drivers/mtd/devices/doc2000.c
+++ b/drivers/mtd/devices/doc2000.c
@@ -59,13 +59,10 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
59 size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel); 59 size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
60static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, 60static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
61 size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel); 61 size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
62static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, 62static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
63 unsigned long count, loff_t to, size_t *retlen, 63 struct mtd_oob_ops *ops);
64 u_char *eccbuf, struct nand_oobinfo *oobsel); 64static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
65static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, 65 struct mtd_oob_ops *ops);
66 size_t *retlen, u_char *buf);
67static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
68 size_t *retlen, const u_char *buf);
69static int doc_write_oob_nolock(struct mtd_info *mtd, loff_t ofs, size_t len, 66static int doc_write_oob_nolock(struct mtd_info *mtd, loff_t ofs, size_t len,
70 size_t *retlen, const u_char *buf); 67 size_t *retlen, const u_char *buf);
71static int doc_erase (struct mtd_info *mtd, struct erase_info *instr); 68static int doc_erase (struct mtd_info *mtd, struct erase_info *instr);
@@ -517,16 +514,9 @@ static int DoC2k_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2)
517 return retval; 514 return retval;
518} 515}
519 516
520static const char im_name[] = "DoC2k_init"; 517/* This routine is found from the docprobe code by symbol_get(),
521 518 * which will bump the use count of this module. */
522/* This routine is made available to other mtd code via 519void DoC2k_init(struct mtd_info *mtd)
523 * inter_module_register. It must only be accessed through
524 * inter_module_get which will bump the use count of this module. The
525 * addresses passed back in mtd are valid as long as the use count of
526 * this module is non-zero, i.e. between inter_module_get and
527 * inter_module_put. Keith Owens <kaos@ocs.com.au> 29 Oct 2000.
528 */
529static void DoC2k_init(struct mtd_info *mtd)
530{ 520{
531 struct DiskOnChip *this = mtd->priv; 521 struct DiskOnChip *this = mtd->priv;
532 struct DiskOnChip *old = NULL; 522 struct DiskOnChip *old = NULL;
@@ -586,7 +576,7 @@ static void DoC2k_init(struct mtd_info *mtd)
586 mtd->ecctype = MTD_ECC_RS_DiskOnChip; 576 mtd->ecctype = MTD_ECC_RS_DiskOnChip;
587 mtd->size = 0; 577 mtd->size = 0;
588 mtd->erasesize = 0; 578 mtd->erasesize = 0;
589 mtd->oobblock = 512; 579 mtd->writesize = 512;
590 mtd->oobsize = 16; 580 mtd->oobsize = 16;
591 mtd->owner = THIS_MODULE; 581 mtd->owner = THIS_MODULE;
592 mtd->erase = doc_erase; 582 mtd->erase = doc_erase;
@@ -594,9 +584,6 @@ static void DoC2k_init(struct mtd_info *mtd)
594 mtd->unpoint = NULL; 584 mtd->unpoint = NULL;
595 mtd->read = doc_read; 585 mtd->read = doc_read;
596 mtd->write = doc_write; 586 mtd->write = doc_write;
597 mtd->read_ecc = doc_read_ecc;
598 mtd->write_ecc = doc_write_ecc;
599 mtd->writev_ecc = doc_writev_ecc;
600 mtd->read_oob = doc_read_oob; 587 mtd->read_oob = doc_read_oob;
601 mtd->write_oob = doc_write_oob; 588 mtd->write_oob = doc_write_oob;
602 mtd->sync = NULL; 589 mtd->sync = NULL;
@@ -623,6 +610,7 @@ static void DoC2k_init(struct mtd_info *mtd)
623 return; 610 return;
624 } 611 }
625} 612}
613EXPORT_SYMBOL_GPL(DoC2k_init);
626 614
627static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, 615static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
628 size_t * retlen, u_char * buf) 616 size_t * retlen, u_char * buf)
@@ -971,72 +959,18 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
971 return 0; 959 return 0;
972} 960}
973 961
974static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, 962static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
975 unsigned long count, loff_t to, size_t *retlen, 963 struct mtd_oob_ops *ops)
976 u_char *eccbuf, struct nand_oobinfo *oobsel)
977{
978 static char static_buf[512];
979 static DEFINE_MUTEX(writev_buf_mutex);
980
981 size_t totretlen = 0;
982 size_t thisvecofs = 0;
983 int ret= 0;
984
985 mutex_lock(&writev_buf_mutex);
986
987 while(count) {
988 size_t thislen, thisretlen;
989 unsigned char *buf;
990
991 buf = vecs->iov_base + thisvecofs;
992 thislen = vecs->iov_len - thisvecofs;
993
994
995 if (thislen >= 512) {
996 thislen = thislen & ~(512-1);
997 thisvecofs += thislen;
998 } else {
999 /* Not enough to fill a page. Copy into buf */
1000 memcpy(static_buf, buf, thislen);
1001 buf = &static_buf[thislen];
1002
1003 while(count && thislen < 512) {
1004 vecs++;
1005 count--;
1006 thisvecofs = min((512-thislen), vecs->iov_len);
1007 memcpy(buf, vecs->iov_base, thisvecofs);
1008 thislen += thisvecofs;
1009 buf += thisvecofs;
1010 }
1011 buf = static_buf;
1012 }
1013 if (count && thisvecofs == vecs->iov_len) {
1014 thisvecofs = 0;
1015 vecs++;
1016 count--;
1017 }
1018 ret = doc_write_ecc(mtd, to, thislen, &thisretlen, buf, eccbuf, oobsel);
1019
1020 totretlen += thisretlen;
1021
1022 if (ret || thisretlen != thislen)
1023 break;
1024
1025 to += thislen;
1026 }
1027
1028 mutex_unlock(&writev_buf_mutex);
1029 *retlen = totretlen;
1030 return ret;
1031}
1032
1033
1034static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
1035 size_t * retlen, u_char * buf)
1036{ 964{
1037 struct DiskOnChip *this = mtd->priv; 965 struct DiskOnChip *this = mtd->priv;
1038 int len256 = 0, ret; 966 int len256 = 0, ret;
1039 struct Nand *mychip; 967 struct Nand *mychip;
968 uint8_t *buf = ops->oobbuf;
969 size_t len = ops->len;
970
971 BUG_ON(ops->mode != MTD_OOB_PLACE);
972
973 ofs += ops->ooboffs;
1040 974
1041 mutex_lock(&this->lock); 975 mutex_lock(&this->lock);
1042 976
@@ -1077,7 +1011,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
1077 1011
1078 DoC_ReadBuf(this, &buf[len256], len - len256); 1012 DoC_ReadBuf(this, &buf[len256], len - len256);
1079 1013
1080 *retlen = len; 1014 ops->retlen = len;
1081 /* Reading the full OOB data drops us off of the end of the page, 1015 /* Reading the full OOB data drops us off of the end of the page,
1082 * causing the flash device to go into busy mode, so we need 1016 * causing the flash device to go into busy mode, so we need
1083 * to wait until ready 11.4.1 and Toshiba TC58256FT docs */ 1017 * to wait until ready 11.4.1 and Toshiba TC58256FT docs */
@@ -1192,17 +1126,20 @@ static int doc_write_oob_nolock(struct mtd_info *mtd, loff_t ofs, size_t len,
1192 1126
1193} 1127}
1194 1128
1195static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, 1129static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
1196 size_t * retlen, const u_char * buf) 1130 struct mtd_oob_ops *ops)
1197{ 1131{
1198 struct DiskOnChip *this = mtd->priv; 1132 struct DiskOnChip *this = mtd->priv;
1199 int ret; 1133 int ret;
1200 1134
1201 mutex_lock(&this->lock); 1135 BUG_ON(ops->mode != MTD_OOB_PLACE);
1202 ret = doc_write_oob_nolock(mtd, ofs, len, retlen, buf); 1136
1137 mutex_lock(&this->lock);
1138 ret = doc_write_oob_nolock(mtd, ofs + ops->ooboffs, ops->len,
1139 &ops->retlen, ops->oobbuf);
1203 1140
1204 mutex_unlock(&this->lock); 1141 mutex_unlock(&this->lock);
1205 return ret; 1142 return ret;
1206} 1143}
1207 1144
1208static int doc_erase(struct mtd_info *mtd, struct erase_info *instr) 1145static int doc_erase(struct mtd_info *mtd, struct erase_info *instr)
@@ -1277,12 +1214,6 @@ static int doc_erase(struct mtd_info *mtd, struct erase_info *instr)
1277 * 1214 *
1278 ****************************************************************************/ 1215 ****************************************************************************/
1279 1216
1280static int __init init_doc2000(void)
1281{
1282 inter_module_register(im_name, THIS_MODULE, &DoC2k_init);
1283 return 0;
1284}
1285
1286static void __exit cleanup_doc2000(void) 1217static void __exit cleanup_doc2000(void)
1287{ 1218{
1288 struct mtd_info *mtd; 1219 struct mtd_info *mtd;
@@ -1298,11 +1229,9 @@ static void __exit cleanup_doc2000(void)
1298 kfree(this->chips); 1229 kfree(this->chips);
1299 kfree(mtd); 1230 kfree(mtd);
1300 } 1231 }
1301 inter_module_unregister(im_name);
1302} 1232}
1303 1233
1304module_exit(cleanup_doc2000); 1234module_exit(cleanup_doc2000);
1305module_init(init_doc2000);
1306 1235
1307MODULE_LICENSE("GPL"); 1236MODULE_LICENSE("GPL");
1308MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org> et al."); 1237MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org> et al.");