Re: [U-Boot] [U-BOOT PATCH 2/3] spi: nor: add support for is25wp256

2019-08-26 Thread Bin Meng
On Wed, Aug 14, 2019 at 1:23 AM Sagar Shrikant Kadam
 wrote:
>
> Enable support for spi nor device(is25wp256) mounted on
> HiFive Unleashed Rev A00 board.
>
> Thanks to Bhargav Shah for porting this patch which is based on
> linux patches https://lkml.org/lkml/2019/7/2/859.
>
> Additionally, set the proper number of sectors in the device id table,
> so that the sf probe shows the correct size of the flash device.
> Added SPI_NOR_HAS_BP3 bit to indicate that this nor device has BP3 bit
> present for the lock/unlock mechanism.
> Registered a post bfpt fixup handler for this device as the address width
> advertised by the flash during nor scan is not correct.
>
> This flash is tested for plain SPI mode although it also supports QUAD
> I/O mode.
>
> Signed-off-by: Bhargav Shah 
> Signed-off-by: Sagar Shrikant Kadam 
> ---
>  board/sifive/fu540/Kconfig |   5 +
>  drivers/mtd/spi/sf_internal.h  |  18 +++
>  drivers/mtd/spi/spi-nor-core.c | 340 
> +++--
>  drivers/mtd/spi/spi-nor-ids.c  |   5 +
>  include/linux/mtd/spi-nor.h|   8 +
>  5 files changed, 326 insertions(+), 50 deletions(-)
>
> diff --git a/board/sifive/fu540/Kconfig b/board/sifive/fu540/Kconfig
> index 5d65080..f9d5ec1 100644
> --- a/board/sifive/fu540/Kconfig
> +++ b/board/sifive/fu540/Kconfig
> @@ -40,6 +40,11 @@ config BOARD_SPECIFIC_OPTIONS # dummy
> imply SIFIVE_SERIAL
> imply SPI
> imply SPI_SIFIVE
> +   imply SPI_FLASH
> +   imply SPI_FLASH_ISSI
> +   imply SPI_FLASH_SFDP_SUPPORT
> +   imply CMD_MTD
> +   imply CMD_SF
> imply MMC
> imply MMC_SPI
> imply MMC_BROKEN_CD

This should be a separate patch.

> diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
> index c5e68d8..6523107 100644
> --- a/drivers/mtd/spi/sf_internal.h
> +++ b/drivers/mtd/spi/sf_internal.h
> @@ -65,6 +65,13 @@ struct flash_info {
>  #define NO_CHIP_ERASE  BIT(12) /* Chip does not support chip erase */
>  #define SPI_NOR_SKIP_SFDP  BIT(13) /* Skip parsing of SFDP tables */
>  #define USE_CLSR   BIT(14) /* use CLSR command */
> +#define SPI_NOR_HAS_BP3BIT(15) /*
> +* Flash SR has block protect bits
> +* for lock/unlock purpose, few 
> support
> +* BP0-BP2 while few support BP0-BP3.
> +* This flag identifies devices that
> +* support BP3 bit.
> +*/
>
>  #ifdef CONFIG_SPI_FLASH_SFDP_SUPPORT
> /* Part specific fixup hooks */
> @@ -72,6 +79,17 @@ struct flash_info {
>  #endif
>  };
>
> +#ifdef CONFIG_SPI_FLASH_SFDP_SUPPORT
> +/*
> + * Declare manufacturer specific fixup handlers that
> + * can be registered as fixup's in flash info table
> + * so as to update any wrong/broken SFDP parameter.
> + */
> +#ifdef CONFIG_SPI_FLASH_ISSI
> +extern struct spi_nor_fixups is25wp256_fixups;
> +#endif
> +#endif
> +
>  extern const struct flash_info spi_nor_ids[];
>
>  #define JEDEC_MFR(info)((info)->id[0])
> diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
> index 4306d19..46d278d 100644
> --- a/drivers/mtd/spi/spi-nor-core.c
> +++ b/drivers/mtd/spi/spi-nor-core.c
> @@ -582,7 +582,8 @@ erase_err:
> return ret;
>  }
>
> -#if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST)
> +#if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST) || \
> +   defined(CONFIG_SPI_FLASH_ISSI)
>  /* Write status register and ensure bits in mask match written values */
>  static int write_sr_and_check(struct spi_nor *nor, u8 status_new, u8 mask)
>  {
> @@ -604,14 +605,45 @@ static int write_sr_and_check(struct spi_nor *nor, u8 
> status_new, u8 mask)
> return ((ret & mask) != (status_new & mask)) ? -EIO : 0;
>  }
>
> +/**
> + * spi_nor_read_fr() -read function register
> + * @nor: pointer to a 'struct spi_nor'.
> + *
> + * ISSI devices have top/bottom area protection bits selection into function
> + * reg. The bits in FR are OTP. So once it's written, it cannot be changed.
> + *
> + * Return: Value in function register or negative if error.
> + */
> +static int spi_nor_read_fr(struct spi_nor *nor)
> +{
> +   int ret;
> +   u8 val;
> +
> +   ret = nor->read_reg(nor, SPINOR_OP_RDFR, , 1);
> +   if (ret < 0) {
> +   pr_err("error %d reading FR\n", ret);
> +   return ret;
> +   }
> +
> +   return val;
> +}
> +
>  static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs,
>  uint64_t *len)
>  {
> struct mtd_info *mtd = >mtd;
> -   u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
> -   int shift = ffs(mask) - 1;
> +   u8 mask = 0;
> +   u8 fr = 0;
> +   int shift = 0;
> int pow;
>
> +   if 

[U-Boot] [U-BOOT PATCH 2/3] spi: nor: add support for is25wp256

2019-08-13 Thread Sagar Shrikant Kadam
Enable support for spi nor device(is25wp256) mounted on
HiFive Unleashed Rev A00 board.

Thanks to Bhargav Shah for porting this patch which is based on
linux patches https://lkml.org/lkml/2019/7/2/859.

Additionally, set the proper number of sectors in the device id table,
so that the sf probe shows the correct size of the flash device.
Added SPI_NOR_HAS_BP3 bit to indicate that this nor device has BP3 bit
present for the lock/unlock mechanism.
Registered a post bfpt fixup handler for this device as the address width
advertised by the flash during nor scan is not correct.

This flash is tested for plain SPI mode although it also supports QUAD
I/O mode.

Signed-off-by: Bhargav Shah 
Signed-off-by: Sagar Shrikant Kadam 
---
 board/sifive/fu540/Kconfig |   5 +
 drivers/mtd/spi/sf_internal.h  |  18 +++
 drivers/mtd/spi/spi-nor-core.c | 340 +++--
 drivers/mtd/spi/spi-nor-ids.c  |   5 +
 include/linux/mtd/spi-nor.h|   8 +
 5 files changed, 326 insertions(+), 50 deletions(-)

diff --git a/board/sifive/fu540/Kconfig b/board/sifive/fu540/Kconfig
index 5d65080..f9d5ec1 100644
--- a/board/sifive/fu540/Kconfig
+++ b/board/sifive/fu540/Kconfig
@@ -40,6 +40,11 @@ config BOARD_SPECIFIC_OPTIONS # dummy
imply SIFIVE_SERIAL
imply SPI
imply SPI_SIFIVE
+   imply SPI_FLASH
+   imply SPI_FLASH_ISSI
+   imply SPI_FLASH_SFDP_SUPPORT
+   imply CMD_MTD
+   imply CMD_SF
imply MMC
imply MMC_SPI
imply MMC_BROKEN_CD
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
index c5e68d8..6523107 100644
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -65,6 +65,13 @@ struct flash_info {
 #define NO_CHIP_ERASE  BIT(12) /* Chip does not support chip erase */
 #define SPI_NOR_SKIP_SFDP  BIT(13) /* Skip parsing of SFDP tables */
 #define USE_CLSR   BIT(14) /* use CLSR command */
+#define SPI_NOR_HAS_BP3BIT(15) /*
+* Flash SR has block protect bits
+* for lock/unlock purpose, few support
+* BP0-BP2 while few support BP0-BP3.
+* This flag identifies devices that
+* support BP3 bit.
+*/
 
 #ifdef CONFIG_SPI_FLASH_SFDP_SUPPORT
/* Part specific fixup hooks */
@@ -72,6 +79,17 @@ struct flash_info {
 #endif
 };
 
+#ifdef CONFIG_SPI_FLASH_SFDP_SUPPORT
+/*
+ * Declare manufacturer specific fixup handlers that
+ * can be registered as fixup's in flash info table
+ * so as to update any wrong/broken SFDP parameter.
+ */
+#ifdef CONFIG_SPI_FLASH_ISSI
+extern struct spi_nor_fixups is25wp256_fixups;
+#endif
+#endif
+
 extern const struct flash_info spi_nor_ids[];
 
 #define JEDEC_MFR(info)((info)->id[0])
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 4306d19..46d278d 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -582,7 +582,8 @@ erase_err:
return ret;
 }
 
-#if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST)
+#if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST) || \
+   defined(CONFIG_SPI_FLASH_ISSI)
 /* Write status register and ensure bits in mask match written values */
 static int write_sr_and_check(struct spi_nor *nor, u8 status_new, u8 mask)
 {
@@ -604,14 +605,45 @@ static int write_sr_and_check(struct spi_nor *nor, u8 
status_new, u8 mask)
return ((ret & mask) != (status_new & mask)) ? -EIO : 0;
 }
 
+/**
+ * spi_nor_read_fr() -read function register
+ * @nor: pointer to a 'struct spi_nor'.
+ *
+ * ISSI devices have top/bottom area protection bits selection into function
+ * reg. The bits in FR are OTP. So once it's written, it cannot be changed.
+ *
+ * Return: Value in function register or negative if error.
+ */
+static int spi_nor_read_fr(struct spi_nor *nor)
+{
+   int ret;
+   u8 val;
+
+   ret = nor->read_reg(nor, SPINOR_OP_RDFR, , 1);
+   if (ret < 0) {
+   pr_err("error %d reading FR\n", ret);
+   return ret;
+   }
+
+   return val;
+}
+
 static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs,
 uint64_t *len)
 {
struct mtd_info *mtd = >mtd;
-   u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
-   int shift = ffs(mask) - 1;
+   u8 mask = 0;
+   u8 fr = 0;
+   int shift = 0;
int pow;
 
+   if (nor->flags & SNOR_F_HAS_BP3)
+   mask = SR_BP3 | SR_BP2 | SR_BP1 | SR_BP0;
+   else
+   mask = SR_BP2 | SR_BP1 | SR_BP0;
+
+   shift = ffs(mask) - 1;
+
if (!(sr & mask)) {
/* No protection */
*ofs = 0;
@@ -619,10 +651,20 @@ static void stm_get_locked_range(struct spi_nor *nor, u8 
sr,