mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 02:39:48 +00:00
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:
parent
2317f56c05
commit
03231f9b78
19 changed files with 53 additions and 31 deletions
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue