xref: /openbmc/u-boot/board/socrates/nand.c (revision 9973e3c6)
1 /*
2  * (C) Copyright 2008
3  * Sergei Poselenov, Emcraft Systems, sposelenov@emcraft.com.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23 
24 #include <common.h>
25 
26 #if defined(CFG_NAND_BASE)
27 #include <nand.h>
28 #include <asm/errno.h>
29 #include <asm/io.h>
30 
31 static int state;
32 static void nand_write_byte(struct mtd_info *mtd, u_char byte);
33 static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len);
34 static void nand_write_word(struct mtd_info *mtd, u16 word);
35 static u_char nand_read_byte(struct mtd_info *mtd);
36 static u16 nand_read_word(struct mtd_info *mtd);
37 static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len);
38 static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len);
39 static int nand_device_ready(struct mtd_info *mtdinfo);
40 static void nand_hwcontrol(struct mtd_info *mtdinfo, int cmd);
41 
42 #define FPGA_NAND_CMD_MASK		(0x7 << 28)
43 #define FPGA_NAND_CMD_COMMAND	(0x0 << 28)
44 #define FPGA_NAND_CMD_ADDR		(0x1 << 28)
45 #define FPGA_NAND_CMD_READ		(0x2 << 28)
46 #define FPGA_NAND_CMD_WRITE		(0x3 << 28)
47 #define FPGA_NAND_BUSY			(0x1 << 15)
48 #define FPGA_NAND_ENABLE		(0x1 << 31)
49 #define FPGA_NAND_DATA_SHIFT	16
50 
51 /**
52  * nand_write_byte -  write one byte to the chip
53  * @mtd:	MTD device structure
54  * @byte:	pointer to data byte to write
55  */
56 static void nand_write_byte(struct mtd_info *mtd, u_char byte)
57 {
58 	nand_write_buf(mtd, (const uchar *)&byte, sizeof(byte));
59 }
60 
61 /**
62  * nand_write_word -  write one word to the chip
63  * @mtd:	MTD device structure
64  * @word:	data word to write
65  */
66 static void nand_write_word(struct mtd_info *mtd, u16 word)
67 {
68 	nand_write_buf(mtd, (const uchar *)&word, sizeof(word));
69 }
70 
71 /**
72  * nand_write_buf -  write buffer to chip
73  * @mtd:	MTD device structure
74  * @buf:	data buffer
75  * @len:	number of bytes to write
76  */
77 static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
78 {
79 	int i;
80 	struct nand_chip *this = mtd->priv;
81 	long val;
82 
83 	if ((state & FPGA_NAND_CMD_MASK) == FPGA_NAND_CMD_MASK) {
84 		/* Write data */
85 		val = (state & FPGA_NAND_ENABLE) | FPGA_NAND_CMD_WRITE;
86 	} else {
87 		/* Write address or command */
88 		val = state;
89 	}
90 
91 	for (i = 0; i < len; i++) {
92 		out_be32(this->IO_ADDR_W, val | (buf[i] << FPGA_NAND_DATA_SHIFT));
93 	}
94 }
95 
96 
97 /**
98  * nand_read_byte -  read one byte from the chip
99  * @mtd:	MTD device structure
100  */
101 static u_char nand_read_byte(struct mtd_info *mtd)
102 {
103 	u8 byte;
104 	nand_read_buf(mtd, (uchar *)&byte, sizeof(byte));
105 	return byte;
106 }
107 
108 /**
109  * nand_read_word -  read one word from the chip
110  * @mtd:	MTD device structure
111  */
112 static u16 nand_read_word(struct mtd_info *mtd)
113 {
114 	u16 word;
115 	nand_read_buf(mtd, (uchar *)&word, sizeof(word));
116 	return word;
117 }
118 
119 /**
120  * nand_read_buf -  read chip data into buffer
121  * @mtd:	MTD device structure
122  * @buf:	buffer to store date
123  * @len:	number of bytes to read
124  */
125 static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
126 {
127 	int i;
128 	struct nand_chip *this = mtd->priv;
129 	int val;
130 
131 	val = (state & FPGA_NAND_ENABLE) | FPGA_NAND_CMD_READ;
132 
133 	out_be32(this->IO_ADDR_W, val);
134 	for (i = 0; i < len; i++) {
135 		buf[i] = (in_be32(this->IO_ADDR_R) >> FPGA_NAND_DATA_SHIFT) & 0xff;
136 	}
137 }
138 
139 /**
140  * nand_verify_buf -  Verify chip data against buffer
141  * @mtd:	MTD device structure
142  * @buf:	buffer containing the data to compare
143  * @len:	number of bytes to compare
144  */
145 static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
146 {
147 	int i;
148 
149 	for (i = 0; i < len; i++) {
150 		if (buf[i] != nand_read_byte(mtd));
151 		return -EFAULT;
152 	}
153 	return 0;
154 }
155 
156 /**
157  * nand_device_ready - Check the NAND device is ready for next command.
158  * @mtd:	MTD device structure
159  */
160 static int nand_device_ready(struct mtd_info *mtdinfo)
161 {
162 	struct nand_chip *this = mtdinfo->priv;
163 
164 	if (in_be32(this->IO_ADDR_W) & FPGA_NAND_BUSY)
165 		return 0; /* busy */
166 	return 1;
167 }
168 
169 /**
170  * nand_hwcontrol - NAND control functions wrapper.
171  * @mtd:	MTD device structure
172  * @cmd:	Command
173  */
174 static void nand_hwcontrol(struct mtd_info *mtdinfo, int cmd)
175 {
176 
177 	switch(cmd) {
178 	case NAND_CTL_CLRALE:
179 		state |= FPGA_NAND_CMD_MASK; /* use all 1s to mark */
180 		break;
181 	case NAND_CTL_CLRCLE:
182 		state |= FPGA_NAND_CMD_MASK; /* use all 1s to mark */
183 		break;
184 	case NAND_CTL_SETCLE:
185 		state = (state & ~FPGA_NAND_CMD_MASK) | FPGA_NAND_CMD_COMMAND;
186 		break;
187 	case NAND_CTL_SETALE:
188 		state = (state & ~FPGA_NAND_CMD_MASK) | FPGA_NAND_CMD_ADDR;
189 		break;
190 	case NAND_CTL_SETNCE:
191 		state |= FPGA_NAND_ENABLE;
192 		break;
193 	case NAND_CTL_CLRNCE:
194 		state &= ~FPGA_NAND_ENABLE;
195 		break;
196 	default:
197 		printf("%s: unknown cmd %#x\n", __FUNCTION__, cmd);
198 		break;
199 	}
200 }
201 
202 int board_nand_init(struct nand_chip *nand)
203 {
204 	nand->hwcontrol = nand_hwcontrol;
205 	nand->eccmode = NAND_ECC_SOFT;
206 	nand->dev_ready = nand_device_ready;
207 	nand->write_byte = nand_write_byte;
208 	nand->read_byte = nand_read_byte;
209 	nand->write_word = nand_write_word;
210 	nand->read_word = nand_read_word;
211 	nand->write_buf = nand_write_buf;
212 	nand->read_buf = nand_read_buf;
213 	nand->verify_buf = nand_verify_buf;
214 
215 	return 0;
216 }
217 
218 #endif
219