aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/devices
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/devices')
-rw-r--r--drivers/mtd/devices/tegra_nand.c1802
-rw-r--r--drivers/mtd/devices/tegra_nand.h148
2 files changed, 1950 insertions, 0 deletions
diff --git a/drivers/mtd/devices/tegra_nand.c b/drivers/mtd/devices/tegra_nand.c
new file mode 100644
index 00000000000..c8a3e7090b9
--- /dev/null
+++ b/drivers/mtd/devices/tegra_nand.c
@@ -0,0 +1,1802 @@
1/*
2 * drivers/mtd/devices/tegra_nand.c
3 *
4 * Copyright (C) 2010 Google, Inc.
5 * Author: Dima Zavin <dima@android.com>
6 * Colin Cross <ccross@android.com>
7 *
8 * Copyright (C) 2010-2011 Nvidia Graphics Pvt. Ltd.
9 * http://www.nvidia.com
10 *
11 * This software is licensed under the terms of the GNU General Public
12 * License version 2, as published by the Free Software Foundation, and
13 * may be copied, distributed, and modified under those terms.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * Derived from: drivers/mtd/nand/nand_base.c
21 * drivers/mtd/nand/pxa3xx.c
22 *
23 */
24
25#include <linux/delay.h>
26#include <linux/dma-mapping.h>
27#include <linux/init.h>
28#include <linux/interrupt.h>
29#include <linux/io.h>
30#include <linux/module.h>
31#include <linux/mutex.h>
32#include <linux/mtd/nand.h>
33#include <linux/mtd/mtd.h>
34#include <linux/mtd/partitions.h>
35#include <linux/platform_device.h>
36#include <linux/types.h>
37#include <linux/clk.h>
38#include <linux/slab.h>
39#include <linux/gpio.h>
40
41#include <mach/nand.h>
42
43#include "tegra_nand.h"
44
45#define DRIVER_NAME "tegra_nand"
46#define DRIVER_DESC "Nvidia Tegra NAND Flash Controller driver"
47
48#define MAX_DMA_SZ SZ_64K
49#define ECC_BUF_SZ SZ_1K
50
51/* FIXME: is this right?!
52 * NvRM code says it should be 128 bytes, but that seems awfully small
53 */
54
55/*#define TEGRA_NAND_DEBUG
56#define TEGRA_NAND_DEBUG_PEDANTIC*/
57
58#ifdef TEGRA_NAND_DEBUG
59#define TEGRA_DBG(fmt, args...) \
60 do { pr_info(fmt, ##args); } while (0)
61#else
62#define TEGRA_DBG(fmt, args...)
63#endif
64
65/* TODO: will vary with devices, move into appropriate device spcific header */
66#define SCAN_TIMING_VAL 0x3f0bd214
67#define SCAN_TIMING2_VAL 0xb
68
69#define TIMEOUT (2 * HZ)
70/* TODO: pull in the register defs (fields, masks, etc) from Nvidia files
71 * so we don't have to redefine them */
72
73static const char *part_probes[] = { "cmdlinepart", NULL, };
74
75struct tegra_nand_chip {
76 spinlock_t lock;
77 uint32_t chipsize;
78 int num_chips;
79 int curr_chip;
80
81 /* addr >> chip_shift == chip number */
82 uint32_t chip_shift;
83 /* (addr >> page_shift) & page_mask == page number within chip */
84 uint32_t page_shift;
85 uint32_t page_mask;
86 /* column within page */
87 uint32_t column_mask;
88 /* addr >> block_shift == block number (across the whole mtd dev, not
89 * just a single chip. */
90 uint32_t block_shift;
91
92 void *priv;
93};
94
95struct tegra_nand_info {
96 struct tegra_nand_chip chip;
97 struct mtd_info mtd;
98 struct tegra_nand_platform *plat;
99 struct device *dev;
100 struct mtd_partition *parts;
101
102 /* synchronizes access to accessing the actual NAND controller */
103 struct mutex lock;
104 /* partial_unaligned_rw_buffer is temporary buffer used during
105 reading of unaligned data from nand pages or if data to be read
106 is less than nand page size.
107 */
108 uint8_t *partial_unaligned_rw_buffer;
109
110 void *oob_dma_buf;
111 dma_addr_t oob_dma_addr;
112 /* ecc error vector info (offset into page and data mask to apply */
113 void *ecc_buf;
114 dma_addr_t ecc_addr;
115 /* ecc error status (page number, err_cnt) */
116 uint32_t *ecc_errs;
117 uint32_t num_ecc_errs;
118 uint32_t max_ecc_errs;
119 spinlock_t ecc_lock;
120
121 uint32_t command_reg;
122 uint32_t config_reg;
123 uint32_t dmactrl_reg;
124
125 struct completion cmd_complete;
126 struct completion dma_complete;
127
128 /* bad block bitmap: 1 == good, 0 == bad/unknown */
129 unsigned long *bb_bitmap;
130
131 struct clk *clk;
132 uint32_t is_data_bus_width_16;
133 uint32_t device_id;
134 uint32_t vendor_id;
135 uint32_t dev_parms;
136 uint32_t num_bad_blocks;
137};
138#define MTD_TO_INFO(mtd) container_of((mtd), struct tegra_nand_info, mtd)
139
140/* 64 byte oob block info for large page (== 2KB) device
141 *
142 * OOB flash layout for Tegra with Reed-Solomon 4 symbol correct ECC:
143 * Skipped bytes(4)
144 * Main area Ecc(36)
145 * Tag data(20)
146 * Tag data Ecc(4)
147 *
148 * Yaffs2 will use 16 tag bytes.
149 */
150
151static struct nand_ecclayout tegra_nand_oob_64 = {
152 .eccbytes = 36,
153 .eccpos = {
154 4, 5, 6, 7, 8, 9, 10, 11, 12,
155 13, 14, 15, 16, 17, 18, 19, 20, 21,
156 22, 23, 24, 25, 26, 27, 28, 29, 30,
157 31, 32, 33, 34, 35, 36, 37, 38, 39,
158 },
159 .oobavail = 20,
160 .oobfree = {
161 {.offset = 40,
162 .length = 20,
163 },
164 },
165};
166
167static struct nand_ecclayout tegra_nand_oob_128 = {
168 .eccbytes = 72,
169 .eccpos = {
170 4, 5, 6, 7, 8, 9, 10, 11, 12,
171 13, 14, 15, 16, 17, 18, 19, 20, 21,
172 22, 23, 24, 25, 26, 27, 28, 29, 30,
173 31, 32, 33, 34, 35, 36, 37, 38, 39,
174 40, 41, 42, 43, 44, 45, 46, 47, 48,
175 49, 50, 51, 52, 53, 54, 55, 56, 57,
176 58, 59, 60, 61, 62, 63, 64, 65, 66,
177 /* ECC POS is only of size 64 bytes so commenting the remaining
178 * bytes here. As driver uses the Hardware ECC so it there is
179 * no issue with it
180 */
181 /*67, 68, 69, 70, 71, 72, 73, 74, 75, */
182 },
183 .oobavail = 48,
184 .oobfree = {
185 {.offset = 76,
186 .length = 48,
187 },
188 },
189};
190
191static struct nand_flash_dev *find_nand_flash_device(int dev_id)
192{
193 struct nand_flash_dev *dev = &nand_flash_ids[0];
194
195 while (dev->name && dev->id != dev_id)
196 dev++;
197 return dev->name ? dev : NULL;
198}
199
200static struct nand_manufacturers *find_nand_flash_vendor(int vendor_id)
201{
202 struct nand_manufacturers *vendor = &nand_manuf_ids[0];
203
204 while (vendor->id && vendor->id != vendor_id)
205 vendor++;
206 return vendor->id ? vendor : NULL;
207}
208
209#define REG_NAME(name) { name, #name }
210static struct {
211 uint32_t addr;
212 char *name;
213} reg_names[] = {
214 REG_NAME(COMMAND_REG),
215 REG_NAME(STATUS_REG),
216 REG_NAME(ISR_REG),
217