From patchwork Tue Oct 20 13:03:28 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fabio Estevam X-Patchwork-Id: 532954 X-Patchwork-Delegate: jagannadh.teki@gmail.com 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 5BA281401F0 for ; Wed, 21 Oct 2015 00:04:05 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id D8AF14B668; Tue, 20 Oct 2015 15:04:01 +0200 (CEST) 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 jpVlT-0hXCCL; Tue, 20 Oct 2015 15:04:01 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id BF3D14B660; Tue, 20 Oct 2015 15:03:57 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 994914B62B for ; Tue, 20 Oct 2015 15:03:52 +0200 (CEST) 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 PYFMZHYGpZdu for ; Tue, 20 Oct 2015 15:03:52 +0200 (CEST) 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 na01-bl2-obe.outbound.protection.outlook.com (mail-bl2on0119.outbound.protection.outlook.com [65.55.169.119]) by theia.denx.de (Postfix) with ESMTPS id 0ED6D4B62A for ; Tue, 20 Oct 2015 15:03:46 +0200 (CEST) Received: from BLUPR0301CA0004.namprd03.prod.outlook.com (10.162.113.142) by BLUPR03MB1458.namprd03.prod.outlook.com (10.163.81.155) with Microsoft SMTP Server (TLS) id 15.1.300.14; Tue, 20 Oct 2015 13:03:44 +0000 Received: from BN1BFFO11FD003.protection.gbl (2a01:111:f400:7c10::1:197) by BLUPR0301CA0004.outlook.office365.com (2a01:111:e400:5259::14) with Microsoft SMTP Server (TLS) id 15.1.300.14 via Frontend Transport; Tue, 20 Oct 2015 13:03:44 +0000 Authentication-Results: spf=fail (sender IP is 192.88.168.50) smtp.mailfrom=freescale.com; freescale.mail.onmicrosoft.com; dkim=none (message not signed) header.d=none; freescale.mail.onmicrosoft.com; dmarc=none action=none header.from=freescale.com; Received-SPF: Fail (protection.outlook.com: domain of freescale.com does not designate 192.88.168.50 as permitted sender) receiver=protection.outlook.com; client-ip=192.88.168.50; helo=tx30smr01.am.freescale.net; Received: from tx30smr01.am.freescale.net (192.88.168.50) by BN1BFFO11FD003.mail.protection.outlook.com (10.58.144.66) with Microsoft SMTP Server (TLS) id 15.1.300.4 via Frontend Transport; Tue, 20 Oct 2015 13:03:43 +0000 Received: from fabio-Latitude-E6410.am.freescale.net (fabio-Latitude-E6410.am.freescale.net [10.29.244.34]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id t9KD3cxR020034; Tue, 20 Oct 2015 06:03:42 -0700 From: Fabio Estevam To: Date: Tue, 20 Oct 2015 11:03:28 -0200 Message-ID: <1445346209-12210-3-git-send-email-fabio.estevam@freescale.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1445346209-12210-1-git-send-email-fabio.estevam@freescale.com> References: <1445346209-12210-1-git-send-email-fabio.estevam@freescale.com> X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1; BN1BFFO11FD003; 1:XJidbZbgkCiF8o/rpHpg2yTkK3nZksPDMbDfjbk+IJYWvRpv/cekyCP18KXiuLQiAYI9hKewPUbNgKgTRZ5cIjF1xuWq38TcyT0LkIlpQ6fotAYvhPORU7rCuxpZjqi+bYMHl8EfveDU+rjVuddfsmOHHj0dwpSSQw2SYzc9F4yCFgJQ8NAjaOaT46ryBAjvvJqRLuBvCWtsr4e1LuNTOmbv+TVHRETNn4BtjEz9aofu5IpdO0FlRm+KBbolvMMnAFlPQgho0hNdccdEvxDEqNZO7HrIPw5sFfqWEwSWd6rgez6HA+w1d+3RnLJhjUAThdjEc+XIN13Ua842djEijd2veHicjOCEKTsbLEwOkKxD8vwOLOKZJvhhixK5nltXMtLPARSoHfPR23wRMj8Drg== X-Forefront-Antispam-Report: CIP:192.88.168.50; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10019020)(6009001)(2980300002)(1110001)(1109001)(339900001)(199003)(189002)(106466001)(105606002)(5001960100002)(50226001)(36756003)(575784001)(85426001)(5007970100001)(107886002)(189998001)(110136002)(5003940100001)(2351001)(229853001)(5008740100001)(46102003)(87936001)(33646002)(6806005)(19580405001)(50986999)(47776003)(11100500001)(76176999)(77096005)(48376002)(64706001)(2950100001)(86362001)(50466002)(15975445007)(19580395003)(97736004)(104016004)(5001920100001)(92566002)(81156007)(4001430100001); DIR:OUT; SFP:1102; SCL:1; SRVR:BLUPR03MB1458; H:tx30smr01.am.freescale.net; FPR:; SPF:Fail; PTR:InfoDomainNonexistent; A:1; MX:1; LANG:en; MIME-Version: 1.0 X-Microsoft-Exchange-Diagnostics: 1; BLUPR03MB1458; 2:wfyHuB9e7c/KTcOkvAZ59DxWdGj8a0Fv2lcV39pj8dX+GJKUrIb7467SleB1408q3FB9vhkL8X0CvBddJTPjlaioUeM3T8qc0R9dk1LsfiNF6LCtH7/E5R2EVrg8Y0kyk+JpRN/8k/5fCzRHZvRZogKAbojYVnGUdhape7+Hlk8=; 3:V7sv+fMJGrtyiy1DLtYE1BaggZdUvT2gkrYyhm22HR7RyksdXMzYnQUUyBUmLXSCPiCRQ0z4bFSNLLEopbJKh1hacPNXZnjBQVwn/qy+RWxi/b0XMVDPKzGffjdROpJRmmIpE54bnp2gaqW5dUyTtkv4b5poMiuNS7tZ+GM8ROw2Y21W4VTCs+P5mRAADEmc0Pku++g9utuSdkbTA1vtOhHsLk7VgYXu1/YrCiQ+N40=; 25:AYuYvPERhw4WxphgCiTKfimCguqw0J3dPH63zp7Y7Wy3HQq6jYubf8UM9KmTdErvhWPsOmYMH8pf/oDzc+JvudqL1AJluxVapTWrEf+jkb7Bn1r5oaCss1BhpdL7FVuFp7r8b52fHz4YM/rqJkdNNe+mVHDizbzX9doJFuHPxl9IIHzPyr3JRPJBBvDVAk+i2hZ3rFAtL1OhL4vXj+tmy2q0pcy4pkzxvqedAtfi+oLA5pl0ARibdOMIct1G+VHwT/Jrdj8zXRqP/LeesAyKGA== X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BLUPR03MB1458; X-Microsoft-Exchange-Diagnostics: 1; BLUPR03MB1458; 20:09jchEj7hq4rNBuU9d6+dYdLUB1ZBUv8KfeyBh1sS55YZpMLEz1V/cOi6Iq5zOml03VGepRTzk+jvb64H15fK7OC6xVHK3jNn2dyYcz5d66gxZpXkkYIpzc8k8CYw/BZ8wARa7S5zWftAdJ+LI9Gi4vZfqKes6F+dmRcDfXQq3Y/icicybzSJ4jnD2T++vjaKaru2z9bEL9B5FE+0xLP4NGWGrm76ExjJVtvamWRcVZ8RIsCxaOX3TXDX7UmL8UDw2JP+5Dr/oJUo8rciftTy7FnUe8oNXRjOEwDGq0vFVtB+O2I42meduN1FmmjgRsSv9BtM5q0B46EyfSi492f2WujTJjtguln0/YWcZkz7Mk=; 4:h67c713x7aLa5mYZsUeRgsm/c7TjEqZna3niPvozo5LOovhRbhy7mC15RJycPB+uzagJ9ST09GbnhSEIfEBEgQuTawhzpAQs0M7LG2eVq1aB0/KCK0QneNArIIss61y/fmmofDaQ028NSJ8Lkn2SymDaHAmkoQr4hEMSyNLntGB4p8S8xNVe4B4Q+ZSwjR5wwFEToj7f9lBq8L6YVkRyrm16ZtR+csXz01mUZcxQB8CCrQBi0fiF6YZwOQ9pV3125n5V7P+WIX3BW0GOSHuXe9knCya7AmgmmXxBN2avjmBDNshmaO7FBZz4UHs0RJJmMniIwJNFxqoq8UtLPQHGd+qVE38WJzYFwzuCksLklZo= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(101931422205132); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(2401047)(8121501046)(520078)(5005006)(3002001); SRVR:BLUPR03MB1458; BCL:0; PCL:0; RULEID:; SRVR:BLUPR03MB1458; X-Forefront-PRVS: 073515755F X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BLUPR03MB1458; 23:aYmOGISgLIJGuv7IcIDPJONk3TnHFQedsUusVwhxw?= =?us-ascii?Q?IBQv02lzV/JgWsSNz2j58MUXccLljRQGnT1A5gwq9W/KCLOfOapa6YSCInVy?= =?us-ascii?Q?//8wYRvt+FcAB3/zsJeoR/iELWpky1Cnep+SufZoutNArxih6gYw6TM7GUeu?= =?us-ascii?Q?7VuTY8Aadvcieuf3xXMGUKRkBKecD1VuCYWhREit5DlzcbwPTwJ5xUmJfADx?= =?us-ascii?Q?V67xVrkmF0e5J23U5P8gJzGtG/GRpPzpcaVTb+nC0Chm3F5ATEswiIkgF73d?= =?us-ascii?Q?ybnC08G3Z25aBA/s2eGqKeA5GUC1nMfNgTVNXNmm+KqbeghJPzHi93U67B7r?= =?us-ascii?Q?YFq6aeLqFvpRrNnYdN03Ex5hZfyJ4L4cgx47F/urtbrmhUCqeb2Seq6NHUmL?= =?us-ascii?Q?aq6JhIyp1GUoo0cuuv4TKb9+Jr0a5KmhgRlDyTjfZLDP0C/0boYszxZSzP6k?= =?us-ascii?Q?jzq3g4vpYNa4YzvFspFG6FfhI7es4I0JBen4pJENdcKQJq16aBm3+rrtMPM9?= =?us-ascii?Q?XRwcblnL5lW6YQUcMMg35qRyYTqs1hoHrlkc9cKFS3ocXG+1uZ1fFkvjbFbH?= =?us-ascii?Q?FFvdoQZp1WLs9HnjRy/zxPkupYEIgSXcmQK5D0NGHrlFm7GQ9Kp1p1MxP6wn?= =?us-ascii?Q?2jOlkRcBUgCoNl9AxG4jpfTReur3am+6wrgYnx42FKc4IzXpKaOHw1ZrWAnK?= =?us-ascii?Q?/OMnNOTiR11hnBPHSylb7x58Uc56TWDRszP1Hy6L/e0aY0CGxgwWJeDHJMVU?= =?us-ascii?Q?vpAZHOoB+FO1aWRHMpvYnEUmavrKVb3NefHiJ3MOsnx9lPw7XStbYArC8m3O?= =?us-ascii?Q?4u9VP6UHriE5aKOxiHKBaeo+gqVg/Ltj+tVlksMTuvHBn+l3TzbvfEYO5wOa?= =?us-ascii?Q?9Dn/pPlNixEu3k7ACM8PIdidPdVgbHQPoDNT9Ed0GDuo0D6RWrn4v0GVsBxl?= =?us-ascii?Q?D17A6owLbja4GEpf/UmNmcg03eKwtF9oCuBrFaG6X+NLwkGvRanbeAqdySEA?= =?us-ascii?Q?jPFYVwR4onH11i/4JMvJNGyVB3spu/ecdeuSsMjb9Wfies01oQILhPz7sqtc?= =?us-ascii?Q?aksxvIE8t6ng++Is4EmmLaN85r026bz2saVWUZMBUdgj9b/FdYlM3q9wm+75?= =?us-ascii?Q?fdl45yhH5Q5/tQjmc8JCjPUMBcHObSENJIMJW3I6AR2OfaKU3rAL6mFHzv5N?= =?us-ascii?Q?v+n9Jy0390O0b1lwbQ3z7UlNnWiMdMdT9G/?= X-Microsoft-Exchange-Diagnostics: 1; BLUPR03MB1458; 5:+sDwWB0Lag/dQ8GnzURMEIvafKPUXKKcJWw8fkV5gG5ukM5SrFZizojc3LWCX/aWlDT0Pt8LeRZbnWQu3rMImxZGVhIWhi8OhrcaEsWexEKxk76MU4OVSAqMBnud/NSlrzuiVXo3pqjvLPkZKJ+QiA==; 24:O+iNr53qLY1uCCUK+ke3+ADZ0vrf8FZYV3lpYPGhdREzy5kSCu9Z5xbwlfb7ZgS2GFn7/KIjqdeBpTpXsM717ItjfwtqjwbthhOc7Wer+Ys=; 20:i2wQeNjlqKIw5pa6E+awVkMSHw7TZhiyPNzrHDTqe9bfwuTmDKzibKxcs5lDPj1GN91RrI6HF00+ZuOYcehCEQ== X-OriginatorOrg: freescale.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Oct 2015 13:03:43.9500 (UTC) X-MS-Exchange-CrossTenant-Id: 710a03f5-10f6-4d38-9ff4-a80b81da590d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=710a03f5-10f6-4d38-9ff4-a80b81da590d; Ip=[192.88.168.50]; Helo=[tx30smr01.am.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BLUPR03MB1458 Cc: Fabio Estevam , u-boot@lists.denx.de, yorksun@freescale.com, otavio@ossystems.com.br, trini@konsulko.com Subject: [U-Boot] [PATCH v9 3/4] spi: sf_ops: Add SPI protection mechanism from the kernel 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: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Add the SPI NOR protection mechanism from the kernel. This code is based on the work from Brian Norris https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/commit/drivers/mtd/spi-nor/spi-nor.c?id=62593cf40b23b523b9fc9334ca61ba6c595ebb09 Signed-off-by: Fabio Estevam --- Changes since v8: - None drivers/mtd/spi/sf_ops.c | 170 +++++++++++++++++++++++++++++++++++++++++++++++ include/spi_flash.h | 4 ++ 2 files changed, 174 insertions(+) diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index 900ec1f..928f9c1 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "sf_internal.h" @@ -573,3 +574,172 @@ int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len, return ret; } #endif + +#ifdef CONFIG_SPI_FLASH_STMICRO +static void stm_get_locked_range(struct spi_flash *flash, u8 sr, loff_t *ofs, + u32 *len) +{ + u8 mask = SR_BP2 | SR_BP1 | SR_BP0; + int shift = ffs(mask) - 1; + int pow; + + if (!(sr & mask)) { + /* No protection */ + *ofs = 0; + *len = 0; + } else { + pow = ((sr & mask) ^ mask) >> shift; + *len = flash->size >> pow; + *ofs = flash->size - *len; + } +} + +/* + * Return 1 if the entire region is locked, 0 otherwise + */ +static int stm_is_locked_sr(struct spi_flash *flash, loff_t ofs, u32 len, + u8 sr) +{ + loff_t lock_offs; + u32 lock_len; + + stm_get_locked_range(flash, sr, &lock_offs, &lock_len); + + return (ofs + len <= lock_offs + lock_len) && (ofs >= lock_offs); +} + +/* + * Check if a region of the flash is (completely) locked. See stm_lock() for + * more info. + * + * Returns 1 if entire region is locked, 0 if any portion is unlocked, and + * negative on errors. + */ +int stm_is_locked(struct spi_flash *flash, loff_t ofs, u32 len) +{ + int status; + u8 sr; + + status = spi_flash_cmd_read_status(flash, &sr); + if (status < 0) + return status; + + return stm_is_locked_sr(flash, ofs, len, sr); +} + +/* + * Lock a region of the flash. Compatible with ST Micro and similar flash. + * Supports only the block protection bits BP{0,1,2} in the status register + * (SR). Does not support these features found in newer SR bitfields: + * - TB: top/bottom protect - only handle TB=0 (top protect) + * - SEC: sector/block protect - only handle SEC=0 (block protect) + * - CMP: complement protect - only support CMP=0 (range is not complemented) + * + * Sample table portion for 8MB flash (Winbond w25q64fw): + * + * SEC | TB | BP2 | BP1 | BP0 | Prot Length | Protected Portion + * -------------------------------------------------------------------------- + * X | X | 0 | 0 | 0 | NONE | NONE + * 0 | 0 | 0 | 0 | 1 | 128 KB | Upper 1/64 + * 0 | 0 | 0 | 1 | 0 | 256 KB | Upper 1/32 + * 0 | 0 | 0 | 1 | 1 | 512 KB | Upper 1/16 + * 0 | 0 | 1 | 0 | 0 | 1 MB | Upper 1/8 + * 0 | 0 | 1 | 0 | 1 | 2 MB | Upper 1/4 + * 0 | 0 | 1 | 1 | 0 | 4 MB | Upper 1/2 + * X | X | 1 | 1 | 1 | 8 MB | ALL + * + * Returns negative on errors, 0 on success. + */ +int stm_lock(struct spi_flash *flash, u32 ofs, u32 len) +{ + u8 status_old, status_new; + u8 mask = SR_BP2 | SR_BP1 | SR_BP0; + u8 shift = ffs(mask) - 1, pow, val; + + spi_flash_cmd_read_status(flash, &status_old); + + /* SPI NOR always locks to the end */ + if (ofs + len != flash->size) { + /* Does combined region extend to end? */ + if (!stm_is_locked_sr(flash, ofs + len, flash->size - ofs - len, + status_old)) + return -EINVAL; + len = flash->size - ofs; + } + + /* + * Need smallest pow such that: + * + * 1 / (2^pow) <= (len / size) + * + * so (assuming power-of-2 size) we do: + * + * pow = ceil(log2(size / len)) = log2(size) - floor(log2(len)) + */ + pow = ilog2(flash->size) - ilog2(len); + val = mask - (pow << shift); + if (val & ~mask) + return -EINVAL; + + /* Don't "lock" with no region! */ + if (!(val & mask)) + return -EINVAL; + + status_new = (status_old & ~mask) | val; + + /* Only modify protection if it will not unlock other areas */ + if ((status_new & mask) <= (status_old & mask)) + return -EINVAL; + + spi_flash_cmd_write_status(flash, status_new); + + return 0; +} + +/* + * Unlock a region of the flash. See stm_lock() for more info + * + * Returns negative on errors, 0 on success. + */ +int stm_unlock(struct spi_flash *flash, u32 ofs, u32 len) +{ + uint8_t status_old, status_new; + u8 mask = SR_BP2 | SR_BP1 | SR_BP0; + u8 shift = ffs(mask) - 1, pow, val; + + spi_flash_cmd_read_status(flash, &status_old); + + /* Cannot unlock; would unlock larger region than requested */ + if (stm_is_locked_sr(flash, status_old, ofs - flash->erase_size, + flash->erase_size)) + return -EINVAL; + /* + * Need largest pow such that: + * + * 1 / (2^pow) >= (len / size) + * + * so (assuming power-of-2 size) we do: + * + * pow = floor(log2(size / len)) = log2(size) - ceil(log2(len)) + */ + pow = ilog2(flash->size) - order_base_2(flash->size - (ofs + len)); + if (ofs + len == flash->size) { + val = 0; /* fully unlocked */ + } else { + val = mask - (pow << shift); + /* Some power-of-two sizes are not supported */ + if (val & ~mask) + return -EINVAL; + } + + status_new = (status_old & ~mask) | val; + + /* Only modify protection if it will not lock other areas */ + if ((status_new & mask) >= (status_old & mask)) + return -EINVAL; + + spi_flash_cmd_write_status(flash, status_new); + + return 0; +} +#endif /* CONFIG_SPI_FLASH_STMICRO */ diff --git a/include/spi_flash.h b/include/spi_flash.h index 3b2d555..73b2b0a 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -31,6 +31,10 @@ # define CONFIG_SF_DEFAULT_BUS 0 #endif +#define SR_BP0 BIT(2) /* Block protect 0 */ +#define SR_BP1 BIT(3) /* Block protect 1 */ +#define SR_BP2 BIT(4) /* Block protect 2 */ + struct spi_slave; /**