cfi_flash: Enable PPB protection for all AMD cmdset flash chips
[pandora-u-boot.git] / drivers / mtd / cfi_flash.c
index b2dfc53..048a7a7 100644 (file)
@@ -1128,7 +1128,7 @@ int flash_erase (flash_info_t * info, int s_first, int s_last)
                                                AMD_CMD_ERASE_START);
                                flash_unlock_seq (info, sect);
                                flash_write_cmd (info, sect, 0,
-                                                AMD_CMD_ERASE_SECTOR);
+                                                info->cmd_erase_sector);
                                break;
 #ifdef CONFIG_FLASH_CFI_LEGACY
                        case CFI_CMDSET_AMD_LEGACY:
@@ -1425,13 +1425,18 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
        return flash_write_cfiword (info, wp, cword);
 }
 
+static inline int manufact_match(flash_info_t *info, u32 manu)
+{
+       return info->manufacturer_id == ((manu & FLASH_VENDMASK) >> 16);
+}
+
 /*-----------------------------------------------------------------------
  */
 #ifdef CONFIG_SYS_FLASH_PROTECTION
 
 static int cfi_protect_bugfix(flash_info_t *info, long sector, int prot)
 {
-       if (info->manufacturer_id == ((INTEL_MANUFACT & FLASH_VENDMASK) >> 16)
+       if (manufact_match(info, INTEL_MANUFACT)
            && info->device_id == NUMONYX_256MBIT) {
                /*
                 * see errata called
@@ -1488,8 +1493,7 @@ int flash_real_protect (flash_info_t * info, long sector, int prot)
                case CFI_CMDSET_AMD_EXTENDED:
                case CFI_CMDSET_AMD_STANDARD:
                        /* U-Boot only checks the first byte */
-                       if (info->manufacturer_id ==
-                           ((ATM_MANUFACT & FLASH_VENDMASK) >> 16)) {
+                       if (manufact_match(info, ATM_MANUFACT)) {
                                if (prot) {
                                        flash_unlock_seq (info, 0);
                                        flash_write_cmd (info, 0,
@@ -1507,8 +1511,7 @@ int flash_real_protect (flash_info_t * info, long sector, int prot)
                                                        0, ATM_CMD_UNLOCK_SECT);
                                }
                        }
-                       if (info->manufacturer_id ==
-                           ((AMD_MANUFACT & FLASH_VENDMASK) >> 16)) {
+                       if (info->legacy_unlock) {
                                int flag = disable_interrupts();
                                int lock_flag;
 
@@ -1733,18 +1736,15 @@ static void cmdset_amd_read_jedec_ids(flash_info_t *info)
 static int cmdset_amd_init(flash_info_t *info, struct cfi_qry *qry)
 {
        info->cmd_reset = AMD_CMD_RESET;
+       info->cmd_erase_sector = AMD_CMD_ERASE_SECTOR;
 
        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 ==
-           ((AMD_MANUFACT & FLASH_VENDMASK) >> 16)) {
-               ushort spus;
-
-               /* read sector protect/unprotect scheme */
-               spus = flash_read_uchar(info, info->ext_addr + 9);
-               if (spus == 0x8)
+       if (info->ext_addr) {
+               /* read sector protect/unprotect scheme (at 0x49) */
+               if (flash_read_uchar(info, info->ext_addr + 9) == 0x8)
                        info->legacy_unlock = 1;
        }
 #endif
@@ -2003,6 +2003,25 @@ static void flash_fixup_stm(flash_info_t *info, struct cfi_qry *qry)
        }
 }
 
+static void flash_fixup_sst(flash_info_t *info, struct cfi_qry *qry)
+{
+       /*
+        * SST, for many recent nor parallel flashes, says they are
+        * CFI-conformant. This is not true, since qry struct.
+        * reports a std. AMD command set (0x0002), while SST allows to
+        * erase two different sector sizes for the same memory.
+        * 64KB sector (SST call it block)  needs 0x30 to be erased.
+        * 4KB  sector (SST call it sector) needs 0x50 to be erased.
+        * Since CFI query detect the 4KB number of sectors, users expects
+        * a sector granularity of 4KB, and it is here set.
+        */
+       if (info->device_id == 0x5D23 || /* SST39VF3201B */
+           info->device_id == 0x5C23) { /* SST39VF3202B */
+               /* set sector granularity to 4KB */
+               info->cmd_erase_sector=0x50;
+       }
+}
+
 /*
  * The following code cannot be run from FLASH!
  *
@@ -2081,6 +2100,9 @@ ulong flash_get_size (phys_addr_t base, int banknum)
                case 0x0020:
                        flash_fixup_stm(info, &qry);
                        break;
+               case 0x00bf: /* SST */
+                       flash_fixup_sst(info, &qry);
+                       break;
                }
 
                debug ("manufacturer is %d\n", info->vendor);
@@ -2158,6 +2180,27 @@ ulong flash_get_size (phys_addr_t base, int banknum)
                                                             FLASH_OFFSET_PROTECT,
                                                             FLASH_STATUS_PROTECT);
                                        break;
+                               case CFI_CMDSET_AMD_EXTENDED:
+                               case CFI_CMDSET_AMD_STANDARD:
+                                       if (!info->legacy_unlock) {
+                                               /* default: not protected */
+                                               info->protect[sect_cnt] = 0;
+                                               break;
+                                       }
+
+                                       /* Read protection (PPB) from sector */
+                                       flash_write_cmd(info, 0, 0,
+                                                       info->cmd_reset);
+                                       flash_unlock_seq(info, 0);
+                                       flash_write_cmd(info, 0,
+                                                       info->addr_unlock1,
+                                                       FLASH_CMD_READ_ID);
+                                       info->protect[sect_cnt] =
+                                               flash_isset(
+                                                       info, sect_cnt,
+                                                       FLASH_OFFSET_PROTECT,
+                                                       FLASH_STATUS_PROTECT);
+                                       break;
                                default:
                                        /* default: not protected */
                                        info->protect[sect_cnt] = 0;