77 * Peter Pan <peterpandong@micron.com>
88 */
99
10+ #include <linux/mtd/mtd.h>
1011#include <linux/slab.h>
1112
13+ #include "sfc_nand.h"
1214#include "sfc_nand_mtd.h"
1315
1416#ifdef CONFIG_MTD_NAND_BBT_USING_FLASH
@@ -44,12 +46,13 @@ static int nanddev_read_bbt(struct snand_mtd_dev *nand, u32 block, bool update)
4446 unsigned int nbytes = DIV_ROUND_UP (nblocks * bits_per_block ,
4547 BITS_PER_LONG ) * sizeof (* nand -> bbt .cache );
4648 struct mtd_info * mtd = snanddev_to_mtd (nand );
47- u8 * data_buf , * oob_buf ;
49+ u8 * data_buf , * oob_buf , * temp_buf ;
4850 struct nanddev_bbt_info * bbt_info ;
4951 struct mtd_oob_ops ops ;
50- int bbt_page_num ;
52+ u32 bbt_page_num ;
5153 int ret = 0 ;
5254 unsigned int version = 0 ;
55+ u32 page_addr , i ;
5356
5457 if (!nand -> bbt .cache )
5558 return - ENOMEM ;
@@ -74,22 +77,35 @@ static int nanddev_read_bbt(struct snand_mtd_dev *nand, u32 block, bool update)
7477 bbt_info = (struct nanddev_bbt_info * )(data_buf + nbytes );
7578
7679 memset (& ops , 0 , sizeof (struct mtd_oob_ops ));
77- ops .mode = MTD_OPS_RAW ;
80+ ops .mode = MTD_OPS_PLACE_OOB ;
7881 ops .datbuf = data_buf ;
7982 ops .len = bbt_page_num * mtd -> writesize ;
8083 ops .oobbuf = oob_buf ;
8184 ops .ooblen = bbt_page_num * mtd -> oobsize ;
8285 ops .ooboffs = 0 ;
8386
8487 /* Store one entry for each block */
85- ret = sfc_nand_read_mtd (mtd , block * mtd -> erasesize , & ops );
86- if (ret < 0 ) {
87- pr_err ("%s fail %d\n" , __func__ , ret );
88- ret = - EIO ;
89- goto out ;
90- } else {
91- ret = 0 ;
88+ temp_buf = kzalloc (mtd -> writesize + mtd -> oobsize , GFP_KERNEL );
89+ if (!temp_buf ) {
90+ kfree (data_buf );
91+ kfree (oob_buf );
92+
93+ return - ENOMEM ;
9294 }
95+ page_addr = (u32 )(block << (mtd -> erasesize_shift - mtd -> writesize_shift ));
96+ for (i = 0 ; i < bbt_page_num ; i ++ ) {
97+ ret = sfc_nand_read_page_raw (0 , page_addr + i , (u32 * )temp_buf );
98+ if (ret < 0 ) {
99+ pr_err ("%s fail %d\n" , __func__ , ret );
100+ ret = - EIO ;
101+ kfree (temp_buf );
102+ goto out ;
103+ }
104+
105+ memcpy (ops .datbuf + i * mtd -> writesize , temp_buf , mtd -> writesize );
106+ memcpy (ops .oobbuf + i * mtd -> oobsize , temp_buf + mtd -> writesize , mtd -> oobsize );
107+ }
108+ kfree (temp_buf );
93109
94110 if (oob_buf [0 ] != 0xff && !memcmp (bbt_pattern , bbt_info -> pattern , 4 ))
95111 version = bbt_info -> version ;
@@ -114,11 +130,12 @@ static int nanddev_write_bbt(struct snand_mtd_dev *nand, u32 block)
114130 unsigned int nbytes = DIV_ROUND_UP (nblocks * bits_per_block ,
115131 BITS_PER_LONG ) * sizeof (* nand -> bbt .cache );
116132 struct mtd_info * mtd = snanddev_to_mtd (nand );
117- u8 * data_buf , * oob_buf ;
133+ u8 * data_buf , * oob_buf , * temp_buf ;
118134 struct nanddev_bbt_info * bbt_info ;
119135 struct mtd_oob_ops ops ;
120- int bbt_page_num ;
136+ u32 bbt_page_num ;
121137 int ret = 0 ;
138+ u32 page_addr , i ;
122139
123140 BBT_DBG ("write_bbt to blk=%d ver=%d\n" , block , nand -> bbt .version );
124141 if (!nand -> bbt .cache )
@@ -149,7 +166,7 @@ static int nanddev_write_bbt(struct snand_mtd_dev *nand, u32 block)
149166 bbt_info -> version = nand -> bbt .version ;
150167
151168 /* Store one entry for each block */
152- ret = sfc_nand_erase_mtd (mtd , block << mtd -> erasesize_shift );
169+ ret = sfc_nand_erase_mtd (mtd , block / mtd -> erasesize );
153170 if (ret )
154171 goto out ;
155172
@@ -159,7 +176,28 @@ static int nanddev_write_bbt(struct snand_mtd_dev *nand, u32 block)
159176 ops .oobbuf = oob_buf ;
160177 ops .ooblen = bbt_page_num * mtd -> oobsize ;
161178 ops .ooboffs = 0 ;
162- ret = sfc_nand_write_mtd (mtd , block * mtd -> erasesize , & ops );
179+
180+ temp_buf = kzalloc (mtd -> writesize + mtd -> oobsize , GFP_KERNEL );
181+ if (!temp_buf ) {
182+ kfree (data_buf );
183+ kfree (oob_buf );
184+
185+ return - ENOMEM ;
186+ }
187+ page_addr = (u32 )(block << (mtd -> erasesize_shift - mtd -> writesize_shift ));
188+ for (i = 0 ; i < bbt_page_num ; i ++ ) {
189+ memcpy (temp_buf , ops .datbuf + i * mtd -> writesize , mtd -> writesize );
190+ memcpy (temp_buf + mtd -> writesize , ops .oobbuf + i * mtd -> oobsize , mtd -> oobsize );
191+
192+ ret = sfc_nand_prog_page_raw (0 , page_addr + i , (u32 * )temp_buf );
193+ if (ret < 0 ) {
194+ pr_err ("%s fail %d\n" , __func__ , ret );
195+ ret = - EIO ;
196+ kfree (temp_buf );
197+ goto out ;
198+ }
199+ }
200+ kfree (temp_buf );
163201
164202out :
165203 kfree (data_buf );
@@ -196,7 +234,7 @@ static int nanddev_scan_bbt(struct snand_mtd_dev *nand)
196234{
197235 unsigned int nblocks = snanddev_neraseblocks (nand );
198236 u32 start_block , block ;
199- int ret ;
237+ int ret = 0 ;
200238
201239 nand -> bbt .version = 0 ;
202240 start_block = nblocks - NANDDEV_BBT_SCAN_MAXBLOCKS ;
@@ -213,7 +251,7 @@ static int nanddev_scan_bbt(struct snand_mtd_dev *nand)
213251 }
214252 }
215253
216- return 0 ;
254+ return ret ;
217255}
218256
219257#endif
0 commit comments