Commit a45af6d3 authored by Konstantin Porotchkin's avatar Konstantin Porotchkin Committed by Gregory CLEMENT

clk: mvebu: cp110: add sdio clock to cp-110 system controller

This commit updates the CP110 system controller driver to add the
definition for a missing clock.

The SDIO clock is dedicated driving the SDHCI interface and its frequency
is 400MHz (2/5 of PLL source clock).

The SDIO interface should be bound to this clock and not the core clock
as in the older code.
Using the wrong clock lead to a maximum SDHCI frequency of 250 Mhz, while
the HW really supports up to 400 Mhz.

This patch also fixes the NAND clock relationship documentation.
Signed-off-by: default avatarKonstantin Porotchkin <kostap@marvell.com>
[gregory.clement@free-electrons.com:
- use sdio instead of emmc to name the clock]
Reviewed-by: default avatarThomas Petazzoni <thomas.petazzoni@free-electrons.com>
Acked-by: default avatarRob Herring <robh@kernel.org>
Signed-off-by: default avatarGregory CLEMENT <gregory.clement@free-electrons.com>
parent 5ffeb5f5
...@@ -11,15 +11,16 @@ ...@@ -11,15 +11,16 @@
*/ */
/* /*
* CP110 has 5 core clocks: * CP110 has 6 core clocks:
* *
* - APLL (1 Ghz) * - APLL (1 Ghz)
* - PPv2 core (1/3 APLL) * - PPv2 core (1/3 APLL)
* - EIP (1/2 APLL) * - EIP (1/2 APLL)
* - Core (1/2 EIP) * - Core (1/2 EIP)
* - SDIO (2/5 APLL)
* *
* - NAND clock, which is either: * - NAND clock, which is either:
* - Equal to the core clock * - Equal to SDIO clock
* - 2/5 APLL * - 2/5 APLL
* *
* CP110 has 32 gatable clocks, for the various peripherals in the * CP110 has 32 gatable clocks, for the various peripherals in the
...@@ -46,7 +47,7 @@ enum { ...@@ -46,7 +47,7 @@ enum {
CP110_CLK_TYPE_GATABLE, CP110_CLK_TYPE_GATABLE,
}; };
#define CP110_MAX_CORE_CLOCKS 5 #define CP110_MAX_CORE_CLOCKS 6
#define CP110_MAX_GATABLE_CLOCKS 32 #define CP110_MAX_GATABLE_CLOCKS 32
#define CP110_CLK_NUM \ #define CP110_CLK_NUM \
...@@ -57,6 +58,7 @@ enum { ...@@ -57,6 +58,7 @@ enum {
#define CP110_CORE_EIP 2 #define CP110_CORE_EIP 2
#define CP110_CORE_CORE 3 #define CP110_CORE_CORE 3
#define CP110_CORE_NAND 4 #define CP110_CORE_NAND 4
#define CP110_CORE_SDIO 5
/* A number of gatable clocks need special handling */ /* A number of gatable clocks need special handling */
#define CP110_GATE_AUDIO 0 #define CP110_GATE_AUDIO 0
...@@ -235,7 +237,8 @@ static int cp110_syscon_common_probe(struct platform_device *pdev, ...@@ -235,7 +237,8 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
struct regmap *regmap; struct regmap *regmap;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
const char *ppv2_name, *apll_name, *core_name, *eip_name, *nand_name; const char *ppv2_name, *apll_name, *core_name, *eip_name, *nand_name,
*sdio_name;
struct clk_hw_onecell_data *cp110_clk_data; struct clk_hw_onecell_data *cp110_clk_data;
struct clk_hw *hw, **cp110_clks; struct clk_hw *hw, **cp110_clks;
u32 nand_clk_ctrl; u32 nand_clk_ctrl;
...@@ -315,6 +318,17 @@ static int cp110_syscon_common_probe(struct platform_device *pdev, ...@@ -315,6 +318,17 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
cp110_clks[CP110_CORE_NAND] = hw; cp110_clks[CP110_CORE_NAND] = hw;
/* SDIO clock is APLL/2.5 */
sdio_name = cp110_unique_name(dev, syscon_node, "sdio-core");
hw = clk_hw_register_fixed_factor(NULL, sdio_name,
apll_name, 0, 2, 5);
if (IS_ERR(hw)) {
ret = PTR_ERR(hw);
goto fail_sdio;
}
cp110_clks[CP110_CORE_SDIO] = hw;
/* create the unique name for all the gate clocks */ /* create the unique name for all the gate clocks */
for (i = 0; i < ARRAY_SIZE(gate_base_names); i++) for (i = 0; i < ARRAY_SIZE(gate_base_names); i++)
gate_name[i] = cp110_unique_name(dev, syscon_node, gate_name[i] = cp110_unique_name(dev, syscon_node,
...@@ -344,6 +358,8 @@ static int cp110_syscon_common_probe(struct platform_device *pdev, ...@@ -344,6 +358,8 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
parent = ppv2_name; parent = ppv2_name;
break; break;
case CP110_GATE_SDIO: case CP110_GATE_SDIO:
parent = sdio_name;
break;
case CP110_GATE_GOP_DP: case CP110_GATE_GOP_DP:
parent = gate_name[CP110_GATE_SDMMC_GOP]; parent = gate_name[CP110_GATE_SDMMC_GOP];
break; break;
...@@ -391,6 +407,8 @@ static int cp110_syscon_common_probe(struct platform_device *pdev, ...@@ -391,6 +407,8 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
cp110_unregister_gate(hw); cp110_unregister_gate(hw);
} }
clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_SDIO]);
fail_sdio:
clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_NAND]); clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_NAND]);
fail_nand: fail_nand:
clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]); clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]);
......
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