.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) 2016 Sigma Designs |
---|
3 | | - * |
---|
4 | | - * This program is free software; you can redistribute it and/or |
---|
5 | | - * modify it under the terms of the GNU General Public License |
---|
6 | | - * version 2 as published by the Free Software Foundation. |
---|
7 | 4 | */ |
---|
8 | 5 | |
---|
9 | 6 | #include <linux/io.h> |
---|
.. | .. |
---|
116 | 113 | |
---|
117 | 114 | #define TIMING(t0, t1, t2, t3) ((t0) << 24 | (t1) << 16 | (t2) << 8 | (t3)) |
---|
118 | 115 | |
---|
119 | | -static void tango_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) |
---|
| 116 | +static void tango_select_target(struct nand_chip *chip, unsigned int cs) |
---|
120 | 117 | { |
---|
121 | | - struct tango_chip *tchip = to_tango_chip(mtd_to_nand(mtd)); |
---|
122 | | - |
---|
123 | | - if (ctrl & NAND_CLE) |
---|
124 | | - writeb_relaxed(dat, tchip->base + PBUS_CMD); |
---|
125 | | - |
---|
126 | | - if (ctrl & NAND_ALE) |
---|
127 | | - writeb_relaxed(dat, tchip->base + PBUS_ADDR); |
---|
128 | | -} |
---|
129 | | - |
---|
130 | | -static int tango_dev_ready(struct mtd_info *mtd) |
---|
131 | | -{ |
---|
132 | | - struct nand_chip *chip = mtd_to_nand(mtd); |
---|
133 | | - struct tango_nfc *nfc = to_tango_nfc(chip->controller); |
---|
134 | | - |
---|
135 | | - return readl_relaxed(nfc->pbus_base + PBUS_CS_CTRL) & PBUS_IORDY; |
---|
136 | | -} |
---|
137 | | - |
---|
138 | | -static u8 tango_read_byte(struct mtd_info *mtd) |
---|
139 | | -{ |
---|
140 | | - struct tango_chip *tchip = to_tango_chip(mtd_to_nand(mtd)); |
---|
141 | | - |
---|
142 | | - return readb_relaxed(tchip->base + PBUS_DATA); |
---|
143 | | -} |
---|
144 | | - |
---|
145 | | -static void tango_read_buf(struct mtd_info *mtd, u8 *buf, int len) |
---|
146 | | -{ |
---|
147 | | - struct tango_chip *tchip = to_tango_chip(mtd_to_nand(mtd)); |
---|
148 | | - |
---|
149 | | - ioread8_rep(tchip->base + PBUS_DATA, buf, len); |
---|
150 | | -} |
---|
151 | | - |
---|
152 | | -static void tango_write_buf(struct mtd_info *mtd, const u8 *buf, int len) |
---|
153 | | -{ |
---|
154 | | - struct tango_chip *tchip = to_tango_chip(mtd_to_nand(mtd)); |
---|
155 | | - |
---|
156 | | - iowrite8_rep(tchip->base + PBUS_DATA, buf, len); |
---|
157 | | -} |
---|
158 | | - |
---|
159 | | -static void tango_select_chip(struct mtd_info *mtd, int idx) |
---|
160 | | -{ |
---|
161 | | - struct nand_chip *chip = mtd_to_nand(mtd); |
---|
162 | 118 | struct tango_nfc *nfc = to_tango_nfc(chip->controller); |
---|
163 | 119 | struct tango_chip *tchip = to_tango_chip(chip); |
---|
164 | | - |
---|
165 | | - if (idx < 0) |
---|
166 | | - return; /* No "chip unselect" function */ |
---|
167 | 120 | |
---|
168 | 121 | writel_relaxed(tchip->timing1, nfc->reg_base + NFC_TIMING1); |
---|
169 | 122 | writel_relaxed(tchip->timing2, nfc->reg_base + NFC_TIMING2); |
---|
.. | .. |
---|
171 | 124 | writel_relaxed(tchip->pkt_0_cfg, nfc->reg_base + NFC_PKT_0_CFG); |
---|
172 | 125 | writel_relaxed(tchip->pkt_n_cfg, nfc->reg_base + NFC_PKT_N_CFG); |
---|
173 | 126 | writel_relaxed(tchip->bb_cfg, nfc->reg_base + NFC_BB_CFG); |
---|
| 127 | +} |
---|
| 128 | + |
---|
| 129 | +static int tango_waitrdy(struct nand_chip *chip, unsigned int timeout_ms) |
---|
| 130 | +{ |
---|
| 131 | + struct tango_nfc *nfc = to_tango_nfc(chip->controller); |
---|
| 132 | + u32 status; |
---|
| 133 | + |
---|
| 134 | + return readl_relaxed_poll_timeout(nfc->pbus_base + PBUS_CS_CTRL, |
---|
| 135 | + status, status & PBUS_IORDY, 20, |
---|
| 136 | + timeout_ms); |
---|
| 137 | +} |
---|
| 138 | + |
---|
| 139 | +static int tango_exec_instr(struct nand_chip *chip, |
---|
| 140 | + const struct nand_op_instr *instr) |
---|
| 141 | +{ |
---|
| 142 | + struct tango_chip *tchip = to_tango_chip(chip); |
---|
| 143 | + unsigned int i; |
---|
| 144 | + |
---|
| 145 | + switch (instr->type) { |
---|
| 146 | + case NAND_OP_CMD_INSTR: |
---|
| 147 | + writeb_relaxed(instr->ctx.cmd.opcode, tchip->base + PBUS_CMD); |
---|
| 148 | + return 0; |
---|
| 149 | + case NAND_OP_ADDR_INSTR: |
---|
| 150 | + for (i = 0; i < instr->ctx.addr.naddrs; i++) |
---|
| 151 | + writeb_relaxed(instr->ctx.addr.addrs[i], |
---|
| 152 | + tchip->base + PBUS_ADDR); |
---|
| 153 | + return 0; |
---|
| 154 | + case NAND_OP_DATA_IN_INSTR: |
---|
| 155 | + ioread8_rep(tchip->base + PBUS_DATA, instr->ctx.data.buf.in, |
---|
| 156 | + instr->ctx.data.len); |
---|
| 157 | + return 0; |
---|
| 158 | + case NAND_OP_DATA_OUT_INSTR: |
---|
| 159 | + iowrite8_rep(tchip->base + PBUS_DATA, instr->ctx.data.buf.out, |
---|
| 160 | + instr->ctx.data.len); |
---|
| 161 | + return 0; |
---|
| 162 | + case NAND_OP_WAITRDY_INSTR: |
---|
| 163 | + return tango_waitrdy(chip, |
---|
| 164 | + instr->ctx.waitrdy.timeout_ms); |
---|
| 165 | + default: |
---|
| 166 | + break; |
---|
| 167 | + } |
---|
| 168 | + |
---|
| 169 | + return -EINVAL; |
---|
| 170 | +} |
---|
| 171 | + |
---|
| 172 | +static int tango_exec_op(struct nand_chip *chip, |
---|
| 173 | + const struct nand_operation *op, |
---|
| 174 | + bool check_only) |
---|
| 175 | +{ |
---|
| 176 | + unsigned int i; |
---|
| 177 | + int ret = 0; |
---|
| 178 | + |
---|
| 179 | + if (check_only) |
---|
| 180 | + return 0; |
---|
| 181 | + |
---|
| 182 | + tango_select_target(chip, op->cs); |
---|
| 183 | + for (i = 0; i < op->ninstrs; i++) { |
---|
| 184 | + ret = tango_exec_instr(chip, &op->instrs[i]); |
---|
| 185 | + if (ret) |
---|
| 186 | + break; |
---|
| 187 | + } |
---|
| 188 | + |
---|
| 189 | + return ret; |
---|
174 | 190 | } |
---|
175 | 191 | |
---|
176 | 192 | /* |
---|
.. | .. |
---|
277 | 293 | return err; |
---|
278 | 294 | } |
---|
279 | 295 | |
---|
280 | | -static int tango_read_page(struct mtd_info *mtd, struct nand_chip *chip, |
---|
281 | | - u8 *buf, int oob_required, int page) |
---|
| 296 | +static int tango_read_page(struct nand_chip *chip, u8 *buf, |
---|
| 297 | + int oob_required, int page) |
---|
282 | 298 | { |
---|
| 299 | + struct mtd_info *mtd = nand_to_mtd(chip); |
---|
283 | 300 | struct tango_nfc *nfc = to_tango_nfc(chip->controller); |
---|
284 | 301 | int err, res, len = mtd->writesize; |
---|
285 | 302 | |
---|
| 303 | + tango_select_target(chip, chip->cur_cs); |
---|
286 | 304 | if (oob_required) |
---|
287 | | - chip->ecc.read_oob(mtd, chip, page); |
---|
| 305 | + chip->ecc.read_oob(chip, page); |
---|
288 | 306 | |
---|
289 | 307 | err = do_dma(nfc, DMA_FROM_DEVICE, NFC_READ, buf, len, page); |
---|
290 | 308 | if (err) |
---|
.. | .. |
---|
292 | 310 | |
---|
293 | 311 | res = decode_error_report(chip); |
---|
294 | 312 | if (res < 0) { |
---|
295 | | - chip->ecc.read_oob_raw(mtd, chip, page); |
---|
| 313 | + chip->ecc.read_oob_raw(chip, page); |
---|
296 | 314 | res = check_erased_page(chip, buf); |
---|
297 | 315 | } |
---|
298 | 316 | |
---|
299 | 317 | return res; |
---|
300 | 318 | } |
---|
301 | 319 | |
---|
302 | | -static int tango_write_page(struct mtd_info *mtd, struct nand_chip *chip, |
---|
303 | | - const u8 *buf, int oob_required, int page) |
---|
| 320 | +static int tango_write_page(struct nand_chip *chip, const u8 *buf, |
---|
| 321 | + int oob_required, int page) |
---|
304 | 322 | { |
---|
| 323 | + struct mtd_info *mtd = nand_to_mtd(chip); |
---|
305 | 324 | struct tango_nfc *nfc = to_tango_nfc(chip->controller); |
---|
306 | | - int err, status, len = mtd->writesize; |
---|
| 325 | + const struct nand_sdr_timings *timings; |
---|
| 326 | + int err, len = mtd->writesize; |
---|
| 327 | + u8 status; |
---|
307 | 328 | |
---|
308 | 329 | /* Calling tango_write_oob() would send PAGEPROG twice */ |
---|
309 | 330 | if (oob_required) |
---|
310 | 331 | return -ENOTSUPP; |
---|
311 | 332 | |
---|
| 333 | + tango_select_target(chip, chip->cur_cs); |
---|
312 | 334 | writel_relaxed(0xffffffff, nfc->mem_base + METADATA); |
---|
313 | 335 | err = do_dma(nfc, DMA_TO_DEVICE, NFC_WRITE, buf, len, page); |
---|
314 | 336 | if (err) |
---|
315 | 337 | return err; |
---|
316 | 338 | |
---|
317 | | - status = chip->waitfunc(mtd, chip); |
---|
318 | | - if (status & NAND_STATUS_FAIL) |
---|
319 | | - return -EIO; |
---|
| 339 | + timings = nand_get_sdr_timings(nand_get_interface_config(chip)); |
---|
| 340 | + err = tango_waitrdy(chip, PSEC_TO_MSEC(timings->tR_max)); |
---|
| 341 | + if (err) |
---|
| 342 | + return err; |
---|
320 | 343 | |
---|
321 | | - return 0; |
---|
| 344 | + err = nand_status_op(chip, &status); |
---|
| 345 | + if (err) |
---|
| 346 | + return err; |
---|
| 347 | + |
---|
| 348 | + return (status & NAND_STATUS_FAIL) ? -EIO : 0; |
---|
322 | 349 | } |
---|
323 | 350 | |
---|
324 | 351 | static void aux_read(struct nand_chip *chip, u8 **buf, int len, int *pos) |
---|
325 | 352 | { |
---|
326 | | - struct mtd_info *mtd = nand_to_mtd(chip); |
---|
327 | | - |
---|
328 | 353 | *pos += len; |
---|
329 | 354 | |
---|
330 | 355 | if (!*buf) { |
---|
331 | 356 | /* skip over "len" bytes */ |
---|
332 | 357 | nand_change_read_column_op(chip, *pos, NULL, 0, false); |
---|
333 | 358 | } else { |
---|
334 | | - tango_read_buf(mtd, *buf, len); |
---|
| 359 | + struct tango_chip *tchip = to_tango_chip(chip); |
---|
| 360 | + |
---|
| 361 | + ioread8_rep(tchip->base + PBUS_DATA, *buf, len); |
---|
335 | 362 | *buf += len; |
---|
336 | 363 | } |
---|
337 | 364 | } |
---|
338 | 365 | |
---|
339 | 366 | static void aux_write(struct nand_chip *chip, const u8 **buf, int len, int *pos) |
---|
340 | 367 | { |
---|
341 | | - struct mtd_info *mtd = nand_to_mtd(chip); |
---|
342 | | - |
---|
343 | 368 | *pos += len; |
---|
344 | 369 | |
---|
345 | 370 | if (!*buf) { |
---|
346 | 371 | /* skip over "len" bytes */ |
---|
347 | 372 | nand_change_write_column_op(chip, *pos, NULL, 0, false); |
---|
348 | 373 | } else { |
---|
349 | | - tango_write_buf(mtd, *buf, len); |
---|
| 374 | + struct tango_chip *tchip = to_tango_chip(chip); |
---|
| 375 | + |
---|
| 376 | + iowrite8_rep(tchip->base + PBUS_DATA, *buf, len); |
---|
350 | 377 | *buf += len; |
---|
351 | 378 | } |
---|
352 | 379 | } |
---|
.. | .. |
---|
424 | 451 | aux_write(chip, &oob, ecc_size, &pos); |
---|
425 | 452 | } |
---|
426 | 453 | |
---|
427 | | -static int tango_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, |
---|
428 | | - u8 *buf, int oob_required, int page) |
---|
| 454 | +static int tango_read_page_raw(struct nand_chip *chip, u8 *buf, |
---|
| 455 | + int oob_required, int page) |
---|
429 | 456 | { |
---|
| 457 | + tango_select_target(chip, chip->cur_cs); |
---|
430 | 458 | nand_read_page_op(chip, page, 0, NULL, 0); |
---|
431 | 459 | raw_read(chip, buf, chip->oob_poi); |
---|
432 | 460 | return 0; |
---|
433 | 461 | } |
---|
434 | 462 | |
---|
435 | | -static int tango_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, |
---|
436 | | - const u8 *buf, int oob_required, int page) |
---|
| 463 | +static int tango_write_page_raw(struct nand_chip *chip, const u8 *buf, |
---|
| 464 | + int oob_required, int page) |
---|
437 | 465 | { |
---|
| 466 | + tango_select_target(chip, chip->cur_cs); |
---|
438 | 467 | nand_prog_page_begin_op(chip, page, 0, NULL, 0); |
---|
439 | 468 | raw_write(chip, buf, chip->oob_poi); |
---|
440 | 469 | return nand_prog_page_end_op(chip); |
---|
441 | 470 | } |
---|
442 | 471 | |
---|
443 | | -static int tango_read_oob(struct mtd_info *mtd, struct nand_chip *chip, |
---|
444 | | - int page) |
---|
| 472 | +static int tango_read_oob(struct nand_chip *chip, int page) |
---|
445 | 473 | { |
---|
| 474 | + tango_select_target(chip, chip->cur_cs); |
---|
446 | 475 | nand_read_page_op(chip, page, 0, NULL, 0); |
---|
447 | 476 | raw_read(chip, NULL, chip->oob_poi); |
---|
448 | 477 | return 0; |
---|
449 | 478 | } |
---|
450 | 479 | |
---|
451 | | -static int tango_write_oob(struct mtd_info *mtd, struct nand_chip *chip, |
---|
452 | | - int page) |
---|
| 480 | +static int tango_write_oob(struct nand_chip *chip, int page) |
---|
453 | 481 | { |
---|
| 482 | + tango_select_target(chip, chip->cur_cs); |
---|
454 | 483 | nand_prog_page_begin_op(chip, page, 0, NULL, 0); |
---|
455 | 484 | raw_write(chip, NULL, chip->oob_poi); |
---|
456 | 485 | return nand_prog_page_end_op(chip); |
---|
.. | .. |
---|
485 | 514 | return DIV_ROUND_UP_ULL((u64)kHz * ps, NSEC_PER_SEC); |
---|
486 | 515 | } |
---|
487 | 516 | |
---|
488 | | -static int tango_set_timings(struct mtd_info *mtd, int csline, |
---|
489 | | - const struct nand_data_interface *conf) |
---|
| 517 | +static int tango_set_timings(struct nand_chip *chip, int csline, |
---|
| 518 | + const struct nand_interface_config *conf) |
---|
490 | 519 | { |
---|
491 | 520 | const struct nand_sdr_timings *sdr = nand_get_sdr_timings(conf); |
---|
492 | | - struct nand_chip *chip = mtd_to_nand(mtd); |
---|
493 | 521 | struct tango_nfc *nfc = to_tango_nfc(chip->controller); |
---|
494 | 522 | struct tango_chip *tchip = to_tango_chip(chip); |
---|
495 | 523 | u32 Trdy, Textw, Twc, Twpw, Tacc, Thold, Trpw, Textr; |
---|
.. | .. |
---|
521 | 549 | { |
---|
522 | 550 | struct nand_ecc_ctrl *ecc = &chip->ecc; |
---|
523 | 551 | |
---|
524 | | - ecc->mode = NAND_ECC_HW; |
---|
525 | | - ecc->algo = NAND_ECC_BCH; |
---|
| 552 | + ecc->engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; |
---|
| 553 | + ecc->algo = NAND_ECC_ALGO_BCH; |
---|
526 | 554 | ecc->bytes = DIV_ROUND_UP(ecc->strength * FIELD_ORDER, BITS_PER_BYTE); |
---|
527 | 555 | |
---|
528 | 556 | ecc->read_page_raw = tango_read_page_raw; |
---|
.. | .. |
---|
537 | 565 | |
---|
538 | 566 | static const struct nand_controller_ops tango_controller_ops = { |
---|
539 | 567 | .attach_chip = tango_attach_chip, |
---|
| 568 | + .setup_interface = tango_set_timings, |
---|
| 569 | + .exec_op = tango_exec_op, |
---|
540 | 570 | }; |
---|
541 | 571 | |
---|
542 | 572 | static int chip_init(struct device *dev, struct device_node *np) |
---|
.. | .. |
---|
571 | 601 | ecc = &chip->ecc; |
---|
572 | 602 | mtd = nand_to_mtd(chip); |
---|
573 | 603 | |
---|
574 | | - chip->read_byte = tango_read_byte; |
---|
575 | | - chip->write_buf = tango_write_buf; |
---|
576 | | - chip->read_buf = tango_read_buf; |
---|
577 | | - chip->select_chip = tango_select_chip; |
---|
578 | | - chip->cmd_ctrl = tango_cmd_ctrl; |
---|
579 | | - chip->dev_ready = tango_dev_ready; |
---|
580 | | - chip->setup_data_interface = tango_set_timings; |
---|
581 | | - chip->options = NAND_USE_BOUNCE_BUFFER | |
---|
| 604 | + chip->options = NAND_USES_DMA | |
---|
582 | 605 | NAND_NO_SUBPAGE_WRITE | |
---|
583 | 606 | NAND_WAIT_TCCS; |
---|
584 | 607 | chip->controller = &nfc->hw; |
---|
.. | .. |
---|
610 | 633 | |
---|
611 | 634 | static int tango_nand_remove(struct platform_device *pdev) |
---|
612 | 635 | { |
---|
613 | | - int cs; |
---|
614 | 636 | struct tango_nfc *nfc = platform_get_drvdata(pdev); |
---|
| 637 | + struct nand_chip *chip; |
---|
| 638 | + int cs, ret; |
---|
615 | 639 | |
---|
616 | 640 | dma_release_channel(nfc->chan); |
---|
617 | 641 | |
---|
618 | 642 | for (cs = 0; cs < MAX_CS; ++cs) { |
---|
619 | | - if (nfc->chips[cs]) |
---|
620 | | - nand_release(&nfc->chips[cs]->nand_chip); |
---|
| 643 | + if (nfc->chips[cs]) { |
---|
| 644 | + chip = &nfc->chips[cs]->nand_chip; |
---|
| 645 | + ret = mtd_device_unregister(nand_to_mtd(chip)); |
---|
| 646 | + WARN_ON(ret); |
---|
| 647 | + nand_cleanup(chip); |
---|
| 648 | + } |
---|
621 | 649 | } |
---|
622 | 650 | |
---|
623 | 651 | return 0; |
---|
.. | .. |
---|
669 | 697 | err = chip_init(&pdev->dev, np); |
---|
670 | 698 | if (err) { |
---|
671 | 699 | tango_nand_remove(pdev); |
---|
| 700 | + of_node_put(np); |
---|
672 | 701 | return err; |
---|
673 | 702 | } |
---|
674 | 703 | } |
---|