You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/06/02 07:25:56 UTC

[incubator-nuttx] branch master updated: arm/tlsr82: support flash protection and voltage calibration.

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new acf21d2a8e arm/tlsr82: support flash protection and voltage calibration.
acf21d2a8e is described below

commit acf21d2a8e17211f5bf0e06dae219bda5169fb00
Author: wangbowen6 <wa...@xiaomi.com>
AuthorDate: Wed Jun 1 16:00:11 2022 +0800

    arm/tlsr82: support flash protection and voltage calibration.
    
    Signed-off-by: wangbowen6 <wa...@xiaomi.com>
---
 arch/arm/src/tlsr82/Kconfig            |  25 ++++
 arch/arm/src/tlsr82/tlsr82_flash.c     | 262 ++++++++++++++++++++++++++++++++-
 arch/arm/src/tlsr82/tlsr82_flash.h     |  26 ++++
 arch/arm/src/tlsr82/tlsr82_flash_mtd.c | 105 +++++++++++++
 4 files changed, 417 insertions(+), 1 deletion(-)

diff --git a/arch/arm/src/tlsr82/Kconfig b/arch/arm/src/tlsr82/Kconfig
index 1adae2580f..8587ed74b5 100644
--- a/arch/arm/src/tlsr82/Kconfig
+++ b/arch/arm/src/tlsr82/Kconfig
@@ -422,6 +422,31 @@ config TLSR82_FLASH_WRITE_BUFFER_SIZE
 		Flash byte write buffer size, the larger this size, the higher byte write
 		efficiency.
 
+config TLSR82_FLASH_PROTECT
+	bool "Flash erase/write protect enable"
+	default n
+	---help---
+		When enable this config, application can use ioctl(fd, MTDIOC_PROTECT/
+		MTDIOC_UNPROTECT, arg) to protect or unprotect the flash. The protect
+		and unprotect operations cost several millisecond, be careful to use it
+		if the application has performance requirements.
+
+config TLSR82_FLASH_CALI
+	bool "Flash volatge calibration enable"
+	default n
+	---help---
+		When enable the flash calibration, flash driver will read the calibration
+		parameters stored in the falsh during initialization and use these
+		parameters to calibrate the flash voltage.
+
+config TLSR82_FLASH_CALI_PARA_ADDR
+	hex "Flash voltage calibration address"
+	default 0x3ffd0
+	depends on TLSR82_FLASH_CALI
+	---help---
+		This is the flash calibration parameters address, this address must be
+		equal to the address defined in production tools.
+
 config TLSR82_FLASH_TEST
 	bool "Enable the falsh test when initializing"
 	default n
diff --git a/arch/arm/src/tlsr82/tlsr82_flash.c b/arch/arm/src/tlsr82/tlsr82_flash.c
index 7e73b27d09..fa11d993b1 100644
--- a/arch/arm/src/tlsr82/tlsr82_flash.c
+++ b/arch/arm/src/tlsr82/tlsr82_flash.c
@@ -61,6 +61,35 @@
 #  define FLASH_MID_TH25D40UA                  0x1360eb
 #endif
 
+/* Flash status register bit definitions
+ * FLASH_STATUS_WIP: The Write In Progress (WIP) bit indicates whether
+ *                   the memory is busy in program/erase/write status
+ *                   register progress.
+ * FLASH_STATUS_WEL: The Write Enable Latch (WEL) bit indicates the
+ *                   status of the internal Write Enable Latch.
+ * FLASH_STATUS_BP:  The Block Protect (BP2, BP1, BP0) bits are
+ *                   non-volatile. They define the size of the area to be
+ *                   software protected against Program and Erase commands.
+ * FLASH_STATUS_SRP: The Status Register Protect (SRP) bit operates in
+ *                   conjunction with the Write Protect (WP#) signal.
+ */
+
+#define FLASH_STATUS_WIP_SHIFT               0
+#define FLASH_STATUS_WIP_MASK                (0x1 << FLASH_STATUS_WIP_SHIFT)
+#define FLASH_STATUS_WEL_SHIFT               1
+#define FLASH_STATUS_WEL_MASK                (0x1 << FLASH_STATUS_WEL_SHIFT)
+#define FLASH_STATUS_BP_SHIFT                2
+#define FLASH_STATUS_BP_MASK                 (0x7 << FLASH_STATUS_BP_SHIFT)
+#define FLASH_STATUS_RSVD_SHIFT              5
+#define FLASH_STATUS_RSVD_MASK               (0x3 << FLASH_STATUS_RSVD_SHIFT)
+#define FLASH_STATUS_SRP_SHIFT               7
+#define FLASH_STATUS_SRP_MASK                (0x1 << FLASH_STATUS_SRP_SHIFT)
+
+/* NONE: do not protect, ALL: protect all the flash */
+
+#define FLASH_STATUS_BP_NONE                 (0x0 << FLASH_STATUS_BP_SHIFT)
+#define FLASH_STATUS_BP_ALL                  (0x7 << FLASH_STATUS_BP_SHIFT)
+
 /* Flash command definitions */
 
 #define FLASH_INVALID_ADDR                   0xffffffff
@@ -89,6 +118,11 @@
 #define FLASH_CMD_READ_UID1                  0x4b
 #define FLASH_CMD_READ_UID2                  0x5a
 
+/* Flash status type definitions */
+
+#define FLASH_STATUS_TYPE_8BIT               0x0
+#define FLASH_STATUS_TYPE_16BIT              0x1
+
 /* Flash lock/unlock macros definitions */
 
 #ifndef CONFIG_TLSR8278_BLE_SDK
@@ -452,6 +486,137 @@ void tlsr82_flash_write_data(uint32_t addr, const uint8_t *buf, uint32_t len)
   tlsr82_flash_write(FLASH_CMD_WRITE, addr, buf, len);
 }
 
+/****************************************************************************
+ * Name: tlsr82_flash_read_status
+ *
+ * Description:
+ *   This function reads the status of flash.
+ *
+ * Input Parameters:
+ *   cmd  - the cmd of read status.
+ *
+ * Returned Value:
+ *   status.
+ *
+ ****************************************************************************/
+
+uint8_t tlsr82_flash_read_status(uint8_t cmd)
+{
+  uint8_t status = 0;
+
+  tlsr82_flash_read(cmd, FLASH_INVALID_ADDR, 0, &status, 1);
+
+  return status;
+}
+
+/****************************************************************************
+ * Name: tlsr82_flash_write_status
+ *
+ * Description:
+ *   Write the status to flash status register.
+ *
+ * Input Parameters:
+ *   type   - the type of status.8 bit or 16 bit.
+ *   status - the value of status.
+ *
+ * Returned Value:
+ *   void
+ *
+ ****************************************************************************/
+
+void tlsr82_flash_write_status(uint8_t type, uint16_t status)
+{
+  uint8_t buf[2];
+
+  /* Follow the sdk to write flash status register */
+
+  buf[0] = (uint8_t)(status & 0x00ff);
+  buf[1] = (uint8_t)(status >> 8);
+
+  if (type == FLASH_STATUS_TYPE_8BIT)
+    {
+      tlsr82_flash_write(FLASH_CMD_WRITE_STATUS_LBYTE,
+                         FLASH_INVALID_ADDR, buf, 1);
+    }
+  else if (type == FLASH_STATUS_TYPE_16BIT)
+    {
+      tlsr82_flash_write(FLASH_CMD_WRITE_STATUS_LBYTE,
+                         FLASH_INVALID_ADDR, buf, 2);
+    }
+}
+
+/****************************************************************************
+ * Name: tlsr82_flash_protect
+ *
+ * Description:
+ *   This function serves to set the protection area of the flash.
+ *   Note: after check the sdk code, this function can be applied to all
+ *         flash chips:
+ *         FLASH_MID_GD25LD10C 0x1160c8 128K
+ *         FLASH_MID_GD25LD40C 0x1360c8 512K
+ *         FLASH_MID_GD25LD80C 0x1460c8 1M
+ *         FLASH_MID_ZB25WD10A 0x11325e 128K
+ *         FLASH_MID_ZB25WD40B 0x13325e 512K
+ *         FLASH_MID_ZB25WD80B 0x14325e 1M
+ *         FLASH_MID_ZB25WD20A 0x12325e 256K
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_TLSR82_FLASH_PROTECT
+void tlsr82_flash_protect(void)
+{
+  uint8_t status;
+  uint8_t data;
+
+  status = tlsr82_flash_read_status(FLASH_CMD_READ_STATUS_LBYTE);
+  data   = FLASH_STATUS_BP_ALL | (status & (~FLASH_STATUS_BP_MASK));
+
+  tlsr82_flash_write_status(FLASH_STATUS_TYPE_8BIT, data);
+}
+#endif
+
+/****************************************************************************
+ * Name: tlsr82_flash_unprotect
+ *
+ * Description:
+ *   This function serves to release flash protection.
+ *   Note: after check the sdk code, this function can be applied to all
+ *         flash chips:
+ *         FLASH_MID_GD25LD10C 0x1160c8 128K
+ *         FLASH_MID_GD25LD40C 0x1360c8 512K
+ *         FLASH_MID_GD25LD80C 0x1460c8 1M
+ *         FLASH_MID_ZB25WD10A 0x11325e 128K
+ *         FLASH_MID_ZB25WD40B 0x13325e 512K
+ *         FLASH_MID_ZB25WD80B 0x14325e 1M
+ *         FLASH_MID_ZB25WD20A 0x12325e 256K
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   void
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_TLSR82_FLASH_PROTECT
+void tlsr82_flash_unprotect(void)
+{
+  uint8_t status;
+  uint8_t data;
+
+  status = tlsr82_flash_read_status(FLASH_CMD_READ_STATUS_LBYTE);
+  data   = FLASH_STATUS_BP_NONE | (status & (~FLASH_STATUS_BP_MASK));
+
+  tlsr82_flash_write_status(FLASH_STATUS_TYPE_8BIT, data);
+}
+#endif
+
 /****************************************************************************
  * Name: tlsr82_flash_read_uid
  *
@@ -502,7 +667,7 @@ int tlsr82_flash_miduid_check(uint32_t *pmid, uint8_t *puid)
   /* Read the flash manufacaturer ID */
 
   tlsr82_flash_read(FLASH_CMD_READ_JEDEC_ID, FLASH_INVALID_ADDR,
-           0, (uint8_t *)pmid, 3);
+                    0, (uint8_t *)pmid, 3);
 #ifdef CONFIG_ARCH_CHIP_TLSR8258
   if (mid == FLASH_MID_GD25LE80C)
     {
@@ -542,3 +707,98 @@ int tlsr82_flash_miduid_check(uint32_t *pmid, uint8_t *puid)
 
   return OK;
 }
