Skip to contentSkip to conversation

altera_qspi: add lock unlock ops

PATCH Superseded Thomas Chou 3 participants 12 messages Nov 29, 2015 – Dec 6, 2015 Memory technology devices (MTD)

lore
Share & tools
lore
#0 lore raw

PATCH 1/2 altera_qspi: add lock unlock ops

Add lock() and unlock() mtd ops to altera_qspi.

---
 drivers/mtd/altera_qspi.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)
drivers/mtd/altera_qspi.c +82 -0
index 50c6e0e..89f04a4 100644
@@ -46,10 +46,24 @@ struct altera_qspi_platdata {
 
 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];	/* FLASH chips info */
 
+static void altera_qspi_get_locked_range(struct mtd_info *mtd, loff_t *ofs,
+					 uint64_t *len);
+
 void flash_print_info(flash_info_t *info)
 {
+	struct mtd_info *mtd = info->mtd;
+	loff_t ofs;
+	uint64_t len;
+
 	printf("Altera QSPI flash  Size: %ld MB in %d Sectors\n",
 	       info->size >> 20, info->sector_count);
+	altera_qspi_get_locked_range(mtd, &ofs, &len);
+	printf("  %08lX +%lX", info->start[0], info->size);
+	if (len) {
+		printf(", protected %08lX +%lX",
+		       info->start[0] + (ulong)ofs, (ulong)len);
+	}
+	putc('\n');
 }
 
 int flash_erase(flash_info_t *info, int s_first, int s_last)
@@ -171,6 +185,72 @@ static void altera_qspi_sync(struct mtd_info *mtd)
 {
 }
 
+static void altera_qspi_get_locked_range(struct mtd_info *mtd, loff_t *ofs,
+					 uint64_t *len)
+{
+	struct udevice *dev = mtd->dev;
+	struct altera_qspi_platdata *pdata = dev_get_platdata(dev);
+	struct altera_qspi_regs *regs = pdata->regs;
+	u32 stat = readl(&regs->rd_status);
+	unsigned pow = ((stat >> 2) & 0x7) | ((stat >> 3) & 0x8);
+
+	*ofs = 0;
+	*len = 0;
+	if (pow) {
+		*len = mtd->erasesize << (pow - 1);
+		if (!(stat & 0x20))
+			*ofs = mtd->size - *len;
+	}
+}
+
+static int altera_qspi_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+	struct udevice *dev = mtd->dev;
+	struct altera_qspi_platdata *pdata = dev_get_platdata(dev);
+	struct altera_qspi_regs *regs = pdata->regs;
+	u32 sector_start, sector_end;
+	uint64_t num_sectors;
+	u32 mem_op;
+	u32 sr_bp;
+	u32 sr_tb;
+
+	num_sectors = mtd->size / mtd->erasesize;
+	sector_start = ofs / mtd->erasesize;
+	sector_end = (ofs + len) / mtd->erasesize;
+
+	if (sector_start >= num_sectors / 2) {
+		sr_bp = fls(num_sectors - 1 - sector_start) + 1;
+		sr_tb = 0;
+	} else if (sector_end < num_sectors / 2) {
+		sr_bp = fls(sector_end) + 1;
+		sr_tb = 1;
+	} else {
+		sr_bp = 15;
+		sr_tb = 0;
+	}
+
+	mem_op = (sr_tb << 12) | (sr_bp << 8);
+	mem_op |= QUADSPI_MEM_OP_SECTOR_PROTECT;
+	debug("lock %08x\n", mem_op);
+	writel(mem_op, &regs->mem_op);
+
+	return 0;
+}
+
+static int altera_qspi_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+	struct udevice *dev = mtd->dev;
+	struct altera_qspi_platdata *pdata = dev_get_platdata(dev);
+	struct altera_qspi_regs *regs = pdata->regs;
+	u32 mem_op;
+
+	mem_op = QUADSPI_MEM_OP_SECTOR_PROTECT;
+	debug("unlock %08x\n", mem_op);
+	writel(mem_op, &regs->mem_op);
+
+	return 0;
+}
+
 static int altera_qspi_probe(struct udevice *dev)
 {
 	struct altera_qspi_platdata *pdata = dev_get_platdata(dev);
@@ -196,6 +276,8 @@ static int altera_qspi_probe(struct udevice *dev)
 	mtd->_read		= altera_qspi_read;
 	mtd->_write		= altera_qspi_write;
 	mtd->_sync		= altera_qspi_sync;
+	mtd->_lock		= altera_qspi_lock;
+	mtd->_unlock		= altera_qspi_unlock;
 	mtd->numeraseregions = 0;
 	mtd->erasesize = 0x10000;
 	if (add_mtd_device(mtd))
Signature · 1 line
2.5.0
#1 lore raw

PATCH 2/2 altera_qspi: fix erase and write error code

Fix erase and write error code, which should be "protected".

---
 drivers/mtd/altera_qspi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/mtd/altera_qspi.c +2 -2
index 89f04a4..cf45e73 100644
@@ -77,7 +77,7 @@ int flash_erase(flash_info_t *info, int s_first, int s_last)
 	instr.len = mtd->erasesize * (s_last + 1 - s_first);
 	ret = mtd_erase(mtd, &instr);
 	if (ret)
-		return ERR_NOT_ERASED;
+		return ERR_PROTECTED;
 
 	return 0;
 }
