All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/4] clk: sunxi: mmc: Last bits of phase handling
@ 2014-12-16 21:38 Maxime Ripard
  2014-12-16 21:38 ` [PATCH v2 1/4] clk: sunxi: Rework MMC phase clocks Maxime Ripard
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: Maxime Ripard @ 2014-12-16 21:38 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

These are the last patches of the serie converting the custom phase
API to the proper common clock framework API.

These patches have already been discussed in length, only the patch 1
is new and should ease the handling of our MMC clocks.

Thanks,
Maxime

Changes from v1:
  - Fixed memory leak when a phase clock registration fails
  - Moved the spinlock declaration
  - Updated the DT bindings docs

Maxime Ripard (4):
  clk: sunxi: Rework MMC phase clocks
  ARM: sunxi: dt: Add sample and output mmc clocks
  mmc: sunxi: Convert MMC driver to the standard clock phase API
  clk: sunxi: Remove custom phase function

 Documentation/devicetree/bindings/clock/sunxi.txt  |   7 +-
 .../devicetree/bindings/mmc/sunxi-mmc.txt          |   8 +-
 arch/arm/boot/dts/sun4i-a10.dtsi                   |  72 +++++++----
 arch/arm/boot/dts/sun5i-a10s.dtsi                  |  54 ++++++---
 arch/arm/boot/dts/sun5i-a13.dtsi                   |  44 +++++--
 arch/arm/boot/dts/sun6i-a31.dtsi                   |  72 +++++++----
 arch/arm/boot/dts/sun7i-a20.dtsi                   |  72 +++++++----
 arch/arm/boot/dts/sun8i-a23.dtsi                   |  54 ++++++---
 drivers/clk/sunxi/clk-mod0.c                       | 131 +++++++++++----------
 drivers/clk/sunxi/clk-sunxi.c                      |  37 ------
 drivers/mmc/host/sunxi-mmc.c                       |  72 +++++++----
 include/linux/clk/sunxi.h                          |  22 ----
 12 files changed, 392 insertions(+), 253 deletions(-)
 delete mode 100644 include/linux/clk/sunxi.h

-- 
2.2.0

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 1/4] clk: sunxi: Rework MMC phase clocks
  2014-12-16 21:38 [PATCH v2 0/4] clk: sunxi: mmc: Last bits of phase handling Maxime Ripard
@ 2014-12-16 21:38 ` Maxime Ripard
  2014-12-17  6:58   ` Chen-Yu Tsai
  2014-12-16 21:38 ` [PATCH v2 2/4] ARM: sunxi: dt: Add sample and output mmc clocks Maxime Ripard
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 11+ messages in thread
From: Maxime Ripard @ 2014-12-16 21:38 UTC (permalink / raw)
  To: linux-arm-kernel

Instead of having three different clocks for the main MMC clock and the two
phase sub-clocks, which involved having three different drivers sharing the
same register, rework it to have the same single driver registering three
different clocks.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 Documentation/devicetree/bindings/clock/sunxi.txt |   7 +-
 drivers/clk/sunxi/clk-mod0.c                      | 131 ++++++++++++----------
 2 files changed, 74 insertions(+), 64 deletions(-)

diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index 9dc4f55a04ad..8c60433a7fc9 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -55,8 +55,7 @@ Required properties:
 	"allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
 	"allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23
 	"allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13
-	"allwinner,sun4i-a10-mmc-output-clk" - for the MMC output clock on A10
-	"allwinner,sun4i-a10-mmc-sample-clk" - for the MMC sample clock on A10
+	"allwinner,sun4i-a10-mmc-clk" - for the MMC clock
 	"allwinner,sun4i-a10-mod0-clk" - for the module 0 family of clocks
 	"allwinner,sun8i-a23-mbus-clk" - for the MBUS clock on A23
 	"allwinner,sun7i-a20-out-clk" - for the external output clocks
@@ -95,6 +94,10 @@ For "allwinner,sun6i-a31-pll6-clk", there are 2 outputs. The first output
 is the normal PLL6 output, or "pll6". The second output is rate doubled
 PLL6, or "pll6x2".
 
+The "allwinner,sun4i-a10-mmc-clk" has three different outputs: the
+main clock, with the ID 0, and the output and sample clocks, with the
+IDs 1 and 2, respectively.
+
 For example:
 
 osc24M: clk at 01c20050 {
diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c
index 658d74f39451..4ac52c703818 100644
--- a/drivers/clk/sunxi/clk-mod0.c
+++ b/drivers/clk/sunxi/clk-mod0.c
@@ -115,14 +115,10 @@ static void __init sun5i_a13_mbus_setup(struct device_node *node)
 }
 CLK_OF_DECLARE(sun5i_a13_mbus, "allwinner,sun5i-a13-mbus-clk", sun5i_a13_mbus_setup);
 
-struct mmc_phase_data {
-	u8	offset;
-};
-
 struct mmc_phase {
 	struct clk_hw		hw;
+	u8			offset;
 	void __iomem		*reg;
-	struct mmc_phase_data	*data;
 	spinlock_t		*lock;
 };
 
@@ -138,7 +134,7 @@ static int mmc_get_phase(struct clk_hw *hw)
 	u8 delay;
 
 	value = readl(phase->reg);
-	delay = (value >> phase->data->offset) & 0x3;
+	delay = (value >> phase->offset) & 0x3;
 
 	if (!delay)
 		return 180;
@@ -226,8 +222,8 @@ static int mmc_set_phase(struct clk_hw *hw, int degrees)
 
 	spin_lock_irqsave(phase->lock, flags);
 	value = readl(phase->reg);
-	value &= ~GENMASK(phase->data->offset + 3, phase->data->offset);
-	value |= delay << phase->data->offset;
+	value &= ~GENMASK(phase->offset + 3, phase->offset);
+	value |= delay << phase->offset;
 	writel(value, phase->reg);
 	spin_unlock_irqrestore(phase->lock, flags);
 
@@ -239,66 +235,77 @@ static const struct clk_ops mmc_clk_ops = {
 	.set_phase	= mmc_set_phase,
 };
 
-static void __init sun4i_a10_mmc_phase_setup(struct device_node *node,
-					     struct mmc_phase_data *data)
-{
-	const char *parent_names[1] = { of_clk_get_parent_name(node, 0) };
-	struct clk_init_data init = {
-		.num_parents	= 1,
-		.parent_names	= parent_names,
-		.ops		= &mmc_clk_ops,
-	};
-
-	struct mmc_phase *phase;
-	struct clk *clk;
-
-	phase = kmalloc(sizeof(*phase), GFP_KERNEL);
-	if (!phase)
-		return;
-
-	phase->hw.init = &init;
+static DEFINE_SPINLOCK(sun4i_a10_mmc_lock);
 
-	phase->reg = of_iomap(node, 0);
-	if (!phase->reg)
-		goto err_free;
+static void __init sun4i_a10_mmc_setup(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	const char *parent;
+	void __iomem *reg;
+	int i;
 
-	phase->data = data;
-	phase->lock = &sun4i_a10_mod0_lock;
+	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+	if (IS_ERR(reg)) {
+		pr_err("Couldn't map the %s clock registers\n", node->name);
+		return;
+	}
 
-	if (of_property_read_string(node, "clock-output-names", &init.name))
-		init.name = node->name;
+	clk_data = kmalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		return;
 
-	clk = clk_register(NULL, &phase->hw);
-	if (IS_ERR(clk))
-		goto err_unmap;
+	clk_data->clks = kcalloc(3, sizeof(*clk_data->clks), GFP_KERNEL);
+	if (!clk_data->clks)
+		goto err_free_data;
+
+	clk_data->clk_num = 3;
+	clk_data->clks[0] = sunxi_factors_register(node,
+						   &sun4i_a10_mod0_data,
+						   &sun4i_a10_mmc_lock, reg);
+	if (!clk_data->clks[0])
+		goto err_free_clks;
+
+	parent = __clk_get_name(clk_data->clks[0]);
+
+	for (i = 1; i < 3; i++) {
+		struct clk_init_data init = {
+			.num_parents	= 1,
+			.parent_names	= &parent,
+			.ops		= &mmc_clk_ops,
+		};
+		struct mmc_phase *phase;
+
+		phase = kmalloc(sizeof(*phase), GFP_KERNEL);
+		if (!phase)
+			continue;
+
+		phase->hw.init = &init;
+		phase->reg = reg;
+		phase->lock = &sun4i_a10_mmc_lock;
+
+		if (i == 1)
+			phase->offset = 8;
+		else
+			phase->offset = 20;
+
+		if (of_property_read_string_index(node, "clock-output-names",
+						  i, &init.name))
+			init.name = node->name;
+
+		clk_data->clks[i] = clk_register(NULL, &phase->hw);
+		if (IS_ERR(clk_data->clks[i])) {
+			kfree(phase);
+			continue;
+		}
+	}
 
-	of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
 
 	return;
 
-err_unmap:
-	iounmap(phase->reg);
-err_free:
-	kfree(phase);
-}
-
-
-static struct mmc_phase_data mmc_output_clk = {
-	.offset	= 8,
-};
-
-static struct mmc_phase_data mmc_sample_clk = {
-	.offset	= 20,
-};
-
-static void __init sun4i_a10_mmc_output_setup(struct device_node *node)
-{
-	sun4i_a10_mmc_phase_setup(node, &mmc_output_clk);
-}
-CLK_OF_DECLARE(sun4i_a10_mmc_output, "allwinner,sun4i-a10-mmc-output-clk", sun4i_a10_mmc_output_setup);
-
-static void __init sun4i_a10_mmc_sample_setup(struct device_node *node)
-{
-	sun4i_a10_mmc_phase_setup(node, &mmc_sample_clk);
+err_free_clks:
+	kfree(clk_data->clks);
+err_free_data:
+	kfree(clk_data);
 }
-CLK_OF_DECLARE(sun4i_a10_mmc_sample, "allwinner,sun4i-a10-mmc-sample-clk", sun4i_a10_mmc_sample_setup);
+CLK_OF_DECLARE(sun4i_a10_mmc, "allwinner,sun4i-a10-mmc-clk", sun4i_a10_mmc_setup);
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v2 2/4] ARM: sunxi: dt: Add sample and output mmc clocks
  2014-12-16 21:38 [PATCH v2 0/4] clk: sunxi: mmc: Last bits of phase handling Maxime Ripard
  2014-12-16 21:38 ` [PATCH v2 1/4] clk: sunxi: Rework MMC phase clocks Maxime Ripard
@ 2014-12-16 21:38 ` Maxime Ripard
  2014-12-16 21:38 ` [PATCH v2 3/4] mmc: sunxi: Convert MMC driver to the standard clock phase API Maxime Ripard
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 11+ messages in thread
From: Maxime Ripard @ 2014-12-16 21:38 UTC (permalink / raw)
  To: linux-arm-kernel

Add the sample and output clocks for the MMC phase support.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun4i-a10.dtsi  | 72 ++++++++++++++++++++++++++++-----------
 arch/arm/boot/dts/sun5i-a10s.dtsi | 54 +++++++++++++++++++++--------
 arch/arm/boot/dts/sun5i-a13.dtsi  | 44 +++++++++++++++++-------
 arch/arm/boot/dts/sun6i-a31.dtsi  | 72 ++++++++++++++++++++++++++++-----------
 arch/arm/boot/dts/sun7i-a20.dtsi  | 72 ++++++++++++++++++++++++++++-----------
 arch/arm/boot/dts/sun8i-a23.dtsi  | 54 +++++++++++++++++++++--------
 6 files changed, 265 insertions(+), 103 deletions(-)

diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index 7b4099fcf817..bb6b6ae95d82 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -226,35 +226,43 @@
 		};
 
 		mmc0_clk: clk at 01c20088 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			#clock-cells = <1>;
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c20088 0x4>;
 			clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-			clock-output-names = "mmc0";
+			clock-output-names = "mmc0",
+					     "mmc0_output",
+					     "mmc0_sample";
 		};
 
 		mmc1_clk: clk at 01c2008c {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			#clock-cells = <1>;
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c2008c 0x4>;
 			clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-			clock-output-names = "mmc1";
+			clock-output-names = "mmc1",
+					     "mmc1_output",
+					     "mmc1_sample";
 		};
 
 		mmc2_clk: clk at 01c20090 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			#clock-cells = <1>;
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c20090 0x4>;
 			clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-			clock-output-names = "mmc2";
+			clock-output-names = "mmc2",
+					     "mmc2_output",
+					     "mmc2_sample";
 		};
 
 		mmc3_clk: clk at 01c20094 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			#clock-cells = <1>;
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c20094 0x4>;
 			clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-			clock-output-names = "mmc3";
+			clock-output-names = "mmc3",
+					     "mmc3_output",
+					     "mmc3_sample";
 		};
 
 		ts_clk: clk at 01c20098 {
@@ -398,8 +406,14 @@
 		mmc0: mmc at 01c0f000 {
 			compatible = "allwinner,sun4i-a10-mmc";
 			reg = <0x01c0f000 0x1000>;
-			clocks = <&ahb_gates 8>, <&mmc0_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 8>,
+				 <&mmc0_clk 0>,
+				 <&mmc0_clk 1>,
+				 <&mmc0_clk 2>;
+			clock-names = "ahb",
+				      "mmc",
+				      "output",
+				      "sample";
 			interrupts = <32>;
 			status = "disabled";
 		};
@@ -407,8 +421,14 @@
 		mmc1: mmc at 01c10000 {
 			compatible = "allwinner,sun4i-a10-mmc";
 			reg = <0x01c10000 0x1000>;
-			clocks = <&ahb_gates 9>, <&mmc1_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 9>,
+				 <&mmc1_clk 0>,
+				 <&mmc1_clk 1>,
+				 <&mmc1_clk 2>;
+			clock-names = "ahb",
+				      "mmc",
+				      "output",
+				      "sample";
 			interrupts = <33>;
 			status = "disabled";
 		};
@@ -416,8 +436,14 @@
 		mmc2: mmc at 01c11000 {
 			compatible = "allwinner,sun4i-a10-mmc";
 			reg = <0x01c11000 0x1000>;
-			clocks = <&ahb_gates 10>, <&mmc2_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 10>,
+				 <&mmc2_clk 0>,
+				 <&mmc2_clk 1>,
+				 <&mmc2_clk 2>;
+			clock-names = "ahb",
+				      "mmc",
+				      "output",
+				      "sample";
 			interrupts = <34>;
 			status = "disabled";
 		};
@@ -425,8 +451,14 @@
 		mmc3: mmc at 01c12000 {
 			compatible = "allwinner,sun4i-a10-mmc";
 			reg = <0x01c12000 0x1000>;
-			clocks = <&ahb_gates 11>, <&mmc3_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 11>,
+				 <&mmc3_clk 0>,
+				 <&mmc3_clk 1>,
+				 <&mmc3_clk 2>;
+			clock-names = "ahb",
+				      "mmc",
+				      "output",
+				      "sample";
 			interrupts = <35>;
 			status = "disabled";
 		};
diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
index 1b76667f3182..0e011427615f 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -211,27 +211,33 @@
 		};
 
 		mmc0_clk: clk at 01c20088 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			#clock-cells = <1>;
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c20088 0x4>;
 			clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-			clock-output-names = "mmc0";
+			clock-output-names = "mmc0",
+					     "mmc0_output",
+					     "mmc0_sample";
 		};
 
 		mmc1_clk: clk at 01c2008c {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			#clock-cells = <1>;
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c2008c 0x4>;
 			clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-			clock-output-names = "mmc1";
+			clock-output-names = "mmc1",
+					     "mmc1_output",
+					     "mmc1_sample";
 		};
 
 		mmc2_clk: clk at 01c20090 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			#clock-cells = <1>;
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c20090 0x4>;
 			clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-			clock-output-names = "mmc2";
+			clock-output-names = "mmc2",
+					     "mmc2_output",
+					     "mmc2_sample";
 		};
 
 		ts_clk: clk at 01c20098 {
@@ -359,8 +365,14 @@
 		mmc0: mmc at 01c0f000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c0f000 0x1000>;
-			clocks = <&ahb_gates 8>, <&mmc0_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 8>,
+				 <&mmc0_clk 0>,
+				 <&mmc0_clk 1>,
+				 <&mmc0_clk 2>;
+			clock-names = "ahb",
+				      "mmc",
+				      "output",
+				      "sample";
 			interrupts = <32>;
 			status = "disabled";
 		};
@@ -368,8 +380,14 @@
 		mmc1: mmc at 01c10000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c10000 0x1000>;
-			clocks = <&ahb_gates 9>, <&mmc1_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 9>,
+				 <&mmc1_clk 0>,
+				 <&mmc1_clk 1>,
+				 <&mmc1_clk 2>;
+			clock-names = "ahb",
+				      "mmc",
+				      "output",
+				      "sample";
 			interrupts = <33>;
 			status = "disabled";
 		};
@@ -377,8 +395,14 @@
 		mmc2: mmc at 01c11000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c11000 0x1000>;
-			clocks = <&ahb_gates 10>, <&mmc2_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 10>,
+				 <&mmc2_clk 0>,
+				 <&mmc2_clk 1>,
+				 <&mmc2_clk 2>;
+			clock-names = "ahb",
+				      "mmc",
+				      "output",
+				      "sample";
 			interrupts = <34>;
 			status = "disabled";
 		};
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index c35217ea1f64..cbb63b750e08 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -195,27 +195,33 @@
 		};
 
 		mmc0_clk: clk at 01c20088 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			#clock-cells = <1>;
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c20088 0x4>;
 			clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-			clock-output-names = "mmc0";
+			clock-output-names = "mmc0",
+					     "mmc0_output",
+					     "mmc0_sample";
 		};
 
 		mmc1_clk: clk at 01c2008c {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			#clock-cells = <1>;
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c2008c 0x4>;
 			clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-			clock-output-names = "mmc1";
+			clock-output-names = "mmc1",
+					     "mmc1_output",
+					     "mmc1_sample";
 		};
 
 		mmc2_clk: clk at 01c20090 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			#clock-cells = <1>;
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c20090 0x4>;
 			clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-			clock-output-names = "mmc2";
+			clock-output-names = "mmc2",
+					     "mmc2_output",
+					     "mmc2_sample";
 		};
 
 		ts_clk: clk at 01c20098 {
@@ -327,8 +333,14 @@
 		mmc0: mmc at 01c0f000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c0f000 0x1000>;
-			clocks = <&ahb_gates 8>, <&mmc0_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 8>,
+				 <&mmc0_clk 0>,
+				 <&mmc0_clk 1>,
+				 <&mmc0_clk 2>;
+			clock-names = "ahb",
+				      "mmc",
+				      "output",
+				      "sample";
 			interrupts = <32>;
 			status = "disabled";
 		};
@@ -336,8 +348,14 @@
 		mmc2: mmc at 01c11000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c11000 0x1000>;
-			clocks = <&ahb_gates 10>, <&mmc2_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 10>,
+				 <&mmc2_clk 0>,
+				 <&mmc2_clk 1>,
+				 <&mmc2_clk 2>;
+			clock-names = "ahb",
+				      "mmc",
+				      "output",
+				      "sample";
 			interrupts = <34>;
 			status = "disabled";
 		};
diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
index 62d932e9b7d1..3e7db5191516 100644
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -241,35 +241,43 @@
 		};
 
 		mmc0_clk: clk at 01c20088 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			#clock-cells = <1>;
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c20088 0x4>;
 			clocks = <&osc24M>, <&pll6 0>;
-			clock-output-names = "mmc0";
+			clock-output-names = "mmc0",
+					     "mmc0_output",
+					     "mmc0_sample";
 		};
 
 		mmc1_clk: clk at 01c2008c {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			#clock-cells = <1>;
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c2008c 0x4>;
 			clocks = <&osc24M>, <&pll6 0>;
-			clock-output-names = "mmc1";
+			clock-output-names = "mmc1",
+					     "mmc1_output",
+					     "mmc1_sample";
 		};
 
 		mmc2_clk: clk at 01c20090 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			#clock-cells = <1>;
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c20090 0x4>;
 			clocks = <&osc24M>, <&pll6 0>;
-			clock-output-names = "mmc2";
+			clock-output-names = "mmc2",
+					     "mmc2_output",
+					     "mmc2_sample";
 		};
 
 		mmc3_clk: clk at 01c20094 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			#clock-cells = <1>;
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c20094 0x4>;
 			clocks = <&osc24M>, <&pll6 0>;
-			clock-output-names = "mmc3";
+			clock-output-names = "mmc3",
+					     "mmc3_output",
+					     "mmc3_sample";
 		};
 
 		spi0_clk: clk at 01c200a0 {
@@ -366,8 +374,14 @@
 		mmc0: mmc at 01c0f000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c0f000 0x1000>;
-			clocks = <&ahb1_gates 8>, <&mmc0_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb1_gates 8>,
+				 <&mmc0_clk 0>,
+				 <&mmc0_clk 1>,
+				 <&mmc0_clk 2>;
+			clock-names = "ahb",
+				      "mmc",
+				      "output",
+				      "sample";
 			resets = <&ahb1_rst 8>;
 			reset-names = "ahb";
 			interrupts = <0 60 4>;
@@ -377,8 +391,14 @@
 		mmc1: mmc at 01c10000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c10000 0x1000>;
-			clocks = <&ahb1_gates 9>, <&mmc1_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb1_gates 9>,
+				 <&mmc1_clk 0>,
+				 <&mmc1_clk 1>,
+				 <&mmc1_clk 2>;
+			clock-names = "ahb",
+				      "mmc",
+				      "output",
+				      "sample";
 			resets = <&ahb1_rst 9>;
 			reset-names = "ahb";
 			interrupts = <0 61 4>;
@@ -388,8 +408,14 @@
 		mmc2: mmc at 01c11000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c11000 0x1000>;
-			clocks = <&ahb1_gates 10>, <&mmc2_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb1_gates 10>,
+				 <&mmc2_clk 0>,
+				 <&mmc2_clk 1>,
+				 <&mmc2_clk 2>;
+			clock-names = "ahb",
+				      "mmc",
+				      "output",
+				      "sample";
 			resets = <&ahb1_rst 10>;
 			reset-names = "ahb";
 			interrupts = <0 62 4>;
@@ -399,8 +425,14 @@
 		mmc3: mmc at 01c12000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c12000 0x1000>;
-			clocks = <&ahb1_gates 11>, <&mmc3_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb1_gates 11>,
+				 <&mmc3_clk 0>,
+				 <&mmc3_clk 1>,
+				 <&mmc3_clk 2>;
+			clock-names = "ahb",
+				      "mmc",
+				      "output",
+				      "sample";
 			resets = <&ahb1_rst 11>;
 			reset-names = "ahb";
 			interrupts = <0 63 4>;
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index e21ce5992d56..fa51bffcaf1d 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -274,35 +274,43 @@
 		};
 
 		mmc0_clk: clk at 01c20088 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			#clock-cells = <1>;
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c20088 0x4>;
 			clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-			clock-output-names = "mmc0";
+			clock-output-names = "mmc0",
+					     "mmc0_output",
+					     "mmc0_sample";
 		};
 
 		mmc1_clk: clk at 01c2008c {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			#clock-cells = <1>;
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c2008c 0x4>;
 			clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-			clock-output-names = "mmc1";
+			clock-output-names = "mmc1",
+					     "mmc1_output",
+					     "mmc1_sample";
 		};
 
 		mmc2_clk: clk at 01c20090 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			#clock-cells = <1>;
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c20090 0x4>;
 			clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-			clock-output-names = "mmc2";
+			clock-output-names = "mmc2",
+					     "mmc2_output",
+					     "mmc2_sample";
 		};
 
 		mmc3_clk: clk at 01c20094 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			#clock-cells = <1>;
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c20094 0x4>;
 			clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-			clock-output-names = "mmc3";
+			clock-output-names = "mmc3",
+					     "mmc3_output",
+					     "mmc3_sample";
 		};
 
 		ts_clk: clk at 01c20098 {
@@ -518,8 +526,14 @@
 		mmc0: mmc at 01c0f000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c0f000 0x1000>;
-			clocks = <&ahb_gates 8>, <&mmc0_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 8>,
+				 <&mmc0_clk 0>,
+				 <&mmc0_clk 1>,
+				 <&mmc0_clk 2>;
+			clock-names = "ahb",
+				      "mmc",
+				      "output",
+				      "sample";
 			interrupts = <0 32 4>;
 			status = "disabled";
 		};
@@ -527,8 +541,14 @@
 		mmc1: mmc at 01c10000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c10000 0x1000>;
-			clocks = <&ahb_gates 9>, <&mmc1_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 9>,
+				 <&mmc1_clk 0>,
+				 <&mmc1_clk 1>,
+				 <&mmc1_clk 2>;
+			clock-names = "ahb",
+				      "mmc",
+				      "output",
+				      "sample";
 			interrupts = <0 33 4>;
 			status = "disabled";
 		};
@@ -536,8 +556,14 @@
 		mmc2: mmc at 01c11000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c11000 0x1000>;
-			clocks = <&ahb_gates 10>, <&mmc2_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 10>,
+				 <&mmc2_clk 0>,
+				 <&mmc2_clk 1>,
+				 <&mmc2_clk 2>;
+			clock-names = "ahb",
+				      "mmc",
+				      "output",
+				      "sample";
 			interrupts = <0 34 4>;
 			status = "disabled";
 		};
@@ -545,8 +571,14 @@
 		mmc3: mmc at 01c12000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c12000 0x1000>;
-			clocks = <&ahb_gates 11>, <&mmc3_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 11>,
+				 <&mmc3_clk 0>,
+				 <&mmc3_clk 1>,
+				 <&mmc3_clk 2>;
+			clock-names = "ahb",
+				      "mmc",
+				      "output",
+				      "sample";
 			interrupts = <0 35 4>;
 			status = "disabled";
 		};
diff --git a/arch/arm/boot/dts/sun8i-a23.dtsi b/arch/arm/boot/dts/sun8i-a23.dtsi
index 2fcccf0cbcee..43a0688fffa0 100644
--- a/arch/arm/boot/dts/sun8i-a23.dtsi
+++ b/arch/arm/boot/dts/sun8i-a23.dtsi
@@ -209,27 +209,33 @@
 		};
 
 		mmc0_clk: clk at 01c20088 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			#clock-cells = <1>;
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c20088 0x4>;
 			clocks = <&osc24M>, <&pll6 0>;
-			clock-output-names = "mmc0";
+			clock-output-names = "mmc0",
+					     "mmc0_output",
+					     "mmc0_sample";
 		};
 
 		mmc1_clk: clk at 01c2008c {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			#clock-cells = <1>;
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c2008c 0x4>;
 			clocks = <&osc24M>, <&pll6 0>;
-			clock-output-names = "mmc1";
+			clock-output-names = "mmc1",
+					     "mmc1_output",
+					     "mmc1_sample";
 		};
 
 		mmc2_clk: clk at 01c20090 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			#clock-cells = <1>;
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c20090 0x4>;
 			clocks = <&osc24M>, <&pll6 0>;
-			clock-output-names = "mmc2";
+			clock-output-names = "mmc2",
+					     "mmc2_output",
+					     "mmc2_sample";
 		};
 
 		mbus_clk: clk at 01c2015c {
@@ -259,8 +265,14 @@
 		mmc0: mmc at 01c0f000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c0f000 0x1000>;
-			clocks = <&ahb1_gates 8>, <&mmc0_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb1_gates 8>,
+				 <&mmc0_clk 0>,
+				 <&mmc0_clk 1>,
+				 <&mmc0_clk 2>;
+			clock-names = "ahb",
+				      "mmc",
+				      "output",
+				      "sample";
 			resets = <&ahb1_rst 8>;
 			reset-names = "ahb";
 			interrupts = <0 60 4>;
@@ -270,8 +282,14 @@
 		mmc1: mmc at 01c10000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c10000 0x1000>;
-			clocks = <&ahb1_gates 9>, <&mmc1_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb1_gates 9>,
+				 <&mmc1_clk 0>,
+				 <&mmc1_clk 1>,
+				 <&mmc1_clk 2>;
+			clock-names = "ahb",
+				      "mmc",
+				      "output",
+				      "sample";
 			resets = <&ahb1_rst 9>;
 			reset-names = "ahb";
 			interrupts = <0 61 4>;
@@ -281,8 +299,14 @@
 		mmc2: mmc at 01c11000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c11000 0x1000>;
-			clocks = <&ahb1_gates 10>, <&mmc2_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb1_gates 10>,
+				 <&mmc2_clk 0>,
+				 <&mmc2_clk 1>,
+				 <&mmc2_clk 2>;
+			clock-names = "ahb",
+				      "mmc",
+				      "output",
+				      "sample";
 			resets = <&ahb1_rst 10>;
 			reset-names = "ahb";
 			interrupts = <0 62 4>;
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v2 3/4] mmc: sunxi: Convert MMC driver to the standard clock phase API
  2014-12-16 21:38 [PATCH v2 0/4] clk: sunxi: mmc: Last bits of phase handling Maxime Ripard
  2014-12-16 21:38 ` [PATCH v2 1/4] clk: sunxi: Rework MMC phase clocks Maxime Ripard
  2014-12-16 21:38 ` [PATCH v2 2/4] ARM: sunxi: dt: Add sample and output mmc clocks Maxime Ripard
@ 2014-12-16 21:38 ` Maxime Ripard
  2014-12-17  4:17   ` Chen-Yu Tsai
  2014-12-16 21:38 ` [PATCH v2 4/4] clk: sunxi: Remove custom phase function Maxime Ripard
  2014-12-17 10:54 ` [PATCH v2 0/4] clk: sunxi: mmc: Last bits of phase handling Chen-Yu Tsai
  4 siblings, 1 reply; 11+ messages in thread
From: Maxime Ripard @ 2014-12-16 21:38 UTC (permalink / raw)
  To: linux-arm-kernel

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>
---
 .../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 d1663b3c4143..afe20c322e55 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.2.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v2 4/4] clk: sunxi: Remove custom phase function
  2014-12-16 21:38 [PATCH v2 0/4] clk: sunxi: mmc: Last bits of phase handling Maxime Ripard
                   ` (2 preceding siblings ...)
  2014-12-16 21:38 ` [PATCH v2 3/4] mmc: sunxi: Convert MMC driver to the standard clock phase API Maxime Ripard
@ 2014-12-16 21:38 ` Maxime Ripard
  2014-12-17 10:54 ` [PATCH v2 0/4] clk: sunxi: mmc: Last bits of phase handling Chen-Yu Tsai
  4 siblings, 0 replies; 11+ messages in thread
From: Maxime Ripard @ 2014-12-16 21:38 UTC (permalink / raw)
  To: linux-arm-kernel

Now that we don't have any user left for our custom phase function, we can
safely remove this hack from the code.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/clk/sunxi/clk-sunxi.c | 37 -------------------------------------
 include/linux/clk/sunxi.h     | 22 ----------------------
 2 files changed, 59 deletions(-)
 delete mode 100644 include/linux/clk/sunxi.h

diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 68ac9f068c4b..fab22c68d05e 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -563,43 +563,6 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate,
 }
 
 /**
- * clk_sunxi_mmc_phase_control() - configures MMC clock phase control
- */
-
-void clk_sunxi_mmc_phase_control(struct clk *clk, u8 sample, u8 output)
-{
-	#define to_clk_composite(_hw) container_of(_hw, struct clk_composite, hw)
-	#define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw)
-
-	struct clk_hw *hw = __clk_get_hw(clk);
-	struct clk_composite *composite = to_clk_composite(hw);
-	struct clk_hw *rate_hw = composite->rate_hw;
-	struct clk_factors *factors = to_clk_factors(rate_hw);
-	unsigned long flags = 0;
-	u32 reg;
-
-	if (factors->lock)
-		spin_lock_irqsave(factors->lock, flags);
-
-	reg = readl(factors->reg);
-
-	/* set sample clock phase control */
-	reg &= ~(0x7 << 20);
-	reg |= ((sample & 0x7) << 20);
-
-	/* set output clock phase control */
-	reg &= ~(0x7 << 8);
-	reg |= ((output & 0x7) << 8);
-
-	writel(reg, factors->reg);
-
-	if (factors->lock)
-		spin_unlock_irqrestore(factors->lock, flags);
-}
-EXPORT_SYMBOL(clk_sunxi_mmc_phase_control);
-
-
-/**
  * sunxi_factors_clk_setup() - Setup function for factor clocks
  */
 
diff --git a/include/linux/clk/sunxi.h b/include/linux/clk/sunxi.h
deleted file mode 100644
index aed28c4451d9..000000000000
--- a/include/linux/clk/sunxi.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2013 - Hans de Goede <hdegoede@redhat.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __LINUX_CLK_SUNXI_H_
-#define __LINUX_CLK_SUNXI_H_
-
-#include <linux/clk.h>
-
-void clk_sunxi_mmc_phase_control(struct clk *clk, u8 sample, u8 output);
-
-#endif
-- 
2.2.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v2 3/4] mmc: sunxi: Convert MMC driver to the standard clock phase API
  2014-12-16 21:38 ` [PATCH v2 3/4] mmc: sunxi: Convert MMC driver to the standard clock phase API Maxime Ripard
