aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/spectra
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/spectra')
-rw-r--r--drivers/staging/spectra/Kconfig41
-rw-r--r--drivers/staging/spectra/Makefile11
-rw-r--r--drivers/staging/spectra/README29
-rw-r--r--drivers/staging/spectra/ffsdefs.h58
-rw-r--r--drivers/staging/spectra/ffsport.c841
-rw-r--r--drivers/staging/spectra/ffsport.h85
-rw-r--r--drivers/staging/spectra/flash.c4305
-rw-r--r--drivers/staging/spectra/flash.h198
-rw-r--r--drivers/staging/spectra/lld.c339
-rw-r--r--drivers/staging/spectra/lld.h111
-rw-r--r--drivers/staging/spectra/lld_cdma.c910
-rw-r--r--drivers/staging/spectra/lld_cdma.h123
-rw-r--r--drivers/staging/spectra/lld_emu.c776
-rw-r--r--drivers/staging/spectra/lld_emu.h51
-rw-r--r--drivers/staging/spectra/lld_mtd.c683
-rw-r--r--drivers/staging/spectra/lld_mtd.h51
-rw-r--r--drivers/staging/spectra/lld_nand.c2619
-rw-r--r--drivers/staging/spectra/lld_nand.h131
-rw-r--r--drivers/staging/spectra/nand_regs.h619
-rw-r--r--drivers/staging/spectra/spectraswconfig.h82
20 files changed, 12063 insertions, 0 deletions
diff --git a/drivers/staging/spectra/Kconfig b/drivers/staging/spectra/Kconfig
new file mode 100644
index 00000000000..4fc20648483
--- /dev/null
+++ b/drivers/staging/spectra/Kconfig
@@ -0,0 +1,41 @@
1
2menuconfig SPECTRA
3 tristate "Denali Spectra Flash Translation Layer"
4 depends on BLOCK
5 depends on X86_MRST
6 default n
7 ---help---
8 Enable the FTL pseudo-filesystem used with the NAND Flash
9 controller on Intel Moorestown Platform to pretend to be a disk.
10
11choice
12 prompt "Compile for"
13 depends on SPECTRA
14 default SPECTRA_MRST_HW
15
16config SPECTRA_MRST_HW
17 bool "Moorestown hardware mode"
18 help
19 Driver communicates with the Moorestown hardware's register interface.
20 in DMA mode.
21
22config SPECTRA_MTD
23 bool "Linux MTD mode"
24 depends on MTD
25 help
26 Driver communicates with the kernel MTD subsystem instead of its own
27 built-in hardware driver.
28
29config SPECTRA_EMU
30 bool "RAM emulator testing"
31 help
32 Driver emulates Flash on a RAM buffer and / or disk file. Useful to test the behavior of FTL layer.
33
34endchoice
35
36config SPECTRA_MRST_HW_DMA
37 bool
38 default n
39 depends on SPECTRA_MRST_HW
40 help
41 Use DMA for native hardware interface.
diff --git a/drivers/staging/spectra/Makefile b/drivers/staging/spectra/Makefile
new file mode 100644
index 00000000000..f777dfba05a
--- /dev/null
+++ b/drivers/staging/spectra/Makefile
@@ -0,0 +1,11 @@
1#
2# Makefile of Intel Moorestown NAND controller driver
3#
4
5obj-$(CONFIG_SPECTRA) += spectra.o
6spectra-y := ffsport.o flash.o lld.o
7spectra-$(CONFIG_SPECTRA_MRST_HW) += lld_nand.o
8spectra-$(CONFIG_SPECTRA_MRST_HW_DMA) += lld_cdma.o
9spectra-$(CONFIG_SPECTRA_EMU) += lld_emu.o
10spectra-$(CONFIG_SPECTRA_MTD) += lld_mtd.o
11
diff --git a/drivers/staging/spectra/README b/drivers/staging/spectra/README
new file mode 100644
index 00000000000..ecba559b899
--- /dev/null
+++ b/drivers/staging/spectra/README
@@ -0,0 +1,29 @@
1This is a driver for NAND controller of Intel Moorestown platform.
2
3This driver is a standalone linux block device driver, it acts as if it's a normal hard disk.
4It includes three layer:
5 block layer interface - file ffsport.c
6 Flash Translation Layer (FTL) - file flash.c (implement the NAND flash Translation Layer, includs address mapping, garbage collection, wear-leveling and so on)
7 Low level layer - file lld_nand.c/lld_cdma.c/lld_emu.c (which implements actual controller hardware registers access)
8
9This driver can be build as modules or build-in.
10
11Dependency:
12This driver has dependency on IA Firmware of Intel Moorestown platform.
13It need the IA Firmware to create the block table for the first time.
14And to validate this driver code without IA Firmware, you can change the
15macro AUTO_FORMAT_FLASH from 0 to 1 in file spectraswconfig.h. Thus the
16driver will erase the whole nand flash and create a new block table.
17
18TODO:
19 - Enable Command DMA feature support
20 - lower the memory footprint
21 - Remove most of the unnecessary global variables
22 - Change all the upcase variable / functions name to lowercase
23 - Some other misc bugs
24
25Please send patches to:
26 Greg Kroah-Hartman <gregkh@suse.de>
27
28And Cc to: Gao Yunpeng <yunpeng.gao@intel.com>
29
diff --git a/drivers/staging/spectra/ffsdefs.h b/drivers/staging/spectra/ffsdefs.h
new file mode 100644
index 00000000000..a9e9cd233d2
--- /dev/null
+++ b/drivers/staging/spectra/ffsdefs.h
@@ -0,0 +1,58 @@
1/*
2 * NAND Flash Controller Device Driver
3 * Copyright (c) 2009, Intel Corporation and its suppliers.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19
20#ifndef _FFSDEFS_
21#define _FFSDEFS_
22
23#define CLEAR 0 /*use this to clear a field instead of "fail"*/
24#define SET 1 /*use this to set a field instead of "pass"*/
25#define FAIL 1 /*failed flag*/
26#define PASS 0 /*success flag*/
27#define ERR -1 /*error flag*/
28
29#define ERASE_CMD 10
30#define WRITE_MAIN_CMD 11
31#define READ_MAIN_CMD 12
32#define WRITE_SPARE_CMD 13
33#define READ_SPARE_CMD 14
34#define WRITE_MAIN_SPARE_CMD 15
35#define READ_MAIN_SPARE_CMD 16
36#define MEMCOPY_CMD 17
37#define DUMMY_CMD 99
38
39#define EVENT_PASS 0x00
40#define EVENT_CORRECTABLE_DATA_ERROR_FIXED 0x01
41#define EVENT_UNCORRECTABLE_DATA_ERROR 0x02
42#define EVENT_TIME_OUT 0x03
43#define EVENT_PROGRAM_FAILURE 0x04
44#define EVENT_ERASE_FAILURE 0x05
45#define EVENT_MEMCOPY_FAILURE 0x06
46#define EVENT_FAIL 0x07
47
48#define EVENT_NONE 0x22
49#define EVENT_DMA_CMD_COMP 0x77
50#define EVENT_ECC_TRANSACTION_DONE 0x88
51#define EVENT_DMA_CMD_FAIL 0x99
52
53#define CMD_PASS 0
54#define CMD_FAIL 1
55#define CMD_ABORT 2
56#define CMD_NOT_DONE 3
57
58#endif /* _FFSDEFS_ */
diff --git a/drivers/staging/spectra/ffsport.c b/drivers/staging/spectra/ffsport.c
new file mode 100644
index 00000000000..506547b603e
--- /dev/null
+++ b/drivers/staging/spectra/ffsport.c
@@ -0,0 +1,841 @@
1/*
2 * NAND Flash Controller Device Driver
3 * Copyright (c) 2009, Intel Corporation and its suppliers.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19
20#include "ffsport.h"
21#include "flash.h"
22#include <linux/interrupt.h>
23#include <linux/delay.h>
24#include <linux/blkdev.h>
25#include <linux/wait.h>
26#include <linux/mutex.h>
27#include <linux/kthread.h>
28#include <linux/log2.h>
29#include <linux/init.h>
30#include <linux/slab.h>
31#include <linux/async.h>
32
33/**** Helper functions used for Div, Remainder operation on u64 ****/
34
35/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
36* Function: GLOB_Calc_Used_Bits
37* Inputs: Power of 2 number
38* Outputs: Number of Used Bits
39* 0, if the argument is 0
40* Description: Calculate the number of bits used by a given power of 2 number
41* Number can be up to 32 bit
42*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
43int GLOB_Calc_Used_Bits(u32 n)
44{
45 int tot_bits = 0;
46
47 if (n >= 1 << 16) {
48 n >>= 16;
49 tot_bits += 16;
50 }
51
52 if (n >= 1 << 8) {
53 n >>= 8;
54 tot_bits += 8;
55 }
56
57 if (n >= 1 << 4) {
58 n >>= 4;
59 tot_bits += 4;
60 }
61
62 if (n >= 1 << 2) {
63 n >>= 2;
64 tot_bits += 2;
65 }
66
67 if (n >= 1 << 1)
68 tot_bits += 1;
69
70 return ((n == 0) ? (0) : tot_bits);
71}
72
73/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
74* Function: GLOB_u64_Div
75* Inputs: Number of u64
76* A power of 2 number as Division
77* Outputs: Quotient of the Divisor operation
78* Description: It divides the address by divisor by using bit shift operation
79* (essentially without explicitely using "/").
80* Divisor is a power of 2 number and Divided is of u64
81*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
82u64 GLOB_u64_Div(u64 addr, u32 divisor)
83{
84 return (u64)(addr >> GLOB_Calc_Used_Bits(divisor));
85}
86
87/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
88* Function: GLOB_u64_Remainder
89* Inputs: Number of u64
90* Divisor Type (1 -PageAddress, 2- BlockAddress)
91* Outputs: Remainder of the Division operation
92* Description: It calculates the remainder of a number (of u64) by
93* divisor(power of 2 number ) by using bit shifting and multiply
94* operation(essentially without explicitely using "/").
95*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
96u64 GLOB_u64_Remainder(u64 addr, u32 divisor_type)
97{
98 u64 result = 0;
99
100 if (divisor_type == 1) { /* Remainder -- Page */
101 result = (addr >> DeviceInfo.nBitsInPageDataSize);
102 result = result * DeviceInfo.wPageDataSize;
103 } else if (divisor_type == 2) { /* Remainder -- Block */
104 result = (addr >> DeviceInfo.nBitsInBlockDataSize);
105 result = result * DeviceInfo.wBlockDataSize;
106 }
107
108 result = addr - result;
109
110 return result;
111}
112
113#define NUM_DEVICES 1
114#define PARTITIONS 8
115
116#define GLOB_SBD_NAME "nd"
117#define GLOB_SBD_IRQ_NUM (29)
118
119#define GLOB_SBD_IOCTL_GC (0x7701)
120#define GLOB_SBD_IOCTL_WL (0x7702)
121#define GLOB_SBD_IOCTL_FORMAT (0x7703)
122#define GLOB_SBD_IOCTL_ERASE_FLASH (0x7704)
123#define GLOB_SBD_IOCTL_FLUSH_CACHE (0x7705)
124#define GLOB_SBD_IOCTL_COPY_BLK_TABLE (0x7706)
125#define GLOB_SBD_IOCTL_COPY_WEAR_LEVELING_TABLE (0x7707)
126#define GLOB_SBD_IOCTL_GET_NAND_INFO (0x7708)
127#define GLOB_SBD_IOCTL_WRITE_DATA (0x7709)
128#define GLOB_SBD_IOCTL_READ_DATA (0x770A)
129
130static int reserved_mb = 0;
131module_param(reserved_mb, int, 0);
132MODULE_PARM_DESC(reserved_mb, "Reserved space for OS image, in MiB (default 25 MiB)");
133
134int nand_debug_level;
135module_param(nand_debug_level, int, 0644);
136MODULE_PARM_DESC(nand_debug_level, "debug level value: 1-3");
137
138MODULE_LICENSE("GPL");
139
140struct spectra_nand_dev {
141 struct pci_dev *dev;
142 u64 size;
143 u16 users;
144 spinlock_t qlock;
145 void __iomem *ioaddr; /* Mapped address */
146 struct request_queue *queue;
147 struct task_struct *thread;
148 struct gendisk *gd;
149 u8 *tmp_buf;
150};
151
152
153static int GLOB_SBD_majornum;
154
155static char *GLOB_version = GLOB_VERSION;
156
157static struct spectra_nand_dev nand_device[NUM_DEVICES];
158
159static struct mutex spectra_lock;
160
161static int res_blks_os = 1;
162
163struct spectra_indentfy_dev_tag IdentifyDeviceData;
164
165static int force_flush_cache(void)
166{
167 nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
168 __FILE__, __LINE__, __func__);
169
170 if (ERR == GLOB_FTL_Flush_Cache()) {
171 printk(KERN_ERR "Fail to Flush FTL Cache!\n");
172 return -EFAULT;
173 }
174#if CMD_DMA
175 if (glob_ftl_execute_cmds())
176 return -EIO;
177 else
178 return 0;
179#endif
180 return 0;
181}
182
183struct ioctl_rw_page_info {
184 u8 *data;
185 unsigned int page;
186};
187
188static int ioctl_read_page_data(unsigned long arg)
189{
190 u8 *buf;
191 struct ioctl_rw_page_info info;
192 int result = PASS;
193
194 if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
195 return -EFAULT;
196
197 buf = kmalloc(IdentifyDeviceData.PageDataSize, GFP_ATOMIC);
198 if (!buf) {
199 printk(KERN_ERR "ioctl_read_page_data: "
200 "failed to allocate memory\n");
201 return -ENOMEM;
202 }
203
204 mutex_lock(&spectra_lock);
205 result = GLOB_FTL_Page_Read(buf,
206 (u64)info.page * IdentifyDeviceData.PageDataSize);
207 mutex_unlock(&spectra_lock);
208
209 if (copy_to_user((void __user *)info.data, buf,
210 IdentifyDeviceData.PageDataSize)) {
211 printk(KERN_ERR "ioctl_read_page_data: "
212 "failed to copy user data\n");
213 kfree(buf);
214 return -EFAULT;
215 }
216
217 kfree(buf);
218 return result;
219}
220
221static int ioctl_write_page_data(unsigned long arg)
222{
223 u8 *buf;
224 struct ioctl_rw_page_info info;
225 int result = PASS;
226
227 if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
228 return -EFAULT;
229
230 buf = kmalloc(IdentifyDeviceData.PageDataSize, GFP_ATOMIC);
231 if (!buf) {
232 printk(KERN_ERR "ioctl_write_page_data: "
233 "failed to allocate memory\n");
234 return -ENOMEM;
235 }
236
237 if (copy_from_user(buf, (void __user *)info.data,
238 IdentifyDeviceData.PageDataSize)) {
239 printk(KERN_ERR "ioctl_write_page_data: "
240 "failed to copy user data\n");
241 kfree(buf);
242 return -EFAULT;
243 }
244
245 mutex_lock(&spectra_lock);
246 result = GLOB_FTL_Page_Write(buf,
247 (u64)info.page * IdentifyDeviceData.PageDataSize);
248 mutex_unlock(&spectra_lock);
249
250 kfree(buf);
251 return result;
252}
253
254/* Return how many blocks should be reserved for bad block replacement */
255static int get_res_blk_num_bad_blk(void)
256{
257 return IdentifyDeviceData.wDataBlockNum / 10;
258}
259
260/* Return how many blocks should be reserved for OS image */
261static int get_res_blk_num_os(void)
262{
263 u32 res_blks, blk_size;
264
265 blk_size = IdentifyDeviceData.PageDataSize *
266 IdentifyDeviceData.PagesPerBlock;
267
268 res_blks = (reserved_mb * 1024 * 1024) / blk_size;
269
270 if ((res_blks < 1) || (res_blks >= IdentifyDeviceData.wDataBlockNum))
271 res_blks = 1; /* Reserved 1 block for block table */
272
273 return res_blks;
274}
275
276/* Transfer a full request. */
277static int do_transfer(struct spectra_nand_dev *tr, struct request *req)
278{
279 u64 start_addr, addr;
280 u32 logical_start_sect, hd_start_sect;
281 u32 nsect, hd_sects;
282 u32 rsect, tsect = 0;
283 char *buf;
284 u32 ratio = IdentifyDeviceData.PageDataSize >> 9;
285
286 start_addr = (u64)(blk_rq_pos(req)) << 9;
287 /* Add a big enough offset to prevent the OS Image from
288 * being accessed or damaged by file system */
289 start_addr += IdentifyDeviceData.PageDataSize *
290 IdentifyDeviceData.PagesPerBlock *
291 res_blks_os;
292
293 if (req->cmd_type & REQ_FLUSH) {
294 if (force_flush_cache()) /* Fail to flush cache */
295 return -EIO;
296 else
297 return 0;
298 }
299
300 if (req->cmd_type != REQ_TYPE_FS)
301 return -EIO;
302
303 if (blk_rq_pos(req) + blk_rq_cur_sectors(req) > get_capacity(tr->gd)) {
304 printk(KERN_ERR "Spectra error: request over the NAND "
305 "capacity!sector %d, current_nr_sectors %d, "
306 "while capacity is %d\n",
307 (int)blk_rq_pos(req),
308 blk_rq_cur_sectors(req),
309 (int)get_capacity(tr->gd));
310 return -EIO;
311 }
312
313 logical_start_sect = start_addr >> 9;
314 hd_start_sect = logical_start_sect / ratio;
315 rsect = logical_start_sect - hd_start_sect * ratio;
316
317 addr = (u64)hd_start_sect * ratio * 512;
318 buf = req->buffer;
319 nsect = blk_rq_cur_sectors(req);
320
321 if (rsect)
322 tsect = (ratio - rsect) < nsect ? (ratio - rsect) : nsect;
323
324 switch (rq_data_dir(req)) {
325 case READ:
326 /* Read the first NAND page */
327 if (rsect) {
328 if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) {
329 printk(KERN_ERR "Error in %s, Line %d\n",
330 __FILE__, __LINE__);
331 return -EIO;
332 }
333 memcpy(buf, tr->tmp_buf + (rsect << 9), tsect << 9);
334 addr += IdentifyDeviceData.PageDataSize;
335 buf += tsect << 9;
336 nsect -= tsect;
337 }
338
339 /* Read the other NAND pages */
340 for (hd_sects = nsect / ratio; hd_sects > 0; hd_sects--) {
341 if (GLOB_FTL_Page_Read(buf, addr)) {
342 printk(KERN_ERR "Error in %s, Line %d\n",
343 __FILE__, __LINE__);
344 return -EIO;
345 }
346 addr += IdentifyDeviceData.PageDataSize;
347 buf += IdentifyDeviceData.PageDataSize;
348 }
349
350 /* Read the last NAND pages */
351 if (nsect % ratio) {
352 if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) {
353 printk(KERN_ERR "Error in %s, Line %d\n",
354 __FILE__, __LINE__);
355 return -EIO;
356 }
357 memcpy(buf, tr->tmp_buf, (nsect % ratio) << 9);
358 }
359#if CMD_DMA
360 if (glob_ftl_execute_cmds())
361 return -EIO;
362 else
363 return 0;
364#endif
365 return 0;
366
367 case WRITE:
368 /* Write the first NAND page */
369 if (rsect) {
370 if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) {
371 printk(KERN_ERR "Error in %s, Line %d\n",
372 __FILE__, __LINE__);
373 return -EIO;
374 }
375 memcpy(tr->tmp_buf + (rsect << 9), buf, tsect << 9);
376 if (GLOB_FTL_Page_Write(tr->tmp_buf, addr)) {
377 printk(KERN_ERR "Error in %s, Line %d\n",
378 __FILE__, __LINE__);
379 return -EIO;
380 }
381 addr += IdentifyDeviceData.PageDataSize;
382 buf += tsect << 9;
383 nsect -= tsect;
384 }
385
386 /* Write the other NAND pages */
387 for (hd_sects = nsect / ratio; hd_sects > 0; hd_sects--) {
388 if (GLOB_FTL_Page_Write(buf, addr)) {
389 printk(KERN_ERR "Error in %s, Line %d\n",
390 __FILE__, __LINE__);
391 return -EIO;
392 }
393 addr += IdentifyDeviceData.PageDataSize;
394 buf += IdentifyDeviceData.PageDataSize;
395 }
396
397 /* Write the last NAND pages */
398 if (nsect % ratio) {
399 if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) {
400 printk(KERN_ERR "Error in %s, Line %d\n",
401 __FILE__, __LINE__);
402 return -EIO;
403 }
404 memcpy(tr->tmp_buf, buf, (nsect % ratio) << 9);
405 if (GLOB_FTL_Page_Write(tr->tmp_buf, addr)) {
406 printk(KERN_ERR "Error in %s, Line %d\n",
407 __FILE__, __LINE__);
408 return -EIO;
409 }
410 }
411#if CMD_DMA
412 if (glob_ftl_execute_cmds())
413 return -EIO;
414 else
415 return 0;
416#endif
417 return 0;
418
419 default:
420 printk(KERN_NOTICE "Unknown request %u\n", rq_data_dir(req));
421 return -EIO;
422 }
423}
424
425/* This function is copied from drivers/mtd/mtd_blkdevs.c */
426static int spectra_trans_thread(void *arg)
427{
428 struct spectra_nand_dev *tr = arg;
429 struct request_queue *rq = tr->queue;
430 struct request *req = NULL;
431
432 /* we might get involved when memory gets low, so use PF_MEMALLOC */
433 current->flags |= PF_MEMALLOC;
434
435 spin_lock_irq(rq->queue_lock);
436 while (!kthread_should_stop()) {
437 int res;
438
439 if (!req) {
440 req = blk_fetch_request(rq);
441 if (!req) {
442 set_current_state(TASK_INTERRUPTIBLE);
443 spin_unlock_irq(rq->queue_lock);
444 schedule();
445 spin_lock_irq(rq->queue_lock);
446 continue;
447 }
448 }
449
450 spin_unlock_irq(rq->queue_lock);
451
452 mutex_lock(&spectra_lock);
453 res = do_transfer(tr, req);
454 mutex_unlock(&spectra_lock);
455
456 spin_lock_irq(rq->queue_lock);
457
458 if (!__blk_end_request_cur(req, res))
459 req = NULL;
460 }
461
462 if (req)
463 __blk_end_request_all(req, -EIO);
464
465 spin_unlock_irq(rq->queue_lock);
466
467 return 0;
468}
469
470
471/* Request function that "handles clustering". */
472static void GLOB_SBD_request(struct request_queue *rq)
473{
474 struct spectra_nand_dev *pdev = rq->queuedata;
475 wake_up_process(pdev->thread);
476}
477
478static int GLOB_SBD_open(struct block_device *bdev, fmode_t mode)
479
480{
481 nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
482 __FILE__, __LINE__, __func__);
483 return 0;
484}
485
486static int GLOB_SBD_release(struct gendisk *disk, fmode_t mode)
487{
488 int ret;
489
490 nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
491 __FILE__, __LINE__, __func__);
492
493 mutex_lock(&spectra_lock);
494 ret = force_flush_cache();
495 mutex_unlock(&spectra_lock);
496
497 return 0;
498}
499
500static int GLOB_SBD_getgeo(struct block_device *bdev, struct hd_geometry *geo)
501{
502 geo->heads = 4;
503 geo->sectors = 16;
504 geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16);
505
506 nand_dbg_print(NAND_DBG_DEBUG,
507 "heads: %d, sectors: %d, cylinders: %d\n",
508 geo->heads, geo->sectors, geo->cylinders);
509
510 return 0;
511}
512
513int GLOB_SBD_ioctl(struct block_device *bdev, fmode_t mode,
514 unsigned int cmd, unsigned long arg)
515{
516 int ret;
517
518 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
519 __FILE__, __LINE__, __func__);
520
521 switch (cmd) {
522 case GLOB_SBD_IOCTL_GC:
523 nand_dbg_print(NAND_DBG_DEBUG,
524 "Spectra IOCTL: Garbage Collection "
525 "being performed\n");
526 if (PASS != GLOB_FTL_Garbage_Collection())
527 return -EFAULT;
528 return 0;
529
530 case GLOB_SBD_IOCTL_WL:
531 nand_dbg_print(NAND_DBG_DEBUG,
532 "Spectra IOCTL: Static Wear Leveling "
533 "being performed\n");
534 if (PASS != GLOB_FTL_Wear_Leveling())
535 return -EFAULT;
536 return 0;
537
538 case GLOB_SBD_IOCTL_FORMAT:
539 nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: Flash format "
540 "being performed\n");
541 if (PASS != GLOB_FTL_Flash_Format())
542 return -EFAULT;
543 return 0;
544
545 case GLOB_SBD_IOCTL_FLUSH_CACHE:
546 nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: Cache flush "
547 "being performed\n");
548 mutex_lock(&spectra_lock);
549 ret = force_flush_cache();
550 mutex_unlock(&spectra_lock);
551 return ret;
552
553 case GLOB_SBD_IOCTL_COPY_BLK_TABLE:
554 nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: "
555 "Copy block table\n");
556 if (copy_to_user((void __user *)arg,
557 get_blk_table_start_addr(),
558 get_blk_table_len()))
559 return -EFAULT;
560 return 0;
561
562 case GLOB_SBD_IOCTL_COPY_WEAR_LEVELING_TABLE:
563 nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: "
564 "Copy wear leveling table\n");
565 if (copy_to_user((void __user *)arg,
566 get_wear_leveling_table_start_addr(),
567 get_wear_leveling_table_len()))
568 return -EFAULT;
569 return 0;
570
571 case GLOB_SBD_IOCTL_GET_NAND_INFO:
572 nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: "
573 "Get NAND info\n");
574 if (copy_to_user((void __user *)arg, &IdentifyDeviceData,
575 sizeof(IdentifyDeviceData)))
576 return -EFAULT;
577 return 0;
578
579 case GLOB_SBD_IOCTL_WRITE_DATA:
580 nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: "
581 "Write one page data\n");
582 return ioctl_write_page_data(arg);
583
584 case GLOB_SBD_IOCTL_READ_DATA:
585 nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: "
586 "Read one page data\n");
587 return ioctl_read_page_data(arg);
588 }
589
590 return -ENOTTY;
591}
592
593static DEFINE_MUTEX(ffsport_mutex);
594
595int GLOB_SBD_unlocked_ioctl(struct block_device *bdev, fmode_t mode,
596 unsigned int cmd, unsigned long arg)
597{
598 int ret;
599
600 mutex_lock(&ffsport_mutex);
601 ret = GLOB_SBD_ioctl(bdev, mode, cmd, arg);
602 mutex_unlock(&ffsport_mutex);
603
604 return ret;
605}
606
607static struct block_device_operations GLOB_SBD_ops = {
608 .owner = THIS_MODULE,
609 .open = GLOB_SBD_open,
610 .release = GLOB_SBD_release,
611 .ioctl = GLOB_SBD_unlocked_ioctl,
612 .getgeo = GLOB_SBD_getgeo,
613};
614
615static int SBD_setup_device(struct spectra_nand_dev *dev, int which)
616{
617 int res_blks;
618 u32 sects;
619
620 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
621 __FILE__, __LINE__, __func__);
622
623 memset(dev, 0, sizeof(struct spectra_nand_dev));
624
625 nand_dbg_print(NAND_DBG_WARN, "Reserved %d blocks "
626 "for OS image, %d blocks for bad block replacement.\n",
627 get_res_blk_num_os(),
628 get_res_blk_num_bad_blk());
629
630 res_blks = get_res_blk_num_bad_blk() + get_res_blk_num_os();
631
632 dev->size = (u64)IdentifyDeviceData.PageDataSize *
633 IdentifyDeviceData.PagesPerBlock *
634 (IdentifyDeviceData.wDataBlockNum - res_blks);
635
636 res_blks_os = get_res_blk_num_os();
637
638 spin_lock_init(&dev->qlock);
639
640 dev->tmp_buf = kmalloc(IdentifyDeviceData.PageDataSize, GFP_ATOMIC);
641 if (!dev->tmp_buf) {
642 printk(KERN_ERR "Failed to kmalloc memory in %s Line %d, exit.\n",
643 __FILE__, __LINE__);
644 goto out_vfree;
645 }
646
647 dev->queue = blk_init_queue(GLOB_SBD_request, &dev->qlock);
648 if (dev->queue == NULL) {
649 printk(KERN_ERR
650 "Spectra: Request queue could not be initialized."
651 " Aborting\n ");
652 goto out_vfree;
653 }
654 dev->queue->queuedata = dev;
655
656 /* As Linux block layer doesn't support >4KB hardware sector, */
657 /* Here we force report 512 byte hardware sector size to Kernel */
658 blk_queue_logical_block_size(dev->queue, 512);
659
660 blk_queue_flush(dev->queue, REQ_FLUSH);
661
662 dev->thread = kthread_run(spectra_trans_thread, dev, "nand_thd");
663 if (IS_ERR(dev->thread)) {
664 blk_cleanup_queue(dev->queue);
665 unregister_blkdev(GLOB_SBD_majornum, GLOB_SBD_NAME);
666 return PTR_ERR(dev->thread);
667 }
668
669 dev->gd = alloc_disk(PARTITIONS);
670 if (!dev->gd) {
671 printk(KERN_ERR
672 "Spectra: Could not allocate disk. Aborting \n ");
673 goto out_vfree;
674 }
675 dev->gd->major = GLOB_SBD_majornum;
676 dev->gd->first_minor = which * PARTITIONS;
677 dev->gd->fops = &GLOB_SBD_ops;
678 dev->gd->queue = dev->queue;
679 dev->gd->private_data = dev;
680 snprintf(dev->gd->disk_name, 32, "%s%c", GLOB_SBD_NAME, which + 'a');
681
682 sects = dev->size >> 9;
683 nand_dbg_print(NAND_DBG_WARN, "Capacity sects: %d\n", sects);
684 set_capacity(dev->gd, sects);
685
686 add_disk(dev->gd);
687
688 return 0;
689out_vfree:
690 return -ENOMEM;
691}
692
693/*
694static ssize_t show_nand_block_num(struct device *dev,
695 struct device_attribute *attr, char *buf)
696{
697 return snprintf(buf, PAGE_SIZE, "%d\n",
698 (int)IdentifyDeviceData.wDataBlockNum);
699}
700
701static ssize_t show_nand_pages_per_block(struct device *dev,
702 struct device_attribute *attr, char *buf)
703{
704 return snprintf(buf, PAGE_SIZE, "%d\n",
705 (int)IdentifyDeviceData.PagesPerBlock);
706}
707
708static ssize_t show_nand_page_size(struct device *dev,
709 struct device_attribute *attr, char *buf)
710{
711 return snprintf(buf, PAGE_SIZE, "%d\n",
712 (int)IdentifyDeviceData.PageDataSize);
713}
714
715static DEVICE_ATTR(nand_block_num, 0444, show_nand_block_num, NULL);
716static DEVICE_ATTR(nand_pages_per_block, 0444, show_nand_pages_per_block, NULL);
717static DEVICE_ATTR(nand_page_size, 0444, show_nand_page_size, NULL);
718
719static void create_sysfs_entry(struct device *dev)
720{
721 if (device_create_file(dev, &dev_attr_nand_block_num))
722 printk(KERN_ERR "Spectra: "
723 "failed to create sysfs entry nand_block_num.\n");
724 if (device_create_file(dev, &dev_attr_nand_pages_per_block))
725 printk(KERN_ERR "Spectra: "
726 "failed to create sysfs entry nand_pages_per_block.\n");
727 if (device_create_file(dev, &dev_attr_nand_page_size))
728 printk(KERN_ERR "Spectra: "
729 "failed to create sysfs entry nand_page_size.\n");
730}
731*/
732
733static void register_spectra_ftl_async(void *unused, async_cookie_t cookie)
734{
735 int i;
736
737 /* create_sysfs_entry(&dev->dev); */
738
739 if (PASS != GLOB_FTL_IdentifyDevice(&IdentifyDeviceData)) {
740 printk(KERN_ERR "Spectra: Unable to Read Flash Device. "
741 "Aborting\n");
742 return;
743 } else {
744 nand_dbg_print(NAND_DBG_WARN, "In GLOB_SBD_init: "
745 "Num blocks=%d, pagesperblock=%d, "
746 "pagedatasize=%d, ECCBytesPerSector=%d\n",
747 (int)IdentifyDeviceData.NumBlocks,
748 (int)IdentifyDeviceData.PagesPerBlock,
749 (int)IdentifyDeviceData.PageDataSize,
750 (int)IdentifyDeviceData.wECCBytesPerSector);
751 }
752
753 printk(KERN_ALERT "Spectra: searching block table, please wait ...\n");
754 if (GLOB_FTL_Init() != PASS) {
755 printk(KERN_ERR "Spectra: Unable to Initialize FTL Layer. "
756 "Aborting\n");
757 goto out_ftl_flash_register;
758 }
759 printk(KERN_ALERT "Spectra: block table has been found.\n");
760
761 GLOB_SBD_majornum = register_blkdev(0, GLOB_SBD_NAME);
762 if (GLOB_SBD_majornum <= 0) {
763 printk(KERN_ERR "Unable to get the major %d for Spectra",
764 GLOB_SBD_majornum);
765 goto out_ftl_flash_register;
766 }
767
768 for (i = 0; i < NUM_DEVICES; i++)
769 if (SBD_setup_device(&nand_device[i], i) == -ENOMEM)
770 goto out_blk_register;
771
772 nand_dbg_print(NAND_DBG_DEBUG,
773 "Spectra: module loaded with major number %d\n",
774 GLOB_SBD_majornum);
775
776 return;
777
778out_blk_register:
779 unregister_blkdev(GLOB_SBD_majornum, GLOB_SBD_NAME);
780out_ftl_flash_register:
781 GLOB_FTL_Cache_Release();
782 printk(KERN_ERR "Spectra: Module load failed.\n");
783}
784
785int register_spectra_ftl()
786{
787 async_schedule(register_spectra_ftl_async, NULL);
788 return 0;
789}
790EXPORT_SYMBOL_GPL(register_spectra_ftl);
791
792static int GLOB_SBD_init(void)
793{
794 /* Set debug output level (0~3) here. 3 is most verbose */
795 printk(KERN_ALERT "Spectra: %s\n", GLOB_version);
796
797 mutex_init(&spectra_lock);
798
799 if (PASS != GLOB_FTL_Flash_Init()) {
800 printk(KERN_ERR "Spectra: Unable to Initialize Flash Device. "
801 "Aborting\n");
802 return -ENODEV;
803 }
804 return 0;
805}
806
807static void __exit GLOB_SBD_exit(void)
808{
809 int i;
810
811 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
812 __FILE__, __LINE__, __func__);
813
814 for (i = 0; i < NUM_DEVICES; i++) {
815 struct spectra_nand_dev *dev = &nand_device[i];
816 if (dev->gd) {
817 del_gendisk(dev->gd);
818 put_disk(dev->gd);
819 }
820 if (dev->queue)
821 blk_cleanup_queue(dev->queue);
822 kfree(dev->tmp_buf);
823 }
824
825 unregister_blkdev(GLOB_SBD_majornum, GLOB_SBD_NAME);
826
827 mutex_lock(&spectra_lock);
828 force_flush_cache();
829 mutex_unlock(&spectra_lock);
830
831 GLOB_FTL_Cache_Release();
832
833 GLOB_FTL_Flash_Release();
834
835 nand_dbg_print(NAND_DBG_DEBUG,
836 "Spectra FTL module (major number %d) unloaded.\n",
837 GLOB_SBD_majornum);
838}
839
840module_init(GLOB_SBD_init);
841module_exit(GLOB_SBD_exit);
diff --git a/drivers/staging/spectra/ffsport.h b/drivers/staging/spectra/ffsport.h
new file mode 100644
index 00000000000..85c0750612f
--- /dev/null
+++ b/drivers/staging/spectra/ffsport.h
@@ -0,0 +1,85 @@
1/*
2 * NAND Flash Controller Device Driver
3 * Copyright (c) 2009, Intel Corporation and its suppliers.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19
20#ifndef _FFSPORT_
21#define _FFSPORT_
22
23#include "ffsdefs.h"
24
25#if defined __GNUC__
26#define PACKED
27#define PACKED_GNU __attribute__ ((packed))
28#define UNALIGNED
29#endif
30
31#include <linux/semaphore.h>
32#include <linux/string.h> /* for strcpy(), stricmp(), etc */
33#include <linux/mm.h> /* for kmalloc(), kfree() */
34#include <linux/vmalloc.h>
35#include <linux/module.h>
36#include <linux/moduleparam.h>
37#include <linux/init.h>
38
39#include <linux/kernel.h> /* printk() */
40#include <linux/fs.h> /* everything... */
41#include <linux/errno.h> /* error codes */
42#include <linux/types.h> /* size_t */
43#include <linux/genhd.h>
44#include <linux/blkdev.h>
45#include <linux/hdreg.h>
46#include <linux/pci.h>
47#include "flash.h"
48
49#define VERBOSE 1
50
51#define NAND_DBG_WARN 1
52#define NAND_DBG_DEBUG 2
53#define NAND_DBG_TRACE 3
54
55extern int nand_debug_level;
56
57#ifdef VERBOSE
58#define nand_dbg_print(level, args...) \
59 do { \
60 if (level <= nand_debug_level) \
61 printk(KERN_ALERT args); \
62 } while (0)
63#else
64#define nand_dbg_print(level, args...)
65#endif
66
67#ifdef SUPPORT_BIG_ENDIAN
68#define INVERTUINT16(w) ((u16)(((u16)(w)) << 8) | \
69 (u16)((u16)(w) >> 8))
70
71#define INVERTUINT32(dw) (((u32)(dw) << 24) | \
72 (((u32)(dw) << 8) & 0x00ff0000) | \
73 (((u32)(dw) >> 8) & 0x0000ff00) | \
74 ((u32)(dw) >> 24))
75#else
76#define INVERTUINT16(w) w
77#define INVERTUINT32(dw) dw
78#endif
79
80extern int GLOB_Calc_Used_Bits(u32 n);
81extern u64 GLOB_u64_Div(u64 addr, u32 divisor);
82extern u64 GLOB_u64_Remainder(u64 addr, u32 divisor_type);
83extern int register_spectra_ftl(void);
84
85#endif /* _FFSPORT_ */
diff --git a/drivers/staging/spectra/flash.c b/drivers/staging/spectra/flash.c
new file mode 100644
index 00000000000..aead358e5c2
--- /dev/null
+++ b/drivers/staging/spectra/flash.c
@@ -0,0 +1,4305 @@
1/*
2 * NAND Flash Controller Device Driver
3 * Copyright (c) 2009, Intel Corporation and its suppliers.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19
20#include <linux/fs.h>
21#include <linux/slab.h>
22
23#include "flash.h"
24#include "ffsdefs.h"
25#include "lld.h"
26#include "lld_nand.h"
27#if CMD_DMA
28#include "lld_cdma.h"
29#endif
30
31#define BLK_FROM_ADDR(addr) ((u32)(addr >> DeviceInfo.nBitsInBlockDataSize))
32#define PAGE_FROM_ADDR(addr, Block) ((u16)((addr - (u64)Block * \
33 DeviceInfo.wBlockDataSize) >> DeviceInfo.nBitsInPageDataSize))
34
35#define IS_SPARE_BLOCK(blk) (BAD_BLOCK != (pbt[blk] &\
36 BAD_BLOCK) && SPARE_BLOCK == (pbt[blk] & SPARE_BLOCK))
37
38#define IS_DATA_BLOCK(blk) (0 == (pbt[blk] & BAD_BLOCK))
39
40#define IS_DISCARDED_BLOCK(blk) (BAD_BLOCK != (pbt[blk] &\
41 BAD_BLOCK) && DISCARD_BLOCK == (pbt[blk] & DISCARD_BLOCK))
42
43#define IS_BAD_BLOCK(blk) (BAD_BLOCK == (pbt[blk] & BAD_BLOCK))
44
45#if DEBUG_BNDRY
46void debug_boundary_lineno_error(int chnl, int limit, int no,
47 int lineno, char *filename)
48{
49 if (chnl >= limit)
50 printk(KERN_ERR "Boundary Check Fail value %d >= limit %d, "
51 "at %s:%d. Other info:%d. Aborting...\n",
52 chnl, limit, filename, lineno, no);
53}
54/* static int globalmemsize; */
55#endif
56
57static u16 FTL_Cache_If_Hit(u64 dwPageAddr);
58static int FTL_Cache_Read(u64 dwPageAddr);
59static void FTL_Cache_Read_Page(u8 *pData, u64 dwPageAddr,
60 u16 cache_blk);
61static void FTL_Cache_Write_Page(u8 *pData, u64 dwPageAddr,
62 u8 cache_blk, u16 flag);
63static int FTL_Cache_Write(void);
64static void FTL_Calculate_LRU(void);
65static u32 FTL_Get_Block_Index(u32 wBlockNum);
66
67static int FTL_Search_Block_Table_IN_Block(u32 BT_Block,
68 u8 BT_Tag, u16 *Page);
69static int FTL_Read_Block_Table(void);
70static int FTL_Write_Block_Table(int wForce);
71static int FTL_Write_Block_Table_Data(void);
72static int FTL_Check_Block_Table(int wOldTable);
73static int FTL_Static_Wear_Leveling(void);
74static u32 FTL_Replace_Block_Table(void);
75static int FTL_Write_IN_Progress_Block_Table_Page(void);
76
77static u32 FTL_Get_Page_Num(u64 length);
78static u64 FTL_Get_Physical_Block_Addr(u64 blk_addr);
79
80static u32 FTL_Replace_OneBlock(u32 wBlockNum,
81 u32 wReplaceNum);
82static u32 FTL_Replace_LWBlock(u32 wBlockNum,
83 int *pGarbageCollect);
84static u32 FTL_Replace_MWBlock(void);
85static int FTL_Replace_Block(u64 blk_addr);
86static int FTL_Adjust_Relative_Erase_Count(u32 Index_of_MAX);
87
88struct device_info_tag DeviceInfo;
89struct flash_cache_tag Cache;
90static struct spectra_l2_cache_info cache_l2;
91
92static u8 *cache_l2_page_buf;
93static u8 *cache_l2_blk_buf;
94
95u8 *g_pBlockTable;
96u8 *g_pWearCounter;
97u16 *g_pReadCounter;
98u32 *g_pBTBlocks;
99static u16 g_wBlockTableOffset;
100static u32 g_wBlockTableIndex;
101static u8 g_cBlockTableStatus;
102
103static u8 *g_pTempBuf;
104static u8 *flag_check_blk_table;
105static u8 *tmp_buf_search_bt_in_block;
106static u8 *spare_buf_search_bt_in_block;
107static u8 *spare_buf_bt_search_bt_in_block;
108static u8 *tmp_buf1_read_blk_table;
109static u8 *tmp_buf2_read_blk_table;
110static u8 *flags_static_wear_leveling;
111static u8 *tmp_buf_write_blk_table_data;
112static u8 *tmp_buf_read_disturbance;
113
114u8 *buf_read_page_main_spare;
115u8 *buf_write_page_main_spare;
116u8 *buf_read_page_spare;
117u8 *buf_get_bad_block;
118
119#if (RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE && CMD_DMA)
120struct flash_cache_delta_list_tag int_cache[MAX_CHANS + MAX_DESCS];
121struct flash_cache_tag cache_start_copy;
122#endif
123
124int g_wNumFreeBlocks;
125u8 g_SBDCmdIndex;
126
127static u8 *g_pIPF;
128static u8 bt_flag = FIRST_BT_ID;
129static u8 bt_block_changed;
130
131static u16 cache_block_to_write;
132static u8 last_erased = FIRST_BT_ID;
133
134static u8 GC_Called;
135static u8 BT_GC_Called;
136
137#if CMD_DMA
138#define COPY_BACK_BUF_NUM 10
139
140static u8 ftl_cmd_cnt; /* Init value is 0 */
141u8 *g_pBTDelta;
142u8 *g_pBTDelta_Free;
143u8 *g_pBTStartingCopy;
144u8 *g_pWearCounterCopy;
145u16 *g_pReadCounterCopy;
146u8 *g_pBlockTableCopies;
147u8 *g_pNextBlockTable;
148static u8 *cp_back_buf_copies[COPY_BACK_BUF_NUM];
149static int cp_back_buf_idx;
150
151static u8 *g_temp_buf;
152
153#pragma pack(push, 1)
154#pragma pack(1)
155struct BTableChangesDelta {
156 u8 ftl_cmd_cnt;
157 u8 ValidFields;
158 u16 g_wBlockTableOffset;
159 u32 g_wBlockTableIndex;
160 u32 BT_Index;
161 u32 BT_Entry_Value;
162 u32 WC_Index;
163 u8 WC_Entry_Value;
164 u32 RC_Index;
165 u16 RC_Entry_Value;
166};
167
168#pragma pack(pop)
169
170struct BTableChangesDelta *p_BTableChangesDelta;
171#endif
172
173
174#define MARK_BLOCK_AS_BAD(blocknode) (blocknode |= BAD_BLOCK)
175#define MARK_BLK_AS_DISCARD(blk) (blk = (blk & ~SPARE_BLOCK) | DISCARD_BLOCK)
176
177#define FTL_Get_LBAPBA_Table_Mem_Size_Bytes() (DeviceInfo.wDataBlockNum *\
178 sizeof(u32))
179#define FTL_Get_WearCounter_Table_Mem_Size_Bytes() (DeviceInfo.wDataBlockNum *\
180 sizeof(u8))
181#define FTL_Get_ReadCounter_Table_Mem_Size_Bytes() (DeviceInfo.wDataBlockNum *\
182 sizeof(u16))
183#if SUPPORT_LARGE_BLOCKNUM
184#define FTL_Get_LBAPBA_Table_Flash_Size_Bytes() (DeviceInfo.wDataBlockNum *\
185 sizeof(u8) * 3)
186#else
187#define FTL_Get_LBAPBA_Table_Flash_Size_Bytes() (DeviceInfo.wDataBlockNum *\
188 sizeof(u16))
189#endif
190#define FTL_Get_WearCounter_Table_Flash_Size_Bytes \
191 FTL_Get_WearCounter_Table_Mem_Size_Bytes
192#define FTL_Get_ReadCounter_Table_Flash_Size_Bytes \
193 FTL_Get_ReadCounter_Table_Mem_Size_Bytes
194
195static u32 FTL_Get_Block_Table_Flash_Size_Bytes(void)
196{
197 u32 byte_num;
198
199 if (DeviceInfo.MLCDevice) {
200 byte_num = FTL_Get_LBAPBA_Table_Flash_Size_Bytes() +
201 DeviceInfo.wDataBlockNum * sizeof(u8) +
202 DeviceInfo.wDataBlockNum * sizeof(u16);
203 } else {
204 byte_num = FTL_Get_LBAPBA_Table_Flash_Size_Bytes() +
205 DeviceInfo.wDataBlockNum * sizeof(u8);
206 }
207
208 byte_num += 4 * sizeof(u8);
209
210 return byte_num;
211}
212
213static u16 FTL_Get_Block_Table_Flash_Size_Pages(void)
214{
215 return (u16)FTL_Get_Page_Num(FTL_Get_Block_Table_Flash_Size_Bytes());
216}
217
218static int FTL_Copy_Block_Table_To_Flash(u8 *flashBuf, u32 sizeToTx,
219 u32 sizeTxed)
220{
221 u32 wBytesCopied, blk_tbl_size, wBytes;
222 u32 *pbt = (u32 *)g_pBlockTable;
223
224 blk_tbl_size = FTL_Get_LBAPBA_Table_Flash_Size_Bytes();
225 for (wBytes = 0;
226 (wBytes < sizeToTx) && ((wBytes + sizeTxed) < blk_tbl_size);
227 wBytes++) {
228#if SUPPORT_LARGE_BLOCKNUM
229 flashBuf[wBytes] = (u8)(pbt[(wBytes + sizeTxed) / 3]
230 >> (((wBytes + sizeTxed) % 3) ?
231 ((((wBytes + sizeTxed) % 3) == 2) ? 0 : 8) : 16)) & 0xFF;
232#else
233 flashBuf[wBytes] = (u8)(pbt[(wBytes + sizeTxed) / 2]
234 >> (((wBytes + sizeTxed) % 2) ? 0 : 8)) & 0xFF;
235#endif
236 }
237
238 sizeTxed = (sizeTxed > blk_tbl_size) ? (sizeTxed - blk_tbl_size) : 0;
239 blk_tbl_size = FTL_Get_WearCounter_Table_Flash_Size_Bytes();
240 wBytesCopied = wBytes;
241 wBytes = ((blk_tbl_size - sizeTxed) > (sizeToTx - wBytesCopied)) ?
242 (sizeToTx - wBytesCopied) : (blk_tbl_size - sizeTxed);
243 memcpy(flashBuf + wBytesCopied, g_pWearCounter + sizeTxed, wBytes);
244
245 sizeTxed = (sizeTxed > blk_tbl_size) ? (sizeTxed - blk_tbl_size) : 0;
246
247 if (DeviceInfo.MLCDevice) {
248 blk_tbl_size = FTL_Get_ReadCounter_Table_Flash_Size_Bytes();
249 wBytesCopied += wBytes;
250 for (wBytes = 0; ((wBytes + wBytesCopied) < sizeToTx) &&
251 ((wBytes + sizeTxed) < blk_tbl_size); wBytes++)
252 flashBuf[wBytes + wBytesCopied] =
253 (g_pReadCounter[(wBytes + sizeTxed) / 2] >>
254 (((wBytes + sizeTxed) % 2) ? 0 : 8)) & 0xFF;
255 }
256
257 return wBytesCopied + wBytes;
258}
259
260static int FTL_Copy_Block_Table_From_Flash(u8 *flashBuf,
261 u32 sizeToTx, u32 sizeTxed)
262{
263 u32 wBytesCopied, blk_tbl_size, wBytes;
264 u32 *pbt = (u32 *)g_pBlockTable;
265
266 blk_tbl_size = FTL_Get_LBAPBA_Table_Flash_Size_Bytes();
267 for (wBytes = 0; (wBytes < sizeToTx) &&
268 ((wBytes + sizeTxed) < blk_tbl_size); wBytes++) {
269#if SUPPORT_LARGE_BLOCKNUM
270 if (!((wBytes + sizeTxed) % 3))
271 pbt[(wBytes + sizeTxed) / 3] = 0;
272 pbt[(wBytes + sizeTxed) / 3] |=
273 (flashBuf[wBytes] << (((wBytes + sizeTxed) % 3) ?
274 ((((wBytes + sizeTxed) % 3) == 2) ? 0 : 8) : 16));
275#else
276 if (!((wBytes + sizeTxed) % 2))
277 pbt[(wBytes + sizeTxed) / 2] = 0;
278 pbt[(wBytes + sizeTxed) / 2] |=
279 (flashBuf[wBytes] << (((wBytes + sizeTxed) % 2) ?
280 0 : 8));
281#endif
282 }
283
284 sizeTxed = (sizeTxed > blk_tbl_size) ? (sizeTxed - blk_tbl_size) : 0;
285 blk_tbl_size = FTL_Get_WearCounter_Table_Flash_Size_Bytes();
286 wBytesCopied = wBytes;
287 wBytes = ((blk_tbl_size - sizeTxed) > (sizeToTx - wBytesCopied)) ?
288 (sizeToTx - wBytesCopied) : (blk_tbl_size - sizeTxed);
289 memcpy(g_pWearCounter + sizeTxed, flashBuf + wBytesCopied, wBytes);
290 sizeTxed = (sizeTxed > blk_tbl_size) ? (sizeTxed - blk_tbl_size) : 0;
291
292 if (DeviceInfo.MLCDevice) {
293 wBytesCopied += wBytes;
294 blk_tbl_size = FTL_Get_ReadCounter_Table_Flash_Size_Bytes();
295 for (wBytes = 0; ((wBytes + wBytesCopied) < sizeToTx) &&
296 ((wBytes + sizeTxed) < blk_tbl_size); wBytes++) {
297 if (((wBytes + sizeTxed) % 2))
298 g_pReadCounter[(wBytes + sizeTxed) / 2] = 0;
299 g_pReadCounter[(wBytes + sizeTxed) / 2] |=
300 (flashBuf[wBytes] <<
301 (((wBytes + sizeTxed) % 2) ? 0 : 8));
302 }
303 }
304
305 return wBytesCopied+wBytes;
306}
307
308static int FTL_Insert_Block_Table_Signature(u8 *buf, u8 tag)
309{
310 int i;
311
312 for (i = 0; i < BTSIG_BYTES; i++)
313 buf[BTSIG_OFFSET + i] =
314 ((tag + (i * BTSIG_DELTA) - FIRST_BT_ID) %
315 (1 + LAST_BT_ID-FIRST_BT_ID)) + FIRST_BT_ID;
316
317 return PASS;
318}
319
320static int FTL_Extract_Block_Table_Tag(u8 *buf, u8 **tagarray)
321{
322 static u8 tag[BTSIG_BYTES >> 1];
323 int i, j, k, tagi, tagtemp, status;
324
325 *tagarray = (u8 *)tag;
326 tagi = 0;
327
328 for (i = 0; i < (BTSIG_BYTES - 1); i++) {
329 for (j = i + 1; (j < BTSIG_BYTES) &&
330 (tagi < (BTSIG_BYTES >> 1)); j++) {
331 tagtemp = buf[BTSIG_OFFSET + j] -
332 buf[BTSIG_OFFSET + i];
333 if (tagtemp && !(tagtemp % BTSIG_DELTA)) {
334 tagtemp = (buf[BTSIG_OFFSET + i] +
335 (1 + LAST_BT_ID - FIRST_BT_ID) -
336 (i * BTSIG_DELTA)) %
337 (1 + LAST_BT_ID - FIRST_BT_ID);
338 status = FAIL;
339 for (k = 0; k < tagi; k++) {
340 if (tagtemp == tag[k])
341 status = PASS;
342 }
343
344 if (status == FAIL) {
345 tag[tagi++] = tagtemp;
346 i = (j == (i + 1)) ? i + 1 : i;
347 j = (j == (i + 1)) ? i + 1 : i;
348 }
349 }
350 }
351 }
352
353 return tagi;
354}
355
356
357static int FTL_Execute_SPL_Recovery(void)
358{
359 u32 j, block, blks;
360 u32 *pbt = (u32 *)g_pBlockTable;
361 int ret;
362
363 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
364 __FILE__, __LINE__, __func__);
365
366 blks = DeviceInfo.wSpectraEndBlock - DeviceInfo.wSpectraStartBlock;
367 for (j = 0; j <= blks; j++) {
368 block = (pbt[j]);
369 if (((block & BAD_BLOCK) != BAD_BLOCK) &&
370 ((block & SPARE_BLOCK) == SPARE_BLOCK)) {
371 ret = GLOB_LLD_Erase_Block(block & ~BAD_BLOCK);
372 if (FAIL == ret) {
373 nand_dbg_print(NAND_DBG_WARN,
374 "NAND Program fail in %s, Line %d, "
375 "Function: %s, new Bad Block %d "
376 "generated!\n",
377 __FILE__, __LINE__, __func__,
378 (int)(block & ~BAD_BLOCK));
379 MARK_BLOCK_AS_BAD(pbt[j]);
380 }
381 }
382 }
383
384 return PASS;
385}
386
387/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
388* Function: GLOB_FTL_IdentifyDevice
389* Inputs: pointer to identify data structure
390* Outputs: PASS / FAIL
391* Description: the identify data structure is filled in with
392* information for the block driver.
393*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
394int GLOB_FTL_IdentifyDevice(struct spectra_indentfy_dev_tag *dev_data)
395{
396 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
397 __FILE__, __LINE__, __func__);
398
399 dev_data->NumBlocks = DeviceInfo.wTotalBlocks;
400 dev_data->PagesPerBlock = DeviceInfo.wPagesPerBlock;
401 dev_data->PageDataSize = DeviceInfo.wPageDataSize;
402 dev_data->wECCBytesPerSector = DeviceInfo.wECCBytesPerSector;
403 dev_data->wDataBlockNum = DeviceInfo.wDataBlockNum;
404
405 return PASS;
406}
407
408/* ..... */
409static int allocate_memory(void)
410{
411 u32 block_table_size, page_size, block_size, mem_size;
412 u32 total_bytes = 0;
413 int i;
414#if CMD_DMA
415 int j;
416#endif
417
418 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
419 __FILE__, __LINE__, __func__);
420
421 page_size = DeviceInfo.wPageSize;
422 block_size = DeviceInfo.wPagesPerBlock * DeviceInfo.wPageDataSize;
423
424 block_table_size = DeviceInfo.wDataBlockNum *
425 (sizeof(u32) + sizeof(u8) + sizeof(u16));
426 block_table_size += (DeviceInfo.wPageDataSize -
427 (block_table_size % DeviceInfo.wPageDataSize)) %
428 DeviceInfo.wPageDataSize;
429
430 /* Malloc memory for block tables */
431 g_pBlockTable = kzalloc(block_table_size, GFP_ATOMIC);
432 if (!g_pBlockTable)
433 goto block_table_fail;
434 total_bytes += block_table_size;
435
436 g_pWearCounter = (u8 *)(g_pBlockTable +
437 DeviceInfo.wDataBlockNum * sizeof(u32));
438
439 if (DeviceInfo.MLCDevice)
440 g_pReadCounter = (u16 *)(g_pBlockTable +
441 DeviceInfo.wDataBlockNum *
442 (sizeof(u32) + sizeof(u8)));
443
444 /* Malloc memory and init for cache items */
445 for (i = 0; i < CACHE_ITEM_NUM; i++) {
446 Cache.array[i].address = NAND_CACHE_INIT_ADDR;
447 Cache.array[i].use_cnt = 0;
448 Cache.array[i].changed = CLEAR;
449 Cache.array[i].buf = kzalloc(Cache.cache_item_size,
450 GFP_ATOMIC);
451 if (!Cache.array[i].buf)
452 goto cache_item_fail;
453 total_bytes += Cache.cache_item_size;
454 }
455
456 /* Malloc memory for IPF */
457 g_pIPF = kzalloc(page_size, GFP_ATOMIC);
458 if (!g_pIPF)
459 goto ipf_fail;
460 total_bytes += page_size;
461
462 /* Malloc memory for data merging during Level2 Cache flush */
463 cache_l2_page_buf = kmalloc(page_size, GFP_ATOMIC);
464 if (!cache_l2_page_buf)
465 goto cache_l2_page_buf_fail;
466 memset(cache_l2_page_buf, 0xff, page_size);
467 total_bytes += page_size;
468
469 cache_l2_blk_buf = kmalloc(block_size, GFP_ATOMIC);
470 if (!cache_l2_blk_buf)
471 goto cache_l2_blk_buf_fail;
472 memset(cache_l2_blk_buf, 0xff, block_size);
473 total_bytes += block_size;
474
475 /* Malloc memory for temp buffer */
476 g_pTempBuf = kzalloc(Cache.cache_item_size, GFP_ATOMIC);
477 if (!g_pTempBuf)
478 goto Temp_buf_fail;
479 total_bytes += Cache.cache_item_size;
480
481 /* Malloc memory for block table blocks */
482 mem_size = (1 + LAST_BT_ID - FIRST_BT_ID) * sizeof(u32);
483 g_pBTBlocks = kmalloc(mem_size, GFP_ATOMIC);
484 if (!g_pBTBlocks)
485 goto bt_blocks_fail;
486 memset(g_pBTBlocks, 0xff, mem_size);
487 total_bytes += mem_size;
488
489 /* Malloc memory for function FTL_Check_Block_Table */
490 flag_check_blk_table = kmalloc(DeviceInfo.wDataBlockNum, GFP_ATOMIC);
491 if (!flag_check_blk_table)
492 goto flag_check_blk_table_fail;
493 total_bytes += DeviceInfo.wDataBlockNum;
494
495 /* Malloc memory for function FTL_Search_Block_Table_IN_Block */
496 tmp_buf_search_bt_in_block = kmalloc(page_size, GFP_ATOMIC);
497 if (!tmp_buf_search_bt_in_block)
498 goto tmp_buf_search_bt_in_block_fail;
499 memset(tmp_buf_search_bt_in_block, 0xff, page_size);
500 total_bytes += page_size;
501
502 mem_size = DeviceInfo.wPageSize - DeviceInfo.wPageDataSize;
503 spare_buf_search_bt_in_block = kmalloc(mem_size, GFP_ATOMIC);
504 if (!spare_buf_search_bt_in_block)
505 goto spare_buf_search_bt_in_block_fail;
506 memset(spare_buf_search_bt_in_block, 0xff, mem_size);
507 total_bytes += mem_size;
508
509 spare_buf_bt_search_bt_in_block = kmalloc(mem_size, GFP_ATOMIC);
510 if (!spare_buf_bt_search_bt_in_block)
511 goto spare_buf_bt_search_bt_in_block_fail;
512 memset(spare_buf_bt_search_bt_in_block, 0xff, mem_size);
513 total_bytes += mem_size;
514
515 /* Malloc memory for function FTL_Read_Block_Table */
516 tmp_buf1_read_blk_table = kmalloc(page_size, GFP_ATOMIC);
517 if (!tmp_buf1_read_blk_table)
518 goto tmp_buf1_read_blk_table_fail;
519 memset(tmp_buf1_read_blk_table, 0xff, page_size);
520 total_bytes += page_size;
521
522 tmp_buf2_read_blk_table = kmalloc(page_size, GFP_ATOMIC);
523 if (!tmp_buf2_read_blk_table)
524 goto tmp_buf2_read_blk_table_fail;
525 memset(tmp_buf2_read_blk_table, 0xff, page_size);
526 total_bytes += page_size;
527
528 /* Malloc memory for function FTL_Static_Wear_Leveling */
529 flags_static_wear_leveling = kmalloc(DeviceInfo.wDataBlockNum,
530 GFP_ATOMIC);
531 if (!flags_static_wear_leveling)
532 goto flags_static_wear_leveling_fail;
533 total_bytes += DeviceInfo.wDataBlockNum;
534
535 /* Malloc memory for function FTL_Write_Block_Table_Data */
536 if (FTL_Get_Block_Table_Flash_Size_Pages() > 3)
537 mem_size = FTL_Get_Block_Table_Flash_Size_Bytes() -
538 2 * DeviceInfo.wPageSize;
539 else
540 mem_size = DeviceInfo.wPageSize;
541 tmp_buf_write_blk_table_data = kmalloc(mem_size, GFP_ATOMIC);
542 if (!tmp_buf_write_blk_table_data)
543 goto tmp_buf_write_blk_table_data_fail;
544 memset(tmp_buf_write_blk_table_data, 0xff, mem_size);
545 total_bytes += mem_size;
546
547 /* Malloc memory for function FTL_Read_Disturbance */
548 tmp_buf_read_disturbance = kmalloc(block_size, GFP_ATOMIC);
549 if (!tmp_buf_read_disturbance)
550 goto tmp_buf_read_disturbance_fail;
551 memset(tmp_buf_read_disturbance, 0xff, block_size);
552 total_bytes += block_size;
553
554 /* Alloc mem for function NAND_Read_Page_Main_Spare of lld_nand.c */
555 buf_read_page_main_spare = kmalloc(DeviceInfo.wPageSize, GFP_ATOMIC);
556 if (!buf_read_page_main_spare)
557 goto buf_read_page_main_spare_fail;
558 total_bytes += DeviceInfo.wPageSize;
559
560 /* Alloc mem for function NAND_Write_Page_Main_Spare of lld_nand.c */
561 buf_write_page_main_spare = kmalloc(DeviceInfo.wPageSize, GFP_ATOMIC);
562 if (!buf_write_page_main_spare)
563 goto buf_write_page_main_spare_fail;
564 total_bytes += DeviceInfo.wPageSize;
565
566 /* Alloc mem for function NAND_Read_Page_Spare of lld_nand.c */
567 buf_read_page_spare = kmalloc(DeviceInfo.wPageSpareSize, GFP_ATOMIC);
568 if (!buf_read_page_spare)
569 goto buf_read_page_spare_fail;
570 memset(buf_read_page_spare, 0xff, DeviceInfo.wPageSpareSize);
571 total_bytes += DeviceInfo.wPageSpareSize;
572
573 /* Alloc mem for function NAND_Get_Bad_Block of lld_nand.c */
574 buf_get_bad_block = kmalloc(DeviceInfo.wPageSpareSize, GFP_ATOMIC);
575 if (!buf_get_bad_block)
576 goto buf_get_bad_block_fail;
577 memset(buf_get_bad_block, 0xff, DeviceInfo.wPageSpareSize);
578 total_bytes += DeviceInfo.wPageSpareSize;
579
580#if CMD_DMA
581 g_temp_buf = kmalloc(block_size, GFP_ATOMIC);
582 if (!g_temp_buf)
583 goto temp_buf_fail;
584 memset(g_temp_buf, 0xff, block_size);
585 total_bytes += block_size;
586
587 /* Malloc memory for copy of block table used in CDMA mode */
588 g_pBTStartingCopy = kzalloc(block_table_size, GFP_ATOMIC);
589 if (!g_pBTStartingCopy)
590 goto bt_starting_copy;
591 total_bytes += block_table_size;
592
593 g_pWearCounterCopy = (u8 *)(g_pBTStartingCopy +
594 DeviceInfo.wDataBlockNum * sizeof(u32));
595
596 if (DeviceInfo.MLCDevice)
597 g_pReadCounterCopy = (u16 *)(g_pBTStartingCopy +
598 DeviceInfo.wDataBlockNum *
599 (sizeof(u32) + sizeof(u8)));
600
601 /* Malloc memory for block table copies */
602 mem_size = 5 * DeviceInfo.wDataBlockNum * sizeof(u32) +
603 5 * DeviceInfo.wDataBlockNum * sizeof(u8);
604 if (DeviceInfo.MLCDevice)
605 mem_size += 5 * DeviceInfo.wDataBlockNum * sizeof(u16);
606 g_pBlockTableCopies = kzalloc(mem_size, GFP_ATOMIC);
607 if (!g_pBlockTableCopies)
608 goto blk_table_copies_fail;
609 total_bytes += mem_size;
610 g_pNextBlockTable = g_pBlockTableCopies;
611
612 /* Malloc memory for Block Table Delta */
613 mem_size = MAX_DESCS * sizeof(struct BTableChangesDelta);
614 g_pBTDelta = kzalloc(mem_size, GFP_ATOMIC);
615 if (!g_pBTDelta)
616 goto bt_delta_fail;
617 total_bytes += mem_size;
618 g_pBTDelta_Free = g_pBTDelta;
619
620 /* Malloc memory for Copy Back Buffers */
621 for (j = 0; j < COPY_BACK_BUF_NUM; j++) {
622 cp_back_buf_copies[j] = kzalloc(block_size, GFP_ATOMIC);
623 if (!cp_back_buf_copies[j])
624 goto cp_back_buf_copies_fail;
625 total_bytes += block_size;
626 }
627 cp_back_buf_idx = 0;
628
629 /* Malloc memory for pending commands list */
630 mem_size = sizeof(struct pending_cmd) * MAX_DESCS;
631 info.pcmds = kzalloc(mem_size, GFP_KERNEL);
632 if (!info.pcmds)
633 goto pending_cmds_buf_fail;
634 total_bytes += mem_size;
635
636 /* Malloc memory for CDMA descripter table */
637 mem_size = sizeof(struct cdma_descriptor) * MAX_DESCS;
638 info.cdma_desc_buf = kzalloc(mem_size, GFP_KERNEL);
639 if (!info.cdma_desc_buf)
640 goto cdma_desc_buf_fail;
641 total_bytes += mem_size;
642
643 /* Malloc memory for Memcpy descripter table */
644 mem_size = sizeof(struct memcpy_descriptor) * MAX_DESCS;
645 info.memcp_desc_buf = kzalloc(mem_size, GFP_KERNEL);
646 if (!info.memcp_desc_buf)
647 goto memcp_desc_buf_fail;
648 total_bytes += mem_size;
649#endif
650
651 nand_dbg_print(NAND_DBG_WARN,
652 "Total memory allocated in FTL layer: %d\n", total_bytes);
653
654 return PASS;
655
656#if CMD_DMA
657memcp_desc_buf_fail:
658 kfree(info.cdma_desc_buf);
659cdma_desc_buf_fail:
660 kfree(info.pcmds);
661pending_cmds_buf_fail:
662cp_back_buf_copies_fail:
663 j--;
664 for (; j >= 0; j--)
665 kfree(cp_back_buf_copies[j]);
666 kfree(g_pBTDelta);
667bt_delta_fail:
668 kfree(g_pBlockTableCopies);
669blk_table_copies_fail:
670 kfree(g_pBTStartingCopy);
671bt_starting_copy:
672 kfree(g_temp_buf);
673temp_buf_fail:
674 kfree(buf_get_bad_block);
675#endif
676
677buf_get_bad_block_fail:
678 kfree(buf_read_page_spare);
679buf_read_page_spare_fail:
680 kfree(buf_write_page_main_spare);
681buf_write_page_main_spare_fail:
682 kfree(buf_read_page_main_spare);
683buf_read_page_main_spare_fail:
684 kfree(tmp_buf_read_disturbance);
685tmp_buf_read_disturbance_fail:
686 kfree(tmp_buf_write_blk_table_data);
687tmp_buf_write_blk_table_data_fail:
688 kfree(flags_static_wear_leveling);
689flags_static_wear_leveling_fail:
690 kfree(tmp_buf2_read_blk_table);
691tmp_buf2_read_blk_table_fail:
692 kfree(tmp_buf1_read_blk_table);
693tmp_buf1_read_blk_table_fail:
694 kfree(spare_buf_bt_search_bt_in_block);
695spare_buf_bt_search_bt_in_block_fail:
696 kfree(spare_buf_search_bt_in_block);
697spare_buf_search_bt_in_block_fail:
698 kfree(tmp_buf_search_bt_in_block);
699tmp_buf_search_bt_in_block_fail:
700 kfree(flag_check_blk_table);
701flag_check_blk_table_fail:
702 kfree(g_pBTBlocks);
703bt_blocks_fail:
704 kfree(g_pTempBuf);
705Temp_buf_fail:
706 kfree(cache_l2_blk_buf);
707cache_l2_blk_buf_fail:
708 kfree(cache_l2_page_buf);
709cache_l2_page_buf_fail:
710 kfree(g_pIPF);
711ipf_fail:
712cache_item_fail:
713 i--;
714 for (; i >= 0; i--)
715 kfree(Cache.array[i].buf);
716 kfree(g_pBlockTable);
717block_table_fail:
718 printk(KERN_ERR "Failed to kmalloc memory in %s Line %d.\n",
719 __FILE__, __LINE__);
720
721 return -ENOMEM;
722}
723
724/* .... */
725static int free_memory(void)
726{
727 int i;
728
729#if CMD_DMA
730 kfree(info.memcp_desc_buf);
731 kfree(info.cdma_desc_buf);
732 kfree(info.pcmds);
733 for (i = COPY_BACK_BUF_NUM - 1; i >= 0; i--)
734 kfree(cp_back_buf_copies[i]);
735 kfree(g_pBTDelta);
736 kfree(g_pBlockTableCopies);
737 kfree(g_pBTStartingCopy);
738 kfree(g_temp_buf);
739 kfree(buf_get_bad_block);
740#endif
741 kfree(buf_read_page_spare);
742 kfree(buf_write_page_main_spare);
743 kfree(buf_read_page_main_spare);
744 kfree(tmp_buf_read_disturbance);
745 kfree(tmp_buf_write_blk_table_data);
746 kfree(flags_static_wear_leveling);
747 kfree(tmp_buf2_read_blk_table);
748 kfree(tmp_buf1_read_blk_table);
749 kfree(spare_buf_bt_search_bt_in_block);
750 kfree(spare_buf_search_bt_in_block);
751 kfree(tmp_buf_search_bt_in_block);
752 kfree(flag_check_blk_table);
753 kfree(g_pBTBlocks);
754 kfree(g_pTempBuf);
755 kfree(g_pIPF);
756 for (i = CACHE_ITEM_NUM - 1; i >= 0; i--)
757 kfree(Cache.array[i].buf);
758 kfree(g_pBlockTable);
759
760 return 0;
761}
762
763static void dump_cache_l2_table(void)
764{
765 struct list_head *p;
766 struct spectra_l2_cache_list *pnd;
767 int n;
768
769 n = 0;
770 list_for_each(p, &cache_l2.table.list) {
771 pnd = list_entry(p, struct spectra_l2_cache_list, list);
772 nand_dbg_print(NAND_DBG_WARN, "dump_cache_l2_table node: %d, logical_blk_num: %d\n", n, pnd->logical_blk_num);
773/*
774 for (i = 0; i < DeviceInfo.wPagesPerBlock; i++) {
775 if (pnd->pages_array[i] != MAX_U32_VALUE)
776 nand_dbg_print(NAND_DBG_WARN, " pages_array[%d]: 0x%x\n", i, pnd->pages_array[i]);
777 }
778*/
779 n++;
780 }
781}
782
783/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
784* Function: GLOB_FTL_Init
785* Inputs: none
786* Outputs: PASS=0 / FAIL=1
787* Description: allocates the memory for cache array,
788* important data structures
789* clears the cache array
790* reads the block table from flash into array
791*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
792int GLOB_FTL_Init(void)
793{
794 int i;
795
796 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
797 __FILE__, __LINE__, __func__);
798
799 Cache.pages_per_item = 1;
800 Cache.cache_item_size = 1 * DeviceInfo.wPageDataSize;
801
802 if (allocate_memory() != PASS)
803 return FAIL;
804
805#if CMD_DMA
806#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
807 memcpy((void *)&cache_start_copy, (void *)&Cache,
808 sizeof(struct flash_cache_tag));
809 memset((void *)&int_cache, -1,
810 sizeof(struct flash_cache_delta_list_tag) *
811 (MAX_CHANS + MAX_DESCS));
812#endif
813 ftl_cmd_cnt = 0;
814#endif
815
816 if (FTL_Read_Block_Table() != PASS)
817 return FAIL;
818
819 /* Init the Level2 Cache data structure */
820 for (i = 0; i < BLK_NUM_FOR_L2_CACHE; i++)
821 cache_l2.blk_array[i] = MAX_U32_VALUE;
822 cache_l2.cur_blk_idx = 0;
823 cache_l2.cur_page_num = 0;
824 INIT_LIST_HEAD(&cache_l2.table.list);
825 cache_l2.table.logical_blk_num = MAX_U32_VALUE;
826
827 dump_cache_l2_table();
828
829 return 0;
830}
831
832
833#if CMD_DMA
834#if 0
835static void save_blk_table_changes(u16 idx)
836{
837 u8 ftl_cmd;
838 u32 *pbt = (u32 *)g_pBTStartingCopy;
839
840#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
841 u16 id;
842 u8 cache_blks;
843
844 id = idx - MAX_CHANS;
845 if (int_cache[id].item != -1) {
846 cache_blks = int_cache[id].item;
847 cache_start_copy.array[cache_blks].address =
848 int_cache[id].cache.address;
849 cache_start_copy.array[cache_blks].changed =
850 int_cache[id].cache.changed;
851 }
852#endif
853
854 ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt;
855
856 while (ftl_cmd <= PendingCMD[idx].Tag) {
857 if (p_BTableChangesDelta->ValidFields == 0x01) {
858 g_wBlockTableOffset =
859 p_BTableChangesDelta->g_wBlockTableOffset;
860 } else if (p_BTableChangesDelta->ValidFields == 0x0C) {
861 pbt[p_BTableChangesDelta->BT_Index] =
862 p_BTableChangesDelta->BT_Entry_Value;
863 debug_boundary_error(((
864 p_BTableChangesDelta->BT_Index)),
865 DeviceInfo.wDataBlockNum, 0);
866 } else if (p_BTableChangesDelta->ValidFields == 0x03) {
867 g_wBlockTableOffset =
868 p_BTableChangesDelta->g_wBlockTableOffset;
869 g_wBlockTableIndex =
870 p_BTableChangesDelta->g_wBlockTableIndex;
871 } else if (p_BTableChangesDelta->ValidFields == 0x30) {
872 g_pWearCounterCopy[p_BTableChangesDelta->WC_Index] =
873 p_BTableChangesDelta->WC_Entry_Value;
874 } else if ((DeviceInfo.MLCDevice) &&
875 (p_BTableChangesDelta->ValidFields == 0xC0)) {
876 g_pReadCounterCopy[p_BTableChangesDelta->RC_Index] =
877 p_BTableChangesDelta->RC_Entry_Value;
878 nand_dbg_print(NAND_DBG_DEBUG,
879 "In event status setting read counter "
880 "GLOB_ftl_cmd_cnt %u Count %u Index %u\n",
881 ftl_cmd,
882 p_BTableChangesDelta->RC_Entry_Value,
883 (unsigned int)p_BTableChangesDelta->RC_Index);
884 } else {
885 nand_dbg_print(NAND_DBG_DEBUG,
886 "This should never occur \n");
887 }
888 p_BTableChangesDelta += 1;
889 ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt;
890 }
891}
892
893static void discard_cmds(u16 n)
894{
895 u32 *pbt = (u32 *)g_pBTStartingCopy;
896 u8 ftl_cmd;
897 unsigned long k;
898#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
899 u8 cache_blks;
900 u16 id;
901#endif
902
903 if ((PendingCMD[n].CMD == WRITE_MAIN_CMD) ||
904 (PendingCMD[n].CMD == WRITE_MAIN_SPARE_CMD)) {
905 for (k = 0; k < DeviceInfo.wDataBlockNum; k++) {
906 if (PendingCMD[n].Block == (pbt[k] & (~BAD_BLOCK)))
907 MARK_BLK_AS_DISCARD(pbt[k]);
908 }
909 }
910
911 ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt;
912 while (ftl_cmd <= PendingCMD[n].Tag) {
913 p_BTableChangesDelta += 1;
914 ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt;
915 }
916
917#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
918 id = n - MAX_CHANS;
919
920 if (int_cache[id].item != -1) {
921 cache_blks = int_cache[id].item;
922 if (PendingCMD[n].CMD == MEMCOPY_CMD) {
923 if ((cache_start_copy.array[cache_blks].buf <=
924 PendingCMD[n].DataDestAddr) &&
925 ((cache_start_copy.array[cache_blks].buf +
926 Cache.cache_item_size) >
927 PendingCMD[n].DataDestAddr)) {
928 cache_start_copy.array[cache_blks].address =
929 NAND_CACHE_INIT_ADDR;
930 cache_start_copy.array[cache_blks].use_cnt =
931 0;
932 cache_start_copy.array[cache_blks].changed =
933 CLEAR;
934 }
935 } else {
936 cache_start_copy.array[cache_blks].address =
937 int_cache[id].cache.address;
938 cache_start_copy.array[cache_blks].changed =
939 int_cache[id].cache.changed;
940 }
941 }
942#endif
943}
944
945static void process_cmd_pass(int *first_failed_cmd, u16 idx)
946{
947 if (0 == *first_failed_cmd)
948 save_blk_table_changes(idx);
949 else
950 discard_cmds(idx);
951}
952
953static void process_cmd_fail_abort(int *first_failed_cmd,
954 u16 idx, int event)
955{
956 u32 *pbt = (u32 *)g_pBTStartingCopy;
957 u8 ftl_cmd;
958 unsigned long i;
959 int erase_fail, program_fail;
960#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
961 u8 cache_blks;
962 u16 id;
963#endif
964
965 if (0 == *first_failed_cmd)
966 *first_failed_cmd = PendingCMD[idx].SBDCmdIndex;
967
968 nand_dbg_print(NAND_DBG_DEBUG, "Uncorrectable error has occurred "
969 "while executing %u Command %u accesing Block %u\n",
970 (unsigned int)p_BTableChangesDelta->ftl_cmd_cnt,
971 PendingCMD[idx].CMD,
972 (unsigned int)PendingCMD[idx].Block);
973
974 ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt;
975 while (ftl_cmd <= PendingCMD[idx].Tag) {
976 p_BTableChangesDelta += 1;
977 ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt;
978 }
979
980#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
981 id = idx - MAX_CHANS;
982
983 if (int_cache[id].item != -1) {
984 cache_blks = int_cache[id].item;
985 if ((PendingCMD[idx].CMD == WRITE_MAIN_CMD)) {
986 cache_start_copy.array[cache_blks].address =
987 int_cache[id].cache.address;
988 cache_start_copy.array[cache_blks].changed = SET;
989 } else if ((PendingCMD[idx].CMD == READ_MAIN_CMD)) {
990 cache_start_copy.array[cache_blks].address =
991 NAND_CACHE_INIT_ADDR;
992 cache_start_copy.array[cache_blks].use_cnt = 0;
993 cache_start_copy.array[cache_blks].changed =
994 CLEAR;
995 } else if (PendingCMD[idx].CMD == ERASE_CMD) {
996 /* ? */
997 } else if (PendingCMD[idx].CMD == MEMCOPY_CMD) {
998 /* ? */
999 }
1000 }
1001#endif
1002
1003 erase_fail = (event == EVENT_ERASE_FAILURE) &&
1004 (PendingCMD[idx].CMD == ERASE_CMD);
1005
1006 program_fail = (event == EVENT_PROGRAM_FAILURE) &&
1007 ((PendingCMD[idx].CMD == WRITE_MAIN_CMD) ||
1008 (PendingCMD[idx].CMD == WRITE_MAIN_SPARE_CMD));
1009
1010 if (erase_fail || program_fail) {
1011 for (i = 0; i < DeviceInfo.wDataBlockNum; i++) {
1012 if (PendingCMD[idx].Block ==
1013 (pbt[i] & (~BAD_BLOCK)))
1014 MARK_BLOCK_AS_BAD(pbt[i]);
1015 }
1016 }
1017}
1018
1019static void process_cmd(int *first_failed_cmd, u16 idx, int event)
1020{
1021 u8 ftl_cmd;
1022 int cmd_match = 0;
1023
1024 if (p_BTableChangesDelta->ftl_cmd_cnt == PendingCMD[idx].Tag)
1025 cmd_match = 1;
1026
1027 if (PendingCMD[idx].Status == CMD_PASS) {
1028 process_cmd_pass(first_failed_cmd, idx);
1029 } else if ((PendingCMD[idx].Status == CMD_FAIL) ||
1030 (PendingCMD[idx].Status == CMD_ABORT)) {
1031 process_cmd_fail_abort(first_failed_cmd, idx, event);
1032 } else if ((PendingCMD[idx].Status == CMD_NOT_DONE) &&
1033 PendingCMD[idx].Tag) {
1034 nand_dbg_print(NAND_DBG_DEBUG,
1035 " Command no. %hu is not executed\n",
1036 (unsigned int)PendingCMD[idx].Tag);
1037 ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt;
1038 while (ftl_cmd <= PendingCMD[idx].Tag) {
1039 p_BTableChangesDelta += 1;
1040 ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt;
1041 }
1042 }
1043}
1044#endif
1045
1046static void process_cmd(int *first_failed_cmd, u16 idx, int event)
1047{
1048 printk(KERN_ERR "temporary workaround function. "
1049 "Should not be called! \n");
1050}
1051
1052/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
1053* Function: GLOB_FTL_Event_Status
1054* Inputs: none
1055* Outputs: Event Code
1056* Description: It is called by SBD after hardware interrupt signalling
1057* completion of commands chain
1058* It does following things
1059* get event status from LLD
1060* analyze command chain status
1061* determine last command executed
1062* analyze results
1063* rebuild the block table in case of uncorrectable error
1064* return event code
1065*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
1066int GLOB_FTL_Event_Status(int *first_failed_cmd)
1067{
1068 int event_code = PASS;
1069 u16 i_P;
1070
1071 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
1072 __FILE__, __LINE__, __func__);
1073
1074 *first_failed_cmd = 0;
1075
1076 event_code = GLOB_LLD_Event_Status();
1077
1078 switch (event_code) {
1079 case EVENT_PASS:
1080 nand_dbg_print(NAND_DBG_DEBUG, "Handling EVENT_PASS\n");
1081 break;
1082 case EVENT_UNCORRECTABLE_DATA_ERROR:
1083 nand_dbg_print(NAND_DBG_DEBUG, "Handling Uncorrectable ECC!\n");
1084 break;
1085 case EVENT_PROGRAM_FAILURE:
1086 case EVENT_ERASE_FAILURE:
1087 nand_dbg_print(NAND_DBG_WARN, "Handling Ugly case. "
1088 "Event code: 0x%x\n", event_code);
1089 p_BTableChangesDelta =
1090 (struct BTableChangesDelta *)g_pBTDelta;
1091 for (i_P = MAX_CHANS; i_P < (ftl_cmd_cnt + MAX_CHANS);
1092 i_P++)
1093 process_cmd(first_failed_cmd, i_P, event_code);
1094 memcpy(g_pBlockTable, g_pBTStartingCopy,
1095 DeviceInfo.wDataBlockNum * sizeof(u32));
1096 memcpy(g_pWearCounter, g_pWearCounterCopy,
1097 DeviceInfo.wDataBlockNum * sizeof(u8));
1098 if (DeviceInfo.MLCDevice)
1099 memcpy(g_pReadCounter, g_pReadCounterCopy,
1100 DeviceInfo.wDataBlockNum * sizeof(u16));
1101
1102#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
1103 memcpy((void *)&Cache, (void *)&cache_start_copy,
1104 sizeof(struct flash_cache_tag));
1105 memset((void *)&int_cache, -1,
1106 sizeof(struct flash_cache_delta_list_tag) *
1107 (MAX_DESCS + MAX_CHANS));
1108#endif
1109 break;
1110 default:
1111 nand_dbg_print(NAND_DBG_WARN,
1112 "Handling unexpected event code - 0x%x\n",
1113 event_code);
1114 event_code = ERR;
1115 break;
1116 }
1117
1118 memcpy(g_pBTStartingCopy, g_pBlockTable,
1119 DeviceInfo.wDataBlockNum * sizeof(u32));
1120 memcpy(g_pWearCounterCopy, g_pWearCounter,
1121 DeviceInfo.wDataBlockNum * sizeof(u8));
1122 if (DeviceInfo.MLCDevice)
1123 memcpy(g_pReadCounterCopy, g_pReadCounter,
1124 DeviceInfo.wDataBlockNum * sizeof(u16));
1125
1126 g_pBTDelta_Free = g_pBTDelta;
1127 ftl_cmd_cnt = 0;
1128 g_pNextBlockTable = g_pBlockTableCopies;
1129 cp_back_buf_idx = 0;
1130
1131#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
1132 memcpy((void *)&cache_start_copy, (void *)&Cache,
1133 sizeof(struct flash_cache_tag));
1134 memset((void *)&int_cache, -1,
1135 sizeof(struct flash_cache_delta_list_tag) *
1136 (MAX_DESCS + MAX_CHANS));
1137#endif
1138
1139 return event_code;
1140}
1141
1142/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
1143* Function: glob_ftl_execute_cmds
1144* Inputs: none
1145* Outputs: none
1146* Description: pass thru to LLD
1147***************************************************************/
1148u16 glob_ftl_execute_cmds(void)
1149{
1150 nand_dbg_print(NAND_DBG_TRACE,
1151 "glob_ftl_execute_cmds: ftl_cmd_cnt %u\n",
1152 (unsigned int)ftl_cmd_cnt);
1153 g_SBDCmdIndex = 0;
1154 return glob_lld_execute_cmds();
1155}
1156
1157#endif
1158
1159#if !CMD_DMA
1160/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
1161* Function: GLOB_FTL_Read Immediate
1162* Inputs: pointer to data
1163* address of data
1164* Outputs: PASS / FAIL
1165* Description: Reads one page of data into RAM directly from flash without
1166* using or disturbing cache.It is assumed this function is called
1167* with CMD-DMA disabled.
1168*****************************************************************/
1169int GLOB_FTL_Read_Immediate(u8 *read_data, u64 addr)
1170{
1171 int wResult = FAIL;
1172 u32 Block;
1173 u16 Page;
1174 u32 phy_blk;
1175 u32 *pbt = (u32 *)g_pBlockTable;
1176
1177 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
1178 __FILE__, __LINE__, __func__);
1179
1180 Block = BLK_FROM_ADDR(addr);
1181 Page = PAGE_FROM_ADDR(addr, Block);
1182
1183 if (!IS_SPARE_BLOCK(Block))
1184 return FAIL;
1185
1186 phy_blk = pbt[Block];
1187 wResult = GLOB_LLD_Read_Page_Main(read_data, phy_blk, Page, 1);
1188
1189 if (DeviceInfo.MLCDevice) {
1190 g_pReadCounter[phy_blk - DeviceInfo.wSpectraStartBlock]++;
1191 if (g_pReadCounter[phy_blk - DeviceInfo.wSpectraStartBlock]
1192 >= MAX_READ_COUNTER)
1193 FTL_Read_Disturbance(phy_blk);
1194 if (g_cBlockTableStatus != IN_PROGRESS_BLOCK_TABLE) {
1195 g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE;
1196 FTL_Write_IN_Progress_Block_Table_Page();
1197 }
1198 }
1199
1200 return wResult;
1201}
1202#endif
1203
1204#ifdef SUPPORT_BIG_ENDIAN
1205/*********************************************************************
1206* Function: FTL_Invert_Block_Table
1207* Inputs: none
1208* Outputs: none
1209* Description: Re-format the block table in ram based on BIG_ENDIAN and
1210* LARGE_BLOCKNUM if necessary
1211**********************************************************************/
1212static void FTL_Invert_Block_Table(void)
1213{
1214 u32 i;
1215 u32 *pbt = (u32 *)g_pBlockTable;
1216
1217 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
1218 __FILE__, __LINE__, __func__);
1219
1220#ifdef SUPPORT_LARGE_BLOCKNUM
1221 for (i = 0; i < DeviceInfo.wDataBlockNum; i++) {
1222 pbt[i] = INVERTUINT32(pbt[i]);
1223 g_pWearCounter[i] = INVERTUINT32(g_pWearCounter[i]);
1224 }
1225#else
1226 for (i = 0; i < DeviceInfo.wDataBlockNum; i++) {
1227 pbt[i] = INVERTUINT16(pbt[i]);
1228 g_pWearCounter[i] = INVERTUINT16(g_pWearCounter[i]);
1229 }
1230#endif
1231}
1232#endif
1233
1234/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
1235* Function: GLOB_FTL_Flash_Init
1236* Inputs: none
1237* Outputs: PASS=0 / FAIL=0x01 (based on read ID)
1238* Description: The flash controller is initialized
1239* The flash device is reset
1240* Perform a flash READ ID command to confirm that a
1241* valid device is attached and active.
1242* The DeviceInfo structure gets filled in
1243*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
1244int GLOB_FTL_Flash_Init(void)
1245{
1246 int status = FAIL;
1247
1248 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
1249 __FILE__, __LINE__, __func__);
1250
1251 g_SBDCmdIndex = 0;
1252
1253 status = GLOB_LLD_Flash_Init();
1254
1255 return status;
1256}
1257
1258/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
1259* Inputs: none
1260* Outputs: PASS=0 / FAIL=0x01 (based on read ID)
1261* Description: The flash controller is released
1262*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
1263int GLOB_FTL_Flash_Release(void)
1264{
1265 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
1266 __FILE__, __LINE__, __func__);
1267
1268 return GLOB_LLD_Flash_Release();
1269}
1270
1271
1272/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
1273* Function: GLOB_FTL_Cache_Release
1274* Inputs: none
1275* Outputs: none
1276* Description: release all allocated memory in GLOB_FTL_Init
1277* (allocated in GLOB_FTL_Init)
1278*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
1279void GLOB_FTL_Cache_Release(void)
1280{
1281 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
1282 __FILE__, __LINE__, __func__);
1283
1284 free_memory();
1285}
1286
1287/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
1288* Function: FTL_Cache_If_Hit
1289* Inputs: Page Address
1290* Outputs: Block number/UNHIT BLOCK
1291* Description: Determines if the addressed page is in cache
1292*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
1293static u16 FTL_Cache_If_Hit(u64 page_addr)
1294{
1295 u16 item;
1296 u64 addr;
1297 int i;
1298
1299 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
1300 __FILE__, __LINE__, __func__);
1301
1302 item = UNHIT_CACHE_ITEM;
1303 for (i = 0; i < CACHE_ITEM_NUM; i++) {
1304 addr = Cache.array[i].address;
1305 if ((page_addr >= addr) &&
1306 (page_addr < (addr + Cache.cache_item_size))) {
1307 item = i;
1308 break;
1309 }
1310 }
1311
1312 return item;
1313}
1314
1315/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
1316* Function: FTL_Calculate_LRU
1317* Inputs: None
1318* Outputs: None
1319* Description: Calculate the least recently block in a cache and record its
1320* index in LRU field.
1321*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
1322static void FTL_Calculate_LRU(void)
1323{
1324 u16 i, bCurrentLRU, bTempCount;
1325
1326 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
1327 __FILE__, __LINE__, __func__);
1328
1329 bCurrentLRU = 0;
1330 bTempCount = MAX_WORD_VALUE;
1331
1332 for (i = 0; i < CACHE_ITEM_NUM; i++) {
1333 if (Cache.array[i].use_cnt < bTempCount) {
1334 bCurrentLRU = i;
1335 bTempCount = Cache.array[i].use_cnt;
1336 }
1337 }
1338
1339 Cache.LRU = bCurrentLRU;
1340}
1341
1342/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
1343* Function: FTL_Cache_Read_Page
1344* Inputs: pointer to read buffer, logical address and cache item number
1345* Outputs: None
1346* Description: Read the page from the cached block addressed by blocknumber
1347*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
1348static void FTL_Cache_Read_Page(u8 *data_buf, u64 logic_addr, u16 cache_item)
1349{
1350 u8 *start_addr;
1351
1352 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
1353 __FILE__, __LINE__, __func__);
1354
1355 start_addr = Cache.array[cache_item].buf;
1356 start_addr += (u32)(((logic_addr - Cache.array[cache_item].address) >>
1357 DeviceInfo.nBitsInPageDataSize) * DeviceInfo.wPageDataSize);
1358
1359#if CMD_DMA
1360 GLOB_LLD_MemCopy_CMD(data_buf, start_addr,
1361 DeviceInfo.wPageDataSize, 0);
1362 ftl_cmd_cnt++;
1363#else
1364 memcpy(data_buf, start_addr, DeviceInfo.wPageDataSize);
1365#endif
1366
1367 if (Cache.array[cache_item].use_cnt < MAX_WORD_VALUE)
1368 Cache.array[cache_item].use_cnt++;
1369}
1370
1371/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
1372* Function: FTL_Cache_Read_All
1373* Inputs: pointer to read buffer,block address
1374* Outputs: PASS=0 / FAIL =1
1375* Description: It reads pages in cache
1376*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
1377static int FTL_Cache_Read_All(u8 *pData, u64 phy_addr)
1378{
1379 int wResult = PASS;
1380 u32 Block;
1381 u32 lba;
1382 u16 Page;
1383 u16 PageCount;
1384 u32 *pbt = (u32 *)g_pBlockTable;
1385 u32 i;
1386
1387 Block = BLK_FROM_ADDR(phy_addr);
1388 Page = PAGE_FROM_ADDR(phy_addr, Block);
1389 PageCount = Cache.pages_per_item;
1390
1391 nand_dbg_print(NAND_DBG_DEBUG,
1392 "%s, Line %d, Function: %s, Block: 0x%x\n",
1393 __FILE__, __LINE__, __func__, Block);
1394
1395 lba = 0xffffffff;
1396 for (i = 0; i < DeviceInfo.wDataBlockNum; i++) {
1397 if ((pbt[i] & (~BAD_BLOCK)) == Block) {
1398 lba = i;
1399 if (IS_SPARE_BLOCK(i) || IS_BAD_BLOCK(i) ||
1400 IS_DISCARDED_BLOCK(i)) {
1401 /* Add by yunpeng -2008.12.3 */
1402#if CMD_DMA
1403 GLOB_LLD_MemCopy_CMD(pData, g_temp_buf,
1404 PageCount * DeviceInfo.wPageDataSize, 0);
1405 ftl_cmd_cnt++;
1406#else
1407 memset(pData, 0xFF,
1408 PageCount * DeviceInfo.wPageDataSize);
1409#endif
1410 return wResult;
1411 } else {
1412 continue; /* break ?? */
1413 }
1414 }
1415 }
1416
1417 if (0xffffffff == lba)
1418 printk(KERN_ERR "FTL_Cache_Read_All: Block is not found in BT\n");
1419
1420#if CMD_DMA
1421 wResult = GLOB_LLD_Read_Page_Main_cdma(pData, Block, Page,
1422 PageCount, LLD_CMD_FLAG_MODE_CDMA);
1423 if (DeviceInfo.MLCDevice) {
1424 g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock]++;
1425 nand_dbg_print(NAND_DBG_DEBUG,
1426 "Read Counter modified in ftl_cmd_cnt %u"
1427 " Block %u Counter%u\n",
1428 ftl_cmd_cnt, (unsigned int)Block,
1429 g_pReadCounter[Block -
1430 DeviceInfo.wSpectraStartBlock]);
1431
1432 p_BTableChangesDelta =
1433 (struct BTableChangesDelta *)g_pBTDelta_Free;
1434 g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
1435 p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt;
1436 p_BTableChangesDelta->RC_Index =
1437 Block - DeviceInfo.wSpectraStartBlock;
1438 p_BTableChangesDelta->RC_Entry_Value =
1439 g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock];
1440 p_BTableChangesDelta->ValidFields = 0xC0;
1441
1442 ftl_cmd_cnt++;
1443
1444 if (g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock] >=
1445 MAX_READ_COUNTER)
1446 FTL_Read_Disturbance(Block);
1447 if (g_cBlockTableStatus != IN_PROGRESS_BLOCK_TABLE) {
1448 g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE;
1449 FTL_Write_IN_Progress_Block_Table_Page();
1450 }
1451 } else {
1452 ftl_cmd_cnt++;
1453 }
1454#else
1455 wResult = GLOB_LLD_Read_Page_Main(pData, Block, Page, PageCount);
1456 if (wResult == FAIL)
1457 return wResult;
1458
1459 if (DeviceInfo.MLCDevice) {
1460 g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock]++;
1461 if (g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock] >=
1462 MAX_READ_COUNTER)
1463 FTL_Read_Disturbance(Block);
1464 if (g_cBlockTableStatus != IN_PROGRESS_BLOCK_TABLE) {
1465 g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE;
1466 FTL_Write_IN_Progress_Block_Table_Page();
1467 }
1468 }
1469#endif
1470 return wResult;
1471}
1472
1473/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
1474* Function: FTL_Cache_Write_All
1475* Inputs: pointer to cache in sys memory
1476* address of free block in flash
1477* Outputs: PASS=0 / FAIL=1
1478* Description: writes all the pages of the block in cache to flash
1479*
1480* NOTE:need to make sure this works ok when cache is limited
1481* to a partial block. This is where copy-back would be
1482* activated. This would require knowing which pages in the
1483* cached block are clean/dirty.Right now we only know if
1484* the whole block is clean/dirty.
1485*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
1486static int FTL_Cache_Write_All(u8 *pData, u64 blk_addr)
1487{
1488 u16 wResult = PASS;
1489 u32 Block;
1490 u16 Page;
1491 u16 PageCount;
1492
1493 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
1494 __FILE__, __LINE__, __func__);
1495
1496 nand_dbg_print(NAND_DBG_DEBUG, "This block %d going to be written "
1497 "on %d\n", cache_block_to_write,
1498 (u32)(blk_addr >> DeviceInfo.nBitsInBlockDataSize));
1499
1500 Block = BLK_FROM_ADDR(blk_addr);
1501 Page = PAGE_FROM_ADDR(blk_addr, Block);
1502 PageCount = Cache.pages_per_item;
1503
1504#if CMD_DMA
1505 if (FAIL == GLOB_LLD_Write_Page_Main_cdma(pData,
1506 Block, Page, PageCount)) {
1507 nand_dbg_print(NAND_DBG_WARN,
1508 "NAND Program fail in %s, Line %d, "
1509 "Function: %s, new Bad Block %d generated! "
1510 "Need Bad Block replacing.\n",
1511 __FILE__, __LINE__, __func__, Block);
1512 wResult = FAIL;
1513 }
1514 ftl_cmd_cnt++;
1515#else
1516 if (FAIL == GLOB_LLD_Write_Page_Main(pData, Block, Page, PageCount)) {
1517 nand_dbg_print(NAND_DBG_WARN, "NAND Program fail in %s,"
1518 " Line %d, Function %s, new Bad Block %d generated!"
1519 "Need Bad Block replacing.\n",
1520 __FILE__, __LINE__, __func__, Block);
1521 wResult = FAIL;
1522 }
1523#endif
1524 return wResult;
1525}
1526
1527/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
1528* Function: FTL_Copy_Block
1529* Inputs: source block address
1530* Destination block address
1531* Outputs: PASS=0 / FAIL=1
1532* Description: used only for static wear leveling to move the block
1533* containing static data to new blocks(more worn)
1534*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
1535int FTL_Copy_Block(u64 old_blk_addr, u64 blk_addr)
1536{
1537 int i, r1, r2, wResult = PASS;
1538
1539 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
1540 __FILE__, __LINE__, __func__);
1541
1542 for (i = 0; i < DeviceInfo.wPagesPerBlock; i += Cache.pages_per_item) {
1543 r1 = FTL_Cache_Read_All(g_pTempBuf, old_blk_addr +
1544 i * DeviceInfo.wPageDataSize);
1545 r2 = FTL_Cache_Write_All(g_pTempBuf, blk_addr +
1546 i * DeviceInfo.wPageDataSize);
1547 if ((ERR == r1) || (FAIL == r2)) {
1548 wResult = FAIL;
1549 break;
1550 }
1551 }
1552
1553 return wResult;
1554}
1555
1556/* Search the block table to find out the least wear block and then return it */
1557static u32 find_least_worn_blk_for_l2_cache(void)
1558{
1559 int i;
1560 u32 *pbt = (u32 *)g_pBlockTable;
1561 u8 least_wear_cnt = MAX_BYTE_VALUE;
1562 u32 least_wear_blk_idx = MAX_U32_VALUE;
1563 u32 phy_idx;
1564
1565 for (i = 0; i < DeviceInfo.wDataBlockNum; i++) {
1566 if (IS_SPARE_BLOCK(i)) {
1567 phy_idx = (u32)((~BAD_BLOCK) & pbt[i]);
1568 if (phy_idx > DeviceInfo.wSpectraEndBlock)
1569 printk(KERN_ERR "find_least_worn_blk_for_l2_cache: "
1570 "Too big phy block num (%d)\n", phy_idx);
1571 if (g_pWearCounter[phy_idx -DeviceInfo.wSpectraStartBlock] < least_wear_cnt) {
1572 least_wear_cnt = g_pWearCounter[phy_idx - DeviceInfo.wSpectraStartBlock];
1573 least_wear_blk_idx = i;
1574 }
1575 }
1576 }
1577
1578 nand_dbg_print(NAND_DBG_WARN,
1579 "find_least_worn_blk_for_l2_cache: "
1580 "find block %d with least worn counter (%d)\n",
1581 least_wear_blk_idx, least_wear_cnt);
1582
1583 return least_wear_blk_idx;
1584}
1585
1586
1587
1588/* Get blocks for Level2 Cache */
1589static int get_l2_cache_blks(void)
1590{
1591 int n;
1592 u32 blk;
1593 u32 *pbt = (u32 *)g_pBlockTable;
1594
1595 for (n = 0; n < BLK_NUM_FOR_L2_CACHE; n++) {
1596 blk = find_least_worn_blk_for_l2_cache();
1597 if (blk >= DeviceInfo.wDataBlockNum) {
1598 nand_dbg_print(NAND_DBG_WARN,
1599 "find_least_worn_blk_for_l2_cache: "
1600 "No enough free NAND blocks (n: %d) for L2 Cache!\n", n);
1601 return FAIL;
1602 }
1603 /* Tag the free block as discard in block table */
1604 pbt[blk] = (pbt[blk] & (~BAD_BLOCK)) | DISCARD_BLOCK;
1605 /* Add the free block to the L2 Cache block array */
1606 cache_l2.blk_array[n] = pbt[blk] & (~BAD_BLOCK);
1607 }
1608
1609 return PASS;
1610}
1611
1612static int erase_l2_cache_blocks(void)
1613{
1614 int i, ret = PASS;
1615 u32 pblk, lblk = BAD_BLOCK;
1616 u64 addr;
1617 u32 *pbt = (u32 *)g_pBlockTable;
1618
1619 nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
1620 __FILE__, __LINE__, __func__);
1621
1622 for (i = 0; i < BLK_NUM_FOR_L2_CACHE; i++) {
1623 pblk = cache_l2.blk_array[i];
1624
1625 /* If the L2 cache block is invalid, then just skip it */
1626 if (MAX_U32_VALUE == pblk)
1627 continue;
1628
1629 BUG_ON(pblk > DeviceInfo.wSpectraEndBlock);
1630
1631 addr = (u64)pblk << DeviceInfo.nBitsInBlockDataSize;
1632 if (PASS == GLOB_FTL_Block_Erase(addr)) {
1633 /* Get logical block number of the erased block */
1634 lblk = FTL_Get_Block_Index(pblk);
1635 BUG_ON(BAD_BLOCK == lblk);
1636 /* Tag it as free in the block table */
1637 pbt[lblk] &= (u32)(~DISCARD_BLOCK);
1638 pbt[lblk] |= (u32)(SPARE_BLOCK);
1639 } else {
1640 MARK_BLOCK_AS_BAD(pbt[lblk]);
1641 ret = ERR;
1642 }
1643 }
1644
1645 return ret;
1646}
1647
1648/*
1649 * Merge the valid data page in the L2 cache blocks into NAND.
1650*/
1651static int flush_l2_cache(void)
1652{
1653 struct list_head *p;
1654 struct spectra_l2_cache_list *pnd, *tmp_pnd;
1655 u32 *pbt = (u32 *)g_pBlockTable;
1656 u32 phy_blk, l2_blk;
1657 u64 addr;
1658 u16 l2_page;
1659 int i, ret = PASS;
1660
1661 nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
1662 __FILE__, __LINE__, __func__);
1663
1664 if (list_empty(&cache_l2.table.list)) /* No data to flush */
1665 return ret;
1666
1667 //dump_cache_l2_table();
1668
1669 if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) {
1670 g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE;
1671 FTL_Write_IN_Progress_Block_Table_Page();
1672 }
1673
1674 list_for_each(p, &cache_l2.table.list) {
1675 pnd = list_entry(p, struct spectra_l2_cache_list, list);
1676 if (IS_SPARE_BLOCK(pnd->logical_blk_num) ||
1677 IS_BAD_BLOCK(pnd->logical_blk_num) ||
1678 IS_DISCARDED_BLOCK(pnd->logical_blk_num)) {
1679 nand_dbg_print(NAND_DBG_WARN, "%s, Line %d\n", __FILE__, __LINE__);
1680 memset(cache_l2_blk_buf, 0xff, DeviceInfo.wPagesPerBlock * DeviceInfo.wPageDataSize);
1681 } else {
1682 nand_dbg_print(NAND_DBG_WARN, "%s, Line %d\n", __FILE__, __LINE__);
1683 phy_blk = pbt[pnd->logical_blk_num] & (~BAD_BLOCK);
1684 ret = GLOB_LLD_Read_Page_Main(cache_l2_blk_buf,
1685 phy_blk, 0, DeviceInfo.wPagesPerBlock);
1686 if (ret == FAIL) {
1687 printk(KERN_ERR "Read NAND page fail in %s, Line %d\n", __FILE__, __LINE__);
1688 }
1689 }
1690
1691 for (i = 0; i < DeviceInfo.wPagesPerBlock; i++) {
1692 if (pnd->pages_array[i] != MAX_U32_VALUE) {
1693 l2_blk = cache_l2.blk_array[(pnd->pages_array[i] >> 16) & 0xffff];
1694 l2_page = pnd->pages_array[i] & 0xffff;
1695 ret = GLOB_LLD_Read_Page_Main(cache_l2_page_buf, l2_blk, l2_page, 1);
1696 if (ret == FAIL) {
1697 printk(KERN_ERR "Read NAND page fail in %s, Line %d\n", __FILE__, __LINE__);
1698 }
1699 memcpy(cache_l2_blk_buf + i * DeviceInfo.wPageDataSize, cache_l2_page_buf, DeviceInfo.wPageDataSize);
1700 }
1701 }
1702
1703 /* Find a free block and tag the original block as discarded */
1704 addr = (u64)pnd->logical_blk_num << DeviceInfo.nBitsInBlockDataSize;
1705 ret = FTL_Replace_Block(addr);
1706 if (ret == FAIL) {
1707 printk(KERN_ERR "FTL_Replace_Block fail in %s, Line %d\n", __FILE__, __LINE__);
1708 }
1709
1710 /* Write back the updated data into NAND */
1711 phy_blk = pbt[pnd->logical_blk_num] & (~BAD_BLOCK);
1712 if (FAIL == GLOB_LLD_Write_Page_Main(cache_l2_blk_buf, phy_blk, 0, DeviceInfo.wPagesPerBlock)) {
1713 nand_dbg_print(NAND_DBG_WARN,
1714 "Program NAND block %d fail in %s, Line %d\n",
1715 phy_blk, __FILE__, __LINE__);
1716 /* This may not be really a bad block. So just tag it as discarded. */
1717 /* Then it has a chance to be erased when garbage collection. */
1718 /* If it is really bad, then the erase will fail and it will be marked */
1719 /* as bad then. Otherwise it will be marked as free and can be used again */
1720 MARK_BLK_AS_DISCARD(pbt[pnd->logical_blk_num]);
1721 /* Find another free block and write it again */
1722 FTL_Replace_Block(addr);
1723 phy_blk = pbt[pnd->logical_blk_num] & (~BAD_BLOCK);
1724 if (FAIL == GLOB_LLD_Write_Page_Main(cache_l2_blk_buf, phy_blk, 0, DeviceInfo.wPagesPerBlock)) {
1725 printk(KERN_ERR "Failed to write back block %d when flush L2 cache."
1726 "Some data will be lost!\n", phy_blk);
1727 MARK_BLOCK_AS_BAD(pbt[pnd->logical_blk_num]);
1728 }
1729 } else {
1730 /* tag the new free block as used block */
1731 pbt[pnd->logical_blk_num] &= (~SPARE_BLOCK);
1732 }
1733 }
1734
1735 /* Destroy the L2 Cache table and free the memory of all nodes */
1736 list_for_each_entry_safe(pnd, tmp_pnd, &cache_l2.table.list, list) {
1737 list_del(&pnd->list);
1738 kfree(pnd);
1739 }
1740
1741 /* Erase discard L2 cache blocks */
1742 if (erase_l2_cache_blocks() != PASS)
1743 nand_dbg_print(NAND_DBG_WARN,
1744 " Erase L2 cache blocks error in %s, Line %d\n",
1745 __FILE__, __LINE__);
1746
1747 /* Init the Level2 Cache data structure */
1748 for (i = 0; i < BLK_NUM_FOR_L2_CACHE; i++)
1749 cache_l2.blk_array[i] = MAX_U32_VALUE;
1750 cache_l2.cur_blk_idx = 0;
1751 cache_l2.cur_page_num = 0;
1752 INIT_LIST_HEAD(&cache_l2.table.list);
1753 cache_l2.table.logical_blk_num = MAX_U32_VALUE;
1754
1755 return ret;
1756}
1757
1758/*
1759 * Write back a changed victim cache item to the Level2 Cache
1760 * and update the L2 Cache table to map the change.
1761 * If the L2 Cache is full, then start to do the L2 Cache flush.
1762*/
1763static int write_back_to_l2_cache(u8 *buf, u64 logical_addr)
1764{
1765 u32 logical_blk_num;
1766 u16 logical_page_num;
1767 struct list_head *p;
1768 struct spectra_l2_cache_list *pnd, *pnd_new;
1769 u32 node_size;
1770 int i, found;
1771
1772 nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
1773 __FILE__, __LINE__, __func__);
1774
1775 /*
1776 * If Level2 Cache table is empty, then it means either:
1777 * 1. This is the first time that the function called after FTL_init
1778 * or
1779 * 2. The Level2 Cache has just been flushed
1780 *
1781 * So, 'steal' some free blocks from NAND for L2 Cache using
1782 * by just mask them as discard in the block table
1783 */
1784 if (list_empty(&cache_l2.table.list)) {
1785 BUG_ON(cache_l2.cur_blk_idx != 0);
1786 BUG_ON(cache_l2.cur_page_num!= 0);
1787 BUG_ON(cache_l2.table.logical_blk_num != MAX_U32_VALUE);
1788 if (FAIL == get_l2_cache_blks()) {
1789 GLOB_FTL_Garbage_Collection();
1790 if (FAIL == get_l2_cache_blks()) {
1791 printk(KERN_ALERT "Fail to get L2 cache blks!\n");
1792 return FAIL;
1793 }
1794 }
1795 }
1796
1797 logical_blk_num = BLK_FROM_ADDR(logical_addr);
1798 logical_page_num = PAGE_FROM_ADDR(logical_addr, logical_blk_num);
1799 BUG_ON(logical_blk_num == MAX_U32_VALUE);
1800
1801 /* Write the cache item data into the current position of L2 Cache */
1802#if CMD_DMA
1803 /*
1804 * TODO
1805 */
1806#else
1807 if (FAIL == GLOB_LLD_Write_Page_Main(buf,
1808 cache_l2.blk_array[cache_l2.cur_blk_idx],
1809 cache_l2.cur_page_num, 1)) {
1810 nand_dbg_print(NAND_DBG_WARN, "NAND Program fail in "
1811 "%s, Line %d, new Bad Block %d generated!\n",
1812 __FILE__, __LINE__,
1813 cache_l2.blk_array[cache_l2.cur_blk_idx]);
1814
1815 /* TODO: tag the current block as bad and try again */
1816
1817 return FAIL;
1818 }
1819#endif
1820
1821 /*
1822 * Update the L2 Cache table.
1823 *
1824 * First seaching in the table to see whether the logical block
1825 * has been mapped. If not, then kmalloc a new node for the
1826 * logical block, fill data, and then insert it to the list.
1827 * Otherwise, just update the mapped node directly.
1828 */
1829 found = 0;
1830 list_for_each(p, &cache_l2.table.list) {
1831 pnd = list_entry(p, struct spectra_l2_cache_list, list);
1832 if (pnd->logical_blk_num == logical_blk_num) {
1833 pnd->pages_array[logical_page_num] =
1834 (cache_l2.cur_blk_idx << 16) |
1835 cache_l2.cur_page_num;
1836 found = 1;
1837 break;
1838 }
1839 }
1840 if (!found) { /* Create new node for the logical block here */
1841
1842 /* The logical pages to physical pages map array is
1843 * located at the end of struct spectra_l2_cache_list.
1844 */
1845 node_size = sizeof(struct spectra_l2_cache_list) +
1846 sizeof(u32) * DeviceInfo.wPagesPerBlock;
1847 pnd_new = kmalloc(node_size, GFP_ATOMIC);
1848 if (!pnd_new) {
1849 printk(KERN_ERR "Failed to kmalloc in %s Line %d\n",
1850 __FILE__, __LINE__);
1851 /*
1852 * TODO: Need to flush all the L2 cache into NAND ASAP
1853 * since no memory available here
1854 */
1855 }
1856 pnd_new->logical_blk_num = logical_blk_num;
1857 for (i = 0; i < DeviceInfo.wPagesPerBlock; i++)
1858 pnd_new->pages_array[i] = MAX_U32_VALUE;
1859 pnd_new->pages_array[logical_page_num] =
1860 (cache_l2.cur_blk_idx << 16) | cache_l2.cur_page_num;
1861 list_add(&pnd_new->list, &cache_l2.table.list);
1862 }
1863
1864 /* Increasing the current position pointer of the L2 Cache */
1865 cache_l2.cur_page_num++;
1866 if (cache_l2.cur_page_num >= DeviceInfo.wPagesPerBlock) {
1867 cache_l2.cur_blk_idx++;
1868 if (cache_l2.cur_blk_idx >= BLK_NUM_FOR_L2_CACHE) {
1869 /* The L2 Cache is full. Need to flush it now */
1870 nand_dbg_print(NAND_DBG_WARN,
1871 "L2 Cache is full, will start to flush it\n");
1872 flush_l2_cache();
1873 } else {
1874 cache_l2.cur_page_num = 0;
1875 }
1876 }
1877
1878 return PASS;
1879}
1880
1881/*
1882 * Search in the Level2 Cache table to find the cache item.
1883 * If find, read the data from the NAND page of L2 Cache,
1884 * Otherwise, return FAIL.
1885 */
1886static int search_l2_cache(u8 *buf, u64 logical_addr)
1887{
1888 u32 logical_blk_num;
1889 u16 logical_page_num;
1890 struct list_head *p;
1891 struct spectra_l2_cache_list *pnd;
1892 u32 tmp = MAX_U32_VALUE;
1893 u32 phy_blk;
1894 u16 phy_page;
1895 int ret = FAIL;
1896
1897 logical_blk_num = BLK_FROM_ADDR(logical_addr);
1898 logical_page_num = PAGE_FROM_ADDR(logical_addr, logical_blk_num);
1899
1900 list_for_each(p, &cache_l2.table.list) {
1901 pnd = list_entry(p, struct spectra_l2_cache_list, list);
1902 if (pnd->logical_blk_num == logical_blk_num) {
1903 tmp = pnd->pages_array[logical_page_num];
1904 break;
1905 }
1906 }
1907
1908 if (tmp != MAX_U32_VALUE) { /* Found valid map */
1909 phy_blk = cache_l2.blk_array[(tmp >> 16) & 0xFFFF];
1910 phy_page = tmp & 0xFFFF;
1911#if CMD_DMA
1912 /* TODO */
1913#else
1914 ret = GLOB_LLD_Read_Page_Main(buf, phy_blk, phy_page, 1);
1915#endif
1916 }
1917
1918 return ret;
1919}
1920
1921/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
1922* Function: FTL_Cache_Write_Page
1923* Inputs: Pointer to buffer, page address, cache block number
1924* Outputs: PASS=0 / FAIL=1
1925* Description: It writes the data in Cache Block
1926*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
1927static void FTL_Cache_Write_Page(u8 *pData, u64 page_addr,
1928 u8 cache_blk, u16 flag)
1929{
1930 u8 *pDest;
1931 u64 addr;
1932
1933 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
1934 __FILE__, __LINE__, __func__);
1935
1936 addr = Cache.array[cache_blk].address;
1937 pDest = Cache.array[cache_blk].buf;
1938
1939 pDest += (unsigned long)(page_addr - addr);
1940 Cache.array[cache_blk].changed = SET;
1941#if CMD_DMA
1942#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
1943 int_cache[ftl_cmd_cnt].item = cache_blk;
1944 int_cache[ftl_cmd_cnt].cache.address =
1945 Cache.array[cache_blk].address;
1946 int_cache[ftl_cmd_cnt].cache.changed =
1947 Cache.array[cache_blk].changed;
1948#endif
1949 GLOB_LLD_MemCopy_CMD(pDest, pData, DeviceInfo.wPageDataSize, flag);
1950 ftl_cmd_cnt++;
1951#else
1952 memcpy(pDest, pData, DeviceInfo.wPageDataSize);
1953#endif
1954 if (Cache.array[cache_blk].use_cnt < MAX_WORD_VALUE)
1955 Cache.array[cache_blk].use_cnt++;
1956}
1957
1958/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
1959* Function: FTL_Cache_Write
1960* Inputs: none
1961* Outputs: PASS=0 / FAIL=1
1962* Description: It writes least frequently used Cache block to flash if it
1963* has been changed
1964*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
1965static int FTL_Cache_Write(void)
1966{
1967 int i, bResult = PASS;
1968 u16 bNO, least_count = 0xFFFF;
1969
1970 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
1971 __FILE__, __LINE__, __func__);
1972
1973 FTL_Calculate_LRU();
1974
1975 bNO = Cache.LRU;
1976 nand_dbg_print(NAND_DBG_DEBUG, "FTL_Cache_Write: "
1977 "Least used cache block is %d\n", bNO);
1978
1979 if (Cache.array[bNO].changed != SET)
1980 return bResult;
1981
1982 nand_dbg_print(NAND_DBG_DEBUG, "FTL_Cache_Write: Cache"
1983 " Block %d containing logical block %d is dirty\n",
1984 bNO,
1985 (u32)(Cache.array[bNO].address >>
1986 DeviceInfo.nBitsInBlockDataSize));
1987#if CMD_DMA
1988#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
1989 int_cache[ftl_cmd_cnt].item = bNO;
1990 int_cache[ftl_cmd_cnt].cache.address =
1991 Cache.array[bNO].address;
1992 int_cache[ftl_cmd_cnt].cache.changed = CLEAR;
1993#endif
1994#endif
1995 bResult = write_back_to_l2_cache(Cache.array[bNO].buf,
1996 Cache.array[bNO].address);
1997 if (bResult != ERR)
1998 Cache.array[bNO].changed = CLEAR;
1999
2000 least_count = Cache.array[bNO].use_cnt;
2001
2002 for (i = 0; i < CACHE_ITEM_NUM; i++) {
2003 if (i == bNO)
2004 continue;
2005 if (Cache.array[i].use_cnt > 0)
2006 Cache.array[i].use_cnt -= least_count;
2007 }
2008
2009 return bResult;
2010}
2011
2012/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
2013* Function: FTL_Cache_Read
2014* Inputs: Page address
2015* Outputs: PASS=0 / FAIL=1
2016* Description: It reads the block from device in Cache Block
2017* Set the LRU count to 1
2018* Mark the Cache Block as clean
2019*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
2020static int FTL_Cache_Read(u64 logical_addr)
2021{
2022 u64 item_addr, phy_addr;
2023 u16 num;
2024 int ret;
2025
2026 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
2027 __FILE__, __LINE__, __func__);
2028
2029 num = Cache.LRU; /* The LRU cache item will be overwritten */
2030
2031 item_addr = (u64)GLOB_u64_Div(logical_addr, Cache.cache_item_size) *
2032 Cache.cache_item_size;
2033 Cache.array[num].address = item_addr;
2034 Cache.array[num].use_cnt = 1;
2035 Cache.array[num].changed = CLEAR;
2036
2037#if CMD_DMA
2038#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
2039 int_cache[ftl_cmd_cnt].item = num;
2040 int_cache[ftl_cmd_cnt].cache.address =
2041 Cache.array[num].address;
2042 int_cache[ftl_cmd_cnt].cache.changed =
2043 Cache.array[num].changed;
2044#endif
2045#endif
2046 /*
2047 * Search in L2 Cache. If hit, fill data into L1 Cache item buffer,
2048 * Otherwise, read it from NAND
2049 */
2050 ret = search_l2_cache(Cache.array[num].buf, logical_addr);
2051 if (PASS == ret) /* Hit in L2 Cache */
2052 return ret;
2053
2054 /* Compute the physical start address of NAND device according to */
2055 /* the logical start address of the cache item (LRU cache item) */
2056 phy_addr = FTL_Get_Physical_Block_Addr(item_addr) +
2057 GLOB_u64_Remainder(item_addr, 2);
2058
2059 return FTL_Cache_Read_All(Cache.array[num].buf, phy_addr);
2060}
2061
2062/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
2063* Function: FTL_Check_Block_Table
2064* Inputs: ?
2065* Outputs: PASS=0 / FAIL=1
2066* Description: It checks the correctness of each block table entry
2067*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
2068static int FTL_Check_Block_Table(int wOldTable)
2069{
2070 u32 i;
2071 int wResult = PASS;
2072 u32 blk_idx;
2073 u32 *pbt = (u32 *)g_pBlockTable;
2074 u8 *pFlag = flag_check_blk_table;
2075
2076 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
2077 __FILE__, __LINE__, __func__);
2078
2079 if (NULL != pFlag) {
2080 memset(pFlag, FAIL, DeviceInfo.wDataBlockNum);
2081 for (i = 0; i < DeviceInfo.wDataBlockNum; i++) {
2082 blk_idx = (u32)(pbt[i] & (~BAD_BLOCK));
2083
2084 /*
2085 * 20081006/KBV - Changed to pFlag[i] reference
2086 * to avoid buffer overflow
2087 */
2088
2089 /*
2090 * 2008-10-20 Yunpeng Note: This change avoid
2091 * buffer overflow, but changed function of
2092 * the code, so it should be re-write later
2093 */
2094 if ((blk_idx > DeviceInfo.wSpectraEndBlock) ||
2095 PASS == pFlag[i]) {
2096 wResult = FAIL;
2097 break;
2098 } else {
2099 pFlag[i] = PASS;
2100 }
2101 }
2102 }
2103
2104 return wResult;
2105}
2106
2107
2108/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
2109* Function: FTL_Write_Block_Table
2110* Inputs: flasg
2111* Outputs: 0=Block Table was updated. No write done. 1=Block write needs to
2112* happen. -1 Error
2113* Description: It writes the block table
2114* Block table always mapped to LBA 0 which inturn mapped
2115* to any physical block
2116*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
2117static int FTL_Write_Block_Table(int wForce)
2118{
2119 u32 *pbt = (u32 *)g_pBlockTable;
2120 int wSuccess = PASS;
2121 u32 wTempBlockTableIndex;
2122 u16 bt_pages, new_bt_offset;
2123 u8 blockchangeoccured = 0;
2124
2125 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
2126 __FILE__, __LINE__, __func__);
2127
2128 bt_pages = FTL_Get_Block_Table_Flash_Size_Pages();
2129
2130 if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus)
2131 return 0;
2132
2133 if (PASS == wForce) {
2134 g_wBlockTableOffset =
2135 (u16)(DeviceInfo.wPagesPerBlock - bt_pages);
2136#if CMD_DMA
2137 p_BTableChangesDelta =
2138 (struct BTableChangesDelta *)g_pBTDelta_Free;
2139 g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
2140
2141 p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt;
2142 p_BTableChangesDelta->g_wBlockTableOffset =
2143 g_wBlockTableOffset;
2144 p_BTableChangesDelta->ValidFields = 0x01;
2145#endif
2146 }
2147
2148 nand_dbg_print(NAND_DBG_DEBUG,
2149 "Inside FTL_Write_Block_Table: block %d Page:%d\n",
2150 g_wBlockTableIndex, g_wBlockTableOffset);
2151
2152 do {
2153 new_bt_offset = g_wBlockTableOffset + bt_pages + 1;
2154 if ((0 == (new_bt_offset % DeviceInfo.wPagesPerBlock)) ||
2155 (new_bt_offset > DeviceInfo.wPagesPerBlock) ||
2156 (FAIL == wSuccess)) {
2157 wTempBlockTableIndex = FTL_Replace_Block_Table();
2158 if (BAD_BLOCK == wTempBlockTableIndex)
2159 return ERR;
2160 if (!blockchangeoccured) {
2161 bt_block_changed = 1;
2162 blockchangeoccured = 1;
2163 }
2164
2165 g_wBlockTableIndex = wTempBlockTableIndex;
2166 g_wBlockTableOffset = 0;
2167 pbt[BLOCK_TABLE_INDEX] = g_wBlockTableIndex;
2168#if CMD_DMA
2169 p_BTableChangesDelta =
2170 (struct BTableChangesDelta *)g_pBTDelta_Free;
2171 g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
2172
2173 p_BTableChangesDelta->ftl_cmd_cnt =
2174 ftl_cmd_cnt;
2175 p_BTableChangesDelta->g_wBlockTableOffset =
2176 g_wBlockTableOffset;
2177 p_BTableChangesDelta->g_wBlockTableIndex =
2178 g_wBlockTableIndex;
2179 p_BTableChangesDelta->ValidFields = 0x03;
2180
2181 p_BTableChangesDelta =
2182 (struct BTableChangesDelta *)g_pBTDelta_Free;
2183 g_pBTDelta_Free +=
2184 sizeof(struct BTableChangesDelta);
2185
2186 p_BTableChangesDelta->ftl_cmd_cnt =
2187 ftl_cmd_cnt;
2188 p_BTableChangesDelta->BT_Index =
2189 BLOCK_TABLE_INDEX;
2190 p_BTableChangesDelta->BT_Entry_Value =
2191 pbt[BLOCK_TABLE_INDEX];
2192 p_BTableChangesDelta->ValidFields = 0x0C;
2193#endif
2194 }
2195
2196 wSuccess = FTL_Write_Block_Table_Data();
2197 if (FAIL == wSuccess)
2198 MARK_BLOCK_AS_BAD(pbt[BLOCK_TABLE_INDEX]);
2199 } while (FAIL == wSuccess);
2200
2201 g_cBlockTableStatus = CURRENT_BLOCK_TABLE;
2202
2203 return 1;
2204}
2205
2206static int force_format_nand(void)
2207{
2208 u32 i;
2209
2210 /* Force erase the whole unprotected physical partiton of NAND */
2211 printk(KERN_ALERT "Start to force erase whole NAND device ...\n");
2212 printk(KERN_ALERT "From phyical block %d to %d\n",
2213 DeviceInfo.wSpectraStartBlock, DeviceInfo.wSpectraEndBlock);
2214 for (i = DeviceInfo.wSpectraStartBlock; i <= DeviceInfo.wSpectraEndBlock; i++) {
2215 if (GLOB_LLD_Erase_Block(i))
2216 printk(KERN_ERR "Failed to force erase NAND block %d\n", i);
2217 }
2218 printk(KERN_ALERT "Force Erase ends. Please reboot the system ...\n");
2219 while(1);
2220
2221 return PASS;
2222}
2223
2224int GLOB_FTL_Flash_Format(void)
2225{
2226 //return FTL_Format_Flash(1);
2227 return force_format_nand();
2228
2229}
2230
2231/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
2232* Function: FTL_Search_Block_Table_IN_Block
2233* Inputs: Block Number
2234* Pointer to page
2235* Outputs: PASS / FAIL
2236* Page contatining the block table
2237* Description: It searches the block table in the block
2238* passed as an argument.
2239*
2240*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
2241static int FTL_Search_Block_Table_IN_Block(u32 BT_Block,
2242 u8 BT_Tag, u16 *Page)
2243{
2244 u16 i, j, k;
2245 u16 Result = PASS;
2246 u16 Last_IPF = 0;
2247 u8 BT_Found = 0;
2248 u8 *tagarray;
2249 u8 *tempbuf = tmp_buf_search_bt_in_block;
2250 u8 *pSpareBuf = spare_buf_search_bt_in_block;
2251 u8 *pSpareBufBTLastPage = spare_buf_bt_search_bt_in_block;
2252 u8 bt_flag_last_page = 0xFF;
2253 u8 search_in_previous_pages = 0;
2254 u16 bt_pages;
2255
2256 nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
2257 __FILE__, __LINE__, __func__);
2258
2259 nand_dbg_print(NAND_DBG_DEBUG,
2260 "Searching block table in %u block\n",
2261 (unsigned int)BT_Block);
2262
2263 bt_pages = FTL_Get_Block_Table_Flash_Size_Pages();
2264
2265 for (i = bt_pages; i < DeviceInfo.wPagesPerBlock;
2266 i += (bt_pages + 1)) {
2267 nand_dbg_print(NAND_DBG_DEBUG,
2268 "Searching last IPF: %d\n", i);
2269 Result = GLOB_LLD_Read_Page_Main_Polling(tempbuf,
2270 BT_Block, i, 1);
2271
2272 if (0 == memcmp(tempbuf, g_pIPF, DeviceInfo.wPageDataSize)) {
2273 if ((i + bt_pages + 1) < DeviceInfo.wPagesPerBlock) {
2274 continue;
2275 } else {
2276 search_in_previous_pages = 1;
2277 Last_IPF = i;
2278 }
2279 }
2280
2281 if (!search_in_previous_pages) {
2282 if (i != bt_pages) {
2283 i -= (bt_pages + 1);
2284 Last_IPF = i;
2285 }
2286 }
2287
2288 if (0 == Last_IPF)
2289 break;
2290
2291 if (!search_in_previous_pages) {
2292 i = i + 1;
2293 nand_dbg_print(NAND_DBG_DEBUG,
2294 "Reading the spare area of Block %u Page %u",
2295 (unsigned int)BT_Block, i);
2296 Result = GLOB_LLD_Read_Page_Spare(pSpareBuf,
2297 BT_Block, i, 1);
2298 nand_dbg_print(NAND_DBG_DEBUG,
2299 "Reading the spare area of Block %u Page %u",
2300 (unsigned int)BT_Block, i + bt_pages - 1);
2301 Result = GLOB_LLD_Read_Page_Spare(pSpareBufBTLastPage,
2302 BT_Block, i + bt_pages - 1, 1);
2303
2304 k = 0;
2305 j = FTL_Extract_Block_Table_Tag(pSpareBuf, &tagarray);
2306 if (j) {
2307 for (; k < j; k++) {
2308 if (tagarray[k] == BT_Tag)
2309 break;
2310 }
2311 }
2312
2313 if (k < j)
2314 bt_flag = tagarray[k];
2315 else
2316 Result = FAIL;
2317
2318 if (Result == PASS) {
2319 k = 0;
2320 j = FTL_Extract_Block_Table_Tag(
2321 pSpareBufBTLastPage, &tagarray);
2322 if (j) {
2323 for (; k < j; k++) {
2324 if (tagarray[k] == BT_Tag)
2325 break;
2326 }
2327 }
2328
2329 if (k < j)
2330 bt_flag_last_page = tagarray[k];
2331 else
2332 Result = FAIL;
2333
2334 if (Result == PASS) {
2335 if (bt_flag == bt_flag_last_page) {
2336 nand_dbg_print(NAND_DBG_DEBUG,
2337 "Block table is found"
2338 " in page after IPF "
2339 "at block %d "
2340 "page %d\n",
2341 (int)BT_Block, i);
2342 BT_Found = 1;
2343 *Page = i;
2344 g_cBlockTableStatus =
2345 CURRENT_BLOCK_TABLE;
2346 break;
2347 } else {
2348 Result = FAIL;
2349 }
2350 }
2351 }
2352 }
2353
2354 if (search_in_previous_pages)
2355 i = i - bt_pages;
2356 else
2357 i = i - (bt_pages + 1);
2358
2359 Result = PASS;
2360
2361 nand_dbg_print(NAND_DBG_DEBUG,
2362 "Reading the spare area of Block %d Page %d",
2363 (int)BT_Block, i);
2364
2365 Result = GLOB_LLD_Read_Page_Spare(pSpareBuf, BT_Block, i, 1);
2366 nand_dbg_print(NAND_DBG_DEBUG,
2367 "Reading the spare area of Block %u Page %u",
2368 (unsigned int)BT_Block, i + bt_pages - 1);
2369
2370 Result = GLOB_LLD_Read_Page_Spare(pSpareBufBTLastPage,
2371 BT_Block, i + bt_pages - 1, 1);
2372
2373 k = 0;
2374 j = FTL_Extract_Block_Table_Tag(pSpareBuf, &tagarray);
2375 if (j) {
2376 for (; k < j; k++) {
2377 if (tagarray[k] == BT_Tag)
2378 break;
2379 }
2380 }
2381
2382 if (k < j)
2383 bt_flag = tagarray[k];
2384 else
2385 Result = FAIL;
2386
2387 if (Result == PASS) {
2388 k = 0;
2389 j = FTL_Extract_Block_Table_Tag(pSpareBufBTLastPage,
2390 &tagarray);
2391 if (j) {
2392 for (; k < j; k++) {
2393 if (tagarray[k] == BT_Tag)
2394 break;
2395 }
2396 }
2397
2398 if (k < j) {
2399 bt_flag_last_page = tagarray[k];
2400 } else {
2401 Result = FAIL;
2402 break;
2403 }
2404
2405 if (Result == PASS) {
2406 if (bt_flag == bt_flag_last_page) {
2407 nand_dbg_print(NAND_DBG_DEBUG,
2408 "Block table is found "
2409 "in page prior to IPF "
2410 "at block %u page %d\n",
2411 (unsigned int)BT_Block, i);
2412 BT_Found = 1;
2413 *Page = i;
2414 g_cBlockTableStatus =
2415 IN_PROGRESS_BLOCK_TABLE;
2416 break;
2417 } else {
2418 Result = FAIL;
2419 break;
2420 }
2421 }
2422 }
2423 }
2424
2425 if (Result == FAIL) {
2426 if ((Last_IPF > bt_pages) && (i < Last_IPF) && (!BT_Found)) {
2427 BT_Found = 1;
2428 *Page = i - (bt_pages + 1);
2429 }
2430 if ((Last_IPF == bt_pages) && (i < Last_IPF) && (!BT_Found))
2431 goto func_return;
2432 }
2433
2434 if (Last_IPF == 0) {
2435 i = 0;
2436 Result = PASS;
2437 nand_dbg_print(NAND_DBG_DEBUG, "Reading the spare area of "
2438 "Block %u Page %u", (unsigned int)BT_Block, i);
2439
2440 Result = GLOB_LLD_Read_Page_Spare(pSpareBuf, BT_Block, i, 1);
2441 nand_dbg_print(NAND_DBG_DEBUG,
2442 "Reading the spare area of Block %u Page %u",
2443 (unsigned int)BT_Block, i + bt_pages - 1);
2444 Result = GLOB_LLD_Read_Page_Spare(pSpareBufBTLastPage,
2445 BT_Block, i + bt_pages - 1, 1);
2446
2447 k = 0;
2448 j = FTL_Extract_Block_Table_Tag(pSpareBuf, &tagarray);
2449 if (j) {
2450 for (; k < j; k++) {
2451 if (tagarray[k] == BT_Tag)
2452 break;
2453 }
2454 }
2455
2456 if (k < j)
2457 bt_flag = tagarray[k];
2458 else
2459 Result = FAIL;
2460
2461 if (Result == PASS) {
2462 k = 0;
2463 j = FTL_Extract_Block_Table_Tag(pSpareBufBTLastPage,
2464 &tagarray);
2465 if (j) {
2466 for (; k < j; k++) {
2467 if (tagarray[k] == BT_Tag)
2468 break;
2469 }
2470 }
2471
2472 if (k < j)
2473 bt_flag_last_page = tagarray[k];
2474 else
2475 Result = FAIL;
2476
2477 if (Result == PASS) {
2478 if (bt_flag == bt_flag_last_page) {
2479 nand_dbg_print(NAND_DBG_DEBUG,
2480 "Block table is found "
2481 "in page after IPF at "
2482 "block %u page %u\n",
2483 (unsigned int)BT_Block,
2484 (unsigned int)i);
2485 BT_Found = 1;
2486 *Page = i;
2487 g_cBlockTableStatus =
2488 CURRENT_BLOCK_TABLE;
2489 goto func_return;
2490 } else {
2491 Result = FAIL;
2492 }
2493 }
2494 }
2495
2496 if (Result == FAIL)
2497 goto func_return;
2498 }
2499func_return:
2500 return Result;
2501}
2502
2503u8 *get_blk_table_start_addr(void)
2504{
2505 return g_pBlockTable;
2506}
2507
2508unsigned long get_blk_table_len(void)
2509{
2510 return DeviceInfo.wDataBlockNum * sizeof(u32);
2511}
2512
2513u8 *get_wear_leveling_table_start_addr(void)
2514{
2515 return g_pWearCounter;
2516}
2517
2518unsigned long get_wear_leveling_table_len(void)
2519{
2520 return DeviceInfo.wDataBlockNum * sizeof(u8);
2521}
2522
2523/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
2524* Function: FTL_Read_Block_Table
2525* Inputs: none
2526* Outputs: PASS / FAIL
2527* Description: read the flash spare area and find a block containing the
2528* most recent block table(having largest block_table_counter).
2529* Find the last written Block table in this block.
2530* Check the correctness of Block Table
2531* If CDMA is enabled, this function is called in
2532* polling mode.
2533* We don't need to store changes in Block table in this
2534* function as it is called only at initialization
2535*
2536* Note: Currently this function is called at initialization
2537* before any read/erase/write command issued to flash so,
2538* there is no need to wait for CDMA list to complete as of now
2539*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
2540static int FTL_Read_Block_Table(void)
2541{
2542 u16 i = 0;
2543 int k, j;
2544 u8 *tempBuf, *tagarray;
2545 int wResult = FAIL;
2546 int status = FAIL;
2547 u8 block_table_found = 0;
2548 int search_result;
2549 u32 Block;
2550 u16 Page = 0;
2551 u16 PageCount;
2552 u16 bt_pages;
2553 int wBytesCopied = 0, tempvar;
2554
2555 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
2556 __FILE__, __LINE__, __func__);
2557
2558 tempBuf = tmp_buf1_read_blk_table;
2559 bt_pages = FTL_Get_Block_Table_Flash_Size_Pages();
2560
2561 for (j = DeviceInfo.wSpectraStartBlock;
2562 j <= (int)DeviceInfo.wSpectraEndBlock;
2563 j++) {
2564 status = GLOB_LLD_Read_Page_Spare(tempBuf, j, 0, 1);
2565 k = 0;
2566 i = FTL_Extract_Block_Table_Tag(tempBuf, &tagarray);
2567 if (i) {
2568 status = GLOB_LLD_Read_Page_Main_Polling(tempBuf,
2569 j, 0, 1);
2570 for (; k < i; k++) {
2571 if (tagarray[k] == tempBuf[3])
2572 break;
2573 }
2574 }
2575
2576 if (k < i)
2577 k = tagarray[k];
2578 else
2579 continue;
2580
2581 nand_dbg_print(NAND_DBG_DEBUG,
2582 "Block table is contained in Block %d %d\n",
2583 (unsigned int)j, (unsigned int)k);
2584
2585 if (g_pBTBlocks[k-FIRST_BT_ID] == BTBLOCK_INVAL) {
2586 g_pBTBlocks[k-FIRST_BT_ID] = j;
2587 block_table_found = 1;
2588 } else {
2589 printk(KERN_ERR "FTL_Read_Block_Table -"
2590 "This should never happens. "
2591 "Two block table have same counter %u!\n", k);
2592 }
2593 }
2594
2595 if (block_table_found) {
2596 if (g_pBTBlocks[FIRST_BT_ID - FIRST_BT_ID] != BTBLOCK_INVAL &&
2597 g_pBTBlocks[LAST_BT_ID - FIRST_BT_ID] != BTBLOCK_INVAL) {
2598 j = LAST_BT_ID;
2599 while ((j > FIRST_BT_ID) &&
2600 (g_pBTBlocks[j - FIRST_BT_ID] != BTBLOCK_INVAL))
2601 j--;
2602 if (j == FIRST_BT_ID) {
2603 j = LAST_BT_ID;
2604 last_erased = LAST_BT_ID;
2605 } else {
2606 last_erased = (u8)j + 1;
2607 while ((j > FIRST_BT_ID) && (BTBLOCK_INVAL ==
2608 g_pBTBlocks[j - FIRST_BT_ID]))
2609 j--;
2610 }
2611 } else {
2612 j = FIRST_BT_ID;
2613 while (g_pBTBlocks[j - FIRST_BT_ID] == BTBLOCK_INVAL)
2614 j++;
2615 last_erased = (u8)j;
2616 while ((j < LAST_BT_ID) && (BTBLOCK_INVAL !=
2617 g_pBTBlocks[j - FIRST_BT_ID]))
2618 j++;
2619 if (g_pBTBlocks[j-FIRST_BT_ID] == BTBLOCK_INVAL)
2620 j--;
2621 }
2622
2623 if (last_erased > j)
2624 j += (1 + LAST_BT_ID - FIRST_BT_ID);
2625
2626 for (; (j >= last_erased) && (FAIL == wResult); j--) {
2627 i = (j - FIRST_BT_ID) %
2628 (1 + LAST_BT_ID - FIRST_BT_ID);
2629 search_result =
2630 FTL_Search_Block_Table_IN_Block(g_pBTBlocks[i],
2631 i + FIRST_BT_ID, &Page);
2632 if (g_cBlockTableStatus == IN_PROGRESS_BLOCK_TABLE)
2633 block_table_found = 0;
2634
2635 while ((search_result == PASS) && (FAIL == wResult)) {
2636 nand_dbg_print(NAND_DBG_DEBUG,
2637 "FTL_Read_Block_Table:"
2638 "Block: %u Page: %u "
2639 "contains block table\n",
2640 (unsigned int)g_pBTBlocks[i],
2641 (unsigned int)Page);
2642
2643 tempBuf = tmp_buf2_read_blk_table;
2644
2645 for (k = 0; k < bt_pages; k++) {
2646 Block = g_pBTBlocks[i];
2647 PageCount = 1;
2648
2649 status =
2650 GLOB_LLD_Read_Page_Main_Polling(
2651 tempBuf, Block, Page, PageCount);
2652
2653 tempvar = k ? 0 : 4;
2654
2655 wBytesCopied +=
2656 FTL_Copy_Block_Table_From_Flash(
2657 tempBuf + tempvar,
2658 DeviceInfo.wPageDataSize - tempvar,
2659 wBytesCopied);
2660
2661 Page++;
2662 }
2663
2664 wResult = FTL_Check_Block_Table(FAIL);
2665 if (FAIL == wResult) {
2666 block_table_found = 0;
2667 if (Page > bt_pages)
2668 Page -= ((bt_pages<<1) + 1);
2669 else
2670 search_result = FAIL;
2671 }
2672 }
2673 }
2674 }
2675
2676 if (PASS == wResult) {
2677 if (!block_table_found)
2678 FTL_Execute_SPL_Recovery();
2679
2680 if (g_cBlockTableStatus == IN_PROGRESS_BLOCK_TABLE)
2681 g_wBlockTableOffset = (u16)Page + 1;
2682 else
2683 g_wBlockTableOffset = (u16)Page - bt_pages;
2684
2685 g_wBlockTableIndex = (u32)g_pBTBlocks[i];
2686
2687#if CMD_DMA
2688 if (DeviceInfo.MLCDevice)
2689 memcpy(g_pBTStartingCopy, g_pBlockTable,
2690 DeviceInfo.wDataBlockNum * sizeof(u32)
2691 + DeviceInfo.wDataBlockNum * sizeof(u8)
2692 + DeviceInfo.wDataBlockNum * sizeof(u16));
2693 else
2694 memcpy(g_pBTStartingCopy, g_pBlockTable,
2695 DeviceInfo.wDataBlockNum * sizeof(u32)
2696 + DeviceInfo.wDataBlockNum * sizeof(u8));
2697#endif
2698 }
2699
2700 if (FAIL == wResult)
2701 printk(KERN_ERR "Yunpeng - "
2702 "Can not find valid spectra block table!\n");
2703
2704#if AUTO_FORMAT_FLASH
2705 if (FAIL == wResult) {
2706 nand_dbg_print(NAND_DBG_DEBUG, "doing auto-format\n");
2707 wResult = FTL_Format_Flash(0);
2708 }
2709#endif
2710
2711 return wResult;
2712}
2713
2714/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
2715* Function: FTL_Get_Page_Num
2716* Inputs: Size in bytes
2717* Outputs: Size in pages
2718* Description: It calculates the pages required for the length passed
2719*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
2720static u32 FTL_Get_Page_Num(u64 length)
2721{
2722 return (u32)((length >> DeviceInfo.nBitsInPageDataSize) +
2723 (GLOB_u64_Remainder(length , 1) > 0 ? 1 : 0));
2724}
2725
2726/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
2727* Function: FTL_Get_Physical_Block_Addr
2728* Inputs: Block Address (byte format)
2729* Outputs: Physical address of the block.
2730* Description: It translates LBA to PBA by returning address stored
2731* at the LBA location in the block table
2732*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
2733static u64 FTL_Get_Physical_Block_Addr(u64 logical_addr)
2734{
2735 u32 *pbt;
2736 u64 physical_addr;
2737
2738 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
2739 __FILE__, __LINE__, __func__);
2740
2741 pbt = (u32 *)g_pBlockTable;
2742 physical_addr = (u64) DeviceInfo.wBlockDataSize *
2743 (pbt[BLK_FROM_ADDR(logical_addr)] & (~BAD_BLOCK));
2744
2745 return physical_addr;
2746}
2747
2748/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
2749* Function: FTL_Get_Block_Index
2750* Inputs: Physical Block no.
2751* Outputs: Logical block no. /BAD_BLOCK
2752* Description: It returns the logical block no. for the PBA passed
2753*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
2754static u32 FTL_Get_Block_Index(u32 wBlockNum)
2755{
2756 u32 *pbt = (u32 *)g_pBlockTable;
2757 u32 i;
2758
2759 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
2760 __FILE__, __LINE__, __func__);
2761
2762 for (i = 0; i < DeviceInfo.wDataBlockNum; i++)
2763 if (wBlockNum == (pbt[i] & (~BAD_BLOCK)))
2764 return i;
2765
2766 return BAD_BLOCK;
2767}
2768
2769/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
2770* Function: GLOB_FTL_Wear_Leveling
2771* Inputs: none
2772* Outputs: PASS=0
2773* Description: This is static wear leveling (done by explicit call)
2774* do complete static wear leveling
2775* do complete garbage collection
2776*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
2777int GLOB_FTL_Wear_Leveling(void)
2778{
2779 nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
2780 __FILE__, __LINE__, __func__);
2781
2782 FTL_Static_Wear_Leveling();
2783 GLOB_FTL_Garbage_Collection();
2784
2785 return PASS;
2786}
2787
2788static void find_least_most_worn(u8 *chg,
2789 u32 *least_idx, u8 *least_cnt,
2790 u32 *most_idx, u8 *most_cnt)
2791{
2792 u32 *pbt = (u32 *)g_pBlockTable;
2793 u32 idx;
2794 u8 cnt;
2795 int i;
2796
2797 for (i = BLOCK_TABLE_INDEX + 1; i < DeviceInfo.wDataBlockNum; i++) {
2798 if (IS_BAD_BLOCK(i) || PASS == chg[i])
2799 continue;
2800
2801 idx = (u32) ((~BAD_BLOCK) & pbt[i]);
2802 cnt = g_pWearCounter[idx - DeviceInfo.wSpectraStartBlock];
2803
2804 if (IS_SPARE_BLOCK(i)) {
2805 if (cnt > *most_cnt) {
2806 *most_cnt = cnt;
2807 *most_idx = idx;
2808 }
2809 }
2810
2811 if (IS_DATA_BLOCK(i)) {
2812 if (cnt < *least_cnt) {
2813 *least_cnt = cnt;
2814 *least_idx = idx;
2815 }
2816 }
2817
2818 if (PASS == chg[*most_idx] || PASS == chg[*least_idx]) {
2819 debug_boundary_error(*most_idx,
2820 DeviceInfo.wDataBlockNum, 0);
2821 debug_boundary_error(*least_idx,
2822 DeviceInfo.wDataBlockNum, 0);
2823 continue;
2824 }
2825 }
2826}
2827
2828static int move_blks_for_wear_leveling(u8 *chg,
2829 u32 *least_idx, u32 *rep_blk_num, int *result)
2830{
2831 u32 *pbt = (u32 *)g_pBlockTable;
2832 u32 rep_blk;
2833 int j, ret_cp_blk, ret_erase;
2834 int ret = PASS;
2835
2836 chg[*least_idx] = PASS;
2837 debug_boundary_error(*least_idx, DeviceInfo.wDataBlockNum, 0);
2838
2839 rep_blk = FTL_Replace_MWBlock();
2840 if (rep_blk != BAD_BLOCK) {
2841 nand_dbg_print(NAND_DBG_DEBUG,
2842 "More than two spare blocks exist so do it\n");
2843 nand_dbg_print(NAND_DBG_DEBUG, "Block Replaced is %d\n",
2844 rep_blk);
2845
2846 chg[rep_blk] = PASS;
2847
2848 if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) {
2849 g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE;
2850 FTL_Write_IN_Progress_Block_Table_Page();
2851 }
2852
2853 for (j = 0; j < RETRY_TIMES; j++) {
2854 ret_cp_blk = FTL_Copy_Block((u64)(*least_idx) *
2855 DeviceInfo.wBlockDataSize,
2856 (u64)rep_blk * DeviceInfo.wBlockDataSize);
2857 if (FAIL == ret_cp_blk) {
2858 ret_erase = GLOB_FTL_Block_Erase((u64)rep_blk
2859 * DeviceInfo.wBlockDataSize);
2860 if (FAIL == ret_erase)
2861 MARK_BLOCK_AS_BAD(pbt[rep_blk]);
2862 } else {
2863 nand_dbg_print(NAND_DBG_DEBUG,
2864 "FTL_Copy_Block == OK\n");
2865 break;
2866 }
2867 }
2868
2869 if (j < RETRY_TIMES) {
2870 u32 tmp;
2871 u32 old_idx = FTL_Get_Block_Index(*least_idx);
2872 u32 rep_idx = FTL_Get_Block_Index(rep_blk);
2873 tmp = (u32)(DISCARD_BLOCK | pbt[old_idx]);
2874 pbt[old_idx] = (u32)((~SPARE_BLOCK) &
2875 pbt[rep_idx]);
2876 pbt[rep_idx] = tmp;
2877#if CMD_DMA
2878 p_BTableChangesDelta = (struct BTableChangesDelta *)
2879 g_pBTDelta_Free;
2880 g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
2881 p_BTableChangesDelta->ftl_cmd_cnt =
2882 ftl_cmd_cnt;
2883 p_BTableChangesDelta->BT_Index = old_idx;
2884 p_BTableChangesDelta->BT_Entry_Value = pbt[old_idx];
2885 p_BTableChangesDelta->ValidFields = 0x0C;
2886
2887 p_BTableChangesDelta = (struct BTableChangesDelta *)
2888 g_pBTDelta_Free;
2889 g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
2890
2891 p_BTableChangesDelta->ftl_cmd_cnt =
2892 ftl_cmd_cnt;
2893 p_BTableChangesDelta->BT_Index = rep_idx;
2894 p_BTableChangesDelta->BT_Entry_Value = pbt[rep_idx];
2895 p_BTableChangesDelta->ValidFields = 0x0C;
2896#endif
2897 } else {
2898 pbt[FTL_Get_Block_Index(rep_blk)] |= BAD_BLOCK;
2899#if CMD_DMA
2900 p_BTableChangesDelta = (struct BTableChangesDelta *)
2901 g_pBTDelta_Free;
2902 g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
2903
2904 p_BTableChangesDelta->ftl_cmd_cnt =
2905 ftl_cmd_cnt;
2906 p_BTableChangesDelta->BT_Index =
2907 FTL_Get_Block_Index(rep_blk);
2908 p_BTableChangesDelta->BT_Entry_Value =
2909 pbt[FTL_Get_Block_Index(rep_blk)];
2910 p_BTableChangesDelta->ValidFields = 0x0C;
2911#endif
2912 *result = FAIL;
2913 ret = FAIL;
2914 }
2915
2916 if (((*rep_blk_num)++) > WEAR_LEVELING_BLOCK_NUM)
2917 ret = FAIL;
2918 } else {
2919 printk(KERN_ERR "Less than 3 spare blocks exist so quit\n");
2920 ret = FAIL;
2921 }
2922
2923 return ret;
2924}
2925
2926/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
2927* Function: FTL_Static_Wear_Leveling
2928* Inputs: none
2929* Outputs: PASS=0 / FAIL=1
2930* Description: This is static wear leveling (done by explicit call)
2931* search for most&least used
2932* if difference < GATE:
2933* update the block table with exhange
2934* mark block table in flash as IN_PROGRESS
2935* copy flash block
2936* the caller should handle GC clean up after calling this function
2937*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
2938int FTL_Static_Wear_Leveling(void)
2939{
2940 u8 most_worn_cnt;
2941 u8 least_worn_cnt;
2942 u32 most_worn_idx;
2943 u32 least_worn_idx;
2944 int result = PASS;
2945 int go_on = PASS;
2946 u32 replaced_blks = 0;
2947 u8 *chang_flag = flags_static_wear_leveling;
2948
2949 nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
2950 __FILE__, __LINE__, __func__);
2951
2952 if (!chang_flag)
2953 return FAIL;
2954
2955 memset(chang_flag, FAIL, DeviceInfo.wDataBlockNum);
2956 while (go_on == PASS) {
2957 nand_dbg_print(NAND_DBG_DEBUG,
2958 "starting static wear leveling\n");
2959 most_worn_cnt = 0;
2960 least_worn_cnt = 0xFF;
2961 least_worn_idx = BLOCK_TABLE_INDEX;
2962 most_worn_idx = BLOCK_TABLE_INDEX;
2963
2964 find_least_most_worn(chang_flag, &least_worn_idx,
2965 &least_worn_cnt, &most_worn_idx, &most_worn_cnt);
2966
2967 nand_dbg_print(NAND_DBG_DEBUG,
2968 "Used and least worn is block %u, whos count is %u\n",
2969 (unsigned int)least_worn_idx,
2970 (unsigned int)least_worn_cnt);
2971
2972 nand_dbg_print(NAND_DBG_DEBUG,
2973 "Free and most worn is block %u, whos count is %u\n",
2974 (unsigned int)most_worn_idx,
2975 (unsigned int)most_worn_cnt);
2976
2977 if ((most_worn_cnt > least_worn_cnt) &&
2978 (most_worn_cnt - least_worn_cnt > WEAR_LEVELING_GATE))
2979 go_on = move_blks_for_wear_leveling(chang_flag,
2980 &least_worn_idx, &replaced_blks, &result);
2981 else
2982 go_on = FAIL;
2983 }
2984
2985 return result;
2986}
2987
2988#if CMD_DMA
2989static int do_garbage_collection(u32 discard_cnt)
2990{
2991 u32 *pbt = (u32 *)g_pBlockTable;
2992 u32 pba;
2993 u8 bt_block_erased = 0;
2994 int i, cnt, ret = FAIL;
2995 u64 addr;
2996
2997 i = 0;
2998 while ((i < DeviceInfo.wDataBlockNum) && (discard_cnt > 0) &&
2999 ((ftl_cmd_cnt + 28) < 256)) {
3000 if (((pbt[i] & BAD_BLOCK) != BAD_BLOCK) &&
3001 (pbt[i] & DISCARD_BLOCK)) {
3002 if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) {
3003 g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE;
3004 FTL_Write_IN_Progress_Block_Table_Page();
3005 }
3006
3007 addr = FTL_Get_Physical_Block_Addr((u64)i *
3008 DeviceInfo.wBlockDataSize);
3009 pba = BLK_FROM_ADDR(addr);
3010
3011 for (cnt = FIRST_BT_ID; cnt <= LAST_BT_ID; cnt++) {
3012 if (pba == g_pBTBlocks[cnt - FIRST_BT_ID]) {
3013 nand_dbg_print(NAND_DBG_DEBUG,
3014 "GC will erase BT block %u\n",
3015 (unsigned int)pba);
3016 discard_cnt--;
3017 i++;
3018 bt_block_erased = 1;
3019 break;
3020 }
3021 }
3022
3023 if (bt_block_erased) {
3024 bt_block_erased = 0;
3025 continue;
3026 }
3027
3028 addr = FTL_Get_Physical_Block_Addr((u64)i *
3029 DeviceInfo.wBlockDataSize);
3030
3031 if (PASS == GLOB_FTL_Block_Erase(addr)) {
3032 pbt[i] &= (u32)(~DISCARD_BLOCK);
3033 pbt[i] |= (u32)(SPARE_BLOCK);
3034 p_BTableChangesDelta =
3035 (struct BTableChangesDelta *)
3036 g_pBTDelta_Free;
3037 g_pBTDelta_Free +=
3038 sizeof(struct BTableChangesDelta);
3039 p_BTableChangesDelta->ftl_cmd_cnt =
3040 ftl_cmd_cnt - 1;
3041 p_BTableChangesDelta->BT_Index = i;
3042 p_BTableChangesDelta->BT_Entry_Value = pbt[i];
3043 p_BTableChangesDelta->ValidFields = 0x0C;
3044 discard_cnt--;
3045 ret = PASS;
3046 } else {
3047 MARK_BLOCK_AS_BAD(pbt[i]);
3048 }
3049 }
3050
3051 i++;
3052 }
3053
3054 return ret;
3055}
3056
3057#else
3058static int do_garbage_collection(u32 discard_cnt)
3059{
3060 u32 *pbt = (u32 *)g_pBlockTable;
3061 u32 pba;
3062 u8 bt_block_erased = 0;
3063 int i, cnt, ret = FAIL;
3064 u64 addr;
3065
3066 i = 0;
3067 while ((i < DeviceInfo.wDataBlockNum) && (discard_cnt > 0)) {
3068 if (((pbt[i] & BAD_BLOCK) != BAD_BLOCK) &&
3069 (pbt[i] & DISCARD_BLOCK)) {
3070 if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) {
3071 g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE;
3072 FTL_Write_IN_Progress_Block_Table_Page();
3073 }
3074
3075 addr = FTL_Get_Physical_Block_Addr((u64)i *
3076 DeviceInfo.wBlockDataSize);
3077 pba = BLK_FROM_ADDR(addr);
3078
3079 for (cnt = FIRST_BT_ID; cnt <= LAST_BT_ID; cnt++) {
3080 if (pba == g_pBTBlocks[cnt - FIRST_BT_ID]) {
3081 nand_dbg_print(NAND_DBG_DEBUG,
3082 "GC will erase BT block %d\n",
3083 pba);
3084 discard_cnt--;
3085 i++;
3086 bt_block_erased = 1;
3087 break;
3088 }
3089 }
3090
3091 if (bt_block_erased) {
3092 bt_block_erased = 0;
3093 continue;
3094 }
3095
3096 /* If the discard block is L2 cache block, then just skip it */
3097 for (cnt = 0; cnt < BLK_NUM_FOR_L2_CACHE; cnt++) {
3098 if (cache_l2.blk_array[cnt] == pba) {
3099 nand_dbg_print(NAND_DBG_DEBUG,
3100 "GC will erase L2 cache blk %d\n",
3101 pba);
3102 break;
3103 }
3104 }
3105 if (cnt < BLK_NUM_FOR_L2_CACHE) { /* Skip it */
3106 discard_cnt--;
3107 i++;
3108 continue;
3109 }
3110
3111 addr = FTL_Get_Physical_Block_Addr((u64)i *
3112 DeviceInfo.wBlockDataSize);
3113
3114 if (PASS == GLOB_FTL_Block_Erase(addr)) {
3115 pbt[i] &= (u32)(~DISCARD_BLOCK);
3116 pbt[i] |= (u32)(SPARE_BLOCK);
3117 discard_cnt--;
3118 ret = PASS;
3119 } else {
3120 MARK_BLOCK_AS_BAD(pbt[i]);
3121 }
3122 }
3123
3124 i++;
3125 }
3126
3127 return ret;
3128}
3129#endif
3130
3131/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
3132* Function: GLOB_FTL_Garbage_Collection
3133* Inputs: none
3134* Outputs: PASS / FAIL (returns the number of un-erased blocks
3135* Description: search the block table for all discarded blocks to erase
3136* for each discarded block:
3137* set the flash block to IN_PROGRESS
3138* erase the block
3139* update the block table
3140* write the block table to flash
3141*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
3142int GLOB_FTL_Garbage_Collection(void)
3143{
3144 u32 i;
3145 u32 wDiscard = 0;
3146 int wResult = FAIL;
3147 u32 *pbt = (u32 *)g_pBlockTable;
3148
3149 nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
3150 __FILE__, __LINE__, __func__);
3151
3152 if (GC_Called) {
3153 printk(KERN_ALERT "GLOB_FTL_Garbage_Collection() "
3154 "has been re-entered! Exit.\n");
3155 return PASS;
3156 }
3157
3158 GC_Called = 1;
3159
3160 GLOB_FTL_BT_Garbage_Collection();
3161
3162 for (i = 0; i < DeviceInfo.wDataBlockNum; i++) {
3163 if (IS_DISCARDED_BLOCK(i))
3164 wDiscard++;
3165 }
3166
3167 if (wDiscard <= 0) {
3168 GC_Called = 0;
3169 return wResult;
3170 }
3171
3172 nand_dbg_print(NAND_DBG_DEBUG,
3173 "Found %d discarded blocks\n", wDiscard);
3174
3175 FTL_Write_Block_Table(FAIL);
3176
3177 wResult = do_garbage_collection(wDiscard);
3178
3179 FTL_Write_Block_Table(FAIL);
3180
3181 GC_Called = 0;
3182
3183 return wResult;
3184}
3185
3186
3187#if CMD_DMA
3188static int do_bt_garbage_collection(void)
3189{
3190 u32 pba, lba;
3191 u32 *pbt = (u32 *)g_pBlockTable;
3192 u32 *pBTBlocksNode = (u32 *)g_pBTBlocks;
3193 u64 addr;
3194 int i, ret = FAIL;
3195
3196 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
3197 __FILE__, __LINE__, __func__);
3198
3199 if (BT_GC_Called)
3200 return PASS;
3201
3202 BT_GC_Called = 1;
3203
3204 for (i = last_erased; (i <= LAST_BT_ID) &&
3205 (g_pBTBlocks[((i + 2) % (1 + LAST_BT_ID - FIRST_BT_ID)) +
3206 FIRST_BT_ID - FIRST_BT_ID] != BTBLOCK_INVAL) &&
3207 ((ftl_cmd_cnt + 28)) < 256; i++) {
3208 pba = pBTBlocksNode[i - FIRST_BT_ID];
3209 lba = FTL_Get_Block_Index(pba);
3210 nand_dbg_print(NAND_DBG_DEBUG,
3211 "do_bt_garbage_collection: pba %d, lba %d\n",
3212 pba, lba);
3213 nand_dbg_print(NAND_DBG_DEBUG,
3214 "Block Table Entry: %d", pbt[lba]);
3215
3216 if (((pbt[lba] & BAD_BLOCK) != BAD_BLOCK) &&
3217 (pbt[lba] & DISCARD_BLOCK)) {
3218 nand_dbg_print(NAND_DBG_DEBUG,
3219 "do_bt_garbage_collection_cdma: "
3220 "Erasing Block tables present in block %d\n",
3221 pba);
3222 addr = FTL_Get_Physical_Block_Addr((u64)lba *
3223 DeviceInfo.wBlockDataSize);
3224 if (PASS == GLOB_FTL_Block_Erase(addr)) {
3225 pbt[lba] &= (u32)(~DISCARD_BLOCK);
3226 pbt[lba] |= (u32)(SPARE_BLOCK);
3227
3228 p_BTableChangesDelta =
3229 (struct BTableChangesDelta *)
3230 g_pBTDelta_Free;
3231 g_pBTDelta_Free +=
3232 sizeof(struct BTableChangesDelta);
3233
3234 p_BTableChangesDelta->ftl_cmd_cnt =
3235 ftl_cmd_cnt - 1;
3236 p_BTableChangesDelta->BT_Index = lba;
3237 p_BTableChangesDelta->BT_Entry_Value =
3238 pbt[lba];
3239
3240 p_BTableChangesDelta->ValidFields = 0x0C;
3241
3242 ret = PASS;
3243 pBTBlocksNode[last_erased - FIRST_BT_ID] =
3244 BTBLOCK_INVAL;
3245 nand_dbg_print(NAND_DBG_DEBUG,
3246 "resetting bt entry at index %d "
3247 "value %d\n", i,
3248 pBTBlocksNode[i - FIRST_BT_ID]);
3249 if (last_erased == LAST_BT_ID)
3250 last_erased = FIRST_BT_ID;
3251 else
3252 last_erased++;
3253 } else {
3254 MARK_BLOCK_AS_BAD(pbt[lba]);
3255 }
3256 }
3257 }
3258
3259 BT_GC_Called = 0;
3260
3261 return ret;
3262}
3263
3264#else
3265static int do_bt_garbage_collection(void)
3266{
3267 u32 pba, lba;
3268 u32 *pbt = (u32 *)g_pBlockTable;
3269 u32 *pBTBlocksNode = (u32 *)g_pBTBlocks;
3270 u64 addr;
3271 int i, ret = FAIL;
3272
3273 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
3274 __FILE__, __LINE__, __func__);
3275
3276 if (BT_GC_Called)
3277 return PASS;
3278
3279 BT_GC_Called = 1;
3280
3281 for (i = last_erased; (i <= LAST_BT_ID) &&
3282 (g_pBTBlocks[((i + 2) % (1 + LAST_BT_ID - FIRST_BT_ID)) +
3283 FIRST_BT_ID - FIRST_BT_ID] != BTBLOCK_INVAL); i++) {
3284 pba = pBTBlocksNode[i - FIRST_BT_ID];
3285 lba = FTL_Get_Block_Index(pba);
3286 nand_dbg_print(NAND_DBG_DEBUG,
3287 "do_bt_garbage_collection_cdma: pba %d, lba %d\n",
3288 pba, lba);
3289 nand_dbg_print(NAND_DBG_DEBUG,
3290 "Block Table Entry: %d", pbt[lba]);
3291
3292 if (((pbt[lba] & BAD_BLOCK) != BAD_BLOCK) &&
3293 (pbt[lba] & DISCARD_BLOCK)) {
3294 nand_dbg_print(NAND_DBG_DEBUG,
3295 "do_bt_garbage_collection: "
3296 "Erasing Block tables present in block %d\n",
3297 pba);
3298 addr = FTL_Get_Physical_Block_Addr((u64)lba *
3299 DeviceInfo.wBlockDataSize);
3300 if (PASS == GLOB_FTL_Block_Erase(addr)) {
3301 pbt[lba] &= (u32)(~DISCARD_BLOCK);
3302 pbt[lba] |= (u32)(SPARE_BLOCK);
3303 ret = PASS;
3304 pBTBlocksNode[last_erased - FIRST_BT_ID] =
3305 BTBLOCK_INVAL;
3306 nand_dbg_print(NAND_DBG_DEBUG,
3307 "resetting bt entry at index %d "
3308 "value %d\n", i,
3309 pBTBlocksNode[i - FIRST_BT_ID]);
3310 if (last_erased == LAST_BT_ID)
3311 last_erased = FIRST_BT_ID;
3312 else
3313 last_erased++;
3314 } else {
3315 MARK_BLOCK_AS_BAD(pbt[lba]);
3316 }
3317 }
3318 }
3319
3320 BT_GC_Called = 0;
3321
3322 return ret;
3323}
3324
3325#endif
3326
3327/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
3328* Function: GLOB_FTL_BT_Garbage_Collection
3329* Inputs: none
3330* Outputs: PASS / FAIL (returns the number of un-erased blocks
3331* Description: Erases discarded blocks containing Block table
3332*
3333*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
3334int GLOB_FTL_BT_Garbage_Collection(void)
3335{
3336 return do_bt_garbage_collection();
3337}
3338
3339/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
3340* Function: FTL_Replace_OneBlock
3341* Inputs: Block number 1
3342* Block number 2
3343* Outputs: Replaced Block Number
3344* Description: Interchange block table entries at wBlockNum and wReplaceNum
3345*
3346*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
3347static u32 FTL_Replace_OneBlock(u32 blk, u32 rep_blk)
3348{
3349 u32 tmp_blk;
3350 u32 replace_node = BAD_BLOCK;
3351 u32 *pbt = (u32 *)g_pBlockTable;
3352
3353 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
3354 __FILE__, __LINE__, __func__);
3355
3356 if (rep_blk != BAD_BLOCK) {
3357 if (IS_BAD_BLOCK(blk))
3358 tmp_blk = pbt[blk];
3359 else
3360 tmp_blk = DISCARD_BLOCK | (~SPARE_BLOCK & pbt[blk]);
3361
3362 replace_node = (u32) ((~SPARE_BLOCK) & pbt[rep_blk]);
3363 pbt[blk] = replace_node;
3364 pbt[rep_blk] = tmp_blk;
3365
3366#if CMD_DMA
3367 p_BTableChangesDelta =
3368 (struct BTableChangesDelta *)g_pBTDelta_Free;
3369 g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
3370
3371 p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt;
3372 p_BTableChangesDelta->BT_Index = blk;
3373 p_BTableChangesDelta->BT_Entry_Value = pbt[blk];
3374
3375 p_BTableChangesDelta->ValidFields = 0x0C;
3376
3377 p_BTableChangesDelta =
3378 (struct BTableChangesDelta *)g_pBTDelta_Free;
3379 g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
3380
3381 p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt;
3382 p_BTableChangesDelta->BT_Index = rep_blk;
3383 p_BTableChangesDelta->BT_Entry_Value = pbt[rep_blk];
3384 p_BTableChangesDelta->ValidFields = 0x0C;
3385#endif
3386 }
3387
3388 return replace_node;
3389}
3390
3391/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
3392* Function: FTL_Write_Block_Table_Data
3393* Inputs: Block table size in pages
3394* Outputs: PASS=0 / FAIL=1
3395* Description: Write block table data in flash
3396* If first page and last page
3397* Write data+BT flag
3398* else
3399* Write data
3400* BT flag is a counter. Its value is incremented for block table
3401* write in a new Block
3402*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
3403static int FTL_Write_Block_Table_Data(void)
3404{
3405 u64 dwBlockTableAddr, pTempAddr;
3406 u32 Block;
3407 u16 Page, PageCount;
3408 u8 *tempBuf = tmp_buf_write_blk_table_data;
3409 int wBytesCopied;
3410 u16 bt_pages;
3411
3412 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
3413 __FILE__, __LINE__, __func__);
3414
3415 dwBlockTableAddr =
3416 (u64)((u64)g_wBlockTableIndex * DeviceInfo.wBlockDataSize +
3417 (u64)g_wBlockTableOffset * DeviceInfo.wPageDataSize);
3418 pTempAddr = dwBlockTableAddr;
3419
3420 bt_pages = FTL_Get_Block_Table_Flash_Size_Pages();
3421
3422 nand_dbg_print(NAND_DBG_DEBUG, "FTL_Write_Block_Table_Data: "
3423 "page= %d BlockTableIndex= %d "
3424 "BlockTableOffset=%d\n", bt_pages,
3425 g_wBlockTableIndex, g_wBlockTableOffset);
3426
3427 Block = BLK_FROM_ADDR(pTempAddr);
3428 Page = PAGE_FROM_ADDR(pTempAddr, Block);
3429 PageCount = 1;
3430
3431 if (bt_block_changed) {
3432 if (bt_flag == LAST_BT_ID) {
3433 bt_flag = FIRST_BT_ID;
3434 g_pBTBlocks[bt_flag - FIRST_BT_ID] = Block;
3435 } else if (bt_flag < LAST_BT_ID) {
3436 bt_flag++;
3437 g_pBTBlocks[bt_flag - FIRST_BT_ID] = Block;
3438 }
3439
3440 if ((bt_flag > (LAST_BT_ID-4)) &&
3441 g_pBTBlocks[FIRST_BT_ID - FIRST_BT_ID] !=
3442 BTBLOCK_INVAL) {
3443 bt_block_changed = 0;
3444 GLOB_FTL_BT_Garbage_Collection();
3445 }
3446
3447 bt_block_changed = 0;
3448 nand_dbg_print(NAND_DBG_DEBUG,
3449 "Block Table Counter is %u Block %u\n",
3450 bt_flag, (unsigned int)Block);
3451 }
3452
3453 memset(tempBuf, 0, 3);
3454 tempBuf[3] = bt_flag;
3455 wBytesCopied = FTL_Copy_Block_Table_To_Flash(tempBuf + 4,
3456 DeviceInfo.wPageDataSize - 4, 0);
3457 memset(&tempBuf[wBytesCopied + 4], 0xff,
3458 DeviceInfo.wPageSize - (wBytesCopied + 4));
3459 FTL_Insert_Block_Table_Signature(&tempBuf[DeviceInfo.wPageDataSize],
3460 bt_flag);
3461
3462#if CMD_DMA
3463 memcpy(g_pNextBlockTable, tempBuf,
3464 DeviceInfo.wPageSize * sizeof(u8));
3465 nand_dbg_print(NAND_DBG_DEBUG, "Writing First Page of Block Table "
3466 "Block %u Page %u\n", (unsigned int)Block, Page);
3467 if (FAIL == GLOB_LLD_Write_Page_Main_Spare_cdma(g_pNextBlockTable,
3468 Block, Page, 1,
3469 LLD_CMD_FLAG_MODE_CDMA | LLD_CMD_FLAG_ORDER_BEFORE_REST)) {
3470 nand_dbg_print(NAND_DBG_WARN, "NAND Program fail in "
3471 "%s, Line %d, Function: %s, "
3472 "new Bad Block %d generated!\n",
3473 __FILE__, __LINE__, __func__, Block);
3474 goto func_return;
3475 }
3476
3477 ftl_cmd_cnt++;
3478 g_pNextBlockTable += ((DeviceInfo.wPageSize * sizeof(u8)));
3479#else
3480 if (FAIL == GLOB_LLD_Write_Page_Main_Spare(tempBuf, Block, Page, 1)) {
3481 nand_dbg_print(NAND_DBG_WARN,
3482 "NAND Program fail in %s, Line %d, Function: %s, "
3483 "new Bad Block %d generated!\n",
3484 __FILE__, __LINE__, __func__, Block);
3485 goto func_return;
3486 }
3487#endif
3488
3489 if (bt_pages > 1) {
3490 PageCount = bt_pages - 1;
3491 if (PageCount > 1) {
3492 wBytesCopied += FTL_Copy_Block_Table_To_Flash(tempBuf,
3493 DeviceInfo.wPageDataSize * (PageCount - 1),
3494 wBytesCopied);
3495
3496#if CMD_DMA
3497 memcpy(g_pNextBlockTable, tempBuf,
3498 (PageCount - 1) * DeviceInfo.wPageDataSize);
3499 if (FAIL == GLOB_LLD_Write_Page_Main_cdma(
3500 g_pNextBlockTable, Block, Page + 1,
3501 PageCount - 1)) {
3502 nand_dbg_print(NAND_DBG_WARN,
3503 "NAND Program fail in %s, Line %d, "
3504 "Function: %s, "
3505 "new Bad Block %d generated!\n",
3506 __FILE__, __LINE__, __func__,
3507 (int)Block);
3508 goto func_return;
3509 }
3510
3511 ftl_cmd_cnt++;
3512 g_pNextBlockTable += (PageCount - 1) *
3513 DeviceInfo.wPageDataSize * sizeof(u8);
3514#else
3515 if (FAIL == GLOB_LLD_Write_Page_Main(tempBuf,
3516 Block, Page + 1, PageCount - 1)) {
3517 nand_dbg_print(NAND_DBG_WARN,
3518 "NAND Program fail in %s, Line %d, "
3519 "Function: %s, "
3520 "new Bad Block %d generated!\n",
3521 __FILE__, __LINE__, __func__,
3522 (int)Block);
3523 goto func_return;
3524 }
3525#endif
3526 }
3527
3528 wBytesCopied = FTL_Copy_Block_Table_To_Flash(tempBuf,
3529 DeviceInfo.wPageDataSize, wBytesCopied);
3530 memset(&tempBuf[wBytesCopied], 0xff,
3531 DeviceInfo.wPageSize-wBytesCopied);
3532 FTL_Insert_Block_Table_Signature(
3533 &tempBuf[DeviceInfo.wPageDataSize], bt_flag);
3534#if CMD_DMA
3535 memcpy(g_pNextBlockTable, tempBuf,
3536 DeviceInfo.wPageSize * sizeof(u8));
3537 nand_dbg_print(NAND_DBG_DEBUG,
3538 "Writing the last Page of Block Table "
3539 "Block %u Page %u\n",
3540 (unsigned int)Block, Page + bt_pages - 1);
3541 if (FAIL == GLOB_LLD_Write_Page_Main_Spare_cdma(
3542 g_pNextBlockTable, Block, Page + bt_pages - 1, 1,
3543 LLD_CMD_FLAG_MODE_CDMA |
3544 LLD_CMD_FLAG_ORDER_BEFORE_REST)) {
3545 nand_dbg_print(NAND_DBG_WARN,
3546 "NAND Program fail in %s, Line %d, "
3547 "Function: %s, new Bad Block %d generated!\n",
3548 __FILE__, __LINE__, __func__, Block);
3549 goto func_return;
3550 }
3551 ftl_cmd_cnt++;
3552#else
3553 if (FAIL == GLOB_LLD_Write_Page_Main_Spare(tempBuf,
3554 Block, Page+bt_pages - 1, 1)) {
3555 nand_dbg_print(NAND_DBG_WARN,
3556 "NAND Program fail in %s, Line %d, "
3557 "Function: %s, "
3558 "new Bad Block %d generated!\n",
3559 __FILE__, __LINE__, __func__, Block);
3560 goto func_return;
3561 }
3562#endif
3563 }
3564
3565 nand_dbg_print(NAND_DBG_DEBUG, "FTL_Write_Block_Table_Data: done\n");
3566
3567func_return:
3568 return PASS;
3569}
3570
3571/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
3572* Function: FTL_Replace_Block_Table
3573* Inputs: None
3574* Outputs: PASS=0 / FAIL=1
3575* Description: Get a new block to write block table
3576*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
3577static u32 FTL_Replace_Block_Table(void)
3578{
3579 u32 blk;
3580 int gc;
3581
3582 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
3583 __FILE__, __LINE__, __func__);
3584
3585 blk = FTL_Replace_LWBlock(BLOCK_TABLE_INDEX, &gc);
3586
3587 if ((BAD_BLOCK == blk) && (PASS == gc)) {
3588 GLOB_FTL_Garbage_Collection();
3589 blk = FTL_Replace_LWBlock(BLOCK_TABLE_INDEX, &gc);
3590 }
3591 if (BAD_BLOCK == blk)
3592 printk(KERN_ERR "%s, %s: There is no spare block. "
3593 "It should never happen\n",
3594 __FILE__, __func__);
3595
3596 nand_dbg_print(NAND_DBG_DEBUG, "New Block table Block is %d\n", blk);
3597
3598 return blk;
3599}
3600
3601/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
3602* Function: FTL_Replace_LWBlock
3603* Inputs: Block number
3604* Pointer to Garbage Collect flag
3605* Outputs:
3606* Description: Determine the least weared block by traversing
3607* block table
3608* Set Garbage collection to be called if number of spare
3609* block is less than Free Block Gate count
3610* Change Block table entry to map least worn block for current
3611* operation
3612*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
3613static u32 FTL_Replace_LWBlock(u32 wBlockNum, int *pGarbageCollect)
3614{
3615 u32 i;
3616 u32 *pbt = (u32 *)g_pBlockTable;
3617 u8 wLeastWornCounter = 0xFF;
3618 u32 wLeastWornIndex = BAD_BLOCK;
3619 u32 wSpareBlockNum = 0;
3620 u32 wDiscardBlockNum = 0;
3621
3622 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
3623 __FILE__, __LINE__, __func__);
3624
3625 if (IS_SPARE_BLOCK(wBlockNum)) {
3626 *pGarbageCollect = FAIL;
3627 pbt[wBlockNum] = (u32)(pbt[wBlockNum] & (~SPARE_BLOCK));
3628#if CMD_DMA
3629 p_BTableChangesDelta =
3630 (struct BTableChangesDelta *)g_pBTDelta_Free;
3631 g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
3632 p_BTableChangesDelta->ftl_cmd_cnt =
3633 ftl_cmd_cnt;
3634 p_BTableChangesDelta->BT_Index = (u32)(wBlockNum);
3635 p_BTableChangesDelta->BT_Entry_Value = pbt[wBlockNum];
3636 p_BTableChangesDelta->ValidFields = 0x0C;
3637#endif
3638 return pbt[wBlockNum];
3639 }
3640
3641 for (i = 0; i < DeviceInfo.wDataBlockNum; i++) {
3642 if (IS_DISCARDED_BLOCK(i))
3643 wDiscardBlockNum++;
3644
3645 if (IS_SPARE_BLOCK(i)) {
3646 u32 wPhysicalIndex = (u32)((~BAD_BLOCK) & pbt[i]);
3647 if (wPhysicalIndex > DeviceInfo.wSpectraEndBlock)
3648 printk(KERN_ERR "FTL_Replace_LWBlock: "
3649 "This should never occur!\n");
3650 if (g_pWearCounter[wPhysicalIndex -
3651 DeviceInfo.wSpectraStartBlock] <
3652 wLeastWornCounter) {
3653 wLeastWornCounter =
3654 g_pWearCounter[wPhysicalIndex -
3655 DeviceInfo.wSpectraStartBlock];
3656 wLeastWornIndex = i;
3657 }
3658 wSpareBlockNum++;
3659 }
3660 }
3661
3662 nand_dbg_print(NAND_DBG_WARN,
3663 "FTL_Replace_LWBlock: Least Worn Counter %d\n",
3664 (int)wLeastWornCounter);
3665
3666 if ((wDiscardBlockNum >= NUM_FREE_BLOCKS_GATE) ||
3667 (wSpareBlockNum <= NUM_FREE_BLOCKS_GATE))
3668 *pGarbageCollect = PASS;
3669 else
3670 *pGarbageCollect = FAIL;
3671
3672 nand_dbg_print(NAND_DBG_DEBUG,
3673 "FTL_Replace_LWBlock: Discarded Blocks %u Spare"
3674 " Blocks %u\n",
3675 (unsigned int)wDiscardBlockNum,
3676 (unsigned int)wSpareBlockNum);
3677
3678 return FTL_Replace_OneBlock(wBlockNum, wLeastWornIndex);
3679}
3680
3681/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
3682* Function: FTL_Replace_MWBlock
3683* Inputs: None
3684* Outputs: most worn spare block no./BAD_BLOCK
3685* Description: It finds most worn spare block.
3686*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
3687static u32 FTL_Replace_MWBlock(void)
3688{
3689 u32 i;
3690 u32 *pbt = (u32 *)g_pBlockTable;
3691 u8 wMostWornCounter = 0;
3692 u32 wMostWornIndex = BAD_BLOCK;
3693 u32 wSpareBlockNum = 0;
3694
3695 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
3696 __FILE__, __LINE__, __func__);
3697
3698 for (i = 0; i < DeviceInfo.wDataBlockNum; i++) {
3699 if (IS_SPARE_BLOCK(i)) {
3700 u32 wPhysicalIndex = (u32)((~SPARE_BLOCK) & pbt[i]);
3701 if (g_pWearCounter[wPhysicalIndex -
3702 DeviceInfo.wSpectraStartBlock] >
3703 wMostWornCounter) {
3704 wMostWornCounter =
3705 g_pWearCounter[wPhysicalIndex -
3706 DeviceInfo.wSpectraStartBlock];
3707 wMostWornIndex = wPhysicalIndex;
3708 }
3709 wSpareBlockNum++;
3710 }
3711 }
3712
3713 if (wSpareBlockNum <= 2)
3714 return BAD_BLOCK;
3715
3716 return wMostWornIndex;
3717}
3718
3719/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
3720* Function: FTL_Replace_Block
3721* Inputs: Block Address
3722* Outputs: PASS=0 / FAIL=1
3723* Description: If block specified by blk_addr parameter is not free,
3724* replace it with the least worn block.
3725*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
3726static int FTL_Replace_Block(u64 blk_addr)
3727{
3728 u32 current_blk = BLK_FROM_ADDR(blk_addr);
3729 u32 *pbt = (u32 *)g_pBlockTable;
3730 int wResult = PASS;
3731 int GarbageCollect = FAIL;
3732
3733 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
3734 __FILE__, __LINE__, __func__);
3735
3736 if (IS_SPARE_BLOCK(current_blk)) {
3737 pbt[current_blk] = (~SPARE_BLOCK) & pbt[current_blk];
3738#if CMD_DMA
3739 p_BTableChangesDelta =
3740 (struct BTableChangesDelta *)g_pBTDelta_Free;
3741 g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
3742 p_BTableChangesDelta->ftl_cmd_cnt =
3743 ftl_cmd_cnt;
3744 p_BTableChangesDelta->BT_Index = current_blk;
3745 p_BTableChangesDelta->BT_Entry_Value = pbt[current_blk];
3746 p_BTableChangesDelta->ValidFields = 0x0C ;
3747#endif
3748 return wResult;
3749 }
3750
3751 FTL_Replace_LWBlock(current_blk, &GarbageCollect);
3752
3753 if (PASS == GarbageCollect)
3754 wResult = GLOB_FTL_Garbage_Collection();
3755
3756 return wResult;
3757}
3758
3759/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
3760* Function: GLOB_FTL_Is_BadBlock
3761* Inputs: block number to test
3762* Outputs: PASS (block is BAD) / FAIL (block is not bad)
3763* Description: test if this block number is flagged as bad
3764*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
3765int GLOB_FTL_Is_BadBlock(u32 wBlockNum)
3766{
3767 u32 *pbt = (u32 *)g_pBlockTable;
3768
3769 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
3770 __FILE__, __LINE__, __func__);
3771
3772 if (wBlockNum >= DeviceInfo.wSpectraStartBlock
3773 && BAD_BLOCK == (pbt[wBlockNum] & BAD_BLOCK))
3774 return PASS;
3775 else
3776 return FAIL;
3777}
3778
3779/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
3780* Function: GLOB_FTL_Flush_Cache
3781* Inputs: none
3782* Outputs: PASS=0 / FAIL=1
3783* Description: flush all the cache blocks to flash
3784* if a cache block is not dirty, don't do anything with it
3785* else, write the block and update the block table
3786* Note: This function should be called at shutdown/power down.
3787* to write important data into device
3788*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
3789int GLOB_FTL_Flush_Cache(void)
3790{
3791 int i, ret;
3792
3793 nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
3794 __FILE__, __LINE__, __func__);
3795
3796 for (i = 0; i < CACHE_ITEM_NUM; i++) {
3797 if (SET == Cache.array[i].changed) {
3798#if CMD_DMA
3799#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
3800 int_cache[ftl_cmd_cnt].item = i;
3801 int_cache[ftl_cmd_cnt].cache.address =
3802 Cache.array[i].address;
3803 int_cache[ftl_cmd_cnt].cache.changed = CLEAR;
3804#endif
3805#endif
3806 ret = write_back_to_l2_cache(Cache.array[i].buf, Cache.array[i].address);
3807 if (PASS == ret) {
3808 Cache.array[i].changed = CLEAR;
3809 } else {
3810 printk(KERN_ALERT "Failed when write back to L2 cache!\n");
3811 /* TODO - How to handle this? */
3812 }
3813 }
3814 }
3815
3816 flush_l2_cache();
3817
3818 return FTL_Write_Block_Table(FAIL);
3819}
3820
3821/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
3822* Function: GLOB_FTL_Page_Read
3823* Inputs: pointer to data
3824* logical address of data (u64 is LBA * Bytes/Page)
3825* Outputs: PASS=0 / FAIL=1
3826* Description: reads a page of data into RAM from the cache
3827* if the data is not already in cache, read from flash to cache
3828*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
3829int GLOB_FTL_Page_Read(u8 *data, u64 logical_addr)
3830{
3831 u16 cache_item;
3832 int res = PASS;
3833
3834 nand_dbg_print(NAND_DBG_DEBUG, "GLOB_FTL_Page_Read - "
3835 "page_addr: %llu\n", logical_addr);
3836
3837 cache_item = FTL_Cache_If_Hit(logical_addr);
3838
3839 if (UNHIT_CACHE_ITEM == cache_item) {
3840 nand_dbg_print(NAND_DBG_DEBUG,
3841 "GLOB_FTL_Page_Read: Cache not hit\n");
3842 res = FTL_Cache_Write();
3843 if (ERR == FTL_Cache_Read(logical_addr))
3844 res = ERR;
3845 cache_item = Cache.LRU;
3846 }
3847
3848 FTL_Cache_Read_Page(data, logical_addr, cache_item);
3849
3850 return res;
3851}
3852
3853/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
3854* Function: GLOB_FTL_Page_Write
3855* Inputs: pointer to data
3856* address of data (ADDRESSTYPE is LBA * Bytes/Page)
3857* Outputs: PASS=0 / FAIL=1
3858* Description: writes a page of data from RAM to the cache
3859* if the data is not already in cache, write back the
3860* least recently used block and read the addressed block
3861* from flash to cache
3862*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
3863int GLOB_FTL_Page_Write(u8 *pData, u64 dwPageAddr)
3864{
3865 u16 cache_blk;
3866 u32 *pbt = (u32 *)g_pBlockTable;
3867 int wResult = PASS;
3868
3869 nand_dbg_print(NAND_DBG_TRACE, "GLOB_FTL_Page_Write - "
3870 "dwPageAddr: %llu\n", dwPageAddr);
3871
3872 cache_blk = FTL_Cache_If_Hit(dwPageAddr);
3873
3874 if (UNHIT_CACHE_ITEM == cache_blk) {
3875 wResult = FTL_Cache_Write();
3876 if (IS_BAD_BLOCK(BLK_FROM_ADDR(dwPageAddr))) {
3877 wResult = FTL_Replace_Block(dwPageAddr);
3878 pbt[BLK_FROM_ADDR(dwPageAddr)] |= SPARE_BLOCK;
3879 if (wResult == FAIL)
3880 return FAIL;
3881 }
3882 if (ERR == FTL_Cache_Read(dwPageAddr))
3883 wResult = ERR;
3884 cache_blk = Cache.LRU;
3885 FTL_Cache_Write_Page(pData, dwPageAddr, cache_blk, 0);
3886 } else {
3887#if CMD_DMA
3888 FTL_Cache_Write_Page(pData, dwPageAddr, cache_blk,
3889 LLD_CMD_FLAG_ORDER_BEFORE_REST);
3890#else
3891 FTL_Cache_Write_Page(pData, dwPageAddr, cache_blk, 0);
3892#endif
3893 }
3894
3895 return wResult;
3896}
3897
3898/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
3899* Function: GLOB_FTL_Block_Erase
3900* Inputs: address of block to erase (now in byte format, should change to
3901* block format)
3902* Outputs: PASS=0 / FAIL=1
3903* Description: erases the specified block
3904* increments the erase count
3905* If erase count reaches its upper limit,call function to
3906* do the adjustment as per the relative erase count values
3907*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
3908int GLOB_FTL_Block_Erase(u64 blk_addr)
3909{
3910 int status;
3911 u32 BlkIdx;
3912
3913 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
3914 __FILE__, __LINE__, __func__);
3915
3916 BlkIdx = (u32)(blk_addr >> DeviceInfo.nBitsInBlockDataSize);
3917
3918 if (BlkIdx < DeviceInfo.wSpectraStartBlock) {
3919 printk(KERN_ERR "GLOB_FTL_Block_Erase: "
3920 "This should never occur\n");
3921 return FAIL;
3922 }
3923
3924#if CMD_DMA
3925 status = GLOB_LLD_Erase_Block_cdma(BlkIdx, LLD_CMD_FLAG_MODE_CDMA);
3926 if (status == FAIL)
3927 nand_dbg_print(NAND_DBG_WARN,
3928 "NAND Program fail in %s, Line %d, "
3929 "Function: %s, new Bad Block %d generated!\n",
3930 __FILE__, __LINE__, __func__, BlkIdx);
3931#else
3932 status = GLOB_LLD_Erase_Block(BlkIdx);
3933 if (status == FAIL) {
3934 nand_dbg_print(NAND_DBG_WARN,
3935 "NAND Program fail in %s, Line %d, "
3936 "Function: %s, new Bad Block %d generated!\n",
3937 __FILE__, __LINE__, __func__, BlkIdx);
3938 return status;
3939 }
3940#endif
3941
3942 if (DeviceInfo.MLCDevice) {
3943 g_pReadCounter[BlkIdx - DeviceInfo.wSpectraStartBlock] = 0;
3944 if (g_cBlockTableStatus != IN_PROGRESS_BLOCK_TABLE) {
3945 g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE;
3946 FTL_Write_IN_Progress_Block_Table_Page();
3947 }
3948 }
3949
3950 g_pWearCounter[BlkIdx - DeviceInfo.wSpectraStartBlock]++;
3951
3952#if CMD_DMA
3953 p_BTableChangesDelta =
3954 (struct BTableChangesDelta *)g_pBTDelta_Free;
3955 g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
3956 p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt;
3957 p_BTableChangesDelta->WC_Index =
3958 BlkIdx - DeviceInfo.wSpectraStartBlock;
3959 p_BTableChangesDelta->WC_Entry_Value =
3960 g_pWearCounter[BlkIdx - DeviceInfo.wSpectraStartBlock];
3961 p_BTableChangesDelta->ValidFields = 0x30;
3962
3963 if (DeviceInfo.MLCDevice) {
3964 p_BTableChangesDelta =
3965 (struct BTableChangesDelta *)g_pBTDelta_Free;
3966 g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
3967 p_BTableChangesDelta->ftl_cmd_cnt =
3968 ftl_cmd_cnt;
3969 p_BTableChangesDelta->RC_Index =
3970 BlkIdx - DeviceInfo.wSpectraStartBlock;
3971 p_BTableChangesDelta->RC_Entry_Value =
3972 g_pReadCounter[BlkIdx -
3973 DeviceInfo.wSpectraStartBlock];
3974 p_BTableChangesDelta->ValidFields = 0xC0;
3975 }
3976
3977 ftl_cmd_cnt++;
3978#endif
3979
3980 if (g_pWearCounter[BlkIdx - DeviceInfo.wSpectraStartBlock] == 0xFE)
3981 FTL_Adjust_Relative_Erase_Count(BlkIdx);
3982
3983 return status;
3984}
3985
3986
3987/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
3988* Function: FTL_Adjust_Relative_Erase_Count
3989* Inputs: index to block that was just incremented and is at the max
3990* Outputs: PASS=0 / FAIL=1
3991* Description: If any erase counts at MAX, adjusts erase count of every
3992* block by subtracting least worn
3993* counter from counter value of every entry in wear table
3994*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
3995static int FTL_Adjust_Relative_Erase_Count(u32 Index_of_MAX)
3996{
3997 u8 wLeastWornCounter = MAX_BYTE_VALUE;
3998 u8 wWearCounter;
3999 u32 i, wWearIndex;
4000 u32 *pbt = (u32 *)g_pBlockTable;
4001 int wResult = PASS;
4002
4003 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
4004 __FILE__, __LINE__, __func__);
4005
4006 for (i = 0; i < DeviceInfo.wDataBlockNum; i++) {
4007 if (IS_BAD_BLOCK(i))
4008 continue;
4009 wWearIndex = (u32)(pbt[i] & (~BAD_BLOCK));
4010
4011 if ((wWearIndex - DeviceInfo.wSpectraStartBlock) < 0)
4012 printk(KERN_ERR "FTL_Adjust_Relative_Erase_Count:"
4013 "This should never occur\n");
4014 wWearCounter = g_pWearCounter[wWearIndex -
4015 DeviceInfo.wSpectraStartBlock];
4016 if (wWearCounter < wLeastWornCounter)
4017 wLeastWornCounter = wWearCounter;
4018 }
4019
4020 if (wLeastWornCounter == 0) {
4021 nand_dbg_print(NAND_DBG_WARN,
4022 "Adjusting Wear Levelling Counters: Special Case\n");
4023 g_pWearCounter[Index_of_MAX -
4024 DeviceInfo.wSpectraStartBlock]--;
4025#if CMD_DMA
4026 p_BTableChangesDelta =
4027 (struct BTableChangesDelta *)g_pBTDelta_Free;
4028 g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
4029 p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt;
4030 p_BTableChangesDelta->WC_Index =
4031 Index_of_MAX - DeviceInfo.wSpectraStartBlock;
4032 p_BTableChangesDelta->WC_Entry_Value =
4033 g_pWearCounter[Index_of_MAX -
4034 DeviceInfo.wSpectraStartBlock];
4035 p_BTableChangesDelta->ValidFields = 0x30;
4036#endif
4037 FTL_Static_Wear_Leveling();
4038 } else {
4039 for (i = 0; i < DeviceInfo.wDataBlockNum; i++)
4040 if (!IS_BAD_BLOCK(i)) {
4041 wWearIndex = (u32)(pbt[i] & (~BAD_BLOCK));
4042 g_pWearCounter[wWearIndex -
4043 DeviceInfo.wSpectraStartBlock] =
4044 (u8)(g_pWearCounter
4045 [wWearIndex -
4046 DeviceInfo.wSpectraStartBlock] -
4047 wLeastWornCounter);
4048#if CMD_DMA
4049 p_BTableChangesDelta =
4050 (struct BTableChangesDelta *)g_pBTDelta_Free;
4051 g_pBTDelta_Free +=
4052 sizeof(struct BTableChangesDelta);
4053
4054 p_BTableChangesDelta->ftl_cmd_cnt =
4055 ftl_cmd_cnt;
4056 p_BTableChangesDelta->WC_Index = wWearIndex -
4057 DeviceInfo.wSpectraStartBlock;
4058 p_BTableChangesDelta->WC_Entry_Value =
4059 g_pWearCounter[wWearIndex -
4060 DeviceInfo.wSpectraStartBlock];
4061 p_BTableChangesDelta->ValidFields = 0x30;
4062#endif
4063 }
4064 }
4065
4066 return wResult;
4067}
4068
4069/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
4070* Function: FTL_Write_IN_Progress_Block_Table_Page
4071* Inputs: None
4072* Outputs: None
4073* Description: It writes in-progress flag page to the page next to
4074* block table
4075***********************************************************************/
4076static int FTL_Write_IN_Progress_Block_Table_Page(void)
4077{
4078 int wResult = PASS;
4079 u16 bt_pages;
4080 u16 dwIPFPageAddr;
4081#if CMD_DMA
4082#else
4083 u32 *pbt = (u32 *)g_pBlockTable;
4084 u32 wTempBlockTableIndex;
4085#endif
4086
4087 nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
4088 __FILE__, __LINE__, __func__);
4089
4090 bt_pages = FTL_Get_Block_Table_Flash_Size_Pages();
4091
4092 dwIPFPageAddr = g_wBlockTableOffset + bt_pages;
4093
4094 nand_dbg_print(NAND_DBG_DEBUG, "Writing IPF at "
4095 "Block %d Page %d\n",
4096 g_wBlockTableIndex, dwIPFPageAddr);
4097
4098#if CMD_DMA
4099 wResult = GLOB_LLD_Write_Page_Main_Spare_cdma(g_pIPF,
4100 g_wBlockTableIndex, dwIPFPageAddr, 1,
4101 LLD_CMD_FLAG_MODE_CDMA | LLD_CMD_FLAG_ORDER_BEFORE_REST);
4102 if (wResult == FAIL) {
4103 nand_dbg_print(NAND_DBG_WARN,
4104 "NAND Program fail in %s, Line %d, "
4105 "Function: %s, new Bad Block %d generated!\n",
4106 __FILE__, __LINE__, __func__,
4107 g_wBlockTableIndex);
4108 }
4109 g_wBlockTableOffset = dwIPFPageAddr + 1;
4110 p_BTableChangesDelta = (struct BTableChangesDelta *)g_pBTDelta_Free;
4111 g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
4112 p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt;
4113 p_BTableChangesDelta->g_wBlockTableOffset = g_wBlockTableOffset;
4114 p_BTableChangesDelta->ValidFields = 0x01;
4115 ftl_cmd_cnt++;
4116#else
4117 wResult = GLOB_LLD_Write_Page_Main_Spare(g_pIPF,
4118 g_wBlockTableIndex, dwIPFPageAddr, 1);
4119 if (wResult == FAIL) {
4120 nand_dbg_print(NAND_DBG_WARN,
4121 "NAND Program fail in %s, Line %d, "
4122 "Function: %s, new Bad Block %d generated!\n",
4123 __FILE__, __LINE__, __func__,
4124 (int)g_wBlockTableIndex);
4125 MARK_BLOCK_AS_BAD(pbt[BLOCK_TABLE_INDEX]);
4126 wTempBlockTableIndex = FTL_Replace_Block_Table();
4127 bt_block_changed = 1;
4128 if (BAD_BLOCK == wTempBlockTableIndex)
4129 return ERR;
4130 g_wBlockTableIndex = wTempBlockTableIndex;
4131 g_wBlockTableOffset = 0;
4132 /* Block table tag is '00'. Means it's used one */
4133 pbt[BLOCK_TABLE_INDEX] = g_wBlockTableIndex;
4134 return FAIL;
4135 }
4136 g_wBlockTableOffset = dwIPFPageAddr + 1;
4137#endif
4138 return wResult;
4139}
4140
4141/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
4142* Function: FTL_Read_Disturbance
4143* Inputs: block address
4144* Outputs: PASS=0 / FAIL=1
4145* Description: used to handle read disturbance. Data in block that
4146* reaches its read limit is moved to new block
4147*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
4148int FTL_Read_Disturbance(u32 blk_addr)
4149{
4150 int wResult = FAIL;
4151 u32 *pbt = (u32 *) g_pBlockTable;
4152 u32 dwOldBlockAddr = blk_addr;
4153 u32 wBlockNum;
4154 u32 i;
4155 u32 wLeastReadCounter = 0xFFFF;
4156 u32 wLeastReadIndex = BAD_BLOCK;
4157 u32 wSpareBlockNum = 0;
4158 u32 wTempNode;
4159 u32 wReplacedNode;
4160 u8 *g_pTempBuf;
4161
4162 nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
4163 __FILE__, __LINE__, __func__);
4164
4165#if CMD_DMA
4166 g_pTempBuf = cp_back_buf_copies[cp_back_buf_idx];
4167 cp_back_buf_idx++;
4168 if (cp_back_buf_idx > COPY_BACK_BUF_NUM) {
4169 printk(KERN_ERR "cp_back_buf_copies overflow! Exit."
4170 "Maybe too many pending commands in your CDMA chain.\n");
4171 return FAIL;
4172 }
4173#else
4174 g_pTempBuf = tmp_buf_read_disturbance;
4175#endif
4176
4177 wBlockNum = FTL_Get_Block_Index(blk_addr);
4178
4179 do {
4180 /* This is a bug.Here 'i' should be logical block number
4181 * and start from 1 (0 is reserved for block table).
4182 * Have fixed it. - Yunpeng 2008. 12. 19
4183 */
4184 for (i = 1; i < DeviceInfo.wDataBlockNum; i++) {
4185 if (IS_SPARE_BLOCK(i)) {
4186 u32 wPhysicalIndex =
4187 (u32)((~SPARE_BLOCK) & pbt[i]);
4188 if (g_pReadCounter[wPhysicalIndex -
4189 DeviceInfo.wSpectraStartBlock] <
4190 wLeastReadCounter) {
4191 wLeastReadCounter =
4192 g_pReadCounter[wPhysicalIndex -
4193 DeviceInfo.wSpectraStartBlock];
4194 wLeastReadIndex = i;
4195 }
4196 wSpareBlockNum++;
4197 }
4198 }
4199
4200 if (wSpareBlockNum <= NUM_FREE_BLOCKS_GATE) {
4201 wResult = GLOB_FTL_Garbage_Collection();
4202 if (PASS == wResult)
4203 continue;
4204 else
4205 break;
4206 } else {
4207 wTempNode = (u32)(DISCARD_BLOCK | pbt[wBlockNum]);
4208 wReplacedNode = (u32)((~SPARE_BLOCK) &
4209 pbt[wLeastReadIndex]);
4210#if CMD_DMA
4211 pbt[wBlockNum] = wReplacedNode;
4212 pbt[wLeastReadIndex] = wTempNode;
4213 p_BTableChangesDelta =
4214 (struct BTableChangesDelta *)g_pBTDelta_Free;
4215 g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
4216
4217 p_BTableChangesDelta->ftl_cmd_cnt =
4218 ftl_cmd_cnt;
4219 p_BTableChangesDelta->BT_Index = wBlockNum;
4220 p_BTableChangesDelta->BT_Entry_Value = pbt[wBlockNum];
4221 p_BTableChangesDelta->ValidFields = 0x0C;
4222
4223 p_BTableChangesDelta =
4224 (struct BTableChangesDelta *)g_pBTDelta_Free;
4225 g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
4226
4227 p_BTableChangesDelta->ftl_cmd_cnt =
4228 ftl_cmd_cnt;
4229 p_BTableChangesDelta->BT_Index = wLeastReadIndex;
4230 p_BTableChangesDelta->BT_Entry_Value =
4231 pbt[wLeastReadIndex];
4232 p_BTableChangesDelta->ValidFields = 0x0C;
4233
4234 wResult = GLOB_LLD_Read_Page_Main_cdma(g_pTempBuf,
4235 dwOldBlockAddr, 0, DeviceInfo.wPagesPerBlock,
4236 LLD_CMD_FLAG_MODE_CDMA);
4237 if (wResult == FAIL)
4238 return wResult;
4239
4240 ftl_cmd_cnt++;
4241
4242 if (wResult != FAIL) {
4243 if (FAIL == GLOB_LLD_Write_Page_Main_cdma(
4244 g_pTempBuf, pbt[wBlockNum], 0,
4245 DeviceInfo.wPagesPerBlock)) {
4246 nand_dbg_print(NAND_DBG_WARN,
4247 "NAND Program fail in "
4248 "%s, Line %d, Function: %s, "
4249 "new Bad Block %d "
4250 "generated!\n",
4251 __FILE__, __LINE__, __func__,
4252 (int)pbt[wBlockNum]);
4253 wResult = FAIL;
4254 MARK_BLOCK_AS_BAD(pbt[wBlockNum]);
4255 }
4256 ftl_cmd_cnt++;
4257 }
4258#else
4259 wResult = GLOB_LLD_Read_Page_Main(g_pTempBuf,
4260 dwOldBlockAddr, 0, DeviceInfo.wPagesPerBlock);
4261 if (wResult == FAIL)
4262 return wResult;
4263
4264 if (wResult != FAIL) {
4265 /* This is a bug. At this time, pbt[wBlockNum]
4266 is still the physical address of
4267 discard block, and should not be write.
4268 Have fixed it as below.
4269 -- Yunpeng 2008.12.19
4270 */
4271 wResult = GLOB_LLD_Write_Page_Main(g_pTempBuf,
4272 wReplacedNode, 0,
4273 DeviceInfo.wPagesPerBlock);
4274 if (wResult == FAIL) {
4275 nand_dbg_print(NAND_DBG_WARN,
4276 "NAND Program fail in "
4277 "%s, Line %d, Function: %s, "
4278 "new Bad Block %d "
4279 "generated!\n",
4280 __FILE__, __LINE__, __func__,
4281 (int)wReplacedNode);
4282 MARK_BLOCK_AS_BAD(wReplacedNode);
4283 } else {
4284 pbt[wBlockNum] = wReplacedNode;
4285 pbt[wLeastReadIndex] = wTempNode;
4286 }
4287 }
4288
4289 if ((wResult == PASS) && (g_cBlockTableStatus !=
4290 IN_PROGRESS_BLOCK_TABLE)) {
4291 g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE;
4292 FTL_Write_IN_Progress_Block_Table_Page();
4293 }
4294#endif
4295 }
4296 } while (wResult != PASS)
4297 ;
4298
4299#if CMD_DMA
4300 /* ... */
4301#endif
4302
4303 return wResult;
4304}
4305
diff --git a/drivers/staging/spectra/flash.h b/drivers/staging/spectra/flash.h
new file mode 100644
index 00000000000..e59cf4ede55
--- /dev/null
+++ b/drivers/staging/spectra/flash.h
@@ -0,0 +1,198 @@
1/*
2 * NAND Flash Controller Device Driver
3 * Copyright (c) 2009, Intel Corporation and its suppliers.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19
20#ifndef _FLASH_INTERFACE_
21#define _FLASH_INTERFACE_
22
23#include "ffsport.h"
24#include "spectraswconfig.h"
25
26#define MAX_BYTE_VALUE 0xFF
27#define MAX_WORD_VALUE 0xFFFF
28#define MAX_U32_VALUE 0xFFFFFFFF
29
30#define MAX_BLOCKNODE_VALUE 0xFFFFFF
31#define DISCARD_BLOCK 0x800000
32#define SPARE_BLOCK 0x400000
33#define BAD_BLOCK 0xC00000
34
35#define UNHIT_CACHE_ITEM 0xFFFF
36
37#define NAND_CACHE_INIT_ADDR 0xffffffffffffffffULL
38
39#define IN_PROGRESS_BLOCK_TABLE 0x00
40#define CURRENT_BLOCK_TABLE 0x01
41
42#define BTSIG_OFFSET (0)
43#define BTSIG_BYTES (5)
44#define BTSIG_DELTA (3)
45
46#define MAX_READ_COUNTER 0x2710
47
48#define FIRST_BT_ID (1)
49#define LAST_BT_ID (254)
50#define BTBLOCK_INVAL (u32)(0xFFFFFFFF)
51
52struct device_info_tag {
53 u16 wDeviceMaker;
54 u16 wDeviceID;
55 u32 wDeviceType;
56 u32 wSpectraStartBlock;
57 u32 wSpectraEndBlock;
58 u32 wTotalBlocks;
59 u16 wPagesPerBlock;
60 u16 wPageSize;
61 u16 wPageDataSize;
62 u16 wPageSpareSize;
63 u16 wNumPageSpareFlag;
64 u16 wECCBytesPerSector;
65 u32 wBlockSize;
66 u32 wBlockDataSize;
67 u32 wDataBlockNum;
68 u8 bPlaneNum;
69 u16 wDeviceMainAreaSize;
70 u16 wDeviceSpareAreaSize;
71 u16 wDevicesConnected;
72 u16 wDeviceWidth;
73 u16 wHWRevision;
74 u16 wHWFeatures;
75
76 u16 wONFIDevFeatures;
77 u16 wONFIOptCommands;
78 u16 wONFITimingMode;
79 u16 wONFIPgmCacheTimingMode;
80
81 u16 MLCDevice;
82 u16 wSpareSkipBytes;
83
84 u8 nBitsInPageNumber;
85 u8 nBitsInPageDataSize;
86 u8 nBitsInBlockDataSize;
87};
88
89extern struct device_info_tag DeviceInfo;
90
91/* Cache item format */
92struct flash_cache_item_tag {
93 u64 address;
94 u16 use_cnt;
95 u16 changed;
96 u8 *buf;
97};
98
99struct flash_cache_tag {
100 u32 cache_item_size; /* Size in bytes of each cache item */
101 u16 pages_per_item; /* How many NAND pages in each cache item */
102 u16 LRU; /* No. of the least recently used cache item */
103 struct flash_cache_item_tag array[CACHE_ITEM_NUM];
104};
105
106/*
107 *Data structure for each list node of the management table
108 * used for the Level 2 Cache. Each node maps one logical NAND block.
109 */
110struct spectra_l2_cache_list {
111 struct list_head list;
112 u32 logical_blk_num; /* Logical block number */
113 u32 pages_array[]; /* Page map array of this logical block.
114 * Array index is the logical block number,
115 * and for every item of this arry:
116 * high 16 bit is index of the L2 cache block num,
117 * low 16 bit is the phy page num
118 * of the above L2 cache block.
119 * This array will be kmalloc during run time.
120 */
121};
122
123struct spectra_l2_cache_info {
124 u32 blk_array[BLK_NUM_FOR_L2_CACHE];
125 u16 cur_blk_idx; /* idx to the phy block number of current using */
126 u16 cur_page_num; /* pages number of current using */
127 struct spectra_l2_cache_list table; /* First node of the table */
128};
129
130#define RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE 1
131
132#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
133struct flash_cache_mod_item_tag {
134 u64 address;
135 u8 changed;
136};
137
138struct flash_cache_delta_list_tag {
139 u8 item; /* used cache item */
140 struct flash_cache_mod_item_tag cache;
141};
142#endif
143
144extern struct flash_cache_tag Cache;
145
146extern u8 *buf_read_page_main_spare;
147extern u8 *buf_write_page_main_spare;
148extern u8 *buf_read_page_spare;
149extern u8 *buf_get_bad_block;
150extern u8 *cdma_desc_buf;
151extern u8 *memcp_desc_buf;
152
153/* struture used for IndentfyDevice function */
154struct spectra_indentfy_dev_tag {
155 u32 NumBlocks;
156 u16 PagesPerBlock;
157 u16 PageDataSize;
158 u16 wECCBytesPerSector;
159 u32 wDataBlockNum;
160};
161
162int GLOB_FTL_Flash_Init(void);
163int GLOB_FTL_Flash_Release(void);
164/*void GLOB_FTL_Erase_Flash(void);*/
165int GLOB_FTL_Block_Erase(u64 block_addr);
166int GLOB_FTL_Is_BadBlock(u32 block_num);
167int GLOB_FTL_IdentifyDevice(struct spectra_indentfy_dev_tag *dev_data);
168int GLOB_FTL_Event_Status(int *);
169u16 glob_ftl_execute_cmds(void);
170
171/*int FTL_Read_Disturbance(ADDRESSTYPE dwBlockAddr);*/
172int FTL_Read_Disturbance(u32 dwBlockAddr);
173
174/*Flash r/w based on cache*/
175int GLOB_FTL_Page_Read(u8 *read_data, u64 page_addr);
176int GLOB_FTL_Page_Write(u8 *write_data, u64 page_addr);
177int GLOB_FTL_Wear_Leveling(void);
178int GLOB_FTL_Flash_Format(void);
179int GLOB_FTL_Init(void);
180int GLOB_FTL_Flush_Cache(void);
181int GLOB_FTL_Garbage_Collection(void);
182int GLOB_FTL_BT_Garbage_Collection(void);
183void GLOB_FTL_Cache_Release(void);
184u8 *get_blk_table_start_addr(void);
185u8 *get_wear_leveling_table_start_addr(void);
186unsigned long get_blk_table_len(void);
187unsigned long get_wear_leveling_table_len(void);
188
189#if DEBUG_BNDRY
190void debug_boundary_lineno_error(int chnl, int limit, int no, int lineno,
191 char *filename);
192#define debug_boundary_error(chnl, limit, no) debug_boundary_lineno_error(chnl,\
193 limit, no, __LINE__, __FILE__)
194#else
195#define debug_boundary_error(chnl, limit, no) ;
196#endif
197
198#endif /*_FLASH_INTERFACE_*/
diff --git a/drivers/staging/spectra/lld.c b/drivers/staging/spectra/lld.c
new file mode 100644
index 00000000000..5c3b9762dc3
--- /dev/null
+++ b/drivers/staging/spectra/lld.c
@@ -0,0 +1,339 @@
1/*
2 * NAND Flash Controller Device Driver
3 * Copyright (c) 2009, Intel Corporation and its suppliers.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19
20#include "spectraswconfig.h"
21#include "ffsport.h"
22#include "ffsdefs.h"
23#include "lld.h"
24#include "lld_nand.h"
25
26/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
27#if FLASH_EMU /* vector all the LLD calls to the LLD_EMU code */
28#include "lld_emu.h"
29#include "lld_cdma.h"
30
31/* common functions: */
32u16 GLOB_LLD_Flash_Reset(void)
33{
34 return emu_Flash_Reset();
35}
36
37u16 GLOB_LLD_Read_Device_ID(void)
38{
39 return emu_Read_Device_ID();
40}
41
42int GLOB_LLD_Flash_Release(void)
43{
44 return emu_Flash_Release();
45}
46
47u16 GLOB_LLD_Flash_Init(void)
48{
49 return emu_Flash_Init();
50}
51
52u16 GLOB_LLD_Erase_Block(u32 block_add)
53{
54 return emu_Erase_Block(block_add);
55}
56
57u16 GLOB_LLD_Write_Page_Main(u8 *write_data, u32 block, u16 Page,
58 u16 PageCount)
59{
60 return emu_Write_Page_Main(write_data, block, Page, PageCount);
61}
62
63u16 GLOB_LLD_Read_Page_Main(u8 *read_data, u32 block, u16 Page,
64 u16 PageCount)
65{
66 return emu_Read_Page_Main(read_data, block, Page, PageCount);
67}
68
69u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data,
70 u32 block, u16 page, u16 page_count)
71{
72 return emu_Read_Page_Main(read_data, block, page, page_count);
73}
74
75u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data, u32 block,
76 u16 Page, u16 PageCount)
77{
78 return emu_Write_Page_Main_Spare(write_data, block, Page, PageCount);
79}
80
81u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data, u32 block,
82 u16 Page, u16 PageCount)
83{
84 return emu_Read_Page_Main_Spare(read_data, block, Page, PageCount);
85}
86
87u16 GLOB_LLD_Write_Page_Spare(u8 *write_data, u32 block, u16 Page,
88 u16 PageCount)
89{
90 return emu_Write_Page_Spare(write_data, block, Page, PageCount);
91}
92
93u16 GLOB_LLD_Read_Page_Spare(u8 *read_data, u32 block, u16 Page,
94 u16 PageCount)
95{
96 return emu_Read_Page_Spare(read_data, block, Page, PageCount);
97}
98
99u16 GLOB_LLD_Get_Bad_Block(u32 block)
100{
101 return emu_Get_Bad_Block(block);
102}
103
104#endif /* FLASH_EMU */
105
106/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
107#if FLASH_MTD /* vector all the LLD calls to the LLD_MTD code */
108#include "lld_mtd.h"
109#include "lld_cdma.h"
110
111/* common functions: */
112u16 GLOB_LLD_Flash_Reset(void)
113{
114 return mtd_Flash_Reset();
115}
116
117u16 GLOB_LLD_Read_Device_ID(void)
118{
119 return mtd_Read_Device_ID();
120}
121
122int GLOB_LLD_Flash_Release(void)
123{
124 return mtd_Flash_Release();
125}
126
127u16 GLOB_LLD_Flash_Init(void)
128{
129 return mtd_Flash_Init();
130}
131
132u16 GLOB_LLD_Erase_Block(u32 block_add)
133{
134 return mtd_Erase_Block(block_add);
135}
136
137u16 GLOB_LLD_Write_Page_Main(u8 *write_data, u32 block, u16 Page,
138 u16 PageCount)
139{
140 return mtd_Write_Page_Main(write_data, block, Page, PageCount);
141}
142
143u16 GLOB_LLD_Read_Page_Main(u8 *read_data, u32 block, u16 Page,
144 u16 PageCount)
145{
146 return mtd_Read_Page_Main(read_data, block, Page, PageCount);
147}
148
149u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data,
150 u32 block, u16 page, u16 page_count)
151{
152 return mtd_Read_Page_Main(read_data, block, page, page_count);
153}
154
155u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data, u32 block,
156 u16 Page, u16 PageCount)
157{
158 return mtd_Write_Page_Main_Spare(write_data, block, Page, PageCount);
159}
160
161u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data, u32 block,
162 u16 Page, u16 PageCount)
163{
164 return mtd_Read_Page_Main_Spare(read_data, block, Page, PageCount);
165}
166
167u16 GLOB_LLD_Write_Page_Spare(u8 *write_data, u32 block, u16 Page,
168 u16 PageCount)
169{
170 return mtd_Write_Page_Spare(write_data, block, Page, PageCount);
171}
172
173u16 GLOB_LLD_Read_Page_Spare(u8 *read_data, u32 block, u16 Page,
174 u16 PageCount)
175{
176 return mtd_Read_Page_Spare(read_data, block, Page, PageCount);
177}
178
179u16 GLOB_LLD_Get_Bad_Block(u32 block)
180{
181 return mtd_Get_Bad_Block(block);
182}
183
184#endif /* FLASH_MTD */
185
186/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
187#if FLASH_NAND /* vector all the LLD calls to the NAND controller code */
188#include "lld_nand.h"
189#include "lld_cdma.h"
190#include "flash.h"
191
192/* common functions for LLD_NAND */
193void GLOB_LLD_ECC_Control(int enable)
194{
195 NAND_ECC_Ctrl(enable);
196}
197
198/* common functions for LLD_NAND */
199u16 GLOB_LLD_Flash_Reset(void)
200{
201 return NAND_Flash_Reset();
202}
203
204u16 GLOB_LLD_Read_Device_ID(void)
205{
206 return NAND_Read_Device_ID();
207}
208
209u16 GLOB_LLD_UnlockArrayAll(void)
210{
211 return NAND_UnlockArrayAll();
212}
213
214u16 GLOB_LLD_Flash_Init(void)
215{
216 return NAND_Flash_Init();
217}
218
219int GLOB_LLD_Flash_Release(void)
220{
221 return nand_release_spectra();
222}
223
224u16 GLOB_LLD_Erase_Block(u32 block_add)
225{
226 return NAND_Erase_Block(block_add);
227}
228
229
230u16 GLOB_LLD_Write_Page_Main(u8 *write_data, u32 block, u16 Page,
231 u16 PageCount)
232{
233 return NAND_Write_Page_Main(write_data, block, Page, PageCount);
234}
235
236u16 GLOB_LLD_Read_Page_Main(u8 *read_data, u32 block, u16 page,
237 u16 page_count)
238{
239 if (page_count == 1) /* Using polling to improve read speed */
240 return NAND_Read_Page_Main_Polling(read_data, block, page, 1);
241 else
242 return NAND_Read_Page_Main(read_data, block, page, page_count);
243}
244
245u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data,
246 u32 block, u16 page, u16 page_count)
247{
248 return NAND_Read_Page_Main_Polling(read_data,
249 block, page, page_count);
250}
251
252u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data, u32 block,
253 u16 Page, u16 PageCount)
254{
255 return NAND_Write_Page_Main_Spare(write_data, block, Page, PageCount);
256}
257
258u16 GLOB_LLD_Write_Page_Spare(u8 *write_data, u32 block, u16 Page,
259 u16 PageCount)
260{
261 return NAND_Write_Page_Spare(write_data, block, Page, PageCount);
262}
263
264u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data, u32 block,
265 u16 page, u16 page_count)
266{
267 return NAND_Read_Page_Main_Spare(read_data, block, page, page_count);
268}
269
270u16 GLOB_LLD_Read_Page_Spare(u8 *read_data, u32 block, u16 Page,
271 u16 PageCount)
272{
273 return NAND_Read_Page_Spare(read_data, block, Page, PageCount);
274}
275
276u16 GLOB_LLD_Get_Bad_Block(u32 block)
277{
278 return NAND_Get_Bad_Block(block);
279}
280
281#if CMD_DMA
282u16 GLOB_LLD_Event_Status(void)
283{
284 return CDMA_Event_Status();
285}
286
287u16 glob_lld_execute_cmds(void)
288{
289 return CDMA_Execute_CMDs();
290}
291
292u16 GLOB_LLD_MemCopy_CMD(u8 *dest, u8 *src,
293 u32 ByteCount, u16 flag)
294{
295 /* Replace the hardware memcopy with software memcpy function */
296 if (CDMA_Execute_CMDs())
297 return FAIL;
298 memcpy(dest, src, ByteCount);
299 return PASS;
300
301 /* return CDMA_MemCopy_CMD(dest, src, ByteCount, flag); */
302}
303
304u16 GLOB_LLD_Erase_Block_cdma(u32 block, u16 flags)
305{
306 return CDMA_Data_CMD(ERASE_CMD, 0, block, 0, 0, flags);
307}
308
309u16 GLOB_LLD_Write_Page_Main_cdma(u8 *data, u32 block, u16 page, u16 count)
310{
311 return CDMA_Data_CMD(WRITE_MAIN_CMD, data, block, page, count, 0);
312}
313
314u16 GLOB_LLD_Read_Page_Main_cdma(u8 *data, u32 block, u16 page,
315 u16 count, u16 flags)
316{
317 return CDMA_Data_CMD(READ_MAIN_CMD, data, block, page, count, flags);
318}
319
320u16 GLOB_LLD_Write_Page_Main_Spare_cdma(u8 *data, u32 block, u16 page,
321 u16 count, u16 flags)
322{
323 return CDMA_Data_CMD(WRITE_MAIN_SPARE_CMD,
324 data, block, page, count, flags);
325}
326
327u16 GLOB_LLD_Read_Page_Main_Spare_cdma(u8 *data,
328 u32 block, u16 page, u16 count)
329{
330 return CDMA_Data_CMD(READ_MAIN_SPARE_CMD, data, block, page, count,
331 LLD_CMD_FLAG_MODE_CDMA);
332}
333
334#endif /* CMD_DMA */
335#endif /* FLASH_NAND */
336
337/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
338
339/* end of LLD.c */
diff --git a/drivers/staging/spectra/lld.h b/drivers/staging/spectra/lld.h
new file mode 100644
index 00000000000..d3738e0e1fe
--- /dev/null
+++ b/drivers/staging/spectra/lld.h
@@ -0,0 +1,111 @@
1/*
2 * NAND Flash Controller Device Driver
3 * Copyright (c) 2009, Intel Corporation and its suppliers.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19
20
21
22#ifndef _LLD_
23#define _LLD_
24
25#include "ffsport.h"
26#include "spectraswconfig.h"
27#include "flash.h"
28
29#define GOOD_BLOCK 0
30#define DEFECTIVE_BLOCK 1
31#define READ_ERROR 2
32
33#define CLK_X 5
34#define CLK_MULTI 4
35
36/* Typedefs */
37
38/* prototypes: API for LLD */
39/* Currently, Write_Page_Main
40 * MemCopy
41 * Read_Page_Main_Spare
42 * do not have flag because they were not implemented prior to this
43 * They are not being added to keep changes to a minimum for now.
44 * Currently, they are not required (only reqd for Wr_P_M_S.)
45 * Later on, these NEED to be changed.
46 */
47
48extern void GLOB_LLD_ECC_Control(int enable);
49
50extern u16 GLOB_LLD_Flash_Reset(void);
51
52extern u16 GLOB_LLD_Read_Device_ID(void);
53
54extern u16 GLOB_LLD_UnlockArrayAll(void);
55
56extern u16 GLOB_LLD_Flash_Init(void);
57
58extern int GLOB_LLD_Flash_Release(void);
59
60extern u16 GLOB_LLD_Erase_Block(u32 block_add);
61
62extern u16 GLOB_LLD_Write_Page_Main(u8 *write_data,
63 u32 block, u16 Page, u16 PageCount);
64
65extern u16 GLOB_LLD_Read_Page_Main(u8 *read_data,
66 u32 block, u16 page, u16 page_count);
67
68extern u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data,
69 u32 block, u16 page, u16 page_count);
70
71extern u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data,
72 u32 block, u16 Page, u16 PageCount);
73
74extern u16 GLOB_LLD_Write_Page_Spare(u8 *write_data,
75 u32 block, u16 Page, u16 PageCount);
76
77extern u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data,
78 u32 block, u16 page, u16 page_count);
79
80extern u16 GLOB_LLD_Read_Page_Spare(u8 *read_data,
81 u32 block, u16 Page, u16 PageCount);
82
83extern u16 GLOB_LLD_Get_Bad_Block(u32 block);
84
85extern u16 GLOB_LLD_Event_Status(void);
86
87extern u16 GLOB_LLD_MemCopy_CMD(u8 *dest, u8 *src, u32 ByteCount, u16 flag);
88
89extern u16 glob_lld_execute_cmds(void);
90
91extern u16 GLOB_LLD_Erase_Block_cdma(u32 block, u16 flags);
92
93extern u16 GLOB_LLD_Write_Page_Main_cdma(u8 *data,
94 u32 block, u16 page, u16 count);
95
96extern u16 GLOB_LLD_Read_Page_Main_cdma(u8 *data,
97 u32 block, u16 page, u16 count, u16 flags);
98
99extern u16 GLOB_LLD_Write_Page_Main_Spare_cdma(u8 *data,
100 u32 block, u16 page, u16 count, u16 flags);
101
102extern u16 GLOB_LLD_Read_Page_Main_Spare_cdma(u8 *data,
103 u32 block, u16 page, u16 count);
104
105#define LLD_CMD_FLAG_ORDER_BEFORE_REST (0x1)
106#define LLD_CMD_FLAG_MODE_CDMA (0x8)
107
108
109#endif /*_LLD_ */
110
111
diff --git a/drivers/staging/spectra/lld_cdma.c b/drivers/staging/spectra/lld_cdma.c
new file mode 100644
index 00000000000..c6e76103d43
--- /dev/null
+++ b/drivers/staging/spectra/lld_cdma.c
@@ -0,0 +1,910 @@
1/*
2 * NAND Flash Controller Device Driver
3 * Copyright (c) 2009, Intel Corporation and its suppliers.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19
20#include <linux/fs.h>
21#include <linux/slab.h>
22
23#include "spectraswconfig.h"
24#include "lld.h"
25#include "lld_nand.h"
26#include "lld_cdma.h"
27#include "lld_emu.h"
28#include "flash.h"
29#include "nand_regs.h"
30
31#define MAX_PENDING_CMDS 4
32#define MODE_02 (0x2 << 26)
33
34/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
35* Function: CDMA_Data_Cmd
36* Inputs: cmd code (aligned for hw)
37* data: pointer to source or destination
38* block: block address
39* page: page address
40* num: num pages to transfer
41* Outputs: PASS
42* Description: This function takes the parameters and puts them
43* into the "pending commands" array.
44* It does not parse or validate the parameters.
45* The array index is same as the tag.
46*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
47u16 CDMA_Data_CMD(u8 cmd, u8 *data, u32 block, u16 page, u16 num, u16 flags)
48{
49 u8 bank;
50
51 nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
52 __FILE__, __LINE__, __func__);
53
54 if (0 == cmd)
55 nand_dbg_print(NAND_DBG_DEBUG,
56 "%s, Line %d, Illegal cmd (0)\n", __FILE__, __LINE__);
57
58 /* If a command of another bank comes, then first execute */
59 /* pending commands of the current bank, then set the new */
60 /* bank as current bank */
61 bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
62 if (bank != info.flash_bank) {
63 nand_dbg_print(NAND_DBG_WARN,
64 "Will access new bank. old bank: %d, new bank: %d\n",
65 info.flash_bank, bank);
66 if (CDMA_Execute_CMDs()) {
67 printk(KERN_ERR "CDMA_Execute_CMDs fail!\n");
68 return FAIL;
69 }
70 info.flash_bank = bank;
71 }
72
73 info.pcmds[info.pcmds_num].CMD = cmd;
74 info.pcmds[info.pcmds_num].DataAddr = data;
75 info.pcmds[info.pcmds_num].Block = block;
76 info.pcmds[info.pcmds_num].Page = page;
77 info.pcmds[info.pcmds_num].PageCount = num;
78 info.pcmds[info.pcmds_num].DataDestAddr = 0;
79 info.pcmds[info.pcmds_num].DataSrcAddr = 0;
80 info.pcmds[info.pcmds_num].MemCopyByteCnt = 0;
81 info.pcmds[info.pcmds_num].Flags = flags;
82 info.pcmds[info.pcmds_num].Status = 0xB0B;
83
84 switch (cmd) {
85 case WRITE_MAIN_SPARE_CMD:
86 Conv_Main_Spare_Data_Log2Phy_Format(data, num);
87 break;
88 case WRITE_SPARE_CMD:
89 Conv_Spare_Data_Log2Phy_Format(data);
90 break;
91 default:
92 break;
93 }
94
95 info.pcmds_num++;
96
97 if (info.pcmds_num >= MAX_PENDING_CMDS) {
98 if (CDMA_Execute_CMDs()) {
99 printk(KERN_ERR "CDMA_Execute_CMDs fail!\n");
100 return FAIL;
101 }
102 }
103
104 return PASS;
105}
106
107/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
108* Function: CDMA_MemCopy_CMD
109* Inputs: dest: pointer to destination
110* src: pointer to source
111* count: num bytes to transfer
112* Outputs: PASS
113* Description: This function takes the parameters and puts them
114* into the "pending commands" array.
115* It does not parse or validate the parameters.
116* The array index is same as the tag.
117*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
118u16 CDMA_MemCopy_CMD(u8 *dest, u8 *src, u32 byte_cnt, u16 flags)
119{
120 nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
121 __FILE__, __LINE__, __func__);
122
123 info.pcmds[info.pcmds_num].CMD = MEMCOPY_CMD;
124 info.pcmds[info.pcmds_num].DataAddr = 0;
125 info.pcmds[info.pcmds_num].Block = 0;
126 info.pcmds[info.pcmds_num].Page = 0;
127 info.pcmds[info.pcmds_num].PageCount = 0;
128 info.pcmds[info.pcmds_num].DataDestAddr = dest;
129 info.pcmds[info.pcmds_num].DataSrcAddr = src;
130 info.pcmds[info.pcmds_num].MemCopyByteCnt = byte_cnt;
131 info.pcmds[info.pcmds_num].Flags = flags;
132 info.pcmds[info.pcmds_num].Status = 0xB0B;
133
134 info.pcmds_num++;
135
136 if (info.pcmds_num >= MAX_PENDING_CMDS) {
137 if (CDMA_Execute_CMDs()) {
138 printk(KERN_ERR "CDMA_Execute_CMDs fail!\n");
139 return FAIL;
140 }
141 }
142
143 return PASS;
144}
145
146#if 0
147/* Prints the PendingCMDs array */
148void print_pending_cmds(void)
149{
150 u16 i;
151
152 nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
153 __FILE__, __LINE__, __func__);
154
155 for (i = 0; i < info.pcmds_num; i++) {
156 nand_dbg_print(NAND_DBG_DEBUG, "\ni: %d\n", i);
157 switch (info.pcmds[i].CMD) {
158 case ERASE_CMD:
159 nand_dbg_print(NAND_DBG_DEBUG,
160 "Erase Command (0x%x)\n",
161 info.pcmds[i].CMD);
162 break;
163 case WRITE_MAIN_CMD:
164 nand_dbg_print(NAND_DBG_DEBUG,
165 "Write Main Command (0x%x)\n",
166 info.pcmds[i].CMD);
167 break;
168 case WRITE_MAIN_SPARE_CMD:
169 nand_dbg_print(NAND_DBG_DEBUG,
170 "Write Main Spare Command (0x%x)\n",
171 info.pcmds[i].CMD);
172 break;
173 case READ_MAIN_SPARE_CMD:
174 nand_dbg_print(NAND_DBG_DEBUG,
175 "Read Main Spare Command (0x%x)\n",
176 info.pcmds[i].CMD);
177 break;
178 case READ_MAIN_CMD:
179 nand_dbg_print(NAND_DBG_DEBUG,
180 "Read Main Command (0x%x)\n",
181 info.pcmds[i].CMD);
182 break;
183 case MEMCOPY_CMD:
184 nand_dbg_print(NAND_DBG_DEBUG,
185 "Memcopy Command (0x%x)\n",
186 info.pcmds[i].CMD);
187 break;
188 case DUMMY_CMD:
189 nand_dbg_print(NAND_DBG_DEBUG,
190 "Dummy Command (0x%x)\n",
191 info.pcmds[i].CMD);
192 break;
193 default:
194 nand_dbg_print(NAND_DBG_DEBUG,
195 "Illegal Command (0x%x)\n",
196 info.pcmds[i].CMD);
197 break;
198 }
199
200 nand_dbg_print(NAND_DBG_DEBUG, "DataAddr: 0x%x\n",
201 (u32)info.pcmds[i].DataAddr);
202 nand_dbg_print(NAND_DBG_DEBUG, "Block: %d\n",
203 info.pcmds[i].Block);
204 nand_dbg_print(NAND_DBG_DEBUG, "Page: %d\n",
205 info.pcmds[i].Page);
206 nand_dbg_print(NAND_DBG_DEBUG, "PageCount: %d\n",
207 info.pcmds[i].PageCount);
208 nand_dbg_print(NAND_DBG_DEBUG, "DataDestAddr: 0x%x\n",
209 (u32)info.pcmds[i].DataDestAddr);
210 nand_dbg_print(NAND_DBG_DEBUG, "DataSrcAddr: 0x%x\n",
211 (u32)info.pcmds[i].DataSrcAddr);
212 nand_dbg_print(NAND_DBG_DEBUG, "MemCopyByteCnt: %d\n",
213 info.pcmds[i].MemCopyByteCnt);
214 nand_dbg_print(NAND_DBG_DEBUG, "Flags: 0x%x\n",
215 info.pcmds[i].Flags);
216 nand_dbg_print(NAND_DBG_DEBUG, "Status: 0x%x\n",
217 info.pcmds[i].Status);
218 }
219}
220
221/* Print the CDMA descriptors */
222void print_cdma_descriptors(void)
223{
224 struct cdma_descriptor *pc;
225 int i;
226
227 pc = (struct cdma_descriptor *)info.cdma_desc_buf;
228
229 nand_dbg_print(NAND_DBG_DEBUG, "\nWill dump cdma descriptors:\n");
230
231 for (i = 0; i < info.cdma_num; i++) {
232 nand_dbg_print(NAND_DBG_DEBUG, "\ni: %d\n", i);
233 nand_dbg_print(NAND_DBG_DEBUG,
234 "NxtPointerHi: 0x%x, NxtPointerLo: 0x%x\n",
235 pc[i].NxtPointerHi, pc[i].NxtPointerLo);
236 nand_dbg_print(NAND_DBG_DEBUG,
237 "FlashPointerHi: 0x%x, FlashPointerLo: 0x%x\n",
238 pc[i].FlashPointerHi, pc[i].FlashPointerLo);
239 nand_dbg_print(NAND_DBG_DEBUG, "CommandType: 0x%x\n",
240 pc[i].CommandType);
241 nand_dbg_print(NAND_DBG_DEBUG,
242 "MemAddrHi: 0x%x, MemAddrLo: 0x%x\n",
243 pc[i].MemAddrHi, pc[i].MemAddrLo);
244 nand_dbg_print(NAND_DBG_DEBUG, "CommandFlags: 0x%x\n",
245 pc[i].CommandFlags);
246 nand_dbg_print(NAND_DBG_DEBUG, "Channel: %d, Status: 0x%x\n",
247 pc[i].Channel, pc[i].Status);
248 nand_dbg_print(NAND_DBG_DEBUG,
249 "MemCopyPointerHi: 0x%x, MemCopyPointerLo: 0x%x\n",
250 pc[i].MemCopyPointerHi, pc[i].MemCopyPointerLo);
251 nand_dbg_print(NAND_DBG_DEBUG,
252 "Reserved12: 0x%x, Reserved13: 0x%x, "
253 "Reserved14: 0x%x, pcmd: %d\n",
254 pc[i].Reserved12, pc[i].Reserved13,
255 pc[i].Reserved14, pc[i].pcmd);
256 }
257}
258
259/* Print the Memory copy descriptors */
260static void print_memcp_descriptors(void)
261{
262 struct memcpy_descriptor *pm;
263 int i;
264
265 pm = (struct memcpy_descriptor *)info.memcp_desc_buf;
266
267 nand_dbg_print(NAND_DBG_DEBUG, "\nWill dump mem_cpy descriptors:\n");
268
269 for (i = 0; i < info.cdma_num; i++) {
270 nand_dbg_print(NAND_DBG_DEBUG, "\ni: %d\n", i);
271 nand_dbg_print(NAND_DBG_DEBUG,
272 "NxtPointerHi: 0x%x, NxtPointerLo: 0x%x\n",
273 pm[i].NxtPointerHi, pm[i].NxtPointerLo);
274 nand_dbg_print(NAND_DBG_DEBUG,
275 "SrcAddrHi: 0x%x, SrcAddrLo: 0x%x\n",
276 pm[i].SrcAddrHi, pm[i].SrcAddrLo);
277 nand_dbg_print(NAND_DBG_DEBUG,
278 "DestAddrHi: 0x%x, DestAddrLo: 0x%x\n",
279 pm[i].DestAddrHi, pm[i].DestAddrLo);
280 nand_dbg_print(NAND_DBG_DEBUG, "XferSize: %d\n",
281 pm[i].XferSize);
282 nand_dbg_print(NAND_DBG_DEBUG, "MemCopyFlags: 0x%x\n",
283 pm[i].MemCopyFlags);
284 nand_dbg_print(NAND_DBG_DEBUG, "MemCopyStatus: %d\n",
285 pm[i].MemCopyStatus);
286 nand_dbg_print(NAND_DBG_DEBUG, "reserved9: 0x%x\n",
287 pm[i].reserved9);
288 nand_dbg_print(NAND_DBG_DEBUG, "reserved10: 0x%x\n",
289 pm[i].reserved10);
290 nand_dbg_print(NAND_DBG_DEBUG, "reserved11: 0x%x\n",
291 pm[i].reserved11);
292 nand_dbg_print(NAND_DBG_DEBUG, "reserved12: 0x%x\n",
293 pm[i].reserved12);
294 nand_dbg_print(NAND_DBG_DEBUG, "reserved13: 0x%x\n",
295 pm[i].reserved13);
296 nand_dbg_print(NAND_DBG_DEBUG, "reserved14: 0x%x\n",
297 pm[i].reserved14);
298 nand_dbg_print(NAND_DBG_DEBUG, "reserved15: 0x%x\n",
299 pm[i].reserved15);
300 }
301}
302#endif
303
304/* Reset cdma_descriptor chain to 0 */
305static void reset_cdma_desc(int i)
306{
307 struct cdma_descriptor *ptr;
308
309 BUG_ON(i >= MAX_DESCS);
310
311 ptr = (struct cdma_descriptor *)info.cdma_desc_buf;
312
313 ptr[i].NxtPointerHi = 0;
314 ptr[i].NxtPointerLo = 0;
315 ptr[i].FlashPointerHi = 0;
316 ptr[i].FlashPointerLo = 0;
317 ptr[i].CommandType = 0;
318 ptr[i].MemAddrHi = 0;
319 ptr[i].MemAddrLo = 0;
320 ptr[i].CommandFlags = 0;
321 ptr[i].Channel = 0;
322 ptr[i].Status = 0;
323 ptr[i].MemCopyPointerHi = 0;
324 ptr[i].MemCopyPointerLo = 0;
325}
326
327/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
328* Function: CDMA_UpdateEventStatus
329* Inputs: none
330* Outputs: none
331* Description: This function update the event status of all the channels
332* when an error condition is reported.
333*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
334void CDMA_UpdateEventStatus(void)
335{
336 int i, j, active_chan;
337 struct cdma_descriptor *ptr;
338
339 nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
340 __FILE__, __LINE__, __func__);
341
342 ptr = (struct cdma_descriptor *)info.cdma_desc_buf;
343
344 for (j = 0; j < info.cdma_num; j++) {
345 /* Check for the descriptor with failure */
346 if ((ptr[j].Status & CMD_DMA_DESC_FAIL))
347 break;
348
349 }
350
351 /* All the previous cmd's status for this channel must be good */
352 for (i = 0; i < j; i++) {
353 if (ptr[i].pcmd != 0xff)
354 info.pcmds[ptr[i].pcmd].Status = CMD_PASS;
355 }
356
357 /* Abort the channel with type 0 reset command. It resets the */
358 /* selected channel after the descriptor completes the flash */
359 /* operation and status has been updated for the descriptor. */
360 /* Memory Copy and Sync associated with this descriptor will */
361 /* not be executed */
362 active_chan = ioread32(FlashReg + CHNL_ACTIVE);
363 if ((active_chan & (1 << info.flash_bank)) == (1 << info.flash_bank)) {
364 iowrite32(MODE_02 | (0 << 4), FlashMem); /* Type 0 reset */
365 iowrite32((0xF << 4) | info.flash_bank, FlashMem + 0x10);
366 } else { /* Should not reached here */
367 printk(KERN_ERR "Error! Used bank is not set in"
368 " reg CHNL_ACTIVE\n");
369 }
370}
371
372static void cdma_trans(u16 chan)
373{
374 u32 addr;
375
376 addr = info.cdma_desc;
377
378 iowrite32(MODE_10 | (chan << 24), FlashMem);
379 iowrite32((1 << 7) | chan, FlashMem + 0x10);
380
381 iowrite32(MODE_10 | (chan << 24) | ((0x0FFFF & (addr >> 16)) << 8),
382 FlashMem);
383 iowrite32((1 << 7) | (1 << 4) | 0, FlashMem + 0x10);
384
385 iowrite32(MODE_10 | (chan << 24) | ((0x0FFFF & addr) << 8), FlashMem);
386 iowrite32((1 << 7) | (1 << 5) | 0, FlashMem + 0x10);
387
388 iowrite32(MODE_10 | (chan << 24), FlashMem);
389 iowrite32((1 << 7) | (1 << 5) | (1 << 4) | 0, FlashMem + 0x10);
390}
391
392/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
393* Function: CDMA_Execute_CMDs (for use with CMD_DMA)
394* Inputs: tag_count: the number of pending cmds to do
395* Outputs: PASS/FAIL
396* Description: Build the SDMA chain(s) by making one CMD-DMA descriptor
397* for each pending command, start the CDMA engine, and return.
398*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
399u16 CDMA_Execute_CMDs(void)
400{
401 int i, ret;
402 u64 flash_add;
403 u32 ptr;
404 dma_addr_t map_addr, next_ptr;
405 u16 status = PASS;
406 u16 tmp_c;
407 struct cdma_descriptor *pc;
408 struct memcpy_descriptor *pm;
409
410 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
411 __FILE__, __LINE__, __func__);
412
413 /* No pending cmds to execute, just exit */
414 if (0 == info.pcmds_num) {
415 nand_dbg_print(NAND_DBG_TRACE,
416 "No pending cmds to execute. Just exit.\n");
417 return PASS;
418 }
419
420 for (i = 0; i < MAX_DESCS; i++)
421 reset_cdma_desc(i);
422
423 pc = (struct cdma_descriptor *)info.cdma_desc_buf;
424 pm = (struct memcpy_descriptor *)info.memcp_desc_buf;
425
426 info.cdma_desc = virt_to_bus(info.cdma_desc_buf);
427 info.memcp_desc = virt_to_bus(info.memcp_desc_buf);
428 next_ptr = info.cdma_desc;
429 info.cdma_num = 0;
430
431 for (i = 0; i < info.pcmds_num; i++) {
432 if (info.pcmds[i].Block >= DeviceInfo.wTotalBlocks) {
433 info.pcmds[i].Status = CMD_NOT_DONE;
434 continue;
435 }
436
437 next_ptr += sizeof(struct cdma_descriptor);
438 pc[info.cdma_num].NxtPointerHi = next_ptr >> 16;
439 pc[info.cdma_num].NxtPointerLo = next_ptr & 0xffff;
440
441 /* Use the Block offset within a bank */
442 tmp_c = info.pcmds[i].Block /
443 (DeviceInfo.wTotalBlocks / totalUsedBanks);
444 flash_add = (u64)(info.pcmds[i].Block - tmp_c *
445 (DeviceInfo.wTotalBlocks / totalUsedBanks)) *
446 DeviceInfo.wBlockDataSize +
447 (u64)(info.pcmds[i].Page) *
448 DeviceInfo.wPageDataSize;
449
450 ptr = MODE_10 | (info.flash_bank << 24) |
451 (u32)GLOB_u64_Div(flash_add,
452 DeviceInfo.wPageDataSize);
453 pc[info.cdma_num].FlashPointerHi = ptr >> 16;
454 pc[info.cdma_num].FlashPointerLo = ptr & 0xffff;
455
456 if ((info.pcmds[i].CMD == WRITE_MAIN_SPARE_CMD) ||
457 (info.pcmds[i].CMD == READ_MAIN_SPARE_CMD)) {
458 /* Descriptor to set Main+Spare Access Mode */
459 pc[info.cdma_num].CommandType = 0x43;
460 pc[info.cdma_num].CommandFlags =
461 (0 << 10) | (1 << 9) | (0 << 8) | 0x40;
462 pc[info.cdma_num].MemAddrHi = 0;
463 pc[info.cdma_num].MemAddrLo = 0;
464 pc[info.cdma_num].Channel = 0;
465 pc[info.cdma_num].Status = 0;
466 pc[info.cdma_num].pcmd = i;
467
468 info.cdma_num++;
469 BUG_ON(info.cdma_num >= MAX_DESCS);
470
471 reset_cdma_desc(info.cdma_num);
472 next_ptr += sizeof(struct cdma_descriptor);
473 pc[info.cdma_num].NxtPointerHi = next_ptr >> 16;
474 pc[info.cdma_num].NxtPointerLo = next_ptr & 0xffff;
475 pc[info.cdma_num].FlashPointerHi = ptr >> 16;
476 pc[info.cdma_num].FlashPointerLo = ptr & 0xffff;
477 }
478
479 switch (info.pcmds[i].CMD) {
480 case ERASE_CMD:
481 pc[info.cdma_num].CommandType = 1;
482 pc[info.cdma_num].CommandFlags =
483 (0 << 10) | (1 << 9) | (0 << 8) | 0x40;
484 pc[info.cdma_num].MemAddrHi = 0;
485 pc[info.cdma_num].MemAddrLo = 0;
486 break;
487
488 case WRITE_MAIN_CMD:
489 pc[info.cdma_num].CommandType =
490 0x2100 | info.pcmds[i].PageCount;
491 pc[info.cdma_num].CommandFlags =
492 (0 << 10) | (1 << 9) | (0 << 8) | 0x40;
493 map_addr = virt_to_bus(info.pcmds[i].DataAddr);
494 pc[info.cdma_num].MemAddrHi = map_addr >> 16;
495 pc[info.cdma_num].MemAddrLo = map_addr & 0xffff;
496 break;
497
498 case READ_MAIN_CMD:
499 pc[info.cdma_num].CommandType =
500 0x2000 | info.pcmds[i].PageCount;
501 pc[info.cdma_num].CommandFlags =
502 (0 << 10) | (1 << 9) | (0 << 8) | 0x40;
503 map_addr = virt_to_bus(info.pcmds[i].DataAddr);
504 pc[info.cdma_num].MemAddrHi = map_addr >> 16;
505 pc[info.cdma_num].MemAddrLo = map_addr & 0xffff;
506 break;
507
508 case WRITE_MAIN_SPARE_CMD:
509 pc[info.cdma_num].CommandType =
510 0x2100 | info.pcmds[i].PageCount;
511 pc[info.cdma_num].CommandFlags =
512 (0 << 10) | (1 << 9) | (0 << 8) | 0x40;
513 map_addr = virt_to_bus(info.pcmds[i].DataAddr);
514 pc[info.cdma_num].MemAddrHi = map_addr >> 16;
515 pc[info.cdma_num].MemAddrLo = map_addr & 0xffff;
516 break;
517
518 case READ_MAIN_SPARE_CMD:
519 pc[info.cdma_num].CommandType =
520 0x2000 | info.pcmds[i].PageCount;
521 pc[info.cdma_num].CommandFlags =
522 (0 << 10) | (1 << 9) | (0 << 8) | 0x40;
523 map_addr = virt_to_bus(info.pcmds[i].DataAddr);
524 pc[info.cdma_num].MemAddrHi = map_addr >> 16;
525 pc[info.cdma_num].MemAddrLo = map_addr & 0xffff;
526 break;
527
528 case MEMCOPY_CMD:
529 pc[info.cdma_num].CommandType = 0xFFFF; /* NOP cmd */
530 /* Set bit 11 to let the CDMA engine continue to */
531 /* execute only after it has finished processing */
532 /* the memcopy descriptor. */
533 /* Also set bit 10 and bit 9 to 1 */
534 pc[info.cdma_num].CommandFlags = 0x0E40;
535 map_addr = info.memcp_desc + info.cdma_num *
536 sizeof(struct memcpy_descriptor);
537 pc[info.cdma_num].MemCopyPointerHi = map_addr >> 16;
538 pc[info.cdma_num].MemCopyPointerLo = map_addr & 0xffff;
539
540 pm[info.cdma_num].NxtPointerHi = 0;
541 pm[info.cdma_num].NxtPointerLo = 0;
542
543 map_addr = virt_to_bus(info.pcmds[i].DataSrcAddr);
544 pm[info.cdma_num].SrcAddrHi = map_addr >> 16;
545 pm[info.cdma_num].SrcAddrLo = map_addr & 0xffff;
546 map_addr = virt_to_bus(info.pcmds[i].DataDestAddr);
547 pm[info.cdma_num].DestAddrHi = map_addr >> 16;
548 pm[info.cdma_num].DestAddrLo = map_addr & 0xffff;
549
550 pm[info.cdma_num].XferSize =
551 info.pcmds[i].MemCopyByteCnt;
552 pm[info.cdma_num].MemCopyFlags =
553 (0 << 15 | 0 << 14 | 27 << 8 | 0x40);
554 pm[info.cdma_num].MemCopyStatus = 0;
555 break;
556
557 case DUMMY_CMD:
558 default:
559 pc[info.cdma_num].CommandType = 0XFFFF;
560 pc[info.cdma_num].CommandFlags =
561 (0 << 10) | (1 << 9) | (0 << 8) | 0x40;
562 pc[info.cdma_num].MemAddrHi = 0;
563 pc[info.cdma_num].MemAddrLo = 0;
564 break;
565 }
566
567 pc[info.cdma_num].Channel = 0;
568 pc[info.cdma_num].Status = 0;
569 pc[info.cdma_num].pcmd = i;
570
571 info.cdma_num++;
572 BUG_ON(info.cdma_num >= MAX_DESCS);
573
574 if ((info.pcmds[i].CMD == WRITE_MAIN_SPARE_CMD) ||
575 (info.pcmds[i].CMD == READ_MAIN_SPARE_CMD)) {
576 /* Descriptor to set back Main Area Access Mode */
577 reset_cdma_desc(info.cdma_num);
578 next_ptr += sizeof(struct cdma_descriptor);
579 pc[info.cdma_num].NxtPointerHi = next_ptr >> 16;
580 pc[info.cdma_num].NxtPointerLo = next_ptr & 0xffff;
581
582 pc[info.cdma_num].FlashPointerHi = ptr >> 16;
583 pc[info.cdma_num].FlashPointerLo = ptr & 0xffff;
584
585 pc[info.cdma_num].CommandType = 0x42;
586 pc[info.cdma_num].CommandFlags =
587 (0 << 10) | (1 << 9) | (0 << 8) | 0x40;
588 pc[info.cdma_num].MemAddrHi = 0;
589 pc[info.cdma_num].MemAddrLo = 0;
590
591 pc[info.cdma_num].Channel = 0;
592 pc[info.cdma_num].Status = 0;
593 pc[info.cdma_num].pcmd = i;
594
595 info.cdma_num++;
596 BUG_ON(info.cdma_num >= MAX_DESCS);
597 }
598 }
599
600 /* Add a dummy descriptor at end of the CDMA chain */
601 reset_cdma_desc(info.cdma_num);
602 ptr = MODE_10 | (info.flash_bank << 24);
603 pc[info.cdma_num].FlashPointerHi = ptr >> 16;
604 pc[info.cdma_num].FlashPointerLo = ptr & 0xffff;
605 pc[info.cdma_num].CommandType = 0xFFFF; /* NOP command */
606 /* Set Command Flags for the last CDMA descriptor: */
607 /* set Continue bit (bit 9) to 0 and Interrupt bit (bit 8) to 1 */
608 pc[info.cdma_num].CommandFlags =
609 (0 << 10) | (0 << 9) | (1 << 8) | 0x40;
610 pc[info.cdma_num].pcmd = 0xff; /* Set it to an illegal value */
611 info.cdma_num++;
612 BUG_ON(info.cdma_num >= MAX_DESCS);
613
614 iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable Interrupt */
615
616 iowrite32(1, FlashReg + DMA_ENABLE);
617 /* Wait for DMA to be enabled before issuing the next command */
618 while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
619 ;
620 cdma_trans(info.flash_bank);
621
622 ret = wait_for_completion_timeout(&info.complete, 50 * HZ);
623 if (!ret)
624 printk(KERN_ERR "Wait for completion timeout "
625 "in %s, Line %d\n", __FILE__, __LINE__);
626 status = info.ret;
627
628 info.pcmds_num = 0; /* Clear the pending cmds number to 0 */
629
630 return status;
631}
632
633int is_cdma_interrupt(void)
634{
635 u32 ints_b0, ints_b1, ints_b2, ints_b3, ints_cdma;
636 u32 int_en_mask;
637 u32 cdma_int_en_mask;
638
639 nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
640 __FILE__, __LINE__, __func__);
641
642 /* Set the global Enable masks for only those interrupts
643 * that are supported */
644 cdma_int_en_mask = (DMA_INTR__DESC_COMP_CHANNEL0 |
645 DMA_INTR__DESC_COMP_CHANNEL1 |
646 DMA_INTR__DESC_COMP_CHANNEL2 |
647 DMA_INTR__DESC_COMP_CHANNEL3 |
648 DMA_INTR__MEMCOPY_DESC_COMP);
649
650 int_en_mask = (INTR_STATUS0__ECC_ERR |
651 INTR_STATUS0__PROGRAM_FAIL |
652 INTR_STATUS0__ERASE_FAIL);
653
654 ints_b0 = ioread32(FlashReg + INTR_STATUS0) & int_en_mask;
655 ints_b1 = ioread32(FlashReg + INTR_STATUS1) & int_en_mask;
656 ints_b2 = ioread32(FlashReg + INTR_STATUS2) & int_en_mask;
657 ints_b3 = ioread32(FlashReg + INTR_STATUS3) & int_en_mask;
658 ints_cdma = ioread32(FlashReg + DMA_INTR) & cdma_int_en_mask;
659
660 nand_dbg_print(NAND_DBG_WARN, "ints_bank0 to ints_bank3: "
661 "0x%x, 0x%x, 0x%x, 0x%x, ints_cdma: 0x%x\n",
662 ints_b0, ints_b1, ints_b2, ints_b3, ints_cdma);
663
664 if (ints_b0 || ints_b1 || ints_b2 || ints_b3 || ints_cdma) {
665 return 1;
666 } else {
667 iowrite32(ints_b0, FlashReg + INTR_STATUS0);
668 iowrite32(ints_b1, FlashReg + INTR_STATUS1);
669 iowrite32(ints_b2, FlashReg + INTR_STATUS2);
670 iowrite32(ints_b3, FlashReg + INTR_STATUS3);
671 nand_dbg_print(NAND_DBG_DEBUG,
672 "Not a NAND controller interrupt! Ignore it.\n");
673 return 0;
674 }
675}
676
677static void update_event_status(void)
678{
679 int i;
680 struct cdma_descriptor *ptr;
681
682 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
683 __FILE__, __LINE__, __func__);
684
685 ptr = (struct cdma_descriptor *)info.cdma_desc_buf;
686
687 for (i = 0; i < info.cdma_num; i++) {
688 if (ptr[i].pcmd != 0xff)
689 info.pcmds[ptr[i].pcmd].Status = CMD_PASS;
690 if ((ptr[i].CommandType == 0x41) ||
691 (ptr[i].CommandType == 0x42) ||
692 (ptr[i].CommandType == 0x43))
693 continue;
694
695 switch (info.pcmds[ptr[i].pcmd].CMD) {
696 case READ_MAIN_SPARE_CMD:
697 Conv_Main_Spare_Data_Phy2Log_Format(
698 info.pcmds[ptr[i].pcmd].DataAddr,
699 info.pcmds[ptr[i].pcmd].PageCount);
700 break;
701 case READ_SPARE_CMD:
702 Conv_Spare_Data_Phy2Log_Format(
703 info.pcmds[ptr[i].pcmd].DataAddr);
704 break;
705 }
706 }
707}
708
709static u16 do_ecc_for_desc(u32 ch, u8 *buf, u16 page)
710{
711 u16 event = EVENT_NONE;
712 u16 err_byte;
713 u16 err_page = 0;
714 u8 err_sector;
715 u8 err_device;
716 u16 ecc_correction_info;
717 u16 err_address;
718 u32 eccSectorSize;
719 u8 *err_pos;
720
721 nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
722 __FILE__, __LINE__, __func__);
723
724 eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected);
725
726 do {
727 if (0 == ch)
728 err_page = ioread32(FlashReg + ERR_PAGE_ADDR0);
729 else if (1 == ch)
730 err_page = ioread32(FlashReg + ERR_PAGE_ADDR1);
731 else if (2 == ch)
732 err_page = ioread32(FlashReg + ERR_PAGE_ADDR2);
733 else if (3 == ch)
734 err_page = ioread32(FlashReg + ERR_PAGE_ADDR3);
735
736 err_address = ioread32(FlashReg + ECC_ERROR_ADDRESS);
737 err_byte = err_address & ECC_ERROR_ADDRESS__OFFSET;
738 err_sector = ((err_address &
739 ECC_ERROR_ADDRESS__SECTOR_NR) >> 12);
740
741 ecc_correction_info = ioread32(FlashReg + ERR_CORRECTION_INFO);
742 err_device = ((ecc_correction_info &
743 ERR_CORRECTION_INFO__DEVICE_NR) >> 8);
744
745 if (ecc_correction_info & ERR_CORRECTION_INFO__ERROR_TYPE) {
746 event = EVENT_UNCORRECTABLE_DATA_ERROR;
747 } else {
748 event = EVENT_CORRECTABLE_DATA_ERROR_FIXED;
749 if (err_byte < ECC_SECTOR_SIZE) {
750 err_pos = buf +
751 (err_page - page) *
752 DeviceInfo.wPageDataSize +
753 err_sector * eccSectorSize +
754 err_byte *
755 DeviceInfo.wDevicesConnected +
756 err_device;
757 *err_pos ^= ecc_correction_info &
758 ERR_CORRECTION_INFO__BYTEMASK;
759 }
760 }
761 } while (!(ecc_correction_info & ERR_CORRECTION_INFO__LAST_ERR_INFO));
762
763 return event;
764}
765
766static u16 process_ecc_int(u32 c, u16 *p_desc_num)
767{
768 struct cdma_descriptor *ptr;
769 u16 j;
770 int event = EVENT_PASS;
771
772 nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
773 __FILE__, __LINE__, __func__);
774
775 if (c != info.flash_bank)
776 printk(KERN_ERR "Error!info.flash_bank is %d, while c is %d\n",
777 info.flash_bank, c);
778
779 ptr = (struct cdma_descriptor *)info.cdma_desc_buf;
780
781 for (j = 0; j < info.cdma_num; j++)
782 if ((ptr[j].Status & CMD_DMA_DESC_COMP) != CMD_DMA_DESC_COMP)
783 break;
784
785 *p_desc_num = j; /* Pass the descripter number found here */
786
787 if (j >= info.cdma_num) {
788 printk(KERN_ERR "Can not find the correct descriptor number "
789 "when ecc interrupt triggered!"
790 "info.cdma_num: %d, j: %d\n", info.cdma_num, j);
791 return EVENT_UNCORRECTABLE_DATA_ERROR;
792 }
793
794 event = do_ecc_for_desc(c, info.pcmds[ptr[j].pcmd].DataAddr,
795 info.pcmds[ptr[j].pcmd].Page);
796
797 if (EVENT_UNCORRECTABLE_DATA_ERROR == event) {
798 printk(KERN_ERR "Uncorrectable ECC error!"
799 "info.cdma_num: %d, j: %d, "
800 "pending cmd CMD: 0x%x, "
801 "Block: 0x%x, Page: 0x%x, PageCount: 0x%x\n",
802 info.cdma_num, j,
803 info.pcmds[ptr[j].pcmd].CMD,
804 info.pcmds[ptr[j].pcmd].Block,
805 info.pcmds[ptr[j].pcmd].Page,
806 info.pcmds[ptr[j].pcmd].PageCount);
807
808 if (ptr[j].pcmd != 0xff)
809 info.pcmds[ptr[j].pcmd].Status = CMD_FAIL;
810 CDMA_UpdateEventStatus();
811 }
812
813 return event;
814}
815
816static void process_prog_erase_fail_int(u16 desc_num)
817{
818 struct cdma_descriptor *ptr;
819
820 nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
821 __FILE__, __LINE__, __func__);
822
823 ptr = (struct cdma_descriptor *)info.cdma_desc_buf;
824
825 if (ptr[desc_num].pcmd != 0xFF)
826 info.pcmds[ptr[desc_num].pcmd].Status = CMD_FAIL;
827
828 CDMA_UpdateEventStatus();
829}
830
831/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
832* Function: CDMA_Event_Status (for use with CMD_DMA)
833* Inputs: none
834* Outputs: Event_Status code
835* Description: This function is called after an interrupt has happened
836* It reads the HW status register and ...tbd
837* It returns the appropriate event status
838*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
839u16 CDMA_Event_Status(void)
840{
841 u32 ints_addr[4] = {INTR_STATUS0, INTR_STATUS1,
842 INTR_STATUS2, INTR_STATUS3};
843 u32 dma_intr_bit[4] = {DMA_INTR__DESC_COMP_CHANNEL0,
844 DMA_INTR__DESC_COMP_CHANNEL1,
845 DMA_INTR__DESC_COMP_CHANNEL2,
846 DMA_INTR__DESC_COMP_CHANNEL3};
847 u32 cdma_int_status, int_status;
848 u32 ecc_enable = 0;
849 u16 event = EVENT_PASS;
850 u16 cur_desc = 0;
851
852 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
853 __FILE__, __LINE__, __func__);
854
855 ecc_enable = ioread32(FlashReg + ECC_ENABLE);
856
857 while (1) {
858 int_status = ioread32(FlashReg + ints_addr[info.flash_bank]);
859 if (ecc_enable && (int_status & INTR_STATUS0__ECC_ERR)) {
860 event = process_ecc_int(info.flash_bank, &cur_desc);
861 iowrite32(INTR_STATUS0__ECC_ERR,
862 FlashReg + ints_addr[info.flash_bank]);
863 if (EVENT_UNCORRECTABLE_DATA_ERROR == event) {
864 nand_dbg_print(NAND_DBG_WARN,
865 "ints_bank0 to ints_bank3: "
866 "0x%x, 0x%x, 0x%x, 0x%x, "
867 "ints_cdma: 0x%x\n",
868 ioread32(FlashReg + INTR_STATUS0),
869 ioread32(FlashReg + INTR_STATUS1),
870 ioread32(FlashReg + INTR_STATUS2),
871 ioread32(FlashReg + INTR_STATUS3),
872 ioread32(FlashReg + DMA_INTR));
873 break;
874 }
875 } else if (int_status & INTR_STATUS0__PROGRAM_FAIL) {
876 printk(KERN_ERR "NAND program fail interrupt!\n");
877 process_prog_erase_fail_int(cur_desc);
878 event = EVENT_PROGRAM_FAILURE;
879 break;
880 } else if (int_status & INTR_STATUS0__ERASE_FAIL) {
881 printk(KERN_ERR "NAND erase fail interrupt!\n");
882 process_prog_erase_fail_int(cur_desc);
883 event = EVENT_ERASE_FAILURE;
884 break;
885 } else {
886 cdma_int_status = ioread32(FlashReg + DMA_INTR);
887 if (cdma_int_status & dma_intr_bit[info.flash_bank]) {
888 iowrite32(dma_intr_bit[info.flash_bank],
889 FlashReg + DMA_INTR);
890 update_event_status();
891 event = EVENT_PASS;
892 break;
893 }
894 }
895 }
896
897 int_status = ioread32(FlashReg + ints_addr[info.flash_bank]);
898 iowrite32(int_status, FlashReg + ints_addr[info.flash_bank]);
899 cdma_int_status = ioread32(FlashReg + DMA_INTR);
900 iowrite32(cdma_int_status, FlashReg + DMA_INTR);
901
902 iowrite32(0, FlashReg + DMA_ENABLE);
903 while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
904 ;
905
906 return event;
907}
908
909
910
diff --git a/drivers/staging/spectra/lld_cdma.h b/drivers/staging/spectra/lld_cdma.h
new file mode 100644
index 00000000000..854ea066f0c
--- /dev/null
+++ b/drivers/staging/spectra/lld_cdma.h
@@ -0,0 +1,123 @@
1/*
2 * NAND Flash Controller Device Driver
3 * Copyright (c) 2009, Intel Corporation and its suppliers.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19
20/* header for LLD_CDMA.c module */
21
22#ifndef _LLD_CDMA_
23#define _LLD_CDMA_
24
25#include "flash.h"
26
27#define DEBUG_SYNC 1
28
29/*/////////// CDMA specific MACRO definition */
30#define MAX_DESCS (255)
31#define MAX_CHANS (4)
32#define MAX_SYNC_POINTS (16)
33#define MAX_DESC_PER_CHAN (MAX_DESCS * 3 + MAX_SYNC_POINTS + 2)
34
35#define CHANNEL_SYNC_MASK (0x000F)
36#define CHANNEL_DMA_MASK (0x00F0)
37#define CHANNEL_ID_MASK (0x0300)
38#define CHANNEL_CONT_MASK (0x4000)
39#define CHANNEL_INTR_MASK (0x8000)
40
41#define CHANNEL_SYNC_OFFSET (0)
42#define CHANNEL_DMA_OFFSET (4)
43#define CHANNEL_ID_OFFSET (8)
44#define CHANNEL_CONT_OFFSET (14)
45#define CHANNEL_INTR_OFFSET (15)
46
47u16 CDMA_Data_CMD(u8 cmd, u8 *data, u32 block, u16 page, u16 num, u16 flags);
48u16 CDMA_MemCopy_CMD(u8 *dest, u8 *src, u32 byte_cnt, u16 flags);
49u16 CDMA_Execute_CMDs(void);
50void print_pending_cmds(void);
51void print_cdma_descriptors(void);
52
53extern u8 g_SBDCmdIndex;
54extern struct mrst_nand_info info;
55
56
57/*/////////// prototypes: APIs for LLD_CDMA */
58int is_cdma_interrupt(void);
59u16 CDMA_Event_Status(void);
60
61/* CMD-DMA Descriptor Struct. These are defined by the CMD_DMA HW */
62struct cdma_descriptor {
63 u32 NxtPointerHi;
64 u32 NxtPointerLo;
65 u32 FlashPointerHi;
66 u32 FlashPointerLo;
67 u32 CommandType;
68 u32 MemAddrHi;
69 u32 MemAddrLo;
70 u32 CommandFlags;
71 u32 Channel;
72 u32 Status;
73 u32 MemCopyPointerHi;
74 u32 MemCopyPointerLo;
75 u32 Reserved12;
76 u32 Reserved13;
77 u32 Reserved14;
78 u32 pcmd; /* pending cmd num related to this descriptor */
79};
80
81/* This struct holds one MemCopy descriptor as defined by the HW */
82struct memcpy_descriptor {
83 u32 NxtPointerHi;
84 u32 NxtPointerLo;
85 u32 SrcAddrHi;
86 u32 SrcAddrLo;
87 u32 DestAddrHi;
88 u32 DestAddrLo;
89 u32 XferSize;
90 u32 MemCopyFlags;
91 u32 MemCopyStatus;
92 u32 reserved9;
93 u32 reserved10;
94 u32 reserved11;
95 u32 reserved12;
96 u32 reserved13;
97 u32 reserved14;
98 u32 reserved15;
99};
100
101/* Pending CMD table entries (includes MemCopy parameters */
102struct pending_cmd {
103 u8 CMD;
104 u8 *DataAddr;
105 u32 Block;
106 u16 Page;
107 u16 PageCount;
108 u8 *DataDestAddr;
109 u8 *DataSrcAddr;
110 u32 MemCopyByteCnt;
111 u16 Flags;
112 u16 Status;
113};
114
115#if DEBUG_SYNC
116extern u32 debug_sync_cnt;
117#endif
118
119/* Definitions for CMD DMA descriptor chain fields */
120#define CMD_DMA_DESC_COMP 0x8000
121#define CMD_DMA_DESC_FAIL 0x4000
122
123#endif /*_LLD_CDMA_*/
diff --git a/drivers/staging/spectra/lld_emu.c b/drivers/staging/spectra/lld_emu.c
new file mode 100644
index 00000000000..095f2f0c2e5
--- /dev/null
+++ b/drivers/staging/spectra/lld_emu.c
@@ -0,0 +1,776 @@
1/*
2 * NAND Flash Controller Device Driver
3 * Copyright (c) 2009, Intel Corporation and its suppliers.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19
20#include <linux/fs.h>
21#include <linux/slab.h>
22#include "flash.h"
23#include "ffsdefs.h"
24#include "lld_emu.h"
25#include "lld.h"
26#if CMD_DMA
27#include "lld_cdma.h"
28#if FLASH_EMU
29u32 totalUsedBanks;
30u32 valid_banks[MAX_CHANS];
31#endif
32#endif
33
34#define GLOB_LLD_PAGES 64
35#define GLOB_LLD_PAGE_SIZE (512+16)
36#define GLOB_LLD_PAGE_DATA_SIZE 512
37#define GLOB_LLD_BLOCKS 2048
38
39#if FLASH_EMU /* This is for entire module */
40
41static u8 *flash_memory[GLOB_LLD_BLOCKS * GLOB_LLD_PAGES];
42
43/* Read nand emu file and then fill it's content to flash_memory */
44int emu_load_file_to_mem(void)
45{
46 mm_segment_t fs;
47 struct file *nef_filp = NULL;
48 struct inode *inode = NULL;
49 loff_t nef_size = 0;
50 loff_t tmp_file_offset, file_offset;
51 ssize_t nread;
52 int i, rc = -EINVAL;
53
54 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
55 __FILE__, __LINE__, __func__);
56
57 fs = get_fs();
58 set_fs(get_ds());
59
60 nef_filp = filp_open("/root/nand_emu_file", O_RDWR | O_LARGEFILE, 0);
61 if (IS_ERR(nef_filp)) {
62 printk(KERN_ERR "filp_open error: "
63 "Unable to open nand emu file!\n");
64 return PTR_ERR(nef_filp);
65 }
66
67 if (nef_filp->f_path.dentry) {
68 inode = nef_filp->f_path.dentry->d_inode;
69 } else {
70 printk(KERN_ERR "Can not get valid inode!\n");
71 goto out;
72 }
73
74 nef_size = i_size_read(inode->i_mapping->host);
75 if (nef_size <= 0) {
76 printk(KERN_ERR "Invalid nand emu file size: "
77 "0x%llx\n", nef_size);
78 goto out;
79 } else {
80 nand_dbg_print(NAND_DBG_DEBUG, "nand emu file size: %lld\n",
81 nef_size);
82 }
83
84 file_offset = 0;
85 for (i = 0; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++) {
86 tmp_file_offset = file_offset;
87 nread = vfs_read(nef_filp,
88 (char __user *)flash_memory[i],
89 GLOB_LLD_PAGE_SIZE, &tmp_file_offset);
90 if (nread < GLOB_LLD_PAGE_SIZE) {
91 printk(KERN_ERR "%s, Line %d - "
92 "nand emu file partial read: "
93 "%d bytes\n", __FILE__, __LINE__, (int)nread);
94 goto out;
95 }
96 file_offset += GLOB_LLD_PAGE_SIZE;
97 }
98 rc = 0;
99
100out:
101 filp_close(nef_filp, current->files);
102 set_fs(fs);
103 return rc;
104}
105
106/* Write contents of flash_memory to nand emu file */
107int emu_write_mem_to_file(void)
108{
109 mm_segment_t fs;
110 struct file *nef_filp = NULL;
111 struct inode *inode = NULL;
112 loff_t nef_size = 0;
113 loff_t tmp_file_offset, file_offset;
114 ssize_t nwritten;
115 int i, rc = -EINVAL;
116
117 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
118 __FILE__, __LINE__, __func__);
119
120 fs = get_fs();
121 set_fs(get_ds());
122
123 nef_filp = filp_open("/root/nand_emu_file", O_RDWR | O_LARGEFILE, 0);
124 if (IS_ERR(nef_filp)) {
125 printk(KERN_ERR "filp_open error: "
126 "Unable to open nand emu file!\n");
127 return PTR_ERR(nef_filp);
128 }
129
130 if (nef_filp->f_path.dentry) {
131 inode = nef_filp->f_path.dentry->d_inode;
132 } else {
133 printk(KERN_ERR "Invalid " "nef_filp->f_path.dentry value!\n");
134 goto out;
135 }
136
137 nef_size = i_size_read(inode->i_mapping->host);
138 if (nef_size <= 0) {
139 printk(KERN_ERR "Invalid "
140 "nand emu file size: 0x%llx\n", nef_size);
141 goto out;
142 } else {
143 nand_dbg_print(NAND_DBG_DEBUG, "nand emu file size: "
144 "%lld\n", nef_size);
145 }
146
147 file_offset = 0;
148 for (i = 0; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++) {
149 tmp_file_offset = file_offset;
150 nwritten = vfs_write(nef_filp,
151 (char __user *)flash_memory[i],
152 GLOB_LLD_PAGE_SIZE, &tmp_file_offset);
153 if (nwritten < GLOB_LLD_PAGE_SIZE) {
154 printk(KERN_ERR "%s, Line %d - "
155 "nand emu file partial write: "
156 "%d bytes\n", __FILE__, __LINE__, (int)nwritten);
157 goto out;
158 }
159 file_offset += GLOB_LLD_PAGE_SIZE;
160 }
161 rc = 0;
162
163out:
164 filp_close(nef_filp, current->files);
165 set_fs(fs);
166 return rc;
167}
168
169/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
170* Function: emu_Flash_Init
171* Inputs: none
172* Outputs: PASS=0 (notice 0=ok here)
173* Description: Creates & initializes the flash RAM array.
174*
175*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
176u16 emu_Flash_Init(void)
177{
178 int i;
179
180 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
181 __FILE__, __LINE__, __func__);
182
183 flash_memory[0] = vmalloc(GLOB_LLD_PAGE_SIZE * GLOB_LLD_BLOCKS *
184 GLOB_LLD_PAGES * sizeof(u8));
185 if (!flash_memory[0]) {
186 printk(KERN_ERR "Fail to allocate memory "
187 "for nand emulator!\n");
188 return ERR;
189 }
190
191 memset((char *)(flash_memory[0]), 0xFF,
192 GLOB_LLD_PAGE_SIZE * GLOB_LLD_BLOCKS * GLOB_LLD_PAGES *
193 sizeof(u8));
194
195 for (i = 1; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++)
196 flash_memory[i] = flash_memory[i - 1] + GLOB_LLD_PAGE_SIZE;
197
198 emu_load_file_to_mem(); /* Load nand emu file to mem */
199
200 return PASS;
201}
202
203/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
204* Function: emu_Flash_Release
205* Inputs: none
206* Outputs: PASS=0 (notice 0=ok here)
207* Description: Releases the flash.
208*
209*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
210int emu_Flash_Release(void)
211{
212 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
213 __FILE__, __LINE__, __func__);
214
215 emu_write_mem_to_file(); /* Write back mem to nand emu file */
216
217 vfree(flash_memory[0]);
218 return PASS;
219}
220
221/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
222* Function: emu_Read_Device_ID
223* Inputs: none
224* Outputs: PASS=1 FAIL=0
225* Description: Reads the info from the controller registers.
226* Sets up DeviceInfo structure with device parameters
227*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
228
229u16 emu_Read_Device_ID(void)
230{
231 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
232 __FILE__, __LINE__, __func__);
233
234 DeviceInfo.wDeviceMaker = 0;
235 DeviceInfo.wDeviceType = 8;
236 DeviceInfo.wSpectraStartBlock = 36;
237 DeviceInfo.wSpectraEndBlock = GLOB_LLD_BLOCKS - 1;
238 DeviceInfo.wTotalBlocks = GLOB_LLD_BLOCKS;
239 DeviceInfo.wPagesPerBlock = GLOB_LLD_PAGES;
240 DeviceInfo.wPageSize = GLOB_LLD_PAGE_SIZE;
241 DeviceInfo.wPageDataSize = GLOB_LLD_PAGE_DATA_SIZE;
242 DeviceInfo.wPageSpareSize = GLOB_LLD_PAGE_SIZE -
243 GLOB_LLD_PAGE_DATA_SIZE;
244 DeviceInfo.wBlockSize = DeviceInfo.wPageSize * GLOB_LLD_PAGES;
245 DeviceInfo.wBlockDataSize = DeviceInfo.wPageDataSize * GLOB_LLD_PAGES;
246 DeviceInfo.wDataBlockNum = (u32) (DeviceInfo.wSpectraEndBlock -
247 DeviceInfo.wSpectraStartBlock
248 + 1);
249 DeviceInfo.MLCDevice = 1; /* Emulate MLC device */
250 DeviceInfo.nBitsInPageNumber =
251 (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPagesPerBlock);
252 DeviceInfo.nBitsInPageDataSize =
253 (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPageDataSize);
254 DeviceInfo.nBitsInBlockDataSize =
255 (u8)GLOB_Calc_Used_Bits(DeviceInfo.wBlockDataSize);
256
257#if CMD_DMA
258 totalUsedBanks = 4;
259 valid_banks[0] = 1;
260 valid_banks[1] = 1;
261 valid_banks[2] = 1;
262 valid_banks[3] = 1;
263#endif
264
265 return PASS;
266}
267
268/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
269* Function: emu_Flash_Reset
270* Inputs: none
271* Outputs: PASS=0 (notice 0=ok here)
272* Description: Reset the flash
273*
274*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
275u16 emu_Flash_Reset(void)
276{
277 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
278 __FILE__, __LINE__, __func__);
279
280 return PASS;
281}
282
283/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
284* Function: emu_Erase_Block
285* Inputs: Address
286* Outputs: PASS=0 (notice 0=ok here)
287* Description: Erase a block
288*
289*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
290u16 emu_Erase_Block(u32 block_add)
291{
292 int i;
293
294 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
295 __FILE__, __LINE__, __func__);
296
297 if (block_add >= DeviceInfo.wTotalBlocks) {
298 printk(KERN_ERR "emu_Erase_Block error! "
299 "Too big block address: %d\n", block_add);
300 return FAIL;
301 }
302
303 nand_dbg_print(NAND_DBG_DEBUG, "Erasing block %d\n",
304 (int)block_add);
305
306 for (i = block_add * GLOB_LLD_PAGES;
307 i < ((block_add + 1) * GLOB_LLD_PAGES); i++) {
308 if (flash_memory[i]) {
309 memset((u8 *)(flash_memory[i]), 0xFF,
310 DeviceInfo.wPageSize * sizeof(u8));
311 }
312 }
313
314 return PASS;
315}
316
317/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
318* Function: emu_Write_Page_Main
319* Inputs: Write buffer address pointer
320* Block number
321* Page number
322* Number of pages to process
323* Outputs: PASS=0 (notice 0=ok here)
324* Description: Write the data in the buffer to main area of flash
325*
326*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
327u16 emu_Write_Page_Main(u8 *write_data, u32 Block,
328 u16 Page, u16 PageCount)
329{
330 int i;
331
332 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
333 __FILE__, __LINE__, __func__);
334
335 if (Block >= DeviceInfo.wTotalBlocks)
336 return FAIL;
337
338 if (Page + PageCount > DeviceInfo.wPagesPerBlock)
339 return FAIL;
340
341 nand_dbg_print(NAND_DBG_DEBUG, "emu_Write_Page_Main: "
342 "lba %u Page %u PageCount %u\n",
343 (unsigned int)Block,
344 (unsigned int)Page, (unsigned int)PageCount);
345
346 for (i = 0; i < PageCount; i++) {
347 if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
348 printk(KERN_ERR "Run out of memory\n");
349 return FAIL;
350 }
351 memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]),
352 write_data, DeviceInfo.wPageDataSize);
353 write_data += DeviceInfo.wPageDataSize;
354 Page++;
355 }
356
357 return PASS;
358}
359
360/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
361* Function: emu_Read_Page_Main
362* Inputs: Read buffer address pointer
363* Block number
364* Page number
365* Number of pages to process
366* Outputs: PASS=0 (notice 0=ok here)
367* Description: Read the data from the flash main area to the buffer
368*
369*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
370u16 emu_Read_Page_Main(u8 *read_data, u32 Block,
371 u16 Page, u16 PageCount)
372{
373 int i;
374
375 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
376 __FILE__, __LINE__, __func__);
377
378 if (Block >= DeviceInfo.wTotalBlocks)
379 return FAIL;
380
381 if (Page + PageCount > DeviceInfo.wPagesPerBlock)
382 return FAIL;
383
384 nand_dbg_print(NAND_DBG_DEBUG, "emu_Read_Page_Main: "
385 "lba %u Page %u PageCount %u\n",
386 (unsigned int)Block,
387 (unsigned int)Page, (unsigned int)PageCount);
388
389 for (i = 0; i < PageCount; i++) {
390 if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
391 memset(read_data, 0xFF, DeviceInfo.wPageDataSize);
392 } else {
393 memcpy(read_data,
394 (u8 *) (flash_memory[Block * GLOB_LLD_PAGES
395 + Page]),
396 DeviceInfo.wPageDataSize);
397 }
398 read_data += DeviceInfo.wPageDataSize;
399 Page++;
400 }
401
402 return PASS;
403}
404
405#ifndef ELDORA
406/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
407* Function: emu_Read_Page_Main_Spare
408* Inputs: Write Buffer
409* Address
410* Buffer size
411* Outputs: PASS=0 (notice 0=ok here)
412* Description: Read from flash main+spare area
413*
414*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
415u16 emu_Read_Page_Main_Spare(u8 *read_data, u32 Block,
416 u16 Page, u16 PageCount)
417{
418 int i;
419
420 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
421 __FILE__, __LINE__, __func__);
422
423 if (Block >= DeviceInfo.wTotalBlocks) {
424 printk(KERN_ERR "Read Page Main+Spare "
425 "Error: Block Address too big\n");
426 return FAIL;
427 }
428
429 if (Page + PageCount > DeviceInfo.wPagesPerBlock) {
430 printk(KERN_ERR "Read Page Main+Spare "
431 "Error: Page number too big\n");
432 return FAIL;
433 }
434
435 nand_dbg_print(NAND_DBG_DEBUG, "Read Page Main + Spare - "
436 "No. of pages %u block %u start page %u\n",
437 (unsigned int)PageCount,
438 (unsigned int)Block, (unsigned int)Page);
439
440 for (i = 0; i < PageCount; i++) {
441 if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
442 memset(read_data, 0xFF, DeviceInfo.wPageSize);
443 } else {
444 memcpy(read_data, (u8 *) (flash_memory[Block *
445 GLOB_LLD_PAGES
446 + Page]),
447 DeviceInfo.wPageSize);
448 }
449
450 read_data += DeviceInfo.wPageSize;
451 Page++;
452 }
453
454 return PASS;
455}
456
457/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
458* Function: emu_Write_Page_Main_Spare
459* Inputs: Write buffer
460* address
461* buffer length
462* Outputs: PASS=0 (notice 0=ok here)
463* Description: Write the buffer to main+spare area of flash
464*
465*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
466u16 emu_Write_Page_Main_Spare(u8 *write_data, u32 Block,
467 u16 Page, u16 page_count)
468{
469 u16 i;
470
471 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
472 __FILE__, __LINE__, __func__);
473
474 if (Block >= DeviceInfo.wTotalBlocks) {
475 printk(KERN_ERR "Write Page Main + Spare "
476 "Error: Block Address too big\n");
477 return FAIL;
478 }
479
480 if (Page + page_count > DeviceInfo.wPagesPerBlock) {
481 printk(KERN_ERR "Write Page Main + Spare "
482 "Error: Page number too big\n");
483 return FAIL;
484 }
485
486 nand_dbg_print(NAND_DBG_DEBUG, "Write Page Main+Spare - "
487 "No. of pages %u block %u start page %u\n",
488 (unsigned int)page_count,
489 (unsigned int)Block, (unsigned int)Page);
490
491 for (i = 0; i < page_count; i++) {
492 if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
493 printk(KERN_ERR "Run out of memory!\n");
494 return FAIL;
495 }
496 memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]),
497 write_data, DeviceInfo.wPageSize);
498 write_data += DeviceInfo.wPageSize;
499 Page++;
500 }
501
502 return PASS;
503}
504
505/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
506* Function: emu_Write_Page_Spare
507* Inputs: Write buffer
508* Address
509* buffer size
510* Outputs: PASS=0 (notice 0=ok here)
511* Description: Write the buffer in the spare area
512*
513*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
514u16 emu_Write_Page_Spare(u8 *write_data, u32 Block,
515 u16 Page, u16 PageCount)
516{
517 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
518 __FILE__, __LINE__, __func__);
519
520 if (Block >= DeviceInfo.wTotalBlocks) {
521 printk(KERN_ERR "Read Page Spare Error: "
522 "Block Address too big\n");
523 return FAIL;
524 }
525
526 if (Page + PageCount > DeviceInfo.wPagesPerBlock) {
527 printk(KERN_ERR "Read Page Spare Error: "
528 "Page number too big\n");
529 return FAIL;
530 }
531
532 nand_dbg_print(NAND_DBG_DEBUG, "Write Page Spare- "
533 "block %u page %u\n",
534 (unsigned int)Block, (unsigned int)Page);
535
536 if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
537 printk(KERN_ERR "Run out of memory!\n");
538 return FAIL;
539 }
540
541 memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page] +
542 DeviceInfo.wPageDataSize), write_data,
543 (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize));
544
545 return PASS;
546}
547
548/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
549* Function: emu_Read_Page_Spare
550* Inputs: Write Buffer
551* Address
552* Buffer size
553* Outputs: PASS=0 (notice 0=ok here)
554* Description: Read data from the spare area
555*
556*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
557u16 emu_Read_Page_Spare(u8 *write_data, u32 Block,
558 u16 Page, u16 PageCount)
559{
560 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
561 __FILE__, __LINE__, __func__);
562
563 if (Block >= DeviceInfo.wTotalBlocks) {
564 printk(KERN_ERR "Read Page Spare "
565 "Error: Block Address too big\n");
566 return FAIL;
567 }
568
569 if (Page + PageCount > DeviceInfo.wPagesPerBlock) {
570 printk(KERN_ERR "Read Page Spare "
571 "Error: Page number too big\n");
572 return FAIL;
573 }
574
575 nand_dbg_print(NAND_DBG_DEBUG, "Read Page Spare- "
576 "block %u page %u\n",
577 (unsigned int)Block, (unsigned int)Page);
578
579 if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
580 memset(write_data, 0xFF,
581 (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize));
582 } else {
583 memcpy(write_data,
584 (u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]
585 + DeviceInfo.wPageDataSize),
586 (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize));
587 }
588
589 return PASS;
590}
591
592/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
593* Function: emu_Enable_Disable_Interrupts
594* Inputs: enable or disable
595* Outputs: none
596* Description: NOP
597*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
598void emu_Enable_Disable_Interrupts(u16 INT_ENABLE)
599{
600 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
601 __FILE__, __LINE__, __func__);
602}
603
604u16 emu_Get_Bad_Block(u32 block)
605{
606 return 0;
607}
608
609#if CMD_DMA
610/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
611* Support for CDMA functions
612************************************
613* emu_CDMA_Flash_Init
614* CDMA_process_data command (use LLD_CDMA)
615* CDMA_MemCopy_CMD (use LLD_CDMA)
616* emu_CDMA_execute all commands
617* emu_CDMA_Event_Status
618*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
619u16 emu_CDMA_Flash_Init(void)
620{
621 u16 i;
622
623 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
624 __FILE__, __LINE__, __func__);
625
626 for (i = 0; i < MAX_DESCS + MAX_CHANS; i++) {
627 PendingCMD[i].CMD = 0;
628 PendingCMD[i].Tag = 0;
629 PendingCMD[i].DataAddr = 0;
630 PendingCMD[i].Block = 0;
631 PendingCMD[i].Page = 0;
632 PendingCMD[i].PageCount = 0;
633 PendingCMD[i].DataDestAddr = 0;
634 PendingCMD[i].DataSrcAddr = 0;
635 PendingCMD[i].MemCopyByteCnt = 0;
636 PendingCMD[i].ChanSync[0] = 0;
637 PendingCMD[i].ChanSync[1] = 0;
638 PendingCMD[i].ChanSync[2] = 0;
639 PendingCMD[i].ChanSync[3] = 0;
640 PendingCMD[i].ChanSync[4] = 0;
641 PendingCMD[i].Status = 3;
642 }
643
644 return PASS;
645}
646
647static void emu_isr(int irq, void *dev_id)
648{
649 /* TODO: ... */
650}
651
652/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
653* Function: CDMA_Execute_CMDs
654* Inputs: tag_count: the number of pending cmds to do
655* Outputs: PASS/FAIL
656* Description: execute each command in the pending CMD array
657*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
658u16 emu_CDMA_Execute_CMDs(u16 tag_count)
659{
660 u16 i, j;
661 u8 CMD; /* cmd parameter */
662 u8 *data;
663 u32 block;
664 u16 page;
665 u16 count;
666 u16 status = PASS;
667
668 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
669 __FILE__, __LINE__, __func__);
670
671 nand_dbg_print(NAND_DBG_TRACE, "At start of Execute CMDs: "
672 "Tag Count %u\n", tag_count);
673
674 for (i = 0; i < totalUsedBanks; i++) {
675 PendingCMD[i].CMD = DUMMY_CMD;
676 PendingCMD[i].Tag = 0xFF;
677 PendingCMD[i].Block =
678 (DeviceInfo.wTotalBlocks / totalUsedBanks) * i;
679
680 for (j = 0; j <= MAX_CHANS; j++)
681 PendingCMD[i].ChanSync[j] = 0;
682 }
683
684 CDMA_Execute_CMDs(tag_count);
685
686 print_pending_cmds(tag_count);
687
688#if DEBUG_SYNC
689 }
690 debug_sync_cnt++;
691#endif
692
693 for (i = MAX_CHANS;
694 i < tag_count + MAX_CHANS; i++) {
695 CMD = PendingCMD[i].CMD;
696 data = PendingCMD[i].DataAddr;
697 block = PendingCMD[i].Block;
698 page = PendingCMD[i].Page;
699 count = PendingCMD[i].PageCount;
700
701 switch (CMD) {
702 case ERASE_CMD:
703 emu_Erase_Block(block);
704 PendingCMD[i].Status = PASS;
705 break;
706 case WRITE_MAIN_CMD:
707 emu_Write_Page_Main(data, block, page, count);
708 PendingCMD[i].Status = PASS;
709 break;
710 case WRITE_MAIN_SPARE_CMD:
711 emu_Write_Page_Main_Spare(data, block, page, count);
712 PendingCMD[i].Status = PASS;
713 break;
714 case READ_MAIN_CMD:
715 emu_Read_Page_Main(data, block, page, count);
716 PendingCMD[i].Status = PASS;
717 break;
718 case MEMCOPY_CMD:
719 memcpy(PendingCMD[i].DataDestAddr,
720 PendingCMD[i].DataSrcAddr,
721 PendingCMD[i].MemCopyByteCnt);
722 case DUMMY_CMD:
723 PendingCMD[i].Status = PASS;
724 break;
725 default:
726 PendingCMD[i].Status = FAIL;
727 break;
728 }
729 }
730
731 /*
732 * Temperory adding code to reset PendingCMD array for basic testing.
733 * It should be done at the end of event status function.
734 */
735 for (i = tag_count + MAX_CHANS; i < MAX_DESCS; i++) {
736 PendingCMD[i].CMD = 0;
737 PendingCMD[i].Tag = 0;
738 PendingCMD[i].DataAddr = 0;
739 PendingCMD[i].Block = 0;
740 PendingCMD[i].Page = 0;
741 PendingCMD[i].PageCount = 0;
742 PendingCMD[i].DataDestAddr = 0;
743 PendingCMD[i].DataSrcAddr = 0;
744 PendingCMD[i].MemCopyByteCnt = 0;
745 PendingCMD[i].ChanSync[0] = 0;
746 PendingCMD[i].ChanSync[1] = 0;
747 PendingCMD[i].ChanSync[2] = 0;
748 PendingCMD[i].ChanSync[3] = 0;
749 PendingCMD[i].ChanSync[4] = 0;
750 PendingCMD[i].Status = CMD_NOT_DONE;
751 }
752
753 nand_dbg_print(NAND_DBG_TRACE, "At end of Execute CMDs.\n");
754
755 emu_isr(0, 0); /* This is a null isr now. Need fill it in future */
756
757 return status;
758}
759
760/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
761* Function: emu_Event_Status
762* Inputs: none
763* Outputs: Event_Status code
764* Description: This function can also be used to force errors
765*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
766u16 emu_CDMA_Event_Status(void)
767{
768 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
769 __FILE__, __LINE__, __func__);
770
771 return EVENT_PASS;
772}
773
774#endif /* CMD_DMA */
775#endif /* !ELDORA */
776#endif /* FLASH_EMU */
diff --git a/drivers/staging/spectra/lld_emu.h b/drivers/staging/spectra/lld_emu.h
new file mode 100644
index 00000000000..63f84c38d3c
--- /dev/null
+++ b/drivers/staging/spectra/lld_emu.h
@@ -0,0 +1,51 @@
1/*
2 * NAND Flash Controller Device Driver
3 * Copyright (c) 2009, Intel Corporation and its suppliers.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19
20#ifndef _LLD_EMU_
21#define _LLD_EMU_
22
23#include "ffsport.h"
24#include "ffsdefs.h"
25
26/* prototypes: emulator API functions */
27extern u16 emu_Flash_Reset(void);
28extern u16 emu_Flash_Init(void);
29extern int emu_Flash_Release(void);
30extern u16 emu_Read_Device_ID(void);
31extern u16 emu_Erase_Block(u32 block_addr);
32extern u16 emu_Write_Page_Main(u8 *write_data, u32 Block,
33 u16 Page, u16 PageCount);
34extern u16 emu_Read_Page_Main(u8 *read_data, u32 Block, u16 Page,
35 u16 PageCount);
36extern u16 emu_Event_Status(void);
37extern void emu_Enable_Disable_Interrupts(u16 INT_ENABLE);
38extern u16 emu_Write_Page_Main_Spare(u8 *write_data, u32 Block,
39 u16 Page, u16 PageCount);
40extern u16 emu_Write_Page_Spare(u8 *write_data, u32 Block,
41 u16 Page, u16 PageCount);
42extern u16 emu_Read_Page_Main_Spare(u8 *read_data, u32 Block,
43 u16 Page, u16 PageCount);
44extern u16 emu_Read_Page_Spare(u8 *read_data, u32 Block, u16 Page,
45 u16 PageCount);
46extern u16 emu_Get_Bad_Block(u32 block);
47
48u16 emu_CDMA_Flash_Init(void);
49u16 emu_CDMA_Execute_CMDs(u16 tag_count);
50u16 emu_CDMA_Event_Status(void);
51#endif /*_LLD_EMU_*/
diff --git a/drivers/staging/spectra/lld_mtd.c b/drivers/staging/spectra/lld_mtd.c
new file mode 100644
index 00000000000..2bd34662beb
--- /dev/null
+++ b/drivers/staging/spectra/lld_mtd.c
@@ -0,0 +1,683 @@
1/*
2 * NAND Flash Controller Device Driver
3 * Copyright (c) 2009, Intel Corporation and its suppliers.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19
20#include <linux/fs.h>
21#include <linux/slab.h>
22#include <linux/mtd/mtd.h>
23#include "flash.h"
24#include "ffsdefs.h"
25#include "lld_emu.h"
26#include "lld.h"
27#if CMD_DMA
28#include "lld_cdma.h"
29u32 totalUsedBanks;
30u32 valid_banks[MAX_CHANS];
31#endif
32
33#define GLOB_LLD_PAGES 64
34#define GLOB_LLD_PAGE_SIZE (512+16)
35#define GLOB_LLD_PAGE_DATA_SIZE 512
36#define GLOB_LLD_BLOCKS 2048
37
38static struct mtd_info *spectra_mtd;
39static int mtddev = -1;
40module_param(mtddev, int, 0);
41
42/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
43* Function: mtd_Flash_Init
44* Inputs: none
45* Outputs: PASS=0 (notice 0=ok here)
46* Description: Creates & initializes the flash RAM array.
47*
48*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
49u16 mtd_Flash_Init(void)
50{
51 if (mtddev == -1) {
52 printk(KERN_ERR "No MTD device specified. Give mtddev parameter\n");
53 return FAIL;
54 }
55
56 spectra_mtd = get_mtd_device(NULL, mtddev);
57 if (!spectra_mtd) {
58 printk(KERN_ERR "Failed to obtain MTD device #%d\n", mtddev);
59 return FAIL;
60 }
61
62 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
63 __FILE__, __LINE__, __func__);
64
65 return PASS;
66}
67
68/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
69* Function: mtd_Flash_Release
70* Inputs: none
71* Outputs: PASS=0 (notice 0=ok here)
72* Description: Releases the flash.
73*
74*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
75int mtd_Flash_Release(void)
76{
77 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
78 __FILE__, __LINE__, __func__);
79 if (!spectra_mtd)
80 return PASS;
81
82 put_mtd_device(spectra_mtd);
83 spectra_mtd = NULL;
84
85 return PASS;
86}
87
88/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
89* Function: mtd_Read_Device_ID
90* Inputs: none
91* Outputs: PASS=1 FAIL=0
92* Description: Reads the info from the controller registers.
93* Sets up DeviceInfo structure with device parameters
94*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
95
96u16 mtd_Read_Device_ID(void)
97{
98 uint64_t tmp;
99 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
100 __FILE__, __LINE__, __func__);
101
102 if (!spectra_mtd)
103 return FAIL;
104
105 DeviceInfo.wDeviceMaker = 0;
106 DeviceInfo.wDeviceType = 8;
107 DeviceInfo.wSpectraStartBlock = SPECTRA_START_BLOCK;
108 tmp = spectra_mtd->size;
109 do_div(tmp, spectra_mtd->erasesize);
110 DeviceInfo.wTotalBlocks = tmp;
111 DeviceInfo.wSpectraEndBlock = DeviceInfo.wTotalBlocks - 1;
112 DeviceInfo.wPagesPerBlock = spectra_mtd->erasesize / spectra_mtd->writesize;
113 DeviceInfo.wPageSize = spectra_mtd->writesize + spectra_mtd->oobsize;
114 DeviceInfo.wPageDataSize = spectra_mtd->writesize;
115 DeviceInfo.wPageSpareSize = spectra_mtd->oobsize;
116 DeviceInfo.wBlockSize = DeviceInfo.wPageSize * DeviceInfo.wPagesPerBlock;
117 DeviceInfo.wBlockDataSize = DeviceInfo.wPageDataSize * DeviceInfo.wPagesPerBlock;
118 DeviceInfo.wDataBlockNum = (u32) (DeviceInfo.wSpectraEndBlock -
119 DeviceInfo.wSpectraStartBlock
120 + 1);
121 DeviceInfo.MLCDevice = 0;//spectra_mtd->celltype & NAND_CI_CELLTYPE_MSK;
122 DeviceInfo.nBitsInPageNumber =
123 (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPagesPerBlock);
124 DeviceInfo.nBitsInPageDataSize =
125 (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPageDataSize);
126 DeviceInfo.nBitsInBlockDataSize =
127 (u8)GLOB_Calc_Used_Bits(DeviceInfo.wBlockDataSize);
128
129#if CMD_DMA
130 totalUsedBanks = 4;
131 valid_banks[0] = 1;
132 valid_banks[1] = 1;
133 valid_banks[2] = 1;
134 valid_banks[3] = 1;
135#endif
136
137 return PASS;
138}
139
140/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
141* Function: mtd_Flash_Reset
142* Inputs: none
143* Outputs: PASS=0 (notice 0=ok here)
144* Description: Reset the flash
145*
146*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
147u16 mtd_Flash_Reset(void)
148{
149 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
150 __FILE__, __LINE__, __func__);
151
152 return PASS;
153}
154
155void erase_callback(struct erase_info *e)
156{
157 complete((void *)e->priv);
158}
159
160/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
161* Function: mtd_Erase_Block
162* Inputs: Address
163* Outputs: PASS=0 (notice 0=ok here)
164* Description: Erase a block
165*
166*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
167u16 mtd_Erase_Block(u32 block_add)
168{
169 struct erase_info erase;
170 DECLARE_COMPLETION_ONSTACK(comp);
171 int ret;
172
173 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
174 __FILE__, __LINE__, __func__);
175
176 if (block_add >= DeviceInfo.wTotalBlocks) {
177 printk(KERN_ERR "mtd_Erase_Block error! "
178 "Too big block address: %d\n", block_add);
179 return FAIL;
180 }
181
182 nand_dbg_print(NAND_DBG_DEBUG, "Erasing block %d\n",
183 (int)block_add);
184
185 erase.mtd = spectra_mtd;
186 erase.callback = erase_callback;
187 erase.addr = block_add * spectra_mtd->erasesize;
188 erase.len = spectra_mtd->erasesize;
189 erase.priv = (unsigned long)&comp;
190
191 ret = spectra_mtd->erase(spectra_mtd, &erase);
192 if (!ret) {
193 wait_for_completion(&comp);
194 if (erase.state != MTD_ERASE_DONE)
195 ret = -EIO;
196 }
197 if (ret) {
198 printk(KERN_WARNING "mtd_Erase_Block error! "
199 "erase of region [0x%llx, 0x%llx] failed\n",
200 erase.addr, erase.len);
201 return FAIL;
202 }
203
204 return PASS;
205}
206
207/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
208* Function: mtd_Write_Page_Main
209* Inputs: Write buffer address pointer
210* Block number
211* Page number
212* Number of pages to process
213* Outputs: PASS=0 (notice 0=ok here)
214* Description: Write the data in the buffer to main area of flash
215*
216*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
217u16 mtd_Write_Page_Main(u8 *write_data, u32 Block,
218 u16 Page, u16 PageCount)
219{
220 size_t retlen;
221 int ret = 0;
222
223 if (Block >= DeviceInfo.wTotalBlocks)
224 return FAIL;
225
226 if (Page + PageCount > DeviceInfo.wPagesPerBlock)
227 return FAIL;
228
229 nand_dbg_print(NAND_DBG_DEBUG, "mtd_Write_Page_Main: "
230 "lba %u Page %u PageCount %u\n",
231 (unsigned int)Block,
232 (unsigned int)Page, (unsigned int)PageCount);
233
234
235 while (PageCount) {
236 ret = spectra_mtd->write(spectra_mtd,
237 (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize),
238 DeviceInfo.wPageDataSize, &retlen, write_data);
239 if (ret) {
240 printk(KERN_ERR "%s failed %d\n", __func__, ret);
241 return FAIL;
242 }
243 write_data += DeviceInfo.wPageDataSize;
244 Page++;
245 PageCount--;
246 }
247
248 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
249 __FILE__, __LINE__, __func__);
250
251 return PASS;
252}
253
254/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
255* Function: mtd_Read_Page_Main
256* Inputs: Read buffer address pointer
257* Block number
258* Page number
259* Number of pages to process
260* Outputs: PASS=0 (notice 0=ok here)
261* Description: Read the data from the flash main area to the buffer
262*
263*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
264u16 mtd_Read_Page_Main(u8 *read_data, u32 Block,
265 u16 Page, u16 PageCount)
266{
267 size_t retlen;
268 int ret = 0;
269
270 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
271 __FILE__, __LINE__, __func__);
272
273 if (Block >= DeviceInfo.wTotalBlocks)
274 return FAIL;
275
276 if (Page + PageCount > DeviceInfo.wPagesPerBlock)
277 return FAIL;
278
279 nand_dbg_print(NAND_DBG_DEBUG, "mtd_Read_Page_Main: "
280 "lba %u Page %u PageCount %u\n",
281 (unsigned int)Block,
282 (unsigned int)Page, (unsigned int)PageCount);
283
284
285 while (PageCount) {
286 ret = spectra_mtd->read(spectra_mtd,
287 (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize),
288 DeviceInfo.wPageDataSize, &retlen, read_data);
289 if (ret) {
290 printk(KERN_ERR "%s failed %d\n", __func__, ret);
291 return FAIL;
292 }
293 read_data += DeviceInfo.wPageDataSize;
294 Page++;
295 PageCount--;
296 }
297
298 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
299 __FILE__, __LINE__, __func__);
300
301 return PASS;
302}
303
304#ifndef ELDORA
305/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
306* Function: mtd_Read_Page_Main_Spare
307* Inputs: Write Buffer
308* Address
309* Buffer size
310* Outputs: PASS=0 (notice 0=ok here)
311* Description: Read from flash main+spare area
312*
313*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
314u16 mtd_Read_Page_Main_Spare(u8 *read_data, u32 Block,
315 u16 Page, u16 PageCount)
316{
317 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
318 __FILE__, __LINE__, __func__);
319
320 if (Block >= DeviceInfo.wTotalBlocks) {
321 printk(KERN_ERR "Read Page Main+Spare "
322 "Error: Block Address too big\n");
323 return FAIL;
324 }
325
326 if (Page + PageCount > DeviceInfo.wPagesPerBlock) {
327 printk(KERN_ERR "Read Page Main+Spare "
328 "Error: Page number %d+%d too big in block %d\n",
329 Page, PageCount, Block);
330 return FAIL;
331 }
332
333 nand_dbg_print(NAND_DBG_DEBUG, "Read Page Main + Spare - "
334 "No. of pages %u block %u start page %u\n",
335 (unsigned int)PageCount,
336 (unsigned int)Block, (unsigned int)Page);
337
338
339 while (PageCount) {
340 struct mtd_oob_ops ops;
341 int ret;
342
343 ops.mode = MTD_OOB_AUTO;
344 ops.datbuf = read_data;
345 ops.len = DeviceInfo.wPageDataSize;
346 ops.oobbuf = read_data + DeviceInfo.wPageDataSize + BTSIG_OFFSET;
347 ops.ooblen = BTSIG_BYTES;
348 ops.ooboffs = 0;
349
350 ret = spectra_mtd->read_oob(spectra_mtd,
351 (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize),
352 &ops);
353 if (ret) {
354 printk(KERN_ERR "%s failed %d\n", __func__, ret);
355 return FAIL;
356 }
357 read_data += DeviceInfo.wPageSize;
358 Page++;
359 PageCount--;
360 }
361
362 return PASS;
363}
364
365/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
366* Function: mtd_Write_Page_Main_Spare
367* Inputs: Write buffer
368* address
369* buffer length
370* Outputs: PASS=0 (notice 0=ok here)
371* Description: Write the buffer to main+spare area of flash
372*
373*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
374u16 mtd_Write_Page_Main_Spare(u8 *write_data, u32 Block,
375 u16 Page, u16 page_count)
376{
377 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
378 __FILE__, __LINE__, __func__);
379
380 if (Block >= DeviceInfo.wTotalBlocks) {
381 printk(KERN_ERR "Write Page Main + Spare "
382 "Error: Block Address too big\n");
383 return FAIL;
384 }
385
386 if (Page + page_count > DeviceInfo.wPagesPerBlock) {
387 printk(KERN_ERR "Write Page Main + Spare "
388 "Error: Page number %d+%d too big in block %d\n",
389 Page, page_count, Block);
390 WARN_ON(1);
391 return FAIL;
392 }
393
394 nand_dbg_print(NAND_DBG_DEBUG, "Write Page Main+Spare - "
395 "No. of pages %u block %u start page %u\n",
396 (unsigned int)page_count,
397 (unsigned int)Block, (unsigned int)Page);
398
399 while (page_count) {
400 struct mtd_oob_ops ops;
401 int ret;
402
403 ops.mode = MTD_OOB_AUTO;
404 ops.datbuf = write_data;
405 ops.len = DeviceInfo.wPageDataSize;
406 ops.oobbuf = write_data + DeviceInfo.wPageDataSize + BTSIG_OFFSET;
407 ops.ooblen = BTSIG_BYTES;
408 ops.ooboffs = 0;
409
410 ret = spectra_mtd->write_oob(spectra_mtd,
411 (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize),
412 &ops);
413 if (ret) {
414 printk(KERN_ERR "%s failed %d\n", __func__, ret);
415 return FAIL;
416 }
417 write_data += DeviceInfo.wPageSize;
418 Page++;
419 page_count--;
420 }
421
422 return PASS;
423}
424
425/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
426* Function: mtd_Write_Page_Spare
427* Inputs: Write buffer
428* Address
429* buffer size
430* Outputs: PASS=0 (notice 0=ok here)
431* Description: Write the buffer in the spare area
432*
433*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
434u16 mtd_Write_Page_Spare(u8 *write_data, u32 Block,
435 u16 Page, u16 PageCount)
436{
437 WARN_ON(1);
438 return FAIL;
439}
440
441/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
442* Function: mtd_Read_Page_Spare
443* Inputs: Write Buffer
444* Address
445* Buffer size
446* Outputs: PASS=0 (notice 0=ok here)
447* Description: Read data from the spare area
448*
449*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
450u16 mtd_Read_Page_Spare(u8 *read_data, u32 Block,
451 u16 Page, u16 PageCount)
452{
453 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
454 __FILE__, __LINE__, __func__);
455
456 if (Block >= DeviceInfo.wTotalBlocks) {
457 printk(KERN_ERR "Read Page Spare "
458 "Error: Block Address too big\n");
459 return FAIL;
460 }
461
462 if (Page + PageCount > DeviceInfo.wPagesPerBlock) {
463 printk(KERN_ERR "Read Page Spare "
464 "Error: Page number too big\n");
465 return FAIL;
466 }
467
468 nand_dbg_print(NAND_DBG_DEBUG, "Read Page Spare- "
469 "block %u page %u (%u pages)\n",
470 (unsigned int)Block, (unsigned int)Page, PageCount);
471
472 while (PageCount) {
473 struct mtd_oob_ops ops;
474 int ret;
475
476 ops.mode = MTD_OOB_AUTO;
477 ops.datbuf = NULL;
478 ops.len = 0;
479 ops.oobbuf = read_data;
480 ops.ooblen = BTSIG_BYTES;
481 ops.ooboffs = 0;
482
483 ret = spectra_mtd->read_oob(spectra_mtd,
484 (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize),
485 &ops);
486 if (ret) {
487 printk(KERN_ERR "%s failed %d\n", __func__, ret);
488 return FAIL;
489 }
490
491 read_data += DeviceInfo.wPageSize;
492 Page++;
493 PageCount--;
494 }
495
496 return PASS;
497}
498
499/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
500* Function: mtd_Enable_Disable_Interrupts
501* Inputs: enable or disable
502* Outputs: none
503* Description: NOP
504*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
505void mtd_Enable_Disable_Interrupts(u16 INT_ENABLE)
506{
507 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
508 __FILE__, __LINE__, __func__);
509}
510
511u16 mtd_Get_Bad_Block(u32 block)
512{
513 return 0;
514}
515
516#if CMD_DMA
517/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
518* Support for CDMA functions
519************************************
520* mtd_CDMA_Flash_Init
521* CDMA_process_data command (use LLD_CDMA)
522* CDMA_MemCopy_CMD (use LLD_CDMA)
523* mtd_CDMA_execute all commands
524* mtd_CDMA_Event_Status
525*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
526u16 mtd_CDMA_Flash_Init(void)
527{
528 u16 i;
529
530 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
531 __FILE__, __LINE__, __func__);
532
533 for (i = 0; i < MAX_DESCS + MAX_CHANS; i++) {
534 PendingCMD[i].CMD = 0;
535 PendingCMD[i].Tag = 0;
536 PendingCMD[i].DataAddr = 0;
537 PendingCMD[i].Block = 0;
538 PendingCMD[i].Page = 0;
539 PendingCMD[i].PageCount = 0;
540 PendingCMD[i].DataDestAddr = 0;
541 PendingCMD[i].DataSrcAddr = 0;
542 PendingCMD[i].MemCopyByteCnt = 0;
543 PendingCMD[i].ChanSync[0] = 0;
544 PendingCMD[i].ChanSync[1] = 0;
545 PendingCMD[i].ChanSync[2] = 0;
546 PendingCMD[i].ChanSync[3] = 0;
547 PendingCMD[i].ChanSync[4] = 0;
548 PendingCMD[i].Status = 3;
549 }
550
551 return PASS;
552}
553
554static void mtd_isr(int irq, void *dev_id)
555{
556 /* TODO: ... */
557}
558
559/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
560* Function: CDMA_Execute_CMDs
561* Inputs: tag_count: the number of pending cmds to do
562* Outputs: PASS/FAIL
563* Description: execute each command in the pending CMD array
564*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
565u16 mtd_CDMA_Execute_CMDs(u16 tag_count)
566{
567 u16 i, j;
568 u8 CMD; /* cmd parameter */
569 u8 *data;
570 u32 block;
571 u16 page;
572 u16 count;
573 u16 status = PASS;
574
575 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
576 __FILE__, __LINE__, __func__);
577
578 nand_dbg_print(NAND_DBG_TRACE, "At start of Execute CMDs: "
579 "Tag Count %u\n", tag_count);
580
581 for (i = 0; i < totalUsedBanks; i++) {
582 PendingCMD[i].CMD = DUMMY_CMD;
583 PendingCMD[i].Tag = 0xFF;
584 PendingCMD[i].Block =
585 (DeviceInfo.wTotalBlocks / totalUsedBanks) * i;
586
587 for (j = 0; j <= MAX_CHANS; j++)
588 PendingCMD[i].ChanSync[j] = 0;
589 }
590
591 CDMA_Execute_CMDs(tag_count);
592
593#ifdef VERBOSE
594 print_pending_cmds(tag_count);
595#endif
596#if DEBUG_SYNC
597 }
598 debug_sync_cnt++;
599#endif
600
601 for (i = MAX_CHANS;
602 i < tag_count + MAX_CHANS; i++) {
603 CMD = PendingCMD[i].CMD;
604 data = PendingCMD[i].DataAddr;
605 block = PendingCMD[i].Block;
606 page = PendingCMD[i].Page;
607 count = PendingCMD[i].PageCount;
608
609 switch (CMD) {
610 case ERASE_CMD:
611 mtd_Erase_Block(block);
612 PendingCMD[i].Status = PASS;
613 break;
614 case WRITE_MAIN_CMD:
615 mtd_Write_Page_Main(data, block, page, count);
616 PendingCMD[i].Status = PASS;
617 break;
618 case WRITE_MAIN_SPARE_CMD:
619 mtd_Write_Page_Main_Spare(data, block, page, count);
620 PendingCMD[i].Status = PASS;
621 break;
622 case READ_MAIN_CMD:
623 mtd_Read_Page_Main(data, block, page, count);
624 PendingCMD[i].Status = PASS;
625 break;
626 case MEMCOPY_CMD:
627 memcpy(PendingCMD[i].DataDestAddr,
628 PendingCMD[i].DataSrcAddr,
629 PendingCMD[i].MemCopyByteCnt);
630 case DUMMY_CMD:
631 PendingCMD[i].Status = PASS;
632 break;
633 default:
634 PendingCMD[i].Status = FAIL;
635 break;
636 }
637 }
638
639 /*
640 * Temperory adding code to reset PendingCMD array for basic testing.
641 * It should be done at the end of event status function.
642 */
643 for (i = tag_count + MAX_CHANS; i < MAX_DESCS; i++) {
644 PendingCMD[i].CMD = 0;
645 PendingCMD[i].Tag = 0;
646 PendingCMD[i].DataAddr = 0;
647 PendingCMD[i].Block = 0;
648 PendingCMD[i].Page = 0;
649 PendingCMD[i].PageCount = 0;
650 PendingCMD[i].DataDestAddr = 0;
651 PendingCMD[i].DataSrcAddr = 0;
652 PendingCMD[i].MemCopyByteCnt = 0;
653 PendingCMD[i].ChanSync[0] = 0;
654 PendingCMD[i].ChanSync[1] = 0;
655 PendingCMD[i].ChanSync[2] = 0;
656 PendingCMD[i].ChanSync[3] = 0;
657 PendingCMD[i].ChanSync[4] = 0;
658 PendingCMD[i].Status = CMD_NOT_DONE;
659 }
660
661 nand_dbg_print(NAND_DBG_TRACE, "At end of Execute CMDs.\n");
662
663 mtd_isr(0, 0); /* This is a null isr now. Need fill it in future */
664
665 return status;
666}
667
668/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
669* Function: mtd_Event_Status
670* Inputs: none
671* Outputs: Event_Status code
672* Description: This function can also be used to force errors
673*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
674u16 mtd_CDMA_Event_Status(void)
675{
676 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
677 __FILE__, __LINE__, __func__);
678
679 return EVENT_PASS;
680}
681
682#endif /* CMD_DMA */
683#endif /* !ELDORA */
diff --git a/drivers/staging/spectra/lld_mtd.h b/drivers/staging/spectra/lld_mtd.h
new file mode 100644
index 00000000000..4e81ee87b53
--- /dev/null
+++ b/drivers/staging/spectra/lld_mtd.h
@@ -0,0 +1,51 @@
1/*
2 * NAND Flash Controller Device Driver
3 * Copyright (c) 2009, Intel Corporation and its suppliers.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19
20#ifndef _LLD_MTD_
21#define _LLD_MTD_
22
23#include "ffsport.h"
24#include "ffsdefs.h"
25
26/* prototypes: MTD API functions */
27extern u16 mtd_Flash_Reset(void);
28extern u16 mtd_Flash_Init(void);
29extern int mtd_Flash_Release(void);
30extern u16 mtd_Read_Device_ID(void);
31extern u16 mtd_Erase_Block(u32 block_addr);
32extern u16 mtd_Write_Page_Main(u8 *write_data, u32 Block,
33 u16 Page, u16 PageCount);
34extern u16 mtd_Read_Page_Main(u8 *read_data, u32 Block, u16 Page,
35 u16 PageCount);
36extern u16 mtd_Event_Status(void);
37extern void mtd_Enable_Disable_Interrupts(u16 INT_ENABLE);
38extern u16 mtd_Write_Page_Main_Spare(u8 *write_data, u32 Block,
39 u16 Page, u16 PageCount);
40extern u16 mtd_Write_Page_Spare(u8 *write_data, u32 Block,
41 u16 Page, u16 PageCount);
42extern u16 mtd_Read_Page_Main_Spare(u8 *read_data, u32 Block,
43 u16 Page, u16 PageCount);
44extern u16 mtd_Read_Page_Spare(u8 *read_data, u32 Block, u16 Page,
45 u16 PageCount);
46extern u16 mtd_Get_Bad_Block(u32 block);
47
48u16 mtd_CDMA_Flash_Init(void);
49u16 mtd_CDMA_Execute_CMDs(u16 tag_count);
50u16 mtd_CDMA_Event_Status(void);
51#endif /*_LLD_MTD_*/
diff --git a/drivers/staging/spectra/lld_nand.c b/drivers/staging/spectra/lld_nand.c
new file mode 100644
index 00000000000..60a14ff26c7
--- /dev/null
+++ b/drivers/staging/spectra/lld_nand.c
@@ -0,0 +1,2619 @@
1/*
2 * NAND Flash Controller Device Driver
3 * Copyright (c) 2009, Intel Corporation and its suppliers.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19
20#include "lld.h"
21#include "lld_nand.h"
22#include "lld_cdma.h"
23
24#include "spectraswconfig.h"
25#include "flash.h"
26#include "ffsdefs.h"
27
28#include <linux/interrupt.h>
29#include <linux/delay.h>
30#include <linux/wait.h>
31#include <linux/mutex.h>
32
33#include "nand_regs.h"
34
35#define SPECTRA_NAND_NAME "nd"
36
37#define CEIL_DIV(X, Y) (((X)%(Y)) ? ((X)/(Y)+1) : ((X)/(Y)))
38#define MAX_PAGES_PER_RW 128
39
40#define INT_IDLE_STATE 0
41#define INT_READ_PAGE_MAIN 0x01
42#define INT_WRITE_PAGE_MAIN 0x02
43#define INT_PIPELINE_READ_AHEAD 0x04
44#define INT_PIPELINE_WRITE_AHEAD 0x08
45#define INT_MULTI_PLANE_READ 0x10
46#define INT_MULTI_PLANE_WRITE 0x11
47
48static u32 enable_ecc;
49
50struct mrst_nand_info info;
51
52int totalUsedBanks;
53u32 GLOB_valid_banks[LLD_MAX_FLASH_BANKS];
54
55void __iomem *FlashReg;
56void __iomem *FlashMem;
57
58u16 conf_parameters[] = {
59 0x0000,
60 0x0000,
61 0x01F4,
62 0x01F4,
63 0x01F4,
64 0x01F4,
65 0x0000,
66 0x0000,
67 0x0001,
68 0x0000,
69 0x0000,
70 0x0000,
71 0x0000,
72 0x0040,
73 0x0001,
74 0x000A,
75 0x000A,
76 0x000A,
77 0x0000,
78 0x0000,
79 0x0005,
80 0x0012,
81 0x000C
82};
83
84u16 NAND_Get_Bad_Block(u32 block)
85{
86 u32 status = PASS;
87 u32 flag_bytes = 0;
88 u32 skip_bytes = DeviceInfo.wSpareSkipBytes;
89 u32 page, i;
90 u8 *pReadSpareBuf = buf_get_bad_block;
91
92 if (enable_ecc)
93 flag_bytes = DeviceInfo.wNumPageSpareFlag;
94
95 for (page = 0; page < 2; page++) {
96 status = NAND_Read_Page_Spare(pReadSpareBuf, block, page, 1);
97 if (status != PASS)
98 return READ_ERROR;
99 for (i = flag_bytes; i < (flag_bytes + skip_bytes); i++)
100 if (pReadSpareBuf[i] != 0xff)
101 return DEFECTIVE_BLOCK;
102 }
103
104 for (page = 1; page < 3; page++) {
105 status = NAND_Read_Page_Spare(pReadSpareBuf, block,
106 DeviceInfo.wPagesPerBlock - page , 1);
107 if (status != PASS)
108 return READ_ERROR;
109 for (i = flag_bytes; i < (flag_bytes + skip_bytes); i++)
110 if (pReadSpareBuf[i] != 0xff)
111 return DEFECTIVE_BLOCK;
112 }
113
114 return GOOD_BLOCK;
115}
116
117
118u16 NAND_Flash_Reset(void)
119{
120 u32 i;
121 u32 intr_status_rst_comp[4] = {INTR_STATUS0__RST_COMP,
122 INTR_STATUS1__RST_COMP,
123 INTR_STATUS2__RST_COMP,
124 INTR_STATUS3__RST_COMP};
125 u32 intr_status_time_out[4] = {INTR_STATUS0__TIME_OUT,
126 INTR_STATUS1__TIME_OUT,
127 INTR_STATUS2__TIME_OUT,
128 INTR_STATUS3__TIME_OUT};
129 u32 intr_status[4] = {INTR_STATUS0, INTR_STATUS1,
130 INTR_STATUS2, INTR_STATUS3};
131 u32 device_reset_banks[4] = {DEVICE_RESET__BANK0,
132 DEVICE_RESET__BANK1,
133 DEVICE_RESET__BANK2,
134 DEVICE_RESET__BANK3};
135
136 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
137 __FILE__, __LINE__, __func__);
138
139 for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++)
140 iowrite32(intr_status_rst_comp[i] | intr_status_time_out[i],
141 FlashReg + intr_status[i]);
142
143 for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++) {
144 iowrite32(device_reset_banks[i], FlashReg + DEVICE_RESET);
145 while (!(ioread32(FlashReg + intr_status[i]) &
146 (intr_status_rst_comp[i] | intr_status_time_out[i])))
147 ;
148 if (ioread32(FlashReg + intr_status[i]) &
149 intr_status_time_out[i])
150 nand_dbg_print(NAND_DBG_WARN,
151 "NAND Reset operation timed out on bank %d\n", i);
152 }
153
154 for (i = 0; i < LLD_MAX_FLASH_BANKS; i++)
155 iowrite32(intr_status_rst_comp[i] | intr_status_time_out[i],
156 FlashReg + intr_status[i]);
157
158 return PASS;
159}
160
161static void NAND_ONFi_Timing_Mode(u16 mode)
162{
163 u16 Trea[6] = {40, 30, 25, 20, 20, 16};
164 u16 Trp[6] = {50, 25, 17, 15, 12, 10};
165 u16 Treh[6] = {30, 15, 15, 10, 10, 7};
166 u16 Trc[6] = {100, 50, 35, 30, 25, 20};
167 u16 Trhoh[6] = {0, 15, 15, 15, 15, 15};
168 u16 Trloh[6] = {0, 0, 0, 0, 5, 5};
169 u16 Tcea[6] = {100, 45, 30, 25, 25, 25};
170 u16 Tadl[6] = {200, 100, 100, 100, 70, 70};
171 u16 Trhw[6] = {200, 100, 100, 100, 100, 100};
172 u16 Trhz[6] = {200, 100, 100, 100, 100, 100};
173 u16 Twhr[6] = {120, 80, 80, 60, 60, 60};
174 u16 Tcs[6] = {70, 35, 25, 25, 20, 15};
175
176 u16 TclsRising = 1;
177 u16 data_invalid_rhoh, data_invalid_rloh, data_invalid;
178 u16 dv_window = 0;
179 u16 en_lo, en_hi;
180 u16 acc_clks;
181 u16 addr_2_data, re_2_we, re_2_re, we_2_re, cs_cnt;
182
183 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
184 __FILE__, __LINE__, __func__);
185
186 en_lo = CEIL_DIV(Trp[mode], CLK_X);
187 en_hi = CEIL_DIV(Treh[mode], CLK_X);
188
189#if ONFI_BLOOM_TIME
190 if ((en_hi * CLK_X) < (Treh[mode] + 2))
191 en_hi++;
192#endif
193
194 if ((en_lo + en_hi) * CLK_X < Trc[mode])
195 en_lo += CEIL_DIV((Trc[mode] - (en_lo + en_hi) * CLK_X), CLK_X);
196
197 if ((en_lo + en_hi) < CLK_MULTI)
198 en_lo += CLK_MULTI - en_lo - en_hi;
199
200 while (dv_window < 8) {
201 data_invalid_rhoh = en_lo * CLK_X + Trhoh[mode];
202
203 data_invalid_rloh = (en_lo + en_hi) * CLK_X + Trloh[mode];
204
205 data_invalid =
206 data_invalid_rhoh <
207 data_invalid_rloh ? data_invalid_rhoh : data_invalid_rloh;
208
209 dv_window = data_invalid - Trea[mode];
210
211 if (dv_window < 8)
212 en_lo++;
213 }
214
215 acc_clks = CEIL_DIV(Trea[mode], CLK_X);
216
217 while (((acc_clks * CLK_X) - Trea[mode]) < 3)
218 acc_clks++;
219
220 if ((data_invalid - acc_clks * CLK_X) < 2)
221 nand_dbg_print(NAND_DBG_WARN, "%s, Line %d: Warning!\n",
222 __FILE__, __LINE__);
223
224 addr_2_data = CEIL_DIV(Tadl[mode], CLK_X);
225 re_2_we = CEIL_DIV(Trhw[mode], CLK_X);
226 re_2_re = CEIL_DIV(Trhz[mode], CLK_X);
227 we_2_re = CEIL_DIV(Twhr[mode], CLK_X);
228 cs_cnt = CEIL_DIV((Tcs[mode] - Trp[mode]), CLK_X);
229 if (!TclsRising)
230 cs_cnt = CEIL_DIV(Tcs[mode], CLK_X);
231 if (cs_cnt == 0)
232 cs_cnt = 1;
233
234 if (Tcea[mode]) {
235 while (((cs_cnt * CLK_X) + Trea[mode]) < Tcea[mode])
236 cs_cnt++;
237 }
238
239#if MODE5_WORKAROUND
240 if (mode == 5)
241 acc_clks = 5;
242#endif
243
244 /* Sighting 3462430: Temporary hack for MT29F128G08CJABAWP:B */
245 if ((ioread32(FlashReg + MANUFACTURER_ID) == 0) &&
246 (ioread32(FlashReg + DEVICE_ID) == 0x88))
247 acc_clks = 6;
248
249 iowrite32(acc_clks, FlashReg + ACC_CLKS);
250 iowrite32(re_2_we, FlashReg + RE_2_WE);
251 iowrite32(re_2_re, FlashReg + RE_2_RE);
252 iowrite32(we_2_re, FlashReg + WE_2_RE);
253 iowrite32(addr_2_data, FlashReg + ADDR_2_DATA);
254 iowrite32(en_lo, FlashReg + RDWR_EN_LO_CNT);
255 iowrite32(en_hi, FlashReg + RDWR_EN_HI_CNT);
256 iowrite32(cs_cnt, FlashReg + CS_SETUP_CNT);
257}
258
259static void index_addr(u32 address, u32 data)
260{
261 iowrite32(address, FlashMem);
262 iowrite32(data, FlashMem + 0x10);
263}
264
265static void index_addr_read_data(u32 address, u32 *pdata)
266{
267 iowrite32(address, FlashMem);
268 *pdata = ioread32(FlashMem + 0x10);
269}
270
271static void set_ecc_config(void)
272{
273#if SUPPORT_8BITECC
274 if ((ioread32(FlashReg + DEVICE_MAIN_AREA_SIZE) < 4096) ||
275 (ioread32(FlashReg + DEVICE_SPARE_AREA_SIZE) <= 128))
276 iowrite32(8, FlashReg + ECC_CORRECTION);
277#endif
278
279 if ((ioread32(FlashReg + ECC_CORRECTION) & ECC_CORRECTION__VALUE)
280 == 1) {
281 DeviceInfo.wECCBytesPerSector = 4;
282 DeviceInfo.wECCBytesPerSector *= DeviceInfo.wDevicesConnected;
283 DeviceInfo.wNumPageSpareFlag =
284 DeviceInfo.wPageSpareSize -
285 DeviceInfo.wPageDataSize /
286 (ECC_SECTOR_SIZE * DeviceInfo.wDevicesConnected) *
287 DeviceInfo.wECCBytesPerSector
288 - DeviceInfo.wSpareSkipBytes;
289 } else {
290 DeviceInfo.wECCBytesPerSector =
291 (ioread32(FlashReg + ECC_CORRECTION) &
292 ECC_CORRECTION__VALUE) * 13 / 8;
293 if ((DeviceInfo.wECCBytesPerSector) % 2 == 0)
294 DeviceInfo.wECCBytesPerSector += 2;
295 else
296 DeviceInfo.wECCBytesPerSector += 1;
297
298 DeviceInfo.wECCBytesPerSector *= DeviceInfo.wDevicesConnected;
299 DeviceInfo.wNumPageSpareFlag = DeviceInfo.wPageSpareSize -
300 DeviceInfo.wPageDataSize /
301 (ECC_SECTOR_SIZE * DeviceInfo.wDevicesConnected) *
302 DeviceInfo.wECCBytesPerSector
303 - DeviceInfo.wSpareSkipBytes;
304 }
305}
306
307static u16 get_onfi_nand_para(void)
308{
309 int i;
310 u16 blks_lun_l, blks_lun_h, n_of_luns;
311 u32 blockperlun, id;
312
313 iowrite32(DEVICE_RESET__BANK0, FlashReg + DEVICE_RESET);
314
315 while (!((ioread32(FlashReg + INTR_STATUS0) &
316 INTR_STATUS0__RST_COMP) |
317 (ioread32(FlashReg + INTR_STATUS0) &
318 INTR_STATUS0__TIME_OUT)))
319 ;
320
321 if (ioread32(FlashReg + INTR_STATUS0) & INTR_STATUS0__RST_COMP) {
322 iowrite32(DEVICE_RESET__BANK1, FlashReg + DEVICE_RESET);
323 while (!((ioread32(FlashReg + INTR_STATUS1) &
324 INTR_STATUS1__RST_COMP) |
325 (ioread32(FlashReg + INTR_STATUS1) &
326 INTR_STATUS1__TIME_OUT)))
327 ;
328
329 if (ioread32(FlashReg + INTR_STATUS1) &
330 INTR_STATUS1__RST_COMP) {
331 iowrite32(DEVICE_RESET__BANK2,
332 FlashReg + DEVICE_RESET);
333 while (!((ioread32(FlashReg + INTR_STATUS2) &
334 INTR_STATUS2__RST_COMP) |
335 (ioread32(FlashReg + INTR_STATUS2) &
336 INTR_STATUS2__TIME_OUT)))
337 ;
338
339 if (ioread32(FlashReg + INTR_STATUS2) &
340 INTR_STATUS2__RST_COMP) {
341 iowrite32(DEVICE_RESET__BANK3,
342 FlashReg + DEVICE_RESET);
343 while (!((ioread32(FlashReg + INTR_STATUS3) &
344 INTR_STATUS3__RST_COMP) |
345 (ioread32(FlashReg + INTR_STATUS3) &
346 INTR_STATUS3__TIME_OUT)))
347 ;
348 } else {
349 printk(KERN_ERR "Getting a time out for bank 2!\n");
350 }
351 } else {
352 printk(KERN_ERR "Getting a time out for bank 1!\n");
353 }
354 }
355
356 iowrite32(INTR_STATUS0__TIME_OUT, FlashReg + INTR_STATUS0);
357 iowrite32(INTR_STATUS1__TIME_OUT, FlashReg + INTR_STATUS1);
358 iowrite32(INTR_STATUS2__TIME_OUT, FlashReg + INTR_STATUS2);
359 iowrite32(INTR_STATUS3__TIME_OUT, FlashReg + INTR_STATUS3);
360
361 DeviceInfo.wONFIDevFeatures =
362 ioread32(FlashReg + ONFI_DEVICE_FEATURES);
363 DeviceInfo.wONFIOptCommands =
364 ioread32(FlashReg + ONFI_OPTIONAL_COMMANDS);
365 DeviceInfo.wONFITimingMode =
366 ioread32(FlashReg + ONFI_TIMING_MODE);
367 DeviceInfo.wONFIPgmCacheTimingMode =
368 ioread32(FlashReg + ONFI_PGM_CACHE_TIMING_MODE);
369
370 n_of_luns = ioread32(FlashReg + ONFI_DEVICE_NO_OF_LUNS) &
371 ONFI_DEVICE_NO_OF_LUNS__NO_OF_LUNS;
372 blks_lun_l = ioread32(FlashReg + ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L);
373 blks_lun_h = ioread32(FlashReg + ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U);
374
375 blockperlun = (blks_lun_h << 16) | blks_lun_l;
376
377 DeviceInfo.wTotalBlocks = n_of_luns * blockperlun;
378
379 if (!(ioread32(FlashReg + ONFI_TIMING_MODE) &
380 ONFI_TIMING_MODE__VALUE))
381 return FAIL;
382
383 for (i = 5; i > 0; i--) {
384 if (ioread32(FlashReg + ONFI_TIMING_MODE) & (0x01 << i))
385 break;
386 }
387
388 NAND_ONFi_Timing_Mode(i);
389
390 index_addr(MODE_11 | 0, 0x90);
391 index_addr(MODE_11 | 1, 0);
392
393 for (i = 0; i < 3; i++)
394 index_addr_read_data(MODE_11 | 2, &id);
395
396 nand_dbg_print(NAND_DBG_DEBUG, "3rd ID: 0x%x\n", id);
397
398 DeviceInfo.MLCDevice = id & 0x0C;
399
400 /* By now, all the ONFI devices we know support the page cache */
401 /* rw feature. So here we enable the pipeline_rw_ahead feature */
402 /* iowrite32(1, FlashReg + CACHE_WRITE_ENABLE); */
403 /* iowrite32(1, FlashReg + CACHE_READ_ENABLE); */
404
405 return PASS;
406}
407
408static void get_samsung_nand_para(void)
409{
410 u8 no_of_planes;
411 u32 blk_size;
412 u64 plane_size, capacity;
413 u32 id_bytes[5];
414 int i;
415
416 index_addr((u32)(MODE_11 | 0), 0x90);
417 index_addr((u32)(MODE_11 | 1), 0);
418 for (i = 0; i < 5; i++)
419 index_addr_read_data((u32)(MODE_11 | 2), &id_bytes[i]);
420
421 nand_dbg_print(NAND_DBG_DEBUG,
422 "ID bytes: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
423 id_bytes[0], id_bytes[1], id_bytes[2],
424 id_bytes[3], id_bytes[4]);
425
426 if ((id_bytes[1] & 0xff) == 0xd3) { /* Samsung K9WAG08U1A */
427 /* Set timing register values according to datasheet */
428 iowrite32(5, FlashReg + ACC_CLKS);
429 iowrite32(20, FlashReg + RE_2_WE);
430 iowrite32(12, FlashReg + WE_2_RE);
431 iowrite32(14, FlashReg + ADDR_2_DATA);
432 iowrite32(3, FlashReg + RDWR_EN_LO_CNT);
433 iowrite32(2, FlashReg + RDWR_EN_HI_CNT);
434 iowrite32(2, FlashReg + CS_SETUP_CNT);
435 }
436
437 no_of_planes = 1 << ((id_bytes[4] & 0x0c) >> 2);
438 plane_size = (u64)64 << ((id_bytes[4] & 0x70) >> 4);
439 blk_size = 64 << ((ioread32(FlashReg + DEVICE_PARAM_1) & 0x30) >> 4);
440 capacity = (u64)128 * plane_size * no_of_planes;
441
442 DeviceInfo.wTotalBlocks = (u32)GLOB_u64_Div(capacity, blk_size);
443}
444
445static void get_toshiba_nand_para(void)
446{
447 void __iomem *scratch_reg;
448 u32 tmp;
449
450 /* Workaround to fix a controller bug which reports a wrong */
451 /* spare area size for some kind of Toshiba NAND device */
452 if ((ioread32(FlashReg + DEVICE_MAIN_AREA_SIZE) == 4096) &&
453 (ioread32(FlashReg + DEVICE_SPARE_AREA_SIZE) == 64)) {
454 iowrite32(216, FlashReg + DEVICE_SPARE_AREA_SIZE);
455 tmp = ioread32(FlashReg + DEVICES_CONNECTED) *
456 ioread32(FlashReg + DEVICE_SPARE_AREA_SIZE);
457 iowrite32(tmp, FlashReg + LOGICAL_PAGE_SPARE_SIZE);
458#if SUPPORT_15BITECC
459 iowrite32(15, FlashReg + ECC_CORRECTION);
460#elif SUPPORT_8BITECC
461 iowrite32(8, FlashReg + ECC_CORRECTION);
462#endif
463 }
464
465 /* As Toshiba NAND can not provide it's block number, */
466 /* so here we need user to provide the correct block */
467 /* number in a scratch register before the Linux NAND */
468 /* driver is loaded. If no valid value found in the scratch */
469 /* register, then we use default block number value */
470 scratch_reg = ioremap_nocache(SCRATCH_REG_ADDR, SCRATCH_REG_SIZE);
471 if (!scratch_reg) {
472 printk(KERN_ERR "Spectra: ioremap failed in %s, Line %d",
473 __FILE__, __LINE__);
474 DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS;
475 } else {
476 nand_dbg_print(NAND_DBG_WARN,
477 "Spectra: ioremap reg address: 0x%p\n", scratch_reg);
478 DeviceInfo.wTotalBlocks = 1 << ioread8(scratch_reg);
479 if (DeviceInfo.wTotalBlocks < 512)
480 DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS;
481 iounmap(scratch_reg);
482 }
483}
484
485static void get_hynix_nand_para(void)
486{
487 void __iomem *scratch_reg;
488 u32 main_size, spare_size;
489
490 switch (DeviceInfo.wDeviceID) {
491 case 0xD5: /* Hynix H27UAG8T2A, H27UBG8U5A or H27UCG8VFA */
492 case 0xD7: /* Hynix H27UDG8VEM, H27UCG8UDM or H27UCG8V5A */
493 iowrite32(128, FlashReg + PAGES_PER_BLOCK);
494 iowrite32(4096, FlashReg + DEVICE_MAIN_AREA_SIZE);
495 iowrite32(224, FlashReg + DEVICE_SPARE_AREA_SIZE);
496 main_size = 4096 * ioread32(FlashReg + DEVICES_CONNECTED);
497 spare_size = 224 * ioread32(FlashReg + DEVICES_CONNECTED);
498 iowrite32(main_size, FlashReg + LOGICAL_PAGE_DATA_SIZE);
499 iowrite32(spare_size, FlashReg + LOGICAL_PAGE_SPARE_SIZE);
500 iowrite32(0, FlashReg + DEVICE_WIDTH);
501#if SUPPORT_15BITECC
502 iowrite32(15, FlashReg + ECC_CORRECTION);
503#elif SUPPORT_8BITECC
504 iowrite32(8, FlashReg + ECC_CORRECTION);
505#endif
506 DeviceInfo.MLCDevice = 1;
507 break;
508 default:
509 nand_dbg_print(NAND_DBG_WARN,
510 "Spectra: Unknown Hynix NAND (Device ID: 0x%x)."
511 "Will use default parameter values instead.\n",
512 DeviceInfo.wDeviceID);
513 }
514
515 scratch_reg = ioremap_nocache(SCRATCH_REG_ADDR, SCRATCH_REG_SIZE);
516 if (!scratch_reg) {
517 printk(KERN_ERR "Spectra: ioremap failed in %s, Line %d",
518 __FILE__, __LINE__);
519 DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS;
520 } else {
521 nand_dbg_print(NAND_DBG_WARN,
522 "Spectra: ioremap reg address: 0x%p\n", scratch_reg);
523 DeviceInfo.wTotalBlocks = 1 << ioread8(scratch_reg);
524 if (DeviceInfo.wTotalBlocks < 512)
525 DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS;
526 iounmap(scratch_reg);
527 }
528}
529
530static void find_valid_banks(void)
531{
532 u32 id[LLD_MAX_FLASH_BANKS];
533 int i;
534
535 totalUsedBanks = 0;
536 for (i = 0; i < LLD_MAX_FLASH_BANKS; i++) {
537 index_addr((u32)(MODE_11 | (i << 24) | 0), 0x90);
538 index_addr((u32)(MODE_11 | (i << 24) | 1), 0);
539 index_addr_read_data((u32)(MODE_11 | (i << 24) | 2), &id[i]);
540
541 nand_dbg_print(NAND_DBG_DEBUG,
542 "Return 1st ID for bank[%d]: %x\n", i, id[i]);
543
544 if (i == 0) {
545 if (id[i] & 0x0ff)
546 GLOB_valid_banks[i] = 1;
547 } else {
548 if ((id[i] & 0x0ff) == (id[0] & 0x0ff))
549 GLOB_valid_banks[i] = 1;
550 }
551
552 totalUsedBanks += GLOB_valid_banks[i];
553 }
554
555 nand_dbg_print(NAND_DBG_DEBUG,
556 "totalUsedBanks: %d\n", totalUsedBanks);
557}
558
559static void detect_partition_feature(void)
560{
561 if (ioread32(FlashReg + FEATURES) & FEATURES__PARTITION) {
562 if ((ioread32(FlashReg + PERM_SRC_ID_1) &
563 PERM_SRC_ID_1__SRCID) == SPECTRA_PARTITION_ID) {
564 DeviceInfo.wSpectraStartBlock =
565 ((ioread32(FlashReg + MIN_MAX_BANK_1) &
566 MIN_MAX_BANK_1__MIN_VALUE) *
567 DeviceInfo.wTotalBlocks)
568 +
569 (ioread32(FlashReg + MIN_BLK_ADDR_1) &
570 MIN_BLK_ADDR_1__VALUE);
571
572 DeviceInfo.wSpectraEndBlock =
573 (((ioread32(FlashReg + MIN_MAX_BANK_1) &
574 MIN_MAX_BANK_1__MAX_VALUE) >> 2) *
575 DeviceInfo.wTotalBlocks)
576 +
577 (ioread32(FlashReg + MAX_BLK_ADDR_1) &
578 MAX_BLK_ADDR_1__VALUE);
579
580 DeviceInfo.wTotalBlocks *= totalUsedBanks;
581
582 if (DeviceInfo.wSpectraEndBlock >=
583 DeviceInfo.wTotalBlocks) {
584 DeviceInfo.wSpectraEndBlock =
585 DeviceInfo.wTotalBlocks - 1;
586 }
587
588 DeviceInfo.wDataBlockNum =
589 DeviceInfo.wSpectraEndBlock -
590 DeviceInfo.wSpectraStartBlock + 1;
591 } else {
592 DeviceInfo.wTotalBlocks *= totalUsedBanks;
593 DeviceInfo.wSpectraStartBlock = SPECTRA_START_BLOCK;
594 DeviceInfo.wSpectraEndBlock =
595 DeviceInfo.wTotalBlocks - 1;
596 DeviceInfo.wDataBlockNum =
597 DeviceInfo.wSpectraEndBlock -
598 DeviceInfo.wSpectraStartBlock + 1;
599 }
600 } else {
601 DeviceInfo.wTotalBlocks *= totalUsedBanks;
602 DeviceInfo.wSpectraStartBlock = SPECTRA_START_BLOCK;
603 DeviceInfo.wSpectraEndBlock = DeviceInfo.wTotalBlocks - 1;
604 DeviceInfo.wDataBlockNum =
605 DeviceInfo.wSpectraEndBlock -
606 DeviceInfo.wSpectraStartBlock + 1;
607 }
608}
609
610static void dump_device_info(void)
611{
612 nand_dbg_print(NAND_DBG_DEBUG, "DeviceInfo:\n");
613 nand_dbg_print(NAND_DBG_DEBUG, "DeviceMaker: 0x%x\n",
614 DeviceInfo.wDeviceMaker);
615 nand_dbg_print(NAND_DBG_DEBUG, "DeviceID: 0x%x\n",
616 DeviceInfo.wDeviceID);
617 nand_dbg_print(NAND_DBG_DEBUG, "DeviceType: 0x%x\n",
618 DeviceInfo.wDeviceType);
619 nand_dbg_print(NAND_DBG_DEBUG, "SpectraStartBlock: %d\n",
620 DeviceInfo.wSpectraStartBlock);
621 nand_dbg_print(NAND_DBG_DEBUG, "SpectraEndBlock: %d\n",
622 DeviceInfo.wSpectraEndBlock);
623 nand_dbg_print(NAND_DBG_DEBUG, "TotalBlocks: %d\n",
624 DeviceInfo.wTotalBlocks);
625 nand_dbg_print(NAND_DBG_DEBUG, "PagesPerBlock: %d\n",
626 DeviceInfo.wPagesPerBlock);
627 nand_dbg_print(NAND_DBG_DEBUG, "PageSize: %d\n",
628 DeviceInfo.wPageSize);
629 nand_dbg_print(NAND_DBG_DEBUG, "PageDataSize: %d\n",
630 DeviceInfo.wPageDataSize);
631 nand_dbg_print(NAND_DBG_DEBUG, "PageSpareSize: %d\n",
632 DeviceInfo.wPageSpareSize);
633 nand_dbg_print(NAND_DBG_DEBUG, "NumPageSpareFlag: %d\n",
634 DeviceInfo.wNumPageSpareFlag);
635 nand_dbg_print(NAND_DBG_DEBUG, "ECCBytesPerSector: %d\n",
636 DeviceInfo.wECCBytesPerSector);
637 nand_dbg_print(NAND_DBG_DEBUG, "BlockSize: %d\n",
638 DeviceInfo.wBlockSize);
639 nand_dbg_print(NAND_DBG_DEBUG, "BlockDataSize: %d\n",
640 DeviceInfo.wBlockDataSize);
641 nand_dbg_print(NAND_DBG_DEBUG, "DataBlockNum: %d\n",
642 DeviceInfo.wDataBlockNum);
643 nand_dbg_print(NAND_DBG_DEBUG, "PlaneNum: %d\n",
644 DeviceInfo.bPlaneNum);
645 nand_dbg_print(NAND_DBG_DEBUG, "DeviceMainAreaSize: %d\n",
646 DeviceInfo.wDeviceMainAreaSize);
647 nand_dbg_print(NAND_DBG_DEBUG, "DeviceSpareAreaSize: %d\n",
648 DeviceInfo.wDeviceSpareAreaSize);
649 nand_dbg_print(NAND_DBG_DEBUG, "DevicesConnected: %d\n",
650 DeviceInfo.wDevicesConnected);
651 nand_dbg_print(NAND_DBG_DEBUG, "DeviceWidth: %d\n",
652 DeviceInfo.wDeviceWidth);
653 nand_dbg_print(NAND_DBG_DEBUG, "HWRevision: 0x%x\n",
654 DeviceInfo.wHWRevision);
655 nand_dbg_print(NAND_DBG_DEBUG, "HWFeatures: 0x%x\n",
656 DeviceInfo.wHWFeatures);
657 nand_dbg_print(NAND_DBG_DEBUG, "ONFIDevFeatures: 0x%x\n",
658 DeviceInfo.wONFIDevFeatures);
659 nand_dbg_print(NAND_DBG_DEBUG, "ONFIOptCommands: 0x%x\n",
660 DeviceInfo.wONFIOptCommands);
661 nand_dbg_print(NAND_DBG_DEBUG, "ONFITimingMode: 0x%x\n",
662 DeviceInfo.wONFITimingMode);
663 nand_dbg_print(NAND_DBG_DEBUG, "ONFIPgmCacheTimingMode: 0x%x\n",
664 DeviceInfo.wONFIPgmCacheTimingMode);
665 nand_dbg_print(NAND_DBG_DEBUG, "MLCDevice: %s\n",
666 DeviceInfo.MLCDevice ? "Yes" : "No");
667 nand_dbg_print(NAND_DBG_DEBUG, "SpareSkipBytes: %d\n",
668 DeviceInfo.wSpareSkipBytes);
669 nand_dbg_print(NAND_DBG_DEBUG, "BitsInPageNumber: %d\n",
670 DeviceInfo.nBitsInPageNumber);
671 nand_dbg_print(NAND_DBG_DEBUG, "BitsInPageDataSize: %d\n",
672 DeviceInfo.nBitsInPageDataSize);
673 nand_dbg_print(NAND_DBG_DEBUG, "BitsInBlockDataSize: %d\n",
674 DeviceInfo.nBitsInBlockDataSize);
675}
676
677u16 NAND_Read_Device_ID(void)
678{
679 u16 status = PASS;
680 u8 no_of_planes;
681
682 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
683 __FILE__, __LINE__, __func__);
684
685 iowrite32(0x02, FlashReg + SPARE_AREA_SKIP_BYTES);
686 iowrite32(0xffff, FlashReg + SPARE_AREA_MARKER);
687 DeviceInfo.wDeviceMaker = ioread32(FlashReg + MANUFACTURER_ID);
688 DeviceInfo.wDeviceID = ioread32(FlashReg + DEVICE_ID);
689 DeviceInfo.MLCDevice = ioread32(FlashReg + DEVICE_PARAM_0) & 0x0c;
690
691 if (ioread32(FlashReg + ONFI_DEVICE_NO_OF_LUNS) &
692 ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE) { /* ONFI 1.0 NAND */
693 if (FAIL == get_onfi_nand_para())
694 return FAIL;
695 } else if (DeviceInfo.wDeviceMaker == 0xEC) { /* Samsung NAND */
696 get_samsung_nand_para();
697 } else if (DeviceInfo.wDeviceMaker == 0x98) { /* Toshiba NAND */
698 get_toshiba_nand_para();
699 } else if (DeviceInfo.wDeviceMaker == 0xAD) { /* Hynix NAND */
700 get_hynix_nand_para();
701 } else {
702 DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS;
703 }
704
705 nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:"
706 "acc_clks: %d, re_2_we: %d, we_2_re: %d,"
707 "addr_2_data: %d, rdwr_en_lo_cnt: %d, "
708 "rdwr_en_hi_cnt: %d, cs_setup_cnt: %d\n",
709 ioread32(FlashReg + ACC_CLKS),
710 ioread32(FlashReg + RE_2_WE),
711 ioread32(FlashReg + WE_2_RE),
712 ioread32(FlashReg + ADDR_2_DATA),
713 ioread32(FlashReg + RDWR_EN_LO_CNT),
714 ioread32(FlashReg + RDWR_EN_HI_CNT),
715 ioread32(FlashReg + CS_SETUP_CNT));
716
717 DeviceInfo.wHWRevision = ioread32(FlashReg + REVISION);
718 DeviceInfo.wHWFeatures = ioread32(FlashReg + FEATURES);
719
720 DeviceInfo.wDeviceMainAreaSize =
721 ioread32(FlashReg + DEVICE_MAIN_AREA_SIZE);
722 DeviceInfo.wDeviceSpareAreaSize =
723 ioread32(FlashReg + DEVICE_SPARE_AREA_SIZE);
724
725 DeviceInfo.wPageDataSize =
726 ioread32(FlashReg + LOGICAL_PAGE_DATA_SIZE);
727
728 /* Note: When using the Micon 4K NAND device, the controller will report
729 * Page Spare Size as 216 bytes. But Micron's Spec say it's 218 bytes.
730 * And if force set it to 218 bytes, the controller can not work
731 * correctly. So just let it be. But keep in mind that this bug may
732 * cause
733 * other problems in future. - Yunpeng 2008-10-10
734 */
735 DeviceInfo.wPageSpareSize =
736 ioread32(FlashReg + LOGICAL_PAGE_SPARE_SIZE);
737
738 DeviceInfo.wPagesPerBlock = ioread32(FlashReg + PAGES_PER_BLOCK);
739
740 DeviceInfo.wPageSize =
741 DeviceInfo.wPageDataSize + DeviceInfo.wPageSpareSize;
742 DeviceInfo.wBlockSize =
743 DeviceInfo.wPageSize * DeviceInfo.wPagesPerBlock;
744 DeviceInfo.wBlockDataSize =
745 DeviceInfo.wPagesPerBlock * DeviceInfo.wPageDataSize;
746
747 DeviceInfo.wDeviceWidth = ioread32(FlashReg + DEVICE_WIDTH);
748 DeviceInfo.wDeviceType =
749 ((ioread32(FlashReg + DEVICE_WIDTH) > 0) ? 16 : 8);
750
751 DeviceInfo.wDevicesConnected = ioread32(FlashReg + DEVICES_CONNECTED);
752
753 DeviceInfo.wSpareSkipBytes =
754 ioread32(FlashReg + SPARE_AREA_SKIP_BYTES) *
755 DeviceInfo.wDevicesConnected;
756
757 DeviceInfo.nBitsInPageNumber =
758 (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPagesPerBlock);
759 DeviceInfo.nBitsInPageDataSize =
760 (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPageDataSize);
761 DeviceInfo.nBitsInBlockDataSize =
762 (u8)GLOB_Calc_Used_Bits(DeviceInfo.wBlockDataSize);
763
764 set_ecc_config();
765
766 no_of_planes = ioread32(FlashReg + NUMBER_OF_PLANES) &
767 NUMBER_OF_PLANES__VALUE;
768
769 switch (no_of_planes) {
770 case 0:
771 case 1:
772 case 3:
773 case 7:
774 DeviceInfo.bPlaneNum = no_of_planes + 1;
775 break;
776 default:
777 status = FAIL;
778 break;
779 }
780
781 find_valid_banks();
782
783 detect_partition_feature();
784
785 dump_device_info();
786
787 return status;
788}
789
790u16 NAND_UnlockArrayAll(void)
791{
792 u64 start_addr, end_addr;
793
794 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
795 __FILE__, __LINE__, __func__);
796
797 start_addr = 0;
798 end_addr = ((u64)DeviceInfo.wBlockSize *
799 (DeviceInfo.wTotalBlocks - 1)) >>
800 DeviceInfo.nBitsInPageDataSize;
801
802 index_addr((u32)(MODE_10 | (u32)start_addr), 0x10);
803 index_addr((u32)(MODE_10 | (u32)end_addr), 0x11);
804
805 return PASS;
806}
807
808void NAND_LLD_Enable_Disable_Interrupts(u16 INT_ENABLE)
809{
810 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
811 __FILE__, __LINE__, __func__);
812
813 if (INT_ENABLE)
814 iowrite32(1, FlashReg + GLOBAL_INT_ENABLE);
815 else
816 iowrite32(0, FlashReg + GLOBAL_INT_ENABLE);
817}
818
819u16 NAND_Erase_Block(u32 block)
820{
821 u16 status = PASS;
822 u64 flash_add;
823 u16 flash_bank;
824 u32 intr_status = 0;
825 u32 intr_status_addresses[4] = {INTR_STATUS0,
826 INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
827
828 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
829 __FILE__, __LINE__, __func__);
830
831 flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks))
832 * DeviceInfo.wBlockDataSize;
833
834 flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
835
836 if (block >= DeviceInfo.wTotalBlocks)
837 status = FAIL;
838
839 if (status == PASS) {
840 intr_status = intr_status_addresses[flash_bank];
841
842 iowrite32(INTR_STATUS0__ERASE_COMP | INTR_STATUS0__ERASE_FAIL,
843 FlashReg + intr_status);
844
845 index_addr((u32)(MODE_10 | (flash_bank << 24) |
846 (flash_add >> DeviceInfo.nBitsInPageDataSize)), 1);
847
848 while (!(ioread32(FlashReg + intr_status) &
849 (INTR_STATUS0__ERASE_COMP | INTR_STATUS0__ERASE_FAIL)))
850 ;
851
852 if (ioread32(FlashReg + intr_status) &
853 INTR_STATUS0__ERASE_FAIL)
854 status = FAIL;
855
856 iowrite32(INTR_STATUS0__ERASE_COMP | INTR_STATUS0__ERASE_FAIL,
857 FlashReg + intr_status);
858 }
859
860 return status;
861}
862
863static u32 Boundary_Check_Block_Page(u32 block, u16 page,
864 u16 page_count)
865{
866 u32 status = PASS;
867
868 if (block >= DeviceInfo.wTotalBlocks)
869 status = FAIL;
870
871 if (page + page_count > DeviceInfo.wPagesPerBlock)
872 status = FAIL;
873
874 return status;
875}
876
877u16 NAND_Read_Page_Spare(u8 *read_data, u32 block, u16 page,
878 u16 page_count)
879{
880 u32 status = PASS;
881 u32 i;
882 u64 flash_add;
883 u32 PageSpareSize = DeviceInfo.wPageSpareSize;
884 u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag;
885 u32 flash_bank;
886 u32 intr_status = 0;
887 u32 intr_status_addresses[4] = {INTR_STATUS0,
888 INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
889 u8 *page_spare = buf_read_page_spare;
890
891 if (block >= DeviceInfo.wTotalBlocks) {
892 printk(KERN_ERR "block too big: %d\n", (int)block);
893 status = FAIL;
894 }
895
896 if (page >= DeviceInfo.wPagesPerBlock) {
897 printk(KERN_ERR "page too big: %d\n", page);
898 status = FAIL;
899 }
900
901 if (page_count > 1) {
902 printk(KERN_ERR "page count too big: %d\n", page_count);
903 status = FAIL;
904 }
905
906 flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks))
907 * DeviceInfo.wBlockDataSize +
908 (u64)page * DeviceInfo.wPageDataSize;
909
910 flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
911
912 if (status == PASS) {
913 intr_status = intr_status_addresses[flash_bank];
914 iowrite32(ioread32(FlashReg + intr_status),
915 FlashReg + intr_status);
916
917 index_addr((u32)(MODE_10 | (flash_bank << 24) |
918 (flash_add >> DeviceInfo.nBitsInPageDataSize)),
919 0x41);
920 index_addr((u32)(MODE_10 | (flash_bank << 24) |
921 (flash_add >> DeviceInfo.nBitsInPageDataSize)),
922 0x2000 | page_count);
923 while (!(ioread32(FlashReg + intr_status) &
924 INTR_STATUS0__LOAD_COMP))
925 ;
926
927 iowrite32((u32)(MODE_01 | (flash_bank << 24) |
928 (flash_add >> DeviceInfo.nBitsInPageDataSize)),
929 FlashMem);
930
931 for (i = 0; i < (PageSpareSize / 4); i++)
932 *((u32 *)page_spare + i) =
933 ioread32(FlashMem + 0x10);
934
935 if (enable_ecc) {
936 for (i = 0; i < spareFlagBytes; i++)
937 read_data[i] =
938 page_spare[PageSpareSize -
939 spareFlagBytes + i];
940 for (i = 0; i < (PageSpareSize - spareFlagBytes); i++)
941 read_data[spareFlagBytes + i] =
942 page_spare[i];
943 } else {
944 for (i = 0; i < PageSpareSize; i++)
945 read_data[i] = page_spare[i];
946 }
947
948 index_addr((u32)(MODE_10 | (flash_bank << 24) |
949 (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42);
950 }
951
952 return status;
953}
954
955/* No use function. Should be removed later */
956u16 NAND_Write_Page_Spare(u8 *write_data, u32 block, u16 page,
957 u16 page_count)
958{
959 printk(KERN_ERR
960 "Error! This function (NAND_Write_Page_Spare) should never"
961 " be called!\n");
962 return ERR;
963}
964
965/* op value: 0 - DDMA read; 1 - DDMA write */
966static void ddma_trans(u8 *data, u64 flash_add,
967 u32 flash_bank, int op, u32 numPages)
968{
969 u32 data_addr;
970
971 /* Map virtual address to bus address for DDMA */
972 data_addr = virt_to_bus(data);
973
974 index_addr((u32)(MODE_10 | (flash_bank << 24) |
975 (flash_add >> DeviceInfo.nBitsInPageDataSize)),
976 (u16)(2 << 12) | (op << 8) | numPages);
977
978 index_addr((u32)(MODE_10 | (flash_bank << 24) |
979 ((u16)(0x0FFFF & (data_addr >> 16)) << 8)),
980 (u16)(2 << 12) | (2 << 8) | 0);
981
982 index_addr((u32)(MODE_10 | (flash_bank << 24) |
983 ((u16)(0x0FFFF & data_addr) << 8)),
984 (u16)(2 << 12) | (3 << 8) | 0);
985
986 index_addr((u32)(MODE_10 | (flash_bank << 24) |
987 (1 << 16) | (0x40 << 8)),
988 (u16)(2 << 12) | (4 << 8) | 0);
989}
990
991/* If data in buf are all 0xff, then return 1; otherwise return 0 */
992static int check_all_1(u8 *buf)
993{
994 int i, j, cnt;
995
996 for (i = 0; i < DeviceInfo.wPageDataSize; i++) {
997 if (buf[i] != 0xff) {
998 cnt = 0;
999 nand_dbg_print(NAND_DBG_WARN,
1000 "the first non-0xff data byte is: %d\n", i);
1001 for (j = i; j < DeviceInfo.wPageDataSize; j++) {
1002 nand_dbg_print(NAND_DBG_WARN, "0x%x ", buf[j]);
1003 cnt++;
1004 if (cnt > 8)
1005 break;
1006 }
1007 nand_dbg_print(NAND_DBG_WARN, "\n");
1008 return 0;
1009 }
1010 }
1011
1012 return 1;
1013}
1014
1015static int do_ecc_new(unsigned long bank, u8 *buf,
1016 u32 block, u16 page)
1017{
1018 int status = PASS;
1019 u16 err_page = 0;
1020 u16 err_byte;
1021 u8 err_sect;
1022 u8 err_dev;
1023 u16 err_fix_info;
1024 u16 err_addr;
1025 u32 ecc_sect_size;
1026 u8 *err_pos;
1027 u32 err_page_addr[4] = {ERR_PAGE_ADDR0,
1028 ERR_PAGE_ADDR1, ERR_PAGE_ADDR2, ERR_PAGE_ADDR3};
1029
1030 ecc_sect_size = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected);
1031
1032 do {
1033 err_page = ioread32(FlashReg + err_page_addr[bank]);
1034 err_addr = ioread32(FlashReg + ECC_ERROR_ADDRESS);
1035 err_byte = err_addr & ECC_ERROR_ADDRESS__OFFSET;
1036 err_sect = ((err_addr & ECC_ERROR_ADDRESS__SECTOR_NR) >> 12);
1037 err_fix_info = ioread32(FlashReg + ERR_CORRECTION_INFO);
1038 err_dev = ((err_fix_info & ERR_CORRECTION_INFO__DEVICE_NR)
1039 >> 8);
1040 if (err_fix_info & ERR_CORRECTION_INFO__ERROR_TYPE) {
1041 nand_dbg_print(NAND_DBG_WARN,
1042 "%s, Line %d Uncorrectable ECC error "
1043 "when read block %d page %d."
1044 "PTN_INTR register: 0x%x "
1045 "err_page: %d, err_sect: %d, err_byte: %d, "
1046 "err_dev: %d, ecc_sect_size: %d, "
1047 "err_fix_info: 0x%x\n",
1048 __FILE__, __LINE__, block, page,
1049 ioread32(FlashReg + PTN_INTR),
1050 err_page, err_sect, err_byte, err_dev,
1051 ecc_sect_size, (u32)err_fix_info);
1052
1053 if (check_all_1(buf))
1054 nand_dbg_print(NAND_DBG_WARN, "%s, Line %d"
1055 "All 0xff!\n",
1056 __FILE__, __LINE__);
1057 else
1058 nand_dbg_print(NAND_DBG_WARN, "%s, Line %d"
1059 "Not all 0xff!\n",
1060 __FILE__, __LINE__);
1061 status = FAIL;
1062 } else {
1063 nand_dbg_print(NAND_DBG_WARN,
1064 "%s, Line %d Found ECC error "
1065 "when read block %d page %d."
1066 "err_page: %d, err_sect: %d, err_byte: %d, "
1067 "err_dev: %d, ecc_sect_size: %d, "
1068 "err_fix_info: 0x%x\n",
1069 __FILE__, __LINE__, block, page,
1070 err_page, err_sect, err_byte, err_dev,
1071 ecc_sect_size, (u32)err_fix_info);
1072 if (err_byte < ECC_SECTOR_SIZE) {
1073 err_pos = buf +
1074 (err_page - page) *
1075 DeviceInfo.wPageDataSize +
1076 err_sect * ecc_sect_size +
1077 err_byte *
1078 DeviceInfo.wDevicesConnected +
1079 err_dev;
1080
1081 *err_pos ^= err_fix_info &
1082 ERR_CORRECTION_INFO__BYTEMASK;
1083 }
1084 }
1085 } while (!(err_fix_info & ERR_CORRECTION_INFO__LAST_ERR_INFO));
1086
1087 return status;
1088}
1089
1090u16 NAND_Read_Page_Main_Polling(u8 *read_data,
1091 u32 block, u16 page, u16 page_count)
1092{
1093 u32 status = PASS;
1094 u64 flash_add;
1095 u32 intr_status = 0;
1096 u32 flash_bank;
1097 u32 intr_status_addresses[4] = {INTR_STATUS0,
1098 INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
1099 u8 *read_data_l;
1100
1101 nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
1102 __FILE__, __LINE__, __func__);
1103
1104 status = Boundary_Check_Block_Page(block, page, page_count);
1105 if (status != PASS)
1106 return status;
1107
1108 flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks))
1109 * DeviceInfo.wBlockDataSize +
1110 (u64)page * DeviceInfo.wPageDataSize;
1111 flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
1112
1113 iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
1114
1115 intr_status = intr_status_addresses[flash_bank];
1116 iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
1117
1118 if (page_count > 1) {
1119 read_data_l = read_data;
1120 while (page_count > MAX_PAGES_PER_RW) {
1121 if (ioread32(FlashReg + MULTIPLANE_OPERATION))
1122 status = NAND_Multiplane_Read(read_data_l,
1123 block, page, MAX_PAGES_PER_RW);
1124 else
1125 status = NAND_Pipeline_Read_Ahead_Polling(
1126 read_data_l, block, page,
1127 MAX_PAGES_PER_RW);
1128
1129 if (status == FAIL)
1130 return status;
1131
1132 read_data_l += DeviceInfo.wPageDataSize *
1133 MAX_PAGES_PER_RW;
1134 page_count -= MAX_PAGES_PER_RW;
1135 page += MAX_PAGES_PER_RW;
1136 }
1137 if (ioread32(FlashReg + MULTIPLANE_OPERATION))
1138 status = NAND_Multiplane_Read(read_data_l,
1139 block, page, page_count);
1140 else
1141 status = NAND_Pipeline_Read_Ahead_Polling(
1142 read_data_l, block, page, page_count);
1143
1144 return status;
1145 }
1146
1147 iowrite32(1, FlashReg + DMA_ENABLE);
1148 while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
1149 ;
1150
1151 iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
1152 iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
1153
1154 ddma_trans(read_data, flash_add, flash_bank, 0, 1);
1155
1156 if (enable_ecc) {
1157 while (!(ioread32(FlashReg + intr_status) &
1158 (INTR_STATUS0__ECC_TRANSACTION_DONE |
1159 INTR_STATUS0__ECC_ERR)))
1160 ;
1161
1162 if (ioread32(FlashReg + intr_status) &
1163 INTR_STATUS0__ECC_ERR) {
1164 iowrite32(INTR_STATUS0__ECC_ERR,
1165 FlashReg + intr_status);
1166 status = do_ecc_new(flash_bank, read_data,
1167 block, page);
1168 }
1169
1170 if (ioread32(FlashReg + intr_status) &
1171 INTR_STATUS0__ECC_TRANSACTION_DONE &
1172 INTR_STATUS0__ECC_ERR)
1173 iowrite32(INTR_STATUS0__ECC_TRANSACTION_DONE |
1174 INTR_STATUS0__ECC_ERR,
1175 FlashReg + intr_status);
1176 else if (ioread32(FlashReg + intr_status) &
1177 INTR_STATUS0__ECC_TRANSACTION_DONE)
1178 iowrite32(INTR_STATUS0__ECC_TRANSACTION_DONE,
1179 FlashReg + intr_status);
1180 else if (ioread32(FlashReg + intr_status) &
1181 INTR_STATUS0__ECC_ERR)
1182 iowrite32(INTR_STATUS0__ECC_ERR,
1183 FlashReg + intr_status);
1184 } else {
1185 while (!(ioread32(FlashReg + intr_status) &
1186 INTR_STATUS0__DMA_CMD_COMP))
1187 ;
1188 iowrite32(INTR_STATUS0__DMA_CMD_COMP, FlashReg + intr_status);
1189 }
1190
1191 iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
1192
1193 iowrite32(0, FlashReg + DMA_ENABLE);
1194 while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
1195 ;
1196
1197 return status;
1198}
1199
1200u16 NAND_Pipeline_Read_Ahead_Polling(u8 *read_data,
1201 u32 block, u16 page, u16 page_count)
1202{
1203 u32 status = PASS;
1204 u32 NumPages = page_count;
1205 u64 flash_add;
1206 u32 flash_bank;
1207 u32 intr_status = 0;
1208 u32 intr_status_addresses[4] = {INTR_STATUS0,
1209 INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
1210 u32 ecc_done_OR_dma_comp;
1211
1212 nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
1213 __FILE__, __LINE__, __func__);
1214
1215 status = Boundary_Check_Block_Page(block, page, page_count);
1216
1217 if (page_count < 2)
1218 status = FAIL;
1219
1220 flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks))
1221 *DeviceInfo.wBlockDataSize +
1222 (u64)page * DeviceInfo.wPageDataSize;
1223
1224 flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
1225
1226 if (status == PASS) {
1227 intr_status = intr_status_addresses[flash_bank];
1228 iowrite32(ioread32(FlashReg + intr_status),
1229 FlashReg + intr_status);
1230
1231 iowrite32(1, FlashReg + DMA_ENABLE);
1232 while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
1233 ;
1234
1235 iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
1236
1237 index_addr((u32)(MODE_10 | (flash_bank << 24) |
1238 (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42);
1239 ddma_trans(read_data, flash_add, flash_bank, 0, NumPages);
1240
1241 ecc_done_OR_dma_comp = 0;
1242 while (1) {
1243 if (enable_ecc) {
1244 while (!ioread32(FlashReg + intr_status))
1245 ;
1246
1247 if (ioread32(FlashReg + intr_status) &
1248 INTR_STATUS0__ECC_ERR) {
1249 iowrite32(INTR_STATUS0__ECC_ERR,
1250 FlashReg + intr_status);
1251 status = do_ecc_new(flash_bank,
1252 read_data, block, page);
1253 } else if (ioread32(FlashReg + intr_status) &
1254 INTR_STATUS0__DMA_CMD_COMP) {
1255 iowrite32(INTR_STATUS0__DMA_CMD_COMP,
1256 FlashReg + intr_status);
1257
1258 if (1 == ecc_done_OR_dma_comp)
1259 break;
1260
1261 ecc_done_OR_dma_comp = 1;
1262 } else if (ioread32(FlashReg + intr_status) &
1263 INTR_STATUS0__ECC_TRANSACTION_DONE) {
1264 iowrite32(
1265 INTR_STATUS0__ECC_TRANSACTION_DONE,
1266 FlashReg + intr_status);
1267
1268 if (1 == ecc_done_OR_dma_comp)
1269 break;
1270
1271 ecc_done_OR_dma_comp = 1;
1272 }
1273 } else {
1274 while (!(ioread32(FlashReg + intr_status) &
1275 INTR_STATUS0__DMA_CMD_COMP))
1276 ;
1277
1278 iowrite32(INTR_STATUS0__DMA_CMD_COMP,
1279 FlashReg + intr_status);
1280 break;
1281 }
1282
1283 iowrite32((~INTR_STATUS0__ECC_ERR) &
1284 (~INTR_STATUS0__ECC_TRANSACTION_DONE) &
1285 (~INTR_STATUS0__DMA_CMD_COMP),
1286 FlashReg + intr_status);
1287
1288 }
1289
1290 iowrite32(ioread32(FlashReg + intr_status),
1291 FlashReg + intr_status);
1292
1293 iowrite32(0, FlashReg + DMA_ENABLE);
1294
1295 while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
1296 ;
1297 }
1298 return status;
1299}
1300
1301u16 NAND_Read_Page_Main(u8 *read_data, u32 block, u16 page,
1302 u16 page_count)
1303{
1304 u32 status = PASS;
1305 u64 flash_add;
1306 u32 intr_status = 0;
1307 u32 flash_bank;
1308 u32 intr_status_addresses[4] = {INTR_STATUS0,
1309 INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
1310 int ret;
1311 u8 *read_data_l;
1312
1313 nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
1314 __FILE__, __LINE__, __func__);
1315
1316 status = Boundary_Check_Block_Page(block, page, page_count);
1317 if (status != PASS)
1318 return status;
1319
1320 flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks))
1321 * DeviceInfo.wBlockDataSize +
1322 (u64)page * DeviceInfo.wPageDataSize;
1323 flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
1324
1325 iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
1326
1327 intr_status = intr_status_addresses[flash_bank];
1328 iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
1329
1330 if (page_count > 1) {
1331 read_data_l = read_data;
1332 while (page_count > MAX_PAGES_PER_RW) {
1333 if (ioread32(FlashReg + MULTIPLANE_OPERATION))
1334 status = NAND_Multiplane_Read(read_data_l,
1335 block, page, MAX_PAGES_PER_RW);
1336 else
1337 status = NAND_Pipeline_Read_Ahead(
1338 read_data_l, block, page,
1339 MAX_PAGES_PER_RW);
1340
1341 if (status == FAIL)
1342 return status;
1343
1344 read_data_l += DeviceInfo.wPageDataSize *
1345 MAX_PAGES_PER_RW;
1346 page_count -= MAX_PAGES_PER_RW;
1347 page += MAX_PAGES_PER_RW;
1348 }
1349 if (ioread32(FlashReg + MULTIPLANE_OPERATION))
1350 status = NAND_Multiplane_Read(read_data_l,
1351 block, page, page_count);
1352 else
1353 status = NAND_Pipeline_Read_Ahead(
1354 read_data_l, block, page, page_count);
1355
1356 return status;
1357 }
1358
1359 iowrite32(1, FlashReg + DMA_ENABLE);
1360 while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
1361 ;
1362
1363 iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
1364 iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
1365
1366 /* Fill the mrst_nand_info structure */
1367 info.state = INT_READ_PAGE_MAIN;
1368 info.read_data = read_data;
1369 info.flash_bank = flash_bank;
1370 info.block = block;
1371 info.page = page;
1372 info.ret = PASS;
1373
1374 ddma_trans(read_data, flash_add, flash_bank, 0, 1);
1375
1376 iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable Interrupt */
1377
1378 ret = wait_for_completion_timeout(&info.complete, 10 * HZ);
1379 if (!ret) {
1380 printk(KERN_ERR "Wait for completion timeout "
1381 "in %s, Line %d\n", __FILE__, __LINE__);
1382 status = ERR;
1383 } else {
1384 status = info.ret;
1385 }
1386
1387 iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
1388
1389 iowrite32(0, FlashReg + DMA_ENABLE);
1390 while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
1391 ;
1392
1393 return status;
1394}
1395
1396void Conv_Spare_Data_Log2Phy_Format(u8 *data)
1397{
1398 int i;
1399 const u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag;
1400 const u32 PageSpareSize = DeviceInfo.wPageSpareSize;
1401
1402 if (enable_ecc) {
1403 for (i = spareFlagBytes - 1; i >= 0; i--)
1404 data[PageSpareSize - spareFlagBytes + i] = data[i];
1405 }
1406}
1407
1408void Conv_Spare_Data_Phy2Log_Format(u8 *data)
1409{
1410 int i;
1411 const u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag;
1412 const u32 PageSpareSize = DeviceInfo.wPageSpareSize;
1413
1414 if (enable_ecc) {
1415 for (i = 0; i < spareFlagBytes; i++)
1416 data[i] = data[PageSpareSize - spareFlagBytes + i];
1417 }
1418}
1419
1420
1421void Conv_Main_Spare_Data_Log2Phy_Format(u8 *data, u16 page_count)
1422{
1423 const u32 PageSize = DeviceInfo.wPageSize;
1424 const u32 PageDataSize = DeviceInfo.wPageDataSize;
1425 const u32 eccBytes = DeviceInfo.wECCBytesPerSector;
1426 const u32 spareSkipBytes = DeviceInfo.wSpareSkipBytes;
1427 const u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag;
1428 u32 eccSectorSize;
1429 u32 page_offset;
1430 int i, j;
1431
1432 eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected);
1433 if (enable_ecc) {
1434 while (page_count > 0) {
1435 page_offset = (page_count - 1) * PageSize;
1436 j = (DeviceInfo.wPageDataSize / eccSectorSize);
1437 for (i = spareFlagBytes - 1; i >= 0; i--)
1438 data[page_offset +
1439 (eccSectorSize + eccBytes) * j + i] =
1440 data[page_offset + PageDataSize + i];
1441 for (j--; j >= 1; j--) {
1442 for (i = eccSectorSize - 1; i >= 0; i--)
1443 data[page_offset +
1444 (eccSectorSize + eccBytes) * j + i] =
1445 data[page_offset +
1446 eccSectorSize * j + i];
1447 }
1448 for (i = (PageSize - spareSkipBytes) - 1;
1449 i >= PageDataSize; i--)
1450 data[page_offset + i + spareSkipBytes] =
1451 data[page_offset + i];
1452 page_count--;
1453 }
1454 }
1455}
1456
1457void Conv_Main_Spare_Data_Phy2Log_Format(u8 *data, u16 page_count)
1458{
1459 const u32 PageSize = DeviceInfo.wPageSize;
1460 const u32 PageDataSize = DeviceInfo.wPageDataSize;
1461 const u32 eccBytes = DeviceInfo.wECCBytesPerSector;
1462 const u32 spareSkipBytes = DeviceInfo.wSpareSkipBytes;
1463 const u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag;
1464 u32 eccSectorSize;
1465 u32 page_offset;
1466 int i, j;
1467
1468 eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected);
1469 if (enable_ecc) {
1470 while (page_count > 0) {
1471 page_offset = (page_count - 1) * PageSize;
1472 for (i = PageDataSize;
1473 i < PageSize - spareSkipBytes;
1474 i++)
1475 data[page_offset + i] =
1476 data[page_offset + i +
1477 spareSkipBytes];
1478 for (j = 1;
1479 j < DeviceInfo.wPageDataSize / eccSectorSize;
1480 j++) {
1481 for (i = 0; i < eccSectorSize; i++)
1482 data[page_offset +
1483 eccSectorSize * j + i] =
1484 data[page_offset +
1485 (eccSectorSize + eccBytes) * j
1486 + i];
1487 }
1488 for (i = 0; i < spareFlagBytes; i++)
1489 data[page_offset + PageDataSize + i] =
1490 data[page_offset +
1491 (eccSectorSize + eccBytes) * j + i];
1492 page_count--;
1493 }
1494 }
1495}
1496
1497/* Un-tested function */
1498u16 NAND_Multiplane_Read(u8 *read_data, u32 block, u16 page,
1499 u16 page_count)
1500{
1501 u32 status = PASS;
1502 u32 NumPages = page_count;
1503 u64 flash_add;
1504 u32 flash_bank;
1505 u32 intr_status = 0;
1506 u32 intr_status_addresses[4] = {INTR_STATUS0,
1507 INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
1508 u32 ecc_done_OR_dma_comp;
1509
1510 nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
1511 __FILE__, __LINE__, __func__);
1512
1513 status = Boundary_Check_Block_Page(block, page, page_count);
1514
1515 flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks))
1516 * DeviceInfo.wBlockDataSize +
1517 (u64)page * DeviceInfo.wPageDataSize;
1518
1519 flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
1520
1521 if (status == PASS) {
1522 intr_status = intr_status_addresses[flash_bank];
1523 iowrite32(ioread32(FlashReg + intr_status),
1524 FlashReg + intr_status);
1525
1526 iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
1527 iowrite32(0x01, FlashReg + MULTIPLANE_OPERATION);
1528
1529 iowrite32(1, FlashReg + DMA_ENABLE);
1530 while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
1531 ;
1532 index_addr((u32)(MODE_10 | (flash_bank << 24) |
1533 (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42);
1534 ddma_trans(read_data, flash_add, flash_bank, 0, NumPages);
1535
1536 ecc_done_OR_dma_comp = 0;
1537 while (1) {
1538 if (enable_ecc) {
1539 while (!ioread32(FlashReg + intr_status))
1540 ;
1541
1542 if (ioread32(FlashReg + intr_status) &
1543 INTR_STATUS0__ECC_ERR) {
1544 iowrite32(INTR_STATUS0__ECC_ERR,
1545 FlashReg + intr_status);
1546 status = do_ecc_new(flash_bank,
1547 read_data, block, page);
1548 } else if (ioread32(FlashReg + intr_status) &
1549 INTR_STATUS0__DMA_CMD_COMP) {
1550 iowrite32(INTR_STATUS0__DMA_CMD_COMP,
1551 FlashReg + intr_status);
1552
1553 if (1 == ecc_done_OR_dma_comp)
1554 break;
1555
1556 ecc_done_OR_dma_comp = 1;
1557 } else if (ioread32(FlashReg + intr_status) &
1558 INTR_STATUS0__ECC_TRANSACTION_DONE) {
1559 iowrite32(
1560 INTR_STATUS0__ECC_TRANSACTION_DONE,
1561 FlashReg + intr_status);
1562
1563 if (1 == ecc_done_OR_dma_comp)
1564 break;
1565
1566 ecc_done_OR_dma_comp = 1;
1567 }
1568 } else {
1569 while (!(ioread32(FlashReg + intr_status) &
1570 INTR_STATUS0__DMA_CMD_COMP))
1571 ;
1572 iowrite32(INTR_STATUS0__DMA_CMD_COMP,
1573 FlashReg + intr_status);
1574 break;
1575 }
1576
1577 iowrite32((~INTR_STATUS0__ECC_ERR) &
1578 (~INTR_STATUS0__ECC_TRANSACTION_DONE) &
1579 (~INTR_STATUS0__DMA_CMD_COMP),
1580 FlashReg + intr_status);
1581
1582 }
1583
1584 iowrite32(ioread32(FlashReg + intr_status),
1585 FlashReg + intr_status);
1586
1587 iowrite32(0, FlashReg + DMA_ENABLE);
1588
1589 while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
1590 ;
1591
1592 iowrite32(0, FlashReg + MULTIPLANE_OPERATION);
1593 }
1594
1595 return status;
1596}
1597
1598u16 NAND_Pipeline_Read_Ahead(u8 *read_data, u32 block,
1599 u16 page, u16 page_count)
1600{
1601 u32 status = PASS;
1602 u32 NumPages = page_count;
1603 u64 flash_add;
1604 u32 flash_bank;
1605 u32 intr_status = 0;
1606 u32 intr_status_addresses[4] = {INTR_STATUS0,
1607 INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
1608 int ret;
1609
1610 nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
1611 __FILE__, __LINE__, __func__);
1612
1613 status = Boundary_Check_Block_Page(block, page, page_count);
1614
1615 if (page_count < 2)
1616 status = FAIL;
1617
1618 if (status != PASS)
1619 return status;
1620
1621 flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks))
1622 *DeviceInfo.wBlockDataSize +
1623 (u64)page * DeviceInfo.wPageDataSize;
1624
1625 flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
1626
1627 intr_status = intr_status_addresses[flash_bank];
1628 iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
1629
1630 iowrite32(1, FlashReg + DMA_ENABLE);
1631 while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
1632 ;
1633
1634 iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
1635
1636 /* Fill the mrst_nand_info structure */
1637 info.state = INT_PIPELINE_READ_AHEAD;
1638 info.read_data = read_data;
1639 info.flash_bank = flash_bank;
1640 info.block = block;
1641 info.page = page;
1642 info.ret = PASS;
1643
1644 index_addr((u32)(MODE_10 | (flash_bank << 24) |
1645 (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42);
1646
1647 ddma_trans(read_data, flash_add, flash_bank, 0, NumPages);
1648
1649 iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable Interrupt */
1650
1651 ret = wait_for_completion_timeout(&info.complete, 10 * HZ);
1652 if (!ret) {
1653 printk(KERN_ERR "Wait for completion timeout "
1654 "in %s, Line %d\n", __FILE__, __LINE__);
1655 status = ERR;
1656 } else {
1657 status = info.ret;
1658 }
1659
1660 iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
1661
1662 iowrite32(0, FlashReg + DMA_ENABLE);
1663
1664 while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
1665 ;
1666
1667 return status;
1668}
1669
1670
1671u16 NAND_Write_Page_Main(u8 *write_data, u32 block, u16 page,
1672 u16 page_count)
1673{
1674 u32 status = PASS;
1675 u64 flash_add;
1676 u32 intr_status = 0;
1677 u32 flash_bank;
1678 u32 intr_status_addresses[4] = {INTR_STATUS0,
1679 INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
1680 int ret;
1681 u8 *write_data_l;
1682
1683 nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
1684 __FILE__, __LINE__, __func__);
1685
1686 status = Boundary_Check_Block_Page(block, page, page_count);
1687 if (status != PASS)
1688 return status;
1689
1690 flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks))
1691 * DeviceInfo.wBlockDataSize +
1692 (u64)page * DeviceInfo.wPageDataSize;
1693
1694 flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
1695
1696 intr_status = intr_status_addresses[flash_bank];
1697
1698 iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
1699
1700 iowrite32(INTR_STATUS0__PROGRAM_COMP |
1701 INTR_STATUS0__PROGRAM_FAIL, FlashReg + intr_status);
1702
1703 if (page_count > 1) {
1704 write_data_l = write_data;
1705 while (page_count > MAX_PAGES_PER_RW) {
1706 if (ioread32(FlashReg + MULTIPLANE_OPERATION))
1707 status = NAND_Multiplane_Write(write_data_l,
1708 block, page, MAX_PAGES_PER_RW);
1709 else
1710 status = NAND_Pipeline_Write_Ahead(
1711 write_data_l, block, page,
1712 MAX_PAGES_PER_RW);
1713 if (status == FAIL)
1714 return status;
1715
1716 write_data_l += DeviceInfo.wPageDataSize *
1717 MAX_PAGES_PER_RW;
1718 page_count -= MAX_PAGES_PER_RW;
1719 page += MAX_PAGES_PER_RW;
1720 }
1721 if (ioread32(FlashReg + MULTIPLANE_OPERATION))
1722 status = NAND_Multiplane_Write(write_data_l,
1723 block, page, page_count);
1724 else
1725 status = NAND_Pipeline_Write_Ahead(write_data_l,
1726 block, page, page_count);
1727
1728 return status;
1729 }
1730
1731 iowrite32(1, FlashReg + DMA_ENABLE);
1732 while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
1733 ;
1734
1735 iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
1736
1737 iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
1738
1739 /* Fill the mrst_nand_info structure */
1740 info.state = INT_WRITE_PAGE_MAIN;
1741 info.write_data = write_data;
1742 info.flash_bank = flash_bank;
1743 info.block = block;
1744 info.page = page;
1745 info.ret = PASS;
1746
1747 ddma_trans(write_data, flash_add, flash_bank, 1, 1);
1748
1749 iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable interrupt */
1750
1751 ret = wait_for_completion_timeout(&info.complete, 10 * HZ);
1752 if (!ret) {
1753 printk(KERN_ERR "Wait for completion timeout "
1754 "in %s, Line %d\n", __FILE__, __LINE__);
1755 status = ERR;
1756 } else {
1757 status = info.ret;
1758 }
1759
1760 iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
1761
1762 iowrite32(0, FlashReg + DMA_ENABLE);
1763 while (ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)
1764 ;
1765
1766 return status;
1767}
1768
1769void NAND_ECC_Ctrl(int enable)
1770{
1771 if (enable) {
1772 nand_dbg_print(NAND_DBG_WARN,
1773 "Will enable ECC in %s, Line %d, Function: %s\n",
1774 __FILE__, __LINE__, __func__);
1775 iowrite32(1, FlashReg + ECC_ENABLE);
1776 enable_ecc = 1;
1777 } else {
1778 nand_dbg_print(NAND_DBG_WARN,
1779 "Will disable ECC in %s, Line %d, Function: %s\n",
1780 __FILE__, __LINE__, __func__);
1781 iowrite32(0, FlashReg + ECC_ENABLE);
1782 enable_ecc = 0;
1783 }
1784}
1785
1786u16 NAND_Write_Page_Main_Spare(u8 *write_data, u32 block,
1787 u16 page, u16 page_count)
1788{
1789 u32 status = PASS;
1790 u32 i, j, page_num = 0;
1791 u32 PageSize = DeviceInfo.wPageSize;
1792 u32 PageDataSize = DeviceInfo.wPageDataSize;
1793 u32 eccBytes = DeviceInfo.wECCBytesPerSector;
1794 u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag;
1795 u32 spareSkipBytes = DeviceInfo.wSpareSkipBytes;
1796 u64 flash_add;
1797 u32 eccSectorSize;
1798 u32 flash_bank;
1799 u32 intr_status = 0;
1800 u32 intr_status_addresses[4] = {INTR_STATUS0,
1801 INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
1802 u8 *page_main_spare = buf_write_page_main_spare;
1803
1804 nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
1805 __FILE__, __LINE__, __func__);
1806
1807 eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected);
1808
1809 status = Boundary_Check_Block_Page(block, page, page_count);
1810
1811 flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
1812
1813 if (status == PASS) {
1814 intr_status = intr_status_addresses[flash_bank];
1815
1816 iowrite32(1, FlashReg + TRANSFER_SPARE_REG);
1817
1818 while ((status != FAIL) && (page_count > 0)) {
1819 flash_add = (u64)(block %
1820 (DeviceInfo.wTotalBlocks / totalUsedBanks)) *
1821 DeviceInfo.wBlockDataSize +
1822 (u64)page * DeviceInfo.wPageDataSize;
1823
1824 iowrite32(ioread32(FlashReg + intr_status),
1825 FlashReg + intr_status);
1826
1827 iowrite32((u32)(MODE_01 | (flash_bank << 24) |
1828 (flash_add >>
1829 DeviceInfo.nBitsInPageDataSize)),
1830 FlashMem);
1831
1832 if (enable_ecc) {
1833 for (j = 0;
1834 j <
1835 DeviceInfo.wPageDataSize / eccSectorSize;
1836 j++) {
1837 for (i = 0; i < eccSectorSize; i++)
1838 page_main_spare[(eccSectorSize +
1839 eccBytes) * j +
1840 i] =
1841 write_data[eccSectorSize *
1842 j + i];
1843
1844 for (i = 0; i < eccBytes; i++)
1845 page_main_spare[(eccSectorSize +
1846 eccBytes) * j +
1847 eccSectorSize +
1848 i] =
1849 write_data[PageDataSize +
1850 spareFlagBytes +
1851 eccBytes * j +
1852 i];
1853 }
1854
1855 for (i = 0; i < spareFlagBytes; i++)
1856 page_main_spare[(eccSectorSize +
1857 eccBytes) * j + i] =
1858 write_data[PageDataSize + i];
1859
1860 for (i = PageSize - 1; i >= PageDataSize +
1861 spareSkipBytes; i--)
1862 page_main_spare[i] = page_main_spare[i -
1863 spareSkipBytes];
1864
1865 for (i = PageDataSize; i < PageDataSize +
1866 spareSkipBytes; i++)
1867 page_main_spare[i] = 0xff;
1868
1869 for (i = 0; i < PageSize / 4; i++)
1870 iowrite32(
1871 *((u32 *)page_main_spare + i),
1872 FlashMem + 0x10);
1873 } else {
1874
1875 for (i = 0; i < PageSize / 4; i++)
1876 iowrite32(*((u32 *)write_data + i),
1877 FlashMem + 0x10);
1878 }
1879
1880 while (!(ioread32(FlashReg + intr_status) &
1881 (INTR_STATUS0__PROGRAM_COMP |
1882 INTR_STATUS0__PROGRAM_FAIL)))
1883 ;
1884
1885 if (ioread32(FlashReg + intr_status) &
1886 INTR_STATUS0__PROGRAM_FAIL)
1887 status = FAIL;
1888
1889 iowrite32(ioread32(FlashReg + intr_status),
1890 FlashReg + intr_status);
1891
1892 page_num++;
1893 page_count--;
1894 write_data += PageSize;
1895 }
1896
1897 iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
1898 }
1899
1900 return status;
1901}
1902
1903u16 NAND_Read_Page_Main_Spare(u8 *read_data, u32 block, u16 page,
1904 u16 page_count)
1905{
1906 u32 status = PASS;
1907 u32 i, j;
1908 u64 flash_add = 0;
1909 u32 PageSize = DeviceInfo.wPageSize;
1910 u32 PageDataSize = DeviceInfo.wPageDataSize;
1911 u32 PageSpareSize = DeviceInfo.wPageSpareSize;
1912 u32 eccBytes = DeviceInfo.wECCBytesPerSector;
1913 u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag;
1914 u32 spareSkipBytes = DeviceInfo.wSpareSkipBytes;
1915 u32 eccSectorSize;
1916 u32 flash_bank;
1917 u32 intr_status = 0;
1918 u8 *read_data_l = read_data;
1919 u32 intr_status_addresses[4] = {INTR_STATUS0,
1920 INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
1921 u8 *page_main_spare = buf_read_page_main_spare;
1922
1923 nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
1924 __FILE__, __LINE__, __func__);
1925
1926 eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected);
1927
1928 status = Boundary_Check_Block_Page(block, page, page_count);
1929
1930 flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
1931
1932 if (status == PASS) {
1933 intr_status = intr_status_addresses[flash_bank];
1934
1935 iowrite32(1, FlashReg + TRANSFER_SPARE_REG);
1936
1937 iowrite32(ioread32(FlashReg + intr_status),
1938 FlashReg + intr_status);
1939
1940 while ((status != FAIL) && (page_count > 0)) {
1941 flash_add = (u64)(block %
1942 (DeviceInfo.wTotalBlocks / totalUsedBanks))
1943 * DeviceInfo.wBlockDataSize +
1944 (u64)page * DeviceInfo.wPageDataSize;
1945
1946 index_addr((u32)(MODE_10 | (flash_bank << 24) |
1947 (flash_add >> DeviceInfo.nBitsInPageDataSize)),
1948 0x43);
1949 index_addr((u32)(MODE_10 | (flash_bank << 24) |
1950 (flash_add >> DeviceInfo.nBitsInPageDataSize)),
1951 0x2000 | page_count);
1952
1953 while (!(ioread32(FlashReg + intr_status) &
1954 INTR_STATUS0__LOAD_COMP))
1955 ;
1956
1957 iowrite32((u32)(MODE_01 | (flash_bank << 24) |
1958 (flash_add >>
1959 DeviceInfo.nBitsInPageDataSize)),
1960 FlashMem);
1961
1962 for (i = 0; i < PageSize / 4; i++)
1963 *(((u32 *)page_main_spare) + i) =
1964 ioread32(FlashMem + 0x10);
1965
1966 if (enable_ecc) {
1967 for (i = PageDataSize; i < PageSize -
1968 spareSkipBytes; i++)
1969 page_main_spare[i] = page_main_spare[i +
1970 spareSkipBytes];
1971
1972 for (j = 0;
1973 j < DeviceInfo.wPageDataSize / eccSectorSize;
1974 j++) {
1975
1976 for (i = 0; i < eccSectorSize; i++)
1977 read_data_l[eccSectorSize * j +
1978 i] =
1979 page_main_spare[
1980 (eccSectorSize +
1981 eccBytes) * j + i];
1982
1983 for (i = 0; i < eccBytes; i++)
1984 read_data_l[PageDataSize +
1985 spareFlagBytes +
1986 eccBytes * j + i] =
1987 page_main_spare[
1988 (eccSectorSize +
1989 eccBytes) * j +
1990 eccSectorSize + i];
1991 }
1992
1993 for (i = 0; i < spareFlagBytes; i++)
1994 read_data_l[PageDataSize + i] =
1995 page_main_spare[(eccSectorSize +
1996 eccBytes) * j + i];
1997 } else {
1998 for (i = 0; i < (PageDataSize + PageSpareSize);
1999 i++)
2000 read_data_l[i] = page_main_spare[i];
2001
2002 }
2003
2004 if (enable_ecc) {
2005 while (!(ioread32(FlashReg + intr_status) &
2006 (INTR_STATUS0__ECC_TRANSACTION_DONE |
2007 INTR_STATUS0__ECC_ERR)))
2008 ;
2009
2010 if (ioread32(FlashReg + intr_status) &
2011 INTR_STATUS0__ECC_ERR) {
2012 iowrite32(INTR_STATUS0__ECC_ERR,
2013 FlashReg + intr_status);
2014 status = do_ecc_new(flash_bank,
2015 read_data, block, page);
2016 }
2017
2018 if (ioread32(FlashReg + intr_status) &
2019 INTR_STATUS0__ECC_TRANSACTION_DONE &
2020 INTR_STATUS0__ECC_ERR) {
2021 iowrite32(INTR_STATUS0__ECC_ERR |
2022 INTR_STATUS0__ECC_TRANSACTION_DONE,
2023 FlashReg + intr_status);
2024 } else if (ioread32(FlashReg + intr_status) &
2025 INTR_STATUS0__ECC_TRANSACTION_DONE) {
2026 iowrite32(
2027 INTR_STATUS0__ECC_TRANSACTION_DONE,
2028 FlashReg + intr_status);
2029 } else if (ioread32(FlashReg + intr_status) &
2030 INTR_STATUS0__ECC_ERR) {
2031 iowrite32(INTR_STATUS0__ECC_ERR,
2032 FlashReg + intr_status);
2033 }
2034 }
2035
2036 page++;
2037 page_count--;
2038 read_data_l += PageSize;
2039 }
2040 }
2041
2042 iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
2043
2044 index_addr((u32)(MODE_10 | (flash_bank << 24) |
2045 (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42);
2046
2047 return status;
2048}
2049
2050u16 NAND_Pipeline_Write_Ahead(u8 *write_data, u32 block,
2051 u16 page, u16 page_count)
2052{
2053 u16 status = PASS;
2054 u32 NumPages = page_count;
2055 u64 flash_add;
2056 u32 flash_bank;
2057 u32 intr_status = 0;
2058 u32 intr_status_addresses[4] = {INTR_STATUS0,
2059 INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
2060 int ret;
2061
2062 nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
2063 __FILE__, __LINE__, __func__);
2064
2065 status = Boundary_Check_Block_Page(block, page, page_count);
2066
2067 if (page_count < 2)
2068 status = FAIL;
2069
2070 if (status != PASS)
2071 return status;
2072
2073 flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks))
2074 * DeviceInfo.wBlockDataSize +
2075 (u64)page * DeviceInfo.wPageDataSize;
2076
2077 flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
2078
2079 intr_status = intr_status_addresses[flash_bank];
2080 iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
2081
2082 iowrite32(1, FlashReg + DMA_ENABLE);
2083 while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
2084 ;
2085
2086 iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
2087
2088 /* Fill the mrst_nand_info structure */
2089 info.state = INT_PIPELINE_WRITE_AHEAD;
2090 info.write_data = write_data;
2091 info.flash_bank = flash_bank;
2092 info.block = block;
2093 info.page = page;
2094 info.ret = PASS;
2095
2096 index_addr((u32)(MODE_10 | (flash_bank << 24) |
2097 (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42);
2098
2099 ddma_trans(write_data, flash_add, flash_bank, 1, NumPages);
2100
2101 iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable interrupt */
2102
2103 ret = wait_for_completion_timeout(&info.complete, 10 * HZ);
2104 if (!ret) {
2105 printk(KERN_ERR "Wait for completion timeout "
2106 "in %s, Line %d\n", __FILE__, __LINE__);
2107 status = ERR;
2108 } else {
2109 status = info.ret;
2110 }
2111
2112 iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
2113
2114 iowrite32(0, FlashReg + DMA_ENABLE);
2115 while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
2116 ;
2117
2118 return status;
2119}
2120
2121/* Un-tested function */
2122u16 NAND_Multiplane_Write(u8 *write_data, u32 block, u16 page,
2123 u16 page_count)
2124{
2125 u16 status = PASS;
2126 u32 NumPages = page_count;
2127 u64 flash_add;
2128 u32 flash_bank;
2129 u32 intr_status = 0;
2130 u32 intr_status_addresses[4] = {INTR_STATUS0,
2131 INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
2132 u16 status2 = PASS;
2133 u32 t;
2134
2135 nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
2136 __FILE__, __LINE__, __func__);
2137
2138 status = Boundary_Check_Block_Page(block, page, page_count);
2139 if (status != PASS)
2140 return status;
2141
2142 flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks))
2143 * DeviceInfo.wBlockDataSize +
2144 (u64)page * DeviceInfo.wPageDataSize;
2145
2146 flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks);
2147
2148 intr_status = intr_status_addresses[flash_bank];
2149 iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
2150
2151 iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
2152 iowrite32(0x01, FlashReg + MULTIPLANE_OPERATION);
2153
2154 iowrite32(1, FlashReg + DMA_ENABLE);
2155 while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
2156 ;
2157
2158 iowrite32(0, FlashReg + TRANSFER_SPARE_REG);
2159
2160 index_addr((u32)(MODE_10 | (flash_bank << 24) |
2161 (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42);
2162
2163 ddma_trans(write_data, flash_add, flash_bank, 1, NumPages);
2164
2165 while (1) {
2166 while (!ioread32(FlashReg + intr_status))
2167 ;
2168
2169 if (ioread32(FlashReg + intr_status) &
2170 INTR_STATUS0__DMA_CMD_COMP) {
2171 iowrite32(INTR_STATUS0__DMA_CMD_COMP,
2172 FlashReg + intr_status);
2173 status = PASS;
2174 if (status2 == FAIL)
2175 status = FAIL;
2176 break;
2177 } else if (ioread32(FlashReg + intr_status) &
2178 INTR_STATUS0__PROGRAM_FAIL) {
2179 status2 = FAIL;
2180 status = FAIL;
2181 t = ioread32(FlashReg + intr_status) &
2182 INTR_STATUS0__PROGRAM_FAIL;
2183 iowrite32(t, FlashReg + intr_status);
2184 } else {
2185 iowrite32((~INTR_STATUS0__PROGRAM_FAIL) &
2186 (~INTR_STATUS0__DMA_CMD_COMP),
2187 FlashReg + intr_status);
2188 }
2189 }
2190
2191 iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status);
2192
2193 iowrite32(0, FlashReg + DMA_ENABLE);
2194
2195 while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG))
2196 ;
2197
2198 iowrite32(0, FlashReg + MULTIPLANE_OPERATION);
2199
2200 return status;
2201}
2202
2203
2204#if CMD_DMA
2205static irqreturn_t cdma_isr(int irq, void *dev_id)
2206{
2207 struct mrst_nand_info *dev = dev_id;
2208 int first_failed_cmd;
2209
2210 nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
2211 __FILE__, __LINE__, __func__);
2212
2213 if (!is_cdma_interrupt())
2214 return IRQ_NONE;
2215
2216 /* Disable controller interrupts */
2217 iowrite32(0, FlashReg + GLOBAL_INT_ENABLE);
2218 GLOB_FTL_Event_Status(&first_failed_cmd);
2219 complete(&dev->complete);
2220
2221 return IRQ_HANDLED;
2222}
2223#else
2224static void handle_nand_int_read(struct mrst_nand_info *dev)
2225{
2226 u32 intr_status_addresses[4] = {INTR_STATUS0,
2227 INTR_STATUS1, INTR_STATUS2, INTR_STATUS3};
2228 u32 intr_status;
2229 u32 ecc_done_OR_dma_comp = 0;
2230
2231 nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
2232 __FILE__, __LINE__, __func__);
2233
2234 dev->ret = PASS;
2235 intr_status = intr_status_addresses[dev->flash_bank];
2236
2237 while (1) {
2238 if (enable_ecc) {
2239 if (ioread32(FlashReg + intr_status) &
2240 INTR_STATUS0__ECC_ERR) {
2241 iowrite32(INTR_STATUS0__ECC_ERR,
2242 FlashReg + intr_status);
2243 dev->ret = do_ecc_new(dev->flash_bank,
2244 dev->read_data,
2245 dev->block, dev->page);
2246 } else if (ioread32(FlashReg + intr_status) &
2247 INTR_STATUS0__DMA_CMD_COMP) {
2248 iowrite32(INTR_STATUS0__DMA_CMD_COMP,
2249 FlashReg + intr_status);
2250 if (1 == ecc_done_OR_dma_comp)
2251 break;
2252 ecc_done_OR_dma_comp = 1;
2253 } else if (ioread32(FlashReg + intr_status) &
2254 INTR_STATUS0__ECC_TRANSACTION_DONE) {
2255 iowrite32(INTR_STATUS0__ECC_TRANSACTION_DONE,
2256 FlashReg + intr_status);
2257 if (1 == ecc_done_OR_dma_comp)
2258 break;
2259 ecc_done_OR_dma_comp = 1;
2260 }
2261 } else {
2262 if (ioread32(FlashReg + intr_status) &
2263 INTR_STATUS0__DMA_CMD_COMP) {
2264 iowrite32(INTR_STATUS0__DMA_CMD_COMP,
2265 FlashReg + intr_status);
2266 break;
2267 } else {
2268 printk(KERN_ERR "Illegal INTS "
2269 "(offset addr 0x%x) value: 0x%x\n",
2270 intr_status,
2271 ioread32(FlashReg + intr_status));
2272 }
2273 }
2274
2275 iowrite32((~INTR_STATUS0__ECC_ERR) &
2276 (~INTR_STATUS0__ECC_TRANSACTION_DONE) &
2277 (~INTR_STATUS0__DMA_CMD_COMP),
2278 FlashReg + intr_status);
2279 }
2280}
2281
2282static void handle_nand_int_write(struct mrst_nand_info *dev)
2283{
2284 u32 intr_status;
2285 u32 intr[4] = {INTR_STATUS0, INTR_STATUS1,
2286 INTR_STATUS2, INTR_STATUS3};
2287 int status = PASS;
2288
2289 nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n",
2290 __FILE__, __LINE__, __func__);
2291
2292 dev->ret = PASS;
2293 intr_status = intr[dev->flash_bank];
2294
2295 while (1) {
2296 while (!ioread32(FlashReg + intr_status))
2297 ;
2298
2299 if (ioread32(FlashReg + intr_status) &
2300 INTR_STATUS0__DMA_CMD_COMP) {
2301 iowrite32(INTR_STATUS0__DMA_CMD_COMP,
2302 FlashReg + intr_status);
2303 if (FAIL == status)
2304 dev->ret = FAIL;
2305 break;
2306 } else if (ioread32(FlashReg + intr_status) &
2307 INTR_STATUS0__PROGRAM_FAIL) {
2308 status = FAIL;
2309 iowrite32(INTR_STATUS0__PROGRAM_FAIL,
2310 FlashReg + intr_status);
2311 } else {
2312 iowrite32((~INTR_STATUS0__PROGRAM_FAIL) &
2313 (~INTR_STATUS0__DMA_CMD_COMP),
2314 FlashReg + intr_status);
2315 }
2316 }
2317}
2318
2319static irqreturn_t ddma_isr(int irq, void *dev_id)
2320{
2321 struct mrst_nand_info *dev = dev_id;
2322 u32 int_mask, ints0, ints1, ints2, ints3, ints_offset;
2323 u32 intr[4] = {INTR_STATUS0, INTR_STATUS1,
2324 INTR_STATUS2, INTR_STATUS3};
2325
2326 int_mask = INTR_STATUS0__DMA_CMD_COMP |
2327 INTR_STATUS0__ECC_TRANSACTION_DONE |
2328 INTR_STATUS0__ECC_ERR |
2329 INTR_STATUS0__PROGRAM_FAIL |
2330 INTR_STATUS0__ERASE_FAIL;
2331
2332 ints0 = ioread32(FlashReg + INTR_STATUS0);
2333 ints1 = ioread32(FlashReg + INTR_STATUS1);
2334 ints2 = ioread32(FlashReg + INTR_STATUS2);
2335 ints3 = ioread32(FlashReg + INTR_STATUS3);
2336
2337 ints_offset = intr[dev->flash_bank];
2338
2339 nand_dbg_print(NAND_DBG_DEBUG,
2340 "INTR0: 0x%x, INTR1: 0x%x, INTR2: 0x%x, INTR3: 0x%x, "
2341 "DMA_INTR: 0x%x, "
2342 "dev->state: 0x%x, dev->flash_bank: %d\n",
2343 ints0, ints1, ints2, ints3,
2344 ioread32(FlashReg + DMA_INTR),
2345 dev->state, dev->flash_bank);
2346
2347 if (!(ioread32(FlashReg + ints_offset) & int_mask)) {
2348 iowrite32(ints0, FlashReg + INTR_STATUS0);
2349 iowrite32(ints1, FlashReg + INTR_STATUS1);
2350 iowrite32(ints2, FlashReg + INTR_STATUS2);
2351 iowrite32(ints3, FlashReg + INTR_STATUS3);
2352 nand_dbg_print(NAND_DBG_WARN,
2353 "ddma_isr: Invalid interrupt for NAND controller. "
2354 "Ignore it\n");
2355 return IRQ_NONE;
2356 }
2357
2358 switch (dev->state) {
2359 case INT_READ_PAGE_MAIN:
2360 case INT_PIPELINE_READ_AHEAD:
2361 /* Disable controller interrupts */
2362 iowrite32(0, FlashReg + GLOBAL_INT_ENABLE);
2363 handle_nand_int_read(dev);
2364 break;
2365 case INT_WRITE_PAGE_MAIN:
2366 case INT_PIPELINE_WRITE_AHEAD:
2367 iowrite32(0, FlashReg + GLOBAL_INT_ENABLE);
2368 handle_nand_int_write(dev);
2369 break;
2370 default:
2371 printk(KERN_ERR "ddma_isr - Illegal state: 0x%x\n",
2372 dev->state);
2373 return IRQ_NONE;
2374 }
2375
2376 dev->state = INT_IDLE_STATE;
2377 complete(&dev->complete);
2378 return IRQ_HANDLED;
2379}
2380#endif
2381
2382static const struct pci_device_id nand_pci_ids[] = {
2383 {
2384 .vendor = 0x8086,
2385 .device = 0x0809,
2386 .subvendor = PCI_ANY_ID,
2387 .subdevice = PCI_ANY_ID,
2388 },
2389 { /* end: all zeroes */ }
2390};
2391
2392static int nand_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
2393{
2394 int ret = -ENODEV;
2395 unsigned long csr_base;
2396 unsigned long csr_len;
2397 struct mrst_nand_info *pndev = &info;
2398 u32 int_mask;
2399
2400 ret = pci_enable_device(dev);
2401 if (ret) {
2402 printk(KERN_ERR "Spectra: pci_enable_device failed.\n");
2403 return ret;
2404 }
2405
2406 nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
2407 __FILE__, __LINE__, __func__);
2408
2409 FlashReg = ioremap_nocache(GLOB_HWCTL_REG_BASE,
2410 GLOB_HWCTL_REG_SIZE);
2411 if (!FlashReg) {
2412 printk(KERN_ERR "Spectra: ioremap_nocache failed!");
2413 goto failed_disable;
2414 }
2415 nand_dbg_print(NAND_DBG_WARN,
2416 "Spectra: Remapped reg base address: "
2417 "0x%p, len: %d\n",
2418 FlashReg, GLOB_HWCTL_REG_SIZE);
2419
2420 FlashMem = ioremap_nocache(GLOB_HWCTL_MEM_BASE,
2421 GLOB_HWCTL_MEM_SIZE);
2422 if (!FlashMem) {
2423 printk(KERN_ERR "Spectra: ioremap_nocache failed!");
2424 iounmap(FlashReg);
2425 goto failed_disable;
2426 }
2427 nand_dbg_print(NAND_DBG_WARN,
2428 "Spectra: Remapped flash base address: "
2429 "0x%p, len: %d\n",
2430 (void *)FlashMem, GLOB_HWCTL_MEM_SIZE);
2431
2432 nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:"
2433 "acc_clks: %d, re_2_we: %d, we_2_re: %d,"
2434 "addr_2_data: %d, rdwr_en_lo_cnt: %d, "
2435 "rdwr_en_hi_cnt: %d, cs_setup_cnt: %d\n",
2436 ioread32(FlashReg + ACC_CLKS),
2437 ioread32(FlashReg + RE_2_WE),
2438 ioread32(FlashReg + WE_2_RE),
2439 ioread32(FlashReg + ADDR_2_DATA),
2440 ioread32(FlashReg + RDWR_EN_LO_CNT),
2441 ioread32(FlashReg + RDWR_EN_HI_CNT),
2442 ioread32(FlashReg + CS_SETUP_CNT));
2443
2444 NAND_Flash_Reset();
2445
2446 iowrite32(0, FlashReg + GLOBAL_INT_ENABLE);
2447
2448#if CMD_DMA
2449 info.pcmds_num = 0;
2450 info.flash_bank = 0;
2451 info.cdma_num = 0;
2452 int_mask = (DMA_INTR__DESC_COMP_CHANNEL0 |
2453 DMA_INTR__DESC_COMP_CHANNEL1 |
2454 DMA_INTR__DESC_COMP_CHANNEL2 |
2455 DMA_INTR__DESC_COMP_CHANNEL3 |
2456 DMA_INTR__MEMCOPY_DESC_COMP);
2457 iowrite32(int_mask, FlashReg + DMA_INTR_EN);
2458 iowrite32(0xFFFF, FlashReg + DMA_INTR);
2459
2460 int_mask = (INTR_STATUS0__ECC_ERR |
2461 INTR_STATUS0__PROGRAM_FAIL |
2462 INTR_STATUS0__ERASE_FAIL);
2463#else
2464 int_mask = INTR_STATUS0__DMA_CMD_COMP |
2465 INTR_STATUS0__ECC_TRANSACTION_DONE |
2466 INTR_STATUS0__ECC_ERR |
2467 INTR_STATUS0__PROGRAM_FAIL |
2468 INTR_STATUS0__ERASE_FAIL;
2469#endif
2470 iowrite32(int_mask, FlashReg + INTR_EN0);
2471 iowrite32(int_mask, FlashReg + INTR_EN1);
2472 iowrite32(int_mask, FlashReg + INTR_EN2);
2473 iowrite32(int_mask, FlashReg + INTR_EN3);
2474
2475 /* Clear all status bits */
2476 iowrite32(0xFFFF, FlashReg + INTR_STATUS0);
2477 iowrite32(0xFFFF, FlashReg + INTR_STATUS1);
2478 iowrite32(0xFFFF, FlashReg + INTR_STATUS2);
2479 iowrite32(0xFFFF, FlashReg + INTR_STATUS3);
2480
2481 iowrite32(0x0F, FlashReg + RB_PIN_ENABLED);
2482 iowrite32(CHIP_EN_DONT_CARE__FLAG, FlashReg + CHIP_ENABLE_DONT_CARE);
2483
2484 /* Should set value for these registers when init */
2485 iowrite32(0, FlashReg + TWO_ROW_ADDR_CYCLES);
2486 iowrite32(1, FlashReg + ECC_ENABLE);
2487 enable_ecc = 1;
2488
2489 pci_set_master(dev);
2490 pndev->dev = dev;
2491
2492 csr_base = pci_resource_start(dev, 0);
2493 if (!csr_base) {
2494 printk(KERN_ERR "Spectra: pci_resource_start failed!\n");
2495 ret = -ENODEV;
2496 goto failed_req_csr;
2497 }
2498
2499 csr_len = pci_resource_len(dev, 0);
2500 if (!csr_len) {
2501 printk(KERN_ERR "Spectra: pci_resource_len failed!\n");
2502 ret = -ENODEV;
2503 goto failed_req_csr;
2504 }
2505
2506 ret = pci_request_regions(dev, SPECTRA_NAND_NAME);
2507 if (ret) {
2508 printk(KERN_ERR "Spectra: Unable to request "
2509 "memory region\n");
2510 goto failed_req_csr;
2511 }
2512
2513 pndev->ioaddr = ioremap_nocache(csr_base, csr_len);
2514 if (!pndev->ioaddr) {
2515 printk(KERN_ERR "Spectra: Unable to remap memory region\n");
2516 ret = -ENOMEM;
2517 goto failed_remap_csr;
2518 }
2519 nand_dbg_print(NAND_DBG_DEBUG, "Spectra: CSR 0x%08lx -> 0x%p (0x%lx)\n",
2520 csr_base, pndev->ioaddr, csr_len);
2521
2522 init_completion(&pndev->complete);
2523 nand_dbg_print(NAND_DBG_DEBUG, "Spectra: IRQ %d\n", dev->irq);
2524
2525#if CMD_DMA
2526 if (request_irq(dev->irq, cdma_isr, IRQF_SHARED,
2527 SPECTRA_NAND_NAME, &info)) {
2528 printk(KERN_ERR "Spectra: Unable to allocate IRQ\n");
2529 ret = -ENODEV;
2530 iounmap(pndev->ioaddr);
2531 goto failed_remap_csr;
2532 }
2533#else
2534 if (request_irq(dev->irq, ddma_isr, IRQF_SHARED,
2535 SPECTRA_NAND_NAME, &info)) {
2536 printk(KERN_ERR "Spectra: Unable to allocate IRQ\n");
2537 ret = -ENODEV;
2538 iounmap(pndev->ioaddr);
2539 goto failed_remap_csr;
2540 }
2541#endif
2542
2543 pci_set_drvdata(dev, pndev);
2544
2545 ret = GLOB_LLD_Read_Device_ID();
2546 if (ret) {
2547 iounmap(pndev->ioaddr);
2548 goto failed_remap_csr;
2549 }
2550
2551 ret = register_spectra_ftl();
2552 if (ret) {
2553 iounmap(pndev->ioaddr);
2554 goto failed_remap_csr;
2555 }
2556
2557 return 0;
2558
2559failed_remap_csr:
2560 pci_release_regions(dev);
2561failed_req_csr:
2562 iounmap(FlashMem);
2563 iounmap(FlashReg);
2564failed_disable:
2565 pci_disable_device(dev);
2566
2567 return ret;
2568}
2569
2570static void nand_pci_remove(struct pci_dev *dev)
2571{
2572 struct mrst_nand_info *pndev = pci_get_drvdata(dev);
2573
2574 nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n",
2575 __FILE__, __LINE__, __func__);
2576
2577#if CMD_DMA
2578 free_irq(dev->irq, pndev);
2579#endif
2580 iounmap(pndev->ioaddr);
2581 pci_release_regions(dev);
2582 pci_disable_device(dev);
2583}
2584
2585MODULE_DEVICE_TABLE(pci, nand_pci_ids);
2586
2587static struct pci_driver nand_pci_driver = {
2588 .name = SPECTRA_NAND_NAME,
2589 .id_table = nand_pci_ids,
2590 .probe = nand_pci_probe,
2591 .remove = nand_pci_remove,
2592};
2593
2594int NAND_Flash_Init(void)
2595{
2596 int retval;
2597
2598 nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
2599 __FILE__, __LINE__, __func__);
2600
2601 retval = pci_register_driver(&nand_pci_driver);
2602 if (retval)
2603 return -ENOMEM;
2604
2605 return PASS;
2606}
2607
2608/* Free memory */
2609int nand_release_spectra(void)
2610{
2611 pci_unregister_driver(&nand_pci_driver);
2612 iounmap(FlashMem);
2613 iounmap(FlashReg);
2614
2615 return 0;
2616}
2617
2618
2619
diff --git a/drivers/staging/spectra/lld_nand.h b/drivers/staging/spectra/lld_nand.h
new file mode 100644
index 00000000000..d08388287da
--- /dev/null
+++ b/drivers/staging/spectra/lld_nand.h
@@ -0,0 +1,131 @@
1/*
2 * NAND Flash Controller Device Driver
3 * Copyright (c) 2009, Intel Corporation and its suppliers.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19
20#ifndef _LLD_NAND_
21#define _LLD_NAND_
22
23#ifdef ELDORA
24#include "defs.h"
25#else
26#include "flash.h"
27#include "ffsport.h"
28#endif
29
30#define MODE_00 0x00000000
31#define MODE_01 0x04000000
32#define MODE_10 0x08000000
33#define MODE_11 0x0C000000
34
35
36#define DATA_TRANSFER_MODE 0
37#define PROTECTION_PER_BLOCK 1
38#define LOAD_WAIT_COUNT 2
39#define PROGRAM_WAIT_COUNT 3
40#define ERASE_WAIT_COUNT 4
41#define INT_MONITOR_CYCLE_COUNT 5
42#define READ_BUSY_PIN_ENABLED 6
43#define MULTIPLANE_OPERATION_SUPPORT 7
44#define PRE_FETCH_MODE 8
45#define CE_DONT_CARE_SUPPORT 9
46#define COPYBACK_SUPPORT 10
47#define CACHE_WRITE_SUPPORT 11
48#define CACHE_READ_SUPPORT 12
49#define NUM_PAGES_IN_BLOCK 13
50#define ECC_ENABLE_SELECT 14
51#define WRITE_ENABLE_2_READ_ENABLE 15
52#define ADDRESS_2_DATA 16
53#define READ_ENABLE_2_WRITE_ENABLE 17
54#define TWO_ROW_ADDRESS_CYCLES 18
55#define MULTIPLANE_ADDRESS_RESTRICT 19
56#define ACC_CLOCKS 20
57#define READ_WRITE_ENABLE_LOW_COUNT 21
58#define READ_WRITE_ENABLE_HIGH_COUNT 22
59
60#define ECC_SECTOR_SIZE 512
61#define LLD_MAX_FLASH_BANKS 4
62
63struct mrst_nand_info {
64 struct pci_dev *dev;
65 u32 state;
66 u32 flash_bank;
67 u8 *read_data;
68 u8 *write_data;
69 u32 block;
70 u16 page;
71 u32 use_dma;
72 void __iomem *ioaddr; /* Mapped io reg base address */
73 int ret;
74 u32 pcmds_num;
75 struct pending_cmd *pcmds;
76 int cdma_num; /* CDMA descriptor number in this chan */
77 u8 *cdma_desc_buf; /* CDMA descriptor table */
78 u8 *memcp_desc_buf; /* Memory copy descriptor table */
79 dma_addr_t cdma_desc; /* Mapped CDMA descriptor table */
80 dma_addr_t memcp_desc; /* Mapped memory copy descriptor table */
81 struct completion complete;
82};
83
84int NAND_Flash_Init(void);
85int nand_release_spectra(void);
86u16 NAND_Flash_Reset(void);
87u16 NAND_Read_Device_ID(void);
88u16 NAND_Erase_Block(u32 flash_add);
89u16 NAND_Write_Page_Main(u8 *write_data, u32 block, u16 page,
90 u16 page_count);
91u16 NAND_Read_Page_Main(u8 *read_data, u32 block, u16 page,
92 u16 page_count);
93u16 NAND_UnlockArrayAll(void);
94u16 NAND_Write_Page_Main_Spare(u8 *write_data, u32 block,
95 u16 page, u16 page_count);
96u16 NAND_Write_Page_Spare(u8 *read_data, u32 block, u16 page,
97 u16 page_count);
98u16 NAND_Read_Page_Main_Spare(u8 *read_data, u32 block, u16 page,
99 u16 page_count);
100u16 NAND_Read_Page_Spare(u8 *read_data, u32 block, u16 page,
101 u16 page_count);
102void NAND_LLD_Enable_Disable_Interrupts(u16 INT_ENABLE);
103u16 NAND_Get_Bad_Block(u32 block);
104u16 NAND_Pipeline_Read_Ahead(u8 *read_data, u32 block, u16 page,
105 u16 page_count);
106u16 NAND_Pipeline_Write_Ahead(u8 *write_data, u32 block,
107 u16 page, u16 page_count);
108u16 NAND_Multiplane_Read(u8 *read_data, u32 block, u16 page,
109 u16 page_count);
110u16 NAND_Multiplane_Write(u8 *write_data, u32 block, u16 page,
111 u16 page_count);
112void NAND_ECC_Ctrl(int enable);
113u16 NAND_Read_Page_Main_Polling(u8 *read_data,
114 u32 block, u16 page, u16 page_count);
115u16 NAND_Pipeline_Read_Ahead_Polling(u8 *read_data,
116 u32 block, u16 page, u16 page_count);
117void Conv_Spare_Data_Log2Phy_Format(u8 *data);
118void Conv_Spare_Data_Phy2Log_Format(u8 *data);
119void Conv_Main_Spare_Data_Log2Phy_Format(u8 *data, u16 page_count);
120void Conv_Main_Spare_Data_Phy2Log_Format(u8 *data, u16 page_count);
121
122extern void __iomem *FlashReg;
123extern void __iomem *FlashMem;
124
125extern int totalUsedBanks;
126extern u32 GLOB_valid_banks[LLD_MAX_FLASH_BANKS];
127
128#endif /*_LLD_NAND_*/
129
130
131
diff --git a/drivers/staging/spectra/nand_regs.h b/drivers/staging/spectra/nand_regs.h
new file mode 100644
index 00000000000..e192e4ae8c1
--- /dev/null
+++ b/drivers/staging/spectra/nand_regs.h
@@ -0,0 +1,619 @@
1/*
2 * NAND Flash Controller Device Driver
3 * Copyright (c) 2009, Intel Corporation and its suppliers.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19
20#define DEVICE_RESET 0x0
21#define DEVICE_RESET__BANK0 0x0001
22#define DEVICE_RESET__BANK1 0x0002
23#define DEVICE_RESET__BANK2 0x0004
24#define DEVICE_RESET__BANK3 0x0008
25
26#define TRANSFER_SPARE_REG 0x10
27#define TRANSFER_SPARE_REG__FLAG 0x0001
28
29#define LOAD_WAIT_CNT 0x20
30#define LOAD_WAIT_CNT__VALUE 0xffff
31
32#define PROGRAM_WAIT_CNT 0x30
33#define PROGRAM_WAIT_CNT__VALUE 0xffff
34
35#define ERASE_WAIT_CNT 0x40
36#define ERASE_WAIT_CNT__VALUE 0xffff
37
38#define INT_MON_CYCCNT 0x50
39#define INT_MON_CYCCNT__VALUE 0xffff
40
41#define RB_PIN_ENABLED 0x60
42#define RB_PIN_ENABLED__BANK0 0x0001
43#define RB_PIN_ENABLED__BANK1 0x0002
44#define RB_PIN_ENABLED__BANK2 0x0004
45#define RB_PIN_ENABLED__BANK3 0x0008
46
47#define MULTIPLANE_OPERATION 0x70
48#define MULTIPLANE_OPERATION__FLAG 0x0001
49
50#define MULTIPLANE_READ_ENABLE 0x80
51#define MULTIPLANE_READ_ENABLE__FLAG 0x0001
52
53#define COPYBACK_DISABLE 0x90
54#define COPYBACK_DISABLE__FLAG 0x0001
55
56#define CACHE_WRITE_ENABLE 0xa0
57#define CACHE_WRITE_ENABLE__FLAG 0x0001
58
59#define CACHE_READ_ENABLE 0xb0
60#define CACHE_READ_ENABLE__FLAG 0x0001
61
62#define PREFETCH_MODE 0xc0
63#define PREFETCH_MODE__PREFETCH_EN 0x0001
64#define PREFETCH_MODE__PREFETCH_BURST_LENGTH 0xfff0
65
66#define CHIP_ENABLE_DONT_CARE 0xd0
67#define CHIP_EN_DONT_CARE__FLAG 0x01
68
69#define ECC_ENABLE 0xe0
70#define ECC_ENABLE__FLAG 0x0001
71
72#define GLOBAL_INT_ENABLE 0xf0
73#define GLOBAL_INT_EN_FLAG 0x01
74
75#define WE_2_RE 0x100
76#define WE_2_RE__VALUE 0x003f
77
78#define ADDR_2_DATA 0x110
79#define ADDR_2_DATA__VALUE 0x003f
80
81#define RE_2_WE 0x120
82#define RE_2_WE__VALUE 0x003f
83
84#define ACC_CLKS 0x130
85#define ACC_CLKS__VALUE 0x000f
86
87#define NUMBER_OF_PLANES 0x140
88#define NUMBER_OF_PLANES__VALUE 0x0007
89
90#define PAGES_PER_BLOCK 0x150
91#define PAGES_PER_BLOCK__VALUE 0xffff
92
93#define DEVICE_WIDTH 0x160
94#define DEVICE_WIDTH__VALUE 0x0003
95
96#define DEVICE_MAIN_AREA_SIZE 0x170
97#define DEVICE_MAIN_AREA_SIZE__VALUE 0xffff
98
99#define DEVICE_SPARE_AREA_SIZE 0x180
100#define DEVICE_SPARE_AREA_SIZE__VALUE 0xffff
101
102#define TWO_ROW_ADDR_CYCLES 0x190
103#define TWO_ROW_ADDR_CYCLES__FLAG 0x0001
104
105#define MULTIPLANE_ADDR_RESTRICT 0x1a0
106#define MULTIPLANE_ADDR_RESTRICT__FLAG 0x0001
107
108#define ECC_CORRECTION 0x1b0
109#define ECC_CORRECTION__VALUE 0x001f
110
111#define READ_MODE 0x1c0
112#define READ_MODE__VALUE 0x000f
113
114#define WRITE_MODE 0x1d0
115#define WRITE_MODE__VALUE 0x000f
116
117#define COPYBACK_MODE 0x1e0
118#define COPYBACK_MODE__VALUE 0x000f
119
120#define RDWR_EN_LO_CNT 0x1f0
121#define RDWR_EN_LO_CNT__VALUE 0x001f
122
123#define RDWR_EN_HI_CNT 0x200
124#define RDWR_EN_HI_CNT__VALUE 0x001f
125
126#define MAX_RD_DELAY 0x210
127#define MAX_RD_DELAY__VALUE 0x000f
128
129#define CS_SETUP_CNT 0x220
130#define CS_SETUP_CNT__VALUE 0x001f
131
132#define SPARE_AREA_SKIP_BYTES 0x230
133#define SPARE_AREA_SKIP_BYTES__VALUE 0x003f
134
135#define SPARE_AREA_MARKER 0x240
136#define SPARE_AREA_MARKER__VALUE 0xffff
137
138#define DEVICES_CONNECTED 0x250
139#define DEVICES_CONNECTED__VALUE 0x0007
140
141#define DIE_MASK 0x260
142#define DIE_MASK__VALUE 0x00ff
143
144#define FIRST_BLOCK_OF_NEXT_PLANE 0x270
145#define FIRST_BLOCK_OF_NEXT_PLANE__VALUE 0xffff
146
147#define WRITE_PROTECT 0x280
148#define WRITE_PROTECT__FLAG 0x0001
149
150#define RE_2_RE 0x290
151#define RE_2_RE__VALUE 0x003f
152
153#define MANUFACTURER_ID 0x300
154#define MANUFACTURER_ID__VALUE 0x00ff
155
156#define DEVICE_ID 0x310
157#define DEVICE_ID__VALUE 0x00ff
158
159#define DEVICE_PARAM_0 0x320
160#define DEVICE_PARAM_0__VALUE 0x00ff
161
162#define DEVICE_PARAM_1 0x330
163#define DEVICE_PARAM_1__VALUE 0x00ff
164
165#define DEVICE_PARAM_2 0x340
166#define DEVICE_PARAM_2__VALUE 0x00ff
167
168#define LOGICAL_PAGE_DATA_SIZE 0x350
169#define LOGICAL_PAGE_DATA_SIZE__VALUE 0xffff
170
171#define LOGICAL_PAGE_SPARE_SIZE 0x360
172#define LOGICAL_PAGE_SPARE_SIZE__VALUE 0xffff
173
174#define REVISION 0x370
175#define REVISION__VALUE 0xffff
176
177#define ONFI_DEVICE_FEATURES 0x380
178#define ONFI_DEVICE_FEATURES__VALUE 0x003f
179
180#define ONFI_OPTIONAL_COMMANDS 0x390
181#define ONFI_OPTIONAL_COMMANDS__VALUE 0x003f
182
183#define ONFI_TIMING_MODE 0x3a0
184#define ONFI_TIMING_MODE__VALUE 0x003f
185
186#define ONFI_PGM_CACHE_TIMING_MODE 0x3b0
187#define ONFI_PGM_CACHE_TIMING_MODE__VALUE 0x003f
188
189#define ONFI_DEVICE_NO_OF_LUNS 0x3c0
190#define ONFI_DEVICE_NO_OF_LUNS__NO_OF_LUNS 0x00ff
191#define ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE 0x0100
192
193#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L 0x3d0
194#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L__VALUE 0xffff
195
196#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U 0x3e0
197#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U__VALUE 0xffff
198
199#define FEATURES 0x3f0
200#define FEATURES__N_BANKS 0x0003
201#define FEATURES__ECC_MAX_ERR 0x003c
202#define FEATURES__DMA 0x0040
203#define FEATURES__CMD_DMA 0x0080
204#define FEATURES__PARTITION 0x0100
205#define FEATURES__XDMA_SIDEBAND 0x0200
206#define FEATURES__GPREG 0x0400
207#define FEATURES__INDEX_ADDR 0x0800
208
209#define TRANSFER_MODE 0x400
210#define TRANSFER_MODE__VALUE 0x0003
211
212#define INTR_STATUS0 0x410
213#define INTR_STATUS0__ECC_TRANSACTION_DONE 0x0001
214#define INTR_STATUS0__ECC_ERR 0x0002
215#define INTR_STATUS0__DMA_CMD_COMP 0x0004
216#define INTR_STATUS0__TIME_OUT 0x0008
217#define INTR_STATUS0__PROGRAM_FAIL 0x0010
218#define INTR_STATUS0__ERASE_FAIL 0x0020
219#define INTR_STATUS0__LOAD_COMP 0x0040
220#define INTR_STATUS0__PROGRAM_COMP 0x0080
221#define INTR_STATUS0__ERASE_COMP 0x0100
222#define INTR_STATUS0__PIPE_CPYBCK_CMD_COMP 0x0200
223#define INTR_STATUS0__LOCKED_BLK 0x0400
224#define INTR_STATUS0__UNSUP_CMD 0x0800
225#define INTR_STATUS0__INT_ACT 0x1000
226#define INTR_STATUS0__RST_COMP 0x2000
227#define INTR_STATUS0__PIPE_CMD_ERR 0x4000
228#define INTR_STATUS0__PAGE_XFER_INC 0x8000
229
230#define INTR_EN0 0x420
231#define INTR_EN0__ECC_TRANSACTION_DONE 0x0001
232#define INTR_EN0__ECC_ERR 0x0002
233#define INTR_EN0__DMA_CMD_COMP 0x0004
234#define INTR_EN0__TIME_OUT 0x0008
235#define INTR_EN0__PROGRAM_FAIL 0x0010
236#define INTR_EN0__ERASE_FAIL 0x0020
237#define INTR_EN0__LOAD_COMP 0x0040
238#define INTR_EN0__PROGRAM_COMP 0x0080
239#define INTR_EN0__ERASE_COMP 0x0100
240#define INTR_EN0__PIPE_CPYBCK_CMD_COMP 0x0200
241#define INTR_EN0__LOCKED_BLK 0x0400
242#define INTR_EN0__UNSUP_CMD 0x0800
243#define INTR_EN0__INT_ACT 0x1000
244#define INTR_EN0__RST_COMP 0x2000
245#define INTR_EN0__PIPE_CMD_ERR 0x4000
246#define INTR_EN0__PAGE_XFER_INC 0x8000
247
248#define PAGE_CNT0 0x430
249#define PAGE_CNT0__VALUE 0x00ff
250
251#define ERR_PAGE_ADDR0 0x440
252#define ERR_PAGE_ADDR0__VALUE 0xffff
253
254#define ERR_BLOCK_ADDR0 0x450
255#define ERR_BLOCK_ADDR0__VALUE 0xffff
256
257#define INTR_STATUS1 0x460
258#define INTR_STATUS1__ECC_TRANSACTION_DONE 0x0001
259#define INTR_STATUS1__ECC_ERR 0x0002
260#define INTR_STATUS1__DMA_CMD_COMP 0x0004
261#define INTR_STATUS1__TIME_OUT 0x0008
262#define INTR_STATUS1__PROGRAM_FAIL 0x0010
263#define INTR_STATUS1__ERASE_FAIL 0x0020
264#define INTR_STATUS1__LOAD_COMP 0x0040
265#define INTR_STATUS1__PROGRAM_COMP 0x0080
266#define INTR_STATUS1__ERASE_COMP 0x0100
267#define INTR_STATUS1__PIPE_CPYBCK_CMD_COMP 0x0200
268#define INTR_STATUS1__LOCKED_BLK 0x0400
269#define INTR_STATUS1__UNSUP_CMD 0x0800
270#define INTR_STATUS1__INT_ACT 0x1000
271#define INTR_STATUS1__RST_COMP 0x2000
272#define INTR_STATUS1__PIPE_CMD_ERR 0x4000
273#define INTR_STATUS1__PAGE_XFER_INC 0x8000
274
275#define INTR_EN1 0x470
276#define INTR_EN1__ECC_TRANSACTION_DONE 0x0001
277#define INTR_EN1__ECC_ERR 0x0002
278#define INTR_EN1__DMA_CMD_COMP 0x0004
279#define INTR_EN1__TIME_OUT 0x0008
280#define INTR_EN1__PROGRAM_FAIL 0x0010
281#define INTR_EN1__ERASE_FAIL 0x0020
282#define INTR_EN1__LOAD_COMP 0x0040
283#define INTR_EN1__PROGRAM_COMP 0x0080
284#define INTR_EN1__ERASE_COMP 0x0100
285#define INTR_EN1__PIPE_CPYBCK_CMD_COMP 0x0200
286#define INTR_EN1__LOCKED_BLK 0x0400
287#define INTR_EN1__UNSUP_CMD 0x0800
288#define INTR_EN1__INT_ACT 0x1000
289#define INTR_EN1__RST_COMP 0x2000
290#define INTR_EN1__PIPE_CMD_ERR 0x4000
291#define INTR_EN1__PAGE_XFER_INC 0x8000
292
293#define PAGE_CNT1 0x480
294#define PAGE_CNT1__VALUE 0x00ff
295
296#define ERR_PAGE_ADDR1 0x490
297#define ERR_PAGE_ADDR1__VALUE 0xffff
298
299#define ERR_BLOCK_ADDR1 0x4a0
300#define ERR_BLOCK_ADDR1__VALUE 0xffff
301
302#define INTR_STATUS2 0x4b0
303#define INTR_STATUS2__ECC_TRANSACTION_DONE 0x0001
304#define INTR_STATUS2__ECC_ERR 0x0002
305#define INTR_STATUS2__DMA_CMD_COMP 0x0004
306#define INTR_STATUS2__TIME_OUT 0x0008
307#define INTR_STATUS2__PROGRAM_FAIL 0x0010
308#define INTR_STATUS2__ERASE_FAIL 0x0020
309#define INTR_STATUS2__LOAD_COMP 0x0040
310#define INTR_STATUS2__PROGRAM_COMP 0x0080
311#define INTR_STATUS2__ERASE_COMP 0x0100
312#define INTR_STATUS2__PIPE_CPYBCK_CMD_COMP 0x0200
313#define INTR_STATUS2__LOCKED_BLK 0x0400
314#define INTR_STATUS2__UNSUP_CMD 0x0800
315#define INTR_STATUS2__INT_ACT 0x1000
316#define INTR_STATUS2__RST_COMP 0x2000
317#define INTR_STATUS2__PIPE_CMD_ERR 0x4000
318#define INTR_STATUS2__PAGE_XFER_INC 0x8000
319
320#define INTR_EN2 0x4c0
321#define INTR_EN2__ECC_TRANSACTION_DONE 0x0001
322#define INTR_EN2__ECC_ERR 0x0002
323#define INTR_EN2__DMA_CMD_COMP 0x0004
324#define INTR_EN2__TIME_OUT 0x0008
325#define INTR_EN2__PROGRAM_FAIL 0x0010
326#define INTR_EN2__ERASE_FAIL 0x0020
327#define INTR_EN2__LOAD_COMP 0x0040
328#define INTR_EN2__PROGRAM_COMP 0x0080
329#define INTR_EN2__ERASE_COMP 0x0100
330#define INTR_EN2__PIPE_CPYBCK_CMD_COMP 0x0200
331#define INTR_EN2__LOCKED_BLK 0x0400
332#define INTR_EN2__UNSUP_CMD 0x0800
333#define INTR_EN2__INT_ACT 0x1000
334#define INTR_EN2__RST_COMP 0x2000
335#define INTR_EN2__PIPE_CMD_ERR 0x4000
336#define INTR_EN2__PAGE_XFER_INC 0x8000
337
338#define PAGE_CNT2 0x4d0
339#define PAGE_CNT2__VALUE 0x00ff
340
341#define ERR_PAGE_ADDR2 0x4e0
342#define ERR_PAGE_ADDR2__VALUE 0xffff
343
344#define ERR_BLOCK_ADDR2 0x4f0
345#define ERR_BLOCK_ADDR2__VALUE 0xffff
346
347#define INTR_STATUS3 0x500
348#define INTR_STATUS3__ECC_TRANSACTION_DONE 0x0001
349#define INTR_STATUS3__ECC_ERR 0x0002
350#define INTR_STATUS3__DMA_CMD_COMP 0x0004
351#define INTR_STATUS3__TIME_OUT 0x0008
352#define INTR_STATUS3__PROGRAM_FAIL 0x0010
353#define INTR_STATUS3__ERASE_FAIL 0x0020
354#define INTR_STATUS3__LOAD_COMP 0x0040
355#define INTR_STATUS3__PROGRAM_COMP 0x0080
356#define INTR_STATUS3__ERASE_COMP 0x0100
357#define INTR_STATUS3__PIPE_CPYBCK_CMD_COMP 0x0200
358#define INTR_STATUS3__LOCKED_BLK 0x0400
359#define INTR_STATUS3__UNSUP_CMD 0x0800
360#define INTR_STATUS3__INT_ACT 0x1000
361#define INTR_STATUS3__RST_COMP 0x2000
362#define INTR_STATUS3__PIPE_CMD_ERR 0x4000
363#define INTR_STATUS3__PAGE_XFER_INC 0x8000
364
365#define INTR_EN3 0x510
366#define INTR_EN3__ECC_TRANSACTION_DONE 0x0001
367#define INTR_EN3__ECC_ERR 0x0002
368#define INTR_EN3__DMA_CMD_COMP 0x0004
369#define INTR_EN3__TIME_OUT 0x0008
370#define INTR_EN3__PROGRAM_FAIL 0x0010
371#define INTR_EN3__ERASE_FAIL 0x0020
372#define INTR_EN3__LOAD_COMP 0x0040
373#define INTR_EN3__PROGRAM_COMP 0x0080
374#define INTR_EN3__ERASE_COMP 0x0100
375#define INTR_EN3__PIPE_CPYBCK_CMD_COMP 0x0200
376#define INTR_EN3__LOCKED_BLK 0x0400
377#define INTR_EN3__UNSUP_CMD 0x0800
378#define INTR_EN3__INT_ACT 0x1000
379#define INTR_EN3__RST_COMP 0x2000
380#define INTR_EN3__PIPE_CMD_ERR 0x4000
381#define INTR_EN3__PAGE_XFER_INC 0x8000
382
383#define PAGE_CNT3 0x520
384#define PAGE_CNT3__VALUE 0x00ff
385
386#define ERR_PAGE_ADDR3 0x530
387#define ERR_PAGE_ADDR3__VALUE 0xffff
388
389#define ERR_BLOCK_ADDR3 0x540
390#define ERR_BLOCK_ADDR3__VALUE 0xffff
391
392#define DATA_INTR 0x550
393#define DATA_INTR__WRITE_SPACE_AV 0x0001
394#define DATA_INTR__READ_DATA_AV 0x0002
395
396#define DATA_INTR_EN 0x560
397#define DATA_INTR_EN__WRITE_SPACE_AV 0x0001
398#define DATA_INTR_EN__READ_DATA_AV 0x0002
399
400#define GPREG_0 0x570
401#define GPREG_0__VALUE 0xffff
402
403#define GPREG_1 0x580
404#define GPREG_1__VALUE 0xffff
405
406#define GPREG_2 0x590
407#define GPREG_2__VALUE 0xffff
408
409#define GPREG_3 0x5a0
410#define GPREG_3__VALUE 0xffff
411
412#define ECC_THRESHOLD 0x600
413#define ECC_THRESHOLD__VALUE 0x03ff
414
415#define ECC_ERROR_BLOCK_ADDRESS 0x610
416#define ECC_ERROR_BLOCK_ADDRESS__VALUE 0xffff
417
418#define ECC_ERROR_PAGE_ADDRESS 0x620
419#define ECC_ERROR_PAGE_ADDRESS__VALUE 0x0fff
420#define ECC_ERROR_PAGE_ADDRESS__BANK 0xf000
421
422#define ECC_ERROR_ADDRESS 0x630
423#define ECC_ERROR_ADDRESS__OFFSET 0x0fff
424#define ECC_ERROR_ADDRESS__SECTOR_NR 0xf000
425
426#define ERR_CORRECTION_INFO 0x640
427#define ERR_CORRECTION_INFO__BYTEMASK 0x00ff
428#define ERR_CORRECTION_INFO__DEVICE_NR 0x0f00
429#define ERR_CORRECTION_INFO__ERROR_TYPE 0x4000
430#define ERR_CORRECTION_INFO__LAST_ERR_INFO 0x8000
431
432#define DMA_ENABLE 0x700
433#define DMA_ENABLE__FLAG 0x0001
434
435#define IGNORE_ECC_DONE 0x710
436#define IGNORE_ECC_DONE__FLAG 0x0001
437
438#define DMA_INTR 0x720
439#define DMA_INTR__TARGET_ERROR 0x0001
440#define DMA_INTR__DESC_COMP_CHANNEL0 0x0002
441#define DMA_INTR__DESC_COMP_CHANNEL1 0x0004
442#define DMA_INTR__DESC_COMP_CHANNEL2 0x0008
443#define DMA_INTR__DESC_COMP_CHANNEL3 0x0010
444#define DMA_INTR__MEMCOPY_DESC_COMP 0x0020
445
446#define DMA_INTR_EN 0x730
447#define DMA_INTR_EN__TARGET_ERROR 0x0001
448#define DMA_INTR_EN__DESC_COMP_CHANNEL0 0x0002
449#define DMA_INTR_EN__DESC_COMP_CHANNEL1 0x0004
450#define DMA_INTR_EN__DESC_COMP_CHANNEL2 0x0008
451#define DMA_INTR_EN__DESC_COMP_CHANNEL3 0x0010
452#define DMA_INTR_EN__MEMCOPY_DESC_COMP 0x0020
453
454#define TARGET_ERR_ADDR_LO 0x740
455#define TARGET_ERR_ADDR_LO__VALUE 0xffff
456
457#define TARGET_ERR_ADDR_HI 0x750
458#define TARGET_ERR_ADDR_HI__VALUE 0xffff
459
460#define CHNL_ACTIVE 0x760
461#define CHNL_ACTIVE__CHANNEL0 0x0001
462#define CHNL_ACTIVE__CHANNEL1 0x0002
463#define CHNL_ACTIVE__CHANNEL2 0x0004
464#define CHNL_ACTIVE__CHANNEL3 0x0008
465
466#define ACTIVE_SRC_ID 0x800
467#define ACTIVE_SRC_ID__VALUE 0x00ff
468
469#define PTN_INTR 0x810
470#define PTN_INTR__CONFIG_ERROR 0x0001
471#define PTN_INTR__ACCESS_ERROR_BANK0 0x0002
472#define PTN_INTR__ACCESS_ERROR_BANK1 0x0004
473#define PTN_INTR__ACCESS_ERROR_BANK2 0x0008
474#define PTN_INTR__ACCESS_ERROR_BANK3 0x0010
475#define PTN_INTR__REG_ACCESS_ERROR 0x0020
476
477#define PTN_INTR_EN 0x820
478#define PTN_INTR_EN__CONFIG_ERROR 0x0001
479#define PTN_INTR_EN__ACCESS_ERROR_BANK0 0x0002
480#define PTN_INTR_EN__ACCESS_ERROR_BANK1 0x0004
481#define PTN_INTR_EN__ACCESS_ERROR_BANK2 0x0008
482#define PTN_INTR_EN__ACCESS_ERROR_BANK3 0x0010
483#define PTN_INTR_EN__REG_ACCESS_ERROR 0x0020
484
485#define PERM_SRC_ID_0 0x830
486#define PERM_SRC_ID_0__SRCID 0x00ff
487#define PERM_SRC_ID_0__DIRECT_ACCESS_ACTIVE 0x0800
488#define PERM_SRC_ID_0__WRITE_ACTIVE 0x2000
489#define PERM_SRC_ID_0__READ_ACTIVE 0x4000
490#define PERM_SRC_ID_0__PARTITION_VALID 0x8000
491
492#define MIN_BLK_ADDR_0 0x840
493#define MIN_BLK_ADDR_0__VALUE 0xffff
494
495#define MAX_BLK_ADDR_0 0x850
496#define MAX_BLK_ADDR_0__VALUE 0xffff
497
498#define MIN_MAX_BANK_0 0x860
499#define MIN_MAX_BANK_0__MIN_VALUE 0x0003
500#define MIN_MAX_BANK_0__MAX_VALUE 0x000c
501
502#define PERM_SRC_ID_1 0x870
503#define PERM_SRC_ID_1__SRCID 0x00ff
504#define PERM_SRC_ID_1__DIRECT_ACCESS_ACTIVE 0x0800
505#define PERM_SRC_ID_1__WRITE_ACTIVE 0x2000
506#define PERM_SRC_ID_1__READ_ACTIVE 0x4000
507#define PERM_SRC_ID_1__PARTITION_VALID 0x8000
508
509#define MIN_BLK_ADDR_1 0x880
510#define MIN_BLK_ADDR_1__VALUE 0xffff
511
512#define MAX_BLK_ADDR_1 0x890
513#define MAX_BLK_ADDR_1__VALUE 0xffff
514
515#define MIN_MAX_BANK_1 0x8a0
516#define MIN_MAX_BANK_1__MIN_VALUE 0x0003
517#define MIN_MAX_BANK_1__MAX_VALUE 0x000c
518
519#define PERM_SRC_ID_2 0x8b0
520#define PERM_SRC_ID_2__SRCID 0x00ff
521#define PERM_SRC_ID_2__DIRECT_ACCESS_ACTIVE 0x0800
522#define PERM_SRC_ID_2__WRITE_ACTIVE 0x2000
523#define PERM_SRC_ID_2__READ_ACTIVE 0x4000
524#define PERM_SRC_ID_2__PARTITION_VALID 0x8000
525
526#define MIN_BLK_ADDR_2 0x8c0
527#define MIN_BLK_ADDR_2__VALUE 0xffff
528
529#define MAX_BLK_ADDR_2 0x8d0
530#define MAX_BLK_ADDR_2__VALUE 0xffff
531
532#define MIN_MAX_BANK_2 0x8e0
533#define MIN_MAX_BANK_2__MIN_VALUE 0x0003
534#define MIN_MAX_BANK_2__MAX_VALUE 0x000c
535
536#define PERM_SRC_ID_3 0x8f0
537#define PERM_SRC_ID_3__SRCID 0x00ff
538#define PERM_SRC_ID_3__DIRECT_ACCESS_ACTIVE 0x0800
539#define PERM_SRC_ID_3__WRITE_ACTIVE 0x2000
540#define PERM_SRC_ID_3__READ_ACTIVE 0x4000
541#define PERM_SRC_ID_3__PARTITION_VALID 0x8000
542
543#define MIN_BLK_ADDR_3 0x900
544#define MIN_BLK_ADDR_3__VALUE 0xffff
545
546#define MAX_BLK_ADDR_3 0x910
547#define MAX_BLK_ADDR_3__VALUE 0xffff
548
549#define MIN_MAX_BANK_3 0x920
550#define MIN_MAX_BANK_3__MIN_VALUE 0x0003
551#define MIN_MAX_BANK_3__MAX_VALUE 0x000c
552
553#define PERM_SRC_ID_4 0x930
554#define PERM_SRC_ID_4__SRCID 0x00ff
555#define PERM_SRC_ID_4__DIRECT_ACCESS_ACTIVE 0x0800
556#define PERM_SRC_ID_4__WRITE_ACTIVE 0x2000
557#define PERM_SRC_ID_4__READ_ACTIVE 0x4000
558#define PERM_SRC_ID_4__PARTITION_VALID 0x8000
559
560#define MIN_BLK_ADDR_4 0x940
561#define MIN_BLK_ADDR_4__VALUE 0xffff
562
563#define MAX_BLK_ADDR_4 0x950
564#define MAX_BLK_ADDR_4__VALUE 0xffff
565
566#define MIN_MAX_BANK_4 0x960
567#define MIN_MAX_BANK_4__MIN_VALUE 0x0003
568#define MIN_MAX_BANK_4__MAX_VALUE 0x000c
569
570#define PERM_SRC_ID_5 0x970
571#define PERM_SRC_ID_5__SRCID 0x00ff
572#define PERM_SRC_ID_5__DIRECT_ACCESS_ACTIVE 0x0800
573#define PERM_SRC_ID_5__WRITE_ACTIVE 0x2000
574#define PERM_SRC_ID_5__READ_ACTIVE 0x4000
575#define PERM_SRC_ID_5__PARTITION_VALID 0x8000
576
577#define MIN_BLK_ADDR_5 0x980
578#define MIN_BLK_ADDR_5__VALUE 0xffff
579
580#define MAX_BLK_ADDR_5 0x990
581#define MAX_BLK_ADDR_5__VALUE 0xffff
582
583#define MIN_MAX_BANK_5 0x9a0
584#define MIN_MAX_BANK_5__MIN_VALUE 0x0003
585#define MIN_MAX_BANK_5__MAX_VALUE 0x000c
586
587#define PERM_SRC_ID_6 0x9b0
588#define PERM_SRC_ID_6__SRCID 0x00ff
589#define PERM_SRC_ID_6__DIRECT_ACCESS_ACTIVE 0x0800
590#define PERM_SRC_ID_6__WRITE_ACTIVE 0x2000
591#define PERM_SRC_ID_6__READ_ACTIVE 0x4000
592#define PERM_SRC_ID_6__PARTITION_VALID 0x8000
593
594#define MIN_BLK_ADDR_6 0x9c0
595#define MIN_BLK_ADDR_6__VALUE 0xffff
596
597#define MAX_BLK_ADDR_6 0x9d0
598#define MAX_BLK_ADDR_6__VALUE 0xffff
599
600#define MIN_MAX_BANK_6 0x9e0
601#define MIN_MAX_BANK_6__MIN_VALUE 0x0003
602#define MIN_MAX_BANK_6__MAX_VALUE 0x000c
603
604#define PERM_SRC_ID_7 0x9f0
605#define PERM_SRC_ID_7__SRCID 0x00ff
606#define PERM_SRC_ID_7__DIRECT_ACCESS_ACTIVE 0x0800
607#define PERM_SRC_ID_7__WRITE_ACTIVE 0x2000
608#define PERM_SRC_ID_7__READ_ACTIVE 0x4000
609#define PERM_SRC_ID_7__PARTITION_VALID 0x8000
610
611#define MIN_BLK_ADDR_7 0xa00
612#define MIN_BLK_ADDR_7__VALUE 0xffff
613
614#define MAX_BLK_ADDR_7 0xa10
615#define MAX_BLK_ADDR_7__VALUE 0xffff
616
617#define MIN_MAX_BANK_7 0xa20
618#define MIN_MAX_BANK_7__MIN_VALUE 0x0003
619#define MIN_MAX_BANK_7__MAX_VALUE 0x000c
diff --git a/drivers/staging/spectra/spectraswconfig.h b/drivers/staging/spectra/spectraswconfig.h
new file mode 100644
index 00000000000..17259469e95
--- /dev/null
+++ b/drivers/staging/spectra/spectraswconfig.h
@@ -0,0 +1,82 @@
1/*
2 * NAND Flash Controller Device Driver
3 * Copyright (c) 2009, Intel Corporation and its suppliers.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19
20#ifndef _SPECTRASWCONFIG_
21#define _SPECTRASWCONFIG_
22
23/* NAND driver version */
24#define GLOB_VERSION "driver version 20100311"
25
26
27/***** Common Parameters *****/
28#define RETRY_TIMES 3
29
30#define READ_BADBLOCK_INFO 1
31#define READBACK_VERIFY 0
32#define AUTO_FORMAT_FLASH 0
33
34/***** Cache Parameters *****/
35#define CACHE_ITEM_NUM 128
36#define BLK_NUM_FOR_L2_CACHE 16
37
38/***** Block Table Parameters *****/
39#define BLOCK_TABLE_INDEX 0
40
41/***** Wear Leveling Parameters *****/
42#define WEAR_LEVELING_GATE 0x10
43#define WEAR_LEVELING_BLOCK_NUM 10
44
45#define DEBUG_BNDRY 0
46
47/***** Product Feature Support *****/
48#define FLASH_EMU defined(CONFIG_SPECTRA_EMU)
49#define FLASH_NAND defined(CONFIG_SPECTRA_MRST_HW)
50#define FLASH_MTD defined(CONFIG_SPECTRA_MTD)
51#define CMD_DMA defined(CONFIG_SPECTRA_MRST_HW_DMA)
52
53#define SPECTRA_PARTITION_ID 0
54
55/* Enable this macro if the number of flash blocks is larger than 16K. */
56#define SUPPORT_LARGE_BLOCKNUM 1
57
58/**** Block Table and Reserved Block Parameters *****/
59#define SPECTRA_START_BLOCK 3
60//#define NUM_FREE_BLOCKS_GATE 30
61#define NUM_FREE_BLOCKS_GATE 60
62
63/**** Hardware Parameters ****/
64#define GLOB_HWCTL_REG_BASE 0xFFA40000
65#define GLOB_HWCTL_REG_SIZE 4096
66
67#define GLOB_HWCTL_MEM_BASE 0xFFA48000
68#define GLOB_HWCTL_MEM_SIZE 4096
69
70/* KBV - Updated to LNW scratch register address */
71#define SCRATCH_REG_ADDR 0xFF108018
72#define SCRATCH_REG_SIZE 64
73
74#define GLOB_HWCTL_DEFAULT_BLKS 2048
75
76#define SUPPORT_15BITECC 1
77#define SUPPORT_8BITECC 1
78
79#define ONFI_BLOOM_TIME 0
80#define MODE5_WORKAROUND 1
81
82#endif /*_SPECTRASWCONFIG_*/