Commit 774c0103 authored by Maxime Ripard's avatar Maxime Ripard Committed by Ulf Hansson

mmc: sunxi: Move resources management to separate functions

We've had all our resources management, and especially the clocks and reset
sequence, done directly as part of the probe.

As we want to implement runtime_pm, we'll obviously want to have that
moved outside of the probe so that we can call do it in our runtime suspend
and resume hooks without too much duplication.
Signed-off-by: default avatarMaxime Ripard <maxime.ripard@bootlin.com>
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent e382ab74
......@@ -268,6 +268,7 @@ struct sunxi_mmc_cfg {
};
struct sunxi_mmc_host {
struct device *dev;
struct mmc_host *mmc;
struct reset_control *reset;
const struct sunxi_mmc_cfg *cfg;
......@@ -1165,6 +1166,80 @@ static const struct of_device_id sunxi_mmc_of_match[] = {
};
MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match);
static int sunxi_mmc_enable(struct sunxi_mmc_host *host)
{
int ret;
ret = clk_prepare_enable(host->clk_ahb);
if (ret) {
dev_err(dev, "Couldn't enable the bus clocks (%d)\n", ret);
return ret;
}
ret = clk_prepare_enable(host->clk_mmc);
if (ret) {
dev_err(host->dev, "Enable mmc clk err %d\n", ret);
goto error_disable_clk_ahb;
}
ret = clk_prepare_enable(host->clk_output);
if (ret) {
dev_err(host->dev, "Enable output clk err %d\n", ret);
goto error_disable_clk_mmc;
}
ret = clk_prepare_enable(host->clk_sample);
if (ret) {
dev_err(host->dev, "Enable sample clk err %d\n", ret);
goto error_disable_clk_output;
}
if (!IS_ERR(host->reset)) {
ret = reset_control_reset(host->reset);
if (ret) {
dev_err(dev, "Couldn't reset the MMC controller (%d)\n",
ret);
goto error_disable_clk_sample;
}
}
/*
* Sometimes the controller asserts the irq on boot for some reason,
* make sure the controller is in a sane state before enabling irqs.
*/
ret = sunxi_mmc_reset_host(host);
if (ret)
goto error_assert_reset;
return 0;
error_assert_reset:
if (!IS_ERR(host->reset))
reset_control_assert(host->reset);
error_disable_clk_sample:
clk_disable_unprepare(host->clk_sample);
error_disable_clk_output:
clk_disable_unprepare(host->clk_output);
error_disable_clk_mmc:
clk_disable_unprepare(host->clk_mmc);
error_disable_clk_ahb:
clk_disable_unprepare(host->clk_ahb);
return ret;
}
static void sunxi_mmc_disable(struct sunxi_mmc_host *host)
{
sunxi_mmc_reset_host(host);
if (!IS_ERR(host->reset))
reset_control_assert(host->reset);
clk_disable_unprepare(host->clk_sample);
clk_disable_unprepare(host->clk_output);
clk_disable_unprepare(host->clk_mmc);
clk_disable_unprepare(host->clk_ahb);
}
static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
struct platform_device *pdev)
{
......@@ -1214,66 +1289,21 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
if (PTR_ERR(host->reset) == -EPROBE_DEFER)
return PTR_ERR(host->reset);
ret = clk_prepare_enable(host->clk_ahb);
if (ret) {
dev_err(&pdev->dev, "Enable ahb clk err %d\n", ret);
return ret;
}
ret = clk_prepare_enable(host->clk_mmc);
if (ret) {
dev_err(&pdev->dev, "Enable mmc clk err %d\n", ret);
goto error_disable_clk_ahb;
}
ret = clk_prepare_enable(host->clk_output);
if (ret) {
dev_err(&pdev->dev, "Enable output clk err %d\n", ret);
goto error_disable_clk_mmc;
}
ret = clk_prepare_enable(host->clk_sample);
if (ret) {
dev_err(&pdev->dev, "Enable sample clk err %d\n", ret);
goto error_disable_clk_output;
}
if (!IS_ERR(host->reset)) {
ret = reset_control_reset(host->reset);
if (ret) {
dev_err(&pdev->dev, "reset err %d\n", ret);
goto error_disable_clk_sample;
}
}
/*
* Sometimes the controller asserts the irq on boot for some reason,
* make sure the controller is in a sane state before enabling irqs.
*/
ret = sunxi_mmc_reset_host(host);
ret = sunxi_mmc_enable(host);
if (ret)
goto error_assert_reset;
return ret;
host->irq = platform_get_irq(pdev, 0);
if (host->irq <= 0) {
ret = -EINVAL;
goto error_assert_reset;
goto error_disable_mmc;
}
return devm_request_threaded_irq(&pdev->dev, host->irq, sunxi_mmc_irq,
sunxi_mmc_handle_manual_stop, 0, "sunxi-mmc", host);
error_assert_reset:
if (!IS_ERR(host->reset))
reset_control_assert(host->reset);
error_disable_clk_sample:
clk_disable_unprepare(host->clk_sample);
error_disable_clk_output:
clk_disable_unprepare(host->clk_output);
error_disable_clk_mmc:
clk_disable_unprepare(host->clk_mmc);
error_disable_clk_ahb:
clk_disable_unprepare(host->clk_ahb);
error_disable_mmc:
sunxi_mmc_disable(host);
return ret;
}
......@@ -1290,6 +1320,7 @@ static int sunxi_mmc_probe(struct platform_device *pdev)
}
host = mmc_priv(mmc);
host->dev = &pdev->dev;
host->mmc = mmc;
spin_lock_init(&host->lock);
......@@ -1370,16 +1401,7 @@ static int sunxi_mmc_remove(struct platform_device *pdev)
mmc_remove_host(mmc);
disable_irq(host->irq);
sunxi_mmc_reset_host(host);
if (!IS_ERR(host->reset))
reset_control_assert(host->reset);
clk_disable_unprepare(host->clk_sample);
clk_disable_unprepare(host->clk_output);
clk_disable_unprepare(host->clk_mmc);
clk_disable_unprepare(host->clk_ahb);
sunxi_mmc_disable(host);
dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
mmc_free_host(mmc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment