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)