From patchwork Wed Dec 20 10:32:52 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Prabhakar Kushwaha X-Patchwork-Id: 851360 X-Patchwork-Delegate: jagannadh.teki@gmail.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=) Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3z1rjq6y6Hz9s74 for ; Wed, 20 Dec 2017 21:34:23 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 98C9CC21DD9; Wed, 20 Dec 2017 10:34:00 +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=BAD_ENC_HEADER, RCVD_IN_DNSWL_BLOCKED, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS 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 4C2D6C220FD; Wed, 20 Dec 2017 10:33:53 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 1B980C220C8; Wed, 20 Dec 2017 10:33:44 +0000 (UTC) Received: from NAM03-CO1-obe.outbound.protection.outlook.com (mail-co1nam03on0062.outbound.protection.outlook.com [104.47.40.62]) by lists.denx.de (Postfix) with ESMTPS id 2F45EC21F09 for ; Wed, 20 Dec 2017 10:33:40 +0000 (UTC) Received: from CY1PR03CA0008.namprd03.prod.outlook.com (10.174.128.18) by BN3PR03MB2356.namprd03.prod.outlook.com (10.166.74.151) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.323.15; Wed, 20 Dec 2017 10:33:37 +0000 Received: from BY2FFO11FD016.protection.gbl (2a01:111:f400:7c0c::147) by CY1PR03CA0008.outlook.office365.com (2603:10b6:600::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.345.14 via Frontend Transport; Wed, 20 Dec 2017 10:33:37 +0000 Authentication-Results: spf=temperror (sender IP is 192.88.168.50) smtp.mailfrom=nxp.com; nxp.com; dkim=none (message not signed) header.d=none; nxp.com; dmarc=temperror action=none header.from=nxp.com; Received-SPF: TempError (protection.outlook.com: error in processing during lookup of nxp.com: DNS Timeout) Received: from tx30smr01.am.freescale.net (192.88.168.50) by BY2FFO11FD016.mail.protection.outlook.com (10.1.14.148) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.20.302.6 via Frontend Transport; Wed, 20 Dec 2017 10:33:22 +0000 Received: from VirtualBox.ap.freescale.net ([10.232.40.41]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id vBKAXQ7d030746; Wed, 20 Dec 2017 03:33:32 -0700 From: Prabhakar Kushwaha To: Date: Wed, 20 Dec 2017 16:02:52 +0530 Message-ID: <1513765974-4690-2-git-send-email-prabhakar.kushwaha@nxp.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1513765974-4690-1-git-send-email-prabhakar.kushwaha@nxp.com> References: <1513765974-4690-1-git-send-email-prabhakar.kushwaha@nxp.com> X-EOPAttributedMessage: 0 X-Matching-Connectors: 131582396030580831; (91ab9b29-cfa4-454e-5278-08d120cd25b8); () X-Forefront-Antispam-Report: CIP:192.88.168.50; IPV:NLI; CTRY:US; EFV:NLI; SFV:NSPM; SFS:(10009020)(7966004)(336005)(39860400002)(376002)(396003)(346002)(39380400002)(2980300002)(377424004)(189003)(199004)(6666003)(36756003)(2351001)(230783001)(106466001)(105606002)(305945005)(316002)(39060400002)(16586007)(86362001)(104016004)(50466002)(2906002)(356003)(4326008)(48376002)(53936002)(81156014)(59450400001)(77096006)(51416003)(54906003)(8676002)(76176011)(498600001)(50226002)(47776003)(6916009)(2950100002)(81166006)(8936002)(8656006)(97736004)(5660300001); DIR:OUT; SFP:1101; SCL:1; SRVR:BN3PR03MB2356; H:tx30smr01.am.freescale.net; FPR:; SPF:TempError; PTR:ErrorRetry; MX:1; A:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; BY2FFO11FD016; 1:ptLchcOyJunyrtF36LWgZRsV6Uqt9hlBaMJa7ZGrBv17vUhyDS6VHIDj6kgLduXan1CciB6sFl2d7pFgqayB9nnpLUISkjzvGcIEiRN3oHGwsjTkGBTadxOP97RpLxyM MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 89639b54-74e1-4913-f85f-08d54795188f X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(5600026)(4604075)(4534020)(4628075)(201703131517081)(2017052603307); SRVR:BN3PR03MB2356; X-Microsoft-Exchange-Diagnostics: 1; BN3PR03MB2356; 3:MDXLKMXVcMx0tnabApQzTsHG7gynflOOxoSCY5fCcKhhxtXRO+cYRySSt/rGc5kKC4qL782qPyNgUHok19LpJIfcz8uKAtjR/JrMPMdA4x+yvbXXeoh7HTTCDU0DCfW5MDH9dt/g4uMrYXoJSumcD3XBreHap1wolGFR0nnppfupd+u57RFuk3DgTj4/dXWnmAjcFPAp6VNsdxbm3ns0+BqM3M5gqNQrBT9BgPXa7N8YdO9TOwLUQ3kodIQe29AKk0EIVH/1WXF5rHkA9JB95B+C02e5alx8cDnpTvTvlgiwgNww8J0b9uezEXAbg33hrYrm9zO3wn88Gr0bx2QAMN9SIFPsJ8HGb1fzt6mS0n0=; 25:tBfWq0X2pjSd+Y2a0YaJ5mYRROAsvd/g+vNZ9KJuRymBEQlRQyx1NtrijUrE+aCWjGb8kGN+FjpHfTdLqbwVrb5QtOVAY4uQ8apJNtZqgv5qVrzvwruI9CIOx9hu8MN9yYtOGOYFxozMeMYtXBGvlOfmLCi3DPLwVUMBxOA11dW4bclGIOJikdDZnkB5RKRPBIxA4b5EeySFGqS2PHqslxHnoh78w0GyVZw9lu2jjAr9sbAqpDw3qSBOY7WflkaApNBj+MvnxDpj4vBjnJIOwvm6LJRWx/fzkBEGulhHiw9Eucn8xOmyXnNg8pL1RIKh7YQroK8nMYbjBPxwCyj6Y+j3nvZYwt+IwT8vno/7Avs= X-MS-TrafficTypeDiagnostic: BN3PR03MB2356: X-Microsoft-Exchange-Diagnostics: 1; BN3PR03MB2356; 31:izVtR/VNNa8JIfjkKvvIeYYb6EqJgQLL9VU2q1Yg0uFE2Dee5GDzCGE8+KrK/UHel3/CIXRPQm4ZTCo61jy3z08ol5wenU52GOCVSKs54UWeaKIGsb6gOw7l625SquGusEyYWQNTYAh+e5ku/ratYo814G6UIynVX8axe6bpXU++vPHCBIN9EtB85R2jFysVR9IeBsH8Wb2c5XWH2mz8YEmQljDl2Agr4bM18DkpKIQ=; 4:ogOyg6fdGDA0vyB5ohMAfWLh3Ll8GKBC3czdwCMwl3rlbUmtr9Sgv3G6UtXwcxBSQOr8jP81uWOQ6zR0TE+7iEumthH9cXGIVmeS/yVpxupxt4CHFrQJ2sWUZsjHtb335iZhWbLATYEzgb5InOWRo4dagkZj3l/YUdkLMzIqx+gVRNsb3opx3abDMqLsw6UgxA0ZqeKrJ8wkgZM9aYeg53ZLleGy5d8ZjAFzb7S28jSP3T/BAQTEpndnmkmKYqepESC0RhkO4yzBG7ZflpHEj3Y6p7KFfdImaIuiGXRlclXZqwTgndBG9yAmbKh/tDR9 X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(185117386973197); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6095135)(2401047)(8121501046)(5005006)(3002001)(10201501046)(3231023)(93006095)(93001095)(6055026)(6096035)(20161123556025)(20161123563025)(201703131430075)(201703131433075)(201703131441075)(201703131448075)(201703161259150)(20161123561025)(20161123559100)(20161123565025)(201708071742011); SRVR:BN3PR03MB2356; BCL:0; PCL:0; RULEID:(100000803101)(100110400095)(400006); SRVR:BN3PR03MB2356; X-Forefront-PRVS: 0527DFA348 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BN3PR03MB2356; 23:l+uOst+bFoRb0/euHw+kKJ+lCo6+QxrJtTyKA+p4l?= Py4VewpgAn0DRNsz/OUEuEQG0p67KOr1VYj1Y57YrUnUf/O8O5L6q+uFfHVtFDSdqB83Y0f4fNMs2JtdcwrXrguQF3CGOf5zSjNKYdSQ7+Cjs5bMlj73eB3/S/apLFz72cEw6XS541Ukevoq6ugWhPycQtq3alMAnjngGuZqdmky+SnTg7iZDPxWCbibwNtcEdyNK8FUQv17/Pabrs9jpVkhdaZfqb4PthqSmUGWfUS6DWcOKeWTPNHyHNvAHGcWTguFPFPGjH1MQlYXMcdbWpSIQOhiEkFfiEuYl7hAAZ2+HIepCM82BmPBYzNL4dNk6t9yWZdhr/5/dCHyvV9GH/ljqhIKPcOBBgVgjtDC+lYkQN1liNVCd4C4nPynp42DNWF23XGx5dGPqcPd7tleB77M7r+plTL1p5grEz9REPGbU5npoDm2tRdtqX+bZtv/BMCNlwtK582y8UHAdSGMVVSaQVOHKDhI5RCnWMVkYc+3jVIfFkF+myNTwmeQduz2vXEsPAlKQMa4b6JxJNnAQVKvxMlwbbPTBwEKlUoJ8Rvo8QKUYPTv+cKu0dPync2AaFjH5W/rc0e76pFvuUVAF8qJcUFY+MW/lVJ77+X8gZuNb9KDYpw3a10g+c6/Ksn1b5Oz1YBejs8DDAtHMTJu/qYX5/ctZLFVjqMi13HtxT8y36/3/b2RY5CDTA4CEAOZ9V6Uw9WW3bhRKT3ti2fY0w2CojSu1GQwsm/cS98M5UphaJzopnHkdK50ajZMcd/Vu+rZHQKTKIt2njGscUWqRz2v5KO6eXxNWCunRgIrxkUU9M7iqC78JrvTXh5Xe9Vga1qcDPpobdlLm3JWM1T7zk9IKVCIuSFgiycAGD6fnoG6wp/kB96Xg175IAeCqvw3JS/9fBNqZ3NuoRwta3Sf7Pxe2QQboUvBhVr9RN5azaZ/Ny2jlnKNbkrQ8ep3rQFwHu2mCUS9VkFIXAegTGOHQQw5XI4tFP5Bx4BfVLi0nDEFOCxOl9LzL7kz3tiC7ak/X3uyLEVfwx0GdWtJdl5LsJk+vEtB8hc17odbzNgYoRZ7Q== X-Microsoft-Exchange-Diagnostics: 1; BN3PR03MB2356; 6:/G9ZWnyKMKQ68OOdex/OYx3kelAreqIz0bJbWmsvUv8p8rp+OSr4tL6hZibUm6nR2BV8dOmjK0t4d9YJ9co+pA3TLTA41egLYTDRBB/RMIo4dB1okdOj9l8abWeBRdYHIWlIdv4zSLaYMBsRwNjSJevfHFyJhsww2eeBNHaRebh9TjdkgnV+iFDllyBtyvZZQsGE2A4CWF/XsjZsR3IcNd3ojP6zBK37Hh36lFxZ4+s0HTQyQXG0fx6zuyWOTiXpjXFeKEczSN8Dt0UtGeH2lzgu/1Go1BltYw128GKo4HSj8Gh6gUDGP5Rwb6u4XXT1QbM+b3gFdXlBbyghBupsp5zBZuz2Si1TrRyr2t1Er7s=; 5:yUvEmT+7BoqgsVM1ruzDkF8veA5QiJafnU4IBTdxKxcghPZEEjRhmBdgeFqnUogCXWHYFhrLta2E4Ej5NnpjKNucirh9zbQdpLWAtE4B7sfbcjFItZY5xSp+NSWJeZMQRdIpI80HMYeXJ0zw0HVZ3KPrGkx18mMNikMv1TO6xAg=; 24:+nSegzH19g4p2xqFNrfNER/TmawvBrvtAv4x/xgKh0Q4S0/XB/9j7zpC4c3DEso6MINEWj+WCBJbvQC0RHywsTdGyjwsEghj64LQZckZ1fQ=; 7:tgCzc51oDjHwjyIPlpWN9iRXnbRHuS+t/cEN5At8/V0rciN+UJg14M0pUVE7P4myrLJnB3UGs7Bc3SvDUsmtxtHSC2NPt5SD+wal2fn6RfNl6zoWHubWPtqtHjg01ZMqrYjITVgNPeE5Rv76lc3tYYuUUWE32UtGwEA+hJIKA/fUoohn+uS+T+432LQsPTcHaqCoMie2VXz3IoTCwwZaXDIwqzTxAOJDZBZ48T1Scm/RfORm9Wuhh0x/E3pOMmku SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Dec 2017 10:33:22.8708 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 89639b54-74e1-4913-f85f-08d54795188f X-MS-Exchange-CrossTenant-Id: 5afe0b00-7697-4969-b663-5eab37d5f47e X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=5afe0b00-7697-4969-b663-5eab37d5f47e; Ip=[192.88.168.50]; Helo=[tx30smr01.am.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN3PR03MB2356 Cc: suresh.gupta@nxp.com, cyrille.pitchen@wedev4u.fr Subject: [U-Boot] [PATCH 1/3] sf: Add support of 1-2-2, 1-4-4 IO READ protocols 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: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" IO READ protocols transfers both address and data on multiple data bits. 1-2-2(DUAL IO), 1-4-4(QUAD IO) transfer address on 2 data bits or 4 bits per rising edge of SCK respectively. This patch update spi_nor_flash_parameter->spi_nor_read_command array based on DUAL or QUAD IO flag enabled in flash_info for a flash. Signed-off-by: Prabhakar Kushwaha --- drivers/mtd/spi/spi_flash.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 51e28bf..4ff8d8b 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -1071,8 +1071,12 @@ int spi_flash_scan(struct spi_flash *flash) flash->read_cmd = CMD_READ_ARRAY_FAST; if (spi->mode & SPI_RX_SLOW) flash->read_cmd = CMD_READ_ARRAY_SLOW; + else if (spi->mode & SPI_RX_QUAD && info->flags & RD_QUADIO) + flash->read_cmd = CMD_READ_QUAD_IO_FAST; else if (spi->mode & SPI_RX_QUAD && info->flags & RD_QUAD) flash->read_cmd = CMD_READ_QUAD_OUTPUT_FAST; + else if (spi->mode & SPI_RX_DUAL && info->flags & RD_DUALIO) + flash->read_cmd = CMD_READ_DUAL_IO_FAST; else if (spi->mode & SPI_RX_DUAL && info->flags & RD_DUAL) flash->read_cmd = CMD_READ_DUAL_OUTPUT_FAST; From patchwork Wed Dec 20 10:32:53 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Prabhakar Kushwaha X-Patchwork-Id: 851362 X-Patchwork-Delegate: jagannadh.teki@gmail.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=) Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3z1rkw5gcVz9s74 for ; Wed, 20 Dec 2017 21:35:20 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 69E1DC22144; Wed, 20 Dec 2017 10:34:20 +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=BAD_ENC_HEADER, RCVD_IN_DNSWL_BLOCKED, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS 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 58731C22104; Wed, 20 Dec 2017 10:34:11 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 8B263C21E28; Wed, 20 Dec 2017 10:33:49 +0000 (UTC) Received: from NAM02-SN1-obe.outbound.protection.outlook.com (mail-sn1nam02on0082.outbound.protection.outlook.com [104.47.36.82]) by lists.denx.de (Postfix) with ESMTPS id 6603EC21F30 for ; Wed, 20 Dec 2017 10:33:44 +0000 (UTC) Received: from BN3PR03CA0085.namprd03.prod.outlook.com (10.167.1.173) by DM5PR03MB2699.namprd03.prod.outlook.com (10.168.197.137) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.323.15; Wed, 20 Dec 2017 10:33:42 +0000 Received: from BY2FFO11FD003.protection.gbl (2a01:111:f400:7c0c::197) by BN3PR03CA0085.outlook.office365.com (2a01:111:e400:7a4d::45) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.323.15 via Frontend Transport; Wed, 20 Dec 2017 10:33:41 +0000 Authentication-Results: spf=fail (sender IP is 192.88.168.50) smtp.mailfrom=nxp.com; ti.com; dkim=none (message not signed) header.d=none;ti.com; dmarc=fail action=none header.from=nxp.com; Received-SPF: Fail (protection.outlook.com: domain of nxp.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 BY2FFO11FD003.mail.protection.outlook.com (10.1.14.125) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.20.302.6 via Frontend Transport; Wed, 20 Dec 2017 10:33:28 +0000 Received: from VirtualBox.ap.freescale.net ([10.232.40.41]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id vBKAXQ7e030746; Wed, 20 Dec 2017 03:33:37 -0700 From: Prabhakar Kushwaha To: Date: Wed, 20 Dec 2017 16:02:53 +0530 Message-ID: <1513765974-4690-3-git-send-email-prabhakar.kushwaha@nxp.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1513765974-4690-1-git-send-email-prabhakar.kushwaha@nxp.com> References: <1513765974-4690-1-git-send-email-prabhakar.kushwaha@nxp.com> X-EOPAttributedMessage: 0 X-Matching-Connectors: 131582396089441259; (91ab9b29-cfa4-454e-5278-08d120cd25b8); () X-Forefront-Antispam-Report: CIP:192.88.168.50; IPV:NLI; CTRY:US; EFV:NLI; SFV:NSPM; SFS:(10009020)(336005)(396003)(39860400002)(346002)(39380400002)(376002)(2980300002)(1109001)(1110001)(339900001)(189003)(199004)(966005)(48376002)(104016004)(2950100002)(36756003)(8656006)(6916009)(6666003)(575784001)(50466002)(86362001)(97736004)(54906003)(316002)(16586007)(6306002)(77096006)(47776003)(106466001)(498600001)(2351001)(2906002)(85426001)(53936002)(51416003)(68736007)(5660300001)(59450400001)(76176011)(105606002)(50226002)(8676002)(305945005)(39060400002)(4326008)(356003)(8936002)(81166006)(81156014); DIR:OUT; SFP:1101; SCL:1; SRVR:DM5PR03MB2699; H:tx30smr01.am.freescale.net; FPR:; SPF:Fail; PTR:InfoDomainNonexistent; MX:1; A:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; BY2FFO11FD003; 1:5rGJi53jGgO00MbQxO2txdz0SCx5g4cSVt10bjdETSUywF0lWONjc4+Qn8ggdl9ZW2S8gIyD1PKmSWTggE4l9MoSleVlvy95M+lRpOxehnPRBiFUPwwHT7hYV0VbEBvZ MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 964889bb-bd28-4ad8-1beb-08d547951c12 X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(5600026)(4604075)(4534020)(4628075)(201703131517081)(2017052603307); SRVR:DM5PR03MB2699; X-Microsoft-Exchange-Diagnostics: 1; DM5PR03MB2699; 3:BeeC/aogiCbW4GGLiaJoBRSVXicbXmatb41AZ6B8JfMEmbUiVKhca3kvz2UdXfrWv3v6lV3Lll6v+KugPeSavyuiSXE7swR8a5hilHdwqUrkZevpiF3DzqNkXwjxHvamIHTtQ6uiT7WszQaWjZdcwh5buXJczrgS/XU3eD3si7aaQGq5QHgpOewRt/qZ5zvRS2TogOxmM8C/bHVuFcSBUmFGB192uP2g7fVwGdOZaba9VM0wZxiEdZbJ2/73QH4XbINny8KRY3cjwGZmPoUbgtLE1iMgsn8ddJIlm3eqhI/Gpsr9GqamL/7CVnr2xOKnagw9PrWW8Zoqxt/ck7HuxRpyTSnn4cg/xlZ3Xb1l9e0=; 25:507BcmJr7d10B0HtbC8ArBIIhwW/DqfKG5qsE9x5JGiL1cwRnKF9AGw7p8bm6I+MFFIC2XjBPyJJlu+lAsbg8lW+d9gUXaXwlta44ACzWoAsedsmwAUlT6I1Ktr3YowQEJm8Ln+pFUiEuml1Wx6WuUaoURebP9DRbQiA2Qsz5dXFwguFZZVwzBhnDWUv0N+q2hb+8aF9eBUxG8JAJKczhQzCTd16HitGet+Ol4RDlF9wHsKDLxGaO7cm96HyLWkQtDJWAlDB3SHpGsddJIBZ6ygNAyPS3CGTvLSZiuOoR/akVmYNfAKyMYSovJCj8ZTJJy7RzSRF3qWu2Vaf/ITvKg== X-MS-TrafficTypeDiagnostic: DM5PR03MB2699: X-Microsoft-Exchange-Diagnostics: 1; DM5PR03MB2699; 31:rrEiGrBgkRdSjcQjuTOvAGTTz1CYvAAAsAmg49RIoHFoRw9ghax+cXCDAxRY6TINv3BomWXrifnT1NKWTlioCHb4aZNgS64gzy7MvfLejjflls0vQGh/Vih6zbNkHcboVdfsfI8mG290MlBok+KTv/vqnIDPd+tDud+dbY2m9Hwm+f1/z5VY0QSrnYeFX+B75Gij9v24nZR5NQamAS6HG17pU7kmdrLBdU31zx5iPoo=; 4:cBNTCqIjaIrTpAejvYKQ7QdyehqMhIizgBVvbkPzqP0llp3HhAPmoKB5+PPy5edT59H3MEBL9IMtWBy8vJ5a2HahinHkwBc++R7IHYXm8VHIHk8B84Px5VDYJJd7D1ujNybWY4gXF4ZOI3lToQlajJ3PKtQygluxKzhKLtBH21xJ+fo4HMzGHCm3dW6TfGMfRTyyrPUGhqAXiMFraN7wS+FJnHt4+fkP4RSZx4W/BPJZFjpDSohmKp4yoq09Zwwj02GsdXyZCb7Rvc4UTzlERxPwkubMJh+bcACROD1UKwKpptxflTI9NjC7GfPkjOaWztA4oELvmUuLVziLSTi1bmNTZvlSURdsdgJEGA/z3Ko= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(31051911155226)(185117386973197); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6095135)(2401047)(8121501046)(5005006)(93006095)(93001095)(10201501046)(3231023)(3002001)(6055026)(6096035)(201703131430075)(201703131433075)(201703131448075)(201703161259150)(201703151042153)(20161123559100)(20161123565025)(20161123563025)(20161123561025)(20161123556025)(201708071742011); SRVR:DM5PR03MB2699; BCL:0; PCL:0; RULEID:(100000803101)(100110400095)(400006); SRVR:DM5PR03MB2699; X-Forefront-PRVS: 0527DFA348 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; DM5PR03MB2699; 23:uXD/M0p2lYt01kru1i93MVt+K9v3af8hjWbQsHC2T?= ZE7lu8ak0BLUGa7XCWReUI9zLaoDVDBXlsBotmDxfMCgHF94glwjn3bw7xiip91G0YL759ysL8gn+n+U96NmqFTs3QCkkS8REbhT9czMLKFqeWGoNRZSX25M5vCIRhxOEqjoe024qHOcj6gu6RgPEmlxdzo0li9/0zSZX7rsJvgk6oaFEWZiweA/S+HHSaaPiOYjrzU2sxW2XykiQqYYFVSLREkE+LXYLSg+xqlyzNj55oanD8BMwQmPPJsC+Rjtjf6ce6I0/iqmmv5vYYZ41nYDAYIAetA0jp0m/8iTVNYak7zJtYovkFfV/7LEyrHLP1xHFWUR8pR6/5hUwnqh1xTliHny7aawCwlW9pl6iRYuZYKYLfkkBpyXk7QdEXaIRYXyGxBwn4r1PY/xxHJbWkbjSKqq7X2pg1H3U0g5ScxePSPsSX9R5ecWIBPLX7GRcMqjlIIWTl6FnzPCrga14xO8QBmZQ/Y4CwQSTadTZY10CxM10xUJe5PalyPRhCJ0d0yMulMZxq1Vj0RikmwQ+5nEoBAy3+x0jMoZKqxyp//ayHqgtnO8BkrRwKbXjDcKU/Bio2/BMhLohB7uvtm7OnooQfhMLrnzK1sGCzcfAlfR0W6/WXwPmNx42DIUH2zTCUdtXmDa038fPhlwUyRRNVHTDp/NW8VrPUEtRESXBGqOcURTKVK3I/D7ogIyGCYkXhYhqhROXKbEOfWaja9fw94nFASfp3lSJ7Y3S8hQnPaWK2L8z01u31wOS7S+d69hHUKhMIK1rIcIEFKWCK1M5/EbKAcZ8WzLXboikKdq444EfIeh4JIvnca+rgY6tpHRbGaig2I4wh1FfjJc9rl3b1GIdSfESGbPhMDaZrzI0l3Q0stU5nNTvMmMHxMYSoVVTmKi4njwiJVA4KLkOnmJth+2mDw7rh+jzKJ37DLqfcKE92naFzlMlzGQVTpS4MH5dK32TW+LsPsPRuRv2zljIWEty8ZCsv2wMJsP45QV09HRGz7RPSaXKx4qe0FSR+ucSGiSDh1s3GvfrnVqRBF2WDA1Q/1lwpSkBI6XHS/xOm4NcORzAdyY+cwkXF9NxOFlZg45oR15FOmm3hWeul11UNrdHtmMbfSc6L6LCrver4LJ3LvFefLanTyVg3wyVRJC3BDFEb9D2Ze7Aov+LPm4eaJ X-Microsoft-Exchange-Diagnostics: 1; DM5PR03MB2699; 6:pwoSHIaXRUDApcDZu4QN/lrKvRKoGI6YnPCo+DWMuISrzeu9PSQVA66cMgPp6FwFIztbMYt+NtKjeFWcIoaj6+b+H0Hnk1zDX/68etFGrGMXi9BHYDvcYIG3i+wUTvS9dWDezXk+mLjTR9r4Nczuuk+lBgv8FSGprQYdC01Y6lzU+P5icglPfrmULDvDRIJVwku0WeGD4T95vkUiPqqW+bbWm0URqqfiuwmVaiiDTLiB8C8TvPpTTFd8l5Bpo6XUIeGdP6GBo1bT9oV1YCS7qY8uA/KBpiHlkl+6l2HLMBaSaSp9WLgJiwBvosTFnS+s+JMvTbucxy1+eKjEuzYJW3vbIG5I3RJ0DZrq4KPkeUo=; 5:W2UM20/zJIQdW51YX9W/o+yRAfwMDyNUyJPNRf2TVzwwjZyuubFl6XRGkFSi+ZjR/JNHIZLVFnvfmQatBdtygiBzuRB3OWH7fPPFJk1+Ie/cPvDYk6klVQMx39of3YsGQuizU5UkQ75UHI3wGlRPKMxh8wZu8muJ/c6tRcTteSc=; 24:dKJFQ6hmClgN+Qq2el7uIhAYXzvKKqj1rIt+OepOVO8Nhu8j9N+9x2Qj9CVvhF+HKa/Ja2gF7/rnvKyCmOqQyHBJRqWQn6qGqp/faC/IFiw=; 7:qn2E7ppZXS4CcO1bs9amo/RlTSo5+cjvV/ZEz9+IW/nuW23sBlJ4/jdDUgzLGvt2rBm74jXTsfDnqCT+VLGyNRkpIwGF4wYQ0icqwEsm5pxFsoWxuwgNP5L3hRbI/j0SZMZsli1yfSAmfrOdVlvSpqOCEzWf37bqDO1jbzmrJ8XbYi7QDSY0Wx0jl4ukMiehlE0KFXggk5XtrEKiEKAsZAkVjrcmIiM2XAlH0fuJ4HglKXPPtFFV4M2nZFY8MP0N SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Dec 2017 10:33:28.7569 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 964889bb-bd28-4ad8-1beb-08d547951c12 X-MS-Exchange-CrossTenant-Id: 5afe0b00-7697-4969-b663-5eab37d5f47e X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=5afe0b00-7697-4969-b663-5eab37d5f47e; Ip=[192.88.168.50]; Helo=[tx30smr01.am.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM5PR03MB2699 Cc: suresh.gupta@nxp.com, cyrille.pitchen@wedev4u.fr Subject: [U-Boot] [PATCH 2/3] sf: add method to support memory size above 128Mib 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: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" This patch add support of memories with size above 128Mib. It has been ported from Linux commit "mtd: spi-nor: add a stateless method to support memory size above 128Mib". It convert 3byte opcode into 4byte opcode based upon OPCODES_4B or Spansion flash. Also the commands are malloc'ed at run time based on 3byte or 4byte address opcode requirement. Signed-off-by: Prabhakar Kushwaha CC: Cyrille Pitchen CC: Marek Vasut CC: Vignesh R --- depends upon https://patchwork.ozlabs.org/patch/826919/ drivers/mtd/spi/sf_internal.h | 28 ++++++++- drivers/mtd/spi/spi_flash.c | 136 ++++++++++++++++++++++++++++++++++++------ include/spi_flash.h | 2 + 3 files changed, 146 insertions(+), 20 deletions(-) diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 06dee0a..164b0ea 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -27,7 +27,8 @@ enum spi_nor_option_flags { }; #define SPI_FLASH_3B_ADDR_LEN 3 -#define SPI_FLASH_CMD_LEN (1 + SPI_FLASH_3B_ADDR_LEN) +#define SPI_FLASH_4B_ADDR_LEN 4 +#define SPI_FLASH_MAX_ADDR_WIDTH 4 #define SPI_FLASH_16MB_BOUN 0x1000000 /* CFI Manufacture ID's */ @@ -57,13 +58,30 @@ enum spi_nor_option_flags { #define CMD_READ_DUAL_IO_FAST 0xbb #define CMD_READ_QUAD_OUTPUT_FAST 0x6b #define CMD_READ_QUAD_IO_FAST 0xeb + +/* 4B READ commands */ +#define CMD_READ_ARRAY_SLOW_4B 0x13 +#define CMD_READ_ARRAY_FAST_4B 0x0c +#define CMD_READ_DUAL_OUTPUT_FAST_4B 0x3c +#define CMD_READ_DUAL_IO_FAST_4B 0xbc +#define CMD_READ_QUAD_OUTPUT_FAST_4B 0x6c +#define CMD_READ_QUAD_IO_FAST_4B 0xec + +/* 4B Write commands */ +#define CMD_PAGE_PROGRAM_4B 0x12 + +/* 4B Erase commands */ +#define CMD_ERASE_4K_4B 0x21 +#define CMD_ERASE_CHIP_4B 0x5c +#define CMD_ERASE_64K_4B 0xdc + #define CMD_READ_ID 0x9f #define CMD_READ_STATUS 0x05 #define CMD_READ_STATUS1 0x35 #define CMD_READ_CONFIG 0x35 #define CMD_FLAG_STATUS 0x70 -#define CMD_EN4B 0xB7 -#define CMD_EX4B 0xE9 +#define CMD_EN4B 0xB7 +#define CMD_EX4B 0xE9 /* Bank addr access commands */ #ifdef CONFIG_SPI_FLASH_BAR @@ -133,6 +151,10 @@ struct spi_flash_info { #define RD_DUAL BIT(5) /* use Dual Read */ #define RD_QUADIO BIT(6) /* use Quad IO Read */ #define RD_DUALIO BIT(7) /* use Dual IO Read */ +#define OPCODES_4B BIT(8) /* + * Use dedicated 4byte address op codes + * to support memory size above 128Mib. + */ #define RD_FULL (RD_QUAD | RD_DUAL | RD_QUADIO | RD_DUALIO) }; diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 7581622..4d2e58e 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -22,12 +22,28 @@ DECLARE_GLOBAL_DATA_PTR; -static void spi_flash_addr(u32 addr, u8 *cmd) +static void spi_flash_addr(struct spi_flash *flash, u32 addr, u8 *cmd) { /* cmd[0] is actual command */ - cmd[1] = addr >> 16; - cmd[2] = addr >> 8; - cmd[3] = addr >> 0; + + switch (flash->addr_width) { + case SPI_FLASH_3B_ADDR_LEN: + cmd[1] = addr >> 16; + cmd[2] = addr >> 8; + cmd[3] = addr >> 0; + break; + + case SPI_FLASH_4B_ADDR_LEN: + cmd[1] = addr >> 24; + cmd[2] = addr >> 16; + cmd[3] = addr >> 8; + cmd[4] = addr >> 0; + break; + + default: + debug("SF: Wrong opcode size\n"); + break; + } } static int read_sr(struct spi_flash *flash, u8 *rs) @@ -74,6 +90,64 @@ static int write_sr(struct spi_flash *flash, u8 ws) return 0; } +static u8 spi_flash_convert_opcode(u8 opcode, const u8 table[][2], size_t size) +{ + size_t i; + + for (i = 0; i < size; i++) + if (table[i][0] == opcode) + return table[i][1]; + + /* No conversion found, keep input op code. */ + return opcode; +} + +static inline u8 spi_flash_convert_3to4_read(u8 opcode) +{ + static const u8 spi_flash_3to4_read[][2] = { + { CMD_READ_ARRAY_SLOW, CMD_READ_ARRAY_SLOW_4B }, + { CMD_READ_ARRAY_FAST, CMD_READ_ARRAY_FAST_4B }, + { CMD_READ_DUAL_OUTPUT_FAST, CMD_READ_DUAL_OUTPUT_FAST_4B }, + { CMD_READ_DUAL_IO_FAST, CMD_READ_DUAL_IO_FAST_4B }, + { CMD_READ_QUAD_OUTPUT_FAST, CMD_READ_QUAD_OUTPUT_FAST_4B }, + { CMD_READ_QUAD_IO_FAST, CMD_READ_QUAD_IO_FAST_4B }, + + }; + + return spi_flash_convert_opcode(opcode, spi_flash_3to4_read, + ARRAY_SIZE(spi_flash_3to4_read)); +} + +static inline u8 spi_flash_convert_3to4_program(u8 opcode) +{ + static const u8 spi_flash_3to4_program[][2] = { + { CMD_PAGE_PROGRAM, CMD_PAGE_PROGRAM_4B }, + }; + + return spi_flash_convert_opcode(opcode, spi_flash_3to4_program, + ARRAY_SIZE(spi_flash_3to4_program)); +} + +static inline u8 spi_flash_convert_3to4_erase(u8 opcode) +{ + static const u8 spi_flash_3to4_erase[][2] = { + { CMD_ERASE_4K, CMD_ERASE_4K_4B }, + { CMD_ERASE_CHIP, CMD_ERASE_CHIP_4B }, + { CMD_ERASE_64K, CMD_ERASE_64K_4B }, + }; + + return spi_flash_convert_opcode(opcode, spi_flash_3to4_erase, + ARRAY_SIZE(spi_flash_3to4_erase)); +} + +static void spi_flash_set_4byte_opcodes(struct spi_flash *flash, + const struct spi_flash_info *info) +{ + flash->read_cmd = spi_flash_convert_3to4_read(flash->read_cmd); + flash->write_cmd = spi_flash_convert_3to4_program(flash->write_cmd); + flash->erase_cmd = spi_flash_convert_3to4_erase(flash->erase_cmd); +} + #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) static int read_cr(struct spi_flash *flash, u8 *rc) { @@ -364,7 +438,7 @@ int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len) { u32 erase_size, erase_addr; - u8 cmd[SPI_FLASH_CMD_LEN]; + u8 *cmd, cmdsz; int ret = -1; erase_size = flash->erase_size; @@ -381,6 +455,13 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len) } } + cmdsz = 1 + flash->addr_width; + cmd = calloc(1, cmdsz); + if (!cmd) { + debug("SF: Failed to allocate cmd\n"); + return -ENOMEM; + } + cmd[0] = flash->erase_cmd; while (len) { erase_addr = offset; @@ -394,12 +475,12 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len) if (ret < 0) return ret; #endif - spi_flash_addr(erase_addr, cmd); + spi_flash_addr(flash, erase_addr, cmd); debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1], cmd[2], cmd[3], erase_addr); - ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0); + ret = spi_flash_write_common(flash, cmd, cmdsz, NULL, 0); if (ret < 0) { debug("SF: erase failed\n"); break; @@ -423,7 +504,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, unsigned long byte_addr, page_size; u32 write_addr; size_t chunk_len, actual; - u8 cmd[SPI_FLASH_CMD_LEN]; + u8 *cmd, cmdsz; int ret = -1; page_size = flash->page_size; @@ -436,6 +517,13 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, } } + cmdsz = 1 + flash->addr_width; + cmd = calloc(1, cmdsz); + if (!cmd) { + debug("SF: Failed to allocate cmd\n"); + return -ENOMEM; + } + cmd[0] = flash->write_cmd; for (actual = 0; actual < len; actual += chunk_len) { write_addr = offset; @@ -456,13 +544,13 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, chunk_len = min(chunk_len, (size_t)spi->max_write_size); - spi_flash_addr(write_addr, cmd); + spi_flash_addr(flash, write_addr, cmd); debug("SF: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n", buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len); - ret = spi_flash_write_common(flash, cmd, sizeof(cmd), - buf + actual, chunk_len); + ret = spi_flash_write_common(flash, cmd, cmdsz, + buf + actual, chunk_len); if (ret < 0) { debug("SF: write failed\n"); break; @@ -537,7 +625,7 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, return 0; } - cmdsz = SPI_FLASH_CMD_LEN + flash->dummy_byte; + cmdsz = 1 + flash->addr_width + flash->dummy_byte; cmd = calloc(1, cmdsz); if (!cmd) { debug("SF: Failed to allocate cmd\n"); @@ -565,7 +653,7 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, else read_len = remain_len; - spi_flash_addr(read_addr, cmd); + spi_flash_addr(flash, read_addr, cmd); ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len); if (ret < 0) { @@ -1172,10 +1260,6 @@ int spi_flash_scan(struct spi_flash *flash) flash->flags |= SNOR_F_USE_FSR; #endif - /* disable 4-byte addressing if the device exceeds 16MiB */ - if (flash->size > SPI_FLASH_16MB_BOUN) - set_4byte(flash, info, 0); - /* Configure the BAR - discover bank cmds and read current bank */ #ifdef CONFIG_SPI_FLASH_BAR ret = read_bar(flash, info); @@ -1211,5 +1295,23 @@ int spi_flash_scan(struct spi_flash *flash) } #endif + flash->addr_width = SPI_FLASH_3B_ADDR_LEN; + + if (flash->size > SPI_FLASH_16MB_BOUN) { + /* enable 4-byte addressing if the device exceeds 16MiB */ + flash->addr_width = SPI_FLASH_4B_ADDR_LEN; + if (JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_SPANSION || + info->flags & OPCODES_4B) + spi_flash_set_4byte_opcodes(flash, info); + else + set_4byte(flash, info, 1); + } + + if (flash->addr_width > SPI_FLASH_MAX_ADDR_WIDTH) { + dev_err(dev, "address width is too large: %u\n", + flash->addr_width); + return -EINVAL; + } + return 0; } diff --git a/include/spi_flash.h b/include/spi_flash.h index be2fe3f..5a91671 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -48,6 +48,7 @@ struct spi_slave; * @read_cmd: Read cmd - Array Fast, Extn read and quad read. * @write_cmd: Write cmd - page and quad program. * @dummy_byte: Dummy cycles for read operation. + * @addr_width: number of address bytes * @memory_map: Address of read-only SPI flash access * @flash_lock: lock a region of the SPI Flash * @flash_unlock: unlock a region of the SPI Flash @@ -84,6 +85,7 @@ struct spi_flash { u8 write_cmd; u8 dummy_byte; + u8 addr_width; void *memory_map; int (*flash_lock)(struct spi_flash *flash, u32 ofs, size_t len); From patchwork Wed Dec 20 10:32:54 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Prabhakar Kushwaha X-Patchwork-Id: 851361 X-Patchwork-Delegate: jagannadh.teki@gmail.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=) Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3z1rks6xh1z9s74 for ; Wed, 20 Dec 2017 21:35:16 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 34684C21E28; Wed, 20 Dec 2017 10:34:54 +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=BAD_ENC_HEADER, RCVD_IN_DNSWL_BLOCKED, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS 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 2975AC220A8; Wed, 20 Dec 2017 10:34:19 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 3AD10C22134; Wed, 20 Dec 2017 10:33:53 +0000 (UTC) Received: from NAM01-BN3-obe.outbound.protection.outlook.com (mail-bn3nam01on0066.outbound.protection.outlook.com [104.47.33.66]) by lists.denx.de (Postfix) with ESMTPS id 78C0EC22119 for ; Wed, 20 Dec 2017 10:33:48 +0000 (UTC) Received: from CY1PR03CA0039.namprd03.prod.outlook.com (10.174.128.49) by BN6PR03MB2691.namprd03.prod.outlook.com (10.173.144.10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.345.14; Wed, 20 Dec 2017 10:33:46 +0000 Received: from BL2FFO11OLC006.protection.gbl (2a01:111:f400:7c09::124) by CY1PR03CA0039.outlook.office365.com (2603:10b6:600::49) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.323.15 via Frontend Transport; Wed, 20 Dec 2017 10:33:46 +0000 Authentication-Results: spf=fail (sender IP is 192.88.168.50) smtp.mailfrom=nxp.com; nxp.com; dkim=none (message not signed) header.d=none;nxp.com; dmarc=fail action=none header.from=nxp.com; Received-SPF: Fail (protection.outlook.com: domain of nxp.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 BL2FFO11OLC006.mail.protection.outlook.com (10.173.160.95) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.20.302.6 via Frontend Transport; Wed, 20 Dec 2017 10:33:33 +0000 Received: from VirtualBox.ap.freescale.net ([10.232.40.41]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id vBKAXQ7f030746; Wed, 20 Dec 2017 03:33:42 -0700 From: Prabhakar Kushwaha To: Date: Wed, 20 Dec 2017 16:02:54 +0530 Message-ID: <1513765974-4690-4-git-send-email-prabhakar.kushwaha@nxp.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1513765974-4690-1-git-send-email-prabhakar.kushwaha@nxp.com> References: <1513765974-4690-1-git-send-email-prabhakar.kushwaha@nxp.com> X-EOPAttributedMessage: 0 X-Matching-Connectors: 131582396136639650; (91ab9b29-cfa4-454e-5278-08d120cd25b8); () X-Forefront-Antispam-Report: CIP:192.88.168.50; IPV:NLI; CTRY:US; EFV:NLI; SFV:NSPM; SFS:(10009020)(336005)(7966004)(376002)(396003)(346002)(39380400002)(39860400002)(2980300002)(1110001)(1109001)(339900001)(199004)(189003)(52314003)(377424004)(48376002)(104016004)(2351001)(51416003)(8656006)(53936002)(77096006)(50466002)(47776003)(59450400001)(4326008)(16586007)(316002)(8936002)(498600001)(68736007)(76176011)(6666003)(2950100002)(6916009)(85426001)(50226002)(5660300001)(54906003)(305945005)(575784001)(39060400002)(356003)(36756003)(2906002)(105606002)(106466001)(81166006)(81156014)(86362001)(8676002)(97736004); DIR:OUT; SFP:1101; SCL:1; SRVR:BN6PR03MB2691; H:tx30smr01.am.freescale.net; FPR:; SPF:Fail; PTR:InfoDomainNonexistent; A:1; MX:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; BL2FFO11OLC006; 1:SbEWwgN6dRaYeAgYd/FREJKDjE8WTKmZlsma8EjNjlqm7fqom1nvXp9p0EsVahzkMW8RcM5mYiYE+KzFzeFq3U5sHzgOC17d+DYuLDrCbcgS9ElBFgHy9G+xCisKv5mh MIME-Version: 1.0 X-MS-Office365-Filtering-Correlation-Id: 227a7a8b-55b2-4a76-4ca2-08d547951ee2 X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(5600026)(4604075)(4534020)(4628075)(201703131517081)(2017052603307); SRVR:BN6PR03MB2691; X-Microsoft-Exchange-Diagnostics: 1; BN6PR03MB2691; 3:S7GwImMnRnssD6nFNT/xOAZM62mr1JlRoqwYpYengjBDdoWJJGNQ1RTi4G2cgBiSn8ELIfJfXEwVFvxEBbfQCrUfnCBfmZN7bHeEI0xUXMPb8seKeX0148WhX8eIOTioBCtjjJKP8tbSxyGQCYMDCE6AkOhe+NZJ3dQhtZPaL2g5rCOZXTzjqKtPA4sehVmR9UXSG6a9OqKpBevcvOQ6oTghoIuLUNnaHDYyZgOT6tbGotjRwJG7YKu75T1SHuc2nT5tVENF87cZMl1fF5T2cgejAaaneDeIE5QA5c1C7SOGhKfmiJYo777/mru8v9TZDkGP248a+1YH1EUcLCy81rjBO1n9CrAZSGUFRZWCdio=; 25:uXf/F4ZuYSrHAoiBBdGuv94LYsGfPWmpoHmrN9fUjBtp8CDsXcLoPlIaeiTbfCFq9uTLHYJryWY+3sYX8+jpgTIQ3bbVCHHlc52XO9ylCX0CEOfhKS8BwlPaDVbKcYqh+bVu0s/doZxajxs3gTuaQ5gd9wr5cL5hnYtXH2Pi77u65w5bzLb4wyTYJ24RmJX9+s7RouKnELeIiSej3wTVBqmrhP0KHuBXUOL/T/rmw8uWtZRw8Sd5NtzVIdE6GnYRlsPlivUdQPmwx7GZKqDoJVoAMZth5SrvA0MZtwHHJoatwRQudxYOfjsotJ2ymVo584ltL/nUa2/KGq5QYZjgufNlC6OaQ85tVInDz4uRJbk= X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BN6PR03MB2691: X-Microsoft-Exchange-Diagnostics: 1; BN6PR03MB2691; 31:aQ0uZvUTGl8pB54eWzXa4XgeDlbjJLVM9YYqtJyZG881KfZstJH7gGqNqPZDqtwy3kYDL9y1DmRDgfz56DR9Rf4AJOt30EzxHr/fj8l07DhT2JsstJlijBdd9WYRKHvDiZfE7N5QloIQtYiZWeR0IoonU8/XJuii4wT0px+unlfU+1RulIFwL/xKMNwYpUv/B62tBW0FfjCazDqOf+grlzVZCCGLIUfQreJGtbn4xag=; 4:EEK4euYbC9Oc/rTzvVsSwpYKPE4YypGWKE13M8LkgsQR9lw60eYo5d/kKAI9gYW5mN1JCXB723exTwjOXOI2vqkrKeSb3hVPP5nHrDVwhmoX+Paj5LDE61cPglSO2t9i5DkSsxsoOUgTNCbq4xI7pp5ukpJnbBWEuJiAcsQz14Mjwevg/UYEOFVjMewWo2cN95OH/XRxerF2A/bpZEgXnAWmTuf/71gDotqHUeggSk74vqzE2PvH2xGyYnamq0i1iJIWlOINGcDYOK0K5fH1jhYlXiE9W8YevwGJGlLg5pKYjyFFlr7zZHtkk6rFiAtq X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(185117386973197); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6095135)(2401047)(8121501046)(5005006)(3002001)(93006095)(93001095)(10201501046)(3231023)(6055026)(6096035)(20161123561025)(20161123565025)(20161123556025)(20161123563025)(20161123559100)(201703131430075)(201703131441075)(201703131448075)(201703131433075)(201703161259150)(201708071742011); SRVR:BN6PR03MB2691; BCL:0; PCL:0; RULEID:(100000803101)(100110400095)(400006); SRVR:BN6PR03MB2691; X-Forefront-PRVS: 0527DFA348 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BN6PR03MB2691; 23:W3Yg4wW43ozJXqROdfrWCpJG9Ke79ImkgRNdnV9Cm?= lJELxujSbwFmWWv9Z+z0TpZggsCYRsKeImxFjrVjmb305F0s+Yjs/twjUfg7LYKTcNDh/73zZFcsljaLPmwy/hIdH7ykmUC7A8YUYa37ZIV9zDFdJpxkJT2bJ3LN23c7l1O4XyejPD1F3dfok2/uHugrDPJK2g15g8sLhU4489PdymYFN1vOqH6o0Gir9tvQpP09okuI6hGRkrfgYU4r3DqI6uU3G4vog4nXJGz22KYXTbSta7fSPZsItSRSDRC0Tp7kqlov7XkDmTsCFHRe8FmS0XIwaDVbof4frelLGHTZs55ayutLvf6CZCSPg1EBItqe0yGJv1UjxdP2AhGwIU4zDG0VGHeArB1qJkmCfkSDlqvfFwisWYJUYK9eF5SUz3wHTNm8cqsutLJPaGN0TGWVLnt0dkuS0kzus+939viDB7lllljts3020bRIMq0SOVWpjsrK1gOl1V2CTHRlYxgxy1888A6yGaAaE1aAdAgVLICNtbWs7SB1NIPABjjSryi2Uq+w+j4JWr8iof6D+tfIAKpRNQFpWVn7zK2PnI6pLKAdI2GN4TUY8Z6qR85rNa7Av+JsByDdWoOwm4BG1Vm7/r66kfw3Wfqc+QKCf/CMIDSj3C7/jWlvmqlM3hKuh4ZRksCxiL+d/lOQ9UPQMFD5SGS8MjJT8s1YDcuzMRyTWJs9bYDciyGD6lLvMvtHVKD1WSNv5XBbUgiLShVIpThiZNcFvIZ9xbUtg9Vlc3x7qVsmP4TX4LqZ/baANquYOU0UkalknZfsmcvlRcUotyH5ZThDhwl2STj+r8KB4H5NHwHwkBDezCcyv03+jgfgxVJT16kiBvC6EWW1z9Ym2I24sFAyJTlUyetXFUULxgegmphfKvTpVWEmiI4FPYM5Vpwx3dBpenkzyriF2XEqrNnVAwoXzE4RABcdxz5B+QO7SX8QAYfxcP97mMTx6pJ0z/6IM84qML+nbiKMHr5EopHo0RJPo9ru/aPZEZXDszZDGc+zCtkXfl2Eh75isxR+DTyAI7YHeYxPNpDk1Pnv7e8Oui0xrQQHGAJ1J3rhMK8fRPzeFms//BpYY2BA8whLxP3i2i1EXoiD7EfLKtvbEAusioboKxSoqbvPkKvNWkKIXdZd9A5fNF0z/5bA4yrHnnv9iCMc0Ad0YA4f1SlXzTCr+Xc0pGUUnzNu1jWLtZIzQ== X-Microsoft-Exchange-Diagnostics: 1; BN6PR03MB2691; 6:HxZfF+KVHbXmRhEptYDoFC4V9zA7qdX7eLUJAbMptU6ZdBVzex9g29MILv6vvMm7USYz8aUN96VunWbosUnsU4zAK8r8BTeDPDBTl6bTPRzWAEzQC7pcGsbV8AXbSbnnZ6yFEcWoUaZDjnrUcTnxOMBLSkluMuh8ivbYQvkOm6p8FI2Jd4+HP+kR6gJfxylAYaK8FdT0VVyBRk2HIpAYDpp/Cpaf+N1yN+xMa66iPQqi5yic7HL3+zbuFq+G5qdjxJ/T8zfvHi1TkjpzqDXbvHigEGBq0n1PM71NSjJygcMF4jUbVv03+/dnuWTbbSJyDDl0BHGU58zAlMl0G5sddcxk9UIQfZic8zee/JC6flY=; 5:oCdCR0OiIuQz+/Y7/qkgtB2MMAZkZJz2AllAULmd+PYnUFZdK6/B0Xw/bfXwx2B4x+E3EWTvQlH20k4LboBd/qe6mjX1LooXG9hvGs7aXdsrAlnNCzHhIhsy+IkuhGzUu9wR9HZeJ4IK69BtwCkG6b8jf2wRQSx93Iz+o4r7ZjU=; 24:UzbACyyt2MF6xpjkwQG5DpeyPs4YRuI85xABq+82CYUeMUjvcaXKpdl+O26l2DOBjA91ZSrnzmNCjIA8lDBhi72Zv/7XFsQQZ8vwqh9FXzQ=; 7:TZI6gDYPiDVXKOOKKrLN8SPzA8hnxyJQmpkJNmBpLZHidpSiBmJ/L63NQgvtxCH1qgIJnqSObrVmk5JvgFesotvNvjlTJSnzqHxhZ00IDXKBDElZGAr8xpjup2ZFGtn49vUvblOTpezGoD7n3sLNyi2ok0j2vPF4fYNqUsGt5w9g0RPwTHwiiX5w7LfOe00KweW+k8AUnZwWmLTNoq270q2r+HuDadAynh4OBjKCezUjaLD9Fik7m9wgekIO5RZG SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Dec 2017 10:33:33.4923 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 227a7a8b-55b2-4a76-4ca2-08d547951ee2 X-MS-Exchange-CrossTenant-Id: 5afe0b00-7697-4969-b663-5eab37d5f47e X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=5afe0b00-7697-4969-b663-5eab37d5f47e; Ip=[192.88.168.50]; Helo=[tx30smr01.am.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN6PR03MB2691 Cc: suresh.gupta@nxp.com, cyrille.pitchen@wedev4u.fr Subject: [U-Boot] [PATCH 3/3] sf: parse Serial Flash Discoverable Parameters (SFDP) tables 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: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" This patch adds support to the JESD216 rev B standard and parses the SFDP tables to dynamically initialize the 'struct spi_nor_flash_parameter'. It has been ported from Linux commit "mtd: spi-nor: parse Serial Flash Discoverable Parameters (SFDP) tables". It Also ports all modifications done on top of the mentioned commit. This feature is enabled by defining FLASH_SFDP in spi_flash_info's flag field. Signed-off-by: Prabhakar Kushwaha CC: Cyrille Pitchen CC: Marek Vasut --- drivers/mtd/spi/sf_internal.h | 204 +++++++++++++++++++++ drivers/mtd/spi/spi_flash.c | 416 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 619 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 164b0ea..73fe207 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -12,6 +12,7 @@ #include #include +#include /* Dual SPI flash memories - see SPI_COMM_DUAL_... */ enum spi_dual_flash { @@ -82,6 +83,7 @@ enum spi_nor_option_flags { #define CMD_FLAG_STATUS 0x70 #define CMD_EN4B 0xB7 #define CMD_EX4B 0xE9 +#define CMD_READ_SFDP 0x5a /* Bank addr access commands */ #ifdef CONFIG_SPI_FLASH_BAR @@ -155,9 +157,211 @@ struct spi_flash_info { * Use dedicated 4byte address op codes * to support memory size above 128Mib. */ +#define FLASH_SFDP BIT(9) /* Parse SFDP tables */ #define RD_FULL (RD_QUAD | RD_DUAL | RD_QUADIO | RD_DUALIO) }; +struct sfdp_parameter_header { + u8 id_lsb; + u8 minor; + u8 major; + u8 length; /* in double words */ + u8 parameter_table_pointer[3]; /* byte address */ + u8 id_msb; +}; + +#define SFDP_PARAM_HEADER_ID(p) (((p)->id_msb << 8) | (p)->id_lsb) +#define SFDP_PARAM_HEADER_PTP(p) \ + (((p)->parameter_table_pointer[2] << 16) | \ + ((p)->parameter_table_pointer[1] << 8) | \ + ((p)->parameter_table_pointer[0] << 0)) + +#define SFDP_BFPT_ID 0xff00 /* Basic Flash Parameter Table */ +#define SFDP_SECTOR_MAP_ID 0xff81 /* Sector Map Table */ + +#define SFDP_SIGNATURE 0x50444653U +#define SFDP_JESD216_MAJOR 1 +#define SFDP_JESD216_MINOR 0 +#define SFDP_JESD216A_MINOR 5 +#define SFDP_JESD216B_MINOR 6 + +struct sfdp_header { + u32 signature; /* Ox50444653U <=> "SFDP" */ + u8 minor; + u8 major; + u8 nph; /* 0-base number of parameter headers */ + u8 unused; + + /* Basic Flash Parameter Table. */ + struct sfdp_parameter_header bfpt_header; +}; + +/* Basic Flash Parameter Table */ + +/* + * JESD216 rev B defines a Basic Flash Parameter Table of 16 DWORDs. + * They are indexed from 1 but C arrays are indexed from 0. + */ +#define BFPT_DWORD(i) ((i) - 1) +#define BFPT_DWORD_MAX 16 + +/* The first version of JESB216 defined only 9 DWORDs. */ +#define BFPT_DWORD_MAX_JESD216 9 + +/* 1st DWORD. */ +#define BFPT_DWORD1_FAST_READ_1_1_2 BIT(16) +#define BFPT_DWORD1_ADDRESS_BYTES_MASK GENMASK(18, 17) +#define BFPT_DWORD1_ADDRESS_BYTES_3_ONLY (0x0UL << 17) +#define BFPT_DWORD1_ADDRESS_BYTES_3_OR_4 (0x1UL << 17) +#define BFPT_DWORD1_ADDRESS_BYTES_4_ONLY (0x2UL << 17) +#define BFPT_DWORD1_DTR BIT(19) +#define BFPT_DWORD1_FAST_READ_1_2_2 BIT(20) +#define BFPT_DWORD1_FAST_READ_1_4_4 BIT(21) +#define BFPT_DWORD1_FAST_READ_1_1_4 BIT(22) + +/* 5th DWORD. */ +#define BFPT_DWORD5_FAST_READ_2_2_2 BIT(0) +#define BFPT_DWORD5_FAST_READ_4_4_4 BIT(4) + +/* 11th DWORD. */ +#define BFPT_DWORD11_PAGE_SIZE_SHIFT 4 +#define BFPT_DWORD11_PAGE_SIZE_MASK GENMASK(7, 4) + +/* 15th DWORD. */ + +/* + * (from JESD216 rev B) + * Quad Enable Requirements (QER): + * - 000b: Device does not have a QE bit. Device detects 1-1-4 and 1-4-4 + * reads based on instruction. DQ3/HOLD# functions are hold during + * instruction phase. + * - 001b: QE is bit 1 of status register 2. It is set via Write Status with + * two data bytes where bit 1 of the second byte is one. + * [...] + * Writing only one byte to the status register has the side-effect of + * clearing status register 2, including the QE bit. The 100b code is + * used if writing one byte to the status register does not modify + * status register 2. + * - 010b: QE is bit 6 of status register 1. It is set via Write Status with + * one data byte where bit 6 is one. + * [...] + * - 011b: QE is bit 7 of status register 2. It is set via Write status + * register 2 instruction 3Eh with one data byte where bit 7 is one. + * [...] + * The status register 2 is read using instruction 3Fh. + * - 100b: QE is bit 1 of status register 2. It is set via Write Status with + * two data bytes where bit 1 of the second byte is one. + * [...] + * In contrast to the 001b code, writing one byte to the status + * register does not modify status register 2. + * - 101b: QE is bit 1 of status register 2. Status register 1 is read using + * Read Status instruction 05h. Status register2 is read using + * instruction 35h. QE is set via Writ Status instruction 01h with + * two data bytes where bit 1 of the second byte is one. + * [...] + */ +#define BFPT_DWORD15_QER_MASK GENMASK(22, 20) +#define BFPT_DWORD15_QER_NONE (0x0UL << 20) /* Micron */ +#define BFPT_DWORD15_QER_SR2_BIT1_BUGGY (0x1UL << 20) +#define BFPT_DWORD15_QER_SR1_BIT6 (0x2UL << 20) /* Macronix */ +#define BFPT_DWORD15_QER_SR2_BIT7 (0x3UL << 20) +#define BFPT_DWORD15_QER_SR2_BIT1_NO_RD (0x4UL << 20) +#define BFPT_DWORD15_QER_SR2_BIT1 (0x5UL << 20) /* Spansion */ + +struct sfdp_bfpt { + u32 dwords[BFPT_DWORD_MAX]; +}; + +/* Fast Read settings. */ + +struct sfdp_bfpt_read { + /* + * The bit in BFPT DWORD tells us + * whether the Fast Read x-y-z command is supported. + */ + u32 supported_dword; + u32 supported_bit; + + /* + * The half-word at offset in BFPT DWORD + * encodes the op code, the number of mode clocks and the number of wait + * states to be used by Fast Read x-y-z command. + */ + u32 settings_dword; + u32 settings_shift; + + /* The SPI Read x-y-z command. */ + u8 read_cmd; + +}; + +static const struct sfdp_bfpt_read sfdp_bfpt_reads[] = { + /* Fast Read 1-1-2 */ + { + BFPT_DWORD(1), BIT(16), /* Supported bit */ + BFPT_DWORD(4), 0, /* Settings */ + CMD_READ_DUAL_OUTPUT_FAST, + }, + + /* Fast Read 1-2-2 */ + { + BFPT_DWORD(1), BIT(20), /* Supported bit */ + BFPT_DWORD(4), 16, /* Settings */ + CMD_READ_DUAL_IO_FAST, + }, + + /* Fast Read 2-2-2 */ + { + BFPT_DWORD(5), BIT(0), /* Supported bit */ + BFPT_DWORD(6), 16, /* Settings */ + 0xFF, /* Not supported cmd */ + }, + + /* Fast Read 1-1-4 */ + { + BFPT_DWORD(1), BIT(22), /* Supported bit */ + BFPT_DWORD(3), 16, /* Settings */ + CMD_READ_QUAD_OUTPUT_FAST, + }, + + /* Fast Read 1-4-4 */ + { + BFPT_DWORD(1), BIT(21), /* Supported bit */ + BFPT_DWORD(3), 0, /* Settings */ + CMD_READ_QUAD_IO_FAST, + }, + + /* Fast Read 4-4-4 */ + { + BFPT_DWORD(5), BIT(4), /* Supported bit */ + BFPT_DWORD(7), 16, /* Settings */ + 0xFF, /* Not supported cmd */ + }, +}; + +struct sfdp_bfpt_erase { + /* + * The half-word at offset in DWORD encodes the + * op code and erase sector size to be used by Sector Erase commands. + */ + u32 dword; + u32 shift; +}; + +static const struct sfdp_bfpt_erase sfdp_bfpt_erases[] = { + /* Erase Type 1 in DWORD8 bits[15:0] */ + {BFPT_DWORD(8), 0}, + + /* Erase Type 2 in DWORD8 bits[31:16] */ + {BFPT_DWORD(8), 16}, + + /* Erase Type 3 in DWORD9 bits[15:0] */ + {BFPT_DWORD(9), 0}, + + /* Erase Type 4 in DWORD9 bits[31:16] */ + {BFPT_DWORD(9), 16}, +}; + extern const struct spi_flash_info spi_flash_ids[]; /* Send a single-byte command to the device and read the response */ diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 4d2e58e..2bc3af8 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -1107,6 +1107,417 @@ int spi_flash_decode_fdt(struct spi_flash *flash) } #endif /* CONFIG_IS_ENABLED(OF_CONTROL) */ +/* + * Serial Flash Discoverable Parameters (SFDP) parsing. + */ + +/** + * spi_flash_read_sfdp() - read Serial Flash Discoverable Parameters. + * @flash: pointer to a 'struct spi_flash' + * @addr: offset in the SFDP area to start reading data from + * @len: number of bytes to read + * @buf: buffer where the SFDP data are copied into (dma-safe memory) + * + * Whatever the actual numbers of bytes for address and dummy cycles are + * for (Fast) Read commands, the Read SFDP (5Ah) instruction is always + * followed by a 3-byte address and 8 dummy clock cycles. + * + * Return: 0 on success, -errno otherwise. + */ +static int spi_flash_read_sfdp(struct spi_flash *flash, u32 addr, + size_t len, void *buf) +{ + u8 addr_width, read_cmd, dummy_byte; + int ret; + + ret = spi_claim_bus(flash->spi); + if (ret) { + debug("SF: Unable to claim SPI bus\n"); + return ret; + } + + read_cmd = flash->read_cmd; + addr_width = flash->addr_width; + dummy_byte = flash->dummy_byte; + + flash->read_cmd = CMD_READ_SFDP; + flash->addr_width = 3; + flash->dummy_byte = 2; + + ret = spi_flash_cmd_read_ops(flash, addr, len, (u8 *)buf); + if (ret < 0) + goto read_err; + ret = 0; + +read_err: + flash->read_cmd = read_cmd; + flash->addr_width = addr_width; + flash->dummy_byte = dummy_byte; + + spi_release_bus(flash->spi); + return ret; +} + +/** + * spi_flash_read_sfdp_dma_unsafe() - read Serial Flash Discoverable Parameters. + * @flash: pointer to a 'struct spi_flash' + * @addr: offset in the SFDP area to start reading data from + * @len: number of bytes to read + * @buf: buffer where the SFDP data are copied into + * + * Wrap spi_flash_read_sfdp() using a kmalloc'ed bounce buffer as @buf is now + * not guaranteed to be dma-safe. + * + * Return: -ENOMEM if kmalloc() fails, the return code of spi_flash_read_sfdp() + * otherwise. + */ +static int spi_flash_read_sfdp_dma_unsafe(struct spi_flash *flash, u32 addr, + size_t len, void *buf) +{ + void *dma_safe_buf; + int ret; + + dma_safe_buf = kmalloc(len, GFP_KERNEL); + if (!dma_safe_buf) + return -ENOMEM; + + ret = spi_flash_read_sfdp(flash, addr, len, dma_safe_buf); + memcpy(buf, dma_safe_buf, len); + kfree(dma_safe_buf); + + return ret; +} + +/** + * spi_flash_parse_bfpt() - read and parse the Basic Flash Parameter Table. + * @flash: pointer to a 'struct spi_flash' + * @info: pointer to a 'struct spi_flash_info' + * @bfpt_header: pointer to the 'struct sfdp_parameter_header' describing + * the Basic Flash Parameter Table length and version + * + * The Basic Flash Parameter Table is the main and only mandatory table as + * defined by the SFDP (JESD216) specification. + * It provides us with the total size (memory density) of the data array and + * the number of address bytes for Fast Read, Page Program and Sector Erase + * commands. + * For Fast READ commands, it also gives the number of mode clock cycles and + * wait states (regrouped in the number of dummy clock cycles) for each + * supported instruction op code. + * For Page Program, the page size is now available since JESD216 rev A, however + * the supported instruction op codes are still not provided. + * For Sector Erase commands, this table stores the supported instruction op + * codes and the associated sector sizes. + * Finally, the Quad Enable Requirements (QER) are also available since JESD216 + * rev A. The QER bits encode the manufacturer dependent procedure to be + * executed to set the Quad Enable (QE) bit in some internal register of the + * Quad SPI memory. Indeed the QE bit, when it exists, must be set before + * sending any Quad SPI command to the memory. Actually, setting the QE bit + * tells the memory to reassign its WP# and HOLD#/RESET# pins to functions IO2 + * and IO3 hence enabling 4 (Quad) I/O lines. + * + * Return: 0 on success, -errno otherwise. + */ +static int spi_flash_parse_bfpt(struct spi_flash *flash, + const struct sfdp_parameter_header *bfpt_header) +{ + struct spi_slave *spi = flash->spi; + struct sfdp_bfpt bfpt; + size_t len; + int i, err; + u32 addr; + u16 half; + + /* JESD216 Basic Flash Parameter Table length is at least 9 DWORDs. */ + if (bfpt_header->length < BFPT_DWORD_MAX_JESD216) + return -EINVAL; + + /* Read the Basic Flash Parameter Table. */ + len = min_t(size_t, sizeof(bfpt), + bfpt_header->length * sizeof(u32)); + addr = SFDP_PARAM_HEADER_PTP(bfpt_header); + memset(&bfpt, 0, sizeof(bfpt)); + err = spi_flash_read_sfdp_dma_unsafe(flash, addr, len, &bfpt); + if (err < 0) + return err; + + /* Fix endianness of the BFPT DWORDs. */ + for (i = 0; i < BFPT_DWORD_MAX; i++) + bfpt.dwords[i] = le32_to_cpu(bfpt.dwords[i]); + + /* Number of address bytes. */ + switch (bfpt.dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) { + case BFPT_DWORD1_ADDRESS_BYTES_3_ONLY: + flash->addr_width = 3; + break; + + case BFPT_DWORD1_ADDRESS_BYTES_4_ONLY: + flash->addr_width = 4; + break; + + case BFPT_DWORD1_ADDRESS_BYTES_3_OR_4: + flash->addr_width = 3; + break; + + default: /* Reserved */ + break; + } + + /* Flash Memory Density (in bits). */ + flash->size = bfpt.dwords[BFPT_DWORD(2)]; + if (flash->size & BIT(31)) { + flash->size &= ~BIT(31); + + /* + * Prevent overflows on params->size. Anyway, a NOR of 2^64 + * bits is unlikely to exist so this error probably means + * the BFPT we are reading is corrupted/wrong. + */ + if (flash->size > 63) + return -EINVAL; + + flash->size = 1ULL << flash->size; + } else { + flash->size++; + } + flash->size >>= 3; /* Convert to bytes. */ + flash->size <<= flash->shift; + + /* Fast Read settings. */ + for (i = 0; i < ARRAY_SIZE(sfdp_bfpt_reads); i++) { + const struct sfdp_bfpt_read *rd = &sfdp_bfpt_reads[i]; + u32 mode_dummy_cycle; + + if (!(bfpt.dwords[rd->supported_dword] & rd->supported_bit)) + continue; + + half = bfpt.dwords[rd->settings_dword] >> rd->settings_shift; + mode_dummy_cycle = ((half >> 5) & 0x07) + ((half >> 0) & 0x1f); + + flash->dummy_byte = mode_dummy_cycle / 8; + + switch (rd->read_cmd) { + case CMD_READ_QUAD_OUTPUT_FAST: + case CMD_READ_QUAD_IO_FAST: + if (spi->mode & SPI_RX_QUAD) { + flash->read_cmd = rd->read_cmd; + + if (flash->read_cmd == CMD_READ_QUAD_IO_FAST) + flash->dummy_byte = + (mode_dummy_cycle * 4) / 8; + } + break; + + case CMD_READ_DUAL_OUTPUT_FAST: + case CMD_READ_DUAL_IO_FAST: + if (spi->mode & SPI_RX_DUAL && + !(spi->mode & SPI_RX_QUAD)) { + flash->read_cmd = rd->read_cmd; + + if (flash->read_cmd == CMD_READ_DUAL_IO_FAST) + flash->dummy_byte = + (mode_dummy_cycle * 2) / 8; + } + + break; + + default: + debug("read_cmd=0x%x is not supported\n", rd->read_cmd); + break; + } + } + + if (spi->mode & SPI_RX_SLOW && + !(spi->mode & (SPI_RX_QUAD | SPI_RX_DUAL))) + flash->read_cmd = CMD_READ_ARRAY_SLOW; + else + flash->read_cmd = CMD_READ_ARRAY_FAST; + + /* Sector Erase settings. */ + for (i = 0; i < ARRAY_SIZE(sfdp_bfpt_erases); i++) { + const struct sfdp_bfpt_erase *er = &sfdp_bfpt_erases[i]; + u32 erasesize; + u8 opcode; + + half = bfpt.dwords[er->dword] >> er->shift; + erasesize = half & 0xff; + + /* erasesize == 0 means this Erase Type is not supported. */ + if (!erasesize) + continue; + + erasesize = 1U << erasesize; + opcode = (half >> 8) & 0xff; +#ifdef CONFIG_SPI_FLASH_USE_4K_SECTORS + if (erasesize == SZ_4K) { + flash->erase_cmd = opcode; + flash->erase_size = erasesize; + break; + } +#endif + if (!flash->erase_size || flash->erase_size < erasesize) { + flash->erase_cmd = opcode; + flash->erase_size = erasesize; + } + } + + flash->erase_size <<= flash->shift; + + flash->sector_size = flash->erase_size; + + /* Stop here if not JESD216 rev A or later. */ + if (bfpt_header->length < BFPT_DWORD_MAX) + return 0; + + /* Page size: this field specifies 'N' so the page size = 2^N bytes. */ + flash->page_size = bfpt.dwords[BFPT_DWORD(11)]; + flash->page_size &= BFPT_DWORD11_PAGE_SIZE_MASK; + flash->page_size >>= BFPT_DWORD11_PAGE_SIZE_SHIFT; + flash->page_size = 1U << flash->page_size; + flash->page_size <<= flash->shift; + + if ((flash->read_cmd == CMD_READ_QUAD_OUTPUT_FAST) || + (flash->read_cmd == CMD_READ_QUAD_IO_FAST) || + (flash->write_cmd == CMD_QUAD_PAGE_PROGRAM)) { + /* Quad Enable Requirements. */ + switch (bfpt.dwords[BFPT_DWORD(15)] & BFPT_DWORD15_QER_MASK) { + case BFPT_DWORD15_QER_NONE: + break; + + case BFPT_DWORD15_QER_SR2_BIT1_BUGGY: + case BFPT_DWORD15_QER_SR2_BIT1_NO_RD: + break; + + case BFPT_DWORD15_QER_SR1_BIT6: +#ifdef CONFIG_SPI_FLASH_MACRONIX + macronix_quad_enable(flash); +#endif + break; + + case BFPT_DWORD15_QER_SR2_BIT7: + + break; + + case BFPT_DWORD15_QER_SR2_BIT1: +#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) + spansion_quad_enable(flash); +#endif + break; + + default: + return -EINVAL; + } + } + + return 0; +} + +/** + * spi_flash_parse_sfdp() - parse the Serial Flash Discoverable Parameters. + * @flash: pointer to a 'struct spi_flash' + * + * The Serial Flash Discoverable Parameters are described by the JEDEC JESD216 + * specification. This is a standard which tends to supported by almost all + * (Q)SPI memory manufacturers. Those hard-coded tables allow us to learn at + * runtime the main parameters needed to perform basic SPI flash operations such + * as Fast Read, Page Program or Sector Erase commands. + * + * Return: 0 on success, -errno otherwise. + */ +static int spi_flash_parse_sfdp(struct spi_flash *flash) +{ + const struct sfdp_parameter_header *param_header, *bfpt_header; + struct sfdp_parameter_header *param_headers = NULL; + struct sfdp_header header; + size_t psize; + int i, err; + + /* Get the SFDP header. */ + err = spi_flash_read_sfdp_dma_unsafe(flash, 0, sizeof(header), &header); + if (err < 0) + return err; + + /* Check the SFDP header version. */ + if (le32_to_cpu(header.signature) != SFDP_SIGNATURE || + header.major != SFDP_JESD216_MAJOR || + header.minor < SFDP_JESD216_MINOR) + return -EINVAL; + + /* + * Verify that the first and only mandatory parameter header is a + * Basic Flash Parameter Table header as specified in JESD216. + */ + bfpt_header = &header.bfpt_header; + if (SFDP_PARAM_HEADER_ID(bfpt_header) != SFDP_BFPT_ID || + bfpt_header->major != SFDP_JESD216_MAJOR) + return -EINVAL; + + /* + * Allocate memory then read all parameter headers with a single + * Read SFDP command. These parameter headers will actually be parsed + * twice: a first time to get the latest revision of the basic flash + * parameter table, then a second time to handle the supported optional + * tables. + * Hence we read the parameter headers once for all to reduce the + * processing time. Also we use kmalloc() instead of devm_kmalloc() + * because we don't need to keep these parameter headers: the allocated + * memory is always released with kfree() before exiting this function. + */ + if (header.nph) { + psize = header.nph * sizeof(*param_headers); + + param_headers = kmalloc(psize, GFP_KERNEL); + if (!param_headers) + return -ENOMEM; + + err = spi_flash_read_sfdp(flash, sizeof(header), + psize, param_headers); + if (err < 0) { + debug("SF: failed to read SFDP parameter headers\n"); + goto exit; + } + } + + /* + * Check other parameter headers to get the latest revision of + * the basic flash parameter table. + */ + for (i = 0; i < header.nph; i++) { + param_header = ¶m_headers[i]; + + if (SFDP_PARAM_HEADER_ID(param_header) == SFDP_BFPT_ID && + param_header->major == SFDP_JESD216_MAJOR && + (param_header->minor > bfpt_header->minor || + (param_header->minor == bfpt_header->minor && + param_header->length > bfpt_header->length))) + bfpt_header = param_header; + } + + err = spi_flash_parse_bfpt(flash, bfpt_header); + if (err) + goto exit; + + /* Parse other parameter headers. */ + for (i = 0; i < header.nph; i++) { + param_header = ¶m_headers[i]; + + switch (SFDP_PARAM_HEADER_ID(param_header)) { + case SFDP_SECTOR_MAP_ID: + debug("non-uniform erase sector maps not supported\n"); + break; + + default: + break; + } + + if (err) + goto exit; + } + +exit: + kfree(param_headers); + return err; +} + int spi_flash_scan(struct spi_flash *flash) { struct spi_slave *spi = flash->spi; @@ -1294,9 +1705,12 @@ int spi_flash_scan(struct spi_flash *flash) puts(" Full access #define CONFIG_SPI_FLASH_BAR\n"); } #endif - flash->addr_width = SPI_FLASH_3B_ADDR_LEN; + /* Override the parameters with data read from SFDP tables. */ + if (info->flags & (FLASH_SFDP)) + spi_flash_parse_sfdp(flash); + if (flash->size > SPI_FLASH_16MB_BOUN) { /* enable 4-byte addressing if the device exceeds 16MiB */ flash->addr_width = SPI_FLASH_4B_ADDR_LEN;