blob: b12ed83ebd564d0d5835f6849822f4a08537372b [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 Brezilloncc6822f2016-03-04 17:56:47 +0100778static inline u32 sunxi_nfc_buf_to_user_data(const u8 *buf)
779{
780 return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
781}
782
783static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct mtd_info *mtd, u8 *oob,
784 int step, bool bbm, int page)
785{
786 struct nand_chip *nand = mtd_to_nand(mtd);
787 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
788
789 sunxi_nfc_user_data_to_buf(readl(nfc->regs + NFC_REG_USER_DATA(step)),
790 oob);
791
792 /* De-randomize the Bad Block Marker. */
793 if (bbm && (nand->options & NAND_NEED_SCRAMBLING))
794 sunxi_nfc_randomize_bbm(mtd, page, oob);
795}
796
797static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct mtd_info *mtd,
798 const u8 *oob, int step,
799 bool bbm, int page)
800{
801 struct nand_chip *nand = mtd_to_nand(mtd);
802 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
803 u8 user_data[4];
804
805 /* Randomize the Bad Block Marker. */
806 if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) {
807 memcpy(user_data, oob, sizeof(user_data));
808 sunxi_nfc_randomize_bbm(mtd, page, user_data);
809 oob = user_data;
810 }
811
812 writel(sunxi_nfc_buf_to_user_data(oob),
813 nfc->regs + NFC_REG_USER_DATA(step));
814}
815
816static void sunxi_nfc_hw_ecc_update_stats(struct mtd_info *mtd,
817 unsigned int *max_bitflips, int ret)
818{
819 if (ret < 0) {
820 mtd->ecc_stats.failed++;
821 } else {
822 mtd->ecc_stats.corrected += ret;
823 *max_bitflips = max_t(unsigned int, *max_bitflips, ret);
824 }
825}
826
827static int sunxi_nfc_hw_ecc_correct(struct mtd_info *mtd, u8 *data, u8 *oob,
828 int step, bool *erased)
829{
830 struct nand_chip *nand = mtd_to_nand(mtd);
831 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
832 struct nand_ecc_ctrl *ecc = &nand->ecc;
833 u32 status, tmp;
834
835 *erased = false;
836
837 status = readl(nfc->regs + NFC_REG_ECC_ST);
838
839 if (status & NFC_ECC_ERR(step))
840 return -EBADMSG;
841
842 if (status & NFC_ECC_PAT_FOUND(step)) {
843 u8 pattern;
844
845 if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID) & 0x1))) {
846 pattern = 0x0;
847 } else {
848 pattern = 0xff;
849 *erased = true;
850 }
851
852 if (data)
853 memset(data, pattern, ecc->size);
854
855 if (oob)
856 memset(oob, pattern, ecc->bytes + 4);
857
858 return 0;
859 }
860
861 tmp = readl(nfc->regs + NFC_REG_ECC_ERR_CNT(step));
862
863 return NFC_ECC_ERR_CNT(step, tmp);
864}
865
Boris BREZILLON913821b2015-09-30 23:45:24 +0200866static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
867 u8 *data, int data_off,
868 u8 *oob, int oob_off,
869 int *cur_off,
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100870 unsigned int *max_bitflips,
Boris Brezillon828dec12016-03-04 18:09:21 +0100871 bool bbm, bool oob_required, int page)
Boris BREZILLON913821b2015-09-30 23:45:24 +0200872{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100873 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200874 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
875 struct nand_ecc_ctrl *ecc = &nand->ecc;
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100876 int raw_mode = 0;
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100877 bool erased;
Boris BREZILLON913821b2015-09-30 23:45:24 +0200878 int ret;
879
880 if (*cur_off != data_off)
881 nand->cmdfunc(mtd, NAND_CMD_RNDOUT, data_off, -1);
882
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100883 sunxi_nfc_randomizer_read_buf(mtd, NULL, ecc->size, false, page);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200884
Boris BREZILLON74eb9ff2015-10-20 22:16:00 +0200885 if (data_off + ecc->size != oob_off)
Boris BREZILLON913821b2015-09-30 23:45:24 +0200886 nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1);
887
888 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
889 if (ret)
890 return ret;
891
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100892 sunxi_nfc_randomizer_enable(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200893 writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP,
894 nfc->regs + NFC_REG_CMD);
895
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +0100896 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100897 sunxi_nfc_randomizer_disable(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200898 if (ret)
899 return ret;
900
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100901 *cur_off = oob_off + ecc->bytes + 4;
902
Boris Brezillon828dec12016-03-04 18:09:21 +0100903 ret = sunxi_nfc_hw_ecc_correct(mtd, data, oob_required ? oob : NULL, 0,
904 &erased);
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100905 if (erased)
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100906 return 1;
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100907
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100908 if (ret < 0) {
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100909 /*
910 * Re-read the data with the randomizer disabled to identify
911 * bitflips in erased pages.
912 */
913 if (nand->options & NAND_NEED_SCRAMBLING) {
914 nand->cmdfunc(mtd, NAND_CMD_RNDOUT, data_off, -1);
915 nand->read_buf(mtd, data, ecc->size);
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100916 } else {
917 memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE,
918 ecc->size);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100919 }
920
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100921 nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1);
922 nand->read_buf(mtd, oob, ecc->bytes + 4);
923
Boris BREZILLON146b5032015-09-30 23:45:29 +0200924 ret = nand_check_erased_ecc_chunk(data, ecc->size,
925 oob, ecc->bytes + 4,
926 NULL, 0, ecc->strength);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100927 if (ret >= 0)
928 raw_mode = 1;
Boris BREZILLONf363e0f2015-09-30 23:45:27 +0200929 } else {
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100930 memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size);
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100931
Boris Brezillon828dec12016-03-04 18:09:21 +0100932 if (oob_required) {
933 nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1);
934 sunxi_nfc_randomizer_read_buf(mtd, oob, ecc->bytes + 4,
935 true, page);
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100936
Boris Brezillon828dec12016-03-04 18:09:21 +0100937 sunxi_nfc_hw_ecc_get_prot_oob_bytes(mtd, oob, 0,
938 bbm, page);
939 }
Boris BREZILLONf363e0f2015-09-30 23:45:27 +0200940 }
Boris BREZILLON913821b2015-09-30 23:45:24 +0200941
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100942 sunxi_nfc_hw_ecc_update_stats(mtd, max_bitflips, ret);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200943
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100944 return raw_mode;
Boris BREZILLON913821b2015-09-30 23:45:24 +0200945}
946
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200947static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd,
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100948 u8 *oob, int *cur_off,
949 bool randomize, int page)
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200950{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100951 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200952 struct nand_ecc_ctrl *ecc = &nand->ecc;
953 int offset = ((ecc->bytes + 4) * ecc->steps);
954 int len = mtd->oobsize - offset;
955
956 if (len <= 0)
957 return;
958
Boris Brezillonc4f3ef22016-03-04 18:13:10 +0100959 if (!cur_off || *cur_off != offset)
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200960 nand->cmdfunc(mtd, NAND_CMD_RNDOUT,
961 offset + mtd->writesize, -1);
962
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100963 if (!randomize)
964 sunxi_nfc_read_buf(mtd, oob + offset, len);
965 else
966 sunxi_nfc_randomizer_read_buf(mtd, oob + offset, len,
967 false, page);
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200968
Boris Brezillonc4f3ef22016-03-04 18:13:10 +0100969 if (cur_off)
970 *cur_off = mtd->oobsize + mtd->writesize;
Boris BREZILLON35d0e242015-09-30 23:45:26 +0200971}
972
Boris BREZILLON913821b2015-09-30 23:45:24 +0200973static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd,
974 const u8 *data, int data_off,
975 const u8 *oob, int oob_off,
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100976 int *cur_off, bool bbm,
977 int page)
Boris BREZILLON913821b2015-09-30 23:45:24 +0200978{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100979 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200980 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
981 struct nand_ecc_ctrl *ecc = &nand->ecc;
982 int ret;
983
984 if (data_off != *cur_off)
985 nand->cmdfunc(mtd, NAND_CMD_RNDIN, data_off, -1);
986
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100987 sunxi_nfc_randomizer_write_buf(mtd, data, ecc->size, false, page);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200988
Boris BREZILLON74eb9ff2015-10-20 22:16:00 +0200989 if (data_off + ecc->size != oob_off)
Boris BREZILLON913821b2015-09-30 23:45:24 +0200990 nand->cmdfunc(mtd, NAND_CMD_RNDIN, oob_off, -1);
991
992 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
993 if (ret)
994 return ret;
995
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100996 sunxi_nfc_randomizer_enable(mtd);
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100997 sunxi_nfc_hw_ecc_set_prot_oob_bytes(mtd, oob, 0, bbm, page);
998
Boris BREZILLON913821b2015-09-30 23:45:24 +0200999 writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD |
1000 NFC_ACCESS_DIR | NFC_ECC_OP,
1001 nfc->regs + NFC_REG_CMD);
1002
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +01001003 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0);
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001004 sunxi_nfc_randomizer_disable(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +02001005 if (ret)
1006 return ret;
1007
1008 *cur_off = oob_off + ecc->bytes + 4;
1009
1010 return 0;
1011}
1012
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001013static void sunxi_nfc_hw_ecc_write_extra_oob(struct mtd_info *mtd,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001014 u8 *oob, int *cur_off,
1015 int page)
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001016{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +01001017 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001018 struct nand_ecc_ctrl *ecc = &nand->ecc;
1019 int offset = ((ecc->bytes + 4) * ecc->steps);
1020 int len = mtd->oobsize - offset;
1021
1022 if (len <= 0)
1023 return;
1024
Boris Brezillonc4f3ef22016-03-04 18:13:10 +01001025 if (!cur_off || *cur_off != offset)
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001026 nand->cmdfunc(mtd, NAND_CMD_RNDIN,
1027 offset + mtd->writesize, -1);
1028
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001029 sunxi_nfc_randomizer_write_buf(mtd, oob + offset, len, false, page);
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001030
Boris Brezillonc4f3ef22016-03-04 18:13:10 +01001031 if (cur_off)
1032 *cur_off = mtd->oobsize + mtd->writesize;
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001033}
1034
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001035static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd,
1036 struct nand_chip *chip, uint8_t *buf,
1037 int oob_required, int page)
1038{
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001039 struct nand_ecc_ctrl *ecc = &chip->ecc;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001040 unsigned int max_bitflips = 0;
Boris BREZILLONb4625512015-09-30 23:45:25 +02001041 int ret, i, cur_off = 0;
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001042 bool raw_mode = false;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001043
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001044 sunxi_nfc_hw_ecc_enable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001045
1046 for (i = 0; i < ecc->steps; i++) {
Boris BREZILLONb4625512015-09-30 23:45:25 +02001047 int data_off = i * ecc->size;
1048 int oob_off = i * (ecc->bytes + 4);
1049 u8 *data = buf + data_off;
1050 u8 *oob = chip->oob_poi + oob_off;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001051
Boris BREZILLONb4625512015-09-30 23:45:25 +02001052 ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob,
1053 oob_off + mtd->writesize,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001054 &cur_off, &max_bitflips,
Boris Brezillon828dec12016-03-04 18:09:21 +01001055 !i, oob_required, page);
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001056 if (ret < 0)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001057 return ret;
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001058 else if (ret)
1059 raw_mode = true;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001060 }
1061
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001062 if (oob_required)
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001063 sunxi_nfc_hw_ecc_read_extra_oob(mtd, chip->oob_poi, &cur_off,
1064 !raw_mode, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001065
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001066 sunxi_nfc_hw_ecc_disable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001067
1068 return max_bitflips;
1069}
1070
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001071static int sunxi_nfc_hw_ecc_read_subpage(struct mtd_info *mtd,
1072 struct nand_chip *chip,
1073 u32 data_offs, u32 readlen,
1074 u8 *bufpoi, int page)
1075{
1076 struct nand_ecc_ctrl *ecc = &chip->ecc;
1077 int ret, i, cur_off = 0;
1078 unsigned int max_bitflips = 0;
1079
1080 sunxi_nfc_hw_ecc_enable(mtd);
1081
1082 chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
1083 for (i = data_offs / ecc->size;
1084 i < DIV_ROUND_UP(data_offs + readlen, ecc->size); i++) {
1085 int data_off = i * ecc->size;
1086 int oob_off = i * (ecc->bytes + 4);
1087 u8 *data = bufpoi + data_off;
1088 u8 *oob = chip->oob_poi + oob_off;
1089
1090 ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off,
1091 oob,
1092 oob_off + mtd->writesize,
Boris Brezillon828dec12016-03-04 18:09:21 +01001093 &cur_off, &max_bitflips, !i,
1094 false, page);
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001095 if (ret < 0)
1096 return ret;
1097 }
1098
1099 sunxi_nfc_hw_ecc_disable(mtd);
1100
1101 return max_bitflips;
1102}
1103
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001104static int sunxi_nfc_hw_ecc_write_page(struct mtd_info *mtd,
1105 struct nand_chip *chip,
Boris BREZILLON45aaeff2015-10-13 11:22:18 +02001106 const uint8_t *buf, int oob_required,
1107 int page)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001108{
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001109 struct nand_ecc_ctrl *ecc = &chip->ecc;
Boris BREZILLONb4625512015-09-30 23:45:25 +02001110 int ret, i, cur_off = 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001111
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001112 sunxi_nfc_hw_ecc_enable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001113
1114 for (i = 0; i < ecc->steps; i++) {
Boris BREZILLONb4625512015-09-30 23:45:25 +02001115 int data_off = i * ecc->size;
1116 int oob_off = i * (ecc->bytes + 4);
1117 const u8 *data = buf + data_off;
1118 const u8 *oob = chip->oob_poi + oob_off;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001119
Boris BREZILLONb4625512015-09-30 23:45:25 +02001120 ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off, oob,
1121 oob_off + mtd->writesize,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001122 &cur_off, !i, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001123 if (ret)
1124 return ret;
1125 }
1126
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001127 if (oob_required || (chip->options & NAND_NEED_SCRAMBLING))
1128 sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi,
1129 &cur_off, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001130
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001131 sunxi_nfc_hw_ecc_disable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001132
1133 return 0;
1134}
1135
1136static int sunxi_nfc_hw_syndrome_ecc_read_page(struct mtd_info *mtd,
1137 struct nand_chip *chip,
1138 uint8_t *buf, int oob_required,
1139 int page)
1140{
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001141 struct nand_ecc_ctrl *ecc = &chip->ecc;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001142 unsigned int max_bitflips = 0;
Boris BREZILLONb4625512015-09-30 23:45:25 +02001143 int ret, i, cur_off = 0;
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001144 bool raw_mode = false;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001145
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001146 sunxi_nfc_hw_ecc_enable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001147
1148 for (i = 0; i < ecc->steps; i++) {
Boris BREZILLONb4625512015-09-30 23:45:25 +02001149 int data_off = i * (ecc->size + ecc->bytes + 4);
1150 int oob_off = data_off + ecc->size;
1151 u8 *data = buf + (i * ecc->size);
1152 u8 *oob = chip->oob_poi + (i * (ecc->bytes + 4));
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001153
Boris BREZILLONb4625512015-09-30 23:45:25 +02001154 ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob,
1155 oob_off, &cur_off,
Boris Brezillon828dec12016-03-04 18:09:21 +01001156 &max_bitflips, !i,
1157 oob_required,
1158 page);
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001159 if (ret < 0)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001160 return ret;
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001161 else if (ret)
1162 raw_mode = true;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001163 }
1164
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001165 if (oob_required)
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001166 sunxi_nfc_hw_ecc_read_extra_oob(mtd, chip->oob_poi, &cur_off,
1167 !raw_mode, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001168
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001169 sunxi_nfc_hw_ecc_disable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001170
1171 return max_bitflips;
1172}
1173
1174static int sunxi_nfc_hw_syndrome_ecc_write_page(struct mtd_info *mtd,
1175 struct nand_chip *chip,
1176 const uint8_t *buf,
Boris BREZILLON45aaeff2015-10-13 11:22:18 +02001177 int oob_required, int page)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001178{
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001179 struct nand_ecc_ctrl *ecc = &chip->ecc;
Boris BREZILLONb4625512015-09-30 23:45:25 +02001180 int ret, i, cur_off = 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001181
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001182 sunxi_nfc_hw_ecc_enable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001183
1184 for (i = 0; i < ecc->steps; i++) {
Boris BREZILLONb4625512015-09-30 23:45:25 +02001185 int data_off = i * (ecc->size + ecc->bytes + 4);
1186 int oob_off = data_off + ecc->size;
1187 const u8 *data = buf + (i * ecc->size);
1188 const u8 *oob = chip->oob_poi + (i * (ecc->bytes + 4));
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001189
Boris BREZILLONb4625512015-09-30 23:45:25 +02001190 ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001191 oob, oob_off, &cur_off,
1192 false, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001193 if (ret)
1194 return ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001195 }
1196
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001197 if (oob_required || (chip->options & NAND_NEED_SCRAMBLING))
1198 sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi,
1199 &cur_off, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001200
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001201 sunxi_nfc_hw_ecc_disable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001202
1203 return 0;
1204}
1205
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001206static int sunxi_nfc_hw_common_ecc_read_oob(struct mtd_info *mtd,
1207 struct nand_chip *chip,
1208 int page)
1209{
1210 chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
1211
1212 chip->pagebuf = -1;
1213
1214 return chip->ecc.read_page(mtd, chip, chip->buffers->databuf, 1, page);
1215}
1216
1217static int sunxi_nfc_hw_common_ecc_write_oob(struct mtd_info *mtd,
1218 struct nand_chip *chip,
1219 int page)
1220{
1221 int ret, status;
1222
1223 chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0, page);
1224
1225 chip->pagebuf = -1;
1226
1227 memset(chip->buffers->databuf, 0xff, mtd->writesize);
1228 ret = chip->ecc.write_page(mtd, chip, chip->buffers->databuf, 1, page);
1229 if (ret)
1230 return ret;
1231
1232 /* Send command to program the OOB data */
1233 chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
1234
1235 status = chip->waitfunc(mtd, chip);
1236
1237 return status & NAND_STATUS_FAIL ? -EIO : 0;
1238}
1239
Roy Spliet9c618292015-06-26 11:00:10 +02001240static const s32 tWB_lut[] = {6, 12, 16, 20};
1241static const s32 tRHW_lut[] = {4, 8, 12, 20};
1242
1243static int _sunxi_nand_lookup_timing(const s32 *lut, int lut_size, u32 duration,
1244 u32 clk_period)
1245{
1246 u32 clk_cycles = DIV_ROUND_UP(duration, clk_period);
1247 int i;
1248
1249 for (i = 0; i < lut_size; i++) {
1250 if (clk_cycles <= lut[i])
1251 return i;
1252 }
1253
1254 /* Doesn't fit */
1255 return -EINVAL;
1256}
1257
1258#define sunxi_nand_lookup_timing(l, p, c) \
1259 _sunxi_nand_lookup_timing(l, ARRAY_SIZE(l), p, c)
1260
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001261static int sunxi_nand_chip_set_timings(struct sunxi_nand_chip *chip,
1262 const struct nand_sdr_timings *timings)
1263{
Roy Spliet9c618292015-06-26 11:00:10 +02001264 struct sunxi_nfc *nfc = to_sunxi_nfc(chip->nand.controller);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001265 u32 min_clk_period = 0;
Roy Spliet9c618292015-06-26 11:00:10 +02001266 s32 tWB, tADL, tWHR, tRHW, tCAD;
Boris Brezillon2d434572015-12-02 15:57:20 +01001267 long real_clk_rate;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001268
1269 /* T1 <=> tCLS */
1270 if (timings->tCLS_min > min_clk_period)
1271 min_clk_period = timings->tCLS_min;
1272
1273 /* T2 <=> tCLH */
1274 if (timings->tCLH_min > min_clk_period)
1275 min_clk_period = timings->tCLH_min;
1276
1277 /* T3 <=> tCS */
1278 if (timings->tCS_min > min_clk_period)
1279 min_clk_period = timings->tCS_min;
1280
1281 /* T4 <=> tCH */
1282 if (timings->tCH_min > min_clk_period)
1283 min_clk_period = timings->tCH_min;
1284
1285 /* T5 <=> tWP */
1286 if (timings->tWP_min > min_clk_period)
1287 min_clk_period = timings->tWP_min;
1288
1289 /* T6 <=> tWH */
1290 if (timings->tWH_min > min_clk_period)
1291 min_clk_period = timings->tWH_min;
1292
1293 /* T7 <=> tALS */
1294 if (timings->tALS_min > min_clk_period)
1295 min_clk_period = timings->tALS_min;
1296
1297 /* T8 <=> tDS */
1298 if (timings->tDS_min > min_clk_period)
1299 min_clk_period = timings->tDS_min;
1300
1301 /* T9 <=> tDH */
1302 if (timings->tDH_min > min_clk_period)
1303 min_clk_period = timings->tDH_min;
1304
1305 /* T10 <=> tRR */
1306 if (timings->tRR_min > (min_clk_period * 3))
1307 min_clk_period = DIV_ROUND_UP(timings->tRR_min, 3);
1308
1309 /* T11 <=> tALH */
1310 if (timings->tALH_min > min_clk_period)
1311 min_clk_period = timings->tALH_min;
1312
1313 /* T12 <=> tRP */
1314 if (timings->tRP_min > min_clk_period)
1315 min_clk_period = timings->tRP_min;
1316
1317 /* T13 <=> tREH */
1318 if (timings->tREH_min > min_clk_period)
1319 min_clk_period = timings->tREH_min;
1320
1321 /* T14 <=> tRC */
1322 if (timings->tRC_min > (min_clk_period * 2))
1323 min_clk_period = DIV_ROUND_UP(timings->tRC_min, 2);
1324
1325 /* T15 <=> tWC */
1326 if (timings->tWC_min > (min_clk_period * 2))
1327 min_clk_period = DIV_ROUND_UP(timings->tWC_min, 2);
1328
Roy Spliet9c618292015-06-26 11:00:10 +02001329 /* T16 - T19 + tCAD */
Boris Brezillon5abcd952015-11-11 22:30:30 +01001330 if (timings->tWB_max > (min_clk_period * 20))
1331 min_clk_period = DIV_ROUND_UP(timings->tWB_max, 20);
1332
1333 if (timings->tADL_min > (min_clk_period * 32))
1334 min_clk_period = DIV_ROUND_UP(timings->tADL_min, 32);
1335
1336 if (timings->tWHR_min > (min_clk_period * 32))
1337 min_clk_period = DIV_ROUND_UP(timings->tWHR_min, 32);
1338
1339 if (timings->tRHW_min > (min_clk_period * 20))
1340 min_clk_period = DIV_ROUND_UP(timings->tRHW_min, 20);
1341
Roy Spliet9c618292015-06-26 11:00:10 +02001342 tWB = sunxi_nand_lookup_timing(tWB_lut, timings->tWB_max,
1343 min_clk_period);
1344 if (tWB < 0) {
1345 dev_err(nfc->dev, "unsupported tWB\n");
1346 return tWB;
1347 }
1348
1349 tADL = DIV_ROUND_UP(timings->tADL_min, min_clk_period) >> 3;
1350 if (tADL > 3) {
1351 dev_err(nfc->dev, "unsupported tADL\n");
1352 return -EINVAL;
1353 }
1354
1355 tWHR = DIV_ROUND_UP(timings->tWHR_min, min_clk_period) >> 3;
1356 if (tWHR > 3) {
1357 dev_err(nfc->dev, "unsupported tWHR\n");
1358 return -EINVAL;
1359 }
1360
1361 tRHW = sunxi_nand_lookup_timing(tRHW_lut, timings->tRHW_min,
1362 min_clk_period);
1363 if (tRHW < 0) {
1364 dev_err(nfc->dev, "unsupported tRHW\n");
1365 return tRHW;
1366 }
1367
1368 /*
1369 * TODO: according to ONFI specs this value only applies for DDR NAND,
1370 * but Allwinner seems to set this to 0x7. Mimic them for now.
1371 */
1372 tCAD = 0x7;
1373
1374 /* TODO: A83 has some more bits for CDQSS, CS, CLHZ, CCS, WC */
1375 chip->timing_cfg = NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001376
1377 /* Convert min_clk_period from picoseconds to nanoseconds */
1378 min_clk_period = DIV_ROUND_UP(min_clk_period, 1000);
1379
1380 /*
Boris Brezillon2f9992e2015-12-02 15:10:40 +01001381 * Unlike what is stated in Allwinner datasheet, the clk_rate should
1382 * be set to (1 / min_clk_period), and not (2 / min_clk_period).
1383 * This new formula was verified with a scope and validated by
1384 * Allwinner engineers.
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001385 */
Boris Brezillon2f9992e2015-12-02 15:10:40 +01001386 chip->clk_rate = NSEC_PER_SEC / min_clk_period;
Boris Brezillon2d434572015-12-02 15:57:20 +01001387 real_clk_rate = clk_round_rate(nfc->mod_clk, chip->clk_rate);
1388
1389 /*
1390 * ONFI specification 3.1, paragraph 4.15.2 dictates that EDO data
1391 * output cycle timings shall be used if the host drives tRC less than
1392 * 30 ns.
1393 */
1394 min_clk_period = NSEC_PER_SEC / real_clk_rate;
1395 chip->timing_ctl = ((min_clk_period * 2) < 30) ?
1396 NFC_TIMING_CTL_EDO : 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001397
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001398 return 0;
1399}
1400
1401static int sunxi_nand_chip_init_timings(struct sunxi_nand_chip *chip,
1402 struct device_node *np)
1403{
Boris BREZILLON32e9f2d2015-12-10 09:00:26 +01001404 struct mtd_info *mtd = nand_to_mtd(&chip->nand);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001405 const struct nand_sdr_timings *timings;
1406 int ret;
1407 int mode;
1408
1409 mode = onfi_get_async_timing_mode(&chip->nand);
1410 if (mode == ONFI_TIMING_MODE_UNKNOWN) {
1411 mode = chip->nand.onfi_timing_mode_default;
1412 } else {
1413 uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {};
Stefan Roese7eadd472015-08-28 14:45:21 +02001414 int i;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001415
1416 mode = fls(mode) - 1;
1417 if (mode < 0)
1418 mode = 0;
1419
1420 feature[0] = mode;
Stefan Roese7eadd472015-08-28 14:45:21 +02001421 for (i = 0; i < chip->nsels; i++) {
Boris BREZILLON32e9f2d2015-12-10 09:00:26 +01001422 chip->nand.select_chip(mtd, i);
1423 ret = chip->nand.onfi_set_features(mtd, &chip->nand,
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001424 ONFI_FEATURE_ADDR_TIMING_MODE,
1425 feature);
Boris BREZILLON32e9f2d2015-12-10 09:00:26 +01001426 chip->nand.select_chip(mtd, -1);
Stefan Roese7eadd472015-08-28 14:45:21 +02001427 if (ret)
1428 return ret;
1429 }
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001430 }
1431
1432 timings = onfi_async_timing_mode_to_sdr_timings(mode);
1433 if (IS_ERR(timings))
1434 return PTR_ERR(timings);
1435
1436 return sunxi_nand_chip_set_timings(chip, timings);
1437}
1438
1439static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd,
1440 struct nand_ecc_ctrl *ecc,
1441 struct device_node *np)
1442{
1443 static const u8 strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 };
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +01001444 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001445 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
1446 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
1447 struct sunxi_nand_hw_ecc *data;
1448 struct nand_ecclayout *layout;
1449 int nsectors;
1450 int ret;
1451 int i;
1452
1453 data = kzalloc(sizeof(*data), GFP_KERNEL);
1454 if (!data)
1455 return -ENOMEM;
1456
1457 /* Add ECC info retrieval from DT */
1458 for (i = 0; i < ARRAY_SIZE(strengths); i++) {
1459 if (ecc->strength <= strengths[i])
1460 break;
1461 }
1462
1463 if (i >= ARRAY_SIZE(strengths)) {
1464 dev_err(nfc->dev, "unsupported strength\n");
1465 ret = -ENOTSUPP;
1466 goto err;
1467 }
1468
1469 data->mode = i;
1470
1471 /* HW ECC always request ECC bytes for 1024 bytes blocks */
1472 ecc->bytes = DIV_ROUND_UP(ecc->strength * fls(8 * 1024), 8);
1473
1474 /* HW ECC always work with even numbers of ECC bytes */
1475 ecc->bytes = ALIGN(ecc->bytes, 2);
1476
1477 layout = &data->layout;
1478 nsectors = mtd->writesize / ecc->size;
1479
1480 if (mtd->oobsize < ((ecc->bytes + 4) * nsectors)) {
1481 ret = -EINVAL;
1482 goto err;
1483 }
1484
1485 layout->eccbytes = (ecc->bytes * nsectors);
1486
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001487 ecc->read_oob = sunxi_nfc_hw_common_ecc_read_oob;
1488 ecc->write_oob = sunxi_nfc_hw_common_ecc_write_oob;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001489 ecc->layout = layout;
1490 ecc->priv = data;
1491
1492 return 0;
1493
1494err:
1495 kfree(data);
1496
1497 return ret;
1498}
1499
1500static void sunxi_nand_hw_common_ecc_ctrl_cleanup(struct nand_ecc_ctrl *ecc)
1501{
1502 kfree(ecc->priv);
1503}
1504
1505static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
1506 struct nand_ecc_ctrl *ecc,
1507 struct device_node *np)
1508{
1509 struct nand_ecclayout *layout;
1510 int nsectors;
1511 int i, j;
1512 int ret;
1513
1514 ret = sunxi_nand_hw_common_ecc_ctrl_init(mtd, ecc, np);
1515 if (ret)
1516 return ret;
1517
1518 ecc->read_page = sunxi_nfc_hw_ecc_read_page;
1519 ecc->write_page = sunxi_nfc_hw_ecc_write_page;
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001520 ecc->read_oob_raw = nand_read_oob_std;
1521 ecc->write_oob_raw = nand_write_oob_std;
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001522 ecc->read_subpage = sunxi_nfc_hw_ecc_read_subpage;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001523 layout = ecc->layout;
1524 nsectors = mtd->writesize / ecc->size;
1525
1526 for (i = 0; i < nsectors; i++) {
1527 if (i) {
1528 layout->oobfree[i].offset =
1529 layout->oobfree[i - 1].offset +
1530 layout->oobfree[i - 1].length +
1531 ecc->bytes;
1532 layout->oobfree[i].length = 4;
1533 } else {
1534 /*
1535 * The first 2 bytes are used for BB markers, hence we
1536 * only have 2 bytes available in the first user data
1537 * section.
1538 */
1539 layout->oobfree[i].length = 2;
1540 layout->oobfree[i].offset = 2;
1541 }
1542
1543 for (j = 0; j < ecc->bytes; j++)
1544 layout->eccpos[(ecc->bytes * i) + j] =
1545 layout->oobfree[i].offset +
1546 layout->oobfree[i].length + j;
1547 }
1548
1549 if (mtd->oobsize > (ecc->bytes + 4) * nsectors) {
1550 layout->oobfree[nsectors].offset =
1551 layout->oobfree[nsectors - 1].offset +
1552 layout->oobfree[nsectors - 1].length +
1553 ecc->bytes;
1554 layout->oobfree[nsectors].length = mtd->oobsize -
1555 ((ecc->bytes + 4) * nsectors);
1556 }
1557
1558 return 0;
1559}
1560
1561static int sunxi_nand_hw_syndrome_ecc_ctrl_init(struct mtd_info *mtd,
1562 struct nand_ecc_ctrl *ecc,
1563 struct device_node *np)
1564{
1565 struct nand_ecclayout *layout;
1566 int nsectors;
1567 int i;
1568 int ret;
1569
1570 ret = sunxi_nand_hw_common_ecc_ctrl_init(mtd, ecc, np);
1571 if (ret)
1572 return ret;
1573
1574 ecc->prepad = 4;
1575 ecc->read_page = sunxi_nfc_hw_syndrome_ecc_read_page;
1576 ecc->write_page = sunxi_nfc_hw_syndrome_ecc_write_page;
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001577 ecc->read_oob_raw = nand_read_oob_syndrome;
1578 ecc->write_oob_raw = nand_write_oob_syndrome;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001579
1580 layout = ecc->layout;
1581 nsectors = mtd->writesize / ecc->size;
1582
1583 for (i = 0; i < (ecc->bytes * nsectors); i++)
1584 layout->eccpos[i] = i;
1585
1586 layout->oobfree[0].length = mtd->oobsize - i;
1587 layout->oobfree[0].offset = i;
1588
1589 return 0;
1590}
1591
1592static void sunxi_nand_ecc_cleanup(struct nand_ecc_ctrl *ecc)
1593{
1594 switch (ecc->mode) {
1595 case NAND_ECC_HW:
1596 case NAND_ECC_HW_SYNDROME:
1597 sunxi_nand_hw_common_ecc_ctrl_cleanup(ecc);
1598 break;
1599 case NAND_ECC_NONE:
1600 kfree(ecc->layout);
1601 default:
1602 break;
1603 }
1604}
1605
1606static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc,
1607 struct device_node *np)
1608{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +01001609 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001610 int ret;
1611
Boris BREZILLONa3d22a52015-09-02 10:30:25 +02001612 if (!ecc->size) {
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001613 ecc->size = nand->ecc_step_ds;
1614 ecc->strength = nand->ecc_strength_ds;
1615 }
1616
1617 if (!ecc->size || !ecc->strength)
1618 return -EINVAL;
1619
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001620 switch (ecc->mode) {
1621 case NAND_ECC_SOFT_BCH:
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001622 break;
1623 case NAND_ECC_HW:
1624 ret = sunxi_nand_hw_ecc_ctrl_init(mtd, ecc, np);
1625 if (ret)
1626 return ret;
1627 break;
1628 case NAND_ECC_HW_SYNDROME:
1629 ret = sunxi_nand_hw_syndrome_ecc_ctrl_init(mtd, ecc, np);
1630 if (ret)
1631 return ret;
1632 break;
1633 case NAND_ECC_NONE:
1634 ecc->layout = kzalloc(sizeof(*ecc->layout), GFP_KERNEL);
1635 if (!ecc->layout)
1636 return -ENOMEM;
1637 ecc->layout->oobfree[0].length = mtd->oobsize;
1638 case NAND_ECC_SOFT:
1639 break;
1640 default:
1641 return -EINVAL;
1642 }
1643
1644 return 0;
1645}
1646
1647static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
1648 struct device_node *np)
1649{
1650 const struct nand_sdr_timings *timings;
1651 struct sunxi_nand_chip *chip;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001652 struct mtd_info *mtd;
1653 struct nand_chip *nand;
1654 int nsels;
1655 int ret;
1656 int i;
1657 u32 tmp;
1658
1659 if (!of_get_property(np, "reg", &nsels))
1660 return -EINVAL;
1661
1662 nsels /= sizeof(u32);
1663 if (!nsels) {
1664 dev_err(dev, "invalid reg property size\n");
1665 return -EINVAL;
1666 }
1667
1668 chip = devm_kzalloc(dev,
1669 sizeof(*chip) +
1670 (nsels * sizeof(struct sunxi_nand_chip_sel)),
1671 GFP_KERNEL);
1672 if (!chip) {
1673 dev_err(dev, "could not allocate chip\n");
1674 return -ENOMEM;
1675 }
1676
1677 chip->nsels = nsels;
1678 chip->selected = -1;
1679
1680 for (i = 0; i < nsels; i++) {
1681 ret = of_property_read_u32_index(np, "reg", i, &tmp);
1682 if (ret) {
1683 dev_err(dev, "could not retrieve reg property: %d\n",
1684 ret);
1685 return ret;
1686 }
1687
1688 if (tmp > NFC_MAX_CS) {
1689 dev_err(dev,
1690 "invalid reg value: %u (max CS = 7)\n",
1691 tmp);
1692 return -EINVAL;
1693 }
1694
1695 if (test_and_set_bit(tmp, &nfc->assigned_cs)) {
1696 dev_err(dev, "CS %d already assigned\n", tmp);
1697 return -EINVAL;
1698 }
1699
1700 chip->sels[i].cs = tmp;
1701
1702 if (!of_property_read_u32_index(np, "allwinner,rb", i, &tmp) &&
1703 tmp < 2) {
1704 chip->sels[i].rb.type = RB_NATIVE;
1705 chip->sels[i].rb.info.nativeid = tmp;
1706 } else {
1707 ret = of_get_named_gpio(np, "rb-gpios", i);
1708 if (ret >= 0) {
1709 tmp = ret;
1710 chip->sels[i].rb.type = RB_GPIO;
1711 chip->sels[i].rb.info.gpio = tmp;
1712 ret = devm_gpio_request(dev, tmp, "nand-rb");
1713 if (ret)
1714 return ret;
1715
1716 ret = gpio_direction_input(tmp);
1717 if (ret)
1718 return ret;
1719 } else {
1720 chip->sels[i].rb.type = RB_NONE;
1721 }
1722 }
1723 }
1724
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001725 nand = &chip->nand;
1726 /* Default tR value specified in the ONFI spec (chapter 4.15.1) */
1727 nand->chip_delay = 200;
1728 nand->controller = &nfc->controller;
Boris BREZILLONa3d22a52015-09-02 10:30:25 +02001729 /*
1730 * Set the ECC mode to the default value in case nothing is specified
1731 * in the DT.
1732 */
1733 nand->ecc.mode = NAND_ECC_HW;
Brian Norris63752192015-10-30 20:33:23 -07001734 nand_set_flash_node(nand, np);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001735 nand->select_chip = sunxi_nfc_select_chip;
1736 nand->cmd_ctrl = sunxi_nfc_cmd_ctrl;
1737 nand->read_buf = sunxi_nfc_read_buf;
1738 nand->write_buf = sunxi_nfc_write_buf;
1739 nand->read_byte = sunxi_nfc_read_byte;
1740
Boris BREZILLON32e9f2d2015-12-10 09:00:26 +01001741 mtd = nand_to_mtd(nand);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001742 mtd->dev.parent = dev;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001743
Boris Brezillon9edb4702015-12-02 16:00:57 +01001744 timings = onfi_async_timing_mode_to_sdr_timings(0);
1745 if (IS_ERR(timings)) {
1746 ret = PTR_ERR(timings);
1747 dev_err(dev,
1748 "could not retrieve timings for ONFI mode 0: %d\n",
1749 ret);
1750 return ret;
1751 }
1752
1753 ret = sunxi_nand_chip_set_timings(chip, timings);
1754 if (ret) {
1755 dev_err(dev, "could not configure chip timings: %d\n", ret);
1756 return ret;
1757 }
1758
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001759 ret = nand_scan_ident(mtd, nsels, NULL);
1760 if (ret)
1761 return ret;
1762
Boris BREZILLONa3d22a52015-09-02 10:30:25 +02001763 if (nand->bbt_options & NAND_BBT_USE_FLASH)
1764 nand->bbt_options |= NAND_BBT_NO_OOB;
1765
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001766 if (nand->options & NAND_NEED_SCRAMBLING)
1767 nand->options |= NAND_NO_SUBPAGE_WRITE;
1768
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001769 nand->options |= NAND_SUBPAGE_READ;
1770
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001771 ret = sunxi_nand_chip_init_timings(chip, np);
1772 if (ret) {
1773 dev_err(dev, "could not configure chip timings: %d\n", ret);
1774 return ret;
1775 }
1776
1777 ret = sunxi_nand_ecc_init(mtd, &nand->ecc, np);
1778 if (ret) {
1779 dev_err(dev, "ECC init failed: %d\n", ret);
1780 return ret;
1781 }
1782
1783 ret = nand_scan_tail(mtd);
1784 if (ret) {
1785 dev_err(dev, "nand_scan_tail failed: %d\n", ret);
1786 return ret;
1787 }
1788
Brian Norrisa61ae812015-10-30 20:33:25 -07001789 ret = mtd_device_register(mtd, NULL, 0);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001790 if (ret) {
1791 dev_err(dev, "failed to register mtd device: %d\n", ret);
1792 nand_release(mtd);
1793 return ret;
1794 }
1795
1796 list_add_tail(&chip->node, &nfc->chips);
1797
1798 return 0;
1799}
1800
1801static int sunxi_nand_chips_init(struct device *dev, struct sunxi_nfc *nfc)
1802{
1803 struct device_node *np = dev->of_node;
1804 struct device_node *nand_np;
1805 int nchips = of_get_child_count(np);
1806 int ret;
1807
1808 if (nchips > 8) {
1809 dev_err(dev, "too many NAND chips: %d (max = 8)\n", nchips);
1810 return -EINVAL;
1811 }
1812
1813 for_each_child_of_node(np, nand_np) {
1814 ret = sunxi_nand_chip_init(dev, nfc, nand_np);
Julia Lawalla81c0f02015-11-18 23:04:12 +01001815 if (ret) {
1816 of_node_put(nand_np);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001817 return ret;
Julia Lawalla81c0f02015-11-18 23:04:12 +01001818 }
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001819 }
1820
1821 return 0;
1822}
1823
1824static void sunxi_nand_chips_cleanup(struct sunxi_nfc *nfc)
1825{
1826 struct sunxi_nand_chip *chip;
1827
1828 while (!list_empty(&nfc->chips)) {
1829 chip = list_first_entry(&nfc->chips, struct sunxi_nand_chip,
1830 node);
Boris BREZILLON32e9f2d2015-12-10 09:00:26 +01001831 nand_release(nand_to_mtd(&chip->nand));
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001832 sunxi_nand_ecc_cleanup(&chip->nand.ecc);
Boris BREZILLON8e375cc2015-09-13 18:14:43 +02001833 list_del(&chip->node);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001834 }
1835}
1836
1837static int sunxi_nfc_probe(struct platform_device *pdev)
1838{
1839 struct device *dev = &pdev->dev;
1840 struct resource *r;
1841 struct sunxi_nfc *nfc;
1842 int irq;
1843 int ret;
1844
1845 nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
1846 if (!nfc)
1847 return -ENOMEM;
1848
1849 nfc->dev = dev;
1850 spin_lock_init(&nfc->controller.lock);
1851 init_waitqueue_head(&nfc->controller.wq);
1852 INIT_LIST_HEAD(&nfc->chips);
1853
1854 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1855 nfc->regs = devm_ioremap_resource(dev, r);
1856 if (IS_ERR(nfc->regs))
1857 return PTR_ERR(nfc->regs);
1858
1859 irq = platform_get_irq(pdev, 0);
1860 if (irq < 0) {
1861 dev_err(dev, "failed to retrieve irq\n");
1862 return irq;
1863 }
1864
1865 nfc->ahb_clk = devm_clk_get(dev, "ahb");
1866 if (IS_ERR(nfc->ahb_clk)) {
1867 dev_err(dev, "failed to retrieve ahb clk\n");
1868 return PTR_ERR(nfc->ahb_clk);
1869 }
1870
1871 ret = clk_prepare_enable(nfc->ahb_clk);
1872 if (ret)
1873 return ret;
1874
1875 nfc->mod_clk = devm_clk_get(dev, "mod");
1876 if (IS_ERR(nfc->mod_clk)) {
1877 dev_err(dev, "failed to retrieve mod clk\n");
1878 ret = PTR_ERR(nfc->mod_clk);
1879 goto out_ahb_clk_unprepare;
1880 }
1881
1882 ret = clk_prepare_enable(nfc->mod_clk);
1883 if (ret)
1884 goto out_ahb_clk_unprepare;
1885
1886 ret = sunxi_nfc_rst(nfc);
1887 if (ret)
1888 goto out_mod_clk_unprepare;
1889
1890 writel(0, nfc->regs + NFC_REG_INT);
1891 ret = devm_request_irq(dev, irq, sunxi_nfc_interrupt,
1892 0, "sunxi-nand", nfc);
1893 if (ret)
1894 goto out_mod_clk_unprepare;
1895
1896 platform_set_drvdata(pdev, nfc);
1897
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001898 ret = sunxi_nand_chips_init(dev, nfc);
1899 if (ret) {
1900 dev_err(dev, "failed to init nand chips\n");
1901 goto out_mod_clk_unprepare;
1902 }
1903
1904 return 0;
1905
1906out_mod_clk_unprepare:
1907 clk_disable_unprepare(nfc->mod_clk);
1908out_ahb_clk_unprepare:
1909 clk_disable_unprepare(nfc->ahb_clk);
1910
1911 return ret;
1912}
1913
1914static int sunxi_nfc_remove(struct platform_device *pdev)
1915{
1916 struct sunxi_nfc *nfc = platform_get_drvdata(pdev);
1917
1918 sunxi_nand_chips_cleanup(nfc);
Boris Brezillondd26a452016-03-04 18:26:40 +01001919 clk_disable_unprepare(nfc->mod_clk);
1920 clk_disable_unprepare(nfc->ahb_clk);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001921
1922 return 0;
1923}
1924
1925static const struct of_device_id sunxi_nfc_ids[] = {
1926 { .compatible = "allwinner,sun4i-a10-nand" },
1927 { /* sentinel */ }
1928};
1929MODULE_DEVICE_TABLE(of, sunxi_nfc_ids);
1930
1931static struct platform_driver sunxi_nfc_driver = {
1932 .driver = {
1933 .name = "sunxi_nand",
1934 .of_match_table = sunxi_nfc_ids,
1935 },
1936 .probe = sunxi_nfc_probe,
1937 .remove = sunxi_nfc_remove,
1938};
1939module_platform_driver(sunxi_nfc_driver);
1940
1941MODULE_LICENSE("GPL v2");
1942MODULE_AUTHOR("Boris BREZILLON");
1943MODULE_DESCRIPTION("Allwinner NAND Flash Controller driver");
1944MODULE_ALIAS("platform:sunxi_nand");