Lines Matching +full:host +full:- +full:command
1 // SPDX-License-Identifier: GPL-2.0-or-later
5 * Copyright © 2012-2014 HiSilicon Technologies Co., Ltd.
21 #include <linux/dma-mapping.h>
132 unsigned int command; member
144 static inline unsigned int hinfc_read(struct hinfc_host *host, unsigned int reg) in hinfc_read() argument
146 return readl(host->iobase + reg); in hinfc_read()
149 static inline void hinfc_write(struct hinfc_host *host, unsigned int value, in hinfc_write() argument
152 writel(value, host->iobase + reg); in hinfc_write()
155 static void wait_controller_finished(struct hinfc_host *host) in wait_controller_finished() argument
161 val = hinfc_read(host, HINFC504_STATUS); in wait_controller_finished()
162 if (host->command == NAND_CMD_ERASE2) { in wait_controller_finished()
166 val = hinfc_read(host, HINFC504_STATUS); in wait_controller_finished()
176 dev_err(host->dev, "Wait NAND controller exec cmd timeout.\n"); in wait_controller_finished()
179 static void hisi_nfc_dma_transfer(struct hinfc_host *host, int todev) in hisi_nfc_dma_transfer() argument
181 struct nand_chip *chip = &host->chip; in hisi_nfc_dma_transfer()
186 hinfc_write(host, host->dma_buffer, HINFC504_DMA_ADDR_DATA); in hisi_nfc_dma_transfer()
187 hinfc_write(host, host->dma_oob, HINFC504_DMA_ADDR_OOB); in hisi_nfc_dma_transfer()
189 if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_NONE) { in hisi_nfc_dma_transfer()
190 hinfc_write(host, ((mtd->oobsize & HINFC504_DMA_LEN_OOB_MASK) in hisi_nfc_dma_transfer()
193 hinfc_write(host, HINFC504_DMA_PARA_DATA_RW_EN in hisi_nfc_dma_transfer()
196 if (host->command == NAND_CMD_READOOB) in hisi_nfc_dma_transfer()
197 hinfc_write(host, HINFC504_DMA_PARA_OOB_RW_EN in hisi_nfc_dma_transfer()
201 hinfc_write(host, HINFC504_DMA_PARA_DATA_RW_EN in hisi_nfc_dma_transfer()
213 | ((host->addr_cycle == 4 ? 1 : 0) in hisi_nfc_dma_transfer()
215 | ((host->chipselect & HINFC504_DMA_CTRL_CS_MASK) in hisi_nfc_dma_transfer()
221 init_completion(&host->cmd_complete); in hisi_nfc_dma_transfer()
223 hinfc_write(host, val, HINFC504_DMA_CTRL); in hisi_nfc_dma_transfer()
224 ret = wait_for_completion_timeout(&host->cmd_complete, in hisi_nfc_dma_transfer()
228 dev_err(host->dev, "DMA operation(irq) timeout!\n"); in hisi_nfc_dma_transfer()
230 val = hinfc_read(host, HINFC504_DMA_CTRL); in hisi_nfc_dma_transfer()
232 dev_err(host->dev, "DMA is already done but without irq ACK!\n"); in hisi_nfc_dma_transfer()
234 dev_err(host->dev, "DMA is really timeout!\n"); in hisi_nfc_dma_transfer()
238 static int hisi_nfc_send_cmd_pageprog(struct hinfc_host *host) in hisi_nfc_send_cmd_pageprog() argument
240 host->addr_value[0] &= 0xffff0000; in hisi_nfc_send_cmd_pageprog()
242 hinfc_write(host, host->addr_value[0], HINFC504_ADDRL); in hisi_nfc_send_cmd_pageprog()
243 hinfc_write(host, host->addr_value[1], HINFC504_ADDRH); in hisi_nfc_send_cmd_pageprog()
244 hinfc_write(host, NAND_CMD_PAGEPROG << 8 | NAND_CMD_SEQIN, in hisi_nfc_send_cmd_pageprog()
247 hisi_nfc_dma_transfer(host, 1); in hisi_nfc_send_cmd_pageprog()
252 static int hisi_nfc_send_cmd_readstart(struct hinfc_host *host) in hisi_nfc_send_cmd_readstart() argument
254 struct mtd_info *mtd = nand_to_mtd(&host->chip); in hisi_nfc_send_cmd_readstart()
256 if ((host->addr_value[0] == host->cache_addr_value[0]) && in hisi_nfc_send_cmd_readstart()
257 (host->addr_value[1] == host->cache_addr_value[1])) in hisi_nfc_send_cmd_readstart()
260 host->addr_value[0] &= 0xffff0000; in hisi_nfc_send_cmd_readstart()
262 hinfc_write(host, host->addr_value[0], HINFC504_ADDRL); in hisi_nfc_send_cmd_readstart()
263 hinfc_write(host, host->addr_value[1], HINFC504_ADDRH); in hisi_nfc_send_cmd_readstart()
264 hinfc_write(host, NAND_CMD_READSTART << 8 | NAND_CMD_READ0, in hisi_nfc_send_cmd_readstart()
267 hinfc_write(host, 0, HINFC504_LOG_READ_ADDR); in hisi_nfc_send_cmd_readstart()
268 hinfc_write(host, mtd->writesize + mtd->oobsize, in hisi_nfc_send_cmd_readstart()
271 hisi_nfc_dma_transfer(host, 0); in hisi_nfc_send_cmd_readstart()
273 host->cache_addr_value[0] = host->addr_value[0]; in hisi_nfc_send_cmd_readstart()
274 host->cache_addr_value[1] = host->addr_value[1]; in hisi_nfc_send_cmd_readstart()
279 static int hisi_nfc_send_cmd_erase(struct hinfc_host *host) in hisi_nfc_send_cmd_erase() argument
281 hinfc_write(host, host->addr_value[0], HINFC504_ADDRL); in hisi_nfc_send_cmd_erase()
282 hinfc_write(host, (NAND_CMD_ERASE2 << 8) | NAND_CMD_ERASE1, in hisi_nfc_send_cmd_erase()
285 hinfc_write(host, HINFC504_OP_WAIT_READY_EN in hisi_nfc_send_cmd_erase()
289 | ((host->chipselect & HINFC504_OP_NF_CS_MASK) in hisi_nfc_send_cmd_erase()
291 | ((host->addr_cycle & HINFC504_OP_ADDR_CYCLE_MASK) in hisi_nfc_send_cmd_erase()
295 wait_controller_finished(host); in hisi_nfc_send_cmd_erase()
300 static int hisi_nfc_send_cmd_readid(struct hinfc_host *host) in hisi_nfc_send_cmd_readid() argument
302 hinfc_write(host, HINFC504_NANDINFO_LEN, HINFC504_DATA_NUM); in hisi_nfc_send_cmd_readid()
303 hinfc_write(host, NAND_CMD_READID, HINFC504_CMD); in hisi_nfc_send_cmd_readid()
304 hinfc_write(host, 0, HINFC504_ADDRL); in hisi_nfc_send_cmd_readid()
306 hinfc_write(host, HINFC504_OP_CMD1_EN | HINFC504_OP_ADDR_EN in hisi_nfc_send_cmd_readid()
308 | ((host->chipselect & HINFC504_OP_NF_CS_MASK) in hisi_nfc_send_cmd_readid()
312 wait_controller_finished(host); in hisi_nfc_send_cmd_readid()
317 static int hisi_nfc_send_cmd_status(struct hinfc_host *host) in hisi_nfc_send_cmd_status() argument
319 hinfc_write(host, HINFC504_NANDINFO_LEN, HINFC504_DATA_NUM); in hisi_nfc_send_cmd_status()
320 hinfc_write(host, NAND_CMD_STATUS, HINFC504_CMD); in hisi_nfc_send_cmd_status()
321 hinfc_write(host, HINFC504_OP_CMD1_EN in hisi_nfc_send_cmd_status()
323 | ((host->chipselect & HINFC504_OP_NF_CS_MASK) in hisi_nfc_send_cmd_status()
327 wait_controller_finished(host); in hisi_nfc_send_cmd_status()
332 static int hisi_nfc_send_cmd_reset(struct hinfc_host *host, int chipselect) in hisi_nfc_send_cmd_reset() argument
334 hinfc_write(host, NAND_CMD_RESET, HINFC504_CMD); in hisi_nfc_send_cmd_reset()
336 hinfc_write(host, HINFC504_OP_CMD1_EN in hisi_nfc_send_cmd_reset()
342 wait_controller_finished(host); in hisi_nfc_send_cmd_reset()
349 struct hinfc_host *host = nand_get_controller_data(chip); in hisi_nfc_select_chip() local
354 host->chipselect = chipselect; in hisi_nfc_select_chip()
359 struct hinfc_host *host = nand_get_controller_data(chip); in hisi_nfc_read_byte() local
361 if (host->command == NAND_CMD_STATUS) in hisi_nfc_read_byte()
362 return *(uint8_t *)(host->mmio); in hisi_nfc_read_byte()
364 host->offset++; in hisi_nfc_read_byte()
366 if (host->command == NAND_CMD_READID) in hisi_nfc_read_byte()
367 return *(uint8_t *)(host->mmio + host->offset - 1); in hisi_nfc_read_byte()
369 return *(uint8_t *)(host->buffer + host->offset - 1); in hisi_nfc_read_byte()
375 struct hinfc_host *host = nand_get_controller_data(chip); in hisi_nfc_write_buf() local
377 memcpy(host->buffer + host->offset, buf, len); in hisi_nfc_write_buf()
378 host->offset += len; in hisi_nfc_write_buf()
383 struct hinfc_host *host = nand_get_controller_data(chip); in hisi_nfc_read_buf() local
385 memcpy(buf, host->buffer + host->offset, len); in hisi_nfc_read_buf()
386 host->offset += len; in hisi_nfc_read_buf()
392 struct hinfc_host *host = nand_get_controller_data(chip); in set_addr() local
393 unsigned int command = host->command; in set_addr() local
395 host->addr_cycle = 0; in set_addr()
396 host->addr_value[0] = 0; in set_addr()
397 host->addr_value[1] = 0; in set_addr()
400 if (column != -1) { in set_addr()
402 if (chip->options & NAND_BUSWIDTH_16 && in set_addr()
403 !nand_opcode_8bits(command)) in set_addr()
406 host->addr_value[0] = column & 0xffff; in set_addr()
407 host->addr_cycle = 2; in set_addr()
409 if (page_addr != -1) { in set_addr()
410 host->addr_value[0] |= (page_addr & 0xffff) in set_addr()
411 << (host->addr_cycle * 8); in set_addr()
412 host->addr_cycle += 2; in set_addr()
413 if (chip->options & NAND_ROW_ADDR_3) { in set_addr()
414 host->addr_cycle += 1; in set_addr()
415 if (host->command == NAND_CMD_ERASE1) in set_addr()
416 host->addr_value[0] |= ((page_addr >> 16) & 0xff) << 16; in set_addr()
418 host->addr_value[1] |= ((page_addr >> 16) & 0xff); in set_addr()
423 static void hisi_nfc_cmdfunc(struct nand_chip *chip, unsigned command, in hisi_nfc_cmdfunc() argument
427 struct hinfc_host *host = nand_get_controller_data(chip); in hisi_nfc_cmdfunc() local
431 host->command = command; in hisi_nfc_cmdfunc()
433 switch (command) { in hisi_nfc_cmdfunc()
436 if (command == NAND_CMD_READ0) in hisi_nfc_cmdfunc()
437 host->offset = column; in hisi_nfc_cmdfunc()
439 host->offset = column + mtd->writesize; in hisi_nfc_cmdfunc()
443 hisi_nfc_send_cmd_readstart(host); in hisi_nfc_cmdfunc()
447 host->offset = column; in hisi_nfc_cmdfunc()
456 hisi_nfc_send_cmd_pageprog(host); in hisi_nfc_cmdfunc()
460 hisi_nfc_send_cmd_erase(host); in hisi_nfc_cmdfunc()
464 host->offset = column; in hisi_nfc_cmdfunc()
465 memset(host->mmio, 0, 0x10); in hisi_nfc_cmdfunc()
466 hisi_nfc_send_cmd_readid(host); in hisi_nfc_cmdfunc()
470 flag = hinfc_read(host, HINFC504_CON); in hisi_nfc_cmdfunc()
471 if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_ON_HOST) in hisi_nfc_cmdfunc()
472 hinfc_write(host, in hisi_nfc_cmdfunc()
476 host->offset = 0; in hisi_nfc_cmdfunc()
477 memset(host->mmio, 0, 0x10); in hisi_nfc_cmdfunc()
478 hisi_nfc_send_cmd_status(host); in hisi_nfc_cmdfunc()
479 hinfc_write(host, flag, HINFC504_CON); in hisi_nfc_cmdfunc()
483 hisi_nfc_send_cmd_reset(host, host->chipselect); in hisi_nfc_cmdfunc()
487 dev_err(host->dev, "Error: unsupported cmd(cmd=%x, col=%x, page=%x)\n", in hisi_nfc_cmdfunc()
488 command, column, page_addr); in hisi_nfc_cmdfunc()
492 host->cache_addr_value[0] = ~0; in hisi_nfc_cmdfunc()
493 host->cache_addr_value[1] = ~0; in hisi_nfc_cmdfunc()
499 struct hinfc_host *host = devid; in hinfc_irq_handle() local
502 flag = hinfc_read(host, HINFC504_INTS); in hinfc_irq_handle()
504 host->irq_status |= flag; in hinfc_irq_handle()
507 hinfc_write(host, HINFC504_INTCLR_DMA, HINFC504_INTCLR); in hinfc_irq_handle()
508 complete(&host->cmd_complete); in hinfc_irq_handle()
510 hinfc_write(host, HINFC504_INTCLR_CE, HINFC504_INTCLR); in hinfc_irq_handle()
512 hinfc_write(host, HINFC504_INTCLR_UE, HINFC504_INTCLR); in hinfc_irq_handle()
522 struct hinfc_host *host = nand_get_controller_data(chip); in hisi_nand_read_page_hwecc() local
526 nand_read_page_op(chip, page, 0, buf, mtd->writesize); in hisi_nand_read_page_hwecc()
527 chip->legacy.read_buf(chip, chip->oob_poi, mtd->oobsize); in hisi_nand_read_page_hwecc()
530 if (host->irq_status & HINFC504_INTS_UE) { in hisi_nand_read_page_hwecc()
531 mtd->ecc_stats.failed++; in hisi_nand_read_page_hwecc()
532 } else if (host->irq_status & HINFC504_INTS_CE) { in hisi_nand_read_page_hwecc()
534 switch (chip->ecc.strength) { in hisi_nand_read_page_hwecc()
536 status_ecc = hinfc_read(host, HINFC504_ECC_STATUS) >> in hisi_nand_read_page_hwecc()
543 mtd->ecc_stats.corrected += stat; in hisi_nand_read_page_hwecc()
546 host->irq_status = 0; in hisi_nand_read_page_hwecc()
554 struct hinfc_host *host = nand_get_controller_data(chip); in hisi_nand_read_oob() local
556 nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize); in hisi_nand_read_oob()
558 if (host->irq_status & HINFC504_INTS_UE) { in hisi_nand_read_oob()
559 host->irq_status = 0; in hisi_nand_read_oob()
560 return -EBADMSG; in hisi_nand_read_oob()
563 host->irq_status = 0; in hisi_nand_read_oob()
573 nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize); in hisi_nand_write_page_hwecc()
575 chip->legacy.write_buf(chip, chip->oob_poi, mtd->oobsize); in hisi_nand_write_page_hwecc()
580 static void hisi_nfc_host_init(struct hinfc_host *host) in hisi_nfc_host_init() argument
582 struct nand_chip *chip = &host->chip; in hisi_nfc_host_init()
585 host->version = hinfc_read(host, HINFC_VERSION); in hisi_nfc_host_init()
586 host->addr_cycle = 0; in hisi_nfc_host_init()
587 host->addr_value[0] = 0; in hisi_nfc_host_init()
588 host->addr_value[1] = 0; in hisi_nfc_host_init()
589 host->cache_addr_value[0] = ~0; in hisi_nfc_host_init()
590 host->cache_addr_value[1] = ~0; in hisi_nfc_host_init()
591 host->chipselect = 0; in hisi_nfc_host_init()
599 | ((chip->options & NAND_BUSWIDTH_16) ? in hisi_nfc_host_init()
601 hinfc_write(host, flag, HINFC504_CON); in hisi_nfc_host_init()
603 memset(host->mmio, 0xff, HINFC504_BUFFER_BASE_ADDRESS_LEN); in hisi_nfc_host_init()
605 hinfc_write(host, SET_HINFC504_PWIDTH(HINFC504_W_LATCH, in hisi_nfc_host_init()
609 hinfc_write(host, HINFC504_INTEN_DMA, HINFC504_INTEN); in hisi_nfc_host_init()
616 return -ENOTSUPP; in hisi_ooblayout_ecc()
623 return -ERANGE; in hisi_ooblayout_free()
625 oobregion->offset = 2; in hisi_ooblayout_free()
626 oobregion->length = 6; in hisi_ooblayout_free()
636 static int hisi_nfc_ecc_probe(struct hinfc_host *host) in hisi_nfc_ecc_probe() argument
640 struct device *dev = host->dev; in hisi_nfc_ecc_probe()
641 struct nand_chip *chip = &host->chip; in hisi_nfc_ecc_probe()
644 size = chip->ecc.size; in hisi_nfc_ecc_probe()
645 strength = chip->ecc.strength; in hisi_nfc_ecc_probe()
648 return -EINVAL; in hisi_nfc_ecc_probe()
654 return -EINVAL; in hisi_nfc_ecc_probe()
657 chip->ecc.size = size; in hisi_nfc_ecc_probe()
658 chip->ecc.strength = strength; in hisi_nfc_ecc_probe()
660 chip->ecc.read_page = hisi_nand_read_page_hwecc; in hisi_nfc_ecc_probe()
661 chip->ecc.read_oob = hisi_nand_read_oob; in hisi_nfc_ecc_probe()
662 chip->ecc.write_page = hisi_nand_write_page_hwecc; in hisi_nfc_ecc_probe()
664 switch (chip->ecc.strength) { in hisi_nfc_ecc_probe()
667 if (mtd->writesize == 2048) in hisi_nfc_ecc_probe()
675 dev_err(dev, "not support strength: %d\n", chip->ecc.strength); in hisi_nfc_ecc_probe()
676 return -EINVAL; in hisi_nfc_ecc_probe()
679 flag = hinfc_read(host, HINFC504_CON); in hisi_nfc_ecc_probe()
683 hinfc_write(host, flag, HINFC504_CON); in hisi_nfc_ecc_probe()
686 flag = hinfc_read(host, HINFC504_INTEN) & 0xfff; in hisi_nfc_ecc_probe()
687 hinfc_write(host, flag | HINFC504_INTEN_UE | HINFC504_INTEN_CE, in hisi_nfc_ecc_probe()
696 struct hinfc_host *host = nand_get_controller_data(chip); in hisi_nfc_attach_chip() local
699 host->buffer = dmam_alloc_coherent(host->dev, in hisi_nfc_attach_chip()
700 mtd->writesize + mtd->oobsize, in hisi_nfc_attach_chip()
701 &host->dma_buffer, GFP_KERNEL); in hisi_nfc_attach_chip()
702 if (!host->buffer) in hisi_nfc_attach_chip()
703 return -ENOMEM; in hisi_nfc_attach_chip()
705 host->dma_oob = host->dma_buffer + mtd->writesize; in hisi_nfc_attach_chip()
706 memset(host->buffer, 0xff, mtd->writesize + mtd->oobsize); in hisi_nfc_attach_chip()
708 flag = hinfc_read(host, HINFC504_CON); in hisi_nfc_attach_chip()
710 switch (mtd->writesize) { in hisi_nfc_attach_chip()
719 dev_err(host->dev, "NON-2KB page size nand flash\n"); in hisi_nfc_attach_chip()
720 return -EINVAL; in hisi_nfc_attach_chip()
722 hinfc_write(host, flag, HINFC504_CON); in hisi_nfc_attach_chip()
724 if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_ON_HOST) in hisi_nfc_attach_chip()
725 hisi_nfc_ecc_probe(host); in hisi_nfc_attach_chip()
737 struct device *dev = &pdev->dev; in hisi_nfc_probe()
738 struct hinfc_host *host; in hisi_nfc_probe() local
741 struct device_node *np = dev->of_node; in hisi_nfc_probe()
743 host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL); in hisi_nfc_probe()
744 if (!host) in hisi_nfc_probe()
745 return -ENOMEM; in hisi_nfc_probe()
746 host->dev = dev; in hisi_nfc_probe()
748 platform_set_drvdata(pdev, host); in hisi_nfc_probe()
749 chip = &host->chip; in hisi_nfc_probe()
754 return -ENXIO; in hisi_nfc_probe()
756 host->iobase = devm_platform_ioremap_resource(pdev, 0); in hisi_nfc_probe()
757 if (IS_ERR(host->iobase)) in hisi_nfc_probe()
758 return PTR_ERR(host->iobase); in hisi_nfc_probe()
760 host->mmio = devm_platform_ioremap_resource(pdev, 1); in hisi_nfc_probe()
761 if (IS_ERR(host->mmio)) in hisi_nfc_probe()
762 return PTR_ERR(host->mmio); in hisi_nfc_probe()
764 mtd->name = "hisi_nand"; in hisi_nfc_probe()
765 mtd->dev.parent = &pdev->dev; in hisi_nfc_probe()
767 nand_set_controller_data(chip, host); in hisi_nfc_probe()
769 chip->legacy.cmdfunc = hisi_nfc_cmdfunc; in hisi_nfc_probe()
770 chip->legacy.select_chip = hisi_nfc_select_chip; in hisi_nfc_probe()
771 chip->legacy.read_byte = hisi_nfc_read_byte; in hisi_nfc_probe()
772 chip->legacy.write_buf = hisi_nfc_write_buf; in hisi_nfc_probe()
773 chip->legacy.read_buf = hisi_nfc_read_buf; in hisi_nfc_probe()
774 chip->legacy.chip_delay = HINFC504_CHIP_DELAY; in hisi_nfc_probe()
775 chip->legacy.set_features = nand_get_set_features_notsupp; in hisi_nfc_probe()
776 chip->legacy.get_features = nand_get_set_features_notsupp; in hisi_nfc_probe()
778 hisi_nfc_host_init(host); in hisi_nfc_probe()
780 ret = devm_request_irq(dev, irq, hinfc_irq_handle, 0x0, "nandc", host); in hisi_nfc_probe()
786 chip->legacy.dummy_controller.ops = &hisi_nfc_controller_ops; in hisi_nfc_probe()
803 struct hinfc_host *host = platform_get_drvdata(pdev); in hisi_nfc_remove() local
804 struct nand_chip *chip = &host->chip; in hisi_nfc_remove()
815 struct hinfc_host *host = dev_get_drvdata(dev); in hisi_nfc_suspend() local
819 if (((hinfc_read(host, HINFC504_STATUS) & 0x1) == 0x0) && in hisi_nfc_suspend()
820 (hinfc_read(host, HINFC504_DMA_CTRL) & in hisi_nfc_suspend()
827 dev_err(host->dev, "nand controller suspend timeout.\n"); in hisi_nfc_suspend()
829 return -EAGAIN; in hisi_nfc_suspend()
835 struct hinfc_host *host = dev_get_drvdata(dev); in hisi_nfc_resume() local
836 struct nand_chip *chip = &host->chip; in hisi_nfc_resume()
838 for (cs = 0; cs < nanddev_ntargets(&chip->base); cs++) in hisi_nfc_resume()
839 hisi_nfc_send_cmd_reset(host, cs); in hisi_nfc_resume()
840 hinfc_write(host, SET_HINFC504_PWIDTH(HINFC504_W_LATCH, in hisi_nfc_resume()
849 { .compatible = "hisilicon,504-nfc" },