disable sdhc clock while it is not used -blog archive

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

disable sdhc clock while it is not used -blog archive

2,075 Views
JayTu
NXP Employee
NXP Employee

Many customers met the issue with wifi driver. The following command shows sdhc clock not being disabled when wifi driver is removed.

# cat /proc/cpu/clocks | busybox grep sdhc
mxsdhci.3-3                           ______    0   200000000 (200MHz)
mxsdhci.2-2                           ______    0   200000000 (200MHz)
mxsdhci.1-1                           ______    0   200000000 (200MHz)
mxsdhci.0-0                           ______    0   200000000 (200MHz)
#
# insmod ar6000.ko
AR6000: configuration opcode 7 is only used for RTOS systems, not Linux systems#
AR6K: ** HIF layer does not support scatter requests (17)
wmi_control_rx() : Unknown id 0x101e

#
# cat /proc/cpu/clocks | busybox grep sdhc
mxsdhci.3-3                           ______    0   200000000 (200MHz)
mxsdhci.2-2                           ______    0   200000000 (200MHz)
mxsdhci.1-1                           ______    1   200000000 (200MHz)
mxsdhci.0-0                           ______    1   200000000 (200MHz)
#
#
# rmmod ar6000.ko
debug_hdr_ptr: 0x541e40
Attempting to reset target on instance destroy....
#
# cat /proc/cpu/clocks | busybox grep sdhc
mxsdhci.3-3                           ______    0   200000000 (200MHz)
mxsdhci.2-2                           ______    0   200000000 (200MHz)
mxsdhci.1-1                           ______    1   200000000 (200MHz)

 

Before digging it, why we care this clock seriously?

FSL implement one *mechanism* that can save more power by putting DDR into self refresh. The idea behind this is that, copies the code/data into iram, cpu then execute the instruction from iram. Then DDR can enter self refresh mode.

To start this mechanism, we need to make sure all the clock referenced from DDR must not being used since putting DDR into self refresh mode will turn off its clock.

SD's clock is this case, it referenced from DDR clock.

 

Then, how to disable SD clock?

In the sd host driver, we export a function to do this:

 132 void sdhci_clock_enable(struct mmc_host *mmc, unsigned int enable)
 133 {
 134         struct sdhci_host *host;
 135
 136         host = mmc_priv(mmc);
 137         if (enable) {
 138                 clk_enable(host->clk);
 139                 host->plat_data->clk_flg = 1;
 140         } else {
 141                 clk_disable(host->clk);
 142                 host->plat_data->clk_flg = 0;
 143         }
 144 }
 145 EXPORT_SYMBOL(sdhci_clock_enable);

It hopes its client driver, i.e., wifi driver, to call this explicitly to disable clock. Take Atheros for example:

static void hifDeviceRemoved(struct sdio_func *func)
{
    struct mmc_host *host = func->card->host;

    ...
    sdhci_clock_enable(host, 0);
}

static struct sdio_driver ar6k_driver = {
    .name = "ar6k_wlan",
    .id_table = ar6k_id_table,
    .probe = hifDeviceInserted,
    .remove = hifDeviceRemoved,
};

When rmmod this driver, hifDeviceRemoved() got called, it *notifies* host driver to disable clock for it.

 

Why host not smart to disable clock when its client not used?

To look into the host driver more as below,

1066 static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
1067 {
1068         struct sdhci_host *host;
1069         unsigned long flags;
1070
1071         host = mmc_priv(mmc);
1072
1073         /* Enable the clock */
1074         if (!host->plat_data->clk_flg) {
1075                 clk_enable(host->clk);
1076                 host->plat_data->clk_flg = 1;
1077         }
                 ...
         }

It turns on the clock when to access *SD card*, and disables clock after finishing accessing card.

1340 static void sdhci_finish_worker(struct work_struct *work)
1341 {
                 ....

1421         if (req_done && host->plat_data->clk_flg &&
1422                 !(host->plat_data->clk_always_on) &&
1423                 !(func && sdio_func_present(func) && func->dev.driver)) {
1424                 clk_disable(host->clk);
1425                 host->plat_data->clk_flg = 0;
1426         }

                 ....
         }
It checks particularly when it's not SDIO. (Wifi is using SDIO) In other words, host driver can be smart to SD card but not SDIO.

In SD card case, all read/write command issued from host, and always the one way direction, so host can be smart this way.

For SDIO, it is not always that transaction is issued by host. When data packets arrived, it interrupts cpu.

On this case, its clock can not disabled otherwise we can't get the interrupt.

 

One alternative solution is that, we turn one data pin to gpio and configured it as wake up source.

We can then disable SDIO clock, when wifi driver needs to wake up host, it triggers the gpio. Host can then configure the gpio back to data pin and turn on clock.

Not sure if it can really be used this way, just my thought. :-)

1 Reply

793 Views
waterzhou
Contributor V

Can you decrible the ploatform and software version you are using?

We have fixed this issue in our iMX.6 ICS recently.

Why does the clock still on after removing  wifi's driver? "Sdio funcs" are enabled after insmoding wifi drivers. Disable them after rmmoding wifi drivers.

And the sdio devices will be still at present , not removed. This is decided by your hardware designs.

  • If the sdio's power pin and detection pin is into one, our now software logic is right.
  • but if sdio's power pin and detection pin are seperate, this logic will be wrong. In this scenario, removing wifi driver should also including sdio device's removing.

Here I can give two ways to fix this issue:

  1. add force-detect and force-remove function in mmc driver
  2. Enable runtime pm for mmc, add MMC_REMOVE_CARD capacity for host.

For the first way, we can add "force-remove" when doing rmmod driver. Then the sdio devices will  be powered off with clock disabled. when doing insmod driver, we should do "force-detect" card.  For different kernel versin, the patch is also different. Give me your software info I can give you a patch to try.

For the second way, we must enable runtime power management config. and add MMC_REMOVE_CARD capacity for sdhci host. Then it will do power off sdio drivers when doing rmmod driver.

About "One alternative solution is that, we turn one data pin to gpio and configured it as wake up source.We can then disable SDIO clock, when wifi driver needs to wake up host, it triggers the gpio. Host can then configure the gpio back to data pin and turn on clock.", it is an important feature of  wifi----wake up application processor in suspend mode. Only when both wifi and host support this feature, we can then realize it.

Hope this can help you.

0 Kudos