Merge tag 'mmc-v4.14-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 7 Oct 2017 17:03:03 +0000 (10:03 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 7 Oct 2017 17:03:03 +0000 (10:03 -0700)
Pull MMC fixes from Ulf Hansson:
 "MMC core:

   - Fix driver strength selection when selecting hs400es

   - Delete bounce buffer handling:

     This change fixes a problem related to how bounce buffers are being
     allocated. However, instead of trying to fix that, let's just
     remove the mmc bounce buffer code altogether, as it has practically
     no use.

  MMC host:

   - meson-gx: A couple of fixes related to clock/phase/tuning

   - sdhci-xenon: Fix clock resource by adding an optional bus clock"

* tag 'mmc-v4.14-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc:
  mmc: sdhci-xenon: Fix clock resource by adding an optional bus clock
  mmc: meson-gx: include tx phase in the tuning process
  mmc: meson-gx: fix rx phase reset
  mmc: meson-gx: make sure the clock is rounded down
  mmc: Delete bounce buffer handling
  mmc: core: add driver strength selection when selecting hs400es

Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.txt
drivers/mmc/core/block.c
drivers/mmc/core/mmc.c
drivers/mmc/core/queue.c
drivers/mmc/core/queue.h
drivers/mmc/host/cavium.c
drivers/mmc/host/meson-gx-mmc.c
drivers/mmc/host/pxamci.c
drivers/mmc/host/sdhci-xenon.c
drivers/mmc/host/sdhci-xenon.h
include/linux/mmc/host.h

index b878a1e305af6e143a646b3473be522c82a62e8a..ed1456f5c94dda21ecaf2eebd86bcd7934d11376 100644 (file)
@@ -16,11 +16,13 @@ Required Properties:
 
 - clocks:
   Array of clocks required for SDHC.
-  Require at least input clock for Xenon IP core.
+  Require at least input clock for Xenon IP core. For Armada AP806 and
+  CP110, the AXI clock is also mandatory.
 
 - clock-names:
   Array of names corresponding to clocks property.
   The input clock for Xenon IP core should be named as "core".
+  The input clock for the AXI bus must be named as "axi".
 
 - reg:
   * For "marvell,armada-3700-sdhci", two register areas.
@@ -106,8 +108,8 @@ Example:
                compatible = "marvell,armada-ap806-sdhci";
                reg = <0xaa0000 0x1000>;
                interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>
-               clocks = <&emmc_clk>;
-               clock-names = "core";
+               clocks = <&emmc_clk>,<&axi_clk>;
+               clock-names = "core", "axi";
                bus-width = <4>;
                marvell,xenon-phy-slow-mode;
                marvell,xenon-tun-count = <11>;
@@ -126,8 +128,8 @@ Example:
                interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>
                vqmmc-supply = <&sd_vqmmc_regulator>;
                vmmc-supply = <&sd_vmmc_regulator>;
-               clocks = <&sdclk>;
-               clock-names = "core";
+               clocks = <&sdclk>, <&axi_clk>;
+               clock-names = "core", "axi";
                bus-width = <4>;
                marvell,xenon-tun-count = <9>;
        };
index 29fc1e662891d7bc2157ff55740bd2f110f4e14d..2ad7b5c691569e37cd366425c62c6ae0514f3857 100644 (file)
@@ -1634,8 +1634,6 @@ static void mmc_blk_data_prep(struct mmc_queue *mq, struct mmc_queue_req *mqrq,
        }
 
        mqrq->areq.mrq = &brq->mrq;
-
-       mmc_queue_bounce_pre(mqrq);
 }
 
 static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
@@ -1829,7 +1827,6 @@ static void mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *new_req)
                brq = &mq_rq->brq;
                old_req = mmc_queue_req_to_req(mq_rq);
                type = rq_data_dir(old_req) == READ ? MMC_BLK_READ : MMC_BLK_WRITE;
-               mmc_queue_bounce_post(mq_rq);
 
                switch (status) {
                case MMC_BLK_SUCCESS:
index a7eb623f8daa3e610891ffb30157dd5e4dd4e103..36217ad5e9b1fbddb4c5dedf6dd711374fc27497 100644 (file)
@@ -1286,6 +1286,23 @@ out_err:
        return err;
 }
 
