aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Daudt <csd@broadcom.com>2012-09-21 17:40:25 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2012-09-29 10:54:09 -0400
commitb2bc415b6b7bb240b967f6dd95007a2cf7b4c424 (patch)
tree1c8401a0e04e1df05beefc57d47bd313900135b0
parent5ca7f41528922c90da3ae3b917dc904047513be2 (diff)
mtd: remove bcmring NAND driver
This driver is being removed as part of the cleanup of the bcmring SoC from mainline as it is no longer maintained. Signed-off-by: Christian Daudt <csd@broadcom.com> Reviewed-by: Jiandong Zheng <jdzheng@broadcom.com> Acked-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
-rw-r--r--MAINTAINERS9
-rw-r--r--drivers/mtd/nand/Kconfig16
-rw-r--r--drivers/mtd/nand/Makefile1
-rw-r--r--drivers/mtd/nand/bcm_umi_bch.c210
-rw-r--r--drivers/mtd/nand/bcm_umi_nand.c533
-rw-r--r--drivers/mtd/nand/nand_bcm_umi.c149
-rw-r--r--drivers/mtd/nand/nand_bcm_umi.h337
7 files changed, 0 insertions, 1255 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 61ad79ea2b08..0709df21b8a2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -665,15 +665,6 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
665S: Maintained 665S: Maintained
666F: arch/arm/mach-bcmring 666F: arch/arm/mach-bcmring
667 667
668ARM/BCMRING MTD NAND DRIVER
669M: Jiandong Zheng <jdzheng@broadcom.com>
670M: Scott Branden <sbranden@broadcom.com>
671L: linux-mtd@lists.infradead.org
672S: Maintained
673F: drivers/mtd/nand/bcm_umi_nand.c
674F: drivers/mtd/nand/bcm_umi_bch.c
675F: drivers/mtd/nand/nand_bcm_umi.h
676
677ARM/CALXEDA HIGHBANK ARCHITECTURE 668ARM/CALXEDA HIGHBANK ARCHITECTURE
678M: Rob Herring <rob.herring@calxeda.com> 669M: Rob Herring <rob.herring@calxeda.com>
679L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) 670L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 6010b500f93d..baa343634819 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -258,22 +258,6 @@ config MTD_NAND_S3C2410_CLKSTOP
258 when the is NAND chip selected or released, but will save 258 when the is NAND chip selected or released, but will save
259 approximately 5mA of power when there is nothing happening. 259 approximately 5mA of power when there is nothing happening.
260 260
261config MTD_NAND_BCM_UMI
262 tristate "NAND Flash support for BCM Reference Boards"
263 depends on ARCH_BCMRING
264 help
265 This enables the NAND flash controller on the BCM UMI block.
266
267 No board specific support is done by this driver, each board
268 must advertise a platform_device for the driver to attach.
269
270config MTD_NAND_BCM_UMI_HWCS
271 bool "BCM UMI NAND Hardware CS"
272 depends on MTD_NAND_BCM_UMI
273 help
274 Enable the use of the BCM UMI block's internal CS using NAND.
275 This should only be used if you know the external NAND CS can toggle.
276
277config MTD_NAND_DISKONCHIP 261config MTD_NAND_DISKONCHIP
278 tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)" 262 tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)"
279 depends on EXPERIMENTAL 263 depends on EXPERIMENTAL
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index c4b0ab316bab..2cbd0916b733 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -48,7 +48,6 @@ obj-$(CONFIG_MTD_NAND_SOCRATES) += socrates_nand.o
48obj-$(CONFIG_MTD_NAND_TXX9NDFMC) += txx9ndfmc.o 48obj-$(CONFIG_MTD_NAND_TXX9NDFMC) += txx9ndfmc.o
49obj-$(CONFIG_MTD_NAND_NUC900) += nuc900_nand.o 49obj-$(CONFIG_MTD_NAND_NUC900) += nuc900_nand.o
50obj-$(CONFIG_MTD_NAND_NOMADIK) += nomadik_nand.o 50obj-$(CONFIG_MTD_NAND_NOMADIK) += nomadik_nand.o
51obj-$(CONFIG_MTD_NAND_BCM_UMI) += bcm_umi_nand.o nand_bcm_umi.o
52obj-$(CONFIG_MTD_NAND_MPC5121_NFC) += mpc5121_nfc.o 51obj-$(CONFIG_MTD_NAND_MPC5121_NFC) += mpc5121_nfc.o
53obj-$(CONFIG_MTD_NAND_RICOH) += r852.o 52obj-$(CONFIG_MTD_NAND_RICOH) += r852.o
54obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o 53obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o
diff --git a/drivers/mtd/nand/bcm_umi_bch.c b/drivers/mtd/nand/bcm_umi_bch.c
deleted file mode 100644
index ce39c8705d62..000000000000
--- a/drivers/mtd/nand/bcm_umi_bch.c
+++ /dev/null
@@ -1,210 +0,0 @@
1/*****************************************************************************
2* Copyright 2004 - 2009 Broadcom Corporation. All rights reserved.
3*
4* Unless you and Broadcom execute a separate written software license
5* agreement governing use of this software, this software is licensed to you
6* under the terms of the GNU General Public License version 2, available at
7* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
8*
9* Notwithstanding the above, under no circumstances may you combine this
10* software in any way with any other Broadcom software provided under a
11* license other than the GPL, without Broadcom's express prior written
12* consent.
13*****************************************************************************/
14
15/* ---- Include Files ---------------------------------------------------- */
16#include "nand_bcm_umi.h"
17
18/* ---- External Variable Declarations ----------------------------------- */
19/* ---- External Function Prototypes ------------------------------------- */
20/* ---- Public Variables ------------------------------------------------- */
21/* ---- Private Constants and Types -------------------------------------- */
22
23/* ---- Private Function Prototypes -------------------------------------- */
24static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd,
25 struct nand_chip *chip, uint8_t *buf, int oob_required, int page);
26static int bcm_umi_bch_write_page_hwecc(struct mtd_info *mtd,
27 struct nand_chip *chip, const uint8_t *buf, int oob_required);
28
29/* ---- Private Variables ------------------------------------------------ */
30
31/*
32** nand_hw_eccoob
33** New oob placement block for use with hardware ecc generation.
34*/
35static struct nand_ecclayout nand_hw_eccoob_512 = {
36 /* Reserve 5 for BI indicator */
37 .oobfree = {
38#if (NAND_ECC_NUM_BYTES > 3)
39 {.offset = 0, .length = 2}
40#else
41 {.offset = 0, .length = 5},
42 {.offset = 6, .length = 7}
43#endif
44 }
45};
46
47/*
48** We treat the OOB for a 2K page as if it were 4 512 byte oobs,
49** except the BI is at byte 0.
50*/
51static struct nand_ecclayout nand_hw_eccoob_2048 = {
52 /* Reserve 0 as BI indicator */
53 .oobfree = {
54#if (NAND_ECC_NUM_BYTES > 10)
55 {.offset = 1, .length = 2},
56#elif (NAND_ECC_NUM_BYTES > 7)
57 {.offset = 1, .length = 5},
58 {.offset = 16, .length = 6},
59 {.offset = 32, .length = 6},
60 {.offset = 48, .length = 6}
61#else
62 {.offset = 1, .length = 8},
63 {.offset = 16, .length = 9},
64 {.offset = 32, .length = 9},
65 {.offset = 48, .length = 9}
66#endif
67 }
68};
69
70/* We treat the OOB for a 4K page as if it were 8 512 byte oobs,
71 * except the BI is at byte 0. */
72static struct nand_ecclayout nand_hw_eccoob_4096 = {
73 /* Reserve 0 as BI indicator */
74 .oobfree = {
75#if (NAND_ECC_NUM_BYTES > 10)
76 {.offset = 1, .length = 2},
77 {.offset = 16, .length = 3},
78 {.offset = 32, .length = 3},
79 {.offset = 48, .length = 3},
80 {.offset = 64, .length = 3},
81 {.offset = 80, .length = 3},
82 {.offset = 96, .length = 3},
83 {.offset = 112, .length = 3}
84#else
85 {.offset = 1, .length = 5},
86 {.offset = 16, .length = 6},
87 {.offset = 32, .length = 6},
88 {.offset = 48, .length = 6},
89 {.offset = 64, .length = 6},
90 {.offset = 80, .length = 6},
91 {.offset = 96, .length = 6},
92 {.offset = 112, .length = 6}
93#endif
94 }
95};
96
97/* ---- Private Functions ------------------------------------------------ */
98/* ==== Public Functions ================================================= */
99
100/****************************************************************************
101*
102* bcm_umi_bch_read_page_hwecc - hardware ecc based page read function
103* @mtd: mtd info structure
104* @chip: nand chip info structure
105* @buf: buffer to store read data
106* @oob_required: caller expects OOB data read to chip->oob_poi
107*
108***************************************************************************/
109static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd,
110 struct nand_chip *chip, uint8_t * buf,
111 int oob_required, int page)
112{
113 int sectorIdx = 0;
114 int eccsize = chip->ecc.size;
115 int eccsteps = chip->ecc.steps;
116 uint8_t *datap = buf;
117 uint8_t eccCalc[NAND_ECC_NUM_BYTES];
118 int sectorOobSize = mtd->oobsize / eccsteps;
119 int stat;
120 unsigned int max_bitflips = 0;
121
122 for (sectorIdx = 0; sectorIdx < eccsteps;
123 sectorIdx++, datap += eccsize) {
124 if (sectorIdx > 0) {
125 /* Seek to page location within sector */
126 chip->cmdfunc(mtd, NAND_CMD_RNDOUT, sectorIdx * eccsize,
127 -1);
128 }
129
130 /* Enable hardware ECC before reading the buf */
131 nand_bcm_umi_bch_enable_read_hwecc();
132
133 /* Read in data */
134 bcm_umi_nand_read_buf(mtd, datap, eccsize);
135
136 /* Pause hardware ECC after reading the buf */
137 nand_bcm_umi_bch_pause_read_ecc_calc();
138
139 /* Read the OOB ECC */
140 chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
141 mtd->writesize + sectorIdx * sectorOobSize, -1);
142 nand_bcm_umi_bch_read_oobEcc(mtd->writesize, eccCalc,
143 NAND_ECC_NUM_BYTES,
144 chip->oob_poi +
145 sectorIdx * sectorOobSize);
146
147 /* Correct any ECC detected errors */
148 stat =
149 nand_bcm_umi_bch_correct_page(datap, eccCalc,
150 NAND_ECC_NUM_BYTES);
151
152 /* Update Stats */
153 if (stat < 0) {
154#if defined(NAND_BCM_UMI_DEBUG)
155 printk(KERN_WARNING "%s uncorr_err sectorIdx=%d\n",
156 __func__, sectorIdx);
157 printk(KERN_WARNING "%s data %*ph\n",
158 __func__, 8, datap);
159 printk(KERN_WARNING "%s ecc %*ph\n",
160 __func__, 13, eccCalc);
161 BUG();
162#endif
163 mtd->ecc_stats.failed++;
164 } else {
165#if defined(NAND_BCM_UMI_DEBUG)
166 if (stat > 0) {
167 printk(KERN_INFO
168 "%s %d correctable_errors detected\n",
169 __func__, stat);
170 }
171#endif
172 mtd->ecc_stats.corrected += stat;
173 max_bitflips = max_t(unsigned int, max_bitflips, stat);
174 }
175 }
176 return max_bitflips;
177}
178
179/****************************************************************************
180*
181* bcm_umi_bch_write_page_hwecc - hardware ecc based page write function
182* @mtd: mtd info structure
183* @chip: nand chip info structure
184* @buf: data buffer
185* @oob_required: must write chip->oob_poi to OOB
186*
187***************************************************************************/
188static int bcm_umi_bch_write_page_hwecc(struct mtd_info *mtd,
189 struct nand_chip *chip, const uint8_t *buf, int oob_required)
190{
191 int sectorIdx = 0;
192 int eccsize = chip->ecc.size;
193 int eccsteps = chip->ecc.steps;
194 const uint8_t *datap = buf;
195 uint8_t *oobp = chip->oob_poi;
196 int sectorOobSize = mtd->oobsize / eccsteps;
197
198 for (sectorIdx = 0; sectorIdx < eccsteps;
199 sectorIdx++, datap += eccsize, oobp += sectorOobSize) {
200 /* Enable hardware ECC before writing the buf */
201 nand_bcm_umi_bch_enable_write_hwecc();
202 bcm_umi_nand_write_buf(mtd, datap, eccsize);
203 nand_bcm_umi_bch_write_oobEcc(mtd->writesize, oobp,
204 NAND_ECC_NUM_BYTES);
205 }
206
207 bcm_umi_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize);
208
209 return 0;
210}
diff --git a/drivers/mtd/nand/bcm_umi_nand.c b/drivers/mtd/nand/bcm_umi_nand.c
deleted file mode 100644
index 3fcbcbc7b082..000000000000
--- a/drivers/mtd/nand/bcm_umi_nand.c
+++ /dev/null
@@ -1,533 +0,0 @@
1/*****************************************************************************
2* Copyright 2004 - 2009 Broadcom Corporation. All rights reserved.
3*
4* Unless you and Broadcom execute a separate written software license
5* agreement governing use of this software, this software is licensed to you
6* under the terms of the GNU General Public License version 2, available at
7* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
8*
9* Notwithstanding the above, under no circumstances may you combine this
10* software in any way with any other Broadcom software provided under a
11* license other than the GPL, without Broadcom's express prior written
12* consent.
13*****************************************************************************/
14
15/* ---- Include Files ---------------------------------------------------- */
16#include <linux/module.h>
17#include <linux/types.h>
18#include <linux/init.h>
19#include <linux/kernel.h>
20#include <linux/slab.h>
21#include <linux/string.h>
22#include <linux/ioport.h>
23#include <linux/device.h>
24#include <linux/delay.h>
25#include <linux/err.h>
26#include <linux/io.h>
27#include <linux/platform_device.h>
28#include <linux/mtd/mtd.h>
29#include <linux/mtd/nand.h>
30#include <linux/mtd/nand_ecc.h>
31#include <linux/mtd/partitions.h>
32
33#include <asm/mach-types.h>
34
35#include <mach/reg_nand.h>
36#include <mach/reg_umi.h>
37
38#include "nand_bcm_umi.h"
39
40#include <mach/memory_settings.h>
41
42#define USE_DMA 1
43#include <mach/dma.h>
44#include <linux/dma-mapping.h>
45#include <linux/completion.h>
46
47/* ---- External Variable Declarations ----------------------------------- */
48/* ---- External Function Prototypes ------------------------------------- */
49/* ---- Public Variables ------------------------------------------------- */
50/* ---- Private Constants and Types -------------------------------------- */
51static const __devinitconst char gBanner[] = KERN_INFO \
52 "BCM UMI MTD NAND Driver: 1.00\n";
53
54#if NAND_ECC_BCH
55static uint8_t scan_ff_pattern[] = { 0xff };
56
57static struct nand_bbt_descr largepage_bbt = {
58 .options = 0,
59 .offs = 0,
60 .len = 1,
61 .pattern = scan_ff_pattern
62};
63#endif
64
65/*
66** Preallocate a buffer to avoid having to do this every dma operation.
67** This is the size of the preallocated coherent DMA buffer.
68*/
69#if USE_DMA
70#define DMA_MIN_BUFLEN 512
71#define DMA_MAX_BUFLEN PAGE_SIZE
72#define USE_DIRECT_IO(len) (((len) < DMA_MIN_BUFLEN) || \
73 ((len) > DMA_MAX_BUFLEN))
74
75/*
76 * The current NAND data space goes from 0x80001900 to 0x80001FFF,
77 * which is only 0x700 = 1792 bytes long. This is too small for 2K, 4K page
78 * size NAND flash. Need to break the DMA down to multiple 1Ks.
79 *
80 * Need to make sure REG_NAND_DATA_PADDR + DMA_MAX_LEN < 0x80002000
81 */
82#define DMA_MAX_LEN 1024
83
84#else /* !USE_DMA */
85#define DMA_MIN_BUFLEN 0
86#define DMA_MAX_BUFLEN 0
87#define USE_DIRECT_IO(len) 1
88#endif
89/* ---- Private Function Prototypes -------------------------------------- */
90static void bcm_umi_nand_read_buf(struct mtd_info *mtd, u_char * buf, int len);
91static void bcm_umi_nand_write_buf(struct mtd_info *mtd, const u_char * buf,
92 int len);
93
94/* ---- Private Variables ------------------------------------------------ */
95static struct mtd_info *board_mtd;
96static void __iomem *bcm_umi_io_base;
97static void *virtPtr;
98static dma_addr_t physPtr;
99static struct completion nand_comp;
100
101/* ---- Private Functions ------------------------------------------------ */
102#if NAND_ECC_BCH
103#include "bcm_umi_bch.c"
104#else
105#include "bcm_umi_hamming.c"
106#endif
107
108#if USE_DMA
109
110/* Handler called when the DMA finishes. */
111static void nand_dma_handler(DMA_Device_t dev, int reason, void *userData)
112{
113 complete(&nand_comp);
114}
115
116static int nand_dma_init(void)
117{
118 int rc;
119
120 rc = dma_set_device_handler(DMA_DEVICE_NAND_MEM_TO_MEM,
121 nand_dma_handler, NULL);
122 if (rc != 0) {
123 printk(KERN_ERR "dma_set_device_handler failed: %d\n", rc);
124 return rc;
125 }
126
127 virtPtr =
128 dma_alloc_coherent(NULL, DMA_MAX_BUFLEN, &physPtr, GFP_KERNEL);
129 if (virtPtr == NULL) {
130 printk(KERN_ERR "NAND - Failed to allocate memory for DMA buffer\n");
131 return -ENOMEM;
132 }
133
134 return 0;
135}
136
137static void nand_dma_term(void)
138{
139 if (virtPtr != NULL)
140 dma_free_coherent(NULL, DMA_MAX_BUFLEN, virtPtr, physPtr);
141}
142
143static void nand_dma_read(void *buf, int len)
144{
145 int offset = 0;
146 int tmp_len = 0;
147 int len_left = len;
148 DMA_Handle_t hndl;
149
150 if (virtPtr == NULL)
151 panic("nand_dma_read: virtPtr == NULL\n");
152
153 if ((void *)physPtr == NULL)
154 panic("nand_dma_read: physPtr == NULL\n");
155
156 hndl = dma_request_channel(DMA_DEVICE_NAND_MEM_TO_MEM);
157 if (hndl < 0) {
158 printk(KERN_ERR
159 "nand_dma_read: unable to allocate dma channel: %d\n",
160 (int)hndl);
161 panic("\n");
162 }
163
164 while (len_left > 0) {
165 if (len_left > DMA_MAX_LEN) {
166 tmp_len = DMA_MAX_LEN;
167 len_left -= DMA_MAX_LEN;
168 } else {
169 tmp_len = len_left;
170 len_left = 0;
171 }
172
173 init_completion(&nand_comp);
174 dma_transfer_mem_to_mem(hndl, REG_NAND_DATA_PADDR,
175 physPtr + offset, tmp_len);
176 wait_for_completion(&nand_comp);
177
178 offset += tmp_len;
179 }
180
181 dma_free_channel(hndl);
182
183 if (buf != NULL)
184 memcpy(buf, virtPtr, len);
185}
186
187static void nand_dma_write(const void *buf, int len)
188{
189 int offset = 0;
190 int tmp_len = 0;
191 int len_left = len;
192 DMA_Handle_t hndl;
193
194 if (buf == NULL)
195 panic("nand_dma_write: buf == NULL\n");
196
197 if (virtPtr == NULL)
198 panic("nand_dma_write: virtPtr == NULL\n");
199
200 if ((void *)physPtr == NULL)
201 panic("nand_dma_write: physPtr == NULL\n");
202
203 memcpy(virtPtr, buf, len);
204
205
206 hndl = dma_request_channel(DMA_DEVICE_NAND_MEM_TO_MEM);
207 if (hndl < 0) {
208 printk(KERN_ERR
209 "nand_dma_write: unable to allocate dma channel: %d\n",
210 (int)hndl);
211 panic("\n");
212 }
213
214 while (len_left > 0) {
215 if (len_left > DMA_MAX_LEN) {
216 tmp_len = DMA_MAX_LEN;
217 len_left -= DMA_MAX_LEN;
218 } else {
219 tmp_len = len_left;
220 len_left = 0;
221 }
222
223 init_completion(&nand_comp);
224 dma_transfer_mem_to_mem(hndl, physPtr + offset,
225 REG_NAND_DATA_PADDR, tmp_len);
226 wait_for_completion(&nand_comp);
227
228 offset += tmp_len;
229 }
230
231 dma_free_channel(hndl);
232}
233
234#endif
235
236static int nand_dev_ready(struct mtd_info *mtd)
237{
238 return nand_bcm_umi_dev_ready();
239}
240
241/****************************************************************************
242*
243* bcm_umi_nand_inithw
244*
245* This routine does the necessary hardware (board-specific)
246* initializations. This includes setting up the timings, etc.
247*
248***************************************************************************/
249int bcm_umi_nand_inithw(void)
250{
251 /* Configure nand timing parameters */
252 REG_UMI_NAND_TCR &= ~0x7ffff;
253 REG_UMI_NAND_TCR |= HW_CFG_NAND_TCR;
254
255#if !defined(CONFIG_MTD_NAND_BCM_UMI_HWCS)
256 /* enable software control of CS */
257 REG_UMI_NAND_TCR |= REG_UMI_NAND_TCR_CS_SWCTRL;
258#endif
259
260 /* keep NAND chip select asserted */
261 REG_UMI_NAND_RCSR |= REG_UMI_NAND_RCSR_CS_ASSERTED;
262
263 REG_UMI_NAND_TCR &= ~REG_UMI_NAND_TCR_WORD16;
264 /* enable writes to flash */
265 REG_UMI_MMD_ICR |= REG_UMI_MMD_ICR_FLASH_WP;
266
267 writel(NAND_CMD_RESET, bcm_umi_io_base + REG_NAND_CMD_OFFSET);
268 nand_bcm_umi_wait_till_ready();
269
270#if NAND_ECC_BCH
271 nand_bcm_umi_bch_config_ecc(NAND_ECC_NUM_BYTES);
272#endif
273
274 return 0;
275}
276
277/* Used to turn latch the proper register for access. */
278static void bcm_umi_nand_hwcontrol(struct mtd_info *mtd, int cmd,
279 unsigned int ctrl)
280{
281 /* send command to hardware */
282 struct nand_chip *chip = mtd->priv;
283 if (ctrl & NAND_CTRL_CHANGE) {
284 if (ctrl & NAND_CLE) {
285 chip->IO_ADDR_W = bcm_umi_io_base + REG_NAND_CMD_OFFSET;
286 goto CMD;
287 }
288 if (ctrl & NAND_ALE) {
289 chip->IO_ADDR_W =
290 bcm_umi_io_base + REG_NAND_ADDR_OFFSET;
291 goto CMD;
292 }
293 chip->IO_ADDR_W = bcm_umi_io_base + REG_NAND_DATA8_OFFSET;
294 }
295
296CMD:
297 /* Send command to chip directly */
298 if (cmd != NAND_CMD_NONE)
299 writeb(cmd, chip->IO_ADDR_W);
300}
301
302static void bcm_umi_nand_write_buf(struct mtd_info *mtd, const u_char * buf,
303 int len)
304{
305 if (USE_DIRECT_IO(len)) {
306 /* Do it the old way if the buffer is small or too large.
307 * Probably quicker than starting and checking dma. */
308 int i;
309 struct nand_chip *this = mtd->priv;
310
311 for (i = 0; i < len; i++)
312 writeb(buf[i], this->IO_ADDR_W);
313 }
314#if USE_DMA
315 else
316 nand_dma_write(buf, len);
317#endif
318}
319
320static void bcm_umi_nand_read_buf(struct mtd_info *mtd, u_char * buf, int len)
321{
322 if (USE_DIRECT_IO(len)) {
323 int i;
324 struct nand_chip *this = mtd->priv;
325
326 for (i = 0; i < len; i++)
327 buf[i] = readb(this->IO_ADDR_R);
328 }
329#if USE_DMA
330 else
331 nand_dma_read(buf, len);
332#endif
333}
334
335static int __devinit bcm_umi_nand_probe(struct platform_device *pdev)
336{
337 struct nand_chip *this;
338 struct resource *r;
339 int err = 0;
340
341 printk(gBanner);
342
343 /* Allocate memory for MTD device structure and private data */
344 board_mtd =
345 kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip),
346 GFP_KERNEL);
347 if (!board_mtd) {
348 printk(KERN_WARNING
349 "Unable to allocate NAND MTD device structure.\n");
350 return -ENOMEM;
351 }
352
353 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
354
355 if (!r) {
356 err = -ENXIO;
357 goto out_free;
358 }
359
360 /* map physical address */
361 bcm_umi_io_base = ioremap(r->start, resource_size(r));
362
363 if (!bcm_umi_io_base) {
364 printk(KERN_ERR "ioremap to access BCM UMI NAND chip failed\n");
365 err = -EIO;
366 goto out_free;
367 }
368
369 /* Get pointer to private data */
370 this = (struct nand_chip *)(&board_mtd[1]);
371
372 /* Initialize structures */
373 memset((char *)board_mtd, 0, sizeof(struct mtd_info));
374 memset((char *)this, 0, sizeof(struct nand_chip));
375
376 /* Link the private data with the MTD structure */
377 board_mtd->priv = this;
378
379 /* Initialize the NAND hardware. */
380 if (bcm_umi_nand_inithw() < 0) {
381 printk(KERN_ERR "BCM UMI NAND chip could not be initialized\n");
382 err = -EIO;
383 goto out_unmap;
384 }
385
386 /* Set address of NAND IO lines */
387 this->IO_ADDR_W = bcm_umi_io_base + REG_NAND_DATA8_OFFSET;
388 this->IO_ADDR_R = bcm_umi_io_base + REG_NAND_DATA8_OFFSET;
389
390 /* Set command delay time, see datasheet for correct value */
391 this->chip_delay = 0;
392 /* Assign the device ready function, if available */
393 this->dev_ready = nand_dev_ready;
394 this->options = 0;
395
396 this->write_buf = bcm_umi_nand_write_buf;
397 this->read_buf = bcm_umi_nand_read_buf;
398
399 this->cmd_ctrl = bcm_umi_nand_hwcontrol;
400 this->ecc.mode = NAND_ECC_HW;
401 this->ecc.size = 512;
402 this->ecc.bytes = NAND_ECC_NUM_BYTES;
403#if NAND_ECC_BCH
404 this->ecc.read_page = bcm_umi_bch_read_page_hwecc;
405 this->ecc.write_page = bcm_umi_bch_write_page_hwecc;
406#else
407 this->ecc.correct = nand_correct_data512;
408 this->ecc.calculate = bcm_umi_hamming_get_hw_ecc;
409 this->ecc.hwctl = bcm_umi_hamming_enable_hwecc;
410#endif
411
412#if USE_DMA
413 err = nand_dma_init();
414 if (err != 0)
415 goto out_unmap;
416#endif
417
418 /* Figure out the size of the device that we have.
419 * We need to do this to figure out which ECC
420 * layout we'll be using.
421 */
422
423 err = nand_scan_ident(board_mtd, 1, NULL);
424 if (err) {
425 printk(KERN_ERR "nand_scan failed: %d\n", err);
426 goto out_unmap;
427 }
428
429 /* Now that we know the nand size, we can setup the ECC layout */
430
431 switch (board_mtd->writesize) { /* writesize is the pagesize */
432 case 4096:
433 this->ecc.layout = &nand_hw_eccoob_4096;
434 break;
435 case 2048:
436 this->ecc.layout = &nand_hw_eccoob_2048;
437 break;
438 case 512:
439 this->ecc.layout = &nand_hw_eccoob_512;
440 break;
441 default:
442 {
443 printk(KERN_ERR "NAND - Unrecognized pagesize: %d\n",
444 board_mtd->writesize);
445 err = -EINVAL;
446 goto out_unmap;
447 }
448 }
449
450#if NAND_ECC_BCH
451 if (board_mtd->writesize > 512) {
452 if (this->bbt_options & NAND_BBT_USE_FLASH)
453 largepage_bbt.options = NAND_BBT_SCAN2NDPAGE;
454 this->badblock_pattern = &largepage_bbt;
455 }
456
457 this->ecc.strength = 8;
458
459#endif
460
461 /* Now finish off the scan, now that ecc.layout has been initialized. */
462
463 err = nand_scan_tail(board_mtd);
464 if (err) {
465 printk(KERN_ERR "nand_scan failed: %d\n", err);
466 goto out_unmap;
467 }
468
469 /* Register the partitions */
470 board_mtd->name = "bcm_umi-nand";
471 mtd_device_parse_register(board_mtd, NULL, NULL, NULL, 0);
472
473 /* Return happy */
474 return 0;
475out_unmap:
476 iounmap(bcm_umi_io_base);
477out_free:
478 kfree(board_mtd);
479 return err;
480}
481
482static int bcm_umi_nand_remove(struct platform_device *pdev)
483{
484#if USE_DMA
485 nand_dma_term();
486#endif
487
488 /* Release resources, unregister device */
489 nand_release(board_mtd);
490
491 /* unmap physical address */
492 iounmap(bcm_umi_io_base);
493
494 /* Free the MTD device structure */
495 kfree(board_mtd);
496
497 return 0;
498}
499
500#ifdef CONFIG_PM
501static int bcm_umi_nand_suspend(struct platform_device *pdev,
502 pm_message_t state)
503{
504 printk(KERN_ERR "MTD NAND suspend is being called\n");
505 return 0;
506}
507
508static int bcm_umi_nand_resume(struct platform_device *pdev)
509{
510 printk(KERN_ERR "MTD NAND resume is being called\n");
511 return 0;
512}
513#else
514#define bcm_umi_nand_suspend NULL
515#define bcm_umi_nand_resume NULL
516#endif
517
518static struct platform_driver nand_driver = {
519 .driver = {
520 .name = "bcm-nand",
521 .owner = THIS_MODULE,
522 },
523 .probe = bcm_umi_nand_probe,
524 .remove = bcm_umi_nand_remove,
525 .suspend = bcm_umi_nand_suspend,
526 .resume = bcm_umi_nand_resume,
527};
528
529module_platform_driver(nand_driver);
530
531MODULE_LICENSE("GPL");
532MODULE_AUTHOR("Broadcom");
533MODULE_DESCRIPTION("BCM UMI MTD NAND driver");
diff --git a/drivers/mtd/nand/nand_bcm_umi.c b/drivers/mtd/nand/nand_bcm_umi.c
deleted file mode 100644
index 46a6bc9c4b74..000000000000
--- a/drivers/mtd/nand/nand_bcm_umi.c
+++ /dev/null
@@ -1,149 +0,0 @@
1/*****************************************************************************
2* Copyright 2004 - 2009 Broadcom Corporation. All rights reserved.
3*
4* Unless you and Broadcom execute a separate written software license
5* agreement governing use of this software, this software is licensed to you
6* under the terms of the GNU General Public License version 2, available at
7* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
8*
9* Notwithstanding the above, under no circumstances may you combine this
10* software in any way with any other Broadcom software provided under a
11* license other than the GPL, without Broadcom's express prior written
12* consent.
13*****************************************************************************/
14
15/* ---- Include Files ---------------------------------------------------- */
16#include <mach/reg_umi.h>
17#include "nand_bcm_umi.h"
18#ifdef BOOT0_BUILD
19#include <uart.h>
20#endif
21
22/* ---- External Variable Declarations ----------------------------------- */
23/* ---- External Function Prototypes ------------------------------------- */
24/* ---- Public Variables ------------------------------------------------- */
25/* ---- Private Constants and Types -------------------------------------- */
26/* ---- Private Function Prototypes -------------------------------------- */
27/* ---- Private Variables ------------------------------------------------ */
28/* ---- Private Functions ------------------------------------------------ */
29
30#if NAND_ECC_BCH
31/****************************************************************************
32* nand_bch_ecc_flip_bit - Routine to flip an errored bit
33*
34* PURPOSE:
35* This is a helper routine that flips the bit (0 -> 1 or 1 -> 0) of the
36* errored bit specified
37*
38* PARAMETERS:
39* datap - Container that holds the 512 byte data
40* errorLocation - Location of the bit that needs to be flipped
41*
42* RETURNS:
43* None
44****************************************************************************/
45static void nand_bcm_umi_bch_ecc_flip_bit(uint8_t *datap, int errorLocation)
46{
47 int locWithinAByte = (errorLocation & REG_UMI_BCH_ERR_LOC_BYTE) >> 0;
48 int locWithinAWord = (errorLocation & REG_UMI_BCH_ERR_LOC_WORD) >> 3;
49 int locWithinAPage = (errorLocation & REG_UMI_BCH_ERR_LOC_PAGE) >> 5;
50
51 uint8_t errorByte = 0;
52 uint8_t byteMask = 1 << locWithinAByte;
53
54 /* BCH uses big endian, need to change the location
55 * bits to little endian */
56 locWithinAWord = 3 - locWithinAWord;
57
58 errorByte = datap[locWithinAPage * sizeof(uint32_t) + locWithinAWord];
59
60#ifdef BOOT0_BUILD
61 puthexs("\nECC Correct Offset: ",
62 locWithinAPage * sizeof(uint32_t) + locWithinAWord);
63 puthexs(" errorByte:", errorByte);
64 puthex8(" Bit: ", locWithinAByte);
65#endif
66
67 if (errorByte & byteMask) {
68 /* bit needs to be cleared */
69 errorByte &= ~byteMask;
70 } else {
71 /* bit needs to be set */
72 errorByte |= byteMask;
73 }
74
75 /* write back the value with the fixed bit */
76 datap[locWithinAPage * sizeof(uint32_t) + locWithinAWord] = errorByte;
77}
78
79/****************************************************************************
80* nand_correct_page_bch - Routine to correct bit errors when reading NAND
81*
82* PURPOSE:
83* This routine reads the BCH registers to determine if there are any bit
84* errors during the read of the last 512 bytes of data + ECC bytes. If
85* errors exists, the routine fixes it.
86*
87* PARAMETERS:
88* datap - Container that holds the 512 byte data
89*
90* RETURNS:
91* 0 or greater = Number of errors corrected
92* (No errors are found or errors have been fixed)
93* -1 = Error(s) cannot be fixed
94****************************************************************************/
95int nand_bcm_umi_bch_correct_page(uint8_t *datap, uint8_t *readEccData,
96 int numEccBytes)
97{
98 int numErrors;
99 int errorLocation;
100 int idx;
101 uint32_t regValue;
102
103 /* wait for read ECC to be valid */
104 regValue = nand_bcm_umi_bch_poll_read_ecc_calc();
105
106 /*
107 * read the control status register to determine if there
108 * are error'ed bits
109 * see if errors are correctible
110 */
111 if ((regValue & REG_UMI_BCH_CTRL_STATUS_UNCORR_ERR) > 0) {
112 int i;
113
114 for (i = 0; i < numEccBytes; i++) {
115 if (readEccData[i] != 0xff) {
116 /* errors cannot be fixed, return -1 */
117 return -1;
118 }
119 }
120 /* If ECC is unprogrammed then we can't correct,
121 * assume everything OK */
122 return 0;
123 }
124
125 if ((regValue & REG_UMI_BCH_CTRL_STATUS_CORR_ERR) == 0) {
126 /* no errors */
127 return 0;
128 }
129
130 /*
131 * Fix errored bits by doing the following:
132 * 1. Read the number of errors in the control and status register
133 * 2. Read the error location registers that corresponds to the number
134 * of errors reported
135 * 3. Invert the bit in the data
136 */
137 numErrors = (regValue & REG_UMI_BCH_CTRL_STATUS_NB_CORR_ERROR) >> 20;
138
139 for (idx = 0; idx < numErrors; idx++) {
140 errorLocation =
141 REG_UMI_BCH_ERR_LOC_ADDR(idx) & REG_UMI_BCH_ERR_LOC_MASK;
142
143 /* Flip bit */
144 nand_bcm_umi_bch_ecc_flip_bit(datap, errorLocation);
145 }
146 /* Errors corrected */
147 return numErrors;
148}
149#endif
diff --git a/drivers/mtd/nand/nand_bcm_umi.h b/drivers/mtd/nand/nand_bcm_umi.h
deleted file mode 100644
index 198b304d6f72..000000000000
--- a/drivers/mtd/nand/nand_bcm_umi.h
+++ /dev/null
@@ -1,337 +0,0 @@
1/*****************************************************************************
2* Copyright 2003 - 2009 Broadcom Corporation. All rights reserved.
3*
4* Unless you and Broadcom execute a separate written software license
5* agreement governing use of this software, this software is licensed to you
6* under the terms of the GNU General Public License version 2, available at
7* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
8*
9* Notwithstanding the above, under no circumstances may you combine this
10* software in any way with any other Broadcom software provided under a
11* license other than the GPL, without Broadcom's express prior written
12* consent.
13*****************************************************************************/
14#ifndef NAND_BCM_UMI_H
15#define NAND_BCM_UMI_H
16
17/* ---- Include Files ---------------------------------------------------- */
18#include <mach/reg_umi.h>
19#include <mach/reg_nand.h>
20#include <cfg_global.h>
21
22/* ---- Constants and Types ---------------------------------------------- */
23#if (CFG_GLOBAL_CHIP_FAMILY == CFG_GLOBAL_CHIP_FAMILY_BCMRING)
24#define NAND_ECC_BCH (CFG_GLOBAL_CHIP_REV > 0xA0)
25#else
26#define NAND_ECC_BCH 0
27#endif
28
29#define CFG_GLOBAL_NAND_ECC_BCH_NUM_BYTES 13
30
31#if NAND_ECC_BCH
32#ifdef BOOT0_BUILD
33#define NAND_ECC_NUM_BYTES 13
34#else
35#define NAND_ECC_NUM_BYTES CFG_GLOBAL_NAND_ECC_BCH_NUM_BYTES
36#endif
37#else
38#define NAND_ECC_NUM_BYTES 3
39#endif
40
41#define NAND_DATA_ACCESS_SIZE 512
42
43/* ---- Variable Externs ------------------------------------------ */
44/* ---- Function Prototypes --------------------------------------- */
45int nand_bcm_umi_bch_correct_page(uint8_t *datap, uint8_t *readEccData,
46 int numEccBytes);
47
48/* Check in device is ready */
49static inline int nand_bcm_umi_dev_ready(void)
50{
51 return REG_UMI_NAND_RCSR & REG_UMI_NAND_RCSR_RDY;
52}
53
54/* Wait until device is ready */
55static inline void nand_bcm_umi_wait_till_ready(void)
56{
57 while (nand_bcm_umi_dev_ready() == 0)
58 ;
59}
60
61/* Enable Hamming ECC */
62static inline void nand_bcm_umi_hamming_enable_hwecc(void)
63{
64 /* disable and reset ECC, 512 byte page */
65 REG_UMI_NAND_ECC_CSR &= ~(REG_UMI_NAND_ECC_CSR_ECC_ENABLE |
66 REG_UMI_NAND_ECC_CSR_256BYTE);
67 /* enable ECC */
68 REG_UMI_NAND_ECC_CSR |= REG_UMI_NAND_ECC_CSR_ECC_ENABLE;
69}
70
71#if NAND_ECC_BCH
72/* BCH ECC specifics */
73#define ECC_BITS_PER_CORRECTABLE_BIT 13
74
75/* Enable BCH Read ECC */
76static inline void nand_bcm_umi_bch_enable_read_hwecc(void)
77{
78 /* disable and reset ECC */
79 REG_UMI_BCH_CTRL_STATUS = REG_UMI_BCH_CTRL_STATUS_RD_ECC_VALID;
80 /* Turn on ECC */
81 REG_UMI_BCH_CTRL_STATUS = REG_UMI_BCH_CTRL_STATUS_ECC_RD_EN;
82}
83
84/* Enable BCH Write ECC */
85static inline void nand_bcm_umi_bch_enable_write_hwecc(void)
86{
87 /* disable and reset ECC */
88 REG_UMI_BCH_CTRL_STATUS = REG_UMI_BCH_CTRL_STATUS_WR_ECC_VALID;
89 /* Turn on ECC */
90 REG_UMI_BCH_CTRL_STATUS = REG_UMI_BCH_CTRL_STATUS_ECC_WR_EN;
91}
92
93/* Config number of BCH ECC bytes */
94static inline void nand_bcm_umi_bch_config_ecc(uint8_t numEccBytes)
95{
96 uint32_t nValue;
97 uint32_t tValue;
98 uint32_t kValue;
99 uint32_t numBits = numEccBytes * 8;
100
101 /* disable and reset ECC */
102 REG_UMI_BCH_CTRL_STATUS =
103 REG_UMI_BCH_CTRL_STATUS_WR_ECC_VALID |
104 REG_UMI_BCH_CTRL_STATUS_RD_ECC_VALID;
105
106 /* Every correctible bit requires 13 ECC bits */
107 tValue = (uint32_t) (numBits / ECC_BITS_PER_CORRECTABLE_BIT);
108
109 /* Total data in number of bits for generating and computing BCH ECC */
110 nValue = (NAND_DATA_ACCESS_SIZE + numEccBytes) * 8;
111
112 /* K parameter is used internally. K = N - (T * 13) */
113 kValue = nValue - (tValue * ECC_BITS_PER_CORRECTABLE_BIT);
114
115 /* Write the settings */
116 REG_UMI_BCH_N = nValue;
117 REG_UMI_BCH_T = tValue;
118 REG_UMI_BCH_K = kValue;
119}
120
121/* Pause during ECC read calculation to skip bytes in OOB */
122static inline void nand_bcm_umi_bch_pause_read_ecc_calc(void)
123{
124 REG_UMI_BCH_CTRL_STATUS =
125 REG_UMI_BCH_CTRL_STATUS_ECC_RD_EN |
126 REG_UMI_BCH_CTRL_STATUS_PAUSE_ECC_DEC;
127}
128
129/* Resume during ECC read calculation after skipping bytes in OOB */
130static inline void nand_bcm_umi_bch_resume_read_ecc_calc(void)
131{
132 REG_UMI_BCH_CTRL_STATUS = REG_UMI_BCH_CTRL_STATUS_ECC_RD_EN;
133}
134
135/* Poll read ECC calc to check when hardware completes */
136static inline uint32_t nand_bcm_umi_bch_poll_read_ecc_calc(void)
137{
138 uint32_t regVal;
139
140 do {
141 /* wait for ECC to be valid */
142 regVal = REG_UMI_BCH_CTRL_STATUS;
143 } while ((regVal & REG_UMI_BCH_CTRL_STATUS_RD_ECC_VALID) == 0);
144
145 return regVal;
146}
147
148/* Poll write ECC calc to check when hardware completes */
149static inline void nand_bcm_umi_bch_poll_write_ecc_calc(void)
150{
151 /* wait for ECC to be valid */
152 while ((REG_UMI_BCH_CTRL_STATUS & REG_UMI_BCH_CTRL_STATUS_WR_ECC_VALID)
153 == 0)
154 ;
155}
156
157/* Read the OOB and ECC, for kernel write OOB to a buffer */
158#if defined(__KERNEL__) && !defined(STANDALONE)
159static inline void nand_bcm_umi_bch_read_oobEcc(uint32_t pageSize,
160 uint8_t *eccCalc, int numEccBytes, uint8_t *oobp)
161#else
162static inline void nand_bcm_umi_bch_read_oobEcc(uint32_t pageSize,
163 uint8_t *eccCalc, int numEccBytes)
164#endif
165{
166 int eccPos = 0;
167 int numToRead = 16; /* There are 16 bytes per sector in the OOB */
168
169 /* ECC is already paused when this function is called */
170 if (pageSize != NAND_DATA_ACCESS_SIZE) {
171 /* skip BI */
172#if defined(__KERNEL__) && !defined(STANDALONE)
173 *oobp++ = REG_NAND_DATA8;
174#else
175 REG_NAND_DATA8;
176#endif
177 numToRead--;
178 }
179
180 while (numToRead > numEccBytes) {
181 /* skip free oob region */
182#if defined(__KERNEL__) && !defined(STANDALONE)
183 *oobp++ = REG_NAND_DATA8;
184#else
185 REG_NAND_DATA8;
186#endif
187 numToRead--;
188 }
189
190 if (pageSize == NAND_DATA_ACCESS_SIZE) {
191 /* read ECC bytes before BI */
192 nand_bcm_umi_bch_resume_read_ecc_calc();
193
194 while (numToRead > 11) {
195#if defined(__KERNEL__) && !defined(STANDALONE)
196 *oobp = REG_NAND_DATA8;
197 eccCalc[eccPos++] = *oobp;
198 oobp++;
199#else
200 eccCalc[eccPos++] = REG_NAND_DATA8;
201#endif
202 numToRead--;
203 }
204
205 nand_bcm_umi_bch_pause_read_ecc_calc();
206
207 if (numToRead == 11) {
208 /* read BI */
209#if defined(__KERNEL__) && !defined(STANDALONE)
210 *oobp++ = REG_NAND_DATA8;
211#else
212 REG_NAND_DATA8;
213#endif
214 numToRead--;
215 }
216
217 }
218 /* read ECC bytes */
219 nand_bcm_umi_bch_resume_read_ecc_calc();
220 while (numToRead) {
221#if defined(__KERNEL__) && !defined(STANDALONE)
222 *oobp = REG_NAND_DATA8;
223 eccCalc[eccPos++] = *oobp;
224 oobp++;
225#else
226 eccCalc[eccPos++] = REG_NAND_DATA8;
227#endif
228 numToRead--;
229 }
230}
231
232/* Helper function to write ECC */
233static inline void NAND_BCM_UMI_ECC_WRITE(int numEccBytes, int eccBytePos,
234 uint8_t *oobp, uint8_t eccVal)
235{
236 if (eccBytePos <= numEccBytes)
237 *oobp = eccVal;
238}
239
240/* Write OOB with ECC */
241static inline void nand_bcm_umi_bch_write_oobEcc(uint32_t pageSize,
242 uint8_t *oobp, int numEccBytes)
243{
244 uint32_t eccVal = 0xffffffff;
245
246 /* wait for write ECC to be valid */
247 nand_bcm_umi_bch_poll_write_ecc_calc();
248
249 /*
250 ** Get the hardware ecc from the 32-bit result registers.
251 ** Read after 512 byte accesses. Format B3B2B1B0
252 ** where B3 = ecc3, etc.
253 */
254
255 if (pageSize == NAND_DATA_ACCESS_SIZE) {
256 /* Now fill in the ECC bytes */
257 if (numEccBytes >= 13)
258 eccVal = REG_UMI_BCH_WR_ECC_3;
259
260 /* Usually we skip CM in oob[0,1] */
261 NAND_BCM_UMI_ECC_WRITE(numEccBytes, 15, &oobp[0],
262 (eccVal >> 16) & 0xff);
263 NAND_BCM_UMI_ECC_WRITE(numEccBytes, 14, &oobp[1],
264 (eccVal >> 8) & 0xff);
265
266 /* Write ECC in oob[2,3,4] */
267 NAND_BCM_UMI_ECC_WRITE(numEccBytes, 13, &oobp[2],
268 eccVal & 0xff); /* ECC 12 */
269
270 if (numEccBytes >= 9)
271 eccVal = REG_UMI_BCH_WR_ECC_2;
272
273 NAND_BCM_UMI_ECC_WRITE(numEccBytes, 12, &oobp[3],
274 (eccVal >> 24) & 0xff); /* ECC11 */
275 NAND_BCM_UMI_ECC_WRITE(numEccBytes, 11, &oobp[4],
276 (eccVal >> 16) & 0xff); /* ECC10 */
277
278 /* Always Skip BI in oob[5] */
279 } else {
280 /* Always Skip BI in oob[0] */
281
282 /* Now fill in the ECC bytes */
283 if (numEccBytes >= 13)
284 eccVal = REG_UMI_BCH_WR_ECC_3;
285
286 /* Usually skip CM in oob[1,2] */
287 NAND_BCM_UMI_ECC_WRITE(numEccBytes, 15, &oobp[1],
288 (eccVal >> 16) & 0xff);
289 NAND_BCM_UMI_ECC_WRITE(numEccBytes, 14, &oobp[2],
290 (eccVal >> 8) & 0xff);
291
292 /* Write ECC in oob[3-15] */
293 NAND_BCM_UMI_ECC_WRITE(numEccBytes, 13, &oobp[3],
294 eccVal & 0xff); /* ECC12 */
295
296 if (numEccBytes >= 9)
297 eccVal = REG_UMI_BCH_WR_ECC_2;
298
299 NAND_BCM_UMI_ECC_WRITE(numEccBytes, 12, &oobp[4],
300 (eccVal >> 24) & 0xff); /* ECC11 */
301 NAND_BCM_UMI_ECC_WRITE(numEccBytes, 11, &oobp[5],
302 (eccVal >> 16) & 0xff); /* ECC10 */
303 }
304
305 /* Fill in the remainder of ECC locations */
306 NAND_BCM_UMI_ECC_WRITE(numEccBytes, 10, &oobp[6],
307 (eccVal >> 8) & 0xff); /* ECC9 */
308 NAND_BCM_UMI_ECC_WRITE(numEccBytes, 9, &oobp[7],
309 eccVal & 0xff); /* ECC8 */
310
311 if (numEccBytes >= 5)
312 eccVal = REG_UMI_BCH_WR_ECC_1;
313
314 NAND_BCM_UMI_ECC_WRITE(numEccBytes, 8, &oobp[8],
315 (eccVal >> 24) & 0xff); /* ECC7 */
316 NAND_BCM_UMI_ECC_WRITE(numEccBytes, 7, &oobp[9],
317 (eccVal >> 16) & 0xff); /* ECC6 */
318 NAND_BCM_UMI_ECC_WRITE(numEccBytes, 6, &oobp[10],
319 (eccVal >> 8) & 0xff); /* ECC5 */
320 NAND_BCM_UMI_ECC_WRITE(numEccBytes, 5, &oobp[11],
321 eccVal & 0xff); /* ECC4 */
322
323 if (numEccBytes >= 1)
324 eccVal = REG_UMI_BCH_WR_ECC_0;
325
326 NAND_BCM_UMI_ECC_WRITE(numEccBytes, 4, &oobp[12],
327 (eccVal >> 24) & 0xff); /* ECC3 */
328 NAND_BCM_UMI_ECC_WRITE(numEccBytes, 3, &oobp[13],
329 (eccVal >> 16) & 0xff); /* ECC2 */
330 NAND_BCM_UMI_ECC_WRITE(numEccBytes, 2, &oobp[14],
331 (eccVal >> 8) & 0xff); /* ECC1 */
332 NAND_BCM_UMI_ECC_WRITE(numEccBytes, 1, &oobp[15],
333 eccVal & 0xff); /* ECC0 */
334}
335#endif
336
337#endif /* NAND_BCM_UMI_H */