1212#include <linux/io.h>
1313#include <linux/iopoll.h>
1414#include <linux/module.h>
15+ #include <linux/mtd/nand.h>
16+ #include <linux/mtd/nand-ecc-mxic.h>
1517#include <linux/platform_device.h>
1618#include <linux/pm_runtime.h>
1719#include <linux/spi/spi.h>
167169#define HW_TEST (x ) (0xe0 + ((x) * 4))
168170
169171struct mxic_spi {
172+ struct device * dev ;
170173 struct clk * ps_clk ;
171174 struct clk * send_clk ;
172175 struct clk * send_dly_clk ;
@@ -177,6 +180,12 @@ struct mxic_spi {
177180 dma_addr_t dma ;
178181 size_t size ;
179182 } linear ;
183+
184+ struct {
185+ bool use_pipelined_conf ;
186+ struct nand_ecc_engine * pipelined_engine ;
187+ void * ctx ;
188+ } ecc ;
180189};
181190
182191static int mxic_spi_clk_enable (struct mxic_spi * mxic )
@@ -400,7 +409,15 @@ static ssize_t mxic_spi_mem_dirmap_read(struct spi_mem_dirmap_desc *desc,
400409 LMODE_EN ,
401410 mxic -> regs + LRD_CTRL );
402411
403- memcpy_fromio (buf , mxic -> linear .map , len );
412+ if (mxic -> ecc .use_pipelined_conf && desc -> info .op_tmpl .data .ecc ) {
413+ ret = mxic_ecc_process_data_pipelined (mxic -> ecc .pipelined_engine ,
414+ NAND_PAGE_READ ,
415+ mxic -> linear .dma + offs );
416+ if (ret )
417+ return ret ;
418+ } else {
419+ memcpy_fromio (buf , mxic -> linear .map , len );
420+ }
404421
405422 writel (INT_LRD_DIS , mxic -> regs + INT_STS );
406423 writel (0 , mxic -> regs + LRD_CTRL );
@@ -436,7 +453,15 @@ static ssize_t mxic_spi_mem_dirmap_write(struct spi_mem_dirmap_desc *desc,
436453 LMODE_EN ,
437454 mxic -> regs + LWR_CTRL );
438455
439- memcpy_toio (mxic -> linear .map , buf , len );
456+ if (mxic -> ecc .use_pipelined_conf && desc -> info .op_tmpl .data .ecc ) {
457+ ret = mxic_ecc_process_data_pipelined (mxic -> ecc .pipelined_engine ,
458+ NAND_PAGE_WRITE ,
459+ mxic -> linear .dma + offs );
460+ if (ret )
461+ return ret ;
462+ } else {
463+ memcpy_toio (mxic -> linear .map , buf , len );
464+ }
440465
441466 writel (INT_LWR_DIS , mxic -> regs + INT_STS );
442467 writel (0 , mxic -> regs + LWR_CTRL );
@@ -547,6 +572,7 @@ static const struct spi_controller_mem_ops mxic_spi_mem_ops = {
547572
548573static const struct spi_controller_mem_caps mxic_spi_mem_caps = {
549574 .dtr = true,
575+ .ecc = true,
550576};
551577
552578static void mxic_spi_set_cs (struct spi_device * spi , bool lvl )
@@ -611,6 +637,80 @@ static int mxic_spi_transfer_one(struct spi_master *master,
611637 return 0 ;
612638}
613639
640+ /* ECC wrapper */
641+ static int mxic_spi_mem_ecc_init_ctx (struct nand_device * nand )
642+ {
643+ struct nand_ecc_engine_ops * ops = mxic_ecc_get_pipelined_ops ();
644+ struct mxic_spi * mxic = nand -> ecc .engine -> priv ;
645+
646+ mxic -> ecc .use_pipelined_conf = true;
647+
648+ return ops -> init_ctx (nand );
649+ }
650+
651+ static void mxic_spi_mem_ecc_cleanup_ctx (struct nand_device * nand )
652+ {
653+ struct nand_ecc_engine_ops * ops = mxic_ecc_get_pipelined_ops ();
654+ struct mxic_spi * mxic = nand -> ecc .engine -> priv ;
655+
656+ mxic -> ecc .use_pipelined_conf = false;
657+
658+ ops -> cleanup_ctx (nand );
659+ }
660+
661+ static int mxic_spi_mem_ecc_prepare_io_req (struct nand_device * nand ,
662+ struct nand_page_io_req * req )
663+ {
664+ struct nand_ecc_engine_ops * ops = mxic_ecc_get_pipelined_ops ();
665+
666+ return ops -> prepare_io_req (nand , req );
667+ }
668+
669+ static int mxic_spi_mem_ecc_finish_io_req (struct nand_device * nand ,
670+ struct nand_page_io_req * req )
671+ {
672+ struct nand_ecc_engine_ops * ops = mxic_ecc_get_pipelined_ops ();
673+
674+ return ops -> finish_io_req (nand , req );
675+ }
676+
677+ static struct nand_ecc_engine_ops mxic_spi_mem_ecc_engine_pipelined_ops = {
678+ .init_ctx = mxic_spi_mem_ecc_init_ctx ,
679+ .cleanup_ctx = mxic_spi_mem_ecc_cleanup_ctx ,
680+ .prepare_io_req = mxic_spi_mem_ecc_prepare_io_req ,
681+ .finish_io_req = mxic_spi_mem_ecc_finish_io_req ,
682+ };
683+
684+ static void mxic_spi_mem_ecc_remove (struct mxic_spi * mxic )
685+ {
686+ if (mxic -> ecc .pipelined_engine ) {
687+ mxic_ecc_put_pipelined_engine (mxic -> ecc .pipelined_engine );
688+ nand_ecc_unregister_on_host_hw_engine (mxic -> ecc .pipelined_engine );
689+ }
690+ }
691+
692+ static int mxic_spi_mem_ecc_probe (struct platform_device * pdev ,
693+ struct mxic_spi * mxic )
694+ {
695+ struct nand_ecc_engine * eng ;
696+
697+ if (!mxic_ecc_get_pipelined_ops ())
698+ return - EOPNOTSUPP ;
699+
700+ eng = mxic_ecc_get_pipelined_engine (pdev );
701+ if (IS_ERR (eng ))
702+ return PTR_ERR (eng );
703+
704+ eng -> dev = & pdev -> dev ;
705+ eng -> integration = NAND_ECC_ENGINE_INTEGRATION_PIPELINED ;
706+ eng -> ops = & mxic_spi_mem_ecc_engine_pipelined_ops ;
707+ eng -> priv = mxic ;
708+ mxic -> ecc .pipelined_engine = eng ;
709+ nand_ecc_register_on_host_hw_engine (eng );
710+
711+ return 0 ;
712+ }
713+
614714static int __maybe_unused mxic_spi_runtime_suspend (struct device * dev )
615715{
616716 struct spi_master * master = dev_get_drvdata (dev );
@@ -656,6 +756,7 @@ static int mxic_spi_probe(struct platform_device *pdev)
656756 platform_set_drvdata (pdev , master );
657757
658758 mxic = spi_master_get_devdata (master );
759+ mxic -> dev = & pdev -> dev ;
659760
660761 master -> dev .of_node = pdev -> dev .of_node ;
661762
@@ -702,6 +803,12 @@ static int mxic_spi_probe(struct platform_device *pdev)
702803
703804 mxic_spi_hw_init (mxic );
704805
806+ ret = mxic_spi_mem_ecc_probe (pdev , mxic );
807+ if (ret == - EPROBE_DEFER ) {
808+ pm_runtime_disable (& pdev -> dev );
809+ return ret ;
810+ }
811+
705812 ret = spi_register_master (master );
706813 if (ret ) {
707814 dev_err (& pdev -> dev , "spi_register_master failed\n" );
@@ -714,8 +821,10 @@ static int mxic_spi_probe(struct platform_device *pdev)
714821static int mxic_spi_remove (struct platform_device * pdev )
715822{
716823 struct spi_master * master = platform_get_drvdata (pdev );
824+ struct mxic_spi * mxic = spi_master_get_devdata (master );
717825
718826 pm_runtime_disable (& pdev -> dev );
827+ mxic_spi_mem_ecc_remove (mxic );
719828 spi_unregister_master (master );
720829
721830 return 0 ;
0 commit comments