]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/tqc/tqm8272/nand.c
Merge branch 'master' of git://git.denx.de/u-boot-arc
[karo-tx-uboot.git] / board / tqc / tqm8272 / nand.c
1 /*
2  * (C) Copyright 2008
3  * Heiko Schocher, DENX Software Engineering, hs@denx.de.
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <common.h>
9 #include <ioports.h>
10 #include <mpc8260.h>
11
12 #include "tqm8272.h"
13
14 /* UPM pattern for bus clock = 66.7 MHz */
15 static const uint upmTable67[] =
16 {
17     /* Offset   UPM Read Single RAM array entry -> NAND Read Data */
18     /* 0x00 */  0x0fa3f100, 0x0fa3b000, 0x0fa33100, 0x0fa33000,
19     /* 0x04 */  0x0fa33000, 0x0fa33004, 0xfffffc01, 0xfffffc00,
20
21                 /* UPM Read Burst RAM array entry -> unused */
22     /* 0x08 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
23     /* 0x0C */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
24
25                 /* UPM Read Burst RAM array entry -> unused */
26     /* 0x10 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
27     /* 0x14 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
28
29                 /* UPM Write Single RAM array entry -> NAND Write Data, ADDR and CMD */
30     /* 0x18 */  0x00a3fc00, 0x00a3fc00, 0x00a3fc00, 0x00a3fc00,
31     /* 0x1C */  0x0fa3fc00, 0x0fa3fc04, 0xfffffc01, 0xfffffc00,
32
33                 /* UPM Write Burst RAM array entry -> unused */
34     /* 0x20 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
35     /* 0x24 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
36     /* 0x28 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
37     /* 0x2C */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
38
39                 /* UPM Refresh Timer RAM array entry -> unused */
40     /* 0x30 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
41     /* 0x34 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
42     /* 0x38 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
43
44                 /* UPM Exception RAM array entry -> unsused */
45     /* 0x3C */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
46 };
47
48 /* UPM pattern for bus clock = 100 MHz */
49 static const uint upmTable100[] =
50 {
51     /* Offset   UPM Read Single RAM array entry -> NAND Read Data */
52     /* 0x00 */  0x0fa3f200, 0x0fa3b000, 0x0fa33300, 0x0fa33000,
53     /* 0x04 */  0x0fa33000, 0x0fa33004, 0xfffffc01, 0xfffffc00,
54
55                 /* UPM Read Burst RAM array entry -> unused */
56     /* 0x08 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
57     /* 0x0C */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
58
59                 /* UPM Read Burst RAM array entry -> unused */
60     /* 0x10 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
61     /* 0x14 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
62
63                 /* UPM Write Single RAM array entry -> NAND Write Data, ADDR and CMD */
64     /* 0x18 */  0x00a3ff00, 0x00a3fc00, 0x00a3fc00, 0x0fa3fc00,
65     /* 0x1C */  0x0fa3fc00, 0x0fa3fc04, 0xfffffc01, 0xfffffc00,
66
67                 /* UPM Write Burst RAM array entry -> unused */
68     /* 0x20 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
69     /* 0x24 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
70     /* 0x28 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
71     /* 0x2C */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
72
73                 /* UPM Refresh Timer RAM array entry -> unused */
74     /* 0x30 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
75     /* 0x34 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
76     /* 0x38 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
77
78                 /* UPM Exception RAM array entry -> unsused */
79     /* 0x3C */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
80 };
81
82 /* UPM pattern for bus clock = 133.3 MHz */
83 static const uint upmTable133[] =
84 {
85     /* Offset   UPM Read Single RAM array entry -> NAND Read Data */
86     /* 0x00 */  0x0fa3f300, 0x0fa3b000, 0x0fa33300, 0x0fa33000,
87     /* 0x04 */  0x0fa33200, 0x0fa33004, 0xfffffc01, 0xfffffc00,
88
89                 /* UPM Read Burst RAM array entry -> unused */
90     /* 0x08 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
91     /* 0x0C */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
92
93                 /* UPM Read Burst RAM array entry -> unused */
94     /* 0x10 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
95     /* 0x14 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
96
97                 /* UPM Write Single RAM array entry -> NAND Write Data, ADDR and CMD */
98     /* 0x18 */  0x00a3ff00, 0x00a3fc00, 0x00a3fd00, 0x0fa3fc00,
99     /* 0x1C */  0x0fa3fd00, 0x0fa3fc04, 0xfffffc01, 0xfffffc00,
100
101                 /* UPM Write Burst RAM array entry -> unused */
102     /* 0x20 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
103     /* 0x24 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
104     /* 0x28 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
105     /* 0x2C */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
106
107                 /* UPM Refresh Timer RAM array entry -> unused */
108     /* 0x30 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
109     /* 0x34 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc00,
110     /* 0x38 */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
111
112                 /* UPM Exception RAM array entry -> unsused */
113     /* 0x3C */  0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01,
114 };
115
116 static int      chipsel = 0;
117
118 #if defined(CONFIG_CMD_NAND)
119
120 #include <nand.h>
121 #include <linux/mtd/mtd.h>
122
123 static u8 hwctl = 0;
124
125 static void upmnand_write_byte(struct mtd_info *mtdinfo, u_char byte)
126 {
127         struct nand_chip *this = mtdinfo->priv;
128         ulong base = (ulong) (this->IO_ADDR_W + chipsel * CONFIG_SYS_NAND_CS_DIST);
129
130         if (hwctl & 0x1) {
131                 WRITE_NAND_UPM(byte, base, CONFIG_SYS_NAND_UPM_WRITE_CMD_OFS);
132         } else if (hwctl & 0x2) {
133                 WRITE_NAND_UPM(byte, base, CONFIG_SYS_NAND_UPM_WRITE_ADDR_OFS);
134         } else {
135                 WRITE_NAND(byte, base);
136         }
137 }
138
139 static void upmnand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
140 {
141         if (ctrl & NAND_CTRL_CHANGE) {
142                 if ( ctrl & NAND_CLE )
143                         hwctl |= 0x1;
144                 else
145                         hwctl &= ~0x1;
146                 if ( ctrl & NAND_ALE )
147                         hwctl |= 0x2;
148                 else
149                         hwctl &= ~0x2;
150         }
151         if (cmd != NAND_CMD_NONE)
152                 upmnand_write_byte (mtd, cmd);
153 }
154
155 static u_char upmnand_read_byte(struct mtd_info *mtdinfo)
156 {
157         struct nand_chip *this = mtdinfo->priv;
158         ulong base = (ulong) (this->IO_ADDR_W + chipsel * CONFIG_SYS_NAND_CS_DIST);
159
160         return READ_NAND(base);
161 }
162
163 static int tqm8272_dev_ready(struct mtd_info *mtdinfo)
164 {
165         /* constant delay (see also tR in the datasheet) */
166         udelay(12); \
167         return 1;
168 }
169
170 #ifndef CONFIG_NAND_SPL
171 static void tqm8272_read_buf(struct mtd_info *mtdinfo, uint8_t *buf, int len)
172 {
173         struct nand_chip *this = mtdinfo->priv;
174         unsigned char *base = (unsigned char *) (this->IO_ADDR_W + chipsel * CONFIG_SYS_NAND_CS_DIST);
175         int     i;
176
177         for (i = 0; i< len; i++)
178                 buf[i] = *base;
179 }
180
181 static void tqm8272_write_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len)
182 {
183         struct nand_chip *this = mtdinfo->priv;
184         unsigned char *base = (unsigned char *) (this->IO_ADDR_W + chipsel * CONFIG_SYS_NAND_CS_DIST);
185         int     i;
186
187         for (i = 0; i< len; i++)
188                 *base = buf[i];
189 }
190
191 #if defined(CONFIG_MTD_NAND_VERIFY_WRITE)
192 static int tqm8272_verify_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len)
193 {
194         struct nand_chip *this = mtdinfo->priv;
195         unsigned char *base = (unsigned char *) (this->IO_ADDR_W + chipsel * CONFIG_SYS_NAND_CS_DIST);
196         int     i;
197
198         for (i = 0; i < len; i++)
199                 if (buf[i] != *base)
200                         return -1;
201         return 0;
202 }
203 #endif
204 #endif /* #ifndef CONFIG_NAND_SPL */
205
206 void board_nand_select_device(struct nand_chip *nand, int chip)
207 {
208         chipsel = chip;
209 }
210
211 int board_nand_init(struct nand_chip *nand)
212 {
213         static  int     UpmInit = 0;
214         volatile immap_t * immr = (immap_t *)CONFIG_SYS_IMMR;
215         volatile memctl8260_t *memctl = &immr->im_memctl;
216
217         if (hwinf.nand == 0) return -1;
218
219         /* Setup the UPM */
220         if (UpmInit == 0) {
221                 switch (hwinf.busclk_real) {
222                 case 100000000:
223                         upmconfig (UPMB, (uint *) upmTable100,
224                            sizeof (upmTable100) / sizeof (uint));
225                         break;
226                 case 133333333:
227                         upmconfig (UPMB, (uint *) upmTable133,
228                            sizeof (upmTable133) / sizeof (uint));
229                         break;
230                 default:
231                         upmconfig (UPMB, (uint *) upmTable67,
232                            sizeof (upmTable67) / sizeof (uint));
233                         break;
234                 }
235                 UpmInit = 1;
236         }
237
238         /* Setup the memctrl */
239         memctl->memc_or3 = CONFIG_SYS_NAND_OR;
240         memctl->memc_br3 = CONFIG_SYS_NAND_BR;
241         memctl->memc_mbmr = (MxMR_OP_NORM);
242
243         nand->ecc.mode = NAND_ECC_SOFT;
244
245         nand->cmd_ctrl   = upmnand_hwcontrol;
246         nand->read_byte  = upmnand_read_byte;
247         nand->dev_ready  = tqm8272_dev_ready;
248
249 #ifndef CONFIG_NAND_SPL
250         nand->write_buf  = tqm8272_write_buf;
251         nand->read_buf   = tqm8272_read_buf;
252 #if defined(CONFIG_MTD_NAND_VERIFY_WRITE)
253         nand->verify_buf = tqm8272_verify_buf;
254 #endif
255 #endif
256
257         /*
258          * Select required NAND chip
259          */
260         board_nand_select_device(nand, 0);
261         return 0;
262 }
263
264 #endif