Changeset 1115
- Timestamp:
- 07/29/10 15:09:18 (18 months ago)
- Location:
- trunk
- Files:
-
- 7 edited
-
chipdrivers.h (modified) (1 diff)
-
flash.h (modified) (2 diffs)
-
flashchips.c (modified) (19 diffs)
-
flashchips.h (modified) (1 diff)
-
spi.c (modified) (1 diff)
-
spi.h (modified) (2 diffs)
-
spi25.c (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/chipdrivers.h
r1083 r1115 48 48 int spi_chip_read(struct flashchip *flash, uint8_t *buf, int start, int len); 49 49 uint8_t spi_read_status_register(void); 50 int spi_prettyprint_status_register_at25df(struct flashchip *flash); 51 int spi_prettyprint_status_register_at25df_sec(struct flashchip *flash); 52 int spi_prettyprint_status_register_at25f(struct flashchip *flash); 53 int spi_prettyprint_status_register_at25fs010(struct flashchip *flash); 54 int spi_prettyprint_status_register_at25fs040(struct flashchip *flash); 50 55 int spi_disable_blockprotect(struct flashchip *flash); 56 int spi_disable_blockprotect_at25df(struct flashchip *flash); 57 int spi_disable_blockprotect_at25df_sec(struct flashchip *flash); 58 int spi_disable_blockprotect_at25f(struct flashchip *flash); 59 int spi_disable_blockprotect_at25fs010(struct flashchip *flash); 60 int spi_disable_blockprotect_at25fs040(struct flashchip *flash); 51 61 int spi_byte_program(int addr, uint8_t databyte); 52 62 int spi_nbyte_program(int addr, uint8_t *bytes, int len); -
trunk/flash.h
r1112 r1115 70 70 /* 71 71 * How many different erase functions do we have per chip? 72 */ 73 #define NUM_ERASEFUNCTIONS 5 72 * Atmel AT25FS010 has 6 different functions. 73 */ 74 #define NUM_ERASEFUNCTIONS 6 74 75 75 76 #define FEATURE_REGISTERMAP (1 << 0) … … 83 84 #define FEATURE_ADDR_AAA (2 << 2) 84 85 #define FEATURE_ADDR_SHIFTED (1 << 5) 86 #define FEATURE_WRSR_EWSR (1 << 6) 87 #define FEATURE_WRSR_WREN (1 << 7) 88 #define FEATURE_WRSR_EITHER (FEATURE_WRSR_EWSR | FEATURE_WRSR_WREN) 85 89 86 90 struct flashchip { -
trunk/flashchips.c
r1114 r1115 790 790 .total_size = 256, 791 791 .page_size = 256, 792 .feature_bits = FEATURE_WRSR_WREN, 792 793 .tested = TEST_UNTESTED, 793 794 .probe = probe_spi_rdid, … … 812 813 } 813 814 }, 814 .unlock = spi_disable_blockprotect, 815 .printlock = spi_prettyprint_status_register_at25df, 816 .unlock = spi_disable_blockprotect_at25df, 815 817 .write = spi_chip_write_256, 816 818 .read = spi_chip_read, … … 825 827 .total_size = 512, 826 828 .page_size = 256, 829 .feature_bits = FEATURE_WRSR_WREN, 827 830 .tested = TEST_UNTESTED, 828 831 .probe = probe_spi_rdid, … … 847 850 } 848 851 }, 849 .unlock = spi_disable_blockprotect, 852 .printlock = spi_prettyprint_status_register_at25df, 853 .unlock = spi_disable_blockprotect_at25df, 850 854 .write = spi_chip_write_256, 851 855 .read = spi_chip_read, … … 860 864 .total_size = 1024, 861 865 .page_size = 256, 866 .feature_bits = FEATURE_WRSR_WREN, 862 867 .tested = TEST_UNTESTED, 863 868 .probe = probe_spi_rdid, … … 882 887 } 883 888 }, 884 .unlock = spi_disable_blockprotect, 889 .printlock = spi_prettyprint_status_register_at25df, 890 .unlock = spi_disable_blockprotect_at25df, 891 .write = spi_chip_write_256, 892 .read = spi_chip_read, 893 }, 894 895 { 896 .vendor = "Atmel", 897 .name = "AT25DF081A", 898 .bustype = CHIP_BUSTYPE_SPI, 899 .manufacture_id = ATMEL_ID, 900 .model_id = AT_25DF081A, 901 .total_size = 1024, 902 .page_size = 256, 903 .feature_bits = FEATURE_WRSR_WREN, 904 .tested = TEST_UNTESTED, 905 .probe = probe_spi_rdid, 906 .probe_timing = TIMING_ZERO, 907 .block_erasers = 908 { 909 { 910 .eraseblocks = { {4 * 1024, 256} }, 911 .block_erase = spi_block_erase_20, 912 }, { 913 .eraseblocks = { {32 * 1024, 32} }, 914 .block_erase = spi_block_erase_52, 915 }, { 916 .eraseblocks = { {64 * 1024, 16} }, 917 .block_erase = spi_block_erase_d8, 918 }, { 919 .eraseblocks = { {1024 * 1024, 1} }, 920 .block_erase = spi_block_erase_60, 921 }, { 922 .eraseblocks = { {1024 * 1024, 1} }, 923 .block_erase = spi_block_erase_c7, 924 } 925 }, 926 .printlock = spi_prettyprint_status_register_at25df_sec, 927 .unlock = spi_disable_blockprotect_at25df_sec, 885 928 .write = spi_chip_write_256, 886 929 .read = spi_chip_read, … … 895 938 .total_size = 2048, 896 939 .page_size = 256, 940 .feature_bits = FEATURE_WRSR_WREN, 897 941 .tested = TEST_UNTESTED, 898 942 .probe = probe_spi_rdid, … … 917 961 } 918 962 }, 919 .unlock = spi_disable_blockprotect, 963 .printlock = spi_prettyprint_status_register_at25df_sec, 964 .unlock = spi_disable_blockprotect_at25df_sec, 920 965 .write = spi_chip_write_256, 921 966 .read = spi_chip_read, … … 930 975 .total_size = 4096, 931 976 .page_size = 256, 977 .feature_bits = FEATURE_WRSR_WREN, 932 978 .tested = TEST_OK_PRW, 933 979 .probe = probe_spi_rdid, … … 952 998 } 953 999 }, 954 .unlock = spi_disable_blockprotect, 1000 .printlock = spi_prettyprint_status_register_at25df, 1001 .unlock = spi_disable_blockprotect_at25df, 955 1002 .write = spi_chip_write_256, 956 1003 .read = spi_chip_read, … … 965 1012 .total_size = 4096, 966 1013 .page_size = 256, 1014 .feature_bits = FEATURE_WRSR_WREN, 967 1015 .tested = TEST_UNTESTED, 968 1016 .probe = probe_spi_rdid, … … 987 1035 } 988 1036 }, 989 .unlock = spi_disable_blockprotect, 1037 .printlock = spi_prettyprint_status_register_at25df_sec, 1038 .unlock = spi_disable_blockprotect_at25df_sec, 990 1039 .write = spi_chip_write_256, 991 1040 .read = spi_chip_read, … … 1000 1049 .total_size = 8192, 1001 1050 .page_size = 256, 1051 .feature_bits = FEATURE_WRSR_WREN, 1002 1052 .tested = TEST_UNTESTED, 1003 1053 .probe = probe_spi_rdid, … … 1022 1072 } 1023 1073 }, 1024 .unlock = spi_disable_blockprotect, 1074 .printlock = spi_prettyprint_status_register_at25df_sec, 1075 .unlock = spi_disable_blockprotect_at25df_sec, 1076 .write = spi_chip_write_256, 1077 .read = spi_chip_read, 1078 }, 1079 1080 { 1081 .vendor = "Atmel", 1082 .name = "AT25DQ161", 1083 .bustype = CHIP_BUSTYPE_SPI, 1084 .manufacture_id = ATMEL_ID, 1085 .model_id = AT_25DQ161, 1086 .total_size = 2048, 1087 .page_size = 256, 1088 .feature_bits = FEATURE_WRSR_WREN, 1089 .tested = TEST_UNTESTED, 1090 .probe = probe_spi_rdid, 1091 .probe_timing = TIMING_ZERO, 1092 .block_erasers = 1093 { 1094 { 1095 .eraseblocks = { {4 * 1024, 512} }, 1096 .block_erase = spi_block_erase_20, 1097 }, { 1098 .eraseblocks = { {32 * 1024, 64} }, 1099 .block_erase = spi_block_erase_52, 1100 }, { 1101 .eraseblocks = { {64 * 1024, 32} }, 1102 .block_erase = spi_block_erase_d8, 1103 }, { 1104 .eraseblocks = { {2 * 1024 * 1024, 1} }, 1105 .block_erase = spi_block_erase_60, 1106 }, { 1107 .eraseblocks = { {2 * 1024 * 1024, 1} }, 1108 .block_erase = spi_block_erase_c7, 1109 } 1110 }, 1111 .printlock = spi_prettyprint_status_register_at25df_sec, 1112 .unlock = spi_disable_blockprotect_at25df_sec, 1025 1113 .write = spi_chip_write_256, 1026 1114 .read = spi_chip_read, … … 1035 1123 .total_size = 64, 1036 1124 .page_size = 256, 1125 .feature_bits = FEATURE_WRSR_WREN, 1037 1126 .tested = TEST_UNTESTED, 1038 1127 .probe = probe_spi_rdid, … … 1057 1146 } 1058 1147 }, 1059 .unlock = spi_disable_blockprotect, 1148 .printlock = spi_prettyprint_status_register_at25f, 1149 .unlock = spi_disable_blockprotect_at25f, 1060 1150 .write = spi_chip_write_256, 1061 1151 .read = spi_chip_read, … … 1079 1169 .block_erase = spi_block_erase_20, 1080 1170 }, { 1171 .eraseblocks = { {4 * 1024, 32} }, 1172 .block_erase = spi_block_erase_d7, 1173 }, { 1081 1174 .eraseblocks = { {32 * 1024, 4} }, 1082 1175 .block_erase = spi_block_erase_52, … … 1092 1185 } 1093 1186 }, 1094 .unlock = spi_disable_blockprotect, 1187 .printlock = spi_prettyprint_status_register_at25fs010, 1188 .unlock = spi_disable_blockprotect_at25fs010, 1095 1189 .write = spi_chip_write_256, 1096 1190 .read = spi_chip_read, … … 1127 1221 } 1128 1222 }, 1129 .unlock = spi_disable_blockprotect, 1223 .printlock = spi_prettyprint_status_register_at25fs040, 1224 .unlock = spi_disable_blockprotect_at25fs040, 1130 1225 .write = spi_chip_write_256, 1131 1226 .read = spi_chip_read, -
trunk/flashchips.h
r1097 r1115 111 111 #define AT_25DF041A 0x4401 112 112 #define AT_25DF081 0x4502 113 #define AT_25DF081A 0x4501 /* Yes, 81A has a lower number than 81 */ 113 114 #define AT_25DF161 0x4602 114 115 #define AT_25DF321 0x4700 /* Same as 26DF321 */ 115 116 #define AT_25DF321A 0x4701 116 117 #define AT_25DF641 0x4800 117 #define AT_25F512A 0x65 /* Needs special RDID. AT25F512A_RDID 15 1d */ 118 #define AT_25DQ161 0x8600 119 #define AT25F512 /* No device ID found in datasheet. Vendor ID 120 * can be read with AT25F512A_RDID */ 121 #define AT_25F512A 0x65 /* Needs AT25F512A_RDID */ 118 122 #define AT_25F512B 0x6500 123 #define AT25F1024 /* No device ID found in datasheet. Vendor ID 124 * can be read with AT25F512A_RDID */ 125 #define AT_25F1024A 0x60 /* Needs AT25F512A_RDID */ 119 126 #define AT_25FS010 0x6601 120 127 #define AT_25FS040 0x6604 -
trunk/spi.c
r1113 r1115 30 30 31 31 enum spi_controller spi_controller = SPI_CONTROLLER_NONE; 32 33 void spi_prettyprint_status_register(struct flashchip *flash);34 32 35 33 const struct spi_programmer spi_programmer[] = { -
trunk/spi.h
r1052 r1115 32 32 33 33 /* AT25F512A has bit 3 as don't care bit in commands */ 34 #define AT25F512A_RDID 0x15 34 #define AT25F512A_RDID 0x15 /* 0x15 or 0x1d */ 35 35 #define AT25F512A_RDID_OUTSIZE 0x01 36 36 #define AT25F512A_RDID_INSIZE 0x02 … … 124 124 #define SPI_INVALID_ADDRESS -3 125 125 #define SPI_INVALID_LENGTH -4 126 #define SPI_FLASHROM_BUG -5 126 127 127 128 #endif /* !__SPI_H__ */ -
trunk/spi25.c
r1112 r1115 313 313 314 314 /* Prettyprint the status register. Common definitions. */ 315 void spi_prettyprint_status_register_common(uint8_t status) 315 static void spi_prettyprint_status_register_welwip(uint8_t status) 316 { 317 msg_cdbg("Chip status register: Write Enable Latch (WEL) is " 318 "%sset\n", (status & (1 << 1)) ? "" : "not "); 319 msg_cdbg("Chip status register: Write In Progress (WIP/BUSY) is " 320 "%sset\n", (status & (1 << 0)) ? "" : "not "); 321 } 322 323 /* Prettyprint the status register. Common definitions. */ 324 static void spi_prettyprint_status_register_common(uint8_t status) 316 325 { 317 326 msg_cdbg("Chip status register: Bit 5 / Block Protect 3 (BP3) is " … … 323 332 msg_cdbg("Chip status register: Bit 2 / Block Protect 0 (BP0) is " 324 333 "%sset\n", (status & (1 << 2)) ? "" : "not "); 325 msg_cdbg("Chip status register: Write Enable Latch (WEL) is " 326 "%sset\n", (status & (1 << 1)) ? "" : "not "); 327 msg_cdbg("Chip status register: Write In Progress (WIP/BUSY) is " 328 "%sset\n", (status & (1 << 0)) ? "" : "not "); 334 spi_prettyprint_status_register_welwip(status); 329 335 } 330 336 … … 337 343 "(SRWD) is %sset\n", (status & (1 << 7)) ? "" : "not "); 338 344 spi_prettyprint_status_register_common(status); 345 } 346 347 /* Prettyprint the status register. Common definitions. */ 348 static void spi_prettyprint_status_register_at25_srplepewpp(uint8_t status) 349 { 350 msg_cdbg("Chip status register: Sector Protection Register Lock (SRPL) " 351 "is %sset\n", (status & (1 << 7)) ? "" : "not "); 352 msg_cdbg("Chip status register: Bit 6 " 353 "is %sset\n", (status & (1 << 6)) ? "" : "not "); 354 msg_cdbg("Chip status register: Erase/Program Error (EPE) " 355 "is %sset\n", (status & (1 << 5)) ? "" : "not "); 356 msg_cdbg("Chip status register: WP# pin (WPP) " 357 "is %sactive\n", (status & (1 << 4)) ? "not " : ""); 358 } 359 360 int spi_prettyprint_status_register_at25df(struct flashchip *flash) 361 { 362 uint8_t status; 363 364 status = spi_read_status_register(); 365 msg_cdbg("Chip status register is %02x\n", status); 366 367 spi_prettyprint_status_register_at25_srplepewpp(status); 368 msg_cdbg("Chip status register: Software Protection Status (SWP): "); 369 switch (status & (3 << 2)) { 370 case 0x0 << 2: 371 msg_cdbg("no sectors are protected\n"); 372 break; 373 case 0x1 << 2: 374 msg_cdbg("some sectors are protected\n"); 375 /* FIXME: Read individual Sector Protection Registers. */ 376 break; 377 case 0x3 << 2: 378 msg_cdbg("all sectors are protected\n"); 379 break; 380 default: 381 msg_cdbg("reserved for future use\n"); 382 break; 383 } 384 spi_prettyprint_status_register_welwip(status); 385 return 0; 386 } 387 388 int spi_prettyprint_status_register_at25df_sec(struct flashchip *flash) 389 { 390 /* FIXME: We should check the security lockdown. */ 391 msg_cdbg("Ignoring security lockdown (if present)\n"); 392 msg_cdbg("Ignoring status register byte 2\n"); 393 return spi_prettyprint_status_register_at25df(flash); 394 } 395 396 int spi_prettyprint_status_register_at25f(struct flashchip *flash) 397 { 398 uint8_t status; 399 400 status = spi_read_status_register(); 401 msg_cdbg("Chip status register is %02x\n", status); 402 403 spi_prettyprint_status_register_at25_srplepewpp(status); 404 msg_cdbg("Chip status register: Bit 3 " 405 "is %sset\n", (status & (1 << 3)) ? "" : "not "); 406 msg_cdbg("Chip status register: Block Protect 0 (BP0) is " 407 "%sset, %s sectors are protected\n", 408 (status & (1 << 2)) ? "" : "not ", 409 (status & (1 << 2)) ? "all" : "no"); 410 spi_prettyprint_status_register_welwip(status); 411 return 0; 412 } 413 414 int spi_prettyprint_status_register_at25fs010(struct flashchip *flash) 415 { 416 uint8_t status; 417 418 status = spi_read_status_register(); 419 msg_cdbg("Chip status register is %02x\n", status); 420 421 msg_cdbg("Chip status register: Status Register Write Protect (WPEN) " 422 "is %sset\n", (status & (1 << 7)) ? "" : "not "); 423 msg_cdbg("Chip status register: Bit 6 / Block Protect 4 (BP4) is " 424 "%sset\n", (status & (1 << 6)) ? "" : "not "); 425 msg_cdbg("Chip status register: Bit 5 / Block Protect 3 (BP3) is " 426 "%sset\n", (status & (1 << 5)) ? "" : "not "); 427 msg_cdbg("Chip status register: Bit 4 is " 428 "%sset\n", (status & (1 << 4)) ? "" : "not "); 429 msg_cdbg("Chip status register: Bit 3 / Block Protect 1 (BP1) is " 430 "%sset\n", (status & (1 << 3)) ? "" : "not "); 431 msg_cdbg("Chip status register: Bit 2 / Block Protect 0 (BP0) is " 432 "%sset\n", (status & (1 << 2)) ? "" : "not "); 433 /* FIXME: Pretty-print detailed sector protection status. */ 434 spi_prettyprint_status_register_welwip(status); 435 return 0; 436 } 437 438 int spi_prettyprint_status_register_at25fs040(struct flashchip *flash) 439 { 440 uint8_t status; 441 442 status = spi_read_status_register(); 443 msg_cdbg("Chip status register is %02x\n", status); 444 445 msg_cdbg("Chip status register: Status Register Write Protect (WPEN) " 446 "is %sset\n", (status & (1 << 7)) ? "" : "not "); 447 msg_cdbg("Chip status register: Bit 6 / Block Protect 4 (BP4) is " 448 "%sset\n", (status & (1 << 6)) ? "" : "not "); 449 msg_cdbg("Chip status register: Bit 5 / Block Protect 3 (BP3) is " 450 "%sset\n", (status & (1 << 5)) ? "" : "not "); 451 msg_cdbg("Chip status register: Bit 4 / Block Protect 2 (BP2) is " 452 "%sset\n", (status & (1 << 4)) ? "" : "not "); 453 msg_cdbg("Chip status register: Bit 3 / Block Protect 1 (BP1) is " 454 "%sset\n", (status & (1 << 3)) ? "" : "not "); 455 msg_cdbg("Chip status register: Bit 2 / Block Protect 0 (BP0) is " 456 "%sset\n", (status & (1 << 2)) ? "" : "not "); 457 /* FIXME: Pretty-print detailed sector protection status. */ 458 spi_prettyprint_status_register_welwip(status); 459 return 0; 339 460 } 340 461 … … 733 854 * generic that this... 734 855 */ 735 int spi_write_status_register(int status)856 static int spi_write_status_register_ewsr(struct flashchip *flash, int status) 736 857 { 737 858 int result; 738 859 struct spi_command cmds[] = { 739 860 { 740 /* FIXME:WRSR requires either EWSR or WREN depending on chip type. */861 /* WRSR requires either EWSR or WREN depending on chip type. */ 741 862 .writecnt = JEDEC_EWSR_OUTSIZE, 742 863 .writearr = (const unsigned char[]){ JEDEC_EWSR }, … … 760 881 __func__); 761 882 } 883 /* WRSR performs a self-timed erase before the changes take effect. */ 884 programmer_delay(100 * 1000); 762 885 return result; 886 } 887 888 static int spi_write_status_register_wren(struct flashchip *flash, int status) 889 { 890 int result; 891 struct spi_command cmds[] = { 892 { 893 /* WRSR requires either EWSR or WREN depending on chip type. */ 894 .writecnt = JEDEC_WREN_OUTSIZE, 895 .writearr = (const unsigned char[]){ JEDEC_WREN }, 896 .readcnt = 0, 897 .readarr = NULL, 898 }, { 899 .writecnt = JEDEC_WRSR_OUTSIZE, 900 .writearr = (const unsigned char[]){ JEDEC_WRSR, (unsigned char) status }, 901 .readcnt = 0, 902 .readarr = NULL, 903 }, { 904 .writecnt = 0, 905 .writearr = NULL, 906 .readcnt = 0, 907 .readarr = NULL, 908 }}; 909 910 result = spi_send_multicommand(cmds); 911 if (result) { 912 msg_cerr("%s failed during command execution\n", 913 __func__); 914 } 915 /* WRSR performs a self-timed erase before the changes take effect. */ 916 programmer_delay(100 * 1000); 917 return result; 918 } 919 920 static int spi_write_status_register(struct flashchip *flash, int status) 921 { 922 int ret = 1; 923 924 if (!(flash->feature_bits & (FEATURE_WRSR_WREN | FEATURE_WRSR_EWSR))) { 925 msg_cdbg("Missing status register write definition, assuming " 926 "EWSR is needed\n"); 927 flash->feature_bits |= FEATURE_WRSR_EWSR; 928 } 929 if (flash->feature_bits & FEATURE_WRSR_WREN) 930 ret = spi_write_status_register_wren(flash, status); 931 if (ret && (flash->feature_bits & FEATURE_WRSR_EWSR)) 932 ret = spi_write_status_register_ewsr(flash, status); 933 return ret; 763 934 } 764 935 … … 845 1016 } 846 1017 1018 /* A generic brute-force block protection disable works like this: 1019 * Write 0x00 to the status register. Check if any locks are still set (that 1020 * part is chip specific). Repeat once. 1021 */ 847 1022 int spi_disable_blockprotect(struct flashchip *flash) 848 1023 { … … 851 1026 852 1027 status = spi_read_status_register(); 853 /* If there is block protection in effect, unprotect it first. */ 1028 /* If block protection is disabled, stop here. */ 1029 if ((status & 0x3c) == 0) 1030 return 0; 1031 1032 msg_cdbg("Some block protection in effect, disabling\n"); 1033 result = spi_write_status_register(flash, status & ~0x3c); 1034 if (result) { 1035 msg_cerr("spi_write_status_register failed\n"); 1036 return result; 1037 } 1038 status = spi_read_status_register(); 854 1039 if ((status & 0x3c) != 0) { 855 msg_cdbg("Some block protection in effect, disabling\n"); 856 result = spi_write_status_register(status & ~0x3c); 1040 msg_cerr("Block protection could not be disabled!\n"); 1041 return 1; 1042 } 1043 return 0; 1044 } 1045 1046 int spi_disable_blockprotect_at25df(struct flashchip *flash) 1047 { 1048 uint8_t status; 1049 int result; 1050 1051 status = spi_read_status_register(); 1052 /* If block protection is disabled, stop here. */ 1053 if ((status & (3 << 2)) == 0) 1054 return 0; 1055 1056 msg_cdbg("Some block protection in effect, disabling\n"); 1057 if (status & (1 << 7)) { 1058 msg_cdbg("Need to disable Sector Protection Register Lock\n"); 1059 if ((status & (1 << 4)) == 0) { 1060 msg_cerr("WP# pin is active, disabling " 1061 "write protection is impossible.\n"); 1062 return 1; 1063 } 1064 /* All bits except bit 7 (SPRL) are readonly. */ 1065 result = spi_write_status_register(flash, status & ~(1 << 7)); 857 1066 if (result) { 858 1067 msg_cerr("spi_write_status_register failed\n"); 859 1068 return result; 860 1069 } 861 status = spi_read_status_register(); 862 if ((status & 0x3c) != 0) { 863 msg_cerr("Block protection could not be disabled!\n"); 864 return 1; 1070 1071 } 1072 /* Global unprotect. Make sure to mask SPRL as well. */ 1073 result = spi_write_status_register(flash, status & ~0xbc); 1074 if (result) { 1075 msg_cerr("spi_write_status_register failed\n"); 1076 return result; 1077 } 1078 status = spi_read_status_register(); 1079 if ((status & (3 << 2)) != 0) { 1080 msg_cerr("Block protection could not be disabled!\n"); 1081 return 1; 1082 } 1083 return 0; 1084 } 1085 1086 int spi_disable_blockprotect_at25df_sec(struct flashchip *flash) 1087 { 1088 /* FIXME: We should check the security lockdown. */ 1089 msg_cinfo("Ignoring security lockdown (if present)\n"); 1090 return spi_disable_blockprotect_at25df(flash); 1091 } 1092 1093 int spi_disable_blockprotect_at25f(struct flashchip *flash) 1094 { 1095 /* spi_disable_blockprotect_at25df is not really the right way to do 1096 * this, but the side effects of said function work here as well. 1097 */ 1098 return spi_disable_blockprotect_at25df(flash); 1099 } 1100 1101 int spi_disable_blockprotect_at25fs010(struct flashchip *flash) 1102 { 1103 uint8_t status; 1104 int result; 1105 1106 status = spi_read_status_register(); 1107 /* If block protection is disabled, stop here. */ 1108 if ((status & 0x6c) == 0) 1109 return 0; 1110 1111 msg_cdbg("Some block protection in effect, disabling\n"); 1112 if (status & (1 << 7)) { 1113 msg_cdbg("Need to disable Status Register Write Protect\n"); 1114 /* Clear bit 7 (WPEN). */ 1115 result = spi_write_status_register(flash, status & ~(1 << 7)); 1116 if (result) { 1117 msg_cerr("spi_write_status_register failed\n"); 1118 return result; 865 1119 } 1120 } 1121 /* Global unprotect. Make sure to mask WPEN as well. */ 1122 result = spi_write_status_register(flash, status & ~0xec); 1123 if (result) { 1124 msg_cerr("spi_write_status_register failed\n"); 1125 return result; 1126 } 1127 status = spi_read_status_register(); 1128 if ((status & 0x6c) != 0) { 1129 msg_cerr("Block protection could not be disabled!\n"); 1130 return 1; 1131 } 1132 return 0; 1133 } 1134 int spi_disable_blockprotect_at25fs040(struct flashchip *flash) 1135 { 1136 uint8_t status; 1137 int result; 1138 1139 status = spi_read_status_register(); 1140 /* If block protection is disabled, stop here. */ 1141 if ((status & 0x7c) == 0) 1142 return 0; 1143 1144 msg_cdbg("Some block protection in effect, disabling\n"); 1145 if (status & (1 << 7)) { 1146 msg_cdbg("Need to disable Status Register Write Protect\n"); 1147 /* Clear bit 7 (WPEN). */ 1148 result = spi_write_status_register(flash, status & ~(1 << 7)); 1149 if (result) { 1150 msg_cerr("spi_write_status_register failed\n"); 1151 return result; 1152 } 1153 } 1154 /* Global unprotect. Make sure to mask WPEN as well. */ 1155 result = spi_write_status_register(flash, status & ~0xfc); 1156 if (result) { 1157 msg_cerr("spi_write_status_register failed\n"); 1158 return result; 1159 } 1160 status = spi_read_status_register(); 1161 if ((status & 0x7c) != 0) { 1162 msg_cerr("Block protection could not be disabled!\n"); 1163 return 1; 866 1164 } 867 1165 return 0;
Note: See TracChangeset
for help on using the changeset viewer.