+
+/****************************************************************************
+ * Name: tlsr82_flash_calibrate
+ *
+ * Description:
+ *   Follow telink sdk to do flash voltage calibration, the flash supply
+ *   voltage accuracy is very important, the low flash supply voltage will
+ *   cause the flash data destoied.
+ *
+ * Input Parameters:
+ *   mid - manufacaturer
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_TLSR82_FLASH_CALI
+void tlsr82_flash_calibrate(uint32_t mid)
+{
+#if defined(CONFIG_ARCH_CHIP_TLSR8278)
+
+  uint16_t cali_data = *(uint16_t *)CONFIG_TLSR82_FLASH_CALI_PARA_ADDR;
+
+  finfo("cali_data=0x%x\n");
+
+  if ((0xffff == cali_data) || (0 != (cali_data & 0xf8f8)))
+    {
+      /* No flash calibration paramters */
+
+      finfo("No flash calibration parameters\n");
+
+      if (mid == FLASH_MID_ZB25WD10A || mid == FLASH_MID_ZB25WD40B ||
+          mid == FLASH_MID_ZB25WD80B || mid == FLASH_MID_ZB25WD20A)
+        {
+          /* LDO mode flash ldo trim 1.95V */
+
+          tlsr82_analog_write(0x09, ((tlsr82_analog_read(0x09) & 0x8f) |
+                                     (FLASH_VOLTAGE_1V95 << 4)));
+
+          /* DCDC mode flash ldo trim 1.90V */
+
+          tlsr82_analog_write(0x0c, ((tlsr82_analog_read(0x0c) & 0xf8) |
+                                     FLASH_VOLTAGE_1V9));
+        }
+    }
+  else
+    {
+      /* Flash calibration parameters exist, write the flash calibration
+       * parameters to the register
+       */
+
+      finfo("Calibrate the flash voltage\n");
+
+      tlsr82_analog_write(0x09, ((tlsr82_analog_read(0x09) & 0x8f) |
+                                 ((cali_data & 0xff00) >> 4)));
+      tlsr82_analog_write(0x0c, ((tlsr82_analog_read(0x0c) & 0xf8) |
+                                 (cali_data & 0xff)));
+    }
+
+#elif defined(CONFIG_ARCH_CHIP_TLSR8258)
+
+  uint8_t cali_data = *(uint8_t *)CONFIG_TLSR82_FLASH_CALI_PARA_ADDR;
+
+  finfo("cali_data=0x%x\n");
+
+  if (0xff == cali_data)
+    {
+      /* No flash calibration paramters */
+
+      finfo("No flash calibration parameters\n");
+
+      if (mid == FLASH_MID_ZB25WD10A || mid == FLASH_MID_ZB25WD40B ||
+          mid == FLASH_MID_ZB25WD80B || mid == FLASH_MID_ZB25WD20A)
+        {
+          /* DCDC mode flash ldo trim 1.95V */
+
+          tlsr82_analog_write(0x0c, ((tlsr82_analog_read(0x0c) & 0xf8) |
+                                     FLASH_VOLTAGE_1V95));
+        }
+    }
+  else
+    {
+      /* Flash calibration parameters exist, write the flash calibration
+       * parameters to the register
+       */
+
+      finfo("Calibrate the flash voltage\n");
+
+      tlsr82_analog_write(0x0c, ((tlsr82_analog_read(0x0c) & 0xf8) |
+                                 (cali_data & 0x7)));
+    }
+#endif
+}
+#endif
diff --git a/arch/arm/src/tlsr82/tlsr82_flash.h b/arch/arm/src/tlsr82/tlsr82_flash.h
index 3ae53207b5..7d42b8e82a 100644
--- a/arch/arm/src/tlsr82/tlsr82_flash.h
+++ b/arch/arm/src/tlsr82/tlsr82_flash.h
@@ -37,6 +37,15 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
+#define FLASH_VOLTAGE_1V6                    0x00
+#define FLASH_VOLTAGE_1V65                   0x01
+#define FLASH_VOLTAGE_1V7                    0x02
+#define FLASH_VOLTAGE_1V75                   0x03
+#define FLASH_VOLTAGE_1V8                    0x04
+#define FLASH_VOLTAGE_1V85                   0x05
+#define FLASH_VOLTAGE_1V9                    0x06
+#define FLASH_VOLTAGE_1V95                   0x07
+
 /****************************************************************************
  * Public Types
  ****************************************************************************/
