blob: 8be3dba07ff7e8d0c65239f6a2b7d7bb16a55682 [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>
34#include <linux/mtd/nand.h>
35#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>
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020042
43#define NFC_REG_CTL 0x0000
44#define NFC_REG_ST 0x0004
45#define NFC_REG_INT 0x0008
46#define NFC_REG_TIMING_CTL 0x000C
47#define NFC_REG_TIMING_CFG 0x0010
48#define NFC_REG_ADDR_LOW 0x0014
49#define NFC_REG_ADDR_HIGH 0x0018
50#define NFC_REG_SECTOR_NUM 0x001C
51#define NFC_REG_CNT 0x0020
52#define NFC_REG_CMD 0x0024
53#define NFC_REG_RCMD_SET 0x0028
54#define NFC_REG_WCMD_SET 0x002C
55#define NFC_REG_IO_DATA 0x0030
56#define NFC_REG_ECC_CTL 0x0034
57#define NFC_REG_ECC_ST 0x0038
58#define NFC_REG_DEBUG 0x003C
Boris BREZILLONb6a02c02015-09-16 09:46:36 +020059#define NFC_REG_ECC_ERR_CNT(x) ((0x0040 + (x)) & ~0x3)
60#define NFC_REG_USER_DATA(x) (0x0050 + ((x) * 4))
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020061#define NFC_REG_SPARE_AREA 0x00A0
Boris BREZILLON4be4e032015-12-02 12:01:07 +010062#define NFC_REG_PAT_ID 0x00A4
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020063#define NFC_RAM0_BASE 0x0400
64#define NFC_RAM1_BASE 0x0800
65
66/* define bit use in NFC_CTL */
67#define NFC_EN BIT(0)
68#define NFC_RESET BIT(1)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +020069#define NFC_BUS_WIDTH_MSK BIT(2)
70#define NFC_BUS_WIDTH_8 (0 << 2)
71#define NFC_BUS_WIDTH_16 (1 << 2)
72#define NFC_RB_SEL_MSK BIT(3)
73#define NFC_RB_SEL(x) ((x) << 3)
74#define NFC_CE_SEL_MSK GENMASK(26, 24)
75#define NFC_CE_SEL(x) ((x) << 24)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020076#define NFC_CE_CTL BIT(6)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +020077#define NFC_PAGE_SHIFT_MSK GENMASK(11, 8)
78#define NFC_PAGE_SHIFT(x) (((x) < 10 ? 0 : (x) - 10) << 8)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020079#define NFC_SAM BIT(12)
80#define NFC_RAM_METHOD BIT(14)
81#define NFC_DEBUG_CTL BIT(31)
82
83/* define bit use in NFC_ST */
84#define NFC_RB_B2R BIT(0)
85#define NFC_CMD_INT_FLAG BIT(1)
86#define NFC_DMA_INT_FLAG BIT(2)
87#define NFC_CMD_FIFO_STATUS BIT(3)
88#define NFC_STA BIT(4)
89#define NFC_NATCH_INT_FLAG BIT(5)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +020090#define NFC_RB_STATE(x) BIT(x + 8)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +020091
92/* define bit use in NFC_INT */
93#define NFC_B2R_INT_ENABLE BIT(0)
94#define NFC_CMD_INT_ENABLE BIT(1)
95#define NFC_DMA_INT_ENABLE BIT(2)
96#define NFC_INT_MASK (NFC_B2R_INT_ENABLE | \
97 NFC_CMD_INT_ENABLE | \
98 NFC_DMA_INT_ENABLE)
99
Roy Splietd052e502015-06-26 11:00:11 +0200100/* define bit use in NFC_TIMING_CTL */
101#define NFC_TIMING_CTL_EDO BIT(8)
102
Roy Spliet9c618292015-06-26 11:00:10 +0200103/* define NFC_TIMING_CFG register layout */
104#define NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD) \
105 (((tWB) & 0x3) | (((tADL) & 0x3) << 2) | \
106 (((tWHR) & 0x3) << 4) | (((tRHW) & 0x3) << 6) | \
107 (((tCAD) & 0x7) << 8))
108
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200109/* define bit use in NFC_CMD */
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200110#define NFC_CMD_LOW_BYTE_MSK GENMASK(7, 0)
111#define NFC_CMD_HIGH_BYTE_MSK GENMASK(15, 8)
112#define NFC_CMD(x) (x)
113#define NFC_ADR_NUM_MSK GENMASK(18, 16)
114#define NFC_ADR_NUM(x) (((x) - 1) << 16)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200115#define NFC_SEND_ADR BIT(19)
116#define NFC_ACCESS_DIR BIT(20)
117#define NFC_DATA_TRANS BIT(21)
118#define NFC_SEND_CMD1 BIT(22)
119#define NFC_WAIT_FLAG BIT(23)
120#define NFC_SEND_CMD2 BIT(24)
121#define NFC_SEQ BIT(25)
122#define NFC_DATA_SWAP_METHOD BIT(26)
123#define NFC_ROW_AUTO_INC BIT(27)
124#define NFC_SEND_CMD3 BIT(28)
125#define NFC_SEND_CMD4 BIT(29)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200126#define NFC_CMD_TYPE_MSK GENMASK(31, 30)
127#define NFC_NORMAL_OP (0 << 30)
128#define NFC_ECC_OP (1 << 30)
129#define NFC_PAGE_OP (2 << 30)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200130
131/* define bit use in NFC_RCMD_SET */
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200132#define NFC_READ_CMD_MSK GENMASK(7, 0)
133#define NFC_RND_READ_CMD0_MSK GENMASK(15, 8)
134#define NFC_RND_READ_CMD1_MSK GENMASK(23, 16)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200135
136/* define bit use in NFC_WCMD_SET */
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200137#define NFC_PROGRAM_CMD_MSK GENMASK(7, 0)
138#define NFC_RND_WRITE_CMD_MSK GENMASK(15, 8)
139#define NFC_READ_CMD0_MSK GENMASK(23, 16)
140#define NFC_READ_CMD1_MSK GENMASK(31, 24)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200141
142/* define bit use in NFC_ECC_CTL */
143#define NFC_ECC_EN BIT(0)
144#define NFC_ECC_PIPELINE BIT(3)
145#define NFC_ECC_EXCEPTION BIT(4)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200146#define NFC_ECC_BLOCK_SIZE_MSK BIT(5)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200147#define NFC_RANDOM_EN BIT(9)
148#define NFC_RANDOM_DIRECTION BIT(10)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200149#define NFC_ECC_MODE_MSK GENMASK(15, 12)
150#define NFC_ECC_MODE(x) ((x) << 12)
151#define NFC_RANDOM_SEED_MSK GENMASK(30, 16)
152#define NFC_RANDOM_SEED(x) ((x) << 16)
153
154/* define bit use in NFC_ECC_ST */
155#define NFC_ECC_ERR(x) BIT(x)
156#define NFC_ECC_PAT_FOUND(x) BIT(x + 16)
Boris Brezillonf8b04742016-03-04 17:25:08 +0100157#define NFC_ECC_ERR_CNT(b, x) (((x) >> (((b) % 4) * 8)) & 0xff)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200158
159#define NFC_DEFAULT_TIMEOUT_MS 1000
160
161#define NFC_SRAM_SIZE 1024
162
163#define NFC_MAX_CS 7
164
165/*
166 * Ready/Busy detection type: describes the Ready/Busy detection modes
167 *
168 * @RB_NONE: no external detection available, rely on STATUS command
169 * and software timeouts
170 * @RB_NATIVE: use sunxi NAND controller Ready/Busy support. The Ready/Busy
171 * pin of the NAND flash chip must be connected to one of the
172 * native NAND R/B pins (those which can be muxed to the NAND
173 * Controller)
174 * @RB_GPIO: use a simple GPIO to handle Ready/Busy status. The Ready/Busy
175 * pin of the NAND flash chip must be connected to a GPIO capable
176 * pin.
177 */
178enum sunxi_nand_rb_type {
179 RB_NONE,
180 RB_NATIVE,
181 RB_GPIO,
182};
183
184/*
185 * Ready/Busy structure: stores information related to Ready/Busy detection
186 *
187 * @type: the Ready/Busy detection mode
188 * @info: information related to the R/B detection mode. Either a gpio
189 * id or a native R/B id (those supported by the NAND controller).
190 */
191struct sunxi_nand_rb {
192 enum sunxi_nand_rb_type type;
193 union {
194 int gpio;
195 int nativeid;
196 } info;
197};
198
199/*
200 * Chip Select structure: stores information related to NAND Chip Select
201 *
202 * @cs: the NAND CS id used to communicate with a NAND Chip
203 * @rb: the Ready/Busy description
204 */
205struct sunxi_nand_chip_sel {
206 u8 cs;
207 struct sunxi_nand_rb rb;
208};
209
210/*
211 * sunxi HW ECC infos: stores information related to HW ECC support
212 *
213 * @mode: the sunxi ECC mode field deduced from ECC requirements
214 * @layout: the OOB layout depending on the ECC requirements and the
215 * selected ECC mode
216 */
217struct sunxi_nand_hw_ecc {
218 int mode;
219 struct nand_ecclayout layout;
220};
221
222/*
223 * NAND chip structure: stores NAND chip device related information
224 *
225 * @node: used to store NAND chips into a list
226 * @nand: base NAND chip structure
227 * @mtd: base MTD structure
228 * @clk_rate: clk_rate required for this NAND chip
Roy Spliet9c618292015-06-26 11:00:10 +0200229 * @timing_cfg TIMING_CFG register value for this NAND chip
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200230 * @selected: current active CS
231 * @nsels: number of CS lines required by the NAND chip
232 * @sels: array of CS lines descriptions
233 */
234struct sunxi_nand_chip {
235 struct list_head node;
236 struct nand_chip nand;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200237 unsigned long clk_rate;
Roy Spliet9c618292015-06-26 11:00:10 +0200238 u32 timing_cfg;
Roy Splietd052e502015-06-26 11:00:11 +0200239 u32 timing_ctl;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200240 int selected;
Boris Brezillone9aa6712015-09-16 09:05:31 +0200241 int addr_cycles;
242 u32 addr[2];
243 int cmd_cycles;
244 u8 cmd[2];
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200245 int nsels;
246 struct sunxi_nand_chip_sel sels[0];
247};
248
249static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
250{
251 return container_of(nand, struct sunxi_nand_chip, nand);
252}
253
254/*
255 * NAND Controller structure: stores sunxi NAND controller information
256 *
257 * @controller: base controller structure
258 * @dev: parent device (used to print error messages)
259 * @regs: NAND controller registers
260 * @ahb_clk: NAND Controller AHB clock
261 * @mod_clk: NAND Controller mod clock
262 * @assigned_cs: bitmask describing already assigned CS lines
263 * @clk_rate: NAND controller current clock rate
264 * @chips: a list containing all the NAND chips attached to
265 * this NAND controller
266 * @complete: a completion object used to wait for NAND
267 * controller events
268 */
269struct sunxi_nfc {
270 struct nand_hw_control controller;
271 struct device *dev;
272 void __iomem *regs;
273 struct clk *ahb_clk;
274 struct clk *mod_clk;
275 unsigned long assigned_cs;
276 unsigned long clk_rate;
277 struct list_head chips;
278 struct completion complete;
279};
280
281static inline struct sunxi_nfc *to_sunxi_nfc(struct nand_hw_control *ctrl)
282{
283 return container_of(ctrl, struct sunxi_nfc, controller);
284}
285
286static irqreturn_t sunxi_nfc_interrupt(int irq, void *dev_id)
287{
288 struct sunxi_nfc *nfc = dev_id;
289 u32 st = readl(nfc->regs + NFC_REG_ST);
290 u32 ien = readl(nfc->regs + NFC_REG_INT);
291
292 if (!(ien & st))
293 return IRQ_NONE;
294
295 if ((ien & st) == ien)
296 complete(&nfc->complete);
297
298 writel(st & NFC_INT_MASK, nfc->regs + NFC_REG_ST);
299 writel(~st & ien & NFC_INT_MASK, nfc->regs + NFC_REG_INT);
300
301 return IRQ_HANDLED;
302}
303
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100304static int sunxi_nfc_wait_events(struct sunxi_nfc *nfc, u32 events,
305 bool use_polling, unsigned int timeout_ms)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200306{
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100307 int ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200308
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100309 if (events & ~NFC_INT_MASK)
310 return -EINVAL;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200311
312 if (!timeout_ms)
313 timeout_ms = NFC_DEFAULT_TIMEOUT_MS;
314
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100315 if (!use_polling) {
316 init_completion(&nfc->complete);
317
318 writel(events, nfc->regs + NFC_REG_INT);
319
320 ret = wait_for_completion_timeout(&nfc->complete,
321 msecs_to_jiffies(timeout_ms));
322
323 writel(0, nfc->regs + NFC_REG_INT);
324 } else {
325 u32 status;
326
327 ret = readl_poll_timeout(nfc->regs + NFC_REG_ST, status,
328 (status & events) == events, 1,
329 timeout_ms * 1000);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200330 }
331
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100332 writel(events & NFC_INT_MASK, nfc->regs + NFC_REG_ST);
333
334 if (ret)
335 dev_err(nfc->dev, "wait interrupt timedout\n");
336
337 return ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200338}
339
340static int sunxi_nfc_wait_cmd_fifo_empty(struct sunxi_nfc *nfc)
341{
Boris Brezillon166f08c2016-03-07 15:25:17 +0100342 u32 status;
343 int ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200344
Boris Brezillon166f08c2016-03-07 15:25:17 +0100345 ret = readl_poll_timeout(nfc->regs + NFC_REG_ST, status,
346 !(status & NFC_CMD_FIFO_STATUS), 1,
347 NFC_DEFAULT_TIMEOUT_MS * 1000);
348 if (ret)
349 dev_err(nfc->dev, "wait for empty cmd FIFO timedout\n");
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200350
Boris Brezillon166f08c2016-03-07 15:25:17 +0100351 return ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200352}
353
354static int sunxi_nfc_rst(struct sunxi_nfc *nfc)
355{
Boris Brezillon166f08c2016-03-07 15:25:17 +0100356 u32 ctl;
357 int ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200358
359 writel(0, nfc->regs + NFC_REG_ECC_CTL);
360 writel(NFC_RESET, nfc->regs + NFC_REG_CTL);
361
Boris Brezillon166f08c2016-03-07 15:25:17 +0100362 ret = readl_poll_timeout(nfc->regs + NFC_REG_CTL, ctl,
363 !(ctl & NFC_RESET), 1,
364 NFC_DEFAULT_TIMEOUT_MS * 1000);
365 if (ret)
366 dev_err(nfc->dev, "wait for NAND controller reset timedout\n");
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200367
Boris Brezillon166f08c2016-03-07 15:25:17 +0100368 return ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200369}
370
371static int sunxi_nfc_dev_ready(struct mtd_info *mtd)
372{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100373 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200374 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
375 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
376 struct sunxi_nand_rb *rb;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200377 int ret;
378
379 if (sunxi_nand->selected < 0)
380 return 0;
381
382 rb = &sunxi_nand->sels[sunxi_nand->selected].rb;
383
384 switch (rb->type) {
385 case RB_NATIVE:
386 ret = !!(readl(nfc->regs + NFC_REG_ST) &
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200387 NFC_RB_STATE(rb->info.nativeid));
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200388 break;
389 case RB_GPIO:
390 ret = gpio_get_value(rb->info.gpio);
391 break;
392 case RB_NONE:
393 default:
394 ret = 0;
395 dev_err(nfc->dev, "cannot check R/B NAND status!\n");
396 break;
397 }
398
399 return ret;
400}
401
402static void sunxi_nfc_select_chip(struct mtd_info *mtd, int chip)
403{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100404 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200405 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
406 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
407 struct sunxi_nand_chip_sel *sel;
408 u32 ctl;
409
410 if (chip > 0 && chip >= sunxi_nand->nsels)
411 return;
412
413 if (chip == sunxi_nand->selected)
414 return;
415
416 ctl = readl(nfc->regs + NFC_REG_CTL) &
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200417 ~(NFC_PAGE_SHIFT_MSK | NFC_CE_SEL_MSK | NFC_RB_SEL_MSK | NFC_EN);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200418
419 if (chip >= 0) {
420 sel = &sunxi_nand->sels[chip];
421
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200422 ctl |= NFC_CE_SEL(sel->cs) | NFC_EN |
Boris Brezillon68ffbf72016-03-04 17:29:20 +0100423 NFC_PAGE_SHIFT(nand->page_shift);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200424 if (sel->rb.type == RB_NONE) {
425 nand->dev_ready = NULL;
426 } else {
427 nand->dev_ready = sunxi_nfc_dev_ready;
428 if (sel->rb.type == RB_NATIVE)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200429 ctl |= NFC_RB_SEL(sel->rb.info.nativeid);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200430 }
431
432 writel(mtd->writesize, nfc->regs + NFC_REG_SPARE_AREA);
433
434 if (nfc->clk_rate != sunxi_nand->clk_rate) {
435 clk_set_rate(nfc->mod_clk, sunxi_nand->clk_rate);
436 nfc->clk_rate = sunxi_nand->clk_rate;
437 }
438 }
439
Roy Splietd052e502015-06-26 11:00:11 +0200440 writel(sunxi_nand->timing_ctl, nfc->regs + NFC_REG_TIMING_CTL);
Roy Spliet9c618292015-06-26 11:00:10 +0200441 writel(sunxi_nand->timing_cfg, nfc->regs + NFC_REG_TIMING_CFG);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200442 writel(ctl, nfc->regs + NFC_REG_CTL);
443
444 sunxi_nand->selected = chip;
445}
446
447static void sunxi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
448{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100449 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200450 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
451 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
452 int ret;
453 int cnt;
454 int offs = 0;
455 u32 tmp;
456
457 while (len > offs) {
458 cnt = min(len - offs, NFC_SRAM_SIZE);
459
460 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
461 if (ret)
462 break;
463
464 writel(cnt, nfc->regs + NFC_REG_CNT);
465 tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD;
466 writel(tmp, nfc->regs + NFC_REG_CMD);
467
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100468 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200469 if (ret)
470 break;
471
472 if (buf)
473 memcpy_fromio(buf + offs, nfc->regs + NFC_RAM0_BASE,
474 cnt);
475 offs += cnt;
476 }
477}
478
479static void sunxi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf,
480 int len)
481{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100482 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200483 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
484 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
485 int ret;
486 int cnt;
487 int offs = 0;
488 u32 tmp;
489
490 while (len > offs) {
491 cnt = min(len - offs, NFC_SRAM_SIZE);
492
493 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
494 if (ret)
495 break;
496
497 writel(cnt, nfc->regs + NFC_REG_CNT);
498 memcpy_toio(nfc->regs + NFC_RAM0_BASE, buf + offs, cnt);
499 tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD |
500 NFC_ACCESS_DIR;
501 writel(tmp, nfc->regs + NFC_REG_CMD);
502
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100503 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200504 if (ret)
505 break;
506
507 offs += cnt;
508 }
509}
510
511static uint8_t sunxi_nfc_read_byte(struct mtd_info *mtd)
512{
513 uint8_t ret;
514
515 sunxi_nfc_read_buf(mtd, &ret, 1);
516
517 return ret;
518}
519
520static void sunxi_nfc_cmd_ctrl(struct mtd_info *mtd, int dat,
521 unsigned int ctrl)
522{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100523 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200524 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
525 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
526 int ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200527
528 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
529 if (ret)
530 return;
531
Boris Brezillone9aa6712015-09-16 09:05:31 +0200532 if (dat == NAND_CMD_NONE && (ctrl & NAND_NCE) &&
533 !(ctrl & (NAND_CLE | NAND_ALE))) {
534 u32 cmd = 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200535
Boris Brezillone9aa6712015-09-16 09:05:31 +0200536 if (!sunxi_nand->addr_cycles && !sunxi_nand->cmd_cycles)
537 return;
538
539 if (sunxi_nand->cmd_cycles--)
540 cmd |= NFC_SEND_CMD1 | sunxi_nand->cmd[0];
541
542 if (sunxi_nand->cmd_cycles--) {
543 cmd |= NFC_SEND_CMD2;
544 writel(sunxi_nand->cmd[1],
545 nfc->regs + NFC_REG_RCMD_SET);
546 }
547
548 sunxi_nand->cmd_cycles = 0;
549
550 if (sunxi_nand->addr_cycles) {
551 cmd |= NFC_SEND_ADR |
552 NFC_ADR_NUM(sunxi_nand->addr_cycles);
553 writel(sunxi_nand->addr[0],
554 nfc->regs + NFC_REG_ADDR_LOW);
555 }
556
557 if (sunxi_nand->addr_cycles > 4)
558 writel(sunxi_nand->addr[1],
559 nfc->regs + NFC_REG_ADDR_HIGH);
560
561 writel(cmd, nfc->regs + NFC_REG_CMD);
562 sunxi_nand->addr[0] = 0;
563 sunxi_nand->addr[1] = 0;
564 sunxi_nand->addr_cycles = 0;
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100565 sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200566 }
567
Boris Brezillone9aa6712015-09-16 09:05:31 +0200568 if (ctrl & NAND_CLE) {
569 sunxi_nand->cmd[sunxi_nand->cmd_cycles++] = dat;
570 } else if (ctrl & NAND_ALE) {
571 sunxi_nand->addr[sunxi_nand->addr_cycles / 4] |=
572 dat << ((sunxi_nand->addr_cycles % 4) * 8);
573 sunxi_nand->addr_cycles++;
574 }
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200575}
576
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100577/* These seed values have been extracted from Allwinner's BSP */
578static const u16 sunxi_nfc_randomizer_page_seeds[] = {
579 0x2b75, 0x0bd0, 0x5ca3, 0x62d1, 0x1c93, 0x07e9, 0x2162, 0x3a72,
580 0x0d67, 0x67f9, 0x1be7, 0x077d, 0x032f, 0x0dac, 0x2716, 0x2436,
581 0x7922, 0x1510, 0x3860, 0x5287, 0x480f, 0x4252, 0x1789, 0x5a2d,
582 0x2a49, 0x5e10, 0x437f, 0x4b4e, 0x2f45, 0x216e, 0x5cb7, 0x7130,
583 0x2a3f, 0x60e4, 0x4dc9, 0x0ef0, 0x0f52, 0x1bb9, 0x6211, 0x7a56,
584 0x226d, 0x4ea7, 0x6f36, 0x3692, 0x38bf, 0x0c62, 0x05eb, 0x4c55,
585 0x60f4, 0x728c, 0x3b6f, 0x2037, 0x7f69, 0x0936, 0x651a, 0x4ceb,
586 0x6218, 0x79f3, 0x383f, 0x18d9, 0x4f05, 0x5c82, 0x2912, 0x6f17,
587 0x6856, 0x5938, 0x1007, 0x61ab, 0x3e7f, 0x57c2, 0x542f, 0x4f62,
588 0x7454, 0x2eac, 0x7739, 0x42d4, 0x2f90, 0x435a, 0x2e52, 0x2064,
589 0x637c, 0x66ad, 0x2c90, 0x0bad, 0x759c, 0x0029, 0x0986, 0x7126,
590 0x1ca7, 0x1605, 0x386a, 0x27f5, 0x1380, 0x6d75, 0x24c3, 0x0f8e,
591 0x2b7a, 0x1418, 0x1fd1, 0x7dc1, 0x2d8e, 0x43af, 0x2267, 0x7da3,
592 0x4e3d, 0x1338, 0x50db, 0x454d, 0x764d, 0x40a3, 0x42e6, 0x262b,
593 0x2d2e, 0x1aea, 0x2e17, 0x173d, 0x3a6e, 0x71bf, 0x25f9, 0x0a5d,
594 0x7c57, 0x0fbe, 0x46ce, 0x4939, 0x6b17, 0x37bb, 0x3e91, 0x76db,
595};
596
597/*
598 * sunxi_nfc_randomizer_ecc512_seeds and sunxi_nfc_randomizer_ecc1024_seeds
599 * have been generated using
600 * sunxi_nfc_randomizer_step(seed, (step_size * 8) + 15), which is what
601 * the randomizer engine does internally before de/scrambling OOB data.
602 *
603 * Those tables are statically defined to avoid calculating randomizer state
604 * at runtime.
605 */
606static const u16 sunxi_nfc_randomizer_ecc512_seeds[] = {
607 0x3346, 0x367f, 0x1f18, 0x769a, 0x4f64, 0x068c, 0x2ef1, 0x6b64,
608 0x28a9, 0x15d7, 0x30f8, 0x3659, 0x53db, 0x7c5f, 0x71d4, 0x4409,
609 0x26eb, 0x03cc, 0x655d, 0x47d4, 0x4daa, 0x0877, 0x712d, 0x3617,
610 0x3264, 0x49aa, 0x7f9e, 0x588e, 0x4fbc, 0x7176, 0x7f91, 0x6c6d,
611 0x4b95, 0x5fb7, 0x3844, 0x4037, 0x0184, 0x081b, 0x0ee8, 0x5b91,
612 0x293d, 0x1f71, 0x0e6f, 0x402b, 0x5122, 0x1e52, 0x22be, 0x3d2d,
613 0x75bc, 0x7c60, 0x6291, 0x1a2f, 0x61d4, 0x74aa, 0x4140, 0x29ab,
614 0x472d, 0x2852, 0x017e, 0x15e8, 0x5ec2, 0x17cf, 0x7d0f, 0x06b8,
615 0x117a, 0x6b94, 0x789b, 0x3126, 0x6ac5, 0x5be7, 0x150f, 0x51f8,
616 0x7889, 0x0aa5, 0x663d, 0x77e8, 0x0b87, 0x3dcb, 0x360d, 0x218b,
617 0x512f, 0x7dc9, 0x6a4d, 0x630a, 0x3547, 0x1dd2, 0x5aea, 0x69a5,
618 0x7bfa, 0x5e4f, 0x1519, 0x6430, 0x3a0e, 0x5eb3, 0x5425, 0x0c7a,
619 0x5540, 0x3670, 0x63c1, 0x31e9, 0x5a39, 0x2de7, 0x5979, 0x2891,
620 0x1562, 0x014b, 0x5b05, 0x2756, 0x5a34, 0x13aa, 0x6cb5, 0x2c36,
621 0x5e72, 0x1306, 0x0861, 0x15ef, 0x1ee8, 0x5a37, 0x7ac4, 0x45dd,
622 0x44c4, 0x7266, 0x2f41, 0x3ccc, 0x045e, 0x7d40, 0x7c66, 0x0fa0,
623};
624
625static const u16 sunxi_nfc_randomizer_ecc1024_seeds[] = {
626 0x2cf5, 0x35f1, 0x63a4, 0x5274, 0x2bd2, 0x778b, 0x7285, 0x32b6,
627 0x6a5c, 0x70d6, 0x757d, 0x6769, 0x5375, 0x1e81, 0x0cf3, 0x3982,
628 0x6787, 0x042a, 0x6c49, 0x1925, 0x56a8, 0x40a9, 0x063e, 0x7bd9,
629 0x4dbf, 0x55ec, 0x672e, 0x7334, 0x5185, 0x4d00, 0x232a, 0x7e07,
630 0x445d, 0x6b92, 0x528f, 0x4255, 0x53ba, 0x7d82, 0x2a2e, 0x3a4e,
631 0x75eb, 0x450c, 0x6844, 0x1b5d, 0x581a, 0x4cc6, 0x0379, 0x37b2,
632 0x419f, 0x0e92, 0x6b27, 0x5624, 0x01e3, 0x07c1, 0x44a5, 0x130c,
633 0x13e8, 0x5910, 0x0876, 0x60c5, 0x54e3, 0x5b7f, 0x2269, 0x509f,
634 0x7665, 0x36fd, 0x3e9a, 0x0579, 0x6295, 0x14ef, 0x0a81, 0x1bcc,
635 0x4b16, 0x64db, 0x0514, 0x4f07, 0x0591, 0x3576, 0x6853, 0x0d9e,
636 0x259f, 0x38b7, 0x64fb, 0x3094, 0x4693, 0x6ddd, 0x29bb, 0x0bc8,
637 0x3f47, 0x490e, 0x0c0e, 0x7933, 0x3c9e, 0x5840, 0x398d, 0x3e68,
638 0x4af1, 0x71f5, 0x57cf, 0x1121, 0x64eb, 0x3579, 0x15ac, 0x584d,
639 0x5f2a, 0x47e2, 0x6528, 0x6eac, 0x196e, 0x6b96, 0x0450, 0x0179,
640 0x609c, 0x06e1, 0x4626, 0x42c7, 0x273e, 0x486f, 0x0705, 0x1601,
641 0x145b, 0x407e, 0x062b, 0x57a5, 0x53f9, 0x5659, 0x4410, 0x3ccd,
642};
643
644static u16 sunxi_nfc_randomizer_step(u16 state, int count)
645{
646 state &= 0x7fff;
647
648 /*
649 * This loop is just a simple implementation of a Fibonacci LFSR using
650 * the x16 + x15 + 1 polynomial.
651 */
652 while (count--)
653 state = ((state >> 1) |
654 (((state ^ (state >> 1)) & 1) << 14)) & 0x7fff;
655
656 return state;
657}
658
659static u16 sunxi_nfc_randomizer_state(struct mtd_info *mtd, int page, bool ecc)
660{
661 const u16 *seeds = sunxi_nfc_randomizer_page_seeds;
Brian Norris46c135c2016-01-22 18:57:13 -0800662 int mod = mtd_div_by_ws(mtd->erasesize, mtd);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100663
664 if (mod > ARRAY_SIZE(sunxi_nfc_randomizer_page_seeds))
665 mod = ARRAY_SIZE(sunxi_nfc_randomizer_page_seeds);
666
667 if (ecc) {
668 if (mtd->ecc_step_size == 512)
669 seeds = sunxi_nfc_randomizer_ecc512_seeds;
670 else
671 seeds = sunxi_nfc_randomizer_ecc1024_seeds;
672 }
673
674 return seeds[page % mod];
675}
676
677static void sunxi_nfc_randomizer_config(struct mtd_info *mtd,
678 int page, bool ecc)
679{
Boris BREZILLONf671a1f2016-03-05 00:21:20 +0100680 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100681 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
682 u32 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
683 u16 state;
684
685 if (!(nand->options & NAND_NEED_SCRAMBLING))
686 return;
687
688 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
689 state = sunxi_nfc_randomizer_state(mtd, page, ecc);
690 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_RANDOM_SEED_MSK;
691 writel(ecc_ctl | NFC_RANDOM_SEED(state), nfc->regs + NFC_REG_ECC_CTL);
692}
693
694static void sunxi_nfc_randomizer_enable(struct mtd_info *mtd)
695{
Boris BREZILLONf671a1f2016-03-05 00:21:20 +0100696 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100697 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
698
699 if (!(nand->options & NAND_NEED_SCRAMBLING))
700 return;
701
702 writel(readl(nfc->regs + NFC_REG_ECC_CTL) | NFC_RANDOM_EN,
703 nfc->regs + NFC_REG_ECC_CTL);
704}
705
706static void sunxi_nfc_randomizer_disable(struct mtd_info *mtd)
707{
Boris BREZILLONf671a1f2016-03-05 00:21:20 +0100708 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100709 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
710
711 if (!(nand->options & NAND_NEED_SCRAMBLING))
712 return;
713
714 writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_RANDOM_EN,
715 nfc->regs + NFC_REG_ECC_CTL);
716}
717
718static void sunxi_nfc_randomize_bbm(struct mtd_info *mtd, int page, u8 *bbm)
719{
720 u16 state = sunxi_nfc_randomizer_state(mtd, page, true);
721
722 bbm[0] ^= state;
723 bbm[1] ^= sunxi_nfc_randomizer_step(state, 8);
724}
725
726static void sunxi_nfc_randomizer_write_buf(struct mtd_info *mtd,
727 const uint8_t *buf, int len,
728 bool ecc, int page)
729{
730 sunxi_nfc_randomizer_config(mtd, page, ecc);
731 sunxi_nfc_randomizer_enable(mtd);
732 sunxi_nfc_write_buf(mtd, buf, len);
733 sunxi_nfc_randomizer_disable(mtd);
734}
735
736static void sunxi_nfc_randomizer_read_buf(struct mtd_info *mtd, uint8_t *buf,
737 int len, bool ecc, int page)
738{
739 sunxi_nfc_randomizer_config(mtd, page, ecc);
740 sunxi_nfc_randomizer_enable(mtd);
741 sunxi_nfc_read_buf(mtd, buf, len);
742 sunxi_nfc_randomizer_disable(mtd);
743}
744
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200745static void sunxi_nfc_hw_ecc_enable(struct mtd_info *mtd)
746{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100747 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200748 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
749 struct sunxi_nand_hw_ecc *data = nand->ecc.priv;
750 u32 ecc_ctl;
751
752 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
753 ecc_ctl &= ~(NFC_ECC_MODE_MSK | NFC_ECC_PIPELINE |
754 NFC_ECC_BLOCK_SIZE_MSK);
Boris Brezillon336de7b2016-03-04 17:33:10 +0100755 ecc_ctl |= NFC_ECC_EN | NFC_ECC_MODE(data->mode) | NFC_ECC_EXCEPTION |
756 NFC_ECC_PIPELINE;
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200757
758 writel(ecc_ctl, nfc->regs + NFC_REG_ECC_CTL);
759}
760
761static void sunxi_nfc_hw_ecc_disable(struct mtd_info *mtd)
762{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100763 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200764 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
765
766 writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_ECC_EN,
767 nfc->regs + NFC_REG_ECC_CTL);
768}
769
Boris BREZILLONf363e0f2015-09-30 23:45:27 +0200770static inline void sunxi_nfc_user_data_to_buf(u32 user_data, u8 *buf)
771{
772 buf[0] = user_data;
773 buf[1] = user_data >> 8;
774 buf[2] = user_data >> 16;
775 buf[3] = user_data >> 24;
776}
777
Boris BREZILLON913821b2015-09-30 23:45:24 +0200778static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
779 u8 *data, int data_off,
780 u8 *oob, int oob_off,
781 int *cur_off,
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100782 unsigned int *max_bitflips,
783 bool bbm, int page)
Boris BREZILLON913821b2015-09-30 23:45:24 +0200784{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100785 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200786 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
787 struct nand_ecc_ctrl *ecc = &nand->ecc;
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100788 int raw_mode = 0;
Boris BREZILLON913821b2015-09-30 23:45:24 +0200789 u32 status;
790 int ret;
791
792 if (*cur_off != data_off)
793 nand->cmdfunc(mtd, NAND_CMD_RNDOUT, data_off, -1);
794
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100795 sunxi_nfc_randomizer_read_buf(mtd, NULL, ecc->size, false, page);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200796
Boris BREZILLON74eb9ff2015-10-20 22:16:00 +0200797 if (data_off + ecc->size != oob_off)
Boris BREZILLON913821b2015-09-30 23:45:24 +0200798 nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1);
799
800 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
801 if (ret)
802 return ret;
803
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100804 sunxi_nfc_randomizer_enable(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200805 writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP,
806 nfc->regs + NFC_REG_CMD);
807
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100808 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100809 sunxi_nfc_randomizer_disable(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200810 if (ret)
811 return ret;
812
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100813 *cur_off = oob_off + ecc->bytes + 4;
814
Boris BREZILLON913821b2015-09-30 23:45:24 +0200815 status = readl(nfc->regs + NFC_REG_ECC_ST);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100816 if (status & NFC_ECC_PAT_FOUND(0)) {
817 u8 pattern = 0xff;
818
819 if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID) & 0x1)))
820 pattern = 0x0;
821
822 memset(data, pattern, ecc->size);
823 memset(oob, pattern, ecc->bytes + 4);
824
825 return 1;
826 }
827
Boris BREZILLON913821b2015-09-30 23:45:24 +0200828 ret = NFC_ECC_ERR_CNT(0, readl(nfc->regs + NFC_REG_ECC_ERR_CNT(0)));
829
830 memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size);
831
832 nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100833 sunxi_nfc_randomizer_read_buf(mtd, oob, ecc->bytes + 4, true, page);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200834
Boris BREZILLONf363e0f2015-09-30 23:45:27 +0200835 if (status & NFC_ECC_ERR(0)) {
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100836 /*
837 * Re-read the data with the randomizer disabled to identify
838 * bitflips in erased pages.
839 */
840 if (nand->options & NAND_NEED_SCRAMBLING) {
841 nand->cmdfunc(mtd, NAND_CMD_RNDOUT, data_off, -1);
842 nand->read_buf(mtd, data, ecc->size);
843 nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1);
844 nand->read_buf(mtd, oob, ecc->bytes + 4);
845 }
846
Boris BREZILLON146b5032015-09-30 23:45:29 +0200847 ret = nand_check_erased_ecc_chunk(data, ecc->size,
848 oob, ecc->bytes + 4,
849 NULL, 0, ecc->strength);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100850 if (ret >= 0)
851 raw_mode = 1;
Boris BREZILLONf363e0f2015-09-30 23:45:27 +0200852 } else {
853 /*
854 * The engine protects 4 bytes of OOB data per chunk.
855 * Retrieve the corrected OOB bytes.
856 */
857 sunxi_nfc_user_data_to_buf(readl(nfc->regs + NFC_REG_USER_DATA(0)),
858 oob);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100859
860 /* De-randomize the Bad Block Marker. */
861 if (bbm && nand->options & NAND_NEED_SCRAMBLING)
862 sunxi_nfc_randomize_bbm(mtd, page, oob);
Boris BREZILLONf363e0f2015-09-30 23:45:27 +0200863 }
Boris BREZILLON913821b2015-09-30 23:45:24 +0200864
865 if (ret < 0) {
866 mtd->ecc_stats.failed++;
867 } else {
868 mtd->ecc_stats.corrected += ret;
869 *max_bitflips = max_t(unsigned int, *max_bitflips, ret);
870 }
871
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100872 return raw_mode;
Boris BREZILLON913821b2015-09-30 23:45:24 +0200873}
874
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200875static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd,
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100876 u8 *oob, int *cur_off,
877 bool randomize, int page)
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200878{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100879 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200880 struct nand_ecc_ctrl *ecc = &nand->ecc;
881 int offset = ((ecc->bytes + 4) * ecc->steps);
882 int len = mtd->oobsize - offset;
883
884 if (len <= 0)
885 return;
886
887 if (*cur_off != offset)
888 nand->cmdfunc(mtd, NAND_CMD_RNDOUT,
889 offset + mtd->writesize, -1);
890
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100891 if (!randomize)
892 sunxi_nfc_read_buf(mtd, oob + offset, len);
893 else
894 sunxi_nfc_randomizer_read_buf(mtd, oob + offset, len,
895 false, page);
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200896
897 *cur_off = mtd->oobsize + mtd->writesize;
898}
899
Boris BREZILLON23151fd2015-09-30 23:45:28 +0200900static inline u32 sunxi_nfc_buf_to_user_data(const u8 *buf)
901{
902 return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
903}
904
Boris BREZILLON913821b2015-09-30 23:45:24 +0200905static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd,
906 const u8 *data, int data_off,
907 const u8 *oob, int oob_off,
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100908 int *cur_off, bool bbm,
909 int page)
Boris BREZILLON913821b2015-09-30 23:45:24 +0200910{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100911 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200912 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
913 struct nand_ecc_ctrl *ecc = &nand->ecc;
914 int ret;
915
916 if (data_off != *cur_off)
917 nand->cmdfunc(mtd, NAND_CMD_RNDIN, data_off, -1);
918
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100919 sunxi_nfc_randomizer_write_buf(mtd, data, ecc->size, false, page);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200920
921 /* Fill OOB data in */
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100922 if ((nand->options & NAND_NEED_SCRAMBLING) && bbm) {
923 u8 user_data[4];
924
925 memcpy(user_data, oob, 4);
926 sunxi_nfc_randomize_bbm(mtd, page, user_data);
927 writel(sunxi_nfc_buf_to_user_data(user_data),
928 nfc->regs + NFC_REG_USER_DATA(0));
929 } else {
930 writel(sunxi_nfc_buf_to_user_data(oob),
931 nfc->regs + NFC_REG_USER_DATA(0));
932 }
Boris BREZILLON913821b2015-09-30 23:45:24 +0200933
Boris BREZILLON74eb9ff2015-10-20 22:16:00 +0200934 if (data_off + ecc->size != oob_off)
Boris BREZILLON913821b2015-09-30 23:45:24 +0200935 nand->cmdfunc(mtd, NAND_CMD_RNDIN, oob_off, -1);
936
937 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
938 if (ret)
939 return ret;
940
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100941 sunxi_nfc_randomizer_enable(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200942 writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD |
943 NFC_ACCESS_DIR | NFC_ECC_OP,
944 nfc->regs + NFC_REG_CMD);
945
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100946 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100947 sunxi_nfc_randomizer_disable(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200948 if (ret)
949 return ret;
950
951 *cur_off = oob_off + ecc->bytes + 4;
952
953 return 0;
954}
955
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200956static void sunxi_nfc_hw_ecc_write_extra_oob(struct mtd_info *mtd,
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100957 u8 *oob, int *cur_off,
958 int page)
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200959{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100960 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200961 struct nand_ecc_ctrl *ecc = &nand->ecc;
962 int offset = ((ecc->bytes + 4) * ecc->steps);
963 int len = mtd->oobsize - offset;
964
965 if (len <= 0)
966 return;
967
968 if (*cur_off != offset)
969 nand->cmdfunc(mtd, NAND_CMD_RNDIN,
970 offset + mtd->writesize, -1);
971
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100972 sunxi_nfc_randomizer_write_buf(mtd, oob + offset, len, false, page);
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200973
974 *cur_off = mtd->oobsize + mtd->writesize;
975}
976
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200977static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd,
978 struct nand_chip *chip, uint8_t *buf,
979 int oob_required, int page)
980{
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200981 struct nand_ecc_ctrl *ecc = &chip->ecc;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200982 unsigned int max_bitflips = 0;
Boris BREZILLONb4625512015-09-30 23:45:25 +0200983 int ret, i, cur_off = 0;
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100984 bool raw_mode = false;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200985
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200986 sunxi_nfc_hw_ecc_enable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200987
988 for (i = 0; i < ecc->steps; i++) {
Boris BREZILLONb4625512015-09-30 23:45:25 +0200989 int data_off = i * ecc->size;
990 int oob_off = i * (ecc->bytes + 4);
991 u8 *data = buf + data_off;
992 u8 *oob = chip->oob_poi + oob_off;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200993
Boris BREZILLONb4625512015-09-30 23:45:25 +0200994 ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob,
995 oob_off + mtd->writesize,
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100996 &cur_off, &max_bitflips,
997 !i, page);
998 if (ret < 0)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200999 return ret;
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001000 else if (ret)
1001 raw_mode = true;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001002 }
1003
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001004 if (oob_required)
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001005 sunxi_nfc_hw_ecc_read_extra_oob(mtd, chip->oob_poi, &cur_off,
1006 !raw_mode, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001007
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001008 sunxi_nfc_hw_ecc_disable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001009
1010 return max_bitflips;
1011}
1012
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001013static int sunxi_nfc_hw_ecc_read_subpage(struct mtd_info *mtd,
1014 struct nand_chip *chip,
1015 u32 data_offs, u32 readlen,
1016 u8 *bufpoi, int page)
1017{
1018 struct nand_ecc_ctrl *ecc = &chip->ecc;
1019 int ret, i, cur_off = 0;
1020 unsigned int max_bitflips = 0;
1021
1022 sunxi_nfc_hw_ecc_enable(mtd);
1023
1024 chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
1025 for (i = data_offs / ecc->size;
1026 i < DIV_ROUND_UP(data_offs + readlen, ecc->size); i++) {
1027 int data_off = i * ecc->size;
1028 int oob_off = i * (ecc->bytes + 4);
1029 u8 *data = bufpoi + data_off;
1030 u8 *oob = chip->oob_poi + oob_off;
1031
1032 ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off,
1033 oob,
1034 oob_off + mtd->writesize,
1035 &cur_off, &max_bitflips,
1036 !i, page);
1037 if (ret < 0)
1038 return ret;
1039 }
1040
1041 sunxi_nfc_hw_ecc_disable(mtd);
1042
1043 return max_bitflips;
1044}
1045
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001046static int sunxi_nfc_hw_ecc_write_page(struct mtd_info *mtd,
1047 struct nand_chip *chip,
Boris BREZILLON45aaeff2015-10-13 11:22:18 +02001048 const uint8_t *buf, int oob_required,
1049 int page)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001050{
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001051 struct nand_ecc_ctrl *ecc = &chip->ecc;
Boris BREZILLONb4625512015-09-30 23:45:25 +02001052 int ret, i, cur_off = 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001053
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001054 sunxi_nfc_hw_ecc_enable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001055
1056 for (i = 0; i < ecc->steps; i++) {
Boris BREZILLONb4625512015-09-30 23:45:25 +02001057 int data_off = i * ecc->size;
1058 int oob_off = i * (ecc->bytes + 4);
1059 const u8 *data = buf + data_off;
1060 const u8 *oob = chip->oob_poi + oob_off;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001061
Boris BREZILLONb4625512015-09-30 23:45:25 +02001062 ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off, oob,
1063 oob_off + mtd->writesize,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001064 &cur_off, !i, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001065 if (ret)
1066 return ret;
1067 }
1068
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001069 if (oob_required || (chip->options & NAND_NEED_SCRAMBLING))
1070 sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi,
1071 &cur_off, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001072
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001073 sunxi_nfc_hw_ecc_disable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001074
1075 return 0;
1076}
1077
1078static int sunxi_nfc_hw_syndrome_ecc_read_page(struct mtd_info *mtd,
1079 struct nand_chip *chip,
1080 uint8_t *buf, int oob_required,
1081 int page)
1082{
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001083 struct nand_ecc_ctrl *ecc = &chip->ecc;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001084 unsigned int max_bitflips = 0;
Boris BREZILLONb4625512015-09-30 23:45:25 +02001085 int ret, i, cur_off = 0;
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001086 bool raw_mode = false;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001087
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001088 sunxi_nfc_hw_ecc_enable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001089
1090 for (i = 0; i < ecc->steps; i++) {
Boris BREZILLONb4625512015-09-30 23:45:25 +02001091 int data_off = i * (ecc->size + ecc->bytes + 4);
1092 int oob_off = data_off + ecc->size;
1093 u8 *data = buf + (i * ecc->size);
1094 u8 *oob = chip->oob_poi + (i * (ecc->bytes + 4));
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001095
Boris BREZILLONb4625512015-09-30 23:45:25 +02001096 ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob,
1097 oob_off, &cur_off,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001098 &max_bitflips, !i, page);
1099 if (ret < 0)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001100 return ret;
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001101 else if (ret)
1102 raw_mode = true;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001103 }
1104
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001105 if (oob_required)
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001106 sunxi_nfc_hw_ecc_read_extra_oob(mtd, chip->oob_poi, &cur_off,
1107 !raw_mode, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001108
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001109 sunxi_nfc_hw_ecc_disable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001110
1111 return max_bitflips;
1112}
1113
1114static int sunxi_nfc_hw_syndrome_ecc_write_page(struct mtd_info *mtd,
1115 struct nand_chip *chip,
1116 const uint8_t *buf,
Boris BREZILLON45aaeff2015-10-13 11:22:18 +02001117 int oob_required, int page)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001118{
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001119 struct nand_ecc_ctrl *ecc = &chip->ecc;
Boris BREZILLONb4625512015-09-30 23:45:25 +02001120 int ret, i, cur_off = 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001121
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001122 sunxi_nfc_hw_ecc_enable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001123
1124 for (i = 0; i < ecc->steps; i++) {
Boris BREZILLONb4625512015-09-30 23:45:25 +02001125 int data_off = i * (ecc->size + ecc->bytes + 4);
1126 int oob_off = data_off + ecc->size;
1127 const u8 *data = buf + (i * ecc->size);
1128 const u8 *oob = chip->oob_poi + (i * (ecc->bytes + 4));
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001129
Boris BREZILLONb4625512015-09-30 23:45:25 +02001130 ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001131 oob, oob_off, &cur_off,
1132 false, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001133 if (ret)
1134 return ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001135 }
1136
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001137 if (oob_required || (chip->options & NAND_NEED_SCRAMBLING))
1138 sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi,
1139 &cur_off, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001140
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001141 sunxi_nfc_hw_ecc_disable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001142
1143 return 0;
1144}
1145
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001146static int sunxi_nfc_hw_common_ecc_read_oob(struct mtd_info *mtd,
1147 struct nand_chip *chip,
1148 int page)
1149{
1150 chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
1151
1152 chip->pagebuf = -1;
1153
1154 return chip->ecc.read_page(mtd, chip, chip->buffers->databuf, 1, page);
1155}
1156
1157static int sunxi_nfc_hw_common_ecc_write_oob(struct mtd_info *mtd,
1158 struct nand_chip *chip,
1159 int page)
1160{
1161 int ret, status;
1162
1163 chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0, page);
1164
1165 chip->pagebuf = -1;
1166
1167 memset(chip->buffers->databuf, 0xff, mtd->writesize);
1168 ret = chip->ecc.write_page(mtd, chip, chip->buffers->databuf, 1, page);
1169 if (ret)
1170 return ret;
1171
1172 /* Send command to program the OOB data */
1173 chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
1174
1175 status = chip->waitfunc(mtd, chip);
1176
1177 return status & NAND_STATUS_FAIL ? -EIO : 0;
1178}
1179
Roy Spliet9c618292015-06-26 11:00:10 +02001180static const s32 tWB_lut[] = {6, 12, 16, 20};
1181static const s32 tRHW_lut[] = {4, 8, 12, 20};
1182
1183static int _sunxi_nand_lookup_timing(const s32 *lut, int lut_size, u32 duration,
1184 u32 clk_period)
1185{
1186 u32 clk_cycles = DIV_ROUND_UP(duration, clk_period);
1187 int i;
1188
1189 for (i = 0; i < lut_size; i++) {
1190 if (clk_cycles <= lut[i])
1191 return i;
1192 }
1193
1194 /* Doesn't fit */
1195 return -EINVAL;
1196}
1197
1198#define sunxi_nand_lookup_timing(l, p, c) \
1199 _sunxi_nand_lookup_timing(l, ARRAY_SIZE(l), p, c)
1200
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001201static int sunxi_nand_chip_set_timings(struct sunxi_nand_chip *chip,
1202 const struct nand_sdr_timings *timings)
1203{
Roy Spliet9c618292015-06-26 11:00:10 +02001204 struct sunxi_nfc *nfc = to_sunxi_nfc(chip->nand.controller);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001205 u32 min_clk_period = 0;
Roy Spliet9c618292015-06-26 11:00:10 +02001206 s32 tWB, tADL, tWHR, tRHW, tCAD;
Boris Brezillon2d434572015-12-02 15:57:20 +01001207 long real_clk_rate;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001208
1209 /* T1 <=> tCLS */
1210 if (timings->tCLS_min > min_clk_period)
1211 min_clk_period = timings->tCLS_min;
1212
1213 /* T2 <=> tCLH */
1214 if (timings->tCLH_min > min_clk_period)
1215 min_clk_period = timings->tCLH_min;
1216
1217 /* T3 <=> tCS */
1218 if (timings->tCS_min > min_clk_period)
1219 min_clk_period = timings->tCS_min;
1220
1221 /* T4 <=> tCH */
1222 if (timings->tCH_min > min_clk_period)
1223 min_clk_period = timings->tCH_min;
1224
1225 /* T5 <=> tWP */
1226 if (timings->tWP_min > min_clk_period)
1227 min_clk_period = timings->tWP_min;
1228
1229 /* T6 <=> tWH */
1230 if (timings->tWH_min > min_clk_period)
1231 min_clk_period = timings->tWH_min;
1232
1233 /* T7 <=> tALS */
1234 if (timings->tALS_min > min_clk_period)
1235 min_clk_period = timings->tALS_min;
1236
1237 /* T8 <=> tDS */
1238 if (timings->tDS_min > min_clk_period)
1239 min_clk_period = timings->tDS_min;
1240
1241 /* T9 <=> tDH */
1242 if (timings->tDH_min > min_clk_period)
1243 min_clk_period = timings->tDH_min;
1244
1245 /* T10 <=> tRR */
1246 if (timings->tRR_min > (min_clk_period * 3))
1247 min_clk_period = DIV_ROUND_UP(timings->tRR_min, 3);
1248
1249 /* T11 <=> tALH */
1250 if (timings->tALH_min > min_clk_period)
1251 min_clk_period = timings->tALH_min;
1252
1253 /* T12 <=> tRP */
1254 if (timings->tRP_min > min_clk_period)
1255 min_clk_period = timings->tRP_min;
1256
1257 /* T13 <=> tREH */
1258 if (timings->tREH_min > min_clk_period)
1259 min_clk_period = timings->tREH_min;
1260
1261 /* T14 <=> tRC */
1262 if (timings->tRC_min > (min_clk_period * 2))
1263 min_clk_period = DIV_ROUND_UP(timings->tRC_min, 2);
1264
1265 /* T15 <=> tWC */
1266 if (timings->tWC_min > (min_clk_period * 2))
1267 min_clk_period = DIV_ROUND_UP(timings->tWC_min, 2);
1268
Roy Spliet9c618292015-06-26 11:00:10 +02001269 /* T16 - T19 + tCAD */
Boris Brezillon5abcd952015-11-11 22:30:30 +01001270 if (timings->tWB_max > (min_clk_period * 20))
1271 min_clk_period = DIV_ROUND_UP(timings->tWB_max, 20);
1272
1273 if (timings->tADL_min > (min_clk_period * 32))
1274 min_clk_period = DIV_ROUND_UP(timings->tADL_min, 32);
1275
1276 if (timings->tWHR_min > (min_clk_period * 32))
1277 min_clk_period = DIV_ROUND_UP(timings->tWHR_min, 32);
1278
1279 if (timings->tRHW_min > (min_clk_period * 20))
1280 min_clk_period = DIV_ROUND_UP(timings->tRHW_min, 20);
1281
Roy Spliet9c618292015-06-26 11:00:10 +02001282 tWB = sunxi_nand_lookup_timing(tWB_lut, timings->tWB_max,
1283 min_clk_period);
1284 if (tWB < 0) {
1285 dev_err(nfc->dev, "unsupported tWB\n");
1286 return tWB;
1287 }
1288
1289 tADL = DIV_ROUND_UP(timings->tADL_min, min_clk_period) >> 3;
1290 if (tADL > 3) {
1291 dev_err(nfc->dev, "unsupported tADL\n");
1292 return -EINVAL;
1293 }
1294
1295 tWHR = DIV_ROUND_UP(timings->tWHR_min, min_clk_period) >> 3;
1296 if (tWHR > 3) {
1297 dev_err(nfc->dev, "unsupported tWHR\n");
1298 return -EINVAL;
1299 }
1300
1301 tRHW = sunxi_nand_lookup_timing(tRHW_lut, timings->tRHW_min,
1302 min_clk_period);
1303 if (tRHW < 0) {
1304 dev_err(nfc->dev, "unsupported tRHW\n");
1305 return tRHW;
1306 }
1307
1308 /*
1309 * TODO: according to ONFI specs this value only applies for DDR NAND,
1310 * but Allwinner seems to set this to 0x7. Mimic them for now.
1311 */
1312 tCAD = 0x7;
1313
1314 /* TODO: A83 has some more bits for CDQSS, CS, CLHZ, CCS, WC */
1315 chip->timing_cfg = NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001316
1317 /* Convert min_clk_period from picoseconds to nanoseconds */
1318 min_clk_period = DIV_ROUND_UP(min_clk_period, 1000);
1319
1320 /*
Boris Brezillon2f9992e2015-12-02 15:10:40 +01001321 * Unlike what is stated in Allwinner datasheet, the clk_rate should
1322 * be set to (1 / min_clk_period), and not (2 / min_clk_period).
1323 * This new formula was verified with a scope and validated by
1324 * Allwinner engineers.
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001325 */
Boris Brezillon2f9992e2015-12-02 15:10:40 +01001326 chip->clk_rate = NSEC_PER_SEC / min_clk_period;
Boris Brezillon2d434572015-12-02 15:57:20 +01001327 real_clk_rate = clk_round_rate(nfc->mod_clk, chip->clk_rate);
1328
1329 /*
1330 * ONFI specification 3.1, paragraph 4.15.2 dictates that EDO data
1331 * output cycle timings shall be used if the host drives tRC less than
1332 * 30 ns.
1333 */
1334 min_clk_period = NSEC_PER_SEC / real_clk_rate;
1335 chip->timing_ctl = ((min_clk_period * 2) < 30) ?
1336 NFC_TIMING_CTL_EDO : 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001337
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001338 return 0;
1339}
1340
1341static int sunxi_nand_chip_init_timings(struct sunxi_nand_chip *chip,
1342 struct device_node *np)
1343{
Boris BREZILLON32e9f2d2015-12-10 09:00:26 +01001344 struct mtd_info *mtd = nand_to_mtd(&chip->nand);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001345 const struct nand_sdr_timings *timings;
1346 int ret;
1347 int mode;
1348
1349 mode = onfi_get_async_timing_mode(&chip->nand);
1350 if (mode == ONFI_TIMING_MODE_UNKNOWN) {
1351 mode = chip->nand.onfi_timing_mode_default;
1352 } else {
1353 uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {};
Stefan Roese7eadd472015-08-28 14:45:21 +02001354 int i;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001355
1356 mode = fls(mode) - 1;
1357 if (mode < 0)
1358 mode = 0;
1359
1360 feature[0] = mode;
Stefan Roese7eadd472015-08-28 14:45:21 +02001361 for (i = 0; i < chip->nsels; i++) {
Boris BREZILLON32e9f2d2015-12-10 09:00:26 +01001362 chip->nand.select_chip(mtd, i);
1363 ret = chip->nand.onfi_set_features(mtd, &chip->nand,
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001364 ONFI_FEATURE_ADDR_TIMING_MODE,
1365 feature);
Boris BREZILLON32e9f2d2015-12-10 09:00:26 +01001366 chip->nand.select_chip(mtd, -1);
Stefan Roese7eadd472015-08-28 14:45:21 +02001367 if (ret)
1368 return ret;
1369 }
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001370 }
1371
1372 timings = onfi_async_timing_mode_to_sdr_timings(mode);
1373 if (IS_ERR(timings))
1374 return PTR_ERR(timings);
1375
1376 return sunxi_nand_chip_set_timings(chip, timings);
1377}
1378
1379static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd,
1380 struct nand_ecc_ctrl *ecc,
1381 struct device_node *np)
1382{
1383 static const u8 strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 };
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +01001384 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001385 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
1386 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
1387 struct sunxi_nand_hw_ecc *data;
1388 struct nand_ecclayout *layout;
1389 int nsectors;
1390 int ret;
1391 int i;
1392
1393 data = kzalloc(sizeof(*data), GFP_KERNEL);
1394 if (!data)
1395 return -ENOMEM;
1396
1397 /* Add ECC info retrieval from DT */
1398 for (i = 0; i < ARRAY_SIZE(strengths); i++) {
1399 if (ecc->strength <= strengths[i])
1400 break;
1401 }
1402
1403 if (i >= ARRAY_SIZE(strengths)) {
1404 dev_err(nfc->dev, "unsupported strength\n");
1405 ret = -ENOTSUPP;
1406 goto err;
1407 }
1408
1409 data->mode = i;
1410
1411 /* HW ECC always request ECC bytes for 1024 bytes blocks */
1412 ecc->bytes = DIV_ROUND_UP(ecc->strength * fls(8 * 1024), 8);
1413
1414 /* HW ECC always work with even numbers of ECC bytes */
1415 ecc->bytes = ALIGN(ecc->bytes, 2);
1416
1417 layout = &data->layout;
1418 nsectors = mtd->writesize / ecc->size;
1419
1420 if (mtd->oobsize < ((ecc->bytes + 4) * nsectors)) {
1421 ret = -EINVAL;
1422 goto err;
1423 }
1424
1425 layout->eccbytes = (ecc->bytes * nsectors);
1426
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001427 ecc->read_oob = sunxi_nfc_hw_common_ecc_read_oob;
1428 ecc->write_oob = sunxi_nfc_hw_common_ecc_write_oob;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001429 ecc->layout = layout;
1430 ecc->priv = data;
1431
1432 return 0;
1433
1434err:
1435 kfree(data);
1436
1437 return ret;
1438}
1439
1440static void sunxi_nand_hw_common_ecc_ctrl_cleanup(struct nand_ecc_ctrl *ecc)
1441{
1442 kfree(ecc->priv);
1443}
1444
1445static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
1446 struct nand_ecc_ctrl *ecc,
1447 struct device_node *np)
1448{
1449 struct nand_ecclayout *layout;
1450 int nsectors;
1451 int i, j;
1452 int ret;
1453
1454 ret = sunxi_nand_hw_common_ecc_ctrl_init(mtd, ecc, np);
1455 if (ret)
1456 return ret;
1457
1458 ecc->read_page = sunxi_nfc_hw_ecc_read_page;
1459 ecc->write_page = sunxi_nfc_hw_ecc_write_page;
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001460 ecc->read_oob_raw = nand_read_oob_std;
1461 ecc->write_oob_raw = nand_write_oob_std;
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001462 ecc->read_subpage = sunxi_nfc_hw_ecc_read_subpage;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001463 layout = ecc->layout;
1464 nsectors = mtd->writesize / ecc->size;
1465
1466 for (i = 0; i < nsectors; i++) {
1467 if (i) {
1468 layout->oobfree[i].offset =
1469 layout->oobfree[i - 1].offset +
1470 layout->oobfree[i - 1].length +
1471 ecc->bytes;
1472 layout->oobfree[i].length = 4;
1473 } else {
1474 /*
1475 * The first 2 bytes are used for BB markers, hence we
1476 * only have 2 bytes available in the first user data
1477 * section.
1478 */
1479 layout->oobfree[i].length = 2;
1480 layout->oobfree[i].offset = 2;
1481 }
1482
1483 for (j = 0; j < ecc->bytes; j++)
1484 layout->eccpos[(ecc->bytes * i) + j] =
1485 layout->oobfree[i].offset +
1486 layout->oobfree[i].length + j;
1487 }
1488
1489 if (mtd->oobsize > (ecc->bytes + 4) * nsectors) {
1490 layout->oobfree[nsectors].offset =
1491 layout->oobfree[nsectors - 1].offset +
1492 layout->oobfree[nsectors - 1].length +
1493 ecc->bytes;
1494 layout->oobfree[nsectors].length = mtd->oobsize -
1495 ((ecc->bytes + 4) * nsectors);
1496 }
1497
1498 return 0;
1499}
1500
1501static int sunxi_nand_hw_syndrome_ecc_ctrl_init(struct mtd_info *mtd,
1502 struct nand_ecc_ctrl *ecc,
1503 struct device_node *np)
1504{
1505 struct nand_ecclayout *layout;
1506 int nsectors;
1507 int i;
1508 int ret;
1509
1510 ret = sunxi_nand_hw_common_ecc_ctrl_init(mtd, ecc, np);
1511 if (ret)
1512 return ret;
1513
1514 ecc->prepad = 4;
1515 ecc->read_page = sunxi_nfc_hw_syndrome_ecc_read_page;
1516 ecc->write_page = sunxi_nfc_hw_syndrome_ecc_write_page;
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001517 ecc->read_oob_raw = nand_read_oob_syndrome;
1518 ecc->write_oob_raw = nand_write_oob_syndrome;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001519
1520 layout = ecc->layout;
1521 nsectors = mtd->writesize / ecc->size;
1522
1523 for (i = 0; i < (ecc->bytes * nsectors); i++)
1524 layout->eccpos[i] = i;
1525
1526 layout->oobfree[0].length = mtd->oobsize - i;
1527 layout->oobfree[0].offset = i;
1528
1529 return 0;
1530}
1531
1532static void sunxi_nand_ecc_cleanup(struct nand_ecc_ctrl *ecc)
1533{
1534 switch (ecc->mode) {
1535 case NAND_ECC_HW:
1536 case NAND_ECC_HW_SYNDROME:
1537 sunxi_nand_hw_common_ecc_ctrl_cleanup(ecc);
1538 break;
1539 case NAND_ECC_NONE:
1540 kfree(ecc->layout);
1541 default:
1542 break;
1543 }
1544}
1545
1546static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc,
1547 struct device_node *np)
1548{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +01001549 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001550 int ret;
1551
Boris BREZILLONa3d22a52015-09-02 10:30:25 +02001552 if (!ecc->size) {
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001553 ecc->size = nand->ecc_step_ds;
1554 ecc->strength = nand->ecc_strength_ds;
1555 }
1556
1557 if (!ecc->size || !ecc->strength)
1558 return -EINVAL;
1559
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001560 switch (ecc->mode) {
1561 case NAND_ECC_SOFT_BCH:
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001562 break;
1563 case NAND_ECC_HW:
1564 ret = sunxi_nand_hw_ecc_ctrl_init(mtd, ecc, np);
1565 if (ret)
1566 return ret;
1567 break;
1568 case NAND_ECC_HW_SYNDROME:
1569 ret = sunxi_nand_hw_syndrome_ecc_ctrl_init(mtd, ecc, np);
1570 if (ret)
1571 return ret;
1572 break;
1573 case NAND_ECC_NONE:
1574 ecc->layout = kzalloc(sizeof(*ecc->layout), GFP_KERNEL);
1575 if (!ecc->layout)
1576 return -ENOMEM;
1577 ecc->layout->oobfree[0].length = mtd->oobsize;
1578 case NAND_ECC_SOFT:
1579 break;
1580 default:
1581 return -EINVAL;
1582 }
1583
1584 return 0;
1585}
1586
1587static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
1588 struct device_node *np)
1589{
1590 const struct nand_sdr_timings *timings;
1591 struct sunxi_nand_chip *chip;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001592 struct mtd_info *mtd;
1593 struct nand_chip *nand;
1594 int nsels;
1595 int ret;
1596 int i;
1597 u32 tmp;
1598
1599 if (!of_get_property(np, "reg", &nsels))
1600 return -EINVAL;
1601
1602 nsels /= sizeof(u32);
1603 if (!nsels) {
1604 dev_err(dev, "invalid reg property size\n");
1605 return -EINVAL;
1606 }
1607
1608 chip = devm_kzalloc(dev,
1609 sizeof(*chip) +
1610 (nsels * sizeof(struct sunxi_nand_chip_sel)),
1611 GFP_KERNEL);
1612 if (!chip) {
1613 dev_err(dev, "could not allocate chip\n");
1614 return -ENOMEM;
1615 }
1616
1617 chip->nsels = nsels;
1618 chip->selected = -1;
1619
1620 for (i = 0; i < nsels; i++) {
1621 ret = of_property_read_u32_index(np, "reg", i, &tmp);
1622 if (ret) {
1623 dev_err(dev, "could not retrieve reg property: %d\n",
1624 ret);
1625 return ret;
1626 }
1627
1628 if (tmp > NFC_MAX_CS) {
1629 dev_err(dev,
1630 "invalid reg value: %u (max CS = 7)\n",
1631 tmp);
1632 return -EINVAL;
1633 }
1634
1635 if (test_and_set_bit(tmp, &nfc->assigned_cs)) {
1636 dev_err(dev, "CS %d already assigned\n", tmp);
1637 return -EINVAL;
1638 }
1639
1640 chip->sels[i].cs = tmp;
1641
1642 if (!of_property_read_u32_index(np, "allwinner,rb", i, &tmp) &&
1643 tmp < 2) {
1644 chip->sels[i].rb.type = RB_NATIVE;
1645 chip->sels[i].rb.info.nativeid = tmp;
1646 } else {
1647 ret = of_get_named_gpio(np, "rb-gpios", i);
1648 if (ret >= 0) {
1649 tmp = ret;
1650 chip->sels[i].rb.type = RB_GPIO;
1651 chip->sels[i].rb.info.gpio = tmp;
1652 ret = devm_gpio_request(dev, tmp, "nand-rb");
1653 if (ret)
1654 return ret;
1655
1656 ret = gpio_direction_input(tmp);
1657 if (ret)
1658 return ret;
1659 } else {
1660 chip->sels[i].rb.type = RB_NONE;
1661 }
1662 }
1663 }
1664
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001665 nand = &chip->nand;
1666 /* Default tR value specified in the ONFI spec (chapter 4.15.1) */
1667 nand->chip_delay = 200;
1668 nand->controller = &nfc->controller;
Boris BREZILLONa3d22a52015-09-02 10:30:25 +02001669 /*
1670 * Set the ECC mode to the default value in case nothing is specified
1671 * in the DT.
1672 */
1673 nand->ecc.mode = NAND_ECC_HW;
Brian Norris63752192015-10-30 20:33:23 -07001674 nand_set_flash_node(nand, np);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001675 nand->select_chip = sunxi_nfc_select_chip;
1676 nand->cmd_ctrl = sunxi_nfc_cmd_ctrl;
1677 nand->read_buf = sunxi_nfc_read_buf;
1678 nand->write_buf = sunxi_nfc_write_buf;
1679 nand->read_byte = sunxi_nfc_read_byte;
1680
Boris BREZILLON32e9f2d2015-12-10 09:00:26 +01001681 mtd = nand_to_mtd(nand);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001682 mtd->dev.parent = dev;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001683
Boris Brezillon9edb4702015-12-02 16:00:57 +01001684 timings = onfi_async_timing_mode_to_sdr_timings(0);
1685 if (IS_ERR(timings)) {
1686 ret = PTR_ERR(timings);
1687 dev_err(dev,
1688 "could not retrieve timings for ONFI mode 0: %d\n",
1689 ret);
1690 return ret;
1691 }
1692
1693 ret = sunxi_nand_chip_set_timings(chip, timings);
1694 if (ret) {
1695 dev_err(dev, "could not configure chip timings: %d\n", ret);
1696 return ret;
1697 }
1698
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001699 ret = nand_scan_ident(mtd, nsels, NULL);
1700 if (ret)
1701 return ret;
1702
Boris BREZILLONa3d22a52015-09-02 10:30:25 +02001703 if (nand->bbt_options & NAND_BBT_USE_FLASH)
1704 nand->bbt_options |= NAND_BBT_NO_OOB;
1705
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001706 if (nand->options & NAND_NEED_SCRAMBLING)
1707 nand->options |= NAND_NO_SUBPAGE_WRITE;
1708
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001709 nand->options |= NAND_SUBPAGE_READ;
1710
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001711 ret = sunxi_nand_chip_init_timings(chip, np);
1712 if (ret) {
1713 dev_err(dev, "could not configure chip timings: %d\n", ret);
1714 return ret;
1715 }
1716
1717 ret = sunxi_nand_ecc_init(mtd, &nand->ecc, np);
1718 if (ret) {
1719 dev_err(dev, "ECC init failed: %d\n", ret);
1720 return ret;
1721 }
1722
1723 ret = nand_scan_tail(mtd);
1724 if (ret) {
1725 dev_err(dev, "nand_scan_tail failed: %d\n", ret);
1726 return ret;
1727 }
1728
Brian Norrisa61ae812015-10-30 20:33:25 -07001729 ret = mtd_device_register(mtd, NULL, 0);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001730 if (ret) {
1731 dev_err(dev, "failed to register mtd device: %d\n", ret);
1732 nand_release(mtd);
1733 return ret;
1734 }
1735
1736 list_add_tail(&chip->node, &nfc->chips);
1737
1738 return 0;
1739}
1740
1741static int sunxi_nand_chips_init(struct device *dev, struct sunxi_nfc *nfc)
1742{
1743 struct device_node *np = dev->of_node;
1744 struct device_node *nand_np;
1745 int nchips = of_get_child_count(np);
1746 int ret;
1747
1748 if (nchips > 8) {
1749 dev_err(dev, "too many NAND chips: %d (max = 8)\n", nchips);
1750 return -EINVAL;
1751 }
1752
1753 for_each_child_of_node(np, nand_np) {
1754 ret = sunxi_nand_chip_init(dev, nfc, nand_np);
Julia Lawalla81c0f02015-11-18 23:04:12 +01001755 if (ret) {
1756 of_node_put(nand_np);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001757 return ret;
Julia Lawalla81c0f02015-11-18 23:04:12 +01001758 }
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001759 }
1760
1761 return 0;
1762}
1763
1764static void sunxi_nand_chips_cleanup(struct sunxi_nfc *nfc)
1765{
1766 struct sunxi_nand_chip *chip;
1767
1768 while (!list_empty(&nfc->chips)) {
1769 chip = list_first_entry(&nfc->chips, struct sunxi_nand_chip,
1770 node);
Boris BREZILLON32e9f2d2015-12-10 09:00:26 +01001771 nand_release(nand_to_mtd(&chip->nand));
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001772 sunxi_nand_ecc_cleanup(&chip->nand.ecc);
Boris BREZILLON8e375cc2015-09-13 18:14:43 +02001773 list_del(&chip->node);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001774 }
1775}
1776
1777static int sunxi_nfc_probe(struct platform_device *pdev)
1778{
1779 struct device *dev = &pdev->dev;
1780 struct resource *r;
1781 struct sunxi_nfc *nfc;
1782 int irq;
1783 int ret;
1784
1785 nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
1786 if (!nfc)
1787 return -ENOMEM;
1788
1789 nfc->dev = dev;
1790 spin_lock_init(&nfc->controller.lock);
1791 init_waitqueue_head(&nfc->controller.wq);
1792 INIT_LIST_HEAD(&nfc->chips);
1793
1794 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1795 nfc->regs = devm_ioremap_resource(dev, r);
1796 if (IS_ERR(nfc->regs))
1797 return PTR_ERR(nfc->regs);
1798
1799 irq = platform_get_irq(pdev, 0);
1800 if (irq < 0) {
1801 dev_err(dev, "failed to retrieve irq\n");
1802 return irq;
1803 }
1804
1805 nfc->ahb_clk = devm_clk_get(dev, "ahb");
1806 if (IS_ERR(nfc->ahb_clk)) {
1807 dev_err(dev, "failed to retrieve ahb clk\n");
1808 return PTR_ERR(nfc->ahb_clk);
1809 }
1810
1811 ret = clk_prepare_enable(nfc->ahb_clk);
1812 if (ret)
1813 return ret;
1814
1815 nfc->mod_clk = devm_clk_get(dev, "mod");
1816 if (IS_ERR(nfc->mod_clk)) {
1817 dev_err(dev, "failed to retrieve mod clk\n");
1818 ret = PTR_ERR(nfc->mod_clk);
1819 goto out_ahb_clk_unprepare;
1820 }
1821
1822 ret = clk_prepare_enable(nfc->mod_clk);
1823 if (ret)
1824 goto out_ahb_clk_unprepare;
1825
1826 ret = sunxi_nfc_rst(nfc);
1827 if (ret)
1828 goto out_mod_clk_unprepare;
1829
1830 writel(0, nfc->regs + NFC_REG_INT);
1831 ret = devm_request_irq(dev, irq, sunxi_nfc_interrupt,
1832 0, "sunxi-nand", nfc);
1833 if (ret)
1834 goto out_mod_clk_unprepare;
1835
1836 platform_set_drvdata(pdev, nfc);
1837
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001838 ret = sunxi_nand_chips_init(dev, nfc);
1839 if (ret) {
1840 dev_err(dev, "failed to init nand chips\n");
1841 goto out_mod_clk_unprepare;
1842 }
1843
1844 return 0;
1845
1846out_mod_clk_unprepare:
1847 clk_disable_unprepare(nfc->mod_clk);
1848out_ahb_clk_unprepare:
1849 clk_disable_unprepare(nfc->ahb_clk);
1850
1851 return ret;
1852}
1853
1854static int sunxi_nfc_remove(struct platform_device *pdev)
1855{
1856 struct sunxi_nfc *nfc = platform_get_drvdata(pdev);
1857
1858 sunxi_nand_chips_cleanup(nfc);
Boris Brezillondd26a452016-03-04 18:26:40 +01001859 clk_disable_unprepare(nfc->mod_clk);
1860 clk_disable_unprepare(nfc->ahb_clk);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001861
1862 return 0;
1863}
1864
1865static const struct of_device_id sunxi_nfc_ids[] = {
1866 { .compatible = "allwinner,sun4i-a10-nand" },
1867 { /* sentinel */ }
1868};
1869MODULE_DEVICE_TABLE(of, sunxi_nfc_ids);
1870
1871static struct platform_driver sunxi_nfc_driver = {
1872 .driver = {
1873 .name = "sunxi_nand",
1874 .of_match_table = sunxi_nfc_ids,
1875 },
1876 .probe = sunxi_nfc_probe,
1877 .remove = sunxi_nfc_remove,
1878};
1879module_platform_driver(sunxi_nfc_driver);
1880
1881MODULE_LICENSE("GPL v2");
1882MODULE_AUTHOR("Boris BREZILLON");
1883MODULE_DESCRIPTION("Allwinner NAND Flash Controller driver");
1884MODULE_ALIAS("platform:sunxi_nand");