@@ -94,7 +94,7 @@ int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 
 	ret = mtd_write(mtd, to, cnt, &retlen, src);
 	if (ret)
-		return ERR_NOT_ERASED;
+		return ERR_PROTECTED;
 
 	return 0;
 }
Signature · 1 line
2.5.0
#2 lore raw

PATCH 2/2 altera_qspi: fix erase and write error code

Quoted 1 line · Thomas Chou

Fix erase and write error code, which should be "protected".

Can you elaborate on why do you think this change is correct please ? That reasoning should be part of the patch description.

Quoted 27 lines
---
 drivers/mtd/altera_qspi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/mtd/altera_qspi.c +2 -2
index 89f04a4..cf45e73 100644
@@ -77,7 +77,7 @@ int flash_erase(flash_info_t *info, int s_first, int
 s_last) instr.len = mtd->erasesize * (s_last + 1 - s_first);
 	ret = mtd_erase(mtd, &instr);
 	if (ret)
-		return ERR_NOT_ERASED;
+		return ERR_PROTECTED;
 
 	return 0;
 }
@@ -94,7 +94,7 @@ int write_buff(flash_info_t *info, uchar *src, ulong
 addr, ulong cnt)
 
 	ret = mtd_write(mtd, to, cnt, &retlen, src);
 	if (ret)
-		return ERR_NOT_ERASED;
+		return ERR_PROTECTED;
 
 	return 0;
Quoted 1 line

}

Best regards,
Marek Vasut

#4 lore raw

PATCH 1/2 altera_qspi: add lock unlock ops

In reply to Thomas Chou
Quoted 13 lines · Thomas Chou

Add lock() and unlock() mtd ops to altera_qspi.

---
 drivers/mtd/altera_qspi.c | 82

+++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+)

drivers/mtd/altera_qspi.c +0 -0
index 50c6e0e..89f04a4 100644

