2828
2929#include "sdhci-pltfm.h"
3030#include "cqhci.h"
31+ #include "sdhci-cqhci.h"
3132
3233#define SDHCI_DWCMSHC_ARG2_STUFF GENMASK(31, 16)
3334
8788#define DWCMSHC_EMMC_DLL_TXCLK 0x808
8889#define DWCMSHC_EMMC_DLL_STRBIN 0x80c
8990#define DECMSHC_EMMC_DLL_CMDOUT 0x810
91+ #define DECMSHC_EMMC_MISC_CON 0x81C
92+ #define MISC_INTCLK_EN BIT(1)
9093#define DWCMSHC_EMMC_DLL_STATUS0 0x840
9194#define DWCMSHC_EMMC_DLL_START BIT(0)
9295#define DWCMSHC_EMMC_DLL_LOCKED BIT(8)
@@ -282,6 +285,7 @@ struct dwcmshc_priv {
282285
283286struct dwcmshc_pltfm_data {
284287 const struct sdhci_pltfm_data pdata ;
288+ const struct cqhci_host_ops * cqhci_host_ops ;
285289 int (* init )(struct device * dev , struct sdhci_host * host , struct dwcmshc_priv * dwc_priv );
286290 void (* postinit )(struct sdhci_host * host , struct dwcmshc_priv * dwc_priv );
287291};
@@ -620,6 +624,68 @@ static void dwcmshc_cqhci_dumpregs(struct mmc_host *mmc)
620624 sdhci_dumpregs (mmc_priv (mmc ));
621625}
622626
627+ static void rk35xx_sdhci_cqe_pre_enable (struct mmc_host * mmc )
628+ {
629+ struct sdhci_host * host = mmc_priv (mmc );
630+ struct sdhci_pltfm_host * pltfm_host = sdhci_priv (host );
631+ struct dwcmshc_priv * dwc_priv = sdhci_pltfm_priv (pltfm_host );
632+ u32 reg ;
633+
634+ reg = sdhci_readl (host , dwc_priv -> vendor_specific_area2 + CQHCI_CFG );
635+ reg |= CQHCI_ENABLE ;
636+ sdhci_writel (host , reg , dwc_priv -> vendor_specific_area2 + CQHCI_CFG );
637+ }
638+
639+ static void rk35xx_sdhci_cqe_enable (struct mmc_host * mmc )
640+ {
641+ struct sdhci_host * host = mmc_priv (mmc );
642+ u32 reg ;
643+
644+ reg = sdhci_readl (host , SDHCI_PRESENT_STATE );
645+ while (reg & SDHCI_DATA_AVAILABLE ) {
646+ sdhci_readl (host , SDHCI_BUFFER );
647+ reg = sdhci_readl (host , SDHCI_PRESENT_STATE );
648+ }
649+
650+ sdhci_writew (host , DWCMSHC_SDHCI_CQE_TRNS_MODE , SDHCI_TRANSFER_MODE );
651+
652+ sdhci_cqe_enable (mmc );
653+ }
654+
655+ static void rk35xx_sdhci_cqe_disable (struct mmc_host * mmc , bool recovery )
656+ {
657+ struct sdhci_host * host = mmc_priv (mmc );
658+ unsigned long flags ;
659+ u32 ctrl ;
660+
661+ /*
662+ * During CQE command transfers, command complete bit gets latched.
663+ * So s/w should clear command complete interrupt status when CQE is
664+ * either halted or disabled. Otherwise unexpected SDCHI legacy
665+ * interrupt gets triggered when CQE is halted/disabled.
666+ */
667+ spin_lock_irqsave (& host -> lock , flags );
668+ ctrl = sdhci_readl (host , SDHCI_INT_ENABLE );
669+ ctrl |= SDHCI_INT_RESPONSE ;
670+ sdhci_writel (host , ctrl , SDHCI_INT_ENABLE );
671+ sdhci_writel (host , SDHCI_INT_RESPONSE , SDHCI_INT_STATUS );
672+ spin_unlock_irqrestore (& host -> lock , flags );
673+
674+ sdhci_cqe_disable (mmc , recovery );
675+ }
676+
677+ static void rk35xx_sdhci_cqe_post_disable (struct mmc_host * mmc )
678+ {
679+ struct sdhci_host * host = mmc_priv (mmc );
680+ struct sdhci_pltfm_host * pltfm_host = sdhci_priv (host );
681+ struct dwcmshc_priv * dwc_priv = sdhci_pltfm_priv (pltfm_host );
682+ u32 ctrl ;
683+
684+ ctrl = sdhci_readl (host , dwc_priv -> vendor_specific_area2 + CQHCI_CFG );
685+ ctrl &= ~CQHCI_ENABLE ;
686+ sdhci_writel (host , ctrl , dwc_priv -> vendor_specific_area2 + CQHCI_CFG );
687+ }
688+
623689static void dwcmshc_rk3568_set_clock (struct sdhci_host * host , unsigned int clock )
624690{
625691 struct sdhci_pltfm_host * pltfm_host = sdhci_priv (host );
@@ -738,6 +804,10 @@ static void rk35xx_sdhci_reset(struct sdhci_host *host, u8 mask)
738804 struct sdhci_pltfm_host * pltfm_host = sdhci_priv (host );
739805 struct dwcmshc_priv * dwc_priv = sdhci_pltfm_priv (pltfm_host );
740806 struct rk35xx_priv * priv = dwc_priv -> priv ;
807+ u32 extra = sdhci_readl (host , DECMSHC_EMMC_MISC_CON );
808+
809+ if ((host -> mmc -> caps2 & MMC_CAP2_CQE ) && (mask & SDHCI_RESET_ALL ))
810+ cqhci_deactivate (host -> mmc );
741811
742812 if (mask & SDHCI_RESET_ALL && priv -> reset ) {
743813 reset_control_assert (priv -> reset );
@@ -746,6 +816,9 @@ static void rk35xx_sdhci_reset(struct sdhci_host *host, u8 mask)
746816 }
747817
748818 sdhci_reset (host , mask );
819+
820+ /* Enable INTERNAL CLOCK */
821+ sdhci_writel (host , MISC_INTCLK_EN | extra , DECMSHC_EMMC_MISC_CON );
749822}
750823
751824static int dwcmshc_rk35xx_init (struct device * dev , struct sdhci_host * host ,
@@ -1664,6 +1737,15 @@ static const struct dwcmshc_pltfm_data sdhci_dwcmshc_bf3_pdata = {
16641737};
16651738#endif
16661739
1740+ static const struct cqhci_host_ops rk35xx_cqhci_ops = {
1741+ .pre_enable = rk35xx_sdhci_cqe_pre_enable ,
1742+ .enable = rk35xx_sdhci_cqe_enable ,
1743+ .disable = rk35xx_sdhci_cqe_disable ,
1744+ .post_disable = rk35xx_sdhci_cqe_post_disable ,
1745+ .dumpregs = dwcmshc_cqhci_dumpregs ,
1746+ .set_tran_desc = dwcmshc_set_tran_desc ,
1747+ };
1748+
16671749static const struct dwcmshc_pltfm_data sdhci_dwcmshc_rk35xx_pdata = {
16681750 .pdata = {
16691751 .ops = & sdhci_dwcmshc_rk35xx_ops ,
@@ -1672,6 +1754,7 @@ static const struct dwcmshc_pltfm_data sdhci_dwcmshc_rk35xx_pdata = {
16721754 .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
16731755 SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN ,
16741756 },
1757+ .cqhci_host_ops = & rk35xx_cqhci_ops ,
16751758 .init = dwcmshc_rk35xx_init ,
16761759 .postinit = dwcmshc_rk35xx_postinit ,
16771760};
@@ -1732,7 +1815,8 @@ static const struct cqhci_host_ops dwcmshc_cqhci_ops = {
17321815 .set_tran_desc = dwcmshc_set_tran_desc ,
17331816};
17341817
1735- static void dwcmshc_cqhci_init (struct sdhci_host * host , struct platform_device * pdev )
1818+ static void dwcmshc_cqhci_init (struct sdhci_host * host , struct platform_device * pdev ,
1819+ const struct dwcmshc_pltfm_data * pltfm_data )
17361820{
17371821 struct cqhci_host * cq_host ;
17381822 struct sdhci_pltfm_host * pltfm_host = sdhci_priv (host );
@@ -1762,7 +1846,10 @@ static void dwcmshc_cqhci_init(struct sdhci_host *host, struct platform_device *
17621846 }
17631847
17641848 cq_host -> mmio = host -> ioaddr + priv -> vendor_specific_area2 ;
1765- cq_host -> ops = & dwcmshc_cqhci_ops ;
1849+ if (pltfm_data -> cqhci_host_ops )
1850+ cq_host -> ops = pltfm_data -> cqhci_host_ops ;
1851+ else
1852+ cq_host -> ops = & dwcmshc_cqhci_ops ;
17661853
17671854 /* Enable using of 128-bit task descriptors */
17681855 dma64 = host -> flags & SDHCI_USE_64_BIT_DMA ;
@@ -1934,7 +2021,7 @@ static int dwcmshc_probe(struct platform_device *pdev)
19342021 priv -> vendor_specific_area2 =
19352022 sdhci_readw (host , DWCMSHC_P_VENDOR_AREA2 );
19362023
1937- dwcmshc_cqhci_init (host , pdev );
2024+ dwcmshc_cqhci_init (host , pdev , pltfm_data );
19382025 }
19392026
19402027 if (pltfm_data -> postinit )
0 commit comments