From nobody Tue Apr 7 01:36:07 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (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 DB7513CFF7D for ; Fri, 3 Apr 2026 16:10:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775232611; cv=none; b=g8pl3FWPxvFDZDSw0UMl/7xz5wuTGoEF3gLifxJYDsfBnidDvKBu2M0uj0axTNbWUGIo172siggG+uwsx5n+6HGPFkHaArubzGEMB3Jejaw/t56YMMkY5vp346dXyVdi9wPy1ZFJRp4btkQhzMSgCzxIAMVoYS9G1HMCaPN2mVI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775232611; c=relaxed/simple; bh=wJlFUDPAi6ogepYsFHibAA47a35dOGAAG0yfdvRFbzw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=IF+AoX9zGPss+witc3GWncn+9D0rAjsSpoiNKshVKii7lxVUwKM4JyKbN+GMU2VZcEv9PJ7+A9hwiud166Vr2O5Dyu0hK0txTltnOS6eQja8rCQCot3NK6Zb1tFGf5OCsTbJrMmOpAC604ZPqrxC8CM9Is6CxIXg0Rr8f8po4I4= 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=LUXasgoY; arc=none smtp.client-ip=185.246.85.4 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="LUXasgoY" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id B6CC34E428D7; Fri, 3 Apr 2026 16:10:08 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 8BF11603C1; Fri, 3 Apr 2026 16:10:08 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id EE5CA104500F6; Fri, 3 Apr 2026 18:10:04 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1775232607; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=xzSy+EhNI9t9zTqMF1NixCi1hFBNiZkvrrCmxjn6Qww=; b=LUXasgoYgUxnSYaqKpNjymZ/Qvv340Urc9Z5AxflgEzL0mlHnOmx6ujlAOqq8HMTe4RnKl SqWLHFfhrDHx0Jp89i1tlZ52r2t5gkEnWBCJ/HR6dAZailfXtM/CXeibU+TJz/xNvDFmuP tBJthi+c4CQUWGOyXv9KKXt8PEQ6G/OFY5niqOnyn3bGp3JFoLke9oQprxN8WA9auU1M34 aa077vkc3vZVDiBF22ZZH9Db51bP0uqyS3sA3+L/Hj910K6OlS4zRwaNfMgpmDdd2ZS0nt CAr7ryl50sDv8YyimqmbKU8MARmDz0mnrHk0ZFHeWxgC/LSo87ber6jHXSw2ag== From: Miquel Raynal Date: Fri, 03 Apr 2026 18:09:31 +0200 Subject: [PATCH v4 13/27] 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: <20260403-winbond-v6-18-rc1-spi-nor-swp-v4-13-833dab5e7288@bootlin.com> References: <20260403-winbond-v6-18-rc1-spi-nor-swp-v4-0-833dab5e7288@bootlin.com> In-Reply-To: <20260403-winbond-v6-18-rc1-spi-nor-swp-v4-0-833dab5e7288@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , 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.3 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 f068cb9c8f6d..e2e423b20989 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) @@ -297,29 +324,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.53.0