summaryrefslogtreecommitdiffstats
path: root/target/linux/ramips/patches-3.18/0075-mtk_nand_alloc_buffer.patch
blob: ac20198aceb4ace040454e0a5bf52819e8740482 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
From patchwork Fri Nov 13 07:55:08 2015
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [OpenWrt-Devel,RFC] A patch for mt7621 nand controler. Revision 2.
From: Kirill Berezin <fyiwdt@gmail.com>
X-Patchwork-Id: 544092
Message-Id: <CAOFwh=DZieEa4ZA0ex6G3OR2OgEeP6Fh+SSw=Zg-L0wWm1QRTA@mail.gmail.com>
To: openwrt-devel@lists.openwrt.org
Date: Fri, 13 Nov 2015 10:55:08 +0300

Hello,

It turned out that mtk_nand driver uses some sophisticated accounting and a
general nand code must be patched.

This patch adds required read and erase calls to a general nand code. I
used a  code  for re6500 released by Linksys as a reference.

All required operations (erase, write and read) are usable. However I found
that jffs2 filesystem can be created only on top of a ubi volume. I tried
to create jffs2 directly on mtd device but pages with clean markers are
became uncorrectable.

This patch also includes changes that I sent earlier.

Best regards,
Kirill.

Signed-off-by: Kirill Berezin (fyiwdt@gmail.com)

diff -urNb a/drivers/mtd/nand/mtk_nand.c b/drivers/mtd/nand/mtk_nand.c
--- a/drivers/mtd/nand/mtk_nand.c	2015-11-06 16:44:31.000000000 +0400
+++ b/drivers/mtd/nand/mtk_nand.c	2015-11-12 10:06:20.080430855 +0400
@@ -110,6 +110,10 @@
 int manu_id;
 int dev_id;
 
+/* this constant was taken from linux/nand/nand.h v 3.14
+ * in later versions it seems it was removed in order to save a bit of space
+ */
+#define NAND_MAX_OOBSIZE 774
 static u8 local_oob_buf[NAND_MAX_OOBSIZE];
 
 static u8 nand_badblock_offset = 0;