@ 2014-12-17  4:17   ` Chen-Yu Tsai
  2014-12-19 17:35     ` Maxime Ripard
  2014-12-19 17:50     ` Maxime Ripard
  0 siblings, 2 replies; 11+ messages in thread
From: Chen-Yu Tsai @ 2014-12-17  4:17 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Wed, Dec 17, 2014 at 5:38 AM, Maxime Ripard
<maxime.ripard@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@free-electrons.com>
> Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
> Acked-by: David Lanzend?rfer <david.lanzendoerfer@o2s.ch>
> ---
>  .../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 d1663b3c4143..afe20c322e55 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>

This conflicts with

    05e07d8 mmc: sunxi: Remove unused includes of linux/clk-private.h

when applied over

    a0eda58 (linux-next/master) Add linux-next specific files for 20141216

>
>  #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;

42 seems like an odd number. Maybe 45?

>         } 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.2.0
>

Otherwise looks good. Thanks!


ChenYu

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 1/4] clk: sunxi: Rework MMC phase clocks
  2014-12-16 21:38 ` [PATCH v2 1/4] clk: sunxi: Rework MMC phase clocks Maxime Ripard
@ 2014-12-17  6:58   ` Chen-Yu Tsai
  2014-12-19 17:35     ` Maxime Ripard
  0 siblings, 1 reply; 11+ messages in thread
