From patchwork Tue Dec 1 09:07:55 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Chou X-Patchwork-Id: 550749 X-Patchwork-Delegate: thomas@wytron.com.tw Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 5AC4D1401E7 for ; Tue, 1 Dec 2015 20:08:22 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id D60AA4B8B6; Tue, 1 Dec 2015 10:08:15 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ZPEUz-vStLy8; Tue, 1 Dec 2015 10:08:15 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 03F2A4B8BD; Tue, 1 Dec 2015 10:08:12 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 190C04B893 for ; Tue, 1 Dec 2015 10:08:06 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id GmJu5Dk2uppT for ; Tue, 1 Dec 2015 10:08:05 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from www.wytron.com.tw (220-134-43-68.HINET-IP.hinet.net [220.134.43.68]) by theia.denx.de (Postfix) with ESMTP id 46FF04B85E for ; Tue, 1 Dec 2015 10:08:01 +0100 (CET) Received: from localhost.localdomain (unknown [192.168.1.250]) by www.wytron.com.tw (Postfix) with ESMTP id D6463D0000D; Tue, 1 Dec 2015 17:07:57 +0800 (CST) From: Thomas Chou To: u-boot@lists.denx.de Date: Tue, 1 Dec 2015 17:07:55 +0800 Message-Id: <1448960876-22615-1-git-send-email-thomas@wytron.com.tw> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1448797103-30524-1-git-send-email-thomas@wytron.com.tw> References: <1448797103-30524-1-git-send-email-thomas@wytron.com.tw> Cc: Marek Vasut , lftan@altera.com, clsee@altera.com Subject: [U-Boot] [PATCH v2 1/2] altera_qspi: add lock unlock ops X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.15 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Add lock() and unlock() mtd ops to altera_qspi. Signed-off-by: Thomas Chou Reviewed-by: Marek Vasut --- 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(+) 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(®s->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, ®s->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, ®s->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))