cfi_flash: add support for Spansion flash PPB sector protection
authorAnatolij Gustschin <agust@denx.de>
Thu, 9 Aug 2012 06:18:12 +0000 (08:18 +0200)
committerStefan Roese <sr@denx.de>
Mon, 13 Aug 2012 12:34:35 +0000 (14:34 +0200)
Erasing flash sectors protected with persistent protection bit (PPB)
mechanism on Spansion flash chips doesn't work. Add sector protection
status checking and sector lock and unlock commands to fix this.

Signed-off-by: Anatolij Gustschin <agust@denx.de>
Cc: Stefan Roese <sr@denx.de>
Signed-off-by: Stefan Roese <sr@denx.de>
drivers/mtd/cfi_flash.c
include/mtd/cfi_flash.h

index 35294bc8c53ff37ffb059ac66765c733d71eacef..50df9b0dda44059f782567afb3ccaf83026d8a3c 100644 (file)
@@ -1447,6 +1447,47 @@ int flash_real_protect (flash_info_t * info, long sector, int prot)
                                                        0, ATM_CMD_UNLOCK_SECT);
                                }
                        }
+                       if (info->manufacturer_id == (uchar)AMD_MANUFACT) {
+                               int flag = disable_interrupts();
+                               int lock_flag;
+
+                               flash_unlock_seq(info, 0);
+                               flash_write_cmd(info, 0, info->addr_unlock1,
+                                               AMD_CMD_SET_PPB_ENTRY);
+                               lock_flag = flash_isset(info, sector, 0, 0x01);
+                               if (prot) {
+                                       if (lock_flag) {
+                                               flash_write_cmd(info, sector, 0,
+                                                       AMD_CMD_PPB_LOCK_BC1);
+                                               flash_write_cmd(info, sector, 0,
+                                                       AMD_CMD_PPB_LOCK_BC2);
+                                       }
+                                       debug("sector %ld %slocked\n", sector,
+                                               lock_flag ? "" : "already ");
+                               } else {
+                                       if (!lock_flag) {
+                                               debug("unlock %ld\n", sector);
+                                               flash_write_cmd(info, 0, 0,
+                                                       AMD_CMD_PPB_UNLOCK_BC1);
+                                               flash_write_cmd(info, 0, 0,
+                                                       AMD_CMD_PPB_UNLOCK_BC2);
+                                       }
+                                       debug("sector %ld %sunlocked\n", sector,
+                                               !lock_flag ? "" : "already ");
+                               }
+                               if (flag)
+                                       enable_interrupts();
+
+                               if (flash_status_check(info, sector,
+                                               info->erase_blk_tout,
+                                               prot ? "protect" : "unprotect"))
+                                       printf("status check error\n");
+
+                               flash_write_cmd(info, 0, 0,
+                                               AMD_CMD_SET_PPB_EXIT_BC1);
+                               flash_write_cmd(info, 0, 0,
+                                               AMD_CMD_SET_PPB_EXIT_BC2);
+                       }
                        break;
 #ifdef CONFIG_FLASH_CFI_LEGACY
                case CFI_CMDSET_AMD_LEGACY:
@@ -1635,6 +1676,17 @@ static int cmdset_amd_init(flash_info_t *info, struct cfi_qry *qry)
        cmdset_amd_read_jedec_ids(info);
        flash_write_cmd(info, 0, info->cfi_offset, FLASH_CMD_CFI);
 
+#ifdef CONFIG_SYS_FLASH_PROTECTION
+       if (info->ext_addr && info->manufacturer_id == (uchar)AMD_MANUFACT) {
+               ushort spus;
+
+               /* read sector protect/unprotect scheme */
+               spus = flash_read_uchar(info, info->ext_addr + 9);
+               if (spus == 0x8)
+                       info->legacy_unlock = 1;
+       }
+#endif
+
        return 0;
 }
 
index 3245b443af4e0d5b02bb432337ebb79ae93e9b9f..966b5e00cac20a3cd36a60917ff226980908ffee 100644 (file)
 #define AMD_CMD_UNLOCK_ACK             0x55
 #define AMD_CMD_WRITE_TO_BUFFER                0x25
 #define AMD_CMD_WRITE_BUFFER_CONFIRM   0x29
+#define AMD_CMD_SET_PPB_ENTRY          0xC0
+#define AMD_CMD_SET_PPB_EXIT_BC1       0x90
+#define AMD_CMD_SET_PPB_EXIT_BC2       0x00
+#define AMD_CMD_PPB_UNLOCK_BC1         0x80
+#define AMD_CMD_PPB_UNLOCK_BC2         0x30
+#define AMD_CMD_PPB_LOCK_BC1           0xA0
+#define AMD_CMD_PPB_LOCK_BC2           0x00
 
 #define AMD_STATUS_TOGGLE              0x40
 #define AMD_STATUS_ERROR               0x20