blob: 07f3ff9a28f23b3044b4fdb73a5152e1d0723679 [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>
32#include <linux/of_gpio.h>
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020033#include <linux/mtd/mtd.h>
Boris Brezillond4092d72017-08-04 17:29:10 +020034#include <linux/mtd/rawnand.h>
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020035#include <linux/mtd/partitions.h>
36#include <linux/clk.h>
37#include <linux/delay.h>
38#include <linux/dmaengine.h>
39#include <linux/gpio.h>
40#include <linux/interrupt.h>
Boris Brezillon166f08c2016-03-07 15:25:17 +010041#include <linux/iopoll.h>
Icenowy Zhengab9d6a72016-06-20 12:48:38 +080042#include <linux/reset.h>
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020043
44#define NFC_REG_CTL 0x0000
45#define NFC_REG_ST 0x0004
46#define NFC_REG_INT 0x0008
47#define NFC_REG_TIMING_CTL 0x000C
48#define NFC_REG_TIMING_CFG 0x0010
49#define NFC_REG_ADDR_LOW 0x0014
50#define NFC_REG_ADDR_HIGH 0x0018
51#define NFC_REG_SECTOR_NUM 0x001C
52#define NFC_REG_CNT 0x0020
53#define NFC_REG_CMD 0x0024
54#define NFC_REG_RCMD_SET 0x0028
55#define NFC_REG_WCMD_SET 0x002C
56#define NFC_REG_IO_DATA 0x0030
57#define NFC_REG_ECC_CTL 0x0034
58#define NFC_REG_ECC_ST 0x0038
59#define NFC_REG_DEBUG 0x003C
Boris BREZILLONb6a02c02015-09-16 09:46:36 +020060#define NFC_REG_ECC_ERR_CNT(x) ((0x0040 + (x)) & ~0x3)
61#define NFC_REG_USER_DATA(x) (0x0050 + ((x) * 4))
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020062#define NFC_REG_SPARE_AREA 0x00A0
Boris BREZILLON4be4e032015-12-02 12:01:07 +010063#define NFC_REG_PAT_ID 0x00A4
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020064#define NFC_RAM0_BASE 0x0400
65#define NFC_RAM1_BASE 0x0800
66
67/* define bit use in NFC_CTL */
68#define NFC_EN BIT(0)
69#define NFC_RESET BIT(1)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +020070#define NFC_BUS_WIDTH_MSK BIT(2)
71#define NFC_BUS_WIDTH_8 (0 << 2)
72#define NFC_BUS_WIDTH_16 (1 << 2)
73#define NFC_RB_SEL_MSK BIT(3)
74#define NFC_RB_SEL(x) ((x) << 3)
75#define NFC_CE_SEL_MSK GENMASK(26, 24)
76#define NFC_CE_SEL(x) ((x) << 24)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020077#define NFC_CE_CTL BIT(6)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +020078#define NFC_PAGE_SHIFT_MSK GENMASK(11, 8)
79#define NFC_PAGE_SHIFT(x) (((x) < 10 ? 0 : (x) - 10) << 8)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020080#define NFC_SAM BIT(12)
81#define NFC_RAM_METHOD BIT(14)
82#define NFC_DEBUG_CTL BIT(31)
83
84/* define bit use in NFC_ST */
85#define NFC_RB_B2R BIT(0)
86#define NFC_CMD_INT_FLAG BIT(1)
87#define NFC_DMA_INT_FLAG BIT(2)
88#define NFC_CMD_FIFO_STATUS BIT(3)
89#define NFC_STA BIT(4)
90#define NFC_NATCH_INT_FLAG BIT(5)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +020091#define NFC_RB_STATE(x) BIT(x + 8)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020092
93/* define bit use in NFC_INT */
94#define NFC_B2R_INT_ENABLE BIT(0)
95#define NFC_CMD_INT_ENABLE BIT(1)
96#define NFC_DMA_INT_ENABLE BIT(2)
97#define NFC_INT_MASK (NFC_B2R_INT_ENABLE | \
98 NFC_CMD_INT_ENABLE | \
99 NFC_DMA_INT_ENABLE)
100
Roy Splietd052e502015-06-26 11:00:11 +0200101/* define bit use in NFC_TIMING_CTL */
102#define NFC_TIMING_CTL_EDO BIT(8)
103
Roy Spliet9c618292015-06-26 11:00:10 +0200104/* define NFC_TIMING_CFG register layout */
105#define NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD) \
106 (((tWB) & 0x3) | (((tADL) & 0x3) << 2) | \
107 (((tWHR) & 0x3) << 4) | (((tRHW) & 0x3) << 6) | \
108 (((tCAD) & 0x7) << 8))
109
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200110/* define bit use in NFC_CMD */
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200111#define NFC_CMD_LOW_BYTE_MSK GENMASK(7, 0)
112#define NFC_CMD_HIGH_BYTE_MSK GENMASK(15, 8)
113#define NFC_CMD(x) (x)
114#define NFC_ADR_NUM_MSK GENMASK(18, 16)
115#define NFC_ADR_NUM(x) (((x) - 1) << 16)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200116#define NFC_SEND_ADR BIT(19)
117#define NFC_ACCESS_DIR BIT(20)
118#define NFC_DATA_TRANS BIT(21)
119#define NFC_SEND_CMD1 BIT(22)
120#define NFC_WAIT_FLAG BIT(23)
121#define NFC_SEND_CMD2 BIT(24)
122#define NFC_SEQ BIT(25)
123#define NFC_DATA_SWAP_METHOD BIT(26)
124#define NFC_ROW_AUTO_INC BIT(27)
125#define NFC_SEND_CMD3 BIT(28)
126#define NFC_SEND_CMD4 BIT(29)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200127#define NFC_CMD_TYPE_MSK GENMASK(31, 30)
128#define NFC_NORMAL_OP (0 << 30)
129#define NFC_ECC_OP (1 << 30)
Boris Brezilloncf3e3fd2018-07-09 22:09:31 +0200130#define NFC_PAGE_OP (2U << 30)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200131
132/* define bit use in NFC_RCMD_SET */
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200133#define NFC_READ_CMD_MSK GENMASK(7, 0)
134#define NFC_RND_READ_CMD0_MSK GENMASK(15, 8)
135#define NFC_RND_READ_CMD1_MSK GENMASK(23, 16)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200136
137/* define bit use in NFC_WCMD_SET */
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200138#define NFC_PROGRAM_CMD_MSK GENMASK(7, 0)
139#define NFC_RND_WRITE_CMD_MSK GENMASK(15, 8)
140#define NFC_READ_CMD0_MSK GENMASK(23, 16)
141#define NFC_READ_CMD1_MSK GENMASK(31, 24)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200142
143/* define bit use in NFC_ECC_CTL */
144#define NFC_ECC_EN BIT(0)
145#define NFC_ECC_PIPELINE BIT(3)
146#define NFC_ECC_EXCEPTION BIT(4)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200147#define NFC_ECC_BLOCK_SIZE_MSK BIT(5)
Boris Brezillonf59dab82016-10-20 10:12:42 +0200148#define NFC_ECC_BLOCK_512 BIT(5)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200149#define NFC_RANDOM_EN BIT(9)
150#define NFC_RANDOM_DIRECTION BIT(10)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200151#define NFC_ECC_MODE_MSK GENMASK(15, 12)
152#define NFC_ECC_MODE(x) ((x) << 12)
153#define NFC_RANDOM_SEED_MSK GENMASK(30, 16)
154#define NFC_RANDOM_SEED(x) ((x) << 16)
155
156/* define bit use in NFC_ECC_ST */
157#define NFC_ECC_ERR(x) BIT(x)
Boris Brezillon614049a2016-04-15 15:10:30 +0200158#define NFC_ECC_ERR_MSK GENMASK(15, 0)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200159#define NFC_ECC_PAT_FOUND(x) BIT(x + 16)
Boris Brezillonf8b04742016-03-04 17:25:08 +0100160#define NFC_ECC_ERR_CNT(b, x) (((x) >> (((b) % 4) * 8)) & 0xff)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200161
162#define NFC_DEFAULT_TIMEOUT_MS 1000
163
164#define NFC_SRAM_SIZE 1024
165
166#define NFC_MAX_CS 7
167
168/*
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200169 * Chip Select structure: stores information related to NAND Chip Select
170 *
171 * @cs: the NAND CS id used to communicate with a NAND Chip
Boris Brezillonddd5ed32018-03-27 09:06:14 +0200172 * @rb: the Ready/Busy pin ID. -1 means no R/B pin connected to the
173 * NFC
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200174 */
175struct sunxi_nand_chip_sel {
176 u8 cs;
Boris Brezillonddd5ed32018-03-27 09:06:14 +0200177 s8 rb;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200178};
179
180/*
181 * sunxi HW ECC infos: stores information related to HW ECC support
182 *
183 * @mode: the sunxi ECC mode field deduced from ECC requirements
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200184 */
185struct sunxi_nand_hw_ecc {
186 int mode;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200187};
188
189/*
190 * NAND chip structure: stores NAND chip device related information
191 *
192 * @node: used to store NAND chips into a list
193 * @nand: base NAND chip structure
194 * @mtd: base MTD structure
195 * @clk_rate: clk_rate required for this NAND chip
Roy Spliet9c618292015-06-26 11:00:10 +0200196 * @timing_cfg TIMING_CFG register value for this NAND chip
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200197 * @selected: current active CS
198 * @nsels: number of CS lines required by the NAND chip
199 * @sels: array of CS lines descriptions
200 */
201struct sunxi_nand_chip {
202 struct list_head node;
203 struct nand_chip nand;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200204 unsigned long clk_rate;
Roy Spliet9c618292015-06-26 11:00:10 +0200205 u32 timing_cfg;
Roy Splietd052e502015-06-26 11:00:11 +0200206 u32 timing_ctl;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200207 int selected;
Boris Brezillone9aa6712015-09-16 09:05:31 +0200208 int addr_cycles;
209 u32 addr[2];
210 int cmd_cycles;
211 u8 cmd[2];
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200212 int nsels;
213 struct sunxi_nand_chip_sel sels[0];
214};
215
216static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
217{
218 return container_of(nand, struct sunxi_nand_chip, nand);
219}
220
221/*
222 * NAND Controller structure: stores sunxi NAND controller information
223 *
224 * @controller: base controller structure
225 * @dev: parent device (used to print error messages)
226 * @regs: NAND controller registers
227 * @ahb_clk: NAND Controller AHB clock
228 * @mod_clk: NAND Controller mod clock
229 * @assigned_cs: bitmask describing already assigned CS lines
230 * @clk_rate: NAND controller current clock rate
231 * @chips: a list containing all the NAND chips attached to
232 * this NAND controller
233 * @complete: a completion object used to wait for NAND
234 * controller events
235 */
236struct sunxi_nfc {
Miquel Raynal7da45132018-07-17 09:08:02 +0200237 struct nand_controller controller;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200238 struct device *dev;
239 void __iomem *regs;
240 struct clk *ahb_clk;
241 struct clk *mod_clk;
Icenowy Zhengab9d6a72016-06-20 12:48:38 +0800242 struct reset_control *reset;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200243 unsigned long assigned_cs;
244 unsigned long clk_rate;
245 struct list_head chips;
246 struct completion complete;
Boris Brezillon614049a2016-04-15 15:10:30 +0200247 struct dma_chan *dmac;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200248};
249
Miquel Raynal7da45132018-07-17 09:08:02 +0200250static inline struct sunxi_nfc *to_sunxi_nfc(struct nand_controller *ctrl)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200251{
252 return container_of(ctrl, struct sunxi_nfc, controller);
253}
254
255static irqreturn_t sunxi_nfc_interrupt(int irq, void *dev_id)
256{
257 struct sunxi_nfc *nfc = dev_id;
258 u32 st = readl(nfc->regs + NFC_REG_ST);
259 u32 ien = readl(nfc->regs + NFC_REG_INT);
260
261 if (!(ien & st))
262 return IRQ_NONE;
263
264 if ((ien & st) == ien)
265 complete(&nfc->complete);
266
267 writel(st & NFC_INT_MASK, nfc->regs + NFC_REG_ST);
268 writel(~st & ien & NFC_INT_MASK, nfc->regs + NFC_REG_INT);
269
270 return IRQ_HANDLED;
271}
272
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100273static int sunxi_nfc_wait_events(struct sunxi_nfc *nfc, u32 events,
274 bool use_polling, unsigned int timeout_ms)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200275{
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100276 int ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200277
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100278 if (events & ~NFC_INT_MASK)
279 return -EINVAL;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200280
281 if (!timeout_ms)
282 timeout_ms = NFC_DEFAULT_TIMEOUT_MS;
283
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100284 if (!use_polling) {
285 init_completion(&nfc->complete);
286
287 writel(events, nfc->regs + NFC_REG_INT);
288
289 ret = wait_for_completion_timeout(&nfc->complete,
290 msecs_to_jiffies(timeout_ms));
Boris Brezillon19649e22017-01-06 10:42:05 +0100291 if (!ret)
292 ret = -ETIMEDOUT;
293 else
294 ret = 0;
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100295
296 writel(0, nfc->regs + NFC_REG_INT);
297 } else {
298 u32 status;
299
300 ret = readl_poll_timeout(nfc->regs + NFC_REG_ST, status,
301 (status & events) == events, 1,
302 timeout_ms * 1000);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200303 }
304
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100305 writel(events & NFC_INT_MASK, nfc->regs + NFC_REG_ST);
306
307 if (ret)
308 dev_err(nfc->dev, "wait interrupt timedout\n");
309
310 return ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200311}
312
313static int sunxi_nfc_wait_cmd_fifo_empty(struct sunxi_nfc *nfc)
314{
Boris Brezillon166f08c2016-03-07 15:25:17 +0100315 u32 status;
316 int ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200317
Boris Brezillon166f08c2016-03-07 15:25:17 +0100318 ret = readl_poll_timeout(nfc->regs + NFC_REG_ST, status,
319 !(status & NFC_CMD_FIFO_STATUS), 1,
320 NFC_DEFAULT_TIMEOUT_MS * 1000);
321 if (ret)
322 dev_err(nfc->dev, "wait for empty cmd FIFO timedout\n");
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200323
Boris Brezillon166f08c2016-03-07 15:25:17 +0100324 return ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200325}
326
327static int sunxi_nfc_rst(struct sunxi_nfc *nfc)
328{
Boris Brezillon166f08c2016-03-07 15:25:17 +0100329 u32 ctl;
330 int ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200331
332 writel(0, nfc->regs + NFC_REG_ECC_CTL);
333 writel(NFC_RESET, nfc->regs + NFC_REG_CTL);
334
Boris Brezillon166f08c2016-03-07 15:25:17 +0100335 ret = readl_poll_timeout(nfc->regs + NFC_REG_CTL, ctl,
336 !(ctl & NFC_RESET), 1,
337 NFC_DEFAULT_TIMEOUT_MS * 1000);
338 if (ret)
339 dev_err(nfc->dev, "wait for NAND controller reset timedout\n");
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200340
Boris Brezillon166f08c2016-03-07 15:25:17 +0100341 return ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200342}
343
Boris Brezillon614049a2016-04-15 15:10:30 +0200344static int sunxi_nfc_dma_op_prepare(struct mtd_info *mtd, const void *buf,
345 int chunksize, int nchunks,
346 enum dma_data_direction ddir,
347 struct scatterlist *sg)
348{
349 struct nand_chip *nand = mtd_to_nand(mtd);
350 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
351 struct dma_async_tx_descriptor *dmad;
352 enum dma_transfer_direction tdir;
353 dma_cookie_t dmat;
354 int ret;
355
356 if (ddir == DMA_FROM_DEVICE)
357 tdir = DMA_DEV_TO_MEM;
358 else
359 tdir = DMA_MEM_TO_DEV;
360
361 sg_init_one(sg, buf, nchunks * chunksize);
362 ret = dma_map_sg(nfc->dev, sg, 1, ddir);
363 if (!ret)
364 return -ENOMEM;
365
366 dmad = dmaengine_prep_slave_sg(nfc->dmac, sg, 1, tdir, DMA_CTRL_ACK);
Wei Yongjun28f3d012016-06-13 14:27:18 +0000367 if (!dmad) {
368 ret = -EINVAL;
Boris Brezillon614049a2016-04-15 15:10:30 +0200369 goto err_unmap_buf;
370 }
371
372 writel(readl(nfc->regs + NFC_REG_CTL) | NFC_RAM_METHOD,
373 nfc->regs + NFC_REG_CTL);
374 writel(nchunks, nfc->regs + NFC_REG_SECTOR_NUM);
375 writel(chunksize, nfc->regs + NFC_REG_CNT);
376 dmat = dmaengine_submit(dmad);
377
378 ret = dma_submit_error(dmat);
379 if (ret)
380 goto err_clr_dma_flag;
381
382 return 0;
383
384err_clr_dma_flag:
385 writel(readl(nfc->regs + NFC_REG_CTL) & ~NFC_RAM_METHOD,
386 nfc->regs + NFC_REG_CTL);
387
388err_unmap_buf:
389 dma_unmap_sg(nfc->dev, sg, 1, ddir);
390 return ret;
391}
392
393static void sunxi_nfc_dma_op_cleanup(struct mtd_info *mtd,
394 enum dma_data_direction ddir,
395 struct scatterlist *sg)
396{
397 struct nand_chip *nand = mtd_to_nand(mtd);
398 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
399
400 dma_unmap_sg(nfc->dev, sg, 1, ddir);
401 writel(readl(nfc->regs + NFC_REG_CTL) & ~NFC_RAM_METHOD,
402 nfc->regs + NFC_REG_CTL);
403}
404
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200405static int sunxi_nfc_dev_ready(struct mtd_info *mtd)
406{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100407 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200408 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
409 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
Boris Brezillonddd5ed32018-03-27 09:06:14 +0200410 u32 mask;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200411
412 if (sunxi_nand->selected < 0)
413 return 0;
414
Boris Brezillonddd5ed32018-03-27 09:06:14 +0200415 if (sunxi_nand->sels[sunxi_nand->selected].rb < 0) {
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200416 dev_err(nfc->dev, "cannot check R/B NAND status!\n");
Boris Brezillonddd5ed32018-03-27 09:06:14 +0200417 return 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200418 }
419
Boris Brezillonddd5ed32018-03-27 09:06:14 +0200420 mask = NFC_RB_STATE(sunxi_nand->sels[sunxi_nand->selected].rb);
421
422 return !!(readl(nfc->regs + NFC_REG_ST) & mask);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200423}
424
425static void sunxi_nfc_select_chip(struct mtd_info *mtd, int chip)
426{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100427 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200428 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
429 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
430 struct sunxi_nand_chip_sel *sel;
431 u32 ctl;
432
433 if (chip > 0 && chip >= sunxi_nand->nsels)
434 return;
435
436 if (chip == sunxi_nand->selected)
437 return;
438
439 ctl = readl(nfc->regs + NFC_REG_CTL) &
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200440 ~(NFC_PAGE_SHIFT_MSK | NFC_CE_SEL_MSK | NFC_RB_SEL_MSK | NFC_EN);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200441
442 if (chip >= 0) {
443 sel = &sunxi_nand->sels[chip];
444
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200445 ctl |= NFC_CE_SEL(sel->cs) | NFC_EN |
Boris Brezillon68ffbf72016-03-04 17:29:20 +0100446 NFC_PAGE_SHIFT(nand->page_shift);
Boris Brezillonddd5ed32018-03-27 09:06:14 +0200447 if (sel->rb < 0) {
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200448 nand->dev_ready = NULL;
449 } else {
450 nand->dev_ready = sunxi_nfc_dev_ready;
Boris Brezillonddd5ed32018-03-27 09:06:14 +0200451 ctl |= NFC_RB_SEL(sel->rb);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200452 }
453
454 writel(mtd->writesize, nfc->regs + NFC_REG_SPARE_AREA);
455
456 if (nfc->clk_rate != sunxi_nand->clk_rate) {
457 clk_set_rate(nfc->mod_clk, sunxi_nand->clk_rate);
458 nfc->clk_rate = sunxi_nand->clk_rate;
459 }
460 }
461
Roy Splietd052e502015-06-26 11:00:11 +0200462 writel(sunxi_nand->timing_ctl, nfc->regs + NFC_REG_TIMING_CTL);
Roy Spliet9c618292015-06-26 11:00:10 +0200463 writel(sunxi_nand->timing_cfg, nfc->regs + NFC_REG_TIMING_CFG);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200464 writel(ctl, nfc->regs + NFC_REG_CTL);
465
466 sunxi_nand->selected = chip;
467}
468
469static void sunxi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
470{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100471 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200472 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
473 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
474 int ret;
475 int cnt;
476 int offs = 0;
477 u32 tmp;
478
479 while (len > offs) {
Boris Brezillon8de15e12017-01-06 10:42:06 +0100480 bool poll = false;
481
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200482 cnt = min(len - offs, NFC_SRAM_SIZE);
483
484 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
485 if (ret)
486 break;
487
488 writel(cnt, nfc->regs + NFC_REG_CNT);
489 tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD;
490 writel(tmp, nfc->regs + NFC_REG_CMD);
491
Boris Brezillon8de15e12017-01-06 10:42:06 +0100492 /* Arbitrary limit for polling mode */
493 if (cnt < 64)
494 poll = true;
495
496 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, poll, 0);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200497 if (ret)
498 break;
499
500 if (buf)
501 memcpy_fromio(buf + offs, nfc->regs + NFC_RAM0_BASE,
502 cnt);
503 offs += cnt;
504 }
505}
506
507static void sunxi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf,
508 int len)
509{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100510 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200511 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
512 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
513 int ret;
514 int cnt;
515 int offs = 0;
516 u32 tmp;
517
518 while (len > offs) {
Boris Brezillon8de15e12017-01-06 10:42:06 +0100519 bool poll = false;
520
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200521 cnt = min(len - offs, NFC_SRAM_SIZE);
522
523 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
524 if (ret)
525 break;
526
527 writel(cnt, nfc->regs + NFC_REG_CNT);
528 memcpy_toio(nfc->regs + NFC_RAM0_BASE, buf + offs, cnt);
529 tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD |
530 NFC_ACCESS_DIR;
531 writel(tmp, nfc->regs + NFC_REG_CMD);
532
Boris Brezillon8de15e12017-01-06 10:42:06 +0100533 /* Arbitrary limit for polling mode */
534 if (cnt < 64)
535 poll = true;
536
537 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, poll, 0);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200538 if (ret)
539 break;
540
541 offs += cnt;
542 }
543}
544
545static uint8_t sunxi_nfc_read_byte(struct mtd_info *mtd)
546{
Boris Brezillon06c8b5d2018-07-09 22:09:32 +0200547 uint8_t ret = 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200548
549 sunxi_nfc_read_buf(mtd, &ret, 1);
550
551 return ret;
552}
553
554static void sunxi_nfc_cmd_ctrl(struct mtd_info *mtd, int dat,
555 unsigned int ctrl)
556{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100557 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200558 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
559 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
560 int ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200561
Boris Brezillone9aa6712015-09-16 09:05:31 +0200562 if (dat == NAND_CMD_NONE && (ctrl & NAND_NCE) &&
563 !(ctrl & (NAND_CLE | NAND_ALE))) {
564 u32 cmd = 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200565
Boris Brezillone9aa6712015-09-16 09:05:31 +0200566 if (!sunxi_nand->addr_cycles && !sunxi_nand->cmd_cycles)
567 return;
568
569 if (sunxi_nand->cmd_cycles--)
570 cmd |= NFC_SEND_CMD1 | sunxi_nand->cmd[0];
571
572 if (sunxi_nand->cmd_cycles--) {
573 cmd |= NFC_SEND_CMD2;
574 writel(sunxi_nand->cmd[1],
575 nfc->regs + NFC_REG_RCMD_SET);
576 }
577
578 sunxi_nand->cmd_cycles = 0;
579
580 if (sunxi_nand->addr_cycles) {
581 cmd |= NFC_SEND_ADR |
582 NFC_ADR_NUM(sunxi_nand->addr_cycles);
583 writel(sunxi_nand->addr[0],
584 nfc->regs + NFC_REG_ADDR_LOW);
585 }
586
587 if (sunxi_nand->addr_cycles > 4)
588 writel(sunxi_nand->addr[1],
589 nfc->regs + NFC_REG_ADDR_HIGH);
590
Boris Brezilloncad32742017-01-06 10:42:07 +0100591 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
592 if (ret)
593 return;
594
Boris Brezillone9aa6712015-09-16 09:05:31 +0200595 writel(cmd, nfc->regs + NFC_REG_CMD);
596 sunxi_nand->addr[0] = 0;
597 sunxi_nand->addr[1] = 0;
598 sunxi_nand->addr_cycles = 0;
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100599 sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200600 }
601
Boris Brezillone9aa6712015-09-16 09:05:31 +0200602 if (ctrl & NAND_CLE) {
603 sunxi_nand->cmd[sunxi_nand->cmd_cycles++] = dat;
604 } else if (ctrl & NAND_ALE) {
605 sunxi_nand->addr[sunxi_nand->addr_cycles / 4] |=
606 dat << ((sunxi_nand->addr_cycles % 4) * 8);
607 sunxi_nand->addr_cycles++;
608 }
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200609}
610
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100611/* These seed values have been extracted from Allwinner's BSP */
612static const u16 sunxi_nfc_randomizer_page_seeds[] = {
613 0x2b75, 0x0bd0, 0x5ca3, 0x62d1, 0x1c93, 0x07e9, 0x2162, 0x3a72,
614 0x0d67, 0x67f9, 0x1be7, 0x077d, 0x032f, 0x0dac, 0x2716, 0x2436,
615 0x7922, 0x1510, 0x3860, 0x5287, 0x480f, 0x4252, 0x1789, 0x5a2d,
616 0x2a49, 0x5e10, 0x437f, 0x4b4e, 0x2f45, 0x216e, 0x5cb7, 0x7130,
617 0x2a3f, 0x60e4, 0x4dc9, 0x0ef0, 0x0f52, 0x1bb9, 0x6211, 0x7a56,
618 0x226d, 0x4ea7, 0x6f36, 0x3692, 0x38bf, 0x0c62, 0x05eb, 0x4c55,
619 0x60f4, 0x728c, 0x3b6f, 0x2037, 0x7f69, 0x0936, 0x651a, 0x4ceb,
620 0x6218, 0x79f3, 0x383f, 0x18d9, 0x4f05, 0x5c82, 0x2912, 0x6f17,
621 0x6856, 0x5938, 0x1007, 0x61ab, 0x3e7f, 0x57c2, 0x542f, 0x4f62,
622 0x7454, 0x2eac, 0x7739, 0x42d4, 0x2f90, 0x435a, 0x2e52, 0x2064,
623 0x637c, 0x66ad, 0x2c90, 0x0bad, 0x759c, 0x0029, 0x0986, 0x7126,
624 0x1ca7, 0x1605, 0x386a, 0x27f5, 0x1380, 0x6d75, 0x24c3, 0x0f8e,
625 0x2b7a, 0x1418, 0x1fd1, 0x7dc1, 0x2d8e, 0x43af, 0x2267, 0x7da3,
626 0x4e3d, 0x1338, 0x50db, 0x454d, 0x764d, 0x40a3, 0x42e6, 0x262b,
627 0x2d2e, 0x1aea, 0x2e17, 0x173d, 0x3a6e, 0x71bf, 0x25f9, 0x0a5d,
628 0x7c57, 0x0fbe, 0x46ce, 0x4939, 0x6b17, 0x37bb, 0x3e91, 0x76db,
629};
630
631/*
632 * sunxi_nfc_randomizer_ecc512_seeds and sunxi_nfc_randomizer_ecc1024_seeds
633 * have been generated using
634 * sunxi_nfc_randomizer_step(seed, (step_size * 8) + 15), which is what
635 * the randomizer engine does internally before de/scrambling OOB data.
636 *
637 * Those tables are statically defined to avoid calculating randomizer state
638 * at runtime.
639 */
640static const u16 sunxi_nfc_randomizer_ecc512_seeds[] = {
641 0x3346, 0x367f, 0x1f18, 0x769a, 0x4f64, 0x068c, 0x2ef1, 0x6b64,
642 0x28a9, 0x15d7, 0x30f8, 0x3659, 0x53db, 0x7c5f, 0x71d4, 0x4409,
643 0x26eb, 0x03cc, 0x655d, 0x47d4, 0x4daa, 0x0877, 0x712d, 0x3617,
644 0x3264, 0x49aa, 0x7f9e, 0x588e, 0x4fbc, 0x7176, 0x7f91, 0x6c6d,
645 0x4b95, 0x5fb7, 0x3844, 0x4037, 0x0184, 0x081b, 0x0ee8, 0x5b91,
646 0x293d, 0x1f71, 0x0e6f, 0x402b, 0x5122, 0x1e52, 0x22be, 0x3d2d,
647 0x75bc, 0x7c60, 0x6291, 0x1a2f, 0x61d4, 0x74aa, 0x4140, 0x29ab,
648 0x472d, 0x2852, 0x017e, 0x15e8, 0x5ec2, 0x17cf, 0x7d0f, 0x06b8,
649 0x117a, 0x6b94, 0x789b, 0x3126, 0x6ac5, 0x5be7, 0x150f, 0x51f8,
650 0x7889, 0x0aa5, 0x663d, 0x77e8, 0x0b87, 0x3dcb, 0x360d, 0x218b,
651 0x512f, 0x7dc9, 0x6a4d, 0x630a, 0x3547, 0x1dd2, 0x5aea, 0x69a5,
652 0x7bfa, 0x5e4f, 0x1519, 0x6430, 0x3a0e, 0x5eb3, 0x5425, 0x0c7a,
653 0x5540, 0x3670, 0x63c1, 0x31e9, 0x5a39, 0x2de7, 0x5979, 0x2891,
654 0x1562, 0x014b, 0x5b05, 0x2756, 0x5a34, 0x13aa, 0x6cb5, 0x2c36,
655 0x5e72, 0x1306, 0x0861, 0x15ef, 0x1ee8, 0x5a37, 0x7ac4, 0x45dd,
656 0x44c4, 0x7266, 0x2f41, 0x3ccc, 0x045e, 0x7d40, 0x7c66, 0x0fa0,
657};
658
659static const u16 sunxi_nfc_randomizer_ecc1024_seeds[] = {
660 0x2cf5, 0x35f1, 0x63a4, 0x5274, 0x2bd2, 0x778b, 0x7285, 0x32b6,
661 0x6a5c, 0x70d6, 0x757d, 0x6769, 0x5375, 0x1e81, 0x0cf3, 0x3982,
662 0x6787, 0x042a, 0x6c49, 0x1925, 0x56a8, 0x40a9, 0x063e, 0x7bd9,
663 0x4dbf, 0x55ec, 0x672e, 0x7334, 0x5185, 0x4d00, 0x232a, 0x7e07,
664 0x445d, 0x6b92, 0x528f, 0x4255, 0x53ba, 0x7d82, 0x2a2e, 0x3a4e,
665 0x75eb, 0x450c, 0x6844, 0x1b5d, 0x581a, 0x4cc6, 0x0379, 0x37b2,
666 0x419f, 0x0e92, 0x6b27, 0x5624, 0x01e3, 0x07c1, 0x44a5, 0x130c,
667 0x13e8, 0x5910, 0x0876, 0x60c5, 0x54e3, 0x5b7f, 0x2269, 0x509f,
668 0x7665, 0x36fd, 0x3e9a, 0x0579, 0x6295, 0x14ef, 0x0a81, 0x1bcc,
669 0x4b16, 0x64db, 0x0514, 0x4f07, 0x0591, 0x3576, 0x6853, 0x0d9e,
670 0x259f, 0x38b7, 0x64fb, 0x3094, 0x4693, 0x6ddd, 0x29bb, 0x0bc8,
671 0x3f47, 0x490e, 0x0c0e, 0x7933, 0x3c9e, 0x5840, 0x398d, 0x3e68,
672 0x4af1, 0x71f5, 0x57cf, 0x1121, 0x64eb, 0x3579, 0x15ac, 0x584d,
673 0x5f2a, 0x47e2, 0x6528, 0x6eac, 0x196e, 0x6b96, 0x0450, 0x0179,
674 0x609c, 0x06e1, 0x4626, 0x42c7, 0x273e, 0x486f, 0x0705, 0x1601,
675 0x145b, 0x407e, 0x062b, 0x57a5, 0x53f9, 0x5659, 0x4410, 0x3ccd,
676};
677
678static u16 sunxi_nfc_randomizer_step(u16 state, int count)
679{
680 state &= 0x7fff;
681
682 /*
683 * This loop is just a simple implementation of a Fibonacci LFSR using
684 * the x16 + x15 + 1 polynomial.
685 */
686 while (count--)
687 state = ((state >> 1) |
688 (((state ^ (state >> 1)) & 1) << 14)) & 0x7fff;
689
690 return state;
691}
692
693static u16 sunxi_nfc_randomizer_state(struct mtd_info *mtd, int page, bool ecc)
694{
695 const u16 *seeds = sunxi_nfc_randomizer_page_seeds;
Brian Norris46c135c2016-01-22 18:57:13 -0800696 int mod = mtd_div_by_ws(mtd->erasesize, mtd);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100697
698 if (mod > ARRAY_SIZE(sunxi_nfc_randomizer_page_seeds))
699 mod = ARRAY_SIZE(sunxi_nfc_randomizer_page_seeds);
700
701 if (ecc) {
702 if (mtd->ecc_step_size == 512)
703 seeds = sunxi_nfc_randomizer_ecc512_seeds;
704 else
705 seeds = sunxi_nfc_randomizer_ecc1024_seeds;
706 }
707
708 return seeds[page % mod];
709}
710
711static void sunxi_nfc_randomizer_config(struct mtd_info *mtd,
712 int page, bool ecc)
713{
Boris BREZILLONf671a1f2016-03-05 00:21:20 +0100714 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100715 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
716 u32 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
717 u16 state;
718
719 if (!(nand->options & NAND_NEED_SCRAMBLING))
720 return;
721
722 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
723 state = sunxi_nfc_randomizer_state(mtd, page, ecc);
724 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_RANDOM_SEED_MSK;
725 writel(ecc_ctl | NFC_RANDOM_SEED(state), nfc->regs + NFC_REG_ECC_CTL);
726}
727
728static void sunxi_nfc_randomizer_enable(struct mtd_info *mtd)
729{
Boris BREZILLONf671a1f2016-03-05 00:21:20 +0100730 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100731 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
732
733 if (!(nand->options & NAND_NEED_SCRAMBLING))
734 return;
735
736 writel(readl(nfc->regs + NFC_REG_ECC_CTL) | NFC_RANDOM_EN,
737 nfc->regs + NFC_REG_ECC_CTL);
738}
739
740static void sunxi_nfc_randomizer_disable(struct mtd_info *mtd)
741{
Boris BREZILLONf671a1f2016-03-05 00:21:20 +0100742 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100743 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
744
745 if (!(nand->options & NAND_NEED_SCRAMBLING))
746 return;
747
748 writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_RANDOM_EN,
749 nfc->regs + NFC_REG_ECC_CTL);
750}
751
752static void sunxi_nfc_randomize_bbm(struct mtd_info *mtd, int page, u8 *bbm)
753{
754 u16 state = sunxi_nfc_randomizer_state(mtd, page, true);
755
756 bbm[0] ^= state;
757 bbm[1] ^= sunxi_nfc_randomizer_step(state, 8);
758}
759
760static void sunxi_nfc_randomizer_write_buf(struct mtd_info *mtd,
761 const uint8_t *buf, int len,
762 bool ecc, int page)
763{
764 sunxi_nfc_randomizer_config(mtd, page, ecc);
765 sunxi_nfc_randomizer_enable(mtd);
766 sunxi_nfc_write_buf(mtd, buf, len);
767 sunxi_nfc_randomizer_disable(mtd);
768}
769
770static void sunxi_nfc_randomizer_read_buf(struct mtd_info *mtd, uint8_t *buf,
771 int len, bool ecc, int page)
772{
773 sunxi_nfc_randomizer_config(mtd, page, ecc);
774 sunxi_nfc_randomizer_enable(mtd);
775 sunxi_nfc_read_buf(mtd, buf, len);
776 sunxi_nfc_randomizer_disable(mtd);
777}
778
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200779static void sunxi_nfc_hw_ecc_enable(struct mtd_info *mtd)
780{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100781 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200782 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
783 struct sunxi_nand_hw_ecc *data = nand->ecc.priv;
784 u32 ecc_ctl;
785
786 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
787 ecc_ctl &= ~(NFC_ECC_MODE_MSK | NFC_ECC_PIPELINE |
788 NFC_ECC_BLOCK_SIZE_MSK);
Boris Brezillon336de7b2016-03-04 17:33:10 +0100789 ecc_ctl |= NFC_ECC_EN | NFC_ECC_MODE(data->mode) | NFC_ECC_EXCEPTION |
790 NFC_ECC_PIPELINE;
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200791
Boris Brezillonf59dab82016-10-20 10:12:42 +0200792 if (nand->ecc.size == 512)
793 ecc_ctl |= NFC_ECC_BLOCK_512;
794
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200795 writel(ecc_ctl, nfc->regs + NFC_REG_ECC_CTL);
796}
797
798static void sunxi_nfc_hw_ecc_disable(struct mtd_info *mtd)
799{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100800 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200801 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
802
803 writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_ECC_EN,
804 nfc->regs + NFC_REG_ECC_CTL);
805}
806
Boris BREZILLONf363e0f2015-09-30 23:45:27 +0200807static inline void sunxi_nfc_user_data_to_buf(u32 user_data, u8 *buf)
808{
809 buf[0] = user_data;
810 buf[1] = user_data >> 8;
811 buf[2] = user_data >> 16;
812 buf[3] = user_data >> 24;
813}
814
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100815static inline u32 sunxi_nfc_buf_to_user_data(const u8 *buf)
816{
817 return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
818}
819
820static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct mtd_info *mtd, u8 *oob,
821 int step, bool bbm, int page)
822{
823 struct nand_chip *nand = mtd_to_nand(mtd);
824 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
825
826 sunxi_nfc_user_data_to_buf(readl(nfc->regs + NFC_REG_USER_DATA(step)),
827 oob);
828
829 /* De-randomize the Bad Block Marker. */
830 if (bbm && (nand->options & NAND_NEED_SCRAMBLING))
831 sunxi_nfc_randomize_bbm(mtd, page, oob);
832}
833
834static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct mtd_info *mtd,
835 const u8 *oob, int step,
836 bool bbm, int page)
837{
838 struct nand_chip *nand = mtd_to_nand(mtd);
839 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
840 u8 user_data[4];
841
842 /* Randomize the Bad Block Marker. */
843 if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) {
844 memcpy(user_data, oob, sizeof(user_data));
845 sunxi_nfc_randomize_bbm(mtd, page, user_data);
846 oob = user_data;
847 }
848
849 writel(sunxi_nfc_buf_to_user_data(oob),
850 nfc->regs + NFC_REG_USER_DATA(step));
851}
852
853static void sunxi_nfc_hw_ecc_update_stats(struct mtd_info *mtd,
854 unsigned int *max_bitflips, int ret)
855{
856 if (ret < 0) {
857 mtd->ecc_stats.failed++;
858 } else {
859 mtd->ecc_stats.corrected += ret;
860 *max_bitflips = max_t(unsigned int, *max_bitflips, ret);
861 }
862}
863
864static int sunxi_nfc_hw_ecc_correct(struct mtd_info *mtd, u8 *data, u8 *oob,
Boris Brezillon614049a2016-04-15 15:10:30 +0200865 int step, u32 status, bool *erased)
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100866{
867 struct nand_chip *nand = mtd_to_nand(mtd);
868 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
869 struct nand_ecc_ctrl *ecc = &nand->ecc;
Boris Brezillon614049a2016-04-15 15:10:30 +0200870 u32 tmp;
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100871
872 *erased = false;
873
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100874 if (status & NFC_ECC_ERR(step))
875 return -EBADMSG;
876
877 if (status & NFC_ECC_PAT_FOUND(step)) {
878 u8 pattern;
879
880 if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID) & 0x1))) {
881 pattern = 0x0;
882 } else {
883 pattern = 0xff;
884 *erased = true;
885 }
886
887 if (data)
888 memset(data, pattern, ecc->size);
889
890 if (oob)
891 memset(oob, pattern, ecc->bytes + 4);
892
893 return 0;
894 }
895
896 tmp = readl(nfc->regs + NFC_REG_ECC_ERR_CNT(step));
897
898 return NFC_ECC_ERR_CNT(step, tmp);
899}
900
Boris BREZILLON913821b2015-09-30 23:45:24 +0200901static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
902 u8 *data, int data_off,
903 u8 *oob, int oob_off,
904 int *cur_off,
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100905 unsigned int *max_bitflips,
Boris Brezillon828dec12016-03-04 18:09:21 +0100906 bool bbm, bool oob_required, int page)
Boris BREZILLON913821b2015-09-30 23:45:24 +0200907{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100908 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200909 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
910 struct nand_ecc_ctrl *ecc = &nand->ecc;
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100911 int raw_mode = 0;
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100912 bool erased;
Boris BREZILLON913821b2015-09-30 23:45:24 +0200913 int ret;
914
915 if (*cur_off != data_off)
Boris Brezillon97d90da2017-11-30 18:01:29 +0100916 nand_change_read_column_op(nand, data_off, NULL, 0, false);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200917
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100918 sunxi_nfc_randomizer_read_buf(mtd, NULL, ecc->size, false, page);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200919
Boris BREZILLON74eb9ff2015-10-20 22:16:00 +0200920 if (data_off + ecc->size != oob_off)
Boris Brezillon97d90da2017-11-30 18:01:29 +0100921 nand_change_read_column_op(nand, oob_off, NULL, 0, false);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200922
923 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
924 if (ret)
925 return ret;
926
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100927 sunxi_nfc_randomizer_enable(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200928 writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP,
929 nfc->regs + NFC_REG_CMD);
930
Boris Brezillon8de15e12017-01-06 10:42:06 +0100931 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100932 sunxi_nfc_randomizer_disable(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200933 if (ret)
934 return ret;
935
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100936 *cur_off = oob_off + ecc->bytes + 4;
937
Boris Brezillon828dec12016-03-04 18:09:21 +0100938 ret = sunxi_nfc_hw_ecc_correct(mtd, data, oob_required ? oob : NULL, 0,
Boris Brezillon614049a2016-04-15 15:10:30 +0200939 readl(nfc->regs + NFC_REG_ECC_ST),
Boris Brezillon828dec12016-03-04 18:09:21 +0100940 &erased);
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100941 if (erased)
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100942 return 1;
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100943
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100944 if (ret < 0) {
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100945 /*
946 * Re-read the data with the randomizer disabled to identify
947 * bitflips in erased pages.
948 */
Boris Brezillon97d90da2017-11-30 18:01:29 +0100949 if (nand->options & NAND_NEED_SCRAMBLING)
950 nand_change_read_column_op(nand, data_off, data,
951 ecc->size, false);
952 else
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100953 memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE,
954 ecc->size);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100955
Boris Brezillon97d90da2017-11-30 18:01:29 +0100956 nand_change_read_column_op(nand, oob_off, oob, ecc->bytes + 4,
957 false);
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100958
Boris BREZILLON146b5032015-09-30 23:45:29 +0200959 ret = nand_check_erased_ecc_chunk(data, ecc->size,
960 oob, ecc->bytes + 4,
961 NULL, 0, ecc->strength);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100962 if (ret >= 0)
963 raw_mode = 1;
Boris BREZILLONf363e0f2015-09-30 23:45:27 +0200964 } else {
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100965 memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100966
Boris Brezillon828dec12016-03-04 18:09:21 +0100967 if (oob_required) {
Boris Brezillon97d90da2017-11-30 18:01:29 +0100968 nand_change_read_column_op(nand, oob_off, NULL, 0,
969 false);
Boris Brezillon828dec12016-03-04 18:09:21 +0100970 sunxi_nfc_randomizer_read_buf(mtd, oob, ecc->bytes + 4,
971 true, page);
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100972
Boris Brezillon828dec12016-03-04 18:09:21 +0100973 sunxi_nfc_hw_ecc_get_prot_oob_bytes(mtd, oob, 0,
974 bbm, page);
975 }
Boris BREZILLONf363e0f2015-09-30 23:45:27 +0200976 }
Boris BREZILLON913821b2015-09-30 23:45:24 +0200977
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100978 sunxi_nfc_hw_ecc_update_stats(mtd, max_bitflips, ret);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200979
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100980 return raw_mode;
Boris BREZILLON913821b2015-09-30 23:45:24 +0200981}
982
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200983static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd,
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100984 u8 *oob, int *cur_off,
985 bool randomize, int page)
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200986{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100987 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200988 struct nand_ecc_ctrl *ecc = &nand->ecc;
989 int offset = ((ecc->bytes + 4) * ecc->steps);
990 int len = mtd->oobsize - offset;
991
992 if (len <= 0)
993 return;
994
Boris Brezillonc4f3ef22016-03-04 18:13:10 +0100995 if (!cur_off || *cur_off != offset)
Boris Brezillon97d90da2017-11-30 18:01:29 +0100996 nand_change_read_column_op(nand, mtd->writesize, NULL, 0,
997 false);
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200998
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100999 if (!randomize)
1000 sunxi_nfc_read_buf(mtd, oob + offset, len);
1001 else
1002 sunxi_nfc_randomizer_read_buf(mtd, oob + offset, len,
1003 false, page);
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001004
Boris Brezillonc4f3ef22016-03-04 18:13:10 +01001005 if (cur_off)
1006 *cur_off = mtd->oobsize + mtd->writesize;
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001007}
1008
Boris Brezillon614049a2016-04-15 15:10:30 +02001009static int sunxi_nfc_hw_ecc_read_chunks_dma(struct mtd_info *mtd, uint8_t *buf,
1010 int oob_required, int page,
1011 int nchunks)
1012{
1013 struct nand_chip *nand = mtd_to_nand(mtd);
1014 bool randomized = nand->options & NAND_NEED_SCRAMBLING;
1015 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
1016 struct nand_ecc_ctrl *ecc = &nand->ecc;
1017 unsigned int max_bitflips = 0;
1018 int ret, i, raw_mode = 0;
1019 struct scatterlist sg;
1020 u32 status;
1021
1022 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
1023 if (ret)
1024 return ret;
1025
1026 ret = sunxi_nfc_dma_op_prepare(mtd, buf, ecc->size, nchunks,
1027 DMA_FROM_DEVICE, &sg);
1028 if (ret)
1029 return ret;
1030
1031 sunxi_nfc_hw_ecc_enable(mtd);
1032 sunxi_nfc_randomizer_config(mtd, page, false);
1033 sunxi_nfc_randomizer_enable(mtd);
1034
1035 writel((NAND_CMD_RNDOUTSTART << 16) | (NAND_CMD_RNDOUT << 8) |
1036 NAND_CMD_READSTART, nfc->regs + NFC_REG_RCMD_SET);
1037
1038 dma_async_issue_pending(nfc->dmac);
1039
1040 writel(NFC_PAGE_OP | NFC_DATA_SWAP_METHOD | NFC_DATA_TRANS,
1041 nfc->regs + NFC_REG_CMD);
1042
Boris Brezillon8de15e12017-01-06 10:42:06 +01001043 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0);
Boris Brezillon614049a2016-04-15 15:10:30 +02001044 if (ret)
1045 dmaengine_terminate_all(nfc->dmac);
1046
1047 sunxi_nfc_randomizer_disable(mtd);
1048 sunxi_nfc_hw_ecc_disable(mtd);
1049
1050 sunxi_nfc_dma_op_cleanup(mtd, DMA_FROM_DEVICE, &sg);
1051
1052 if (ret)
1053 return ret;
1054
1055 status = readl(nfc->regs + NFC_REG_ECC_ST);
1056
1057 for (i = 0; i < nchunks; i++) {
1058 int data_off = i * ecc->size;
1059 int oob_off = i * (ecc->bytes + 4);
1060 u8 *data = buf + data_off;
1061 u8 *oob = nand->oob_poi + oob_off;
1062 bool erased;
1063
1064 ret = sunxi_nfc_hw_ecc_correct(mtd, randomized ? data : NULL,
1065 oob_required ? oob : NULL,
1066 i, status, &erased);
1067
1068 /* ECC errors are handled in the second loop. */
1069 if (ret < 0)
1070 continue;
1071
1072 if (oob_required && !erased) {
1073 /* TODO: use DMA to retrieve OOB */
Boris Brezillon97d90da2017-11-30 18:01:29 +01001074 nand_change_read_column_op(nand,
1075 mtd->writesize + oob_off,
1076 oob, ecc->bytes + 4, false);
Boris Brezillon614049a2016-04-15 15:10:30 +02001077
1078 sunxi_nfc_hw_ecc_get_prot_oob_bytes(mtd, oob, i,
1079 !i, page);
1080 }
1081
1082 if (erased)
1083 raw_mode = 1;
1084
1085 sunxi_nfc_hw_ecc_update_stats(mtd, &max_bitflips, ret);
1086 }
1087
1088 if (status & NFC_ECC_ERR_MSK) {
1089 for (i = 0; i < nchunks; i++) {
1090 int data_off = i * ecc->size;
1091 int oob_off = i * (ecc->bytes + 4);
1092 u8 *data = buf + data_off;
1093 u8 *oob = nand->oob_poi + oob_off;
1094
1095 if (!(status & NFC_ECC_ERR(i)))
1096 continue;
1097
1098 /*
1099 * Re-read the data with the randomizer disabled to
1100 * identify bitflips in erased pages.
Boris Brezillon97d90da2017-11-30 18:01:29 +01001101 * TODO: use DMA to read page in raw mode
Boris Brezillon614049a2016-04-15 15:10:30 +02001102 */
Boris Brezillon97d90da2017-11-30 18:01:29 +01001103 if (randomized)
1104 nand_change_read_column_op(nand, data_off,
1105 data, ecc->size,
1106 false);
Boris Brezillon614049a2016-04-15 15:10:30 +02001107
1108 /* TODO: use DMA to retrieve OOB */
Boris Brezillon97d90da2017-11-30 18:01:29 +01001109 nand_change_read_column_op(nand,
1110 mtd->writesize + oob_off,
1111 oob, ecc->bytes + 4, false);
Boris Brezillon614049a2016-04-15 15:10:30 +02001112
1113 ret = nand_check_erased_ecc_chunk(data, ecc->size,
1114 oob, ecc->bytes + 4,
1115 NULL, 0,
1116 ecc->strength);
1117 if (ret >= 0)
1118 raw_mode = 1;
1119
1120 sunxi_nfc_hw_ecc_update_stats(mtd, &max_bitflips, ret);
1121 }
1122 }
1123
1124 if (oob_required)
1125 sunxi_nfc_hw_ecc_read_extra_oob(mtd, nand->oob_poi,
1126 NULL, !raw_mode,
1127 page);
1128
1129 return max_bitflips;
1130}
1131
Boris BREZILLON913821b2015-09-30 23:45:24 +02001132static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd,
1133 const u8 *data, int data_off,
1134 const u8 *oob, int oob_off,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001135 int *cur_off, bool bbm,
1136 int page)
Boris BREZILLON913821b2015-09-30 23:45:24 +02001137{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +01001138 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +02001139 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
1140 struct nand_ecc_ctrl *ecc = &nand->ecc;
1141 int ret;
1142
1143 if (data_off != *cur_off)
Boris Brezillon97d90da2017-11-30 18:01:29 +01001144 nand_change_write_column_op(nand, data_off, NULL, 0, false);
Boris BREZILLON913821b2015-09-30 23:45:24 +02001145
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001146 sunxi_nfc_randomizer_write_buf(mtd, data, ecc->size, false, page);
Boris BREZILLON913821b2015-09-30 23:45:24 +02001147
Boris BREZILLON74eb9ff2015-10-20 22:16:00 +02001148 if (data_off + ecc->size != oob_off)
Boris Brezillon97d90da2017-11-30 18:01:29 +01001149 nand_change_write_column_op(nand, oob_off, NULL, 0, false);
Boris BREZILLON913821b2015-09-30 23:45:24 +02001150
1151 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
1152 if (ret)
1153 return ret;
1154
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001155 sunxi_nfc_randomizer_enable(mtd);
Boris Brezilloncc6822f2016-03-04 17:56:47 +01001156 sunxi_nfc_hw_ecc_set_prot_oob_bytes(mtd, oob, 0, bbm, page);
1157
Boris BREZILLON913821b2015-09-30 23:45:24 +02001158 writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD |
1159 NFC_ACCESS_DIR | NFC_ECC_OP,
1160 nfc->regs + NFC_REG_CMD);
1161
Boris Brezillon8de15e12017-01-06 10:42:06 +01001162 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0);
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001163 sunxi_nfc_randomizer_disable(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +02001164 if (ret)
1165 return ret;
1166
1167 *cur_off = oob_off + ecc->bytes + 4;
1168
1169 return 0;
1170}
1171
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001172static void sunxi_nfc_hw_ecc_write_extra_oob(struct mtd_info *mtd,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001173 u8 *oob, int *cur_off,
1174 int page)
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001175{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +01001176 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001177 struct nand_ecc_ctrl *ecc = &nand->ecc;
1178 int offset = ((ecc->bytes + 4) * ecc->steps);
1179 int len = mtd->oobsize - offset;
1180
1181 if (len <= 0)
1182 return;
1183
Boris Brezillonc4f3ef22016-03-04 18:13:10 +01001184 if (!cur_off || *cur_off != offset)
Boris Brezillon97d90da2017-11-30 18:01:29 +01001185 nand_change_write_column_op(nand, offset + mtd->writesize,
1186 NULL, 0, false);
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001187
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001188 sunxi_nfc_randomizer_write_buf(mtd, oob + offset, len, false, page);
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001189
Boris Brezillonc4f3ef22016-03-04 18:13:10 +01001190 if (cur_off)
1191 *cur_off = mtd->oobsize + mtd->writesize;
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001192}
1193
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001194static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd,
1195 struct nand_chip *chip, uint8_t *buf,
1196 int oob_required, int page)
1197{
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001198 struct nand_ecc_ctrl *ecc = &chip->ecc;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001199 unsigned int max_bitflips = 0;
Boris BREZILLONb4625512015-09-30 23:45:25 +02001200 int ret, i, cur_off = 0;
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001201 bool raw_mode = false;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001202
Boris Brezillon25f815f2017-11-30 18:01:30 +01001203 nand_read_page_op(chip, page, 0, NULL, 0);
1204
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001205 sunxi_nfc_hw_ecc_enable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001206
1207 for (i = 0; i < ecc->steps; i++) {
Boris BREZILLONb4625512015-09-30 23:45:25 +02001208 int data_off = i * ecc->size;
1209 int oob_off = i * (ecc->bytes + 4);
1210 u8 *data = buf + data_off;
1211 u8 *oob = chip->oob_poi + oob_off;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001212
Boris BREZILLONb4625512015-09-30 23:45:25 +02001213 ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob,
1214 oob_off + mtd->writesize,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001215 &cur_off, &max_bitflips,
Boris Brezillon828dec12016-03-04 18:09:21 +01001216 !i, oob_required, page);
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001217 if (ret < 0)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001218 return ret;
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001219 else if (ret)
1220 raw_mode = true;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001221 }
1222
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001223 if (oob_required)
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001224 sunxi_nfc_hw_ecc_read_extra_oob(mtd, chip->oob_poi, &cur_off,
1225 !raw_mode, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001226
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001227 sunxi_nfc_hw_ecc_disable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001228
1229 return max_bitflips;
1230}
1231
Boris Brezillon614049a2016-04-15 15:10:30 +02001232static int sunxi_nfc_hw_ecc_read_page_dma(struct mtd_info *mtd,
1233 struct nand_chip *chip, u8 *buf,
1234 int oob_required, int page)
1235{
1236 int ret;
1237
Boris Brezillon25f815f2017-11-30 18:01:30 +01001238 nand_read_page_op(chip, page, 0, NULL, 0);
1239
Boris Brezillon614049a2016-04-15 15:10:30 +02001240 ret = sunxi_nfc_hw_ecc_read_chunks_dma(mtd, buf, oob_required, page,
1241 chip->ecc.steps);
1242 if (ret >= 0)
1243 return ret;
1244
1245 /* Fallback to PIO mode */
Boris Brezillon614049a2016-04-15 15:10:30 +02001246 return sunxi_nfc_hw_ecc_read_page(mtd, chip, buf, oob_required, page);
1247}
1248
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001249static int sunxi_nfc_hw_ecc_read_subpage(struct mtd_info *mtd,
1250 struct nand_chip *chip,
1251 u32 data_offs, u32 readlen,
1252 u8 *bufpoi, int page)
1253{
1254 struct nand_ecc_ctrl *ecc = &chip->ecc;
1255 int ret, i, cur_off = 0;
1256 unsigned int max_bitflips = 0;
1257
Boris Brezillon25f815f2017-11-30 18:01:30 +01001258 nand_read_page_op(chip, page, 0, NULL, 0);
1259
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001260 sunxi_nfc_hw_ecc_enable(mtd);
1261
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001262 for (i = data_offs / ecc->size;
1263 i < DIV_ROUND_UP(data_offs + readlen, ecc->size); i++) {
1264 int data_off = i * ecc->size;
1265 int oob_off = i * (ecc->bytes + 4);
1266 u8 *data = bufpoi + data_off;
1267 u8 *oob = chip->oob_poi + oob_off;
1268
1269 ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off,
1270 oob,
1271 oob_off + mtd->writesize,
Boris Brezillon828dec12016-03-04 18:09:21 +01001272 &cur_off, &max_bitflips, !i,
1273 false, page);
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001274 if (ret < 0)
1275 return ret;
1276 }
1277
1278 sunxi_nfc_hw_ecc_disable(mtd);
1279
1280 return max_bitflips;
1281}
1282
Boris Brezillon614049a2016-04-15 15:10:30 +02001283static int sunxi_nfc_hw_ecc_read_subpage_dma(struct mtd_info *mtd,
1284 struct nand_chip *chip,
1285 u32 data_offs, u32 readlen,
1286 u8 *buf, int page)
1287{
1288 int nchunks = DIV_ROUND_UP(data_offs + readlen, chip->ecc.size);
1289 int ret;
1290
Boris Brezillon25f815f2017-11-30 18:01:30 +01001291 nand_read_page_op(chip, page, 0, NULL, 0);
1292
Boris Brezillon614049a2016-04-15 15:10:30 +02001293 ret = sunxi_nfc_hw_ecc_read_chunks_dma(mtd, buf, false, page, nchunks);
1294 if (ret >= 0)
1295 return ret;
1296
1297 /* Fallback to PIO mode */
Boris Brezillon614049a2016-04-15 15:10:30 +02001298 return sunxi_nfc_hw_ecc_read_subpage(mtd, chip, data_offs, readlen,
1299 buf, page);
1300}
1301
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001302static int sunxi_nfc_hw_ecc_write_page(struct mtd_info *mtd,
1303 struct nand_chip *chip,
Boris BREZILLON45aaeff2015-10-13 11:22:18 +02001304 const uint8_t *buf, int oob_required,
1305 int page)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001306{
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001307 struct nand_ecc_ctrl *ecc = &chip->ecc;
Boris BREZILLONb4625512015-09-30 23:45:25 +02001308 int ret, i, cur_off = 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001309
Boris Brezillon25f815f2017-11-30 18:01:30 +01001310 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
1311
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001312 sunxi_nfc_hw_ecc_enable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001313
1314 for (i = 0; i < ecc->steps; i++) {
Boris BREZILLONb4625512015-09-30 23:45:25 +02001315 int data_off = i * ecc->size;
1316 int oob_off = i * (ecc->bytes + 4);
1317 const u8 *data = buf + data_off;
1318 const u8 *oob = chip->oob_poi + oob_off;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001319
Boris BREZILLONb4625512015-09-30 23:45:25 +02001320 ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off, oob,
1321 oob_off + mtd->writesize,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001322 &cur_off, !i, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001323 if (ret)
1324 return ret;
1325 }
1326
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001327 if (oob_required || (chip->options & NAND_NEED_SCRAMBLING))
1328 sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi,
1329 &cur_off, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001330
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001331 sunxi_nfc_hw_ecc_disable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001332
Boris Brezillon25f815f2017-11-30 18:01:30 +01001333 return nand_prog_page_end_op(chip);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001334}
1335
Boris Brezillon03b1d112016-06-06 13:59:14 +02001336static int sunxi_nfc_hw_ecc_write_subpage(struct mtd_info *mtd,
1337 struct nand_chip *chip,
1338 u32 data_offs, u32 data_len,
1339 const u8 *buf, int oob_required,
1340 int page)
1341{
1342 struct nand_ecc_ctrl *ecc = &chip->ecc;
1343 int ret, i, cur_off = 0;
1344
Boris Brezillon25f815f2017-11-30 18:01:30 +01001345 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
1346
Boris Brezillon03b1d112016-06-06 13:59:14 +02001347 sunxi_nfc_hw_ecc_enable(mtd);
1348
1349 for (i = data_offs / ecc->size;
1350 i < DIV_ROUND_UP(data_offs + data_len, ecc->size); i++) {
1351 int data_off = i * ecc->size;
1352 int oob_off = i * (ecc->bytes + 4);
1353 const u8 *data = buf + data_off;
1354 const u8 *oob = chip->oob_poi + oob_off;
1355
1356 ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off, oob,
1357 oob_off + mtd->writesize,
1358 &cur_off, !i, page);
1359 if (ret)
1360 return ret;
1361 }
1362
1363 sunxi_nfc_hw_ecc_disable(mtd);
1364
Boris Brezillon25f815f2017-11-30 18:01:30 +01001365 return nand_prog_page_end_op(chip);
Boris Brezillon03b1d112016-06-06 13:59:14 +02001366}
1367
Boris Brezillon614049a2016-04-15 15:10:30 +02001368static int sunxi_nfc_hw_ecc_write_page_dma(struct mtd_info *mtd,
1369 struct nand_chip *chip,
1370 const u8 *buf,
1371 int oob_required,
1372 int page)
1373{
1374 struct nand_chip *nand = mtd_to_nand(mtd);
1375 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
1376 struct nand_ecc_ctrl *ecc = &nand->ecc;
1377 struct scatterlist sg;
1378 int ret, i;
1379
1380 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
1381 if (ret)
1382 return ret;
1383
1384 ret = sunxi_nfc_dma_op_prepare(mtd, buf, ecc->size, ecc->steps,
1385 DMA_TO_DEVICE, &sg);
1386 if (ret)
1387 goto pio_fallback;
1388
1389 for (i = 0; i < ecc->steps; i++) {
1390 const u8 *oob = nand->oob_poi + (i * (ecc->bytes + 4));
1391
1392 sunxi_nfc_hw_ecc_set_prot_oob_bytes(mtd, oob, i, !i, page);
1393 }
1394
Boris Brezillon25f815f2017-11-30 18:01:30 +01001395 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
1396
Boris Brezillon614049a2016-04-15 15:10:30 +02001397 sunxi_nfc_hw_ecc_enable(mtd);
1398 sunxi_nfc_randomizer_config(mtd, page, false);
1399 sunxi_nfc_randomizer_enable(mtd);
1400
1401 writel((NAND_CMD_RNDIN << 8) | NAND_CMD_PAGEPROG,
1402 nfc->regs + NFC_REG_RCMD_SET);
1403
1404 dma_async_issue_pending(nfc->dmac);
1405
1406 writel(NFC_PAGE_OP | NFC_DATA_SWAP_METHOD |
1407 NFC_DATA_TRANS | NFC_ACCESS_DIR,
1408 nfc->regs + NFC_REG_CMD);
1409
Boris Brezillon8de15e12017-01-06 10:42:06 +01001410 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0);
Boris Brezillon614049a2016-04-15 15:10:30 +02001411 if (ret)
1412 dmaengine_terminate_all(nfc->dmac);
1413
1414 sunxi_nfc_randomizer_disable(mtd);
1415 sunxi_nfc_hw_ecc_disable(mtd);
1416
1417 sunxi_nfc_dma_op_cleanup(mtd, DMA_TO_DEVICE, &sg);
1418
1419 if (ret)
1420 return ret;
1421
1422 if (oob_required || (chip->options & NAND_NEED_SCRAMBLING))
1423 /* TODO: use DMA to transfer extra OOB bytes ? */
1424 sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi,
1425 NULL, page);
1426
Boris Brezillon25f815f2017-11-30 18:01:30 +01001427 return nand_prog_page_end_op(chip);
Boris Brezillon614049a2016-04-15 15:10:30 +02001428
1429pio_fallback:
1430 return sunxi_nfc_hw_ecc_write_page(mtd, chip, buf, oob_required, page);
1431}
1432
Boris Brezillon15d6f112018-03-21 09:36:18 +01001433static int sunxi_nfc_hw_ecc_read_oob(struct mtd_info *mtd,
1434 struct nand_chip *chip,
1435 int page)
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001436{
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001437 chip->pagebuf = -1;
1438
Masahiro Yamadac0313b92017-12-05 17:47:16 +09001439 return chip->ecc.read_page(mtd, chip, chip->data_buf, 1, page);
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001440}
1441
Boris Brezillon15d6f112018-03-21 09:36:18 +01001442static int sunxi_nfc_hw_ecc_write_oob(struct mtd_info *mtd,
1443 struct nand_chip *chip,
1444 int page)
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001445{
Boris Brezillon97d90da2017-11-30 18:01:29 +01001446 int ret;
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001447
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001448 chip->pagebuf = -1;
1449
Masahiro Yamadac0313b92017-12-05 17:47:16 +09001450 memset(chip->data_buf, 0xff, mtd->writesize);
1451 ret = chip->ecc.write_page(mtd, chip, chip->data_buf, 1, page);
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001452 if (ret)
1453 return ret;
1454
1455 /* Send command to program the OOB data */
Boris Brezillon97d90da2017-11-30 18:01:29 +01001456 return nand_prog_page_end_op(chip);
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001457}
1458
Roy Spliet9c618292015-06-26 11:00:10 +02001459static const s32 tWB_lut[] = {6, 12, 16, 20};
1460static const s32 tRHW_lut[] = {4, 8, 12, 20};
1461
1462static int _sunxi_nand_lookup_timing(const s32 *lut, int lut_size, u32 duration,
1463 u32 clk_period)
1464{
1465 u32 clk_cycles = DIV_ROUND_UP(duration, clk_period);
1466 int i;
1467
1468 for (i = 0; i < lut_size; i++) {
1469 if (clk_cycles <= lut[i])
1470 return i;
1471 }
1472
1473 /* Doesn't fit */
1474 return -EINVAL;
1475}
1476
1477#define sunxi_nand_lookup_timing(l, p, c) \
1478 _sunxi_nand_lookup_timing(l, ARRAY_SIZE(l), p, c)
1479
Boris Brezillon104e4422017-03-16 09:35:58 +01001480static int sunxi_nfc_setup_data_interface(struct mtd_info *mtd, int csline,
1481 const struct nand_data_interface *conf)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001482{
Sascha Hauer907f45f2016-09-15 10:32:51 +02001483 struct nand_chip *nand = mtd_to_nand(mtd);
1484 struct sunxi_nand_chip *chip = to_sunxi_nand(nand);
Roy Spliet9c618292015-06-26 11:00:10 +02001485 struct sunxi_nfc *nfc = to_sunxi_nfc(chip->nand.controller);
Sascha Hauer907f45f2016-09-15 10:32:51 +02001486 const struct nand_sdr_timings *timings;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001487 u32 min_clk_period = 0;
Roy Spliet9c618292015-06-26 11:00:10 +02001488 s32 tWB, tADL, tWHR, tRHW, tCAD;
Boris Brezillon2d434572015-12-02 15:57:20 +01001489 long real_clk_rate;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001490
Sascha Hauer907f45f2016-09-15 10:32:51 +02001491 timings = nand_get_sdr_timings(conf);
1492 if (IS_ERR(timings))
1493 return -ENOTSUPP;
1494
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001495 /* T1 <=> tCLS */
1496 if (timings->tCLS_min > min_clk_period)
1497 min_clk_period = timings->tCLS_min;
1498
1499 /* T2 <=> tCLH */
1500 if (timings->tCLH_min > min_clk_period)
1501 min_clk_period = timings->tCLH_min;
1502
1503 /* T3 <=> tCS */
1504 if (timings->tCS_min > min_clk_period)
1505 min_clk_period = timings->tCS_min;
1506
1507 /* T4 <=> tCH */
1508 if (timings->tCH_min > min_clk_period)
1509 min_clk_period = timings->tCH_min;
1510
1511 /* T5 <=> tWP */
1512 if (timings->tWP_min > min_clk_period)
1513 min_clk_period = timings->tWP_min;
1514
1515 /* T6 <=> tWH */
1516 if (timings->tWH_min > min_clk_period)
1517 min_clk_period = timings->tWH_min;
1518
1519 /* T7 <=> tALS */
1520 if (timings->tALS_min > min_clk_period)
1521 min_clk_period = timings->tALS_min;
1522
1523 /* T8 <=> tDS */
1524 if (timings->tDS_min > min_clk_period)
1525 min_clk_period = timings->tDS_min;
1526
1527 /* T9 <=> tDH */
1528 if (timings->tDH_min > min_clk_period)
1529 min_clk_period = timings->tDH_min;
1530
1531 /* T10 <=> tRR */
1532 if (timings->tRR_min > (min_clk_period * 3))
1533 min_clk_period = DIV_ROUND_UP(timings->tRR_min, 3);
1534
1535 /* T11 <=> tALH */
1536 if (timings->tALH_min > min_clk_period)
1537 min_clk_period = timings->tALH_min;
1538
1539 /* T12 <=> tRP */
1540 if (timings->tRP_min > min_clk_period)
1541 min_clk_period = timings->tRP_min;
1542
1543 /* T13 <=> tREH */
1544 if (timings->tREH_min > min_clk_period)
1545 min_clk_period = timings->tREH_min;
1546
1547 /* T14 <=> tRC */
1548 if (timings->tRC_min > (min_clk_period * 2))
1549 min_clk_period = DIV_ROUND_UP(timings->tRC_min, 2);
1550
1551 /* T15 <=> tWC */
1552 if (timings->tWC_min > (min_clk_period * 2))
1553 min_clk_period = DIV_ROUND_UP(timings->tWC_min, 2);
1554
Roy Spliet9c618292015-06-26 11:00:10 +02001555 /* T16 - T19 + tCAD */
Boris Brezillon5abcd952015-11-11 22:30:30 +01001556 if (timings->tWB_max > (min_clk_period * 20))
1557 min_clk_period = DIV_ROUND_UP(timings->tWB_max, 20);
1558
1559 if (timings->tADL_min > (min_clk_period * 32))
1560 min_clk_period = DIV_ROUND_UP(timings->tADL_min, 32);
1561
1562 if (timings->tWHR_min > (min_clk_period * 32))
1563 min_clk_period = DIV_ROUND_UP(timings->tWHR_min, 32);
1564
1565 if (timings->tRHW_min > (min_clk_period * 20))
1566 min_clk_period = DIV_ROUND_UP(timings->tRHW_min, 20);
1567
Roy Spliet9c618292015-06-26 11:00:10 +02001568 tWB = sunxi_nand_lookup_timing(tWB_lut, timings->tWB_max,
1569 min_clk_period);
1570 if (tWB < 0) {
1571 dev_err(nfc->dev, "unsupported tWB\n");
1572 return tWB;
1573 }
1574
1575 tADL = DIV_ROUND_UP(timings->tADL_min, min_clk_period) >> 3;
1576 if (tADL > 3) {
1577 dev_err(nfc->dev, "unsupported tADL\n");
1578 return -EINVAL;
1579 }
1580
1581 tWHR = DIV_ROUND_UP(timings->tWHR_min, min_clk_period) >> 3;
1582 if (tWHR > 3) {
1583 dev_err(nfc->dev, "unsupported tWHR\n");
1584 return -EINVAL;
1585 }
1586
1587 tRHW = sunxi_nand_lookup_timing(tRHW_lut, timings->tRHW_min,
1588 min_clk_period);
1589 if (tRHW < 0) {
1590 dev_err(nfc->dev, "unsupported tRHW\n");
1591 return tRHW;
1592 }
1593
Boris Brezillon104e4422017-03-16 09:35:58 +01001594 if (csline == NAND_DATA_IFACE_CHECK_ONLY)
Sascha Hauer907f45f2016-09-15 10:32:51 +02001595 return 0;
1596
Roy Spliet9c618292015-06-26 11:00:10 +02001597 /*
1598 * TODO: according to ONFI specs this value only applies for DDR NAND,
1599 * but Allwinner seems to set this to 0x7. Mimic them for now.
1600 */
1601 tCAD = 0x7;
1602
1603 /* TODO: A83 has some more bits for CDQSS, CS, CLHZ, CCS, WC */
1604 chip->timing_cfg = NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001605
1606 /* Convert min_clk_period from picoseconds to nanoseconds */
1607 min_clk_period = DIV_ROUND_UP(min_clk_period, 1000);
1608
1609 /*
Boris Brezillon2f9992e2015-12-02 15:10:40 +01001610 * Unlike what is stated in Allwinner datasheet, the clk_rate should
1611 * be set to (1 / min_clk_period), and not (2 / min_clk_period).
1612 * This new formula was verified with a scope and validated by
1613 * Allwinner engineers.
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001614 */
Boris Brezillon2f9992e2015-12-02 15:10:40 +01001615 chip->clk_rate = NSEC_PER_SEC / min_clk_period;
Boris Brezillon2d434572015-12-02 15:57:20 +01001616 real_clk_rate = clk_round_rate(nfc->mod_clk, chip->clk_rate);
Bryan O'Donoghue791eccd2017-07-28 14:22:57 +01001617 if (real_clk_rate <= 0) {
1618 dev_err(nfc->dev, "Unable to round clk %lu\n", chip->clk_rate);
1619 return -EINVAL;
1620 }
Boris Brezillon2d434572015-12-02 15:57:20 +01001621
1622 /*
1623 * ONFI specification 3.1, paragraph 4.15.2 dictates that EDO data
1624 * output cycle timings shall be used if the host drives tRC less than
1625 * 30 ns.
1626 */
1627 min_clk_period = NSEC_PER_SEC / real_clk_rate;
1628 chip->timing_ctl = ((min_clk_period * 2) < 30) ?
1629 NFC_TIMING_CTL_EDO : 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001630
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001631 return 0;
1632}
1633
Boris Brezillonc66811e2016-02-03 20:05:13 +01001634static int sunxi_nand_ooblayout_ecc(struct mtd_info *mtd, int section,
1635 struct mtd_oob_region *oobregion)
1636{
1637 struct nand_chip *nand = mtd_to_nand(mtd);
1638 struct nand_ecc_ctrl *ecc = &nand->ecc;
1639
1640 if (section >= ecc->steps)
1641 return -ERANGE;
1642
1643 oobregion->offset = section * (ecc->bytes + 4) + 4;
1644 oobregion->length = ecc->bytes;
1645
1646 return 0;
1647}
1648
1649static int sunxi_nand_ooblayout_free(struct mtd_info *mtd, int section,
1650 struct mtd_oob_region *oobregion)
1651{
1652 struct nand_chip *nand = mtd_to_nand(mtd);
1653 struct nand_ecc_ctrl *ecc = &nand->ecc;
1654
1655 if (section > ecc->steps)
1656 return -ERANGE;
1657
1658 /*
1659 * The first 2 bytes are used for BB markers, hence we
1660 * only have 2 bytes available in the first user data
1661 * section.
1662 */
1663 if (!section && ecc->mode == NAND_ECC_HW) {
1664 oobregion->offset = 2;
1665 oobregion->length = 2;
1666
1667 return 0;
1668 }
1669
1670 oobregion->offset = section * (ecc->bytes + 4);
1671
1672 if (section < ecc->steps)
1673 oobregion->length = 4;
1674 else
1675 oobregion->offset = mtd->oobsize - oobregion->offset;
1676
1677 return 0;
1678}
1679
1680static const struct mtd_ooblayout_ops sunxi_nand_ooblayout_ops = {
1681 .ecc = sunxi_nand_ooblayout_ecc,
1682 .free = sunxi_nand_ooblayout_free,
1683};
1684
Boris Brezillon15d6f112018-03-21 09:36:18 +01001685static void sunxi_nand_hw_ecc_ctrl_cleanup(struct nand_ecc_ctrl *ecc)
1686{
1687 kfree(ecc->priv);
1688}
1689
1690static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
1691 struct nand_ecc_ctrl *ecc,
1692 struct device_node *np)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001693{
1694 static const u8 strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 };
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +01001695 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001696 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
1697 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
1698 struct sunxi_nand_hw_ecc *data;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001699 int nsectors;
1700 int ret;
1701 int i;
1702
Boris Brezillon4796d862016-06-08 17:04:24 +02001703 if (ecc->options & NAND_ECC_MAXIMIZE) {
1704 int bytes;
1705
1706 ecc->size = 1024;
1707 nsectors = mtd->writesize / ecc->size;
1708
1709 /* Reserve 2 bytes for the BBM */
1710 bytes = (mtd->oobsize - 2) / nsectors;
1711
1712 /* 4 non-ECC bytes are added before each ECC bytes section */
1713 bytes -= 4;
1714
1715 /* and bytes has to be even. */
1716 if (bytes % 2)
1717 bytes--;
1718
1719 ecc->strength = bytes * 8 / fls(8 * ecc->size);
1720
1721 for (i = 0; i < ARRAY_SIZE(strengths); i++) {
1722 if (strengths[i] > ecc->strength)
1723 break;
1724 }
1725
1726 if (!i)
1727 ecc->strength = 0;
1728 else
1729 ecc->strength = strengths[i - 1];
1730 }
1731
Dan Carpenter40297e72016-06-24 15:24:03 +03001732 if (ecc->size != 512 && ecc->size != 1024)
1733 return -EINVAL;
1734
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001735 data = kzalloc(sizeof(*data), GFP_KERNEL);
1736 if (!data)
1737 return -ENOMEM;
1738
Boris Brezillon872164e2016-06-06 13:59:12 +02001739 /* Prefer 1k ECC chunk over 512 ones */
1740 if (ecc->size == 512 && mtd->writesize > 512) {
1741 ecc->size = 1024;
1742 ecc->strength *= 2;
1743 }
1744
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001745 /* Add ECC info retrieval from DT */
1746 for (i = 0; i < ARRAY_SIZE(strengths); i++) {
Miquel Raynalf4c6cd12018-01-24 23:49:31 +01001747 if (ecc->strength <= strengths[i]) {
1748 /*
1749 * Update ecc->strength value with the actual strength
1750 * that will be used by the ECC engine.
1751 */
1752 ecc->strength = strengths[i];
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001753 break;
Miquel Raynalf4c6cd12018-01-24 23:49:31 +01001754 }
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001755 }
1756
1757 if (i >= ARRAY_SIZE(strengths)) {
1758 dev_err(nfc->dev, "unsupported strength\n");
1759 ret = -ENOTSUPP;
1760 goto err;
1761 }
1762
1763 data->mode = i;
1764
1765 /* HW ECC always request ECC bytes for 1024 bytes blocks */
1766 ecc->bytes = DIV_ROUND_UP(ecc->strength * fls(8 * 1024), 8);
1767
1768 /* HW ECC always work with even numbers of ECC bytes */
1769 ecc->bytes = ALIGN(ecc->bytes, 2);
1770
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001771 nsectors = mtd->writesize / ecc->size;
1772
1773 if (mtd->oobsize < ((ecc->bytes + 4) * nsectors)) {
1774 ret = -EINVAL;
1775 goto err;
1776 }
1777
Boris Brezillon15d6f112018-03-21 09:36:18 +01001778 ecc->read_oob = sunxi_nfc_hw_ecc_read_oob;
1779 ecc->write_oob = sunxi_nfc_hw_ecc_write_oob;
Boris Brezillonc66811e2016-02-03 20:05:13 +01001780 mtd_set_ooblayout(mtd, &sunxi_nand_ooblayout_ops);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001781 ecc->priv = data;
1782
Boris Brezillon614049a2016-04-15 15:10:30 +02001783 if (nfc->dmac) {
1784 ecc->read_page = sunxi_nfc_hw_ecc_read_page_dma;
1785 ecc->read_subpage = sunxi_nfc_hw_ecc_read_subpage_dma;
1786 ecc->write_page = sunxi_nfc_hw_ecc_write_page_dma;
1787 nand->options |= NAND_USE_BOUNCE_BUFFER;
1788 } else {
1789 ecc->read_page = sunxi_nfc_hw_ecc_read_page;
1790 ecc->read_subpage = sunxi_nfc_hw_ecc_read_subpage;
1791 ecc->write_page = sunxi_nfc_hw_ecc_write_page;
1792 }
1793
Boris Brezillon03b1d112016-06-06 13:59:14 +02001794 /* TODO: support DMA for raw accesses and subpage write */
1795 ecc->write_subpage = sunxi_nfc_hw_ecc_write_subpage;
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001796 ecc->read_oob_raw = nand_read_oob_std;
1797 ecc->write_oob_raw = nand_write_oob_std;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001798
1799 return 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001800
Boris Brezillon15d6f112018-03-21 09:36:18 +01001801err:
1802 kfree(data);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001803
Boris Brezillon15d6f112018-03-21 09:36:18 +01001804 return ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001805}
1806
1807static void sunxi_nand_ecc_cleanup(struct nand_ecc_ctrl *ecc)
1808{
1809 switch (ecc->mode) {
1810 case NAND_ECC_HW:
Boris Brezillon15d6f112018-03-21 09:36:18 +01001811 sunxi_nand_hw_ecc_ctrl_cleanup(ecc);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001812 break;
1813 case NAND_ECC_NONE:
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001814 default:
1815 break;
1816 }
1817}
1818
1819static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc,
1820 struct device_node *np)
1821{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +01001822 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001823 int ret;
1824
Boris BREZILLONa3d22a52015-09-02 10:30:25 +02001825 if (!ecc->size) {
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001826 ecc->size = nand->ecc_step_ds;
1827 ecc->strength = nand->ecc_strength_ds;
1828 }
1829
1830 if (!ecc->size || !ecc->strength)
1831 return -EINVAL;
1832
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001833 switch (ecc->mode) {
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001834 case NAND_ECC_HW:
1835 ret = sunxi_nand_hw_ecc_ctrl_init(mtd, ecc, np);
1836 if (ret)
1837 return ret;
1838 break;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001839 case NAND_ECC_NONE:
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001840 case NAND_ECC_SOFT:
1841 break;
1842 default:
1843 return -EINVAL;
1844 }
1845
1846 return 0;
1847}
1848
1849static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
1850 struct device_node *np)
1851{
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001852 struct sunxi_nand_chip *chip;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001853 struct mtd_info *mtd;
1854 struct nand_chip *nand;
1855 int nsels;
1856 int ret;
1857 int i;
1858 u32 tmp;
1859
1860 if (!of_get_property(np, "reg", &nsels))
1861 return -EINVAL;
1862
1863 nsels /= sizeof(u32);
1864 if (!nsels) {
1865 dev_err(dev, "invalid reg property size\n");
1866 return -EINVAL;
1867 }
1868
1869 chip = devm_kzalloc(dev,
1870 sizeof(*chip) +
1871 (nsels * sizeof(struct sunxi_nand_chip_sel)),
1872 GFP_KERNEL);
1873 if (!chip) {
1874 dev_err(dev, "could not allocate chip\n");
1875 return -ENOMEM;
1876 }
1877
1878 chip->nsels = nsels;
1879 chip->selected = -1;
1880
1881 for (i = 0; i < nsels; i++) {
1882 ret = of_property_read_u32_index(np, "reg", i, &tmp);
1883 if (ret) {
1884 dev_err(dev, "could not retrieve reg property: %d\n",
1885 ret);
1886 return ret;
1887 }
1888
1889 if (tmp > NFC_MAX_CS) {
1890 dev_err(dev,
1891 "invalid reg value: %u (max CS = 7)\n",
1892 tmp);
1893 return -EINVAL;
1894 }
1895
1896 if (test_and_set_bit(tmp, &nfc->assigned_cs)) {
1897 dev_err(dev, "CS %d already assigned\n", tmp);
1898 return -EINVAL;
1899 }
1900
1901 chip->sels[i].cs = tmp;
1902
1903 if (!of_property_read_u32_index(np, "allwinner,rb", i, &tmp) &&
Boris Brezillonddd5ed32018-03-27 09:06:14 +02001904 tmp < 2)
1905 chip->sels[i].rb = tmp;
1906 else
1907 chip->sels[i].rb = -1;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001908 }
1909
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001910 nand = &chip->nand;
1911 /* Default tR value specified in the ONFI spec (chapter 4.15.1) */
1912 nand->chip_delay = 200;
1913 nand->controller = &nfc->controller;
Boris BREZILLONa3d22a52015-09-02 10:30:25 +02001914 /*
1915 * Set the ECC mode to the default value in case nothing is specified
1916 * in the DT.
1917 */
1918 nand->ecc.mode = NAND_ECC_HW;
Brian Norris63752192015-10-30 20:33:23 -07001919 nand_set_flash_node(nand, np);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001920 nand->select_chip = sunxi_nfc_select_chip;
1921 nand->cmd_ctrl = sunxi_nfc_cmd_ctrl;
1922 nand->read_buf = sunxi_nfc_read_buf;
1923 nand->write_buf = sunxi_nfc_write_buf;
1924 nand->read_byte = sunxi_nfc_read_byte;
Sascha Hauer907f45f2016-09-15 10:32:51 +02001925 nand->setup_data_interface = sunxi_nfc_setup_data_interface;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001926
Boris BREZILLON32e9f2d2015-12-10 09:00:26 +01001927 mtd = nand_to_mtd(nand);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001928 mtd->dev.parent = dev;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001929
1930 ret = nand_scan_ident(mtd, nsels, NULL);
1931 if (ret)
1932 return ret;
1933
Boris BREZILLONa3d22a52015-09-02 10:30:25 +02001934 if (nand->bbt_options & NAND_BBT_USE_FLASH)
1935 nand->bbt_options |= NAND_BBT_NO_OOB;
1936
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001937 if (nand->options & NAND_NEED_SCRAMBLING)
1938 nand->options |= NAND_NO_SUBPAGE_WRITE;
1939
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001940 nand->options |= NAND_SUBPAGE_READ;
1941
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001942 ret = sunxi_nand_ecc_init(mtd, &nand->ecc, np);
1943 if (ret) {
1944 dev_err(dev, "ECC init failed: %d\n", ret);
1945 return ret;
1946 }
1947
1948 ret = nand_scan_tail(mtd);
1949 if (ret) {
1950 dev_err(dev, "nand_scan_tail failed: %d\n", ret);
1951 return ret;
1952 }
1953
Brian Norrisa61ae812015-10-30 20:33:25 -07001954 ret = mtd_device_register(mtd, NULL, 0);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001955 if (ret) {
1956 dev_err(dev, "failed to register mtd device: %d\n", ret);
1957 nand_release(mtd);
1958 return ret;
1959 }
1960
1961 list_add_tail(&chip->node, &nfc->chips);
1962
1963 return 0;
1964}
1965
1966static int sunxi_nand_chips_init(struct device *dev, struct sunxi_nfc *nfc)
1967{
1968 struct device_node *np = dev->of_node;
1969 struct device_node *nand_np;
1970 int nchips = of_get_child_count(np);
1971 int ret;
1972
1973 if (nchips > 8) {
1974 dev_err(dev, "too many NAND chips: %d (max = 8)\n", nchips);
1975 return -EINVAL;
1976 }
1977
1978 for_each_child_of_node(np, nand_np) {
1979 ret = sunxi_nand_chip_init(dev, nfc, nand_np);
Julia Lawalla81c0f02015-11-18 23:04:12 +01001980 if (ret) {
1981 of_node_put(nand_np);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001982 return ret;
Julia Lawalla81c0f02015-11-18 23:04:12 +01001983 }
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001984 }
1985
1986 return 0;
1987}
1988
1989static void sunxi_nand_chips_cleanup(struct sunxi_nfc *nfc)
1990{
1991 struct sunxi_nand_chip *chip;
1992
1993 while (!list_empty(&nfc->chips)) {
1994 chip = list_first_entry(&nfc->chips, struct sunxi_nand_chip,
1995 node);
Boris BREZILLON32e9f2d2015-12-10 09:00:26 +01001996 nand_release(nand_to_mtd(&chip->nand));
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001997 sunxi_nand_ecc_cleanup(&chip->nand.ecc);
Boris BREZILLON8e375cc2015-09-13 18:14:43 +02001998 list_del(&chip->node);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001999 }
2000}
2001
2002static int sunxi_nfc_probe(struct platform_device *pdev)
2003{
2004 struct device *dev = &pdev->dev;
2005 struct resource *r;
2006 struct sunxi_nfc *nfc;
2007 int irq;
2008 int ret;
2009
2010 nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
2011 if (!nfc)
2012 return -ENOMEM;
2013
2014 nfc->dev = dev;
Miquel Raynal7da45132018-07-17 09:08:02 +02002015 nand_controller_init(&nfc->controller);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002016 INIT_LIST_HEAD(&nfc->chips);
2017
2018 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2019 nfc->regs = devm_ioremap_resource(dev, r);
2020 if (IS_ERR(nfc->regs))
2021 return PTR_ERR(nfc->regs);
2022
2023 irq = platform_get_irq(pdev, 0);
2024 if (irq < 0) {
2025 dev_err(dev, "failed to retrieve irq\n");
2026 return irq;
2027 }
2028
2029 nfc->ahb_clk = devm_clk_get(dev, "ahb");
2030 if (IS_ERR(nfc->ahb_clk)) {
2031 dev_err(dev, "failed to retrieve ahb clk\n");
2032 return PTR_ERR(nfc->ahb_clk);
2033 }
2034
2035 ret = clk_prepare_enable(nfc->ahb_clk);
2036 if (ret)
2037 return ret;
2038
2039 nfc->mod_clk = devm_clk_get(dev, "mod");
2040 if (IS_ERR(nfc->mod_clk)) {
2041 dev_err(dev, "failed to retrieve mod clk\n");
2042 ret = PTR_ERR(nfc->mod_clk);
2043 goto out_ahb_clk_unprepare;
2044 }
2045
2046 ret = clk_prepare_enable(nfc->mod_clk);
2047 if (ret)
2048 goto out_ahb_clk_unprepare;
2049
Philipp Zabelfcf59f12017-07-19 17:25:46 +02002050 nfc->reset = devm_reset_control_get_optional_exclusive(dev, "ahb");
Philipp Zabel6b244bb2017-03-15 12:31:47 +01002051 if (IS_ERR(nfc->reset)) {
Icenowy Zhengab9d6a72016-06-20 12:48:38 +08002052 ret = PTR_ERR(nfc->reset);
2053 goto out_mod_clk_unprepare;
2054 }
2055
Philipp Zabel6b244bb2017-03-15 12:31:47 +01002056 ret = reset_control_deassert(nfc->reset);
2057 if (ret) {
2058 dev_err(dev, "reset err %d\n", ret);
2059 goto out_mod_clk_unprepare;
2060 }
2061
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002062 ret = sunxi_nfc_rst(nfc);
2063 if (ret)
Icenowy Zhengab9d6a72016-06-20 12:48:38 +08002064 goto out_ahb_reset_reassert;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002065
2066 writel(0, nfc->regs + NFC_REG_INT);
2067 ret = devm_request_irq(dev, irq, sunxi_nfc_interrupt,
2068 0, "sunxi-nand", nfc);
2069 if (ret)
Icenowy Zhengab9d6a72016-06-20 12:48:38 +08002070 goto out_ahb_reset_reassert;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002071
Boris Brezillon614049a2016-04-15 15:10:30 +02002072 nfc->dmac = dma_request_slave_channel(dev, "rxtx");
2073 if (nfc->dmac) {
2074 struct dma_slave_config dmac_cfg = { };
2075
2076 dmac_cfg.src_addr = r->start + NFC_REG_IO_DATA;
2077 dmac_cfg.dst_addr = dmac_cfg.src_addr;
2078 dmac_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
2079 dmac_cfg.dst_addr_width = dmac_cfg.src_addr_width;
2080 dmac_cfg.src_maxburst = 4;
2081 dmac_cfg.dst_maxburst = 4;
2082 dmaengine_slave_config(nfc->dmac, &dmac_cfg);
2083 } else {
2084 dev_warn(dev, "failed to request rxtx DMA channel\n");
2085 }
2086
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002087 platform_set_drvdata(pdev, nfc);
2088
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002089 ret = sunxi_nand_chips_init(dev, nfc);
2090 if (ret) {
2091 dev_err(dev, "failed to init nand chips\n");
Boris Brezillon614049a2016-04-15 15:10:30 +02002092 goto out_release_dmac;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002093 }
2094
2095 return 0;
2096
Boris Brezillon614049a2016-04-15 15:10:30 +02002097out_release_dmac:
2098 if (nfc->dmac)
2099 dma_release_channel(nfc->dmac);
Icenowy Zhengab9d6a72016-06-20 12:48:38 +08002100out_ahb_reset_reassert:
Philipp Zabel6b244bb2017-03-15 12:31:47 +01002101 reset_control_assert(nfc->reset);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002102out_mod_clk_unprepare:
2103 clk_disable_unprepare(nfc->mod_clk);
2104out_ahb_clk_unprepare:
2105 clk_disable_unprepare(nfc->ahb_clk);
2106
2107 return ret;
2108}
2109
2110static int sunxi_nfc_remove(struct platform_device *pdev)
2111{
2112 struct sunxi_nfc *nfc = platform_get_drvdata(pdev);
2113
2114 sunxi_nand_chips_cleanup(nfc);
Icenowy Zhengab9d6a72016-06-20 12:48:38 +08002115
Philipp Zabel6b244bb2017-03-15 12:31:47 +01002116 reset_control_assert(nfc->reset);
Icenowy Zhengab9d6a72016-06-20 12:48:38 +08002117
Boris Brezillon614049a2016-04-15 15:10:30 +02002118 if (nfc->dmac)
2119 dma_release_channel(nfc->dmac);
Boris Brezillondd26a452016-03-04 18:26:40 +01002120 clk_disable_unprepare(nfc->mod_clk);
2121 clk_disable_unprepare(nfc->ahb_clk);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002122
2123 return 0;
2124}
2125
2126static const struct of_device_id sunxi_nfc_ids[] = {
2127 { .compatible = "allwinner,sun4i-a10-nand" },
2128 { /* sentinel */ }
2129};
2130MODULE_DEVICE_TABLE(of, sunxi_nfc_ids);
2131
2132static struct platform_driver sunxi_nfc_driver = {
2133 .driver = {
2134 .name = "sunxi_nand",
2135 .of_match_table = sunxi_nfc_ids,
2136 },
2137 .probe = sunxi_nfc_probe,
2138 .remove = sunxi_nfc_remove,
2139};
2140module_platform_driver(sunxi_nfc_driver);
2141
2142MODULE_LICENSE("GPL v2");
2143MODULE_AUTHOR("Boris BREZILLON");
2144MODULE_DESCRIPTION("Allwinner NAND Flash Controller driver");
2145MODULE_ALIAS("platform:sunxi_nand");