From: Ludovic Barre <ludovic.barre@xxxxxx> A specific variant could have different power or clock procedures. This patch allows to overwrite the default mmci_set_clkreg and mmci_set_pwrreg for a specific variant. Signed-off-by: Ludovic Barre <ludovic.barre@xxxxxx> --- drivers/mmc/host/mmci.c | 96 +++++++++++++++++++++++++++++-------------------- drivers/mmc/host/mmci.h | 7 ++++ 2 files changed, 64 insertions(+), 39 deletions(-) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index ede95b7..801c86b 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -374,6 +374,52 @@ static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired) mmci_write_clkreg(host, clk); } +static void mmci_set_pwrreg(struct mmci_host *host, unsigned char power_mode, + unsigned int pwr) +{ + struct variant_data *variant = host->variant; + struct mmc_host *mmc = host->mmc; + + switch (power_mode) { + case MMC_POWER_OFF: + if (!IS_ERR(mmc->supply.vmmc)) + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); + + if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled) { + regulator_disable(mmc->supply.vqmmc); + host->vqmmc_enabled = false; + } + + break; + case MMC_POWER_UP: + if (!IS_ERR(mmc->supply.vmmc)) + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, + mmc->ios.vdd); + + /* + * The ST Micro variant doesn't have the PL180s MCI_PWR_UP + * and instead uses MCI_PWR_ON so apply whatever value is + * configured in the variant data. + */ + pwr |= variant->pwrreg_powerup; + + break; + case MMC_POWER_ON: + if (!IS_ERR(mmc->supply.vqmmc) && !host->vqmmc_enabled) { + if (regulator_enable(mmc->supply.vqmmc) < 0) + dev_err(mmc_dev(mmc), + "failed to enable vqmmc regulator\n"); + else + host->vqmmc_enabled = true; + } + + pwr |= MCI_PWR_ON; + break; + } + + mmci_write_pwrreg(host, pwr); +} + static void mmci_request_end(struct mmci_host *host, struct mmc_request *mrq) { @@ -1031,7 +1077,7 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { struct mmci_host *host = mmc_priv(mmc); struct variant_data *variant = host->variant; - u32 pwr = 0; + unsigned int pwr = 0; unsigned long flags; int ret; @@ -1039,42 +1085,6 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) host->plat->ios_handler(mmc_dev(mmc), ios)) dev_err(mmc_dev(mmc), "platform ios_handler failed\n"); - switch (ios->power_mode) { - case MMC_POWER_OFF: - if (!IS_ERR(mmc->supply.vmmc)) - mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); - - if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled) { - regulator_disable(mmc->supply.vqmmc); - host->vqmmc_enabled = false; - } - - break; - case MMC_POWER_UP: - if (!IS_ERR(mmc->supply.vmmc)) - mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd); - - /* - * The ST Micro variant doesn't have the PL180s MCI_PWR_UP - * and instead uses MCI_PWR_ON so apply whatever value is - * configured in the variant data. - */ - pwr |= variant->pwrreg_powerup; - - break; - case MMC_POWER_ON: - if (!IS_ERR(mmc->supply.vqmmc) && !host->vqmmc_enabled) { - ret = regulator_enable(mmc->supply.vqmmc); - if (ret < 0) - dev_err(mmc_dev(mmc), - "failed to enable vqmmc regulator\n"); - else - host->vqmmc_enabled = true; - } - - pwr |= MCI_PWR_ON; - break; - } if (variant->signal_direction && ios->power_mode != MMC_POWER_OFF) { /* @@ -1126,8 +1136,16 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) spin_lock_irqsave(&host->lock, flags); - mmci_set_clkreg(host, ios->clock); - mmci_write_pwrreg(host, pwr); + if (variant->set_clkreg) + variant->set_clkreg(host, ios->clock); + else + mmci_set_clkreg(host, ios->clock); + + if (variant->set_pwrreg) + variant->set_pwrreg(host, ios->power_mode, pwr); + else + mmci_set_pwrreg(host, ios->power_mode, pwr); + mmci_reg_delay(host); spin_unlock_irqrestore(&host->lock, flags); diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index 2ba9640..7265ca6 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h @@ -231,6 +231,7 @@ struct clk; struct dma_chan; +struct mmci_host; /** * struct variant_data - MMCI variant-specific quirks @@ -273,6 +274,8 @@ struct dma_chan; * register. * @opendrain: bitmask identifying the OPENDRAIN bit inside MMCIPOWER register * @mmci_dma: Pointer to platform-specific DMA callbacks. + * @set_clk_ios: if clock procedure of variant is specific + * @set_pwr_ios: if power procedure of variant is specific */ struct variant_data { unsigned int clkreg; @@ -307,6 +310,9 @@ struct variant_data { u32 start_err; u32 opendrain; struct mmci_dma_ops *mmci_dma; + void (*set_clkreg)(struct mmci_host *host, unsigned int desired); + void (*set_pwrreg)(struct mmci_host *host, unsigned char power_mode, + unsigned int pwr); }; struct mmci_host { @@ -328,6 +334,7 @@ struct mmci_host { u32 pwr_reg; u32 pwr_reg_add; u32 clk_reg; + u32 clk_reg_add; u32 datactrl_reg; u32 busy_status; u32 mask1_reg; -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html