+static void mmc_select_driver_type(struct mmc_card *card)
+{
+       int card_drv_type, drive_strength, drv_type;
+
+       card_drv_type = card->ext_csd.raw_driver_strength |
+                       mmc_driver_type_mask(0);
+
+       drive_strength = mmc_select_drive_strength(card,
+                                                  card->ext_csd.hs200_max_dtr,
+                                                  card_drv_type, &drv_type);
+
+       card->drive_strength = drive_strength;
+
+       if (drv_type)
+               mmc_set_driver_type(card->host, drv_type);
+}
+
 static int mmc_select_hs400es(struct mmc_card *card)
 {
        struct mmc_host *host = card->host;
@@ -1341,6 +1358,8 @@ static int mmc_select_hs400es(struct mmc_card *card)
                goto out_err;
        }
 
+       mmc_select_driver_type(card);
+
        /* Switch card to HS400 */
        val = EXT_CSD_TIMING_HS400 |
              card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
@@ -1374,23 +1393,6 @@ out_err:
        return err;
 }
 
-static void mmc_select_driver_type(struct mmc_card *card)
-{
-       int card_drv_type, drive_strength, drv_type;
-
-       card_drv_type = card->ext_csd.raw_driver_strength |
-                       mmc_driver_type_mask(0);
-
-       drive_strength = mmc_select_drive_strength(card,
-                                                  card->ext_csd.hs200_max_dtr,
-                                                  card_drv_type, &drv_type);
-
-       card->drive_strength = drive_strength;
-
-       if (drv_type)
-               mmc_set_driver_type(card->host, drv_type);
-}
-
 /*
  * For device supporting HS200 mode, the following sequence
  * should be done before executing the tuning process.
index 74c663b1c0a7418c53ef0d7fa4ae27e2499d1ff7..0a4e77a5ba33fe7e0009ab1f7f97078a38e1559c 100644 (file)
@@ -23,8 +23,6 @@
 #include "core.h"
 #include "card.h"
 
-#define MMC_QUEUE_BOUNCESZ     65536
-
 /*
  * Prepare a MMC request. This just filters out odd stuff.
  */
@@ -150,26 +148,6 @@ static void mmc_queue_setup_discard(struct request_queue *q,
                queue_flag_set_unlocked(QUEUE_FLAG_SECERASE, q);
 }
 
-static unsigned int mmc_queue_calc_bouncesz(struct mmc_host *host)
-{
-       unsigned int bouncesz = MMC_QUEUE_BOUNCESZ;
-
-       if (host->max_segs != 1 || (host->caps & MMC_CAP_NO_BOUNCE_BUFF))
-               return 0;
-
-       if (bouncesz > host->max_req_size)
-               bouncesz = host->max_req_size;
-       if (bouncesz > host->max_seg_size)
-               bouncesz = host->max_seg_size;
-       if (bouncesz > host->max_blk_count * 512)
-               bouncesz = host->max_blk_count * 512;
-
-       if (bouncesz <= 512)
-               return 0;
-
-       return bouncesz;
-}
-
 /**
  * mmc_init_request() - initialize the MMC-specific per-request data
  * @q: the request queue
@@ -184,26 +162,9 @@ static int mmc_init_request(struct request_queue *q, struct request *req,
        struct mmc_card *card = mq->card;
        struct mmc_host *host = card->host;
 
-       if (card->bouncesz) {
-               mq_rq->bounce_buf = kmalloc(card->bouncesz, gfp);
-               if (!mq_rq->bounce_buf)
-                       return -ENOMEM;
-               if (card->bouncesz > 512) {
-                       mq_rq->sg = mmc_alloc_sg(1, gfp);
-                       if (!mq_rq->sg)
-                               return -ENOMEM;
-                       mq_rq->bounce_sg = mmc_alloc_sg(card->bouncesz / 512,
-                                                       gfp);
-                       if (!mq_rq->bounce_sg)
-                               return -ENOMEM;
-               }
-       } else {
-               mq_rq->bounce_buf = NULL;
-               mq_rq->bounce_sg = NULL;
-               mq_rq->sg = mmc_alloc_sg(host->max_segs, gfp);
-               if (!mq_rq->sg)
-                       return -ENOMEM;
-       }
+       mq_rq->sg = mmc_alloc_sg(host->max_segs, gfp);
+       if (!mq_rq->sg)
+               return -ENOMEM;
 
        return 0;
 }
@@ -212,13 +173,6 @@ static void mmc_exit_request(struct request_queue *q, struct request *req)
 {
        struct mmc_queue_req *mq_rq = req_to_mmc_queue_req(req);
 
-       /* It is OK to kfree(NULL) so this will be smooth */
-       kfree(mq_rq->bounce_sg);
-       mq_rq->bounce_sg = NULL;
-
-       kfree(mq_rq->bounce_buf);
-       mq_rq->bounce_buf = NULL;
-
        kfree(mq_rq->sg);
        mq_rq->sg = NULL;
 }
