blob: d8ad50fbadb7e92b7a1886ee8e8438ac2be5d792 [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>
41#include <linux/io.h>
42
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)
157#define NFC_ECC_ERR_CNT(b, x) (((x) >> ((b) * 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;
241 int nsels;
242 struct sunxi_nand_chip_sel sels[0];
243};
244
245static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
246{
247 return container_of(nand, struct sunxi_nand_chip, nand);
248}
249
250/*
251 * NAND Controller structure: stores sunxi NAND controller information
252 *
253 * @controller: base controller structure
254 * @dev: parent device (used to print error messages)
255 * @regs: NAND controller registers
256 * @ahb_clk: NAND Controller AHB clock
257 * @mod_clk: NAND Controller mod clock
258 * @assigned_cs: bitmask describing already assigned CS lines
259 * @clk_rate: NAND controller current clock rate
260 * @chips: a list containing all the NAND chips attached to
261 * this NAND controller
262 * @complete: a completion object used to wait for NAND
263 * controller events
264 */
265struct sunxi_nfc {
266 struct nand_hw_control controller;
267 struct device *dev;
268 void __iomem *regs;
269 struct clk *ahb_clk;
270 struct clk *mod_clk;
271 unsigned long assigned_cs;
272 unsigned long clk_rate;
273 struct list_head chips;
274 struct completion complete;
275};
276
277static inline struct sunxi_nfc *to_sunxi_nfc(struct nand_hw_control *ctrl)
278{
279 return container_of(ctrl, struct sunxi_nfc, controller);
280}
281
282static irqreturn_t sunxi_nfc_interrupt(int irq, void *dev_id)
283{
284 struct sunxi_nfc *nfc = dev_id;
285 u32 st = readl(nfc->regs + NFC_REG_ST);
286 u32 ien = readl(nfc->regs + NFC_REG_INT);
287
288 if (!(ien & st))
289 return IRQ_NONE;
290
291 if ((ien & st) == ien)
292 complete(&nfc->complete);
293
294 writel(st & NFC_INT_MASK, nfc->regs + NFC_REG_ST);
295 writel(~st & ien & NFC_INT_MASK, nfc->regs + NFC_REG_INT);
296
297 return IRQ_HANDLED;
298}
299
300static int sunxi_nfc_wait_int(struct sunxi_nfc *nfc, u32 flags,
301 unsigned int timeout_ms)
302{
303 init_completion(&nfc->complete);
304
305 writel(flags, nfc->regs + NFC_REG_INT);
306
307 if (!timeout_ms)
308 timeout_ms = NFC_DEFAULT_TIMEOUT_MS;
309
310 if (!wait_for_completion_timeout(&nfc->complete,
311 msecs_to_jiffies(timeout_ms))) {
312 dev_err(nfc->dev, "wait interrupt timedout\n");
313 return -ETIMEDOUT;
314 }
315
316 return 0;
317}
318
319static int sunxi_nfc_wait_cmd_fifo_empty(struct sunxi_nfc *nfc)
320{
321 unsigned long timeout = jiffies +
322 msecs_to_jiffies(NFC_DEFAULT_TIMEOUT_MS);
323
324 do {
325 if (!(readl(nfc->regs + NFC_REG_ST) & NFC_CMD_FIFO_STATUS))
326 return 0;
327 } while (time_before(jiffies, timeout));
328
329 dev_err(nfc->dev, "wait for empty cmd FIFO timedout\n");
330 return -ETIMEDOUT;
331}
332
333static int sunxi_nfc_rst(struct sunxi_nfc *nfc)
334{
335 unsigned long timeout = jiffies +
336 msecs_to_jiffies(NFC_DEFAULT_TIMEOUT_MS);
337
338 writel(0, nfc->regs + NFC_REG_ECC_CTL);
339 writel(NFC_RESET, nfc->regs + NFC_REG_CTL);
340
341 do {
342 if (!(readl(nfc->regs + NFC_REG_CTL) & NFC_RESET))
343 return 0;
344 } while (time_before(jiffies, timeout));
345
346 dev_err(nfc->dev, "wait for NAND controller reset timedout\n");
347 return -ETIMEDOUT;
348}
349
350static int sunxi_nfc_dev_ready(struct mtd_info *mtd)
351{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100352 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200353 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
354 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
355 struct sunxi_nand_rb *rb;
356 unsigned long timeo = (sunxi_nand->nand.state == FL_ERASING ? 400 : 20);
357 int ret;
358
359 if (sunxi_nand->selected < 0)
360 return 0;
361
362 rb = &sunxi_nand->sels[sunxi_nand->selected].rb;
363
364 switch (rb->type) {
365 case RB_NATIVE:
366 ret = !!(readl(nfc->regs + NFC_REG_ST) &
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200367 NFC_RB_STATE(rb->info.nativeid));
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200368 if (ret)
369 break;
370
371 sunxi_nfc_wait_int(nfc, NFC_RB_B2R, timeo);
372 ret = !!(readl(nfc->regs + NFC_REG_ST) &
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200373 NFC_RB_STATE(rb->info.nativeid));
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200374 break;
375 case RB_GPIO:
376 ret = gpio_get_value(rb->info.gpio);
377 break;
378 case RB_NONE:
379 default:
380 ret = 0;
381 dev_err(nfc->dev, "cannot check R/B NAND status!\n");
382 break;
383 }
384
385 return ret;
386}
387
388static void sunxi_nfc_select_chip(struct mtd_info *mtd, int chip)
389{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100390 struct nand_chip *nand = mtd_to_nand(mtd);
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);
393 struct sunxi_nand_chip_sel *sel;
394 u32 ctl;
395
396 if (chip > 0 && chip >= sunxi_nand->nsels)
397 return;
398
399 if (chip == sunxi_nand->selected)
400 return;
401
402 ctl = readl(nfc->regs + NFC_REG_CTL) &
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200403 ~(NFC_PAGE_SHIFT_MSK | NFC_CE_SEL_MSK | NFC_RB_SEL_MSK | NFC_EN);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200404
405 if (chip >= 0) {
406 sel = &sunxi_nand->sels[chip];
407
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200408 ctl |= NFC_CE_SEL(sel->cs) | NFC_EN |
409 NFC_PAGE_SHIFT(nand->page_shift - 10);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200410 if (sel->rb.type == RB_NONE) {
411 nand->dev_ready = NULL;
412 } else {
413 nand->dev_ready = sunxi_nfc_dev_ready;
414 if (sel->rb.type == RB_NATIVE)
Boris BREZILLONb6a02c02015-09-16 09:46:36 +0200415 ctl |= NFC_RB_SEL(sel->rb.info.nativeid);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200416 }
417
418 writel(mtd->writesize, nfc->regs + NFC_REG_SPARE_AREA);
419
420 if (nfc->clk_rate != sunxi_nand->clk_rate) {
421 clk_set_rate(nfc->mod_clk, sunxi_nand->clk_rate);
422 nfc->clk_rate = sunxi_nand->clk_rate;
423 }
424 }
425
Roy Splietd052e502015-06-26 11:00:11 +0200426 writel(sunxi_nand->timing_ctl, nfc->regs + NFC_REG_TIMING_CTL);
Roy Spliet9c618292015-06-26 11:00:10 +0200427 writel(sunxi_nand->timing_cfg, nfc->regs + NFC_REG_TIMING_CFG);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200428 writel(ctl, nfc->regs + NFC_REG_CTL);
429
430 sunxi_nand->selected = chip;
431}
432
433static void sunxi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
434{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100435 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200436 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
437 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
438 int ret;
439 int cnt;
440 int offs = 0;
441 u32 tmp;
442
443 while (len > offs) {
444 cnt = min(len - offs, NFC_SRAM_SIZE);
445
446 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
447 if (ret)
448 break;
449
450 writel(cnt, nfc->regs + NFC_REG_CNT);
451 tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD;
452 writel(tmp, nfc->regs + NFC_REG_CMD);
453
454 ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0);
455 if (ret)
456 break;
457
458 if (buf)
459 memcpy_fromio(buf + offs, nfc->regs + NFC_RAM0_BASE,
460 cnt);
461 offs += cnt;
462 }
463}
464
465static void sunxi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf,
466 int len)
467{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100468 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200469 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
470 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
471 int ret;
472 int cnt;
473 int offs = 0;
474 u32 tmp;
475
476 while (len > offs) {
477 cnt = min(len - offs, NFC_SRAM_SIZE);
478
479 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
480 if (ret)
481 break;
482
483 writel(cnt, nfc->regs + NFC_REG_CNT);
484 memcpy_toio(nfc->regs + NFC_RAM0_BASE, buf + offs, cnt);
485 tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD |
486 NFC_ACCESS_DIR;
487 writel(tmp, nfc->regs + NFC_REG_CMD);
488
489 ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0);
490 if (ret)
491 break;
492
493 offs += cnt;
494 }
495}
496
497static uint8_t sunxi_nfc_read_byte(struct mtd_info *mtd)
498{
499 uint8_t ret;
500
501 sunxi_nfc_read_buf(mtd, &ret, 1);
502
503 return ret;
504}
505
506static void sunxi_nfc_cmd_ctrl(struct mtd_info *mtd, int dat,
507 unsigned int ctrl)
508{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100509 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200510 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
511 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
512 int ret;
513 u32 tmp;
514
515 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
516 if (ret)
517 return;
518
519 if (ctrl & NAND_CTRL_CHANGE) {
520 tmp = readl(nfc->regs + NFC_REG_CTL);
521 if (ctrl & NAND_NCE)
522 tmp |= NFC_CE_CTL;
523 else
524 tmp &= ~NFC_CE_CTL;
525 writel(tmp, nfc->regs + NFC_REG_CTL);
526 }
527
528 if (dat == NAND_CMD_NONE)
529 return;
530
531 if (ctrl & NAND_CLE) {
532 writel(NFC_SEND_CMD1 | dat, nfc->regs + NFC_REG_CMD);
533 } else {
534 writel(dat, nfc->regs + NFC_REG_ADDR_LOW);
535 writel(NFC_SEND_ADR, nfc->regs + NFC_REG_CMD);
536 }
537
538 sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0);
539}
540
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100541/* These seed values have been extracted from Allwinner's BSP */
542static const u16 sunxi_nfc_randomizer_page_seeds[] = {
543 0x2b75, 0x0bd0, 0x5ca3, 0x62d1, 0x1c93, 0x07e9, 0x2162, 0x3a72,
544 0x0d67, 0x67f9, 0x1be7, 0x077d, 0x032f, 0x0dac, 0x2716, 0x2436,
545 0x7922, 0x1510, 0x3860, 0x5287, 0x480f, 0x4252, 0x1789, 0x5a2d,
546 0x2a49, 0x5e10, 0x437f, 0x4b4e, 0x2f45, 0x216e, 0x5cb7, 0x7130,
547 0x2a3f, 0x60e4, 0x4dc9, 0x0ef0, 0x0f52, 0x1bb9, 0x6211, 0x7a56,
548 0x226d, 0x4ea7, 0x6f36, 0x3692, 0x38bf, 0x0c62, 0x05eb, 0x4c55,
549 0x60f4, 0x728c, 0x3b6f, 0x2037, 0x7f69, 0x0936, 0x651a, 0x4ceb,
550 0x6218, 0x79f3, 0x383f, 0x18d9, 0x4f05, 0x5c82, 0x2912, 0x6f17,
551 0x6856, 0x5938, 0x1007, 0x61ab, 0x3e7f, 0x57c2, 0x542f, 0x4f62,
552 0x7454, 0x2eac, 0x7739, 0x42d4, 0x2f90, 0x435a, 0x2e52, 0x2064,
553 0x637c, 0x66ad, 0x2c90, 0x0bad, 0x759c, 0x0029, 0x0986, 0x7126,
554 0x1ca7, 0x1605, 0x386a, 0x27f5, 0x1380, 0x6d75, 0x24c3, 0x0f8e,
555 0x2b7a, 0x1418, 0x1fd1, 0x7dc1, 0x2d8e, 0x43af, 0x2267, 0x7da3,
556 0x4e3d, 0x1338, 0x50db, 0x454d, 0x764d, 0x40a3, 0x42e6, 0x262b,
557 0x2d2e, 0x1aea, 0x2e17, 0x173d, 0x3a6e, 0x71bf, 0x25f9, 0x0a5d,
558 0x7c57, 0x0fbe, 0x46ce, 0x4939, 0x6b17, 0x37bb, 0x3e91, 0x76db,
559};
560
561/*
562 * sunxi_nfc_randomizer_ecc512_seeds and sunxi_nfc_randomizer_ecc1024_seeds
563 * have been generated using
564 * sunxi_nfc_randomizer_step(seed, (step_size * 8) + 15), which is what
565 * the randomizer engine does internally before de/scrambling OOB data.
566 *
567 * Those tables are statically defined to avoid calculating randomizer state
568 * at runtime.
569 */
570static const u16 sunxi_nfc_randomizer_ecc512_seeds[] = {
571 0x3346, 0x367f, 0x1f18, 0x769a, 0x4f64, 0x068c, 0x2ef1, 0x6b64,
572 0x28a9, 0x15d7, 0x30f8, 0x3659, 0x53db, 0x7c5f, 0x71d4, 0x4409,
573 0x26eb, 0x03cc, 0x655d, 0x47d4, 0x4daa, 0x0877, 0x712d, 0x3617,
574 0x3264, 0x49aa, 0x7f9e, 0x588e, 0x4fbc, 0x7176, 0x7f91, 0x6c6d,
575 0x4b95, 0x5fb7, 0x3844, 0x4037, 0x0184, 0x081b, 0x0ee8, 0x5b91,
576 0x293d, 0x1f71, 0x0e6f, 0x402b, 0x5122, 0x1e52, 0x22be, 0x3d2d,
577 0x75bc, 0x7c60, 0x6291, 0x1a2f, 0x61d4, 0x74aa, 0x4140, 0x29ab,
578 0x472d, 0x2852, 0x017e, 0x15e8, 0x5ec2, 0x17cf, 0x7d0f, 0x06b8,
579 0x117a, 0x6b94, 0x789b, 0x3126, 0x6ac5, 0x5be7, 0x150f, 0x51f8,
580 0x7889, 0x0aa5, 0x663d, 0x77e8, 0x0b87, 0x3dcb, 0x360d, 0x218b,
581 0x512f, 0x7dc9, 0x6a4d, 0x630a, 0x3547, 0x1dd2, 0x5aea, 0x69a5,
582 0x7bfa, 0x5e4f, 0x1519, 0x6430, 0x3a0e, 0x5eb3, 0x5425, 0x0c7a,
583 0x5540, 0x3670, 0x63c1, 0x31e9, 0x5a39, 0x2de7, 0x5979, 0x2891,
584 0x1562, 0x014b, 0x5b05, 0x2756, 0x5a34, 0x13aa, 0x6cb5, 0x2c36,
585 0x5e72, 0x1306, 0x0861, 0x15ef, 0x1ee8, 0x5a37, 0x7ac4, 0x45dd,
586 0x44c4, 0x7266, 0x2f41, 0x3ccc, 0x045e, 0x7d40, 0x7c66, 0x0fa0,
587};
588
589static const u16 sunxi_nfc_randomizer_ecc1024_seeds[] = {
590 0x2cf5, 0x35f1, 0x63a4, 0x5274, 0x2bd2, 0x778b, 0x7285, 0x32b6,
591 0x6a5c, 0x70d6, 0x757d, 0x6769, 0x5375, 0x1e81, 0x0cf3, 0x3982,
592 0x6787, 0x042a, 0x6c49, 0x1925, 0x56a8, 0x40a9, 0x063e, 0x7bd9,
593 0x4dbf, 0x55ec, 0x672e, 0x7334, 0x5185, 0x4d00, 0x232a, 0x7e07,
594 0x445d, 0x6b92, 0x528f, 0x4255, 0x53ba, 0x7d82, 0x2a2e, 0x3a4e,
595 0x75eb, 0x450c, 0x6844, 0x1b5d, 0x581a, 0x4cc6, 0x0379, 0x37b2,
596 0x419f, 0x0e92, 0x6b27, 0x5624, 0x01e3, 0x07c1, 0x44a5, 0x130c,
597 0x13e8, 0x5910, 0x0876, 0x60c5, 0x54e3, 0x5b7f, 0x2269, 0x509f,
598 0x7665, 0x36fd, 0x3e9a, 0x0579, 0x6295, 0x14ef, 0x0a81, 0x1bcc,
599 0x4b16, 0x64db, 0x0514, 0x4f07, 0x0591, 0x3576, 0x6853, 0x0d9e,
600 0x259f, 0x38b7, 0x64fb, 0x3094, 0x4693, 0x6ddd, 0x29bb, 0x0bc8,
601 0x3f47, 0x490e, 0x0c0e, 0x7933, 0x3c9e, 0x5840, 0x398d, 0x3e68,
602 0x4af1, 0x71f5, 0x57cf, 0x1121, 0x64eb, 0x3579, 0x15ac, 0x584d,
603 0x5f2a, 0x47e2, 0x6528, 0x6eac, 0x196e, 0x6b96, 0x0450, 0x0179,
604 0x609c, 0x06e1, 0x4626, 0x42c7, 0x273e, 0x486f, 0x0705, 0x1601,
605 0x145b, 0x407e, 0x062b, 0x57a5, 0x53f9, 0x5659, 0x4410, 0x3ccd,
606};
607
608static u16 sunxi_nfc_randomizer_step(u16 state, int count)
609{
610 state &= 0x7fff;
611
612 /*
613 * This loop is just a simple implementation of a Fibonacci LFSR using
614 * the x16 + x15 + 1 polynomial.
615 */
616 while (count--)
617 state = ((state >> 1) |
618 (((state ^ (state >> 1)) & 1) << 14)) & 0x7fff;
619
620 return state;
621}
622
623static u16 sunxi_nfc_randomizer_state(struct mtd_info *mtd, int page, bool ecc)
624{
625 const u16 *seeds = sunxi_nfc_randomizer_page_seeds;
Brian Norris46c135c2016-01-22 18:57:13 -0800626 int mod = mtd_div_by_ws(mtd->erasesize, mtd);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100627
628 if (mod > ARRAY_SIZE(sunxi_nfc_randomizer_page_seeds))
629 mod = ARRAY_SIZE(sunxi_nfc_randomizer_page_seeds);
630
631 if (ecc) {
632 if (mtd->ecc_step_size == 512)
633 seeds = sunxi_nfc_randomizer_ecc512_seeds;
634 else
635 seeds = sunxi_nfc_randomizer_ecc1024_seeds;
636 }
637
638 return seeds[page % mod];
639}
640
641static void sunxi_nfc_randomizer_config(struct mtd_info *mtd,
642 int page, bool ecc)
643{
Boris BREZILLONf671a1f2016-03-05 00:21:20 +0100644 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100645 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
646 u32 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
647 u16 state;
648
649 if (!(nand->options & NAND_NEED_SCRAMBLING))
650 return;
651
652 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
653 state = sunxi_nfc_randomizer_state(mtd, page, ecc);
654 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_RANDOM_SEED_MSK;
655 writel(ecc_ctl | NFC_RANDOM_SEED(state), nfc->regs + NFC_REG_ECC_CTL);
656}
657
658static void sunxi_nfc_randomizer_enable(struct mtd_info *mtd)
659{
Boris BREZILLONf671a1f2016-03-05 00:21:20 +0100660 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100661 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
662
663 if (!(nand->options & NAND_NEED_SCRAMBLING))
664 return;
665
666 writel(readl(nfc->regs + NFC_REG_ECC_CTL) | NFC_RANDOM_EN,
667 nfc->regs + NFC_REG_ECC_CTL);
668}
669
670static void sunxi_nfc_randomizer_disable(struct mtd_info *mtd)
671{
Boris BREZILLONf671a1f2016-03-05 00:21:20 +0100672 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100673 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
674
675 if (!(nand->options & NAND_NEED_SCRAMBLING))
676 return;
677
678 writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_RANDOM_EN,
679 nfc->regs + NFC_REG_ECC_CTL);
680}
681
682static void sunxi_nfc_randomize_bbm(struct mtd_info *mtd, int page, u8 *bbm)
683{
684 u16 state = sunxi_nfc_randomizer_state(mtd, page, true);
685
686 bbm[0] ^= state;
687 bbm[1] ^= sunxi_nfc_randomizer_step(state, 8);
688}
689
690static void sunxi_nfc_randomizer_write_buf(struct mtd_info *mtd,
691 const uint8_t *buf, int len,
692 bool ecc, int page)
693{
694 sunxi_nfc_randomizer_config(mtd, page, ecc);
695 sunxi_nfc_randomizer_enable(mtd);
696 sunxi_nfc_write_buf(mtd, buf, len);
697 sunxi_nfc_randomizer_disable(mtd);
698}
699
700static void sunxi_nfc_randomizer_read_buf(struct mtd_info *mtd, uint8_t *buf,
701 int len, bool ecc, int page)
702{
703 sunxi_nfc_randomizer_config(mtd, page, ecc);
704 sunxi_nfc_randomizer_enable(mtd);
705 sunxi_nfc_read_buf(mtd, buf, len);
706 sunxi_nfc_randomizer_disable(mtd);
707}
708
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200709static void sunxi_nfc_hw_ecc_enable(struct mtd_info *mtd)
710{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100711 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200712 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
713 struct sunxi_nand_hw_ecc *data = nand->ecc.priv;
714 u32 ecc_ctl;
715
716 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
717 ecc_ctl &= ~(NFC_ECC_MODE_MSK | NFC_ECC_PIPELINE |
718 NFC_ECC_BLOCK_SIZE_MSK);
719 ecc_ctl |= NFC_ECC_EN | NFC_ECC_MODE(data->mode) | NFC_ECC_EXCEPTION;
720
721 writel(ecc_ctl, nfc->regs + NFC_REG_ECC_CTL);
722}
723
724static void sunxi_nfc_hw_ecc_disable(struct mtd_info *mtd)
725{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100726 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200727 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
728
729 writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_ECC_EN,
730 nfc->regs + NFC_REG_ECC_CTL);
731}
732
Boris BREZILLONf363e0f2015-09-30 23:45:27 +0200733static inline void sunxi_nfc_user_data_to_buf(u32 user_data, u8 *buf)
734{
735 buf[0] = user_data;
736 buf[1] = user_data >> 8;
737 buf[2] = user_data >> 16;
738 buf[3] = user_data >> 24;
739}
740
Boris BREZILLON913821b2015-09-30 23:45:24 +0200741static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
742 u8 *data, int data_off,
743 u8 *oob, int oob_off,
744 int *cur_off,
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100745 unsigned int *max_bitflips,
746 bool bbm, int page)
Boris BREZILLON913821b2015-09-30 23:45:24 +0200747{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100748 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200749 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
750 struct nand_ecc_ctrl *ecc = &nand->ecc;
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100751 int raw_mode = 0;
Boris BREZILLON913821b2015-09-30 23:45:24 +0200752 u32 status;
753 int ret;
754
755 if (*cur_off != data_off)
756 nand->cmdfunc(mtd, NAND_CMD_RNDOUT, data_off, -1);
757
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100758 sunxi_nfc_randomizer_read_buf(mtd, NULL, ecc->size, false, page);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200759
Boris BREZILLON74eb9ff2015-10-20 22:16:00 +0200760 if (data_off + ecc->size != oob_off)
Boris BREZILLON913821b2015-09-30 23:45:24 +0200761 nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1);
762
763 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
764 if (ret)
765 return ret;
766
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100767 sunxi_nfc_randomizer_enable(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200768 writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP,
769 nfc->regs + NFC_REG_CMD);
770
771 ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100772 sunxi_nfc_randomizer_disable(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200773 if (ret)
774 return ret;
775
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100776 *cur_off = oob_off + ecc->bytes + 4;
777
Boris BREZILLON913821b2015-09-30 23:45:24 +0200778 status = readl(nfc->regs + NFC_REG_ECC_ST);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100779 if (status & NFC_ECC_PAT_FOUND(0)) {
780 u8 pattern = 0xff;
781
782 if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID) & 0x1)))
783 pattern = 0x0;
784
785 memset(data, pattern, ecc->size);
786 memset(oob, pattern, ecc->bytes + 4);
787
788 return 1;
789 }
790
Boris BREZILLON913821b2015-09-30 23:45:24 +0200791 ret = NFC_ECC_ERR_CNT(0, readl(nfc->regs + NFC_REG_ECC_ERR_CNT(0)));
792
793 memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size);
794
795 nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100796 sunxi_nfc_randomizer_read_buf(mtd, oob, ecc->bytes + 4, true, page);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200797
Boris BREZILLONf363e0f2015-09-30 23:45:27 +0200798 if (status & NFC_ECC_ERR(0)) {
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100799 /*
800 * Re-read the data with the randomizer disabled to identify
801 * bitflips in erased pages.
802 */
803 if (nand->options & NAND_NEED_SCRAMBLING) {
804 nand->cmdfunc(mtd, NAND_CMD_RNDOUT, data_off, -1);
805 nand->read_buf(mtd, data, ecc->size);
806 nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1);
807 nand->read_buf(mtd, oob, ecc->bytes + 4);
808 }
809
Boris BREZILLON146b5032015-09-30 23:45:29 +0200810 ret = nand_check_erased_ecc_chunk(data, ecc->size,
811 oob, ecc->bytes + 4,
812 NULL, 0, ecc->strength);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100813 if (ret >= 0)
814 raw_mode = 1;
Boris BREZILLONf363e0f2015-09-30 23:45:27 +0200815 } else {
816 /*
817 * The engine protects 4 bytes of OOB data per chunk.
818 * Retrieve the corrected OOB bytes.
819 */
820 sunxi_nfc_user_data_to_buf(readl(nfc->regs + NFC_REG_USER_DATA(0)),
821 oob);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100822
823 /* De-randomize the Bad Block Marker. */
824 if (bbm && nand->options & NAND_NEED_SCRAMBLING)
825 sunxi_nfc_randomize_bbm(mtd, page, oob);
Boris BREZILLONf363e0f2015-09-30 23:45:27 +0200826 }
Boris BREZILLON913821b2015-09-30 23:45:24 +0200827
828 if (ret < 0) {
829 mtd->ecc_stats.failed++;
830 } else {
831 mtd->ecc_stats.corrected += ret;
832 *max_bitflips = max_t(unsigned int, *max_bitflips, ret);
833 }
834
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100835 return raw_mode;
Boris BREZILLON913821b2015-09-30 23:45:24 +0200836}
837
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200838static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd,
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100839 u8 *oob, int *cur_off,
840 bool randomize, int page)
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200841{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100842 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200843 struct nand_ecc_ctrl *ecc = &nand->ecc;
844 int offset = ((ecc->bytes + 4) * ecc->steps);
845 int len = mtd->oobsize - offset;
846
847 if (len <= 0)
848 return;
849
850 if (*cur_off != offset)
851 nand->cmdfunc(mtd, NAND_CMD_RNDOUT,
852 offset + mtd->writesize, -1);
853
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100854 if (!randomize)
855 sunxi_nfc_read_buf(mtd, oob + offset, len);
856 else
857 sunxi_nfc_randomizer_read_buf(mtd, oob + offset, len,
858 false, page);
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200859
860 *cur_off = mtd->oobsize + mtd->writesize;
861}
862
Boris BREZILLON23151fd2015-09-30 23:45:28 +0200863static inline u32 sunxi_nfc_buf_to_user_data(const u8 *buf)
864{
865 return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
866}
867
Boris BREZILLON913821b2015-09-30 23:45:24 +0200868static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd,
869 const u8 *data, int data_off,
870 const u8 *oob, int oob_off,
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100871 int *cur_off, bool bbm,
872 int page)
Boris BREZILLON913821b2015-09-30 23:45:24 +0200873{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100874 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200875 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
876 struct nand_ecc_ctrl *ecc = &nand->ecc;
877 int ret;
878
879 if (data_off != *cur_off)
880 nand->cmdfunc(mtd, NAND_CMD_RNDIN, data_off, -1);
881
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100882 sunxi_nfc_randomizer_write_buf(mtd, data, ecc->size, false, page);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200883
884 /* Fill OOB data in */
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100885 if ((nand->options & NAND_NEED_SCRAMBLING) && bbm) {
886 u8 user_data[4];
887
888 memcpy(user_data, oob, 4);
889 sunxi_nfc_randomize_bbm(mtd, page, user_data);
890 writel(sunxi_nfc_buf_to_user_data(user_data),
891 nfc->regs + NFC_REG_USER_DATA(0));
892 } else {
893 writel(sunxi_nfc_buf_to_user_data(oob),
894 nfc->regs + NFC_REG_USER_DATA(0));
895 }
Boris BREZILLON913821b2015-09-30 23:45:24 +0200896
Boris BREZILLON74eb9ff2015-10-20 22:16:00 +0200897 if (data_off + ecc->size != oob_off)
Boris BREZILLON913821b2015-09-30 23:45:24 +0200898 nand->cmdfunc(mtd, NAND_CMD_RNDIN, oob_off, -1);
899
900 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
901 if (ret)
902 return ret;
903
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100904 sunxi_nfc_randomizer_enable(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200905 writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD |
906 NFC_ACCESS_DIR | NFC_ECC_OP,
907 nfc->regs + NFC_REG_CMD);
908
909 ret = sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100910 sunxi_nfc_randomizer_disable(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200911 if (ret)
912 return ret;
913
914 *cur_off = oob_off + ecc->bytes + 4;
915
916 return 0;
917}
918
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200919static void sunxi_nfc_hw_ecc_write_extra_oob(struct mtd_info *mtd,
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100920 u8 *oob, int *cur_off,
921 int page)
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200922{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100923 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200924 struct nand_ecc_ctrl *ecc = &nand->ecc;
925 int offset = ((ecc->bytes + 4) * ecc->steps);
926 int len = mtd->oobsize - offset;
927
928 if (len <= 0)
929 return;
930
931 if (*cur_off != offset)
932 nand->cmdfunc(mtd, NAND_CMD_RNDIN,
933 offset + mtd->writesize, -1);
934
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100935 sunxi_nfc_randomizer_write_buf(mtd, oob + offset, len, false, page);
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200936
937 *cur_off = mtd->oobsize + mtd->writesize;
938}
939
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200940static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd,
941 struct nand_chip *chip, uint8_t *buf,
942 int oob_required, int page)
943{
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200944 struct nand_ecc_ctrl *ecc = &chip->ecc;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200945 unsigned int max_bitflips = 0;
Boris BREZILLONb4625512015-09-30 23:45:25 +0200946 int ret, i, cur_off = 0;
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100947 bool raw_mode = false;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200948
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200949 sunxi_nfc_hw_ecc_enable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200950
951 for (i = 0; i < ecc->steps; i++) {
Boris BREZILLONb4625512015-09-30 23:45:25 +0200952 int data_off = i * ecc->size;
953 int oob_off = i * (ecc->bytes + 4);
954 u8 *data = buf + data_off;
955 u8 *oob = chip->oob_poi + oob_off;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200956
Boris BREZILLONb4625512015-09-30 23:45:25 +0200957 ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob,
958 oob_off + mtd->writesize,
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100959 &cur_off, &max_bitflips,
960 !i, page);
961 if (ret < 0)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200962 return ret;
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100963 else if (ret)
964 raw_mode = true;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200965 }
966
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200967 if (oob_required)
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100968 sunxi_nfc_hw_ecc_read_extra_oob(mtd, chip->oob_poi, &cur_off,
969 !raw_mode, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200970
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200971 sunxi_nfc_hw_ecc_disable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200972
973 return max_bitflips;
974}
975
976static int sunxi_nfc_hw_ecc_write_page(struct mtd_info *mtd,
977 struct nand_chip *chip,
Boris BREZILLON45aaeff2015-10-13 11:22:18 +0200978 const uint8_t *buf, int oob_required,
979 int page)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200980{
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200981 struct nand_ecc_ctrl *ecc = &chip->ecc;
Boris BREZILLONb4625512015-09-30 23:45:25 +0200982 int ret, i, cur_off = 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200983
Boris BREZILLONc9118ec2015-09-30 23:45:23 +0200984 sunxi_nfc_hw_ecc_enable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200985
986 for (i = 0; i < ecc->steps; i++) {
Boris BREZILLONb4625512015-09-30 23:45:25 +0200987 int data_off = i * ecc->size;
988 int oob_off = i * (ecc->bytes + 4);
989 const u8 *data = buf + data_off;
990 const u8 *oob = chip->oob_poi + oob_off;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200991
Boris BREZILLONb4625512015-09-30 23:45:25 +0200992 ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off, oob,
993 oob_off + mtd->writesize,
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100994 &cur_off, !i, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +0200995 if (ret)
996 return ret;
997 }
998
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100999 if (oob_required || (chip->options & NAND_NEED_SCRAMBLING))
1000 sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi,
1001 &cur_off, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001002
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001003 sunxi_nfc_hw_ecc_disable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001004
1005 return 0;
1006}
1007
1008static int sunxi_nfc_hw_syndrome_ecc_read_page(struct mtd_info *mtd,
1009 struct nand_chip *chip,
1010 uint8_t *buf, int oob_required,
1011 int page)
1012{
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001013 struct nand_ecc_ctrl *ecc = &chip->ecc;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001014 unsigned int max_bitflips = 0;
Boris BREZILLONb4625512015-09-30 23:45:25 +02001015 int ret, i, cur_off = 0;
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001016 bool raw_mode = false;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001017
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001018 sunxi_nfc_hw_ecc_enable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001019
1020 for (i = 0; i < ecc->steps; i++) {
Boris BREZILLONb4625512015-09-30 23:45:25 +02001021 int data_off = i * (ecc->size + ecc->bytes + 4);
1022 int oob_off = data_off + ecc->size;
1023 u8 *data = buf + (i * ecc->size);
1024 u8 *oob = chip->oob_poi + (i * (ecc->bytes + 4));
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001025
Boris BREZILLONb4625512015-09-30 23:45:25 +02001026 ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob,
1027 oob_off, &cur_off,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001028 &max_bitflips, !i, page);
1029 if (ret < 0)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001030 return ret;
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001031 else if (ret)
1032 raw_mode = true;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001033 }
1034
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001035 if (oob_required)
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001036 sunxi_nfc_hw_ecc_read_extra_oob(mtd, chip->oob_poi, &cur_off,
1037 !raw_mode, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001038
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001039 sunxi_nfc_hw_ecc_disable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001040
1041 return max_bitflips;
1042}
1043
1044static int sunxi_nfc_hw_syndrome_ecc_write_page(struct mtd_info *mtd,
1045 struct nand_chip *chip,
1046 const uint8_t *buf,
Boris BREZILLON45aaeff2015-10-13 11:22:18 +02001047 int oob_required, int page)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001048{
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001049 struct nand_ecc_ctrl *ecc = &chip->ecc;
Boris BREZILLONb4625512015-09-30 23:45:25 +02001050 int ret, i, cur_off = 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001051
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001052 sunxi_nfc_hw_ecc_enable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001053
1054 for (i = 0; i < ecc->steps; i++) {
Boris BREZILLONb4625512015-09-30 23:45:25 +02001055 int data_off = i * (ecc->size + ecc->bytes + 4);
1056 int oob_off = data_off + ecc->size;
1057 const u8 *data = buf + (i * ecc->size);
1058 const u8 *oob = chip->oob_poi + (i * (ecc->bytes + 4));
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001059
Boris BREZILLONb4625512015-09-30 23:45:25 +02001060 ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001061 oob, oob_off, &cur_off,
1062 false, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001063 if (ret)
1064 return ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001065 }
1066
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001067 if (oob_required || (chip->options & NAND_NEED_SCRAMBLING))
1068 sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi,
1069 &cur_off, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001070
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001071 sunxi_nfc_hw_ecc_disable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001072
1073 return 0;
1074}
1075
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001076static int sunxi_nfc_hw_common_ecc_read_oob(struct mtd_info *mtd,
1077 struct nand_chip *chip,
1078 int page)
1079{
1080 chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
1081
1082 chip->pagebuf = -1;
1083
1084 return chip->ecc.read_page(mtd, chip, chip->buffers->databuf, 1, page);
1085}
1086
1087static int sunxi_nfc_hw_common_ecc_write_oob(struct mtd_info *mtd,
1088 struct nand_chip *chip,
1089 int page)
1090{
1091 int ret, status;
1092
1093 chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0, page);
1094
1095 chip->pagebuf = -1;
1096
1097 memset(chip->buffers->databuf, 0xff, mtd->writesize);
1098 ret = chip->ecc.write_page(mtd, chip, chip->buffers->databuf, 1, page);
1099 if (ret)
1100 return ret;
1101
1102 /* Send command to program the OOB data */
1103 chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
1104
1105 status = chip->waitfunc(mtd, chip);
1106
1107 return status & NAND_STATUS_FAIL ? -EIO : 0;
1108}
1109
Roy Spliet9c618292015-06-26 11:00:10 +02001110static const s32 tWB_lut[] = {6, 12, 16, 20};
1111static const s32 tRHW_lut[] = {4, 8, 12, 20};
1112
1113static int _sunxi_nand_lookup_timing(const s32 *lut, int lut_size, u32 duration,
1114 u32 clk_period)
1115{
1116 u32 clk_cycles = DIV_ROUND_UP(duration, clk_period);
1117 int i;
1118
1119 for (i = 0; i < lut_size; i++) {
1120 if (clk_cycles <= lut[i])
1121 return i;
1122 }
1123
1124 /* Doesn't fit */
1125 return -EINVAL;
1126}
1127
1128#define sunxi_nand_lookup_timing(l, p, c) \
1129 _sunxi_nand_lookup_timing(l, ARRAY_SIZE(l), p, c)
1130
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001131static int sunxi_nand_chip_set_timings(struct sunxi_nand_chip *chip,
1132 const struct nand_sdr_timings *timings)
1133{
Roy Spliet9c618292015-06-26 11:00:10 +02001134 struct sunxi_nfc *nfc = to_sunxi_nfc(chip->nand.controller);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001135 u32 min_clk_period = 0;
Roy Spliet9c618292015-06-26 11:00:10 +02001136 s32 tWB, tADL, tWHR, tRHW, tCAD;
Boris Brezillon2d434572015-12-02 15:57:20 +01001137 long real_clk_rate;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001138
1139 /* T1 <=> tCLS */
1140 if (timings->tCLS_min > min_clk_period)
1141 min_clk_period = timings->tCLS_min;
1142
1143 /* T2 <=> tCLH */
1144 if (timings->tCLH_min > min_clk_period)
1145 min_clk_period = timings->tCLH_min;
1146
1147 /* T3 <=> tCS */
1148 if (timings->tCS_min > min_clk_period)
1149 min_clk_period = timings->tCS_min;
1150
1151 /* T4 <=> tCH */
1152 if (timings->tCH_min > min_clk_period)
1153 min_clk_period = timings->tCH_min;
1154
1155 /* T5 <=> tWP */
1156 if (timings->tWP_min > min_clk_period)
1157 min_clk_period = timings->tWP_min;
1158
1159 /* T6 <=> tWH */
1160 if (timings->tWH_min > min_clk_period)
1161 min_clk_period = timings->tWH_min;
1162
1163 /* T7 <=> tALS */
1164 if (timings->tALS_min > min_clk_period)
1165 min_clk_period = timings->tALS_min;
1166
1167 /* T8 <=> tDS */
1168 if (timings->tDS_min > min_clk_period)
1169 min_clk_period = timings->tDS_min;
1170
1171 /* T9 <=> tDH */
1172 if (timings->tDH_min > min_clk_period)
1173 min_clk_period = timings->tDH_min;
1174
1175 /* T10 <=> tRR */
1176 if (timings->tRR_min > (min_clk_period * 3))
1177 min_clk_period = DIV_ROUND_UP(timings->tRR_min, 3);
1178
1179 /* T11 <=> tALH */
1180 if (timings->tALH_min > min_clk_period)
1181 min_clk_period = timings->tALH_min;
1182
1183 /* T12 <=> tRP */
1184 if (timings->tRP_min > min_clk_period)
1185 min_clk_period = timings->tRP_min;
1186
1187 /* T13 <=> tREH */
1188 if (timings->tREH_min > min_clk_period)
1189 min_clk_period = timings->tREH_min;
1190
1191 /* T14 <=> tRC */
1192 if (timings->tRC_min > (min_clk_period * 2))
1193 min_clk_period = DIV_ROUND_UP(timings->tRC_min, 2);
1194
1195 /* T15 <=> tWC */
1196 if (timings->tWC_min > (min_clk_period * 2))
1197 min_clk_period = DIV_ROUND_UP(timings->tWC_min, 2);
1198
Roy Spliet9c618292015-06-26 11:00:10 +02001199 /* T16 - T19 + tCAD */
Boris Brezillon5abcd952015-11-11 22:30:30 +01001200 if (timings->tWB_max > (min_clk_period * 20))
1201 min_clk_period = DIV_ROUND_UP(timings->tWB_max, 20);
1202
1203 if (timings->tADL_min > (min_clk_period * 32))
1204 min_clk_period = DIV_ROUND_UP(timings->tADL_min, 32);
1205
1206 if (timings->tWHR_min > (min_clk_period * 32))
1207 min_clk_period = DIV_ROUND_UP(timings->tWHR_min, 32);
1208
1209 if (timings->tRHW_min > (min_clk_period * 20))
1210 min_clk_period = DIV_ROUND_UP(timings->tRHW_min, 20);
1211
Roy Spliet9c618292015-06-26 11:00:10 +02001212 tWB = sunxi_nand_lookup_timing(tWB_lut, timings->tWB_max,
1213 min_clk_period);
1214 if (tWB < 0) {
1215 dev_err(nfc->dev, "unsupported tWB\n");
1216 return tWB;
1217 }
1218
1219 tADL = DIV_ROUND_UP(timings->tADL_min, min_clk_period) >> 3;
1220 if (tADL > 3) {
1221 dev_err(nfc->dev, "unsupported tADL\n");
1222 return -EINVAL;
1223 }
1224
1225 tWHR = DIV_ROUND_UP(timings->tWHR_min, min_clk_period) >> 3;
1226 if (tWHR > 3) {
1227 dev_err(nfc->dev, "unsupported tWHR\n");
1228 return -EINVAL;
1229 }
1230
1231 tRHW = sunxi_nand_lookup_timing(tRHW_lut, timings->tRHW_min,
1232 min_clk_period);
1233 if (tRHW < 0) {
1234 dev_err(nfc->dev, "unsupported tRHW\n");
1235 return tRHW;
1236 }
1237
1238 /*
1239 * TODO: according to ONFI specs this value only applies for DDR NAND,
1240 * but Allwinner seems to set this to 0x7. Mimic them for now.
1241 */
1242 tCAD = 0x7;
1243
1244 /* TODO: A83 has some more bits for CDQSS, CS, CLHZ, CCS, WC */
1245 chip->timing_cfg = NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001246
1247 /* Convert min_clk_period from picoseconds to nanoseconds */
1248 min_clk_period = DIV_ROUND_UP(min_clk_period, 1000);
1249
1250 /*
Boris Brezillon2f9992e2015-12-02 15:10:40 +01001251 * Unlike what is stated in Allwinner datasheet, the clk_rate should
1252 * be set to (1 / min_clk_period), and not (2 / min_clk_period).
1253 * This new formula was verified with a scope and validated by
1254 * Allwinner engineers.
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001255 */
Boris Brezillon2f9992e2015-12-02 15:10:40 +01001256 chip->clk_rate = NSEC_PER_SEC / min_clk_period;
Boris Brezillon2d434572015-12-02 15:57:20 +01001257 real_clk_rate = clk_round_rate(nfc->mod_clk, chip->clk_rate);
1258
1259 /*
1260 * ONFI specification 3.1, paragraph 4.15.2 dictates that EDO data
1261 * output cycle timings shall be used if the host drives tRC less than
1262 * 30 ns.
1263 */
1264 min_clk_period = NSEC_PER_SEC / real_clk_rate;
1265 chip->timing_ctl = ((min_clk_period * 2) < 30) ?
1266 NFC_TIMING_CTL_EDO : 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001267
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001268 return 0;
1269}
1270
1271static int sunxi_nand_chip_init_timings(struct sunxi_nand_chip *chip,
1272 struct device_node *np)
1273{
Boris BREZILLON32e9f2d2015-12-10 09:00:26 +01001274 struct mtd_info *mtd = nand_to_mtd(&chip->nand);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001275 const struct nand_sdr_timings *timings;
1276 int ret;
1277 int mode;
1278
1279 mode = onfi_get_async_timing_mode(&chip->nand);
1280 if (mode == ONFI_TIMING_MODE_UNKNOWN) {
1281 mode = chip->nand.onfi_timing_mode_default;
1282 } else {
1283 uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {};
Stefan Roese7eadd472015-08-28 14:45:21 +02001284 int i;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001285
1286 mode = fls(mode) - 1;
1287 if (mode < 0)
1288 mode = 0;
1289
1290 feature[0] = mode;
Stefan Roese7eadd472015-08-28 14:45:21 +02001291 for (i = 0; i < chip->nsels; i++) {
Boris BREZILLON32e9f2d2015-12-10 09:00:26 +01001292 chip->nand.select_chip(mtd, i);
1293 ret = chip->nand.onfi_set_features(mtd, &chip->nand,
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001294 ONFI_FEATURE_ADDR_TIMING_MODE,
1295 feature);
Boris BREZILLON32e9f2d2015-12-10 09:00:26 +01001296 chip->nand.select_chip(mtd, -1);
Stefan Roese7eadd472015-08-28 14:45:21 +02001297 if (ret)
1298 return ret;
1299 }
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001300 }
1301
1302 timings = onfi_async_timing_mode_to_sdr_timings(mode);
1303 if (IS_ERR(timings))
1304 return PTR_ERR(timings);
1305
1306 return sunxi_nand_chip_set_timings(chip, timings);
1307}
1308
1309static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd,
1310 struct nand_ecc_ctrl *ecc,
1311 struct device_node *np)
1312{
1313 static const u8 strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 };
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +01001314 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001315 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
1316 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
1317 struct sunxi_nand_hw_ecc *data;
1318 struct nand_ecclayout *layout;
1319 int nsectors;
1320 int ret;
1321 int i;
1322
1323 data = kzalloc(sizeof(*data), GFP_KERNEL);
1324 if (!data)
1325 return -ENOMEM;
1326
1327 /* Add ECC info retrieval from DT */
1328 for (i = 0; i < ARRAY_SIZE(strengths); i++) {
1329 if (ecc->strength <= strengths[i])
1330 break;
1331 }
1332
1333 if (i >= ARRAY_SIZE(strengths)) {
1334 dev_err(nfc->dev, "unsupported strength\n");
1335 ret = -ENOTSUPP;
1336 goto err;
1337 }
1338
1339 data->mode = i;
1340
1341 /* HW ECC always request ECC bytes for 1024 bytes blocks */
1342 ecc->bytes = DIV_ROUND_UP(ecc->strength * fls(8 * 1024), 8);
1343
1344 /* HW ECC always work with even numbers of ECC bytes */
1345 ecc->bytes = ALIGN(ecc->bytes, 2);
1346
1347 layout = &data->layout;
1348 nsectors = mtd->writesize / ecc->size;
1349
1350 if (mtd->oobsize < ((ecc->bytes + 4) * nsectors)) {
1351 ret = -EINVAL;
1352 goto err;
1353 }
1354
1355 layout->eccbytes = (ecc->bytes * nsectors);
1356
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001357 ecc->read_oob = sunxi_nfc_hw_common_ecc_read_oob;
1358 ecc->write_oob = sunxi_nfc_hw_common_ecc_write_oob;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001359 ecc->layout = layout;
1360 ecc->priv = data;
1361
1362 return 0;
1363
1364err:
1365 kfree(data);
1366
1367 return ret;
1368}
1369
1370static void sunxi_nand_hw_common_ecc_ctrl_cleanup(struct nand_ecc_ctrl *ecc)
1371{
1372 kfree(ecc->priv);
1373}
1374
1375static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
1376 struct nand_ecc_ctrl *ecc,
1377 struct device_node *np)
1378{
1379 struct nand_ecclayout *layout;
1380 int nsectors;
1381 int i, j;
1382 int ret;
1383
1384 ret = sunxi_nand_hw_common_ecc_ctrl_init(mtd, ecc, np);
1385 if (ret)
1386 return ret;
1387
1388 ecc->read_page = sunxi_nfc_hw_ecc_read_page;
1389 ecc->write_page = sunxi_nfc_hw_ecc_write_page;
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001390 ecc->read_oob_raw = nand_read_oob_std;
1391 ecc->write_oob_raw = nand_write_oob_std;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001392 layout = ecc->layout;
1393 nsectors = mtd->writesize / ecc->size;
1394
1395 for (i = 0; i < nsectors; i++) {
1396 if (i) {
1397 layout->oobfree[i].offset =
1398 layout->oobfree[i - 1].offset +
1399 layout->oobfree[i - 1].length +
1400 ecc->bytes;
1401 layout->oobfree[i].length = 4;
1402 } else {
1403 /*
1404 * The first 2 bytes are used for BB markers, hence we
1405 * only have 2 bytes available in the first user data
1406 * section.
1407 */
1408 layout->oobfree[i].length = 2;
1409 layout->oobfree[i].offset = 2;
1410 }
1411
1412 for (j = 0; j < ecc->bytes; j++)
1413 layout->eccpos[(ecc->bytes * i) + j] =
1414 layout->oobfree[i].offset +
1415 layout->oobfree[i].length + j;
1416 }
1417
1418 if (mtd->oobsize > (ecc->bytes + 4) * nsectors) {
1419 layout->oobfree[nsectors].offset =
1420 layout->oobfree[nsectors - 1].offset +
1421 layout->oobfree[nsectors - 1].length +
1422 ecc->bytes;
1423 layout->oobfree[nsectors].length = mtd->oobsize -
1424 ((ecc->bytes + 4) * nsectors);
1425 }
1426
1427 return 0;
1428}
1429
1430static int sunxi_nand_hw_syndrome_ecc_ctrl_init(struct mtd_info *mtd,
1431 struct nand_ecc_ctrl *ecc,
1432 struct device_node *np)
1433{
1434 struct nand_ecclayout *layout;
1435 int nsectors;
1436 int i;
1437 int ret;
1438
1439 ret = sunxi_nand_hw_common_ecc_ctrl_init(mtd, ecc, np);
1440 if (ret)
1441 return ret;
1442
1443 ecc->prepad = 4;
1444 ecc->read_page = sunxi_nfc_hw_syndrome_ecc_read_page;
1445 ecc->write_page = sunxi_nfc_hw_syndrome_ecc_write_page;
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001446 ecc->read_oob_raw = nand_read_oob_syndrome;
1447 ecc->write_oob_raw = nand_write_oob_syndrome;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001448
1449 layout = ecc->layout;
1450 nsectors = mtd->writesize / ecc->size;
1451
1452 for (i = 0; i < (ecc->bytes * nsectors); i++)
1453 layout->eccpos[i] = i;
1454
1455 layout->oobfree[0].length = mtd->oobsize - i;
1456 layout->oobfree[0].offset = i;
1457
1458 return 0;
1459}
1460
1461static void sunxi_nand_ecc_cleanup(struct nand_ecc_ctrl *ecc)
1462{
1463 switch (ecc->mode) {
1464 case NAND_ECC_HW:
1465 case NAND_ECC_HW_SYNDROME:
1466 sunxi_nand_hw_common_ecc_ctrl_cleanup(ecc);
1467 break;
1468 case NAND_ECC_NONE:
1469 kfree(ecc->layout);
1470 default:
1471 break;
1472 }
1473}
1474
1475static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc,
1476 struct device_node *np)
1477{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +01001478 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001479 int ret;
1480
Boris BREZILLONa3d22a52015-09-02 10:30:25 +02001481 if (!ecc->size) {
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001482 ecc->size = nand->ecc_step_ds;
1483 ecc->strength = nand->ecc_strength_ds;
1484 }
1485
1486 if (!ecc->size || !ecc->strength)
1487 return -EINVAL;
1488
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001489 switch (ecc->mode) {
1490 case NAND_ECC_SOFT_BCH:
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001491 break;
1492 case NAND_ECC_HW:
1493 ret = sunxi_nand_hw_ecc_ctrl_init(mtd, ecc, np);
1494 if (ret)
1495 return ret;
1496 break;
1497 case NAND_ECC_HW_SYNDROME:
1498 ret = sunxi_nand_hw_syndrome_ecc_ctrl_init(mtd, ecc, np);
1499 if (ret)
1500 return ret;
1501 break;
1502 case NAND_ECC_NONE:
1503 ecc->layout = kzalloc(sizeof(*ecc->layout), GFP_KERNEL);
1504 if (!ecc->layout)
1505 return -ENOMEM;
1506 ecc->layout->oobfree[0].length = mtd->oobsize;
1507 case NAND_ECC_SOFT:
1508 break;
1509 default:
1510 return -EINVAL;
1511 }
1512
1513 return 0;
1514}
1515
1516static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
1517 struct device_node *np)
1518{
1519 const struct nand_sdr_timings *timings;
1520 struct sunxi_nand_chip *chip;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001521 struct mtd_info *mtd;
1522 struct nand_chip *nand;
1523 int nsels;
1524 int ret;
1525 int i;
1526 u32 tmp;
1527
1528 if (!of_get_property(np, "reg", &nsels))
1529 return -EINVAL;
1530
1531 nsels /= sizeof(u32);
1532 if (!nsels) {
1533 dev_err(dev, "invalid reg property size\n");
1534 return -EINVAL;
1535 }
1536
1537 chip = devm_kzalloc(dev,
1538 sizeof(*chip) +
1539 (nsels * sizeof(struct sunxi_nand_chip_sel)),
1540 GFP_KERNEL);
1541 if (!chip) {
1542 dev_err(dev, "could not allocate chip\n");
1543 return -ENOMEM;
1544 }
1545
1546 chip->nsels = nsels;
1547 chip->selected = -1;
1548
1549 for (i = 0; i < nsels; i++) {
1550 ret = of_property_read_u32_index(np, "reg", i, &tmp);
1551 if (ret) {
1552 dev_err(dev, "could not retrieve reg property: %d\n",
1553 ret);
1554 return ret;
1555 }
1556
1557 if (tmp > NFC_MAX_CS) {
1558 dev_err(dev,
1559 "invalid reg value: %u (max CS = 7)\n",
1560 tmp);
1561 return -EINVAL;
1562 }
1563
1564 if (test_and_set_bit(tmp, &nfc->assigned_cs)) {
1565 dev_err(dev, "CS %d already assigned\n", tmp);
1566 return -EINVAL;
1567 }
1568
1569 chip->sels[i].cs = tmp;
1570
1571 if (!of_property_read_u32_index(np, "allwinner,rb", i, &tmp) &&
1572 tmp < 2) {
1573 chip->sels[i].rb.type = RB_NATIVE;
1574 chip->sels[i].rb.info.nativeid = tmp;
1575 } else {
1576 ret = of_get_named_gpio(np, "rb-gpios", i);
1577 if (ret >= 0) {
1578 tmp = ret;
1579 chip->sels[i].rb.type = RB_GPIO;
1580 chip->sels[i].rb.info.gpio = tmp;
1581 ret = devm_gpio_request(dev, tmp, "nand-rb");
1582 if (ret)
1583 return ret;
1584
1585 ret = gpio_direction_input(tmp);
1586 if (ret)
1587 return ret;
1588 } else {
1589 chip->sels[i].rb.type = RB_NONE;
1590 }
1591 }
1592 }
1593
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001594 nand = &chip->nand;
1595 /* Default tR value specified in the ONFI spec (chapter 4.15.1) */
1596 nand->chip_delay = 200;
1597 nand->controller = &nfc->controller;
Boris BREZILLONa3d22a52015-09-02 10:30:25 +02001598 /*
1599 * Set the ECC mode to the default value in case nothing is specified
1600 * in the DT.
1601 */
1602 nand->ecc.mode = NAND_ECC_HW;
Brian Norris63752192015-10-30 20:33:23 -07001603 nand_set_flash_node(nand, np);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001604 nand->select_chip = sunxi_nfc_select_chip;
1605 nand->cmd_ctrl = sunxi_nfc_cmd_ctrl;
1606 nand->read_buf = sunxi_nfc_read_buf;
1607 nand->write_buf = sunxi_nfc_write_buf;
1608 nand->read_byte = sunxi_nfc_read_byte;
1609
Boris BREZILLON32e9f2d2015-12-10 09:00:26 +01001610 mtd = nand_to_mtd(nand);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001611 mtd->dev.parent = dev;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001612
Boris Brezillon9edb4702015-12-02 16:00:57 +01001613 timings = onfi_async_timing_mode_to_sdr_timings(0);
1614 if (IS_ERR(timings)) {
1615 ret = PTR_ERR(timings);
1616 dev_err(dev,
1617 "could not retrieve timings for ONFI mode 0: %d\n",
1618 ret);
1619 return ret;
1620 }
1621
1622 ret = sunxi_nand_chip_set_timings(chip, timings);
1623 if (ret) {
1624 dev_err(dev, "could not configure chip timings: %d\n", ret);
1625 return ret;
1626 }
1627
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001628 ret = nand_scan_ident(mtd, nsels, NULL);
1629 if (ret)
1630 return ret;
1631
Boris BREZILLONa3d22a52015-09-02 10:30:25 +02001632 if (nand->bbt_options & NAND_BBT_USE_FLASH)
1633 nand->bbt_options |= NAND_BBT_NO_OOB;
1634
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001635 if (nand->options & NAND_NEED_SCRAMBLING)
1636 nand->options |= NAND_NO_SUBPAGE_WRITE;
1637
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001638 ret = sunxi_nand_chip_init_timings(chip, np);
1639 if (ret) {
1640 dev_err(dev, "could not configure chip timings: %d\n", ret);
1641 return ret;
1642 }
1643
1644 ret = sunxi_nand_ecc_init(mtd, &nand->ecc, np);
1645 if (ret) {
1646 dev_err(dev, "ECC init failed: %d\n", ret);
1647 return ret;
1648 }
1649
1650 ret = nand_scan_tail(mtd);
1651 if (ret) {
1652 dev_err(dev, "nand_scan_tail failed: %d\n", ret);
1653 return ret;
1654 }
1655
Brian Norrisa61ae812015-10-30 20:33:25 -07001656 ret = mtd_device_register(mtd, NULL, 0);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001657 if (ret) {
1658 dev_err(dev, "failed to register mtd device: %d\n", ret);
1659 nand_release(mtd);
1660 return ret;
1661 }
1662
1663 list_add_tail(&chip->node, &nfc->chips);
1664
1665 return 0;
1666}
1667
1668static int sunxi_nand_chips_init(struct device *dev, struct sunxi_nfc *nfc)
1669{
1670 struct device_node *np = dev->of_node;
1671 struct device_node *nand_np;
1672 int nchips = of_get_child_count(np);
1673 int ret;
1674
1675 if (nchips > 8) {
1676 dev_err(dev, "too many NAND chips: %d (max = 8)\n", nchips);
1677 return -EINVAL;
1678 }
1679
1680 for_each_child_of_node(np, nand_np) {
1681 ret = sunxi_nand_chip_init(dev, nfc, nand_np);
Julia Lawalla81c0f02015-11-18 23:04:12 +01001682 if (ret) {
1683 of_node_put(nand_np);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001684 return ret;
Julia Lawalla81c0f02015-11-18 23:04:12 +01001685 }
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001686 }
1687
1688 return 0;
1689}
1690
1691static void sunxi_nand_chips_cleanup(struct sunxi_nfc *nfc)
1692{
1693 struct sunxi_nand_chip *chip;
1694
1695 while (!list_empty(&nfc->chips)) {
1696 chip = list_first_entry(&nfc->chips, struct sunxi_nand_chip,
1697 node);
Boris BREZILLON32e9f2d2015-12-10 09:00:26 +01001698 nand_release(nand_to_mtd(&chip->nand));
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001699 sunxi_nand_ecc_cleanup(&chip->nand.ecc);
Boris BREZILLON8e375cc2015-09-13 18:14:43 +02001700 list_del(&chip->node);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001701 }
1702}
1703
1704static int sunxi_nfc_probe(struct platform_device *pdev)
1705{
1706 struct device *dev = &pdev->dev;
1707 struct resource *r;
1708 struct sunxi_nfc *nfc;
1709 int irq;
1710 int ret;
1711
1712 nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
1713 if (!nfc)
1714 return -ENOMEM;
1715
1716 nfc->dev = dev;
1717 spin_lock_init(&nfc->controller.lock);
1718 init_waitqueue_head(&nfc->controller.wq);
1719 INIT_LIST_HEAD(&nfc->chips);
1720
1721 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1722 nfc->regs = devm_ioremap_resource(dev, r);
1723 if (IS_ERR(nfc->regs))
1724 return PTR_ERR(nfc->regs);
1725
1726 irq = platform_get_irq(pdev, 0);
1727 if (irq < 0) {
1728 dev_err(dev, "failed to retrieve irq\n");
1729 return irq;
1730 }
1731
1732 nfc->ahb_clk = devm_clk_get(dev, "ahb");
1733 if (IS_ERR(nfc->ahb_clk)) {
1734 dev_err(dev, "failed to retrieve ahb clk\n");
1735 return PTR_ERR(nfc->ahb_clk);
1736 }
1737
1738 ret = clk_prepare_enable(nfc->ahb_clk);
1739 if (ret)
1740 return ret;
1741
1742 nfc->mod_clk = devm_clk_get(dev, "mod");
1743 if (IS_ERR(nfc->mod_clk)) {
1744 dev_err(dev, "failed to retrieve mod clk\n");
1745 ret = PTR_ERR(nfc->mod_clk);
1746 goto out_ahb_clk_unprepare;
1747 }
1748
1749 ret = clk_prepare_enable(nfc->mod_clk);
1750 if (ret)
1751 goto out_ahb_clk_unprepare;
1752
1753 ret = sunxi_nfc_rst(nfc);
1754 if (ret)
1755 goto out_mod_clk_unprepare;
1756
1757 writel(0, nfc->regs + NFC_REG_INT);
1758 ret = devm_request_irq(dev, irq, sunxi_nfc_interrupt,
1759 0, "sunxi-nand", nfc);
1760 if (ret)
1761 goto out_mod_clk_unprepare;
1762
1763 platform_set_drvdata(pdev, nfc);
1764
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001765 ret = sunxi_nand_chips_init(dev, nfc);
1766 if (ret) {
1767 dev_err(dev, "failed to init nand chips\n");
1768 goto out_mod_clk_unprepare;
1769 }
1770
1771 return 0;
1772
1773out_mod_clk_unprepare:
1774 clk_disable_unprepare(nfc->mod_clk);
1775out_ahb_clk_unprepare:
1776 clk_disable_unprepare(nfc->ahb_clk);
1777
1778 return ret;
1779}
1780
1781static int sunxi_nfc_remove(struct platform_device *pdev)
1782{
1783 struct sunxi_nfc *nfc = platform_get_drvdata(pdev);
1784
1785 sunxi_nand_chips_cleanup(nfc);
1786
1787 return 0;
1788}
1789
1790static const struct of_device_id sunxi_nfc_ids[] = {
1791 { .compatible = "allwinner,sun4i-a10-nand" },
1792 { /* sentinel */ }
1793};
1794MODULE_DEVICE_TABLE(of, sunxi_nfc_ids);
1795
1796static struct platform_driver sunxi_nfc_driver = {
1797 .driver = {
1798 .name = "sunxi_nand",
1799 .of_match_table = sunxi_nfc_ids,
1800 },
1801 .probe = sunxi_nfc_probe,
1802 .remove = sunxi_nfc_remove,
1803};
1804module_platform_driver(sunxi_nfc_driver);
1805
1806MODULE_LICENSE("GPL v2");
1807MODULE_AUTHOR("Boris BREZILLON");
1808MODULE_DESCRIPTION("Allwinner NAND Flash Controller driver");
1809MODULE_ALIAS("platform:sunxi_nand");