From patchwork Thu Dec 6 06:21:24 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vipin Kumar X-Patchwork-Id: 204139 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 4ABBC2C0199 for ; Thu, 6 Dec 2012 17:23:05 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id D8B884A18A; Thu, 6 Dec 2012 07:22:51 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de 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 YDVna1kWOL3L; Thu, 6 Dec 2012 07:22:51 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 42A474A1B8; Thu, 6 Dec 2012 07:22:07 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id A662E4A163 for ; Thu, 6 Dec 2012 07:21:50 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de 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 peufY146LKPC for ; Thu, 6 Dec 2012 07:21:49 +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 eu1sys200aog102.obsmtp.com (eu1sys200aog102.obsmtp.com [207.126.144.113]) by theia.denx.de (Postfix) with ESMTPS id A73034A182 for ; Thu, 6 Dec 2012 07:21:45 +0100 (CET) Received: from beta.dmz-ap.st.com ([138.198.100.35]) (using TLSv1) by eu1sys200aob102.postini.com ([207.126.147.11]) with SMTP ID DSNKUMA5d7x1RZwmbmSXIqdw4AYkuSRutyne@postini.com; Thu, 06 Dec 2012 06:21:48 UTC Received: from zeta.dmz-ap.st.com (ns6.st.com [138.198.234.13]) by beta.dmz-ap.st.com (STMicroelectronics) with ESMTP id 9A384E0; Thu, 6 Dec 2012 06:13:28 +0000 (GMT) Received: from Webmail-ap.st.com (eapex1hubcas3.st.com [10.80.176.67]) by zeta.dmz-ap.st.com (STMicroelectronics) with ESMTP id F219DAA9; Thu, 6 Dec 2012 06:21:39 +0000 (GMT) Received: from localhost (10.199.82.27) by Webmail-ap.st.com (10.80.176.7) with Microsoft SMTP Server (TLS) id 8.3.245.1; Thu, 6 Dec 2012 14:21:39 +0800 From: Vipin Kumar To: , , Date: Thu, 6 Dec 2012 11:51:24 +0530 Message-ID: <549a68c6f353eafc3c52098a45257a1403cf5a4b.1354774371.git.vipin.kumar@st.com> X-Mailer: git-send-email 1.8.0 In-Reply-To: References: MIME-Version: 1.0 Cc: spear-devel@list.st.com Subject: [U-Boot] [PATCH resend 7/7] mtd/st_smi: Add mtd support for smi X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de This patch adds mtd device support for smi devices Signed-off-by: Vipin Kumar --- drivers/mtd/st_smi.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 165 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/st_smi.c b/drivers/mtd/st_smi.c index 0e529a4..4d1a6bd 100644 --- a/drivers/mtd/st_smi.c +++ b/drivers/mtd/st_smi.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -37,6 +38,14 @@ static ulong bank_base[CONFIG_SYS_MAX_FLASH_BANKS] = CONFIG_SYS_FLASH_ADDR_BASE; flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; +#if defined(CONFIG_MTD_DEVICE) +/* MTD interface for SMI devices */ +static struct mtd_info smi_mtd_info[CONFIG_SYS_MAX_FLASH_BANKS]; +static char smi_mtd_names[CONFIG_SYS_MAX_FLASH_BANKS][16]; + +static int smi_mtd_init(void); +#endif + /* data structure to maintain flash ids from different vendors */ struct flash_device { char *name; @@ -482,7 +491,9 @@ unsigned long flash_init(void) { unsigned long size = 0; int i, j; - +#if defined(CONFIG_MTD_DEVICE) + int error; +#endif smi_init(); for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) { @@ -498,6 +509,12 @@ unsigned long flash_init(void) } +#if defined(CONFIG_MTD_DEVICE) + error = smi_mtd_init(); + if (error < 0) + return 0; +#endif + return size; } @@ -599,4 +616,150 @@ int flash_erase(flash_info_t *info, int s_first, int s_last) puts(" done\n"); return rcode; } -#endif + +#if defined(CONFIG_MTD_DEVICE) +static int smi_mtd_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + flash_info_t *fi = mtd->priv; + size_t a_start = fi->start[0] + instr->addr; + size_t a_end = a_start + instr->len; + int s_first = -1; + int s_last = -1; + int error, sect; + + for (sect = 0; sect < fi->sector_count; sect++) { + if (a_start == fi->start[sect]) + s_first = sect; + + if (sect < fi->sector_count - 1) { + if (a_end == fi->start[sect + 1]) { + s_last = sect; + break; + } + } else { + s_last = sect; + break; + } + } + + if (s_first >= 0 && s_first <= s_last) { + instr->state = MTD_ERASING; + + error = flash_erase(fi, s_first, s_last); + if (error) { + instr->state = MTD_ERASE_FAILED; + return -EIO; + } + + instr->state = MTD_ERASE_DONE; + mtd_erase_callback(instr); + return 0; + } + + return -EINVAL; +} + +static int smi_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + flash_info_t *fi = mtd->priv; + u_char *f = (u_char *)(fi->start[0]) + from; + + memcpy(buf, f, len); + *retlen = len; + + return 0; +} + +static int smi_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + flash_info_t *fi = mtd->priv; + u_long t = fi->start[0] + to; + int error; + + error = write_buff(fi, (u_char *)buf, t, len); + if (!error) { + *retlen = len; + return 0; + } + + return -EIO; +} + +static void smi_mtd_sync(struct mtd_info *mtd) +{ + /* + * This function should wait until all pending operations + * finish. However this driver is fully synchronous, so + * this function returns immediately + */ +} + +static int smi_mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) +{ + flash_info_t *fi = mtd->priv; + + flash_protect(FLAG_PROTECT_SET, fi->start[0] + ofs, + fi->start[0] + ofs + len - 1, fi); + return 0; +} + +static int smi_mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) +{ + flash_info_t *fi = mtd->priv; + + flash_protect(FLAG_PROTECT_CLEAR, fi->start[0] + ofs, + fi->start[0] + ofs + len - 1, fi); + return 0; +} + +static int smi_mtd_init(void) +{ + struct flash_device *flash_device_p; + struct mtd_info *mtd; + flash_info_t *fi; + int i; + + for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) { + fi = &flash_info[i]; + + if (!fi->size) + continue; + + flash_device_p = get_flash_device(fi->flash_id); + if (!flash_device_p) + return -EIO; + + mtd = &smi_mtd_info[i]; + + memset(mtd, 0, sizeof(struct mtd_info)); + + /* Uniform erase sizes for all sectors */ + mtd->numeraseregions = 0; + mtd->erasesize = flash_device_p->sectorsize; + + sprintf(smi_mtd_names[i], "nor%d", i); + mtd->name = smi_mtd_names[i]; + mtd->type = MTD_NORFLASH; + mtd->flags = MTD_CAP_NORFLASH; + mtd->size = fi->size; + mtd->writesize = 1; + + mtd->erase = smi_mtd_erase; + mtd->read = smi_mtd_read; + mtd->write = smi_mtd_write; + mtd->sync = smi_mtd_sync; + mtd->lock = smi_mtd_lock; + mtd->unlock = smi_mtd_unlock; + mtd->priv = fi; + + if (add_mtd_device(mtd)) + return -ENOMEM; + } + + return 0; +} +#endif /* CONFIG_MTD_DEVICE */ + +#endif /* CONFIG_SYS_NO_FLASH */