@@ -242,12 +196,6 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
        if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
                limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT;
 
-       /*
-        * mmc_init_request() depends on card->bouncesz so it must be calculated
-        * before blk_init_allocated_queue() starts allocating requests.
-        */
-       card->bouncesz = mmc_queue_calc_bouncesz(host);
-
        mq->card = card;
        mq->queue = blk_alloc_queue(GFP_KERNEL);
        if (!mq->queue)
@@ -271,17 +219,11 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
        if (mmc_can_erase(card))
                mmc_queue_setup_discard(mq->queue, card);
 
-       if (card->bouncesz) {
-               blk_queue_max_hw_sectors(mq->queue, card->bouncesz / 512);
-               blk_queue_max_segments(mq->queue, card->bouncesz / 512);
-               blk_queue_max_segment_size(mq->queue, card->bouncesz);
-       } else {
-               blk_queue_bounce_limit(mq->queue, limit);
-               blk_queue_max_hw_sectors(mq->queue,
-                       min(host->max_blk_count, host->max_req_size / 512));
-               blk_queue_max_segments(mq->queue, host->max_segs);
-               blk_queue_max_segment_size(mq->queue, host->max_seg_size);
-       }
+       blk_queue_bounce_limit(mq->queue, limit);
+       blk_queue_max_hw_sectors(mq->queue,
+               min(host->max_blk_count, host->max_req_size / 512));
+       blk_queue_max_segments(mq->queue, host->max_segs);
+       blk_queue_max_segment_size(mq->queue, host->max_seg_size);
 
        sema_init(&mq->thread_sem, 1);
 
@@ -370,56 +312,7 @@ void mmc_queue_resume(struct mmc_queue *mq)
  */
 unsigned int mmc_queue_map_sg(struct mmc_queue *mq, struct mmc_queue_req *mqrq)
 {
-       unsigned int sg_len;
-       size_t buflen;
-       struct scatterlist *sg;
        struct request *req = mmc_queue_req_to_req(mqrq);
-       int i;
-
-       if (!mqrq->bounce_buf)
-               return blk_rq_map_sg(mq->queue, req, mqrq->sg);
-
-       sg_len = blk_rq_map_sg(mq->queue, req, mqrq->bounce_sg);
-
-       mqrq->bounce_sg_len = sg_len;
-
-       buflen = 0;
-       for_each_sg(mqrq->bounce_sg, sg, sg_len, i)
-               buflen += sg->length;
-
-       sg_init_one(mqrq->sg, mqrq->bounce_buf, buflen);
-
-       return 1;
-}
-
-/*
- * If writing, bounce the data to the buffer before the request
- * is sent to the host driver
- */
-void mmc_queue_bounce_pre(struct mmc_queue_req *mqrq)
-{
-       if (!mqrq->bounce_buf)
-               return;
-
-       if (rq_data_dir(mmc_queue_req_to_req(mqrq)) != WRITE)
-               return;
-
-       sg_copy_to_buffer(mqrq->bounce_sg, mqrq->bounce_sg_len,
-               mqrq->bounce_buf, mqrq->sg[0].length);
-}
-
-/*
- * If reading, bounce the data from the buffer after the request
- * has been handled by the host driver
- */
-void mmc_queue_bounce_post(struct mmc_queue_req *mqrq)
-{
-       if (!mqrq->bounce_buf)
-               return;
-
-       if (rq_data_dir(mmc_queue_req_to_req(mqrq)) != READ)
-               return;
 
-       sg_copy_from_buffer(mqrq->bounce_sg, mqrq->bounce_sg_len,
-               mqrq->bounce_buf, mqrq->sg[0].length);
+       return blk_rq_map_sg(mq->queue, req, mqrq->sg);
 }
