linux/drivers/mtd/spi-nor/swp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * SPI NOR Software Write Protection logic.
   4 *
   5 * Copyright (C) 2005, Intec Automation Inc.
   6 * Copyright (C) 2014, Freescale Semiconductor, Inc.
   7 */
   8#include <linux/mtd/mtd.h>
   9#include <linux/mtd/spi-nor.h>
  10
  11#include "core.h"
  12
  13static u8 spi_nor_get_sr_bp_mask(struct spi_nor *nor)
  14{
  15        u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
  16
  17        if (nor->flags & SNOR_F_HAS_SR_BP3_BIT6)
  18                return mask | SR_BP3_BIT6;
  19
  20        if (nor->flags & SNOR_F_HAS_4BIT_BP)
  21                return mask | SR_BP3;
  22
  23        return mask;
  24}
  25
  26static u8 spi_nor_get_sr_tb_mask(struct spi_nor *nor)
  27{
  28        if (nor->flags & SNOR_F_HAS_SR_TB_BIT6)
  29                return SR_TB_BIT6;
  30        else
  31                return SR_TB_BIT5;
  32}
  33
  34static u64 spi_nor_get_min_prot_length_sr(struct spi_nor *nor)
  35{
  36        unsigned int bp_slots, bp_slots_needed;
  37        u8 mask = spi_nor_get_sr_bp_mask(nor);
  38
  39        /* Reserved one for "protect none" and one for "protect all". */
  40        bp_slots = (1 << hweight8(mask)) - 2;
  41        bp_slots_needed = ilog2(nor->info->n_sectors);
  42
  43        if (bp_slots_needed > bp_slots)
  44                return nor->info->sector_size <<
  45                        (bp_slots_needed - bp_slots);
  46        else
  47                return nor->info->sector_size;
  48}
  49
  50static void spi_nor_get_locked_range_sr(struct spi_nor *nor, u8 sr, loff_t *ofs,
  51                                        uint64_t *len)
  52{
  53        struct mtd_info *mtd = &nor->mtd;
  54        u64 min_prot_len;
  55        u8 mask = spi_nor_get_sr_bp_mask(nor);
  56        u8 tb_mask = spi_nor_get_sr_tb_mask(nor);
  57        u8 bp, val = sr & mask;
  58
  59        if (nor->flags & SNOR_F_HAS_SR_BP3_BIT6 && val & SR_BP3_BIT6)
  60                val = (val & ~SR_BP3_BIT6) | SR_BP3;
  61
  62        bp = val >> SR_BP_SHIFT;
  63
  64        if (!bp) {
  65                /* No protection */
  66                *ofs = 0;
  67                *len = 0;
  68                return;
  69        }
  70
  71        min_prot_len = spi_nor_get_min_prot_length_sr(nor);
  72        *len = min_prot_len << (bp - 1);
  73
  74        if (*len > mtd->size)
  75                *len = mtd->size;
  76
  77        if (nor->flags & SNOR_F_HAS_SR_TB && sr & tb_mask)
  78                *ofs = 0;
  79        else
  80                *ofs = mtd->size - *len;
  81}
  82
  83/*
  84 * Return true if the entire region is locked (if @locked is true) or unlocked
  85 * (if @locked is false); false otherwise.
  86 */
  87static bool spi_nor_check_lock_status_sr(struct spi_nor *nor, loff_t ofs,
  88                                         uint64_t len, u8 sr, bool locked)
  89{
  90        loff_t lock_offs, lock_offs_max, offs_max;
  91        uint64_t lock_len;
  92
  93        if (!len)
  94                return true;
  95
  96        spi_nor_get_locked_range_sr(nor, sr, &lock_offs, &lock_len);
  97
  98        lock_offs_max = lock_offs + lock_len;
  99        offs_max = ofs + len;
 100
 101        if (locked)
 102                /* Requested range is a sub-range of locked range */
 103                return (offs_max <= lock_offs_max) && (ofs >= lock_offs);
 104        else
 105                /* Requested range does not overlap with locked range */
 106                return (ofs >= lock_offs_max) || (offs_max <= lock_offs);
 107}
 108
 109static bool spi_nor_is_locked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len,
 110                                 u8 sr)
 111{
 112        return spi_nor_check_lock_status_sr(nor, ofs, len, sr, true);
 113}
 114
 115static bool spi_nor_is_unlocked_sr(struct spi_nor *nor, loff_t ofs,
 116                                   uint64_t len, u8 sr)
 117{
 118        return spi_nor_check_lock_status_sr(nor, ofs, len, sr, false);
 119}
 120
 121/*
 122 * Lock a region of the flash. Compatible with ST Micro and similar flash.
 123 * Supports the block protection bits BP{0,1,2}/BP{0,1,2,3} in the status
 124 * register
 125 * (SR). Does not support these features found in newer SR bitfields:
 126 *   - SEC: sector/block protect - only handle SEC=0 (block protect)
 127 *   - CMP: complement protect - only support CMP=0 (range is not complemented)
 128 *
 129 * Support for the following is provided conditionally for some flash:
 130 *   - TB: top/bottom protect
 131 *
 132 * Sample table portion for 8MB flash (Winbond w25q64fw):
 133 *
 134 *   SEC  |  TB   |  BP2  |  BP1  |  BP0  |  Prot Length  | Protected Portion
 135 *  --------------------------------------------------------------------------
 136 *    X   |   X   |   0   |   0   |   0   |  NONE         | NONE
 137 *    0   |   0   |   0   |   0   |   1   |  128 KB       | Upper 1/64
 138 *    0   |   0   |   0   |   1   |   0   |  256 KB       | Upper 1/32
 139 *    0   |   0   |   0   |   1   |   1   |  512 KB       | Upper 1/16
 140 *    0   |   0   |   1   |   0   |   0   |  1 MB         | Upper 1/8
 141 *    0   |   0   |   1   |   0   |   1   |  2 MB         | Upper 1/4
 142 *    0   |   0   |   1   |   1   |   0   |  4 MB         | Upper 1/2
 143 *    X   |   X   |   1   |   1   |   1   |  8 MB         | ALL
 144 *  ------|-------|-------|-------|-------|---------------|-------------------
 145 *    0   |   1   |   0   |   0   |   1   |  128 KB       | Lower 1/64
 146 *    0   |   1   |   0   |   1   |   0   |  256 KB       | Lower 1/32
 147 *    0   |   1   |   0   |   1   |   1   |  512 KB       | Lower 1/16
 148 *    0   |   1   |   1   |   0   |   0   |  1 MB         | Lower 1/8
 149 *    0   |   1   |   1   |   0   |   1   |  2 MB         | Lower 1/4
 150 *    0   |   1   |   1   |   1   |   0   |  4 MB         | Lower 1/2
 151 *
 152 * Returns negative on errors, 0 on success.
 153 */
 154static int spi_nor_sr_lock(struct spi_nor *nor, loff_t ofs, uint64_t len)
 155{
 156        struct mtd_info *mtd = &nor->mtd;
 157        u64 min_prot_len;
 158        int ret, status_old, status_new;
 159        u8 mask = spi_nor_get_sr_bp_mask(nor);
 160        u8 tb_mask = spi_nor_get_sr_tb_mask(nor);
 161        u8 pow, val;
 162        loff_t lock_len;
 163        bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB;
 164        bool use_top;
 165
 166        ret = spi_nor_read_sr(nor, nor->bouncebuf);
 167        if (ret)
 168                return ret;
 169
 170        status_old = nor->bouncebuf[0];
 171
 172        /* If nothing in our range is unlocked, we don't need to do anything */
 173        if (spi_nor_is_locked_sr(nor, ofs, len, status_old))
 174                return 0;
 175
 176        /* If anything below us is unlocked, we can't use 'bottom' protection */
 177        if (!spi_nor_is_locked_sr(nor, 0, ofs, status_old))
 178                can_be_bottom = false;
 179
 180        /* If anything above us is unlocked, we can't use 'top' protection */
 181        if (!spi_nor_is_locked_sr(nor, ofs + len, mtd->size - (ofs + len),
 182                                  status_old))
 183                can_be_top = false;
 184
 185        if (!can_be_bottom && !can_be_top)
 186                return -EINVAL;
 187
 188        /* Prefer top, if both are valid */
 189        use_top = can_be_top;
 190
 191        /* lock_len: length of region that should end up locked */
 192        if (use_top)
 193                lock_len = mtd->size - ofs;
 194        else
 195                lock_len = ofs + len;
 196
 197        if (lock_len == mtd->size) {
 198                val = mask;
 199        } else {
 200                min_prot_len = spi_nor_get_min_prot_length_sr(nor);
 201                pow = ilog2(lock_len) - ilog2(min_prot_len) + 1;
 202                val = pow << SR_BP_SHIFT;
 203
 204                if (nor->flags & SNOR_F_HAS_SR_BP3_BIT6 && val & SR_BP3)
 205                        val = (val & ~SR_BP3) | SR_BP3_BIT6;
 206
 207                if (val & ~mask)
 208                        return -EINVAL;
 209
 210                /* Don't "lock" with no region! */
 211                if (!(val & mask))
 212                        return -EINVAL;
 213        }
 214
 215        status_new = (status_old & ~mask & ~tb_mask) | val;
 216
 217        /* Disallow further writes if WP pin is asserted */
 218        status_new |= SR_SRWD;
 219
 220        if (!use_top)
 221                status_new |= tb_mask;
 222
 223        /* Don't bother if they're the same */
 224        if (status_new == status_old)
 225                return 0;
 226
 227        /* Only modify protection if it will not unlock other areas */
 228        if ((status_new & mask) < (status_old & mask))
 229                return -EINVAL;
 230
 231        return spi_nor_write_sr_and_check(nor, status_new);
 232}
 233
 234/*
 235 * Unlock a region of the flash. See spi_nor_sr_lock() for more info
 236 *
 237 * Returns negative on errors, 0 on success.
 238 */
 239static int spi_nor_sr_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len)
 240{
 241        struct mtd_info *mtd = &nor->mtd;
 242        u64 min_prot_len;
 243        int ret, status_old, status_new;
 244        u8 mask = spi_nor_get_sr_bp_mask(nor);
 245        u8 tb_mask = spi_nor_get_sr_tb_mask(nor);
 246        u8 pow, val;
 247        loff_t lock_len;
 248        bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB;
 249        bool use_top;
 250
 251        ret = spi_nor_read_sr(nor, nor->bouncebuf);
 252        if (ret)
 253                return ret;
 254
 255        status_old = nor->bouncebuf[0];
 256
 257        /* If nothing in our range is locked, we don't need to do anything */
 258        if (spi_nor_is_unlocked_sr(nor, ofs, len, status_old))
 259                return 0;
 260
 261        /* If anything below us is locked, we can't use 'top' protection */
 262        if (!spi_nor_is_unlocked_sr(nor, 0, ofs, status_old))
 263                can_be_top = false;
 264
 265        /* If anything above us is locked, we can't use 'bottom' protection */
 266        if (!spi_nor_is_unlocked_sr(nor, ofs + len, mtd->size - (ofs + len),
 267                                    status_old))
 268                can_be_bottom = false;
 269
 270        if (!can_be_bottom && !can_be_top)
 271                return -EINVAL;
 272
 273        /* Prefer top, if both are valid */
 274        use_top = can_be_top;
 275
 276        /* lock_len: length of region that should remain locked */
 277        if (use_top)
 278                lock_len = mtd->size - (ofs + len);
 279        else
 280                lock_len = ofs;
 281
 282        if (lock_len == 0) {
 283                val = 0; /* fully unlocked */
 284        } else {
 285                min_prot_len = spi_nor_get_min_prot_length_sr(nor);
 286                pow = ilog2(lock_len) - ilog2(min_prot_len) + 1;
 287                val = pow << SR_BP_SHIFT;
 288
 289                if (nor->flags & SNOR_F_HAS_SR_BP3_BIT6 && val & SR_BP3)
 290                        val = (val & ~SR_BP3) | SR_BP3_BIT6;
 291
 292                /* Some power-of-two sizes are not supported */
 293                if (val & ~mask)
 294                        return -EINVAL;
 295        }
 296
 297        status_new = (status_old & ~mask & ~tb_mask) | val;
 298
 299        /* Don't protect status register if we're fully unlocked */
 300        if (lock_len == 0)
 301                status_new &= ~SR_SRWD;
 302
 303        if (!use_top)
 304                status_new |= tb_mask;
 305
 306        /* Don't bother if they're the same */
 307        if (status_new == status_old)
 308                return 0;
 309
 310        /* Only modify protection if it will not lock other areas */
 311        if ((status_new & mask) > (status_old & mask))
 312                return -EINVAL;
 313
 314        return spi_nor_write_sr_and_check(nor, status_new);
 315}
 316
 317/*
 318 * Check if a region of the flash is (completely) locked. See spi_nor_sr_lock()
 319 * for more info.
 320 *
 321 * Returns 1 if entire region is locked, 0 if any portion is unlocked, and
 322 * negative on errors.
 323 */
 324static int spi_nor_sr_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len)
 325{
 326        int ret;
 327
 328        ret = spi_nor_read_sr(nor, nor->bouncebuf);
 329        if (ret)
 330                return ret;
 331
 332        return spi_nor_is_locked_sr(nor, ofs, len, nor->bouncebuf[0]);
 333}
 334
 335static const struct spi_nor_locking_ops spi_nor_sr_locking_ops = {
 336        .lock = spi_nor_sr_lock,
 337        .unlock = spi_nor_sr_unlock,
 338        .is_locked = spi_nor_sr_is_locked,
 339};
 340
 341void spi_nor_init_default_locking_ops(struct spi_nor *nor)
 342{
 343        nor->params->locking_ops = &spi_nor_sr_locking_ops;
 344}
 345
 346static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 347{
 348        struct spi_nor *nor = mtd_to_spi_nor(mtd);
 349        int ret;
 350
 351        ret = spi_nor_lock_and_prep(nor);
 352        if (ret)
 353                return ret;
 354
 355        ret = nor->params->locking_ops->lock(nor, ofs, len);
 356
 357        spi_nor_unlock_and_unprep(nor);
 358        return ret;
 359}
 360
 361static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 362{
 363        struct spi_nor *nor = mtd_to_spi_nor(mtd);
 364        int ret;
 365
 366        ret = spi_nor_lock_and_prep(nor);
 367        if (ret)
 368                return ret;
 369
 370        ret = nor->params->locking_ops->unlock(nor, ofs, len);
 371
 372        spi_nor_unlock_and_unprep(nor);
 373        return ret;
 374}
 375
 376static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 377{
 378        struct spi_nor *nor = mtd_to_spi_nor(mtd);
 379        int ret;
 380
 381        ret = spi_nor_lock_and_prep(nor);
 382        if (ret)
 383                return ret;
 384
 385        ret = nor->params->locking_ops->is_locked(nor, ofs, len);
 386
 387        spi_nor_unlock_and_unprep(nor);
 388        return ret;
 389}
 390
 391/**
 392 * spi_nor_try_unlock_all() - Tries to unlock the entire flash memory array.
 393 * @nor:        pointer to a 'struct spi_nor'.
 394 *
 395 * Some SPI NOR flashes are write protected by default after a power-on reset
 396 * cycle, in order to avoid inadvertent writes during power-up. Backward
 397 * compatibility imposes to unlock the entire flash memory array at power-up
 398 * by default.
 399 *
 400 * Unprotecting the entire flash array will fail for boards which are hardware
 401 * write-protected. Thus any errors are ignored.
 402 */
 403void spi_nor_try_unlock_all(struct spi_nor *nor)
 404{
 405        int ret;
 406
 407        if (!(nor->flags & SNOR_F_HAS_LOCK))
 408                return;
 409
 410        dev_dbg(nor->dev, "Unprotecting entire flash array\n");
 411
 412        ret = spi_nor_unlock(&nor->mtd, 0, nor->params->size);
 413        if (ret)
 414                dev_dbg(nor->dev, "Failed to unlock the entire flash memory array\n");
 415}
 416
 417void spi_nor_register_locking_ops(struct spi_nor *nor)
 418{
 419        struct mtd_info *mtd = &nor->mtd;
 420
 421        if (!nor->params->locking_ops)
 422                return;
 423
 424        mtd->_lock = spi_nor_lock;
 425        mtd->_unlock = spi_nor_unlock;
 426        mtd->_is_locked = spi_nor_is_locked;
 427}
 428