blob: 7fb2dfabc17e79f2fc1ebac2b07628bd169e4fdc [file] [log] [blame]
Heiko Schochera6f2e452008-08-28 13:50:42 +02001/*
2 * (C) Copyright 2008
3 * Heiko Schocher, DENX Software Engineering, hs@denx.de.
4 *
Wolfgang Denk3765b3e2013-10-07 13:07:26 +02005 * SPDX-License-Identifier: GPL-2.0+
Heiko Schochera6f2e452008-08-28 13:50:42 +02006 */
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 */
15static 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 */
49static 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 */
83static 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
116static int chipsel = 0;
117
118#if defined(CONFIG_CMD_NAND)
119
120#include <nand.h>
121#include <linux/mtd/mtd.h>
122
123static u8 hwctl = 0;
124
125static void upmnand_write_byte(struct mtd_info *mtdinfo, u_char byte)
126{
127 struct nand_chip *this = mtdinfo->priv;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200128 ulong base = (ulong) (this->IO_ADDR_W + chipsel * CONFIG_SYS_NAND_CS_DIST);
Heiko Schochera6f2e452008-08-28 13:50:42 +0200129
130 if (hwctl & 0x1) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200131 WRITE_NAND_UPM(byte, base, CONFIG_SYS_NAND_UPM_WRITE_CMD_OFS);
Heiko Schochera6f2e452008-08-28 13:50:42 +0200132 } else if (hwctl & 0x2) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200133 WRITE_NAND_UPM(byte, base, CONFIG_SYS_NAND_UPM_WRITE_ADDR_OFS);
Heiko Schochera6f2e452008-08-28 13:50:42 +0200134 } else {
135 WRITE_NAND(byte, base);
136 }
137}
138
139static 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
155static u_char upmnand_read_byte(struct mtd_info *mtdinfo)
156{
157 struct nand_chip *this = mtdinfo->priv;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200158 ulong base = (ulong) (this->IO_ADDR_W + chipsel * CONFIG_SYS_NAND_CS_DIST);
Heiko Schochera6f2e452008-08-28 13:50:42 +0200159
160 return READ_NAND(base);
161}
162
163static 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
171static void tqm8272_read_buf(struct mtd_info *mtdinfo, uint8_t *buf, int len)
172{
173 struct nand_chip *this = mtdinfo->priv;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200174 unsigned char *base = (unsigned char *) (this->IO_ADDR_W + chipsel * CONFIG_SYS_NAND_CS_DIST);
Heiko Schochera6f2e452008-08-28 13:50:42 +0200175 int i;
176
177 for (i = 0; i< len; i++)
178 buf[i] = *base;
179}
180
181static void tqm8272_write_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len)
182{
183 struct nand_chip *this = mtdinfo->priv;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200184 unsigned char *base = (unsigned char *) (this->IO_ADDR_W + chipsel * CONFIG_SYS_NAND_CS_DIST);
Heiko Schochera6f2e452008-08-28 13:50:42 +0200185 int i;
186
187 for (i = 0; i< len; i++)
188 *base = buf[i];
189}
190
Heiko Schocherff94bc42014-06-24 10:10:04 +0200191#if defined(CONFIG_MTD_NAND_VERIFY_WRITE)
Heiko Schochera6f2e452008-08-28 13:50:42 +0200192static int tqm8272_verify_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len)
193{
194 struct nand_chip *this = mtdinfo->priv;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200195 unsigned char *base = (unsigned char *) (this->IO_ADDR_W + chipsel * CONFIG_SYS_NAND_CS_DIST);
Heiko Schochera6f2e452008-08-28 13:50:42 +0200196 int i;
197
198 for (i = 0; i < len; i++)
199 if (buf[i] != *base)
200 return -1;
201 return 0;
202}
Heiko Schocherff94bc42014-06-24 10:10:04 +0200203#endif
Heiko Schochera6f2e452008-08-28 13:50:42 +0200204#endif /* #ifndef CONFIG_NAND_SPL */
205
206void board_nand_select_device(struct nand_chip *nand, int chip)
207{
208 chipsel = chip;
209}
210
211int board_nand_init(struct nand_chip *nand)
212{
213 static int UpmInit = 0;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200214 volatile immap_t * immr = (immap_t *)CONFIG_SYS_IMMR;
Heiko Schochera6f2e452008-08-28 13:50:42 +0200215 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 */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200239 memctl->memc_or3 = CONFIG_SYS_NAND_OR;
240 memctl->memc_br3 = CONFIG_SYS_NAND_BR;
Heiko Schochera6f2e452008-08-28 13:50:42 +0200241 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;
Heiko Schocherff94bc42014-06-24 10:10:04 +0200252#if defined(CONFIG_MTD_NAND_VERIFY_WRITE)
Heiko Schochera6f2e452008-08-28 13:50:42 +0200253 nand->verify_buf = tqm8272_verify_buf;
254#endif
Heiko Schocherff94bc42014-06-24 10:10:04 +0200255#endif
Heiko Schochera6f2e452008-08-28 13:50:42 +0200256
257 /*
258 * Select required NAND chip
259 */
260 board_nand_select_device(nand, 0);
261 return 0;
262}
263
264#endif