]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/mtd/nand/kirkwood_nand.c
1cdf286f6076f934871c823cbe1f58c53c761279
[karo-tx-uboot.git] / drivers / mtd / nand / kirkwood_nand.c
1 /*
2  * (C) Copyright 2009
3  * Marvell Semiconductor <www.marvell.com>
4  * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
5  *
6  * See file CREDITS for list of people who contributed to this
7  * project.
8  *
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.
13  *
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.
18  *
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,
22  * MA 02111-1307 USA
23  */
24
25 #include <common.h>
26 #include <asm/io.h>
27 #include <asm/arch/kirkwood.h>
28 #include <nand.h>
29 #include <linux/mtd/nand_ecc.h>
30
31 #ifndef CONFIG_NAND_ECC_ALGO
32 #define CONFIG_NAND_ECC_ALGO    NAND_ECC_SOFT
33 #endif
34
35 /* NAND Flash Soc registers */
36 struct kwnandf_registers {
37         u32 rd_params;  /* 0x10418 */
38         u32 wr_param;   /* 0x1041c */
39         u8  pad[0x10470 - 0x1041c - 4];
40         u32 ctrl;       /* 0x10470 */
41 };
42
43 static struct kwnandf_registers *nf_reg =
44         (struct kwnandf_registers *)KW_NANDF_BASE;
45
46 /*
47  * hardware specific access to control-lines/bits
48  */
49 #define NAND_ACTCEBOOT_BIT              0x02
50
51 static void kw_nand_hwcontrol(struct mtd_info *mtd, int cmd,
52                               unsigned int ctrl)
53 {
54         struct nand_chip *nc = mtd->priv;
55         u32 offs;
56
57         if (cmd == NAND_CMD_NONE)
58                 return;
59
60         if (ctrl & NAND_CLE)
61                 offs = (1 << 0);        /* Commands with A[1:0] == 01 */
62         else if (ctrl & NAND_ALE)
63                 offs = (1 << 1);        /* Addresses with A[1:0] == 10 */
64         else
65                 return;
66
67         writeb(cmd, nc->IO_ADDR_W + offs);
68 }
69
70 void kw_nand_select_chip(struct mtd_info *mtd, int chip)
71 {
72         u32 data;
73
74         data = readl(&nf_reg->ctrl);
75         data |= NAND_ACTCEBOOT_BIT;
76         writel(data, &nf_reg->ctrl);
77 }
78
79 #ifdef CONFIG_NAND_ECC_SOFT_RS
80 static struct nand_ecclayout kw_nand_oob_rs = {
81         .eccbytes = 40,
82         .eccpos = {
83                 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
84                 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
85                 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
86                 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
87         },
88         .oobfree = {
89                 { .offset = 2, .length = 22, },
90         },
91 };
92 #endif
93
94 int board_nand_init(struct nand_chip *nand)
95 {
96         nand->options = NAND_COPYBACK | NAND_CACHEPRG | NAND_NO_PADDING;
97 #ifndef CONFIG_NAND_ECC_SOFT_RS
98         nand->ecc.mode = NAND_ECC_SOFT;
99 #else
100         nand->ecc.mode = NAND_ECC_SOFT_RS;
101         nand->ecc.layout = &kw_nand_oob_rs;
102         nand->ecc.size = 512;
103         nand->ecc.bytes = 10;
104 #endif
105         nand->cmd_ctrl = kw_nand_hwcontrol;
106         nand->chip_delay = 40;
107         nand->select_chip = kw_nand_select_chip;
108         return 0;
109 }