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
|
From 61e17c2f864698033f4661e1fc7ba63d4d982491 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Mon, 7 Dec 2015 17:21:55 +0100
Subject: [PATCH 40/53] nand: add mtk-nand hack/hook
Signed-off-by: John Crispin <blogic@openwrt.org>
---
drivers/mtd/nand/mtk_nand.c | 34 ++++++++++++++++++++++++++++++----
drivers/mtd/nand/nand_base.c | 9 ++++++++-
drivers/mtd/nand/nand_device_list.h | 2 ++
include/linux/mtd/nand.h | 4 ++++
4 files changed, 44 insertions(+), 5 deletions(-)
--- a/drivers/mtd/nand/mtk_nand.c
+++ b/drivers/mtd/nand/mtk_nand.c
@@ -110,6 +110,10 @@ int part_num = NUM_PARTITIONS;
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 @@ mtk_nand_check_bch_error(struct mtd_info
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 @@ mtk_nand_erase_hw(struct mtd_info *mtd,
{
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 @@ mtk_nand_probe(struct platform_device *p
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 @@ mtk_nand_probe(struct platform_device *p
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 @@ out:
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 @@ mtk_nand_remove(struct platform_device *
{
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();
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1727,6 +1727,9 @@ static int nand_do_read_ops(struct mtd_i
__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);
/*
@@ -1745,6 +1748,7 @@ read_retry:
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 */
@@ -2932,8 +2936,11 @@ int nand_erase_nand(struct mtd_info *mtd
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
--- a/drivers/mtd/nand/nand_device_list.h
+++ b/drivers/mtd/nand/nand_device_list.h
@@ -43,6 +43,8 @@ static const flashdev_info gen_FlashTabl
{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},
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -665,6 +665,10 @@ struct nand_chip {
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,
|