From nobody Fri Dec 19 12:14:50 2025 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (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 B69782DECC6; Tue, 28 Oct 2025 07:36:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761636997; cv=none; b=rMPcKTi+BDIfWhB+HHgTyr0A/RqZdbGQo5fY+VwUdtX0VF1L1Wy6HmANFkjhB5oaq7rFlj09xBz1iNn4+cO09bhEnN7bJiIC15iz0BuQCzcxotaaI5BThv0RD4+An/8IE/Q6gOHDvDACebb68z0iY/9eW1lkbbHCmiDp2vonVv8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761636997; c=relaxed/simple; bh=DKFSiwwqGSScbmOK8RHM78h6IWp/AKslZu93MpSlRK8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MNwH6+/SdT6OupWXIyeLsSf2rD/UAKgpILca4dUWSFTYE1zi1eAtB6jOnEXgg0iDdyQit9piXycUSulE3Xa1vDQ3o+AhgrLYSkLfm8OQy+1NbOAm6TmMX38d4h08APlF+BKAkjNOooD3gj+PlBgZfzjZZd3QAho7a9Atqrdefck= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=JG2OUV5U; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="JG2OUV5U" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 60F4F4E41390; Tue, 28 Oct 2025 07:36:33 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 36D59606AB; Tue, 28 Oct 2025 07:36:33 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 9F3F6102F2514; Tue, 28 Oct 2025 08:36:30 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1761636992; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=zq6G5Dl+dSf7UxVAvamTTAQ0U/RkXVyO4ivbKDJ0qjs=; b=JG2OUV5UFRiAmZt0R35HEf3yTg9jFCvMfr2OWxSSqULJBAfGJXPqFlmNnVYA8erpcdyegd tyOE9SjDRKvJWVDnER3cH3bIv717Eo4a/+dydjWXO4p5K5gXkjQbg2DFy5LE8bGYBEnnOe e8W+eOv57d/aldssZ2kN6uuFVtH6XFIMRf4RenXOgpbk1/2inGCZ9d7Pq8LRCWkG8ctKGC JvgiNRtp8qLM12xGdJsZw55STQN9rnGcS+dvFJCHwE3V/HYYdAZVgwLs6Idief5MlKwRHH k4u8p9/o6PNX7M5N02X6MDsWcO9/V5je5Y9VS85JJ31A3ffQjQd5Mff5Z14MBA== From: Richard Genoud To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland Cc: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= , Wentao Liang , Johan Hovold , Maxime Ripard , Thomas Petazzoni , linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, Richard Genoud Subject: [PATCH v4 15/16] mtd: rawnand: sunxi: Add support for H616 nand controller Date: Tue, 28 Oct 2025 08:35:08 +0100 Message-ID: <20251028073534.526992-16-richard.genoud@bootlin.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20251028073534.526992-1-richard.genoud@bootlin.com> References: <20251028073534.526992-1-richard.genoud@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" The H616 nand controller has the same base as A10/A23, with some differences: - mdma is based on chained buffers - its ECC supports up to 80bit per 1024bytes - some registers layouts are a bit different, mainly due do the stronger ECC. - it uses USER_DATA_LEN registers along USER_DATA registers. - it needs a specific clock for ECC and MBUS. Introduce the basic support, with ECC and scrambling, but without DMA/MDMA. Tested on Whatsminer H616 board (with and without scrambling, ECC) Signed-off-by: Richard Genoud --- drivers/mtd/nand/raw/sunxi_nand.c | 185 ++++++++++++++++++++++++++++-- 1 file changed, 177 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 5e030fc2fde5..031ab651c5a8 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -49,17 +49,40 @@ #define NFC_REG_A23_IO_DATA 0x0300 #define NFC_REG_ECC_CTL 0x0034 #define NFC_REG_ECC_ST 0x0038 -#define NFC_REG_DEBUG 0x003C +#define NFC_REG_H6_PAT_FOUND 0x003C #define NFC_REG_A10_ECC_ERR_CNT 0x0040 +#define NFC_REG_H6_ECC_ERR_CNT 0x0050 #define NFC_REG_ECC_ERR_CNT(nfc, x) ((nfc->caps->reg_ecc_err_cnt + (x)) & = ~0x3) +#define NFC_REG_H6_RDATA_CTL 0x0044 +#define NFC_REG_H6_RDATA_0 0x0048 +#define NFC_REG_H6_RDATA_1 0x004C #define NFC_REG_A10_USER_DATA 0x0050 +#define NFC_REG_H6_USER_DATA 0x0080 #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 */ +#define NFC_REG_USER_DATA_LEN_CAPACITY 8 +#define NFC_REG_USER_DATA_LEN(nfc, step) \ + (nfc->caps->reg_user_data_len + \ + ((step) / NFC_REG_USER_DATA_LEN_CAPACITY) * 4) #define NFC_REG_SPARE_AREA(nfc) (nfc->caps->reg_spare_area) #define NFC_REG_A10_SPARE_AREA 0x00A0 #define NFC_REG_PAT_ID(nfc) (nfc->caps->reg_pat_id) #define NFC_REG_A10_PAT_ID 0x00A4 #define NFC_REG_MDMA_ADDR 0x00C0 #define NFC_REG_MDMA_CNT 0x00C4 +#define NFC_REG_H6_EFNAND_STATUS 0x0110 +#define NFC_REG_H6_SPARE_AREA 0x0114 +#define NFC_REG_H6_PAT_ID 0x0118 +#define NFC_REG_H6_DDR2_SPEC_CTL 0x011C +#define NFC_REG_H6_NDMA_MODE_CTL 0x0120 +#define NFC_REG_H6_MDMA_DLBA_REG 0x0200 +#define NFC_REG_H6_MDMA_STA 0x0204 +#define NFC_REG_H6_MDMA_INT_MAS 0x0208 +#define NFC_REG_H6_MDMA_DESC_ADDR 0x020C +#define NFC_REG_H6_MDMA_BUF_ADDR 0x0210 +#define NFC_REG_H6_MDMA_CNT 0x0214 + #define NFC_RAM0_BASE 0x0400 #define NFC_RAM1_BASE 0x0800 =20 @@ -71,6 +94,7 @@ #define NFC_BUS_WIDTH_16 (1 << 2) #define NFC_RB_SEL_MSK BIT(3) #define NFC_RB_SEL(x) ((x) << 3) +/* CE_SEL BIT 27 is meant to be used for GPIO chipselect */ #define NFC_CE_SEL_MSK GENMASK(26, 24) #define NFC_CE_SEL(x) ((x) << 24) #define NFC_CE_CTL BIT(6) @@ -89,6 +113,9 @@ #define NFC_STA BIT(4) #define NFC_NATCH_INT_FLAG BIT(5) #define NFC_RB_STATE(x) BIT(x + 8) +#define NFC_RB_STATE_MSK GENMASK(11, 8) +#define NDFC_RDATA_STA_1 BIT(12) +#define NDFC_RDATA_STA_0 BIT(13) =20 /* define bit use in NFC_INT */ #define NFC_B2R_INT_ENABLE BIT(0) @@ -100,6 +127,7 @@ =20 /* define bit use in NFC_TIMING_CTL */ #define NFC_TIMING_CTL_EDO BIT(8) +#define NFC_TIMING_CTL_E_EDO BIT(9) =20 /* define NFC_TIMING_CFG register layout */ #define NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD) \ @@ -107,9 +135,15 @@ (((tWHR) & 0x3) << 4) | (((tRHW) & 0x3) << 6) | \ (((tCAD) & 0x7) << 8)) =20 +#define NFC_TIMING_CFG2(tCDQSS, tSC, tCLHZ, tCSS, tWC) \ + ((((tCDQSS) & 0x1) << 11) | (((tSC) & 0x3) << 12) | \ + (((tCLHZ) & 0x3) << 14) | (((tCSS) & 0x3) << 16) | \ + (((tWC) & 0x3) << 18)) + /* define bit use in NFC_CMD */ #define NFC_CMD_LOW_BYTE_MSK GENMASK(7, 0) -#define NFC_CMD_HIGH_BYTE_MSK GENMASK(15, 8) +#define NFC_CMD_HIGH_BYTE_MSK GENMASK(15, 8) /* 15-10 reserved on H6 */ +#define NFC_CMD_ADR_NUM_MSK GENMASK(9, 8) #define NFC_CMD(x) (x) #define NFC_ADR_NUM_MSK GENMASK(18, 16) #define NFC_ADR_NUM(x) (((x) - 1) << 16) @@ -122,6 +156,7 @@ #define NFC_SEQ BIT(25) #define NFC_DATA_SWAP_METHOD BIT(26) #define NFC_ROW_AUTO_INC BIT(27) +#define NFC_H6_SEND_RND_CMD2 BIT(27) #define NFC_SEND_CMD3 BIT(28) #define NFC_SEND_CMD4 BIT(29) #define NFC_CMD_TYPE_MSK GENMASK(31, 30) @@ -133,6 +168,7 @@ #define NFC_READ_CMD_MSK GENMASK(7, 0) #define NFC_RND_READ_CMD0_MSK GENMASK(15, 8) #define NFC_RND_READ_CMD1_MSK GENMASK(23, 16) +#define NFC_RND_READ_CMD2_MSK GENMASK(31, 24) =20 /* define bit use in NFC_WCMD_SET */ #define NFC_PROGRAM_CMD_MSK GENMASK(7, 0) @@ -150,6 +186,9 @@ #define NFC_RANDOM_DIRECTION(nfc) (nfc->caps->random_dir_mask) #define NFC_ECC_MODE_MSK(nfc) (nfc->caps->ecc_mode_mask) #define NFC_ECC_MODE(nfc, x) field_prep(NFC_ECC_MODE_MSK(nfc), (x)) +/* RANDOM_PAGE_SIZE: 0: ECC block size 1: page size */ +#define NFC_A23_RANDOM_PAGE_SIZE BIT(11) +#define NFC_H6_RANDOM_PAGE_SIZE BIT(7) #define NFC_RANDOM_SEED_MSK GENMASK(30, 16) #define NFC_RANDOM_SEED(x) ((x) << 16) =20 @@ -165,6 +204,9 @@ =20 #define NFC_ECC_ERR_CNT(b, x) (((x) >> (((b) % 4) * 8)) & 0xff) =20 +#define NFC_USER_DATA_LEN_MSK(step) \ + (0xf << (((step) % NFC_REG_USER_DATA_LEN_CAPACITY) * 4)) + #define NFC_DEFAULT_TIMEOUT_MS 1000 =20 #define NFC_MAX_CS 7 @@ -235,9 +277,12 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(st= ruct nand_chip *nand) * @has_mdma: Use mbus dma mode, otherwise general dma * through MBUS on A23/A33 needs extra configuration. * @has_ecc_block_512: If the ECC can handle 512B or only 1024B chuncks + * @has_ecc_clk: If the controller needs an ECC clock. + * @has_mbus_clk: If the controller needs a mbus clock. * @reg_io_data: I/O data register * @reg_ecc_err_cnt: ECC error counter register * @reg_user_data: User data register + * @reg_user_data_len: User data length register * @reg_spare_area: Spare Area Register * @reg_pat_id: Pattern ID Register * @reg_pat_found: Data Pattern Status Register @@ -249,14 +294,24 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(s= truct nand_chip *nand) * @dma_maxburst: DMA maxburst * @ecc_strengths: Available ECC strengths array * @nstrengths: Size of @ecc_strengths + * @max_ecc_steps: Maximum supported steps for ECC, this is also the + * number of user data registers + * @user_data_len_tab: Table of lenghts supported by USER_DATA_LEN regist= er + * The table index is the value to set in NFC_USER_DATA_LEN + * registers, and the corresponding value is the number of + * bytes to write + * @nuser_data_tab: Size of @user_data_len_tab * @sram_size: Size of the NAND controller SRAM */ struct sunxi_nfc_caps { bool has_mdma; bool has_ecc_block_512; + bool has_ecc_clk; + bool has_mbus_clk; unsigned int reg_io_data; unsigned int reg_ecc_err_cnt; unsigned int reg_user_data; + unsigned int reg_user_data_len; unsigned int reg_spare_area; unsigned int reg_pat_id; unsigned int reg_pat_found; @@ -268,6 +323,9 @@ struct sunxi_nfc_caps { unsigned int dma_maxburst; const u8 *ecc_strengths; unsigned int nstrengths; + const u8 *user_data_len_tab; + unsigned int nuser_data_tab; + unsigned int max_ecc_steps; int sram_size; }; =20 @@ -279,6 +337,8 @@ struct sunxi_nfc_caps { * @regs: NAND controller registers * @ahb_clk: NAND controller AHB clock * @mod_clk: NAND controller mod clock + * @ecc_clk: NAND controller ECC clock + * @mbus_clk: NAND controller MBUS clock * @reset: NAND controller reset line * @assigned_cs: bitmask describing already assigned CS lines * @clk_rate: NAND controller current clock rate @@ -294,6 +354,8 @@ struct sunxi_nfc { void __iomem *regs; struct clk *ahb_clk; struct clk *mod_clk; + struct clk *ecc_clk; + struct clk *mbus_clk; struct reset_control *reset; unsigned long assigned_cs; unsigned long clk_rate; @@ -774,6 +836,53 @@ static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct= nand_chip *nand, u8 *oob, sunxi_nfc_randomize_bbm(nand, page, oob); } =20 +/* + * On H6/H6 the user_data length has to be set in specific registers + * before writing. + */ +static void sunxi_nfc_reset_user_data_len(struct sunxi_nfc *nfc) +{ + int loop_step =3D NFC_REG_USER_DATA_LEN_CAPACITY; + + /* not all SoCs have this register */ + if (!nfc->caps->reg_user_data_len) + return; + + for (int i =3D 0; i < nfc->caps->max_ecc_steps; i +=3D loop_step) + 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) +{ + bool found =3D false; + u32 val; + int i; + + /* not all SoCs have this register */ + if (!nfc->caps->reg_user_data_len) + return; + + for (i =3D 0; i < nfc->caps->nuser_data_tab; i++) { + if (len =3D=3D nfc->caps->user_data_len_tab[i]) { + found =3D true; + break; + } + } + + if (!found) { + dev_warn(nfc->dev, + "Unsupported length for user data reg: %d\n", len); + return; + } + + val =3D readl(nfc->regs + NFC_REG_USER_DATA_LEN(nfc, step)); + + val &=3D ~NFC_USER_DATA_LEN_MSK(step); + val |=3D field_prep(NFC_USER_DATA_LEN_MSK(step), i); + writel(val, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, step)); +} + static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand, const u8 *oob, int step, bool bbm, int page) @@ -868,6 +977,8 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip= *nand, if (ret) return ret; =20 + sunxi_nfc_reset_user_data_len(nfc); + sunxi_nfc_set_user_data_len(nfc, USER_DATA_SZ, 0); sunxi_nfc_randomizer_config(nand, page, false); sunxi_nfc_randomizer_enable(nand); writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP, @@ -978,6 +1089,8 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nan= d_chip *nand, uint8_t *buf return ret; =20 sunxi_nfc_hw_ecc_enable(nand); + sunxi_nfc_reset_user_data_len(nfc); + sunxi_nfc_set_user_data_len(nfc, USER_DATA_SZ, 0); sunxi_nfc_randomizer_config(nand, page, false); sunxi_nfc_randomizer_enable(nand); =20 @@ -1110,6 +1223,8 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_c= hip *nand, =20 sunxi_nfc_randomizer_config(nand, page, false); sunxi_nfc_randomizer_enable(nand); + sunxi_nfc_reset_user_data_len(nfc); + sunxi_nfc_set_user_data_len(nfc, USER_DATA_SZ, 0); sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, 0, bbm, page); =20 writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | @@ -1354,10 +1469,12 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct n= and_chip *nand, if (ret) goto pio_fallback; =20 + sunxi_nfc_reset_user_data_len(nfc); for (i =3D 0; i < ecc->steps; i++) { const u8 *oob =3D nand->oob_poi + (i * (ecc->bytes + USER_DATA_SZ)); =20 sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, i, !i, page); + sunxi_nfc_set_user_data_len(nfc, USER_DATA_SZ, i); } =20 nand_prog_page_begin_op(nand, page, 0, NULL, 0); @@ -2158,6 +2275,10 @@ static int sunxi_nfc_probe(struct platform_device *p= dev) if (irq < 0) return irq; =20 + nfc->caps =3D of_device_get_match_data(dev); + if (!nfc->caps) + return -EINVAL; + nfc->ahb_clk =3D devm_clk_get_enabled(dev, "ahb"); if (IS_ERR(nfc->ahb_clk)) { dev_err(dev, "failed to retrieve ahb clk\n"); @@ -2170,6 +2291,22 @@ static int sunxi_nfc_probe(struct platform_device *p= dev) return PTR_ERR(nfc->mod_clk); } =20 + if (nfc->caps->has_ecc_clk) { + nfc->ecc_clk =3D devm_clk_get_enabled(dev, "ecc"); + if (IS_ERR(nfc->ecc_clk)) { + dev_err(dev, "failed to retrieve ecc clk\n"); + return PTR_ERR(nfc->ecc_clk); + } + } + + if (nfc->caps->has_mbus_clk) { + nfc->mbus_clk =3D devm_clk_get_enabled(dev, "mbus"); + if (IS_ERR(nfc->mbus_clk)) { + dev_err(dev, "failed to retrieve mbus clk\n"); + return PTR_ERR(nfc->mbus_clk); + } + } + nfc->reset =3D devm_reset_control_get_optional_exclusive(dev, "ahb"); if (IS_ERR(nfc->reset)) return PTR_ERR(nfc->reset); @@ -2180,12 +2317,6 @@ static int sunxi_nfc_probe(struct platform_device *p= dev) return ret; } =20 - nfc->caps =3D of_device_get_match_data(&pdev->dev); - if (!nfc->caps) { - ret =3D -EINVAL; - goto out_ahb_reset_reassert; - } - ret =3D sunxi_nfc_rst(nfc); if (ret) goto out_ahb_reset_reassert; @@ -2236,6 +2367,14 @@ static const u8 sunxi_ecc_strengths_a10[] =3D { 16, 24, 28, 32, 40, 48, 56, 60, 64 }; =20 +static const u8 sunxi_ecc_strengths_h6[] =3D { + 16, 24, 28, 32, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80 +}; + +static const u8 sunxi_user_data_len_h6[] =3D { + 0, 4, 8, 12, 16, 20, 24, 28, 32 +}; + static const struct sunxi_nfc_caps sunxi_nfc_a10_caps =3D { .has_ecc_block_512 =3D true, .reg_io_data =3D NFC_REG_A10_IO_DATA, @@ -2252,6 +2391,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_a10_caps= =3D { .dma_maxburst =3D 4, .ecc_strengths =3D sunxi_ecc_strengths_a10, .nstrengths =3D ARRAY_SIZE(sunxi_ecc_strengths_a10), + .max_ecc_steps =3D 16, .sram_size =3D 1024, }; =20 @@ -2272,9 +2412,34 @@ static const struct sunxi_nfc_caps sunxi_nfc_a23_cap= s =3D { .dma_maxburst =3D 8, .ecc_strengths =3D sunxi_ecc_strengths_a10, .nstrengths =3D ARRAY_SIZE(sunxi_ecc_strengths_a10), + .max_ecc_steps =3D 16, .sram_size =3D 1024, }; =20 +static const struct sunxi_nfc_caps sunxi_nfc_h616_caps =3D { + .has_ecc_clk =3D true, + .has_mbus_clk =3D true, + .reg_io_data =3D NFC_REG_A23_IO_DATA, + .reg_ecc_err_cnt =3D NFC_REG_H6_ECC_ERR_CNT, + .reg_user_data =3D NFC_REG_H6_USER_DATA, + .reg_user_data_len =3D NFC_REG_H6_USER_DATA_LEN, + .reg_spare_area =3D NFC_REG_H6_SPARE_AREA, + .reg_pat_id =3D NFC_REG_H6_PAT_ID, + .reg_pat_found =3D NFC_REG_H6_PAT_FOUND, + .random_en_mask =3D BIT(5), + .random_dir_mask =3D BIT(6), + .ecc_mode_mask =3D GENMASK(15, 8), + .ecc_err_mask =3D GENMASK(31, 0), + .pat_found_mask =3D GENMASK(31, 0), + .dma_maxburst =3D 8, + .ecc_strengths =3D sunxi_ecc_strengths_h6, + .nstrengths =3D ARRAY_SIZE(sunxi_ecc_strengths_h6), + .user_data_len_tab =3D sunxi_user_data_len_h6, + .nuser_data_tab =3D ARRAY_SIZE(sunxi_user_data_len_h6), + .max_ecc_steps =3D 32, + .sram_size =3D 8192, +}; + static const struct of_device_id sunxi_nfc_ids[] =3D { { .compatible =3D "allwinner,sun4i-a10-nand", @@ -2284,6 +2449,10 @@ static const struct of_device_id sunxi_nfc_ids[] =3D= { .compatible =3D "allwinner,sun8i-a23-nand-controller", .data =3D &sunxi_nfc_a23_caps, }, + { + .compatible =3D "allwinner,sun50i-h616-nand-controller", + .data =3D &sunxi_nfc_h616_caps, + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, sunxi_nfc_ids); --=20 2.47.3