From: Chen-Yu Tsai @ 2014-12-17  6:58 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Wed, Dec 17, 2014 at 5:38 AM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Instead of having three different clocks for the main MMC clock and the two
> phase sub-clocks, which involved having three different drivers sharing the
> same register, rework it to have the same single driver registering three
> different clocks.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  Documentation/devicetree/bindings/clock/sunxi.txt |   7 +-
>  drivers/clk/sunxi/clk-mod0.c                      | 131 ++++++++++++----------
>  2 files changed, 74 insertions(+), 64 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
> index 9dc4f55a04ad..8c60433a7fc9 100644
> --- a/Documentation/devicetree/bindings/clock/sunxi.txt
> +++ b/Documentation/devicetree/bindings/clock/sunxi.txt
> @@ -55,8 +55,7 @@ Required properties:
>         "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
>         "allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23
>         "allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13
> -       "allwinner,sun4i-a10-mmc-output-clk" - for the MMC output clock on A10
> -       "allwinner,sun4i-a10-mmc-sample-clk" - for the MMC sample clock on A10
> +       "allwinner,sun4i-a10-mmc-clk" - for the MMC clock
>         "allwinner,sun4i-a10-mod0-clk" - for the module 0 family of clocks
>         "allwinner,sun8i-a23-mbus-clk" - for the MBUS clock on A23
>         "allwinner,sun7i-a20-out-clk" - for the external output clocks
> @@ -95,6 +94,10 @@ For "allwinner,sun6i-a31-pll6-clk", there are 2 outputs. The first output
>  is the normal PLL6 output, or "pll6". The second output is rate doubled
>  PLL6, or "pll6x2".
>
> +The "allwinner,sun4i-a10-mmc-clk" has three different outputs: the
> +main clock, with the ID 0, and the output and sample clocks, with the
> +IDs 1 and 2, respectively.
> +