index 04fc89360a7a1a5669d7d3a027edc2fd6fdbc1f6..f18d3f656baa510b6022e9f51efd3990ec5f194d 100644 (file)
@@ -49,9 +49,6 @@ enum mmc_drv_op {
 struct mmc_queue_req {
        struct mmc_blk_request  brq;
        struct scatterlist      *sg;
-       char                    *bounce_buf;
-       struct scatterlist      *bounce_sg;
-       unsigned int            bounce_sg_len;
        struct mmc_async_req    areq;
        enum mmc_drv_op         drv_op;
        int                     drv_op_result;
@@ -81,11 +78,8 @@ extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *,
 extern void mmc_cleanup_queue(struct mmc_queue *);
 extern void mmc_queue_suspend(struct mmc_queue *);
 extern void mmc_queue_resume(struct mmc_queue *);
-
 extern unsigned int mmc_queue_map_sg(struct mmc_queue *,
                                     struct mmc_queue_req *);
-extern void mmc_queue_bounce_pre(struct mmc_queue_req *);
-extern void mmc_queue_bounce_post(struct mmc_queue_req *);
 
 extern int mmc_access_rpmb(struct mmc_queue *);
 
index 27fb625cbcf3ff459a62668a93c80a30883fbe21..fbd29f00fca05e5dc46e09d1aa10c9f619283097 100644 (file)
@@ -1038,7 +1038,7 @@ int cvm_mmc_of_slot_probe(struct device *dev, struct cvm_mmc_host *host)
         */
        mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
                     MMC_CAP_ERASE | MMC_CAP_CMD23 | MMC_CAP_POWER_OFF_CARD |
-                    MMC_CAP_3_3V_DDR | MMC_CAP_NO_BOUNCE_BUFF;
+                    MMC_CAP_3_3V_DDR;
 
        if (host->use_sg)
                mmc->max_segs = 16;
index c885c2d4b90418a93519ab05a989a7d5c77efd76..85745ef179e22b2e49e4b23e15df311891f192dc 100644 (file)
@@ -531,8 +531,7 @@ static int meson_mmc_clk_init(struct meson_host *host)
        div->shift = __ffs(CLK_DIV_MASK);
        div->width = __builtin_popcountl(CLK_DIV_MASK);
        div->hw.init = &init;
-       div->flags = (CLK_DIVIDER_ONE_BASED |
-                     CLK_DIVIDER_ROUND_CLOSEST);
+       div->flags = CLK_DIVIDER_ONE_BASED;
 
        clk = devm_clk_register(host->dev, &div->hw);
        if (WARN_ON(IS_ERR(clk)))
@@ -717,6 +716,22 @@ static int meson_mmc_clk_phase_tuning(struct mmc_host *mmc, u32 opcode,
 static int meson_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode)
 {
        struct meson_host *host = mmc_priv(mmc);
+       int ret;
+
+       /*
+        * If this is the initial tuning, try to get a sane Rx starting
+        * phase before doing the actual tuning.
+        */
+       if (!mmc->doing_retune) {
+               ret = meson_mmc_clk_phase_tuning(mmc, opcode, host->rx_clk);
+
+               if (ret)
+                       return ret;
+       }
+
+       ret = meson_mmc_clk_phase_tuning(mmc, opcode, host->tx_clk);
+       if (ret)
+               return ret;
 
        return meson_mmc_clk_phase_tuning(mmc, opcode, host->rx_clk);
 }
@@ -746,6 +761,11 @@ static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        case MMC_POWER_UP:
                if (!IS_ERR(mmc->supply.vmmc))
                        mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd);
+
+               /* Reset phases */
+               clk_set_phase(host->rx_clk, 0);
+               clk_set_phase(host->tx_clk, 270);
+
                break;
 
        case MMC_POWER_ON:
@@ -759,8 +779,6 @@ static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                                host->vqmmc_enabled = true;
                }
 
-               /* Reset rx phase */
-               clk_set_phase(host->rx_clk, 0);
                break;
        }
 
index 59ab194cb0099b19dcaa247977bc9ccc7c8175e1..c763b404510f3a29d3864290297b22f596701cc3 100644 (file)
@@ -702,11 +702,7 @@ static int pxamci_probe(struct platform_device *pdev)
 
        pxamci_init_ocr(host);
 
