Changeset 1115 for trunk/spi25.c


Ignore:
Timestamp:
07/29/10 15:09:18 (22 months ago)
Author:
hailfinger
Message:

Add detailed status register printing and unlocking for all ATMEL AT25*
chips.

Add support for Atmel AT25DF081A and AT25DQ161.

Some chips require EWSR before WRSR, others require WREN before WRSR,
and some support both variants. Add feature_bits to select the correct
SPI command, and default to EWSR.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@…>
Tested-by: Steven Rosario
Acked-by: Uwe Hermann <uwe@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/spi25.c

    r1112 r1115  
    313313 
    314314/* Prettyprint the status register. Common definitions. */ 
    315 void spi_prettyprint_status_register_common(uint8_t status) 
     315static 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. */ 
     324static void spi_prettyprint_status_register_common(uint8_t status) 
    316325{ 
    317326        msg_cdbg("Chip status register: Bit 5 / Block Protect 3 (BP3) is " 
     
    323332        msg_cdbg("Chip status register: Bit 2 / Block Protect 0 (BP0) is " 
    324333                     "%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); 
    329335} 
    330336 
     
    337343                     "(SRWD) is %sset\n", (status & (1 << 7)) ? "" : "not "); 
    338344        spi_prettyprint_status_register_common(status); 
     345} 
     346 
     347/* Prettyprint the status register. Common definitions. */ 
     348static 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 
     360int 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 
     388int 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 
     396int 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 
     414int 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 
     438int 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; 
    339460} 
    340461 
     
    733854 * generic that this... 
    734855 */ 
    735 int spi_write_status_register(int status) 
     856static int spi_write_status_register_ewsr(struct flashchip *flash, int status) 
    736857{ 
    737858        int result; 
    738859        struct spi_command cmds[] = { 
    739860        { 
    740         /* FIXME: WRSR requires either EWSR or WREN depending on chip type. */ 
     861        /* WRSR requires either EWSR or WREN depending on chip type. */ 
    741862                .writecnt       = JEDEC_EWSR_OUTSIZE, 
    742863                .writearr       = (const unsigned char[]){ JEDEC_EWSR }, 
     
    760881                        __func__); 
    761882        } 
     883        /* WRSR performs a self-timed erase before the changes take effect. */ 
     884        programmer_delay(100 * 1000); 
    762885        return result; 
     886} 
     887 
     888static 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 
     920static 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; 
    763934} 
    764935 
     
    8451016} 
    8461017 
     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 */ 
    8471022int spi_disable_blockprotect(struct flashchip *flash) 
    8481023{ 
     
    8511026 
    8521027        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(); 
    8541039        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 
     1046int 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)); 
    8571066                if (result) { 
    8581067                        msg_cerr("spi_write_status_register failed\n"); 
    8591068                        return result; 
    8601069                } 
    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 
     1086int 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 
     1093int 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 
     1101int 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; 
    8651119                } 
     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} 
     1134int 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; 
    8661164        } 
    8671165        return 0; 
Note: See TracChangeset for help on using the changeset viewer.