Could you also update the mmc/mod0 clock example in the bindings?
Currently it is an mmc module clock using the mod0 compatible.

Thanks.

ChenYu

>  For example:
>
>  osc24M: clk at 01c20050 {
> diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c
> index 658d74f39451..4ac52c703818 100644
> --- a/drivers/clk/sunxi/clk-mod0.c
> +++ b/drivers/clk/sunxi/clk-mod0.c
> @@ -115,14 +115,10 @@ static void __init sun5i_a13_mbus_setup(struct device_node *node)
>  }
>  CLK_OF_DECLARE(sun5i_a13_mbus, "allwinner,sun5i-a13-mbus-clk", sun5i_a13_mbus_setup);
>
> -struct mmc_phase_data {
> -       u8      offset;
> -};
> -
>  struct mmc_phase {
>         struct clk_hw           hw;
> +       u8                      offset;
>         void __iomem            *reg;
> -       struct mmc_phase_data   *data;
>         spinlock_t              *lock;
>  };
>
> @@ -138,7 +134,7 @@ static int mmc_get_phase(struct clk_hw *hw)
>         u8 delay;
>
>         value = readl(phase->reg);
> -       delay = (value >> phase->data->offset) & 0x3;
> +       delay = (value >> phase->offset) & 0x3;
>
>         if (!delay)
>                 return 180;
> @@ -226,8 +222,8 @@ static int mmc_set_phase(struct clk_hw *hw, int degrees)
>
>         spin_lock_irqsave(phase->lock, flags);
>         value = readl(phase->reg);
> -       value &= ~GENMASK(phase->data->offset + 3, phase->data->offset);
> -       value |= delay << phase->data->offset;
> +       value &= ~GENMASK(phase->offset + 3, phase->offset);
> +       value |= delay << phase->offset;
>         writel(value, phase->reg);
>         spin_unlock_irqrestore(phase->lock, flags);
>
> @@ -239,66 +235,77 @@ static const struct clk_ops mmc_clk_ops = {
>         .set_phase      = mmc_set_phase,
>  };
>
> -static void __init sun4i_a10_mmc_phase_setup(struct device_node *node,
> -                                            struct mmc_phase_data *data)
> -{
> -       const char *parent_names[1] = { of_clk_get_parent_name(node, 0) };
> -       struct clk_init_data init = {
> -               .num_parents    = 1,
> -               .parent_names   = parent_names,
> -               .ops            = &mmc_clk_ops,
> -       };
> -
> -       struct mmc_phase *phase;
> -       struct clk *clk;
> -
> -       phase = kmalloc(sizeof(*phase), GFP_KERNEL);
> -       if (!phase)
> -               return;
> -
> -       phase->hw.init = &init;
> +static DEFINE_SPINLOCK(sun4i_a10_mmc_lock);
>
> -       phase->reg = of_iomap(node, 0);
> -       if (!phase->reg)
> -               goto err_free;
> +static void __init sun4i_a10_mmc_setup(struct device_node *node)
> +{
> +       struct clk_onecell_data *clk_data;
> +       const char *parent;
> +       void __iomem *reg;
> +       int i;
>
> -       phase->data = data;
> -       phase->lock = &sun4i_a10_mod0_lock;
> +       reg = of_io_request_and_map(node, 0, of_node_full_name(node));
> +       if (IS_ERR(reg)) {
> +               pr_err("Couldn't map the %s clock registers\n", node->name);
> +               return;
> +       }
>
> -       if (of_property_read_string(node, "clock-output-names", &init.name))
> -               init.name = node->name;
> +       clk_data = kmalloc(sizeof(*clk_data), GFP_KERNEL);
> +       if (!clk_data)
> +               return;
>
> -       clk = clk_register(NULL, &phase->hw);
> -       if (IS_ERR(clk))
> -               goto err_unmap;
> +       clk_data->clks = kcalloc(3, sizeof(*clk_data->clks), GFP_KERNEL);
> +       if (!clk_data->clks)
> +               goto err_free_data;
> +
> +       clk_data->clk_num = 3;
> +       clk_data->clks[0] = sunxi_factors_register(node,
> +                                                  &sun4i_a10_mod0_data,
> +                                                  &sun4i_a10_mmc_lock, reg);
> +       if (!clk_data->clks[0])
> +               goto err_free_clks;
> +
> +       parent = __clk_get_name(clk_data->clks[0]);
> +
> +       for (i = 1; i < 3; i++) {
> +               struct clk_init_data init = {
> +                       .num_parents    = 1,
> +                       .parent_names   = &parent,
> +                       .ops            = &mmc_clk_ops,
> +               };
> +               struct mmc_phase *phase;
> +
> +               phase = kmalloc(sizeof(*phase), GFP_KERNEL);
> +               if (!phase)
> +                       continue;
> +
> +               phase->hw.init = &init;
> +               phase->reg = reg;
> +               phase->lock = &sun4i_a10_mmc_lock;
> +
> +               if (i == 1)
> +                       phase->offset = 8;
> +               else
> +                       phase->offset = 20;
> +
> +               if (of_property_read_string_index(node, "clock-output-names",
> +                                                 i, &init.name))
> +                       init.name = node->name;
> +
> +               clk_data->clks[i] = clk_register(NULL, &phase->hw);
> +               if (IS_ERR(clk_data->clks[i])) {
> +                       kfree(phase);
> +                       continue;
> +               }
> +       }
>
> -       of_clk_add_provider(node, of_clk_src_simple_get, clk);
> +       of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
>
>         return;
>
> -err_unmap:
> -       iounmap(phase->reg);
> -err_free:
> -       kfree(phase);
> -}
> -
> -
> -static struct mmc_phase_data mmc_output_clk = {
> -       .offset = 8,
> -};
> -
> -static struct mmc_phase_data mmc_sample_clk = {
> -       .offset = 20,
> -};
> -
> -static void __init sun4i_a10_mmc_output_setup(struct device_node *node)
> -{
> -       sun4i_a10_mmc_phase_setup(node, &mmc_output_clk);
> -}
> -CLK_OF_DECLARE(sun4i_a10_mmc_output, "allwinner,sun4i-a10-mmc-output-clk", sun4i_a10_mmc_output_setup);
> -
> -static void __init sun4i_a10_mmc_sample_setup(struct device_node *node)
> -{
> -       sun4i_a10_mmc_phase_setup(node, &mmc_sample_clk);
> +err_free_clks:
> +       kfree(clk_data->clks);
> +err_free_data:
> +       kfree(clk_data);
>  }
> -CLK_OF_DECLARE(sun4i_a10_mmc_sample, "allwinner,sun4i-a10-mmc-sample-clk", sun4i_a10_mmc_sample_setup);
> +CLK_OF_DECLARE(sun4i_a10_mmc, "allwinner,sun4i-a10-mmc-clk", sun4i_a10_mmc_setup);
> --
> 2.2.0
>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 0/4] clk: sunxi: mmc: Last bits of phase handling
  2014-12-16 21:38 [PATCH v2 0/4] clk: sunxi: mmc: Last bits of phase handling Maxime Ripard
                   ` (3 preceding siblings ...)
  2014-12-16 21:38 ` [PATCH v2 4/4] clk: sunxi: Remove custom phase function Maxime Ripard
