blob: b71053252a0228e9abc4fcf33e3815371935dd43 [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
959 if (*cur_off != offset)
960 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
969 *cur_off = mtd->oobsize + mtd->writesize;
970}
971
Boris BREZILLON913821b2015-09-30 23:45:24 +0200972static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd,
973 const u8 *data, int data_off,
974 const u8 *oob, int oob_off,
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100975 int *cur_off, bool bbm,
976 int page)
Boris BREZILLON913821b2015-09-30 23:45:24 +0200977{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100978 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200979 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
980 struct nand_ecc_ctrl *ecc = &nand->ecc;
981 int ret;
982
983 if (data_off != *cur_off)
984 nand->cmdfunc(mtd, NAND_CMD_RNDIN, data_off, -1);
985
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100986 sunxi_nfc_randomizer_write_buf(mtd, data, ecc->size, false, page);
Boris BREZILLON913821b2015-09-30 23:45:24 +0200987
Boris BREZILLON74eb9ff2015-10-20 22:16:00 +0200988 if (data_off + ecc->size != oob_off)
Boris BREZILLON913821b2015-09-30 23:45:24 +0200989 nand->cmdfunc(mtd, NAND_CMD_RNDIN, oob_off, -1);
990
991 ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
992 if (ret)
993 return ret;
994
Boris BREZILLON4be4e032015-12-02 12:01:07 +0100995 sunxi_nfc_randomizer_enable(mtd);
Boris Brezilloncc6822f2016-03-04 17:56:47 +0100996 sunxi_nfc_hw_ecc_set_prot_oob_bytes(mtd, oob, 0, bbm, page);
997
Boris BREZILLON913821b2015-09-30 23:45:24 +0200998 writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD |
999 NFC_ACCESS_DIR | NFC_ECC_OP,
1000 nfc->regs + NFC_REG_CMD);
1001
Boris Brezillonc0c9dfa2016-03-07 15:34:39 +01001002 ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0);
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001003 sunxi_nfc_randomizer_disable(mtd);
Boris BREZILLON913821b2015-09-30 23:45:24 +02001004 if (ret)
1005 return ret;
1006
1007 *cur_off = oob_off + ecc->bytes + 4;
1008
1009 return 0;
1010}
1011
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001012static void sunxi_nfc_hw_ecc_write_extra_oob(struct mtd_info *mtd,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001013 u8 *oob, int *cur_off,
1014 int page)
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001015{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +01001016 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001017 struct nand_ecc_ctrl *ecc = &nand->ecc;
1018 int offset = ((ecc->bytes + 4) * ecc->steps);
1019 int len = mtd->oobsize - offset;
1020
1021 if (len <= 0)
1022 return;
1023
1024 if (*cur_off != offset)
1025 nand->cmdfunc(mtd, NAND_CMD_RNDIN,
1026 offset + mtd->writesize, -1);
1027
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001028 sunxi_nfc_randomizer_write_buf(mtd, oob + offset, len, false, page);
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001029
1030 *cur_off = mtd->oobsize + mtd->writesize;
1031}
1032
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001033static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd,
1034 struct nand_chip *chip, uint8_t *buf,
1035 int oob_required, int page)
1036{
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001037 struct nand_ecc_ctrl *ecc = &chip->ecc;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001038 unsigned int max_bitflips = 0;
Boris BREZILLONb4625512015-09-30 23:45:25 +02001039 int ret, i, cur_off = 0;
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001040 bool raw_mode = false;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001041
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001042 sunxi_nfc_hw_ecc_enable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001043
1044 for (i = 0; i < ecc->steps; i++) {
Boris BREZILLONb4625512015-09-30 23:45:25 +02001045 int data_off = i * ecc->size;
1046 int oob_off = i * (ecc->bytes + 4);
1047 u8 *data = buf + data_off;
1048 u8 *oob = chip->oob_poi + oob_off;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001049
Boris BREZILLONb4625512015-09-30 23:45:25 +02001050 ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob,
1051 oob_off + mtd->writesize,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001052 &cur_off, &max_bitflips,
Boris Brezillon828dec12016-03-04 18:09:21 +01001053 !i, oob_required, page);
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001054 if (ret < 0)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001055 return ret;
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001056 else if (ret)
1057 raw_mode = true;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001058 }
1059
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001060 if (oob_required)
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001061 sunxi_nfc_hw_ecc_read_extra_oob(mtd, chip->oob_poi, &cur_off,
1062 !raw_mode, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001063
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001064 sunxi_nfc_hw_ecc_disable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001065
1066 return max_bitflips;
1067}
1068
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001069static int sunxi_nfc_hw_ecc_read_subpage(struct mtd_info *mtd,
1070 struct nand_chip *chip,
1071 u32 data_offs, u32 readlen,
1072 u8 *bufpoi, int page)
1073{
1074 struct nand_ecc_ctrl *ecc = &chip->ecc;
1075 int ret, i, cur_off = 0;
1076 unsigned int max_bitflips = 0;
1077
1078 sunxi_nfc_hw_ecc_enable(mtd);
1079
1080 chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
1081 for (i = data_offs / ecc->size;
1082 i < DIV_ROUND_UP(data_offs + readlen, ecc->size); i++) {
1083 int data_off = i * ecc->size;
1084 int oob_off = i * (ecc->bytes + 4);
1085 u8 *data = bufpoi + data_off;
1086 u8 *oob = chip->oob_poi + oob_off;
1087
1088 ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off,
1089 oob,
1090 oob_off + mtd->writesize,
Boris Brezillon828dec12016-03-04 18:09:21 +01001091 &cur_off, &max_bitflips, !i,
1092 false, page);
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001093 if (ret < 0)
1094 return ret;
1095 }
1096
1097 sunxi_nfc_hw_ecc_disable(mtd);
1098
1099 return max_bitflips;
1100}
1101
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001102static int sunxi_nfc_hw_ecc_write_page(struct mtd_info *mtd,
1103 struct nand_chip *chip,
Boris BREZILLON45aaeff2015-10-13 11:22:18 +02001104 const uint8_t *buf, int oob_required,
1105 int page)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001106{
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001107 struct nand_ecc_ctrl *ecc = &chip->ecc;
Boris BREZILLONb4625512015-09-30 23:45:25 +02001108 int ret, i, cur_off = 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001109
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001110 sunxi_nfc_hw_ecc_enable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001111
1112 for (i = 0; i < ecc->steps; i++) {
Boris BREZILLONb4625512015-09-30 23:45:25 +02001113 int data_off = i * ecc->size;
1114 int oob_off = i * (ecc->bytes + 4);
1115 const u8 *data = buf + data_off;
1116 const u8 *oob = chip->oob_poi + oob_off;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001117
Boris BREZILLONb4625512015-09-30 23:45:25 +02001118 ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off, oob,
1119 oob_off + mtd->writesize,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001120 &cur_off, !i, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001121 if (ret)
1122 return ret;
1123 }
1124
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001125 if (oob_required || (chip->options & NAND_NEED_SCRAMBLING))
1126 sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi,
1127 &cur_off, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001128
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001129 sunxi_nfc_hw_ecc_disable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001130
1131 return 0;
1132}
1133
1134static int sunxi_nfc_hw_syndrome_ecc_read_page(struct mtd_info *mtd,
1135 struct nand_chip *chip,
1136 uint8_t *buf, int oob_required,
1137 int page)
1138{
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001139 struct nand_ecc_ctrl *ecc = &chip->ecc;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001140 unsigned int max_bitflips = 0;
Boris BREZILLONb4625512015-09-30 23:45:25 +02001141 int ret, i, cur_off = 0;
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001142 bool raw_mode = false;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001143
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001144 sunxi_nfc_hw_ecc_enable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001145
1146 for (i = 0; i < ecc->steps; i++) {
Boris BREZILLONb4625512015-09-30 23:45:25 +02001147 int data_off = i * (ecc->size + ecc->bytes + 4);
1148 int oob_off = data_off + ecc->size;
1149 u8 *data = buf + (i * ecc->size);
1150 u8 *oob = chip->oob_poi + (i * (ecc->bytes + 4));
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001151
Boris BREZILLONb4625512015-09-30 23:45:25 +02001152 ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob,
1153 oob_off, &cur_off,
Boris Brezillon828dec12016-03-04 18:09:21 +01001154 &max_bitflips, !i,
1155 oob_required,
1156 page);
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001157 if (ret < 0)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001158 return ret;
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001159 else if (ret)
1160 raw_mode = true;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001161 }
1162
Boris BREZILLON35d0e242015-09-30 23:45:26 +02001163 if (oob_required)
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001164 sunxi_nfc_hw_ecc_read_extra_oob(mtd, chip->oob_poi, &cur_off,
1165 !raw_mode, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001166
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001167 sunxi_nfc_hw_ecc_disable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001168
1169 return max_bitflips;
1170}
1171
1172static int sunxi_nfc_hw_syndrome_ecc_write_page(struct mtd_info *mtd,
1173 struct nand_chip *chip,
1174 const uint8_t *buf,
Boris BREZILLON45aaeff2015-10-13 11:22:18 +02001175 int oob_required, int page)
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001176{
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001177 struct nand_ecc_ctrl *ecc = &chip->ecc;
Boris BREZILLONb4625512015-09-30 23:45:25 +02001178 int ret, i, cur_off = 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001179
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001180 sunxi_nfc_hw_ecc_enable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001181
1182 for (i = 0; i < ecc->steps; i++) {
Boris BREZILLONb4625512015-09-30 23:45:25 +02001183 int data_off = i * (ecc->size + ecc->bytes + 4);
1184 int oob_off = data_off + ecc->size;
1185 const u8 *data = buf + (i * ecc->size);
1186 const u8 *oob = chip->oob_poi + (i * (ecc->bytes + 4));
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001187
Boris BREZILLONb4625512015-09-30 23:45:25 +02001188 ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off,
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001189 oob, oob_off, &cur_off,
1190 false, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001191 if (ret)
1192 return ret;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001193 }
1194
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001195 if (oob_required || (chip->options & NAND_NEED_SCRAMBLING))
1196 sunxi_nfc_hw_ecc_write_extra_oob(mtd, chip->oob_poi,
1197 &cur_off, page);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001198
Boris BREZILLONc9118ec2015-09-30 23:45:23 +02001199 sunxi_nfc_hw_ecc_disable(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001200
1201 return 0;
1202}
1203
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001204static int sunxi_nfc_hw_common_ecc_read_oob(struct mtd_info *mtd,
1205 struct nand_chip *chip,
1206 int page)
1207{
1208 chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
1209
1210 chip->pagebuf = -1;
1211
1212 return chip->ecc.read_page(mtd, chip, chip->buffers->databuf, 1, page);
1213}
1214
1215static int sunxi_nfc_hw_common_ecc_write_oob(struct mtd_info *mtd,
1216 struct nand_chip *chip,
1217 int page)
1218{
1219 int ret, status;
1220
1221 chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0, page);
1222
1223 chip->pagebuf = -1;
1224
1225 memset(chip->buffers->databuf, 0xff, mtd->writesize);
1226 ret = chip->ecc.write_page(mtd, chip, chip->buffers->databuf, 1, page);
1227 if (ret)
1228 return ret;
1229
1230 /* Send command to program the OOB data */
1231 chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
1232
1233 status = chip->waitfunc(mtd, chip);
1234
1235 return status & NAND_STATUS_FAIL ? -EIO : 0;
1236}
1237
Roy Spliet9c618292015-06-26 11:00:10 +02001238static const s32 tWB_lut[] = {6, 12, 16, 20};
1239static const s32 tRHW_lut[] = {4, 8, 12, 20};
1240
1241static int _sunxi_nand_lookup_timing(const s32 *lut, int lut_size, u32 duration,
1242 u32 clk_period)
1243{
1244 u32 clk_cycles = DIV_ROUND_UP(duration, clk_period);
1245 int i;
1246
1247 for (i = 0; i < lut_size; i++) {
1248 if (clk_cycles <= lut[i])
1249 return i;
1250 }
1251
1252 /* Doesn't fit */
1253 return -EINVAL;
1254}
1255
1256#define sunxi_nand_lookup_timing(l, p, c) \
1257 _sunxi_nand_lookup_timing(l, ARRAY_SIZE(l), p, c)
1258
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001259static int sunxi_nand_chip_set_timings(struct sunxi_nand_chip *chip,
1260 const struct nand_sdr_timings *timings)
1261{
Roy Spliet9c618292015-06-26 11:00:10 +02001262 struct sunxi_nfc *nfc = to_sunxi_nfc(chip->nand.controller);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001263 u32 min_clk_period = 0;
Roy Spliet9c618292015-06-26 11:00:10 +02001264 s32 tWB, tADL, tWHR, tRHW, tCAD;
Boris Brezillon2d434572015-12-02 15:57:20 +01001265 long real_clk_rate;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001266
1267 /* T1 <=> tCLS */
1268 if (timings->tCLS_min > min_clk_period)
1269 min_clk_period = timings->tCLS_min;
1270
1271 /* T2 <=> tCLH */
1272 if (timings->tCLH_min > min_clk_period)
1273 min_clk_period = timings->tCLH_min;
1274
1275 /* T3 <=> tCS */
1276 if (timings->tCS_min > min_clk_period)
1277 min_clk_period = timings->tCS_min;
1278
1279 /* T4 <=> tCH */
1280 if (timings->tCH_min > min_clk_period)
1281 min_clk_period = timings->tCH_min;
1282
1283 /* T5 <=> tWP */
1284 if (timings->tWP_min > min_clk_period)
1285 min_clk_period = timings->tWP_min;
1286
1287 /* T6 <=> tWH */
1288 if (timings->tWH_min > min_clk_period)
1289 min_clk_period = timings->tWH_min;
1290
1291 /* T7 <=> tALS */
1292 if (timings->tALS_min > min_clk_period)
1293 min_clk_period = timings->tALS_min;
1294
1295 /* T8 <=> tDS */
1296 if (timings->tDS_min > min_clk_period)
1297 min_clk_period = timings->tDS_min;
1298
1299 /* T9 <=> tDH */
1300 if (timings->tDH_min > min_clk_period)
1301 min_clk_period = timings->tDH_min;
1302
1303 /* T10 <=> tRR */
1304 if (timings->tRR_min > (min_clk_period * 3))
1305 min_clk_period = DIV_ROUND_UP(timings->tRR_min, 3);
1306
1307 /* T11 <=> tALH */
1308 if (timings->tALH_min > min_clk_period)
1309 min_clk_period = timings->tALH_min;
1310
1311 /* T12 <=> tRP */
1312 if (timings->tRP_min > min_clk_period)
1313 min_clk_period = timings->tRP_min;
1314
1315 /* T13 <=> tREH */
1316 if (timings->tREH_min > min_clk_period)
1317 min_clk_period = timings->tREH_min;
1318
1319 /* T14 <=> tRC */
1320 if (timings->tRC_min > (min_clk_period * 2))
1321 min_clk_period = DIV_ROUND_UP(timings->tRC_min, 2);
1322
1323 /* T15 <=> tWC */
1324 if (timings->tWC_min > (min_clk_period * 2))
1325 min_clk_period = DIV_ROUND_UP(timings->tWC_min, 2);
1326
Roy Spliet9c618292015-06-26 11:00:10 +02001327 /* T16 - T19 + tCAD */
Boris Brezillon5abcd952015-11-11 22:30:30 +01001328 if (timings->tWB_max > (min_clk_period * 20))
1329 min_clk_period = DIV_ROUND_UP(timings->tWB_max, 20);
1330
1331 if (timings->tADL_min > (min_clk_period * 32))
1332 min_clk_period = DIV_ROUND_UP(timings->tADL_min, 32);
1333
1334 if (timings->tWHR_min > (min_clk_period * 32))
1335 min_clk_period = DIV_ROUND_UP(timings->tWHR_min, 32);
1336
1337 if (timings->tRHW_min > (min_clk_period * 20))
1338 min_clk_period = DIV_ROUND_UP(timings->tRHW_min, 20);
1339
Roy Spliet9c618292015-06-26 11:00:10 +02001340 tWB = sunxi_nand_lookup_timing(tWB_lut, timings->tWB_max,
1341 min_clk_period);
1342 if (tWB < 0) {
1343 dev_err(nfc->dev, "unsupported tWB\n");
1344 return tWB;
1345 }
1346
1347 tADL = DIV_ROUND_UP(timings->tADL_min, min_clk_period) >> 3;
1348 if (tADL > 3) {
1349 dev_err(nfc->dev, "unsupported tADL\n");
1350 return -EINVAL;
1351 }
1352
1353 tWHR = DIV_ROUND_UP(timings->tWHR_min, min_clk_period) >> 3;
1354 if (tWHR > 3) {
1355 dev_err(nfc->dev, "unsupported tWHR\n");
1356 return -EINVAL;
1357 }
1358
1359 tRHW = sunxi_nand_lookup_timing(tRHW_lut, timings->tRHW_min,
1360 min_clk_period);
1361 if (tRHW < 0) {
1362 dev_err(nfc->dev, "unsupported tRHW\n");
1363 return tRHW;
1364 }
1365
1366 /*
1367 * TODO: according to ONFI specs this value only applies for DDR NAND,
1368 * but Allwinner seems to set this to 0x7. Mimic them for now.
1369 */
1370 tCAD = 0x7;
1371
1372 /* TODO: A83 has some more bits for CDQSS, CS, CLHZ, CCS, WC */
1373 chip->timing_cfg = NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001374
1375 /* Convert min_clk_period from picoseconds to nanoseconds */
1376 min_clk_period = DIV_ROUND_UP(min_clk_period, 1000);
1377
1378 /*
Boris Brezillon2f9992e2015-12-02 15:10:40 +01001379 * Unlike what is stated in Allwinner datasheet, the clk_rate should
1380 * be set to (1 / min_clk_period), and not (2 / min_clk_period).
1381 * This new formula was verified with a scope and validated by
1382 * Allwinner engineers.
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001383 */
Boris Brezillon2f9992e2015-12-02 15:10:40 +01001384 chip->clk_rate = NSEC_PER_SEC / min_clk_period;
Boris Brezillon2d434572015-12-02 15:57:20 +01001385 real_clk_rate = clk_round_rate(nfc->mod_clk, chip->clk_rate);
1386
1387 /*
1388 * ONFI specification 3.1, paragraph 4.15.2 dictates that EDO data
1389 * output cycle timings shall be used if the host drives tRC less than
1390 * 30 ns.
1391 */
1392 min_clk_period = NSEC_PER_SEC / real_clk_rate;
1393 chip->timing_ctl = ((min_clk_period * 2) < 30) ?
1394 NFC_TIMING_CTL_EDO : 0;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001395
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001396 return 0;
1397}
1398
1399static int sunxi_nand_chip_init_timings(struct sunxi_nand_chip *chip,
1400 struct device_node *np)
1401{
Boris BREZILLON32e9f2d2015-12-10 09:00:26 +01001402 struct mtd_info *mtd = nand_to_mtd(&chip->nand);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001403 const struct nand_sdr_timings *timings;
1404 int ret;
1405 int mode;
1406
1407 mode = onfi_get_async_timing_mode(&chip->nand);
1408 if (mode == ONFI_TIMING_MODE_UNKNOWN) {
1409 mode = chip->nand.onfi_timing_mode_default;
1410 } else {
1411 uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {};
Stefan Roese7eadd472015-08-28 14:45:21 +02001412 int i;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001413
1414 mode = fls(mode) - 1;
1415 if (mode < 0)
1416 mode = 0;
1417
1418 feature[0] = mode;
Stefan Roese7eadd472015-08-28 14:45:21 +02001419 for (i = 0; i < chip->nsels; i++) {
Boris BREZILLON32e9f2d2015-12-10 09:00:26 +01001420 chip->nand.select_chip(mtd, i);
1421 ret = chip->nand.onfi_set_features(mtd, &chip->nand,
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001422 ONFI_FEATURE_ADDR_TIMING_MODE,
1423 feature);
Boris BREZILLON32e9f2d2015-12-10 09:00:26 +01001424 chip->nand.select_chip(mtd, -1);
Stefan Roese7eadd472015-08-28 14:45:21 +02001425 if (ret)
1426 return ret;
1427 }
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001428 }
1429
1430 timings = onfi_async_timing_mode_to_sdr_timings(mode);
1431 if (IS_ERR(timings))
1432 return PTR_ERR(timings);
1433
1434 return sunxi_nand_chip_set_timings(chip, timings);
1435}
1436
1437static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd,
1438 struct nand_ecc_ctrl *ecc,
1439 struct device_node *np)
1440{
1441 static const u8 strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 };
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +01001442 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001443 struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
1444 struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
1445 struct sunxi_nand_hw_ecc *data;
1446 struct nand_ecclayout *layout;
1447 int nsectors;
1448 int ret;
1449 int i;
1450
1451 data = kzalloc(sizeof(*data), GFP_KERNEL);
1452 if (!data)
1453 return -ENOMEM;
1454
1455 /* Add ECC info retrieval from DT */
1456 for (i = 0; i < ARRAY_SIZE(strengths); i++) {
1457 if (ecc->strength <= strengths[i])
1458 break;
1459 }
1460
1461 if (i >= ARRAY_SIZE(strengths)) {
1462 dev_err(nfc->dev, "unsupported strength\n");
1463 ret = -ENOTSUPP;
1464 goto err;
1465 }
1466
1467 data->mode = i;
1468
1469 /* HW ECC always request ECC bytes for 1024 bytes blocks */
1470 ecc->bytes = DIV_ROUND_UP(ecc->strength * fls(8 * 1024), 8);
1471
1472 /* HW ECC always work with even numbers of ECC bytes */
1473 ecc->bytes = ALIGN(ecc->bytes, 2);
1474
1475 layout = &data->layout;
1476 nsectors = mtd->writesize / ecc->size;
1477
1478 if (mtd->oobsize < ((ecc->bytes + 4) * nsectors)) {
1479 ret = -EINVAL;
1480 goto err;
1481 }
1482
1483 layout->eccbytes = (ecc->bytes * nsectors);
1484
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001485 ecc->read_oob = sunxi_nfc_hw_common_ecc_read_oob;
1486 ecc->write_oob = sunxi_nfc_hw_common_ecc_write_oob;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001487 ecc->layout = layout;
1488 ecc->priv = data;
1489
1490 return 0;
1491
1492err:
1493 kfree(data);
1494
1495 return ret;
1496}
1497
1498static void sunxi_nand_hw_common_ecc_ctrl_cleanup(struct nand_ecc_ctrl *ecc)
1499{
1500 kfree(ecc->priv);
1501}
1502
1503static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
1504 struct nand_ecc_ctrl *ecc,
1505 struct device_node *np)
1506{
1507 struct nand_ecclayout *layout;
1508 int nsectors;
1509 int i, j;
1510 int ret;
1511
1512 ret = sunxi_nand_hw_common_ecc_ctrl_init(mtd, ecc, np);
1513 if (ret)
1514 return ret;
1515
1516 ecc->read_page = sunxi_nfc_hw_ecc_read_page;
1517 ecc->write_page = sunxi_nfc_hw_ecc_write_page;
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001518 ecc->read_oob_raw = nand_read_oob_std;
1519 ecc->write_oob_raw = nand_write_oob_std;
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001520 ecc->read_subpage = sunxi_nfc_hw_ecc_read_subpage;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001521 layout = ecc->layout;
1522 nsectors = mtd->writesize / ecc->size;
1523
1524 for (i = 0; i < nsectors; i++) {
1525 if (i) {
1526 layout->oobfree[i].offset =
1527 layout->oobfree[i - 1].offset +
1528 layout->oobfree[i - 1].length +
1529 ecc->bytes;
1530 layout->oobfree[i].length = 4;
1531 } else {
1532 /*
1533 * The first 2 bytes are used for BB markers, hence we
1534 * only have 2 bytes available in the first user data
1535 * section.
1536 */
1537 layout->oobfree[i].length = 2;
1538 layout->oobfree[i].offset = 2;
1539 }
1540
1541 for (j = 0; j < ecc->bytes; j++)
1542 layout->eccpos[(ecc->bytes * i) + j] =
1543 layout->oobfree[i].offset +
1544 layout->oobfree[i].length + j;
1545 }
1546
1547 if (mtd->oobsize > (ecc->bytes + 4) * nsectors) {
1548 layout->oobfree[nsectors].offset =
1549 layout->oobfree[nsectors - 1].offset +
1550 layout->oobfree[nsectors - 1].length +
1551 ecc->bytes;
1552 layout->oobfree[nsectors].length = mtd->oobsize -
1553 ((ecc->bytes + 4) * nsectors);
1554 }
1555
1556 return 0;
1557}
1558
1559static int sunxi_nand_hw_syndrome_ecc_ctrl_init(struct mtd_info *mtd,
1560 struct nand_ecc_ctrl *ecc,
1561 struct device_node *np)
1562{
1563 struct nand_ecclayout *layout;
1564 int nsectors;
1565 int i;
1566 int ret;
1567
1568 ret = sunxi_nand_hw_common_ecc_ctrl_init(mtd, ecc, np);
1569 if (ret)
1570 return ret;
1571
1572 ecc->prepad = 4;
1573 ecc->read_page = sunxi_nfc_hw_syndrome_ecc_read_page;
1574 ecc->write_page = sunxi_nfc_hw_syndrome_ecc_write_page;
Boris Brezillon1c1bdd62015-09-02 15:05:52 +02001575 ecc->read_oob_raw = nand_read_oob_syndrome;
1576 ecc->write_oob_raw = nand_write_oob_syndrome;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001577
1578 layout = ecc->layout;
1579 nsectors = mtd->writesize / ecc->size;
1580
1581 for (i = 0; i < (ecc->bytes * nsectors); i++)
1582 layout->eccpos[i] = i;
1583
1584 layout->oobfree[0].length = mtd->oobsize - i;
1585 layout->oobfree[0].offset = i;
1586
1587 return 0;
1588}
1589
1590static void sunxi_nand_ecc_cleanup(struct nand_ecc_ctrl *ecc)
1591{
1592 switch (ecc->mode) {
1593 case NAND_ECC_HW:
1594 case NAND_ECC_HW_SYNDROME:
1595 sunxi_nand_hw_common_ecc_ctrl_cleanup(ecc);
1596 break;
1597 case NAND_ECC_NONE:
1598 kfree(ecc->layout);
1599 default:
1600 break;
1601 }
1602}
1603
1604static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc,
1605 struct device_node *np)
1606{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +01001607 struct nand_chip *nand = mtd_to_nand(mtd);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001608 int ret;
1609
Boris BREZILLONa3d22a52015-09-02 10:30:25 +02001610 if (!ecc->size) {
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001611 ecc->size = nand->ecc_step_ds;
1612 ecc->strength = nand->ecc_strength_ds;
1613 }
1614
1615 if (!ecc->size || !ecc->strength)
1616 return -EINVAL;
1617
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001618 switch (ecc->mode) {
1619 case NAND_ECC_SOFT_BCH:
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001620 break;
1621 case NAND_ECC_HW:
1622 ret = sunxi_nand_hw_ecc_ctrl_init(mtd, ecc, np);
1623 if (ret)
1624 return ret;
1625 break;
1626 case NAND_ECC_HW_SYNDROME:
1627 ret = sunxi_nand_hw_syndrome_ecc_ctrl_init(mtd, ecc, np);
1628 if (ret)
1629 return ret;
1630 break;
1631 case NAND_ECC_NONE:
1632 ecc->layout = kzalloc(sizeof(*ecc->layout), GFP_KERNEL);
1633 if (!ecc->layout)
1634 return -ENOMEM;
1635 ecc->layout->oobfree[0].length = mtd->oobsize;
1636 case NAND_ECC_SOFT:
1637 break;
1638 default:
1639 return -EINVAL;
1640 }
1641
1642 return 0;
1643}
1644
1645static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
1646 struct device_node *np)
1647{
1648 const struct nand_sdr_timings *timings;
1649 struct sunxi_nand_chip *chip;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001650 struct mtd_info *mtd;
1651 struct nand_chip *nand;
1652 int nsels;
1653 int ret;
1654 int i;
1655 u32 tmp;
1656
1657 if (!of_get_property(np, "reg", &nsels))
1658 return -EINVAL;
1659
1660 nsels /= sizeof(u32);
1661 if (!nsels) {
1662 dev_err(dev, "invalid reg property size\n");
1663 return -EINVAL;
1664 }
1665
1666 chip = devm_kzalloc(dev,
1667 sizeof(*chip) +
1668 (nsels * sizeof(struct sunxi_nand_chip_sel)),
1669 GFP_KERNEL);
1670 if (!chip) {
1671 dev_err(dev, "could not allocate chip\n");
1672 return -ENOMEM;
1673 }
1674
1675 chip->nsels = nsels;
1676 chip->selected = -1;
1677
1678 for (i = 0; i < nsels; i++) {
1679 ret = of_property_read_u32_index(np, "reg", i, &tmp);
1680 if (ret) {
1681 dev_err(dev, "could not retrieve reg property: %d\n",
1682 ret);
1683 return ret;
1684 }
1685
1686 if (tmp > NFC_MAX_CS) {
1687 dev_err(dev,
1688 "invalid reg value: %u (max CS = 7)\n",
1689 tmp);
1690 return -EINVAL;
1691 }
1692
1693 if (test_and_set_bit(tmp, &nfc->assigned_cs)) {
1694 dev_err(dev, "CS %d already assigned\n", tmp);
1695 return -EINVAL;
1696 }
1697
1698 chip->sels[i].cs = tmp;
1699
1700 if (!of_property_read_u32_index(np, "allwinner,rb", i, &tmp) &&
1701 tmp < 2) {
1702 chip->sels[i].rb.type = RB_NATIVE;
1703 chip->sels[i].rb.info.nativeid = tmp;
1704 } else {
1705 ret = of_get_named_gpio(np, "rb-gpios", i);
1706 if (ret >= 0) {
1707 tmp = ret;
1708 chip->sels[i].rb.type = RB_GPIO;
1709 chip->sels[i].rb.info.gpio = tmp;
1710 ret = devm_gpio_request(dev, tmp, "nand-rb");
1711 if (ret)
1712 return ret;
1713
1714 ret = gpio_direction_input(tmp);
1715 if (ret)
1716 return ret;
1717 } else {
1718 chip->sels[i].rb.type = RB_NONE;
1719 }
1720 }
1721 }
1722
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001723 nand = &chip->nand;
1724 /* Default tR value specified in the ONFI spec (chapter 4.15.1) */
1725 nand->chip_delay = 200;
1726 nand->controller = &nfc->controller;
Boris BREZILLONa3d22a52015-09-02 10:30:25 +02001727 /*
1728 * Set the ECC mode to the default value in case nothing is specified
1729 * in the DT.
1730 */
1731 nand->ecc.mode = NAND_ECC_HW;
Brian Norris63752192015-10-30 20:33:23 -07001732 nand_set_flash_node(nand, np);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001733 nand->select_chip = sunxi_nfc_select_chip;
1734 nand->cmd_ctrl = sunxi_nfc_cmd_ctrl;
1735 nand->read_buf = sunxi_nfc_read_buf;
1736 nand->write_buf = sunxi_nfc_write_buf;
1737 nand->read_byte = sunxi_nfc_read_byte;
1738
Boris BREZILLON32e9f2d2015-12-10 09:00:26 +01001739 mtd = nand_to_mtd(nand);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001740 mtd->dev.parent = dev;
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001741
Boris Brezillon9edb4702015-12-02 16:00:57 +01001742 timings = onfi_async_timing_mode_to_sdr_timings(0);
1743 if (IS_ERR(timings)) {
1744 ret = PTR_ERR(timings);
1745 dev_err(dev,
1746 "could not retrieve timings for ONFI mode 0: %d\n",
1747 ret);
1748 return ret;
1749 }
1750
1751 ret = sunxi_nand_chip_set_timings(chip, timings);
1752 if (ret) {
1753 dev_err(dev, "could not configure chip timings: %d\n", ret);
1754 return ret;
1755 }
1756
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001757 ret = nand_scan_ident(mtd, nsels, NULL);
1758 if (ret)
1759 return ret;
1760
Boris BREZILLONa3d22a52015-09-02 10:30:25 +02001761 if (nand->bbt_options & NAND_BBT_USE_FLASH)
1762 nand->bbt_options |= NAND_BBT_NO_OOB;
1763
Boris BREZILLON4be4e032015-12-02 12:01:07 +01001764 if (nand->options & NAND_NEED_SCRAMBLING)
1765 nand->options |= NAND_NO_SUBPAGE_WRITE;
1766
Boris Brezillonfe82cce2015-09-16 09:01:45 +02001767 nand->options |= NAND_SUBPAGE_READ;
1768
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001769 ret = sunxi_nand_chip_init_timings(chip, np);
1770 if (ret) {
1771 dev_err(dev, "could not configure chip timings: %d\n", ret);
1772 return ret;
1773 }
1774
1775 ret = sunxi_nand_ecc_init(mtd, &nand->ecc, np);
1776 if (ret) {
1777 dev_err(dev, "ECC init failed: %d\n", ret);
1778 return ret;
1779 }
1780
1781 ret = nand_scan_tail(mtd);
1782 if (ret) {
1783 dev_err(dev, "nand_scan_tail failed: %d\n", ret);
1784 return ret;
1785 }
1786
Brian Norrisa61ae812015-10-30 20:33:25 -07001787 ret = mtd_device_register(mtd, NULL, 0);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001788 if (ret) {
1789 dev_err(dev, "failed to register mtd device: %d\n", ret);
1790 nand_release(mtd);
1791 return ret;
1792 }
1793
1794 list_add_tail(&chip->node, &nfc->chips);
1795
1796 return 0;
1797}
1798
1799static int sunxi_nand_chips_init(struct device *dev, struct sunxi_nfc *nfc)
1800{
1801 struct device_node *np = dev->of_node;
1802 struct device_node *nand_np;
1803 int nchips = of_get_child_count(np);
1804 int ret;
1805
1806 if (nchips > 8) {
1807 dev_err(dev, "too many NAND chips: %d (max = 8)\n", nchips);
1808 return -EINVAL;
1809 }
1810
1811 for_each_child_of_node(np, nand_np) {
1812 ret = sunxi_nand_chip_init(dev, nfc, nand_np);
Julia Lawalla81c0f02015-11-18 23:04:12 +01001813 if (ret) {
1814 of_node_put(nand_np);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001815 return ret;
Julia Lawalla81c0f02015-11-18 23:04:12 +01001816 }
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001817 }
1818
1819 return 0;
1820}
1821
1822static void sunxi_nand_chips_cleanup(struct sunxi_nfc *nfc)
1823{
1824 struct sunxi_nand_chip *chip;
1825
1826 while (!list_empty(&nfc->chips)) {
1827 chip = list_first_entry(&nfc->chips, struct sunxi_nand_chip,
1828 node);
Boris BREZILLON32e9f2d2015-12-10 09:00:26 +01001829 nand_release(nand_to_mtd(&chip->nand));
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001830 sunxi_nand_ecc_cleanup(&chip->nand.ecc);
Boris BREZILLON8e375cc2015-09-13 18:14:43 +02001831 list_del(&chip->node);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001832 }
1833}
1834
1835static int sunxi_nfc_probe(struct platform_device *pdev)
1836{
1837 struct device *dev = &pdev->dev;
1838 struct resource *r;
1839 struct sunxi_nfc *nfc;
1840 int irq;
1841 int ret;
1842
1843 nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
1844 if (!nfc)
1845 return -ENOMEM;
1846
1847 nfc->dev = dev;
1848 spin_lock_init(&nfc->controller.lock);
1849 init_waitqueue_head(&nfc->controller.wq);
1850 INIT_LIST_HEAD(&nfc->chips);
1851
1852 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1853 nfc->regs = devm_ioremap_resource(dev, r);
1854 if (IS_ERR(nfc->regs))
1855 return PTR_ERR(nfc->regs);
1856
1857 irq = platform_get_irq(pdev, 0);
1858 if (irq < 0) {
1859 dev_err(dev, "failed to retrieve irq\n");
1860 return irq;
1861 }
1862
1863 nfc->ahb_clk = devm_clk_get(dev, "ahb");
1864 if (IS_ERR(nfc->ahb_clk)) {
1865 dev_err(dev, "failed to retrieve ahb clk\n");
1866 return PTR_ERR(nfc->ahb_clk);
1867 }
1868
1869 ret = clk_prepare_enable(nfc->ahb_clk);
1870 if (ret)
1871 return ret;
1872
1873 nfc->mod_clk = devm_clk_get(dev, "mod");
1874 if (IS_ERR(nfc->mod_clk)) {
1875 dev_err(dev, "failed to retrieve mod clk\n");
1876 ret = PTR_ERR(nfc->mod_clk);
1877 goto out_ahb_clk_unprepare;
1878 }
1879
1880 ret = clk_prepare_enable(nfc->mod_clk);
1881 if (ret)
1882 goto out_ahb_clk_unprepare;
1883
1884 ret = sunxi_nfc_rst(nfc);
1885 if (ret)
1886 goto out_mod_clk_unprepare;
1887
1888 writel(0, nfc->regs + NFC_REG_INT);
1889 ret = devm_request_irq(dev, irq, sunxi_nfc_interrupt,
1890 0, "sunxi-nand", nfc);
1891 if (ret)
1892 goto out_mod_clk_unprepare;
1893
1894 platform_set_drvdata(pdev, nfc);
1895
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001896 ret = sunxi_nand_chips_init(dev, nfc);
1897 if (ret) {
1898 dev_err(dev, "failed to init nand chips\n");
1899 goto out_mod_clk_unprepare;
1900 }
1901
1902 return 0;
1903
1904out_mod_clk_unprepare:
1905 clk_disable_unprepare(nfc->mod_clk);
1906out_ahb_clk_unprepare:
1907 clk_disable_unprepare(nfc->ahb_clk);
1908
1909 return ret;
1910}
1911
1912static int sunxi_nfc_remove(struct platform_device *pdev)
1913{
1914 struct sunxi_nfc *nfc = platform_get_drvdata(pdev);
1915
1916 sunxi_nand_chips_cleanup(nfc);
Boris Brezillondd26a452016-03-04 18:26:40 +01001917 clk_disable_unprepare(nfc->mod_clk);
1918 clk_disable_unprepare(nfc->ahb_clk);
Boris BREZILLON1fef62c2014-10-21 15:08:41 +02001919
1920 return 0;
1921}
1922
1923static const struct of_device_id sunxi_nfc_ids[] = {
1924 { .compatible = "allwinner,sun4i-a10-nand" },
1925 { /* sentinel */ }
1926};
1927MODULE_DEVICE_TABLE(of, sunxi_nfc_ids);
1928
1929static struct platform_driver sunxi_nfc_driver = {
1930 .driver = {
1931 .name = "sunxi_nand",
1932 .of_match_table = sunxi_nfc_ids,
1933 },
1934 .probe = sunxi_nfc_probe,
1935 .remove = sunxi_nfc_remove,
1936};
1937module_platform_driver(sunxi_nfc_driver);
1938
1939MODULE_LICENSE("GPL v2");
1940MODULE_AUTHOR("Boris BREZILLON");
1941MODULE_DESCRIPTION("Allwinner NAND Flash Controller driver");
1942MODULE_ALIAS("platform:sunxi_nand");