Commit e83b7a8acc420923cbe8a30901d9eb60677f54fb
Committed by
Chris Ball
1 parent
19f1ba51c7
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
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) |