[09/15] mtd: spi-nor-core: Introduce flash-specific fixup hooks
diff mbox series

Message ID 20200226125606.22684-10-p.yadav@ti.com
State Superseded
Delegated to: Jagannadha Sutradharudu Teki
Headers show
Series
  • mtd: spi-nor-core: add xSPI Octal DTR support
Related show

Commit Message

Pratyush Yadav Feb. 26, 2020, 12:55 p.m. UTC
Sometimes the information in a flash's SFDP tables is wrong. Sometimes
some information just can't be expressed in the SFDP table. So,
introduce the fixup hooks to allow tailoring settings for a specific
flash.

Three hooks are added: default_init, post_sfdp, and post_bfpt. These
allow tweaking the flash settings at different point in the probe
sequence. Since the hooks reside in nor->info, set that value just
before the call to spi_nor_init_params().

The hooks and at what points they are executed mimics Linux's spi-nor
framework.

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
---
 drivers/mtd/spi/sf_internal.h  |  3 ++
 drivers/mtd/spi/spi-nor-core.c | 70 +++++++++++++++++++++++++++++++++-
 2 files changed, 71 insertions(+), 2 deletions(-)

Comments

Vignesh Raghavendra March 12, 2020, 6:34 a.m. UTC | #1
On 26/02/20 6:25 pm, Pratyush Yadav wrote:
> diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
> index 1ed4f0907b..94e99eb99f 100644
> --- a/drivers/mtd/spi/spi-nor-core.c
> +++ b/drivers/mtd/spi/spi-nor-core.c
> @@ -148,6 +148,32 @@ struct sfdp_header {
>  struct sfdp_bfpt {
>  	u32	dwords[BFPT_DWORD_MAX];
>  };
> +
> +/**
> + * struct spi_nor_fixups - SPI NOR fixup hooks
> + * @default_init: called after default flash parameters init. Used to tweak
> + *                flash parameters when information provided by the flash_info
> + *                table is incomplete or wrong.
> + * @post_bfpt: called after the BFPT table has been parsed
> + * @post_sfdp: called after SFDP has been parsed (is also called for SPI NORs
> + *             that do not support RDSFDP). Typically used to tweak various
> + *             parameters that could not be extracted by other means (i.e.
> + *             when information provided by the SFDP/flash_info tables are
> + *             incomplete or wrong).
> + *
> + * Those hooks can be used to tweak the SPI NOR configuration when the SFDP
> + * table is broken or not available.
> + */
> +struct spi_nor_fixups {
> +	void (*default_init)(struct spi_nor *nor);
> +	int (*post_bfpt)(struct spi_nor *nor,
> +			 const struct sfdp_parameter_header *bfpt_header,
> +			 const struct sfdp_bfpt *bfpt,
> +			 struct spi_nor_flash_parameter *params);
> +	void (*post_sfdp)(struct spi_nor *nor,
> +			  struct spi_nor_flash_parameter *params);
> +};
> +
>  #endif /* SPI_FLASH_SFDP_SUPPORT */
>  
>  static int spi_nor_read_write_reg(struct spi_nor *nor, struct spi_mem_op
> @@ -1743,6 +1769,19 @@ static const struct sfdp_bfpt_erase sfdp_bfpt_erases[] = {
>  
>  static int spi_nor_hwcaps_read2cmd(u32 hwcaps);
>  
> +static int
> +spi_nor_post_bfpt_fixups(struct spi_nor *nor,
> +			 const struct sfdp_parameter_header *bfpt_header,
> +			 const struct sfdp_bfpt *bfpt,
> +			 struct spi_nor_flash_parameter *params)
> +{
> +	if (nor->info->fixups && nor->info->fixups->post_bfpt)
> +		return nor->info->fixups->post_bfpt(nor, bfpt_header, bfpt,
> +						    params);
> +
> +	return 0;
> +}
> +
>  /**
>   * spi_nor_parse_bfpt() - read and parse the Basic Flash Parameter Table.
>   * @nor:		pointer to a 'struct spi_nor'
> @@ -1914,7 +1953,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
>  		return -EINVAL;
>  	}
>  
> -	return 0;
> +	return spi_nor_post_bfpt_fixups(nor, bfpt_header, &bfpt, params);
>  }
>  
>  /**
> @@ -2074,6 +2113,29 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor,
>  }
>  #endif /* SPI_FLASH_SFDP_SUPPORT */
>  
> +/**
> + * spi_nor_post_sfdp_fixups() - Updates the flash's parameters and settings
> + * after SFDP has been parsed (is also called for SPI NORs that do not
> + * support RDSFDP).
> + * @nor:	pointer to a 'struct spi_nor'
> + *
> + * Typically used to tweak various parameters that could not be extracted by
> + * other means (i.e. when information provided by the SFDP/flash_info tables
> + * are incomplete or wrong).
> + */
> +static void spi_nor_post_sfdp_fixups(struct spi_nor *nor,
> +				     struct spi_nor_flash_parameter *params)
> +{
> +	if (nor->info->fixups && nor->info->fixups->post_sfdp)
> +		nor->info->fixups->post_sfdp(nor, params);
> +}
> +

This would cause build failure as spi_nor_fixups is only available when 
SFDP support is enabled:

drivers/mtd/spi/spi-nor-core.c: In function ‘spi_nor_post_sfdp_fixups’:
drivers/mtd/spi/spi-nor-core.c:2280:44: error: dereferencing pointer to incomplete type ‘const struct spi_nor_fixups’
 2280 |  if (nor->info->fixups && nor->info->fixups->post_sfdp)

May be move all definitions of out the #ifdef

Regards
Vignesh
Pratyush Yadav March 12, 2020, 7:29 a.m. UTC | #2
On 12/03/20 12:04PM, Vignesh Raghavendra wrote:
> 
> 
> On 26/02/20 6:25 pm, Pratyush Yadav wrote:
> > diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
> > index 1ed4f0907b..94e99eb99f 100644
> > --- a/drivers/mtd/spi/spi-nor-core.c
> > +++ b/drivers/mtd/spi/spi-nor-core.c
> > @@ -148,6 +148,32 @@ struct sfdp_header {
> >  struct sfdp_bfpt {
> >  	u32	dwords[BFPT_DWORD_MAX];
> >  };
> > +
> > +/**
> > + * struct spi_nor_fixups - SPI NOR fixup hooks
> > + * @default_init: called after default flash parameters init. Used to tweak
> > + *                flash parameters when information provided by the flash_info
> > + *                table is incomplete or wrong.
> > + * @post_bfpt: called after the BFPT table has been parsed
> > + * @post_sfdp: called after SFDP has been parsed (is also called for SPI NORs
> > + *             that do not support RDSFDP). Typically used to tweak various
> > + *             parameters that could not be extracted by other means (i.e.
> > + *             when information provided by the SFDP/flash_info tables are
> > + *             incomplete or wrong).
> > + *
> > + * Those hooks can be used to tweak the SPI NOR configuration when the SFDP
> > + * table is broken or not available.
> > + */
> > +struct spi_nor_fixups {
> > +	void (*default_init)(struct spi_nor *nor);
> > +	int (*post_bfpt)(struct spi_nor *nor,
> > +			 const struct sfdp_parameter_header *bfpt_header,
> > +			 const struct sfdp_bfpt *bfpt,
> > +			 struct spi_nor_flash_parameter *params);
> > +	void (*post_sfdp)(struct spi_nor *nor,
> > +			  struct spi_nor_flash_parameter *params);
> > +};
> > +
> >  #endif /* SPI_FLASH_SFDP_SUPPORT */
> >  
> >  static int spi_nor_read_write_reg(struct spi_nor *nor, struct spi_mem_op
> > @@ -1743,6 +1769,19 @@ static const struct sfdp_bfpt_erase sfdp_bfpt_erases[] = {
> >  
> >  static int spi_nor_hwcaps_read2cmd(u32 hwcaps);
> >  
> > +static int
> > +spi_nor_post_bfpt_fixups(struct spi_nor *nor,
> > +			 const struct sfdp_parameter_header *bfpt_header,
> > +			 const struct sfdp_bfpt *bfpt,
> > +			 struct spi_nor_flash_parameter *params)
> > +{
> > +	if (nor->info->fixups && nor->info->fixups->post_bfpt)
> > +		return nor->info->fixups->post_bfpt(nor, bfpt_header, bfpt,
> > +						    params);
> > +
> > +	return 0;
> > +}
> > +
> >  /**
> >   * spi_nor_parse_bfpt() - read and parse the Basic Flash Parameter Table.
> >   * @nor:		pointer to a 'struct spi_nor'
> > @@ -1914,7 +1953,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
> >  		return -EINVAL;
> >  	}
> >  
> > -	return 0;
> > +	return spi_nor_post_bfpt_fixups(nor, bfpt_header, &bfpt, params);
> >  }
> >  
> >  /**
> > @@ -2074,6 +2113,29 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor,
> >  }
> >  #endif /* SPI_FLASH_SFDP_SUPPORT */
> >  
> > +/**
> > + * spi_nor_post_sfdp_fixups() - Updates the flash's parameters and settings
> > + * after SFDP has been parsed (is also called for SPI NORs that do not
> > + * support RDSFDP).
> > + * @nor:	pointer to a 'struct spi_nor'
> > + *
> > + * Typically used to tweak various parameters that could not be extracted by
> > + * other means (i.e. when information provided by the SFDP/flash_info tables
> > + * are incomplete or wrong).
> > + */
> > +static void spi_nor_post_sfdp_fixups(struct spi_nor *nor,
> > +				     struct spi_nor_flash_parameter *params)
> > +{
> > +	if (nor->info->fixups && nor->info->fixups->post_sfdp)
> > +		nor->info->fixups->post_sfdp(nor, params);
> > +}
> > +
> 
> This would cause build failure as spi_nor_fixups is only available when 
> SFDP support is enabled:
> 
> drivers/mtd/spi/spi-nor-core.c: In function ‘spi_nor_post_sfdp_fixups’:
> drivers/mtd/spi/spi-nor-core.c:2280:44: error: dereferencing pointer to incomplete type ‘const struct spi_nor_fixups’
>  2280 |  if (nor->info->fixups && nor->info->fixups->post_sfdp)
> 
> May be move all definitions of out the #ifdef

Thanks for catching this. Will fix.

Patch
diff mbox series

diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
index 940b2e4c9e..d689b673ce 100644
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -67,6 +67,9 @@  struct flash_info {
 #define USE_CLSR		BIT(14)	/* use CLSR command */
 #define SPI_NOR_HAS_SST26LOCK	BIT(15)	/* Flash supports lock/unlock via BPR */
 #define SPI_NOR_OCTAL_READ      BIT(16) /* Flash supports Octal Read */
+
+	/* Part specific fixup hooks. */
+	const struct spi_nor_fixups *fixups;
 };
 
 extern const struct flash_info spi_nor_ids[];
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 1ed4f0907b..94e99eb99f 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -148,6 +148,32 @@  struct sfdp_header {
 struct sfdp_bfpt {
 	u32	dwords[BFPT_DWORD_MAX];
 };
+
+/**
+ * struct spi_nor_fixups - SPI NOR fixup hooks
+ * @default_init: called after default flash parameters init. Used to tweak
+ *                flash parameters when information provided by the flash_info
+ *                table is incomplete or wrong.
+ * @post_bfpt: called after the BFPT table has been parsed
+ * @post_sfdp: called after SFDP has been parsed (is also called for SPI NORs
+ *             that do not support RDSFDP). Typically used to tweak various
+ *             parameters that could not be extracted by other means (i.e.
+ *             when information provided by the SFDP/flash_info tables are
+ *             incomplete or wrong).
+ *
+ * Those hooks can be used to tweak the SPI NOR configuration when the SFDP
+ * table is broken or not available.
+ */
+struct spi_nor_fixups {
+	void (*default_init)(struct spi_nor *nor);
+	int (*post_bfpt)(struct spi_nor *nor,
+			 const struct sfdp_parameter_header *bfpt_header,
+			 const struct sfdp_bfpt *bfpt,
+			 struct spi_nor_flash_parameter *params);
+	void (*post_sfdp)(struct spi_nor *nor,
+			  struct spi_nor_flash_parameter *params);
+};
+
 #endif /* SPI_FLASH_SFDP_SUPPORT */
 
 static int spi_nor_read_write_reg(struct spi_nor *nor, struct spi_mem_op
@@ -1743,6 +1769,19 @@  static const struct sfdp_bfpt_erase sfdp_bfpt_erases[] = {
 
 static int spi_nor_hwcaps_read2cmd(u32 hwcaps);
 
+static int
+spi_nor_post_bfpt_fixups(struct spi_nor *nor,
+			 const struct sfdp_parameter_header *bfpt_header,
+			 const struct sfdp_bfpt *bfpt,
+			 struct spi_nor_flash_parameter *params)
+{
+	if (nor->info->fixups && nor->info->fixups->post_bfpt)
+		return nor->info->fixups->post_bfpt(nor, bfpt_header, bfpt,
+						    params);
+
+	return 0;
+}
+
 /**
  * spi_nor_parse_bfpt() - read and parse the Basic Flash Parameter Table.
  * @nor:		pointer to a 'struct spi_nor'
@@ -1914,7 +1953,7 @@  static int spi_nor_parse_bfpt(struct spi_nor *nor,
 		return -EINVAL;
 	}
 
-	return 0;
+	return spi_nor_post_bfpt_fixups(nor, bfpt_header, &bfpt, params);
 }
 
 /**
@@ -2074,6 +2113,29 @@  static int spi_nor_parse_sfdp(struct spi_nor *nor,
 }
 #endif /* SPI_FLASH_SFDP_SUPPORT */
 
+/**
+ * spi_nor_post_sfdp_fixups() - Updates the flash's parameters and settings
+ * after SFDP has been parsed (is also called for SPI NORs that do not
+ * support RDSFDP).
+ * @nor:	pointer to a 'struct spi_nor'
+ *
+ * Typically used to tweak various parameters that could not be extracted by
+ * other means (i.e. when information provided by the SFDP/flash_info tables
+ * are incomplete or wrong).
+ */
+static void spi_nor_post_sfdp_fixups(struct spi_nor *nor,
+				     struct spi_nor_flash_parameter *params)
+{
+	if (nor->info->fixups && nor->info->fixups->post_sfdp)
+		nor->info->fixups->post_sfdp(nor, params);
+}
+
+static void spi_nor_default_init_fixups(struct spi_nor *nor)
+{
+	if (nor->info->fixups && nor->info->fixups->default_init)
+		nor->info->fixups->default_init(nor);
+}
+
 static int spi_nor_init_params(struct spi_nor *nor,
 			       const struct flash_info *info,
 			       struct spi_nor_flash_parameter *params)
@@ -2152,6 +2214,8 @@  static int spi_nor_init_params(struct spi_nor *nor,
 		}
 	}
 
+	spi_nor_default_init_fixups(nor);
+
 	/* Override the parameters with data read from SFDP tables. */
 	nor->addr_width = 0;
 	nor->mtd.erasesize = 0;
@@ -2168,6 +2232,8 @@  static int spi_nor_init_params(struct spi_nor *nor,
 		}
 	}
 
+	spi_nor_post_sfdp_fixups(nor, params);
+
 	return 0;
 }
 
@@ -2463,6 +2529,7 @@  int spi_nor_scan(struct spi_nor *nor)
 	info = spi_nor_read_id(nor);
 	if (IS_ERR_OR_NULL(info))
 		return -ENOENT;
+	nor->info = info;
 	/* Parse the Serial Flash Discoverable Parameters table. */
 	ret = spi_nor_init_params(nor, info, &params);
 	if (ret)
@@ -2567,7 +2634,6 @@  int spi_nor_scan(struct spi_nor *nor)
 	}
 
 	/* Send all the required SPI flash commands to initialize device */
-	nor->info = info;
 	ret = spi_nor_init(nor);
 	if (ret)
 		return ret;