[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