From patchwork Fri Oct 16 03:45:30 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3643 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sin.lore.kernel.org (sin.lore.kernel.org [104.64.211.4]) by mxe881.netcup.net (Postfix) with ESMTPS id E614E1C2044 for ; Fri, 16 Oct 2026 05:49:21 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 104.64.211.4) smtp.mailfrom=linux-sunxi+bounces-26690-noreply=patchwork.local@lists.linux.dev smtp.helo=sin.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 104.64.211.4 as permitted sender) client-ip=104.64.211.4; envelope-from=linux-sunxi+bounces-26690-noreply=patchwork.local@lists.linux.dev; helo=sin.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sin.lore.kernel.org (Postfix) with ESMTP id 344F12752E for ; Fri, 16 Oct 2026 03:46:58 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 9FFC73C1F46; Fri, 16 Oct 2026 03:45:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="kpu2qcJ7" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f51.google.com (mail-ot1-f51.google.com [209.85.210.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3C4E93BED71 for ; Fri, 16 Oct 2026 03:45:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122357; cv=none; b=epb9hNPs4sFcb+qJ5vIqVdKePtBQSi9QtzERclId3dgohtbW1/RlvgAQETlnuT+IhDy5NFZjeGsMmq47aKoDC103cXlvHwbw26dsyrAgxxBRgTivn6fbP+s7NtTKbcVPB8+8TgaFmo9/f1bPA8wJsJjsb0vrTgWP3BCo6pXgCVU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122357; c=relaxed/simple; bh=3PLYNRG+R1vcn+zst5EafJtg8zZpSNmVtMEe2/zmAwI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=E8j4Hrn97+ihIiQWCUYzDQVwM1s7gZTXWxgkp9WY7j2Gbc3Xf6gUmHiAHf30FIEZswn2Naf1ZEA0dM9KFZGV+oKj5C1SIzpSVMxl3/CPS2lB/q3FtYkW8MIe5r5QewJH6DXUTX++WcWPjfVs8UmxOBY2EnYDYC578ksidguLAKk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=kpu2qcJ7; arc=none smtp.client-ip=209.85.210.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-ot1-f51.google.com with SMTP id 46e09a7af769-83bbcfba0ffso2130316a34.0 for ; Thu, 15 Oct 2026 20:45:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792122354; x=1792727154; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=zAN0y/NlYSkso/Y1xGAc/UgZ/A9idw6Kq1nSbL1jYtY=; b=kpu2qcJ7zs3G//7gHhLd9Z84/CCgQ7Nrl0gWxMttbqmPAl60iqHjMv7OWca7sR+mLr aG7YbmFUeQaKwpN+YhiniXYetFnpZ1hV/ZoKRgCgczIRJM+rtpVaayUDDH95bclCvKND gBvakgDe4vVfoC9XkCVsbKxIwVPCh0zBAEhqkV17AfL9M2g3frtB79tkczZabzPpFfoj 32vR4Fkme+MCqruDOvjCFfGERUI2uj727QXmdhvCRNkeBLwUJNGZH0udGcDbn/ItuOuF e2yfrjVeSFgXIX1PZhgXDa5CK4bUlrzUrsatrWohQelhYdPzjF1pGkt+JYwTEt5KGAU1 gAjw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792122354; x=1792727154; h=cc:to:in-reply-to:references: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=zAN0y/NlYSkso/Y1xGAc/UgZ/A9idw6Kq1nSbL1jYtY=; b=q1LO7tHrGJvDU9JJ66K/Dri0kd27FEGSr2owXvvrYz0Xo0WqfiDNCqW1mLZ4nYAx2h 0+7o/PrDFY8gFXtVZP/x0+X/jlY8GplxrxC+NZMLFY7aH86SxjsuVAzEvkdmn/BRiKOl r1GChCeI5fA5zGO0Rj3NKrGhtrcB7ptz+Upad7DkEYtMkQs0qgDQmq2C3lkNPa5eCOVR cUm2/XfZtTJxMBfejxGN2iO4maKBJ4T1x3HHt4qtL63muEtCtR0uxW0eB7yyCRJjAOB2 xLpuUw2/ZeJbgFkurYDuZKFvTuoIC1Fwh/tGaZzX6SbMzUEUfqJQhYKzs9pvF0uK8lOe bguQ== X-Forwarded-Encrypted: i=1; AKwUvByj34w0ETzCeGiDj0qIXwT8C1JCyWUgD3oHcVzgdey0gUMP/yGdDafwk2SfOdDCXl/ipHV040rNNMc69w==@lists.linux.dev X-Gm-Message-State: AFq9FYJr+nwH7MGF6eo3kU67336XpSJ6Bsm+nMXIQX+aRhGlkACQ42bF QnO0RYCSEPSSAq4J1frfB9pWGwwQtsqW/vMbym/Pe5wKXlWfuPh/3qN/ X-Gm-Gg: AYBFou3jI5cEEaEqilGyJ3KkLYdwqxD8EULv7Rcb0BRZkTBF+e65WL7seUDBqGCnI9H KViE3njg6TIr+9AVsiNPiODFdrHYy/qhtvMV3XuY0wAUCyyCnolVf1fxdR5LLW4IUrHxJiJ6TTA 21FjrZvVnmo5KR0F8B8jxa1pyCJwUUrKgl3fk4U8j8tjCg2azStbYbBXt9dqHnEXS4FuOe1+xnq 8dOEuSi6+tUi25KP8bCVBf3Uz9gKZA8iV+F0X9L87L8r1OZo+XbIg2ywp7JSxXBjmk2yxlxUUnZ na57cRgTNqujJnWbJ1sjRnT+/Wlz7YSCvGx5tEXnPwbEOmB8CvjITqAdK/baKVUd96TXysCkYcW IWt1XDPNcoDYoSC8IfWoU7hmNDQVEzoaPC+KMeI13STGxG5YzkOCC/5EUlhI0NRi91ezIYJW0D/ YsqK2VriP7u9sJaU5WWzdg4aF8C3sLLJF+pm+LoYgsz9O+2RMVm1DSnZGcyu9kgYuVuyDTyvFaN 97fRv3M733HyBNpZtJuXtB/QrQfF/iG8CZTzGIXym0R9ety71a0E67YLqBCtevixGahGWlSqG9i wlCxZP1DAVrRYSANV7ib1SattRdUA3WLbVXRjpJ42NWYm6iMy0xFE1iQo7tVsiPW3FPno5yGAwm DiQpp4xsTov3ijFqTXKF2S+dNnBUtzHgR X-Received: by 2002:a05:6830:4c0a:b0:80a:b8da:2792 with SMTP id 46e09a7af769-83094e783camr22214084a34.6.1792122354047; Thu, 15 Oct 2026 20:45:54 -0700 (PDT) Received: from [127.0.1.1] (174-29-1-49.hlrn.qwest.net. [174.29.1.49]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-8429b57870fsm834402a34.0.2026.10.15.20.45.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Oct 2026 20:45:53 -0700 (PDT) From: James Hilliard Date: Thu, 15 Oct 2026 21:45:30 -0600 Subject: [PATCH v8 15/17] mtd: rawnand: sunxi: reduce user-data length register accesses Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20261015-submit-sunxi-nand-vendor-oob-layout-v1-v8-15-8ba4881fbee8@gmail.com> References: <20261015-submit-sunxi-nand-vendor-oob-layout-v1-v8-0-8ba4881fbee8@gmail.com> In-Reply-To: <20261015-submit-sunxi-nand-vendor-oob-layout-v1-v8-0-8ba4881fbee8@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Boris Brezillon , Masahiro Yamada , Brian Norris , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev, devicetree@vger.kernel.org, James Hilliard X-Mailer: b4 0.15.2 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= H6/H616 pack eight ECC steps' user-data length codes into each 32-bit register. DMA currently clears all these registers, then read-modify-writes one field per step, repeatedly accessing the same words. Code zero means no user data; the other codes select lengths from the controller's table. Build each packed value in memory and write it once per DMA batch, including zeros for unused slots. Take each length from the batch's logical step but encode it in the corresponding batch-local hardware slot. Rewrite every register on each batch rather than caching values across resets or changes of chip. Share the encoding with a PIO setter. PIO always uses hardware slot zero, and its page callbacks clear all length registers before the chunk loop. It can therefore write the slot-zero code directly, without a read-modify-write. Keep the page-level clearing so unused slots are also cleared after a DMA-to-PIO fallback. Older controllers without length registers remain unaffected, and the chosen lengths and on-flash layout do not change. Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 79 +++++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 29 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 2a9fe89b1ba5..56594bb41193 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -57,7 +57,7 @@ #define NFC_H6_USER_DATA_REGS 32 #define NFC_REG_USER_DATA(nfc, x) (nfc->caps->reg_user_data + ((x) * 4)) #define NFC_REG_H6_USER_DATA_LEN 0x0070 -/* A USER_DATA_LEN register can hold the length of 8 USER_DATA registers */ +/* Each USER_DATA_LEN register holds eight 4-bit ECC-step user-data length codes. */ #define NFC_REG_USER_DATA_LEN_CAPACITY 8 #define NFC_REG_USER_DATA_LEN(nfc, step) \ (nfc->caps->reg_user_data_len + \ @@ -1025,35 +1025,60 @@ static void sunxi_nfc_reset_user_data_len(struct sunxi_nfc *nfc) writel(0, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, i)); } -static void sunxi_nfc_set_user_data_len(struct sunxi_nfc *nfc, - int len, int step) +static int sunxi_nfc_user_data_len_code(struct sunxi_nfc *nfc, int len) { - bool found = false; - u32 val; int i; + for (i = 0; i < nfc->caps->nuser_data_tab; i++) { + if (len == nfc->caps->user_data_len_tab[i]) + return i; + } + + dev_warn(nfc->dev, "Unsupported length for user data reg: %d\n", len); + return -EINVAL; +} + +static void sunxi_nfc_set_user_data_len_pio(struct sunxi_nfc *nfc, int len) +{ + int code; + /* not all SoCs have this register */ if (!nfc->caps->reg_user_data_len) return; - for (i = 0; i < nfc->caps->nuser_data_tab; i++) { - if (len == nfc->caps->user_data_len_tab[i]) { - found = true; - break; - } - } - - if (!found) { - dev_warn(nfc->dev, - "Unsupported length for user data reg: %d\n", len); + code = sunxi_nfc_user_data_len_code(nfc, len); + if (code < 0) return; - } - val = readl(nfc->regs + NFC_REG_USER_DATA_LEN(nfc, step)); + /* PIO uses slot zero; the page callback clears all other slots. */ + writel(FIELD_PREP(NFC_USER_DATA_LEN_MSK(0), code), + nfc->regs + NFC_REG_USER_DATA_LEN(nfc, 0)); +} + +static void sunxi_nfc_set_user_data_len_dma(struct nand_chip *nand, + int first_step, int nchunks) +{ + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + int first, step, len, code; + u32 val; + + if (!nfc->caps->reg_user_data_len) + return; - val &= ~NFC_USER_DATA_LEN_MSK(step); - val |= field_prep(NFC_USER_DATA_LEN_MSK(step), i); - writel(val, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, step)); + /* Write each packed register once, including zeroes for unused slots. */ + for (first = 0; first < nfc->caps->max_ecc_steps; + first += NFC_REG_USER_DATA_LEN_CAPACITY) { + val = 0; + for (step = first; step < nchunks && + step < first + NFC_REG_USER_DATA_LEN_CAPACITY; step++) { + len = sunxi_nfc_user_data_sz(sunxi_nand, first_step + step); + code = sunxi_nfc_user_data_len_code(nfc, len); + if (code >= 0) + val |= field_prep(NFC_USER_DATA_LEN_MSK(step), code); + } + writel(val, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, first)); + } } static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand, @@ -1425,7 +1450,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand, if (ret) return ret; - sunxi_nfc_set_user_data_len(nfc, user_data_sz, 0); + sunxi_nfc_set_user_data_len_pio(nfc, user_data_sz); sunxi_nfc_randomizer_config(nand, page, false); sunxi_nfc_randomizer_enable(nand); writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP, @@ -1454,7 +1479,7 @@ static int sunxi_nfc_hw_ecc_read_batch_dma(struct nand_chip *nand, struct sunxi_nfc_ecc_snapshot snapshot; struct scatterlist sg; int page = read->page; - int ret, i; + int ret; u32 wait; if (first_step) { @@ -1475,10 +1500,7 @@ static int sunxi_nfc_hw_ecc_read_batch_dma(struct nand_chip *nand, return ret; sunxi_nfc_hw_ecc_enable(nand); - sunxi_nfc_reset_user_data_len(nfc); - for (i = 0; i < nchunks; i++) - sunxi_nfc_set_user_data_len(nfc, - sunxi_nfc_user_data_sz(sunxi_nand, first_step + i), i); + sunxi_nfc_set_user_data_len_dma(nand, first_step, nchunks); /* exec_op() restores the page's spare base during column changes. */ if (first_step) writel(mtd->writesize + sunxi_get_oob_offset(sunxi_nand, ecc, first_step), @@ -1588,7 +1610,7 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand, sunxi_nfc_randomizer_config(nand, page, false); sunxi_nfc_randomizer_enable(nand); - sunxi_nfc_set_user_data_len(nfc, user_data_sz, nfc_step); + sunxi_nfc_set_user_data_len_pio(nfc, user_data_sz); sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, nfc_step, bbm, page, user_data_sz); @@ -1855,7 +1877,7 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *nand, goto pio_fallback; } - sunxi_nfc_reset_user_data_len(nfc); + sunxi_nfc_set_user_data_len_dma(nand, first_step, batch_steps); for (i = first_step; i < first_step + batch_steps; i++) { unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, i); int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, i); @@ -1863,7 +1885,6 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *nand, sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, reg_index, !i, page, user_data_sz); - sunxi_nfc_set_user_data_len(nfc, user_data_sz, i - first_step); reg_index += user_data_sz / 4; }