From patchwork Thu Jun 27 11:19:59 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Kshevetskiy X-Patchwork-Id: 1953181 X-Patchwork-Delegate: dario.binacchi@amarulasolutions.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.a=rsa-sha256 header.s=selector2 header.b=tW41Q9+p; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4W8x1x54xKz20Xg for ; Thu, 27 Jun 2024 21:20:21 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 8DEC588549; Thu, 27 Jun 2024 13:20:18 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.b="tW41Q9+p"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 13FBB88549; Thu, 27 Jun 2024 13:20:17 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,SPF_HELO_PASS, SPF_PASS autolearn=no autolearn_force=no version=3.4.2 Received: from EUR02-VI1-obe.outbound.protection.outlook.com (mail-vi1eur02on20701.outbound.protection.outlook.com [IPv6:2a01:111:f403:2607::701]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id B775288528 for ; Thu, 27 Jun 2024 13:20:14 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mikhail.kshevetskiy@genexis.eu ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=AI7vZtMnmxx7vpeE0RvXdwspampCDPdfsoClyScQ51vWLFztzCiSu9Y85Tl+YK600LXhc2C1D2pLaq0ZWnUpuCKeNsRIMXp5DomMk5iZiIQKla8Z7j2dyZGJ1Mh1RTX96xUVqymPQ8hi+VxZ9h5aa9+4lBBA45JS1UrvafzV+jRZ6Z5cLkaLLWJdwnA65Sg0MkGeJOqNIR36gSoWUKKpwXyyHKgDn2/zHu47Uc4vu9johLse2pLBwV7N85FWnKNWZSHBIpm2Xz2kGnypxgnQDCN48+6aKtWdharroX9lT5t6CGbtodZyRnnRRDF91TZahDa1DJcHJfC9lu5+piArAg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=DHAbXyLYrOulpBoIoeSeQxV+AxwmC8D1VzTh9axr6JI=; b=DrC8K9T6oXN06xPJ31yUZyeM5vBuaPl8rhRSAD9BxG3OTwxMYaVMvgIC8p1KY/kwBZVf0grqHduitUHeiop2+FwBoesdVgal7O7NI6wpkzAGvzRbjh2uWwNU70ND1p/wHdq0+EUrUhTF6u58/80BW8lTZ0v5CrporRYHQAhkjjWZFZESOVxrR7wtoWVj/rzfvB9/TiLwUo+/jOLTkh3vXTikweeTxTMzpSHu25v06GrlYAgPjoDjjvyc4fu4/fAHvCCPnI+NELe18zfTnPzYN/MqArd8QkNfC+lhGce0K4rv8V4i7tbaRBrAm7raU6X6Thseoav2uoy5jZwgbbOKDg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=genexis.eu; dmarc=pass action=none header.from=iopsys.eu; dkim=pass header.d=iopsys.eu; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iopsys.eu; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=DHAbXyLYrOulpBoIoeSeQxV+AxwmC8D1VzTh9axr6JI=; b=tW41Q9+p4OSqodfxak0Kt6mgdxr3xONRrc+AsrSZPwgGExT3oYW05AGK4sImyuxpLVML5jpZMulPRkCPoWyyxNg0fBzeJ0HqBFyPpKSgZ2GwNE6LRbxrEiGzkqVR3SQaZJOTz+FV06TzYN4t2qkczy+LMaW9okNyO+KVKpkAFsq7FkkH7a23unM42/G/AP3vVL0ut/lUy/46p5txpwqbi7IstSM16jMUvzc71GtoKGi7zZeMvYhoY60AoZXgWIkkNpedRmG0gkPODmty7iYICmqdEAvs4IxOftJc9gAs9KXHhB5h4WvCxy5S2BFcO42oGDkth1Gohwx2jsqDWorGGg== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=iopsys.eu; Received: from GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) by PA4PR08MB6064.eurprd08.prod.outlook.com (2603:10a6:102:e2::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.35; Thu, 27 Jun 2024 11:20:12 +0000 Received: from GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0]) by GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0%5]) with mapi id 15.20.7698.025; Thu, 27 Jun 2024 11:20:12 +0000 From: Mikhail Kshevetskiy To: Tom Rini , Dario Binacchi , Michael Trimarchi , Frieder Schrempf , Jagan Teki , Simon Glass , William Zhang , Igor Prusov , Bruce Suen , Dmitry Rokosov , Martin Kurbanov , Chuanhong Guo , Miquel Raynal , Francesco Dolcini , Max Krummenacher , u-boot@lists.denx.de Subject: [PATCH 1/7] mtd: spinand: Use the spi-mem dirmap API Date: Thu, 27 Jun 2024 14:19:59 +0300 Message-ID: <20240627112005.99375-1-mikhail.kshevetskiy@iopsys.eu> X-Mailer: git-send-email 2.43.0 X-ClientProxiedBy: GVX0EPF0000FA79.SWEP280.PROD.OUTLOOK.COM (2603:10a6:144:1:0:4:0:6) To GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: GV2PR08MB8121:EE_|PA4PR08MB6064:EE_ X-MS-Office365-Filtering-Correlation-Id: 0625bcf4-2ae9-4891-abfe-08dc969b1cba X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|1800799024|366016|52116014|7416014|376014|38350700014|921020; X-Microsoft-Antispam-Message-Info: QrIp1aJQVtnZ7tBoVGY7i32Ox9NHix/IQ4h7TwNoFAf+DFC4Kqp/rHZCNcEDlMg9Kf5tfqoJw5Ju7IfthKc9HWbdQ9HXk+OJWZm3LMGTeK2dOmI+eFduCt/asvTdPRuFLbblfcoHsBtQFi3a1Fk7ujfqMl2l1rjDG+28XDJWwqxxwe59Xzl8vEIRibp5/2iFcMOomL7dxHElLYR3yo8wGPKrFa/R2tQ2LQzYvat3PD+19JV8NIe+Dx0gWUCkpeZBkpT5JZJdxf5USlSJANkeWhROsiPhrbVr924WvutyE3pUghjzGmBIQAVzngfJXqy8yM49ItHXdNcHwuMJpmiVvxFKWEUka5HvPKIZ8qvqPVk9s3mClSxMyfZev/jBmJFThQmXSFK8jHF5cNVfYczpUP5AczDPBO4VKerUDJ5PbWVZOF4xZievhmaNteYrx4rGUp/kMvsstJ1l/XrMiQ+lBSXCUfJxn/SJk5tEj43o8g6naGFKfxkHtWvoBVUj56/1+/KV61XscTHX23V+awvbSllVA+D45a3GIJfGbJd04a2aW6Q4cihyeYdIYPnA751LJbX2h7u+xu+nPq0j057/wONIK13QCFdO8GzIyO7M3K4UsIOIGIR5FFC/7Xs27YZCge17sitkp16xxgSXA9L5+zsNcw/ofjVbM3npCUmScoonz08Tm+bAIt1mkuh5P3TTTAGCrETwvBLx9OLCtAEDrq8QVHDLvAgVEN3fnhXeAWcRXP+afaafnHiwd6UTJOsa9AUglekhVvmNjeAAI2L+Rp39H5LLn5/0Fdr4lAppLiY2/TRvlL7Zf9AbrHI6nXrLNq/w+GdEVekG09BOC7kWda0bDiT7vwejrtku3ksjrmLOV6A1WCqT6iaIB1uHZ1izjnQ9uF46Ix4Q7DuEn02il0HvUeCoynOB96HGxUetsUoiOghcfKxsKYo/4PvxdRtPAT/ucl4PkIgiFZEriS0ADhIb6coTHX7/tAJytkmhxZTFWaEISkN1j3eFnJNeMMYE9+DVObbWcOuTApbdacGKKcaxLUBt+uBlZg9OLk1SUYIMAFVTdUabI3CP913rw0kK5Y/QzwN7f+kyNjzkjNlkGAaqd1cYKUEjMCwxPPrYuHr9SKZ7+xzLPFgu3ALCCPoui76jgtk8g9YKHGNwVy/Xp9bq06s+Qc2PMX0eeE1Wuvvaokm6xc3y1PZSKiKh3xKRPho5rpLz7+8Tzm8q8fVJ9pBLmGC3VejDC2Pr7rNI1lTi9zMSJfEAv4NcWy34OMaS6xFezBcSkOdTGhH9b1qvv7tYqCGNg3IqTCkaNyngfMbU16qt4ulPZgq07qMCuBKNd4C5T7nEX+ffSa5Bo8/sGY2wS7msGzvZh8O5lpakagRuIM6OD3VE+HPZDAsD0aQQb0e3lL1IgQ9QC48FctR0EiZMKWupuxuDLIjq3SntPTk= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:GV2PR08MB8121.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(1800799024)(366016)(52116014)(7416014)(376014)(38350700014)(921020); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: GmaSTCy2mFix8QBtjoIqv6fps88lGxPWWNBrGs5NggzTOlxJYWtmKX795b/xrmg2KFYO6i+v8qzDiG4GqfODPGkUIqnPXngaD4IqQn8wfzqcpeaF5IyyF/LfBe3zdTlHqshLeMe631lMRSZml3e4PjiBwuMR4XwX0vUK86D82BABjeGcwPPfLeOkTkhWTaoPJP9bi7yQVfV/IefcSUX8/sJ3ejuyS5AON7BMLQTl4s+1Mk1K8BBjg/2aYfcb/fVymdktWWQUdjYUqHKADKYQFM4v2g6dv+IZ6kXAiUxE8P11fJWse6F0UOwrKdwLm83qOZgwl0zEiM6MdJRyXKu1L352I4ccUvCtcGouYw3dr/wWSdoIA4dMp8GWacPYZZI+hJzTy9OpmEv8tbNbmVrP225L/Xoa7xbKniYzruLhQixN5RqX6Ne81buBO2+vmt5Ux1/DzNlNcgsVAf9b36H1RLiEpP2MTLW6A81NiAyK80/diKBRvFz59iK8YYROc8F789kg5MlTEW4rRdy6+6D7B1UcAGlfkA0mcAuZJOCtIB9kA4YqOah9/edGhYW5t3tkfQQzyYuvPRl7W3luMgBXkrq28qbzUu1KK+nHJEhnLa2cEy6TszpD70rS1ledP6e9S0ubFFff7MW1qmO3xI5NKMAuTrd0jm9gwvH16eU6b4osvtodaZQmnR5gYsuPHUsSp61L3Z9g6pfVv1AjhNKz/q7vspGatrkAYgGM3RwaeyEGvPEkKrvQuV3kpxr09bIcJ7P97mzkI65Ib2iFmp2ilfJnopmN94lYWn7QEI4dwg9ukULeKS2zG+CtUuA//198VnoNYJUhraSAOLCxaw5bnDhacp7DCX2JHo9UOBibLFeglrwnWDEJkVixtyvrlUEw638og/7vMTzwlzvUXsPQhV6aE3qniItFyxqwnLvKVqgwSkVBskSqUoo+dC2n3ztZlX9fHwX05mbIkNOgQOMYKcUB/kwt5hw1Lg3silvPM0TKVShRn5+Fa4G2HK8kWDUeY64zcK0Pq97XxOfQsjk9QIPTq8d3XsZ3ZbHDZ8xjoO1GdMFD4C09K3aq1u2x+LNjfb1pM0uDYCfIUf4Uv6FihW1hpIFsASqcUSQF3/mM4yUffqwo0AQlvjNIrEjiLInKgovmhknh1GrCCQlrKJIZfC0vCcurGy/HZA7pvciUxNywzW6/4IjUyhza8cjv+03sFCYP56C2QmSU3k8ixFgRp6qGPCvz+zhATQA3QlNuQeBjDuayVnqtwmQNFfrTZRGY8r4gkkzoQy3F7mDgk6ocUTxi6qhScZxUO4bTg6SYsa1yUxGSdDLL9d3ycCQC+cUjs1Y7iHpdK9aGQhkkim1iwDGq3XHKnzpbpAundPOX8YSRGFWd8AlMTUlswNXDoC9LJdmk7EO9VeGJqyDYEyoKea7PS0VwAdYEqOdWoW17//emt0x5mkAqLHFAL8JKRyAjJ9dFvfp9NOAwEMCd/EVQ/DhHtU11O0J9Ew9GvDZeVZKA42JrJ2rmMHu87GU6QoqfAcW4AuV+J1EeQDBztdE5G+1LMk6FFtwwsodvUVZFADXPZKu3W2hQCW9Q+c6UfaX179FW8umjPzF7IItVQRFS1V/erA0E/GwPPIooAB9EA98= X-OriginatorOrg: iopsys.eu X-MS-Exchange-CrossTenant-Network-Message-Id: 0625bcf4-2ae9-4891-abfe-08dc969b1cba X-MS-Exchange-CrossTenant-AuthSource: GV2PR08MB8121.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Jun 2024 11:20:12.7386 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 8d891be1-7bce-4216-9a99-bee9de02ba58 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: x0xJ24tcAJP2QSI00sTd3UAFN4S7PToNtFre6GVQOj0FDEdE1TgnoFpunSMrL/luzKI7EeDVHiXkuRD4/OxILMQzQBhy4aZghqx70eaRyBc= X-MS-Exchange-Transport-CrossTenantHeadersStamped: PA4PR08MB6064 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 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" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Make use of the spi-mem direct mapping API to let advanced controllers optimize read/write operations when they support direct mapping. This is a port of linux patch 981d1aa0697ce1393e00933f154d181e965703d0 created by Boris Brezillon . Signed-off-by: Mikhail Kshevetskiy --- drivers/mtd/nand/spi/core.c | 185 +++++++++++++++++------------------- include/linux/mtd/spinand.h | 7 ++ 2 files changed, 95 insertions(+), 97 deletions(-) diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index 62c28aa422d..adc67d7a40d 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -37,21 +37,6 @@ /* SPI NAND index visible in MTD names */ static int spi_nand_idx; -static void spinand_cache_op_adjust_colum(struct spinand_device *spinand, - const struct nand_page_io_req *req, - u16 *column) -{ - struct nand_device *nand = spinand_to_nand(spinand); - unsigned int shift; - - if (nand->memorg.planes_per_lun < 2) - return; - - /* The plane number is passed in MSB just above the column address */ - shift = fls(nand->memorg.pagesize); - *column |= req->pos.plane << shift; -} - static int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val) { struct spi_mem_op op = SPINAND_GET_FEATURE_OP(reg, @@ -245,27 +230,21 @@ static int spinand_load_page_op(struct spinand_device *spinand, static int spinand_read_from_cache_op(struct spinand_device *spinand, const struct nand_page_io_req *req) { - struct spi_mem_op op = *spinand->op_templates.read_cache; struct nand_device *nand = spinand_to_nand(spinand); struct mtd_info *mtd = nanddev_to_mtd(nand); - struct nand_page_io_req adjreq = *req; + struct spi_mem_dirmap_desc *rdesc; unsigned int nbytes = 0; void *buf = NULL; u16 column = 0; - int ret; + ssize_t ret; if (req->datalen) { - adjreq.datalen = nanddev_page_size(nand); - adjreq.dataoffs = 0; - adjreq.databuf.in = spinand->databuf; buf = spinand->databuf; - nbytes = adjreq.datalen; + nbytes = nanddev_page_size(nand); + column = 0; } if (req->ooblen) { - adjreq.ooblen = nanddev_per_page_oobsize(nand); - adjreq.ooboffs = 0; - adjreq.oobbuf.in = spinand->oobbuf; nbytes += nanddev_per_page_oobsize(nand); if (!buf) { buf = spinand->oobbuf; @@ -273,28 +252,19 @@ static int spinand_read_from_cache_op(struct spinand_device *spinand, } } - spinand_cache_op_adjust_colum(spinand, &adjreq, &column); - op.addr.val = column; + rdesc = spinand->dirmaps[req->pos.plane].rdesc; - /* - * Some controllers are limited in term of max RX data size. In this - * case, just repeat the READ_CACHE operation after updating the - * column. - */ while (nbytes) { - op.data.buf.in = buf; - op.data.nbytes = nbytes; - ret = spi_mem_adjust_op_size(spinand->slave, &op); - if (ret) + ret = spi_mem_dirmap_read(rdesc, column, nbytes, buf); + if (ret < 0) return ret; - ret = spi_mem_exec_op(spinand->slave, &op); - if (ret) - return ret; + if (!ret || ret > nbytes) + return -EIO; - buf += op.data.nbytes; - nbytes -= op.data.nbytes; - op.addr.val += op.data.nbytes; + nbytes -= ret; + column += ret; + buf += ret; } if (req->datalen) @@ -318,14 +288,12 @@ static int spinand_read_from_cache_op(struct spinand_device *spinand, static int spinand_write_to_cache_op(struct spinand_device *spinand, const struct nand_page_io_req *req) { - struct spi_mem_op op = *spinand->op_templates.write_cache; struct nand_device *nand = spinand_to_nand(spinand); struct mtd_info *mtd = nanddev_to_mtd(nand); - struct nand_page_io_req adjreq = *req; - unsigned int nbytes = 0; - void *buf = NULL; - u16 column = 0; - int ret; + struct spi_mem_dirmap_desc *wdesc; + unsigned int nbytes, column = 0; + void *buf = spinand->databuf; + ssize_t ret; /* * Looks like PROGRAM LOAD (AKA write cache) does not necessarily reset @@ -334,19 +302,12 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand, * the data portion of the page, otherwise we might corrupt the BBM or * user data previously programmed in OOB area. */ - memset(spinand->databuf, 0xff, - nanddev_page_size(nand) + - nanddev_per_page_oobsize(nand)); + nbytes = nanddev_page_size(nand) + nanddev_per_page_oobsize(nand); + memset(spinand->databuf, 0xff, nbytes); - if (req->datalen) { + if (req->datalen) memcpy(spinand->databuf + req->dataoffs, req->databuf.out, req->datalen); - adjreq.dataoffs = 0; - adjreq.datalen = nanddev_page_size(nand); - adjreq.databuf.out = spinand->databuf; - nbytes = adjreq.datalen; - buf = spinand->databuf; - } if (req->ooblen) { if (req->mode == MTD_OPS_AUTO_OOB) @@ -357,52 +318,21 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand, else memcpy(spinand->oobbuf + req->ooboffs, req->oobbuf.out, req->ooblen); - - adjreq.ooblen = nanddev_per_page_oobsize(nand); - adjreq.ooboffs = 0; - nbytes += nanddev_per_page_oobsize(nand); - if (!buf) { - buf = spinand->oobbuf; - column = nanddev_page_size(nand); - } } - spinand_cache_op_adjust_colum(spinand, &adjreq, &column); - - op = *spinand->op_templates.write_cache; - op.addr.val = column; + wdesc = spinand->dirmaps[req->pos.plane].wdesc; - /* - * Some controllers are limited in term of max TX data size. In this - * case, split the operation into one LOAD CACHE and one or more - * LOAD RANDOM CACHE. - */ while (nbytes) { - op.data.buf.out = buf; - op.data.nbytes = nbytes; - - ret = spi_mem_adjust_op_size(spinand->slave, &op); - if (ret) - return ret; - - ret = spi_mem_exec_op(spinand->slave, &op); - if (ret) + ret = spi_mem_dirmap_write(wdesc, column, nbytes, buf); + if (ret < 0) return ret; - buf += op.data.nbytes; - nbytes -= op.data.nbytes; - op.addr.val += op.data.nbytes; + if (!ret || ret > nbytes) + return -EIO; - /* - * We need to use the RANDOM LOAD CACHE operation if there's - * more than one iteration, because the LOAD operation resets - * the cache to 0xff. - */ - if (nbytes) { - column = op.addr.val; - op = *spinand->op_templates.update_cache; - op.addr.val = column; - } + nbytes -= ret; + column += ret; + buf += ret; } return 0; @@ -815,6 +745,59 @@ static int spinand_mtd_block_isreserved(struct mtd_info *mtd, loff_t offs) return ret; } +static int spinand_create_dirmap(struct spinand_device *spinand, + unsigned int plane) +{ + struct nand_device *nand = spinand_to_nand(spinand); + struct spi_mem_dirmap_info info = { + .length = nanddev_page_size(nand) + + nanddev_per_page_oobsize(nand), + }; + struct spi_mem_dirmap_desc *desc; + + /* The plane number is passed in MSB just above the column address */ + info.offset = plane << fls(nand->memorg.pagesize); + + info.op_tmpl = *spinand->op_templates.update_cache; + desc = spi_mem_dirmap_create(spinand->slave, &info); + if (IS_ERR(desc)) + return PTR_ERR(desc); + + spinand->dirmaps[plane].wdesc = desc; + + info.op_tmpl = *spinand->op_templates.read_cache; + desc = spi_mem_dirmap_create(spinand->slave, &info); + if (IS_ERR(desc)) { + spi_mem_dirmap_destroy(spinand->dirmaps[plane].wdesc); + return PTR_ERR(desc); + } + + spinand->dirmaps[plane].rdesc = desc; + + return 0; +} + +static int spinand_create_dirmaps(struct spinand_device *spinand) +{ + struct nand_device *nand = spinand_to_nand(spinand); + int i, ret; + + spinand->dirmaps = devm_kzalloc(spinand->slave->dev, + sizeof(*spinand->dirmaps) * + nand->memorg.planes_per_lun, + GFP_KERNEL); + if (!spinand->dirmaps) + return -ENOMEM; + + for (i = 0; i < nand->memorg.planes_per_lun; i++) { + ret = spinand_create_dirmap(spinand, i); + if (ret) + return ret; + } + + return 0; +} + static const struct nand_ops spinand_ops = { .erase = spinand_erase, .markbad = spinand_markbad, @@ -1112,6 +1095,14 @@ static int spinand_init(struct spinand_device *spinand) goto err_free_bufs; } + ret = spinand_create_dirmaps(spinand); + if (ret) { + dev_err(spinand->slave->dev, + "Failed to create direct mappings for read/write operations (err = %d)\n", + ret); + goto err_manuf_cleanup; + } + /* After power up, all blocks are locked, so unlock them here. */ for (i = 0; i < nand->memorg.ntargets; i++) { ret = spinand_select_target(spinand, i); diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h index 13b5a52f8b9..5934b7604cc 100644 --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h @@ -363,6 +363,11 @@ struct spinand_info { __VA_ARGS__ \ } +struct spinand_dirmap { + struct spi_mem_dirmap_desc *wdesc; + struct spi_mem_dirmap_desc *rdesc; +}; + /** * struct spinand_device - SPI NAND device instance * @base: NAND device instance @@ -406,6 +411,8 @@ struct spinand_device { const struct spi_mem_op *update_cache; } op_templates; + struct spinand_dirmap *dirmaps; + int (*select_target)(struct spinand_device *spinand, unsigned int target); unsigned int cur_target; From patchwork Thu Jun 27 11:20:00 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Kshevetskiy X-Patchwork-Id: 1953182 X-Patchwork-Delegate: dario.binacchi@amarulasolutions.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.a=rsa-sha256 header.s=selector2 header.b=xLIQZguN; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4W8x273kCTz20Xg for ; Thu, 27 Jun 2024 21:20:31 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id EF80E88569; Thu, 27 Jun 2024 13:20:18 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.b="xLIQZguN"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 8420B8852A; Thu, 27 Jun 2024 13:20:17 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,SPF_HELO_PASS, SPF_PASS autolearn=no autolearn_force=no version=3.4.2 Received: from EUR02-VI1-obe.outbound.protection.outlook.com (mail-vi1eur02on20700.outbound.protection.outlook.com [IPv6:2a01:111:f403:2607::700]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 714138852E for ; Thu, 27 Jun 2024 13:20:15 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mikhail.kshevetskiy@genexis.eu ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=eb4VCdhW65/s6hdoey8DK1t/6U13zJLTTR3HpCBNlh6dyhlMCna7LvTHYOuNlT8bClBRgy99s5tvJhVRUc/pdYfMJyqN6pK0o67WAGSwIchnTQZW2a44/lxQDm//5ghHsAmG6eJd3BO+cEzw+4+6deu/oGIchjrbxsxyu5I7uDg3bsIva1KQEvU8hzD1Rojd6YUFoWXV4aFwe3BrQzsuUlSg2XOWQ9elDPfveefc7fVfZwV+cpbsVc9qQOfp7/0amiwx9Y7Ov3R9JqSeEqhXH9/YseC/B5rH06DvPSoOsuKwGBO6zM0i9E36bea12V6dzEJB6p2gHHNlMd0jmfrQPw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=Q66fcJbJjM2OxpF2cxI0+3gtEFaeBOuxQRfFS1WPzyQ=; b=VvF8UAhhC/Asza/3FrA52eYne/Y9uRZAknZZcqUIaWRlVipqSz+FP2/KvKtso6IlS6mqOOfN85i5b3y5Kf6cxkxJTRHpU2+di+UvEE0PgSxRX5gHtYfY30Qzk9r2Kkh1oKLezlWe36++UwtmTdQc6w5hKs3Lcy3GTXsCvhjaDvPGdOBAh0WfBP4176Fzd1agNV3kOYaUEX9ayeg78pNpjkykBQOR9lWi5MBRvJENu9xU44nuGnuN4k1+Xw1FJdqpTkbMEmZqqC42hJkmMQRsANwLnkgCU7wkaYnLnM81rydP6qQyhMy3yPSQvpZXlBxiSvw6xc+OtS2x5ZugsEof1g== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=genexis.eu; dmarc=pass action=none header.from=iopsys.eu; dkim=pass header.d=iopsys.eu; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iopsys.eu; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Q66fcJbJjM2OxpF2cxI0+3gtEFaeBOuxQRfFS1WPzyQ=; b=xLIQZguNBg2PY9KI5eI/U3flSR2QqxPFjKzK0/ep4R2KpYS438miGxCExnFYWoeyEuHxBkJ0b8hNcTdtMotfQtyKNf8ZiHEY+S+vamO1KsSwzp/BJBUCR+3G5RgAypEcKDlZRqRzQm19Iv+elbszRQogmECpQLZOK5FMQq9UCp6OGPKuNnWHZUqYCoq5jpA94azNEbIlCrfwxKtMBNqzHmCJ1ACSiQdM4nloupQ11zq/qJV1yFwbm81RePVaiPmow3TNZhKFhXDBJ2quAH2huO9MBbyC1OvogskYw3AG1rEexsZg02Nuj6MEdmwL1A/F+p8hIFhp+Bx3RK60/xHNTQ== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=iopsys.eu; Received: from GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) by PA4PR08MB6064.eurprd08.prod.outlook.com (2603:10a6:102:e2::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.35; Thu, 27 Jun 2024 11:20:14 +0000 Received: from GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0]) by GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0%5]) with mapi id 15.20.7698.025; Thu, 27 Jun 2024 11:20:14 +0000 From: Mikhail Kshevetskiy To: Tom Rini , Dario Binacchi , Michael Trimarchi , Frieder Schrempf , Jagan Teki , Simon Glass , William Zhang , Igor Prusov , Bruce Suen , Dmitry Rokosov , Martin Kurbanov , Chuanhong Guo , Miquel Raynal , Francesco Dolcini , Max Krummenacher , u-boot@lists.denx.de Subject: [PATCH 2/7] mtd: spinand: Add a NAND page I/O request type Date: Thu, 27 Jun 2024 14:20:00 +0300 Message-ID: <20240627112005.99375-2-mikhail.kshevetskiy@iopsys.eu> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240627112005.99375-1-mikhail.kshevetskiy@iopsys.eu> References: <20240627112005.99375-1-mikhail.kshevetskiy@iopsys.eu> X-ClientProxiedBy: GVX0EPF0000FA79.SWEP280.PROD.OUTLOOK.COM (2603:10a6:144:1:0:4:0:6) To GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: GV2PR08MB8121:EE_|PA4PR08MB6064:EE_ X-MS-Office365-Filtering-Correlation-Id: b2459e5b-2331-4b51-be9a-08dc969b1d87 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|1800799024|366016|52116014|7416014|376014|38350700014|921020; X-Microsoft-Antispam-Message-Info: ZEQpOwxFfcW2ruOvpeIhZjXXlHWeahct4h20+r/udeW18QH6yz2Vx2LygvmRnIcooStxr+oZNc8BY3PI8v3pFE8mcHI9RmtK0cGX1dj2Jw2vYlDlA0tqZaM6w9733+HpaeGfGq9ei/CNlHpXmrld3n37mZzWTGEOFj3QF/pJSvhUtgzfxTSq04NIcne8BPuby6IwkMKx/Lv8a7YHRbaT3gRXw6o8A7YD7v3wu/RT6gwUy6R6VghlyMNkI7MZ1YbCnStLC0VEZ3bCs14QZuQDxEx25J6GtvbkE5sGzvIFxYYiuETplztH+1tsAz/8lIP+wTMqoiil2XBlfTtA4BrLHbYbGDI2fIXb8cn9H+CKejyAHHZ76sRi+bfTb/1c3mewomWohCmr/FgCUaZzNTtqMhaYjAVQQxorT23Xjr8vokU1IZiMTq9GmH7ifqJDEXVbkncFwy1rMnzrFgT0I2VHpgS6Wxhjo3+FdNlROx4oyzIsZTbo0874Xagr8nrBt/r4LdZ6aNHmC9CpK2GipthC+a/5Da+tI/Z4pnxoIIQ31pqELoFpInMcer61STDeZvvXZk949FwbBQxlj0kNi4QowDBELSrOEcmv7nG6k+afBGwOviKUnctw7u0hXUoXza9Zh25GwBbMj6y++jI7SAa/NGf0ecbtPJcIy8lMU/5di1gvOljFbAlvvnYjC1pt2Rx1pgxVLTYrNy5H75CNGs/pWDjdAF4HVdt+AcPqVUbQji5nJBo7a9o4eDfpccBqKQUFFmyt/6AH1Gr28gSLLU7QTWHh7qjxsuq1ePMuzh+fzI7NsrdQXdnij7ed/6xZmGtdNp3cqmt2aLGdtlY7KyCODurGwV1U3R2FU7Uae/w5nFQe5Zf6K43j+aWh4vAa032wqxJ85NUF2AEDbql4lPKHR3Mzx6hVzWZgQhtrj7x2Bp7IIRnI4ETeoJH2sTlUbdIk58/4mz8m2DfnDq86iZNwqSSs7Tu5ewJuaoKgYf553L9tosM3Dd0S0U7xckFCYaFoXtxPpeFY19TcsKaUjveshJ1Dxoxsrw31pjdQEA1Zc8fdh1mMA6eJZt09q7etAPXUHCEK8Ysp1HlkFiP4zoa7Qw+p3JcbT3fntBgoTkzOPOw5VREdHUJpO+g+LvBQTAx/hqHCwFoCs+O26qkS/DlB+g83iJN6pmpFAIXjHP6hPRjwKW+i1BLPEy/ZsqjcxkgjlGRptjsC3HSExJaBmOKc4Prcxg0/WBxM5BDKGnmhX4Xptmu7CEjmqmdVSzb7d3d9oVQ22qyRvMbx52+82xCcsMdXOG1UyEGRkCMDubqmFuXuAdSWPntZAxzagbnmbCfATMSGAkUnXxt67/KdyO+grpQFTRIRv9Ystc1HvDqBLuqSZKGaERcw1OMrqOp+V/C5h1aZWGe6fg/VMTtc2Sam32akwWfcqQYp2QAZP7agW5U= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:GV2PR08MB8121.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(1800799024)(366016)(52116014)(7416014)(376014)(38350700014)(921020); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: bJJzAzzsn2Kdriz1HU7bOSPDWTH61SnoodDlS6Y24iqFWlpi5re/Qf4u1vrcRAyZ4rdY1z99xsRGW1Ug8sWI70zm/J862BAXQp94wdDQNC0Wsx9kp6H6dljg0uYcWA5ciPzT2oSGCTfXWVraq73k8GEcch+JfdPnzYEzNJ/lsk3S12CzM1QPLel6/S2HhFf0Dpxr7dA+x+dMPbEltc6h1tTzK9V0CTW0l7Nd5A8ptztFMz10PeYdH2WrutMTx54XiPcXUk34wG9WEpbcWqAlHYPAuG2IU+dv8W7M6jPooA2uD3MkwXzYxSQxlzxWo1CCodI0fGa2+NpRvzqlPUH3TIHL7ye0loiz4hENmAopB4meNjxK91HY+X3UartotByzW8IjVVa0N4k0km1FQ/bfzew0aMsixGS1aRLLCVVysraJNAKITe9ZYDDpHHtaN5zlSLIdlGRIt1eQS+pTSscZJWi2t7MGg+6kpQme8eWHrxNTwagDQXUCa0mAahzNhYfzJWIzt+C2BZ53XkWzKClrU44o8pnrvSz9AySyoAZ3sdZUD7oMdP8qFikoFNtK2Okhw9XJttycFTYQwYyTUQDZKLNzfmAXAhR9Rn/dTeL4kDvLJ5/oeykSl8Uxsic22l482yu98OyHZBS3lEQKcd0fE9YFD0S8H+ncO4FGr743XActwLsKjpdiyVY22SMChhcr9Yyv15EwS+rBC8eXDg9ou6xg/k/UHjRHj3/rJiJKkmZjCo7yvHA4dEOq4Udlu/Ih2qT2fhPJDqVW4uHb/XOtr4Gj1O46QsMzcpsNAjik7Gjp2yl0gLnLuuhROqAW3bv50A8dLwgWOIHRCOrFOEY28b88zl1a7qrd2wC5SGnXmNyxUm+uNpVlzwIahpMd6l7ZuFaXu1snWJN51kVrafwcrf+2nELzlJah5TFadl//DcLXhRFcHuzLaJhhuf0PP7mWUZ3kaTwnt/ADHVbr8qOpMUmCasxLCNaU9JM7JUU8E/T4KjdwvYFTGfiGPNcc5uKKQmf0jQz1dL/iF6/8by8bMQyC+EWwLbmjh+X8Dgp44IT5ihsXuG5FOOlDEjNvkWQXHQO91tHtxQChpvxLdk/Nf5VP0CGb9T2ZkOtgPePkS9NDcF5nt97sMeI05fD0JCzl7Zs+amaBu7Mwe1XZ3EOZM4JIPpx9JR6sTgi+NpLqk1XnAWxpuYLOXGyRoDdbcTpTwRRp5kTBtoWORCqdDTTbtfHC1DhTwdkkS+JrRGuzYO874KwC7NYCKcIRUQPzZ3hbFxmdJkRFzLOW8kpk42MU7wrzpomaU+YWdBR4lhuiK09Inj2y6Fk3Q+HsDkk/pD6X4M59Mu/dKFf0a5GylcIYbXgpYInLv30L92Ghj6m3bnRgrRcMsJlAv29tihO2m0aN9COQ9nwW5+Oy3DtHfhzhnm2duck4mamkc0fxxJSP/46KYEAHLHJrNHs6DyeBXlYWAhIpt8wSp22jO2wDqC7wPIkMx0X5b5KM1xHwXnTiz6JoPc2GZLkRkjaXp3cNmV2umzu/+M3QvhbDcSEGnOf7dKeDXcPXpdMeG86k628XkbzI1wSV/np0ECtLGb56IhBJj6J5p+uDHLsUTlgouIPH8RWTwc1s0WbkQ+4eDmSw7uY= X-OriginatorOrg: iopsys.eu X-MS-Exchange-CrossTenant-Network-Message-Id: b2459e5b-2331-4b51-be9a-08dc969b1d87 X-MS-Exchange-CrossTenant-AuthSource: GV2PR08MB8121.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Jun 2024 11:20:14.0938 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 8d891be1-7bce-4216-9a99-bee9de02ba58 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: NvJX5JC3OfuYhx4eUGDlFj5jsteFt+fjAitH4EJP53ZNnVXAPkYUtdM2xV3atGbMAaijo9dXd2OLBW95QsG1LAojCCVZdt5+fCd8sgqsjy4= X-MS-Exchange-Transport-CrossTenantHeadersStamped: PA4PR08MB6064 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 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" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Use an enum to differentiate the type of I/O (reading or writing a page). Also update the request iterator. This is a port of linux patch 701981cab01696584a12e5f0e7c2ad931a326059 created by Miquel Raynal Signed-off-by: Mikhail Kshevetskiy --- drivers/mtd/nand/spi/core.c | 4 ++-- include/linux/mtd/nand.h | 18 ++++++++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index adc67d7a40d..f10a3dbfdff 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -519,7 +519,7 @@ static int spinand_mtd_read(struct mtd_info *mtd, loff_t from, mutex_lock(&spinand->lock); #endif - nanddev_io_for_each_page(nand, from, ops, &iter) { + nanddev_io_for_each_page(nand, NAND_PAGE_READ, from, ops, &iter) { schedule(); ret = spinand_select_target(spinand, iter.req.pos.target); if (ret) @@ -571,7 +571,7 @@ static int spinand_mtd_write(struct mtd_info *mtd, loff_t to, mutex_lock(&spinand->lock); #endif - nanddev_io_for_each_page(nand, to, ops, &iter) { + nanddev_io_for_each_page(nand, NAND_PAGE_WRITE, to, ops, &iter) { schedule(); ret = spinand_select_target(spinand, iter.req.pos.target); if (ret) diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 651f8706df5..0afdaed5715 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -80,8 +80,19 @@ struct nand_pos { unsigned int page; }; +/** + * enum nand_page_io_req_type - Direction of an I/O request + * @NAND_PAGE_READ: from the chip, to the controller + * @NAND_PAGE_WRITE: from the controller, to the chip + */ +enum nand_page_io_req_type { + NAND_PAGE_READ = 0, + NAND_PAGE_WRITE, +}; + /** * struct nand_page_io_req - NAND I/O request object + * @type: the type of page I/O: read or write * @pos: the position this I/O request is targeting * @dataoffs: the offset within the page * @datalen: number of data bytes to read from/write to this page @@ -97,6 +108,7 @@ struct nand_pos { * specific commands/operations. */ struct nand_page_io_req { + enum nand_page_io_req_type type; struct nand_pos pos; unsigned int dataoffs; unsigned int datalen; @@ -613,11 +625,13 @@ static inline void nanddev_pos_next_page(struct nand_device *nand, * layer. */ static inline void nanddev_io_iter_init(struct nand_device *nand, + enum nand_page_io_req_type reqtype, loff_t offs, struct mtd_oob_ops *req, struct nand_io_iter *iter) { struct mtd_info *mtd = nanddev_to_mtd(nand); + iter->req.type = reqtype; iter->req.mode = req->mode; iter->req.dataoffs = nanddev_offs_to_pos(nand, offs, &iter->req.pos); iter->req.ooboffs = req->ooboffs; @@ -687,8 +701,8 @@ static inline bool nanddev_io_iter_end(struct nand_device *nand, * * Should be used for iterate over pages that are contained in an MTD request. */ -#define nanddev_io_for_each_page(nand, start, req, iter) \ - for (nanddev_io_iter_init(nand, start, req, iter); \ +#define nanddev_io_for_each_page(nand, type, start, req, iter) \ + for (nanddev_io_iter_init(nand, type, start, req, iter); \ !nanddev_io_iter_end(nand, iter); \ nanddev_io_iter_next_page(nand, iter)) From patchwork Thu Jun 27 11:20:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Kshevetskiy X-Patchwork-Id: 1953183 X-Patchwork-Delegate: dario.binacchi@amarulasolutions.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.a=rsa-sha256 header.s=selector2 header.b=ir78nJK7; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4W8x2K1lVkz20Xg for ; Thu, 27 Jun 2024 21:20:41 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 6253388578; Thu, 27 Jun 2024 13:20:22 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.b="ir78nJK7"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 041B888571; Thu, 27 Jun 2024 13:20:19 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,SPF_HELO_PASS, SPF_PASS autolearn=no autolearn_force=no version=3.4.2 Received: from EUR02-VI1-obe.outbound.protection.outlook.com (mail-vi1eur02on20700.outbound.protection.outlook.com [IPv6:2a01:111:f403:2607::700]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 11B2A87FC8 for ; Thu, 27 Jun 2024 13:20:17 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mikhail.kshevetskiy@genexis.eu ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Aqo/RMJFXVEGUMEvnBnboRV4L74RZlk9ZDQBXombi/Qh+AiOOrRZM72O9EK0zVEsjmKwm6Vwf1A+va81Pyi44DlsLlZPH1+Mv7jW1d+PpROR00EKF/wrOq4uS4hqnO0CNzSh2XLFb7uH+CoNlXRCgax7bjnYI4dtlh9oIDAtwLXJrjwwZrE7PoocDoACal8JYIJZQSs0nt2Mdqw15YNLqQ4VXDT0o4RdmzTH5hff0XWqjMfNG6uFhKtstK6W6Q4GfH2PFwqm3zPQmtCI74sDBhIFvMh04quknYDO0qghx2IgoaNT6d0W5c8BLXSJHGGLR5La+dzTCDqn6fa5KimXMA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=DquJsJZxclfeFxIAHRTcuvvuMY7RMYPK+T9PA/wUJDc=; b=JJSBfbZTRnT3sFSo5kTapZMfg6jLcy2lN6UrFkDIquAW/8atclyO5UVY614rwUvSR2cUpjDSUhow/Cz1jFG7ZKVhcHTHVbneSfK+8XTQfm4EIv0IiHZPbPpVERRygodHl/IG4tdgXoWF85UComTeqdUIcUOJEu961ZcSoH3Ff5Bl6HDPu/vIh6X1qwEldSdrfUpmOuDuBSZtI+JqCov1kZNDojz5unQF1hLF/5VLU4Y7V6OG3esxRCtpDG8IfwZOuA2q+F33YX+7iSy1gPzbhg61C85I3eZZdRiqFKgLhDFTUoNgAp7II18TItihJ1dmhxymYV2nkA3GR/8NikbXZg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=genexis.eu; dmarc=pass action=none header.from=iopsys.eu; dkim=pass header.d=iopsys.eu; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iopsys.eu; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=DquJsJZxclfeFxIAHRTcuvvuMY7RMYPK+T9PA/wUJDc=; b=ir78nJK7/TTezoboIOOIDu4Y9pxGsjPDdzlJ0voPWuj0rbEtdqLdkelD/4TcGpk8FGm6A3BUkMqIUzXBENXsaQrRFwTdVOKkl/bVq+pbpzU+4CsjBTnEfA9sNpHkf/IQOdAfW0tBAMllstC2zUhiW1EuQTQyMV8ZwOvUr/o6dCVq34MWZIGZYKgBGrpjscuujcmKmkzOwKFrmB7TcwaPXa5hgn8v5ZY3Hn/J8+7GTTPSHtoiNDSF1RJrc3DPfa79loVDmVkDbHhrNt96cV+BCo3nbAhOnyJKK4YjTWmo8IRJMH7MZ4sHcWvz+udv2iX6sAdB5CBZM3A6CWWwD5X4Tw== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=iopsys.eu; Received: from GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) by PA4PR08MB6064.eurprd08.prod.outlook.com (2603:10a6:102:e2::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.35; Thu, 27 Jun 2024 11:20:15 +0000 Received: from GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0]) by GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0%5]) with mapi id 15.20.7698.025; Thu, 27 Jun 2024 11:20:15 +0000 From: Mikhail Kshevetskiy To: Tom Rini , Dario Binacchi , Michael Trimarchi , Frieder Schrempf , Jagan Teki , Simon Glass , William Zhang , Igor Prusov , Bruce Suen , Dmitry Rokosov , Martin Kurbanov , Chuanhong Guo , Miquel Raynal , Francesco Dolcini , Max Krummenacher , u-boot@lists.denx.de Subject: [PATCH 3/7] mtd: spinand: simulate behavior of linux's function spinand_wait() Date: Thu, 27 Jun 2024 14:20:01 +0300 Message-ID: <20240627112005.99375-3-mikhail.kshevetskiy@iopsys.eu> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240627112005.99375-1-mikhail.kshevetskiy@iopsys.eu> References: <20240627112005.99375-1-mikhail.kshevetskiy@iopsys.eu> X-ClientProxiedBy: GVX0EPF0000FA79.SWEP280.PROD.OUTLOOK.COM (2603:10a6:144:1:0:4:0:6) To GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: GV2PR08MB8121:EE_|PA4PR08MB6064:EE_ X-MS-Office365-Filtering-Correlation-Id: d2dcb8f3-bc1b-461d-3c50-08dc969b1e52 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|1800799024|366016|52116014|7416014|376014|38350700014|921020; X-Microsoft-Antispam-Message-Info: HqC0kX26uQMarsmfmIA4PIw3oHlWmUg3LhY1hJpxQW3dPNzGTip+nod/2+fjqd/Xd5WhWUmoe4DManhG5cPG5I33SXodujTKBkdpf+y6z+pAaSXG8my/h1tLDT2jswQpHJyd/3AcuOWKTaJz9Bdu9+noYkQXzvxxBdTnai2S1+qhpUHCXoCgyKXc8XTXretOSkWNJqzMNeqzhofd0m8qIt/A3j/YGy3xHs8Dm6nbfoJShTl+vOD5v0KytuUvqPM6HqhOCFjbKX9fkE72l9MpQ68hkxD4fXj9sbW+vHT1v0OF+UbyzOsdX4GFXkElIg3XGV4kN/j4xiieQlushix1Uyx+937ya/ADvzv5cNOCMNVP61OCC725WPB7E31WW0b7JwLq4+CgmT1MuWm/N3eSYQQtdCeJxckjPuejYGyv4kl4C17GWKMNr7h9c2eg98K15Mk2a1KjJacsxDz4dMqZn3xa9vJ2TkKtVPAhboZtvXYbkAZ75qS5jJEp9+gNIS0SUjTv738MONYmn65su6yhsvE8R1ev28kIWo9yU5uJTYy0Jj/co9p+lylCQBg/NUAZsViqG6N2fq7sxwPO/U9A0ZQOt8B/U3XjDbiZXkA4CSMShXLSDdC57qg31pk8RiDD49LtnS3l/9aPkTyBvMqd8XNvX+p6W4X7hrgDC8gn3h9xWjXqfC+qYgrfpS+FaJa3AVaG9pARErbpjVTEMsN3wVuG2U9TEk6Lz+PHGRT+peL12nKLmg8Pa+A7kCNwrM56SGadeczHU1vg7a8H3Q3GtYa/5qOguYj2IUOqDARvBI8OI9IPbNJkkcYGHsZ7p3CXR4f4d+GxquOtwP6UA+pw/feGBFSo+9+4vRD4WzpmLdUtDD/rChE2XB0yy8kRu8+kkrKOxIpWYqGxDIuKi+nKlD43qNygi7QcZjYhSp/iosJjGO6M9nem+LXHMp/j/aif5DIrwT3csaepPv/eXdEBzR4G+bCZcgAvf9Sq2oVi3muHW9yGiuUzyujAwtIqWMNFawhKHtWp6LEUw483tE+THv/BVHqaWvpkI2eeNu3+NmaJ2PMyluvwuU3KdIYmLRe2Z1090hZa62AkNvUrqlCvyoWRREX1cNF0oU8lw/GUef+FvAO5cKKH0E0tPOFQVWSr0D3vv/d2NfJ1iMacSlpEGNxIniFw0sgh4NmgBGHJY1T+ZnMgUDuA+g7s7czWiE4Ux4ddJ4NBVUX0kHbP1RtXtd97dNnCb/5nmfm69W9I+48UzT4KYSdaZhhsRwd7z0P0x72YIY/zDgX3CJLz5XmcT/Ip9ilt4hoijQBgwpn7AitzUJEcCIpKrSTBHmSTxXBn0kspgnH4TZtR+2pV+GcG5NxNNBUqLsW4fvEBO7QgJR0Ad3Hvb188rm1zoM3V43DhpEv4na+DuTHgNG/NZSEBRueSojCEoOuBoecRm4WG9pg= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:GV2PR08MB8121.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(1800799024)(366016)(52116014)(7416014)(376014)(38350700014)(921020); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: +JI7YYnGib/HfQe5Xf8qnym1S1jOAj9FnbRlRwBUhvsxKqzwkklX2AMsaCwHNzuJaoo9kVaGjrLsggKB0kCVXBfxs4voOBs7iOHe50aVPPbMMfflLLWmg1lBSSqLpHA7X1I9v4W63YCLx+U+R6dfRsCLYbzMZBRVS//cnwMVSEXPxGVJ1nIdAwgapS1kOFGq/uLqEIJo9rC2+xnIAjFsyExgyWDfgIwSoLavm9qc1ygD5mZ7IkQsG/m1FFlRI+kt7Q8lDJpgzfTRkBwL7iGtj1vlqaUn18/j5u2zblAwmIuXFsd46JAeiw6SwTNvqLSTV6xtR+N7/y6AnMl1kft6XJSoH7VdlookKtKbsbiaCahDHEzB2P2w5zrG4xDiGNSgI7rP2AHtCzb06UTHj/4z58b2gHaN7Mm63WZ3jMR6BBZ/Vh6ztIKjNDDrqI8iYdlXQrp8uVXT+dgc4eJFJyCalmNoyZRdi9CteeTDozHJSZD8RXwLNUVbKjgzpLlolr3wYx5GtYTCDz8ZnxVscZaEGvTt3P8GWBALWebdtk8WFMyxjA08cepz9/0rm+7IVnf8BcqVzKiJ1yl8nlBs4+nFss1nMt+vH0SwftPsmmDa04QzV14GMnWAsI6QxzSWKBv9MlVSmxBOc7Jzl8sFKL6Vf55m7/uOei4XNUdrOZZGkWadAD787K5uH/U+h+byT3eFD4amZkrQ2Y5YYxsdpcBLCq6q3vp3PsDK0/U0KnMWP0YAUaLFWR4dJ7YoCvscprCY2tEyUz9sw4zgHjvXUfY6moeNuRtzBqvnXBSRP5PemB6Os6ISREDS8GBIvLjYAnXtxolOXLRhdu+Lazq0agr0Vb3rR4PQ2wnbOblDEPcM01cvdKan0PF/IuKcijrarajMWtdizV0n7vpUdPae6Q7KQ254iPwUars7FAK0qk90rseb/e7gP6H7SXa/5maqTT0sLpedesVI3JSFabIzIUuJuTfPwNhzmWkq05bYJvIDd6iU/14swd2A13Tt3lvqtK2t7HEHRzmPJkJw9jUV7MvKVhhBMh5ySe9aWe9nPKYRYNuY2T2oYN0evS9baT3uhOrIEPScphFRR8srurm/sQwt8xk/9dgw4rmEZZ6SmwVvZJJUvKzFC5P05hKbU60laVgkcQhQsFMpuu0A2V3egg4OiP0cG5QI3CdUTUPutMZqBaq1XWuDoOJV1fQuPkmn/iHpkXZZRBA9hl5KGwyoDG3dL8DhTPy9gGM9gzZzBIHWxVYyOQleVy6prKlD+fV9/1WdrzSTiTmEdvnh2MAn6fRVxMfJjtyJnbxzG4V9S6+MHQzLDiGg+lTeCxucivU4s1sGnRyni9XyxPJC/tZLNXbfm9sCH8xBqILGOkrFX/ZFkuXJg4TAje3mfgj7gEDOR3jH0Txtfm7BbLd3yzeSpHqnguuCrj2zCkimJx4Iei4YXLd7dRmRht06uqlPP5kFe1Cdi80iwkkrM7s6eEWUDJ4ua6VfsCT6av4Wv2B5m45YoRYAX7qseppbL7MzppaXbap9ooNpZNfOKaiJMzEYDbUZtYNR35/KvJKfIlgHPXknoRxKBXLIt30M0eYC14TYE78DFGmjUF3wLm7mY3Ukk0vJ+LxCFeYoQbOI1kuwl42DE6Y= X-OriginatorOrg: iopsys.eu X-MS-Exchange-CrossTenant-Network-Message-Id: d2dcb8f3-bc1b-461d-3c50-08dc969b1e52 X-MS-Exchange-CrossTenant-AuthSource: GV2PR08MB8121.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Jun 2024 11:20:15.4056 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 8d891be1-7bce-4216-9a99-bee9de02ba58 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: V5P3jFCcqHZoEMVF77xdSlN8AVug5dHauoUxJ4i7leWu7EsB8HH3jEA/Azq5gXFM8ivUeHthn9CC79CMQaduDU93I/+Q9VBYRThHdcy71MM= X-MS-Exchange-Transport-CrossTenantHeadersStamped: PA4PR08MB6064 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 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" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean also call schedule() to allow periodic actions Signed-off-by: Mikhail Kshevetskiy --- drivers/mtd/nand/spi/core.c | 35 ++++++++++++++++++++++++++++------- include/linux/mtd/spinand.h | 22 ++++++++++++++++++++++ 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index f10a3dbfdff..8664e882753 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -32,6 +32,7 @@ #include #include #include +#include #endif /* SPI NAND index visible in MTD names */ @@ -358,21 +359,29 @@ static int spinand_erase_op(struct spinand_device *spinand, return spi_mem_exec_op(spinand->slave, &op); } -static int spinand_wait(struct spinand_device *spinand, u8 *s) +static int spinand_wait(struct spinand_device *spinand, + unsigned long initial_delay_us, + unsigned long poll_delay_us, + u8 *s) { unsigned long start, stop; u8 status; int ret; + udelay(initial_delay_us); start = get_timer(0); - stop = 400; + stop = SPINAND_WAITRDY_TIMEOUT_MS; do { + schedule(); + ret = spinand_read_status(spinand, &status); if (ret) return ret; if (!(status & STATUS_BUSY)) goto out; + + udelay(poll_delay_us); } while (get_timer(start) < stop); /* @@ -414,7 +423,10 @@ static int spinand_reset_op(struct spinand_device *spinand) if (ret) return ret; - return spinand_wait(spinand, NULL); + return spinand_wait(spinand, + SPINAND_RESET_INITIAL_DELAY_US, + SPINAND_RESET_POLL_DELAY_US, + NULL); } static int spinand_lock_block(struct spinand_device *spinand, u8 lock) @@ -462,7 +474,10 @@ static int spinand_read_page(struct spinand_device *spinand, if (ret) return ret; - ret = spinand_wait(spinand, &status); + ret = spinand_wait(spinand, + SPINAND_READ_INITIAL_DELAY_US, + SPINAND_READ_POLL_DELAY_US, + &status); if (ret < 0) return ret; @@ -494,9 +509,12 @@ static int spinand_write_page(struct spinand_device *spinand, if (ret) return ret; - ret = spinand_wait(spinand, &status); + ret = spinand_wait(spinand, + SPINAND_WRITE_INITIAL_DELAY_US, + SPINAND_WRITE_POLL_DELAY_US, + &status); if (!ret && (status & STATUS_PROG_FAILED)) - ret = -EIO; + return -EIO; return ret; } @@ -698,7 +716,10 @@ static int spinand_erase(struct nand_device *nand, const struct nand_pos *pos) if (ret) return ret; - ret = spinand_wait(spinand, &status); + ret = spinand_wait(spinand, + SPINAND_ERASE_INITIAL_DELAY_US, + SPINAND_ERASE_POLL_DELAY_US, + &status); if (!ret && (status & STATUS_ERASE_FAILED)) ret = -EIO; diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h index 5934b7604cc..b701d25f73d 100644 --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h @@ -176,6 +176,28 @@ struct spinand_op; struct spinand_device; #define SPINAND_MAX_ID_LEN 4 +/* + * For erase, write and read operation, we got the following timings : + * tBERS (erase) 1ms to 4ms + * tPROG 300us to 400us + * tREAD 25us to 100us + * In order to minimize latency, the min value is divided by 4 for the + * initial delay, and dividing by 20 for the poll delay. + * For reset, 5us/10us/500us if the device is respectively + * reading/programming/erasing when the RESET occurs. Since we always + * issue a RESET when the device is IDLE, 5us is selected for both initial + * and poll delay. + */ +#define SPINAND_READ_INITIAL_DELAY_US 6 +#define SPINAND_READ_POLL_DELAY_US 5 +#define SPINAND_RESET_INITIAL_DELAY_US 5 +#define SPINAND_RESET_POLL_DELAY_US 5 +#define SPINAND_WRITE_INITIAL_DELAY_US 75 +#define SPINAND_WRITE_POLL_DELAY_US 15 +#define SPINAND_ERASE_INITIAL_DELAY_US 250 +#define SPINAND_ERASE_POLL_DELAY_US 50 + +#define SPINAND_WAITRDY_TIMEOUT_MS 400 /** * struct spinand_id - SPI NAND id structure From patchwork Thu Jun 27 11:20:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Kshevetskiy X-Patchwork-Id: 1953184 X-Patchwork-Delegate: dario.binacchi@amarulasolutions.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.a=rsa-sha256 header.s=selector2 header.b=PLuklc+q; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4W8x2W2T3fz20Xg for ; Thu, 27 Jun 2024 21:20:51 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id CFB3988599; Thu, 27 Jun 2024 13:20:22 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.b="PLuklc+q"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 40AD78857E; Thu, 27 Jun 2024 13:20:20 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,SPF_HELO_PASS, SPF_PASS autolearn=no autolearn_force=no version=3.4.2 Received: from EUR02-VI1-obe.outbound.protection.outlook.com (mail-vi1eur02on20700.outbound.protection.outlook.com [IPv6:2a01:111:f403:2607::700]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 2528A87FA7 for ; Thu, 27 Jun 2024 13:20:18 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mikhail.kshevetskiy@genexis.eu ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=c1lsi1NnBw9wPsBnn96AX7WoLa6K64NUIzKqNgyq+Y1+QgI3PdrI9WAdz0qmH+Id2+EVRDfDhhzw3suFFpiW94ixsYZc+K4JR4orFCSMNmQ6wnE8qLKcPOZiyfBPIj67SJHeWQxnYNccp0REI6XDRN/mMzOZwWDHhjclKY+/ctxKBRVgnSP6dyha+Hb5yLJeRfn/M4zbngwAJdiwkBODhgjdi0pS+doXcWFUc0CzGgg2nNrPPEzJ+ELvolQ2K46Qvo2PoJ9iJOEZ0dmnTjm16LMgnc6MYa52Im03h7BUs/e1WoXng+giv+6oFGAw3brFmOdZjn7QLkVySemst8nvxg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=7jCSgvfMYyEH1hallGFAjdPNVGPEJMcBwnQ2iLTYCXw=; b=cMan/5XUh0mINUw+pG5KA2Aa4e2mkks9T9BtFO7JeSJJSuZA8Cbg9vGst8CEucudDZ1YdJPp+bTgd8mRsjJgGpyK+mM4+uiGkJU1/KxhTeubiz+LqLsK1N/QDLuYzM3r+5NUu1C/ztEV6Yzclcn7M7XCAFuimf8Ghqecac9UCPmXWbhH2icgPYI74861XJTmWhEsKAx0imjUgrTUbguldKgkaxXp5NlHhKpUb9uol9QIRp9+wT920FpzmTqaukg5XyEtSZmdWLuMrfp6huiifbwq8rqtCE0ZUNePBEKOz0o2uwKhKsx9Gtpdc2XYp7pUpoez9fJGnqvE0LrI5Rfotg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=genexis.eu; dmarc=pass action=none header.from=iopsys.eu; dkim=pass header.d=iopsys.eu; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iopsys.eu; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=7jCSgvfMYyEH1hallGFAjdPNVGPEJMcBwnQ2iLTYCXw=; b=PLuklc+qGf/9WG/Nmn2jeXzO+kiSIIKGcxFcq+FUO2YogYvCG5JyZENxX4lUlPDFeLti8KXY3KSPz9HkTeC42iDdBcTQHwamkJgcu0vwL1SidlXbQa3OgoMZp/BQCx/P3vBdpQ9qdJYS6oy/9TfqnnK1kfEulyJK/jXA32EXn6gf0dCwpAk3TK7GgPcTJDKzU9XLMKqOyycXrFTLCAsilHQS5J8EHykuvUTccxzkNT1BqgXZTqoTEuLAwMWjpoVjq/3qPRGRariGkcnw3S4234EehQDiryzEwbwZPkzx6O1O+i/t2oGak5MyQXC8hhwUXfeY/kMDYtIYIbDwQ0jRLQ== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=iopsys.eu; Received: from GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) by PA4PR08MB6064.eurprd08.prod.outlook.com (2603:10a6:102:e2::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.35; Thu, 27 Jun 2024 11:20:16 +0000 Received: from GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0]) by GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0%5]) with mapi id 15.20.7698.025; Thu, 27 Jun 2024 11:20:16 +0000 From: Mikhail Kshevetskiy To: Tom Rini , Dario Binacchi , Michael Trimarchi , Frieder Schrempf , Jagan Teki , Simon Glass , William Zhang , Igor Prusov , Bruce Suen , Dmitry Rokosov , Martin Kurbanov , Chuanhong Guo , Miquel Raynal , Francesco Dolcini , Max Krummenacher , u-boot@lists.denx.de Subject: [PATCH 4/7] mtd: spinand: preparation for ecc engine adding Date: Thu, 27 Jun 2024 14:20:02 +0300 Message-ID: <20240627112005.99375-4-mikhail.kshevetskiy@iopsys.eu> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240627112005.99375-1-mikhail.kshevetskiy@iopsys.eu> References: <20240627112005.99375-1-mikhail.kshevetskiy@iopsys.eu> X-ClientProxiedBy: GVX0EPF0000FA79.SWEP280.PROD.OUTLOOK.COM (2603:10a6:144:1:0:4:0:6) To GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: GV2PR08MB8121:EE_|PA4PR08MB6064:EE_ X-MS-Office365-Filtering-Correlation-Id: cefd0147-c875-437d-2b3d-08dc969b1f1b X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|1800799024|366016|52116014|7416014|376014|38350700014|921020; X-Microsoft-Antispam-Message-Info: P1QpPiO1hKSod+CJss/2/OTMZ//bw3+NSXqsCWbmMoIPHVF9fq6Jh0d+cjWLWf4px5T7PDMhdQts+XNQaCRxRzyOpG6XJ7hB1MiWkReQZi7xdV/wFKO8/tncmpAtZZrZDtYtt3HJMTGq6qkBKMirNh1xtlCv1/4Hd+GysEGFBi1Bu7d+Pv2BpTWyNauhCop7/Yigg7fAKzLeZ5lzMo9SHrVTxASFjvI6IMlXZ5FM0Aljyn8VdklIDDLbgKp5PUtOrJzahDnPx/LUk+yk4Oq3+uBC5KFgkgw31+b6SR8C8QN/m5pmuQl1snuPW8PTzTvXifywtPnQp4BnVa/n+DfFnIqg1pvESmDCd2Iqr1RobK+0QPPTuTSccrB/7bFPRAjWGBbOFvJaSQB+jfMC2XZZBN43zRdevac9p70kFy3JAhcuP6jFrB2Rp3lLJ2QVtnY1OvfDOvnFhZRluAb6JXm8rYGBs5JlesakC1Ste2ewzLNILCP+vyXDlaFYcc7JnRMjnyy0TgWtUCUGzOERk3ppCcLSTb36LwQhVYT2iPP639CxR9yEpGrFtBG8+0EMBocAG845f+HS8JMceewA7m/uB3EZe0I+kXH4OmSdrye/Qj29FSdzPQSpqzH0bY2H0Cl8/mm8rmE6R48MY5O5LhU5qpYsUY0OprO6xvh/QUTlLvyX0dh2kuK99+fH3zYa2SKs4vgXq/yXbhT0Gyn0ji2OcezM3qaxmaOTBPcCijgxtal2JXb4dxaFVnknsMnsXPQEFou1HE9rnfGZuCFUL/ICOWWzD22mcNKIQ6QrYwQUcyifcrP9kQAeqdWUm972lmLf2uwpu2fwGXxvaG4or3eFsY+4bsvl/rO9Ge248ufwTRbvej6c+Q7z5yO3uAukvSAiPNdsQtDg8aCRe+7dBPs4CjGEVtSxj8+4nga0tjMlC3ZTcxdiZ+oNIfwnrwr38OEaf4EinjamsZMjlmQIPpGAzhWWbw3z4A+Z7lnQF7hJ/Aa3OXorve1BMTT2AMQWctmBy6wxekHFg2s5ZlBY9JUOjJDgRceeJ+h0d6Pxx3VInfASvJyuhNSpPqZKL6pAyBVxYBrJ3pKKRh31SdfW3pMir0Duqf60TJf7s12r2qKcyOZSqI7XO6OfPFb5qx6rX+QTQ6KXZEh0nnY7arR9ACv2PGooBKfTCP0y7fWLUb6Uk8FQan25C8Il61MyHHQIYfsxRw+ORbhDkstyu9rrZQGd4Rd8fJ4R6U5i7mSmzVwmUxH91wIZpmilPieB4adEVi4PFIZ2+7VZMyjcoIKzNDhazKS7YSq4z3lsnFFA9wM2YCjH46AMZSHBV1CSJ0v4aRYyU/lQxTZBOJGsY7VdhMJNfQRSvViVvUj2UM8MnQ3s1PogVyudjMQQXSGsUqZtsAXqZh22LLSYWM24Yr0pOk81tQRvnXGo0J24xuULZyqCSi0= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:GV2PR08MB8121.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(1800799024)(366016)(52116014)(7416014)(376014)(38350700014)(921020); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: b7wwWRlgTacy54MHNsMKaxGWxHxvVN1DZsyeJtHt2C+6q3LTAhyzKGHpJpCw8zK8njX7s9vTn7KZMUSSMthA6dAyLNebvMMSgMQFL4suTk9O7ULoEH7XO1WeaBWK5+BuUHvzGWjpK9altd04LfpPmvZZ1UytVLhpnh6BjgeFjJnJZHtzNBxFfHCoVuMKlDtoubk090uc3RM6i/z21pbtvrYwG7lg+rxWvvm1XqXhzk1kAjlbxu6A0R7gJxcoEmcofBf5Y9gE9E3SfqMWgskC6UbAAK7xpO2P533FsOw5qxoxTxGC5zWB/NbEWsYBkye/9zR3Ko3Kj6BR2dWLAzjlf+LgFevmI32NCSrro7WR2G1XuToNOa+YvEeVE4QTwYiY8mX86CCKeBhk6I8kkhVLShyeBxq6g725vJvDY7AK/JHNBr5p7hI527LvjPPRkh4t1I+HEZMnC6tkWxj1f5q2M+Q96kngvOEUCBVV/YHx8pw/GORN4Un7ydpARzWpN5rSJS4VkEFMUGyXdP1/BCs5NfDg5cfBfecricdmox970FI6vnYVBC0qVFlvsyBaLBd6vqnJZ5pd1DyID98t3b6NliTEt+Z/zuGuWY5D9ANu3csT/NyMyZerMu7tvnB3CC8tq5QwZk0KrtDUfJAXfFFATWr+6jofBvRWsYOKpxbQisnjRhvUFhDGB+VDvPyq0iK60E8dI37Jy+LR5pPWEcOPRTWek+sKrZbWfeG4dKHJGM7BW1FkCUaaJDXeGhq1vWVsNK/hPntSl8ItvF7OA2myyguQLPe3LMJWOnWDV08Hrqd/B13/dNM7Ule7tJuNa9WxyZPQuFnPT3plZ40LvYxler1j3e4rQIULT4k3XozOzZGoiZTBwIxQJZd0ui52CDIlRFlAjuXoE/z1QIxHzSWa20SO1DxJHkJtJvr5AODXswtBVrhNwVsioDwR2D0/4WaeGNMfsHN1oHj2WYBwfJR88mhv1zWaLfqbdu5XA8t/TikstqLvrBUE+6/uhmlj9iMhNxpxPljVlYpzAgev6mAN2NoFwTVD4kLwCngfHctHf1l0fD61R+udU5/pfm60KnRRpp6+X9RwZVMaDzkmQpY13J+F2+Ve4FeIBhXGo5TgLbFmpS2AL8ELxBTLvRv8E3eBQNXorshZYdfygShiCCSr7ZdLH11Rq1pw4ara6WwmrnCI161wBpJ+/c8mIwHDb716bgZmMOznvrbzt3SQmlj0GrZlNQH2HkiVr/BC+sNMRHo8gPbFDhiCuhOUEiu9IwnbtcKePqYfnlw1M2X7q72N5y8rAEMZRigV1QwJyLqM3x4wNprEemKSlyEtavZ9F9FPsmorrO7H7E3C1z49IJFW3OwZ/CZrMm8XszkZMirI7UgAql2K7SXzMI5p0FJ2PvZ93TDZBuvDEr7gnUlZXBdGZ02p6H3tCaaunwr0T2FdekwOpTe9d08B9/KRWYGT6Lt1LpQW86KGS5n/+7V9XmVL9B4AMb+EJyVJrdNLRgeTF2bMmAk4ZAdqJ08h+0i9gjnZn+0Ubds79QpNJfjvs7gTU3NY9NmjjCgQSEdWMEKg6tu5rtbY5X3vGNd11VBYi9RidbyCD5TX71KRa/xqmHlRzV2GNxmhR+SarmdzKfbrjfo= X-OriginatorOrg: iopsys.eu X-MS-Exchange-CrossTenant-Network-Message-Id: cefd0147-c875-437d-2b3d-08dc969b1f1b X-MS-Exchange-CrossTenant-AuthSource: GV2PR08MB8121.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Jun 2024 11:20:16.7487 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 8d891be1-7bce-4216-9a99-bee9de02ba58 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: iUpEbM5AKF6PMc+KvzrrqWRfeO2nyieYa9S4g5OlVzfwQ8SOLj2BDO0Cn3ajmezTE9wN272G1WP7OdgWIKaQsLhUOjbeGaMXjcUjXrUO9RY= X-MS-Exchange-Transport-CrossTenantHeadersStamped: PA4PR08MB6064 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 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" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Signed-off-by: Mikhail Kshevetskiy --- drivers/mtd/nand/spi/core.c | 259 +++++++++++++++++++++--------------- 1 file changed, 151 insertions(+), 108 deletions(-) diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index 8664e882753..1b2eefc9041 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -156,20 +156,12 @@ int spinand_select_target(struct spinand_device *spinand, unsigned int target) return 0; } -static int spinand_init_cfg_cache(struct spinand_device *spinand) +static int spinand_read_cfg(struct spinand_device *spinand) { struct nand_device *nand = spinand_to_nand(spinand); - struct udevice *dev = spinand->slave->dev; unsigned int target; int ret; - spinand->cfg_cache = devm_kzalloc(dev, - sizeof(*spinand->cfg_cache) * - nand->memorg.ntargets, - GFP_KERNEL); - if (!spinand->cfg_cache) - return -ENOMEM; - for (target = 0; target < nand->memorg.ntargets; target++) { ret = spinand_select_target(spinand, target); if (ret) @@ -188,6 +180,21 @@ static int spinand_init_cfg_cache(struct spinand_device *spinand) return 0; } +static int spinand_init_cfg_cache(struct spinand_device *spinand) +{ + struct nand_device *nand = spinand_to_nand(spinand); + struct udevice *dev = spinand->slave->dev; + + spinand->cfg_cache = devm_kcalloc(dev, + nand->memorg.ntargets, + sizeof(*spinand->cfg_cache), + GFP_KERNEL); + if (!spinand->cfg_cache) + return -ENOMEM; + + return 0; +} + static int spinand_init_quad_enable(struct spinand_device *spinand) { bool enable = false; @@ -211,6 +218,59 @@ static int spinand_ecc_enable(struct spinand_device *spinand, enable ? CFG_ECC_ENABLE : 0); } +static int spinand_check_ecc_status(struct spinand_device *spinand, u8 status) +{ + struct nand_device *nand = spinand_to_nand(spinand); + + if (spinand->eccinfo.get_status) + return spinand->eccinfo.get_status(spinand, status); + + switch (status & STATUS_ECC_MASK) { + case STATUS_ECC_NO_BITFLIPS: + return 0; + + case STATUS_ECC_HAS_BITFLIPS: + /* + * We have no way to know exactly how many bitflips have been + * fixed, so let's return the maximum possible value so that + * wear-leveling layers move the data immediately. + */ + return nand->eccreq.strength; + + case STATUS_ECC_UNCOR_ERROR: + return -EBADMSG; + + default: + break; + } + + return -EINVAL; +} + +static int spinand_noecc_ooblayout_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) +{ + return -ERANGE; +} + +static int spinand_noecc_ooblayout_free(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) +{ + if (section) + return -ERANGE; + + /* Reserve 2 bytes for the BBM. */ + region->offset = 2; + region->length = 62; + + return 0; +} + +static const struct mtd_ooblayout_ops spinand_noecc_ooblayout = { + .ecc = spinand_noecc_ooblayout_ecc, + .rfree = spinand_noecc_ooblayout_free, +}; + static int spinand_write_enable_op(struct spinand_device *spinand) { struct spi_mem_op op = SPINAND_WR_EN_DIS_OP(true); @@ -232,7 +292,7 @@ static int spinand_read_from_cache_op(struct spinand_device *spinand, const struct nand_page_io_req *req) { struct nand_device *nand = spinand_to_nand(spinand); - struct mtd_info *mtd = nanddev_to_mtd(nand); + struct mtd_info *mtd = spinand_to_mtd(spinand); struct spi_mem_dirmap_desc *rdesc; unsigned int nbytes = 0; void *buf = NULL; @@ -290,7 +350,7 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand, const struct nand_page_io_req *req) { struct nand_device *nand = spinand_to_nand(spinand); - struct mtd_info *mtd = nanddev_to_mtd(nand); + struct mtd_info *mtd = spinand_to_mtd(spinand); struct spi_mem_dirmap_desc *wdesc; unsigned int nbytes, column = 0; void *buf = spinand->databuf; @@ -352,7 +412,7 @@ static int spinand_program_op(struct spinand_device *spinand, static int spinand_erase_op(struct spinand_device *spinand, const struct nand_pos *pos) { - struct nand_device *nand = &spinand->base; + struct nand_device *nand = spinand_to_nand(spinand); unsigned int row = nanddev_pos_to_row(nand, pos); struct spi_mem_op op = SPINAND_BLK_ERASE_OP(row); @@ -402,9 +462,8 @@ out: static int spinand_read_id_op(struct spinand_device *spinand, u8 naddr, u8 ndummy, u8 *buf) { - struct spi_mem_op op = SPINAND_READID_OP(naddr, ndummy, - spinand->scratchbuf, - SPINAND_MAX_ID_LEN); + struct spi_mem_op op = SPINAND_READID_OP( + naddr, ndummy, spinand->scratchbuf, SPINAND_MAX_ID_LEN); int ret; ret = spi_mem_exec_op(spinand->slave, &op); @@ -434,35 +493,6 @@ static int spinand_lock_block(struct spinand_device *spinand, u8 lock) return spinand_write_reg_op(spinand, REG_BLOCK_LOCK, lock); } -static int spinand_check_ecc_status(struct spinand_device *spinand, u8 status) -{ - struct nand_device *nand = spinand_to_nand(spinand); - - if (spinand->eccinfo.get_status) - return spinand->eccinfo.get_status(spinand, status); - - switch (status & STATUS_ECC_MASK) { - case STATUS_ECC_NO_BITFLIPS: - return 0; - - case STATUS_ECC_HAS_BITFLIPS: - /* - * We have no way to know exactly how many bitflips have been - * fixed, so let's return the maximum possible value so that - * wear-leveling layers move the data immediately. - */ - return nand->eccreq.strength; - - case STATUS_ECC_UNCOR_ERROR: - return -EBADMSG; - - default: - break; - } - - return -EINVAL; -} - static int spinand_read_page(struct spinand_device *spinand, const struct nand_page_io_req *req, bool ecc_enabled) @@ -524,30 +554,36 @@ static int spinand_mtd_read(struct mtd_info *mtd, loff_t from, { struct spinand_device *spinand = mtd_to_spinand(mtd); struct nand_device *nand = mtd_to_nanddev(mtd); + struct mtd_ecc_stats old_stats; unsigned int max_bitflips = 0; struct nand_io_iter iter; - bool enable_ecc = false; + bool disable_ecc = false; bool ecc_failed = false; int ret = 0; - if (ops->mode != MTD_OPS_RAW && spinand->eccinfo.ooblayout) - enable_ecc = true; + if (ops->mode == MTD_OPS_RAW || !spinand->eccinfo.ooblayout) + disable_ecc = true; #ifndef __UBOOT__ mutex_lock(&spinand->lock); #endif + old_stats = mtd->ecc_stats; + nanddev_io_for_each_page(nand, NAND_PAGE_READ, from, ops, &iter) { schedule(); + if (disable_ecc) + iter.req.mode = MTD_OPS_RAW; + ret = spinand_select_target(spinand, iter.req.pos.target); if (ret) break; - ret = spinand_ecc_enable(spinand, enable_ecc); + ret = spinand_ecc_enable(spinand, !disable_ecc); if (ret) break; - ret = spinand_read_page(spinand, &iter.req, enable_ecc); + ret = spinand_read_page(spinand, &iter.req, !disable_ecc); if (ret < 0 && ret != -EBADMSG) break; @@ -564,6 +600,13 @@ static int spinand_mtd_read(struct mtd_info *mtd, loff_t from, ops->oobretlen += iter.req.ooblen; } + if (ops->stats) { + ops->stats->uncorrectable_errors += + mtd->ecc_stats.failed - old_stats.failed; + ops->stats->corrected_bitflips += + mtd->ecc_stats.corrected - old_stats.corrected; + } + #ifndef __UBOOT__ mutex_unlock(&spinand->lock); #endif @@ -579,11 +622,11 @@ static int spinand_mtd_write(struct mtd_info *mtd, loff_t to, struct spinand_device *spinand = mtd_to_spinand(mtd); struct nand_device *nand = mtd_to_nanddev(mtd); struct nand_io_iter iter; - bool enable_ecc = false; + bool disable_ecc = false; int ret = 0; - if (ops->mode != MTD_OPS_RAW && mtd->ooblayout) - enable_ecc = true; + if (ops->mode == MTD_OPS_RAW || !mtd->ooblayout) + disable_ecc = true; #ifndef __UBOOT__ mutex_lock(&spinand->lock); @@ -591,11 +634,14 @@ static int spinand_mtd_write(struct mtd_info *mtd, loff_t to, nanddev_io_for_each_page(nand, NAND_PAGE_WRITE, to, ops, &iter) { schedule(); + if (disable_ecc) + iter.req.mode = MTD_OPS_RAW; + ret = spinand_select_target(spinand, iter.req.pos.target); if (ret) break; - ret = spinand_ecc_enable(spinand, enable_ecc); + ret = spinand_ecc_enable(spinand, !disable_ecc); if (ret) break; @@ -1039,35 +1085,55 @@ static int spinand_detect(struct spinand_device *spinand) return 0; } -static int spinand_noecc_ooblayout_ecc(struct mtd_info *mtd, int section, - struct mtd_oob_region *region) +static int spinand_init_flash(struct spinand_device *spinand) { - return -ERANGE; -} + struct udevice *dev = spinand->slave->dev; + struct nand_device *nand = spinand_to_nand(spinand); + int ret, i; -static int spinand_noecc_ooblayout_free(struct mtd_info *mtd, int section, - struct mtd_oob_region *region) -{ - if (section) - return -ERANGE; + ret = spinand_read_cfg(spinand); + if (ret) + return ret; - /* Reserve 2 bytes for the BBM. */ - region->offset = 2; - region->length = 62; + ret = spinand_init_quad_enable(spinand); + if (ret) + return ret; - return 0; -} + ret = spinand_upd_cfg(spinand, CFG_OTP_ENABLE, 0); + if (ret) + return ret; -static const struct mtd_ooblayout_ops spinand_noecc_ooblayout = { - .ecc = spinand_noecc_ooblayout_ecc, - .rfree = spinand_noecc_ooblayout_free, -}; + ret = spinand_manufacturer_init(spinand); + if (ret) { + dev_err(dev, + "Failed to initialize the SPI NAND chip (err = %d)\n", + ret); + return ret; + } + + /* After power up, all blocks are locked, so unlock them here. */ + for (i = 0; i < nand->memorg.ntargets; i++) { + ret = spinand_select_target(spinand, i); + if (ret) + break; + + ret = spinand_lock_block(spinand, BL_ALL_UNLOCKED); + if (ret) + break; + } + + if (ret) + spinand_manufacturer_cleanup(spinand); + + return ret; +} static int spinand_init(struct spinand_device *spinand) { + struct udevice *dev = spinand->slave->dev; struct mtd_info *mtd = spinand_to_mtd(spinand); struct nand_device *nand = mtd_to_nanddev(mtd); - int ret, i; + int ret; /* * We need a scratch buffer because the spi_mem interface requires that @@ -1100,49 +1166,14 @@ static int spinand_init(struct spinand_device *spinand) if (ret) goto err_free_bufs; - ret = spinand_init_quad_enable(spinand); + ret = spinand_init_flash(spinand); if (ret) goto err_free_bufs; - ret = spinand_upd_cfg(spinand, CFG_OTP_ENABLE, 0); - if (ret) - goto err_free_bufs; - - ret = spinand_manufacturer_init(spinand); - if (ret) { - dev_err(spinand->slave->dev, - "Failed to initialize the SPI NAND chip (err = %d)\n", - ret); - goto err_free_bufs; - } - - ret = spinand_create_dirmaps(spinand); - if (ret) { - dev_err(spinand->slave->dev, - "Failed to create direct mappings for read/write operations (err = %d)\n", - ret); - goto err_manuf_cleanup; - } - - /* After power up, all blocks are locked, so unlock them here. */ - for (i = 0; i < nand->memorg.ntargets; i++) { - ret = spinand_select_target(spinand, i); - if (ret) - goto err_manuf_cleanup; - - ret = spinand_lock_block(spinand, BL_ALL_UNLOCKED); - if (ret) - goto err_manuf_cleanup; - } - ret = nanddev_init(nand, &spinand_ops, THIS_MODULE); if (ret) goto err_manuf_cleanup; - /* - * Right now, we don't support ECC, so let the whole oob - * area is available for user. - */ mtd->_read_oob = spinand_mtd_read; mtd->_write_oob = spinand_mtd_write; mtd->_block_isbad = spinand_mtd_block_isbad; @@ -1161,8 +1192,18 @@ static int spinand_init(struct spinand_device *spinand) mtd->oobavail = ret; + ret = spinand_create_dirmaps(spinand); + if (ret) { + dev_err(dev, + "Failed to create direct mappings for read/write operations (err = %d)\n", + ret); + goto err_cleanup_ecc_engine; + } + return 0; +err_cleanup_ecc_engine: + err_cleanup_nanddev: nanddev_cleanup(nand); @@ -1262,12 +1303,14 @@ static const struct spi_device_id spinand_ids[] = { { .name = "spi-nand" }, { /* sentinel */ }, }; +MODULE_DEVICE_TABLE(spi, spinand_ids); #ifdef CONFIG_OF static const struct of_device_id spinand_of_ids[] = { { .compatible = "spi-nand" }, { /* sentinel */ }, }; +MODULE_DEVICE_TABLE(of, spinand_of_ids); #endif static struct spi_mem_driver spinand_drv = { From patchwork Thu Jun 27 11:20:03 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Kshevetskiy X-Patchwork-Id: 1953185 X-Patchwork-Delegate: dario.binacchi@amarulasolutions.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.a=rsa-sha256 header.s=selector2 header.b=UQhZ0AXz; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4W8x2k4Lnmz20Xg for ; Thu, 27 Jun 2024 21:21:02 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 65AE688574; Thu, 27 Jun 2024 13:20:26 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.b="UQhZ0AXz"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id CC20B885B5; Thu, 27 Jun 2024 13:20:23 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,SPF_HELO_PASS, SPF_PASS autolearn=no autolearn_force=no version=3.4.2 Received: from EUR05-AM6-obe.outbound.protection.outlook.com (mail-am6eur05on2072a.outbound.protection.outlook.com [IPv6:2a01:111:f403:2612::72a]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 1285587FA7 for ; Thu, 27 Jun 2024 13:20:21 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mikhail.kshevetskiy@genexis.eu ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=KwEwZba4mixBE4g1qodIHlOvMH6t2c/SXSOaek7DK8Iz0nOg7oflQritqbwhjPWPBJFIqBkwMTX8TFSEIxlGuDT0LPrvCPsJ1wcVSaCb/1gbLlUoHLOzDTL/tBXF8lKV0zKZGLYPHVZtMksW4saS1HqL+q9MZ/PxuUi129iT8jOXIRheVQsBDRBclmeCYMqNiZIkgVWe0AZbKWypsjF//dMEYQfQfXMieUByq8N2T/DREmyYooIO7d3OrQj0MFu9/V4/xnD90HjsWsE9+wgMCYIF75qy8LeQJF7RQ2QCIufCFiWRNeDVpz3E7gWTuxZiP5/usMRMGmwoOHj2QLI5Dw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=Brv7K31wkJRhkMwlSPmrK6y0SjJ/EhVW/LeE4rMwT4o=; b=IuFETELF8mNxbdSKEVyr20lpi8P5L9rTk4Mx90Ou2JjvRUSJTWBPGaknocr1NVhNSGErLiBqgrkBSD63LajpTlvsiWQwkj6Kxhwq7oAePmKcYhMASynlNEKIAEmfkfdTCAP4MKVaMYEkYg6pgmbbOo8komGAver4uLZo0t+0nKCrHV1NKrFqshYzaW9e1O5sCFMk9DzedBvngcCjd4K8EXANAq50K7AmX8gO81+dN80fqMGagcT6T7JJVn/4nI8R1k8qPu2P3n1F/8Lkqd0tTJUO/7I+aBiGYZnarE/AYFEPlQQwN3A/F5yX4r7CIYrJXfKphEtcEjeUM9/wTQcA8g== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=genexis.eu; dmarc=pass action=none header.from=iopsys.eu; dkim=pass header.d=iopsys.eu; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iopsys.eu; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Brv7K31wkJRhkMwlSPmrK6y0SjJ/EhVW/LeE4rMwT4o=; b=UQhZ0AXzYAMjdj5A43SXyF0MOj/ky0bzWnzkmZFCoZcP9WhqaYvc8ygzWyx/jcX2SGtpXFznRsZ7at8dl0e6v3k9EYugLdvVNl04oJJt4iZMuojy38pu/hNrI6yb7wK+9n9lfXPupKeNAdENjBhM9gU+kYgW/2xagFF5In/DRaw7dqGaVmsWNJ2RZLOO0VcuGvsPuzjx8QPVx/UvTJ/cy5ifhYKjthaiE1ayvi1kL2KYTyOMYmB/M4t9v5KdedcOifDJtxXfnP+DaJ98BureCNYixXrawpbejNjbyR7BZdt+xddOa1MD+x0zw6FkvUMNKkypuougXZvBhHdkwU+Wbg== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=iopsys.eu; Received: from GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) by AS8PR08MB8970.eurprd08.prod.outlook.com (2603:10a6:20b:5b3::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.35; Thu, 27 Jun 2024 11:20:18 +0000 Received: from GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0]) by GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0%5]) with mapi id 15.20.7698.025; Thu, 27 Jun 2024 11:20:18 +0000 From: Mikhail Kshevetskiy To: Tom Rini , Dario Binacchi , Michael Trimarchi , Frieder Schrempf , Jagan Teki , Simon Glass , William Zhang , Igor Prusov , Bruce Suen , Dmitry Rokosov , Martin Kurbanov , Chuanhong Guo , Miquel Raynal , Francesco Dolcini , Max Krummenacher , u-boot@lists.denx.de Subject: [PATCH 5/7] mtd: nand: add initial ecc engine support Date: Thu, 27 Jun 2024 14:20:03 +0300 Message-ID: <20240627112005.99375-5-mikhail.kshevetskiy@iopsys.eu> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240627112005.99375-1-mikhail.kshevetskiy@iopsys.eu> References: <20240627112005.99375-1-mikhail.kshevetskiy@iopsys.eu> X-ClientProxiedBy: GVX0EPF0000FA79.SWEP280.PROD.OUTLOOK.COM (2603:10a6:144:1:0:4:0:6) To GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: GV2PR08MB8121:EE_|AS8PR08MB8970:EE_ X-MS-Office365-Filtering-Correlation-Id: 6386b7e4-2fef-4553-038b-08dc969b1fed X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|366016|52116014|376014|7416014|1800799024|921020|38350700014; X-Microsoft-Antispam-Message-Info: 5QJWgbFSfD4QYTpLy9IZpmdybG9YUOr0LeCEn1IKTLjDSwW6q2pg7tUh4yJadi2rMuy2mXisHYnmrVQiY/mS1SUnLIaJyd0mpnBljP+3mpSN6+kHf4TgT56mQbi+YDzkPZ2MQUQVhLw0jRc9SqK/cjqNcaA9VRnmHavq5D6/PdSECeGEzFzIIzIEL+Wop++KMlm7ANgEbHXIAcJTFUbR/N59eFfswprXCib5yqJqpV47Jo15vS4DH5Igucg+DUGqEBjks47OJpa7lpYJv7UBOdJ1rGdhgKMTYF2AAaIoYGA/7na5/l0+QjDeiVpLC6FvBD+fSBtkeEH2yk8HYpLpTtqjMoH/wIVXmgT9HL4N3GeKVlIadcBuWmmeFOWccaEauq6BZX5OZSoUl0cpwV0lHn4ylUgkfhrdFpohn823zjqAjYTQk+Pm20br/d2/j5g7bcMbzZ7KgucXbw4jwfjyQ+viQ5XdmUemiNpQ36iH9Xuc6tnTOYtu9A5HOUNC62injyLFEiE0RwVw7DP0BHPgncBeigkzZEBCy4creeQTnCymqHKN0Anc6oqUk0++4RwtjBVfXB0449NcxaMs/jCbogmec5DsdzBD9ARnAoZDuq0JNb7/MHoSRvwFmXlUc1bP2cVFX8MTNAV2MhYikQaaMGuw/R7z6ki0rEHZqCRp9iwvJ6Srx41RLkXaUbljad9RSeDkuzOQqmN6g9u089PfS6tPHfFWZ6xPf309A/f+hJcQXuvcBUDRTlBTjLl2k981JTZXAWyqe6UcGdPBG1DNMVl7hiwybH9SjZazoGK/KR++69oHXfm3LJEFfrUS2c+oa+OK7phLoswn9dOGnr86iKbuq/6xulIMKy6Dmz7Io8NWjjYUl7u76LZnoSLsIdRT64l6EMGJZbuc9A/UB/428359NNuRd0rBcvO4MirO4W7ecZ88rjuofOCGlLsbhAnD9uyP+7tR6GG2BY5YmpAznTCBSkM1lGpB4BXKwK7zULoJqL9EgI+J/ie9qqGnHp7Jh4p1jodnICaBjtpLIDaoFz72MM+B86ef6VihmSM0tl2AsdkYmoHXaXqQZzlNU+emn7RwE7VHSKm81ywVLQB2S23V9YAzcD2swvEuOvuJF/+hl0FpZedR2OIv/I70ze/L246IdU4d+j1rPFk/lI7+yV2s9S3qWZOO5TeG3pUGGwMh+QpXFVgTVXXvrr1f8SFNs17B6nPfVA7cvq7vI5XY/AbdIgzUs2PUdizjl6nDRIMlzV186yCEkiLlI4YTkU7XCZBozY+PUmxRe7XtfHbM/EOVoMzDsD1vmosXnqOhMjJJPtoXvoWBTpWht0emjWKPXglDuDnXhKdD6ETfgxPAcylYWJm6pV3uuhokc8MonEAWt+Y8TtOBW4bT3slAKHUEafRlTEqGqZvwhXoqyQ1pxAp/dVCE/H2PNLRqzqa4S8g= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:GV2PR08MB8121.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(366016)(52116014)(376014)(7416014)(1800799024)(921020)(38350700014); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: dzmMvzmarpJiwwjWDbV7TpZn0aaP/uQ8NtIv8Qy17xiZ0AkoKHwDsS8LOBzsVDPEulKKHKL2bHBU38QLvcNCQoJEPJ59RNQDvISNmSmCY4uGaUk1pmNNx29DhjIrcUyVlcCazBs8G9dTTDHzo4SiPKHAvVbTUwz49bA0uQKWKllVa4F/161RkxAYekGBJOvhZhEikSjO/5+TdLcysDDTVKmelR5OzRxm3SnjE9pOf0za1478Miud4rMmOPrM7p5dM29eJQad/rwqXBBj1p1az0Yuqn1+gf7LHHiyTgYJouNg40I4TLVAeYRUlwHBT1J8aoqz/8XwfM7xkjcSpt7V59E0BjcwC0iBEvlGUsdRQ75Kpswt6lnMk5ZSy80bvEsU1D5k8rkVnrai9N1Vu6FiuivpEWcf+cXuY2d+sIu+cs7F9CVEoX1rsNfwvzwcA7WdVC2M55YVOqHZYfabM+IOziNMBxMlgu0Wh6qoWGsgebJpWhx17yYadEjdAzqdt6lvpJ0y9bhG2AOFe4LuXYdPpZZEqt0Lq1ecx6cqr/Ku8XiiNCSR+ZrgUkHO0J02TDIxilv7k/zHJPfO0EjAcKR4OMp2+9QP5qq/gvY0MBx8+bCUSrEHvatjd+NSZHai0LX/jgPi2AZG6Tfa7RUaJhAqB2acqct8OH/hvmOApWEGEjE+dhdTn4yf/YEdLSkDw7FI0fOHmm33pRQIHIma9k9/m7uEZ1FDNDtwQUGSy7ibIcebkxY0e45mMtfr5j0qTraQ8IfFCu81xC+FPHmfjm3/8ttBbzQaheQ1UHmUi2rn048naQOFDvz6WczDYS2my/uQzjAu1PIs1Ol0WR/FUFiXT6m7ISo0+aScPtgHbzg5/3EYrdpTEM7cmqfOitDjaLCQWD7CpMgwLnVC26JhvLyfx88ZTZ+rweP0ZYfkpo7wKTtchKQ67YphKFJM3niJfOm7EOG2bvet1d65nf0GhfYTTrpXAxRPT/HgkjczamIzpiUP3LwaauOH0e5S/oIxsha6Lkx6kjyyYpM8fhniP0twVwYCoC523/biR925HymP49Hxglk/tN9SzqGzrYFPV82LjiulgZ4Fzf9hKv2JNxfTl8N6TmnmXeDVnEG3nM2PvLPNZ6p13ggaASJpAWJqHU0wbAIhh7EbJsbm7DuQQmK+m1HLUZx9jlu1PhEYEdAblCadLB/kXTTPgbVKAQJWS/7FjuaCnCnIQn3GtJXFoGdKlHlsF+Gn6/MOzWiXVKPkh8BUVa+wEXzat7Z8weKWjAFm+ZwxXNKJ3z5a49YaDlMfdxUhLkLdiv1PxOcV6e2GYU9SKDUCQ1pOcerJ96+DU1kzKA0zQqL9NeQZe4yknxkTIzp2fei4uJZdBY47cmiavw6sDF4T+fiVtKGTbm5llmST+/b97GWNzz1n3KPbtX9MC/iXOxz4rph0E90e3KpkqqvMAQPal8mJAWlAGjJ3zrjL4l8H3oQX3r7GouNVZZ3PhKgrvRZLflDkFq9HMX21bicKCKUSUpe2qlCz6REuBkw0XBg0XdlSNAVrn5JiVB9biiOr53BVcy9GfyVxM/CEcztaBZzC9gD0BHUINuuErC6vU6Cdp6JrvUip3EpsdUj8kIC4e94RE0V8rVD/wIxdy3Y= X-OriginatorOrg: iopsys.eu X-MS-Exchange-CrossTenant-Network-Message-Id: 6386b7e4-2fef-4553-038b-08dc969b1fed X-MS-Exchange-CrossTenant-AuthSource: GV2PR08MB8121.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Jun 2024 11:20:18.1797 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 8d891be1-7bce-4216-9a99-bee9de02ba58 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 9sHopyon3ZGTbPu7s3lrWhMO7/PQ+be/K9ZfxI1z0gR+Mkahvh6okijFCGEjgzybTok7Vhx2/DaMV33Mfku5hrCbdsNt7fr+cENaWbSDT8w= X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR08MB8970 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 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" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean just now only spinand on_die ecc is supported Signed-off-by: Mikhail Kshevetskiy --- drivers/mtd/nand/Makefile | 2 +- drivers/mtd/nand/core.c | 130 +++++++++++++++- drivers/mtd/nand/ecc.c | 150 ++++++++++++++++++ drivers/mtd/nand/spi/core.c | 206 ++++++++++++++++++++----- drivers/mtd/nand/spi/macronix.c | 7 +- drivers/mtd/nand/spi/micron.c | 2 +- drivers/mtd/nand/spi/toshiba.c | 10 +- drivers/mtd/nand/spi/winbond.c | 10 +- include/linux/mtd/nand.h | 260 ++++++++++++++++++++++++++++++-- include/linux/mtd/spinand.h | 13 +- include/spi-mem.h | 2 + 11 files changed, 724 insertions(+), 68 deletions(-) create mode 100644 drivers/mtd/nand/ecc.c diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 96e186600a1..56179188e92 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0+ ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TPL_BUILD),) -nandcore-objs := core.o bbt.o +nandcore-objs := core.o bbt.o ecc.o obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o obj-$(CONFIG_MTD_RAW_NAND) += raw/ obj-$(CONFIG_MTD_SPI_NAND) += spi/ diff --git a/drivers/mtd/nand/core.c b/drivers/mtd/nand/core.c index f6d9c584f78..62bbc12c662 100644 --- a/drivers/mtd/nand/core.c +++ b/drivers/mtd/nand/core.c @@ -130,7 +130,7 @@ EXPORT_SYMBOL_GPL(nanddev_isreserved); * * Return: 0 in case of success, a negative error code otherwise. */ -static int nanddev_erase(struct nand_device *nand, const struct nand_pos *pos) +int nanddev_erase(struct nand_device *nand, const struct nand_pos *pos) { unsigned int entry; @@ -188,6 +188,134 @@ int nanddev_mtd_erase(struct mtd_info *mtd, struct erase_info *einfo) } EXPORT_SYMBOL_GPL(nanddev_mtd_erase); +/** + * nanddev_get_ecc_engine() - Find and get a suitable ECC engine + * @nand: NAND device + */ +static int nanddev_get_ecc_engine(struct nand_device *nand) +{ + int engine_type; + + /* Read the user desires in terms of ECC engine/configuration */ + of_get_nand_ecc_user_config(nand); + + engine_type = nand->ecc.user_conf.engine_type; + if (engine_type == NAND_ECC_ENGINE_TYPE_INVALID) + engine_type = nand->ecc.defaults.engine_type; + + switch (engine_type) { + case NAND_ECC_ENGINE_TYPE_NONE: + return 0; + case NAND_ECC_ENGINE_TYPE_SOFT: + nand->ecc.engine = nand_ecc_get_sw_engine(nand); + break; + case NAND_ECC_ENGINE_TYPE_ON_DIE: + nand->ecc.engine = nand_ecc_get_on_die_hw_engine(nand); + break; + case NAND_ECC_ENGINE_TYPE_ON_HOST: + nand->ecc.engine = nand_ecc_get_on_host_hw_engine(nand); + if (PTR_ERR(nand->ecc.engine) == -EPROBE_DEFER) + return -EPROBE_DEFER; + break; + default: + pr_err("Missing ECC engine type\n"); + } + + if (!nand->ecc.engine) + return -EINVAL; + + return 0; +} + +/** + * nanddev_put_ecc_engine() - Dettach and put the in-use ECC engine + * @nand: NAND device + */ +static int nanddev_put_ecc_engine(struct nand_device *nand) +{ + switch (nand->ecc.ctx.conf.engine_type) { + case NAND_ECC_ENGINE_TYPE_ON_HOST: + nand_ecc_put_on_host_hw_engine(nand); + break; + case NAND_ECC_ENGINE_TYPE_NONE: + case NAND_ECC_ENGINE_TYPE_SOFT: + case NAND_ECC_ENGINE_TYPE_ON_DIE: + default: + break; + } + + return 0; +} + +/** + * nanddev_find_ecc_configuration() - Find a suitable ECC configuration + * @nand: NAND device + */ +static int nanddev_find_ecc_configuration(struct nand_device *nand) +{ + int ret; + + if (!nand->ecc.engine) + return -ENOTSUPP; + + ret = nand_ecc_init_ctx(nand); + if (ret) + return ret; + + if (!nand_ecc_is_strong_enough(nand)) + pr_warn("WARNING: %s: the ECC used on your system is too weak compared to the one required by the NAND chip\n", + nand->mtd->name); + + return 0; +} + +/** + * nanddev_ecc_engine_init() - Initialize an ECC engine for the chip + * @nand: NAND device + */ +int nanddev_ecc_engine_init(struct nand_device *nand) +{ + int ret; + + /* Look for the ECC engine to use */ + ret = nanddev_get_ecc_engine(nand); + if (ret) { + if (ret != -EPROBE_DEFER) + pr_err("No ECC engine found\n"); + + return ret; + } + + /* No ECC engine requested */ + if (!nand->ecc.engine) + return 0; + + /* Configure the engine: balance user input and chip requirements */ + ret = nanddev_find_ecc_configuration(nand); + if (ret) { + pr_err("No suitable ECC configuration\n"); + nanddev_put_ecc_engine(nand); + + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(nanddev_ecc_engine_init); + +/** + * nanddev_ecc_engine_cleanup() - Cleanup ECC engine initializations + * @nand: NAND device + */ +void nanddev_ecc_engine_cleanup(struct nand_device *nand) +{ + if (nand->ecc.engine) + nand_ecc_cleanup_ctx(nand); + + nanddev_put_ecc_engine(nand); +} +EXPORT_SYMBOL_GPL(nanddev_ecc_engine_cleanup); + /** * nanddev_init() - Initialize a NAND device * @nand: NAND device diff --git a/drivers/mtd/nand/ecc.c b/drivers/mtd/nand/ecc.c new file mode 100644 index 00000000000..7c86e9871ad --- /dev/null +++ b/drivers/mtd/nand/ecc.c @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#ifndef __UBOOT__ +#include +#include +#include +#include +#include +#endif +#include + +/** + * nand_ecc_init_ctx - Init the ECC engine context + * @nand: the NAND device + * + * On success, the caller is responsible of calling @nand_ecc_cleanup_ctx(). + */ +int nand_ecc_init_ctx(struct nand_device *nand) +{ + if (!nand->ecc.engine || !nand->ecc.engine->ops->init_ctx) + return 0; + + return nand->ecc.engine->ops->init_ctx(nand); +} +EXPORT_SYMBOL(nand_ecc_init_ctx); + +/** + * nand_ecc_cleanup_ctx - Cleanup the ECC engine context + * @nand: the NAND device + */ +void nand_ecc_cleanup_ctx(struct nand_device *nand) +{ + if (nand->ecc.engine && nand->ecc.engine->ops->cleanup_ctx) + nand->ecc.engine->ops->cleanup_ctx(nand); +} +EXPORT_SYMBOL(nand_ecc_cleanup_ctx); + +/** + * nand_ecc_prepare_io_req - Prepare an I/O request + * @nand: the NAND device + * @req: the I/O request + */ +int nand_ecc_prepare_io_req(struct nand_device *nand, + struct nand_page_io_req *req) +{ + if (!nand->ecc.engine || !nand->ecc.engine->ops->prepare_io_req) + return 0; + + return nand->ecc.engine->ops->prepare_io_req(nand, req); +} +EXPORT_SYMBOL(nand_ecc_prepare_io_req); + +/** + * nand_ecc_finish_io_req - Finish an I/O request + * @nand: the NAND device + * @req: the I/O request + */ +int nand_ecc_finish_io_req(struct nand_device *nand, + struct nand_page_io_req *req) +{ + if (!nand->ecc.engine || !nand->ecc.engine->ops->finish_io_req) + return 0; + + return nand->ecc.engine->ops->finish_io_req(nand, req); +} +EXPORT_SYMBOL(nand_ecc_finish_io_req); + +void of_get_nand_ecc_user_config(struct nand_device *nand) +{ + nand->ecc.user_conf.engine_type = NAND_ECC_ENGINE_TYPE_ON_DIE; + nand->ecc.user_conf.algo = NAND_ECC_ALGO_UNKNOWN; + nand->ecc.user_conf.placement = NAND_ECC_PLACEMENT_UNKNOWN; +} +EXPORT_SYMBOL(of_get_nand_ecc_user_config); + +/** + * nand_ecc_is_strong_enough - Check if the chip configuration meets the + * datasheet requirements. + * + * @nand: Device to check + * + * If our configuration corrects A bits per B bytes and the minimum + * required correction level is X bits per Y bytes, then we must ensure + * both of the following are true: + * + * (1) A / B >= X / Y + * (2) A >= X + * + * Requirement (1) ensures we can correct for the required bitflip density. + * Requirement (2) ensures we can correct even when all bitflips are clumped + * in the same sector. + */ +bool nand_ecc_is_strong_enough(struct nand_device *nand) +{ + const struct nand_ecc_props *reqs = nanddev_get_ecc_requirements(nand); + const struct nand_ecc_props *conf = nanddev_get_ecc_conf(nand); + struct mtd_info *mtd = nanddev_to_mtd(nand); + int corr, ds_corr; + + if (conf->step_size == 0 || reqs->step_size == 0) + /* Not enough information */ + return true; + + /* + * We get the number of corrected bits per page to compare + * the correction density. + */ + corr = (mtd->writesize * conf->strength) / conf->step_size; + ds_corr = (mtd->writesize * reqs->strength) / reqs->step_size; + + return corr >= ds_corr && conf->strength >= reqs->strength; +} +EXPORT_SYMBOL(nand_ecc_is_strong_enough); + +struct nand_ecc_engine *nand_ecc_get_sw_engine(struct nand_device *nand) +{ + unsigned int algo = nand->ecc.user_conf.algo; + + if (algo == NAND_ECC_ALGO_UNKNOWN) + algo = nand->ecc.defaults.algo; + + switch (algo) { + case NAND_ECC_ALGO_HAMMING: + return nand_ecc_sw_hamming_get_engine(); + case NAND_ECC_ALGO_BCH: + return nand_ecc_sw_bch_get_engine(); + default: + break; + } + + return NULL; +} +EXPORT_SYMBOL(nand_ecc_get_sw_engine); + +struct nand_ecc_engine *nand_ecc_get_on_die_hw_engine(struct nand_device *nand) +{ + return nand->ecc.ondie_engine; +} +EXPORT_SYMBOL(nand_ecc_get_on_die_hw_engine); + +struct nand_ecc_engine *nand_ecc_get_on_host_hw_engine(struct nand_device *nand) +{ + return NULL; +} +EXPORT_SYMBOL(nand_ecc_get_on_host_hw_engine); + +void nand_ecc_put_on_host_hw_engine(struct nand_device *nand) +{ +} +EXPORT_SYMBOL(nand_ecc_put_on_host_hw_engine); diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index 1b2eefc9041..c60c3dfad68 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -235,7 +235,7 @@ static int spinand_check_ecc_status(struct spinand_device *spinand, u8 status) * fixed, so let's return the maximum possible value so that * wear-leveling layers move the data immediately. */ - return nand->eccreq.strength; + return nanddev_get_ecc_conf(nand)->strength; case STATUS_ECC_UNCOR_ERROR: return -EBADMSG; @@ -271,6 +271,92 @@ static const struct mtd_ooblayout_ops spinand_noecc_ooblayout = { .rfree = spinand_noecc_ooblayout_free, }; +static int spinand_ondie_ecc_init_ctx(struct nand_device *nand) +{ + struct spinand_device *spinand = nand_to_spinand(nand); + struct mtd_info *mtd = nanddev_to_mtd(nand); + struct spinand_ondie_ecc_conf *engine_conf; + + nand->ecc.ctx.conf.engine_type = NAND_ECC_ENGINE_TYPE_ON_DIE; + nand->ecc.ctx.conf.step_size = nand->ecc.requirements.step_size; + nand->ecc.ctx.conf.strength = nand->ecc.requirements.strength; + + engine_conf = kzalloc(sizeof(*engine_conf), GFP_KERNEL); + if (!engine_conf) + return -ENOMEM; + + nand->ecc.ctx.priv = engine_conf; + + if (spinand->eccinfo.ooblayout) + mtd_set_ooblayout(mtd, spinand->eccinfo.ooblayout); + else + mtd_set_ooblayout(mtd, &spinand_noecc_ooblayout); + + return 0; +} + +static void spinand_ondie_ecc_cleanup_ctx(struct nand_device *nand) +{ + kfree(nand->ecc.ctx.priv); +} + +static int spinand_ondie_ecc_prepare_io_req(struct nand_device *nand, + struct nand_page_io_req *req) +{ + struct spinand_device *spinand = nand_to_spinand(nand); + bool enable = (req->mode != MTD_OPS_RAW); + + memset(spinand->oobbuf, 0xff, nanddev_per_page_oobsize(nand)); + + /* Only enable or disable the engine */ + return spinand_ecc_enable(spinand, enable); +} + +static int spinand_ondie_ecc_finish_io_req(struct nand_device *nand, + struct nand_page_io_req *req) +{ + struct spinand_ondie_ecc_conf *engine_conf = nand->ecc.ctx.priv; + struct spinand_device *spinand = nand_to_spinand(nand); + struct mtd_info *mtd = spinand_to_mtd(spinand); + int ret; + + if (req->mode == MTD_OPS_RAW) + return 0; + + /* Nothing to do when finishing a page write */ + if (req->type == NAND_PAGE_WRITE) + return 0; + + /* Finish a page read: check the status, report errors/bitflips */ + ret = spinand_check_ecc_status(spinand, engine_conf->status); + if (ret == -EBADMSG) + mtd->ecc_stats.failed++; + else if (ret > 0) + mtd->ecc_stats.corrected += ret; + + return ret; +} + +static struct nand_ecc_engine_ops spinand_ondie_ecc_engine_ops = { + .init_ctx = spinand_ondie_ecc_init_ctx, + .cleanup_ctx = spinand_ondie_ecc_cleanup_ctx, + .prepare_io_req = spinand_ondie_ecc_prepare_io_req, + .finish_io_req = spinand_ondie_ecc_finish_io_req, +}; + +static struct nand_ecc_engine spinand_ondie_ecc_engine = { + .ops = &spinand_ondie_ecc_engine_ops, +}; + +static void spinand_ondie_ecc_save_status(struct nand_device *nand, u8 status) +{ + struct spinand_ondie_ecc_conf *engine_conf = nand->ecc.ctx.priv; + + if (nand->ecc.ctx.conf.engine_type == NAND_ECC_ENGINE_TYPE_ON_DIE && + engine_conf) + engine_conf->status = status; +} + static int spinand_write_enable_op(struct spinand_device *spinand) { struct spi_mem_op op = SPINAND_WR_EN_DIS_OP(true); @@ -313,7 +399,10 @@ static int spinand_read_from_cache_op(struct spinand_device *spinand, } } - rdesc = spinand->dirmaps[req->pos.plane].rdesc; + if (req->mode == MTD_OPS_RAW) + rdesc = spinand->dirmaps[req->pos.plane].rdesc; + else + rdesc = spinand->dirmaps[req->pos.plane].rdesc_ecc; while (nbytes) { ret = spi_mem_dirmap_read(rdesc, column, nbytes, buf); @@ -362,9 +451,12 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand, * must fill the page cache entirely even if we only want to program * the data portion of the page, otherwise we might corrupt the BBM or * user data previously programmed in OOB area. + * + * Only reset the data buffer manually, the OOB buffer is prepared by + * ECC engines ->prepare_io_req() callback. */ nbytes = nanddev_page_size(nand) + nanddev_per_page_oobsize(nand); - memset(spinand->databuf, 0xff, nbytes); + memset(spinand->databuf, 0xff, nanddev_page_size(nand)); if (req->datalen) memcpy(spinand->databuf + req->dataoffs, req->databuf.out, @@ -381,7 +473,10 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand, req->ooblen); } - wdesc = spinand->dirmaps[req->pos.plane].wdesc; + if (req->mode == MTD_OPS_RAW) + wdesc = spinand->dirmaps[req->pos.plane].wdesc; + else + wdesc = spinand->dirmaps[req->pos.plane].wdesc_ecc; while (nbytes) { ret = spi_mem_dirmap_write(wdesc, column, nbytes, buf); @@ -494,12 +589,16 @@ static int spinand_lock_block(struct spinand_device *spinand, u8 lock) } static int spinand_read_page(struct spinand_device *spinand, - const struct nand_page_io_req *req, - bool ecc_enabled) + const struct nand_page_io_req *req) { + struct nand_device *nand = spinand_to_nand(spinand); u8 status; int ret; + ret = nand_ecc_prepare_io_req(nand, (struct nand_page_io_req *)req); + if (ret) + return ret; + ret = spinand_load_page_op(spinand, req); if (ret) return ret; @@ -511,22 +610,26 @@ static int spinand_read_page(struct spinand_device *spinand, if (ret < 0) return ret; + spinand_ondie_ecc_save_status(nand, status); + ret = spinand_read_from_cache_op(spinand, req); if (ret) return ret; - if (!ecc_enabled) - return 0; - - return spinand_check_ecc_status(spinand, status); + return nand_ecc_finish_io_req(nand, (struct nand_page_io_req *)req); } static int spinand_write_page(struct spinand_device *spinand, const struct nand_page_io_req *req) { + struct nand_device *nand = spinand_to_nand(spinand); u8 status; int ret; + ret = nand_ecc_prepare_io_req(nand, (struct nand_page_io_req *)req); + if (ret) + return ret; + ret = spinand_write_enable_op(spinand); if (ret) return ret; @@ -546,7 +649,7 @@ static int spinand_write_page(struct spinand_device *spinand, if (!ret && (status & STATUS_PROG_FAILED)) return -EIO; - return ret; + return nand_ecc_finish_io_req(nand, (struct nand_page_io_req *)req); } static int spinand_mtd_read(struct mtd_info *mtd, loff_t from, @@ -554,7 +657,6 @@ static int spinand_mtd_read(struct mtd_info *mtd, loff_t from, { struct spinand_device *spinand = mtd_to_spinand(mtd); struct nand_device *nand = mtd_to_nanddev(mtd); - struct mtd_ecc_stats old_stats; unsigned int max_bitflips = 0; struct nand_io_iter iter; bool disable_ecc = false; @@ -568,8 +670,6 @@ static int spinand_mtd_read(struct mtd_info *mtd, loff_t from, mutex_lock(&spinand->lock); #endif - old_stats = mtd->ecc_stats; - nanddev_io_for_each_page(nand, NAND_PAGE_READ, from, ops, &iter) { schedule(); if (disable_ecc) @@ -579,11 +679,7 @@ static int spinand_mtd_read(struct mtd_info *mtd, loff_t from, if (ret) break; - ret = spinand_ecc_enable(spinand, !disable_ecc); - if (ret) - break; - - ret = spinand_read_page(spinand, &iter.req, !disable_ecc); + ret = spinand_read_page(spinand, &iter.req); if (ret < 0 && ret != -EBADMSG) break; @@ -600,13 +696,6 @@ static int spinand_mtd_read(struct mtd_info *mtd, loff_t from, ops->oobretlen += iter.req.ooblen; } - if (ops->stats) { - ops->stats->uncorrectable_errors += - mtd->ecc_stats.failed - old_stats.failed; - ops->stats->corrected_bitflips += - mtd->ecc_stats.corrected - old_stats.corrected; - } - #ifndef __UBOOT__ mutex_unlock(&spinand->lock); #endif @@ -641,10 +730,6 @@ static int spinand_mtd_write(struct mtd_info *mtd, loff_t to, if (ret) break; - ret = spinand_ecc_enable(spinand, !disable_ecc); - if (ret) - break; - ret = spinand_write_page(spinand, &iter.req); if (ret) break; @@ -673,7 +758,7 @@ static bool spinand_isbad(struct nand_device *nand, const struct nand_pos *pos) }; spinand_select_target(spinand, pos->target); - spinand_read_page(spinand, &req, false); + spinand_read_page(spinand, &req); if (marker[0] != 0xff || marker[1] != 0xff) return true; @@ -841,6 +926,36 @@ static int spinand_create_dirmap(struct spinand_device *spinand, spinand->dirmaps[plane].rdesc = desc; + if (nand->ecc.engine->integration != NAND_ECC_ENGINE_INTEGRATION_PIPELINED) { + spinand->dirmaps[plane].wdesc_ecc = spinand->dirmaps[plane].wdesc; + spinand->dirmaps[plane].rdesc_ecc = spinand->dirmaps[plane].rdesc; + + return 0; + } + + info.op_tmpl = *spinand->op_templates.update_cache; + info.op_tmpl.data.ecc = true; + desc = spi_mem_dirmap_create(spinand->slave, &info); + if (IS_ERR(desc)) { + spi_mem_dirmap_destroy(spinand->dirmaps[plane].wdesc); + spi_mem_dirmap_destroy(spinand->dirmaps[plane].rdesc); + return PTR_ERR(desc); + } + + spinand->dirmaps[plane].wdesc_ecc = desc; + + info.op_tmpl = *spinand->op_templates.read_cache; + info.op_tmpl.data.ecc = true; + desc = spi_mem_dirmap_create(spinand->slave, &info); + if (IS_ERR(desc)) { + spi_mem_dirmap_destroy(spinand->dirmaps[plane].wdesc); + spi_mem_dirmap_destroy(spinand->dirmaps[plane].rdesc); + spi_mem_dirmap_destroy(spinand->dirmaps[plane].wdesc_ecc); + return PTR_ERR(desc); + } + + spinand->dirmaps[plane].rdesc_ecc = desc; + return 0; } @@ -1022,7 +1137,7 @@ int spinand_match_and_init(struct spinand_device *spinand, continue; nand->memorg = table[i].memorg; - nand->eccreq = table[i].eccreq; + nanddev_set_ecc_requirements(nand, &table[i].eccreq); spinand->eccinfo = table[i].eccinfo; spinand->flags = table[i].flags; spinand->id.len = 1 + table[i].devid.len; @@ -1174,6 +1289,15 @@ static int spinand_init(struct spinand_device *spinand) if (ret) goto err_manuf_cleanup; + /* SPI-NAND default ECC engine is on-die */ + nand->ecc.defaults.engine_type = NAND_ECC_ENGINE_TYPE_ON_DIE; + nand->ecc.ondie_engine = &spinand_ondie_ecc_engine; + + spinand_ecc_enable(spinand, false); + ret = nanddev_ecc_engine_init(nand); + if (ret) + goto err_cleanup_nanddev; + mtd->_read_oob = spinand_mtd_read; mtd->_write_oob = spinand_mtd_write; mtd->_block_isbad = spinand_mtd_block_isbad; @@ -1181,17 +1305,18 @@ static int spinand_init(struct spinand_device *spinand) mtd->_block_isreserved = spinand_mtd_block_isreserved; mtd->_erase = spinand_mtd_erase; - if (spinand->eccinfo.ooblayout) - mtd_set_ooblayout(mtd, spinand->eccinfo.ooblayout); - else - mtd_set_ooblayout(mtd, &spinand_noecc_ooblayout); - - ret = mtd_ooblayout_count_freebytes(mtd); - if (ret < 0) - goto err_cleanup_nanddev; + if (nand->ecc.engine) { + ret = mtd_ooblayout_count_freebytes(mtd); + if (ret < 0) + goto err_cleanup_ecc_engine; + } mtd->oobavail = ret; + /* Propagate ECC information to mtd_info */ + mtd->ecc_strength = nanddev_get_ecc_conf(nand)->strength; + mtd->ecc_step_size = nanddev_get_ecc_conf(nand)->step_size; + ret = spinand_create_dirmaps(spinand); if (ret) { dev_err(dev, @@ -1203,6 +1328,7 @@ static int spinand_init(struct spinand_device *spinand) return 0; err_cleanup_ecc_engine: + nanddev_ecc_engine_cleanup(nand); err_cleanup_nanddev: nanddev_cleanup(nand); diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c index 86bffc2800b..064a9d6b2fe 100644 --- a/drivers/mtd/nand/spi/macronix.c +++ b/drivers/mtd/nand/spi/macronix.c @@ -87,10 +87,11 @@ static int mx35lf1ge4ab_ecc_get_status(struct spinand_device *spinand, * data around if it's not necessary. */ if (mx35lf1ge4ab_get_eccsr(spinand, &eccsr)) - return nand->eccreq.strength; + return nanddev_get_ecc_conf(nand)->strength; - if (WARN_ON(eccsr > nand->eccreq.strength || !eccsr)) - return nand->eccreq.strength; + if (WARN_ON(eccsr > nanddev_get_ecc_conf(nand)->strength || + !eccsr)) + return nanddev_get_ecc_conf(nand)->strength; return eccsr; diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c index b538213ed8e..01c177facfb 100644 --- a/drivers/mtd/nand/spi/micron.c +++ b/drivers/mtd/nand/spi/micron.c @@ -14,7 +14,7 @@ #define SPINAND_MFR_MICRON 0x2c -#define MICRON_STATUS_ECC_MASK GENMASK(7, 4) +#define MICRON_STATUS_ECC_MASK GENMASK(6, 4) #define MICRON_STATUS_ECC_NO_BITFLIPS (0 << 4) #define MICRON_STATUS_ECC_1TO3_BITFLIPS (1 << 4) #define MICRON_STATUS_ECC_4TO6_BITFLIPS (3 << 4) diff --git a/drivers/mtd/nand/spi/toshiba.c b/drivers/mtd/nand/spi/toshiba.c index b9908e79271..d264cdf32ce 100644 --- a/drivers/mtd/nand/spi/toshiba.c +++ b/drivers/mtd/nand/spi/toshiba.c @@ -76,7 +76,7 @@ static int tx58cxgxsxraix_ecc_get_status(struct spinand_device *spinand, { struct nand_device *nand = spinand_to_nand(spinand); u8 mbf = 0; - struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, &mbf); + struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, spinand->scratchbuf); switch (status & STATUS_ECC_MASK) { case STATUS_ECC_NO_BITFLIPS: @@ -93,12 +93,12 @@ static int tx58cxgxsxraix_ecc_get_status(struct spinand_device *spinand, * data around if it's not necessary. */ if (spi_mem_exec_op(spinand->slave, &op)) - return nand->eccreq.strength; + return nanddev_get_ecc_conf(nand)->strength; - mbf >>= 4; + mbf = *(spinand->scratchbuf) >> 4; - if (WARN_ON(mbf > nand->eccreq.strength || !mbf)) - return nand->eccreq.strength; + if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf)) + return nanddev_get_ecc_conf(nand)->strength; return mbf; diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c index dd4ed257a83..5fe35e35ed5 100644 --- a/drivers/mtd/nand/spi/winbond.c +++ b/drivers/mtd/nand/spi/winbond.c @@ -111,7 +111,7 @@ static int w25n02kv_ecc_get_status(struct spinand_device *spinand, { struct nand_device *nand = spinand_to_nand(spinand); u8 mbf = 0; - struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, &mbf); + struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, spinand->scratchbuf); switch (status & STATUS_ECC_MASK) { case STATUS_ECC_NO_BITFLIPS: @@ -127,12 +127,12 @@ static int w25n02kv_ecc_get_status(struct spinand_device *spinand, * data around if it's not necessary. */ if (spi_mem_exec_op(spinand->slave, &op)) - return nand->eccreq.strength; + return nanddev_get_ecc_conf(nand)->strength; - mbf >>= 4; + mbf = *(spinand->scratchbuf) >> 4; - if (WARN_ON(mbf > nand->eccreq.strength || !mbf)) - return nand->eccreq.strength; + if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf)) + return nanddev_get_ecc_conf(nand)->strength; return mbf; diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 0afdaed5715..76808559b72 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -12,6 +12,8 @@ #include +struct nand_device; + /** * struct nand_memory_organization - Memory organization structure * @bits_per_cell: number of bits per NAND cell @@ -126,17 +128,72 @@ struct nand_page_io_req { }; /** - * struct nand_ecc_req - NAND ECC requirements + * enum nand_ecc_engine_type - NAND ECC engine type + * @NAND_ECC_ENGINE_TYPE_INVALID: Invalid value + * @NAND_ECC_ENGINE_TYPE_NONE: No ECC correction + * @NAND_ECC_ENGINE_TYPE_SOFT: Software ECC correction + * @NAND_ECC_ENGINE_TYPE_ON_HOST: On host hardware ECC correction + * @NAND_ECC_ENGINE_TYPE_ON_DIE: On chip hardware ECC correction + */ +enum nand_ecc_engine_type { + NAND_ECC_ENGINE_TYPE_INVALID, + NAND_ECC_ENGINE_TYPE_NONE, + NAND_ECC_ENGINE_TYPE_SOFT, + NAND_ECC_ENGINE_TYPE_ON_HOST, + NAND_ECC_ENGINE_TYPE_ON_DIE, +}; + +/** + * enum nand_ecc_placement - NAND ECC bytes placement + * @NAND_ECC_PLACEMENT_UNKNOWN: The actual position of the ECC bytes is unknown + * @NAND_ECC_PLACEMENT_OOB: The ECC bytes are located in the OOB area + * @NAND_ECC_PLACEMENT_INTERLEAVED: Syndrome layout, there are ECC bytes + * interleaved with regular data in the main + * area + */ +enum nand_ecc_placement { + NAND_ECC_PLACEMENT_UNKNOWN, + NAND_ECC_PLACEMENT_OOB, + NAND_ECC_PLACEMENT_INTERLEAVED, +}; + +/** + * enum nand_ecc_algo - NAND ECC algorithm + * @NAND_ECC_ALGO_UNKNOWN: Unknown algorithm + * @NAND_ECC_ALGO_HAMMING: Hamming algorithm + * @NAND_ECC_ALGO_BCH: Bose-Chaudhuri-Hocquenghem algorithm + * @NAND_ECC_ALGO_RS: Reed-Solomon algorithm + */ +enum nand_ecc_algo { + NAND_ECC_ALGO_UNKNOWN, + NAND_ECC_ALGO_HAMMING, + NAND_ECC_ALGO_BCH, + NAND_ECC_ALGO_RS, +}; + +/** + * struct nand_ecc_props - NAND ECC properties + * @engine_type: ECC engine type + * @placement: OOB placement (if relevant) + * @algo: ECC algorithm (if relevant) * @strength: ECC strength - * @step_size: ECC step/block size + * @step_size: Number of bytes per step + * @flags: Misc properties */ -struct nand_ecc_req { +struct nand_ecc_props { + enum nand_ecc_engine_type engine_type; + enum nand_ecc_placement placement; + enum nand_ecc_algo algo; unsigned int strength; unsigned int step_size; + unsigned int flags; }; #define NAND_ECCREQ(str, stp) { .strength = (str), .step_size = (stp) } +/* NAND ECC misc flags */ +#define NAND_ECC_MAXIMIZE_STRENGTH BIT(0) + /** * struct nand_bbt - bad block table object * @cache: in memory BBT cache @@ -145,8 +202,6 @@ struct nand_bbt { unsigned long *cache; }; -struct nand_device; - /** * struct nand_ops - NAND operations * @erase: erase a specific block. No need to check if the block is bad before @@ -169,11 +224,129 @@ struct nand_ops { bool (*isbad)(struct nand_device *nand, const struct nand_pos *pos); }; +/** + * struct nand_ecc_context - Context for the ECC engine + * @conf: basic ECC engine parameters + * @nsteps: number of ECC steps + * @total: total number of bytes used for storing ECC codes, this is used by + * generic OOB layouts + * @priv: ECC engine driver private data + */ +struct nand_ecc_context { + struct nand_ecc_props conf; + unsigned int nsteps; + unsigned int total; + void *priv; +}; + +/** + * struct nand_ecc_engine_ops - ECC engine operations + * @init_ctx: given a desired user configuration for the pointed NAND device, + * requests the ECC engine driver to setup a configuration with + * values it supports. + * @cleanup_ctx: clean the context initialized by @init_ctx. + * @prepare_io_req: is called before reading/writing a page to prepare the I/O + * request to be performed with ECC correction. + * @finish_io_req: is called after reading/writing a page to terminate the I/O + * request and ensure proper ECC correction. + */ +struct nand_ecc_engine_ops { + int (*init_ctx)(struct nand_device *nand); + void (*cleanup_ctx)(struct nand_device *nand); + int (*prepare_io_req)(struct nand_device *nand, + struct nand_page_io_req *req); + int (*finish_io_req)(struct nand_device *nand, + struct nand_page_io_req *req); +}; + +/** + * enum nand_ecc_engine_integration - How the NAND ECC engine is integrated + * @NAND_ECC_ENGINE_INTEGRATION_INVALID: Invalid value + * @NAND_ECC_ENGINE_INTEGRATION_PIPELINED: Pipelined engine, performs on-the-fly + * correction, does not need to copy + * data around + * @NAND_ECC_ENGINE_INTEGRATION_EXTERNAL: External engine, needs to bring the + * data into its own area before use + */ +enum nand_ecc_engine_integration { + NAND_ECC_ENGINE_INTEGRATION_INVALID, + NAND_ECC_ENGINE_INTEGRATION_PIPELINED, + NAND_ECC_ENGINE_INTEGRATION_EXTERNAL, +}; + +/** + * struct nand_ecc_engine - ECC engine abstraction for NAND devices + * @dev: Host device + * @node: Private field for registration time + * @ops: ECC engine operations + * @integration: How the engine is integrated with the host + * (only relevant on %NAND_ECC_ENGINE_TYPE_ON_HOST engines) + * @priv: Private data + */ +struct nand_ecc_engine { + struct device *dev; + struct list_head node; + struct nand_ecc_engine_ops *ops; + enum nand_ecc_engine_integration integration; + void *priv; +}; + +int nand_ecc_init_ctx(struct nand_device *nand); +void nand_ecc_cleanup_ctx(struct nand_device *nand); +int nand_ecc_prepare_io_req(struct nand_device *nand, + struct nand_page_io_req *req); +int nand_ecc_finish_io_req(struct nand_device *nand, + struct nand_page_io_req *req); +bool nand_ecc_is_strong_enough(struct nand_device *nand); + +struct nand_ecc_engine *nand_ecc_get_sw_engine(struct nand_device *nand); +struct nand_ecc_engine *nand_ecc_get_on_die_hw_engine(struct nand_device *nand); +struct nand_ecc_engine *nand_ecc_get_on_host_hw_engine(struct nand_device *nand); +void nand_ecc_put_on_host_hw_engine(struct nand_device *nand); +struct device *nand_ecc_get_engine_dev(struct device *host); + +#if defined(CONFIG_MTD_NAND_ECC_SW_HAMMING) +struct nand_ecc_engine *nand_ecc_sw_hamming_get_engine(void); +#else +static inline struct nand_ecc_engine *nand_ecc_sw_hamming_get_engine(void) +{ + return NULL; +} +#endif + +#if defined(CONFIG_MTD_NAND_ECC_SW_BCH) +struct nand_ecc_engine *nand_ecc_sw_bch_get_engine(void); +#else +static inline struct nand_ecc_engine *nand_ecc_sw_bch_get_engine(void) +{ + return NULL; +} +#endif + +/** + * struct nand_ecc - Information relative to the ECC + * @defaults: Default values, depend on the underlying subsystem + * @requirements: ECC requirements from the NAND chip perspective + * @user_conf: User desires in terms of ECC parameters + * @ctx: ECC context for the ECC engine, derived from the device @requirements + * the @user_conf and the @defaults + * @ondie_engine: On-die ECC engine reference, if any + * @engine: ECC engine actually bound + */ +struct nand_ecc { + struct nand_ecc_props defaults; + struct nand_ecc_props requirements; + struct nand_ecc_props user_conf; + struct nand_ecc_context ctx; + struct nand_ecc_engine *ondie_engine; + struct nand_ecc_engine *engine; +}; + /** * struct nand_device - NAND device * @mtd: MTD instance attached to the NAND device * @memorg: memory layout - * @eccreq: ECC requirements + * @ecc: NAND ECC object attached to the NAND device * @rowconv: position to row address converter * @bbt: bad block table info * @ops: NAND operations attached to the NAND device @@ -181,8 +354,8 @@ struct nand_ops { * Generic NAND object. Specialized NAND layers (raw NAND, SPI NAND, OneNAND) * should declare their own NAND object embedding a nand_device struct (that's * how inheritance is done). - * struct_nand_device->memorg and struct_nand_device->eccreq should be filled - * at device detection time to reflect the NAND device + * struct_nand_device->memorg and struct_nand_device->ecc.requirements should + * be filled at device detection time to reflect the NAND device * capabilities/requirements. Once this is done nanddev_init() can be called. * It will take care of converting NAND information into MTD ones, which means * the specialized NAND layers should never manually tweak @@ -191,7 +364,7 @@ struct nand_ops { struct nand_device { struct mtd_info *mtd; struct nand_memory_organization memorg; - struct nand_ecc_req eccreq; + struct nand_ecc ecc; struct nand_row_converter rowconv; struct nand_bbt bbt; const struct nand_ops *ops; @@ -332,7 +505,7 @@ static inline unsigned int nanddev_ntargets(const struct nand_device *nand) } /** - * nanddev_neraseblocks() - Get the total number of erasablocks + * nanddev_neraseblocks() - Get the total number of eraseblocks * @nand: NAND device * * Return: the total number of eraseblocks exposed by @nand. @@ -370,6 +543,60 @@ nanddev_get_memorg(struct nand_device *nand) return &nand->memorg; } +/** + * nanddev_get_ecc_conf() - Extract the ECC configuration from a NAND device + * @nand: NAND device + */ +static inline const struct nand_ecc_props * +nanddev_get_ecc_conf(struct nand_device *nand) +{ + return &nand->ecc.ctx.conf; +} + +/** + * nanddev_get_ecc_nsteps() - Extract the number of ECC steps + * @nand: NAND device + */ +static inline unsigned int +nanddev_get_ecc_nsteps(struct nand_device *nand) +{ + return nand->ecc.ctx.nsteps; +} + +/** + * nanddev_get_ecc_bytes_per_step() - Extract the number of ECC bytes per step + * @nand: NAND device + */ +static inline unsigned int +nanddev_get_ecc_bytes_per_step(struct nand_device *nand) +{ + return nand->ecc.ctx.total / nand->ecc.ctx.nsteps; +} + +/** + * nanddev_get_ecc_requirements() - Extract the ECC requirements from a NAND + * device + * @nand: NAND device + */ +static inline const struct nand_ecc_props * +nanddev_get_ecc_requirements(struct nand_device *nand) +{ + return &nand->ecc.requirements; +} + +/** + * nanddev_set_ecc_requirements() - Assign the ECC requirements of a NAND + * device + * @nand: NAND device + * @reqs: Requirements + */ +static inline void +nanddev_set_ecc_requirements(struct nand_device *nand, + const struct nand_ecc_props *reqs) +{ + nand->ecc.requirements = *reqs; +} + int nanddev_init(struct nand_device *nand, const struct nand_ops *ops, struct module *owner); void nanddev_cleanup(struct nand_device *nand); @@ -598,7 +825,7 @@ static inline void nanddev_pos_next_eraseblock(struct nand_device *nand, } /** - * nanddev_pos_next_eraseblock() - Move a position to the next page + * nanddev_pos_next_page() - Move a position to the next page * @nand: NAND device * @pos: the position to update * @@ -708,8 +935,18 @@ static inline bool nanddev_io_iter_end(struct nand_device *nand, bool nanddev_isbad(struct nand_device *nand, const struct nand_pos *pos); bool nanddev_isreserved(struct nand_device *nand, const struct nand_pos *pos); +int nanddev_erase(struct nand_device *nand, const struct nand_pos *pos); int nanddev_markbad(struct nand_device *nand, const struct nand_pos *pos); +/* ECC related functions */ +int nanddev_ecc_engine_init(struct nand_device *nand); +void nanddev_ecc_engine_cleanup(struct nand_device *nand); + +static inline void *nand_to_ecc_ctx(struct nand_device *nand) +{ + return nand->ecc.ctx.priv; +} + /* BBT related functions */ enum nand_bbt_block_status { NAND_BBT_BLOCK_STATUS_UNKNOWN, @@ -760,5 +997,6 @@ static inline bool nanddev_bbt_is_initialized(struct nand_device *nand) /* MTD -> NAND helper functions. */ int nanddev_mtd_erase(struct mtd_info *mtd, struct erase_info *einfo); +int nanddev_mtd_max_bad_blocks(struct mtd_info *mtd, loff_t offs, size_t len); #endif /* __LINUX_MTD_NAND_H */ diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h index b701d25f73d..cb32bd44a9a 100644 --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h @@ -316,6 +316,15 @@ struct spinand_ecc_info { #define SPINAND_HAS_QE_BIT BIT(0) #define SPINAND_HAS_CR_FEAT_BIT BIT(1) +/** + * struct spinand_ondie_ecc_conf - private SPI-NAND on-die ECC engine structure + * @status: status of the last wait operation that will be used in case + * ->get_status() is not populated by the spinand device. + */ +struct spinand_ondie_ecc_conf { + u8 status; +}; + /** * struct spinand_info - Structure used to describe SPI NAND chips * @model: model name @@ -339,7 +348,7 @@ struct spinand_info { struct spinand_devid devid; u32 flags; struct nand_memory_organization memorg; - struct nand_ecc_req eccreq; + struct nand_ecc_props eccreq; struct spinand_ecc_info eccinfo; struct { const struct spinand_op_variants *read_cache; @@ -388,6 +397,8 @@ struct spinand_info { struct spinand_dirmap { struct spi_mem_dirmap_desc *wdesc; struct spi_mem_dirmap_desc *rdesc; + struct spi_mem_dirmap_desc *wdesc_ecc; + struct spi_mem_dirmap_desc *rdesc_ecc; }; /** diff --git a/include/spi-mem.h b/include/spi-mem.h index 3c8e95b6f53..82dbe21fd5a 100644 --- a/include/spi-mem.h +++ b/include/spi-mem.h @@ -91,6 +91,7 @@ enum spi_mem_data_dir { * @dummy.dtr: whether the dummy bytes should be sent in DTR mode or not * @data.buswidth: number of IO lanes used to send/receive the data * @data.dtr: whether the data should be sent in DTR mode or not + * @data.ecc: whether error correction is required or not * @data.dir: direction of the transfer * @data.buf.in: input buffer * @data.buf.out: output buffer @@ -119,6 +120,7 @@ struct spi_mem_op { struct { u8 buswidth; u8 dtr : 1; + u8 ecc : 1; enum spi_mem_data_dir dir; unsigned int nbytes; /* buf.{in,out} must be DMA-able. */ From patchwork Thu Jun 27 11:20:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Kshevetskiy X-Patchwork-Id: 1953187 X-Patchwork-Delegate: dario.binacchi@amarulasolutions.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.a=rsa-sha256 header.s=selector2 header.b=mulAJfUk; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4W8x396S9xz20Xg for ; Thu, 27 Jun 2024 21:21:25 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id EB9AC8852E; Thu, 27 Jun 2024 13:20:29 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.b="mulAJfUk"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id F2CE2885A2; Thu, 27 Jun 2024 13:20:26 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,SPF_HELO_PASS, SPF_PASS autolearn=no autolearn_force=no version=3.4.2 Received: from EUR03-VI1-obe.outbound.protection.outlook.com (mail-vi1eur03on2072f.outbound.protection.outlook.com [IPv6:2a01:111:f403:260c::72f]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 3B0B888566 for ; Thu, 27 Jun 2024 13:20:24 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mikhail.kshevetskiy@genexis.eu ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Ea1Hz6fR1Ba4wO37bvQWVBGDhDHQLZtaLFy7rQGah/d6IGAtf47Xgv0RR911fddJrI+3h0y/maJ1ack9teTXF3wFwqlrMAEWP3jxVPRsCmz1AakeTUp8wSMkNfMWPcXD72DnrlVAiwViIWZY+FlmbEPcaH0WA8BPv+soRNEsDm2l1GAsf37P9q7oXZ3WGcdfSuLqL9RZcfsHOgLJ3VjKhpDmCx+2TNKYb4cLW808ATChhLQJlze4fuOJTiEqZRnHHf+GEZg6bJHuy+S9vQa92leKHwDmey/Wkt82kvGTlIbXIWzrW3+YZnJV2SXK8SgOCspbJNUzuv1enCYOHqsI+g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=6S0EMdBdnG2TMoms/Rvf926OmDTjdpeAFkgct9DnsNk=; b=e//7Gz9QQs4CzoFrrNe4eXKkoCSQsVRZvx5h4DGHtXTEoNI99wsBa276zScg25mTwJPGmbEmCo/xE+gU54nTmwlVFG4MlTRNDIb3z4GrqaKx/D0H36lClYWryD4AHoV9oMgdWV5/WLGHVUi+8Ev2Bzcji5bL2PVG2Tmpgl5RoTbTSwsB3j+wTPd8+jOVN2A4nkgTNhiKv/yWoEY66aihxZEE1IxXRpblUdlaVvnaHDMPlQba2WBL8J/KkmobaGmvRMqN9a5NujQ7gXkBTlvthQhsNomk+mSFqPeHfplxTMOCs/gGoJZOJwFG+uE33iE9q/HOaJXkzPNIGCyBVRt8Mw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=genexis.eu; dmarc=pass action=none header.from=iopsys.eu; dkim=pass header.d=iopsys.eu; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iopsys.eu; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=6S0EMdBdnG2TMoms/Rvf926OmDTjdpeAFkgct9DnsNk=; b=mulAJfUk7aMKPaqaR+7XuXyO4HbLzjNXXgEtvPuTgbHWskA5W3mnvYvJwedTeO72prHtmC+nqyVUHhSkqYW/eQr2H83JvxQH057APrCWYvB6h8apS2a9bPgRrs3YgbUckxWWLDWZCVy6XnjvT0f5FjZrWB6nfgnoihFflE/B/UOi7qhim9SJx5tuTZn4uYTG1Xp80WkmbbKIVX9H8TrRdd+YN4ka44xu/boSlmOcOBKviwKtUVcHBDz6zn//1jgN6rN6D8+Yqazj24H5NIt6bWF/lSZEv6wJMwfozQBckHLaO157La6bn2oL/gKxDfdE1g3X8sqdDPdWQaGQPJbEMg== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=iopsys.eu; Received: from GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) by PA4PR08MB6064.eurprd08.prod.outlook.com (2603:10a6:102:e2::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.35; Thu, 27 Jun 2024 11:20:19 +0000 Received: from GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0]) by GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0%5]) with mapi id 15.20.7698.025; Thu, 27 Jun 2024 11:20:19 +0000 From: Mikhail Kshevetskiy To: Tom Rini , Dario Binacchi , Michael Trimarchi , Frieder Schrempf , Jagan Teki , Simon Glass , William Zhang , Igor Prusov , Bruce Suen , Dmitry Rokosov , Martin Kurbanov , Chuanhong Guo , Miquel Raynal , Francesco Dolcini , Max Krummenacher , u-boot@lists.denx.de Subject: [PATCH 6/7] mtd: spinand: sync supported flashes with linux-6.6 Date: Thu, 27 Jun 2024 14:20:04 +0300 Message-ID: <20240627112005.99375-6-mikhail.kshevetskiy@iopsys.eu> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240627112005.99375-1-mikhail.kshevetskiy@iopsys.eu> References: <20240627112005.99375-1-mikhail.kshevetskiy@iopsys.eu> X-ClientProxiedBy: GVX0EPF0000FA79.SWEP280.PROD.OUTLOOK.COM (2603:10a6:144:1:0:4:0:6) To GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: GV2PR08MB8121:EE_|PA4PR08MB6064:EE_ X-MS-Office365-Filtering-Correlation-Id: 9f39e093-1741-4b75-17d1-08dc969b20c3 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|1800799024|366016|52116014|7416014|376014|38350700014|921020; X-Microsoft-Antispam-Message-Info: ORbFpf1Yl1o9a9pj1AoLcobgMz5kUk9n/pejsAX5QVof5zlF4P5+hcA72TDIda83qJbMI8cV9f4lvMunfByaZxH3MNDdOF+x9d5nogDbIei6pW/lOg0oR991OHQCGQ91rxOwXW6mNsq4ysGjrzn0SC3a5Bzayj2vRFTRpKV7qjWXixrOQWehz7nvEjGZ97SH0Tj4zuyONH4QfZq1SGrGbySPpYXBVx+Exz1mkoGDjBfJnpINCe3AkkjxzLS+KwH5bWPQZqXNSyrKqrAH5Y0ff1jsli4s7eBdQAx9+GZdgpyOFv0b/nzZcrVS9m6Pd3WjuHXaovmm0ObvYd8E6whYqI+F0hGsjOg1MuD4clNrgCn3oum3CjCvoszHZpnoS2uw0FpHd2lQ2jmWuNeMnu47c8iQsZPhUNbDoyG0LLFLyd7qUw3aNPBTkDPmAntKMNzlG16n8b1zSYHJHjO0CRctk1DpeMuRV/tEpOD62aGV5tFZkR12hm+IlsR4RCORZZQR9nNosvbDX32XIwc7SilcdwN4xXakr73kXl/0xELrR410z7rxIB2S7YXFMIYSC9J10cQYglVUArvmm5BSwX4fpaorV6312YKTAH0k02xZVCdehgYHGpEblAUDNXkylJbxQSXKoTbqBtkmeuqVvfZhFph5ZoUxMf9/EWkt5WfhhkE96YHh/plw15tZcw1Da+T588ixnDim4++um7HDq3zl4EAasolGDz9KIhEend2UCIAIO9VfCHwYzMLPUTC3ws8JKSwJhjIG8eAaAnNC7U5PQzDY04oYz/Y1bcMECew4P3JBGVbAiWIY1jJshxcq0cSlG4aKs8o5+MkXt/LQSLAri/S6lPtddNg1tNRU6QxNTakjBYXe4R4Be/U0k/g/ptkYsO3tWNM46riR4zAxjuETGfNXnVAwv+droAWjhuKrVC4UcHrDYM263oeJcVsFm/m0qWjOAFyrQq1n7JQBJDYPwxDiMrP8DFxuiosy/OXunnksTOr68A7Ifvtxt0OGBqyJgW0FwI5VFBYv6Lu/6CRv9DxLs1hY77LaDOfEWMfctyW3JZIh3Ljv6adExfQcHOP2bvto+nQ5Adf/iJsrFwaJWz+r0VYOI20+wBfPr/+v9J5a1g4KempFoBL3karPvsYNi0JrpxRA1gspD0wLWhYxh3w6YBpofxnmlp6z3yXOh1456YuYnkKrTBdnVv8COBcHpI4UJEKw7PxvRxwkjzm5wgNk2hJF9r8ypgChfZCzyc4oEqOCLYY26+Q6HPy+E8cYHdr/ZMz2iWSk9eX+QH1xlk+odVttXMRxqS2kq0JkB+r3jBHgqF0pNhkELj+4kxmN3x/8HIHZSYQCy8CXt2/UJHCgMrpbiKULVK+HoTk/JBnNqRYRMm4JidBk1wxW8jvKFTvD3K45MbxyeA+lt8K1EOZ3AVQZP3D18+3J9sO7voQ= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:GV2PR08MB8121.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(1800799024)(366016)(52116014)(7416014)(376014)(38350700014)(921020); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: hmVqJhjSLZT6+9h9LQ6JiOpXkDdOJQQtrKRtFzb+aSskkTRJnRx1wCAdXTvojGHhbrQVCdEIx2zlsf1SemrDy1f5D8taB3SG79XBwiEfoZuEUO2fHqHxNNM7FeAswQUdevJF8vRvXr3+0/g79zVGXovYpNoJ7dtWvlXD8GWrANdCPUk3Bm9mffAUI2K/apTRGmX2Q/at4oAvNbh3faxMLqr0M2zKdcf8SXQQgRTPoPYcfF1a2/t/c7FSlBKL6OcYW87GuUEEMXBpCkPIzg7+HCplttvkXv0yRqN55yLMv3V3KlpJq+CQgJVrfKcIr9K4JE/RoY7CblFFRrlkwIotzYxAPiNZUqHd5WwzBQVt3MSaMesUSm4Z7eNOPBRa0vi+zjysLgWxAiCLEd5Y8Q9o1VkwSAKY7ydUtcxSqFRLWX8KbLEmUgnkDEXhgrHt+hLsukKvCy7Bc9sxd8obfkl8IKuEszC5fURcrA2Khx9ZSlcHdemPmKJCyYXAPRf/IPgv+F57kEqYuneUm85J3a/aBhTqpnzkZcwjWL63g09yIxMtAzoGV/0BfTpo0/MIEGPCrwdszNHDaj00Kwj9MUAjOk6TnqW1pvoBkhYmTit7kWPVtrU36/lf/dgXmNIOupcafyPz8Tr7j3/OszpSj5JGVdh9lQhGsFf4Sbp3BYZ6aL97IxrLvm/WteWjA1NZHomTf2fb4TzATlJbtAvV/xNH8vQeTvd84peOAawVpb9bZNcxhFpCf3bWuJXoHloqpmxpJwZxXBWojV9ENy+Wc3KGqebN6TsDgin8dsYcs5McxPtBkgvfL7hXjZOh3KO3bamMXZ8dyP2W+xmuDA33wA7nsf8eWGPhvoS6aqwWG0sSjhzy8PZENoZNFjF64A0LQBbr3OyY1aSs0wDCq66lwDJNtA7AHE8AMG+atSIYZ8UiSw3+qQsaPV539ssYTNZv6PLf27VJtfaM32/XNXCHrUAXvZC1T00ksGSGlyaQ+mlZCX+PF9vRVxha3p/X4OIC8pK4Dl2BPg/fejp/0PiNOOscfzZfOedbyqFH6uuG96+skm8J17+bI0EMQ5DL9UcZlC6cIFNOE2owK3IoW9NMcLEoU5D0vV2BeyzM1iJKvQ6DbY8fGjnKLvVRftDIhyjolY8Ubodo38Fdp5pWadOQ6JaFQBpvhKBhWLd7Dw7x2sqlYsDIr/EcvpmRxFsS/cbdQGq3jow+oq6mO4PnYdrUbAcI4psT+zDacQYpD2MwLioCiHqPDCucCCx06QN4KJ7bBXLnILsdSBf1t4uZY806zRMi5wKTYbaYMo6hU7eYqsZpLXjPOR3LWj92ak4P5dnjHwO35ngGB6/LJhA1Ri5UEcL9DO8z59BnHiwRQBIEoRLmi/gbYyTa7FsEmdio41XXKe77vGLsTOuwkyxwWGUlM3o+3VTU4E5qMxAt2iVP05FQfxOKk5Pdm2AxjWp+Hvh+BCBsW5xKHoPD87Cq8vIwClmuB+v8B2eVbuSU6sdVFH1X0TthzFCjD0NgIzgR9XunzskQ2JHG2kZkyHmpPtxRe9GvrWh2VbIpO0wZQKIAarqWMOc0Be6LcI9HO+Go8b/UGnzL7AsWicj5HNZaShSciLxmdjX8NiWAKJfa1+iAUOgTZio= X-OriginatorOrg: iopsys.eu X-MS-Exchange-CrossTenant-Network-Message-Id: 9f39e093-1741-4b75-17d1-08dc969b20c3 X-MS-Exchange-CrossTenant-AuthSource: GV2PR08MB8121.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Jun 2024 11:20:19.5135 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 8d891be1-7bce-4216-9a99-bee9de02ba58 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: gdtY2sIOqAI3zaq/wIQnpTlPZh5LKx8uiJtPwJ0HGR9SkTBJ/FOodkLfi2n20MA0qPCY+B+d1MucotE8jEkWEj+FYf+oQ8ApTS1K8TE8QiQ= X-MS-Exchange-Transport-CrossTenantHeadersStamped: PA4PR08MB6064 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 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" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Signed-off-by: Mikhail Kshevetskiy --- drivers/mtd/nand/spi/Makefile | 4 +- drivers/mtd/nand/spi/alliancememory.c | 155 +++++++++++++++++++++ drivers/mtd/nand/spi/ato.c | 84 ++++++++++++ drivers/mtd/nand/spi/core.c | 4 +- drivers/mtd/nand/spi/esmt.c | 9 ++ drivers/mtd/nand/spi/gigadevice.c | 188 +++++++++++++++++++++++++- drivers/mtd/nand/spi/macronix.c | 20 +++ drivers/mtd/nand/spi/toshiba.c | 33 +++++ include/linux/mtd/spinand.h | 4 +- 9 files changed, 496 insertions(+), 5 deletions(-) create mode 100644 drivers/mtd/nand/spi/alliancememory.c create mode 100644 drivers/mtd/nand/spi/ato.c diff --git a/drivers/mtd/nand/spi/Makefile b/drivers/mtd/nand/spi/Makefile index 65b836b34ca..6c733c0cc65 100644 --- a/drivers/mtd/nand/spi/Makefile +++ b/drivers/mtd/nand/spi/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -spinand-objs := core.o esmt.o gigadevice.o macronix.o micron.o paragon.o -spinand-objs += toshiba.o winbond.o xtx.o +spinand-objs := core.o alliancememory.o ato.o esmt.o gigadevice.o macronix.o +spinand-objs += micron.o paragon.o toshiba.o winbond.o xtx.o obj-$(CONFIG_MTD_SPI_NAND) += spinand.o diff --git a/drivers/mtd/nand/spi/alliancememory.c b/drivers/mtd/nand/spi/alliancememory.c new file mode 100644 index 00000000000..e29e4cc77ec --- /dev/null +++ b/drivers/mtd/nand/spi/alliancememory.c @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Author: Mario Kicherer + */ + +#ifndef __UBOOT__ +#include +#include +#endif +#include + +#define SPINAND_MFR_ALLIANCEMEMORY 0x52 + +#define AM_STATUS_ECC_BITMASK (3 << 4) + +#define AM_STATUS_ECC_NONE_DETECTED (0 << 4) +#define AM_STATUS_ECC_CORRECTED (1 << 4) +#define AM_STATUS_ECC_ERRORED (2 << 4) +#define AM_STATUS_ECC_MAX_CORRECTED (3 << 4) + +static SPINAND_OP_VARIANTS(read_cache_variants, + SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); + +static SPINAND_OP_VARIANTS(write_cache_variants, + SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), + SPINAND_PROG_LOAD(true, 0, NULL, 0)); + +static SPINAND_OP_VARIANTS(update_cache_variants, + SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), + SPINAND_PROG_LOAD(false, 0, NULL, 0)); + +static int am_get_eccsize(struct mtd_info *mtd) +{ + if (mtd->oobsize == 64) + return 0x20; + else if (mtd->oobsize == 128) + return 0x38; + else if (mtd->oobsize == 256) + return 0x70; + else + return -EINVAL; +} + +static int am_ooblayout_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) +{ + int ecc_bytes; + + ecc_bytes = am_get_eccsize(mtd); + if (ecc_bytes < 0) + return ecc_bytes; + + region->offset = mtd->oobsize - ecc_bytes; + region->length = ecc_bytes; + + return 0; +} + +static int am_ooblayout_free(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) +{ + int ecc_bytes; + + if (section) + return -ERANGE; + + ecc_bytes = am_get_eccsize(mtd); + if (ecc_bytes < 0) + return ecc_bytes; + + /* + * It is unclear how many bytes are used for the bad block marker. We + * reserve the common two bytes here. + * + * The free area in this kind of flash is divided into chunks where the + * first 4 bytes of each chunk are unprotected. The number of chunks + * depends on the specific model. The models with 4096+256 bytes pages + * have 8 chunks, the others 4 chunks. + */ + + region->offset = 2; + region->length = mtd->oobsize - 2 - ecc_bytes; + + return 0; +} + +static const struct mtd_ooblayout_ops am_ooblayout = { + .ecc = am_ooblayout_ecc, + .rfree = am_ooblayout_free, +}; + +static int am_ecc_get_status(struct spinand_device *spinand, u8 status) +{ + switch (status & AM_STATUS_ECC_BITMASK) { + case AM_STATUS_ECC_NONE_DETECTED: + return 0; + + case AM_STATUS_ECC_CORRECTED: + /* + * use oobsize to determine the flash model and the maximum of + * correctable errors and return maximum - 1 by convention + */ + if (spinand->base.mtd->oobsize == 64) + return 3; + else + return 7; + + case AM_STATUS_ECC_ERRORED: + return -EBADMSG; + + case AM_STATUS_ECC_MAX_CORRECTED: + /* + * use oobsize to determine the flash model and the maximum of + * correctable errors + */ + if (spinand->base.mtd->oobsize == 64) + return 4; + else + return 8; + + default: + break; + } + + return -EINVAL; +} + +static const struct spinand_info alliancememory_spinand_table[] = { + SPINAND_INFO("AS5F34G04SND", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x2f), + NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 1, 1, 1), + NAND_ECCREQ(4, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&am_ooblayout, + am_ecc_get_status)), +}; + +static const struct spinand_manufacturer_ops alliancememory_spinand_manuf_ops = { +}; + +const struct spinand_manufacturer alliancememory_spinand_manufacturer = { + .id = SPINAND_MFR_ALLIANCEMEMORY, + .name = "AllianceMemory", + .chips = alliancememory_spinand_table, + .nchips = ARRAY_SIZE(alliancememory_spinand_table), + .ops = &alliancememory_spinand_manuf_ops, +}; diff --git a/drivers/mtd/nand/spi/ato.c b/drivers/mtd/nand/spi/ato.c new file mode 100644 index 00000000000..f0d4436cf45 --- /dev/null +++ b/drivers/mtd/nand/spi/ato.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022 Aidan MacDonald + * + * Author: Aidan MacDonald + */ + +#ifndef __UBOOT__ +#include +#include +#endif +#include + +#define SPINAND_MFR_ATO 0x9b + +static SPINAND_OP_VARIANTS(read_cache_variants, + SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); + +static SPINAND_OP_VARIANTS(write_cache_variants, + SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), + SPINAND_PROG_LOAD(true, 0, NULL, 0)); + +static SPINAND_OP_VARIANTS(update_cache_variants, + SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), + SPINAND_PROG_LOAD(false, 0, NULL, 0)); + +static int ato25d1ga_ooblayout_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) +{ + if (section > 3) + return -ERANGE; + + region->offset = (16 * section) + 8; + region->length = 8; + return 0; +} + +static int ato25d1ga_ooblayout_free(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) +{ + if (section > 3) + return -ERANGE; + + if (section) { + region->offset = (16 * section); + region->length = 8; + } else { + /* first byte of section 0 is reserved for the BBM */ + region->offset = 1; + region->length = 7; + } + + return 0; +} + +static const struct mtd_ooblayout_ops ato25d1ga_ooblayout = { + .ecc = ato25d1ga_ooblayout_ecc, + .rfree = ato25d1ga_ooblayout_free, +}; + +static const struct spinand_info ato_spinand_table[] = { + SPINAND_INFO("ATO25D1GA", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x12), + NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), + NAND_ECCREQ(1, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&ato25d1ga_ooblayout, NULL)), +}; + +static const struct spinand_manufacturer_ops ato_spinand_manuf_ops = { +}; + +const struct spinand_manufacturer ato_spinand_manufacturer = { + .id = SPINAND_MFR_ATO, + .name = "ATO", + .chips = ato_spinand_table, + .nchips = ARRAY_SIZE(ato_spinand_table), + .ops = &ato_spinand_manuf_ops, +}; diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index c60c3dfad68..9d0d49e32f6 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -987,13 +987,15 @@ static const struct nand_ops spinand_ops = { }; static const struct spinand_manufacturer *spinand_manufacturers[] = { + &alliancememory_spinand_manufacturer, + &ato_spinand_manufacturer, + &esmt_c8_spinand_manufacturer, &gigadevice_spinand_manufacturer, ¯onix_spinand_manufacturer, µn_spinand_manufacturer, ¶gon_spinand_manufacturer, &toshiba_spinand_manufacturer, &winbond_spinand_manufacturer, - &esmt_c8_spinand_manufacturer, &xtx_spinand_manufacturer, }; diff --git a/drivers/mtd/nand/spi/esmt.c b/drivers/mtd/nand/spi/esmt.c index 7e07b26827a..8aec927c7ea 100644 --- a/drivers/mtd/nand/spi/esmt.c +++ b/drivers/mtd/nand/spi/esmt.c @@ -123,6 +123,15 @@ static const struct spinand_info esmt_c8_spinand_table[] = { &update_cache_variants), 0, SPINAND_ECCINFO(&f50l1g41lb_ooblayout, NULL)), + SPINAND_INFO("F50D2G41KA", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x51), + NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + 0, + SPINAND_ECCINFO(&f50l1g41lb_ooblayout, NULL)), }; static const struct spinand_manufacturer_ops esmt_spinand_manuf_ops = { diff --git a/drivers/mtd/nand/spi/gigadevice.c b/drivers/mtd/nand/spi/gigadevice.c index f2ecf47f8d4..fe8c76acac6 100644 --- a/drivers/mtd/nand/spi/gigadevice.c +++ b/drivers/mtd/nand/spi/gigadevice.c @@ -43,6 +43,22 @@ static SPINAND_OP_VARIANTS(read_cache_variants_f, SPINAND_PAGE_READ_FROM_CACHE_OP_3A(true, 0, 1, NULL, 0), SPINAND_PAGE_READ_FROM_CACHE_OP_3A(false, 0, 0, NULL, 0)); +static SPINAND_OP_VARIANTS(read_cache_variants_1gq5, + SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); + +static SPINAND_OP_VARIANTS(read_cache_variants_2gq5, + SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 4, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 2, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); + static SPINAND_OP_VARIANTS(write_cache_variants, SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), SPINAND_PROG_LOAD(true, 0, NULL, 0)); @@ -329,6 +345,36 @@ static const struct spinand_info gigadevice_spinand_table[] = { SPINAND_HAS_QE_BIT, SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, gd5fxgq4uexxg_ecc_get_status)), + SPINAND_INFO("GD5F1GQ4RExxG", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xc1), + NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, + gd5fxgq4uexxg_ecc_get_status)), + SPINAND_INFO("GD5F2GQ4UExxG", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xd2), + NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, + gd5fxgq4uexxg_ecc_get_status)), + SPINAND_INFO("GD5F2GQ4RExxG", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xc2), + NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, + gd5fxgq4uexxg_ecc_get_status)), SPINAND_INFO("GD5F1GQ4UFxxG", SPINAND_ID(SPINAND_READID_METHOD_OPCODE, 0xb1, 0x48), NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), @@ -343,12 +389,152 @@ static const struct spinand_info gigadevice_spinand_table[] = { SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x51), NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), NAND_ECCREQ(4, 512), - SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, + gd5fxgq5xexxg_ecc_get_status)), + SPINAND_INFO("GD5F1GQ5RExxG", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x41), + NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), + NAND_ECCREQ(4, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, + gd5fxgq5xexxg_ecc_get_status)), + SPINAND_INFO("GD5F2GQ5UExxG", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x52), + NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(4, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, + gd5fxgq5xexxg_ecc_get_status)), + SPINAND_INFO("GD5F2GQ5RExxG", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x42), + NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(4, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, + gd5fxgq5xexxg_ecc_get_status)), + SPINAND_INFO("GD5F4GQ6UExxG", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x55), + NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 2, 1), + NAND_ECCREQ(4, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, + gd5fxgq5xexxg_ecc_get_status)), + SPINAND_INFO("GD5F4GQ6RExxG", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x45), + NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 2, 1), + NAND_ECCREQ(4, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5, &write_cache_variants, &update_cache_variants), SPINAND_HAS_QE_BIT, SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, gd5fxgq5xexxg_ecc_get_status)), + SPINAND_INFO("GD5F1GM7UExxG", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x91), + NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, + gd5fxgq4uexxg_ecc_get_status)), + SPINAND_INFO("GD5F1GM7RExxG", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x81), + NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, + gd5fxgq4uexxg_ecc_get_status)), + SPINAND_INFO("GD5F2GM7UExxG", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x92), + NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, + gd5fxgq4uexxg_ecc_get_status)), + SPINAND_INFO("GD5F2GM7RExxG", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x82), + NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, + gd5fxgq4uexxg_ecc_get_status)), + SPINAND_INFO("GD5F4GM8UExxG", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x95), + NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, + gd5fxgq4uexxg_ecc_get_status)), + SPINAND_INFO("GD5F4GM8RExxG", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x85), + NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, + gd5fxgq4uexxg_ecc_get_status)), + SPINAND_INFO("GD5F2GQ5xExxH", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x22), + NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(4, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants_2gq5, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, + gd5fxgq4uexxg_ecc_get_status)), + SPINAND_INFO("GD5F1GQ5RExxH", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x21), + NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), + NAND_ECCREQ(4, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, + gd5fxgq4uexxg_ecc_get_status)), + SPINAND_INFO("GD5F1GQ4RExxH", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xc9), + NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), + NAND_ECCREQ(4, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants_1gq5, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&gd5fxgqx_variant2_ooblayout, + gd5fxgq4uexxg_ecc_get_status)), }; static const struct spinand_manufacturer_ops gigadevice_spinand_manuf_ops = { diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c index 064a9d6b2fe..3475208c923 100644 --- a/drivers/mtd/nand/spi/macronix.c +++ b/drivers/mtd/nand/spi/macronix.c @@ -301,6 +301,26 @@ static const struct spinand_info macronix_spinand_table[] = { SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, mx35lf1ge4ab_ecc_get_status)), + SPINAND_INFO("MX31LF2GE4BC", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x2e), + NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), + SPINAND_INFO("MX3UF2GE4BC", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xae), + NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, + mx35lf1ge4ab_ecc_get_status)), }; static const struct spinand_manufacturer_ops macronix_spinand_manuf_ops = { diff --git a/drivers/mtd/nand/spi/toshiba.c b/drivers/mtd/nand/spi/toshiba.c index d264cdf32ce..bf7da57de13 100644 --- a/drivers/mtd/nand/spi/toshiba.c +++ b/drivers/mtd/nand/spi/toshiba.c @@ -269,6 +269,39 @@ static const struct spinand_info toshiba_spinand_table[] = { SPINAND_HAS_QE_BIT, SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout, tx58cxgxsxraix_ecc_get_status)), + /* 1.8V 1Gb (1st generation) */ + SPINAND_INFO("TC58NYG0S3HBAI4", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xA1), + NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + 0, + SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout, + tx58cxgxsxraix_ecc_get_status)), + /* 1.8V 4Gb (1st generation) */ + SPINAND_INFO("TH58NYG2S3HBAI4", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xAC), + NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 1, 2, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_x4_variants, + &update_cache_x4_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout, + tx58cxgxsxraix_ecc_get_status)), + /* 1.8V 8Gb (1st generation) */ + SPINAND_INFO("TH58NYG3S0HBAI6", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xA3), + NAND_MEMORG(1, 4096, 256, 64, 4096, 80, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_x4_variants, + &update_cache_x4_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&tx58cxgxsxraix_ooblayout, + tx58cxgxsxraix_ecc_get_status)), }; static const struct spinand_manufacturer_ops toshiba_spinand_manuf_ops = { diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h index cb32bd44a9a..ef15e184f2e 100644 --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h @@ -266,13 +266,15 @@ struct spinand_manufacturer { }; /* SPI NAND manufacturers */ +extern const struct spinand_manufacturer alliancememory_spinand_manufacturer; +extern const struct spinand_manufacturer ato_spinand_manufacturer; +extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer; extern const struct spinand_manufacturer gigadevice_spinand_manufacturer; extern const struct spinand_manufacturer macronix_spinand_manufacturer; extern const struct spinand_manufacturer micron_spinand_manufacturer; extern const struct spinand_manufacturer paragon_spinand_manufacturer; extern const struct spinand_manufacturer toshiba_spinand_manufacturer; extern const struct spinand_manufacturer winbond_spinand_manufacturer; -extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer; extern const struct spinand_manufacturer xtx_spinand_manufacturer; /** From patchwork Thu Jun 27 11:20:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikhail Kshevetskiy X-Patchwork-Id: 1953186 X-Patchwork-Delegate: dario.binacchi@amarulasolutions.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.a=rsa-sha256 header.s=selector2 header.b=yvsznJzM; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4W8x303Wbpz20Xg for ; Thu, 27 Jun 2024 21:21:16 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 875928857E; Thu, 27 Jun 2024 13:20:27 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=iopsys.eu header.i=@iopsys.eu header.b="yvsznJzM"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id C0B018852A; Thu, 27 Jun 2024 13:20:25 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,SPF_HELO_PASS, SPF_PASS autolearn=no autolearn_force=no version=3.4.2 Received: from EUR05-AM6-obe.outbound.protection.outlook.com (mail-am6eur05on20727.outbound.protection.outlook.com [IPv6:2a01:111:f403:2612::727]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id EA147885B5 for ; Thu, 27 Jun 2024 13:20:23 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=iopsys.eu Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mikhail.kshevetskiy@genexis.eu ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=PbG6thCKZwx8h40Hk2jHljesnkY5P/DSQ8fsDGuHKXvxVcI+1JQln2sP3RoAMhT6ZDDlrgtHV7tvAl9biIE5/SF76bETrzsvm/06VpsxMx6lFu07Fv1K8Sfzc0yvC96aVAJfOlSE0TgXEQgO9dNrCwCOU4GbQv9tMzPkGXReULFhB7UOTwjX1oTR2M4pC3UF6/xbjaInjgj1nXI/bDCjpWWx5b/XM3Yd1uV8Mp1xTEjsxsuhUQNiCce6YfCEWNASCu1UBUv/VmqAQPGLtBH33vQNdSqv8aEtgvhHTr0JpLtdt5XGbeZUoQi+KoaalV5n3xCjTpBXg9bOsTeXt4TlAQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=nFLRipPIIa5rd7s0ZapIvOyp8CbKJNuM9UY9zwhLcbI=; b=RksErTi9OME5dJs77YM1oWIu2OUbzirk4wUN/Je9I9hJMRVTCiLqufVJF2po0EAMVZvl71lCMAfbjC5x/0KtTBh+nS6UP5AtlVVBQMlE6iDLOqWTI6UJ0Qu1SY2KNtVxKEK/Ya5AUE47Xm3g9xh/1UFJgE5tjTybs27OVKFiHt43cOa96hUYxRmwERhSfa8DZPAVv6jxYI7DLeLoW4pjaD98vKwKarf+6v5oKV2/ayUBhPWSRhpYEsnhTxckbPtMa/7vi/0T1ZGx35enbALVmzdMabJGADwv2hRy0Bq2NEVSDEJr5L9iPWvNmYpjN0AtHvixQazBaIlOxeFAxsL0jQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=genexis.eu; dmarc=pass action=none header.from=iopsys.eu; dkim=pass header.d=iopsys.eu; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iopsys.eu; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=nFLRipPIIa5rd7s0ZapIvOyp8CbKJNuM9UY9zwhLcbI=; b=yvsznJzMVJ/B35S0gex6UWt3Z87iNjaAtcUdVwjoEXrN7c1SBoHLh60NLTDJRWe74rl7Jr7fYW53BhHppSEb67IrrQ4ke6oBPF53UzPAKG/7FNfr7WqL2H2+/8YXw7P71zGoUKX9ClQ0sD/K8bJMzNe380qxXea6AlEVzNQ+TowGm3qrLjoXs5pl62gtImN2qbawKk0ULpmvp9COuLsD60mjYMvAEbfds/OpAkjO4F5hEi56Ie8u0Tg+51uk4Ek8MqmH4cPvqabqI5MbIuRqkDzRcR5WPWnzK5LB+cahxiS3FjJz/FvqwZr5uGCq9bRKOMGjGqCif7xnihOvxcsRxA== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=iopsys.eu; Received: from GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) by AS8PR08MB8970.eurprd08.prod.outlook.com (2603:10a6:20b:5b3::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7698.35; Thu, 27 Jun 2024 11:20:22 +0000 Received: from GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0]) by GV2PR08MB8121.eurprd08.prod.outlook.com ([fe80::4cd3:da80:2532:daa0%5]) with mapi id 15.20.7698.025; Thu, 27 Jun 2024 11:20:22 +0000 From: Mikhail Kshevetskiy To: Tom Rini , Dario Binacchi , Michael Trimarchi , Frieder Schrempf , Jagan Teki , Simon Glass , William Zhang , Igor Prusov , Bruce Suen , Dmitry Rokosov , Martin Kurbanov , Chuanhong Guo , Miquel Raynal , Francesco Dolcini , Max Krummenacher , u-boot@lists.denx.de Subject: [PATCH 7/7] mtd: spinand: add Winbond W25N04KV flash support Date: Thu, 27 Jun 2024 14:20:05 +0300 Message-ID: <20240627112005.99375-7-mikhail.kshevetskiy@iopsys.eu> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240627112005.99375-1-mikhail.kshevetskiy@iopsys.eu> References: <20240627112005.99375-1-mikhail.kshevetskiy@iopsys.eu> X-ClientProxiedBy: GVX0EPF0000FA79.SWEP280.PROD.OUTLOOK.COM (2603:10a6:144:1:0:4:0:6) To GV2PR08MB8121.eurprd08.prod.outlook.com (2603:10a6:150:7d::22) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: GV2PR08MB8121:EE_|AS8PR08MB8970:EE_ X-MS-Office365-Filtering-Correlation-Id: bd83efbd-b20a-422a-31d7-08dc969b218b X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|366016|52116014|376014|7416014|1800799024|921020|38350700014; X-Microsoft-Antispam-Message-Info: nsmLWVNJ2csyAq4Sgeyjy42ii5veT6VDUzmzycDp3EOLahd2U8N6MOHr61Pdagre0bcZKcF8IWQyUXaorAQe/iIH5tC+SiAynrBcKpYTQpEm4fU9kAbmT5QPok1nbAjTM/manSK9U/RTVfO68LizmJKcjNHap5ZbacNsloRGacxLuxxhikzIUGfH3Vmct+I0pGxIYTC7ZagsGKBghrLu0QHGDjQqCAVy7BntwF+ZR/JmDB2m1oPFV6wmOpWk4Y4pRC/yL1syVSfO6V4xF/Qw5+B5lNn2sxdaEYG1zMqN5+bfm4iMHnO1JXSmRCtqeLNsrn79/Rz/uLb1k+BgPqGzQPku27p3XuhvwK1uJhtOZwbl+NPbzdfGbey66BaqnnslzlHWUuhdwuJFfhEoxunGf/6GylZ2YullsffpV3ZlNsIeW/EI+AWAcQFu/af7bfVEd5pLbLFMUbiwKVqdxm2MaPdvnLuSOc7qrKVv5dhGQZW6xS/ICnFQojC0j54Y6zbN4yHvcm06gHEE+xf3fTyL8ZALMriYQIlsr75H3d67zEM+jRWcO5Z5nGtGSJ+pALwjePw0ub71d8kR7rKlr3poCixU9StISrbo+pfYsbX4/wKaTKcblmEVDU1J7fTzPxxPHoqORTwCWuKpfOY5CraO7WVOj7fgikI7Gsv6kZE3YJGqJ7YxFW8Z2L2iB+ovIp1yvmkS+eHgvsJaiT5clQleR21s4ttkJ5PgQFSd/QQbxMtRIWTgfMoNkpg4uZ11w+dwyf5uXbhkg7tbxoPIENM2txPzAwzSUR0PeVX2zTnjI8h3xp+aGn6B8CjScW57teJ1pMBI/6s1/rtdBt0K0n/HsPsk4eT/OUc5QPF07IJmY+IZisTOa4XGlUST6g3sS5b9WMlaCDyMFbPr8vPvCRxXY51hf3CkH+4TgMHsViFd4xM2CZLA7Oc7lns8w6hTAwc3r3yZYNAFLAXZPgZdSY7xBz83L5FDWOU3pDA9nfSTzkaunR6dCOs4WFFyhdzggKsgEoEwGCBWl8vhcIimFJIHGwIOOTzPV7bIwEkC35QlfSC4bBgYddawshwb6ZwGSXM8PIukFpKVupHcJu9plhw5NTA+RYQh/GXVK1yTECGn/8gH2cyR3+cMypLgCtF+Rbv3pR1YeePVQ/cvAT+HoCofhwic4m7xDjgug7xrhKjjQLTCx+DF43aIgZO7sJ+DcZzl0mVkrQm2jM7kIMc+2/x+hKxKJ1mWWJ7fcokaoPSU8j4RblOtSoGMGFF0DOLUWQKZx6vgvDxPVrabiXlq+En1esGsRRos609g9HdX0naU0Ui5bS2jJ/4eBicuw4YdYgLyYPMWBHLZm/0Be0kPCkscZ5r9+h+DNKQB6TF0isdKJ91Ss3AvIp6+6WxGWgkkLIedwnV1MvzQ5iXs95zC69l7AQsn7F6VRvenKQpW3fF0Stc= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:GV2PR08MB8121.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(366016)(52116014)(376014)(7416014)(1800799024)(921020)(38350700014); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: NyKhh21oWaEXA98+P/mBLxDj2sTzqzSj5CfrhBieMCm2+O7hrdnvtojuY+25POn+QniFp1y5PsRMGnBW2d18VJ3UGIJItphW5zypcq/8/m1doGLvUC+DYJYp0kHgK9xQQNZ7/5b++oCuLnJXL36ZuoLIwwK1HxMSEJaH1YD0wN3QIQyFU8hB6zcD21wUAhzfX+MeQutwA07PzdMLqix1ho88qtdCJ4LuPerE6by+2ms+ovPY44lSmrJhrw0UgF7MNM8FFgquw9SDmAMXAcEmGORJ8q9azbhR3Q4rxtN+xo6roEwdezOZcT4bo0UFN+Doun8XtFydVE1cdgH6U3BWtAcukTEjB4lsXdnlSWLDtjYSdtZOQpzcdmFj5ukFEHtVadBrSOwQXo+YvK3uE4qnMESfafAaYrj8gTLLKovZChKqrV0V6sUfm7SQiyk0pK32+wYuaB4BvahZK0ZayWbkq7q4hPG4Qeep7FeMPN0asZ+Ahbj5d+TNvzPXFk8zA0A5RpgO+svIdc/+d2tQMFTVsF1t4eLyjx+6dP+Nwfsc+H8q59wcyyECoYuM9y5mKSVWWTaq3I2oRhc5B6swezh9Qkdj/M+EXRMYRj2kLgeGHwnf6hxt3ZBuwEEVZUzaM7yYKes/uOM0uwpLK6NUTKhvVAyY93RLKe9BKOQjZIq2dAeuhwnpknwtmkNOPz4qMI6SCqbMHKsWvGDmWXWzMAjk8He0jZpRO/vw1kHE5Spjd2qY1fdoqetaUB+/jLxVghHt6FepNvO7a+Gzvd3hNtRf7t0yjDS3grlRfS+MskcpNeUdyEEDiIm4yjFPdS/W+2Sgdni54t6wMCxR/y8hRbuTkMJ0avdsNgjp7e68L9lMH2WUmLf7ts56PLYjvBOTp19iCwW7KMo9jx4mkqTvJqTiOskSEkoT85UvGWqc/VQHNqnlwUqrI9+rakJ2heP7DPglS4j1xcdu+hHTRddNouuPFfZsFCgJ2QGe7LOG5lirWJmZLsLnmKCSiMP3A9uVTZJtnHKY7+Nri+VgFgRux8lxl2L+E4CEMe3VkWCCvwefbhL8GJlwFpNTQX/Td9pdBbnJLZD6PKDXpX9hQbrBC89PPtaposNvIvM4Xhz/spoqtxBCEgBUhgazDnDtnLvsSNoJ+aePxtePTSsggcczeoEQCg214guHdoqw4+VN3HtmxvhlHMbZ2xjAfzFOMxHembBL5D2p/0oJY/fiyO1hKh163S9Sdx5n8YzD/7Natc0B8nIzA0Zab87j8pUEdU1k9k6sQDCbGEasn4VcxQQbLqIQU1Hh10JHTs6VI8ZL6HGByAytQWPrYr5+SK7jR8GqdnI32HaZBx1j0RK/U9POZ23PRmSC1uwj4ScfNpVWQx4tmrK3Jgvebomv0xqgQXp6USxbYTR/w1xcKZnmt1G4h6Cy+d7Sf6FolAMFb52JG2/EGsg/lMrMM4u5993Z2D3FMyN+No5xbbumXJ14V33DgcklkTJlWuAXGVcKr9Hz91YC/YQDG9iW/3ruyaoOtVCa6mhpyiCFOB6RcC6ltF+bzmR76nyqrQuK2EubraZWwIjQ9OcPbsab7IPCg0+Fr31NYac/5EnT9N5qAJK9d+MYso+Y/UjJ45eaX6Yjv/hn9CACXo0= X-OriginatorOrg: iopsys.eu X-MS-Exchange-CrossTenant-Network-Message-Id: bd83efbd-b20a-422a-31d7-08dc969b218b X-MS-Exchange-CrossTenant-AuthSource: GV2PR08MB8121.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Jun 2024 11:20:20.8419 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 8d891be1-7bce-4216-9a99-bee9de02ba58 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 5oxM8dnxnp0h5dwBq2UoOtn+ikwjefsrFpfDp/Bg0jkYwGPpfo2BiUSCMGq107DRQKw0ET6ngDktIQJ0pwjqnFW5mEGNFze+furYU91KHXA= X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR08MB8970 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 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" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Signed-off-by: Mikhail Kshevetskiy --- drivers/mtd/nand/spi/winbond.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c index 5fe35e35ed5..f38ae95c570 100644 --- a/drivers/mtd/nand/spi/winbond.c +++ b/drivers/mtd/nand/spi/winbond.c @@ -172,6 +172,15 @@ static const struct spinand_info winbond_spinand_table[] = { &update_cache_variants), 0, SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)), + SPINAND_INFO("W25N04KV", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x23), + NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + 0, + SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)), }; static int winbond_spinand_init(struct spinand_device *spinand)