mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-20 00:46:22 +07:00
mmc: sunxi: Convert MMC driver to the standard clock phase API
Now that we have proper support to use the generic phase API in our clock driver, switch the MMC driver to use it. Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> Acked-by: Ulf Hansson <ulf.hansson@linaro.org> Acked-by: David Lanzendörfer <david.lanzendoerfer@o2s.ch> Reviewed-by: Chen-Yu Tsai <wens@csie.org> Tested-by: Chen-Yu Tsai <wens@csie.org>
This commit is contained in:
parent
d8c3a392a5
commit
6c09bb851e
@ -10,8 +10,8 @@ Absolute maximum transfer rate is 200MB/s
|
||||
Required properties:
|
||||
- compatible : "allwinner,sun4i-a10-mmc" or "allwinner,sun5i-a13-mmc"
|
||||
- reg : mmc controller base registers
|
||||
- clocks : a list with 2 phandle + clock specifier pairs
|
||||
- clock-names : must contain "ahb" and "mmc"
|
||||
- clocks : a list with 4 phandle + clock specifier pairs
|
||||
- clock-names : must contain "ahb", "mmc", "output" and "sample"
|
||||
- interrupts : mmc controller interrupt
|
||||
|
||||
Optional properties:
|
||||
@ -25,8 +25,8 @@ Examples:
|
||||
mmc0: mmc@01c0f000 {
|
||||
compatible = "allwinner,sun5i-a13-mmc";
|
||||
reg = <0x01c0f000 0x1000>;
|
||||
clocks = <&ahb_gates 8>, <&mmc0_clk>;
|
||||
clock-names = "ahb", "mod";
|
||||
clocks = <&ahb_gates 8>, <&mmc0_clk>, <&mmc0_output_clk>, <&mmc0_sample_clk>;
|
||||
clock-names = "ahb", "mod", "output", "sample";
|
||||
interrupts = <0 32 4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
@ -21,8 +21,6 @@
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk/sunxi.h>
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spinlock.h>
|
||||
@ -229,6 +227,8 @@ struct sunxi_mmc_host {
|
||||
/* clock management */
|
||||
struct clk *clk_ahb;
|
||||
struct clk *clk_mmc;
|
||||
struct clk *clk_sample;
|
||||
struct clk *clk_output;
|
||||
|
||||
/* irq */
|
||||
spinlock_t lock;
|
||||
@ -616,7 +616,7 @@ static int sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en)
|
||||
static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host,
|
||||
struct mmc_ios *ios)
|
||||
{
|
||||
u32 rate, oclk_dly, rval, sclk_dly, src_clk;
|
||||
u32 rate, oclk_dly, rval, sclk_dly;
|
||||
int ret;
|
||||
|
||||
rate = clk_round_rate(host->clk_mmc, ios->clock);
|
||||
@ -642,34 +642,31 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host,
|
||||
|
||||
/* determine delays */
|
||||
if (rate <= 400000) {
|
||||
oclk_dly = 0;
|
||||
sclk_dly = 7;
|
||||
oclk_dly = 180;
|
||||
sclk_dly = 42;
|
||||
} else if (rate <= 25000000) {
|
||||
oclk_dly = 0;
|
||||
sclk_dly = 5;
|
||||
oclk_dly = 180;
|
||||
sclk_dly = 75;
|
||||
} else if (rate <= 50000000) {
|
||||
if (ios->timing == MMC_TIMING_UHS_DDR50) {
|
||||
oclk_dly = 2;
|
||||
sclk_dly = 4;
|
||||
oclk_dly = 60;
|
||||
sclk_dly = 120;
|
||||
} else {
|
||||
oclk_dly = 3;
|
||||
sclk_dly = 5;
|
||||
oclk_dly = 90;
|
||||
sclk_dly = 150;
|
||||
}
|
||||
} else if (rate <= 100000000) {
|
||||
oclk_dly = 6;
|
||||
sclk_dly = 24;
|
||||
} else if (rate <= 200000000) {
|
||||
oclk_dly = 3;
|
||||
sclk_dly = 12;
|
||||
} else {
|
||||
/* rate > 50000000 */
|
||||
oclk_dly = 2;
|
||||
sclk_dly = 4;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
src_clk = clk_get_rate(clk_get_parent(host->clk_mmc));
|
||||
if (src_clk >= 300000000 && src_clk <= 400000000) {
|
||||
if (oclk_dly)
|
||||
oclk_dly--;
|
||||
if (sclk_dly)
|
||||
sclk_dly--;
|
||||
}
|
||||
|
||||
clk_sunxi_mmc_phase_control(host->clk_mmc, sclk_dly, oclk_dly);
|
||||
clk_set_phase(host->clk_sample, sclk_dly);
|
||||
clk_set_phase(host->clk_output, oclk_dly);
|
||||
|
||||
return sunxi_mmc_oclk_onoff(host, 1);
|
||||
}
|
||||
@ -908,6 +905,18 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
|
||||
return PTR_ERR(host->clk_mmc);
|
||||
}
|
||||
|
||||
host->clk_output = devm_clk_get(&pdev->dev, "output");
|
||||
if (IS_ERR(host->clk_output)) {
|
||||
dev_err(&pdev->dev, "Could not get output clock\n");
|
||||
return PTR_ERR(host->clk_output);
|
||||
}
|
||||
|
||||
host->clk_sample = devm_clk_get(&pdev->dev, "sample");
|
||||
if (IS_ERR(host->clk_sample)) {
|
||||
dev_err(&pdev->dev, "Could not get sample clock\n");
|
||||
return PTR_ERR(host->clk_sample);
|
||||
}
|
||||
|
||||
host->reset = devm_reset_control_get(&pdev->dev, "ahb");
|
||||
|
||||
ret = clk_prepare_enable(host->clk_ahb);
|
||||
@ -922,11 +931,23 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
|
||||
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_deassert(host->reset);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "reset err %d\n", ret);
|
||||
goto error_disable_clk_mmc;
|
||||
goto error_disable_clk_sample;
|
||||
}
|
||||
}
|
||||
|
||||
@ -945,6 +966,10 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *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:
|
||||
|
Loading…
Reference in New Issue
Block a user