mtd: rawnand: Macronix: Add support for block protection
Macronix AC/AD series support using SET_FEATURES to change block protection and unprotection. Block protection support can be checked with GET_FEATURES. Signed-off-by: Mason Yang <masonccyang@mxic.com.tw> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> Link: https://lore.kernel.org/linux-mtd/1583220084-10890-3-git-send-email-masonccyang@mxic.com.tw
This commit is contained in:
parent
92270086b7
commit
03a539c7a1
|
@ -11,6 +11,10 @@
|
|||
#define MACRONIX_READ_RETRY_BIT BIT(0)
|
||||
#define MACRONIX_NUM_READ_RETRY_MODES 6
|
||||
|
||||
#define ONFI_FEATURE_ADDR_MXIC_PROTECTION 0xA0
|
||||
#define MXIC_BLOCK_PROTECTION_ALL_LOCK 0x38
|
||||
#define MXIC_BLOCK_PROTECTION_ALL_UNLOCK 0x0
|
||||
|
||||
#define ONFI_FEATURE_ADDR_MXIC_RANDOMIZER 0xB0
|
||||
#define MACRONIX_RANDOMIZER_BIT BIT(1)
|
||||
#define MACRONIX_RANDOMIZER_ENPGM BIT(0)
|
||||
|
@ -172,6 +176,73 @@ static void macronix_nand_fix_broken_get_timings(struct nand_chip *chip)
|
|||
ONFI_FEATURE_ADDR_TIMING_MODE, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Macronix NAND supports Block Protection by Protectoin(PT) pin;
|
||||
* active high at power-on which protects the entire chip even the #WP is
|
||||
* disabled. Lock/unlock protection area can be partition according to
|
||||
* protection bits, i.e. upper 1/2 locked, upper 1/4 locked and so on.
|
||||
*/
|
||||
static int mxic_nand_lock(struct nand_chip *chip, loff_t ofs, uint64_t len)
|
||||
{
|
||||
u8 feature[ONFI_SUBFEATURE_PARAM_LEN];
|
||||
int ret;
|
||||
|
||||
feature[0] = MXIC_BLOCK_PROTECTION_ALL_LOCK;
|
||||
nand_select_target(chip, 0);
|
||||
ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_PROTECTION,
|
||||
feature);
|
||||
nand_deselect_target(chip);
|
||||
if (ret)
|
||||
pr_err("%s all blocks failed\n", __func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mxic_nand_unlock(struct nand_chip *chip, loff_t ofs, uint64_t len)
|
||||
{
|
||||
u8 feature[ONFI_SUBFEATURE_PARAM_LEN];
|
||||
int ret;
|
||||
|
||||
feature[0] = MXIC_BLOCK_PROTECTION_ALL_UNLOCK;
|
||||
nand_select_target(chip, 0);
|
||||
ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_PROTECTION,
|
||||
feature);
|
||||
nand_deselect_target(chip);
|
||||
if (ret)
|
||||
pr_err("%s all blocks failed\n", __func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void macronix_nand_block_protection_support(struct nand_chip *chip)
|
||||
{
|
||||
u8 feature[ONFI_SUBFEATURE_PARAM_LEN];
|
||||
int ret;
|
||||
|
||||
bitmap_set(chip->parameters.get_feature_list,
|
||||
ONFI_FEATURE_ADDR_MXIC_PROTECTION, 1);
|
||||
|
||||
feature[0] = MXIC_BLOCK_PROTECTION_ALL_UNLOCK;
|
||||
nand_select_target(chip, 0);
|
||||
ret = nand_get_features(chip, ONFI_FEATURE_ADDR_MXIC_PROTECTION,
|
||||
feature);
|
||||
nand_deselect_target(chip);
|
||||
if (ret || feature[0] != MXIC_BLOCK_PROTECTION_ALL_LOCK) {
|
||||
if (ret)
|
||||
pr_err("Block protection check failed\n");
|
||||
|
||||
bitmap_clear(chip->parameters.get_feature_list,
|
||||
ONFI_FEATURE_ADDR_MXIC_PROTECTION, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
bitmap_set(chip->parameters.set_feature_list,
|
||||
ONFI_FEATURE_ADDR_MXIC_PROTECTION, 1);
|
||||
|
||||
chip->lock_area = mxic_nand_lock;
|
||||
chip->unlock_area = mxic_nand_unlock;
|
||||
}
|
||||
|
||||
static int macronix_nand_init(struct nand_chip *chip)
|
||||
{
|
||||
if (nand_is_slc(chip))
|
||||
|
@ -179,6 +250,7 @@ static int macronix_nand_init(struct nand_chip *chip)
|
|||
|
||||
macronix_nand_fix_broken_get_timings(chip);
|
||||
macronix_nand_onfi_init(chip);
|
||||
macronix_nand_block_protection_support(chip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue