diff mbox series

mtd: spi-nor: parse SFDP 4-byte Address Instruction Table

Message ID 20181120115512.15958-1-tudor.ambarus@microchip.com
State Changes Requested
Delegated to: Boris Brezillon
Headers show
Series mtd: spi-nor: parse SFDP 4-byte Address Instruction Table | expand

Commit Message

Tudor Ambarus Nov. 20, 2018, 11:55 a.m. UTC
From: Cyrille Pitchen <cyrille.pitchen@microchip.com>

Add support for SFDP (JESD216B) 4-byte Address Instruction Table. This
table is optional but when available, we parse it to get the 4-byte
address op codes supported by the memory.
Using these op codes is stateless as opposed to entering the 4-byte
address mode or setting the Base Address Register (BAR).

Flashes that have the 4BAIT table declared can now support
SPINOR_OP_PP_1_1_4_4B and SPINOR_OP_PP_1_4_4_4B opcodes.

Tested on MX25L25673G.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@microchip.com>
[tudor.ambarus@microchip.com:
- rework erase and page program logic,
- pass DMA-able buffer to spi_nor_read_sfdp(),
- various minor updates.]
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
Depends on spi_nor_sort_erase_mask() defined in
"[PATCH v2] mtd: spi-nor: fix selection of uniform erase type in flexible conf".

 drivers/mtd/spi-nor/spi-nor.c | 189 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 189 insertions(+)

Comments

kernel test robot Nov. 20, 2018, 5:43 p.m. UTC | #1
Hi Cyrille,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on mtd/spi-nor/next]
[also build test ERROR on v4.20-rc3 next-20181120]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Tudor-Ambarus-microchip-com/mtd-spi-nor-parse-SFDP-4-byte-Address-Instruction-Table/20181120-223821
base:   git://git.infradead.org/linux-mtd.git spi-nor/next
config: nds32-allyesconfig (attached as .config)
compiler: nds32le-linux-gcc (GCC) 6.4.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=6.4.0 make.cross ARCH=nds32 

All errors (new ones prefixed by >>):

   drivers/mtd//spi-nor/spi-nor.c: In function 'spi_nor_parse_4bait':
>> drivers/mtd//spi-nor/spi-nor.c:3165:15: error: implicit declaration of function 'spi_nor_sort_erase_mask' [-Werror=implicit-function-declaration]
     erase_mask = spi_nor_sort_erase_mask(map, erase_mask);
                  ^~~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +/spi_nor_sort_erase_mask +3165 drivers/mtd//spi-nor/spi-nor.c

  3053	
  3054	/**
  3055	 * spi_nor_parse_4bait() - parse the 4-Byte Address Instruction Table
  3056	 * @nor:		pointer to a 'struct spi_nor'.
  3057	 * @param_header:	pointer to the 'struct sfdp_parameter_header' describing
  3058	 *			the 4-Byte Address Instruction Table length and version.
  3059	 * @params:		pointer to the 'struct spi_nor_flash_parameter' to be.
  3060	 *
  3061	 * Return: 0 on success, -errno otherwise.
  3062	 */
  3063	static int spi_nor_parse_4bait(struct spi_nor *nor,
  3064				       const struct sfdp_parameter_header *param_header,
  3065				       struct spi_nor_flash_parameter *params)
  3066	{
  3067		static const struct sfdp_4bait reads[] = {
  3068			{ SNOR_HWCAPS_READ,		BIT(0) },
  3069			{ SNOR_HWCAPS_READ_FAST,	BIT(1) },
  3070			{ SNOR_HWCAPS_READ_1_1_2,	BIT(2) },
  3071			{ SNOR_HWCAPS_READ_1_2_2,	BIT(3) },
  3072			{ SNOR_HWCAPS_READ_1_1_4,	BIT(4) },
  3073			{ SNOR_HWCAPS_READ_1_4_4,	BIT(5) },
  3074			{ SNOR_HWCAPS_READ_1_1_1_DTR,	BIT(13) },
  3075			{ SNOR_HWCAPS_READ_1_2_2_DTR,	BIT(14) },
  3076			{ SNOR_HWCAPS_READ_1_4_4_DTR,	BIT(15) },
  3077		};
  3078		static const struct sfdp_4bait programs[] = {
  3079			{ SNOR_HWCAPS_PP,		BIT(6) },
  3080			{ SNOR_HWCAPS_PP_1_1_4,		BIT(7) },
  3081			{ SNOR_HWCAPS_PP_1_4_4,		BIT(8) },
  3082		};
  3083		static const struct sfdp_4bait erases[SNOR_ERASE_TYPE_MAX] = {
  3084			{ 0u /* not used */,		BIT(9) },
  3085			{ 0u /* not used */,		BIT(10) },
  3086			{ 0u /* not used */,		BIT(11) },
  3087			{ 0u /* not used */,		BIT(12) },
  3088		};
  3089		struct spi_nor_pp_command *params_pp = params->page_programs;
  3090		struct spi_nor_erase_map *map = &nor->erase_map;
  3091		struct spi_nor_erase_type *erase_type = map->erase_type;
  3092		u32 *dwords;
  3093		size_t len;
  3094		u32 addr, discard_hwcaps, read_hwcaps, pp_hwcaps, erase_mask;
  3095		int i, ret;
  3096	
  3097		if (param_header->major != SFDP_JESD216_MAJOR ||
  3098		    param_header->length < SFDP_4BAIT_DWORD_MAX)
  3099			return -EINVAL;
  3100	
  3101		/* Read the 4-byte Address Instruction Table. */
  3102		len = sizeof(*dwords) * SFDP_4BAIT_DWORD_MAX;
  3103	
  3104		/* Use a kmalloc'ed bounce buffer to guarantee it is DMA-able. */
  3105		dwords = kmalloc(len, GFP_KERNEL);
  3106		if (!dwords)
  3107			return -ENOMEM;
  3108	
  3109		addr = SFDP_PARAM_HEADER_PTP(param_header);
  3110		ret = spi_nor_read_sfdp(nor, addr, len, dwords);
  3111		if (ret)
  3112			return ret;
  3113	
  3114		/* Fix endianness of the 4BAIT DWORDs. */
  3115		for (i = 0; i < SFDP_4BAIT_DWORD_MAX; i++)
  3116			dwords[i] = le32_to_cpu(dwords[i]);
  3117	
  3118		/*
  3119		 * Compute the subset of (Fast) Read commands for which the 4-byte
  3120		 * version is supported.
  3121		 */
  3122		discard_hwcaps = 0;
  3123		read_hwcaps = 0;
  3124		for (i = 0; i < ARRAY_SIZE(reads); i++) {
  3125			const struct sfdp_4bait *read = &reads[i];
  3126	
  3127			discard_hwcaps |= read->hwcaps;
  3128			if ((params->hwcaps.mask & read->hwcaps) &&
  3129			    (dwords[0] & read->supported_bit))
  3130				read_hwcaps |= read->hwcaps;
  3131		}
  3132	
  3133		/*
  3134		 * Compute the subset of Page Program commands for which the 4-byte
  3135		 * version is supported.
  3136		 */
  3137		pp_hwcaps = 0;
  3138		for (i = 0; i < ARRAY_SIZE(programs); i++) {
  3139			const struct sfdp_4bait *program = &programs[i];
  3140	
  3141			/*
  3142			 * The 4 Byte Address Instruction (Optional) Table is the only
  3143			 * SFDP table that indicates support for Page Program Commands.
  3144			 * Bypass the params->hwcaps.mask and consider 4BAIT the biggest
  3145			 * authority for specifying Page Program support.
  3146			 */
  3147			discard_hwcaps |= program->hwcaps;
  3148			if (dwords[0] & program->supported_bit)
  3149				pp_hwcaps |= program->hwcaps;
  3150		}
  3151	
  3152		/*
  3153		 * Compute the subset of Sector Erase commands for which the 4-byte
  3154		 * version is supported.
  3155		 */
  3156		erase_mask = 0;
  3157		for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) {
  3158			const struct sfdp_4bait *erase = &erases[i];
  3159	
  3160			if (dwords[0] & erase->supported_bit)
  3161				erase_mask |= BIT(i);
  3162		}
  3163	
  3164		/* Replicate the sort done for the map's erase types in BFPT. */
> 3165		erase_mask = spi_nor_sort_erase_mask(map, erase_mask);
  3166	
  3167		/*
  3168		 * We need at least one 4-byte op code per read, program and erase
  3169		 * operation; the .read(), .write() and .erase() hooks share the
  3170		 * nor->addr_width value.
  3171		 */
  3172		if (!read_hwcaps || !pp_hwcaps || !erase_mask)
  3173			goto out;
  3174	
  3175		/*
  3176		 * Discard all operations from the 4-byte instruction set which are
  3177		 * not supported by this memory.
  3178		 */
  3179		params->hwcaps.mask &= ~discard_hwcaps;
  3180		params->hwcaps.mask |= (read_hwcaps | pp_hwcaps);
  3181	
  3182		/* Use the 4-byte address instruction set. */
  3183		for (i = 0; i < SNOR_CMD_READ_MAX; i++) {
  3184			struct spi_nor_read_command *read_cmd = &params->reads[i];
  3185	
  3186			read_cmd->opcode = spi_nor_convert_3to4_read(read_cmd->opcode);
  3187		}
  3188	
  3189		/* 4BAIT is the only SFDP table that indicates page program support. */
  3190		if (pp_hwcaps & SNOR_HWCAPS_PP)
  3191			spi_nor_set_pp_settings(&params_pp[SNOR_CMD_PP],
  3192						SPINOR_OP_PP_4B, SNOR_PROTO_1_1_1);
  3193		if (pp_hwcaps & SNOR_HWCAPS_PP_1_1_4)
  3194			spi_nor_set_pp_settings(&params_pp[SNOR_CMD_PP_1_1_4],
  3195						SPINOR_OP_PP_1_1_4_4B,
  3196						SNOR_PROTO_1_1_4);
  3197		if (pp_hwcaps & SNOR_HWCAPS_PP_1_4_4)
  3198			spi_nor_set_pp_settings(&params_pp[SNOR_CMD_PP_1_4_4],
  3199						SPINOR_OP_PP_1_4_4_4B,
  3200						SNOR_PROTO_1_4_4);
  3201	
  3202		for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) {
  3203			if (erase_mask & BIT(i))
  3204				erase_type[i].opcode = (dwords[1] >>
  3205							erase_type[i].idx * 8) & 0xFF;
  3206			else
  3207				spi_nor_set_erase_type(&erase_type[i], 0u, 0xFF);
  3208		}
  3209	
  3210		/*
  3211		 * We set nor->addr_width here to skip spi_nor_set_4byte_opcodes()
  3212		 * later because this latest function implements a legacy quirk for
  3213		 * the erase size of Spansion memory. However this quirk is no longer
  3214		 * needed with new SFDP compliant memories.
  3215		 */
  3216		nor->addr_width = 4;
  3217		nor->flags |= SPI_NOR_4B_OPCODES;
  3218	
  3219		/* fall through */
  3220	out:
  3221		kfree(dwords);
  3222		return ret;
  3223	}
  3224	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
Boris Brezillon Nov. 28, 2018, 7:57 a.m. UTC | #2
On Tue, 20 Nov 2018 11:55:21 +0000
<Tudor.Ambarus@microchip.com> wrote:

> +
> +	/*
> +	 * We set nor->addr_width here to skip spi_nor_set_4byte_opcodes()
> +	 * later because this latest function implements a legacy quirk for
> +	 * the erase size of Spansion memory. However this quirk is no longer
> +	 * needed with new SFDP compliant memories.
> +	 */
> +	nor->addr_width = 4;
> +	nor->flags |= SPI_NOR_4B_OPCODES;

You mean SNOR_F_4B_OPCODES (the one introduced here [1]), because
SPI_NOR_4B_OPCODES should only be used for flash_info->flags and might
soon conflict with another SNOR_F_ flag?

[1]http://patchwork.ozlabs.org/patch/991476/
Tudor Ambarus Nov. 28, 2018, 2:17 p.m. UTC | #3
On 11/28/2018 09:57 AM, Boris Brezillon wrote:
> On Tue, 20 Nov 2018 11:55:21 +0000
> <Tudor.Ambarus@microchip.com> wrote:
> 
>> +
>> +	/*
>> +	 * We set nor->addr_width here to skip spi_nor_set_4byte_opcodes()
>> +	 * later because this latest function implements a legacy quirk for
>> +	 * the erase size of Spansion memory. However this quirk is no longer
>> +	 * needed with new SFDP compliant memories.
>> +	 */
>> +	nor->addr_width = 4;
>> +	nor->flags |= SPI_NOR_4B_OPCODES;
> 
> You mean SNOR_F_4B_OPCODES (the one introduced here [1]), because
> SPI_NOR_4B_OPCODES should only be used for flash_info->flags and might
> soon conflict with another SNOR_F_ flag?
> 

yes, you're right.

> [1]http://patchwork.ozlabs.org/patch/991476/
> 

Can you apply your patch? Will submit a new version afterwards.

Thanks,
ta
Boris Brezillon Nov. 28, 2018, 2:22 p.m. UTC | #4
On Wed, 28 Nov 2018 14:17:12 +0000
<Tudor.Ambarus@microchip.com> wrote:

> On 11/28/2018 09:57 AM, Boris Brezillon wrote:
> > On Tue, 20 Nov 2018 11:55:21 +0000
> > <Tudor.Ambarus@microchip.com> wrote:
> >   
> >> +
> >> +	/*
> >> +	 * We set nor->addr_width here to skip spi_nor_set_4byte_opcodes()
> >> +	 * later because this latest function implements a legacy quirk for
> >> +	 * the erase size of Spansion memory. However this quirk is no longer
> >> +	 * needed with new SFDP compliant memories.
> >> +	 */
> >> +	nor->addr_width = 4;
> >> +	nor->flags |= SPI_NOR_4B_OPCODES;  
> > 
> > You mean SNOR_F_4B_OPCODES (the one introduced here [1]), because
> > SPI_NOR_4B_OPCODES should only be used for flash_info->flags and might
> > soon conflict with another SNOR_F_ flag?
> >   
> 
> yes, you're right.
> 
> > [1]http://patchwork.ozlabs.org/patch/991476/
> >   
> 
> Can you apply your patch? Will submit a new version afterwards.

Actually, I realized setting SNOR_F_4B_OPCODES when the BFPT advertises
4_BYTES_ONLY is incorrect as 4bytes only can mean "use the 3B opcodes
but pass address on 4 bytes". Here is a new version of this patch [1].
Feel free to pick it up and send it along with your "SFDP 4-byte Address
Instruction Table" patch (I have not reason to send it alone since the
problem I was trying to solve is no longer fixed by [1]).

[1]https://github.com/bbrezillon/linux-0day/commit/a953b6b435ec67bca00d6666f472db5f6dca4f63
diff mbox series

Patch

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 4c7e4dc25006..3495557b4948 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -2268,6 +2268,7 @@  struct sfdp_parameter_header {
 
 #define SFDP_BFPT_ID		0xff00	/* Basic Flash Parameter Table */
 #define SFDP_SECTOR_MAP_ID	0xff81	/* Sector Map Table */
+#define SFDP_4BAIT_ID		0xff84	/* 4-byte Address Instruction Table */
 
 #define SFDP_SIGNATURE		0x50444653U
 #define SFDP_JESD216_MAJOR	1
@@ -3101,6 +3102,190 @@  static int spi_nor_parse_smpt(struct spi_nor *nor,
 	return ret;
 }
 
+#define SFDP_4BAIT_DWORD_MAX	2
+
+struct sfdp_4bait {
+	/* The hardware capability. */
+	u32		hwcaps;
+
+	/*
+	 * The <supported_bit> bit in DWORD1 of the 4BAIT tells us whether
+	 * the associated 4-byte address op code is supported.
+	 */
+	u32		supported_bit;
+};
+
+/**
+ * spi_nor_parse_4bait() - parse the 4-Byte Address Instruction Table
+ * @nor:		pointer to a 'struct spi_nor'.
+ * @param_header:	pointer to the 'struct sfdp_parameter_header' describing
+ *			the 4-Byte Address Instruction Table length and version.
+ * @params:		pointer to the 'struct spi_nor_flash_parameter' to be.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int spi_nor_parse_4bait(struct spi_nor *nor,
+			       const struct sfdp_parameter_header *param_header,
+			       struct spi_nor_flash_parameter *params)
+{
+	static const struct sfdp_4bait reads[] = {
+		{ SNOR_HWCAPS_READ,		BIT(0) },
+		{ SNOR_HWCAPS_READ_FAST,	BIT(1) },
+		{ SNOR_HWCAPS_READ_1_1_2,	BIT(2) },
+		{ SNOR_HWCAPS_READ_1_2_2,	BIT(3) },
+		{ SNOR_HWCAPS_READ_1_1_4,	BIT(4) },
+		{ SNOR_HWCAPS_READ_1_4_4,	BIT(5) },
+		{ SNOR_HWCAPS_READ_1_1_1_DTR,	BIT(13) },
+		{ SNOR_HWCAPS_READ_1_2_2_DTR,	BIT(14) },
+		{ SNOR_HWCAPS_READ_1_4_4_DTR,	BIT(15) },
+	};
+	static const struct sfdp_4bait programs[] = {
+		{ SNOR_HWCAPS_PP,		BIT(6) },
+		{ SNOR_HWCAPS_PP_1_1_4,		BIT(7) },
+		{ SNOR_HWCAPS_PP_1_4_4,		BIT(8) },
+	};
+	static const struct sfdp_4bait erases[SNOR_ERASE_TYPE_MAX] = {
+		{ 0u /* not used */,		BIT(9) },
+		{ 0u /* not used */,		BIT(10) },
+		{ 0u /* not used */,		BIT(11) },
+		{ 0u /* not used */,		BIT(12) },
+	};
+	struct spi_nor_pp_command *params_pp = params->page_programs;
+	struct spi_nor_erase_map *map = &nor->erase_map;
+	struct spi_nor_erase_type *erase_type = map->erase_type;
+	u32 *dwords;
+	size_t len;
+	u32 addr, discard_hwcaps, read_hwcaps, pp_hwcaps, erase_mask;
+	int i, ret;
+
+	if (param_header->major != SFDP_JESD216_MAJOR ||
+	    param_header->length < SFDP_4BAIT_DWORD_MAX)
+		return -EINVAL;
+
+	/* Read the 4-byte Address Instruction Table. */
+	len = sizeof(*dwords) * SFDP_4BAIT_DWORD_MAX;
+
+	/* Use a kmalloc'ed bounce buffer to guarantee it is DMA-able. */
+	dwords = kmalloc(len, GFP_KERNEL);
+	if (!dwords)
+		return -ENOMEM;
+
+	addr = SFDP_PARAM_HEADER_PTP(param_header);
+	ret = spi_nor_read_sfdp(nor, addr, len, dwords);
+	if (ret)
+		return ret;
+
+	/* Fix endianness of the 4BAIT DWORDs. */
+	for (i = 0; i < SFDP_4BAIT_DWORD_MAX; i++)
+		dwords[i] = le32_to_cpu(dwords[i]);
+
+	/*
+	 * Compute the subset of (Fast) Read commands for which the 4-byte
+	 * version is supported.
+	 */
+	discard_hwcaps = 0;
+	read_hwcaps = 0;
+	for (i = 0; i < ARRAY_SIZE(reads); i++) {
+		const struct sfdp_4bait *read = &reads[i];
+
+		discard_hwcaps |= read->hwcaps;
+		if ((params->hwcaps.mask & read->hwcaps) &&
+		    (dwords[0] & read->supported_bit))
+			read_hwcaps |= read->hwcaps;
+	}
+
+	/*
+	 * Compute the subset of Page Program commands for which the 4-byte
+	 * version is supported.
+	 */
+	pp_hwcaps = 0;
+	for (i = 0; i < ARRAY_SIZE(programs); i++) {
+		const struct sfdp_4bait *program = &programs[i];
+
+		/*
+		 * The 4 Byte Address Instruction (Optional) Table is the only
+		 * SFDP table that indicates support for Page Program Commands.
+		 * Bypass the params->hwcaps.mask and consider 4BAIT the biggest
+		 * authority for specifying Page Program support.
+		 */
+		discard_hwcaps |= program->hwcaps;
+		if (dwords[0] & program->supported_bit)
+			pp_hwcaps |= program->hwcaps;
+	}
+
+	/*
+	 * Compute the subset of Sector Erase commands for which the 4-byte
+	 * version is supported.
+	 */
+	erase_mask = 0;
+	for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) {
+		const struct sfdp_4bait *erase = &erases[i];
+
+		if (dwords[0] & erase->supported_bit)
+			erase_mask |= BIT(i);
+	}
+
+	/* Replicate the sort done for the map's erase types in BFPT. */
+	erase_mask = spi_nor_sort_erase_mask(map, erase_mask);
+
+	/*
+	 * We need at least one 4-byte op code per read, program and erase
+	 * operation; the .read(), .write() and .erase() hooks share the
+	 * nor->addr_width value.
+	 */
+	if (!read_hwcaps || !pp_hwcaps || !erase_mask)
+		goto out;
+
+	/*
+	 * Discard all operations from the 4-byte instruction set which are
+	 * not supported by this memory.
+	 */
+	params->hwcaps.mask &= ~discard_hwcaps;
+	params->hwcaps.mask |= (read_hwcaps | pp_hwcaps);
+
+	/* Use the 4-byte address instruction set. */
+	for (i = 0; i < SNOR_CMD_READ_MAX; i++) {
+		struct spi_nor_read_command *read_cmd = &params->reads[i];
+
+		read_cmd->opcode = spi_nor_convert_3to4_read(read_cmd->opcode);
+	}
+
+	/* 4BAIT is the only SFDP table that indicates page program support. */
+	if (pp_hwcaps & SNOR_HWCAPS_PP)
+		spi_nor_set_pp_settings(&params_pp[SNOR_CMD_PP],
+					SPINOR_OP_PP_4B, SNOR_PROTO_1_1_1);
+	if (pp_hwcaps & SNOR_HWCAPS_PP_1_1_4)
+		spi_nor_set_pp_settings(&params_pp[SNOR_CMD_PP_1_1_4],
+					SPINOR_OP_PP_1_1_4_4B,
+					SNOR_PROTO_1_1_4);
+	if (pp_hwcaps & SNOR_HWCAPS_PP_1_4_4)
+		spi_nor_set_pp_settings(&params_pp[SNOR_CMD_PP_1_4_4],
+					SPINOR_OP_PP_1_4_4_4B,
+					SNOR_PROTO_1_4_4);
+
+	for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) {
+		if (erase_mask & BIT(i))
+			erase_type[i].opcode = (dwords[1] >>
+						erase_type[i].idx * 8) & 0xFF;
+		else
+			spi_nor_set_erase_type(&erase_type[i], 0u, 0xFF);
+	}
+
+	/*
+	 * We set nor->addr_width here to skip spi_nor_set_4byte_opcodes()
+	 * later because this latest function implements a legacy quirk for
+	 * the erase size of Spansion memory. However this quirk is no longer
+	 * needed with new SFDP compliant memories.
+	 */
+	nor->addr_width = 4;
+	nor->flags |= SPI_NOR_4B_OPCODES;
+
+	/* fall through */
+out:
+	kfree(dwords);
+	return ret;
+}
+
 /**
  * spi_nor_parse_sfdp() - parse the Serial Flash Discoverable Parameters.
  * @nor:		pointer to a 'struct spi_nor'
@@ -3198,6 +3383,10 @@  static int spi_nor_parse_sfdp(struct spi_nor *nor,
 			err = spi_nor_parse_smpt(nor, param_header);
 			break;
 
+		case SFDP_4BAIT_ID:
+			err = spi_nor_parse_4bait(nor, param_header, params);
+			break;
+
 		default:
 			break;
 		}