drivers/mtd/altera_qspi.c struct altera_qspi_platdata { · line 47

Quoted 2 lines
drivers/mtd/altera_qspi.c +0 -0
@@ -46,10 +46,24 @@ struct altera_qspi_platdata {
 
 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];	/* FLASH chips 

info

drivers/mtd/altera_qspi.c struct altera_qspi_platdata { · line 56

Quoted 10 lines
drivers/mtd/altera_qspi.c +5 -0
 */
 
+static void altera_qspi_get_locked_range(struct mtd_info *mtd, loff_t
 *ofs, +					 uint64_t *len);
+
 void flash_print_info(flash_info_t *info)
 {
+	struct mtd_info *mtd = info->mtd;
+	loff_t ofs;
+	uint64_t len;

u64 please.

drivers/mtd/altera_qspi.c struct altera_qspi_platdata { · line 64

Quoted 8 lines
drivers/mtd/altera_qspi.c +6 -0
+
 	printf("Altera QSPI flash  Size: %ld MB in %d Sectors\n",
 	       info->size >> 20, info->sector_count);
+	altera_qspi_get_locked_range(mtd, &ofs, &len);
+	printf("  %08lX +%lX", info->start[0], info->size);
+	if (len) {
+		printf(", protected %08lX +%lX",
+		       info->start[0] + (ulong)ofs, (ulong)len);

Do you really need the typecasts here ? %llx should do it for the len and dropping the l should do it for ofs I think.

Quoted 14 lines
drivers/mtd/altera_qspi.c +6 -0
+	}
+	putc('\n');
 }
 
 int flash_erase(flash_info_t *info, int s_first, int s_last)
@@ -171,6 +185,72 @@ static void altera_qspi_sync(struct mtd_info *mtd)
 {
 }
 
+static void altera_qspi_get_locked_range(struct mtd_info *mtd, loff_t
 *ofs, +					 uint64_t *len)
+{
+	struct udevice *dev = mtd->dev;
+	struct altera_qspi_platdata *pdata = dev_get_platdata(dev);

drivers/mtd/altera_qspi.c static void altera_qspi_sync(struct mtd_info *mtd) · line 202

Quoted 10 lines
drivers/mtd/altera_qspi.c +10 -0
+	struct altera_qspi_regs *regs = pdata->regs;
+	u32 stat = readl(&regs->rd_status);
+	unsigned pow = ((stat >> 2) & 0x7) | ((stat >> 3) & 0x8);
+
+	*ofs = 0;
+	*len = 0;
+	if (pow) {
+		*len = mtd->erasesize << (pow - 1);
+		if (!(stat & 0x20))
+			*ofs = mtd->size - *len;

What are all these magic numbers ?

drivers/mtd/altera_qspi.c static void altera_qspi_sync(struct mtd_info *mtd) · line 212

Quoted 10 lines
drivers/mtd/altera_qspi.c +9 -0
+	}
+}
+
+static int altera_qspi_lock(struct mtd_info *mtd, loff_t ofs, uint64_t
 len) +{
+	struct udevice *dev = mtd->dev;
+	struct altera_qspi_platdata *pdata = dev_get_platdata(dev);
+	struct altera_qspi_regs *regs = pdata->regs;
+	u32 sector_start, sector_end;
+	uint64_t num_sectors;

u64

drivers/mtd/altera_qspi.c static void altera_qspi_sync(struct mtd_info *mtd) · line 215

Quoted 3 lines
drivers/mtd/altera_qspi.c +3 -0
+	u32 mem_op;
+	u32 sr_bp;
+	u32 sr_tb;

All were just minor nits, thanks!

Best regards,
Marek Vasut

#5 lore raw

PATCH 1/2 altera_qspi: add lock unlock ops

In reply to Thomas Chou
Quoted 8 lines · Thomas Chou

Add lock() and unlock() mtd ops to altera_qspi.

---
 drivers/mtd/altera_qspi.c | 82
+++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)

As agreed with Marek, it would be great that some of the magic number can be converted as defines. FYI, I am opening both Quad SPI controller spec and EPCQ spec to review this :)

Thanks
Chin Liang

#6 lore raw

PATCH v2 1/2 altera_qspi: add lock unlock ops

In reply to Thomas Chou

Add lock() and unlock() mtd ops to altera_qspi.

---
v2
change uint64_t to u64 as suggested by Marek.
add macros for status register.
limit get_locked_range to mtd->size.

 drivers/mtd/altera_qspi.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 95 insertions(+)
drivers/mtd/altera_qspi.c +95 -0
index 50c6e0e..61a6a5e 100644
@@ -14,6 +14,14 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+/* The STATUS register */
+#define QUADSPI_SR_BP0				BIT(2)
+#define QUADSPI_SR_BP1				BIT(3)
+#define QUADSPI_SR_BP2				BIT(4)
+#define QUADSPI_SR_BP2_0			GENMASK(4, 2)
+#define QUADSPI_SR_BP3				BIT(6)
+#define QUADSPI_SR_TB				BIT(5)
+
 /*
  * The QUADSPI_MEM_OP register is used to do memory protect and erase operations
  */
@@ -46,10 +54,24 @@ struct altera_qspi_platdata {
 
 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];	/* FLASH chips info */
 
+static void altera_qspi_get_locked_range(struct mtd_info *mtd, loff_t *ofs,
+					 uint64_t *len);
+
 void flash_print_info(flash_info_t *info)
 {
+	struct mtd_info *mtd = info->mtd;
+	loff_t ofs;
+	u64 len;
+
 	printf("Altera QSPI flash  Size: %ld MB in %d Sectors\n",
 	       info->size >> 20, info->sector_count);
+	altera_qspi_get_locked_range(mtd, &ofs, &len);
+	printf("  %08lX +%lX", info->start[0], info->size);
+	if (len) {
+		printf(", protected %08llX +%llX",
+		       info->start[0] + ofs, len);
+	}
+	putc('\n');
 }
 
 int flash_erase(flash_info_t *info, int s_first, int s_last)
@@ -171,6 +193,77 @@ static void altera_qspi_sync(struct mtd_info *mtd)
 {
 }
 
+static void altera_qspi_get_locked_range(struct mtd_info *mtd, loff_t *ofs,
+					 uint64_t *len)
+{
+	struct udevice *dev = mtd->dev;
+	struct altera_qspi_platdata *pdata = dev_get_platdata(dev);
+	struct altera_qspi_regs *regs = pdata->regs;
+	int shift0 = ffs(QUADSPI_SR_BP2_0) - 1;
+	int shift3 = ffs(QUADSPI_SR_BP3) - 1 - 3;
+	u32 stat = readl(&regs->rd_status);
+	unsigned pow = ((stat & QUADSPI_SR_BP2_0) >> shift0) |
+		((stat & QUADSPI_SR_BP3) >> shift3);
+
+	*ofs = 0;
+	*len = 0;
+	if (pow) {
+		*len = mtd->erasesize << (pow - 1);
+		if (*len > mtd->size)
+			*len = mtd->size;
+		if (!(stat & QUADSPI_SR_TB))
+			*ofs = mtd->size - *len;
+	}
+}
+
+static int altera_qspi_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+	struct udevice *dev = mtd->dev;
+	struct altera_qspi_platdata *pdata = dev_get_platdata(dev);
+	struct altera_qspi_regs *regs = pdata->regs;
+	u32 sector_start, sector_end;
+	u32 num_sectors;
+	u32 mem_op;
+	u32 sr_bp;
+	u32 sr_tb;
+
+	num_sectors = mtd->size / mtd->erasesize;
+	sector_start = ofs / mtd->erasesize;
+	sector_end = (ofs + len) / mtd->erasesize;
+
+	if (sector_start >= num_sectors / 2) {
+		sr_bp = fls(num_sectors - 1 - sector_start) + 1;
+		sr_tb = 0;
+	} else if (sector_end < num_sectors / 2) {
+		sr_bp = fls(sector_end) + 1;
+		sr_tb = 1;
+	} else {
+		sr_bp = 15;
+		sr_tb = 0;
+	}
+
+	mem_op = (sr_tb << 12) | (sr_bp << 8);
+	mem_op |= QUADSPI_MEM_OP_SECTOR_PROTECT;
+	debug("lock %08x\n", mem_op);
+	writel(mem_op, &regs->mem_op);
+
+	return 0;
+}
+
+static int altera_qspi_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+	struct udevice *dev = mtd->dev;
+	struct altera_qspi_platdata *pdata = dev_get_platdata(dev);
+	struct altera_qspi_regs *regs = pdata->regs;
+	u32 mem_op;
+
+	mem_op = QUADSPI_MEM_OP_SECTOR_PROTECT;
+	debug("unlock %08x\n", mem_op);
+	writel(mem_op, &regs->mem_op);
+
+	return 0;
+}
+
 static int altera_qspi_probe(struct udevice *dev)
 {
 	struct altera_qspi_platdata *pdata = dev_get_platdata(dev);
@@ -196,6 +289,8 @@ static int altera_qspi_probe(struct udevice *dev)
 	mtd->_read		= altera_qspi_read;
 	mtd->_write		= altera_qspi_write;
 	mtd->_sync		= altera_qspi_sync;
+	mtd->_lock		= altera_qspi_lock;
+	mtd->_unlock		= altera_qspi_unlock;
 	mtd->numeraseregions = 0;
 	mtd->erasesize = 0x10000;
 	if (add_mtd_device(mtd))
Signature · 1 line
2.5.0
#7 lore raw

PATCH v2 1/2 altera_qspi: add lock unlock ops

Quoted 12 lines · Thomas Chou

Add lock() and unlock() mtd ops to altera_qspi.

---
v2
change uint64_t to u64 as suggested by Marek.
add macros for status register.
limit get_locked_range to mtd->size.

  drivers/mtd/altera_qspi.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++
  1 file changed, 95 insertions(+)

Applied to u-boot-nios.

#9 lore raw

PATCH v2 2/2 altera_qspi: fix erase and write error code

In reply to Thomas Chou

Fix erase and write error code, which should be "protected".

From the "Embedded Peripherals IP User Guide" of Altera,

The "Illegal write" flag indicates that a write instruction is targeting a protected sector on the flash memory. This bit is set to indicate that the IP has cancelled a write instruction.

The "Illegal erase" flag indicates that an erase instruction has been set to a protected sector on the flash memory. This bit is set to indicate that the IP has cancelled the erase instruction.

---
v2
add description as suggested by Marek.

 drivers/mtd/altera_qspi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/mtd/altera_qspi.c +2 -2
index 61a6a5e..617bf5d 100644
@@ -85,7 +85,7 @@ int flash_erase(flash_info_t *info, int s_first, int s_last)
 	instr.len = mtd->erasesize * (s_last + 1 - s_first);
 	ret = mtd_erase(mtd, &instr);
 	if (ret)
-		return ERR_NOT_ERASED;
+		return ERR_PROTECTED;
 
 	return 0;
 }
