// SPDX-License-Identifier: GPL-2.0 /* * SPI NOR Software Write Protection logic. * * Copyright (C) 2005, Intec Automation Inc. * Copyright (C) 2014, Freescale Semiconductor, Inc. */ #include <linux/mtd/mtd.h> #include <linux/mtd/spi-nor.h> #include "core.h" static u8 spi_nor_get_sr_bp_mask(struct spi_nor *nor) { … } static u8 spi_nor_get_sr_tb_mask(struct spi_nor *nor) { … } static u64 spi_nor_get_min_prot_length_sr(struct spi_nor *nor) { … } static void spi_nor_get_locked_range_sr(struct spi_nor *nor, u8 sr, loff_t *ofs, u64 *len) { … } /* * Return true if the entire region is locked (if @locked is true) or unlocked * (if @locked is false); false otherwise. */ static bool spi_nor_check_lock_status_sr(struct spi_nor *nor, loff_t ofs, u64 len, u8 sr, bool locked) { … } static bool spi_nor_is_locked_sr(struct spi_nor *nor, loff_t ofs, u64 len, u8 sr) { … } static bool spi_nor_is_unlocked_sr(struct spi_nor *nor, loff_t ofs, u64 len, u8 sr) { … } /* * Lock a region of the flash. Compatible with ST Micro and similar flash. * Supports the block protection bits BP{0,1,2}/BP{0,1,2,3} in the status * register * (SR). Does not support these features found in newer SR bitfields: * - SEC: sector/block protect - only handle SEC=0 (block protect) * - CMP: complement protect - only support CMP=0 (range is not complemented) * * Support for the following is provided conditionally for some flash: * - TB: top/bottom protect * * Sample table portion for 8MB flash (Winbond w25q64fw): * * SEC | TB | BP2 | BP1 | BP0 | Prot Length | Protected Portion * -------------------------------------------------------------------------- * X | X | 0 | 0 | 0 | NONE | NONE * 0 | 0 | 0 | 0 | 1 | 128 KB | Upper 1/64 * 0 | 0 | 0 | 1 | 0 | 256 KB | Upper 1/32 * 0 | 0 | 0 | 1 | 1 | 512 KB | Upper 1/16 * 0 | 0 | 1 | 0 | 0 | 1 MB | Upper 1/8 * 0 | 0 | 1 | 0 | 1 | 2 MB | Upper 1/4 * 0 | 0 | 1 | 1 | 0 | 4 MB | Upper 1/2 * X | X | 1 | 1 | 1 | 8 MB | ALL * ------|-------|-------|-------|-------|---------------|------------------- * 0 | 1 | 0 | 0 | 1 | 128 KB | Lower 1/64 * 0 | 1 | 0 | 1 | 0 | 256 KB | Lower 1/32 * 0 | 1 | 0 | 1 | 1 | 512 KB | Lower 1/16 * 0 | 1 | 1 | 0 | 0 | 1 MB | Lower 1/8 * 0 | 1 | 1 | 0 | 1 | 2 MB | Lower 1/4 * 0 | 1 | 1 | 1 | 0 | 4 MB | Lower 1/2 * * Returns negative on errors, 0 on success. */ static int spi_nor_sr_lock(struct spi_nor *nor, loff_t ofs, u64 len) { … } /* * Unlock a region of the flash. See spi_nor_sr_lock() for more info * * Returns negative on errors, 0 on success. */ static int spi_nor_sr_unlock(struct spi_nor *nor, loff_t ofs, u64 len) { … } /* * Check if a region of the flash is (completely) locked. See spi_nor_sr_lock() * for more info. * * Returns 1 if entire region is locked, 0 if any portion is unlocked, and * negative on errors. */ static int spi_nor_sr_is_locked(struct spi_nor *nor, loff_t ofs, u64 len) { … } static const struct spi_nor_locking_ops spi_nor_sr_locking_ops = …; void spi_nor_init_default_locking_ops(struct spi_nor *nor) { … } static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, u64 len) { … } static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, u64 len) { … } static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, u64 len) { … } /** * spi_nor_try_unlock_all() - Tries to unlock the entire flash memory array. * @nor: pointer to a 'struct spi_nor'. * * Some SPI NOR flashes are write protected by default after a power-on reset * cycle, in order to avoid inadvertent writes during power-up. Backward * compatibility imposes to unlock the entire flash memory array at power-up * by default. * * Unprotecting the entire flash array will fail for boards which are hardware * write-protected. Thus any errors are ignored. */ void spi_nor_try_unlock_all(struct spi_nor *nor) { … } void spi_nor_set_mtd_locking_ops(struct spi_nor *nor) { … }