mmc: sdhci: convert reset into a library function

Rather than having platform_reset_enter/platform_reset_exit methods,
turn the core of the reset handling into a library function which
platforms can call at the appropriate moment in their (new) reset
method.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Tested-by: Markus Pargmann <mpa@pengutronix.de>
Tested-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Chris Ball <chris@printf.net>
This commit is contained in:
Russell King 2014-04-25 12:57:12 +01:00 committed by Chris Ball
parent 2317f56c05
commit 03231f9b78
19 changed files with 53 additions and 31 deletions

View File

@ -104,11 +104,13 @@ static void sdhci_acpi_int_hw_reset(struct sdhci_host *host)
static const struct sdhci_ops sdhci_acpi_ops_dflt = {
.enable_dma = sdhci_acpi_enable_dma,
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
};
static const struct sdhci_ops sdhci_acpi_ops_int = {
.enable_dma = sdhci_acpi_enable_dma,
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
.hw_reset = sdhci_acpi_int_hw_reset,
};

View File

@ -210,6 +210,7 @@ static struct sdhci_ops sdhci_bcm_kona_ops = {
.get_timeout_clock = sdhci_bcm_kona_get_timeout_clock,
.platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks,
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
.card_event = sdhci_bcm_kona_card_event,
};

View File

