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 коммит произвёл Chris Ball
Родитель 2317f56c05
Коммит 03231f9b78
19 изменённых файлов: 53 добавлений и 31 удалений

Просмотреть файл

@ -104,11 +104,13 @@ static void sdhci_acpi_int_hw_reset(struct sdhci_host *host)
static const struct sdhci_ops sdhci_acpi_ops_dflt = { static const struct sdhci_ops sdhci_acpi_ops_dflt = {
.enable_dma = sdhci_acpi_enable_dma, .enable_dma = sdhci_acpi_enable_dma,
.set_bus_width = sdhci_set_bus_width, .set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
}; };
static const struct sdhci_ops sdhci_acpi_ops_int = { static const struct sdhci_ops sdhci_acpi_ops_int = {
.enable_dma = sdhci_acpi_enable_dma, .enable_dma = sdhci_acpi_enable_dma,
.set_bus_width = sdhci_set_bus_width, .set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
.hw_reset = sdhci_acpi_int_hw_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, .get_timeout_clock = sdhci_bcm_kona_get_timeout_clock,
.platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks, .platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks,
.set_bus_width = sdhci_set_bus_width, .set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
.card_event = sdhci_bcm_kona_card_event, .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_max_clock = sdhci_pltfm_clk_get_max_clock,
.get_min_clock = bcm2835_sdhci_get_min_clock, .get_min_clock = bcm2835_sdhci_get_min_clock,
.set_bus_width = sdhci_set_bus_width, .set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
}; };
static const struct sdhci_pltfm_data bcm2835_sdhci_pdata = { 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, .get_max_clock = sdhci_cns3xxx_get_max_clk,
.set_clock = sdhci_cns3xxx_set_clock, .set_clock = sdhci_cns3xxx_set_clock,
.set_bus_width = sdhci_set_bus_width, .set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
}; };
static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = { 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_w = sdhci_dove_readw,
.read_l = sdhci_dove_readl, .read_l = sdhci_dove_readl,
.set_bus_width = sdhci_set_bus_width, .set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
}; };
static const struct sdhci_pltfm_data sdhci_dove_pdata = { 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, .get_ro = esdhc_pltfm_get_ro,
.set_bus_width = esdhc_pltfm_set_bus_width, .set_bus_width = esdhc_pltfm_set_bus_width,
.set_uhs_signaling = esdhc_set_uhs_signaling, .set_uhs_signaling = esdhc_set_uhs_signaling,
.reset = sdhci_reset,
}; };
static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { 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_max_clock = sdhci_pltfm_clk_get_max_clock,
.get_timeout_clock = sdhci_arasan_get_timeout_clock, .get_timeout_clock = sdhci_arasan_get_timeout_clock,
.set_bus_width = sdhci_set_bus_width, .set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
}; };
static struct sdhci_pltfm_data sdhci_arasan_pdata = { static struct sdhci_pltfm_data sdhci_arasan_pdata = {

Просмотреть файл

@ -309,6 +309,7 @@ static const struct sdhci_ops sdhci_esdhc_ops = {
#endif #endif
.adma_workaround = esdhci_of_adma_workaround, .adma_workaround = esdhci_of_adma_workaround,
.set_bus_width = esdhc_pltfm_set_bus_width, .set_bus_width = esdhc_pltfm_set_bus_width,
.reset = sdhci_reset,
}; };
static const struct sdhci_pltfm_data sdhci_esdhc_pdata = { 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_w = sdhci_hlwd_writew,
.write_b = sdhci_hlwd_writeb, .write_b = sdhci_hlwd_writeb,
.set_bus_width = sdhci_set_bus_width, .set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
}; };
static const struct sdhci_pltfm_data sdhci_hlwd_pdata = { 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 = { static const struct sdhci_ops sdhci_pci_ops = {
.enable_dma = sdhci_pci_enable_dma, .enable_dma = sdhci_pci_enable_dma,
.set_bus_width = sdhci_pci_set_bus_width, .set_bus_width = sdhci_pci_set_bus_width,
.reset = sdhci_reset,
.hw_reset = sdhci_pci_hw_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 = { static const struct sdhci_ops sdhci_pltfm_ops = {
.set_bus_width = sdhci_set_bus_width, .set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
}; };
#ifdef CONFIG_OF #ifdef CONFIG_OF

Просмотреть файл

@ -51,11 +51,13 @@
#define MMC_CARD 0x1000 #define MMC_CARD 0x1000
#define MMC_WIDTH 0x0100 #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 platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
sdhci_reset(host, mask);
if (mask == SDHCI_RESET_ALL) { if (mask == SDHCI_RESET_ALL) {
u16 tmp = 0; 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 = { static const struct sdhci_ops pxav2_sdhci_ops = {
.get_max_clock = sdhci_pltfm_clk_get_max_clock, .get_max_clock = sdhci_pltfm_clk_get_max_clock,
.platform_reset_exit = pxav2_set_private_registers,
.set_bus_width = pxav2_mmc_set_bus_width, .set_bus_width = pxav2_mmc_set_bus_width,
.reset = pxav2_reset,
}; };
#ifdef CONFIG_OF #ifdef CONFIG_OF

Просмотреть файл

@ -112,11 +112,13 @@ static int mv_conf_mbus_windows(struct platform_device *pdev,
return 0; 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 platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
sdhci_reset(host, mask);
if (mask == SDHCI_RESET_ALL) { if (mask == SDHCI_RESET_ALL) {
/* /*
* tune timing of read data/command when crc error happen * 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 = { static const struct sdhci_ops pxav3_sdhci_ops = {
.platform_reset_exit = pxav3_set_private_registers,
.set_uhs_signaling = pxav3_set_uhs_signaling, .set_uhs_signaling = pxav3_set_uhs_signaling,
.platform_send_init_74_clocks = pxav3_gen_init_74_clocks, .platform_send_init_74_clocks = pxav3_gen_init_74_clocks,
.get_max_clock = sdhci_pltfm_clk_get_max_clock, .get_max_clock = sdhci_pltfm_clk_get_max_clock,
.set_bus_width = sdhci_set_bus_width, .set_bus_width = sdhci_set_bus_width,
.reset = pxav3_reset,
}; };
static struct sdhci_pltfm_data sdhci_pxav3_pdata = { 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, .set_clock = sdhci_s3c_set_clock,
.get_min_clock = sdhci_s3c_get_min_clock, .get_min_clock = sdhci_s3c_get_min_clock,
.set_bus_width = sdhci_s3c_set_bus_width, .set_bus_width = sdhci_s3c_set_bus_width,
.reset = sdhci_reset,
}; };
static void sdhci_s3c_notify_change(struct platform_device *dev, int state) 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 = { static struct sdhci_ops sdhci_sirf_ops = {
.get_max_clock = sdhci_sirf_get_max_clk, .get_max_clock = sdhci_sirf_get_max_clk,
.set_bus_width = sdhci_set_bus_width, .set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
}; };
static struct sdhci_pltfm_data sdhci_sirf_pdata = { static struct sdhci_pltfm_data sdhci_sirf_pdata = {

Просмотреть файл

@ -39,6 +39,7 @@ struct spear_sdhci {
/* sdhci ops */ /* sdhci ops */
static const struct sdhci_ops sdhci_pltfm_ops = { static const struct sdhci_ops sdhci_pltfm_ops = {
.set_bus_width = sdhci_set_bus_width, .set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
}; };
#ifdef CONFIG_OF #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); 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_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_tegra *tegra_host = pltfm_host->priv; struct sdhci_tegra *tegra_host = pltfm_host->priv;
const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
sdhci_reset(host, mask);
if (!(mask & SDHCI_RESET_ALL)) if (!(mask & SDHCI_RESET_ALL))
return; return;
@ -152,7 +154,7 @@ static const struct sdhci_ops tegra_sdhci_ops = {
.read_w = tegra_sdhci_readw, .read_w = tegra_sdhci_readw,
.write_l = tegra_sdhci_writel, .write_l = tegra_sdhci_writel,
.set_bus_width = tegra_sdhci_set_bus_width, .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 = { 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); 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; 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); sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET);
@ -198,9 +190,18 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask)
timeout--; timeout--;
mdelay(1); mdelay(1);
} }
}
EXPORT_SYMBOL_GPL(sdhci_reset);
if (host->ops->platform_reset_exit) static void sdhci_do_reset(struct sdhci_host *host, u8 mask)
host->ops->platform_reset_exit(host, 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) { if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) {
sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); 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) static void sdhci_init(struct sdhci_host *host, int soft)
{ {
if (soft) if (soft)
sdhci_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA); sdhci_do_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA);
else 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 | host->ier = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT |
@ -962,8 +963,8 @@ static void sdhci_finish_data(struct sdhci_host *host)
* upon error conditions. * upon error conditions.
*/ */
if (data->error) { if (data->error) {
sdhci_reset(host, SDHCI_RESET_CMD); sdhci_do_reset(host, SDHCI_RESET_CMD);
sdhci_reset(host, SDHCI_RESET_DATA); sdhci_do_reset(host, SDHCI_RESET_DATA);
} }
sdhci_send_command(host, data->stop); 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. * it on each ios seems to solve the problem.
*/ */
if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) 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(); mmiowb();
spin_unlock_irqrestore(&host->lock, flags); 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", pr_err("%s: Resetting controller.\n",
mmc_hostname(host->mmc)); mmc_hostname(host->mmc));
sdhci_reset(host, SDHCI_RESET_CMD); sdhci_do_reset(host, SDHCI_RESET_CMD);
sdhci_reset(host, SDHCI_RESET_DATA); sdhci_do_reset(host, SDHCI_RESET_DATA);
host->mrq->cmd->error = -ENOMEDIUM; host->mrq->cmd->error = -ENOMEDIUM;
tasklet_schedule(&host->finish_tasklet); 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 /* Spec says we should do both at the same time, but Ricoh
controllers do not like that. */ controllers do not like that. */
sdhci_reset(host, SDHCI_RESET_CMD); sdhci_do_reset(host, SDHCI_RESET_CMD);
sdhci_reset(host, SDHCI_RESET_DATA); sdhci_do_reset(host, SDHCI_RESET_DATA);
} }
host->mrq = NULL; host->mrq = NULL;
@ -2791,7 +2792,7 @@ int sdhci_add_host(struct sdhci_host *host)
if (debug_quirks2) if (debug_quirks2)
host->quirks2 = 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 = sdhci_readw(host, SDHCI_HOST_VERSION);
host->version = (host->version & SDHCI_SPEC_VER_MASK) 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 #ifdef SDHCI_USE_LEDS_CLASS
reset: 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_INT_ENABLE);
sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
free_irq(host->irq, host); free_irq(host->irq, host);
@ -3317,7 +3318,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
#endif #endif
if (!dead) 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_INT_ENABLE);
sdhci_writel(host, 0, SDHCI_SIGNAL_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, void (*platform_send_init_74_clocks)(struct sdhci_host *host,
u8 power_mode); u8 power_mode);
unsigned int (*get_ro)(struct sdhci_host *host); unsigned int (*get_ro)(struct sdhci_host *host);
void (*platform_reset_enter)(struct sdhci_host *host, u8 mask); void (*reset)(struct sdhci_host *host, u8 mask);
void (*platform_reset_exit)(struct sdhci_host *host, u8 mask);
int (*platform_execute_tuning)(struct sdhci_host *host, u32 opcode); int (*platform_execute_tuning)(struct sdhci_host *host, u32 opcode);
int (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs); int (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
void (*hw_reset)(struct sdhci_host *host); 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_set_bus_width(struct sdhci_host *host, int width);
void sdhci_reset(struct sdhci_host *host, u8 mask);
#ifdef CONFIG_PM #ifdef CONFIG_PM
extern int sdhci_suspend_host(struct sdhci_host *host); extern int sdhci_suspend_host(struct sdhci_host *host);