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

Signed-off-by: Thomas Chou <tho...@wytron.com.tw>
---
 drivers/mtd/altera_qspi.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)

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

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to