@@ -348,7 +352,7 @@
 		if (0xF == u4ErrNum) {
 			mtd->ecc_stats.failed++;
 			bRet = false;
-			//printk(KERN_ERR"UnCorrectable at PageAddr=%d\n", u4PageAddr);
+			printk(KERN_ERR"mtk_nand: UnCorrectable at PageAddr=%d\n", u4PageAddr);
 		} else {
 			for (i = 0; i < ((u4ErrNum + 1) >> 1); ++i) {
 				au4ErrBitLoc[i] = DRV_Reg32(ECC_DECEL0_REG32 + i);
@@ -1422,7 +1426,7 @@
 {
 	struct nand_chip *chip = (struct nand_chip *)mtd->priv;
 
-	chip->erase_cmd(mtd, page);
+	chip->erase(mtd, page);
 
 	return chip->waitfunc(mtd, chip);
 }
@@ -2094,8 +2098,8 @@
 	nand_chip->write_page = mtk_nand_write_page;
 	nand_chip->ecc.write_oob = mtk_nand_write_oob;
 	nand_chip->block_markbad = mtk_nand_block_markbad;   // need to add nand_get_device()/nand_release_device().
-	//	nand_chip->erase = mtk_nand_erase;	
-	//    nand_chip->read_page = mtk_nand_read_page;
+	nand_chip->erase_mtk = mtk_nand_erase;	
+	nand_chip->read_page = mtk_nand_read_page;
 	nand_chip->ecc.read_oob = mtk_nand_read_oob;
 	nand_chip->block_bad = mtk_nand_block_bad;
 
@@ -2175,6 +2179,21 @@
 	nand_chip->pagemask = (nand_chip->chipsize >> nand_chip->page_shift) - 1;
 	nand_chip->phys_erase_shift = ffs(mtd->erasesize) - 1;
 	nand_chip->chip_shift = ffs(nand_chip->chipsize) - 1;//0x1C;//ffs(nand_chip->chipsize) - 1;
+
+	/* allocate buffers or call select_chip here or a bit earlier*/
+	{
+		struct nand_buffers *nbuf = kzalloc(sizeof(*nbuf) + mtd->writesize + mtd->oobsize * 3, GFP_KERNEL);
+		if (!nbuf) {
+			return -ENOMEM;
+		}
+		nbuf->ecccalc = (uint8_t *)(nbuf + 1);
+		nbuf->ecccode = nbuf->ecccalc + mtd->oobsize;
+		nbuf->databuf = nbuf->ecccode + mtd->oobsize;
+
+		nand_chip->buffers = nbuf;
+		nand_chip->options |= NAND_OWN_BUFFERS;
+	}
+
 	nand_chip->oob_poi = nand_chip->buffers->databuf + mtd->writesize;
 	nand_chip->badblockpos = 0;
 
@@ -2251,6 +2270,9 @@
 	MSG(INIT, "[NFI] mtk_nand_probe fail, err = %d!\n", err);
 	nand_release(mtd);
 	platform_set_drvdata(pdev, NULL);
+	if ( NULL != nand_chip->buffers) {
+		kfree(nand_chip->buffers);
+	}
 	kfree(host);
 	nand_disable_clock();
 	return err;
@@ -2261,8 +2283,12 @@
 {
 	struct mtk_nand_host *host = platform_get_drvdata(pdev);
 	struct mtd_info *mtd = &host->mtd;
+	struct nand_chip *nand_chip = &host->nand_chip;
 
 	nand_release(mtd);
+	if ( NULL != nand_chip->buffers) {
+		kfree(nand_chip->buffers);
+	}
 	kfree(host);
 	nand_disable_clock();
 
diff -urNb a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
--- a/drivers/mtd/nand/nand_base.c	2015-11-06 16:44:31.000000000 +0400
+++ b/drivers/mtd/nand/nand_base.c	2015-11-09 10:24:52.931720862 +0400
@@ -1575,6 +1575,9 @@
 						 __func__, buf);
 
 read_retry:
+#ifdef CONFIG_MTK_MTD_NAND
+			ret = chip->read_page(mtd, chip, bufpoi, page);
+#else
 			chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
 
 			/*
@@ -1593,6 +1596,7 @@
 			else
 				ret = chip->ecc.read_page(mtd, chip, bufpoi,
 							  oob_required, page);
+#endif /* CONFIG_MTK_MTD_NAND */
 			if (ret < 0) {
 				if (use_bufpoi)
 					/* Invalidate page cache */
@@ -2770,8 +2774,11 @@
 		if (page <= chip->pagebuf && chip->pagebuf <
 		    (page + pages_per_block))
 			chip->pagebuf = -1;
-
+#ifdef CONFIG_MTK_MTD_NAND
+		status = chip->erase_mtk(mtd, page & chip->pagemask);
+#else
 		status = chip->erase(mtd, page & chip->pagemask);
+#endif /* CONFIG_MTK_MTD_NAND */
 
 		/*
 		 * See if operation failed and additional status checks are
diff -urNb a/drivers/mtd/nand/nand_device_list.h b/drivers/mtd/nand/nand_device_list.h
--- a/drivers/mtd/nand/nand_device_list.h	2015-11-06 16:44:31.000000000 +0400
+++ b/drivers/mtd/nand/nand_device_list.h	2015-11-06 11:13:26.000000000 +0400
@@ -43,6 +43,8 @@
 	{0xADBC, 0x905554, 5, 16, 512, 128, 2048, 64, 0x10801011, "H9DA4GH4JJAMC", 0},
     {0x01F1, 0x801D01, 4, 8, 128, 128, 2048, 64, 0x30C77fff, "S34ML01G100TF", 0},
     {0x92F1, 0x8095FF, 4, 8, 128, 128, 2048, 64, 0x30C77fff, "F59L1G81A", 0},
+	{0xC8DA, 0x909544, 5, 8, 256, 128, 2048, 64, 0x30C77fff, "F59L2G81A", 0},
+	{0xC8DC, 0x909554, 5, 8, 512, 128, 2048, 64, 0x30C77fff, "F59L4G81A", 0},
 	{0xECD3, 0x519558, 5, 8, 1024, 128, 2048, 64, 0x44333, "K9K8G8000", 0},
     {0xC2F1, 0x801DC2, 4, 8, 128, 128, 2048, 64, 0x30C77fff, "MX30LF1G08AA", 0},
     {0x98D3, 0x902676, 5, 8, 1024, 256, 4096, 224, 0x00C25332, "TC58NVG3S0F", 0},
diff -urNb a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
--- a/include/linux/mtd/nand.h	2015-11-06 16:44:30.000000000 +0400
+++ b/include/linux/mtd/nand.h	2015-11-09 10:18:55.704701886 +0400
@@ -653,6 +653,10 @@
 	int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
 			uint32_t offset, int data_len, const uint8_t *buf,
 			int oob_required, int page, int cached, int raw);
+#ifdef CONFIG_MTK_MTD_NAND
+	int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip, u8 *buf, int page);
+	int (*erase_mtk)(struct mtd_info *mtd, int page);
+#endif /* CONFIG_MTK_MTD_NAND */
 	int (*onfi_set_features)(struct mtd_info *mtd, struct nand_chip *chip,
 			int feature_addr, uint8_t *subfeature_para);
 	int (*onfi_get_features)(struct mtd_info *mtd, struct nand_chip *chip,