]>
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 | ||
3fe00109 | 26 | #if defined(CONFIG_CMD_NAND) |
ba94a1bb WD |
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 | */ | |
cfa460ad | 55 | static void pdnb3_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) |
ba94a1bb | 56 | { |
5e1dae5c | 57 | struct nand_chip *this = mtd->priv; |
cfa460ad WJ |
58 | |
59 | if (ctrl & NAND_CTRL_CHANGE) { | |
60 | if ( ctrl & NAND_CLE ) | |
61 | hwctl |= 0x1; | |
62 | else | |
63 | hwctl &= ~0x1; | |
64 | if ( ctrl & NAND_ALE ) | |
65 | hwctl |= 0x2; | |
66 | else | |
67 | hwctl &= ~0x2; | |
68 | if ( (ctrl & NAND_NCE) != NAND_NCE) | |
69 | writeb(0x00, &(pdnb3_ndfc->term)); | |
ba94a1bb | 70 | } |
cfa460ad WJ |
71 | if (cmd != NAND_CMD_NONE) |
72 | writeb(cmd, this->IO_ADDR_W); | |
ba94a1bb WD |
73 | } |
74 | ||
ba94a1bb WD |
75 | |
76 | static u_char pdnb3_nand_read_byte(struct mtd_info *mtd) | |
77 | { | |
78 | return readb(&(pdnb3_ndfc->data)); | |
79 | } | |
80 | ||
81 | static void pdnb3_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) | |
82 | { | |
83 | int i; | |
84 | ||
85 | for (i = 0; i < len; i++) { | |
86 | if (hwctl & 0x1) | |
87 | writeb(buf[i], &(pdnb3_ndfc->cmd)); | |
88 | else if (hwctl & 0x2) | |
89 | writeb(buf[i], &(pdnb3_ndfc->addr)); | |
90 | else | |
91 | writeb(buf[i], &(pdnb3_ndfc->data)); | |
92 | } | |
93 | } | |
94 | ||
95 | static void pdnb3_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) | |
96 | { | |
97 | int i; | |
98 | ||
99 | if (len % 4) { | |
100 | for (i = 0; i < len; i++) | |
101 | buf[i] = readb(&(pdnb3_ndfc->data)); | |
102 | } else { | |
103 | ulong *ptr = (ulong *)buf; | |
104 | int count = len >> 2; | |
105 | ||
106 | for (i = 0; i < count; i++) | |
107 | *ptr++ = readl(&(pdnb3_ndfc->data)); | |
108 | } | |
109 | } | |
110 | ||
111 | static int pdnb3_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) | |
112 | { | |
113 | int i; | |
114 | ||
115 | for (i = 0; i < len; i++) | |
116 | if (buf[i] != readb(&(pdnb3_ndfc->data))) | |
117 | return i; | |
118 | ||
119 | return 0; | |
120 | } | |
121 | ||
122 | static int pdnb3_nand_dev_ready(struct mtd_info *mtd) | |
123 | { | |
124 | volatile u_char val; | |
125 | ||
126 | /* | |
127 | * Blocking read to wait for NAND to be ready | |
128 | */ | |
129 | val = readb(&(pdnb3_ndfc->wait)); | |
130 | ||
131 | /* | |
132 | * Return always true | |
133 | */ | |
134 | return 1; | |
135 | } | |
136 | ||
fa230445 | 137 | int board_nand_init(struct nand_chip *nand) |
ba94a1bb | 138 | { |
6d0f6bcf | 139 | pdnb3_ndfc = (struct pdnb3_ndfc_regs *)CONFIG_SYS_NAND_BASE; |
ba94a1bb | 140 | |
cfa460ad | 141 | nand->ecc.mode = NAND_ECC_SOFT; |
ba94a1bb WD |
142 | |
143 | /* Set address of NAND IO lines (Using Linear Data Access Region) */ | |
144 | nand->IO_ADDR_R = (void __iomem *) ((ulong) pdnb3_ndfc + 0x4); | |
145 | nand->IO_ADDR_W = (void __iomem *) ((ulong) pdnb3_ndfc + 0x4); | |
146 | /* Reference hardware control function */ | |
cfa460ad | 147 | nand->cmd_ctrl = pdnb3_nand_hwcontrol; |
ba94a1bb WD |
148 | nand->read_byte = pdnb3_nand_read_byte; |
149 | nand->write_buf = pdnb3_nand_write_buf; | |
150 | nand->read_buf = pdnb3_nand_read_buf; | |
151 | nand->verify_buf = pdnb3_nand_verify_buf; | |
152 | nand->dev_ready = pdnb3_nand_dev_ready; | |
fa230445 | 153 | return 0; |
ba94a1bb WD |
154 | } |
155 | #endif |