diff mbox

[U-Boot,v2,1/2] altera_qspi: add lock unlock ops

Message ID 1448960876-22615-1-git-send-email-thomas@wytron.com.tw
State Accepted, archived
Delegated to: Thomas Chou
Headers show

Commit Message

Thomas Chou Dec. 1, 2015, 9:07 a.m. UTC
Add lock() and unlock() mtd ops to altera_qspi.

Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
---
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(+)

Comments

Marek Vasut Dec. 1, 2015, 1:23 p.m. UTC | #1
On Tuesday, December 01, 2015 at 10:07:55 AM, Thomas Chou wrote:
> Add lock() and unlock() mtd ops to altera_qspi.
> 
> Signed-off-by: Thomas Chou <thomas@wytron.com.tw>

Reviewed-by: Marek Vasut <marex@denx.de>

Best regards,
Marek Vasut
Thomas Chou Dec. 6, 2015, 3:32 a.m. UTC | #2
On 2015年12月01日 17:07, Thomas Chou wrote:
> Add lock() and unlock() mtd ops to altera_qspi.
>
> Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
> ---
> 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.
diff mbox

Patch

diff --git a/drivers/mtd/altera_qspi.c b/drivers/mtd/altera_qspi.c
index 50c6e0e..61a6a5e 100644
--- a/drivers/mtd/altera_qspi.c
+++ b/drivers/mtd/altera_qspi.c
@@ -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))