@ 2014-12-17 10:54 ` Chen-Yu Tsai
  4 siblings, 0 replies; 11+ messages in thread
From: Chen-Yu Tsai @ 2014-12-17 10:54 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Wed, Dec 17, 2014 at 5:38 AM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Hi,
>
> These are the last patches of the serie converting the custom phase
> API to the proper common clock framework API.
>
> These patches have already been discussed in length, only the patch 1
> is new and should ease the handling of our MMC clocks.
>
> Thanks,
> Maxime
>
> Changes from v1:
>   - Fixed memory leak when a phase clock registration fails
>   - Moved the spinlock declaration
>   - Updated the DT bindings docs
>
> Maxime Ripard (4):
>   clk: sunxi: Rework MMC phase clocks
>   ARM: sunxi: dt: Add sample and output mmc clocks
>   mmc: sunxi: Convert MMC driver to the standard clock phase API
>   clk: sunxi: Remove custom phase function

Apart from the minor comments, whole series is

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

Also tested on my Cubieboard, Cubieboard2, Hummingbird A31,
and HSG H702 (A13 tablet).


ChenYu

>
>  Documentation/devicetree/bindings/clock/sunxi.txt  |   7 +-
>  .../devicetree/bindings/mmc/sunxi-mmc.txt          |   8 +-
>  arch/arm/boot/dts/sun4i-a10.dtsi                   |  72 +++++++----
>  arch/arm/boot/dts/sun5i-a10s.dtsi                  |  54 ++++++---
>  arch/arm/boot/dts/sun5i-a13.dtsi                   |  44 +++++--
>  arch/arm/boot/dts/sun6i-a31.dtsi                   |  72 +++++++----
>  arch/arm/boot/dts/sun7i-a20.dtsi                   |  72 +++++++----
>  arch/arm/boot/dts/sun8i-a23.dtsi                   |  54 ++++++---
>  drivers/clk/sunxi/clk-mod0.c                       | 131 +++++++++++----------
>  drivers/clk/sunxi/clk-sunxi.c                      |  37 ------
>  drivers/mmc/host/sunxi-mmc.c                       |  72 +++++++----
>  include/linux/clk/sunxi.h                          |  22 ----
>  12 files changed, 392 insertions(+), 253 deletions(-)
>  delete mode 100644 include/linux/clk/sunxi.h
>
> --
> 2.2.0
>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 3/4] mmc: sunxi: Convert MMC driver to the standard clock phase API
  2014-12-17  4:17   ` Chen-Yu Tsai
