Commit e83b7a8acc420923cbe8a30901d9eb60677f54fb

Authored by Guennadi Liakhovetski
Committed by Chris Ball
1 parent 19f1ba51c7

mmc: tmio: fix unbalanced power-on calls with clock-gating enabled

With MMC clock gating enabled the MMC core currently calls MMC host driver's
.set_ios() method with .power_mode == MMC_POWER_ON and the clock value set
either to 0 or to the target rate. The tmio MMC driver then wrongly
translates the latter calls to card slot power-on requests, even when the
slot already was on. This patch fixes the driver to avoid needlessly
incrementing power-supplying regulator's use count.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski+renesas@gmail.com>
Tested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Chris Ball <cjb@laptop.org>

Showing 2 changed files with 35 additions and 12 deletions Side-by-side Diff

drivers/mmc/host/tmio_mmc.h
... ... @@ -40,6 +40,22 @@
40 40  
41 41 struct tmio_mmc_data;
42 42  
  43 +/*
  44 + * We differentiate between the following 3 power states:
  45 + * 1. card slot powered off, controller stopped. This is used, when either there
  46 + * is no card in the slot, or the card really has to be powered down.
  47 + * 2. card slot powered on, controller stopped. This is used, when a card is in
  48 + * the slot, but no activity is currently taking place. This is a power-
  49 + * saving mode with card-state preserved. This state can be entered, e.g.
  50 + * when MMC clock-gating is used.
  51 + * 3. card slot powered on, controller running. This is the actual active state.
  52 + */
  53 +enum tmio_mmc_power {
  54 + TMIO_MMC_OFF_STOP, /* card power off, controller stopped */
  55 + TMIO_MMC_ON_STOP, /* card power on, controller stopped */
  56 + TMIO_MMC_ON_RUN, /* card power on, controller running */
  57 +};
  58 +
43 59 struct tmio_mmc_host {
44 60 void __iomem *ctl;
45 61 unsigned long bus_shift;
... ... @@ -48,8 +64,8 @@
48 64 struct mmc_data *data;
49 65 struct mmc_host *mmc;
50 66  
51   - /* Controller power state */
52   - bool power;
  67 + /* Controller and card power state */
  68 + enum tmio_mmc_power power;
53 69  
54 70 /* Callbacks for clock / power control */
55 71 void (*set_pwr)(struct platform_device *host, int state);
drivers/mmc/host/tmio_mmc_pio.c
... ... @@ -859,7 +859,7 @@
859 859 * is kept positive, so no suspending actually takes place.
860 860 */
861 861 if (ios->power_mode == MMC_POWER_ON && ios->clock) {
862   - if (!host->power) {
  862 + if (host->power != TMIO_MMC_ON_RUN) {
863 863 tmio_mmc_clk_update(mmc);
864 864 pm_runtime_get_sync(dev);
865 865 if (host->resuming) {
866 866  
867 867  
868 868  
869 869  
870 870  
... ... @@ -868,27 +868,34 @@
868 868 }
869 869 }
870 870 tmio_mmc_set_clock(host, ios->clock);
871   - if (!host->power) {
  871 + if (host->power == TMIO_MMC_OFF_STOP)
872 872 /* power up SD card and the bus */
873 873 tmio_mmc_power_on(host, ios->vdd);
874   - host->power = true;
875   - }
  874 + host->power = TMIO_MMC_ON_RUN;
876 875 /* start bus clock */
877 876 tmio_mmc_clk_start(host);
878 877 } else if (ios->power_mode != MMC_POWER_UP) {
879   - if (host->power) {
880   - struct tmio_mmc_data *pdata = host->pdata;
881   - if (ios->power_mode == MMC_POWER_OFF)
  878 + struct tmio_mmc_data *pdata = host->pdata;
  879 + unsigned int old_power = host->power;
  880 +
  881 + if (old_power != TMIO_MMC_OFF_STOP) {
  882 + if (ios->power_mode == MMC_POWER_OFF) {
882 883 tmio_mmc_power_off(host);
  884 + host->power = TMIO_MMC_OFF_STOP;
  885 + } else {
  886 + host->power = TMIO_MMC_ON_STOP;
  887 + }
  888 + }
  889 +
  890 + if (old_power == TMIO_MMC_ON_RUN) {
883 891 tmio_mmc_clk_stop(host);
884   - host->power = false;
885 892 pm_runtime_put(dev);
886 893 if (pdata->clk_disable)
887 894 pdata->clk_disable(host->pdev);
888 895 }
889 896 }
890 897  
891   - if (host->power) {
  898 + if (host->power != TMIO_MMC_OFF_STOP) {
892 899 switch (ios->bus_width) {
893 900 case MMC_BUS_WIDTH_1:
894 901 sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80e0);
... ... @@ -1029,7 +1036,7 @@
1029 1036 mmc->caps & MMC_CAP_NONREMOVABLE ||
1030 1037 mmc->slot.cd_irq >= 0);
1031 1038  
1032   - _host->power = false;
  1039 + _host->power = TMIO_MMC_OFF_STOP;
1033 1040 pm_runtime_enable(&pdev->dev);
1034 1041 ret = pm_runtime_resume(&pdev->dev);
1035 1042 if (ret < 0)