From patchwork Tue Aug 13 16:59:29 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagar Shrikant Kadam X-Patchwork-Id: 1146524 X-Patchwork-Delegate: uboot@andestech.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=sifive.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=sifive.com header.i=@sifive.com header.b="NQEuBY26"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 467KcC4YFXz9sND for ; Wed, 14 Aug 2019 03:35:23 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 5204DC22081; Tue, 13 Aug 2019 17:24:57 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 76C1DC21FED; Tue, 13 Aug 2019 17:24:55 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 20533C22079; Tue, 13 Aug 2019 16:59:54 +0000 (UTC) Received: from mail-pl1-f196.google.com (mail-pl1-f196.google.com [209.85.214.196]) by lists.denx.de (Postfix) with ESMTPS id 724A2C21FBC for ; Tue, 13 Aug 2019 16:59:51 +0000 (UTC) Received: by mail-pl1-f196.google.com with SMTP id bj8so2505476plb.4 for ; Tue, 13 Aug 2019 09:59:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sifive.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=wMP0Pui5VTS7emEwoghcSOIW/l7o50q4LOnKBEz4Heo=; b=NQEuBY26eRwu9xqW1ICkGZjx9TWuwD9hQm/jhny5Nz7Kw1YW+//QES/u82/H2HFyHo RWliwnLAzl3F3o3PW6JD2u5MbKpPamv18LmxFSb727xSM/El9I4+3ks2nvKveQjFHIXQ jKDf7CBK+H08wkK5OZirgF3LRxloh+DtQ7L3jEz2CSTD1Ezw3rRY4tEt2j9FSoXqcAES bjp6BfJwMndRytWLhhUsY8vZ1sFGvNTtxhOasMYK/BXK3Uhf9Kz/l8RTq00b62SbrY+M 4al4ifao13dNja0o52+twCEjwcoLLDm5bLx0BGwFI5qdubwfLrhHYr3Gbzco/Lf7WElA BDlA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=wMP0Pui5VTS7emEwoghcSOIW/l7o50q4LOnKBEz4Heo=; b=JSKmCCYcfxYGXM3avyQYClTC4nEk8Ypd9bG9/veFb0Kd1H2cxmXSpv3d+amRSLjeAW 3y74f5/7mX67y7whGimTcgBm7KVVZCsknHodj5nEPpNv3dvSmwCuuw3c5hxBljYNF5BG idmRVtOfPc039Wm8avIvyKjEu8blEXtQo6cbvsxHxJOcREJi14IsKd/iiUqy0G2e2idP vC2OsOG3GgSF4rR8zYMNDuCX/eTK01DKCG2ba+TiJPzLKzXK3AGpIPfps5IsFnXfTy5j mBaMqNbIce390gg4iiv4qTMuK/v58/kw+g4CGpyV1yz6D3pucPj0l4YkQL1NNWBj9Oc9 MfDA== X-Gm-Message-State: APjAAAWHc7UWEJ62KweboX/K4f4WNIt1nmdnzZ0+eYvqjHwsf5qfASik Gmc+U/cAIuyiHOYJqcbYZ1PlIB7yDuZLzA== X-Google-Smtp-Source: APXvYqxENUhct1Sua2Yo0d+8o4CyVgzHOqVZHSnhZKuXXxiMLKIM/reu+B5YiAxVPTTnFcwfTklBVg== X-Received: by 2002:a17:902:ba96:: with SMTP id k22mr39646563pls.44.1565715589527; Tue, 13 Aug 2019 09:59:49 -0700 (PDT) Received: from gamma07.internal.sifive.com ([64.62.193.194]) by smtp.googlemail.com with ESMTPSA id w11sm6040857pfi.105.2019.08.13.09.59.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 13 Aug 2019 09:59:48 -0700 (PDT) From: Sagar Shrikant Kadam To: u-boot@lists.denx.de, paul.walmsley@sifive.com, palmer@sifive.com, anup.patel@wdc.com, atish.patra@wdc.com, jagan@amarulasolutions.com, vigneshr@ti.com Date: Tue, 13 Aug 2019 09:59:29 -0700 Message-Id: <1565715571-26558-2-git-send-email-sagar.kadam@sifive.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1565715571-26558-1-git-send-email-sagar.kadam@sifive.com> References: <1565715571-26558-1-git-send-email-sagar.kadam@sifive.com> Subject: [U-Boot] [U-BOOT PATCH 1/3] spi: nor: add spi-nor-fixup handlers for nor devices X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 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 support for spi_nor_fixups similar to that done in linux. Flash vendor specific fixups can be registered in spi_nor_ids. and will be called after BFPT parsing to fix any wrong parameter read from SFDP. Signed-off-by: Sagar Shrikant Kadam --- drivers/mtd/spi/sf_internal.h | 5 +++++ drivers/mtd/spi/spi-nor-core.c | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index a6bf734..c5e68d8 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -65,6 +65,11 @@ struct flash_info { #define NO_CHIP_ERASE BIT(12) /* Chip does not support chip erase */ #define SPI_NOR_SKIP_SFDP BIT(13) /* Skip parsing of SFDP tables */ #define USE_CLSR BIT(14) /* use CLSR command */ + +#ifdef CONFIG_SPI_FLASH_SFDP_SUPPORT + /* Part specific fixup hooks */ + const struct spi_nor_fixups *fixups; +#endif }; extern const struct flash_info spi_nor_ids[]; diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index 1acff74..4306d19 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -1623,6 +1623,33 @@ static const struct sfdp_bfpt_erase sfdp_bfpt_erases[] = { static int spi_nor_hwcaps_read2cmd(u32 hwcaps); /** + * struct spi_nor_fixups - SPI NOR fixup hooks + * @post_bfpt: called after the BFPT table has been parsed + * + * Those hooks can be used to tweak the SPI NOR configuration when the SFDP + * table is broken or not available. + */ +struct spi_nor_fixups { + int (*post_bfpt)(struct spi_nor *nor, + const struct sfdp_parameter_header *bfpt_header, + const struct sfdp_bfpt *bfpt, + struct spi_nor_flash_parameter *params); +}; + +static int +spi_nor_post_bfpt_fixups(struct spi_nor *nor, + const struct sfdp_parameter_header *bfpt_header, + const struct sfdp_bfpt *bfpt, + struct spi_nor_flash_parameter *params) +{ + if (nor->info->fixups && nor->info->fixups->post_bfpt) + return nor->info->fixups->post_bfpt(nor, bfpt_header, bfpt, + params); + + return 0; +} + +/** * spi_nor_parse_bfpt() - read and parse the Basic Flash Parameter Table. * @nor: pointer to a 'struct spi_nor' * @bfpt_header: pointer to the 'struct sfdp_parameter_header' describing @@ -1760,7 +1787,8 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, /* Stop here if not JESD216 rev A or later. */ if (bfpt_header->length < BFPT_DWORD_MAX) - return 0; + return spi_nor_post_bfpt_fixups(nor, bfpt_header, &bfpt, + params); /* Page size: this field specifies 'N' so the page size = 2^N bytes. */ params->page_size = bfpt.dwords[BFPT_DWORD(11)]; @@ -1793,7 +1821,8 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, return -EINVAL; } - return 0; + return spi_nor_post_bfpt_fixups(nor, bfpt_header, &bfpt, + params); } /** From patchwork Tue Aug 13 16:59:30 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagar Shrikant Kadam X-Patchwork-Id: 1146522 X-Patchwork-Delegate: uboot@andestech.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=sifive.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=sifive.com header.i=@sifive.com header.b="b3NbnvrK"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 467KS558Njz9sN1 for ; Wed, 14 Aug 2019 03:28:21 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 595DDC2207C; Tue, 13 Aug 2019 17:22:04 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 3E5ABC21FC2; Tue, 13 Aug 2019 17:21:59 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 13CF5C22029; Tue, 13 Aug 2019 16:59:56 +0000 (UTC) Received: from mail-pl1-f194.google.com (mail-pl1-f194.google.com [209.85.214.194]) by lists.denx.de (Postfix) with ESMTPS id A7B2CC21FC2 for ; Tue, 13 Aug 2019 16:59:53 +0000 (UTC) Received: by mail-pl1-f194.google.com with SMTP id g4so3043671plo.3 for ; Tue, 13 Aug 2019 09:59:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sifive.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=S2ii2ZU6F0VX+hhTFVfvcaIaziGbm5Kz8+Su2M/aHdg=; b=b3NbnvrKPlw6ohJyoInFRRB2ltlA0LaKRaDuFxG5viZDkvTs25VMXFEpWSzX4uoGcY tXyMmWMjoPHsA/p1lXSY1r+hsylhmyXjrdITvWkcMkDUMKHBgRk2CoKaEq+AurS75cq9 biGXWXMk3dEY8wu5cKKr9KGtlvXRUnqdoctKstf5gDMyhXwGFN32sqRqgISaxHkBr68O e+rnROnQ0CAHJwO0mujkYPK9NX4Ur7YRgKZC1RLjDQQFL6X3VKBBZzzKMw375rGfZ/PL pJLvXYMprtERXpUvy40ZukRoR07UF577BxjtARBnbIzuMY1I9x8xqeC3o34PXSIIV8XT O11Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=S2ii2ZU6F0VX+hhTFVfvcaIaziGbm5Kz8+Su2M/aHdg=; b=R6vrG/AlTBeJL5hP1fMHaf+LFMJKU1CKJluL/Lvy0nIkv+d/EbgTyzZFoljDZRcSZW qHsH5oKU6dFQr+Z9+IQSt8SMpm3NY1z3BcGmg7WkVW7g9dNb2AFILBroBpPDUiIvOlpk UotKU4fr2BYkqUG0A+E2Jl2ekyzENekqYIG+j1E6qdOczNUCqYEyMGpB2nNLo0/mp5VR flYFb2k8L5RivhUP549xSLjltAmyu9R6giFNzK82OQIEGu/AYvXDSM6P0+XcCkAlGZ1N 47qSqSKIIX7/81JSc6zPkKmHneTtdejtQZXEWegtPhtdv0MhXRMme+IvzVuepS1AhXaL qTEw== X-Gm-Message-State: APjAAAV7d9D6Mc23+3F9/QfdPax5reG7WiI6DLdJ3R5aRCBC9qQ9arqx 8LAKBQFignYIxmt/AWoyM9gpffHkHsrEQw== X-Google-Smtp-Source: APXvYqz2Qljjw07HAHxf/mL0mk/MofXgEj8BLLSrWh9k/XChwt4mLXHn4m4HoTy9+dojaitOUoTqvQ== X-Received: by 2002:a17:902:a586:: with SMTP id az6mr9271691plb.298.1565715591820; Tue, 13 Aug 2019 09:59:51 -0700 (PDT) Received: from gamma07.internal.sifive.com ([64.62.193.194]) by smtp.googlemail.com with ESMTPSA id w11sm6040857pfi.105.2019.08.13.09.59.50 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 13 Aug 2019 09:59:51 -0700 (PDT) From: Sagar Shrikant Kadam To: u-boot@lists.denx.de, paul.walmsley@sifive.com, palmer@sifive.com, anup.patel@wdc.com, atish.patra@wdc.com, jagan@amarulasolutions.com, vigneshr@ti.com Date: Tue, 13 Aug 2019 09:59:30 -0700 Message-Id: <1565715571-26558-3-git-send-email-sagar.kadam@sifive.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1565715571-26558-1-git-send-email-sagar.kadam@sifive.com> References: <1565715571-26558-1-git-send-email-sagar.kadam@sifive.com> Subject: [U-Boot] [U-BOOT PATCH 2/3] spi: nor: add support for is25wp256 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 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" Enable support for spi nor device(is25wp256) mounted on HiFive Unleashed Rev A00 board. Thanks to Bhargav Shah for porting this patch which is based on linux patches https://lkml.org/lkml/2019/7/2/859. Additionally, set the proper number of sectors in the device id table, so that the sf probe shows the correct size of the flash device. Added SPI_NOR_HAS_BP3 bit to indicate that this nor device has BP3 bit present for the lock/unlock mechanism. Registered a post bfpt fixup handler for this device as the address width advertised by the flash during nor scan is not correct. This flash is tested for plain SPI mode although it also supports QUAD I/O mode. Signed-off-by: Bhargav Shah Signed-off-by: Sagar Shrikant Kadam --- board/sifive/fu540/Kconfig | 5 + drivers/mtd/spi/sf_internal.h | 18 +++ drivers/mtd/spi/spi-nor-core.c | 340 +++++++++++++++++++++++++++++++++++------ drivers/mtd/spi/spi-nor-ids.c | 5 + include/linux/mtd/spi-nor.h | 8 + 5 files changed, 326 insertions(+), 50 deletions(-) diff --git a/board/sifive/fu540/Kconfig b/board/sifive/fu540/Kconfig index 5d65080..f9d5ec1 100644 --- a/board/sifive/fu540/Kconfig +++ b/board/sifive/fu540/Kconfig @@ -40,6 +40,11 @@ config BOARD_SPECIFIC_OPTIONS # dummy imply SIFIVE_SERIAL imply SPI imply SPI_SIFIVE + imply SPI_FLASH + imply SPI_FLASH_ISSI + imply SPI_FLASH_SFDP_SUPPORT + imply CMD_MTD + imply CMD_SF imply MMC imply MMC_SPI imply MMC_BROKEN_CD diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index c5e68d8..6523107 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -65,6 +65,13 @@ struct flash_info { #define NO_CHIP_ERASE BIT(12) /* Chip does not support chip erase */ #define SPI_NOR_SKIP_SFDP BIT(13) /* Skip parsing of SFDP tables */ #define USE_CLSR BIT(14) /* use CLSR command */ +#define SPI_NOR_HAS_BP3 BIT(15) /* + * Flash SR has block protect bits + * for lock/unlock purpose, few support + * BP0-BP2 while few support BP0-BP3. + * This flag identifies devices that + * support BP3 bit. + */ #ifdef CONFIG_SPI_FLASH_SFDP_SUPPORT /* Part specific fixup hooks */ @@ -72,6 +79,17 @@ struct flash_info { #endif }; +#ifdef CONFIG_SPI_FLASH_SFDP_SUPPORT +/* + * Declare manufacturer specific fixup handlers that + * can be registered as fixup's in flash info table + * so as to update any wrong/broken SFDP parameter. + */ +#ifdef CONFIG_SPI_FLASH_ISSI +extern struct spi_nor_fixups is25wp256_fixups; +#endif +#endif + extern const struct flash_info spi_nor_ids[]; #define JEDEC_MFR(info) ((info)->id[0]) diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index 4306d19..46d278d 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -582,7 +582,8 @@ erase_err: return ret; } -#if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST) +#if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST) || \ + defined(CONFIG_SPI_FLASH_ISSI) /* Write status register and ensure bits in mask match written values */ static int write_sr_and_check(struct spi_nor *nor, u8 status_new, u8 mask) { @@ -604,14 +605,45 @@ static int write_sr_and_check(struct spi_nor *nor, u8 status_new, u8 mask) return ((ret & mask) != (status_new & mask)) ? -EIO : 0; } +/** + * spi_nor_read_fr() -read function register + * @nor: pointer to a 'struct spi_nor'. + * + * ISSI devices have top/bottom area protection bits selection into function + * reg. The bits in FR are OTP. So once it's written, it cannot be changed. + * + * Return: Value in function register or negative if error. + */ +static int spi_nor_read_fr(struct spi_nor *nor) +{ + int ret; + u8 val; + + ret = nor->read_reg(nor, SPINOR_OP_RDFR, &val, 1); + if (ret < 0) { + pr_err("error %d reading FR\n", ret); + return ret; + } + + return val; +} + static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs, uint64_t *len) { struct mtd_info *mtd = &nor->mtd; - u8 mask = SR_BP2 | SR_BP1 | SR_BP0; - int shift = ffs(mask) - 1; + u8 mask = 0; + u8 fr = 0; + int shift = 0; int pow; + if (nor->flags & SNOR_F_HAS_BP3) + mask = SR_BP3 | SR_BP2 | SR_BP1 | SR_BP0; + else + mask = SR_BP2 | SR_BP1 | SR_BP0; + + shift = ffs(mask) - 1; + if (!(sr & mask)) { /* No protection */ *ofs = 0; @@ -619,10 +651,20 @@ static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs, } else { pow = ((sr & mask) ^ mask) >> shift; *len = mtd->size >> pow; - if (nor->flags & SNOR_F_HAS_SR_TB && sr & SR_TB) - *ofs = 0; - else - *ofs = mtd->size - *len; + + /* ISSI device's have top/bottom select bit in func reg */ + if (JEDEC_MFR(nor->info) == SNOR_MFR_ISSI) { + fr = spi_nor_read_fr(nor); + if (nor->flags & SNOR_F_HAS_SR_TB && fr & FR_TB) + *ofs = 0; + else + *ofs = mtd->size - *len; + } else { + if (nor->flags & SNOR_F_HAS_SR_TB && sr & SR_TB) + *ofs = 0; + else + *ofs = mtd->size - *len; + } } } @@ -649,18 +691,109 @@ static int stm_check_lock_status_sr(struct spi_nor *nor, loff_t ofs, u64 len, return (ofs >= lock_offs + lock_len) || (ofs + len <= lock_offs); } -static int stm_is_locked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len, - u8 sr) +/* + * check if memory region is locked + * + * Returns false if region is locked 0 otherwise. + */ +static int spi_nor_is_locked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len, + u8 sr) { return stm_check_lock_status_sr(nor, ofs, len, sr, true); } -static int stm_is_unlocked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len, - u8 sr) +/* + * check if memory region is unlocked + * + * Returns false if region is locked 0 otherwise. + */ +static int spi_nor_is_unlocked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len, + u8 sr) { return stm_check_lock_status_sr(nor, ofs, len, sr, false); } +/** + * spi_nor_select_zone() - Select top area or bottom area to lock/unlock + * @nor: pointer to a 'struct spi_nor'. + * @ofs: offset from which to lock memory. + * @len: number of bytes to unlock. + * @sr: status register + * @tb: pointer to top/bottom bool used in caller function + * @op: zone selection is for lock/unlock operation. 1: lock 0:unlock + * + * Select the top area / bottom area pattern to protect memory blocks. + * + * Returns negative on errors, 0 on success. + */ +static int spi_nor_select_zone(struct spi_nor *nor, loff_t ofs, uint64_t len, + u8 sr, bool *tb, bool op) +{ + int retval; + bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB; + + if (op) { + /* Select for lock zone operation */ + + /* + * If nothing in our range is unlocked, we don't need + * to do anything. + */ + if (spi_nor_is_locked_sr(nor, ofs, len, sr)) + return 0; + + /* + * If anything below us is unlocked, we can't use 'bottom' + * protection. + */ + if (!spi_nor_is_locked_sr(nor, 0, ofs, sr)) + can_be_bottom = false; + + /* + * If anything above us is unlocked, we can't use 'top' + * protection. + */ + if (!spi_nor_is_locked_sr(nor, ofs + len, + nor->mtd.size - (ofs + len), sr)) + can_be_top = false; + } else { + /* Select unlock zone */ + + /* + * If nothing in our range is locked, we don't need to + * do anything. + */ + if (spi_nor_is_unlocked_sr(nor, ofs, len, sr)) + return 0; + + /* + * If anything below us is locked, we can't use 'top' + * protection + */ + if (!spi_nor_is_unlocked_sr(nor, 0, ofs, sr)) + can_be_top = false; + + /* + * If anything above us is locked, we can't use 'bottom' + * protection + */ + if (!spi_nor_is_unlocked_sr(nor, ofs + len, + nor->mtd.size - (ofs + len), sr)) + can_be_bottom = false; + } + + if (!can_be_bottom && !can_be_top) { + retval = -EINVAL; + } else { + /* Prefer top, if both are valid */ + *tb = can_be_top; + retval = 1; + } + + return retval; +} + +#if !defined(CONFIG_SPI_FLASH_ISSI) /* * Lock a region of the flash. Compatible with ST Micro and similar flash. * Supports the block protection bits BP{0,1,2} in the status register @@ -698,33 +831,19 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) struct mtd_info *mtd = &nor->mtd; int status_old, status_new; u8 mask = SR_BP2 | SR_BP1 | SR_BP0; - u8 shift = ffs(mask) - 1, pow, val; + u8 shift = ffs(mask) - 1, pow, val, ret; loff_t lock_len; - bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB; bool use_top; status_old = read_sr(nor); if (status_old < 0) return status_old; - /* If nothing in our range is unlocked, we don't need to do anything */ - if (stm_is_locked_sr(nor, ofs, len, status_old)) + ret = spi_nor_select_zone(nor, ofs, len, status_old, &use_top, 1); + if (!ret) return 0; - - /* If anything below us is unlocked, we can't use 'bottom' protection */ - if (!stm_is_locked_sr(nor, 0, ofs, status_old)) - can_be_bottom = false; - - /* If anything above us is unlocked, we can't use 'top' protection */ - if (!stm_is_locked_sr(nor, ofs + len, mtd->size - (ofs + len), - status_old)) - can_be_top = false; - - if (!can_be_bottom && !can_be_top) - return -EINVAL; - - /* Prefer top, if both are valid */ - use_top = can_be_top; + else if (ret < 0) + return ret; /* lock_len: length of region that should end up locked */ if (use_top) @@ -778,33 +897,19 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) struct mtd_info *mtd = &nor->mtd; int status_old, status_new; u8 mask = SR_BP2 | SR_BP1 | SR_BP0; - u8 shift = ffs(mask) - 1, pow, val; + u8 shift = ffs(mask) - 1, pow, val, ret; loff_t lock_len; - bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB; bool use_top; status_old = read_sr(nor); if (status_old < 0) return status_old; - /* If nothing in our range is locked, we don't need to do anything */ - if (stm_is_unlocked_sr(nor, ofs, len, status_old)) + ret = spi_nor_select_zone(nor, ofs, len, status_old, &use_top, 0); + if (!ret) return 0; - - /* If anything below us is locked, we can't use 'top' protection */ - if (!stm_is_unlocked_sr(nor, 0, ofs, status_old)) - can_be_top = false; - - /* If anything above us is locked, we can't use 'bottom' protection */ - if (!stm_is_unlocked_sr(nor, ofs + len, mtd->size - (ofs + len), - status_old)) - can_be_bottom = false; - - if (!can_be_bottom && !can_be_top) - return -EINVAL; - - /* Prefer top, if both are valid */ - use_top = can_be_top; + else if (ret < 0) + return ret; /* lock_len: length of region that should remain locked */ if (use_top) @@ -866,8 +971,9 @@ static int stm_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len) if (status < 0) return status; - return stm_is_locked_sr(nor, ofs, len, status); + return spi_nor_is_locked_sr(nor, ofs, len, status); } +#endif /* !CONFIG_SPI_FLASH_ISSI*/ #endif /* CONFIG_SPI_FLASH_STMICRO */ static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) @@ -1142,6 +1248,105 @@ static int macronix_quad_enable(struct spi_nor *nor) } #endif +/** + * issi_lock() - set BP[0123] write-protection. + * @nor: pointer to a 'struct spi_nor'. + * @ofs: offset from which to lock memory. + * @len: number of bytes to unlock. + * + * Lock a region of the flash.Implementation is based on stm_lock + * Supports the block protection bits BP{0,1,2,3} in status register + * + * Return: 0 on success, -errno otherwise. + */ +static int issi_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) +{ + int status_old, status_new, blk_prot; + u8 mask = SR_BP3 | SR_BP2 | SR_BP1 | SR_BP0; + u8 shift = ffs(mask) - 1; + u8 pow, ret; + bool use_top = false; + loff_t lock_len; + + status_old = read_sr(nor); + + /* if status reg is Write protected don't update bit protection */ + if (status_old & SR_SRWD) { + dev_err(nor->dev, + "SR is write protected, can't update BP bits...\n"); + return -EINVAL; + } + + ret = spi_nor_select_zone(nor, ofs, len, status_old, &use_top, 1); + if (!ret) + /* Older protected blocks include the new requested block's */ + return 0; + else if (ret < 0) + return ret; + + /* lock_len: length of region that should end up locked */ + if (use_top) + lock_len = nor->mtd.size - ofs; + else + lock_len = ofs + len; + + pow = order_base_2(lock_len); + blk_prot = mask & (((pow + 1) & 0xf) << shift); + if (lock_len <= 0) { + dev_err(nor->dev, "invalid Length to protect"); + return -EINVAL; + } + + status_new = status_old | blk_prot; + if (status_old == status_new) + return 0; + + return write_sr_and_check(nor, status_new, mask); +} + +/** + * issi_unlock() - clear BP[0123] write-protection. + * @nor: pointer to a 'struct spi_nor'. + * @ofs: offset from which to unlock memory. + * @len: number of bytes to unlock. + * + * Bits [2345] of the Status Register are BP[0123]. + * ISSI chips use a different block protection scheme than other chips. + * Just disable the write-protect unilaterally. + * + * Return: 0 on success, -errno otherwise. + */ +static int issi_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) +{ + int ret, val; + u8 mask = SR_BP0 | SR_BP1 | SR_BP2 | SR_BP3; + + val = read_sr(nor); + if (val < 0) + return val; + if (!(val & mask)) + return 0; + + write_enable(nor); + + write_sr(nor, val & ~mask); + + ret = spi_nor_wait_till_ready(nor); + if (ret) + return ret; + + ret = read_sr(nor); + if (!(ret & mask)) { + dev_info(nor->dev, "ISSI block protect bits cleared SR: 0x%x\n", + ret); + ret = 0; + } else { + dev_err(nor->dev, "ISSI block protect bits not cleared\n"); + ret = -EINVAL; + } + return ret; +} + #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) /* * Write status Register and configuration register with 2 bytes @@ -1649,6 +1854,28 @@ spi_nor_post_bfpt_fixups(struct spi_nor *nor, return 0; } +static int is25wp256_post_bfpt_fixups(struct spi_nor *nor, + const struct sfdp_parameter_header + *bfpt_header, + const struct sfdp_bfpt *bfpt, + struct spi_nor_flash_parameter *params) + +{ + /* IS25WP256 supports 4B opcodes, but the BFPT advertises a + * BFPT_DWORD1_ADDRESS_BYTES_3_ONLY address width. + * Overwrite the address width advertised by the BFPT. + */ + if ((bfpt->dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) == + BFPT_DWORD1_ADDRESS_BYTES_3_ONLY) + nor->addr_width = 4; + + return 0; +} + +struct spi_nor_fixups is25wp256_fixups = { + .post_bfpt = is25wp256_post_bfpt_fixups, +}; + /** * spi_nor_parse_bfpt() - read and parse the Basic Flash Parameter Table. * @nor: pointer to a 'struct spi_nor' @@ -2318,6 +2545,16 @@ int spi_nor_scan(struct spi_nor *nor) mtd->_erase = spi_nor_erase; mtd->_read = spi_nor_read; +#if defined(CONFIG_SPI_FLASH_ISSI) + /* NOR protection support for ISSI chips */ + if (JEDEC_MFR(info) == SNOR_MFR_ISSI && + info->flags & SPI_NOR_HAS_LOCK && + info->flags & SPI_NOR_HAS_BP3) { + nor->flash_lock = issi_lock; + nor->flash_unlock = issi_unlock; + } +#endif + #if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST) /* NOR protection support for STmicro/Micron chips and similar */ if (JEDEC_MFR(info) == SNOR_MFR_ST || @@ -2347,6 +2584,8 @@ int spi_nor_scan(struct spi_nor *nor) if (info->flags & USE_CLSR) nor->flags |= SNOR_F_USE_CLSR; + if (info->flags & SPI_NOR_HAS_BP3) + nor->flags |= SNOR_F_HAS_BP3; if (info->flags & SPI_NOR_NO_ERASE) mtd->flags |= MTD_NO_ERASE; @@ -2377,6 +2616,7 @@ int spi_nor_scan(struct spi_nor *nor) /* enable 4-byte addressing if the device exceeds 16MiB */ nor->addr_width = 4; if (JEDEC_MFR(info) == SNOR_MFR_SPANSION || + JEDEC_MFR(info) == SNOR_MFR_ISSI || info->flags & SPI_NOR_4B_OPCODES) spi_nor_set_4byte_opcodes(nor, info); #else diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c index a3920ba..0d97aa9 100644 --- a/drivers/mtd/spi/spi-nor-ids.c +++ b/drivers/mtd/spi/spi-nor-ids.c @@ -128,6 +128,11 @@ const struct flash_info spi_nor_ids[] = { SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { INFO("is25wp128", 0x9d7018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("is25wp256", 0x9d7019, 0, 64 * 1024, 512, + SECT_4K | SPI_NOR_4B_OPCODES | SPI_NOR_HAS_LOCK | + SPI_NOR_HAS_TB | SPI_NOR_HAS_BP3) + .fixups = &is25wp256_fixups + }, #endif #ifdef CONFIG_SPI_FLASH_MACRONIX /* MACRONIX */ /* Macronix */ diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 88e80af..2fe7812 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -26,6 +26,7 @@ #define SNOR_MFR_SPANSION CFI_MFR_AMD #define SNOR_MFR_SST CFI_MFR_SST #define SNOR_MFR_WINBOND 0xef /* Also used by some Spansion */ +#define SNOR_MFR_ISSI 0x9d /* * Note on opcode nomenclature: some opcodes have a format like @@ -39,6 +40,8 @@ #define SPINOR_OP_WREN 0x06 /* Write enable */ #define SPINOR_OP_RDSR 0x05 /* Read status register */ #define SPINOR_OP_WRSR 0x01 /* Write status register 1 byte */ +#define SPINOR_OP_RDFR 0x48 /* Read Function register */ +#define SPINOR_OP_WRFR 0x42 /* Write Function register 1 byte */ #define SPINOR_OP_RDSR2 0x3f /* Read status register 2 */ #define SPINOR_OP_WRSR2 0x3e /* Write status register 2 */ #define SPINOR_OP_READ 0x03 /* Read data bytes (low frequency) */ @@ -119,6 +122,7 @@ #define SR_BP0 BIT(2) /* Block protect 0 */ #define SR_BP1 BIT(3) /* Block protect 1 */ #define SR_BP2 BIT(4) /* Block protect 2 */ +#define SR_BP3 BIT(5) /* Block protect 3 */ #define SR_TB BIT(5) /* Top/Bottom protect */ #define SR_SRWD BIT(7) /* SR write protect */ /* Spansion/Cypress specific status bits */ @@ -130,6 +134,9 @@ /* Enhanced Volatile Configuration Register bits */ #define EVCR_QUAD_EN_MICRON BIT(7) /* Micron Quad I/O */ +/* Function register bit */ +#define FR_TB BIT(1) /*ISSI: Top/Bottom protect */ + /* Flag Status Register bits */ #define FSR_READY BIT(7) /* Device status, 0 = Busy, 1 = Ready */ #define FSR_E_ERR BIT(5) /* Erase operation status */ @@ -234,6 +241,7 @@ enum spi_nor_option_flags { SNOR_F_READY_XSR_RDY = BIT(4), SNOR_F_USE_CLSR = BIT(5), SNOR_F_BROKEN_RESET = BIT(6), + SNOR_F_HAS_BP3 = BIT(7), }; /** From patchwork Tue Aug 13 16:59:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sagar Shrikant Kadam X-Patchwork-Id: 1146523 X-Patchwork-Delegate: uboot@andestech.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=sifive.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=sifive.com header.i=@sifive.com header.b="ilYf16fA"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 467KXj5HsTz9sND for ; Wed, 14 Aug 2019 03:32:21 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 7A40FC22085; Tue, 13 Aug 2019 17:16:55 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id C73D3C22035; Tue, 13 Aug 2019 17:16:53 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 84830C2203F; Tue, 13 Aug 2019 16:59:56 +0000 (UTC) Received: from mail-pf1-f194.google.com (mail-pf1-f194.google.com [209.85.210.194]) by lists.denx.de (Postfix) with ESMTPS id BE504C21FBE for ; Tue, 13 Aug 2019 16:59:55 +0000 (UTC) Received: by mail-pf1-f194.google.com with SMTP id o70so6603922pfg.5 for ; Tue, 13 Aug 2019 09:59:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sifive.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=6v4YDTvfd/lT5W6pm2bIvqryFIbjz3oWna1WeAROCcY=; b=ilYf16fAiNNJgPup6Jt4S0TkbkqrB3IEqyvhhS6MLrQianVK3Uo7fJOdZ5/C4UveDl Xwz4ZJb27mMLaLJHfSBQxW4sO/34UavAHgWytI4duYRhUavnNS4ii5SqPaOCwfTsyl8J f/uWtDvmtfknWn4rsc+ki4OqrABuidBxMgYqAogRrkhc+xGqRusPEoN0gFJ7nnFFOWk2 fzwbVbGlYv2blVLyfBGu4Pyye6fk5E6XmE7u6kVJdoI/Z7XORu+79BodFOsw1l9a77JI 8zeXYu99hs+uPPgqJDGdTFmfFr5ndT+wopIX/RXncNR5ri1sgapqlroHQj5rZ4YYYCK3 FFxQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=6v4YDTvfd/lT5W6pm2bIvqryFIbjz3oWna1WeAROCcY=; b=gnadt5Uww13eZU2FoTOdg402hQ10eGgtqhNkzZDJU77Jt0/udGYIMOsEtbfhTfTTqw 7IkzdyAezxRtMAFQCOwLCNx5AI4a54KDEVJqbZq+HeU5NkEag9riWreF4bkasppkxbxE rbWKkufTehHqKgH4XJKX4Xjfr6ISBnu8qSOLZOzWAz429yi2STh7F3N0vgs7wY59oKpT 0Ju70/p+FdNOzoYuOvEH78N71Dmwp2/9LGuAr8DJvvtkLTE/+DWg9keyAxLujLRAQrpS ejU/asmNj+ZZaRYCJ7DN1ZAlhfS9WBRcP8ov2EPWbfcIv+r87R1oB8MjWrNK0Yzl3o00 jzoQ== X-Gm-Message-State: APjAAAWV1F7lHvMp6b4ivx9wPX9QALNxUrFnTLE08JWgbobTCnsQuJcZ K19S1Mny9ZnxXR16+JzcorNpnPVDttOdWw== X-Google-Smtp-Source: APXvYqzKKf+qUw6vRDfTbi04VXBiQJjH5wKLrcEecdDzb0YOc9Brv/v9RzFKvUnr5eadE2WombVVgA== X-Received: by 2002:a63:2b84:: with SMTP id r126mr36275436pgr.308.1565715594145; Tue, 13 Aug 2019 09:59:54 -0700 (PDT) Received: from gamma07.internal.sifive.com ([64.62.193.194]) by smtp.googlemail.com with ESMTPSA id w11sm6040857pfi.105.2019.08.13.09.59.53 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 13 Aug 2019 09:59:53 -0700 (PDT) From: Sagar Shrikant Kadam To: u-boot@lists.denx.de, paul.walmsley@sifive.com, palmer@sifive.com, anup.patel@wdc.com, atish.patra@wdc.com, jagan@amarulasolutions.com, vigneshr@ti.com Date: Tue, 13 Aug 2019 09:59:31 -0700 Message-Id: <1565715571-26558-4-git-send-email-sagar.kadam@sifive.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1565715571-26558-1-git-send-email-sagar.kadam@sifive.com> References: <1565715571-26558-1-git-send-email-sagar.kadam@sifive.com> Subject: [U-Boot] [U-BOOT PATCH 3/3] spi: riscv: use single bit mode for spi transfers X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 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" Use the SPI controller in FU540-C000 soc in one bit mode, rather than using spi-tx-bus-width and spi-rx-bus-width passed from the device tree. This patch handles a case where controller mode in format register (0x40) is configured as per the width specified in the dt-node of the slave device. For instance if spi-tx-bus-width and spi-rx-bus-width in the flash device node in dt is set to 4 bit mode, the controller gets configured in QUAD mode, whereas the spi nor scan tries to read the JEDEC ID with the reg_proto set to SNOR_PROTO_1_1_1 and fails. Signed-off-by: Sagar Shrikant Kadam --- drivers/spi/spi-sifive.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/spi/spi-sifive.c b/drivers/spi/spi-sifive.c index 969bd4b..7cf3ea4 100644 --- a/drivers/spi/spi-sifive.c +++ b/drivers/spi/spi-sifive.c @@ -146,12 +146,7 @@ static void sifive_spi_prep_transfer(struct sifive_spi *spi, /* Number of wires ? */ cr &= ~SIFIVE_SPI_FMT_PROTO_MASK; - if ((slave->mode & SPI_TX_QUAD) || (slave->mode & SPI_RX_QUAD)) - cr |= SIFIVE_SPI_FMT_PROTO_QUAD; - else if ((slave->mode & SPI_TX_DUAL) || (slave->mode & SPI_RX_DUAL)) - cr |= SIFIVE_SPI_FMT_PROTO_DUAL; - else - cr |= SIFIVE_SPI_FMT_PROTO_SINGLE; + cr |= SIFIVE_SPI_FMT_PROTO_SINGLE; /* SPI direction in/out ? */ cr &= ~SIFIVE_SPI_FMT_DIR;