@@ -102,7 +102,7 @@ int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 
 	ret = mtd_write(mtd, to, cnt, &retlen, src);
 	if (ret)
-		return ERR_NOT_ERASED;
+		return ERR_PROTECTED;
 
 	return 0;
 }
Signature · 1 line
2.5.0
#10 lore raw

PATCH v2 2/2 altera_qspi: fix erase and write error code

Quoted 8 lines · Thomas Chou

Fix erase and write error code, which should be "protected".

From the "Embedded Peripherals IP User Guide" of Altera,

The "Illegal write" flag indicates that a write instruction is targeting a protected sector on the flash memory. This bit is set to indicate that the IP has cancelled a write instruction.

Quoted 5 lines

The "Illegal erase" flag indicates that an erase instruction has been set to a protected sector on the flash memory. This bit is set to indicate that the IP has cancelled the erase instruction.

Best regards,
Marek Vasut

#11 lore raw

PATCH v2 2/2 altera_qspi: fix erase and write error code

In reply to Thomas Chou
Quoted 12 lines · Thomas Chou

Fix erase and write error code, which should be "protected".

Quoted 1 line

From the "Embedded Peripherals IP User Guide" of Altera,

The "Illegal write" flag indicates that a write instruction is targeting a protected sector on the flash memory. This bit is set to indicate that the IP has cancelled a write instruction.

The "Illegal erase" flag indicates that an erase instruction has been set to a protected sector on the flash memory. This bit is set to indicate that the IP has cancelled the erase instruction.

Quoted 8 lines

---
v2
add description as suggested by Marek.

  drivers/mtd/altera_qspi.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

Applied to u-boot-nios.