@@ -64,8 +73,25 @@ void tlsr82_flash_erase_sector(uint32_t addr);
 void tlsr82_flash_read_data(uint32_t addr, uint8_t *buf, uint32_t len);
 void tlsr82_flash_write_data(uint32_t addr, const uint8_t *buf,
                              uint32_t len);
+uint8_t tlsr82_flash_read_status(uint8_t cmd);
+void tlsr82_flash_write_status(uint8_t type, uint16_t status);
+
+#ifdef CONFIG_TLSR82_FLASH_PROTECT
+void tlsr82_flash_protect(void);
+void tlsr82_flash_unprotect(void);
+#else
+#  define tlsr82_flash_protect()
+#  define tlsr82_flash_unprotect()
+#endif
+
 int tlsr82_flash_miduid_check(uint32_t *pmid, uint8_t *puid);
 
+#ifdef CONFIG_TLSR82_FLASH_CALIBRATE
+void tlsr82_flash_calibrate(uint32_t mid);
+#else
+#  define tlsr82_flash_calibrate(mid)
+#endif
+
 #undef EXTERN
 #if defined(__cplusplus)
 }
diff --git a/arch/arm/src/tlsr82/tlsr82_flash_mtd.c b/arch/arm/src/tlsr82/tlsr82_flash_mtd.c
index 10470cb8f4..26ae10c520 100644
--- a/arch/arm/src/tlsr82/tlsr82_flash_mtd.c
+++ b/arch/arm/src/tlsr82/tlsr82_flash_mtd.c
@@ -96,6 +96,14 @@
 #define FLASH_WRITE_TRACE_START()
 #define FLASH_WRITE_TRACE_END()
 
