@@ -165,6 +165,7 @@ struct meson_host {
165165
166166 unsigned int bounce_buf_size ;
167167 void * bounce_buf ;
168+ void __iomem * bounce_iomem_buf ;
168169 dma_addr_t bounce_dma_addr ;
169170 struct sd_emmc_desc * descs ;
170171 dma_addr_t descs_dma_addr ;
@@ -745,6 +746,47 @@ static void meson_mmc_desc_chain_transfer(struct mmc_host *mmc, u32 cmd_cfg)
745746 writel (start , host -> regs + SD_EMMC_START );
746747}
747748
749+ /* local sg copy to buffer version with _to/fromio usage for dram_access_quirk */
750+ static void meson_mmc_copy_buffer (struct meson_host * host , struct mmc_data * data ,
751+ size_t buflen , bool to_buffer )
752+ {
753+ unsigned int sg_flags = SG_MITER_ATOMIC ;
754+ struct scatterlist * sgl = data -> sg ;
755+ unsigned int nents = data -> sg_len ;
756+ struct sg_mapping_iter miter ;
757+ unsigned int offset = 0 ;
758+
759+ if (to_buffer )
760+ sg_flags |= SG_MITER_FROM_SG ;
761+ else
762+ sg_flags |= SG_MITER_TO_SG ;
763+
764+ sg_miter_start (& miter , sgl , nents , sg_flags );
765+
766+ while ((offset < buflen ) && sg_miter_next (& miter )) {
767+ unsigned int len ;
768+
769+ len = min (miter .length , buflen - offset );
770+
771+ /* When dram_access_quirk, the bounce buffer is a iomem mapping */
772+ if (host -> dram_access_quirk ) {
773+ if (to_buffer )
774+ memcpy_toio (host -> bounce_iomem_buf + offset , miter .addr , len );
775+ else
776+ memcpy_fromio (miter .addr , host -> bounce_iomem_buf + offset , len );
777+ } else {
778+ if (to_buffer )
779+ memcpy (host -> bounce_buf + offset , miter .addr , len );
780+ else
781+ memcpy (miter .addr , host -> bounce_buf + offset , len );
782+ }
783+
784+ offset += len ;
785+ }
786+
787+ sg_miter_stop (& miter );
788+ }
789+
748790static void meson_mmc_start_cmd (struct mmc_host * mmc , struct mmc_command * cmd )
749791{
750792 struct meson_host * host = mmc_priv (mmc );
@@ -788,8 +830,7 @@ static void meson_mmc_start_cmd(struct mmc_host *mmc, struct mmc_command *cmd)
788830 if (data -> flags & MMC_DATA_WRITE ) {
789831 cmd_cfg |= CMD_CFG_DATA_WR ;
790832 WARN_ON (xfer_bytes > host -> bounce_buf_size );
791- sg_copy_to_buffer (data -> sg , data -> sg_len ,
792- host -> bounce_buf , xfer_bytes );
833+ meson_mmc_copy_buffer (host , data , xfer_bytes , true);
793834 dma_wmb ();
794835 }
795836
@@ -958,8 +999,7 @@ static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id)
958999 if (meson_mmc_bounce_buf_read (data )) {
9591000 xfer_bytes = data -> blksz * data -> blocks ;
9601001 WARN_ON (xfer_bytes > host -> bounce_buf_size );
961- sg_copy_from_buffer (data -> sg , data -> sg_len ,
962- host -> bounce_buf , xfer_bytes );
1002+ meson_mmc_copy_buffer (host , data , xfer_bytes , false);
9631003 }
9641004
9651005 next_cmd = meson_mmc_get_next_command (cmd );
@@ -1179,7 +1219,7 @@ static int meson_mmc_probe(struct platform_device *pdev)
11791219 * instead of the DDR memory
11801220 */
11811221 host -> bounce_buf_size = SD_EMMC_SRAM_DATA_BUF_LEN ;
1182- host -> bounce_buf = host -> regs + SD_EMMC_SRAM_DATA_BUF_OFF ;
1222+ host -> bounce_iomem_buf = host -> regs + SD_EMMC_SRAM_DATA_BUF_OFF ;
11831223 host -> bounce_dma_addr = res -> start + SD_EMMC_SRAM_DATA_BUF_OFF ;
11841224 } else {
11851225 /* data bounce buffer */
0 commit comments