4 * Copyright (C) 2002, 2003 ETC s.r.o.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 * Written by Marcel Telka <marcel@telka.sk>, 2002, 2003.
24 * [1] JEDEC Solid State Technology Association, "Common Flash Interface (CFI)",
25 * September 1999, Order Number: JESD68
26 * [2] Intel Corporation, "Common Flash Interface (CFI) and Command Sets
27 * Application Note 646", April 2000, Order Number: 292204-004
35 #include <flash/cfi.h>
42 cfi_array_free( cfi_array_t *cfi_array )
47 if (cfi_array->cfi_chips) {
50 for (i = 0; i < cfi_array->bus_width; i++) {
51 if (!cfi_array->cfi_chips[i])
54 free( cfi_array->cfi_chips[i]->cfi.device_geometry.erase_block_regions );
55 if (cfi_array->cfi_chips[i]->cfi.identification_string.pri_vendor_tbl)
56 free (cfi_array->cfi_chips[i]->cfi.identification_string.pri_vendor_tbl);
57 free( cfi_array->cfi_chips[i] );
59 free( cfi_array->cfi_chips );
66 cfi_detect( bus_t *bus, uint32_t adr, cfi_array_t **cfi_array )
68 unsigned int bw; /* bus width */
69 unsigned int d; /* data offset */
70 int ba; /* bus width address multiplier */
71 int ma; /* flash mode address multiplier */
74 if (!cfi_array || !bus)
75 return -1; /* invalid parameters */
77 *cfi_array = calloc( 1, sizeof (cfi_array_t) );
79 return -2; /* out of memory */
81 (*cfi_array)->bus = bus;
82 (*cfi_array)->address = adr;
83 if (bus_area( bus, adr, &area ) != URJTAG_STATUS_OK)
84 return -8; /* bus width detection failed */
86 if (bw != 8 && bw != 16 && bw != 32)
87 return -3; /* invalid bus width */
88 (*cfi_array)->bus_width = ba = bw / 8;
89 (*cfi_array)->cfi_chips = calloc( ba, sizeof (cfi_chip_t *) );
90 if (!(*cfi_array)->cfi_chips)
91 return -2; /* out of memory */
93 for (d = 0; d < bw; d += 8) {
94 #define A(off) (adr + (off) * ba * ma)
95 #define D(data) ((data) << d)
96 #define gD(data) (((data) >> d) & 0xFF)
97 #define read1(off) gD(bus_read( bus, A(off) ))
98 #define read2(off) (bus_read_start( bus, A(off) ), gD(bus_read_next( bus, A((off) + 1) )) | gD(bus_read_end( bus )) << 8)
99 #define write1(off,data) bus_write( bus, A(off), D(data) )
101 cfi_query_structure_t *cfi;
103 int ret = -4; /* CFI not detected (Q) */
104 uint16_t pri_vendor_tbl_adr;
106 /* detect CFI capable devices - see Table 1 in [1] */
107 for (ma = 1; ma <= 4; ma *= 2) {
108 write1( CFI_CMD_QUERY_OFFSET, CFI_CMD_QUERY );
110 if (read1(CFI_QUERY_ID_OFFSET) == 'Q') {
111 ret = -5; /* CFI not detected (R) */
112 if (read1(CFI_QUERY_ID_OFFSET + 1) == 'R')
116 write1( 0, CFI_CMD_READ_ARRAY1 );
120 return ret; /* CFI not detected (Q or R) */
122 if (read1(CFI_QUERY_ID_OFFSET + 2) != 'Y') {
123 write1( 0, CFI_CMD_READ_ARRAY1 );
124 return -6; /* CFI not detected (Y) */
127 (*cfi_array)->cfi_chips[d / 8] = calloc( 1, sizeof (cfi_chip_t) );
128 if (!(*cfi_array)->cfi_chips[d / 8]) {
129 write1( 0, CFI_CMD_READ_ARRAY1 );
130 return -2; /* out of memory */
132 cfi = &(*cfi_array)->cfi_chips[d / 8]->cfi;
134 /* Identification string - see Table 6 in [1] */
135 cfi->identification_string.pri_id_code = read2(PRI_VENDOR_ID_OFFSET);
136 cfi->identification_string.pri_vendor_tbl = NULL;
137 cfi->identification_string.alt_id_code = read2(ALT_VENDOR_ID_OFFSET);
138 cfi->identification_string.alt_vendor_tbl = NULL;
140 /* System interface information - see Table 7 in [1] */
141 tmp = read1(VCC_MIN_WEV_OFFSET);
142 cfi->system_interface_info.vcc_min_wev = ((tmp >> 4) & 0xF) * 1000 + (tmp & 0xF) * 100;
143 tmp = read1(VCC_MAX_WEV_OFFSET);
144 cfi->system_interface_info.vcc_max_wev = ((tmp >> 4) & 0xF) * 1000 + (tmp & 0xF) * 100;
145 tmp = read1(VPP_MIN_WEV_OFFSET);
146 cfi->system_interface_info.vpp_min_wev = ((tmp >> 4) & 0xF) * 1000 + (tmp & 0xF) * 100;
147 tmp = read1(VPP_MAX_WEV_OFFSET);
148 cfi->system_interface_info.vpp_max_wev = ((tmp >> 4) & 0xF) * 1000 + (tmp & 0xF) * 100;
150 /* TODO: Add out of range checks for timeouts */
151 tmp = read1(TYP_SINGLE_WRITE_TIMEOUT_OFFSET);
152 cfi->system_interface_info.typ_single_write_timeout = tmp ? (1 << tmp) : 0;
154 tmp = read1(TYP_BUFFER_WRITE_TIMEOUT_OFFSET);
155 cfi->system_interface_info.typ_buffer_write_timeout = tmp ? (1 << tmp) : 0;
157 tmp = read1(TYP_BLOCK_ERASE_TIMEOUT_OFFSET);
158 cfi->system_interface_info.typ_block_erase_timeout = tmp ? (1 << tmp) : 0;
160 tmp = read1(TYP_CHIP_ERASE_TIMEOUT_OFFSET);
161 cfi->system_interface_info.typ_chip_erase_timeout = tmp ? (1 << tmp) : 0;
163 tmp = read1(MAX_SINGLE_WRITE_TIMEOUT_OFFSET);
164 cfi->system_interface_info.max_single_write_timeout =
165 (tmp ? (1 << tmp) : 0) * cfi->system_interface_info.typ_single_write_timeout;
167 tmp = read1(MAX_BUFFER_WRITE_TIMEOUT_OFFSET);
168 cfi->system_interface_info.max_buffer_write_timeout =
169 (tmp ? (1 << tmp) : 0) * cfi->system_interface_info.typ_buffer_write_timeout;
171 tmp = read1(MAX_BLOCK_ERASE_TIMEOUT_OFFSET);
172 cfi->system_interface_info.max_block_erase_timeout =
173 (tmp ? (1 << tmp) : 0) * cfi->system_interface_info.typ_block_erase_timeout;
175 tmp = read1(MAX_CHIP_ERASE_TIMEOUT_OFFSET);
176 cfi->system_interface_info.max_chip_erase_timeout =
177 (tmp ? (1 << tmp) : 0) * cfi->system_interface_info.typ_chip_erase_timeout;
179 /* Device geometry - see Table 8 in [1] */
180 /* TODO: Add out of range check */
181 cfi->device_geometry.device_size = 1 << read1(DEVICE_SIZE_OFFSET);
183 cfi->device_geometry.device_interface = read2(FLASH_DEVICE_INTERFACE_OFFSET);
185 /* TODO: Add out of range check */
186 cfi->device_geometry.max_bytes_write = 1 << read2(MAX_BYTES_WRITE_OFFSET);
188 tmp = cfi->device_geometry.number_of_erase_regions = read1(NUMBER_OF_ERASE_REGIONS_OFFSET);
190 cfi->device_geometry.erase_block_regions = malloc( tmp * sizeof (cfi_erase_block_region_t) );
191 if (!cfi->device_geometry.erase_block_regions) {
192 write1( 0, CFI_CMD_READ_ARRAY1 );
193 return -2; /* out of memory */
200 for (i = 0, a = ERASE_BLOCK_REGION_OFFSET; i < tmp; i++, a += 4) {
201 uint32_t y = read2(a);
202 uint32_t z = read2(a + 2) << 8;
205 cfi->device_geometry.erase_block_regions[i].erase_block_size = z;
206 cfi->device_geometry.erase_block_regions[i].number_of_erase_blocks = y + 1;
210 pri_vendor_tbl_adr = read2(PRI_VENDOR_TABLE_ADR_OFFSET);
212 /* AMD CFI Primary Vendor-Specific Extended Query Table - see [3] and [4] */
213 if (cfi->identification_string.pri_id_code == CFI_VENDOR_AMD_SCS
214 && pri_vendor_tbl_adr != 0) {
215 amd_pri_extened_query_structure_t *pri_vendor_tbl;
216 uint8_t major_version;
217 uint8_t minor_version;
218 uint8_t num_of_banks;
221 #define A(off) (adr + (pri_vendor_tbl_adr + off) * ba * ma)
223 if (read1 (0) != 'P' || read1 (1) != 'R' || read1 (2) != 'I') {
224 write1 (0, CFI_CMD_READ_ARRAY1);
225 return -9; /* CFI primary vendor table not detected */
228 major_version = read1 (MAJOR_VERSION_OFFSET);
229 minor_version = read1 (MINOR_VERSION_OFFSET);
230 if (major_version > '1' || (major_version == '1' && minor_version >= '3'))
231 num_of_banks = read1 (BANK_ORGANIZATION_OFFSET);
234 pri_vendor_tbl = (amd_pri_extened_query_structure_t *)
235 calloc (1, sizeof (amd_pri_extened_query_structure_t)
236 + num_of_banks * sizeof (uint8_t));
237 if (!pri_vendor_tbl) {
238 write1 (0, CFI_CMD_READ_ARRAY1);
239 return -2; /* out of memory */
242 if (major_version > '1' || (major_version == '1' && minor_version >= '0')) {
243 pri_vendor_tbl->major_version = major_version;
244 pri_vendor_tbl->minor_version = minor_version;
245 pri_vendor_tbl->address_sensitive_unlock = read1 (ADDRESS_SENSITIVE_UNLOCK_OFFSET);
246 pri_vendor_tbl->erase_suspend = read1 (ERASE_SUSPEND_OFFSET);
247 pri_vendor_tbl->sector_protect = read1 (SECTOR_PROTECT_OFFSET);
248 pri_vendor_tbl->sector_temporary_unprotect = read1 (SECTOR_TEMPORARY_UNPROTECT_OFFSET);
249 pri_vendor_tbl->sector_protect_scheme = read1 (SECTOR_PROTECT_SCHEME_OFFSET);
250 pri_vendor_tbl->simultaneous_operation = read1 (SIMULTANEOUS_OPERATION_OFFSET);
251 pri_vendor_tbl->burst_mode_type = read1 (BURST_MODE_TYPE_OFFSET);
252 pri_vendor_tbl->page_mode_type = read1 (PAGE_MODE_TYPE_OFFSET);
254 if (major_version > '1' || (major_version == '1' && minor_version >= '1')) {
255 tmp = read1 (ACC_MIN_OFFSET);
256 pri_vendor_tbl->acc_min = ((tmp >> 4) & 0xF) * 1000 + (tmp & 0xF) * 100;
257 tmp = read1 (ACC_MAX_OFFSET);
258 pri_vendor_tbl->acc_max = ((tmp >> 4) & 0xF) * 1000 + (tmp & 0xF) * 100;
259 pri_vendor_tbl->top_bottom_sector_flag = read1 (TOP_BOTTOM_SECTOR_FLAG_OFFSET);
261 if (major_version > '1' || (major_version == '1' && minor_version >= '2'))
262 pri_vendor_tbl->program_suspend = read1 (PROGRAM_SUSPEND_OFFSET);
263 if (major_version > '1' || (major_version == '1' && minor_version >= '3')) {
264 if (pri_vendor_tbl->simultaneous_operation)
265 pri_vendor_tbl->bank_organization = read1 (BANK_ORGANIZATION_OFFSET);
267 pri_vendor_tbl->bank_organization = 0;
268 for (i = 0; i < pri_vendor_tbl->bank_organization; i++)
269 pri_vendor_tbl->bank_region_info[i] = read1 (BANK_REGION_INFO_OFFSET + i * sizeof (uint8_t));
271 if (major_version > '1' || (major_version == '1' && minor_version >= '4')) {
272 pri_vendor_tbl->unlock_bypass = read1 (UNLOCK_BYPASS_OFFSET);
273 tmp = read1 (SECSI_SECTOR_SIZE_OFFSET);
274 pri_vendor_tbl->secsi_sector_size = tmp ? (1 << tmp) : 0;
275 tmp = read1 (EMBEDDED_HWRST_TIMEOUT_MAX_OFFSET);
276 pri_vendor_tbl->embedded_hwrst_timeout_max = tmp ? (1 << tmp) : 0;
277 tmp = read1 (NON_EMBEDDED_HWRST_TIMEOUT_MAX_OFFSET);
278 pri_vendor_tbl->non_embedded_hwrst_timeout_max = tmp ? (1 << tmp) : 0;
279 tmp = read1 (ERASE_SUSPEND_TIMEOUT_MAX_OFFSET);
280 pri_vendor_tbl->erase_suspend_timeout_max = tmp ? (1 << tmp) : 0;
281 tmp = read1 (PROGRAM_SUSPEND_TIMEOUT_MAX_OFFSET);
282 pri_vendor_tbl->program_suspend_timeout_max = tmp ? (1 << tmp) : 0;
285 cfi->identification_string.pri_vendor_tbl = (void *) pri_vendor_tbl;
288 #define A(off) (adr + (off) * ba * ma)
290 /* Reverse the order of erase block region information for top boot devices. */
291 if ((major_version > '1' || (major_version == '1' && minor_version >= '1'))
292 && pri_vendor_tbl->top_bottom_sector_flag == 0x3)
295 uint32_t n = cfi->device_geometry.number_of_erase_regions;
297 for (i = 0; i < n / 2; i++) {
298 z = cfi->device_geometry.erase_block_regions[i].erase_block_size;
299 y = cfi->device_geometry.erase_block_regions[i].number_of_erase_blocks;
300 cfi->device_geometry.erase_block_regions[i].erase_block_size
301 = cfi->device_geometry.erase_block_regions[n - i - 1].erase_block_size;
302 cfi->device_geometry.erase_block_regions[i].number_of_erase_blocks
303 = cfi->device_geometry.erase_block_regions[n - i - 1].number_of_erase_blocks;
304 cfi->device_geometry.erase_block_regions[n - i - 1].erase_block_size = z;
305 cfi->device_geometry.erase_block_regions[n - i - 1].number_of_erase_blocks = y;
310 /* TODO: Intel Primary Algorithm Extended Query Table - see Table 5. in [2] */
313 write1( 0, CFI_CMD_READ_ARRAY1 );
322 switch (cfi->device_geometry.device_interface) {
323 case CFI_INTERFACE_X8:
325 return -7; /* error in device detection */
326 (*cfi_array)->cfi_chips[d / 8]->width = 1;
328 case CFI_INTERFACE_X16:
330 return -7; /* error in device detection */
331 (*cfi_array)->cfi_chips[d / 8]->width = 2;
334 case CFI_INTERFACE_X8_X16:
335 if (ma != 1 && ma != 2)
336 return -7; /* error in device detection */
337 (*cfi_array)->cfi_chips[d / 8]->width = 2 / ma;
341 case CFI_INTERFACE_X32:
343 return -7; /* error in device detection */
344 (*cfi_array)->cfi_chips[d / 8]->width = 4;
347 case CFI_INTERFACE_X16_X32:
348 if (ma != 1 && ma != 2)
349 return -7; /* error in device detection */
350 (*cfi_array)->cfi_chips[d / 8]->width = 4 / ma;
357 return -7; /* error in device detection */