static inline void _sdhci_sprd_set_clock(struct sdhci_host *host, unsigned int clk) { struct sdhci_sprd_host *sprd_host = TO_SPRD_HOST(host); u32 div, val, mask; div = sdhci_sprd_calc_div(sprd_host->base_rate, clk); clk |= ((div & 0x300) >> 2) | ((div & 0xFF) << 8); sdhci_enable_clk(host, clk); /* enable auto gate sdhc_enable_auto_gate */ val = sdhci_readl(host, SDHCI_SPRD_REG_32_BUSY_POSI); mask = SDHCI_SPRD_BIT_OUTR_CLK_AUTO_EN | SDHCI_SPRD_BIT_INNR_CLK_AUTO_EN; if (mask != (val & mask)) { val |= mask; sdhci_writel(host, val, SDHCI_SPRD_REG_32_BUSY_POSI); } }
/** * __sdhci_msm_set_clock - sdhci_msm clock control. * * Description: * MSM controller does not use internal divider and * instead directly control the GCC clock as per * HW recommendation. **/ void __sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock) { u16 clk; /* * Keep actual_clock as zero - * - since there is no divider used so no need of having actual_clock. * - MSM controller uses SDCLK for data timeout calculation. If * actual_clock is zero, host->clock is taken for calculation. */ host->mmc->actual_clock = 0; sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); if (clock == 0) return; /* * MSM controller do not use clock divider. * Thus read SDHCI_CLOCK_CONTROL and only enable * clock with no divider value programmed. */ clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); sdhci_enable_clk(host, clk); }