@ -134,6 +134,7 @@ static const struct sdhci_ops bcm2835_sdhci_ops = {
.get_max_clock = sdhci_pltfm_clk_get_max_clock,
.get_min_clock = bcm2835_sdhci_get_min_clock,
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
};
static const struct sdhci_pltfm_data bcm2835_sdhci_pdata = {

View File

@ -83,6 +83,7 @@ static const struct sdhci_ops sdhci_cns3xxx_ops = {
.get_max_clock = sdhci_cns3xxx_get_max_clk,
.set_clock = sdhci_cns3xxx_set_clock,
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
};
static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {

View File

@ -87,6 +87,7 @@ static const struct sdhci_ops sdhci_dove_ops = {
.read_w = sdhci_dove_readw,
.read_l = sdhci_dove_readl,
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
};
static const struct sdhci_pltfm_data sdhci_dove_pdata = {

View File

@ -888,6 +888,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
.get_ro = esdhc_pltfm_get_ro,
.set_bus_width = esdhc_pltfm_set_bus_width,
.set_uhs_signaling = esdhc_set_uhs_signaling,
.reset = sdhci_reset,
};
static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {

View File

@ -55,6 +55,7 @@ static struct sdhci_ops sdhci_arasan_ops = {
.get_max_clock = sdhci_pltfm_clk_get_max_clock,
.get_timeout_clock = sdhci_arasan_get_timeout_clock,
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
};
static struct sdhci_pltfm_data sdhci_arasan_pdata = {

View File

@ -309,6 +309,7 @@ static const struct sdhci_ops sdhci_esdhc_ops = {
#endif
.adma_workaround = esdhci_of_adma_workaround,
.set_bus_width = esdhc_pltfm_set_bus_width,
.reset = sdhci_reset,
};
static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {

View File

@ -59,6 +59,7 @@ static const struct sdhci_ops sdhci_hlwd_ops = {
.write_w = sdhci_hlwd_writew,
.write_b = sdhci_hlwd_writeb,
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
};
static const struct sdhci_pltfm_data sdhci_hlwd_pdata = {

View File

@ -1080,6 +1080,7 @@ static void sdhci_pci_hw_reset(struct sdhci_host *host)
static const struct sdhci_ops sdhci_pci_ops = {
.enable_dma = sdhci_pci_enable_dma,
.set_bus_width = sdhci_pci_set_bus_width,
.reset = sdhci_reset,
.hw_reset = sdhci_pci_hw_reset,
};

View File

@ -46,6 +46,7 @@ EXPORT_SYMBOL_GPL(sdhci_pltfm_clk_get_max_clock);
static const struct sdhci_ops sdhci_pltfm_ops = {
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
};
#ifdef CONFIG_OF

View File

@ -51,11 +51,13 @@
#define MMC_CARD 0x1000
#define MMC_WIDTH 0x0100
static void pxav2_set_private_registers(struct sdhci_host *host, u8 mask)
static void pxav2_reset(struct sdhci_host *host, u8 mask)
{
struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
sdhci_reset(host, mask);
if (mask == SDHCI_RESET_ALL) {
u16 tmp = 0;
@ -111,8 +113,8 @@ static void pxav2_mmc_set_bus_width(struct sdhci_host *host, int width)
static const struct sdhci_ops pxav2_sdhci_ops = {
.get_max_clock = sdhci_pltfm_clk_get_max_clock,
.platform_reset_exit = pxav2_set_private_registers,
.set_bus_width = pxav2_mmc_set_bus_width,
.reset = pxav2_reset,
};
#ifdef CONFIG_OF

View File

@ -112,11 +112,13 @@ static int mv_conf_mbus_windows(struct platform_device *pdev,
return 0;
}
static void pxav3_set_private_registers(struct sdhci_host *host, u8 mask)
static void pxav3_reset(struct sdhci_host *host, u8 mask)
{
struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
sdhci_reset(host, mask);
if (mask == SDHCI_RESET_ALL) {
/*
* tune timing of read data/command when crc error happen
@ -223,11 +225,11 @@ static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
}
static const struct sdhci_ops pxav3_sdhci_ops = {
.platform_reset_exit = pxav3_set_private_registers,
.set_uhs_signaling = pxav3_set_uhs_signaling,
.platform_send_init_74_clocks = pxav3_gen_init_74_clocks,
.get_max_clock = sdhci_pltfm_clk_get_max_clock,
.set_bus_width = sdhci_set_bus_width,
.reset = pxav3_reset,
};
static struct sdhci_pltfm_data sdhci_pxav3_pdata = {

View File

@ -362,6 +362,7 @@ static struct sdhci_ops sdhci_s3c_ops = {
.set_clock = sdhci_s3c_set_clock,
.get_min_clock = sdhci_s3c_get_min_clock,
.set_bus_width = sdhci_s3c_set_bus_width,
.reset = sdhci_reset,
};
static void sdhci_s3c_notify_change(struct platform_device *dev, int state)

View File

@ -30,6 +30,7 @@ static unsigned int sdhci_sirf_get_max_clk(struct sdhci_host *host)
static struct sdhci_ops sdhci_sirf_ops = {
.get_max_clock = sdhci_sirf_get_max_clk,
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
};
static struct sdhci_pltfm_data sdhci_sirf_pdata = {

View File

@ -39,6 +39,7 @@ struct spear_sdhci {
/* sdhci ops */
static const struct sdhci_ops sdhci_pltfm_ops = {
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
};
#ifdef CONFIG_OF

View File

@ -108,12 +108,14 @@ static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host)
return mmc_gpio_get_ro(host->mmc);
}
static void tegra_sdhci_reset_exit(struct sdhci_host *host, u8 mask)
static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_tegra *tegra_host = pltfm_host->priv;
const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
sdhci_reset(host, mask);
if (!(mask & SDHCI_RESET_ALL))
return;
@ -152,7 +154,7 @@ static const struct sdhci_ops tegra_sdhci_ops = {
.read_w = tegra_sdhci_readw,
.write_l = tegra_sdhci_writel,
.set_bus_width = tegra_sdhci_set_bus_width,
.platform_reset_exit = tegra_sdhci_reset_exit,
.reset = tegra_sdhci_reset,
};
static const struct sdhci_pltfm_data sdhci_tegra20_pdata = {

View File

@ -163,17 +163,9 @@ static void sdhci_disable_card_detection(struct sdhci_host *host)
sdhci_set_card_detection(host, false);
}
static void sdhci_reset(struct sdhci_host *host, u8 mask)
void sdhci_reset(struct sdhci_host *host, u8 mask)
{
unsigned long timeout;
if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) &
SDHCI_CARD_PRESENT))
return;
}
if (host->ops->platform_reset_enter)
host->ops->platform_reset_enter(host, mask);
sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET);
@ -198,9 +190,18 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask)
timeout--;
mdelay(1);
}
}
EXPORT_SYMBOL_GPL(sdhci_reset);
if (host->ops->platform_reset_exit)
host->ops->platform_reset_exit(host, mask);
static void sdhci_do_reset(struct sdhci_host *host, u8 mask)
{
if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) &
SDHCI_CARD_PRESENT))
return;
}
host->ops->reset(host, mask);
if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) {
sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
@ -218,9 +219,9 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios);
static void sdhci_init(struct sdhci_host *host, int soft)
{
if (soft)
sdhci_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA);
sdhci_do_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA);
else
sdhci_reset(host, SDHCI_RESET_ALL);
sdhci_do_reset(host, SDHCI_RESET_ALL);
host->ier = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT |
@ -962,8 +963,8 @@ static void sdhci_finish_data(struct sdhci_host *host)
* upon error conditions.
*/
if (data->error) {
sdhci_reset(host, SDHCI_RESET_CMD);
sdhci_reset(host, SDHCI_RESET_DATA);
sdhci_do_reset(host, SDHCI_RESET_CMD);
sdhci_do_reset(host, SDHCI_RESET_DATA);
}
sdhci_send_command(host, data->stop);
@ -1587,7 +1588,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
* it on each ios seems to solve the problem.
*/
if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS)
sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
mmiowb();
spin_unlock_irqrestore(&host->lock, flags);
@ -2086,8 +2087,8 @@ static void sdhci_card_event(struct mmc_host *mmc)
pr_err("%s: Resetting controller.\n",
mmc_hostname(host->mmc));
sdhci_reset(host, SDHCI_RESET_CMD);
sdhci_reset(host, SDHCI_RESET_DATA);
sdhci_do_reset(host, SDHCI_RESET_CMD);
sdhci_do_reset(host, SDHCI_RESET_DATA);
host->mrq->cmd->error = -ENOMEDIUM;
tasklet_schedule(&host->finish_tasklet);
@ -2155,8 +2156,8 @@ static void sdhci_tasklet_finish(unsigned long param)
/* Spec says we should do both at the same time, but Ricoh
controllers do not like that. */
sdhci_reset(host, SDHCI_RESET_CMD);
sdhci_reset(host, SDHCI_RESET_DATA);
sdhci_do_reset(host, SDHCI_RESET_CMD);
sdhci_do_reset(host, SDHCI_RESET_DATA);
}
host->mrq = NULL;
@ -2791,7 +2792,7 @@ int sdhci_add_host(struct sdhci_host *host)
if (debug_quirks2)
host->quirks2 = debug_quirks2;
sdhci_reset(host, SDHCI_RESET_ALL);
sdhci_do_reset(host, SDHCI_RESET_ALL);
host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
host->version = (host->version & SDHCI_SPEC_VER_MASK)
@ -3275,7 +3276,7 @@ int sdhci_add_host(struct sdhci_host *host)
#ifdef SDHCI_USE_LEDS_CLASS
reset:
sdhci_reset(host, SDHCI_RESET_ALL);
sdhci_do_reset(host, SDHCI_RESET_ALL);
sdhci_writel(host, 0, SDHCI_INT_ENABLE);
sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
free_irq(host->irq, host);
@ -3317,7 +3318,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
#endif
if (!dead)
sdhci_reset(host, SDHCI_RESET_ALL);
sdhci_do_reset(host, SDHCI_RESET_ALL);
sdhci_writel(host, 0, SDHCI_INT_ENABLE);
sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);

View File

@ -285,8 +285,7 @@ struct sdhci_ops {
void (*platform_send_init_74_clocks)(struct sdhci_host *host,
u8 power_mode);
unsigned int (*get_ro)(struct sdhci_host *host);
void (*platform_reset_enter)(struct sdhci_host *host, u8 mask);
void (*platform_reset_exit)(struct sdhci_host *host, u8 mask);
void (*reset)(struct sdhci_host *host, u8 mask);
int (*platform_execute_tuning)(struct sdhci_host *host, u32 opcode);
int (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
void (*hw_reset)(struct sdhci_host *host);
@ -402,6 +401,7 @@ static inline bool sdhci_sdio_irq_enabled(struct sdhci_host *host)
}
void sdhci_set_bus_width(struct sdhci_host *host, int width);
void sdhci_reset(struct sdhci_host *host, u8 mask);
#ifdef CONFIG_PM
extern int sdhci_suspend_host(struct sdhci_host *host);