-       /*
-        * This architecture used to disable bounce buffers through its
-        * defconfig, now it is done at runtime as a host property.
-        */
-       mmc->caps = MMC_CAP_NO_BOUNCE_BUFF;
+       mmc->caps = 0;
        host->cmdat = 0;
        if (!cpu_is_pxa25x()) {
                mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
index 2eec2e652c53da9c1f0b9c6156dcdc9778d82d68..0842bbc2d7ad340011a70f43409d2503cf662ff7 100644 (file)
@@ -466,6 +466,7 @@ static int xenon_probe(struct platform_device *pdev)
 {
        struct sdhci_pltfm_host *pltfm_host;
        struct sdhci_host *host;
+       struct xenon_priv *priv;
        int err;
 
        host = sdhci_pltfm_init(pdev, &sdhci_xenon_pdata,
@@ -474,6 +475,7 @@ static int xenon_probe(struct platform_device *pdev)
                return PTR_ERR(host);
 
        pltfm_host = sdhci_priv(host);
+       priv = sdhci_pltfm_priv(pltfm_host);
 
        /*
         * Link Xenon specific mmc_host_ops function,
@@ -491,9 +493,20 @@ static int xenon_probe(struct platform_device *pdev)
        if (err)
                goto free_pltfm;
 
+       priv->axi_clk = devm_clk_get(&pdev->dev, "axi");
+       if (IS_ERR(priv->axi_clk)) {
+               err = PTR_ERR(priv->axi_clk);
+               if (err == -EPROBE_DEFER)
+                       goto err_clk;
+       } else {
+               err = clk_prepare_enable(priv->axi_clk);
+               if (err)
+                       goto err_clk;
+       }
+
        err = mmc_of_parse(host->mmc);
        if (err)
-               goto err_clk;
+               goto err_clk_axi;
 
        sdhci_get_of_property(pdev);
 
@@ -502,11 +515,11 @@ static int xenon_probe(struct platform_device *pdev)
        /* Xenon specific dt parse */
        err = xenon_probe_dt(pdev);
        if (err)
-               goto err_clk;
+               goto err_clk_axi;
 
        err = xenon_sdhc_prepare(host);
        if (err)
-               goto err_clk;
+               goto err_clk_axi;
 
        pm_runtime_get_noresume(&pdev->dev);
        pm_runtime_set_active(&pdev->dev);
@@ -527,6 +540,8 @@ remove_sdhc:
        pm_runtime_disable(&pdev->dev);
        pm_runtime_put_noidle(&pdev->dev);
        xenon_sdhc_unprepare(host);
+err_clk_axi:
+       clk_disable_unprepare(priv->axi_clk);
 err_clk:
        clk_disable_unprepare(pltfm_host->clk);
 free_pltfm:
@@ -538,6 +553,7 @@ static int xenon_remove(struct platform_device *pdev)
 {
        struct sdhci_host *host = platform_get_drvdata(pdev);
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
 
        pm_runtime_get_sync(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
@@ -546,7 +562,7 @@ static int xenon_remove(struct platform_device *pdev)
        sdhci_remove_host(host, 0);
 
        xenon_sdhc_unprepare(host);
-
+       clk_disable_unprepare(priv->axi_clk);
        clk_disable_unprepare(pltfm_host->clk);
 
        sdhci_pltfm_free(pdev);
index 2bc0510c07696a11015c8e3bcee8c3497bd67384..9994995c7c56867bd24835d86bd1343e8fa3b770 100644 (file)
@@ -83,6 +83,7 @@ struct xenon_priv {
        unsigned char   bus_width;
        unsigned char   timing;
        unsigned int    clock;
+       struct clk      *axi_clk;
 
        int             phy_type;
        /*
index f3f2d07feb2a627d9b65409b7e5a0c0e53fe54c2..9a43763a68adb3e998ec942300688f99e065489b 100644 (file)
@@ -316,7 +316,7 @@ struct mmc_host {
 #define MMC_CAP_UHS_SDR50      (1 << 18)       /* Host supports UHS SDR50 mode */
 #define MMC_CAP_UHS_SDR104     (1 << 19)       /* Host supports UHS SDR104 mode */
 #define MMC_CAP_UHS_DDR50      (1 << 20)       /* Host supports UHS DDR50 mode */
-#define MMC_CAP_NO_BOUNCE_BUFF (1 << 21)       /* Disable bounce buffers on host */
+/* (1 << 21) is free for reuse */
 #define MMC_CAP_DRIVER_TYPE_A  (1 << 23)       /* Host supports Driver Type A */
 #define MMC_CAP_DRIVER_TYPE_C  (1 << 24)       /* Host supports Driver Type C */
 #define MMC_CAP_DRIVER_TYPE_D  (1 << 25)       /* Host supports Driver Type D */