@ 2014-12-19 17:35     ` Maxime Ripard
  2014-12-19 17:50     ` Maxime Ripard
  1 sibling, 0 replies; 11+ messages in thread
From: Maxime Ripard @ 2014-12-19 17:35 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Wed, Dec 17, 2014 at 12:17:36PM +0800, Chen-Yu Tsai wrote:
> Hi,
> 
> On Wed, Dec 17, 2014 at 5:38 AM, Maxime Ripard
> <maxime.ripard@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@free-electrons.com>
> > Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
> > Acked-by: David Lanzend?rfer <david.lanzendoerfer@o2s.ch>
> > ---
> >  .../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 d1663b3c4143..afe20c322e55 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>
> 
> This conflicts with
> 
>     05e07d8 mmc: sunxi: Remove unused includes of linux/clk-private.h
> 
> when applied over
> 
>     a0eda58 (linux-next/master) Add linux-next specific files for 20141216

Thanks for the warning :)

It's a pretty trivial conflict though, and I'll be the one merging it.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20141219/ebab5b2a/attachment.sig>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 1/4] clk: sunxi: Rework MMC phase clocks
  2014-12-17  6:58   ` Chen-Yu Tsai
@ 2014-12-19 17:35     ` Maxime Ripard
  0 siblings, 0 replies; 11+ messages in thread
