xref: /openbmc/u-boot/board/socrates/nand.c (revision 7ca6f363)
1 /*
2  * (C) Copyright 2008
3  * Sergei Poselenov, Emcraft Systems, sposelenov@emcraft.com.
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 
8 #include <common.h>
9 
10 #if defined(CONFIG_SYS_NAND_BASE)
11 #include <nand.h>
12 #include <asm/errno.h>
13 #include <asm/io.h>
14 
15 static int state;
16 static void sc_nand_write_byte(struct mtd_info *mtd, u_char byte);
17 static void sc_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len);
18 static u_char sc_nand_read_byte(struct mtd_info *mtd);
19 static u16 sc_nand_read_word(struct mtd_info *mtd);
20 static void sc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len);
21 static int sc_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len);
22 static int sc_nand_device_ready(struct mtd_info *mtdinfo);
23 
24 #define FPGA_NAND_CMD_MASK		(0x7 << 28)
25 #define FPGA_NAND_CMD_COMMAND		(0x0 << 28)
26 #define FPGA_NAND_CMD_ADDR		(0x1 << 28)
27 #define FPGA_NAND_CMD_READ		(0x2 << 28)
28 #define FPGA_NAND_CMD_WRITE		(0x3 << 28)
29 #define FPGA_NAND_BUSY			(0x1 << 15)
30 #define FPGA_NAND_ENABLE		(0x1 << 31)
31 #define FPGA_NAND_DATA_SHIFT		16
32 
33 /**
34  * sc_nand_write_byte -  write one byte to the chip
35  * @mtd:	MTD device structure
36  * @byte:	pointer to data byte to write
37  */
38 static void sc_nand_write_byte(struct mtd_info *mtd, u_char byte)
39 {
40 	sc_nand_write_buf(mtd, (const uchar *)&byte, sizeof(byte));
41 }
42 
43 /**
44  * sc_nand_write_buf -  write buffer to chip
45  * @mtd:	MTD device structure
46  * @buf:	data buffer
47  * @len:	number of bytes to write
48  */
49 static void sc_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
50 {
51 	int i;
52 	struct nand_chip *this = mtd->priv;
53 
54 	for (i = 0; i < len; i++) {
55 		out_be32(this->IO_ADDR_W,
56 			 state | (buf[i] << FPGA_NAND_DATA_SHIFT));
57 	}
58 }
59 
60 
61 /**
62  * sc_nand_read_byte -  read one byte from the chip
63  * @mtd:	MTD device structure
64  */
65 static u_char sc_nand_read_byte(struct mtd_info *mtd)
66 {
67 	u8 byte;
68 	sc_nand_read_buf(mtd, (uchar *)&byte, sizeof(byte));
69 	return byte;
70 }
71 
72 /**
73  * sc_nand_read_word -  read one word from the chip
74  * @mtd:	MTD device structure
75  */
76 static u16 sc_nand_read_word(struct mtd_info *mtd)
77 {
78 	u16 word;
79 	sc_nand_read_buf(mtd, (uchar *)&word, sizeof(word));
80 	return word;
81 }
82 
83 /**
84  * sc_nand_read_buf -  read chip data into buffer
85  * @mtd:	MTD device structure
86  * @buf:	buffer to store date
87  * @len:	number of bytes to read
88  */
89 static void sc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
90 {
91 	int i;
92 	struct nand_chip *this = mtd->priv;
93 	int val;
94 
95 	val = (state & FPGA_NAND_ENABLE) | FPGA_NAND_CMD_READ;
96 
97 	out_be32(this->IO_ADDR_W, val);
98 	for (i = 0; i < len; i++) {
99 		buf[i] = (in_be32(this->IO_ADDR_R) >> FPGA_NAND_DATA_SHIFT) & 0xff;
100 	}
101 }
102 
103 /**
104  * sc_nand_verify_buf -  Verify chip data against buffer
105  * @mtd:	MTD device structure
106  * @buf:	buffer containing the data to compare
107  * @len:	number of bytes to compare
108  */
109 static int sc_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
110 {
111 	int i;
112 
113 	for (i = 0; i < len; i++) {
114 		if (buf[i] != sc_nand_read_byte(mtd));
115 			return -EFAULT;
116 	}
117 	return 0;
118 }
119 
120 /**
121  * sc_nand_device_ready - Check the NAND device is ready for next command.
122  * @mtd:	MTD device structure
123  */
124 static int sc_nand_device_ready(struct mtd_info *mtdinfo)
125 {
126 	struct nand_chip *this = mtdinfo->priv;
127 
128 	if (in_be32(this->IO_ADDR_W) & FPGA_NAND_BUSY)
129 		return 0; /* busy */
130 	return 1;
131 }
132 
133 /**
134  * sc_nand_hwcontrol - NAND control functions wrapper.
135  * @mtd:	MTD device structure
136  * @cmd:	Command
137  */
138 static void sc_nand_hwcontrol(struct mtd_info *mtdinfo, int cmd, unsigned int ctrl)
139 {
140 	if (ctrl & NAND_CTRL_CHANGE) {
141 		state &= ~(FPGA_NAND_CMD_MASK | FPGA_NAND_ENABLE);
142 
143 		switch (ctrl & (NAND_ALE | NAND_CLE)) {
144 		case 0:
145 			state |= FPGA_NAND_CMD_WRITE;
146 			break;
147 
148 		case NAND_ALE:
149 			state |= FPGA_NAND_CMD_ADDR;
150 			break;
151 
152 		case NAND_CLE:
153 			state |= FPGA_NAND_CMD_COMMAND;
154 			break;
155 
156 		default:
157 			printf("%s: unknown ctrl %#x\n", __FUNCTION__, ctrl);
158 		}
159 
160 		if (ctrl & NAND_NCE)
161 			state |= FPGA_NAND_ENABLE;
162 	}
163 
164 	if (cmd != NAND_CMD_NONE)
165 		sc_nand_write_byte(mtdinfo, cmd);
166 }
167 
168 int board_nand_init(struct nand_chip *nand)
169 {
170 	nand->cmd_ctrl = sc_nand_hwcontrol;
171 	nand->ecc.mode = NAND_ECC_SOFT;
172 	nand->dev_ready = sc_nand_device_ready;
173 	nand->read_byte = sc_nand_read_byte;
174 	nand->read_word = sc_nand_read_word;
175 	nand->write_buf = sc_nand_write_buf;
176 	nand->read_buf = sc_nand_read_buf;
177 	nand->verify_buf = sc_nand_verify_buf;
178 
179 	return 0;
180 }
181 
182 #endif
183