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