From: Maxime Ripard @ 2014-12-19 17:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Dec 17, 2014 at 02:58:33PM +0800, Chen-Yu Tsai wrote:
> Hi,
> 
> On Wed, Dec 17, 2014 at 5:38 AM, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> > Instead of having three different clocks for the main MMC clock and the two
> > phase sub-clocks, which involved having three different drivers sharing the
> > same register, rework it to have the same single driver registering three
> > different clocks.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > ---
> >  Documentation/devicetree/bindings/clock/sunxi.txt |   7 +-
> >  drivers/clk/sunxi/clk-mod0.c                      | 131 ++++++++++++----------
> >  2 files changed, 74 insertions(+), 64 deletions(-)
> >
> > diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
> > index 9dc4f55a04ad..8c60433a7fc9 100644
> > --- a/Documentation/devicetree/bindings/clock/sunxi.txt
> > +++ b/Documentation/devicetree/bindings/clock/sunxi.txt
> > @@ -55,8 +55,7 @@ Required properties:
> >         "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
> >         "allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23
> >         "allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13
> > -       "allwinner,sun4i-a10-mmc-output-clk" - for the MMC output clock on A10
> > -       "allwinner,sun4i-a10-mmc-sample-clk" - for the MMC sample clock on A10
> > +       "allwinner,sun4i-a10-mmc-clk" - for the MMC clock
> >         "allwinner,sun4i-a10-mod0-clk" - for the module 0 family of clocks
> >         "allwinner,sun8i-a23-mbus-clk" - for the MBUS clock on A23
> >         "allwinner,sun7i-a20-out-clk" - for the external output clocks
> > @@ -95,6 +94,10 @@ For "allwinner,sun6i-a31-pll6-clk", there are 2 outputs. The first output
> >  is the normal PLL6 output, or "pll6". The second output is rate doubled
> >  PLL6, or "pll6x2".
> >
> > +The "allwinner,sun4i-a10-mmc-clk" has three different outputs: the
> > +main clock, with the ID 0, and the output and sample clocks, with the
> > +IDs 1 and 2, respectively.
> > +
> 
> Could you also update the mmc/mod0 clock example in the bindings?
> Currently it is an mmc module clock using the mod0 compatible.

I'll do that, yep.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20141219/1aafcd8d/attachment.sig>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 3/4] mmc: sunxi: Convert MMC driver to the standard clock phase API
  2014-12-17  4:17   ` Chen-Yu Tsai
  2014-12-19 17:35     ` Maxime Ripard
@ 2014-12-19 17:50     ` Maxime Ripard
  1 sibling, 0 replies; 11+ messages in thread
From: Maxime Ripard @ 2014-12-19 17:50 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Dec 17, 2014 at 12:17:36PM +0800, Chen-Yu Tsai wrote:
> >         /* determine delays */
> >         if (rate <= 400000) {
> > -               oclk_dly = 0;
> > -               sclk_dly = 7;
> > +               oclk_dly = 180;
> > +               sclk_dly = 42;
> 
> 42 seems like an odd number. Maybe 45?

If the rate is at 400kHz, that means that the clock in muxed from the
24M, with a divider of 60.

That means that we can outphase the clocks only by a multiple of 6
(360 / 60). 7 * 6 = 42.

Depending on how the rounding goes, 45 might work too, but if we wan't
to be conservative, 42 doesn't change anything, 45 does.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20141219/ed8963eb/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2014-12-19 17:50 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-12-16 21:38 [PATCH v2 0/4] clk: sunxi: mmc: Last bits of phase handling Maxime Ripard
2014-12-16 21:38 ` [PATCH v2 1/4] clk: sunxi: Rework MMC phase clocks Maxime Ripard
2014-12-17  6:58   ` Chen-Yu Tsai
2014-12-19 17:35     ` Maxime Ripard
2014-12-16 21:38 ` [PATCH v2 2/4] ARM: sunxi: dt: Add sample and output mmc clocks Maxime Ripard
2014-12-16 21:38 ` [PATCH v2 3/4] mmc: sunxi: Convert MMC driver to the standard clock phase API Maxime Ripard
2014-12-17  4:17   ` Chen-Yu Tsai
2014-12-19 17:35     ` Maxime Ripard
2014-12-19 17:50     ` Maxime Ripard
2014-12-16 21:38 ` [PATCH v2 4/4] clk: sunxi: Remove custom phase function Maxime Ripard
2014-12-17 10:54 ` [PATCH v2 0/4] clk: sunxi: mmc: Last bits of phase handling Chen-Yu Tsai

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.