3 * Marvell Semiconductor <www.marvell.com>
4 * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
6 * See file CREDITS for list of people who contributed to this
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
27 #include <asm/arch/kirkwood.h>
29 #include <linux/mtd/nand_ecc.h>
30 #include <linux/mtd/nand_bch.h>
32 #ifndef CONFIG_NAND_ECC_ALGO
33 #define CONFIG_NAND_ECC_ALGO NAND_ECC_SOFT
36 /* NAND Flash Soc registers */
37 struct kwnandf_registers {
38 u32 rd_params; /* 0x10418 */
39 u32 wr_param; /* 0x1041c */
40 u8 pad[0x10470 - 0x1041c - 4];
41 u32 ctrl; /* 0x10470 */
44 static struct kwnandf_registers *nf_reg =
45 (struct kwnandf_registers *)KW_NANDF_BASE;
48 * hardware specific access to control-lines/bits
50 #define NAND_ACTCEBOOT_BIT 0x02
52 static void kw_nand_hwcontrol(struct mtd_info *mtd, int cmd,
55 struct nand_chip *nc = mtd->priv;
58 if (cmd == NAND_CMD_NONE)
62 offs = (1 << 0); /* Commands with A[1:0] == 01 */
63 else if (ctrl & NAND_ALE)
64 offs = (1 << 1); /* Addresses with A[1:0] == 10 */
68 writeb(cmd, nc->IO_ADDR_W + offs);
71 void kw_nand_select_chip(struct mtd_info *mtd, int chip)
75 data = readl(&nf_reg->ctrl);
76 data |= NAND_ACTCEBOOT_BIT;
77 writel(data, &nf_reg->ctrl);
80 #ifdef CONFIG_NAND_ECC_SOFT_RS
81 static struct nand_ecclayout kw_nand_oob_rs = {
84 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
85 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
86 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
87 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
90 { .offset = 2, .length = 22, },
94 static void kw_nand_switch_eccmode(struct mtd_info *mtd,
95 nand_ecc_modes_t eccmode)
97 struct nand_chip *nand = mtd->priv;
99 if (nand->ecc.mode == eccmode)
103 case NAND_ECC_SOFT_RS:
104 nand->ecc.mode = NAND_ECC_SOFT_RS;
105 nand->ecc.layout = &kw_nand_oob_rs;
106 nand->ecc.size = 512;
107 nand->ecc.bytes = 10;
109 case NAND_ECC_SOFT_BCH:
110 nand->ecc.layout = NULL;
115 nand->ecc.layout = NULL;
119 printf("Unsupported ecc mode %u\n", eccmode);
122 nand->ecc.mode = eccmode;
123 nand->options |= NAND_OWN_BUFFERS;
125 nand->options &= ~NAND_OWN_BUFFERS;
128 static int do_kw_nand_switch_eccmode(cmd_tbl_t *cmdtp, int flag, int argc,
131 nand_ecc_modes_t mode;
132 struct mtd_info *mtd;
135 return CMD_RET_USAGE;
136 if (nand_curr_device < 0 ||
137 nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
138 !nand_info[nand_curr_device].name) {
139 printf("Error: Can't switch ecc, no devices available\n");
140 return CMD_RET_FAILURE;
142 mtd = &nand_info[nand_curr_device];
145 struct nand_chip *nand = mtd->priv;
148 switch (nand->ecc.mode) {
152 case NAND_ECC_SOFT_RS:
155 case NAND_ECC_SOFT_BCH:
156 if (mtd_nand_has_bch()) {
162 printf("Unsupported ECC mode %d in use\n", nand->ecc.mode);
163 return CMD_RET_FAILURE;
165 printf("NAND ECC mode: %s\n", modestr);
166 return CMD_RET_SUCCESS;
168 if (strcmp(argv[1], "hamming") == 0 ||
169 strcmp(argv[1], "soft") == 0) {
170 mode = NAND_ECC_SOFT;
171 } else if (strcmp(argv[1], "rs") == 0) {
172 mode = NAND_ECC_SOFT_RS;
173 } else if (strcmp(argv[1], "bch") == 0) {
174 mode = NAND_ECC_SOFT_BCH;
176 printf("Unsupported ECC mode '%s'; supported modes are 'hamming', 'RS'%s\n",
177 argv[1], mtd_nand_has_bch() ? ", 'BCH'" : "");
178 return CMD_RET_USAGE;
181 kw_nand_switch_eccmode(mtd, mode);
182 printf("ECC mode switched to %s\n", argv[1]);
183 return CMD_RET_SUCCESS;
185 U_BOOT_CMD(nandecc, 2, 0, do_kw_nand_switch_eccmode,
189 "HAMMING (1 bit ECC; not suitable for Micron NAND)"
190 "BCH 4 bit ECC; (default)"
191 "RS 4 bit ECC; (write only! for compatibility with ROM code)"
195 int board_nand_init(struct nand_chip *nand)
197 nand->options = NAND_COPYBACK | NAND_CACHEPRG | NAND_NO_PADDING;
198 #ifndef CONFIG_NAND_ECC_SOFT_RS
199 nand->ecc.mode = NAND_ECC_SOFT;
201 nand->ecc.mode = NAND_ECC_SOFT_BCH;
203 nand->cmd_ctrl = kw_nand_hwcontrol;
204 nand->chip_delay = 40;
205 nand->select_chip = kw_nand_select_chip;