1 /* $NetBSD: cfi.c,v 1.6 2011/08/02 03:37:25 cliff Exp $ */ 2 /*- 3 * Copyright (c) 2011 The NetBSD Foundation, Inc. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to The NetBSD Foundation 7 * by Cliff Neighbors. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "opt_flash.h" 32 #include "opt_nor.h" 33 #include "opt_cfi.h" 34 35 #include <sys/cdefs.h> 36 __KERNEL_RCSID(0, "$NetBSD: cfi.c,v 1.6 2011/08/02 03:37:25 cliff Exp $"); 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/cdefs.h> 41 #include <sys/device.h> 42 #include <sys/endian.h> 43 44 #include <sys/bus.h> 45 46 #include <dev/nor/nor.h> 47 #include <dev/nor/cfi.h> 48 #include <dev/nor/cfi_0002.h> 49 50 51 static bool cfi_chip_query(struct cfi * const); 52 static int cfi_scan_media(device_t self, struct nor_chip *chip); 53 static void cfi_init(device_t); 54 static void cfi_select(device_t, bool); 55 static void cfi_read_1(device_t, flash_off_t, uint8_t *); 56 static void cfi_read_2(device_t, flash_off_t, uint16_t *); 57 static void cfi_read_4(device_t, flash_off_t, uint32_t *); 58 static void cfi_read_buf_1(device_t, flash_off_t, uint8_t *, size_t); 59 static void cfi_read_buf_2(device_t, flash_off_t, uint16_t *, size_t); 60 static void cfi_read_buf_4(device_t, flash_off_t, uint32_t *, size_t); 61 static void cfi_write_1(device_t, flash_off_t, uint8_t); 62 static void cfi_write_2(device_t, flash_off_t, uint16_t); 63 static void cfi_write_4(device_t, flash_off_t, uint32_t); 64 static void cfi_write_buf_1(device_t, flash_off_t, const uint8_t *, size_t); 65 static void cfi_write_buf_2(device_t, flash_off_t, const uint16_t *, size_t); 66 static void cfi_write_buf_4(device_t, flash_off_t, const uint32_t *, size_t); 67 static void cfi_jedec_id_1(struct cfi * const ); 68 static void cfi_jedec_id_2(struct cfi * const ); 69 static void cfi_jedec_id_4(struct cfi * const ); 70 static bool cfi_jedec_id(struct cfi * const); 71 static bool cfi_emulate(struct cfi * const); 72 static const struct cfi_jedec_tab * cfi_jedec_search(struct cfi *); 73 static void cfi_jedec_fill(struct cfi * const, 74 const struct cfi_jedec_tab *); 75 #if defined(CFI_DEBUG_JEDEC) || defined(CFI_DEBUG_QRY) 76 static void cfi_hexdump(flash_off_t, void * const, u_int, u_int); 77 #endif 78 79 80 81 /* 82 * NOTE these opmode tables are informed by "Table 1. CFI Query Read" 83 * in Intel "Common Flash Interface (CFI) and Command Sets" 84 * Application Note 646, April 2000 85 * 86 * Assume the byte order of the flash (and of the signature there) 87 * is the same as host byte order. The Intel App. Note describes the 88 * little endian variant. 89 * 90 * XXX down-sized, interleaved & multi-chip opmodes not yet supported 91 */ 92 93 #if BYTE_ORDER == BIG_ENDIAN 94 /* BIG ENDIAN host */ 95 /* 1-byte access */ 96 static const struct cfi_opmodes cfi_opmodes_1[] = { 97 { 0, 0, 0, 0x10, 3, "QRY", "x8 device operating in 8-bit mode" }, 98 }; 99 100 /* 2-byte access */ 101 static const struct cfi_opmodes cfi_opmodes_2[] = { 102 { 1, 1, 0, 0x20, 6, "\0Q\0R\0Y", 103 "x16 device operating in 16-bit mode" }, 104 }; 105 106 /* 4-byte access */ 107 static const struct cfi_opmodes cfi_opmodes_4[] = { 108 { 2, 2, 0, 0x40, 12, "\0\0\0Q\0\0\0R\0\0\0Y", 109 "x32 device operating in 32-bit mode" }, 110 }; 111 #else 112 /* LITTLE ENDIAN host */ 113 /* 1-byte access */ 114 static const struct cfi_opmodes cfi_opmodes_1[] = { 115 { 0, 0, 0, 0x10, 3, "QRY", "x8 device operating in 8-bit mode" }, 116 }; 117 118 /* 2-byte access */ 119 static const struct cfi_opmodes cfi_opmodes_2[] = { 120 { 1, 1, 0, 0x20, 6, "Q\0R\0Y\0", 121 "x16 device operating in 16-bit mode" }, 122 }; 123 124 /* 4-byte access */ 125 static const struct cfi_opmodes cfi_opmodes_4[] = { 126 { 2, 2, 0, 0x40, 12, "Q\0\0\0R\0\0\0Y\0\0\0", 127 "x32 device operating in 32-bit mode" }, 128 }; 129 #endif 130 131 132 #define LOG2_64K 16 133 #define LOG2_128K 17 134 #define LOG2_256K 18 135 #define LOG2_512K 19 136 #define LOG2_1M 20 137 #define LOG2_2M 21 138 #define LOG2_4M 22 139 #define LOG2_8M 23 140 #define LOG2_16M 24 141 #define LOG2_32M 25 142 #define LOG2_64M 26 143 #define LOG2_128M 27 144 #define LOG2_256M 28 145 #define LOG2_512M 29 146 #define LOG2_1G 30 147 #define LOG2_2G 31 148 const struct cfi_jedec_tab cfi_jedec_tab[] = { 149 { 150 .jt_name = "Pm39LV512", 151 .jt_mid = 0x9d, 152 .jt_did = 0x1b, 153 .jt_id_pri = 0, /* XXX */ 154 .jt_id_alt = 0, /* XXX */ 155 .jt_device_size = LOG2_64K, 156 .jt_interface_code_desc = CFI_IFCODE_X8, 157 .jt_erase_blk_regions = 1, 158 .jt_erase_blk_info = { 159 { 4096/256, (64/4)-1 }, 160 }, 161 .jt_write_word_time_typ = 40, 162 .jt_write_nbyte_time_typ = 0, 163 .jt_erase_blk_time_typ = 55, 164 .jt_erase_chip_time_typ = 55, 165 .jt_write_word_time_max = 1, 166 .jt_write_nbyte_time_max = 0, 167 .jt_erase_blk_time_max = 1, 168 .jt_erase_chip_time_max = 1, 169 .jt_opmode = &cfi_opmodes_1[0], 170 }, 171 { 172 .jt_name = "Pm39LV010", 173 .jt_mid = 0x9d, 174 .jt_did = 0x1c, 175 .jt_id_pri = 0, /* XXX */ 176 .jt_id_alt = 0, /* XXX */ 177 .jt_device_size = LOG2_128K, 178 .jt_interface_code_desc = CFI_IFCODE_X8, 179 .jt_erase_blk_regions = 1, 180 .jt_erase_blk_info = { 181 { 4096/256, (128/4)-1 }, 182 }, 183 .jt_write_word_time_typ = 40, 184 .jt_write_nbyte_time_typ = 0, 185 .jt_erase_blk_time_typ = 55, 186 .jt_erase_chip_time_typ = 55, 187 .jt_write_word_time_max = 1, 188 .jt_write_nbyte_time_max = 0, 189 .jt_erase_blk_time_max = 1, 190 .jt_erase_chip_time_max = 1, 191 .jt_opmode = &cfi_opmodes_1[0], 192 }, 193 }; 194 195 196 const struct nor_interface nor_interface_cfi = { 197 .scan_media = cfi_scan_media, 198 .init = cfi_init, 199 .select = cfi_select, 200 .read_1 = cfi_read_1, 201 .read_2 = cfi_read_2, 202 .read_4 = cfi_read_4, 203 .read_buf_1 = cfi_read_buf_1, 204 .read_buf_2 = cfi_read_buf_2, 205 .read_buf_4 = cfi_read_buf_4, 206 .write_1 = cfi_write_1, 207 .write_2 = cfi_write_2, 208 .write_4 = cfi_write_4, 209 .write_buf_1 = cfi_write_buf_1, 210 .write_buf_2 = cfi_write_buf_2, 211 .write_buf_4 = cfi_write_buf_4, 212 .read_page = NULL, /* cmdset */ 213 .program_page = NULL, /* cmdset */ 214 .busy = NULL, 215 .private = NULL, 216 .access_width = -1, 217 .part_info = NULL, 218 .part_num = -1, 219 }; 220 221 222 /* only data[7..0] are used regardless of chip width */ 223 #define cfi_unpack_1(n) ((n) & 0xff) 224 225 /* construct uint16_t */ 226 #define cfi_unpack_2(b0, b1) \ 227 ((cfi_unpack_1(b1) << 8) | cfi_unpack_1(b0)) 228 229 /* construct uint32_t */ 230 #define cfi_unpack_4(b0, b1, b2, b3) \ 231 ((cfi_unpack_1(b3) << 24) | \ 232 (cfi_unpack_1(b2) << 16) | \ 233 (cfi_unpack_1(b1) << 8) | \ 234 (cfi_unpack_1(b0))) 235 236 #define cfi_unpack_qry(qryp, data) \ 237 do { \ 238 (qryp)->qry[0] = cfi_unpack_1(data[0x10]); \ 239 (qryp)->qry[1] = cfi_unpack_1(data[0x11]); \ 240 (qryp)->qry[2] = cfi_unpack_1(data[0x12]); \ 241 (qryp)->id_pri = cfi_unpack_2(data[0x13], data[0x14]); \ 242 (qryp)->addr_pri = cfi_unpack_2(data[0x15], data[0x16]); \ 243 (qryp)->id_alt = cfi_unpack_2(data[0x17], data[0x18]); \ 244 (qryp)->addr_alt = cfi_unpack_2(data[0x19], data[0x1a]); \ 245 (qryp)->vcc_min = cfi_unpack_1(data[0x1b]); \ 246 (qryp)->vcc_max = cfi_unpack_1(data[0x1c]); \ 247 (qryp)->vpp_min = cfi_unpack_1(data[0x1d]); \ 248 (qryp)->vpp_max = cfi_unpack_1(data[0x1e]); \ 249 (qryp)->write_word_time_typ = cfi_unpack_1(data[0x1f]); \ 250 (qryp)->write_nbyte_time_typ = cfi_unpack_1(data[0x20]); \ 251 (qryp)->erase_blk_time_typ = cfi_unpack_1(data[0x21]); \ 252 (qryp)->erase_chip_time_typ = cfi_unpack_1(data[0x22]); \ 253 (qryp)->write_word_time_max = cfi_unpack_1(data[0x23]); \ 254 (qryp)->write_nbyte_time_max = cfi_unpack_1(data[0x24]); \ 255 (qryp)->erase_blk_time_max = cfi_unpack_1(data[0x25]); \ 256 (qryp)->erase_chip_time_max = cfi_unpack_1(data[0x26]); \ 257 (qryp)->device_size = cfi_unpack_1(data[0x27]); \ 258 (qryp)->interface_code_desc = \ 259 cfi_unpack_2(data[0x28], data[0x29]); \ 260 (qryp)->write_nbyte_size_max = \ 261 cfi_unpack_2(data[0x2a], data[0x2b]); \ 262 (qryp)->erase_blk_regions = cfi_unpack_1(data[0x2c]); \ 263 u_int _i = 0x2d; \ 264 const u_int _n = (qryp)->erase_blk_regions; \ 265 KASSERT(_n <= 4); \ 266 for (u_int _r = 0; _r < _n; _r++, _i+=4) { \ 267 (qryp)->erase_blk_info[_r].y = \ 268 cfi_unpack_2(data[_i+0], data[_i+1]); \ 269 (qryp)->erase_blk_info[_r].z = \ 270 cfi_unpack_2(data[_i+2], data[_i+3]); \ 271 } \ 272 } while (0) 273 274 #define cfi_unpack_pri_0002(qryp, data) \ 275 do { \ 276 (qryp)->pri.cmd_0002.pri[0] = cfi_unpack_1(data[0x00]); \ 277 (qryp)->pri.cmd_0002.pri[1] = cfi_unpack_1(data[0x01]); \ 278 (qryp)->pri.cmd_0002.pri[2] = cfi_unpack_1(data[0x02]); \ 279 (qryp)->pri.cmd_0002.version_maj = cfi_unpack_1(data[0x03]); \ 280 (qryp)->pri.cmd_0002.version_min = cfi_unpack_1(data[0x04]); \ 281 (qryp)->pri.cmd_0002.asupt = cfi_unpack_1(data[0x05]); \ 282 (qryp)->pri.cmd_0002.erase_susp = cfi_unpack_1(data[0x06]); \ 283 (qryp)->pri.cmd_0002.sector_prot = cfi_unpack_1(data[0x07]); \ 284 (qryp)->pri.cmd_0002.tmp_sector_unprot = \ 285 cfi_unpack_1(data[0x08]); \ 286 (qryp)->pri.cmd_0002.sector_prot_scheme = \ 287 cfi_unpack_1(data[0x09]); \ 288 (qryp)->pri.cmd_0002.simul_op = cfi_unpack_1(data[0x0a]); \ 289 (qryp)->pri.cmd_0002.burst_mode_type = cfi_unpack_1(data[0x0b]);\ 290 (qryp)->pri.cmd_0002.page_mode_type = cfi_unpack_1(data[0x0c]); \ 291 (qryp)->pri.cmd_0002.acc_min = cfi_unpack_1(data[0x0d]); \ 292 (qryp)->pri.cmd_0002.acc_max = cfi_unpack_1(data[0x0e]); \ 293 (qryp)->pri.cmd_0002.wp_prot = cfi_unpack_1(data[0x0f]); \ 294 /* XXX 1.3 stops here */ \ 295 (qryp)->pri.cmd_0002.prog_susp = cfi_unpack_1(data[0x10]); \ 296 (qryp)->pri.cmd_0002.unlock_bypass = cfi_unpack_1(data[0x11]); \ 297 (qryp)->pri.cmd_0002.sss_size = cfi_unpack_1(data[0x12]); \ 298 (qryp)->pri.cmd_0002.soft_feat = cfi_unpack_1(data[0x13]); \ 299 (qryp)->pri.cmd_0002.page_size = cfi_unpack_1(data[0x14]); \ 300 (qryp)->pri.cmd_0002.erase_susp_time_max = \ 301 cfi_unpack_1(data[0x15]); \ 302 (qryp)->pri.cmd_0002.prog_susp_time_max = \ 303 cfi_unpack_1(data[0x16]); \ 304 (qryp)->pri.cmd_0002.embhwrst_time_max = \ 305 cfi_unpack_1(data[0x38]); \ 306 (qryp)->pri.cmd_0002.hwrst_time_max = \ 307 cfi_unpack_1(data[0x39]); \ 308 } while (0) 309 310 #define CFI_QRY_UNPACK_COMMON(cfi, data, type, found) \ 311 do { \ 312 struct cfi_query_data * const qryp = &cfi->cfi_qry_data; \ 313 \ 314 memset(qryp, 0, sizeof(*qryp)); \ 315 cfi_unpack_qry(qryp, data); \ 316 \ 317 switch (qryp->id_pri) { \ 318 case 0x0002: \ 319 if ((cfi_unpack_1(data[qryp->addr_pri + 0]) == 'P') && \ 320 (cfi_unpack_1(data[qryp->addr_pri + 1]) == 'R') && \ 321 (cfi_unpack_1(data[qryp->addr_pri + 2]) == 'I')) { \ 322 type *pri_data = &data[qryp->addr_pri]; \ 323 cfi_unpack_pri_0002(qryp, pri_data); \ 324 found = true; \ 325 break; \ 326 } \ 327 default: \ 328 printf("%s: unsupported id_pri=%#x\n", \ 329 __func__, qryp->id_pri); \ 330 break; /* unknown command set */ \ 331 } \ 332 } while (0) 333 334 #ifdef CFI_DEBUG_QRY 335 # define CFI_DUMP_QRY(off, p, sz, stride) \ 336 do { \ 337 printf("%s: QRY data\n", __func__); \ 338 cfi_hexdump(off, p, sz, stride); \ 339 } while (0) 340 #else 341 # define CFI_DUMP_QRY(off, p, sz, stride) 342 #endif 343 344 #ifdef CFI_DEBUG_JEDEC 345 # define CFI_DUMP_JEDEC(off, p, sz, stride) \ 346 do { \ 347 printf("%s: JEDEC data\n", __func__); \ 348 cfi_hexdump(off, p, sz, stride); \ 349 } while (0) 350 #else 351 # define CFI_DUMP_JEDEC(off, p, sz, stride) 352 #endif 353 354 355 /* 356 * cfi_chip_query_opmode - determine operational mode based on QRY signature 357 */ 358 static bool 359 cfi_chip_query_opmode(struct cfi *cfi, uint8_t *data, 360 const struct cfi_opmodes *tab, u_int nentries) 361 { 362 for (u_int i=0; i < nentries; i++) { 363 if (memcmp(&data[tab[i].qsa], tab[i].sig, tab[i].len) == 0) { 364 cfi->cfi_opmode = &tab[i]; 365 return true; 366 } 367 } 368 return false; 369 } 370 371 static bool 372 cfi_chip_query_1(struct cfi * const cfi) 373 { 374 uint8_t data[0x80]; 375 376 bus_space_read_region_1(cfi->cfi_bst, cfi->cfi_bsh, 0, data, 377 __arraycount(data)); 378 379 CFI_DUMP_QRY(0, data, sizeof(data), 1); 380 381 bool found = cfi_chip_query_opmode(cfi, data, cfi_opmodes_1, 382 __arraycount(cfi_opmodes_1)); 383 384 if (found) { 385 CFI_QRY_UNPACK_COMMON(cfi, data, uint8_t, found); 386 } 387 388 return found; 389 } 390 391 static bool 392 cfi_chip_query_2(struct cfi * const cfi) 393 { 394 uint16_t data[0x80]; 395 396 bus_space_read_region_2(cfi->cfi_bst, cfi->cfi_bsh, 0, data, 397 __arraycount(data)); 398 399 CFI_DUMP_QRY(0, data, sizeof(data), 2); 400 401 bool found = cfi_chip_query_opmode(cfi, (uint8_t *)data, 402 cfi_opmodes_2, __arraycount(cfi_opmodes_2)); 403 404 if (found) { 405 CFI_QRY_UNPACK_COMMON(cfi, data, uint16_t, found); 406 } 407 408 return found; 409 } 410 411 static bool 412 cfi_chip_query_4(struct cfi * const cfi) 413 { 414 uint32_t data[0x80]; 415 416 bus_space_read_region_4(cfi->cfi_bst, cfi->cfi_bsh, 0, data, 417 __arraycount(data)); 418 419 CFI_DUMP_QRY(0, data, sizeof(data), 4); 420 421 bool found = cfi_chip_query_opmode(cfi, (uint8_t *)data, 422 cfi_opmodes_4, __arraycount(cfi_opmodes_4)); 423 424 if (found) { 425 CFI_QRY_UNPACK_COMMON(cfi, data, uint32_t, found); 426 } 427 428 return found; 429 } 430 431 static bool 432 cfi_chip_query_8(struct cfi * const cfi) 433 { 434 #ifdef NOTYET 435 uint64_t data[0x80]; 436 437 bus_space_read_region_8(cfi->cfi_bst, cfi->cfi_bsh, 0, data, 438 __arraycount(data)); 439 440 CFI_DUMP_QRY(0, data, sizeof(data), 8); 441 442 bool found = cfi_chip_query_opmode(cfi, (uint8_t *)data, 443 cfi_opmodes_8, __arraycount(cfi_opmodes_8)); 444 445 if (found) { 446 CFI_QRY_UNPACK_COMMON(cfi, data, uint64_t, found); 447 } 448 449 return found; 450 #else 451 return false; 452 #endif 453 } 454 455 /* 456 * cfi_chip_query - detect a CFI chip 457 * 458 * fill in the struct cfi as we discover what's there 459 */ 460 static bool 461 cfi_chip_query(struct cfi * const cfi) 462 { 463 bool found = false; 464 const bus_size_t cfi_query_offset[] = { 465 CFI_QUERY_MODE_ADDRESS, 466 CFI_QUERY_MODE_ALT_ADDRESS 467 }; 468 469 KASSERT(cfi != NULL); 470 KASSERT(cfi->cfi_bst != NULL); 471 472 for (int j=0; !found && j < __arraycount(cfi_query_offset); j++) { 473 474 cfi_reset_default(cfi); 475 cfi_cmd(cfi, cfi_query_offset[j], CFI_QUERY_DATA); 476 477 switch(cfi->cfi_portwidth) { 478 case 0: 479 found = cfi_chip_query_1(cfi); 480 break; 481 case 1: 482 found = cfi_chip_query_2(cfi); 483 break; 484 case 2: 485 found = cfi_chip_query_4(cfi); 486 break; 487 case 3: 488 found = cfi_chip_query_8(cfi); 489 break; 490 default: 491 panic("%s: bad portwidth %d\n", 492 __func__, cfi->cfi_portwidth); 493 } 494 } 495 496 if (found) 497 cfi->cfi_emulated = false; 498 499 return found; 500 } 501 502 /* 503 * cfi_probe - search for a CFI NOR trying various port & chip widths 504 * 505 * - gather CFI QRY and PRI data 506 * - gather JEDEC ID data 507 * - if cfi_chip_query() fails, emulate CFI using table data if possible, 508 * otherwise fail. 509 * 510 * NOTE: 511 * striped NOR chips design not supported yet, 512 * so force portwidth=chipwidth for now 513 * eventually permute portwidth seperately 514 */ 515 bool 516 cfi_probe(struct cfi * const cfi) 517 { 518 bool found; 519 520 KASSERT(cfi != NULL); 521 522 for (u_int cw = 0; cw < 3; cw++) { 523 cfi->cfi_portwidth = /* XXX */ 524 cfi->cfi_chipwidth = cw; 525 found = cfi_chip_query(cfi); 526 cfi_jedec_id(cfi); 527 if (! found) 528 found = cfi_emulate(cfi); 529 if (found) 530 break; 531 } 532 533 cfi_reset_default(cfi); /* exit QRY mode */ 534 return found; 535 } 536 537 bool 538 cfi_identify(struct cfi * const cfi) 539 { 540 const bus_space_tag_t bst = cfi->cfi_bst; 541 const bus_space_handle_t bsh = cfi->cfi_bsh; 542 bool found; 543 544 KASSERT(cfi != NULL); 545 KASSERT(bst != NULL); 546 547 memset(cfi, 0, sizeof(struct cfi)); /* XXX clean slate */ 548 cfi->cfi_bst = bst; /* restore bus space */ 549 cfi->cfi_bsh = bsh; /* " " " */ 550 551 found = cfi_probe(cfi); 552 553 cfi_reset_default(cfi); /* exit QRY mode */ 554 555 return found; 556 } 557 558 static int 559 cfi_scan_media(device_t self, struct nor_chip *chip) 560 { 561 struct nor_softc *sc = device_private(self); 562 KASSERT(sc != NULL); 563 KASSERT(sc->sc_nor_if != NULL); 564 struct cfi * const cfi = (struct cfi * const)sc->sc_nor_if->private; 565 KASSERT(cfi != NULL); 566 567 sc->sc_nor_if->access_width = cfi->cfi_portwidth; 568 569 chip->nc_manf_id = cfi->cfi_id_data.id_mid; 570 chip->nc_dev_id = cfi->cfi_id_data.id_did[0]; /* XXX 3 words */ 571 chip->nc_size = 1 << cfi->cfi_qry_data.device_size; 572 573 /* size of line for Read Buf command */ 574 chip->nc_line_size = 1 << cfi->cfi_qry_data.pri.cmd_0002.page_size; 575 576 /* 577 * size of erase block 578 * XXX depends on erase region 579 */ 580 chip->nc_num_luns = 1; 581 chip->nc_lun_blocks = cfi->cfi_qry_data.erase_blk_info[0].y + 1; 582 chip->nc_block_size = cfi->cfi_qry_data.erase_blk_info[0].z * 256; 583 584 switch (cfi->cfi_qry_data.id_pri) { 585 case 0x0002: 586 cfi_0002_init(sc, cfi, chip); 587 break; 588 default: 589 aprint_error_dev(self, "unsupported CFI cmdset %#04x\n", 590 cfi->cfi_qry_data.id_pri); 591 return -1; 592 } 593 594 return 0; 595 } 596 597 void 598 cfi_init(device_t self) 599 { 600 /* nothing */ 601 } 602 603 static void 604 cfi_select(device_t self, bool select) 605 { 606 /* nothing */ 607 } 608 609 static void 610 cfi_read_1(device_t self, flash_off_t offset, uint8_t *datap) 611 { 612 } 613 614 static void 615 cfi_read_2(device_t self, flash_off_t offset, uint16_t *datap) 616 { 617 } 618 619 static void 620 cfi_read_4(device_t self, flash_off_t offset, uint32_t *datap) 621 { 622 } 623 624 static void 625 cfi_read_buf_1(device_t self, flash_off_t offset, uint8_t *datap, size_t size) 626 { 627 } 628 629 static void 630 cfi_read_buf_2(device_t self, flash_off_t offset, uint16_t *datap, size_t size) 631 { 632 } 633 634 static void 635 cfi_read_buf_4(device_t self, flash_off_t offset, uint32_t *datap, size_t size) 636 { 637 } 638 639 static void 640 cfi_write_1(device_t self, flash_off_t offset, uint8_t data) 641 { 642 } 643 644 static void 645 cfi_write_2(device_t self, flash_off_t offset, uint16_t data) 646 { 647 } 648 649 static void 650 cfi_write_4(device_t self, flash_off_t offset, uint32_t data) 651 { 652 } 653 654 static void 655 cfi_write_buf_1(device_t self, flash_off_t offset, const uint8_t *datap, 656 size_t size) 657 { 658 } 659 660 static void 661 cfi_write_buf_2(device_t self, flash_off_t offset, const uint16_t *datap, 662 size_t size) 663 { 664 } 665 666 static void 667 cfi_write_buf_4(device_t self, flash_off_t offset, const uint32_t *datap, 668 size_t size) 669 { 670 } 671 672 void 673 cfi_cmd(struct cfi * const cfi, bus_size_t off, uint32_t val) 674 { 675 const bus_space_tag_t bst = cfi->cfi_bst; 676 bus_space_handle_t bsh = cfi->cfi_bsh; 677 678 off <<= cfi->cfi_portwidth; 679 680 DPRINTF(("%s: %p %x %x %x\n", __func__, bst, bsh, off, val)); 681 682 switch(cfi->cfi_portwidth) { 683 case 0: 684 bus_space_write_1(bst, bsh, off, (uint8_t)val); 685 break; 686 case 1: 687 bus_space_write_2(bst, bsh, off, val); 688 break; 689 case 2: 690 bus_space_write_4(bst, bsh, off, (uint32_t)val); 691 break; 692 #ifdef NOTYET 693 case 3: 694 bus_space_write_4(bst, bsh, off, (uint64_t)val); 695 break; 696 #endif 697 default: 698 panic("%s: bad portwidth %d bytes\n", 699 __func__, 1 << cfi->cfi_portwidth); 700 } 701 } 702 703 /* 704 * cfi_reset_default - when we don't know which command will work, use both 705 */ 706 void 707 cfi_reset_default(struct cfi * const cfi) 708 { 709 cfi_cmd(cfi, CFI_ADDRESS_ANY, CFI_RESET_DATA); 710 cfi_cmd(cfi, CFI_ADDRESS_ANY, CFI_ALT_RESET_DATA); 711 } 712 713 /* 714 * cfi_reset_std - use standard reset command 715 */ 716 void 717 cfi_reset_std(struct cfi * const cfi) 718 { 719 cfi_cmd(cfi, CFI_ADDRESS_ANY, CFI_RESET_DATA); 720 } 721 722 /* 723 * cfi_reset_alt - use "alternate" reset command 724 */ 725 void 726 cfi_reset_alt(struct cfi * const cfi) 727 { 728 cfi_cmd(cfi, CFI_ADDRESS_ANY, CFI_ALT_RESET_DATA); 729 } 730 731 static void 732 cfi_jedec_id_1(struct cfi * const cfi) 733 { 734 struct cfi_jedec_id_data *idp = &cfi->cfi_id_data; 735 uint8_t data[0x10]; 736 737 bus_space_read_region_1(cfi->cfi_bst, cfi->cfi_bsh, 0, data, 738 __arraycount(data)); 739 740 CFI_DUMP_JEDEC(0, data, sizeof(data), 1); 741 742 idp->id_mid = (uint16_t)data[0]; 743 idp->id_did[0] = (uint16_t)data[1]; 744 idp->id_did[1] = (uint16_t)data[0xe]; 745 idp->id_did[2] = (uint16_t)data[0xf]; 746 idp->id_prot_state = (uint16_t)data[2]; 747 idp->id_indicators = (uint16_t)data[3]; 748 749 /* software bits, upper and lower */ 750 idp->id_swb_lo = data[0xc]; 751 idp->id_swb_hi = data[0xd]; 752 753 } 754 755 static void 756 cfi_jedec_id_2(struct cfi * const cfi) 757 { 758 struct cfi_jedec_id_data *idp = &cfi->cfi_id_data; 759 uint16_t data[0x10]; 760 761 bus_space_read_region_2(cfi->cfi_bst, cfi->cfi_bsh, 0, data, 762 __arraycount(data)); 763 764 CFI_DUMP_JEDEC(0, data, sizeof(data), 1); 765 766 idp->id_mid = data[0]; 767 idp->id_did[0] = data[1]; 768 idp->id_did[1] = data[0xe]; 769 idp->id_did[2] = data[0xf]; 770 idp->id_prot_state = data[2]; 771 idp->id_indicators = data[3]; 772 773 /* software bits, upper and lower 774 * - undefined on S29GL-P 775 * - defined on S29GL-S 776 */ 777 idp->id_swb_lo = data[0xc]; 778 idp->id_swb_hi = data[0xd]; 779 780 } 781 782 static void 783 cfi_jedec_id_4(struct cfi * const cfi) 784 { 785 struct cfi_jedec_id_data *idp = &cfi->cfi_id_data; 786 uint32_t data[0x10]; 787 788 bus_space_read_region_4(cfi->cfi_bst, cfi->cfi_bsh, 0, data, 789 __arraycount(data)); 790 791 CFI_DUMP_JEDEC(0, data, sizeof(data), 1); 792 793 idp->id_mid = data[0] & 0xffff; 794 idp->id_did[0] = data[1] & 0xffff; 795 idp->id_did[1] = data[0xe] & 0xffff; 796 idp->id_did[2] = data[0xf] & 0xffff; 797 idp->id_prot_state = data[2] & 0xffff; 798 idp->id_indicators = data[3] & 0xffff; 799 800 /* software bits, upper and lower 801 * - undefined on S29GL-P 802 * - defined on S29GL-S 803 */ 804 idp->id_swb_lo = data[0xc] & 0xffff; 805 idp->id_swb_hi = data[0xd] & 0xffff; 806 807 } 808 809 /* 810 * cfi_jedec_id - get JEDEC ID info 811 */ 812 static bool 813 cfi_jedec_id(struct cfi * const cfi) 814 { 815 816 DPRINTF(("%s\n", __func__)); 817 818 cfi_cmd(cfi, 0x555, 0xaa); 819 cfi_cmd(cfi, 0x2aa, 0x55); 820 cfi_cmd(cfi, 0x555, 0x90); 821 822 switch(cfi->cfi_portwidth) { 823 case 0: 824 cfi_jedec_id_1(cfi); 825 break; 826 case 1: 827 cfi_jedec_id_2(cfi); 828 break; 829 case 2: 830 cfi_jedec_id_4(cfi); 831 break; 832 #ifdef NOTYET 833 case 3: 834 cfi_jedec_id_8(cfi); 835 break; 836 #endif 837 default: 838 panic("%s: bad portwidth %d bytes\n", 839 __func__, 1 << cfi->cfi_portwidth); 840 } 841 842 return true; 843 } 844 845 static bool 846 cfi_emulate(struct cfi * const cfi) 847 { 848 bool found = false; 849 const struct cfi_jedec_tab *jt = cfi_jedec_search(cfi); 850 if (jt != NULL) { 851 found = true; 852 cfi->cfi_emulated = true; 853 cfi_jedec_fill(cfi, jt); 854 } 855 return found; 856 } 857 858 /* 859 * cfi_jedec_search - search cfi_jedec_tab[] for entry matching given JEDEC IDs 860 */ 861 static const struct cfi_jedec_tab * 862 cfi_jedec_search(struct cfi *cfi) 863 { 864 struct cfi_jedec_id_data *idp = &cfi->cfi_id_data; 865 866 for (u_int i=0; i < __arraycount(cfi_jedec_tab); i++) { 867 const struct cfi_jedec_tab *jt = &cfi_jedec_tab[i]; 868 if ((jt->jt_mid == idp->id_mid) && 869 (jt->jt_did == idp->id_did[0])) { 870 return jt; 871 } 872 } 873 return NULL; 874 } 875 876 /* 877 * cfi_jedec_fill - fill in cfi with info from table entry 878 */ 879 static void 880 cfi_jedec_fill(struct cfi *cfi, const struct cfi_jedec_tab *jt) 881 { 882 883 cfi->cfi_name = jt->jt_name; 884 cfi->cfi_opmode = jt->jt_opmode; 885 886 struct cfi_query_data *qryp = &cfi->cfi_qry_data; 887 memset(&qryp, 0, sizeof(*qryp)); 888 qryp->id_pri = jt->jt_id_pri; 889 qryp->id_alt = jt->jt_id_alt; 890 qryp->interface_code_desc = jt->jt_interface_code_desc; 891 qryp->write_word_time_typ = jt->jt_write_word_time_typ; 892 qryp->write_nbyte_time_typ = jt->jt_write_nbyte_time_typ; 893 qryp->erase_blk_time_typ = jt->jt_erase_blk_time_typ; 894 qryp->erase_chip_time_typ = jt->jt_erase_chip_time_typ; 895 qryp->write_word_time_max = jt->jt_write_word_time_max; 896 qryp->write_nbyte_time_max = jt->jt_write_nbyte_time_max; 897 qryp->erase_blk_time_max = jt->jt_erase_blk_time_max; 898 qryp->erase_chip_time_max = jt->jt_erase_chip_time_max; 899 qryp->device_size = jt->jt_device_size; 900 qryp->interface_code_desc = jt->jt_interface_code_desc; 901 qryp->write_nbyte_size_max = jt->jt_write_nbyte_size_max; 902 qryp->erase_blk_regions = jt->jt_erase_blk_regions; 903 for (u_int i=0; i < 4; i++) 904 qryp->erase_blk_info[i] = jt->jt_erase_blk_info[i]; 905 906 } 907 908 void 909 cfi_print(device_t self, struct cfi * const cfi) 910 { 911 char pbuf[sizeof("XXXX MB")]; 912 struct cfi_query_data * const qryp = &cfi->cfi_qry_data; 913 914 format_bytes(pbuf, sizeof(pbuf), 1 << qryp->device_size); 915 if (cfi->cfi_emulated) { 916 aprint_normal_dev(self, "%s NOR flash %s %s\n", 917 cfi->cfi_name, pbuf, 918 cfi_interface_desc_str(qryp->interface_code_desc)); 919 } else { 920 aprint_normal_dev(self, "CFI NOR flash %s %s\n", pbuf, 921 cfi_interface_desc_str(qryp->interface_code_desc)); 922 } 923 #ifdef NOR_VERBOSE 924 aprint_normal_dev(self, "manufacturer id %#x, device id %#x %#x %#x\n", 925 cfi->cfi_id_data.id_mid, 926 cfi->cfi_id_data.id_did[0], 927 cfi->cfi_id_data.id_did[1], 928 cfi->cfi_id_data.id_did[2]); 929 aprint_normal_dev(self, "%s\n", cfi->cfi_opmode->str); 930 aprint_normal_dev(self, "sw bits lo=%#x hi=%#x\n", 931 cfi->cfi_id_data.id_swb_lo, 932 cfi->cfi_id_data.id_swb_hi); 933 aprint_normal_dev(self, "max multibyte write size %d\n", 934 1 << qryp->write_nbyte_size_max); 935 aprint_normal_dev(self, "%d Erase Block Region(s)\n", 936 qryp->erase_blk_regions); 937 for (u_int r=0; r < qryp->erase_blk_regions; r++) { 938 size_t sz = qryp->erase_blk_info[r].z * 256; 939 format_bytes(pbuf, sizeof(pbuf), sz); 940 aprint_normal(" %d: %d blocks, size %s\n", r, 941 qryp->erase_blk_info[r].y + 1, pbuf); 942 } 943 #endif 944 945 switch (cfi->cfi_qry_data.id_pri) { 946 case 0x0002: 947 cfi_0002_print(self, cfi); 948 break; 949 } 950 } 951 952 #if defined(CFI_DEBUG_JEDEC) || defined(CFI_DEBUG_QRY) 953 void 954 cfi_hexdump(flash_off_t offset, void * const v, u_int count, u_int stride) 955 { 956 uint8_t * const data = v; 957 for(int n=0; n < count; n+=16) { 958 int i; 959 printf("%08llx: ", (offset + n) / stride); 960 for(i=n; i < n+16; i++) 961 printf("%02x ", data[i]); 962 printf("\t"); 963 for(i=n; i < n+16; i++) { 964 u_int c = (int)data[i]; 965 if (c >= 0x20 && c < 0x7f) 966 printf("%c", c); 967 else 968 printf("%c", '.'); 969 } 970 printf("\n"); 971 } 972 } 973 #endif 974