]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/tqc/tqm8272/nand.c
Coding Style cleanup: remove trailing white space
[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 static int tqm8272_verify_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len)
192 {
193         struct nand_chip *this = mtdinfo->priv;
194         unsigned char *base = (unsigned char *) (this->IO_ADDR_W + chipsel * CONFIG_SYS_NAND_CS_DIST);
195         int     i;
196
197         for (i = 0; i < len; i++)
198                 if (buf[i] != *base)
199                         return -1;
200         return 0;
201 }
202 #endif /* #ifndef CONFIG_NAND_SPL */
203
204 void board_nand_select_device(struct nand_chip *nand, int chip)
205 {
206         chipsel = chip;
207 }
208
209 int board_nand_init(struct nand_chip *nand)
210 {
211         static  int     UpmInit = 0;
212         volatile immap_t * immr = (immap_t *)CONFIG_SYS_IMMR;
213         volatile memctl8260_t *memctl = &immr->im_memctl;
214
215         if (hwinf.nand == 0) return -1;
216
217         /* Setup the UPM */
218         if (UpmInit == 0) {
219                 switch (hwinf.busclk_real) {
220                 case 100000000:
221                         upmconfig (UPMB, (uint *) upmTable100,
222                            sizeof (upmTable100) / sizeof (uint));
223                         break;
224                 case 133333333:
225                         upmconfig (UPMB, (uint *) upmTable133,
226                            sizeof (upmTable133) / sizeof (uint));
227                         break;
228                 default:
229                         upmconfig (UPMB, (uint *) upmTable67,
230                            sizeof (upmTable67) / sizeof (uint));
231                         break;
232                 }
233                 UpmInit = 1;
234         }
235
236         /* Setup the memctrl */
237         memctl->memc_or3 = CONFIG_SYS_NAND_OR;
238         memctl->memc_br3 = CONFIG_SYS_NAND_BR;
239         memctl->memc_mbmr = (MxMR_OP_NORM);
240
241         nand->ecc.mode = NAND_ECC_SOFT;
242
243         nand->cmd_ctrl   = upmnand_hwcontrol;
244         nand->read_byte  = upmnand_read_byte;
245         nand->dev_ready  = tqm8272_dev_ready;
246
247 #ifndef CONFIG_NAND_SPL
248         nand->write_buf  = tqm8272_write_buf;
249         nand->read_buf   = tqm8272_read_buf;
250         nand->verify_buf = tqm8272_verify_buf;
251 #endif
252
253         /*
254          * Select required NAND chip
255          */
256         board_nand_select_device(nand, 0);
257         return 0;
258 }
259
260 #endif