[PATCH 13/14] mmc: sunxi: Convert MMC driver to the standard clock phase API
Ulf Hansson
ulf.hansson at linaro.org
Wed Aug 13 01:44:42 PDT 2014
On 17 July 2014 11:08, Maxime Ripard <maxime.ripard at free-electrons.com> wrote:
> 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 at free-electrons.com>
I see there are a dependency of the clk patches with the mmc patch. I
suppose it's best to take this set through Mike's clk tree then.
Acked-by: Ulf Hansson <ulf.hansson at linaro.org>
Kind regards
Uffe
> ---
> .../devicetree/bindings/mmc/sunxi-mmc.txt | 8 +--
> drivers/mmc/host/sunxi-mmc.c | 72 +++++++++++++++-------
> 2 files changed, 53 insertions(+), 27 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt b/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt
> index 91b3a3467150..4bf41d833804 100644
> --- a/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt
> +++ b/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt
> @@ -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 at 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";
> };
> diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
> index 024f67c98cdc..8719cefa590d 100644
> --- a/drivers/mmc/host/sunxi-mmc.c
> +++ b/drivers/mmc/host/sunxi-mmc.c
> @@ -22,7 +22,6 @@
>
> #include <linux/clk.h>
> #include <linux/clk-private.h>
> -#include <linux/clk/sunxi.h>
>
> #include <linux/gpio.h>
> #include <linux/platform_device.h>
> @@ -230,6 +229,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;
> @@ -617,7 +618,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);
> @@ -643,34 +644,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);
> }
> @@ -909,6 +907,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);
> @@ -923,11 +933,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;
> }
> }
>
> @@ -946,6 +968,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:
> --
> 2.0.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
More information about the linux-arm-kernel
mailing list