]>
Commit | Line | Data |
---|---|---|
ba94a1bb WD |
1 | /* |
2 | * (C) Copyright 2006 | |
3 | * Stefan Roese, DENX Software Engineering, sr@denx.de. | |
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 (CONFIG_COMMANDS & CFG_CMD_NAND) | |
27 | ||
28 | #include <nand.h> | |
29 | ||
30 | struct pdnb3_ndfc_regs { | |
31 | uchar cmd; | |
32 | uchar wait; | |
33 | uchar addr; | |
34 | uchar term; | |
35 | uchar data; | |
36 | }; | |
37 | ||
38 | static u8 hwctl; | |
39 | static struct pdnb3_ndfc_regs *pdnb3_ndfc; | |
40 | ||
41 | #define readb(addr) *(volatile u_char *)(addr) | |
42 | #define readl(addr) *(volatile u_long *)(addr) | |
43 | #define writeb(d,addr) *(volatile u_char *)(addr) = (d) | |
44 | ||
45 | /* | |
46 | * The PDNB3 has a NAND Flash Controller (NDFC) that handles all accesses to | |
47 | * the NAND devices. The NDFC has command, address and data registers that | |
48 | * when accessed will set up the NAND flash pins appropriately. We'll use the | |
49 | * hwcontrol function to save the configuration in a global variable. | |
50 | * We can then use this information in the read and write functions to | |
51 | * determine which NDFC register to access. | |
52 | * | |
53 | * There is one NAND devices on the board, a Hynix HY27US08561A (32 MByte). | |
54 | */ | |
55 | static void pdnb3_nand_hwcontrol(struct mtd_info *mtd, int cmd) | |
56 | { | |
57 | switch (cmd) { | |
58 | case NAND_CTL_SETCLE: | |
59 | hwctl |= 0x1; | |
60 | break; | |
61 | case NAND_CTL_CLRCLE: | |
62 | hwctl &= ~0x1; | |
63 | break; | |
64 | ||
65 | case NAND_CTL_SETALE: | |
66 | hwctl |= 0x2; | |
67 | break; | |
68 | case NAND_CTL_CLRALE: | |
69 | hwctl &= ~0x2; | |
70 | break; | |
71 | ||
72 | case NAND_CTL_SETNCE: | |
73 | break; | |
74 | case NAND_CTL_CLRNCE: | |
75 | writeb(0x00, &(pdnb3_ndfc->term)); | |
76 | break; | |
77 | } | |
78 | } | |
79 | ||
80 | static void pdnb3_nand_write_byte(struct mtd_info *mtd, u_char byte) | |
81 | { | |
82 | if (hwctl & 0x1) | |
83 | writeb(byte, &(pdnb3_ndfc->cmd)); | |
84 | else if (hwctl & 0x2) | |
85 | writeb(byte, &(pdnb3_ndfc->addr)); | |
86 | else | |
87 | writeb(byte, &(pdnb3_ndfc->data)); | |
88 | } | |
89 | ||
90 | static u_char pdnb3_nand_read_byte(struct mtd_info *mtd) | |
91 | { | |
92 | return readb(&(pdnb3_ndfc->data)); | |
93 | } | |
94 | ||
95 | static void pdnb3_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) | |
96 | { | |
97 | int i; | |
98 | ||
99 | for (i = 0; i < len; i++) { | |
100 | if (hwctl & 0x1) | |
101 | writeb(buf[i], &(pdnb3_ndfc->cmd)); | |
102 | else if (hwctl & 0x2) | |
103 | writeb(buf[i], &(pdnb3_ndfc->addr)); | |
104 | else | |
105 | writeb(buf[i], &(pdnb3_ndfc->data)); | |
106 | } | |
107 | } | |
108 | ||
109 | static void pdnb3_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) | |
110 | { | |
111 | int i; | |
112 | ||
113 | if (len % 4) { | |
114 | for (i = 0; i < len; i++) | |
115 | buf[i] = readb(&(pdnb3_ndfc->data)); | |
116 | } else { | |
117 | ulong *ptr = (ulong *)buf; | |
118 | int count = len >> 2; | |
119 | ||
120 | for (i = 0; i < count; i++) | |
121 | *ptr++ = readl(&(pdnb3_ndfc->data)); | |
122 | } | |
123 | } | |
124 | ||
125 | static int pdnb3_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] != readb(&(pdnb3_ndfc->data))) | |
131 | return i; | |
132 | ||
133 | return 0; | |
134 | } | |
135 | ||
136 | static int pdnb3_nand_dev_ready(struct mtd_info *mtd) | |
137 | { | |
138 | volatile u_char val; | |
139 | ||
140 | /* | |
141 | * Blocking read to wait for NAND to be ready | |
142 | */ | |
143 | val = readb(&(pdnb3_ndfc->wait)); | |
144 | ||
145 | /* | |
146 | * Return always true | |
147 | */ | |
148 | return 1; | |
149 | } | |
150 | ||
fa230445 | 151 | int board_nand_init(struct nand_chip *nand) |
ba94a1bb WD |
152 | { |
153 | pdnb3_ndfc = (struct pdnb3_ndfc_regs *)CFG_NAND_BASE; | |
154 | ||
155 | nand->eccmode = NAND_ECC_SOFT; | |
156 | ||
157 | /* Set address of NAND IO lines (Using Linear Data Access Region) */ | |
158 | nand->IO_ADDR_R = (void __iomem *) ((ulong) pdnb3_ndfc + 0x4); | |
159 | nand->IO_ADDR_W = (void __iomem *) ((ulong) pdnb3_ndfc + 0x4); | |
160 | /* Reference hardware control function */ | |
161 | nand->hwcontrol = pdnb3_nand_hwcontrol; | |
162 | /* Set command delay time */ | |
163 | nand->hwcontrol = pdnb3_nand_hwcontrol; | |
164 | nand->write_byte = pdnb3_nand_write_byte; | |
165 | nand->read_byte = pdnb3_nand_read_byte; | |
166 | nand->write_buf = pdnb3_nand_write_buf; | |
167 | nand->read_buf = pdnb3_nand_read_buf; | |
168 | nand->verify_buf = pdnb3_nand_verify_buf; | |
169 | nand->dev_ready = pdnb3_nand_dev_ready; | |
fa230445 | 170 | return 0; |
ba94a1bb WD |
171 | } |
172 | #endif |