blob: eea64bc3ff1e781bfcf2c78b5f89cc592aefb4f4 [file] [log] [blame]
Boris Brezillonf5f88872018-12-15 09:24:35 +01001// SPDX-License-Identifier: GPL-2.0+
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002/*
3 * Copyright (C) 2013 Boris BREZILLON <b.brezillon.dev@gmail.com>
4 *
5 * Derived from:
6 * https://github.com/yuq/sunxi-nfc-mtd
7 * Copyright (C) 2013 Qiang Yu <yuq825@gmail.com>
8 *
9 * https://github.com/hno/Allwinner-Info
10 * Copyright (C) 2013 Henrik Nordström <Henrik Nordström>
11 *
12 * Copyright (C) 2013 Dmitriy B. <rzk333@gmail.com>
13 * Copyright (C) 2013 Sergey Lapin <slapin@ossfans.org>
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020014 */
15
16#include <linux/dma-mapping.h>
17#include <linux/slab.h>
18#include <linux/module.h>
19#include <linux/moduleparam.h>
20#include <linux/platform_device.h>
21#include <linux/of.h>
22#include <linux/of_device.h>
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020023#include <linux/mtd/mtd.h>
Boris Brezillond4092d72017-08-04 17:29:10 +020024#include <linux/mtd/rawnand.h>
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020025#include <linux/mtd/partitions.h>
26#include <linux/clk.h>
27#include <linux/delay.h>
28#include <linux/dmaengine.h>
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020029#include <linux/interrupt.h>
Boris Brezillon166f08c2016-03-07 15:25:17 +010030#include <linux/iopoll.h>
Icenowy Zhengab9d6a72016-06-20 12:48:38 +080031#include <linux/reset.h>
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020032
33#define NFC_REG_CTL 0x0000
34#define NFC_REG_ST 0x0004
35#define NFC_REG_INT 0x0008
36#define NFC_REG_TIMING_CTL 0x000C
37#define NFC_REG_TIMING_CFG 0x0010
38#define NFC_REG_ADDR_LOW 0x0014
39#define NFC_REG_ADDR_HIGH 0x0018
40#define NFC_REG_SECTOR_NUM 0x001C
41#define NFC_REG_CNT 0x0020
42#define NFC_REG_CMD 0x0024
43#define NFC_REG_RCMD_SET 0x0028
44#define NFC_REG_WCMD_SET 0x002C
45#define NFC_REG_IO_DATA 0x0030
46#define NFC_REG_ECC_CTL 0x0034
47#define NFC_REG_ECC_ST 0x0038
48#define NFC_REG_DEBUG 0x003C
Boris BREZILLONb6a02c02015-09-16 09:46:36 +020049#define NFC_REG_ECC_ERR_CNT(x) ((0x0040 + (x)) & ~0x3)
50#define NFC_REG_USER_DATA(x) (0x0050 + ((x) * 4))
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020051#define NFC_REG_SPARE_AREA 0x00A0
Boris BREZILLON4be4e032015-12-02 12:01:07 +010052#define NFC_REG_PAT_ID 0x00A4
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020053#define NFC_RAM0_BASE 0x0400
54#define NFC_RAM1_BASE 0x0800
55
56/* define bit use in NFC_CTL */
57#define NFC_EN BIT(0)
58#define NFC_RESET BIT(1)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +020059#define NFC_BUS_WIDTH_MSK BIT(2)
60#define NFC_BUS_WIDTH_8 (0 << 2)
61#define NFC_BUS_WIDTH_16 (1 << 2)
62#define NFC_RB_SEL_MSK BIT(3)
63#define NFC_RB_SEL(x) ((x) << 3)
64#define NFC_CE_SEL_MSK GENMASK(26, 24)
65#define NFC_CE_SEL(x) ((x) << 24)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020066#define NFC_CE_CTL BIT(6)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +020067#define NFC_PAGE_SHIFT_MSK GENMASK(11, 8)
68#define NFC_PAGE_SHIFT(x) (((x) < 10 ? 0 : (x) - 10) << 8)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020069#define NFC_SAM BIT(12)
70#define NFC_RAM_METHOD BIT(14)
71#define NFC_DEBUG_CTL BIT(31)
72
73/* define bit use in NFC_ST */
74#define NFC_RB_B2R BIT(0)
75#define NFC_CMD_INT_FLAG BIT(1)
76#define NFC_DMA_INT_FLAG BIT(2)
77#define NFC_CMD_FIFO_STATUS BIT(3)
78#define NFC_STA BIT(4)
79#define NFC_NATCH_INT_FLAG BIT(5)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +020080#define NFC_RB_STATE(x) BIT(x + 8)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020081
82/* define bit use in NFC_INT */
83#define NFC_B2R_INT_ENABLE BIT(0)
84#define NFC_CMD_INT_ENABLE BIT(1)
85#define NFC_DMA_INT_ENABLE BIT(2)
86#define NFC_INT_MASK (NFC_B2R_INT_ENABLE | \
87 NFC_CMD_INT_ENABLE | \
88 NFC_DMA_INT_ENABLE)
89
Roy Splietd052e502015-06-26 11:00:11 +020090/* define bit use in NFC_TIMING_CTL */
91#define NFC_TIMING_CTL_EDO BIT(8)
92
Roy Spliet9c618292015-06-26 11:00:10 +020093/* define NFC_TIMING_CFG register layout */
94#define NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD) \
95 (((tWB) & 0x3) | (((tADL) & 0x3) << 2) | \
96 (((tWHR) & 0x3) << 4) | (((tRHW) & 0x3) << 6) | \
97 (((tCAD) & 0x7) << 8))
98
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020099/* define bit use in NFC_CMD */
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200100#define NFC_CMD_LOW_BYTE_MSK GENMASK(7, 0)
101#define NFC_CMD_HIGH_BYTE_MSK GENMASK(15, 8)
102#define NFC_CMD(x) (x)
103#define NFC_ADR_NUM_MSK GENMASK(18, 16)
104#define NFC_ADR_NUM(x) (((x) - 1) << 16)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200105#define NFC_SEND_ADR BIT(19)
106#define NFC_ACCESS_DIR BIT(20)
107#define NFC_DATA_TRANS BIT(21)
108#define NFC_SEND_CMD1 BIT(22)
109#define NFC_WAIT_FLAG BIT(23)
110#define NFC_SEND_CMD2 BIT(24)
111#define NFC_SEQ BIT(25)
112#define NFC_DATA_SWAP_METHOD BIT(26)
113#define NFC_ROW_AUTO_INC BIT(27)
114#define NFC_SEND_CMD3 BIT(28)
115#define NFC_SEND_CMD4 BIT(29)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200116#define NFC_CMD_TYPE_MSK GENMASK(31, 30)
117#define NFC_NORMAL_OP (0 << 30)
118#define NFC_ECC_OP (1 << 30)
Boris Brezilloncf3e3fd2018-07-09 22:09:31 +0200119#define NFC_PAGE_OP (2U << 30)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200120
121/* define bit use in NFC_RCMD_SET */
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200122#define NFC_READ_CMD_MSK GENMASK(7, 0)
123#define NFC_RND_READ_CMD0_MSK GENMASK(15, 8)
124#define NFC_RND_READ_CMD1_MSK GENMASK(23, 16)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200125
126/* define bit use in NFC_WCMD_SET */
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200127#define NFC_PROGRAM_CMD_MSK GENMASK(7, 0)
128#define NFC_RND_WRITE_CMD_MSK GENMASK(15, 8)
129#define NFC_READ_CMD0_MSK GENMASK(23, 16)
130#define NFC_READ_CMD1_MSK GENMASK(31, 24)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200131
132/* define bit use in NFC_ECC_CTL */
133#define NFC_ECC_EN BIT(0)
134#define NFC_ECC_PIPELINE BIT(3)
135#define NFC_ECC_EXCEPTION BIT(4)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200136#define NFC_ECC_BLOCK_SIZE_MSK BIT(5)
Boris Brezillonf59dab82016-10-20 10:12:42 +0200137#define NFC_ECC_BLOCK_512 BIT(5)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200138#define NFC_RANDOM_EN BIT(9)
139#define NFC_RANDOM_DIRECTION BIT(10)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200140#define NFC_ECC_MODE_MSK GENMASK(15, 12)
141#define NFC_ECC_MODE(x) ((x) << 12)
142#define NFC_RANDOM_SEED_MSK GENMASK(30, 16)
143#define NFC_RANDOM_SEED(x) ((x) << 16)
144
145/* define bit use in NFC_ECC_ST */
146#define NFC_ECC_ERR(x) BIT(x)
Boris Brezillon614049a2016-04-15 15:10:30 +0200147#define NFC_ECC_ERR_MSK GENMASK(15, 0)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200148#define NFC_ECC_PAT_FOUND(x) BIT(x + 16)
Boris Brezillonf8b04742016-03-04 17:25:08 +0100149#define NFC_ECC_ERR_CNT(b, x) (((x) >> (((b) % 4) * 8)) & 0xff)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200150
151#define NFC_DEFAULT_TIMEOUT_MS 1000
152
153#define NFC_SRAM_SIZE 1024
154
155#define NFC_MAX_CS 7
156
157/*
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200158 * Chip Select structure: stores information related to NAND Chip Select
159 *
160 * @cs: the NAND CS id used to communicate with a NAND Chip
Boris Brezillonddd5ed32018-03-27 09:06:14 +0200161 * @rb: the Ready/Busy pin ID. -1 means no R/B pin connected to the
162 * NFC
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200163 */
164struct sunxi_nand_chip_sel {
165 u8 cs;
Boris Brezillonddd5ed32018-03-27 09:06:14 +0200166 s8 rb;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200167};
168
169/*
170 * sunxi HW ECC infos: stores information related to HW ECC support
171 *
172 * @mode: the sunxi ECC mode field deduced from ECC requirements
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200173 */
174struct sunxi_nand_hw_ecc {
175 int mode;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200176};
177
178/*
179 * NAND chip structure: stores NAND chip device related information
180 *
181 * @node: used to store NAND chips into a list
182 * @nand: base NAND chip structure
183 * @mtd: base MTD structure
184 * @clk_rate: clk_rate required for this NAND chip
Roy Spliet9c618292015-06-26 11:00:10 +0200185 * @timing_cfg TIMING_CFG register value for this NAND chip
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200186 * @selected: current active CS
187 * @nsels: number of CS lines required by the NAND chip
188 * @sels: array of CS lines descriptions
189 */
190struct sunxi_nand_chip {
191 struct list_head node;
192 struct nand_chip nand;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200193 unsigned long clk_rate;
Roy Spliet9c618292015-06-26 11:00:10 +0200194 u32 timing_cfg;
Roy Splietd052e502015-06-26 11:00:11 +0200195 u32 timing_ctl;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200196 int selected;
Boris Brezillone9aa6712015-09-16 09:05:31 +0200197 int addr_cycles;
198 u32 addr[2];
199 int cmd_cycles;
200 u8 cmd[2];
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200201 int nsels;
202 struct sunxi_nand_chip_sel sels[0];
203};
204
205static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
206{
207 return container_of(nand, struct sunxi_nand_chip, nand);
208}
209
210/*
211 * NAND Controller structure: stores sunxi NAND controller information
212 *
213 * @controller: base controller structure
214 * @dev: parent device (used to print error messages)
215 * @regs: NAND controller registers
216 * @ahb_clk: NAND Controller AHB clock
217 * @mod_clk: NAND Controller mod clock
218 * @assigned_cs: bitmask describing already assigned CS lines
219 * @clk_rate: NAND controller current clock rate
220 * @chips: a list containing all the NAND chips attached to
221 * this NAND controller
222 * @complete: a completion object used to wait for NAND
223 * controller events
224 */
225struct sunxi_nfc {
Miquel Raynal7da45132018-07-17 09:08:02 +0200226 struct nand_controller controller;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200227 struct device *dev;
228 void __iomem *regs;
229 struct clk *ahb_clk;
230 struct clk *mod_clk;
Icenowy Zhengab9d6a72016-06-20 12:48:38 +0800231 struct reset_control *reset;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200232 unsigned long assigned_cs;
233 unsigned long clk_rate;
234 struct list_head chips;
235 struct completion complete;
Boris Brezillon614049a2016-04-15 15:10:30 +0200236 struct dma_chan *dmac;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200237};
238
Miquel Raynal7da45132018-07-17 09:08:02 +0200239static inline struct sunxi_nfc *to_sunxi_nfc(struct nand_controller *ctrl)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200240{
241 return container_of(ctrl, struct sunxi_nfc, controller);
242}
243
244static irqreturn_t sunxi_nfc_interrupt(int irq, void *dev_id)
245{
246 struct sunxi_nfc *nfc = dev_id;
247 u32 st = readl(nfc->regs + NFC_REG_ST);
248 u32 ien = readl(nfc->regs + NFC_REG_INT);
249
250 if (!(ien & st))
251 return IRQ_NONE;
252
253 if ((ien & st) == ien)
254 complete(&nfc->complete);
255
256 writel(st & NFC_INT_MASK, nfc->regs + NFC_REG_ST);
257 writel(~st & ien & NFC_INT_MASK, nfc->regs + NFC_REG_INT);
258
259 return IRQ_HANDLED;
260}
261
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100262static int sunxi_nfc_wait_events(struct sunxi_nfc *nfc, u32 events,
263 bool use_polling, unsigned int timeout_ms)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200264{
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100265 int ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200266
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100267 if (events & ~NFC_INT_MASK)
268 return -EINVAL;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200269
270 if (!timeout_ms)
271 timeout_ms = NFC_DEFAULT_TIMEOUT_MS;
272
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100273 if (!use_polling) {
274 init_completion(&nfc->complete);
275
276 writel(events, nfc->regs + NFC_REG_INT);
277
278 ret = wait_for_completion_timeout(&nfc->complete,
279 msecs_to_jiffies(timeout_ms));
Boris Brezillon19649e22017-01-06 10:42:05 +0100280 if (!ret)
281 ret = -ETIMEDOUT;
282 else
283 ret = 0;
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100284
285 writel(0, nfc->regs + NFC_REG_INT);
286 } else {
287 u32 status;
288
289 ret = readl_poll_timeout(nfc->regs + NFC_REG_ST, status,
290 (status & events) == events, 1,
291 timeout_ms * 1000);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200292 }
293
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100294 writel(events & NFC_INT_MASK, nfc->regs + NFC_REG_ST);
295
296 if (ret)
297 dev_err(nfc->dev, "wait interrupt timedout\n");
298
299 return ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200300}
301
302static int sunxi_nfc_wait_cmd_fifo_empty(struct sunxi_nfc *nfc)
303{
Boris Brezillon166f08c2016-03-07 15:25:17 +0100304 u32 status;
305 int ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200306
Boris Brezillon166f08c2016-03-07 15:25:17 +0100307 ret = readl_poll_timeout(nfc->regs + NFC_REG_ST, status,
308 !(status & NFC_CMD_FIFO_STATUS), 1,
309 NFC_DEFAULT_TIMEOUT_MS * 1000);
310 if (ret)
311 dev_err(nfc->dev, "wait for empty cmd FIFO timedout\n");
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200312
Boris Brezillon166f08c2016-03-07 15:25:17 +0100313 return ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200314}
315
316static int sunxi_nfc_rst(struct sunxi_nfc *nfc)
317{
Boris Brezillon166f08c2016-03-07 15:25:17 +0100318 u32 ctl;
319 int ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200320
321 writel(0, nfc->regs + NFC_REG_ECC_CTL);
322 writel(NFC_RESET, nfc->regs + NFC_REG_CTL);
323
Boris Brezillon166f08c2016-03-07 15:25:17 +0100324 ret = readl_poll_timeout(nfc->regs + NFC_REG_CTL, ctl,
325 !(ctl & NFC_RESET), 1,
326 NFC_DEFAULT_TIMEOUT_MS * 1000);
327 if (ret)
328 dev_err(nfc->dev, "wait for NAND controller reset timedout\n");
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200329
Boris Brezillon166f08c2016-03-07 15:25:17 +0100330 return ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200331}
332
Boris Brezilloncde567e2018-12-15 09:24:34 +0100333static int sunxi_nfc_dma_op_prepare(struct sunxi_nfc *nfc, const void *buf,
Boris Brezillon614049a2016-04-15 15:10:30 +0200334 int chunksize, int nchunks,
335 enum dma_data_direction ddir,
336 struct scatterlist *sg)
337{
Boris Brezillon614049a2016-04-15 15:10:30 +0200338 struct dma_async_tx_descriptor *dmad;
339 enum dma_transfer_direction tdir;
340 dma_cookie_t dmat;
341 int ret;
342
343 if (ddir == DMA_FROM_DEVICE)
344 tdir = DMA_DEV_TO_MEM;
345 else
346 tdir = DMA_MEM_TO_DEV;
347
348 sg_init_one(sg, buf, nchunks * chunksize);
349 ret = dma_map_sg(nfc->dev, sg, 1, ddir);
350 if (!ret)
351 return -ENOMEM;
352
353 dmad = dmaengine_prep_slave_sg(nfc->dmac, sg, 1, tdir, DMA_CTRL_ACK);
Wei Yongjun28f3d012016-06-13 14:27:18 +0000354 if (!dmad) {
355 ret = -EINVAL;
Boris Brezillon614049a2016-04-15 15:10:30 +0200356 goto err_unmap_buf;
357 }
358
359 writel(readl(nfc->regs + NFC_REG_CTL) | NFC_RAM_METHOD,
360 nfc->regs + NFC_REG_CTL);
361 writel(nchunks, nfc->regs + NFC_REG_SECTOR_NUM);
362 writel(chunksize, nfc->regs + NFC_REG_CNT);
363 dmat = dmaengine_submit(dmad);
364
365 ret = dma_submit_error(dmat);
366 if (ret)
367 goto err_clr_dma_flag;
368
369 return 0;
370
371err_clr_dma_flag:
372 writel(readl(nfc->regs + NFC_REG_CTL) & ~NFC_RAM_METHOD,
373 nfc->regs + NFC_REG_CTL);
374
375err_unmap_buf:
376 dma_unmap_sg(nfc->dev, sg, 1, ddir);
377 return ret;
378}
379
Boris Brezilloncde567e2018-12-15 09:24:34 +0100380static void sunxi_nfc_dma_op_cleanup(struct sunxi_nfc *nfc,
Boris Brezillon614049a2016-04-15 15:10:30 +0200381 enum dma_data_direction ddir,
382 struct scatterlist *sg)
383{
Boris Brezillon614049a2016-04-15 15:10:30 +0200384 dma_unmap_sg(nfc->dev, sg, 1, ddir);
385 writel(readl(nfc->regs + NFC_REG_CTL) & ~NFC_RAM_METHOD,
386 nfc->regs + NFC_REG_CTL);
387}
388
Boris Brezillon50a487e2018-09-06 14:05:27 +0200389static int sunxi_nfc_dev_ready(struct nand_chip *nand)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200390{
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200391 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
392 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
Boris Brezillonddd5ed32018-03-27 09:06:14 +0200393 u32 mask;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200394
395 if (sunxi_nand->selected < 0)
396 return 0;
397
Boris Brezillonddd5ed32018-03-27 09:06:14 +0200398 if (sunxi_nand->sels[sunxi_nand->selected].rb < 0) {
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200399 dev_err(nfc->dev, "cannot check R/B NAND status!\n");
Boris Brezillonddd5ed32018-03-27 09:06:14 +0200400 return 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200401 }
402
Boris Brezillonddd5ed32018-03-27 09:06:14 +0200403 mask = NFC_RB_STATE(sunxi_nand->sels[sunxi_nand->selected].rb);
404
405 return !!(readl(nfc->regs + NFC_REG_ST) & mask);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200406}
407
Boris Brezillon758b56f2018-09-06 14:05:24 +0200408static void sunxi_nfc_select_chip(struct nand_chip *nand, int chip)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200409{
Boris Brezillon758b56f2018-09-06 14:05:24 +0200410 struct mtd_info *mtd = nand_to_mtd(nand);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200411 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
412 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
413 struct sunxi_nand_chip_sel *sel;
414 u32 ctl;
415
416 if (chip > 0 && chip >= sunxi_nand->nsels)
417 return;
418
419 if (chip == sunxi_nand->selected)
420 return;
421
422 ctl = readl(nfc->regs + NFC_REG_CTL) &
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200423 ~(NFC_PAGE_SHIFT_MSK | NFC_CE_SEL_MSK | NFC_RB_SEL_MSK | NFC_EN);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200424
425 if (chip >= 0) {
426 sel = &sunxi_nand->sels[chip];
427
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200428 ctl |= NFC_CE_SEL(sel->cs) | NFC_EN |
Boris Brezillon68ffbf72016-03-04 17:29:20 +0100429 NFC_PAGE_SHIFT(nand->page_shift);
Boris Brezillonddd5ed32018-03-27 09:06:14 +0200430 if (sel->rb < 0) {
Boris Brezillon8395b752018-09-07 00:38:37 +0200431 nand->legacy.dev_ready = NULL;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200432 } else {
Boris Brezillon8395b752018-09-07 00:38:37 +0200433 nand->legacy.dev_ready = sunxi_nfc_dev_ready;
Boris Brezillonddd5ed32018-03-27 09:06:14 +0200434 ctl |= NFC_RB_SEL(sel->rb);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200435 }
436
437 writel(mtd->writesize, nfc->regs + NFC_REG_SPARE_AREA);
438
439 if (nfc->clk_rate != sunxi_nand->clk_rate) {
440 clk_set_rate(nfc->mod_clk, sunxi_nand->clk_rate);
441 nfc->clk_rate = sunxi_nand->clk_rate;
442 }
443 }
444
Roy Splietd052e502015-06-26 11:00:11 +0200445 writel(sunxi_nand->timing_ctl, nfc->regs + NFC_REG_TIMING_CTL);
Roy Spliet9c618292015-06-26 11:00:10 +0200446 writel(sunxi_nand->timing_cfg, nfc->regs + NFC_REG_TIMING_CFG);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200447 writel(ctl, nfc->regs + NFC_REG_CTL);
448
449 sunxi_nand->selected = chip;
450}
451
Boris Brezillon7e534322018-09-06 14:05:22 +0200452static void sunxi_nfc_read_buf(struct nand_chip *nand, uint8_t *buf, int len)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200453{
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200454 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
455 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
456 int ret;
457 int cnt;
458 int offs = 0;
459 u32 tmp;
460
461 while (len > offs) {
Boris Brezillon8de15e12017-01-06 10:42:06 +0100462 bool poll = false;
463
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200464 cnt = min(len - offs, NFC_SRAM_SIZE);
465
466 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
467 if (ret)
468 break;
469
470 writel(cnt, nfc->regs + NFC_REG_CNT);
471 tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD;
472 writel(tmp, nfc->regs + NFC_REG_CMD);
473
Boris Brezillon8de15e12017-01-06 10:42:06 +0100474 /* Arbitrary limit for polling mode */
475 if (cnt < 64)
476 poll = true;
477
478 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, poll, 0);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200479 if (ret)
480 break;
481
482 if (buf)
483 memcpy_fromio(buf + offs, nfc->regs + NFC_RAM0_BASE,
484 cnt);
485 offs += cnt;
486 }
487}
488
Boris Brezillonc0739d82018-09-06 14:05:23 +0200489static void sunxi_nfc_write_buf(struct nand_chip *nand, const uint8_t *buf,
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200490 int len)
491{
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200492 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
493 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
494 int ret;
495 int cnt;
496 int offs = 0;
497 u32 tmp;
498
499 while (len > offs) {
Boris Brezillon8de15e12017-01-06 10:42:06 +0100500 bool poll = false;
501
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200502 cnt = min(len - offs, NFC_SRAM_SIZE);
503
504 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
505 if (ret)
506 break;
507
508 writel(cnt, nfc->regs + NFC_REG_CNT);
509 memcpy_toio(nfc->regs + NFC_RAM0_BASE, buf + offs, cnt);
510 tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD |
511 NFC_ACCESS_DIR;
512 writel(tmp, nfc->regs + NFC_REG_CMD);
513
Boris Brezillon8de15e12017-01-06 10:42:06 +0100514 /* Arbitrary limit for polling mode */
515 if (cnt < 64)
516 poll = true;
517
518 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, poll, 0);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200519 if (ret)
520 break;
521
522 offs += cnt;
523 }
524}
525
Boris Brezillon7e534322018-09-06 14:05:22 +0200526static uint8_t sunxi_nfc_read_byte(struct nand_chip *nand)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200527{
Boris Brezillon06c8b5d2018-07-09 22:09:32 +0200528 uint8_t ret = 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200529
Boris Brezillon7e534322018-09-06 14:05:22 +0200530 sunxi_nfc_read_buf(nand, &ret, 1);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200531
532 return ret;
533}
534
Boris Brezillon0f808c12018-09-06 14:05:26 +0200535static void sunxi_nfc_cmd_ctrl(struct nand_chip *nand, int dat,
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200536 unsigned int ctrl)
537{
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200538 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
539 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
540 int ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200541
Boris Brezillone9aa6712015-09-16 09:05:31 +0200542 if (dat == NAND_CMD_NONE && (ctrl & NAND_NCE) &&
543 !(ctrl & (NAND_CLE | NAND_ALE))) {
544 u32 cmd = 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200545
Boris Brezillone9aa6712015-09-16 09:05:31 +0200546 if (!sunxi_nand->addr_cycles && !sunxi_nand->cmd_cycles)
547 return;
548
549 if (sunxi_nand->cmd_cycles--)
550 cmd |= NFC_SEND_CMD1 | sunxi_nand->cmd[0];
551
552 if (sunxi_nand->cmd_cycles--) {
553 cmd |= NFC_SEND_CMD2;
554 writel(sunxi_nand->cmd[1],
555 nfc->regs + NFC_REG_RCMD_SET);
556 }
557
558 sunxi_nand->cmd_cycles = 0;
559
560 if (sunxi_nand->addr_cycles) {
561 cmd |= NFC_SEND_ADR |
562 NFC_ADR_NUM(sunxi_nand->addr_cycles);
563 writel(sunxi_nand->addr[0],
564 nfc->regs + NFC_REG_ADDR_LOW);
565 }
566
567 if (sunxi_nand->addr_cycles > 4)
568 writel(sunxi_nand->addr[1],
569 nfc->regs + NFC_REG_ADDR_HIGH);
570
Boris Brezilloncad32742017-01-06 10:42:07 +0100571 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
572 if (ret)
573 return;
574
Boris Brezillone9aa6712015-09-16 09:05:31 +0200575 writel(cmd, nfc->regs + NFC_REG_CMD);
576 sunxi_nand->addr[0] = 0;
577 sunxi_nand->addr[1] = 0;
578 sunxi_nand->addr_cycles = 0;
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100579 sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200580 }
581
Boris Brezillone9aa6712015-09-16 09:05:31 +0200582 if (ctrl & NAND_CLE) {
583 sunxi_nand->cmd[sunxi_nand->cmd_cycles++] = dat;
584 } else if (ctrl & NAND_ALE) {
585 sunxi_nand->addr[sunxi_nand->addr_cycles / 4] |=
586 dat << ((sunxi_nand->addr_cycles % 4) * 8);
587 sunxi_nand->addr_cycles++;
588 }
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200589}
590
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100591/* These seed values have been extracted from Allwinner's BSP */
592static const u16 sunxi_nfc_randomizer_page_seeds[] = {
593 0x2b75, 0x0bd0, 0x5ca3, 0x62d1, 0x1c93, 0x07e9, 0x2162, 0x3a72,
594 0x0d67, 0x67f9, 0x1be7, 0x077d, 0x032f, 0x0dac, 0x2716, 0x2436,
595 0x7922, 0x1510, 0x3860, 0x5287, 0x480f, 0x4252, 0x1789, 0x5a2d,
596 0x2a49, 0x5e10, 0x437f, 0x4b4e, 0x2f45, 0x216e, 0x5cb7, 0x7130,
597 0x2a3f, 0x60e4, 0x4dc9, 0x0ef0, 0x0f52, 0x1bb9, 0x6211, 0x7a56,
598 0x226d, 0x4ea7, 0x6f36, 0x3692, 0x38bf, 0x0c62, 0x05eb, 0x4c55,
599 0x60f4, 0x728c, 0x3b6f, 0x2037, 0x7f69, 0x0936, 0x651a, 0x4ceb,
600 0x6218, 0x79f3, 0x383f, 0x18d9, 0x4f05, 0x5c82, 0x2912, 0x6f17,
601 0x6856, 0x5938, 0x1007, 0x61ab, 0x3e7f, 0x57c2, 0x542f, 0x4f62,
602 0x7454, 0x2eac, 0x7739, 0x42d4, 0x2f90, 0x435a, 0x2e52, 0x2064,
603 0x637c, 0x66ad, 0x2c90, 0x0bad, 0x759c, 0x0029, 0x0986, 0x7126,
604 0x1ca7, 0x1605, 0x386a, 0x27f5, 0x1380, 0x6d75, 0x24c3, 0x0f8e,
605 0x2b7a, 0x1418, 0x1fd1, 0x7dc1, 0x2d8e, 0x43af, 0x2267, 0x7da3,
606 0x4e3d, 0x1338, 0x50db, 0x454d, 0x764d, 0x40a3, 0x42e6, 0x262b,
607 0x2d2e, 0x1aea, 0x2e17, 0x173d, 0x3a6e, 0x71bf, 0x25f9, 0x0a5d,
608 0x7c57, 0x0fbe, 0x46ce, 0x4939, 0x6b17, 0x37bb, 0x3e91, 0x76db,
609};
610
611/*
612 * sunxi_nfc_randomizer_ecc512_seeds and sunxi_nfc_randomizer_ecc1024_seeds
613 * have been generated using
614 * sunxi_nfc_randomizer_step(seed, (step_size * 8) + 15), which is what
615 * the randomizer engine does internally before de/scrambling OOB data.
616 *
617 * Those tables are statically defined to avoid calculating randomizer state
618 * at runtime.
619 */
620static const u16 sunxi_nfc_randomizer_ecc512_seeds[] = {
621 0x3346, 0x367f, 0x1f18, 0x769a, 0x4f64, 0x068c, 0x2ef1, 0x6b64,
622 0x28a9, 0x15d7, 0x30f8, 0x3659, 0x53db, 0x7c5f, 0x71d4, 0x4409,
623 0x26eb, 0x03cc, 0x655d, 0x47d4, 0x4daa, 0x0877, 0x712d, 0x3617,
624 0x3264, 0x49aa, 0x7f9e, 0x588e, 0x4fbc, 0x7176, 0x7f91, 0x6c6d,
625 0x4b95, 0x5fb7, 0x3844, 0x4037, 0x0184, 0x081b, 0x0ee8, 0x5b91,
626 0x293d, 0x1f71, 0x0e6f, 0x402b, 0x5122, 0x1e52, 0x22be, 0x3d2d,
627 0x75bc, 0x7c60, 0x6291, 0x1a2f, 0x61d4, 0x74aa, 0x4140, 0x29ab,
628 0x472d, 0x2852, 0x017e, 0x15e8, 0x5ec2, 0x17cf, 0x7d0f, 0x06b8,
629 0x117a, 0x6b94, 0x789b, 0x3126, 0x6ac5, 0x5be7, 0x150f, 0x51f8,
630 0x7889, 0x0aa5, 0x663d, 0x77e8, 0x0b87, 0x3dcb, 0x360d, 0x218b,
631 0x512f, 0x7dc9, 0x6a4d, 0x630a, 0x3547, 0x1dd2, 0x5aea, 0x69a5,
632 0x7bfa, 0x5e4f, 0x1519, 0x6430, 0x3a0e, 0x5eb3, 0x5425, 0x0c7a,
633 0x5540, 0x3670, 0x63c1, 0x31e9, 0x5a39, 0x2de7, 0x5979, 0x2891,
634 0x1562, 0x014b, 0x5b05, 0x2756, 0x5a34, 0x13aa, 0x6cb5, 0x2c36,
635 0x5e72, 0x1306, 0x0861, 0x15ef, 0x1ee8, 0x5a37, 0x7ac4, 0x45dd,
636 0x44c4, 0x7266, 0x2f41, 0x3ccc, 0x045e, 0x7d40, 0x7c66, 0x0fa0,
637};
638
639static const u16 sunxi_nfc_randomizer_ecc1024_seeds[] = {
640 0x2cf5, 0x35f1, 0x63a4, 0x5274, 0x2bd2, 0x778b, 0x7285, 0x32b6,
641 0x6a5c, 0x70d6, 0x757d, 0x6769, 0x5375, 0x1e81, 0x0cf3, 0x3982,
642 0x6787, 0x042a, 0x6c49, 0x1925, 0x56a8, 0x40a9, 0x063e, 0x7bd9,
643 0x4dbf, 0x55ec, 0x672e, 0x7334, 0x5185, 0x4d00, 0x232a, 0x7e07,
644 0x445d, 0x6b92, 0x528f, 0x4255, 0x53ba, 0x7d82, 0x2a2e, 0x3a4e,
645 0x75eb, 0x450c, 0x6844, 0x1b5d, 0x581a, 0x4cc6, 0x0379, 0x37b2,
646 0x419f, 0x0e92, 0x6b27, 0x5624, 0x01e3, 0x07c1, 0x44a5, 0x130c,
647 0x13e8, 0x5910, 0x0876, 0x60c5, 0x54e3, 0x5b7f, 0x2269, 0x509f,
648 0x7665, 0x36fd, 0x3e9a, 0x0579, 0x6295, 0x14ef, 0x0a81, 0x1bcc,
649 0x4b16, 0x64db, 0x0514, 0x4f07, 0x0591, 0x3576, 0x6853, 0x0d9e,
650 0x259f, 0x38b7, 0x64fb, 0x3094, 0x4693, 0x6ddd, 0x29bb, 0x0bc8,
651 0x3f47, 0x490e, 0x0c0e, 0x7933, 0x3c9e, 0x5840, 0x398d, 0x3e68,
652 0x4af1, 0x71f5, 0x57cf, 0x1121, 0x64eb, 0x3579, 0x15ac, 0x584d,
653 0x5f2a, 0x47e2, 0x6528, 0x6eac, 0x196e, 0x6b96, 0x0450, 0x0179,
654 0x609c, 0x06e1, 0x4626, 0x42c7, 0x273e, 0x486f, 0x0705, 0x1601,
655 0x145b, 0x407e, 0x062b, 0x57a5, 0x53f9, 0x5659, 0x4410, 0x3ccd,
656};
657
658static u16 sunxi_nfc_randomizer_step(u16 state, int count)
659{
660 state &= 0x7fff;
661
662 /*
663 * This loop is just a simple implementation of a Fibonacci LFSR using
664 * the x16 + x15 + 1 polynomial.
665 */
666 while (count--)
667 state = ((state >> 1) |
668 (((state ^ (state >> 1)) & 1) << 14)) & 0x7fff;
669
670 return state;
671}
672
Boris Brezilloncde567e2018-12-15 09:24:34 +0100673static u16 sunxi_nfc_randomizer_state(struct nand_chip *nand, int page,
674 bool ecc)
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100675{
Boris Brezilloncde567e2018-12-15 09:24:34 +0100676 struct mtd_info *mtd = nand_to_mtd(nand);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100677 const u16 *seeds = sunxi_nfc_randomizer_page_seeds;
Brian Norris46c135c2016-01-22 18:57:13 -0800678 int mod = mtd_div_by_ws(mtd->erasesize, mtd);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100679
680 if (mod > ARRAY_SIZE(sunxi_nfc_randomizer_page_seeds))
681 mod = ARRAY_SIZE(sunxi_nfc_randomizer_page_seeds);
682
683 if (ecc) {
684 if (mtd->ecc_step_size == 512)
685 seeds = sunxi_nfc_randomizer_ecc512_seeds;
686 else
687 seeds = sunxi_nfc_randomizer_ecc1024_seeds;
688 }
689
690 return seeds[page % mod];
691}
692
Boris Brezilloncde567e2018-12-15 09:24:34 +0100693static void sunxi_nfc_randomizer_config(struct nand_chip *nand, int page,
694 bool ecc)
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100695{
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100696 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
697 u32 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
698 u16 state;
699
700 if (!(nand->options & NAND_NEED_SCRAMBLING))
701 return;
702
703 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
Boris Brezilloncde567e2018-12-15 09:24:34 +0100704 state = sunxi_nfc_randomizer_state(nand, page, ecc);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100705 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_RANDOM_SEED_MSK;
706 writel(ecc_ctl | NFC_RANDOM_SEED(state), nfc->regs + NFC_REG_ECC_CTL);
707}
708
Boris Brezilloncde567e2018-12-15 09:24:34 +0100709static void sunxi_nfc_randomizer_enable(struct nand_chip *nand)
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100710{
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100711 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
712
713 if (!(nand->options & NAND_NEED_SCRAMBLING))
714 return;
715
716 writel(readl(nfc->regs + NFC_REG_ECC_CTL) | NFC_RANDOM_EN,
717 nfc->regs + NFC_REG_ECC_CTL);
718}
719
Boris Brezilloncde567e2018-12-15 09:24:34 +0100720static void sunxi_nfc_randomizer_disable(struct nand_chip *nand)
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100721{
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100722 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
723
724 if (!(nand->options & NAND_NEED_SCRAMBLING))
725 return;
726
727 writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_RANDOM_EN,
728 nfc->regs + NFC_REG_ECC_CTL);
729}
730
Boris Brezilloncde567e2018-12-15 09:24:34 +0100731static void sunxi_nfc_randomize_bbm(struct nand_chip *nand, int page, u8 *bbm)
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100732{
Boris Brezilloncde567e2018-12-15 09:24:34 +0100733 u16 state = sunxi_nfc_randomizer_state(nand, page, true);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100734
735 bbm[0] ^= state;
736 bbm[1] ^= sunxi_nfc_randomizer_step(state, 8);
737}
738
Boris Brezilloncde567e2018-12-15 09:24:34 +0100739static void sunxi_nfc_randomizer_write_buf(struct nand_chip *nand,
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100740 const uint8_t *buf, int len,
741 bool ecc, int page)
742{
Boris Brezilloncde567e2018-12-15 09:24:34 +0100743 sunxi_nfc_randomizer_config(nand, page, ecc);
744 sunxi_nfc_randomizer_enable(nand);
745 sunxi_nfc_write_buf(nand, buf, len);
746 sunxi_nfc_randomizer_disable(nand);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100747}
748
Boris Brezilloncde567e2018-12-15 09:24:34 +0100749static void sunxi_nfc_randomizer_read_buf(struct nand_chip *nand, uint8_t *buf,
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100750 int len, bool ecc, int page)
751{
Boris Brezilloncde567e2018-12-15 09:24:34 +0100752 sunxi_nfc_randomizer_config(nand, page, ecc);
753 sunxi_nfc_randomizer_enable(nand);
754 sunxi_nfc_read_buf(nand, buf, len);
755 sunxi_nfc_randomizer_disable(nand);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100756}
757
Boris Brezilloncde567e2018-12-15 09:24:34 +0100758static void sunxi_nfc_hw_ecc_enable(struct nand_chip *nand)
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200759{
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200760 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
761 struct sunxi_nand_hw_ecc *data = nand->ecc.priv;
762 u32 ecc_ctl;
763
764 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
765 ecc_ctl &= ~(NFC_ECC_MODE_MSK | NFC_ECC_PIPELINE |
766 NFC_ECC_BLOCK_SIZE_MSK);
Boris Brezillon336de7b2016-03-04 17:33:10 +0100767 ecc_ctl |= NFC_ECC_EN | NFC_ECC_MODE(data->mode) | NFC_ECC_EXCEPTION |
768 NFC_ECC_PIPELINE;
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200769
Boris Brezillonf59dab82016-10-20 10:12:42 +0200770 if (nand->ecc.size == 512)
771 ecc_ctl |= NFC_ECC_BLOCK_512;
772
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200773 writel(ecc_ctl, nfc->regs + NFC_REG_ECC_CTL);
774}
775
Boris Brezilloncde567e2018-12-15 09:24:34 +0100776static void sunxi_nfc_hw_ecc_disable(struct nand_chip *nand)
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200777{
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200778 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
779
780 writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_ECC_EN,
781 nfc->regs + NFC_REG_ECC_CTL);
782}
783
Boris BREZILLONf363e0f2015-09-30 23:45:27 +0200784static inline void sunxi_nfc_user_data_to_buf(u32 user_data, u8 *buf)
785{
786 buf[0] = user_data;
787 buf[1] = user_data >> 8;
788 buf[2] = user_data >> 16;
789 buf[3] = user_data >> 24;
790}
791
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100792static inline u32 sunxi_nfc_buf_to_user_data(const u8 *buf)
793{
794 return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
795}
796
Boris Brezilloncde567e2018-12-15 09:24:34 +0100797static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct nand_chip *nand, u8 *oob,
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100798 int step, bool bbm, int page)
799{
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100800 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
801
802 sunxi_nfc_user_data_to_buf(readl(nfc->regs + NFC_REG_USER_DATA(step)),
803 oob);
804
805 /* De-randomize the Bad Block Marker. */
806 if (bbm && (nand->options & NAND_NEED_SCRAMBLING))
Boris Brezilloncde567e2018-12-15 09:24:34 +0100807 sunxi_nfc_randomize_bbm(nand, page, oob);
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100808}
809
Boris Brezilloncde567e2018-12-15 09:24:34 +0100810static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand,
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100811 const u8 *oob, int step,
812 bool bbm, int page)
813{
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100814 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
815 u8 user_data[4];
816
817 /* Randomize the Bad Block Marker. */
818 if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) {
819 memcpy(user_data, oob, sizeof(user_data));
Boris Brezilloncde567e2018-12-15 09:24:34 +0100820 sunxi_nfc_randomize_bbm(nand, page, user_data);
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100821 oob = user_data;
822 }
823
824 writel(sunxi_nfc_buf_to_user_data(oob),
825 nfc->regs + NFC_REG_USER_DATA(step));
826}
827
Boris Brezilloncde567e2018-12-15 09:24:34 +0100828static void sunxi_nfc_hw_ecc_update_stats(struct nand_chip *nand,
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100829 unsigned int *max_bitflips, int ret)
830{
Boris Brezilloncde567e2018-12-15 09:24:34 +0100831 struct mtd_info *mtd = nand_to_mtd(nand);
832
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100833 if (ret < 0) {
834 mtd->ecc_stats.failed++;
835 } else {
836 mtd->ecc_stats.corrected += ret;
837 *max_bitflips = max_t(unsigned int, *max_bitflips, ret);
838 }
839}
840
Boris Brezilloncde567e2018-12-15 09:24:34 +0100841static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *oob,
Boris Brezillon614049a2016-04-15 15:10:30 +0200842 int step, u32 status, bool *erased)
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100843{
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100844 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
845 struct nand_ecc_ctrl *ecc = &nand->ecc;
Boris Brezillon614049a2016-04-15 15:10:30 +0200846 u32 tmp;
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100847
848 *erased = false;
849
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100850 if (status & NFC_ECC_ERR(step))
851 return -EBADMSG;
852
853 if (status & NFC_ECC_PAT_FOUND(step)) {
854 u8 pattern;
855
856 if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID) & 0x1))) {
857 pattern = 0x0;
858 } else {
859 pattern = 0xff;
860 *erased = true;
861 }
862
863 if (data)
864 memset(data, pattern, ecc->size);
865
866 if (oob)
867 memset(oob, pattern, ecc->bytes + 4);
868
869 return 0;
870 }
871
872 tmp = readl(nfc->regs + NFC_REG_ECC_ERR_CNT(step));
873
874 return NFC_ECC_ERR_CNT(step, tmp);
875}
876
Boris Brezilloncde567e2018-12-15 09:24:34 +0100877static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand,
Boris BREZILLON913821b2015-09-30 23:45:24 +0200878 u8 *data, int data_off,
879 u8 *oob, int oob_off,
880 int *cur_off,
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100881 unsigned int *max_bitflips,
Boris Brezillon828dec12016-03-04 18:09:21 +0100882 bool bbm, bool oob_required, int page)
Boris BREZILLON913821b2015-09-30 23:45:24 +0200883{
Boris BREZILLON913821b2015-09-30 23:45:24 +0200884 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
885 struct nand_ecc_ctrl *ecc = &nand->ecc;
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100886 int raw_mode = 0;
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100887 bool erased;
Boris BREZILLON913821b2015-09-30 23:45:24 +0200888 int ret;
889
890 if (*cur_off != data_off)
Boris Brezillon97d90da2017-11-30 18:01:29 +0100891 nand_change_read_column_op(nand, data_off, NULL, 0, false);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200892
Boris Brezilloncde567e2018-12-15 09:24:34 +0100893 sunxi_nfc_randomizer_read_buf(nand, NULL, ecc->size, false, page);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200894
Boris BREZILLON74eb9ff2015-10-20 22:16:00 +0200895 if (data_off + ecc->size != oob_off)
Boris Brezillon97d90da2017-11-30 18:01:29 +0100896 nand_change_read_column_op(nand, oob_off, NULL, 0, false);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200897
898 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
899 if (ret)
900 return ret;
901
Boris Brezilloncde567e2018-12-15 09:24:34 +0100902 sunxi_nfc_randomizer_enable(nand);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200903 writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP,
904 nfc->regs + NFC_REG_CMD);
905
Boris Brezillon8de15e12017-01-06 10:42:06 +0100906 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0);
Boris Brezilloncde567e2018-12-15 09:24:34 +0100907 sunxi_nfc_randomizer_disable(nand);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200908 if (ret)
909 return ret;
910
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100911 *cur_off = oob_off + ecc->bytes + 4;
912
Boris Brezilloncde567e2018-12-15 09:24:34 +0100913 ret = sunxi_nfc_hw_ecc_correct(nand, data, oob_required ? oob : NULL, 0,
Boris Brezillon614049a2016-04-15 15:10:30 +0200914 readl(nfc->regs + NFC_REG_ECC_ST),
Boris Brezillon828dec12016-03-04 18:09:21 +0100915 &erased);
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100916 if (erased)
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100917 return 1;
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100918
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100919 if (ret < 0) {
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100920 /*
921 * Re-read the data with the randomizer disabled to identify
922 * bitflips in erased pages.
923 */
Boris Brezillon97d90da2017-11-30 18:01:29 +0100924 if (nand->options & NAND_NEED_SCRAMBLING)
925 nand_change_read_column_op(nand, data_off, data,
926 ecc->size, false);
927 else
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100928 memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE,
929 ecc->size);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100930
Boris Brezillon97d90da2017-11-30 18:01:29 +0100931 nand_change_read_column_op(nand, oob_off, oob, ecc->bytes + 4,
932 false);
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100933
Boris BREZILLON146b5032015-09-30 23:45:29 +0200934 ret = nand_check_erased_ecc_chunk(data, ecc->size,
935 oob, ecc->bytes + 4,
936 NULL, 0, ecc->strength);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100937 if (ret >= 0)
938 raw_mode = 1;
Boris BREZILLONf363e0f2015-09-30 23:45:27 +0200939 } else {
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100940 memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100941
Boris Brezillon828dec12016-03-04 18:09:21 +0100942 if (oob_required) {
Boris Brezillon97d90da2017-11-30 18:01:29 +0100943 nand_change_read_column_op(nand, oob_off, NULL, 0,
944 false);
Boris Brezilloncde567e2018-12-15 09:24:34 +0100945 sunxi_nfc_randomizer_read_buf(nand, oob, ecc->bytes + 4,
Boris Brezillon828dec12016-03-04 18:09:21 +0100946 true, page);
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100947
Boris Brezilloncde567e2018-12-15 09:24:34 +0100948 sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, 0,
Boris Brezillon828dec12016-03-04 18:09:21 +0100949 bbm, page);
950 }
Boris BREZILLONf363e0f2015-09-30 23:45:27 +0200951 }
Boris BREZILLON913821b2015-09-30 23:45:24 +0200952
Boris Brezilloncde567e2018-12-15 09:24:34 +0100953 sunxi_nfc_hw_ecc_update_stats(nand, max_bitflips, ret);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200954
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100955 return raw_mode;
Boris BREZILLON913821b2015-09-30 23:45:24 +0200956}
957
Boris Brezilloncde567e2018-12-15 09:24:34 +0100958static void sunxi_nfc_hw_ecc_read_extra_oob(struct nand_chip *nand,
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100959 u8 *oob, int *cur_off,
960 bool randomize, int page)
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200961{
Boris Brezilloncde567e2018-12-15 09:24:34 +0100962 struct mtd_info *mtd = nand_to_mtd(nand);
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200963 struct nand_ecc_ctrl *ecc = &nand->ecc;
964 int offset = ((ecc->bytes + 4) * ecc->steps);
965 int len = mtd->oobsize - offset;
966
967 if (len <= 0)
968 return;
969
Boris Brezillonc4f3ef22016-03-04 18:13:10 +0100970 if (!cur_off || *cur_off != offset)
Boris Brezillon97d90da2017-11-30 18:01:29 +0100971 nand_change_read_column_op(nand, mtd->writesize, NULL, 0,
972 false);
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200973
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100974 if (!randomize)
Boris Brezillon7e534322018-09-06 14:05:22 +0200975 sunxi_nfc_read_buf(nand, oob + offset, len);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100976 else
Boris Brezilloncde567e2018-12-15 09:24:34 +0100977 sunxi_nfc_randomizer_read_buf(nand, oob + offset, len,
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100978 false, page);
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200979
Boris Brezillonc4f3ef22016-03-04 18:13:10 +0100980 if (cur_off)
981 *cur_off = mtd->oobsize + mtd->writesize;
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200982}
983
Boris Brezilloncde567e2018-12-15 09:24:34 +0100984static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf,
Boris Brezillon614049a2016-04-15 15:10:30 +0200985 int oob_required, int page,
986 int nchunks)
987{
Boris Brezillon614049a2016-04-15 15:10:30 +0200988 bool randomized = nand->options & NAND_NEED_SCRAMBLING;
989 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
Boris Brezilloncde567e2018-12-15 09:24:34 +0100990 struct mtd_info *mtd = nand_to_mtd(nand);
Boris Brezillon614049a2016-04-15 15:10:30 +0200991 struct nand_ecc_ctrl *ecc = &nand->ecc;
992 unsigned int max_bitflips = 0;
993 int ret, i, raw_mode = 0;
994 struct scatterlist sg;
995 u32 status;
996
997 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
998 if (ret)
999 return ret;
1000
Boris Brezilloncde567e2018-12-15 09:24:34 +01001001 ret = sunxi_nfc_dma_op_prepare(nfc, buf, ecc->size, nchunks,
Boris Brezillon614049a2016-04-15 15:10:30 +02001002 DMA_FROM_DEVICE, &sg);
1003 if (ret)
1004 return ret;
1005
Boris Brezilloncde567e2018-12-15 09:24:34 +01001006 sunxi_nfc_hw_ecc_enable(nand);
1007 sunxi_nfc_randomizer_config(nand, page, false);
1008 sunxi_nfc_randomizer_enable(nand);
Boris Brezillon614049a2016-04-15 15:10:30 +02001009
1010 writel((NAND_CMD_RNDOUTSTART << 16) | (NAND_CMD_RNDOUT << 8) |
1011 NAND_CMD_READSTART, nfc->regs + NFC_REG_RCMD_SET);
1012
1013 dma_async_issue_pending(nfc->dmac);
1014
1015 writel(NFC_PAGE_OP | NFC_DATA_SWAP_METHOD | NFC_DATA_TRANS,
1016 nfc->regs + NFC_REG_CMD);
1017
Boris Brezillon8de15e12017-01-06 10:42:06 +01001018 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0);
Boris Brezillon614049a2016-04-15 15:10:30 +02001019 if (ret)
1020 dmaengine_terminate_all(nfc->dmac);
1021
Boris Brezilloncde567e2018-12-15 09:24:34 +01001022 sunxi_nfc_randomizer_disable(nand);
1023 sunxi_nfc_hw_ecc_disable(nand);
Boris Brezillon614049a2016-04-15 15:10:30 +02001024
Boris Brezilloncde567e2018-12-15 09:24:34 +01001025 sunxi_nfc_dma_op_cleanup(nfc, DMA_FROM_DEVICE, &sg);
Boris Brezillon614049a2016-04-15 15:10:30 +02001026
1027 if (ret)
1028 return ret;
1029
1030 status = readl(nfc->regs + NFC_REG_ECC_ST);
1031
1032 for (i = 0; i < nchunks; i++) {
1033 int data_off = i * ecc->size;
1034 int oob_off = i * (ecc->bytes + 4);
1035 u8 *data = buf + data_off;
1036 u8 *oob = nand->oob_poi + oob_off;
1037 bool erased;
1038
Boris Brezilloncde567e2018-12-15 09:24:34 +01001039 ret = sunxi_nfc_hw_ecc_correct(nand, randomized ? data : NULL,
Boris Brezillon614049a2016-04-15 15:10:30 +02001040 oob_required ? oob : NULL,
1041 i, status, &erased);
1042
1043 /* ECC errors are handled in the second loop. */
1044 if (ret < 0)
1045 continue;
1046
1047 if (oob_required && !erased) {
1048 /* TODO: use DMA to retrieve OOB */
Boris Brezillon97d90da2017-11-30 18:01:29 +01001049 nand_change_read_column_op(nand,
1050 mtd->writesize + oob_off,
1051 oob, ecc->bytes + 4, false);
Boris Brezillon614049a2016-04-15 15:10:30 +02001052
Boris Brezilloncde567e2018-12-15 09:24:34 +01001053 sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, i,
Boris Brezillon614049a2016-04-15 15:10:30 +02001054 !i, page);
1055 }
1056
1057 if (erased)
1058 raw_mode = 1;
1059
Boris Brezilloncde567e2018-12-15 09:24:34 +01001060 sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, ret);
Boris Brezillon614049a2016-04-15 15:10:30 +02001061 }
1062
1063 if (status & NFC_ECC_ERR_MSK) {
1064 for (i = 0; i < nchunks; i++) {
1065 int data_off = i * ecc->size;
1066 int oob_off = i * (ecc->bytes + 4);
1067 u8 *data = buf + data_off;
1068 u8 *oob = nand->oob_poi + oob_off;
1069
1070 if (!(status & NFC_ECC_ERR(i)))
1071 continue;
1072
1073 /*
1074 * Re-read the data with the randomizer disabled to
1075 * identify bitflips in erased pages.
Boris Brezillon97d90da2017-11-30 18:01:29 +01001076 * TODO: use DMA to read page in raw mode
Boris Brezillon614049a2016-04-15 15:10:30 +02001077 */
Boris Brezillon97d90da2017-11-30 18:01:29 +01001078 if (randomized)
1079 nand_change_read_column_op(nand, data_off,
1080 data, ecc->size,
1081 false);
Boris Brezillon614049a2016-04-15 15:10:30 +02001082
1083 /* TODO: use DMA to retrieve OOB */
Boris Brezillon97d90da2017-11-30 18:01:29 +01001084 nand_change_read_column_op(nand,
1085 mtd->writesize + oob_off,
1086 oob, ecc->bytes + 4, false);
Boris Brezillon614049a2016-04-15 15:10:30 +02001087
1088 ret = nand_check_erased_ecc_chunk(data, ecc->size,
1089 oob, ecc->bytes + 4,
1090 NULL, 0,
1091 ecc->strength);
1092 if (ret >= 0)
1093 raw_mode = 1;
1094
Boris Brezilloncde567e2018-12-15 09:24:34 +01001095 sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, ret);
Boris Brezillon614049a2016-04-15 15:10:30 +02001096 }
1097 }
1098
1099 if (oob_required)
Boris Brezilloncde567e2018-12-15 09:24:34 +01001100 sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi,
Boris Brezillon614049a2016-04-15 15:10:30 +02001101 NULL, !raw_mode,
1102 page);
1103
1104 return max_bitflips;
1105}
1106
Boris Brezilloncde567e2018-12-15 09:24:34 +01001107static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand,
Boris BREZILLON913821b2015-09-30 23:45:24 +02001108 const u8 *data, int data_off,
1109 const u8 *oob, int oob_off,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001110 int *cur_off, bool bbm,
1111 int page)
Boris BREZILLON913821b2015-09-30 23:45:24 +02001112{
Boris BREZILLON913821b2015-09-30 23:45:24 +02001113 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
1114 struct nand_ecc_ctrl *ecc = &nand->ecc;
1115 int ret;
1116
1117 if (data_off != *cur_off)
Boris Brezillon97d90da2017-11-30 18:01:29 +01001118 nand_change_write_column_op(nand, data_off, NULL, 0, false);
Boris BREZILLON913821b2015-09-30 23:45:24 +02001119
Boris Brezilloncde567e2018-12-15 09:24:34 +01001120 sunxi_nfc_randomizer_write_buf(nand, data, ecc->size, false, page);
Boris BREZILLON913821b2015-09-30 23:45:24 +02001121
Boris BREZILLON74eb9ff2015-10-20 22:16:00 +02001122 if (data_off + ecc->size != oob_off)
Boris Brezillon97d90da2017-11-30 18:01:29 +01001123 nand_change_write_column_op(nand, oob_off, NULL, 0, false);
Boris BREZILLON913821b2015-09-30 23:45:24 +02001124
1125 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
1126 if (ret)
1127 return ret;
1128
Boris Brezilloncde567e2018-12-15 09:24:34 +01001129 sunxi_nfc_randomizer_enable(nand);
1130 sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, 0, bbm, page);
Boris Brezilloncc6822f2016-03-04 17:56:47 +01001131
Boris BREZILLON913821b2015-09-30 23:45:24 +02001132 writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD |
1133 NFC_ACCESS_DIR | NFC_ECC_OP,
1134 nfc->regs + NFC_REG_CMD);
1135
Boris Brezillon8de15e12017-01-06 10:42:06 +01001136 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0);
Boris Brezilloncde567e2018-12-15 09:24:34 +01001137 sunxi_nfc_randomizer_disable(nand);
Boris BREZILLON913821b2015-09-30 23:45:24 +02001138 if (ret)
1139 return ret;
1140
1141 *cur_off = oob_off + ecc->bytes + 4;
1142
1143 return 0;
1144}
1145
Boris Brezilloncde567e2018-12-15 09:24:34 +01001146static void sunxi_nfc_hw_ecc_write_extra_oob(struct nand_chip *nand,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001147 u8 *oob, int *cur_off,
1148 int page)
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001149{
Boris Brezilloncde567e2018-12-15 09:24:34 +01001150 struct mtd_info *mtd = nand_to_mtd(nand);
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001151 struct nand_ecc_ctrl *ecc = &nand->ecc;
1152 int offset = ((ecc->bytes + 4) * ecc->steps);
1153 int len = mtd->oobsize - offset;
1154
1155 if (len <= 0)
1156 return;
1157
Boris Brezillonc4f3ef22016-03-04 18:13:10 +01001158 if (!cur_off || *cur_off != offset)
Boris Brezillon97d90da2017-11-30 18:01:29 +01001159 nand_change_write_column_op(nand, offset + mtd->writesize,
1160 NULL, 0, false);
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001161
Boris Brezilloncde567e2018-12-15 09:24:34 +01001162 sunxi_nfc_randomizer_write_buf(nand, oob + offset, len, false, page);
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001163
Boris Brezillonc4f3ef22016-03-04 18:13:10 +01001164 if (cur_off)
1165 *cur_off = mtd->oobsize + mtd->writesize;
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001166}
1167
Boris Brezillona55abb32018-12-15 09:24:33 +01001168static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *nand, uint8_t *buf,
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001169 int oob_required, int page)
1170{
Boris Brezillona55abb32018-12-15 09:24:33 +01001171 struct mtd_info *mtd = nand_to_mtd(nand);
1172 struct nand_ecc_ctrl *ecc = &nand->ecc;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001173 unsigned int max_bitflips = 0;
Boris BREZILLONb4625512015-09-30 23:45:25 +02001174 int ret, i, cur_off = 0;
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001175 bool raw_mode = false;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001176
Boris Brezillona55abb32018-12-15 09:24:33 +01001177 nand_read_page_op(nand, page, 0, NULL, 0);
Boris Brezillon25f815f2017-11-30 18:01:30 +01001178
Boris Brezilloncde567e2018-12-15 09:24:34 +01001179 sunxi_nfc_hw_ecc_enable(nand);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001180
1181 for (i = 0; i < ecc->steps; i++) {
Boris BREZILLONb4625512015-09-30 23:45:25 +02001182 int data_off = i * ecc->size;
1183 int oob_off = i * (ecc->bytes + 4);
1184 u8 *data = buf + data_off;
Boris Brezillona55abb32018-12-15 09:24:33 +01001185 u8 *oob = nand->oob_poi + oob_off;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001186
Boris Brezilloncde567e2018-12-15 09:24:34 +01001187 ret = sunxi_nfc_hw_ecc_read_chunk(nand, data, data_off, oob,
Boris BREZILLONb4625512015-09-30 23:45:25 +02001188 oob_off + mtd->writesize,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001189 &cur_off, &max_bitflips,
Boris Brezillon828dec12016-03-04 18:09:21 +01001190 !i, oob_required, page);
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001191 if (ret < 0)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001192 return ret;
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001193 else if (ret)
1194 raw_mode = true;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001195 }
1196
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001197 if (oob_required)
Boris Brezilloncde567e2018-12-15 09:24:34 +01001198 sunxi_nfc_hw_ecc_read_extra_oob(nand, nand->oob_poi, &cur_off,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001199 !raw_mode, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001200
Boris Brezilloncde567e2018-12-15 09:24:34 +01001201 sunxi_nfc_hw_ecc_disable(nand);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001202
1203 return max_bitflips;
1204}
1205
Boris Brezillona55abb32018-12-15 09:24:33 +01001206static int sunxi_nfc_hw_ecc_read_page_dma(struct nand_chip *nand, u8 *buf,
Boris Brezillon614049a2016-04-15 15:10:30 +02001207 int oob_required, int page)
1208{
1209 int ret;
1210
Boris Brezillona55abb32018-12-15 09:24:33 +01001211 nand_read_page_op(nand, page, 0, NULL, 0);
Boris Brezillon25f815f2017-11-30 18:01:30 +01001212
Boris Brezilloncde567e2018-12-15 09:24:34 +01001213 ret = sunxi_nfc_hw_ecc_read_chunks_dma(nand, buf, oob_required, page,
Boris Brezillona55abb32018-12-15 09:24:33 +01001214 nand->ecc.steps);
Boris Brezillon614049a2016-04-15 15:10:30 +02001215 if (ret >= 0)
1216 return ret;
1217
1218 /* Fallback to PIO mode */
Boris Brezillona55abb32018-12-15 09:24:33 +01001219 return sunxi_nfc_hw_ecc_read_page(nand, buf, oob_required, page);
Boris Brezillon614049a2016-04-15 15:10:30 +02001220}
1221
Boris Brezillona55abb32018-12-15 09:24:33 +01001222static int sunxi_nfc_hw_ecc_read_subpage(struct nand_chip *nand,
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001223 u32 data_offs, u32 readlen,
1224 u8 *bufpoi, int page)
1225{
Boris Brezillona55abb32018-12-15 09:24:33 +01001226 struct mtd_info *mtd = nand_to_mtd(nand);
1227 struct nand_ecc_ctrl *ecc = &nand->ecc;
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001228 int ret, i, cur_off = 0;
1229 unsigned int max_bitflips = 0;
1230
Boris Brezillona55abb32018-12-15 09:24:33 +01001231 nand_read_page_op(nand, page, 0, NULL, 0);
Boris Brezillon25f815f2017-11-30 18:01:30 +01001232
Boris Brezilloncde567e2018-12-15 09:24:34 +01001233 sunxi_nfc_hw_ecc_enable(nand);
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001234
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001235 for (i = data_offs / ecc->size;
1236 i < DIV_ROUND_UP(data_offs + readlen, ecc->size); i++) {
1237 int data_off = i * ecc->size;
1238 int oob_off = i * (ecc->bytes + 4);
1239 u8 *data = bufpoi + data_off;
Boris Brezillona55abb32018-12-15 09:24:33 +01001240 u8 *oob = nand->oob_poi + oob_off;
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001241
Boris Brezilloncde567e2018-12-15 09:24:34 +01001242 ret = sunxi_nfc_hw_ecc_read_chunk(nand, data, data_off,
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001243 oob,
1244 oob_off + mtd->writesize,
Boris Brezillon828dec12016-03-04 18:09:21 +01001245 &cur_off, &max_bitflips, !i,
1246 false, page);
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001247 if (ret < 0)
1248 return ret;
1249 }
1250
Boris Brezilloncde567e2018-12-15 09:24:34 +01001251 sunxi_nfc_hw_ecc_disable(nand);
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001252
1253 return max_bitflips;
1254}
1255
Boris Brezillona55abb32018-12-15 09:24:33 +01001256static int sunxi_nfc_hw_ecc_read_subpage_dma(struct nand_chip *nand,
Boris Brezillon614049a2016-04-15 15:10:30 +02001257 u32 data_offs, u32 readlen,
1258 u8 *buf, int page)
1259{
Boris Brezillona55abb32018-12-15 09:24:33 +01001260 int nchunks = DIV_ROUND_UP(data_offs + readlen, nand->ecc.size);
Boris Brezillon614049a2016-04-15 15:10:30 +02001261 int ret;
1262
Boris Brezillona55abb32018-12-15 09:24:33 +01001263 nand_read_page_op(nand, page, 0, NULL, 0);
Boris Brezillon25f815f2017-11-30 18:01:30 +01001264
Boris Brezilloncde567e2018-12-15 09:24:34 +01001265 ret = sunxi_nfc_hw_ecc_read_chunks_dma(nand, buf, false, page, nchunks);
Boris Brezillon614049a2016-04-15 15:10:30 +02001266 if (ret >= 0)
1267 return ret;
1268
1269 /* Fallback to PIO mode */
Boris Brezillona55abb32018-12-15 09:24:33 +01001270 return sunxi_nfc_hw_ecc_read_subpage(nand, data_offs, readlen,
Boris Brezillon614049a2016-04-15 15:10:30 +02001271 buf, page);
1272}
1273
Boris Brezillona55abb32018-12-15 09:24:33 +01001274static int sunxi_nfc_hw_ecc_write_page(struct nand_chip *nand,
Boris BREZILLON45aaeff2015-10-13 11:22:18 +02001275 const uint8_t *buf, int oob_required,
1276 int page)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001277{
Boris Brezillona55abb32018-12-15 09:24:33 +01001278 struct mtd_info *mtd = nand_to_mtd(nand);
1279 struct nand_ecc_ctrl *ecc = &nand->ecc;
Boris BREZILLONb4625512015-09-30 23:45:25 +02001280 int ret, i, cur_off = 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001281
Boris Brezillona55abb32018-12-15 09:24:33 +01001282 nand_prog_page_begin_op(nand, page, 0, NULL, 0);
Boris Brezillon25f815f2017-11-30 18:01:30 +01001283
Boris Brezilloncde567e2018-12-15 09:24:34 +01001284 sunxi_nfc_hw_ecc_enable(nand);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001285
1286 for (i = 0; i < ecc->steps; i++) {
Boris BREZILLONb4625512015-09-30 23:45:25 +02001287 int data_off = i * ecc->size;
1288 int oob_off = i * (ecc->bytes + 4);
1289 const u8 *data = buf + data_off;
Boris Brezillona55abb32018-12-15 09:24:33 +01001290 const u8 *oob = nand->oob_poi + oob_off;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001291
Boris Brezilloncde567e2018-12-15 09:24:34 +01001292 ret = sunxi_nfc_hw_ecc_write_chunk(nand, data, data_off, oob,
Boris BREZILLONb4625512015-09-30 23:45:25 +02001293 oob_off + mtd->writesize,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001294 &cur_off, !i, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001295 if (ret)
1296 return ret;
1297 }
1298
Boris Brezillona55abb32018-12-15 09:24:33 +01001299 if (oob_required || (nand->options & NAND_NEED_SCRAMBLING))
Boris Brezilloncde567e2018-12-15 09:24:34 +01001300 sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001301 &cur_off, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001302
Boris Brezilloncde567e2018-12-15 09:24:34 +01001303 sunxi_nfc_hw_ecc_disable(nand);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001304
Boris Brezillona55abb32018-12-15 09:24:33 +01001305 return nand_prog_page_end_op(nand);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001306}
1307
Boris Brezillona55abb32018-12-15 09:24:33 +01001308static int sunxi_nfc_hw_ecc_write_subpage(struct nand_chip *nand,
Boris Brezillon03b1d112016-06-06 13:59:14 +02001309 u32 data_offs, u32 data_len,
1310 const u8 *buf, int oob_required,
1311 int page)
1312{
Boris Brezillona55abb32018-12-15 09:24:33 +01001313 struct mtd_info *mtd = nand_to_mtd(nand);
1314 struct nand_ecc_ctrl *ecc = &nand->ecc;
Boris Brezillon03b1d112016-06-06 13:59:14 +02001315 int ret, i, cur_off = 0;
1316
Boris Brezillona55abb32018-12-15 09:24:33 +01001317 nand_prog_page_begin_op(nand, page, 0, NULL, 0);
Boris Brezillon25f815f2017-11-30 18:01:30 +01001318
Boris Brezilloncde567e2018-12-15 09:24:34 +01001319 sunxi_nfc_hw_ecc_enable(nand);
Boris Brezillon03b1d112016-06-06 13:59:14 +02001320
1321 for (i = data_offs / ecc->size;
1322 i < DIV_ROUND_UP(data_offs + data_len, ecc->size); i++) {
1323 int data_off = i * ecc->size;
1324 int oob_off = i * (ecc->bytes + 4);
1325 const u8 *data = buf + data_off;
Boris Brezillona55abb32018-12-15 09:24:33 +01001326 const u8 *oob = nand->oob_poi + oob_off;
Boris Brezillon03b1d112016-06-06 13:59:14 +02001327
Boris Brezilloncde567e2018-12-15 09:24:34 +01001328 ret = sunxi_nfc_hw_ecc_write_chunk(nand, data, data_off, oob,
Boris Brezillon03b1d112016-06-06 13:59:14 +02001329 oob_off + mtd->writesize,
1330 &cur_off, !i, page);
1331 if (ret)
1332 return ret;
1333 }
1334
Boris Brezilloncde567e2018-12-15 09:24:34 +01001335 sunxi_nfc_hw_ecc_disable(nand);
Boris Brezillon03b1d112016-06-06 13:59:14 +02001336
Boris Brezillona55abb32018-12-15 09:24:33 +01001337 return nand_prog_page_end_op(nand);
Boris Brezillon03b1d112016-06-06 13:59:14 +02001338}
1339
Boris Brezillona55abb32018-12-15 09:24:33 +01001340static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *nand,
Boris Brezillon614049a2016-04-15 15:10:30 +02001341 const u8 *buf,
1342 int oob_required,
1343 int page)
1344{
Boris Brezillon614049a2016-04-15 15:10:30 +02001345 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
1346 struct nand_ecc_ctrl *ecc = &nand->ecc;
1347 struct scatterlist sg;
1348 int ret, i;
1349
1350 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
1351 if (ret)
1352 return ret;
1353
Boris Brezilloncde567e2018-12-15 09:24:34 +01001354 ret = sunxi_nfc_dma_op_prepare(nfc, buf, ecc->size, ecc->steps,
Boris Brezillon614049a2016-04-15 15:10:30 +02001355 DMA_TO_DEVICE, &sg);
1356 if (ret)
1357 goto pio_fallback;
1358
1359 for (i = 0; i < ecc->steps; i++) {
1360 const u8 *oob = nand->oob_poi + (i * (ecc->bytes + 4));
1361
Boris Brezilloncde567e2018-12-15 09:24:34 +01001362 sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, i, !i, page);
Boris Brezillon614049a2016-04-15 15:10:30 +02001363 }
1364
Boris Brezillona55abb32018-12-15 09:24:33 +01001365 nand_prog_page_begin_op(nand, page, 0, NULL, 0);
Boris Brezillon25f815f2017-11-30 18:01:30 +01001366
Boris Brezilloncde567e2018-12-15 09:24:34 +01001367 sunxi_nfc_hw_ecc_enable(nand);
1368 sunxi_nfc_randomizer_config(nand, page, false);
1369 sunxi_nfc_randomizer_enable(nand);
Boris Brezillon614049a2016-04-15 15:10:30 +02001370
1371 writel((NAND_CMD_RNDIN << 8) | NAND_CMD_PAGEPROG,
Boris Brezillon73277442018-12-16 09:34:17 +01001372 nfc->regs + NFC_REG_WCMD_SET);
Boris Brezillon614049a2016-04-15 15:10:30 +02001373
1374 dma_async_issue_pending(nfc->dmac);
1375
1376 writel(NFC_PAGE_OP | NFC_DATA_SWAP_METHOD |
1377 NFC_DATA_TRANS | NFC_ACCESS_DIR,
1378 nfc->regs + NFC_REG_CMD);
1379
Boris Brezillon8de15e12017-01-06 10:42:06 +01001380 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, false, 0);
Boris Brezillon614049a2016-04-15 15:10:30 +02001381 if (ret)
1382 dmaengine_terminate_all(nfc->dmac);
1383
Boris Brezilloncde567e2018-12-15 09:24:34 +01001384 sunxi_nfc_randomizer_disable(nand);
1385 sunxi_nfc_hw_ecc_disable(nand);
Boris Brezillon614049a2016-04-15 15:10:30 +02001386
Boris Brezilloncde567e2018-12-15 09:24:34 +01001387 sunxi_nfc_dma_op_cleanup(nfc, DMA_TO_DEVICE, &sg);
Boris Brezillon614049a2016-04-15 15:10:30 +02001388
1389 if (ret)
1390 return ret;
1391
Boris Brezillona55abb32018-12-15 09:24:33 +01001392 if (oob_required || (nand->options & NAND_NEED_SCRAMBLING))
Boris Brezillon614049a2016-04-15 15:10:30 +02001393 /* TODO: use DMA to transfer extra OOB bytes ? */
Boris Brezilloncde567e2018-12-15 09:24:34 +01001394 sunxi_nfc_hw_ecc_write_extra_oob(nand, nand->oob_poi,
Boris Brezillon614049a2016-04-15 15:10:30 +02001395 NULL, page);
1396
Boris Brezillona55abb32018-12-15 09:24:33 +01001397 return nand_prog_page_end_op(nand);
Boris Brezillon614049a2016-04-15 15:10:30 +02001398
1399pio_fallback:
Boris Brezillona55abb32018-12-15 09:24:33 +01001400 return sunxi_nfc_hw_ecc_write_page(nand, buf, oob_required, page);
Boris Brezillon614049a2016-04-15 15:10:30 +02001401}
1402
Boris Brezillona55abb32018-12-15 09:24:33 +01001403static int sunxi_nfc_hw_ecc_read_oob(struct nand_chip *nand, int page)
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001404{
Boris Brezillona55abb32018-12-15 09:24:33 +01001405 nand->pagebuf = -1;
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001406
Boris Brezillona55abb32018-12-15 09:24:33 +01001407 return nand->ecc.read_page(nand, nand->data_buf, 1, page);
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001408}
1409
Boris Brezillona55abb32018-12-15 09:24:33 +01001410static int sunxi_nfc_hw_ecc_write_oob(struct nand_chip *nand, int page)
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001411{
Boris Brezillona55abb32018-12-15 09:24:33 +01001412 struct mtd_info *mtd = nand_to_mtd(nand);
Boris Brezillon97d90da2017-11-30 18:01:29 +01001413 int ret;
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001414
Boris Brezillona55abb32018-12-15 09:24:33 +01001415 nand->pagebuf = -1;
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001416
Boris Brezillona55abb32018-12-15 09:24:33 +01001417 memset(nand->data_buf, 0xff, mtd->writesize);
1418 ret = nand->ecc.write_page(nand, nand->data_buf, 1, page);
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001419 if (ret)
1420 return ret;
1421
1422 /* Send command to program the OOB data */
Boris Brezillona55abb32018-12-15 09:24:33 +01001423 return nand_prog_page_end_op(nand);
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001424}
1425
Roy Spliet9c618292015-06-26 11:00:10 +02001426static const s32 tWB_lut[] = {6, 12, 16, 20};
1427static const s32 tRHW_lut[] = {4, 8, 12, 20};
1428
1429static int _sunxi_nand_lookup_timing(const s32 *lut, int lut_size, u32 duration,
1430 u32 clk_period)
1431{
1432 u32 clk_cycles = DIV_ROUND_UP(duration, clk_period);
1433 int i;
1434
1435 for (i = 0; i < lut_size; i++) {
1436 if (clk_cycles <= lut[i])
1437 return i;
1438 }
1439
1440 /* Doesn't fit */
1441 return -EINVAL;
1442}
1443
1444#define sunxi_nand_lookup_timing(l, p, c) \
1445 _sunxi_nand_lookup_timing(l, ARRAY_SIZE(l), p, c)
1446
Boris Brezillon858838b2018-09-06 14:05:33 +02001447static int sunxi_nfc_setup_data_interface(struct nand_chip *nand, int csline,
Boris Brezillon104e4422017-03-16 09:35:58 +01001448 const struct nand_data_interface *conf)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001449{
Boris Brezillonf385ebf2018-12-15 09:24:31 +01001450 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
1451 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
Sascha Hauer907f45f2016-09-15 10:32:51 +02001452 const struct nand_sdr_timings *timings;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001453 u32 min_clk_period = 0;
Roy Spliet9c618292015-06-26 11:00:10 +02001454 s32 tWB, tADL, tWHR, tRHW, tCAD;
Boris Brezillon2d434572015-12-02 15:57:20 +01001455 long real_clk_rate;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001456
Sascha Hauer907f45f2016-09-15 10:32:51 +02001457 timings = nand_get_sdr_timings(conf);
1458 if (IS_ERR(timings))
1459 return -ENOTSUPP;
1460
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001461 /* T1 <=> tCLS */
1462 if (timings->tCLS_min > min_clk_period)
1463 min_clk_period = timings->tCLS_min;
1464
1465 /* T2 <=> tCLH */
1466 if (timings->tCLH_min > min_clk_period)
1467 min_clk_period = timings->tCLH_min;
1468
1469 /* T3 <=> tCS */
1470 if (timings->tCS_min > min_clk_period)
1471 min_clk_period = timings->tCS_min;
1472
1473 /* T4 <=> tCH */
1474 if (timings->tCH_min > min_clk_period)
1475 min_clk_period = timings->tCH_min;
1476
1477 /* T5 <=> tWP */
1478 if (timings->tWP_min > min_clk_period)
1479 min_clk_period = timings->tWP_min;
1480
1481 /* T6 <=> tWH */
1482 if (timings->tWH_min > min_clk_period)
1483 min_clk_period = timings->tWH_min;
1484
1485 /* T7 <=> tALS */
1486 if (timings->tALS_min > min_clk_period)
1487 min_clk_period = timings->tALS_min;
1488
1489 /* T8 <=> tDS */
1490 if (timings->tDS_min > min_clk_period)
1491 min_clk_period = timings->tDS_min;
1492
1493 /* T9 <=> tDH */
1494 if (timings->tDH_min > min_clk_period)
1495 min_clk_period = timings->tDH_min;
1496
1497 /* T10 <=> tRR */
1498 if (timings->tRR_min > (min_clk_period * 3))
1499 min_clk_period = DIV_ROUND_UP(timings->tRR_min, 3);
1500
1501 /* T11 <=> tALH */
1502 if (timings->tALH_min > min_clk_period)
1503 min_clk_period = timings->tALH_min;
1504
1505 /* T12 <=> tRP */
1506 if (timings->tRP_min > min_clk_period)
1507 min_clk_period = timings->tRP_min;
1508
1509 /* T13 <=> tREH */
1510 if (timings->tREH_min > min_clk_period)
1511 min_clk_period = timings->tREH_min;
1512
1513 /* T14 <=> tRC */
1514 if (timings->tRC_min > (min_clk_period * 2))
1515 min_clk_period = DIV_ROUND_UP(timings->tRC_min, 2);
1516
1517 /* T15 <=> tWC */
1518 if (timings->tWC_min > (min_clk_period * 2))
1519 min_clk_period = DIV_ROUND_UP(timings->tWC_min, 2);
1520
Roy Spliet9c618292015-06-26 11:00:10 +02001521 /* T16 - T19 + tCAD */
Boris Brezillon5abcd952015-11-11 22:30:30 +01001522 if (timings->tWB_max > (min_clk_period * 20))
1523 min_clk_period = DIV_ROUND_UP(timings->tWB_max, 20);
1524
1525 if (timings->tADL_min > (min_clk_period * 32))
1526 min_clk_period = DIV_ROUND_UP(timings->tADL_min, 32);
1527
1528 if (timings->tWHR_min > (min_clk_period * 32))
1529 min_clk_period = DIV_ROUND_UP(timings->tWHR_min, 32);
1530
1531 if (timings->tRHW_min > (min_clk_period * 20))
1532 min_clk_period = DIV_ROUND_UP(timings->tRHW_min, 20);
1533
Roy Spliet9c618292015-06-26 11:00:10 +02001534 tWB = sunxi_nand_lookup_timing(tWB_lut, timings->tWB_max,
1535 min_clk_period);
1536 if (tWB < 0) {
1537 dev_err(nfc->dev, "unsupported tWB\n");
1538 return tWB;
1539 }
1540
1541 tADL = DIV_ROUND_UP(timings->tADL_min, min_clk_period) >> 3;
1542 if (tADL > 3) {
1543 dev_err(nfc->dev, "unsupported tADL\n");
1544 return -EINVAL;
1545 }
1546
1547 tWHR = DIV_ROUND_UP(timings->tWHR_min, min_clk_period) >> 3;
1548 if (tWHR > 3) {
1549 dev_err(nfc->dev, "unsupported tWHR\n");
1550 return -EINVAL;
1551 }
1552
1553 tRHW = sunxi_nand_lookup_timing(tRHW_lut, timings->tRHW_min,
1554 min_clk_period);
1555 if (tRHW < 0) {
1556 dev_err(nfc->dev, "unsupported tRHW\n");
1557 return tRHW;
1558 }
1559
Boris Brezillon104e4422017-03-16 09:35:58 +01001560 if (csline == NAND_DATA_IFACE_CHECK_ONLY)
Sascha Hauer907f45f2016-09-15 10:32:51 +02001561 return 0;
1562
Roy Spliet9c618292015-06-26 11:00:10 +02001563 /*
1564 * TODO: according to ONFI specs this value only applies for DDR NAND,
1565 * but Allwinner seems to set this to 0x7. Mimic them for now.
1566 */
1567 tCAD = 0x7;
1568
1569 /* TODO: A83 has some more bits for CDQSS, CS, CLHZ, CCS, WC */
Boris Brezillonf385ebf2018-12-15 09:24:31 +01001570 sunxi_nand->timing_cfg = NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001571
1572 /* Convert min_clk_period from picoseconds to nanoseconds */
1573 min_clk_period = DIV_ROUND_UP(min_clk_period, 1000);
1574
1575 /*
Boris Brezillon2f9992e2015-12-02 15:10:40 +01001576 * Unlike what is stated in Allwinner datasheet, the clk_rate should
1577 * be set to (1 / min_clk_period), and not (2 / min_clk_period).
1578 * This new formula was verified with a scope and validated by
1579 * Allwinner engineers.
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001580 */
Boris Brezillonf385ebf2018-12-15 09:24:31 +01001581 sunxi_nand->clk_rate = NSEC_PER_SEC / min_clk_period;
1582 real_clk_rate = clk_round_rate(nfc->mod_clk, sunxi_nand->clk_rate);
Bryan O'Donoghue791eccd2017-07-28 14:22:57 +01001583 if (real_clk_rate <= 0) {
Boris Brezillonf385ebf2018-12-15 09:24:31 +01001584 dev_err(nfc->dev, "Unable to round clk %lu\n",
1585 sunxi_nand->clk_rate);
Bryan O'Donoghue791eccd2017-07-28 14:22:57 +01001586 return -EINVAL;
1587 }
Boris Brezillon2d434572015-12-02 15:57:20 +01001588
1589 /*
1590 * ONFI specification 3.1, paragraph 4.15.2 dictates that EDO data
1591 * output cycle timings shall be used if the host drives tRC less than
1592 * 30 ns.
1593 */
1594 min_clk_period = NSEC_PER_SEC / real_clk_rate;
Boris Brezillonf385ebf2018-12-15 09:24:31 +01001595 sunxi_nand->timing_ctl = ((min_clk_period * 2) < 30) ?
1596 NFC_TIMING_CTL_EDO : 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001597
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001598 return 0;
1599}
1600
Boris Brezillonc66811e2016-02-03 20:05:13 +01001601static int sunxi_nand_ooblayout_ecc(struct mtd_info *mtd, int section,
1602 struct mtd_oob_region *oobregion)
1603{
1604 struct nand_chip *nand = mtd_to_nand(mtd);
1605 struct nand_ecc_ctrl *ecc = &nand->ecc;
1606
1607 if (section >= ecc->steps)
1608 return -ERANGE;
1609
1610 oobregion->offset = section * (ecc->bytes + 4) + 4;
1611 oobregion->length = ecc->bytes;
1612
1613 return 0;
1614}
1615
1616static int sunxi_nand_ooblayout_free(struct mtd_info *mtd, int section,
1617 struct mtd_oob_region *oobregion)
1618{
1619 struct nand_chip *nand = mtd_to_nand(mtd);
1620 struct nand_ecc_ctrl *ecc = &nand->ecc;
1621
1622 if (section > ecc->steps)
1623 return -ERANGE;
1624
1625 /*
1626 * The first 2 bytes are used for BB markers, hence we
1627 * only have 2 bytes available in the first user data
1628 * section.
1629 */
1630 if (!section && ecc->mode == NAND_ECC_HW) {
1631 oobregion->offset = 2;
1632 oobregion->length = 2;
1633
1634 return 0;
1635 }
1636
1637 oobregion->offset = section * (ecc->bytes + 4);
1638
1639 if (section < ecc->steps)
1640 oobregion->length = 4;
1641 else
1642 oobregion->offset = mtd->oobsize - oobregion->offset;
1643
1644 return 0;
1645}
1646
1647static const struct mtd_ooblayout_ops sunxi_nand_ooblayout_ops = {
1648 .ecc = sunxi_nand_ooblayout_ecc,
1649 .free = sunxi_nand_ooblayout_free,
1650};
1651
Boris Brezillon15d6f112018-03-21 09:36:18 +01001652static void sunxi_nand_hw_ecc_ctrl_cleanup(struct nand_ecc_ctrl *ecc)
1653{
1654 kfree(ecc->priv);
1655}
1656
Boris Brezilloncde567e2018-12-15 09:24:34 +01001657static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand,
Boris Brezillon15d6f112018-03-21 09:36:18 +01001658 struct nand_ecc_ctrl *ecc,
1659 struct device_node *np)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001660{
1661 static const u8 strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 };
Boris Brezilloncde567e2018-12-15 09:24:34 +01001662 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
1663 struct mtd_info *mtd = nand_to_mtd(nand);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001664 struct sunxi_nand_hw_ecc *data;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001665 int nsectors;
1666 int ret;
1667 int i;
1668
Boris Brezillon4796d862016-06-08 17:04:24 +02001669 if (ecc->options & NAND_ECC_MAXIMIZE) {
1670 int bytes;
1671
1672 ecc->size = 1024;
1673 nsectors = mtd->writesize / ecc->size;
1674
1675 /* Reserve 2 bytes for the BBM */
1676 bytes = (mtd->oobsize - 2) / nsectors;
1677
1678 /* 4 non-ECC bytes are added before each ECC bytes section */
1679 bytes -= 4;
1680
1681 /* and bytes has to be even. */
1682 if (bytes % 2)
1683 bytes--;
1684
1685 ecc->strength = bytes * 8 / fls(8 * ecc->size);
1686
1687 for (i = 0; i < ARRAY_SIZE(strengths); i++) {
1688 if (strengths[i] > ecc->strength)
1689 break;
1690 }
1691
1692 if (!i)
1693 ecc->strength = 0;
1694 else
1695 ecc->strength = strengths[i - 1];
1696 }
1697
Dan Carpenter40297e72016-06-24 15:24:03 +03001698 if (ecc->size != 512 && ecc->size != 1024)
1699 return -EINVAL;
1700
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001701 data = kzalloc(sizeof(*data), GFP_KERNEL);
1702 if (!data)
1703 return -ENOMEM;
1704
Boris Brezillon872164e2016-06-06 13:59:12 +02001705 /* Prefer 1k ECC chunk over 512 ones */
1706 if (ecc->size == 512 && mtd->writesize > 512) {
1707 ecc->size = 1024;
1708 ecc->strength *= 2;
1709 }
1710
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001711 /* Add ECC info retrieval from DT */
1712 for (i = 0; i < ARRAY_SIZE(strengths); i++) {
Miquel Raynalf4c6cd12018-01-24 23:49:31 +01001713 if (ecc->strength <= strengths[i]) {
1714 /*
1715 * Update ecc->strength value with the actual strength
1716 * that will be used by the ECC engine.
1717 */
1718 ecc->strength = strengths[i];
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001719 break;
Miquel Raynalf4c6cd12018-01-24 23:49:31 +01001720 }
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001721 }
1722
1723 if (i >= ARRAY_SIZE(strengths)) {
1724 dev_err(nfc->dev, "unsupported strength\n");
1725 ret = -ENOTSUPP;
1726 goto err;
1727 }
1728
1729 data->mode = i;
1730
1731 /* HW ECC always request ECC bytes for 1024 bytes blocks */
1732 ecc->bytes = DIV_ROUND_UP(ecc->strength * fls(8 * 1024), 8);
1733
1734 /* HW ECC always work with even numbers of ECC bytes */
1735 ecc->bytes = ALIGN(ecc->bytes, 2);
1736
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001737 nsectors = mtd->writesize / ecc->size;
1738
1739 if (mtd->oobsize < ((ecc->bytes + 4) * nsectors)) {
1740 ret = -EINVAL;
1741 goto err;
1742 }
1743
Boris Brezillon15d6f112018-03-21 09:36:18 +01001744 ecc->read_oob = sunxi_nfc_hw_ecc_read_oob;
1745 ecc->write_oob = sunxi_nfc_hw_ecc_write_oob;
Boris Brezillonc66811e2016-02-03 20:05:13 +01001746 mtd_set_ooblayout(mtd, &sunxi_nand_ooblayout_ops);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001747 ecc->priv = data;
1748
Boris Brezillon614049a2016-04-15 15:10:30 +02001749 if (nfc->dmac) {
1750 ecc->read_page = sunxi_nfc_hw_ecc_read_page_dma;
1751 ecc->read_subpage = sunxi_nfc_hw_ecc_read_subpage_dma;
1752 ecc->write_page = sunxi_nfc_hw_ecc_write_page_dma;
1753 nand->options |= NAND_USE_BOUNCE_BUFFER;
1754 } else {
1755 ecc->read_page = sunxi_nfc_hw_ecc_read_page;
1756 ecc->read_subpage = sunxi_nfc_hw_ecc_read_subpage;
1757 ecc->write_page = sunxi_nfc_hw_ecc_write_page;
1758 }
1759
Boris Brezillon03b1d112016-06-06 13:59:14 +02001760 /* TODO: support DMA for raw accesses and subpage write */
1761 ecc->write_subpage = sunxi_nfc_hw_ecc_write_subpage;
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001762 ecc->read_oob_raw = nand_read_oob_std;
1763 ecc->write_oob_raw = nand_write_oob_std;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001764
1765 return 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001766
Boris Brezillon15d6f112018-03-21 09:36:18 +01001767err:
1768 kfree(data);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001769
Boris Brezillon15d6f112018-03-21 09:36:18 +01001770 return ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001771}
1772
1773static void sunxi_nand_ecc_cleanup(struct nand_ecc_ctrl *ecc)
1774{
1775 switch (ecc->mode) {
1776 case NAND_ECC_HW:
Boris Brezillon15d6f112018-03-21 09:36:18 +01001777 sunxi_nand_hw_ecc_ctrl_cleanup(ecc);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001778 break;
1779 case NAND_ECC_NONE:
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001780 default:
1781 break;
1782 }
1783}
1784
Miquel Raynal2a4d9c12018-07-20 17:15:13 +02001785static int sunxi_nand_attach_chip(struct nand_chip *nand)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001786{
Miquel Raynal2a4d9c12018-07-20 17:15:13 +02001787 struct nand_ecc_ctrl *ecc = &nand->ecc;
1788 struct device_node *np = nand_get_flash_node(nand);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001789 int ret;
1790
Miquel Raynal2a4d9c12018-07-20 17:15:13 +02001791 if (nand->bbt_options & NAND_BBT_USE_FLASH)
1792 nand->bbt_options |= NAND_BBT_NO_OOB;
1793
1794 if (nand->options & NAND_NEED_SCRAMBLING)
1795 nand->options |= NAND_NO_SUBPAGE_WRITE;
1796
1797 nand->options |= NAND_SUBPAGE_READ;
1798
Boris BREZILLONa3d22a52015-09-02 10:30:25 +02001799 if (!ecc->size) {
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001800 ecc->size = nand->ecc_step_ds;
1801 ecc->strength = nand->ecc_strength_ds;
1802 }
1803
1804 if (!ecc->size || !ecc->strength)
1805 return -EINVAL;
1806
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001807 switch (ecc->mode) {
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001808 case NAND_ECC_HW:
Boris Brezilloncde567e2018-12-15 09:24:34 +01001809 ret = sunxi_nand_hw_ecc_ctrl_init(nand, ecc, np);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001810 if (ret)
1811 return ret;
1812 break;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001813 case NAND_ECC_NONE:
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001814 case NAND_ECC_SOFT:
1815 break;
1816 default:
1817 return -EINVAL;
1818 }
1819
1820 return 0;
1821}
1822
Miquel Raynal2a4d9c12018-07-20 17:15:13 +02001823static const struct nand_controller_ops sunxi_nand_controller_ops = {
1824 .attach_chip = sunxi_nand_attach_chip,
Boris Brezillon7a08dba2018-11-11 08:55:24 +01001825 .setup_data_interface = sunxi_nfc_setup_data_interface,
Miquel Raynal2a4d9c12018-07-20 17:15:13 +02001826};
1827
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001828static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
1829 struct device_node *np)
1830{
Boris Brezillonf385ebf2018-12-15 09:24:31 +01001831 struct sunxi_nand_chip *sunxi_nand;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001832 struct mtd_info *mtd;
1833 struct nand_chip *nand;
1834 int nsels;
1835 int ret;
1836 int i;
1837 u32 tmp;
1838
1839 if (!of_get_property(np, "reg", &nsels))
1840 return -EINVAL;
1841
1842 nsels /= sizeof(u32);
1843 if (!nsels) {
1844 dev_err(dev, "invalid reg property size\n");
1845 return -EINVAL;
1846 }
1847
Boris Brezillon6c721ac2018-12-15 09:24:32 +01001848 sunxi_nand = devm_kzalloc(dev, struct_size(sunxi_nand, sels, nsels),
Boris Brezillonf385ebf2018-12-15 09:24:31 +01001849 GFP_KERNEL);
1850 if (!sunxi_nand) {
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001851 dev_err(dev, "could not allocate chip\n");
1852 return -ENOMEM;
1853 }
1854
Boris Brezillonf385ebf2018-12-15 09:24:31 +01001855 sunxi_nand->nsels = nsels;
1856 sunxi_nand->selected = -1;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001857
1858 for (i = 0; i < nsels; i++) {
1859 ret = of_property_read_u32_index(np, "reg", i, &tmp);
1860 if (ret) {
1861 dev_err(dev, "could not retrieve reg property: %d\n",
1862 ret);
1863 return ret;
1864 }
1865
1866 if (tmp > NFC_MAX_CS) {
1867 dev_err(dev,
1868 "invalid reg value: %u (max CS = 7)\n",
1869 tmp);
1870 return -EINVAL;
1871 }
1872
1873 if (test_and_set_bit(tmp, &nfc->assigned_cs)) {
1874 dev_err(dev, "CS %d already assigned\n", tmp);
1875 return -EINVAL;
1876 }
1877
Boris Brezillonf385ebf2018-12-15 09:24:31 +01001878 sunxi_nand->sels[i].cs = tmp;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001879
1880 if (!of_property_read_u32_index(np, "allwinner,rb", i, &tmp) &&
Boris Brezillonddd5ed32018-03-27 09:06:14 +02001881 tmp < 2)
Boris Brezillonf385ebf2018-12-15 09:24:31 +01001882 sunxi_nand->sels[i].rb = tmp;
Boris Brezillonddd5ed32018-03-27 09:06:14 +02001883 else
Boris Brezillonf385ebf2018-12-15 09:24:31 +01001884 sunxi_nand->sels[i].rb = -1;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001885 }
1886
Boris Brezillonf385ebf2018-12-15 09:24:31 +01001887 nand = &sunxi_nand->nand;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001888 /* Default tR value specified in the ONFI spec (chapter 4.15.1) */
Boris Brezillon3cece3a2018-09-07 00:38:41 +02001889 nand->legacy.chip_delay = 200;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001890 nand->controller = &nfc->controller;
Miquel Raynal2a4d9c12018-07-20 17:15:13 +02001891 nand->controller->ops = &sunxi_nand_controller_ops;
1892
Boris BREZILLONa3d22a52015-09-02 10:30:25 +02001893 /*
1894 * Set the ECC mode to the default value in case nothing is specified
1895 * in the DT.
1896 */
1897 nand->ecc.mode = NAND_ECC_HW;
Brian Norris63752192015-10-30 20:33:23 -07001898 nand_set_flash_node(nand, np);
Boris Brezillon7d6c37e2018-11-11 08:55:22 +01001899 nand->legacy.select_chip = sunxi_nfc_select_chip;
Boris Brezillonbf6065c2018-09-07 00:38:36 +02001900 nand->legacy.cmd_ctrl = sunxi_nfc_cmd_ctrl;
Boris Brezillon716bbba2018-09-07 00:38:35 +02001901 nand->legacy.read_buf = sunxi_nfc_read_buf;
1902 nand->legacy.write_buf = sunxi_nfc_write_buf;
1903 nand->legacy.read_byte = sunxi_nfc_read_byte;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001904
Boris BREZILLON32e9f2d2015-12-10 09:00:26 +01001905 mtd = nand_to_mtd(nand);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001906 mtd->dev.parent = dev;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001907
Boris Brezillon00ad3782018-09-06 14:05:14 +02001908 ret = nand_scan(nand, nsels);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001909 if (ret)
1910 return ret;
1911
Brian Norrisa61ae812015-10-30 20:33:25 -07001912 ret = mtd_device_register(mtd, NULL, 0);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001913 if (ret) {
1914 dev_err(dev, "failed to register mtd device: %d\n", ret);
Boris Brezillon59ac2762018-09-06 14:05:15 +02001915 nand_release(nand);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001916 return ret;
1917 }
1918
Boris Brezillonf385ebf2018-12-15 09:24:31 +01001919 list_add_tail(&sunxi_nand->node, &nfc->chips);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001920
1921 return 0;
1922}
1923
1924static int sunxi_nand_chips_init(struct device *dev, struct sunxi_nfc *nfc)
1925{
1926 struct device_node *np = dev->of_node;
1927 struct device_node *nand_np;
1928 int nchips = of_get_child_count(np);
1929 int ret;
1930
1931 if (nchips > 8) {
1932 dev_err(dev, "too many NAND chips: %d (max = 8)\n", nchips);
1933 return -EINVAL;
1934 }
1935
1936 for_each_child_of_node(np, nand_np) {
1937 ret = sunxi_nand_chip_init(dev, nfc, nand_np);
Julia Lawalla81c0f02015-11-18 23:04:12 +01001938 if (ret) {
1939 of_node_put(nand_np);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001940 return ret;
Julia Lawalla81c0f02015-11-18 23:04:12 +01001941 }
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001942 }
1943
1944 return 0;
1945}
1946
1947static void sunxi_nand_chips_cleanup(struct sunxi_nfc *nfc)
1948{
Boris Brezillonf385ebf2018-12-15 09:24:31 +01001949 struct sunxi_nand_chip *sunxi_nand;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001950
1951 while (!list_empty(&nfc->chips)) {
Boris Brezillonf385ebf2018-12-15 09:24:31 +01001952 sunxi_nand = list_first_entry(&nfc->chips,
1953 struct sunxi_nand_chip,
1954 node);
1955 nand_release(&sunxi_nand->nand);
1956 sunxi_nand_ecc_cleanup(&sunxi_nand->nand.ecc);
1957 list_del(&sunxi_nand->node);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001958 }
1959}
1960
1961static int sunxi_nfc_probe(struct platform_device *pdev)
1962{
1963 struct device *dev = &pdev->dev;
1964 struct resource *r;
1965 struct sunxi_nfc *nfc;
1966 int irq;
1967 int ret;
1968
1969 nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
1970 if (!nfc)
1971 return -ENOMEM;
1972
1973 nfc->dev = dev;
Miquel Raynal7da45132018-07-17 09:08:02 +02001974 nand_controller_init(&nfc->controller);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001975 INIT_LIST_HEAD(&nfc->chips);
1976
1977 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1978 nfc->regs = devm_ioremap_resource(dev, r);
1979 if (IS_ERR(nfc->regs))
1980 return PTR_ERR(nfc->regs);
1981
1982 irq = platform_get_irq(pdev, 0);
1983 if (irq < 0) {
1984 dev_err(dev, "failed to retrieve irq\n");
1985 return irq;
1986 }
1987
1988 nfc->ahb_clk = devm_clk_get(dev, "ahb");
1989 if (IS_ERR(nfc->ahb_clk)) {
1990 dev_err(dev, "failed to retrieve ahb clk\n");
1991 return PTR_ERR(nfc->ahb_clk);
1992 }
1993
1994 ret = clk_prepare_enable(nfc->ahb_clk);
1995 if (ret)
1996 return ret;
1997
1998 nfc->mod_clk = devm_clk_get(dev, "mod");
1999 if (IS_ERR(nfc->mod_clk)) {
2000 dev_err(dev, "failed to retrieve mod clk\n");
2001 ret = PTR_ERR(nfc->mod_clk);
2002 goto out_ahb_clk_unprepare;
2003 }
2004
2005 ret = clk_prepare_enable(nfc->mod_clk);
2006 if (ret)
2007 goto out_ahb_clk_unprepare;
2008
Philipp Zabelfcf59f12017-07-19 17:25:46 +02002009 nfc->reset = devm_reset_control_get_optional_exclusive(dev, "ahb");
Philipp Zabel6b244bb2017-03-15 12:31:47 +01002010 if (IS_ERR(nfc->reset)) {
Icenowy Zhengab9d6a72016-06-20 12:48:38 +08002011 ret = PTR_ERR(nfc->reset);
2012 goto out_mod_clk_unprepare;
2013 }
2014
Philipp Zabel6b244bb2017-03-15 12:31:47 +01002015 ret = reset_control_deassert(nfc->reset);
2016 if (ret) {
2017 dev_err(dev, "reset err %d\n", ret);
2018 goto out_mod_clk_unprepare;
2019 }
2020
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002021 ret = sunxi_nfc_rst(nfc);
2022 if (ret)
Icenowy Zhengab9d6a72016-06-20 12:48:38 +08002023 goto out_ahb_reset_reassert;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002024
2025 writel(0, nfc->regs + NFC_REG_INT);
2026 ret = devm_request_irq(dev, irq, sunxi_nfc_interrupt,
2027 0, "sunxi-nand", nfc);
2028 if (ret)
Icenowy Zhengab9d6a72016-06-20 12:48:38 +08002029 goto out_ahb_reset_reassert;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002030
Boris Brezillon614049a2016-04-15 15:10:30 +02002031 nfc->dmac = dma_request_slave_channel(dev, "rxtx");
2032 if (nfc->dmac) {
2033 struct dma_slave_config dmac_cfg = { };
2034
2035 dmac_cfg.src_addr = r->start + NFC_REG_IO_DATA;
2036 dmac_cfg.dst_addr = dmac_cfg.src_addr;
2037 dmac_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
2038 dmac_cfg.dst_addr_width = dmac_cfg.src_addr_width;
2039 dmac_cfg.src_maxburst = 4;
2040 dmac_cfg.dst_maxburst = 4;
2041 dmaengine_slave_config(nfc->dmac, &dmac_cfg);
2042 } else {
2043 dev_warn(dev, "failed to request rxtx DMA channel\n");
2044 }
2045
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002046 platform_set_drvdata(pdev, nfc);
2047
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002048 ret = sunxi_nand_chips_init(dev, nfc);
2049 if (ret) {
2050 dev_err(dev, "failed to init nand chips\n");
Boris Brezillon614049a2016-04-15 15:10:30 +02002051 goto out_release_dmac;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002052 }
2053
2054 return 0;
2055
Boris Brezillon614049a2016-04-15 15:10:30 +02002056out_release_dmac:
2057 if (nfc->dmac)
2058 dma_release_channel(nfc->dmac);
Icenowy Zhengab9d6a72016-06-20 12:48:38 +08002059out_ahb_reset_reassert:
Philipp Zabel6b244bb2017-03-15 12:31:47 +01002060 reset_control_assert(nfc->reset);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002061out_mod_clk_unprepare:
2062 clk_disable_unprepare(nfc->mod_clk);
2063out_ahb_clk_unprepare:
2064 clk_disable_unprepare(nfc->ahb_clk);
2065
2066 return ret;
2067}
2068
2069static int sunxi_nfc_remove(struct platform_device *pdev)
2070{
2071 struct sunxi_nfc *nfc = platform_get_drvdata(pdev);
2072
2073 sunxi_nand_chips_cleanup(nfc);
Icenowy Zhengab9d6a72016-06-20 12:48:38 +08002074
Philipp Zabel6b244bb2017-03-15 12:31:47 +01002075 reset_control_assert(nfc->reset);
Icenowy Zhengab9d6a72016-06-20 12:48:38 +08002076
Boris Brezillon614049a2016-04-15 15:10:30 +02002077 if (nfc->dmac)
2078 dma_release_channel(nfc->dmac);
Boris Brezillondd26a452016-03-04 18:26:40 +01002079 clk_disable_unprepare(nfc->mod_clk);
2080 clk_disable_unprepare(nfc->ahb_clk);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002081
2082 return 0;
2083}
2084
2085static const struct of_device_id sunxi_nfc_ids[] = {
2086 { .compatible = "allwinner,sun4i-a10-nand" },
2087 { /* sentinel */ }
2088};
2089MODULE_DEVICE_TABLE(of, sunxi_nfc_ids);
2090
2091static struct platform_driver sunxi_nfc_driver = {
2092 .driver = {
2093 .name = "sunxi_nand",
2094 .of_match_table = sunxi_nfc_ids,
2095 },
2096 .probe = sunxi_nfc_probe,
2097 .remove = sunxi_nfc_remove,
2098};
2099module_platform_driver(sunxi_nfc_driver);
2100
Boris Brezillonf5f88872018-12-15 09:24:35 +01002101MODULE_LICENSE("GPL");
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02002102MODULE_AUTHOR("Boris BREZILLON");
2103MODULE_DESCRIPTION("Allwinner NAND Flash Controller driver");
2104MODULE_ALIAS("platform:sunxi_nand");