Mercurial > nand-ecoscentric
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 |
