comparison packages/devs/nand/samsung_k9/current/include/k9_generic_lp.inl @ 3019:fad1849d4bb6

Update samsung_k9 to latest version
author Ross Younger <wry@ecoscentric.com>
date Fri, 07 May 2010 11:54:23 +0100
parents
children 62b2c0f5902b
comparison
equal deleted inserted replaced
3018:158408a8cf85 3019:fad1849d4bb6
1 //=============================================================================
2 //
3 // k9_generic_lp.inl
4 //
5 // Inline include file for the large page members of the Samsung K9F family
6 // NOTE: This file should only be included by k9_generic.inl.
7 //
8 //=============================================================================
9 // ####ECOSGPLCOPYRIGHTBEGIN####
10 // -------------------------------------------
11 // This file is part of eCos, the Embedded Configurable Operating System.
12 // Copyright (C) 2010 eCosCentric Limited.
13 //
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later
17 // version.
18 //
19 // eCos is distributed in the hope that it will be useful, but WITHOUT
20 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // for more details.
23 //
24 // You should have received a copy of the GNU General Public License
25 // along with eCos; if not, write to the Free Software Foundation, Inc.,
26 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27 //
28 // As a special exception, if other files instantiate templates or use
29 // macros or inline functions from this file, or you compile this file
30 // and link it with other works to produce a work based on this file,
31 // this file does not by itself cause the resulting work to be covered by
32 // the GNU General Public License. However the source code for this file
33 // must still be made available in accordance with section (3) of the GNU
34 // General Public License v2.
35 //
36 // This exception does not invalidate any other reasons why a work based
37 // on this file might be covered by the GNU General Public License.
38 // -------------------------------------------
39 // ####ECOSGPLCOPYRIGHTEND####
40 //=============================================================================
41 //#####DESCRIPTIONBEGIN####
42 //
43 // Author(s): wry
44 // Date: 2010-03-16
45 //
46 //####DESCRIPTIONEND####
47 //=============================================================================
48
49 #ifndef CYGFUN_NAND_SAMSUNG_K9_LP
50 #error k9_generic_lp.inl unexpectedly included
51 #endif
52
53 static inline void write_addr_col_lp(cyg_nand_device *ctx, cyg_nand_column_addr col)
54 {
55 // All supported large-page chips are 8-bit, 2112 bytes per page,
56 // column addesses encoded as two bytes.
57 CYG_BYTE addr[2] = { col & 0xff, (col>>8) & 0xff };
58 write_addrbytes(ctx, &addr[0], 2);
59 }
60
61 static inline void write_addr_col_row_lp(cyg_nand_device *ctx,
62 cyg_nand_column_addr c, cyg_uint32 r)
63 {
64 write_addr_col_lp(ctx, c);
65 write_addr_row(ctx, r);
66 }
67
68 static inline void change_read_column_lp(cyg_nand_device *dev, cyg_nand_column_addr col)
69 {
70 write_cmd(dev,0x05);
71 write_addr_col_lp(dev,col);
72 write_cmd(dev,0xe0);
73 // wait tREA before reading further.
74 // This is 18ns, less than an instruction.
75 }
76
77 static inline void change_write_column_lp(cyg_nand_device *dev, cyg_nand_column_addr col)
78 {
79 write_cmd(dev,0x85);
80 write_addr_col_lp(dev,col);
81 // We must wait at least tADL (100ns) before writing further.
82 HAL_DELAY_US(1); // TODO: 1us is a bit wasteful; prefer a tighter sleep duration
83 }
84
85 int nand_k9_read_begin(cyg_nand_device *dev, cyg_nand_page_addr page)
86 {
87 //k9_priv *priv = dev->priv;
88
89 NAND_CHATTER(7,dev,"Reading page %d\n",page);
90 LOCK(dev);
91
92 write_cmd(dev,0x00);
93 write_addr_col_row_lp(dev, 0, page);
94 write_cmd(dev,0x30);
95 wait_ready_or_time(dev, 1, 25 /* tR */);
96 return 0;
97 }
98
99 int nand_k9_read_stride(cyg_nand_device *dev, void * dest, size_t size)
100 {
101 read_data_bulk(dev, dest, size);
102 return 0;
103 }
104
105 int nand_k9_read_finish(cyg_nand_device *dev, void * spare, size_t spare_size)
106 {
107
108 if (spare && spare_size) {
109 change_read_column_lp(dev, 1 << dev->page_bits);
110 read_data_bulk(dev, spare, spare_size);
111 }
112 //k9_reset(dev,5); // Unnecessary.
113 UNLOCK(dev);
114 return 0;
115 }
116
117 int nand_k9_read_part(cyg_nand_device *dev, void *dest,
118 cyg_nand_page_addr page, size_t offset, size_t length)
119 {
120 //k9_priv *priv = dev->priv;
121 NAND_CHATTER(7,dev,"Reading page %d (partial; offset %d, length %d)\n",
122 page, offset, length);
123 LOCK(dev);
124
125 write_cmd(dev,0x00);
126 write_addr_col_row_lp(dev, offset, page);
127 write_cmd(dev,0x30);
128 wait_ready_or_time(dev, 1, 25 /* tR */);
129
130 read_data_bulk(dev, dest, length);
131
132 UNLOCK(dev);
133 return 0;
134 }
135
136 int nand_k9_write_begin(cyg_nand_device *dev, cyg_nand_page_addr page)
137 {
138 k9_priv *priv = dev->priv;
139 // NB: Program with random data input takes a _five_ byte address,
140 // according to spec p24. This doesn't make sense - everything else
141 // about this chip takes a four-byte address - and is contradicted by p32.
142
143 LOCK(dev);
144 priv->pagestash = page;
145 write_cmd(dev,0x80);
146 write_addr_col_row_lp(dev, 0, page);
147
148 return 0;
149 }
150
151 int nand_k9_write_stride(cyg_nand_device *dev, const void * src, size_t size)
152 {
153 write_data_bulk(dev, src, size);
154 return 0;
155 }
156
157 int nand_k9_write_finish(cyg_nand_device *dev, const void * spare, size_t spare_size)
158 {
159 k9_priv *priv = dev->priv;
160 int rv = 0;
161 if (spare && spare_size) {
162 change_write_column_lp(dev, 1 << dev->page_bits);
163 write_data_bulk(dev, spare, spare_size);
164 }
165 write_cmd(dev,0x10);
166 wait_ready_or_status(dev, 1<<6);
167
168 if (read_status(dev) & 1) {
169 NAND_ERROR(dev, "k9fxx08x0x: Programming failed! Page %u", priv->pagestash);
170 rv =-EIO;
171 goto done;
172 } else {
173 NAND_CHATTER(7,dev, "Programmed %u OK\n", priv->pagestash);
174 }
175 done:
176 //k9_reset(dev,5); // Unnecessary.
177 UNLOCK(dev);
178 return rv;
179 }
180
181 #define K9_FACTORY_BAD_COLUMN_ADDR 2048
182
183 // The spec sheet says to check the 1st OOB byte (address 2048) in
184 // both the 1st and 2nd page of the block. If both are 0xFF, the block is OK;
185 // else it's bad.
186 // N.B. This is good for at least K9F1G and K9F2G but might need to be tweaked later.
187 int nand_k9_factorybad_lp(cyg_nand_device *dev, cyg_nand_block_addr blk)
188 {
189 cyg_nand_page_addr page,
190 pagebase = blk * (1<<dev->block_page_bits);
191 const int col = K9_FACTORY_BAD_COLUMN_ADDR;
192 int rv = 0, i;
193
194 LOCK(dev);
195
196 for (i=0; i<2; i++) {
197 page = pagebase+i;
198 write_cmd(dev,0x00);
199 write_addr_col_row_lp(dev, col, page);
200 write_cmd(dev,0x30);
201 wait_ready_or_time(dev, 1, 25 /* tR */);
202 unsigned char t = read_data_1(dev);
203 if (t != 0xff) rv=1;
204 //k9_reset(dev,5); // Unnecessary.
205 }
206
207 UNLOCK(dev);
208 return rv;
209 }
210
211 CYG_NAND_FUNS_V2(nand_k9_funs, nand_k9_devinit,
212 nand_k9_read_begin, nand_k9_read_stride, nand_k9_read_finish,
213 nand_k9_read_part,
214 nand_k9_write_begin, nand_k9_write_stride, nand_k9_write_finish,
215 nand_k9_erase_block, nand_k9_factorybad_lp);
216
217 // key: SUBTYPE( id[1], id[3], // ReadID response, 2nd and 4th bytes
218 // descriptive string,
219 // log2(number of blocks),
220 // log2(total chip size in BYTES),
221 // width of a row address in bytes)
222
223 #ifdef CYGFUN_NAND_SAMSUNG_K9_F2G
224 #define K9F2G08Q0x K9_SUBTYPE(0xaa, 0x15, "K9F2G08Q0x", 11, 28, 3)
225 #define K9F2G08U0x K9_SUBTYPE(0xda, 0x15, "K9F2G08U0x", 11, 28, 3)
226 #endif
227
228 #ifdef CYGFUN_NAND_SAMSUNG_K9_F1G
229 #define K9F1G08U0x K9_SUBTYPE(0xf1, 0x15, "K9F1G08U0x", 10, 27, 2)
230 #endif
231
232 // EOF k9_generic_lp.inl
233