diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c index 35294bc..50df9b0 100644 --- a/drivers/mtd/cfi_flash.c +++ b/drivers/mtd/cfi_flash.c @@ -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; } diff --git a/include/mtd/cfi_flash.h b/include/mtd/cfi_flash.h index 3245b44..966b5e0 100644 --- a/include/mtd/cfi_flash.h +++ b/include/mtd/cfi_flash.h @@ -60,6 +60,13 @@ #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