From nobody Tue Sep 29 05:34:25 2026 Received: from gw2.atmark-techno.com (gw2.atmark-techno.com [35.74.137.57]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0D3193939A2 for ; Wed, 12 Aug 2026 04:14:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=35.74.137.57 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786508053; cv=none; b=WKpNV/MLDCUCCPs0spE7Ubon51KYKcO1V0XOSDDLqRTUVqxuBzIzBlnsFF1EVMSE71AqPQ542J4T7hAwT2vv/Uo4JKkaxbr74kbzDofkaa2En+hkyrQW3ztv034mmQZds75PJoTKiw6Iah0lsG66v5pvqy2QcfKmEwrsCclu0uw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786508053; c=relaxed/simple; bh=0ac+9ChYOT63TLmJE7muZgICUT8deNIQ8Yn5SX6y4Xw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To:Cc; b=KBKkwkzuGmLK37zp/VlyavkD+BwT56gKenrPAz/FJXHi3VLWqYec6WHS6qxW5FsISYud2A4yPKvenH7wBBFqLZM3I84PSz0qOVEIQLyDcH94o/0qDIAOGwAkoWDORdpCYtFK4q/cQqISWBNIFR5SDQmdbCZPt8buY1qAQfUChOw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=atmark-techno.com; spf=pass smtp.mailfrom=atmark-techno.com; dkim=pass (2048-bit key) header.d=atmark-techno.com header.i=@atmark-techno.com header.b=EuTv3tEg; dkim=pass (2048-bit key) header.d=atmark-techno.com header.i=@atmark-techno.com header.b=Jp4YByly; arc=none smtp.client-ip=35.74.137.57 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=atmark-techno.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=atmark-techno.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=atmark-techno.com header.i=@atmark-techno.com header.b="EuTv3tEg"; dkim=pass (2048-bit key) header.d=atmark-techno.com header.i=@atmark-techno.com header.b="Jp4YByly" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=atmark-techno.com; s=gw2_bookworm; t=1786508050; bh=0ac+9ChYOT63TLmJE7muZgICUT8deNIQ8Yn5SX6y4Xw=; h=From:Date:Subject:To:Cc:From; b=EuTv3tEggJJcj6gI6JQItK68beIgS+LEgrIxf0WiSuGKIvSZM5xC8pLl2Jni2lvps zmyjR4JooMIZm4hVYBSSGh8jPtzcSb+p2CL8wSLklEnR82Fn3XSkPUhfG+r/tCtjkA XkkgHYZ/9jSXUBGw2UeACAuFrDJcdA2fAxzu1eJzu5bVjkadOE11BHR1/l2gV7ykvV se9KgVnyRaSns1RQtZ50QIThHaYiFRVXJXwFW7RP1TZxbUz+T55BjcpSmD8V1gemXr kBACRgN3RQji3AecpgvntC2t0r/ud/ufxoN/SGb9MgVW4/EFXvZ2mlThhKDrB/aXLc 1XwYrScOXOIig== Received: from gw2.atmark-techno.com (localhost [127.0.0.1]) by gw2.atmark-techno.com (Postfix) with ESMTP id 97A0A670 for ; Wed, 12 Aug 2026 13:14:10 +0900 (JST) Authentication-Results: gw2.atmark-techno.com; dkim=pass (2048-bit key; unprotected) header.d=atmark-techno.com header.i=@atmark-techno.com header.a=rsa-sha256 header.s=google header.b=Jp4YByly; dkim-atps=neutral Received: from mail-pl1-f197.google.com (mail-pl1-f197.google.com [209.85.214.197]) by gw2.atmark-techno.com (Postfix) with ESMTPS id 4C8211F2 for ; Wed, 12 Aug 2026 13:14:10 +0900 (JST) Received: by mail-pl1-f197.google.com with SMTP id d9443c01a7336-2d02df2bf09so4539745ad.0 for ; Tue, 11 Aug 2026 21:14:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=atmark-techno.com; s=google; t=1786508049; x=1787112849; darn=vger.kernel.org; h=cc:to:message-id:content-transfer-encoding:content-type :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=bVLNluNzT3CgQnEwDzhoLkRU7QTo/hyjSTd200GccGo=; b=Jp4YBylyGND1MpVW7SkXXyuHsceAfOwsykgJ1OfObarHBYkRoI6XNspsr466/AQHdM FN5z30bUNMvqU7RlTReieH3Y9VF0CUYvi5EJML/8c6PV1msP4Pq248XseXu7dTTaYcEp vPn/F7QPRCv47l1jhE4YzYT9OPt58ElRUcaZ8/esPOVIlPdb9p1ZT/znVa+lw8uWJVF4 Vj/WKRcV1NNLxVtOHTgU2XRQtOYgDENWqm/igkIsO/pAl8d6tLQuiyvVCywrjvN9ZTMd 7P9F6U0GvNf+zt1cr3XNGJqEPnnqmvFUjIxO7yJUVx3as0iujVKdt3VlaCOnMnSRMqcx SaIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786508049; x=1787112849; h=cc:to:message-id:content-transfer-encoding:content-type :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=bVLNluNzT3CgQnEwDzhoLkRU7QTo/hyjSTd200GccGo=; b=Z1E/EAvaTR4K2UIlnZaiVBlJ+reA/PCw4mwY3/8gkVffe23XHMl5GcJ1SW2/wBKqTV sDAbj6sQyZXQjveZLv2Q4gscIOUmRA1CJvzs8cG+9oS5jFAZY4OvMuSa61OCeTHSpfy4 V5XqfEByosFHnqkroptfj4eqmMRIJxVbMr2KPetYGCqDrRoxAOgMg0cVWnnJIKxlY/li Jie1oNaRDYVW6Y1Mz6kjjqQxBXq8BpN59Z6w7JOK3AckmHLGkqohC2vNArNvwKf483Vr Zbdp2qKAyiy2CH0v1RVri6oQWWXpL7pg4Upp19Dt0NtMKgeLXtkzZOdI4macPjf2HPrS ccfg== X-Forwarded-Encrypted: i=1; AHgh+Rq1LelZt4zHQrusoDOZJF8c/ldrS0Nc9HszvHrDYl3ogrRkKxi2y5Yg4qY0yYediYptAMTPmc/dljvgif8=@vger.kernel.org X-Gm-Message-State: AOJu0Yyj/Gw3gU+/+0Uxg/Ddq+5NntoSH/2pMyAekjwkUR61laqKhnYE 6necjZ72qb8rd+URLZVlcQUFhwD6B8KZ8ZskO7NPYljm0hDY8WUrIPhUhLE3noM3u7OXv9ZxzZU GoO8wIAr4VctSgwdTIFvzKBtZXJmI7EWUQ6r0PcrZununMWVH+fRjxdFMjrCdZoWZLZM= X-Gm-Gg: AR+sD10xNGNt4rwbX2c7N6Brucj7HQcNsovk9/TD14rnHpUfOg2gIqUl95OV9FOmW4Y Cj9pDrwJquiowElWcO7bz5+Ye54ImejaBIcwJA8jbhvjeLvce17gH4zYALGXHiqbe+VR0bbEUTS v4enKCEdkCx+M4BnWb9guxvjcye4yFHKLbd/BEGnXf0SNHv+KuBmw6j3fwVvRbQJHWooRF6NiM8 9nI4UuC6GNFsukHMBnePkEQofYRpJlyjFRCytCg8kGBo0ftJoXy/rtwcAyKJ7O4ouArO40cWMza 0uOhaZt9ne1YMXU8562oiwhRlX/5yt+zw/PYWS+i85JtC/ltzdohVYbBaSropK1UGemyq5B44l3 fOWxLDXKr8xgIfngH9FxTwowJrZ+8H+jUyEOHROJBT+UscpXr X-Received: by 2002:a17:902:fda3:b0:2ca:53e9:1277 with SMTP id d9443c01a7336-2d345359e86mr30818815ad.1.1786508048718; Tue, 11 Aug 2026 21:14:08 -0700 (PDT) X-Received: by 2002:a17:902:fda3:b0:2ca:53e9:1277 with SMTP id d9443c01a7336-2d345359e86mr30818235ad.1.1786508048208; Tue, 11 Aug 2026 21:14:08 -0700 (PDT) Received: from localhost (sodcd-04p2-40.ppp11.odn.ad.jp. [203.139.65.40]) by smtp.gmail.com with UTF8SMTPSA id d9443c01a7336-2d350fb0cd0sm990655ad.4.2026.08.11.21.14.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 11 Aug 2026 21:14:07 -0700 (PDT) From: Dominique Martinet Date: Wed, 12 Aug 2026 04:14:02 +0000 Subject: [PATCH RFC v2] mtd: spinand: winbond: add support for W25N04LW Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260812-w25n04lw-v2-1-deee97602fc4@atmark-techno.com> X-B4-Tracking: v=1; b=H4sIAAnze2oC/yWNSwuCQBhF/4p82xoZRxNrFRQtCoKCFhEuRh1zY h414yMR/3ujbS6cy+HeASwznFnYeAMY1nLLtXJAlh7kFVVPhnjhGAgmMU4CgjqyUjgSHQrZOoj iIgkjXILT34aV/DtPPeB62EH6L22TvVheTyOTVnFba9PPh20wy1TZ+02fT8d+f1nEJdlWDZIFF VSiTBj/01CRayl9F5CO4/gDvSGlXbUAAAA= X-Change-ID: 20260812-w25n04lw-3e9146d8340f To: Miquel Raynal , Richard Weinberger , Md Sadre Alam , Vignesh Raghavendra Cc: linux-mtd@lists.infradead.org, linux-kernel@vger.kernel.org, Daisuke Mizobuchi , Dominique Martinet X-Mailer: b4 0.16-dev-a9e92 X-Developer-Signature: v=1; a=openpgp-sha256; l=6435; i=dominique.martinet@atmark-techno.com; h=from:subject:message-id; bh=0ac+9ChYOT63TLmJE7muZgICUT8deNIQ8Yn5SX6y4Xw=; b=owEBbQKS/ZANAwAKAfKKYH/WjHEHAcsmYgBqe/MO3uG/4R7lc8o4s5xMilJwZEZPO3d/x24Xf bUZJRwoSYeJAjMEAAEKAB0WIQQoFSiLMD+txr0veJbyimB/1oxxBwUCanvzDgAKCRDyimB/1oxx B+7BD/9lRSSTHY2nEK+x8f5sf1BWpDbFadodXwVg2/h4dQG/qrmo+aaSc5UGuwfgxihFU50fA9n qXjUx2OmFv6BBybxHMe55mcVPtAnYmUV17Z3Izq3mQYDDTHnpbObgoiWpbTX9ZjxqaUwfENvAWt DqD0U9/FJkN96q7SQNUfBEJv6mwrp1RG0xPHvHtMvX7Pmjz+XaRfJ4NvsU3rmwViv9JW6rhy0WV 7oBSZmUofgZksIPnq/Z8TxsuS1pfMEcTWchhGqZOjknY5khn230WnvmvWcemHIdZEpsVOAquWCe tghliUcRzUJ5DjxhotcP7H4FMW8vbuI1sxWMCbpouO8TG3Q1N4DLDKsxKzZWLKMxd64iTIVf35+ iXg5GtT8pmIrhJtl3wJcHnlmLOEQQgx9Qd7RwjNETsa4OodpWFib03mBt4W/2MnecqxUnHiEAJL dFOYKrkoyslM+qGqk2Eeo77vs/ujrQ4GGxQr/BiGUOSbTn9sOVk+0luTj1xi22ozNo9IxNLjik6 MzIyUJDPjJUdXDJ3IFMQZhyhukM3QYc8J1A1raBI4hb99T4PqPyhbUOfbQXOf1qe2cH/d+rSvr/ G1ho8tknGnL0rjJOUBgp/hAF8k04MJv1IrQ85FY6Oc1/5r2XRGWsz7p2fPatB3U1KNswtfq2dXl WdoueJamHmGGP6A== X-Developer-Key: i=dominique.martinet@atmark-techno.com; a=openpgp; fpr=2815288B303FADC6BD2F7896F28A607FD68C7107 Add support for Winbond W25N04LW 4Gbit SPI-NAND: > 1.8V 4G-bit > Raw serial SLC NAND flash memory > Dual/Quad SPI with 104MHz > buffer read, continuous read & sequential read Highlights copied from datasheet: =E2=80=93 Page size: 4,352 Bytes (4096 + 256 Bytes) =E2=80=93 Block size: 64 pages (256K + 16K Bytes) - Built-in 8-Bit ECC for memory array =E2=80=93 ECC status bits indicate ECC results =E2=80=93 Bad Block Management and LUT access =E2=80=93 Software and Hardware Write-Protect =E2=80=93 Power Supply Lock-Down and OTP protection =E2=80=93 Unique ID and Parameter page =E2=80=93 Ten 4KB OTP pages per die =E2=80=93 Read Level Setting for Read Retry The 4096+256 byte page layout is as follow: - 4096 bytes ECC protected "main memory array", subdivided in 8 512 bytes sectors - 128 bytes spare array, subdivided in 8 16 bytes sectors as follow: - 2 bytes bad block marker (no ECC protection) - 2 bytes "user data II" (no ECC protection) - 12 bytes "user data I" (ECC protected) - 128 bytes parity array, subdivided in 8 16 bytes sectors: - 13 bytes ECC for main data and user data - 3 unused bytes This commit does not support most advanced features such as continuous read, LUT management and OTP pages, and only provides basic usage. OOB layout was defined to only show ECC-protected "user data I", leaving "user data II" unavailable. Signed-off-by: Daisuke Mizobuchi Signed-off-by: Dominique Martinet --- Changes in v2: - Link to v1: https://patch.msgid.link/ansYUoNKJyDQ+6f2@hu-mdalam-blr.qualc= omm.com - fixed oob layout - fixed NAND_MEMORG oob size I've tested the NAND with various mtd test utils (mtd_oobtest, mtd_pagetest, mtd_subpagetest, mtd_nandbiterrs and some mtd-utils userspace counterparts) with no problem, but I'm not sure what to do with the ooblayout free() informations: as written in the commit message, this chip has 2+12 bytes of user data per sector where the first two are not ECC protected and the later 12 are. I believe user should make the choice of which oob bytes they want to use, but afaik we can't say "this is not protected", so we can't let them choose and must either say both are free or only provide one like I did here. As an extra data point, this "user area I and II" distinction is the same in W25N04KW (same 2+12), but w25n02kv_ooblayout_free() use there returns the whole 14 bytes as a single chunk, so I explicitly made a different choice here. (I believe that's not something that can be changed easily, so we should discuss this before merging) That aside: - Alam, would you like your name somewhere in the commit? I didn't keep anything from your commit because I already had one, but happy to add a Co-developed-by or something - I kept NAND_ECCREQ(8, 512) like W25N04KW but the datasheet says it's based on 8-bits/544-bytes ECC, so I should set it as (8, 544)? (since it's protecting 512+12 bytes for up to 8 bits corruption) In practice ECC is done by hardware and looks like it is correctly reported (e.g. manually overwriting a couple of bits with nandwrite and checking with nanddump properly corrects and reports number of corrected bits), but might as well get this right, even if as far as I understand nothing actually uses the ECC oob data to double-check hardware status? - I'll shamefully admit I do not understand the read / write / update_cache_variants() I copied from KW, Alam had the same but it'd be great to confirm using the same callbacks makes sense? - (I wrote about OTP in the commit message but have no plan of implementing it at this point as we have no use for it, I still intend to look at continuous read after some other work) Thanks! -Dominique --- drivers/mtd/nand/spi/winbond.c | 42 ++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 42 insertions(+) diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c index 9b78c1e6cbc9..5b86e5cb06a3 100644 --- a/drivers/mtd/nand/spi/winbond.c +++ b/drivers/mtd/nand/spi/winbond.c @@ -335,6 +335,34 @@ static int w25n02kv_ooblayout_free(struct mtd_info *mt= d, int section, return 0; } =20 +static int w25n04lw_ooblayout_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) +{ + if (section > 7) + return -ERANGE; + + region->offset =3D 128 + (16 * section); + region->length =3D 13; + + return 0; +} + +static int w25n04lw_ooblayout_free(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) +{ + if (section > 7) + return -ERANGE; + + // the W25N04LW chip actually has two free ranges per section: + // "User Data I" at (16 * section) + 4, length 12 + // "User Data II" at (16 * section) + 2, length 2 + // The later is not ECC protected so this only returns User Data I + region->offset =3D (16 * section) + 4; + region->length =3D 12; + + return 0; +} + static const struct mtd_ooblayout_ops w25n01kv_ooblayout =3D { .ecc =3D w25n01kv_ooblayout_ecc, .free =3D w25n02kv_ooblayout_free, @@ -345,6 +373,11 @@ static const struct mtd_ooblayout_ops w25n02kv_ooblayo= ut =3D { .free =3D w25n02kv_ooblayout_free, }; =20 +static const struct mtd_ooblayout_ops w25n04lw_ooblayout =3D { + .ecc =3D w25n04lw_ooblayout_ecc, + .free =3D w25n04lw_ooblayout_free, +}; + static int w25n01jw_ooblayout_ecc(struct mtd_info *mtd, int section, struct mtd_oob_region *region) { @@ -768,6 +801,15 @@ static const struct spinand_info winbond_spinand_table= [] =3D { &update_cache_variants), 0, SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)), + SPINAND_INFO("W25N04LW", /* 1.8V */ + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xb2, 0x23), + NAND_MEMORG(1, 4096, 256, 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(&w25n04lw_ooblayout, w25n02kv_ecc_get_status)), SPINAND_INFO("W35N04JW", /* 1.8V */ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xdf, 0x23), NAND_MEMORG(1, 4096, 128, 64, 512, 10, 1, 4, 1), --- base-commit: db2ddb87143519e20a95aa36c60b36107b736a58 change-id: 20260812-w25n04lw-3e9146d8340f Best regards, -- =20 Dominique Martinet