From nobody Wed Feb 11 06:51:13 2026 Received: from smtpout-04.galae.net (smtpout-04.galae.net [185.171.202.116]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DA51E34AB04; Fri, 14 Nov 2025 17:53:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.171.202.116 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763142826; cv=none; b=YnIUOgXvB6Iu3mooJtBwbf/Ftd7hF2XsmWG3y9wqLkUjKlOTdAie0SaDfEMvnbWiIU41WS87Q8MByThshH6bsJPA1XafzuwI0qiY6SQ2hpnRoHfiWzhmBgGApioWCMSLzKqcmyynqvWNDmVZNM2TzRQ+9I/Vw+lmT4D8Vgf5EyU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763142826; c=relaxed/simple; bh=+iWeK1SNziEgD4atEa6EArbgwSOwycrvxugB7HwHJ9g=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=fQB0T56NjvK1dMCbWWf/4sB1ntugLQK5rD/PjV/ZsIQ6iZEECxjFD+aMYB+K2RRG4CA8jAQExUW9AuIFNhS9QRPFC38QpeQXCc7HvvPpL0VxmtYve+rnDI7+O+BHwYM989zWZiknDWoS0iIForkjtukAh1tUuAIO40Md3Npii/I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=l7hN54ih; arc=none smtp.client-ip=185.171.202.116 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="l7hN54ih" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-04.galae.net (Postfix) with ESMTPS id 7D26CC10F6D; Fri, 14 Nov 2025 17:53:20 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 531456060E; Fri, 14 Nov 2025 17:53:42 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id D5377103719B8; Fri, 14 Nov 2025 18:53:39 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1763142821; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=X+WamAy2nRs/ruUdo1bhUm2AXL9vdRoCmEPHNhd85A8=; b=l7hN54ihYOXOl8xCMY6/iScDmoeO9KeCNkS5ahGrpe8iuydviys/kBEHJ4SojnkTfpyhmf PLLuA8c7UckD9hcKmPW10g6T5EWM9KbrN4SvZ0PqG7deQvk2pYGxHayNhhYtdyDp07sJCy V1Qcs3gh+3Dquk8jcpCg29JWWVPDx9RnWS0ma0ltoyDKyMKevbJ7FftFRgqCIDCbESLVc8 SRkcHZRRaNTitI941CMk9lMtq2wnZ0Bdks5OLtLXvI0M9wCXOhCqrLv26va2weG7OJXv7y aqo7zJFFLGkaeqxANfsV3ncophWJhjIWjO6Vk/ok29H05HzUHnlFFFn3MSt4uw== From: Miquel Raynal Date: Fri, 14 Nov 2025 18:53:13 +0100 Subject: [PATCH 12/19] mtd: spi-nor: swp: Create helpers for building the SR register Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251114-winbond-v6-18-rc1-spi-nor-swp-v1-12-487bc7129931@bootlin.com> References: <20251114-winbond-v6-18-rc1-spi-nor-swp-v1-0-487bc7129931@bootlin.com> In-Reply-To: <20251114-winbond-v6-18-rc1-spi-nor-swp-v1-0-487bc7129931@bootlin.com> To: Tudor Ambarus , Pratyush Yadav , Michael Walle , Richard Weinberger , Vignesh Raghavendra , Jonathan Corbet Cc: Sean Anderson , Thomas Petazzoni , Steam Lin , linux-mtd@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.2 X-Last-TLS-Session-Version: TLSv1.3 The status register contains 3 or 4 BP (Block Protect) bits, 0 or 1 TB (Top/Bottom) bit, soon 0 or 1 CMP (Complement) bit. The last BP bit and the TB bit locations change between vendors. The whole logic of buildling the content of the status register based on some input conditions is used two times and soon will be used 4 times. Create dedicated helpers for these steps. Signed-off-by: Miquel Raynal --- drivers/mtd/spi-nor/swp.c | 83 +++++++++++++++++++++++++++++--------------= ---- 1 file changed, 51 insertions(+), 32 deletions(-) diff --git a/drivers/mtd/spi-nor/swp.c b/drivers/mtd/spi-nor/swp.c index 61d899b4fbf42b8bd9d86dc4e6b3ffcfe91a90e8..48c4f76db793a17dedb0f904d57= e446de8fd04cd 100644 --- a/drivers/mtd/spi-nor/swp.c +++ b/drivers/mtd/spi-nor/swp.c @@ -123,6 +123,43 @@ static bool spi_nor_is_unlocked_sr(struct spi_nor *nor= , loff_t ofs, u64 len, return spi_nor_check_lock_status_sr(nor, ofs, len, sr, false); } =20 +static int spi_nor_sr_set_bp_mask(struct spi_nor *nor, u8 *sr, u8 pow) +{ + u8 mask =3D spi_nor_get_sr_bp_mask(nor); + u8 val =3D pow << SR_BP_SHIFT; + + if (nor->flags & SNOR_F_HAS_SR_BP3_BIT6 && val & SR_BP3) + val =3D (val & ~SR_BP3) | SR_BP3_BIT6; + + if (val & ~mask) + return -EINVAL; + + sr[0] =3D val; + + return 0; +} + +static int spi_nor_build_sr(struct spi_nor *nor, const u8 *old_sr, u8 *new= _sr, + u8 pow, bool use_top) +{ + u8 bp_mask =3D spi_nor_get_sr_bp_mask(nor); + u8 tb_mask =3D spi_nor_get_sr_tb_mask(nor); + int ret; + + new_sr[0] =3D old_sr[0] & ~bp_mask & ~tb_mask; + + /* Build BP field*/ + ret =3D spi_nor_sr_set_bp_mask(nor, &new_sr[0], pow); + if (ret) + return ret; + + /* Build TB field */ + if (!use_top) + new_sr[0] |=3D tb_mask; + + return 0; +} + /* * 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 @@ -162,11 +199,10 @@ static int spi_nor_sr_lock(struct spi_nor *nor, loff_= t ofs, u64 len) int ret; u8 status_old[1] =3D {}, status_new[1] =3D {}; u8 bp_mask =3D spi_nor_get_sr_bp_mask(nor); - u8 tb_mask =3D spi_nor_get_sr_tb_mask(nor); - u8 pow, val; loff_t lock_len; bool can_be_top =3D true, can_be_bottom =3D nor->flags & SNOR_F_HAS_SR_TB; bool use_top; + u8 pow; =20 ret =3D spi_nor_read_sr(nor, nor->bouncebuf); if (ret) @@ -200,24 +236,19 @@ static int spi_nor_sr_lock(struct spi_nor *nor, loff_= t ofs, u64 len) lock_len =3D ofs + len; =20 if (lock_len =3D=3D nor->params->size) { - val =3D bp_mask; + pow =3D (nor->flags & SNOR_F_HAS_4BIT_BP) ? GENMASK(3, 0) : GENMASK(2, 0= ); } else { min_prot_len =3D spi_nor_get_min_prot_length_sr(nor); pow =3D ilog2(lock_len) - ilog2(min_prot_len) + 1; - val =3D pow << SR_BP_SHIFT; - - if (nor->flags & SNOR_F_HAS_SR_BP3_BIT6 && val & SR_BP3) - val =3D (val & ~SR_BP3) | SR_BP3_BIT6; - - if (val & ~bp_mask) - return -EINVAL; - - /* Don't "lock" with no region! */ - if (!(val & bp_mask)) - return -EINVAL; } =20 - status_new[0] =3D (status_old[0] & ~bp_mask & ~tb_mask) | val; + ret =3D spi_nor_build_sr(nor, status_old, status_new, pow, use_top); + if (ret) + return ret; + + /* Don't "lock" with no region! */ + if (!(status_new[0] & bp_mask)) + return -EINVAL; =20 /* * Disallow further writes if WP# pin is neither left floating nor @@ -227,9 +258,6 @@ static int spi_nor_sr_lock(struct spi_nor *nor, loff_t = ofs, u64 len) if (!(nor->flags & SNOR_F_NO_WP)) status_new[0] |=3D SR_SRWD; =20 - if (!use_top) - status_new[0] |=3D tb_mask; - /* Don't bother if they're the same */ if (status_new[0] =3D=3D status_old[0]) return 0; @@ -252,11 +280,10 @@ static int spi_nor_sr_unlock(struct spi_nor *nor, lof= f_t ofs, u64 len) int ret; u8 status_old[1], status_new[1]; u8 bp_mask =3D spi_nor_get_sr_bp_mask(nor); - u8 tb_mask =3D spi_nor_get_sr_tb_mask(nor); - u8 pow, val; loff_t lock_len; bool can_be_top =3D true, can_be_bottom =3D nor->flags & SNOR_F_HAS_SR_TB; bool use_top; + u8 pow; =20 ret =3D spi_nor_read_sr(nor, nor->bouncebuf); if (ret) @@ -292,29 +319,21 @@ static int spi_nor_sr_unlock(struct spi_nor *nor, lof= f_t ofs, u64 len) lock_len =3D ofs; =20 if (lock_len =3D=3D 0) { - val =3D 0; /* fully unlocked */ + pow =3D 0; /* fully unlocked */ } else { min_prot_len =3D spi_nor_get_min_prot_length_sr(nor); pow =3D ilog2(lock_len) - ilog2(min_prot_len) + 1; - val =3D pow << SR_BP_SHIFT; =20 - if (nor->flags & SNOR_F_HAS_SR_BP3_BIT6 && val & SR_BP3) - val =3D (val & ~SR_BP3) | SR_BP3_BIT6; - - /* Some power-of-two sizes may not be supported */ - if (val & ~bp_mask) - return -EINVAL; } =20 - status_new[0] =3D (status_old[0] & ~bp_mask & ~tb_mask) | val; + ret =3D spi_nor_build_sr(nor, status_old, status_new, pow, use_top); + if (ret) + return ret; =20 /* Don't protect status register if we're fully unlocked */ if (lock_len =3D=3D 0) status_new[0] &=3D ~SR_SRWD; =20 - if (!use_top) - status_new[0] |=3D tb_mask; - /* Don't bother if they're the same */ if (status_new[0] =3D=3D status_old[0]) return 0; --=20 2.51.0