+/* Flash protect/unprotect trace marco definition */
+
+#define FLASH_PROT_TRACE_START()
+#define FLASH_PROT_TRACE_END()
+
+#define FLASH_UNPROT_TRACE_START()
+#define FLASH_UNPROT_TRACE_END()
+
 #define FLASH_BUF_LIST16(n) \
   n    , n + 1, n +  2, n +  3, n +  4, n +  5, n +  6, n +  7, \
   n + 8, n + 9, n + 10, n + 11, n + 12, n + 13, n + 14, n + 15,
@@ -481,6 +489,83 @@ static int tlsr82_flash_test(struct tlsr82_flash_dev_s *priv)
 
 #endif
 
+#ifdef CONFIG_TLSR82_FLASH_PROTECT
+  /* 5. Flash protect/unprotect test:
+   *    1) erase the chip;
+   *    2) write data into chip;
+   *    3) protect flash;
+   *    4) erase the chip with flash protected;
+   *    5) read the chip, the data should be same as the data written in 2);
+   */
+
+  uint8_t status;
+  uint32_t addr;
+
+  /* 1) erase the chip */
+
+  ferr("Erase chip for protect/unprotect test\n");
+  tlsr82_flash_chip_erase(priv);
+  ferr("Erase chip finished\n");
+
+  /* 2) write data into chip */
+
+  tlsr82_flash_print("Write buffer data:", flash_buffer, TLSR82_PAGE_SIZE);
+  for (i = 0; i < npages; i++)
+    {
+      ret = tlsr82_flash_bwrite(&priv->mtd, i, 1, flash_buffer);
+      if (ret != 1)
+        {
+          ferr("    Flash block write failed, ret=%d\n", ret);
+          goto errout;
+        }
+    }
+
+  /* 3) protect the flash, read the flash status register */
+
+  FLASH_PROT_TRACE_START();
+  tlsr82_flash_protect();
+  FLASH_PROT_TRACE_END();
+
+  status = tlsr82_flash_read_status(5);
+  ferr("Current flash status: 0x%x\n", status);
+
+  /* 4) erase the chip with flash protected */
+
+  addr = priv->baseaddr;
+  for (i = 0; i < priv->nsectors; i++)
+    {
+      tlsr82_flash_erase_sector(addr);
+      addr += priv->sectorsize;
+    }
+
+  FLASH_UNPROT_TRACE_START();
+  tlsr82_flash_unprotect();
+  FLASH_UNPROT_TRACE_END();
+
+  /* 5) read the chip, the data should be same as the data written in 2) */
+
+  for (i = 0; i < npages; i++)
+    {
+      memset(flash_read_buffer, 0, TLSR82_PAGE_SIZE);
+      ret = tlsr82_flash_bread(&priv->mtd, i, 1, flash_read_buffer);
+      if (ret != 1)
+        {
+          ferr("    Flash block read failed, ret=%d\n", ret);
+          goto errout;
+        }
+
+      if (memcmp(flash_read_buffer, flash_buffer, TLSR82_PAGE_SIZE) != 0)
+        {
+          ferr("    Flash write compre is not equal, page_i=%d\n", i);
+          tlsr82_flash_print("Write buffer data:", flash_buffer,
+                             TLSR82_PAGE_SIZE);
+          tlsr82_flash_print("Read buffer data:", flash_read_buffer,
+                             TLSR82_PAGE_SIZE);
+          goto errout;
+        }
+    }
+#endif
+
   ferr("======== Flash test Success ========\n");
 
   return OK;
@@ -685,6 +770,22 @@ static int tlsr82_flash_ioctl(struct mtd_dev_s *dev, int cmd,
         }
         break;
 
+      case MTDIOC_PROTECT:
+        {
+          /* Ignore arg, direct protect full chip */
+
+          tlsr82_flash_protect();
+        }
+        break;
+
+      case MTDIOC_UNPROTECT:
+        {
+          /* Ignore arg, direct unprotect full chip */
+
+          tlsr82_flash_unprotect();
+        }
+        break;
+
       default:
           ret = -ENOTTY; /* Bad/unsupported command */
           break;
@@ -776,6 +877,10 @@ struct mtd_dev_s *tlsr82_flash_initialize(uint32_t offset, uint32_t size)
       goto errout;
     }
 
+  /* Calibrate the flash */
+
+  tlsr82_flash_calibrate(g_flash_mid);
+
 #ifdef CONFIG_TLSR82_FLASH_TEST
   ret = tlsr82_flash_test(priv);
   if (ret < 0)