]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/ppc4xx/ndfc.c
ppc4xx: Undo Sequoia patch for dynamic EBC speed support of 83MHz
[karo-tx-uboot.git] / cpu / ppc4xx / ndfc.c
1 /*
2  * Overview:
3  *   Platform independend driver for NDFC (NanD Flash Controller)
4  *   integrated into EP440 cores
5  *
6  * (C) Copyright 2006
7  * Stefan Roese, DENX Software Engineering, sr@denx.de.
8  *
9  * Based on original work by
10  *      Thomas Gleixner
11  *      Copyright 2006 IBM
12  *
13  * See file CREDITS for list of people who contributed to this
14  * project.
15  *
16  * This program is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License as
18  * published by the Free Software Foundation; either version 2 of
19  * the License, or (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
29  * MA 02111-1307 USA
30  */
31
32 #include <common.h>
33
34 #if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY) && \
35         (defined(CONFIG_440EP) || defined(CONFIG_440GR) ||           \
36          defined(CONFIG_440EPX) || defined(CONFIG_440GRX) ||         \
37          defined(CONFIG_405EZ))
38
39 #include <nand.h>
40 #include <linux/mtd/ndfc.h>
41 #include <asm/processor.h>
42 #include <ppc4xx.h>
43
44 static u8 hwctl = 0;
45
46 static void ndfc_hwcontrol(struct mtd_info *mtdinfo, int cmd)
47 {
48         switch (cmd) {
49         case NAND_CTL_SETCLE:
50                 hwctl |= 0x1;
51                 break;
52
53         case NAND_CTL_CLRCLE:
54                 hwctl &= ~0x1;
55                 break;
56
57         case NAND_CTL_SETALE:
58                 hwctl |= 0x2;
59                 break;
60
61         case NAND_CTL_CLRALE:
62                 hwctl &= ~0x2;
63                 break;
64         }
65 }
66
67 static void ndfc_write_byte(struct mtd_info *mtdinfo, u_char byte)
68 {
69         struct nand_chip *this = mtdinfo->priv;
70         ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc;
71
72         if (hwctl & 0x1)
73                 out8(base + NDFC_CMD, byte);
74         else if (hwctl & 0x2)
75                 out8(base + NDFC_ALE, byte);
76         else
77                 out8(base + NDFC_DATA, byte);
78 }
79
80 static u_char ndfc_read_byte(struct mtd_info *mtdinfo)
81 {
82         struct nand_chip *this = mtdinfo->priv;
83         ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc;
84
85         return (in8(base + NDFC_DATA));
86 }
87
88 static int ndfc_dev_ready(struct mtd_info *mtdinfo)
89 {
90         struct nand_chip *this = mtdinfo->priv;
91         ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc;
92
93         while (!(in32(base + NDFC_STAT) & NDFC_STAT_IS_READY))
94                 ;
95
96         return 1;
97 }
98
99 #ifndef CONFIG_NAND_SPL
100 /*
101  * Don't use these speedup functions in NAND boot image, since the image
102  * has to fit into 4kByte.
103  */
104
105 /*
106  * Speedups for buffer read/write/verify
107  *
108  * NDFC allows 32bit read/write of data. So we can speed up the buffer
109  * functions. No further checking, as nand_base will always read/write
110  * page aligned.
111  */
112 static void ndfc_read_buf(struct mtd_info *mtdinfo, uint8_t *buf, int len)
113 {
114         struct nand_chip *this = mtdinfo->priv;
115         ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc;
116         uint32_t *p = (uint32_t *) buf;
117
118         for (;len > 0; len -= 4)
119                 *p++ = in32(base + NDFC_DATA);
120 }
121
122 static void ndfc_write_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len)
123 {
124         struct nand_chip *this = mtdinfo->priv;
125         ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc;
126         uint32_t *p = (uint32_t *) buf;
127
128         for (; len > 0; len -= 4)
129                 out32(base + NDFC_DATA, *p++);
130 }
131
132 static int ndfc_verify_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len)
133 {
134         struct nand_chip *this = mtdinfo->priv;
135         ulong base = (ulong) this->IO_ADDR_W & 0xfffffffc;
136         uint32_t *p = (uint32_t *) buf;
137
138         for (; len > 0; len -= 4)
139                 if (*p++ != in32(base + NDFC_DATA))
140                         return -1;
141
142         return 0;
143 }
144 #endif /* #ifndef CONFIG_NAND_SPL */
145
146 void board_nand_select_device(struct nand_chip *nand, int chip)
147 {
148         /*
149          * Don't use "chip" to address the NAND device,
150          * generate the cs from the address where it is encoded.
151          */
152         int cs = (ulong)nand->IO_ADDR_W & 0x00000003;
153         ulong base = (ulong)nand->IO_ADDR_W & 0xfffffffc;
154
155         /* Set NandFlash Core Configuration Register */
156         /* 1col x 2 rows */
157         out32(base + NDFC_CCR, 0x00000000 | (cs << 24));
158 }
159
160 int board_nand_init(struct nand_chip *nand)
161 {
162         int cs = (ulong)nand->IO_ADDR_W & 0x00000003;
163         ulong base = (ulong)nand->IO_ADDR_W & 0xfffffffc;
164
165         nand->eccmode = NAND_ECC_SOFT;
166
167         nand->hwcontrol  = ndfc_hwcontrol;
168         nand->read_byte  = ndfc_read_byte;
169         nand->write_byte = ndfc_write_byte;
170         nand->dev_ready  = ndfc_dev_ready;
171
172 #ifndef CONFIG_NAND_SPL
173         nand->write_buf  = ndfc_write_buf;
174         nand->read_buf   = ndfc_read_buf;
175         nand->verify_buf = ndfc_verify_buf;
176 #else
177         /*
178          * Setup EBC (CS0 only right now)
179          */
180         mtebc(EBC0_CFG, 0xb8400000);
181
182         mtebc(pb0cr, CFG_EBC_PB0CR);
183         mtebc(pb0ap, CFG_EBC_PB0AP);
184 #endif
185
186         /*
187          * Select required NAND chip in NDFC
188          */
189         board_nand_select_device(nand, cs);
190         out32(base + NDFC_BCFG0 + (cs << 2), 0x80002222);
191         return 0;
192 }
193
194 #endif