blob: 86d666c0c03c45dd2b6c941fae7faea09ed816c9 [file] [log] [blame]
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001/*
2 * Copyright (C) 2013 Boris BREZILLON <b.brezillon.dev@gmail.com>
3 *
4 * Derived from:
5 * https://github.com/yuq/sunxi-nfc-mtd
6 * Copyright (C) 2013 Qiang Yu <yuq825@gmail.com>
7 *
8 * https://github.com/hno/Allwinner-Info
9 * Copyright (C) 2013 Henrik Nordström <Henrik Nordström>
10 *
11 * Copyright (C) 2013 Dmitriy B. <rzk333@gmail.com>
12 * Copyright (C) 2013 Sergey Lapin <slapin@ossfans.org>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 */
24
25#include <linux/dma-mapping.h>
26#include <linux/slab.h>
27#include <linux/module.h>
28#include <linux/moduleparam.h>
29#include <linux/platform_device.h>
30#include <linux/of.h>
31#include <linux/of_device.h>
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020032#include <linux/mtd/mtd.h>
Boris Brezillond4092d72017-08-04 17:29:10 +020033#include <linux/mtd/rawnand.h>
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020034#include <linux/mtd/partitions.h>
35#include <linux/clk.h>
36#include <linux/delay.h>
37#include <linux/dmaengine.h>
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020038#include <linux/interrupt.h>
Boris Brezillon166f08c2016-03-07 15:25:17 +010039#include <linux/iopoll.h>
Icenowy Zhengab9d6a72016-06-20 12:48:38 +080040#include <linux/reset.h>
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020041
42#define NFC_REG_CTL 0x0000
43#define NFC_REG_ST 0x0004
44#define NFC_REG_INT 0x0008
45#define NFC_REG_TIMING_CTL 0x000C
46#define NFC_REG_TIMING_CFG 0x0010
47#define NFC_REG_ADDR_LOW 0x0014
48#define NFC_REG_ADDR_HIGH 0x0018
49#define NFC_REG_SECTOR_NUM 0x001C
50#define NFC_REG_CNT 0x0020
51#define NFC_REG_CMD 0x0024
52#define NFC_REG_RCMD_SET 0x0028
53#define NFC_REG_WCMD_SET 0x002C
54#define NFC_REG_IO_DATA 0x0030
55#define NFC_REG_ECC_CTL 0x0034
56#define NFC_REG_ECC_ST 0x0038
57#define NFC_REG_DEBUG 0x003C
Boris BREZILLONb6a02c02015-09-16 09:46:36 +020058#define NFC_REG_ECC_ERR_CNT(x) ((0x0040 + (x)) & ~0x3)
59#define NFC_REG_USER_DATA(x) (0x0050 + ((x) * 4))
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020060#define NFC_REG_SPARE_AREA 0x00A0
Boris BREZILLON4be4e032015-12-02 12:01:07 +010061#define NFC_REG_PAT_ID 0x00A4
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020062#define NFC_RAM0_BASE 0x0400
63#define NFC_RAM1_BASE 0x0800
64
65/* define bit use in NFC_CTL */
66#define NFC_EN BIT(0)
67#define NFC_RESET BIT(1)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +020068#define NFC_BUS_WIDTH_MSK BIT(2)
69#define NFC_BUS_WIDTH_8 (0 << 2)
70#define NFC_BUS_WIDTH_16 (1 << 2)
71#define NFC_RB_SEL_MSK BIT(3)
72#define NFC_RB_SEL(x) ((x) << 3)
73#define NFC_CE_SEL_MSK GENMASK(26, 24)
74#define NFC_CE_SEL(x) ((x) << 24)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020075#define NFC_CE_CTL BIT(6)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +020076#define NFC_PAGE_SHIFT_MSK GENMASK(11, 8)
77#define NFC_PAGE_SHIFT(x) (((x) < 10 ? 0 : (x) - 10) << 8)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020078#define NFC_SAM BIT(12)
79#define NFC_RAM_METHOD BIT(14)
80#define NFC_DEBUG_CTL BIT(31)
81
82/* define bit use in NFC_ST */
83#define NFC_RB_B2R BIT(0)
84#define NFC_CMD_INT_FLAG BIT(1)
85#define NFC_DMA_INT_FLAG BIT(2)
86#define NFC_CMD_FIFO_STATUS BIT(3)
87#define NFC_STA BIT(4)
88#define NFC_NATCH_INT_FLAG BIT(5)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +020089#define NFC_RB_STATE(x) BIT(x + 8)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020090
91/* define bit use in NFC_INT */
92#define NFC_B2R_INT_ENABLE BIT(0)
93#define NFC_CMD_INT_ENABLE BIT(1)
94#define NFC_DMA_INT_ENABLE BIT(2)
95#define NFC_INT_MASK (NFC_B2R_INT_ENABLE | \
96 NFC_CMD_INT_ENABLE | \
97 NFC_DMA_INT_ENABLE)
98
Roy Splietd052e502015-06-26 11:00:11 +020099/* define bit use in NFC_TIMING_CTL */
100#define NFC_TIMING_CTL_EDO BIT(8)
101
Roy Spliet9c618292015-06-26 11:00:10 +0200102/* define NFC_TIMING_CFG register layout */
103#define NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD) \
104 (((tWB) & 0x3) | (((tADL) & 0x3) << 2) | \
105 (((tWHR) & 0x3) << 4) | (((tRHW) & 0x3) << 6) | \
106 (((tCAD) & 0x7) << 8))
107
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200108/* define bit use in NFC_CMD */
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200109#define NFC_CMD_LOW_BYTE_MSK GENMASK(7, 0)
110#define NFC_CMD_HIGH_BYTE_MSK GENMASK(15, 8)
111#define NFC_CMD(x) (x)
112#define NFC_ADR_NUM_MSK GENMASK(18, 16)
113#define NFC_ADR_NUM(x) (((x) - 1) << 16)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200114#define NFC_SEND_ADR BIT(19)
115#define NFC_ACCESS_DIR BIT(20)
116#define NFC_DATA_TRANS BIT(21)
117#define NFC_SEND_CMD1 BIT(22)
118#define NFC_WAIT_FLAG BIT(23)
119#define NFC_SEND_CMD2 BIT(24)
120#define NFC_SEQ BIT(25)
121#define NFC_DATA_SWAP_METHOD BIT(26)
122#define NFC_ROW_AUTO_INC BIT(27)
123#define NFC_SEND_CMD3 BIT(28)
124#define NFC_SEND_CMD4 BIT(29)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200125#define NFC_CMD_TYPE_MSK GENMASK(31, 30)
126#define NFC_NORMAL_OP (0 << 30)
127#define NFC_ECC_OP (1 << 30)
Boris Brezilloncf3e3fd2018-07-09 22:09:31 +0200128#define NFC_PAGE_OP (2U << 30)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200129
130/* define bit use in NFC_RCMD_SET */
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200131#define NFC_READ_CMD_MSK GENMASK(7, 0)
132#define NFC_RND_READ_CMD0_MSK GENMASK(15, 8)
133#define NFC_RND_READ_CMD1_MSK GENMASK(23, 16)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200134
135/* define bit use in NFC_WCMD_SET */
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200136#define NFC_PROGRAM_CMD_MSK GENMASK(7, 0)
137#define NFC_RND_WRITE_CMD_MSK GENMASK(15, 8)
138#define NFC_READ_CMD0_MSK GENMASK(23, 16)
139#define NFC_READ_CMD1_MSK GENMASK(31, 24)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200140
141/* define bit use in NFC_ECC_CTL */
142#define NFC_ECC_EN BIT(0)
143#define NFC_ECC_PIPELINE BIT(3)
144#define NFC_ECC_EXCEPTION BIT(4)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200145#define NFC_ECC_BLOCK_SIZE_MSK BIT(5)
Boris Brezillonf59dab82016-10-20 10:12:42 +0200146#define NFC_ECC_BLOCK_512 BIT(5)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200147#define NFC_RANDOM_EN BIT(9)
148#define NFC_RANDOM_DIRECTION BIT(10)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200149#define NFC_ECC_MODE_MSK GENMASK(15, 12)
150#define NFC_ECC_MODE(x) ((x) << 12)
151#define NFC_RANDOM_SEED_MSK GENMASK(30, 16)
152#define NFC_RANDOM_SEED(x) ((x) << 16)
153
154/* define bit use in NFC_ECC_ST */
155#define NFC_ECC_ERR(x) BIT(x)
Boris Brezillon614049a2016-04-15 15:10:30 +0200156#define NFC_ECC_ERR_MSK GENMASK(15, 0)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200157#define NFC_ECC_PAT_FOUND(x) BIT(x + 16)
Boris Brezillonf8b04742016-03-04 17:25:08 +0100158#define NFC_ECC_ERR_CNT(b, x) (((x) >> (((b) % 4) * 8)) & 0xff)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200159
160#define NFC_DEFAULT_TIMEOUT_MS 1000
161
162#define NFC_SRAM_SIZE 1024
163
164#define NFC_MAX_CS 7
165
166/*
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200167 * Chip Select structure: stores information related to NAND Chip Select
168 *
169 * @cs: the NAND CS id used to communicate with a NAND Chip
Boris Brezillonddd5ed32018-03-27 09:06:14 +0200170 * @rb: the Ready/Busy pin ID. -1 means no R/B pin connected to the
171 * NFC
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200172 */
173struct sunxi_nand_chip_sel {
174 u8 cs;
Boris Brezillonddd5ed32018-03-27 09:06:14 +0200175 s8 rb;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200176};
177
178/*
179 * sunxi HW ECC infos: stores information related to HW ECC support
180 *
181 * @mode: the sunxi ECC mode field deduced from ECC requirements
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200182 */
183struct sunxi_nand_hw_ecc {
184 int mode;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200185};
186
187/*
188 * NAND chip structure: stores NAND chip device related information
189 *
190 * @node: used to store NAND chips into a list
191 * @nand: base NAND chip structure
192 * @mtd: base MTD structure
193 * @clk_rate: clk_rate required for this NAND chip
Roy Spliet9c618292015-06-26 11:00:10 +0200194 * @timing_cfg TIMING_CFG register value for this NAND chip
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200195 * @selected: current active CS
196 * @nsels: number of CS lines required by the NAND chip
197 * @sels: array of CS lines descriptions
198 */
199struct sunxi_nand_chip {
200 struct list_head node;
201 struct nand_chip nand;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200202 unsigned long clk_rate;
Roy Spliet9c618292015-06-26 11:00:10 +0200203 u32 timing_cfg;
Roy Splietd052e502015-06-26 11:00:11 +0200204 u32 timing_ctl;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200205 int selected;
Boris Brezillone9aa6712015-09-16 09:05:31 +0200206 int addr_cycles;
207 u32 addr[2];
208 int cmd_cycles;
209 u8 cmd[2];
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200210 int nsels;
211 struct sunxi_nand_chip_sel sels[0];
212};
213
214static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
215{
216 return container_of(nand, struct sunxi_nand_chip, nand);
217}
218
219/*
220 * NAND Controller structure: stores sunxi NAND controller information
221 *
222 * @controller: base controller structure
223 * @dev: parent device (used to print error messages)
224 * @regs: NAND controller registers
225 * @ahb_clk: NAND Controller AHB clock
226 * @mod_clk: NAND Controller mod clock
227 * @assigned_cs: bitmask describing already assigned CS lines
228 * @clk_rate: NAND controller current clock rate
229 * @chips: a list containing all the NAND chips attached to
230 * this NAND controller
231 * @complete: a completion object used to wait for NAND
232 * controller events
233 */
234struct sunxi_nfc {
Miquel Raynal7da45132018-07-17 09:08:02 +0200235 struct nand_controller controller;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200236 struct device *dev;
237 void __iomem *regs;
238 struct clk *ahb_clk;
239 struct clk *mod_clk;
Icenowy Zhengab9d6a72016-06-20 12:48:38 +0800240 struct reset_control *reset;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200241 unsigned long assigned_cs;
242 unsigned long clk_rate;
243 struct list_head chips;
244 struct completion complete;
Boris Brezillon614049a2016-04-15 15:10:30 +0200245 struct dma_chan *dmac;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200246};
247
Miquel Raynal7da45132018-07-17 09:08:02 +0200248static inline struct sunxi_nfc *to_sunxi_nfc(struct nand_controller *ctrl)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200249{
250 return container_of(ctrl, struct sunxi_nfc, controller);
251}
252
253static irqreturn_t sunxi_nfc_interrupt(int irq, void *dev_id)
254{
255 struct sunxi_nfc *nfc = dev_id;
256 u32 st = readl(nfc->regs + NFC_REG_ST);
257 u32 ien = readl(nfc->regs + NFC_REG_INT);
258
259 if (!(ien & st))
260 return IRQ_NONE;
261
262 if ((ien & st) == ien)
263 complete(&nfc->complete);
264
265 writel(st & NFC_INT_MASK, nfc->regs + NFC_REG_ST);
266 writel(~st & ien & NFC_INT_MASK, nfc->regs + NFC_REG_INT);
267
268 return IRQ_HANDLED;
269}
270
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100271static int sunxi_nfc_wait_events(struct sunxi_nfc *nfc, u32 events,
272 bool use_polling, unsigned int timeout_ms)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200273{
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100274 int ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200275
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100276 if (events & ~NFC_INT_MASK)
277 return -EINVAL;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200278
279 if (!timeout_ms)
280 timeout_ms = NFC_DEFAULT_TIMEOUT_MS;
281
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100282 if (!use_polling) {
283 init_completion(&nfc->complete);
284
285 writel(events, nfc->regs + NFC_REG_INT);
286
287 ret = wait_for_completion_timeout(&nfc->complete,
288 msecs_to_jiffies(timeout_ms));
Boris Brezillon19649e22017-01-06 10:42:05 +0100289 if (!ret)
290 ret = -ETIMEDOUT;
291 else
292 ret = 0;
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100293
294 writel(0, nfc->regs + NFC_REG_INT);
295 } else {
296 u32 status;
297
298 ret = readl_poll_timeout(nfc->regs + NFC_REG_ST, status,
299 (status & events) == events, 1,
300 timeout_ms * 1000);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200301 }
302
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100303 writel(events & NFC_INT_MASK, nfc->regs + NFC_REG_ST);
304
305 if (ret)
306 dev_err(nfc->dev, "wait interrupt timedout\n");
307
308 return ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200309}
310
311static int sunxi_nfc_wait_cmd_fifo_empty(struct sunxi_nfc *nfc)
312{
Boris Brezillon166f08c2016-03-07 15:25:17 +0100313 u32 status;
314 int ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200315
Boris Brezillon166f08c2016-03-07 15:25:17 +0100316 ret = readl_poll_timeout(nfc->regs + NFC_REG_ST, status,
317 !(status & NFC_CMD_FIFO_STATUS), 1,
318 NFC_DEFAULT_TIMEOUT_MS * 1000);
319 if (ret)
320 dev_err(nfc->dev, "wait for empty cmd FIFO timedout\n");
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200321
Boris Brezillon166f08c2016-03-07 15:25:17 +0100322 return ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200323}
324
325static int sunxi_nfc_rst(struct sunxi_nfc *nfc)
326{
Boris Brezillon166f08c2016-03-07 15:25:17 +0100327 u32 ctl;
328 int ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200329
330 writel(0, nfc->regs + NFC_REG_ECC_CTL);
331 writel(NFC_RESET, nfc->regs + NFC_REG_CTL);
332
Boris Brezillon166f08c2016-03-07 15:25:17 +0100333 ret = readl_poll_timeout(nfc->regs + NFC_REG_CTL, ctl,
334 !(ctl & NFC_RESET), 1,
335 NFC_DEFAULT_TIMEOUT_MS * 1000);
336 if (ret)
337 dev_err(nfc->dev, "wait for NAND controller reset timedout\n");
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200338
Boris Brezillon166f08c2016-03-07 15:25:17 +0100339 return ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200340}
341
Boris Brezillon614049a2016-04-15 15:10:30 +0200342static int sunxi_nfc_dma_op_prepare(struct mtd_info *mtd, const void *buf,
343 int chunksize, int nchunks,
344 enum dma_data_direction ddir,
345 struct scatterlist *sg)
346{
347 struct nand_chip *nand = mtd_to_nand(mtd);
348 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
349 struct dma_async_tx_descriptor *dmad;
350 enum dma_transfer_direction tdir;
351 dma_cookie_t dmat;
352 int ret;
353
354 if (ddir == DMA_FROM_DEVICE)
355 tdir = DMA_DEV_TO_MEM;
356 else
357 tdir = DMA_MEM_TO_DEV;
358
359 sg_init_one(sg, buf, nchunks * chunksize);
360 ret = dma_map_sg(nfc->dev, sg, 1, ddir);
361 if (!ret)
362 return -ENOMEM;
363
364 dmad = dmaengine_prep_slave_sg(nfc->dmac, sg, 1, tdir, DMA_CTRL_ACK);
Wei Yongjun28f3d012016-06-13 14:27:18 +0000365 if (!dmad) {
366 ret = -EINVAL;
Boris Brezillon614049a2016-04-15 15:10:30 +0200367 goto err_unmap_buf;
368 }
369
370 writel(readl(nfc->regs + NFC_REG_CTL) | NFC_RAM_METHOD,
371 nfc->regs + NFC_REG_CTL);
372 writel(nchunks, nfc->regs + NFC_REG_SECTOR_NUM);
373 writel(chunksize, nfc->regs + NFC_REG_CNT);
374 dmat = dmaengine_submit(dmad);
375
376 ret = dma_submit_error(dmat);
377 if (ret)
378 goto err_clr_dma_flag;
379
380 return 0;
381
382err_clr_dma_flag:
383 writel(readl(nfc->regs + NFC_REG_CTL) & ~NFC_RAM_METHOD,
384 nfc->regs + NFC_REG_CTL);
385
386err_unmap_buf:
387 dma_unmap_sg(nfc->dev, sg, 1, ddir);
388 return ret;
389}
390
391static void sunxi_nfc_dma_op_cleanup(struct mtd_info *mtd,
392 enum dma_data_direction ddir,
393 struct scatterlist *sg)
394{
395 struct nand_chip *nand = mtd_to_nand(mtd);
396 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
397
398 dma_unmap_sg(nfc->dev, sg, 1, ddir);
399 writel(readl(nfc->regs + NFC_REG_CTL) & ~NFC_RAM_METHOD,
400 nfc->regs + NFC_REG_CTL);
401}
402
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200403static int sunxi_nfc_dev_ready(struct mtd_info *mtd)
404{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100405 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200406 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
407 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
Boris Brezillonddd5ed32018-03-27 09:06:14 +0200408 u32 mask;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200409
410 if (sunxi_nand->selected < 0)
411 return 0;
412
Boris Brezillonddd5ed32018-03-27 09:06:14 +0200413 if (sunxi_nand->sels[sunxi_nand->selected].rb < 0) {
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200414 dev_err(nfc->dev, "cannot check R/B NAND status!\n");
Boris Brezillonddd5ed32018-03-27 09:06:14 +0200415 return 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200416 }
417
Boris Brezillonddd5ed32018-03-27 09:06:14 +0200418 mask = NFC_RB_STATE(sunxi_nand->sels[sunxi_nand->selected].rb);
419
420 return !!(readl(nfc->regs + NFC_REG_ST) & mask);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200421}
422
423static void sunxi_nfc_select_chip(struct mtd_info *mtd, int chip)
424{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100425 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200426 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
427 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
428 struct sunxi_nand_chip_sel *sel;
429 u32 ctl;
430
431 if (chip > 0 && chip >= sunxi_nand->nsels)
432 return;
433
434 if (chip == sunxi_nand->selected)
435 return;
436
437 ctl = readl(nfc->regs + NFC_REG_CTL) &
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200438 ~(NFC_PAGE_SHIFT_MSK | NFC_CE_SEL_MSK | NFC_RB_SEL_MSK | NFC_EN);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200439
440 if (chip >= 0) {
441 sel = &sunxi_nand->sels[chip];
442
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200443 ctl |= NFC_CE_SEL(sel->cs) | NFC_EN |
Boris Brezillon68ffbf72016-03-04 17:29:20 +0100444 NFC_PAGE_SHIFT(nand->page_shift);
Boris Brezillonddd5ed32018-03-27 09:06:14 +0200445 if (sel->rb < 0) {
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200446 nand->dev_ready = NULL;
447 } else {
448 nand->dev_ready = sunxi_nfc_dev_ready;
Boris Brezillonddd5ed32018-03-27 09:06:14 +0200449 ctl |= NFC_RB_SEL(sel->rb);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200450 }
451
452 writel(mtd->writesize, nfc->regs + NFC_REG_SPARE_AREA);
453
454 if (nfc->clk_rate != sunxi_nand->clk_rate) {
455 clk_set_rate(nfc->mod_clk, sunxi_nand->clk_rate);
456 nfc->clk_rate = sunxi_nand->clk_rate;
457 }
458 }
459
Roy Splietd052e502015-06-26 11:00:11 +0200460 writel(sunxi_nand->timing_ctl, nfc->regs + NFC_REG_TIMING_CTL);
Roy Spliet9c618292015-06-26 11:00:10 +0200461 writel(sunxi_nand->timing_cfg, nfc->regs + NFC_REG_TIMING_CFG);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200462 writel(ctl, nfc->regs + NFC_REG_CTL);
463
464 sunxi_nand->selected = chip;
465}
466
467static void sunxi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
468{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100469 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200470 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
471 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
472 int ret;
473 int cnt;
474 int offs = 0;
475 u32 tmp;
476
477 while (len > offs) {
Boris Brezillon8de15e12017-01-06 10:42:06 +0100478 bool poll = false;
479
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200480 cnt = min(len - offs, NFC_SRAM_SIZE);
481
482 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
483 if (ret)
484 break;
485
486 writel(cnt, nfc->regs + NFC_REG_CNT);
487 tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD;
488 writel(tmp, nfc->regs + NFC_REG_CMD);
489
Boris Brezillon8de15e12017-01-06 10:42:06 +0100490 /* Arbitrary limit for polling mode */
491 if (cnt < 64)
492 poll = true;
493
494 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, poll, 0);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200495 if (ret)
496 break;
497
498 if (buf)
499 memcpy_fromio(buf + offs, nfc->regs + NFC_RAM0_BASE,
500 cnt);
501 offs += cnt;
502 }
503}
504
505static void sunxi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf,
506 int len)
507{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100508 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200509 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
510 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
511 int ret;
512 int cnt;
513 int offs = 0;
514 u32 tmp;
515
516 while (len > offs) {
Boris Brezillon8de15e12017-01-06 10:42:06 +0100517 bool poll = false;
518
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200519 cnt = min(len - offs, NFC_SRAM_SIZE);
520
521 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
522 if (ret)
523 break;
524
525 writel(cnt, nfc->regs + NFC_REG_CNT);
526 memcpy_toio(nfc->regs + NFC_RAM0_BASE, buf + offs, cnt);
527 tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD |
528 NFC_ACCESS_DIR;
529 writel(tmp, nfc->regs + NFC_REG_CMD);
530
Boris Brezillon8de15e12017-01-06 10:42:06 +0100531 /* Arbitrary limit for polling mode */
532 if (cnt < 64)
533 poll = true;
534
535 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, poll, 0);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200536 if (ret)
537 break;
538
539 offs += cnt;
540 }
541}
542
543static uint8_t sunxi_nfc_read_byte(struct mtd_info *mtd)
544{
Boris Brezillon06c8b5d2018-07-09 22:09:32 +0200545 uint8_t ret = 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200546
547 sunxi_nfc_read_buf(mtd, &ret, 1);
548
549 return ret;
550}
551
552static void sunxi_nfc_cmd_ctrl(struct mtd_info *mtd, int dat,
553 unsigned int ctrl)
554{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100555 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200556 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
557 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
558 int ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200559
Boris Brezillone9aa6712015-09-16 09:05:31 +0200560 if (dat == NAND_CMD_NONE && (ctrl & NAND_NCE) &&
561 !(ctrl & (NAND_CLE | NAND_ALE))) {
562 u32 cmd = 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200563
Boris Brezillone9aa6712015-09-16 09:05:31 +0200564 if (!sunxi_nand->addr_cycles && !sunxi_nand->cmd_cycles)
565 return;
566
567 if (sunxi_nand->cmd_cycles--)
568 cmd |= NFC_SEND_CMD1 | sunxi_nand->cmd[0];
569
570 if (sunxi_nand->cmd_cycles--) {
571 cmd |= NFC_SEND_CMD2;
572 writel(sunxi_nand->cmd[1],
573 nfc->regs + NFC_REG_RCMD_SET);
574 }
575
576 sunxi_nand->cmd_cycles = 0;
577
578 if (sunxi_nand->addr_cycles) {
579 cmd |= NFC_SEND_ADR |
580 NFC_ADR_NUM(sunxi_nand->addr_cycles);
581 writel(sunxi_nand->addr[0],
582 nfc->regs + NFC_REG_ADDR_LOW);
583 }
584
585 if (sunxi_nand->addr_cycles > 4)
586 writel(sunxi_nand->addr[1],
587 nfc->regs + NFC_REG_ADDR_HIGH);
588
Boris Brezilloncad32742017-01-06 10:42:07 +0100589 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
590 if (ret)
591 return;
592
Boris Brezillone9aa6712015-09-16 09:05:31 +0200593 writel(cmd, nfc->regs + NFC_REG_CMD);
594 sunxi_nand->addr[0] = 0;
595 sunxi_nand->addr[1] = 0;
596 sunxi_nand->addr_cycles = 0;
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100597 sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200598 }
599
Boris Brezillone9aa6712015-09-16 09:05:31 +0200600 if (ctrl & NAND_CLE) {
601 sunxi_nand->cmd[sunxi_nand->cmd_cycles++] = dat;
602 } else if (ctrl & NAND_ALE) {
603 sunxi_nand->addr[sunxi_nand->addr_cycles / 4] |=
604 dat << ((sunxi_nand->addr_cycles % 4) * 8);
605 sunxi_nand->addr_cycles++;
606 }
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200607}
608
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100609/* These seed values have been extracted from Allwinner's BSP */
610static const u16 sunxi_nfc_randomizer_page_seeds[] = {
611 0x2b75, 0x0bd0, 0x5ca3, 0x62d1, 0x1c93, 0x07e9, 0x2162, 0x3a72,
612 0x0d67, 0x67f9, 0x1be7, 0x077d, 0x032f, 0x0dac, 0x2716, 0x2436,
613 0x7922, 0x1510, 0x3860, 0x5287, 0x480f, 0x4252, 0x1789, 0x5a2d,
614 0x2a49, 0x5e10, 0x437f, 0x4b4e, 0x2f45, 0x216e, 0x5cb7, 0x7130,
615 0x2a3f, 0x60e4, 0x4dc9, 0x0ef0, 0x0f52, 0x1bb9, 0x6211, 0x7a56,
616 0x226d, 0x4ea7, 0x6f36, 0x3692, 0x38bf, 0x0c62, 0x05eb, 0x4c55,
617 0x60f4, 0x728c, 0x3b6f, 0x2037, 0x7f69, 0x0936, 0x651a, 0x4ceb,
618 0x6218, 0x79f3, 0x383f, 0x18d9, 0x4f05, 0x5c82, 0x2912, 0x6f17,
619 0x6856, 0x5938, 0x1007, 0x61ab, 0x3e7f, 0x57c2, 0x542f, 0x4f62,
620 0x7454, 0x2eac, 0x7739, 0x42d4, 0x2f90, 0x435a, 0x2e52, 0x2064,
621 0x637c, 0x66ad, 0x2c90, 0x0bad, 0x759c, 0x0029, 0x0986, 0x7126,
622 0x1ca7, 0x1605, 0x386a, 0x27f5, 0x1380, 0x6d75, 0x24c3, 0x0f8e,
623 0x2b7a, 0x1418, 0x1fd1, 0x7dc1, 0x2d8e, 0x43af, 0x2267, 0x7da3,
624 0x4e3d, 0x1338, 0x50db, 0x454d, 0x764d, 0x40a3, 0x42e6, 0x262b,
625 0x2d2e, 0x1aea, 0x2e17, 0x173d, 0x3a6e, 0x71bf, 0x25f9, 0x0a5d,
626 0x7c57, 0x0fbe, 0x46ce, 0x4939, 0x6b17, 0x37bb, 0x3e91, 0x76db,
627};
628
629/*
630 * sunxi_nfc_randomizer_ecc512_seeds and sunxi_nfc_randomizer_ecc1024_seeds
631 * have been generated using
632 * sunxi_nfc_randomizer_step(seed, (step_size * 8) + 15), which is what
633 * the randomizer engine does internally before de/scrambling OOB data.
634 *
635 * Those tables are statically defined to avoid calculating randomizer state
636 * at runtime.
637 */
638static const u16 sunxi_nfc_randomizer_ecc512_seeds[] = {
639 0x3346, 0x367f, 0x1f18, 0x769a, 0x4f64, 0x068c, 0x2ef1, 0x6b64,
640 0x28a9, 0x15d7, 0x30f8, 0x3659, 0x53db, 0x7c5f, 0x71d4, 0x4409,
641 0x26eb, 0x03cc, 0x655d, 0x47d4, 0x4daa, 0x0877, 0x712d, 0x3617,
642 0x3264, 0x49aa, 0x7f9e, 0x588e, 0x4fbc, 0x7176, 0x7f91, 0x6c6d,
643 0x4b95, 0x5fb7, 0x3844, 0x4037, 0x0184, 0x081b, 0x0ee8, 0x5b91,
644 0x293d, 0x1f71, 0x0e6f, 0x402b, 0x5122, 0x1e52, 0x22be, 0x3d2d,
645 0x75bc, 0x7c60, 0x6291, 0x1a2f, 0x61d4, 0x74aa, 0x4140, 0x29ab,
646 0x472d, 0x2852, 0x017e, 0x15e8, 0x5ec2, 0x17cf, 0x7d0f, 0x06b8,
647 0x117a, 0x6b94, 0x789b, 0x3126, 0x6ac5, 0x5be7, 0x150f, 0x51f8,
648 0x7889, 0x0aa5, 0x663d, 0x77e8, 0x0b87, 0x3dcb, 0x360d, 0x218b,
649 0x512f, 0x7dc9, 0x6a4d, 0x630a, 0x3547, 0x1dd2, 0x5aea, 0x69a5,
650 0x7bfa, 0x5e4f, 0x1519, 0x6430, 0x3a0e, 0x5eb3, 0x5425, 0x0c7a,
651 0x5540, 0x3670, 0x63c1, 0x31e9, 0x5a39, 0x2de7, 0x5979, 0x2891,
652 0x1562, 0x014b, 0x5b05, 0x2756, 0x5a34, 0x13aa, 0x6cb5, 0x2c36,
653 0x5e72, 0x1306, 0x0861, 0x15ef, 0x1ee8, 0x5a37, 0x7ac4, 0x45dd,
654 0x44c4, 0x7266, 0x2f41, 0x3ccc, 0x045e, 0x7d40, 0x7c66, 0x0fa0,
655};
656
657static const u16 sunxi_nfc_randomizer_ecc1024_seeds[] = {
658 0x2cf5, 0x35f1, 0x63a4, 0x5274, 0x2bd2, 0x778b, 0x7285, 0x32b6,
659 0x6a5c, 0x70d6, 0x757d, 0x6769, 0x5375, 0x1e81, 0x0cf3, 0x3982,
660 0x6787, 0x042a, 0x6c49, 0x1925, 0x56a8, 0x40a9, 0x063e, 0x7bd9,
661 0x4dbf, 0x55ec, 0x672e, 0x7334, 0x5185, 0x4d00, 0x232a, 0x7e07,
662 0x445d, 0x6b92, 0x528f, 0x4255, 0x53ba, 0x7d82, 0x2a2e, 0x3a4e,
663 0x75eb, 0x450c, 0x6844, 0x1b5d, 0x581a, 0x4cc6, 0x0379, 0x37b2,
664 0x419f, 0x0e92, 0x6b27, 0x5624, 0x01e3, 0x07c1, 0x44a5, 0x130c,
665 0x13e8, 0x5910, 0x0876, 0x60c5, 0x54e3, 0x5b7f, 0x2269, 0x509f,
666 0x7665, 0x36fd, 0x3e9a, 0x0579, 0x6295, 0x14ef, 0x0a81, 0x1bcc,
667 0x4b16, 0x64db, 0x0514, 0x4f07, 0x0591, 0x3576, 0x6853, 0x0d9e,
668 0x259f, 0x38b7, 0x64fb, 0x3094, 0x4693, 0x6ddd, 0x29bb, 0x0bc8,
669 0x3f47, 0x490e, 0x0c0e, 0x7933, 0x3c9e, 0x5840, 0x398d, 0x3e68,
670 0x4af1, 0x71f5, 0x57cf, 0x1121, 0x64eb, 0x3579, 0x15ac, 0x584d,
671 0x5f2a, 0x47e2, 0x6528, 0x6eac, 0x196e, 0x6b96, 0x0450, 0x0179,
672 0x609c, 0x06e1, 0x4626, 0x42c7, 0x273e, 0x486f, 0x0705, 0x1601,
673 0x145b, 0x407e, 0x062b, 0x57a5, 0x53f9, 0x5659, 0x4410, 0x3ccd,
674};
675
676static u16 sunxi_nfc_randomizer_step(u16 state, int count)
677{
678 state &= 0x7fff;
679
680 /*
681 * This loop is just a simple implementation of a Fibonacci LFSR using
682 * the x16 + x15 + 1 polynomial.
683 */
684 while (count--)
685 state = ((state >> 1) |
686 (((state ^ (state >> 1)) & 1) << 14)) & 0x7fff;
687
688 return state;
689}
690
691static u16 sunxi_nfc_randomizer_state(struct mtd_info *mtd, int page, bool ecc)
692{
693 const u16 *seeds = sunxi_nfc_randomizer_page_seeds;
Brian Norris46c135c2016-01-22 18:57:13 -0800694 int mod = mtd_div_by_ws(mtd->erasesize, mtd);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100695
696 if (mod > ARRAY_SIZE(sunxi_nfc_randomizer_page_seeds))
697 mod = ARRAY_SIZE(sunxi_nfc_randomizer_page_seeds);
698
699 if (ecc) {
700 if (mtd->ecc_step_size == 512)
701 seeds = sunxi_nfc_randomizer_ecc512_seeds;
702 else
703 seeds = sunxi_nfc_randomizer_ecc1024_seeds;
704 }
705
706 return seeds[page % mod];
707}
708
709static void sunxi_nfc_randomizer_config(struct mtd_info *mtd,
710 int page, bool ecc)
711{
Boris BREZILLONf671a1f2016-03-05 00:21:20 +0100712 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100713 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
714 u32 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
715 u16 state;
716
717 if (!(nand->options & NAND_NEED_SCRAMBLING))
718 return;
719
720 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
721 state = sunxi_nfc_randomizer_state(mtd, page, ecc);
722 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_RANDOM_SEED_MSK;
723 writel(ecc_ctl | NFC_RANDOM_SEED(state), nfc->regs + NFC_REG_ECC_CTL);
724}
725
726static void sunxi_nfc_randomizer_enable(struct mtd_info *mtd)
727{
Boris BREZILLONf671a1f2016-03-05 00:21:20 +0100728 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100729 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
730
731 if (!(nand->options & NAND_NEED_SCRAMBLING))
732 return;
733
734 writel(readl(nfc->regs + NFC_REG_ECC_CTL) | NFC_RANDOM_EN,
735 nfc->regs + NFC_REG_ECC_CTL);
736}
737
738static void sunxi_nfc_randomizer_disable(struct mtd_info *mtd)
739{
Boris BREZILLONf671a1f2016-03-05 00:21:20 +0100740 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100741 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
742
743 if (!(nand->options & NAND_NEED_SCRAMBLING))
744 return;
745
746 writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_RANDOM_EN,
747 nfc->regs + NFC_REG_ECC_CTL);
748}
749
750static void sunxi_nfc_randomize_bbm(struct mtd_info *mtd, int page, u8 *bbm)
751{
752 u16 state = sunxi_nfc_randomizer_state(mtd, page, true);
753
754 bbm[0] ^= state;
755 bbm[1] ^= sunxi_nfc_randomizer_step(state, 8);
756}
757
758static void sunxi_nfc_randomizer_write_buf(struct mtd_info *mtd,
759 const uint8_t *buf, int len,
760 bool ecc, int page)
761{
762 sunxi_nfc_randomizer_config(mtd, page, ecc);
763 sunxi_nfc_randomizer_enable(mtd);
764 sunxi_nfc_write_buf(mtd, buf, len);
765 sunxi_nfc_randomizer_disable(mtd);
766}
767
768static void sunxi_nfc_randomizer_read_buf(struct mtd_info *mtd, uint8_t *buf,
769 int len, bool ecc, int page)
770{
771 sunxi_nfc_randomizer_config(mtd, page, ecc);
772 sunxi_nfc_randomizer_enable(mtd);
773 sunxi_nfc_read_buf(mtd, buf, len);
774 sunxi_nfc_randomizer_disable(mtd);
775}
776
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200777static void sunxi_nfc_hw_ecc_enable(struct mtd_info *mtd)
778{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100779 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200780 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
781 struct sunxi_nand_hw_ecc *data = nand->ecc.priv;
782 u32 ecc_ctl;
783
784 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
785 ecc_ctl &= ~(NFC_ECC_MODE_MSK | NFC_ECC_PIPELINE |
786 NFC_ECC_BLOCK_SIZE_MSK);
Boris Brezillon336de7b2016-03-04 17:33:10 +0100787 ecc_ctl |= NFC_ECC_EN | NFC_ECC_MODE(data->mode) | NFC_ECC_EXCEPTION |
788 NFC_ECC_PIPELINE;
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200789
Boris Brezillonf59dab82016-10-20 10:12:42 +0200790 if (nand->ecc.size == 512)
791 ecc_ctl |= NFC_ECC_BLOCK_512;
792
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200793 writel(ecc_ctl, nfc->regs + NFC_REG_ECC_CTL);
794}
795
796static void sunxi_nfc_hw_ecc_disable(struct mtd_info *mtd)
797{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100798 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200799 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
800
801 writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_ECC_EN,
802 nfc->regs + NFC_REG_ECC_CTL);
803}
804
Boris BREZILLONf363e0f2015-09-30 23:45:27 +0200805static inline void sunxi_nfc_user_data_to_buf(u32 user_data, u8 *buf)
806{
807 buf[0] = user_data;
808 buf[1] = user_data >> 8;
809 buf[2] = user_data >> 16;
810 buf[3] = user_data >> 24;
811}
812
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100813static inline u32 sunxi_nfc_buf_to_user_data(const u8 *buf)
814{
815 return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
816}
817
818static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct mtd_info *mtd, u8 *oob,
819 int step, bool bbm, int page)
820{
821 struct nand_chip *nand = mtd_to_nand(mtd);
822 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
823
824 sunxi_nfc_user_data_to_buf(readl(nfc->regs + NFC_REG_USER_DATA(step)),
825 oob);
826
827 /* De-randomize the Bad Block Marker. */
828 if (bbm && (nand->options & NAND_NEED_SCRAMBLING))
829 sunxi_nfc_randomize_bbm(mtd, page, oob);
830}
831
832static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct mtd_info *mtd,
833 const u8 *oob, int step,
834 bool bbm, int page)
835{
836 struct nand_chip *nand = mtd_to_nand(mtd);
837 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
838 u8 user_data[4];
839
840 /* Randomize the Bad Block Marker. */
841 if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) {
842 memcpy(user_data, oob, sizeof(user_data));
843 sunxi_nfc_randomize_bbm(mtd, page, user_data);
844 oob = user_data;
845 }
846
847 writel(sunxi_nfc_buf_to_user_data(oob),
848 nfc->regs + NFC_REG_USER_DATA(step));
849}
850
851static void sunxi_nfc_hw_ecc_update_stats(struct mtd_info *mtd,
852 unsigned int *max_bitflips, int ret)
853{
854 if (ret < 0) {
855 mtd->ecc_stats.failed++;
856 } else {
857 mtd->ecc_stats.corrected += ret;
858 *max_bitflips = max_t(unsigned int, *max_bitflips, ret);
859 }
860}
861
862static int sunxi_nfc_hw_ecc_correct(struct mtd_info *mtd, u8 *data, u8 *oob,
Boris Brezillon614049a2016-04-15 15:10:30 +0200863 int step, u32 status, bool *erased)
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100864{
865 struct nand_chip *nand = mtd_to_nand(mtd);
866 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
867 struct nand_ecc_ctrl *ecc = &nand->ecc;
Boris Brezillon614049a2016-04-15 15:10:30 +0200868 u32 tmp;
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100869
870 *erased = false;
871
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100872 if (status & NFC_ECC_ERR(step))
873 return -EBADMSG;
874
875 if (status & NFC_ECC_PAT_FOUND(step)) {
876 u8 pattern;
877
878 if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID) & 0x1))) {
879 pattern = 0x0;
880 } else {
881 pattern = 0xff;
882 *erased = true;
883 }
884
885 if (data)
886 memset(data, pattern, ecc->size);
887
888 if (oob)
889 memset(oob, pattern, ecc->bytes + 4);
890
891 return 0;
892 }
893
894 tmp = readl(nfc->regs + NFC_REG_ECC_ERR_CNT(step));
895
896 return NFC_ECC_ERR_CNT(step, tmp);
897}
898
Boris BREZILLON913821b2015-09-30 23:45:24 +0200899static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
900 u8 *data, int data_off,
901 u8 *oob, int oob_off,
902 int *cur_off,
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100903 unsigned int *max_bitflips,
Boris Brezillon828dec12016-03-04 18:09:21 +0100904 bool bbm, bool oob_required, int page)
Boris BREZILLON913821b2015-09-30 23:45:24 +0200905{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100906 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200907 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
908 struct nand_ecc_ctrl *ecc = &nand->ecc;
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100909 int raw_mode = 0;
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100910 bool erased;
Boris BREZILLON913821b2015-09-30 23:45:24 +0200911 int ret;
912
913 if (*cur_off != data_off)
Boris Brezillon97d90da2017-11-30 18:01:29 +0100914 nand_change_read_column_op(nand, data_off, NULL, 0, false);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200915
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100916 sunxi_nfc_randomizer_read_buf(mtd, NULL, ecc->size, false, page);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200917
Boris BREZILLON74eb9ff2015-10-20 22:16:00 +0200918 if (data_off + ecc->size != oob_off)
Boris Brezillon97d90da2017-11-30 18:01:29 +0100919 nand_change_read_column_op(nand, oob_off, NULL, 0, false);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200920
921 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
922 if (ret)
923 return ret;
924
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100925 sunxi_nfc_randomizer_enable(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200926 writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP,
927 nfc->regs + NFC_REG_CMD);
928
Boris Brezillon8de15e12017-01-06 10:42:06 +0100929 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100930 sunxi_nfc_randomizer_disable(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200931 if (ret)
932 return ret;
933
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100934 *cur_off = oob_off + ecc->bytes + 4;
935
Boris Brezillon828dec12016-03-04 18:09:21 +0100936 ret = sunxi_nfc_hw_ecc_correct(mtd, data, oob_required ? oob : NULL, 0,
Boris Brezillon614049a2016-04-15 15:10:30 +0200937 readl(nfc->regs + NFC_REG_ECC_ST),
Boris Brezillon828dec12016-03-04 18:09:21 +0100938 &erased);
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100939 if (erased)
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100940 return 1;
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100941
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100942 if (ret < 0) {
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100943 /*
944 * Re-read the data with the randomizer disabled to identify
945 * bitflips in erased pages.
946 */
Boris Brezillon97d90da2017-11-30 18:01:29 +0100947 if (nand->options & NAND_NEED_SCRAMBLING)
948 nand_change_read_column_op(nand, data_off, data,
949 ecc->size, false);
950 else
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100951 memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE,
952 ecc->size);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100953
Boris Brezillon97d90da2017-11-30 18:01:29 +0100954 nand_change_read_column_op(nand, oob_off, oob, ecc->bytes + 4,
955 false);
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100956
Boris BREZILLON146b5032015-09-30 23:45:29 +0200957 ret = nand_check_erased_ecc_chunk(data, ecc->size,
958 oob, ecc->bytes + 4,
959 NULL, 0, ecc->strength);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100960 if (ret >= 0)
961 raw_mode = 1;
Boris BREZILLONf363e0f2015-09-30 23:45:27 +0200962 } else {
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100963 memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100964
Boris Brezillon828dec12016-03-04 18:09:21 +0100965 if (oob_required) {
Boris Brezillon97d90da2017-11-30 18:01:29 +0100966 nand_change_read_column_op(nand, oob_off, NULL, 0,
967 false);
Boris Brezillon828dec12016-03-04 18:09:21 +0100968 sunxi_nfc_randomizer_read_buf(mtd, oob, ecc->bytes + 4,
969 true, page);
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100970
Boris Brezillon828dec12016-03-04 18:09:21 +0100971 sunxi_nfc_hw_ecc_get_prot_oob_bytes(mtd, oob, 0,
972 bbm, page);
973 }
Boris BREZILLONf363e0f2015-09-30 23:45:27 +0200974 }
Boris BREZILLON913821b2015-09-30 23:45:24 +0200975
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100976 sunxi_nfc_hw_ecc_update_stats(mtd, max_bitflips, ret);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200977
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100978 return raw_mode;
Boris BREZILLON913821b2015-09-30 23:45:24 +0200979}
980
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200981static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd,
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100982 u8 *oob, int *cur_off,
983 bool randomize, int page)
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200984{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100985 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200986 struct nand_ecc_ctrl *ecc = &nand->ecc;
987 int offset = ((ecc->bytes + 4) * ecc->steps);
988 int len = mtd->oobsize - offset;
989
990 if (len <= 0)
991 return;
992
Boris Brezillonc4f3ef22016-03-04 18:13:10 +0100993 if (!cur_off || *cur_off != offset)
Boris Brezillon97d90da2017-11-30 18:01:29 +0100994 nand_change_read_column_op(nand, mtd->writesize, NULL, 0,
995 false);
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200996
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100997 if (!randomize)
998 sunxi_nfc_read_buf(mtd, oob + offset, len);
999 else
1000 sunxi_nfc_randomizer_read_buf(mtd, oob + offset, len,
1001 false, page);
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001002
Boris Brezillonc4f3ef22016-03-04 18:13:10 +01001003 if (cur_off)
1004 *cur_off = mtd->oobsize + mtd->writesize;
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001005}
1006
Boris Brezillon614049a2016-04-15 15:10:30 +02001007static int sunxi_nfc_hw_ecc_read_chunks_dma(struct mtd_info *mtd, uint8_t *buf,
1008 int oob_required, int page,
1009 int nchunks)
1010{
1011 struct nand_chip *nand = mtd_to_nand(mtd);
1012 bool randomized = nand->options & NAND_NEED_SCRAMBLING;
1013 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
1014 struct nand_ecc_ctrl *ecc = &nand->ecc;
1015 unsigned int max_bitflips = 0;
1016 int ret, i, raw_mode = 0;
1017 struct scatterlist sg;
1018 u32 status;
1019
1020 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
1021 if (ret)
1022 return ret;
1023
1024 ret = sunxi_nfc_dma_op_prepare(mtd, buf, ecc->size, nchunks,
1025 DMA_FROM_DEVICE, &sg);
1026 if (ret)
1027 return ret;
1028
1029 sunxi_nfc_hw_ecc_enable(mtd);
1030 sunxi_nfc_randomizer_config(mtd, page, false);
1031 sunxi_nfc_randomizer_enable(mtd);
1032
1033 writel((NAND_CMD_RNDOUTSTART << 16) | (NAND_CMD_RNDOUT << 8) |
1034 NAND_CMD_READSTART, nfc->regs + NFC_REG_RCMD_SET);
1035
1036 dma_async_issue_pending(nfc->dmac);
1037
1038 writel(NFC_PAGE_OP | NFC_DATA_SWAP_METHOD | NFC_DATA_TRANS,
1039 nfc->regs + NFC_REG_CMD);
1040
Boris Brezillon8de15e12017-01-06 10:42:06 +01001041 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0);
Boris Brezillon614049a2016-04-15 15:10:30 +02001042 if (ret)
1043 dmaengine_terminate_all(nfc->dmac);
1044
1045 sunxi_nfc_randomizer_disable(mtd);
1046 sunxi_nfc_hw_ecc_disable(mtd);
1047
1048 sunxi_nfc_dma_op_cleanup(mtd, DMA_FROM_DEVICE, &sg);
1049
1050 if (ret)
1051 return ret;
1052
1053 status = readl(nfc->regs + NFC_REG_ECC_ST);
1054
1055 for (i = 0; i < nchunks; i++) {
1056 int data_off = i * ecc->size;
1057 int oob_off = i * (ecc->bytes + 4);
1058 u8 *data = buf + data_off;
1059 u8 *oob = nand->oob_poi + oob_off;
1060 bool erased;
1061
1062 ret = sunxi_nfc_hw_ecc_correct(mtd, randomized ? data : NULL,
1063 oob_required ? oob : NULL,
1064 i, status, &erased);
1065
1066 /* ECC errors are handled in the second loop. */
1067 if (ret < 0)
1068 continue;
1069
1070 if (oob_required && !erased) {
1071 /* TODO: use DMA to retrieve OOB */
Boris Brezillon97d90da2017-11-30 18:01:29 +01001072 nand_change_read_column_op(nand,
1073 mtd->writesize + oob_off,
1074 oob, ecc->bytes + 4, false);
Boris Brezillon614049a2016-04-15 15:10:30 +02001075
1076 sunxi_nfc_hw_ecc_get_prot_oob_bytes(mtd, oob, i,
1077 !i, page);
1078 }
1079
1080 if (erased)
1081 raw_mode = 1;
1082
1083 sunxi_nfc_hw_ecc_update_stats(mtd, &max_bitflips, ret);
1084 }
1085
1086 if (status & NFC_ECC_ERR_MSK) {
1087 for (i = 0; i < nchunks; i++) {
1088 int data_off = i * ecc->size;
1089 int oob_off = i * (ecc->bytes + 4);
1090 u8 *data = buf + data_off;
1091 u8 *oob = nand->oob_poi + oob_off;
1092
1093 if (!(status & NFC_ECC_ERR(i)))
1094 continue;
1095
1096 /*
1097 * Re-read the data with the randomizer disabled to
1098 * identify bitflips in erased pages.
Boris Brezillon97d90da2017-11-30 18:01:29 +01001099 * TODO: use DMA to read page in raw mode
Boris Brezillon614049a2016-04-15 15:10:30 +02001100 */
Boris Brezillon97d90da2017-11-30 18:01:29 +01001101 if (randomized)
1102 nand_change_read_column_op(nand, data_off,
1103 data, ecc->size,
1104 false);
Boris Brezillon614049a2016-04-15 15:10:30 +02001105
1106 /* TODO: use DMA to retrieve OOB */
Boris Brezillon97d90da2017-11-30 18:01:29 +01001107 nand_change_read_column_op(nand,
1108 mtd->writesize + oob_off,
1109 oob, ecc->bytes + 4, false);
Boris Brezillon614049a2016-04-15 15:10:30 +02001110
1111 ret = nand_check_erased_ecc_chunk(data, ecc->size,
1112 oob, ecc->bytes + 4,
1113 NULL, 0,
1114 ecc->strength);
1115 if (ret >= 0)
1116 raw_mode = 1;
1117
1118 sunxi_nfc_hw_ecc_update_stats(mtd, &max_bitflips, ret);
1119 }
1120 }
1121
1122 if (oob_required)
1123 sunxi_nfc_hw_ecc_read_extra_oob(mtd, nand->oob_poi,
1124 NULL, !raw_mode,
1125 page);
1126
1127 return max_bitflips;
1128}
1129
Boris BREZILLON913821b2015-09-30 23:45:24 +02001130static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd,
1131 const u8 *data, int data_off,
1132 const u8 *oob, int oob_off,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001133 int *cur_off, bool bbm,
1134 int page)
Boris BREZILLON913821b2015-09-30 23:45:24 +02001135{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +01001136 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +02001137 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
1138 struct nand_ecc_ctrl *ecc = &nand->ecc;
1139 int ret;
1140
1141 if (data_off != *cur_off)
Boris Brezillon97d90da2017-11-30 18:01:29 +01001142 nand_change_write_column_op(nand, data_off, NULL, 0, false);
Boris BREZILLON913821b2015-09-30 23:45:24 +02001143
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001144 sunxi_nfc_randomizer_write_buf(mtd, data, ecc->size, false, page);
Boris BREZILLON913821b2015-09-30 23:45:24 +02001145
Boris BREZILLON74eb9ff2015-10-20 22:16:00 +02001146 if (data_off + ecc->size != oob_off)
Boris Brezillon97d90da2017-11-30 18:01:29 +01001147 nand_change_write_column_op(nand, oob_off, NULL, 0, false);
Boris BREZILLON913821b2015-09-30 23:45:24 +02001148
1149 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
1150 if (ret)
1151 return ret;
1152
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001153 sunxi_nfc_randomizer_enable(mtd);
Boris Brezilloncc6822f2016-03-04 17:56:47 +01001154 sunxi_nfc_hw_ecc_set_prot_oob_bytes(mtd, oob, 0, bbm, page);
1155
Boris BREZILLON913821b2015-09-30 23:45:24 +02001156 writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD |
1157 NFC_ACCESS_DIR | NFC_ECC_OP,
1158 nfc->regs + NFC_REG_CMD);
1159
Boris Brezillon8de15e12017-01-06 10:42:06 +01001160 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0);
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001161 sunxi_nfc_randomizer_disable(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +02001162 if (ret)
1163 return ret;
1164
1165 *cur_off = oob_off + ecc->bytes + 4;
1166
1167 return 0;
1168}
1169
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001170static void sunxi_nfc_hw_ecc_write_extra_oob(struct mtd_info *mtd,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001171 u8 *oob, int *cur_off,
1172 int page)
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001173{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +01001174 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001175 struct nand_ecc_ctrl *ecc = &nand->ecc;
1176 int offset = ((ecc->bytes + 4) * ecc->steps);
1177 int len = mtd->oobsize - offset;
1178
1179 if (len <= 0)
1180 return;
1181
Boris Brezillonc4f3ef22016-03-04 18:13:10 +01001182 if (!cur_off || *cur_off != offset)
Boris Brezillon97d90da2017-11-30 18:01:29 +01001183 nand_change_write_column_op(nand, offset + mtd->writesize,
1184 NULL, 0, false);
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001185
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001186 sunxi_nfc_randomizer_write_buf(mtd, oob + offset, len, false, page);
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001187
Boris Brezillonc4f3ef22016-03-04 18:13:10 +01001188 if (cur_off)
1189 *cur_off = mtd->oobsize + mtd->writesize;
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001190}
1191
Boris Brezillonb9761682018-09-06 14:05:20 +02001192static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *chip, uint8_t *buf,
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001193 int oob_required, int page)
1194{
Boris Brezillonb9761682018-09-06 14:05:20 +02001195 struct mtd_info *mtd = nand_to_mtd(chip);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001196 struct nand_ecc_ctrl *ecc = &chip->ecc;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001197 unsigned int max_bitflips = 0;
Boris BREZILLONb4625512015-09-30 23:45:25 +02001198 int ret, i, cur_off = 0;
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001199 bool raw_mode = false;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001200
Boris Brezillon25f815f2017-11-30 18:01:30 +01001201 nand_read_page_op(chip, page, 0, NULL, 0);
1202
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001203 sunxi_nfc_hw_ecc_enable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001204
1205 for (i = 0; i < ecc->steps; i++) {
Boris BREZILLONb4625512015-09-30 23:45:25 +02001206 int data_off = i * ecc->size;
1207 int oob_off = i * (ecc->bytes + 4);
1208 u8 *data = buf + data_off;
1209 u8 *oob = chip->oob_poi + oob_off;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001210
Boris BREZILLONb4625512015-09-30 23:45:25 +02001211 ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob,
1212 oob_off + mtd->writesize,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001213 &cur_off, &max_bitflips,
Boris Brezillon828dec12016-03-04 18:09:21 +01001214 !i, oob_required, page);
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001215 if (ret < 0)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001216 return ret;
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001217 else if (ret)
1218 raw_mode = true;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001219 }
1220
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001221 if (oob_required)
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001222 sunxi_nfc_hw_ecc_read_extra_oob(mtd, chip->oob_poi, &cur_off,
1223 !raw_mode, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001224
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001225 sunxi_nfc_hw_ecc_disable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001226
1227 return max_bitflips;
1228}
1229
Boris Brezillonb9761682018-09-06 14:05:20 +02001230static int sunxi_nfc_hw_ecc_read_page_dma(struct nand_chip *chip, u8 *buf,
Boris Brezillon614049a2016-04-15 15:10:30 +02001231 int oob_required, int page)
1232{
Boris Brezillonb9761682018-09-06 14:05:20 +02001233 struct mtd_info *mtd = nand_to_mtd(chip);
Boris Brezillon614049a2016-04-15 15:10:30 +02001234 int ret;
1235
Boris Brezillon25f815f2017-11-30 18:01:30 +01001236 nand_read_page_op(chip, page, 0, NULL, 0);
1237
Boris Brezillon614049a2016-04-15 15:10:30 +02001238 ret = sunxi_nfc_hw_ecc_read_chunks_dma(mtd, buf, oob_required, page,
1239 chip->ecc.steps);
1240 if (ret >= 0)
1241 return ret;
1242
1243 /* Fallback to PIO mode */
Boris Brezillonb9761682018-09-06 14:05:20 +02001244 return sunxi_nfc_hw_ecc_read_page(chip, buf, oob_required, page);
Boris Brezillon614049a2016-04-15 15:10:30 +02001245}
1246
Boris Brezillonb9761682018-09-06 14:05:20 +02001247static int sunxi_nfc_hw_ecc_read_subpage(struct nand_chip *chip,
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001248 u32 data_offs, u32 readlen,
1249 u8 *bufpoi, int page)
1250{
Boris Brezillonb9761682018-09-06 14:05:20 +02001251 struct mtd_info *mtd = nand_to_mtd(chip);
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001252 struct nand_ecc_ctrl *ecc = &chip->ecc;
1253 int ret, i, cur_off = 0;
1254 unsigned int max_bitflips = 0;
1255
Boris Brezillon25f815f2017-11-30 18:01:30 +01001256 nand_read_page_op(chip, page, 0, NULL, 0);
1257
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001258 sunxi_nfc_hw_ecc_enable(mtd);
1259
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001260 for (i = data_offs / ecc->size;
1261 i < DIV_ROUND_UP(data_offs + readlen, ecc->size); i++) {
1262 int data_off = i * ecc->size;
1263 int oob_off = i * (ecc->bytes + 4);
1264 u8 *data = bufpoi + data_off;
1265 u8 *oob = chip->oob_poi + oob_off;
1266
1267 ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off,
1268 oob,
1269 oob_off + mtd->writesize,
Boris Brezillon828dec12016-03-04 18:09:21 +01001270 &cur_off, &max_bitflips, !i,
1271 false, page);
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001272 if (ret < 0)
1273 return ret;
1274 }
1275
1276 sunxi_nfc_hw_ecc_disable(mtd);
1277
1278 return max_bitflips;
1279}
1280
Boris Brezillonb9761682018-09-06 14:05:20 +02001281static int sunxi_nfc_hw_ecc_read_subpage_dma(struct nand_chip *chip,
Boris Brezillon614049a2016-04-15 15:10:30 +02001282 u32 data_offs, u32 readlen,
1283 u8 *buf, int page)
1284{
Boris Brezillonb9761682018-09-06 14:05:20 +02001285 struct mtd_info *mtd = nand_to_mtd(chip);
Boris Brezillon614049a2016-04-15 15:10:30 +02001286 int nchunks = DIV_ROUND_UP(data_offs + readlen, chip->ecc.size);
1287 int ret;
1288
Boris Brezillon25f815f2017-11-30 18:01:30 +01001289 nand_read_page_op(chip, page, 0, NULL, 0);
1290
Boris Brezillon614049a2016-04-15 15:10:30 +02001291 ret = sunxi_nfc_hw_ecc_read_chunks_dma(mtd, buf, false, page, nchunks);
1292 if (ret >= 0)
1293 return ret;
1294
1295 /* Fallback to PIO mode */
Boris Brezillonb9761682018-09-06 14:05:20 +02001296 return sunxi_nfc_hw_ecc_read_subpage(chip, data_offs, readlen,
Boris Brezillon614049a2016-04-15 15:10:30 +02001297 buf, page);
1298}
1299
Boris Brezillon767eb6f2018-09-06 14:05:21 +02001300static int sunxi_nfc_hw_ecc_write_page(struct nand_chip *chip,
Boris BREZILLON45aaeff2015-10-13 11:22:18 +02001301 const uint8_t *buf, int oob_required,
1302 int page)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001303{
Boris Brezillon767eb6f2018-09-06 14:05:21 +02001304 struct mtd_info *mtd = nand_to_mtd(chip);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001305 struct nand_ecc_ctrl *ecc = &chip->ecc;
Boris BREZILLONb4625512015-09-30 23:45:25 +02001306 int ret, i, cur_off = 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001307
Boris Brezillon25f815f2017-11-30 18:01:30 +01001308 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
1309
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001310 sunxi_nfc_hw_ecc_enable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001311
1312 for (i = 0; i < ecc->steps; i++) {
Boris BREZILLONb4625512015-09-30 23:45:25 +02001313 int data_off = i * ecc->size;
1314 int oob_off = i * (ecc->bytes + 4);
1315 const u8 *data = buf + data_off;
1316 const u8 *oob = chip->oob_poi + oob_off;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001317
Boris BREZILLONb4625512015-09-30 23:45:25 +02001318 ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off, oob,
1319 oob_off + mtd->writesize,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001320 &cur_off, !i, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001321 if (ret)
1322 return ret;
1323 }
1324
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001325 if (oob_required || (chip->options & NAND_NEED_SCRAMBLING))
1326 sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi,
1327 &cur_off, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001328
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001329 sunxi_nfc_hw_ecc_disable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001330
Boris Brezillon25f815f2017-11-30 18:01:30 +01001331 return nand_prog_page_end_op(chip);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001332}
1333
Boris Brezillon767eb6f2018-09-06 14:05:21 +02001334static int sunxi_nfc_hw_ecc_write_subpage(struct nand_chip *chip,
Boris Brezillon03b1d112016-06-06 13:59:14 +02001335 u32 data_offs, u32 data_len,
1336 const u8 *buf, int oob_required,
1337 int page)
1338{
Boris Brezillon767eb6f2018-09-06 14:05:21 +02001339 struct mtd_info *mtd = nand_to_mtd(chip);
Boris Brezillon03b1d112016-06-06 13:59:14 +02001340 struct nand_ecc_ctrl *ecc = &chip->ecc;
1341 int ret, i, cur_off = 0;
1342
Boris Brezillon25f815f2017-11-30 18:01:30 +01001343 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
1344
Boris Brezillon03b1d112016-06-06 13:59:14 +02001345 sunxi_nfc_hw_ecc_enable(mtd);
1346
1347 for (i = data_offs / ecc->size;
1348 i < DIV_ROUND_UP(data_offs + data_len, ecc->size); i++) {
1349 int data_off = i * ecc->size;
1350 int oob_off = i * (ecc->bytes + 4);
1351 const u8 *data = buf + data_off;
1352 const u8 *oob = chip->oob_poi + oob_off;
1353
1354 ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off, oob,
1355 oob_off + mtd->writesize,
1356 &cur_off, !i, page);
1357 if (ret)
1358 return ret;
1359 }
1360
1361 sunxi_nfc_hw_ecc_disable(mtd);
1362
Boris Brezillon25f815f2017-11-30 18:01:30 +01001363 return nand_prog_page_end_op(chip);
Boris Brezillon03b1d112016-06-06 13:59:14 +02001364}
1365
Boris Brezillon767eb6f2018-09-06 14:05:21 +02001366static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *chip,
Boris Brezillon614049a2016-04-15 15:10:30 +02001367 const u8 *buf,
1368 int oob_required,
1369 int page)
1370{
Boris Brezillon767eb6f2018-09-06 14:05:21 +02001371 struct mtd_info *mtd = nand_to_mtd(chip);
Boris Brezillon614049a2016-04-15 15:10:30 +02001372 struct nand_chip *nand = mtd_to_nand(mtd);
1373 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
1374 struct nand_ecc_ctrl *ecc = &nand->ecc;
1375 struct scatterlist sg;
1376 int ret, i;
1377
1378 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
1379 if (ret)
1380 return ret;
1381
1382 ret = sunxi_nfc_dma_op_prepare(mtd, buf, ecc->size, ecc->steps,
1383 DMA_TO_DEVICE, &sg);
1384 if (ret)
1385 goto pio_fallback;
1386
1387 for (i = 0; i < ecc->steps; i++) {
1388 const u8 *oob = nand->oob_poi + (i * (ecc->bytes + 4));
1389
1390 sunxi_nfc_hw_ecc_set_prot_oob_bytes(mtd, oob, i, !i, page);
1391 }
1392
Boris Brezillon25f815f2017-11-30 18:01:30 +01001393 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
1394
Boris Brezillon614049a2016-04-15 15:10:30 +02001395 sunxi_nfc_hw_ecc_enable(mtd);
1396 sunxi_nfc_randomizer_config(mtd, page, false);
1397 sunxi_nfc_randomizer_enable(mtd);
1398
1399 writel((NAND_CMD_RNDIN << 8) | NAND_CMD_PAGEPROG,
1400 nfc->regs + NFC_REG_RCMD_SET);
1401
1402 dma_async_issue_pending(nfc->dmac);
1403
1404 writel(NFC_PAGE_OP | NFC_DATA_SWAP_METHOD |
1405 NFC_DATA_TRANS | NFC_ACCESS_DIR,
1406 nfc->regs + NFC_REG_CMD);
1407
Boris Brezillon8de15e12017-01-06 10:42:06 +01001408 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0);
Boris Brezillon614049a2016-04-15 15:10:30 +02001409 if (ret)
1410 dmaengine_terminate_all(nfc->dmac);
1411
1412 sunxi_nfc_randomizer_disable(mtd);
1413 sunxi_nfc_hw_ecc_disable(mtd);
1414
1415 sunxi_nfc_dma_op_cleanup(mtd, DMA_TO_DEVICE, &sg);
1416
1417 if (ret)
1418 return ret;
1419
1420 if (oob_required || (chip->options & NAND_NEED_SCRAMBLING))
1421 /* TODO: use DMA to transfer extra OOB bytes ? */
1422 sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi,
1423 NULL, page);
1424
Boris Brezillon25f815f2017-11-30 18:01:30 +01001425 return nand_prog_page_end_op(chip);
Boris Brezillon614049a2016-04-15 15:10:30 +02001426
1427pio_fallback:
Boris Brezillon767eb6f2018-09-06 14:05:21 +02001428 return sunxi_nfc_hw_ecc_write_page(chip, buf, oob_required, page);
Boris Brezillon614049a2016-04-15 15:10:30 +02001429}
1430
Boris Brezillonb9761682018-09-06 14:05:20 +02001431static int sunxi_nfc_hw_ecc_read_oob(struct nand_chip *chip, int page)
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001432{
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001433 chip->pagebuf = -1;
1434
Boris Brezillonb9761682018-09-06 14:05:20 +02001435 return chip->ecc.read_page(chip, chip->data_buf, 1, page);
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001436}
1437
Boris Brezillon767eb6f2018-09-06 14:05:21 +02001438static int sunxi_nfc_hw_ecc_write_oob(struct nand_chip *chip, int page)
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001439{
Boris Brezillon767eb6f2018-09-06 14:05:21 +02001440 struct mtd_info *mtd = nand_to_mtd(chip);
Boris Brezillon97d90da2017-11-30 18:01:29 +01001441 int ret;
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001442
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001443 chip->pagebuf = -1;
1444
Masahiro Yamadac0313b92017-12-05 17:47:16 +09001445 memset(chip->data_buf, 0xff, mtd->writesize);
Boris Brezillon767eb6f2018-09-06 14:05:21 +02001446 ret = chip->ecc.write_page(chip, chip->data_buf, 1, page);
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001447 if (ret)
1448 return ret;
1449
1450 /* Send command to program the OOB data */
Boris Brezillon97d90da2017-11-30 18:01:29 +01001451 return nand_prog_page_end_op(chip);
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001452}
1453
Roy Spliet9c618292015-06-26 11:00:10 +02001454static const s32 tWB_lut[] = {6, 12, 16, 20};
1455static const s32 tRHW_lut[] = {4, 8, 12, 20};
1456
1457static int _sunxi_nand_lookup_timing(const s32 *lut, int lut_size, u32 duration,
1458 u32 clk_period)
1459{
1460 u32 clk_cycles = DIV_ROUND_UP(duration, clk_period);
1461 int i;
1462
1463 for (i = 0; i < lut_size; i++) {
1464 if (clk_cycles <= lut[i])
1465 return i;
1466 }
1467
1468 /* Doesn't fit */
1469 return -EINVAL;
1470}
1471
1472#define sunxi_nand_lookup_timing(l, p, c) \
1473 _sunxi_nand_lookup_timing(l, ARRAY_SIZE(l), p, c)
1474
Boris Brezillon104e4422017-03-16 09:35:58 +01001475static int sunxi_nfc_setup_data_interface(struct mtd_info *mtd, int csline,
1476 const struct nand_data_interface *conf)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001477{
Sascha Hauer907f45f2016-09-15 10:32:51 +02001478 struct nand_chip *nand = mtd_to_nand(mtd);
1479 struct sunxi_nand_chip *chip = to_sunxi_nand(nand);
Roy Spliet9c618292015-06-26 11:00:10 +02001480 struct sunxi_nfc *nfc = to_sunxi_nfc(chip->nand.controller);
Sascha Hauer907f45f2016-09-15 10:32:51 +02001481 const struct nand_sdr_timings *timings;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001482 u32 min_clk_period = 0;
Roy Spliet9c618292015-06-26 11:00:10 +02001483 s32 tWB, tADL, tWHR, tRHW, tCAD;
Boris Brezillon2d434572015-12-02 15:57:20 +01001484 long real_clk_rate;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001485
Sascha Hauer907f45f2016-09-15 10:32:51 +02001486 timings = nand_get_sdr_timings(conf);
1487 if (IS_ERR(timings))
1488 return -ENOTSUPP;
1489
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001490 /* T1 <=> tCLS */
1491 if (timings->tCLS_min > min_clk_period)
1492 min_clk_period = timings->tCLS_min;
1493
1494 /* T2 <=> tCLH */
1495 if (timings->tCLH_min > min_clk_period)
1496 min_clk_period = timings->tCLH_min;
1497
1498 /* T3 <=> tCS */
1499 if (timings->tCS_min > min_clk_period)
1500 min_clk_period = timings->tCS_min;
1501
1502 /* T4 <=> tCH */
1503 if (timings->tCH_min > min_clk_period)
1504 min_clk_period = timings->tCH_min;
1505
1506 /* T5 <=> tWP */
1507 if (timings->tWP_min > min_clk_period)
1508 min_clk_period = timings->tWP_min;
1509
1510 /* T6 <=> tWH */
1511 if (timings->tWH_min > min_clk_period)
1512 min_clk_period = timings->tWH_min;
1513
1514 /* T7 <=> tALS */
1515 if (timings->tALS_min > min_clk_period)
1516 min_clk_period = timings->tALS_min;
1517
1518 /* T8 <=> tDS */
1519 if (timings->tDS_min > min_clk_period)
1520 min_clk_period = timings->tDS_min;
1521
1522 /* T9 <=> tDH */
1523 if (timings->tDH_min > min_clk_period)
1524 min_clk_period = timings->tDH_min;
1525
1526 /* T10 <=> tRR */
1527 if (timings->tRR_min > (min_clk_period * 3))
1528 min_clk_period = DIV_ROUND_UP(timings->tRR_min, 3);
1529
1530 /* T11 <=> tALH */
1531 if (timings->tALH_min > min_clk_period)
1532 min_clk_period = timings->tALH_min;
1533
1534 /* T12 <=> tRP */
1535 if (timings->tRP_min > min_clk_period)
1536 min_clk_period = timings->tRP_min;
1537
1538 /* T13 <=> tREH */
1539 if (timings->tREH_min > min_clk_period)
1540 min_clk_period = timings->tREH_min;
1541
1542 /* T14 <=> tRC */
1543 if (timings->tRC_min > (min_clk_period * 2))
1544 min_clk_period = DIV_ROUND_UP(timings->tRC_min, 2);
1545
1546 /* T15 <=> tWC */
1547 if (timings->tWC_min > (min_clk_period * 2))
1548 min_clk_period = DIV_ROUND_UP(timings->tWC_min, 2);
1549
Roy Spliet9c618292015-06-26 11:00:10 +02001550 /* T16 - T19 + tCAD */
Boris Brezillon5abcd952015-11-11 22:30:30 +01001551 if (timings->tWB_max > (min_clk_period * 20))
1552 min_clk_period = DIV_ROUND_UP(timings->tWB_max, 20);
1553
1554 if (timings->tADL_min > (min_clk_period * 32))
1555 min_clk_period = DIV_ROUND_UP(timings->tADL_min, 32);
1556
1557 if (timings->tWHR_min > (min_clk_period * 32))
1558 min_clk_period = DIV_ROUND_UP(timings->tWHR_min, 32);
1559
1560 if (timings->tRHW_min > (min_clk_period * 20))
1561 min_clk_period = DIV_ROUND_UP(timings->tRHW_min, 20);
1562
Roy Spliet9c618292015-06-26 11:00:10 +02001563 tWB = sunxi_nand_lookup_timing(tWB_lut, timings->tWB_max,
1564 min_clk_period);
1565 if (tWB < 0) {
1566 dev_err(nfc->dev, "unsupported tWB\n");
1567 return tWB;
1568 }
1569
1570 tADL = DIV_ROUND_UP(timings->tADL_min, min_clk_period) >> 3;
1571 if (tADL > 3) {
1572 dev_err(nfc->dev, "unsupported tADL\n");
1573 return -EINVAL;
1574 }
1575
1576 tWHR = DIV_ROUND_UP(timings->tWHR_min, min_clk_period) >> 3;
1577 if (tWHR > 3) {
1578 dev_err(nfc->dev, "unsupported tWHR\n");
1579 return -EINVAL;
1580 }
1581
1582 tRHW = sunxi_nand_lookup_timing(tRHW_lut, timings->tRHW_min,
1583 min_clk_period);
1584 if (tRHW < 0) {
1585 dev_err(nfc->dev, "unsupported tRHW\n");
1586 return tRHW;
1587 }
1588
Boris Brezillon104e4422017-03-16 09:35:58 +01001589 if (csline == NAND_DATA_IFACE_CHECK_ONLY)
Sascha Hauer907f45f2016-09-15 10:32:51 +02001590 return 0;
1591
Roy Spliet9c618292015-06-26 11:00:10 +02001592 /*
1593 * TODO: according to ONFI specs this value only applies for DDR NAND,
1594 * but Allwinner seems to set this to 0x7. Mimic them for now.
1595 */
1596 tCAD = 0x7;
1597
1598 /* TODO: A83 has some more bits for CDQSS, CS, CLHZ, CCS, WC */
1599 chip->timing_cfg = NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001600
1601 /* Convert min_clk_period from picoseconds to nanoseconds */
1602 min_clk_period = DIV_ROUND_UP(min_clk_period, 1000);
1603
1604 /*
Boris Brezillon2f9992e2015-12-02 15:10:40 +01001605 * Unlike what is stated in Allwinner datasheet, the clk_rate should
1606 * be set to (1 / min_clk_period), and not (2 / min_clk_period).
1607 * This new formula was verified with a scope and validated by
1608 * Allwinner engineers.
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001609 */
Boris Brezillon2f9992e2015-12-02 15:10:40 +01001610 chip->clk_rate = NSEC_PER_SEC / min_clk_period;
Boris Brezillon2d434572015-12-02 15:57:20 +01001611 real_clk_rate = clk_round_rate(nfc->mod_clk, chip->clk_rate);
Bryan O'Donoghue791eccd2017-07-28 14:22:57 +01001612 if (real_clk_rate <= 0) {
1613 dev_err(nfc->dev, "Unable to round clk %lu\n", chip->clk_rate);
1614 return -EINVAL;
1615 }
Boris Brezillon2d434572015-12-02 15:57:20 +01001616
1617 /*
1618 * ONFI specification 3.1, paragraph 4.15.2 dictates that EDO data
1619 * output cycle timings shall be used if the host drives tRC less than
1620 * 30 ns.
1621 */
1622 min_clk_period = NSEC_PER_SEC / real_clk_rate;
1623 chip->timing_ctl = ((min_clk_period * 2) < 30) ?
1624 NFC_TIMING_CTL_EDO : 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001625
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001626 return 0;
1627}
1628
Boris Brezillonc66811e2016-02-03 20:05:13 +01001629static int sunxi_nand_ooblayout_ecc(struct mtd_info *mtd, int section,
1630 struct mtd_oob_region *oobregion)
1631{
1632 struct nand_chip *nand = mtd_to_nand(mtd);
1633 struct nand_ecc_ctrl *ecc = &nand->ecc;
1634
1635 if (section >= ecc->steps)
1636 return -ERANGE;
1637
1638 oobregion->offset = section * (ecc->bytes + 4) + 4;
1639 oobregion->length = ecc->bytes;
1640
1641 return 0;
1642}
1643
1644static int sunxi_nand_ooblayout_free(struct mtd_info *mtd, int section,
1645 struct mtd_oob_region *oobregion)
1646{
1647 struct nand_chip *nand = mtd_to_nand(mtd);
1648 struct nand_ecc_ctrl *ecc = &nand->ecc;
1649
1650 if (section > ecc->steps)
1651 return -ERANGE;
1652
1653 /*
1654 * The first 2 bytes are used for BB markers, hence we
1655 * only have 2 bytes available in the first user data
1656 * section.
1657 */
1658 if (!section && ecc->mode == NAND_ECC_HW) {
1659 oobregion->offset = 2;
1660 oobregion->length = 2;
1661
1662 return 0;
1663 }
1664
1665 oobregion->offset = section * (ecc->bytes + 4);
1666
1667 if (section < ecc->steps)
1668 oobregion->length = 4;
1669 else
1670 oobregion->offset = mtd->oobsize - oobregion->offset;
1671
1672 return 0;
1673}
1674
1675static const struct mtd_ooblayout_ops sunxi_nand_ooblayout_ops = {
1676 .ecc = sunxi_nand_ooblayout_ecc,
1677 .free = sunxi_nand_ooblayout_free,
1678};
1679
Boris Brezillon15d6f112018-03-21 09:36:18 +01001680static void sunxi_nand_hw_ecc_ctrl_cleanup(struct nand_ecc_ctrl *ecc)
1681{
1682 kfree(ecc->priv);
1683}
1684
1685static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
1686 struct nand_ecc_ctrl *ecc,
1687 struct device_node *np)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001688{
1689 static const u8 strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 };
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +01001690 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001691 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
1692 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
1693 struct sunxi_nand_hw_ecc *data;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001694 int nsectors;
1695 int ret;
1696 int i;
1697
Boris Brezillon4796d862016-06-08 17:04:24 +02001698 if (ecc->options & NAND_ECC_MAXIMIZE) {
1699 int bytes;
1700
1701 ecc->size = 1024;
1702 nsectors = mtd->writesize / ecc->size;
1703
1704 /* Reserve 2 bytes for the BBM */
1705 bytes = (mtd->oobsize - 2) / nsectors;
1706
1707 /* 4 non-ECC bytes are added before each ECC bytes section */
1708 bytes -= 4;
1709
1710 /* and bytes has to be even. */
1711 if (bytes % 2)
1712 bytes--;
1713
1714 ecc->strength = bytes * 8 / fls(8 * ecc->size);
1715
1716 for (i = 0; i < ARRAY_SIZE(strengths); i++) {
1717 if (strengths[i] > ecc->strength)
1718 break;
1719 }
1720
1721 if (!i)
1722 ecc->strength = 0;
1723 else
1724 ecc->strength = strengths[i - 1];
1725 }
1726
Dan Carpenter40297e72016-06-24 15:24:03 +03001727 if (ecc->size != 512 && ecc->size != 1024)
1728 return -EINVAL;
1729
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001730 data = kzalloc(sizeof(*data), GFP_KERNEL);
1731 if (!data)
1732 return -ENOMEM;
1733
Boris Brezillon872164e2016-06-06 13:59:12 +02001734 /* Prefer 1k ECC chunk over 512 ones */
1735 if (ecc->size == 512 && mtd->writesize > 512) {
1736 ecc->size = 1024;
1737 ecc->strength *= 2;
1738 }
1739
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001740 /* Add ECC info retrieval from DT */
1741 for (i = 0; i < ARRAY_SIZE(strengths); i++) {
Miquel Raynalf4c6cd12018-01-24 23:49:31 +01001742 if (ecc->strength <= strengths[i]) {
1743 /*
1744 * Update ecc->strength value with the actual strength
1745 * that will be used by the ECC engine.
1746 */
1747 ecc->strength = strengths[i];
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001748 break;
Miquel Raynalf4c6cd12018-01-24 23:49:31 +01001749 }
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001750 }
1751
1752 if (i >= ARRAY_SIZE(strengths)) {
1753 dev_err(nfc->dev, "unsupported strength\n");
1754 ret = -ENOTSUPP;
1755 goto err;
1756 }
1757
1758 data->mode = i;
1759
1760 /* HW ECC always request ECC bytes for 1024 bytes blocks */
1761 ecc->bytes = DIV_ROUND_UP(ecc->strength * fls(8 * 1024), 8);
1762
1763 /* HW ECC always work with even numbers of ECC bytes */
1764 ecc->bytes = ALIGN(ecc->bytes, 2);
1765
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001766 nsectors = mtd->writesize / ecc->size;
1767
1768 if (mtd->oobsize < ((ecc->bytes + 4) * nsectors)) {
1769 ret = -EINVAL;
1770 goto err;
1771 }
1772
Boris Brezillon15d6f112018-03-21 09:36:18 +01001773 ecc->read_oob = sunxi_nfc_hw_ecc_read_oob;
1774 ecc->write_oob = sunxi_nfc_hw_ecc_write_oob;
Boris Brezillonc66811e2016-02-03 20:05:13 +01001775 mtd_set_ooblayout(mtd, &sunxi_nand_ooblayout_ops);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001776 ecc->priv = data;
1777
Boris Brezillon614049a2016-04-15 15:10:30 +02001778 if (nfc->dmac) {
1779 ecc->read_page = sunxi_nfc_hw_ecc_read_page_dma;
1780 ecc->read_subpage = sunxi_nfc_hw_ecc_read_subpage_dma;
1781 ecc->write_page = sunxi_nfc_hw_ecc_write_page_dma;
1782 nand->options |= NAND_USE_BOUNCE_BUFFER;
1783 } else {
1784 ecc->read_page = sunxi_nfc_hw_ecc_read_page;
1785 ecc->read_subpage = sunxi_nfc_hw_ecc_read_subpage;
1786 ecc->write_page = sunxi_nfc_hw_ecc_write_page;
1787 }
1788
Boris Brezillon03b1d112016-06-06 13:59:14 +02001789 /* TODO: support DMA for raw accesses and subpage write */
1790 ecc->write_subpage = sunxi_nfc_hw_ecc_write_subpage;
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001791 ecc->read_oob_raw = nand_read_oob_std;
1792 ecc->write_oob_raw = nand_write_oob_std;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001793
1794 return 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001795
Boris Brezillon15d6f112018-03-21 09:36:18 +01001796err:
1797 kfree(data);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001798
Boris Brezillon15d6f112018-03-21 09:36:18 +01001799 return ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001800}
1801
1802static void sunxi_nand_ecc_cleanup(struct nand_ecc_ctrl *ecc)
1803{
1804 switch (ecc->mode) {
1805 case NAND_ECC_HW:
Boris Brezillon15d6f112018-03-21 09:36:18 +01001806 sunxi_nand_hw_ecc_ctrl_cleanup(ecc);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001807 break;
1808 case NAND_ECC_NONE:
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001809 default:
1810 break;
1811 }
1812}
1813
Miquel Raynal2a4d9c12018-07-20 17:15:13 +02001814static int sunxi_nand_attach_chip(struct nand_chip *nand)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001815{
Miquel Raynal2a4d9c12018-07-20 17:15:13 +02001816 struct mtd_info *mtd = nand_to_mtd(nand);
1817 struct nand_ecc_ctrl *ecc = &nand->ecc;
1818 struct device_node *np = nand_get_flash_node(nand);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001819 int ret;
1820
Miquel Raynal2a4d9c12018-07-20 17:15:13 +02001821 if (nand->bbt_options & NAND_BBT_USE_FLASH)
1822 nand->bbt_options |= NAND_BBT_NO_OOB;
1823
1824 if (nand->options & NAND_NEED_SCRAMBLING)
1825 nand->options |= NAND_NO_SUBPAGE_WRITE;
1826
1827 nand->options |= NAND_SUBPAGE_READ;
1828
Boris BREZILLONa3d22a52015-09-02 10:30:25 +02001829 if (!ecc->size) {
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001830 ecc->size = nand->ecc_step_ds;
1831 ecc->strength = nand->ecc_strength_ds;
1832 }
1833
1834 if (!ecc->size || !ecc->strength)
1835 return -EINVAL;
1836
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001837 switch (ecc->mode) {
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001838 case NAND_ECC_HW:
1839 ret = sunxi_nand_hw_ecc_ctrl_init(mtd, ecc, np);
1840 if (ret)
1841 return ret;
1842 break;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001843 case NAND_ECC_NONE:
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001844 case NAND_ECC_SOFT:
1845 break;
1846 default:
1847 return -EINVAL;
1848 }
1849
1850 return 0;
1851}
1852
Miquel Raynal2a4d9c12018-07-20 17:15:13 +02001853static const struct nand_controller_ops sunxi_nand_controller_ops = {
1854 .attach_chip = sunxi_nand_attach_chip,
1855};
1856
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001857static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
1858 struct device_node *np)
1859{
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001860 struct sunxi_nand_chip *chip;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001861 struct mtd_info *mtd;
1862 struct nand_chip *nand;
1863 int nsels;
1864 int ret;
1865 int i;
1866 u32 tmp;
1867
1868 if (!of_get_property(np, "reg", &nsels))
1869 return -EINVAL;
1870
1871 nsels /= sizeof(u32);
1872 if (!nsels) {
1873 dev_err(dev, "invalid reg property size\n");
1874 return -EINVAL;
1875 }
1876
1877 chip = devm_kzalloc(dev,
1878 sizeof(*chip) +
1879 (nsels * sizeof(struct sunxi_nand_chip_sel)),
1880 GFP_KERNEL);
1881 if (!chip) {
1882 dev_err(dev, "could not allocate chip\n");
1883 return -ENOMEM;
1884 }
1885
1886 chip->nsels = nsels;
1887 chip->selected = -1;
1888
1889 for (i = 0; i < nsels; i++) {
1890 ret = of_property_read_u32_index(np, "reg", i, &tmp);
1891 if (ret) {
1892 dev_err(dev, "could not retrieve reg property: %d\n",
1893 ret);
1894 return ret;
1895 }
1896
1897 if (tmp > NFC_MAX_CS) {
1898 dev_err(dev,
1899 "invalid reg value: %u (max CS = 7)\n",
1900 tmp);
1901 return -EINVAL;
1902 }
1903
1904 if (test_and_set_bit(tmp, &nfc->assigned_cs)) {
1905 dev_err(dev, "CS %d already assigned\n", tmp);
1906 return -EINVAL;
1907 }
1908
1909 chip->sels[i].cs = tmp;
1910
1911 if (!of_property_read_u32_index(np, "allwinner,rb", i, &tmp) &&
Boris Brezillonddd5ed32018-03-27 09:06:14 +02001912 tmp < 2)
1913 chip->sels[i].rb = tmp;
1914 else
1915 chip->sels[i].rb = -1;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001916 }
1917
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001918 nand = &chip->nand;
1919 /* Default tR value specified in the ONFI spec (chapter 4.15.1) */
1920 nand->chip_delay = 200;
1921 nand->controller = &nfc->controller;
Miquel Raynal2a4d9c12018-07-20 17:15:13 +02001922 nand->controller->ops = &sunxi_nand_controller_ops;
1923
Boris BREZILLONa3d22a52015-09-02 10:30:25 +02001924 /*
1925 * Set the ECC mode to the default value in case nothing is specified
1926 * in the DT.
1927 */
1928 nand->ecc.mode = NAND_ECC_HW;
Brian Norris63752192015-10-30 20:33:23 -07001929 nand_set_flash_node(nand, np);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001930 nand->select_chip = sunxi_nfc_select_chip;
1931 nand->cmd_ctrl = sunxi_nfc_cmd_ctrl;
1932 nand->read_buf = sunxi_nfc_read_buf;
1933 nand->write_buf = sunxi_nfc_write_buf;
1934 nand->read_byte = sunxi_nfc_read_byte;
Sascha Hauer907f45f2016-09-15 10:32:51 +02001935 nand->setup_data_interface = sunxi_nfc_setup_data_interface;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001936
Boris BREZILLON32e9f2d2015-12-10 09:00:26 +01001937 mtd = nand_to_mtd(nand);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001938 mtd->dev.parent = dev;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001939
Boris Brezillon00ad3782018-09-06 14:05:14 +02001940 ret = nand_scan(nand, nsels);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001941 if (ret)
1942 return ret;
1943
Brian Norrisa61ae812015-10-30 20:33:25 -07001944 ret = mtd_device_register(mtd, NULL, 0);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001945 if (ret) {
1946 dev_err(dev, "failed to register mtd device: %d\n", ret);
Boris Brezillon59ac2762018-09-06 14:05:15 +02001947 nand_release(nand);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001948 return ret;
1949 }
1950
1951 list_add_tail(&chip->node, &nfc->chips);
1952
1953 return 0;
1954}
1955
1956static int sunxi_nand_chips_init(struct device *dev, struct sunxi_nfc *nfc)
1957{
1958 struct device_node *np = dev->of_node;
1959 struct device_node *nand_np;
1960 int nchips = of_get_child_count(np);
1961 int ret;
1962
1963 if (nchips > 8) {
1964 dev_err(dev, "too many NAND chips: %d (max = 8)\n", nchips);
1965 return -EINVAL;
1966 }
1967
1968 for_each_child_of_node(np, nand_np) {
1969 ret = sunxi_nand_chip_init(dev, nfc, nand_np);
Julia Lawalla81c0f02015-11-18 23:04:12 +01001970 if (ret) {
1971 of_node_put(nand_np);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001972 return ret;
Julia Lawalla81c0f02015-11-18 23:04:12 +01001973 }
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001974 }
1975
1976 return 0;
1977}
1978
1979static void sunxi_nand_chips_cleanup(struct sunxi_nfc *nfc)
1980{
1981 struct sunxi_nand_chip *chip;
1982
1983 while (!list_empty(&nfc->chips)) {
1984 chip = list_first_entry(&nfc->chips, struct sunxi_nand_chip,
1985 node);
Boris Brezillon59ac2762018-09-06 14:05:15 +02001986 nand_release(&chip->nand);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001987 sunxi_nand_ecc_cleanup(&chip->nand.ecc);
Boris BREZILLON8e375cc2015-09-13 18:14:43 +02001988 list_del(&chip->node);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001989 }
1990}
1991
1992static int sunxi_nfc_probe(struct platform_device *pdev)
1993{
1994 struct device *dev = &pdev->dev;
1995 struct resource *r;
1996 struct sunxi_nfc *nfc;
1997 int irq;
1998 int ret;
1999
2000 nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
2001 if (!nfc)
2002 return -ENOMEM;
2003
2004 nfc->dev = dev;
Miquel Raynal7da45132018-07-17 09:08:02 +02002005 nand_controller_init(&nfc->controller);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002006 INIT_LIST_HEAD(&nfc->chips);
2007
2008 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2009 nfc->regs = devm_ioremap_resource(dev, r);
2010 if (IS_ERR(nfc->regs))
2011 return PTR_ERR(nfc->regs);
2012
2013 irq = platform_get_irq(pdev, 0);
2014 if (irq < 0) {
2015 dev_err(dev, "failed to retrieve irq\n");
2016 return irq;
2017 }
2018
2019 nfc->ahb_clk = devm_clk_get(dev, "ahb");
2020 if (IS_ERR(nfc->ahb_clk)) {
2021 dev_err(dev, "failed to retrieve ahb clk\n");
2022 return PTR_ERR(nfc->ahb_clk);
2023 }
2024
2025 ret = clk_prepare_enable(nfc->ahb_clk);
2026 if (ret)
2027 return ret;
2028
2029 nfc->mod_clk = devm_clk_get(dev, "mod");
2030 if (IS_ERR(nfc->mod_clk)) {
2031 dev_err(dev, "failed to retrieve mod clk\n");
2032 ret = PTR_ERR(nfc->mod_clk);
2033 goto out_ahb_clk_unprepare;
2034 }
2035
2036 ret = clk_prepare_enable(nfc->mod_clk);
2037 if (ret)
2038 goto out_ahb_clk_unprepare;
2039
Philipp Zabelfcf59f12017-07-19 17:25:46 +02002040 nfc->reset = devm_reset_control_get_optional_exclusive(dev, "ahb");
Philipp Zabel6b244bb2017-03-15 12:31:47 +01002041 if (IS_ERR(nfc->reset)) {
Icenowy Zhengab9d6a72016-06-20 12:48:38 +08002042 ret = PTR_ERR(nfc->reset);
2043 goto out_mod_clk_unprepare;
2044 }
2045
Philipp Zabel6b244bb2017-03-15 12:31:47 +01002046 ret = reset_control_deassert(nfc->reset);
2047 if (ret) {
2048 dev_err(dev, "reset err %d\n", ret);
2049 goto out_mod_clk_unprepare;
2050 }
2051
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002052 ret = sunxi_nfc_rst(nfc);
2053 if (ret)
Icenowy Zhengab9d6a72016-06-20 12:48:38 +08002054 goto out_ahb_reset_reassert;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002055
2056 writel(0, nfc->regs + NFC_REG_INT);
2057 ret = devm_request_irq(dev, irq, sunxi_nfc_interrupt,
2058 0, "sunxi-nand", nfc);
2059 if (ret)
Icenowy Zhengab9d6a72016-06-20 12:48:38 +08002060 goto out_ahb_reset_reassert;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002061
Boris Brezillon614049a2016-04-15 15:10:30 +02002062 nfc->dmac = dma_request_slave_channel(dev, "rxtx");
2063 if (nfc->dmac) {
2064 struct dma_slave_config dmac_cfg = { };
2065
2066 dmac_cfg.src_addr = r->start + NFC_REG_IO_DATA;
2067 dmac_cfg.dst_addr = dmac_cfg.src_addr;
2068 dmac_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
2069 dmac_cfg.dst_addr_width = dmac_cfg.src_addr_width;
2070 dmac_cfg.src_maxburst = 4;
2071 dmac_cfg.dst_maxburst = 4;
2072 dmaengine_slave_config(nfc->dmac, &dmac_cfg);
2073 } else {
2074 dev_warn(dev, "failed to request rxtx DMA channel\n");
2075 }
2076
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002077 platform_set_drvdata(pdev, nfc);
2078
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002079 ret = sunxi_nand_chips_init(dev, nfc);
2080 if (ret) {
2081 dev_err(dev, "failed to init nand chips\n");
Boris Brezillon614049a2016-04-15 15:10:30 +02002082 goto out_release_dmac;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002083 }
2084
2085 return 0;
2086
Boris Brezillon614049a2016-04-15 15:10:30 +02002087out_release_dmac:
2088 if (nfc->dmac)
2089 dma_release_channel(nfc->dmac);
Icenowy Zhengab9d6a72016-06-20 12:48:38 +08002090out_ahb_reset_reassert:
Philipp Zabel6b244bb2017-03-15 12:31:47 +01002091 reset_control_assert(nfc->reset);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002092out_mod_clk_unprepare:
2093 clk_disable_unprepare(nfc->mod_clk);
2094out_ahb_clk_unprepare:
2095 clk_disable_unprepare(nfc->ahb_clk);
2096
2097 return ret;
2098}
2099
2100static int sunxi_nfc_remove(struct platform_device *pdev)
2101{
2102 struct sunxi_nfc *nfc = platform_get_drvdata(pdev);
2103
2104 sunxi_nand_chips_cleanup(nfc);
Icenowy Zhengab9d6a72016-06-20 12:48:38 +08002105
Philipp Zabel6b244bb2017-03-15 12:31:47 +01002106 reset_control_assert(nfc->reset);
Icenowy Zhengab9d6a72016-06-20 12:48:38 +08002107
Boris Brezillon614049a2016-04-15 15:10:30 +02002108 if (nfc->dmac)
2109 dma_release_channel(nfc->dmac);
Boris Brezillondd26a452016-03-04 18:26:40 +01002110 clk_disable_unprepare(nfc->mod_clk);
2111 clk_disable_unprepare(nfc->ahb_clk);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002112
2113 return 0;
2114}
2115
2116static const struct of_device_id sunxi_nfc_ids[] = {
2117 { .compatible = "allwinner,sun4i-a10-nand" },
2118 { /* sentinel */ }
2119};
2120MODULE_DEVICE_TABLE(of, sunxi_nfc_ids);
2121
2122static struct platform_driver sunxi_nfc_driver = {
2123 .driver = {
2124 .name = "sunxi_nand",
2125 .of_match_table = sunxi_nfc_ids,
2126 },
2127 .probe = sunxi_nfc_probe,
2128 .remove = sunxi_nfc_remove,
2129};
2130module_platform_driver(sunxi_nfc_driver);
2131
2132MODULE_LICENSE("GPL v2");
2133MODULE_AUTHOR("Boris BREZILLON");
2134MODULE_DESCRIPTION("Allwinner NAND Flash Controller driver");
2135MODULE_ALIAS("platform:sunxi_nand");