diff options
-rw-r--r-- | drivers/clk/samsung/clk-exynos-audss.c | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c index b50469faf70c..f7eff82738ab 100644 --- a/drivers/clk/samsung/clk-exynos-audss.c +++ b/drivers/clk/samsung/clk-exynos-audss.c | |||
@@ -29,6 +29,13 @@ static DEFINE_SPINLOCK(lock); | |||
29 | static struct clk **clk_table; | 29 | static struct clk **clk_table; |
30 | static void __iomem *reg_base; | 30 | static void __iomem *reg_base; |
31 | static struct clk_onecell_data clk_data; | 31 | static struct clk_onecell_data clk_data; |
32 | /* | ||
33 | * On Exynos5420 this will be a clock which has to be enabled before any | ||
34 | * access to audss registers. Typically a child of EPLL. | ||
35 | * | ||
36 | * On other platforms this will be -ENODEV. | ||
37 | */ | ||
38 | static struct clk *epll; | ||
32 | 39 | ||
33 | #define ASS_CLK_SRC 0x0 | 40 | #define ASS_CLK_SRC 0x0 |
34 | #define ASS_CLK_DIV 0x4 | 41 | #define ASS_CLK_DIV 0x4 |
@@ -98,6 +105,8 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) | |||
98 | dev_err(&pdev->dev, "failed to map audss registers\n"); | 105 | dev_err(&pdev->dev, "failed to map audss registers\n"); |
99 | return PTR_ERR(reg_base); | 106 | return PTR_ERR(reg_base); |
100 | } | 107 | } |
108 | /* EPLL don't have to be enabled for boards other than Exynos5420 */ | ||
109 | epll = ERR_PTR(-ENODEV); | ||
101 | 110 | ||
102 | clk_table = devm_kzalloc(&pdev->dev, | 111 | clk_table = devm_kzalloc(&pdev->dev, |
103 | sizeof(struct clk *) * EXYNOS_AUDSS_MAX_CLKS, | 112 | sizeof(struct clk *) * EXYNOS_AUDSS_MAX_CLKS, |
@@ -115,8 +124,20 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) | |||
115 | pll_in = devm_clk_get(&pdev->dev, "pll_in"); | 124 | pll_in = devm_clk_get(&pdev->dev, "pll_in"); |
116 | if (!IS_ERR(pll_ref)) | 125 | if (!IS_ERR(pll_ref)) |
117 | mout_audss_p[0] = __clk_get_name(pll_ref); | 126 | mout_audss_p[0] = __clk_get_name(pll_ref); |
118 | if (!IS_ERR(pll_in)) | 127 | if (!IS_ERR(pll_in)) { |
119 | mout_audss_p[1] = __clk_get_name(pll_in); | 128 | mout_audss_p[1] = __clk_get_name(pll_in); |
129 | |||
130 | if (variant == TYPE_EXYNOS5420) { | ||
131 | epll = pll_in; | ||
132 | |||
133 | ret = clk_prepare_enable(epll); | ||
134 | if (ret) { | ||
135 | dev_err(&pdev->dev, | ||
136 | "failed to prepare the epll clock\n"); | ||
137 | return ret; | ||
138 | } | ||
139 | } | ||
140 | } | ||
120 | clk_table[EXYNOS_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss", | 141 | clk_table[EXYNOS_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss", |
121 | mout_audss_p, ARRAY_SIZE(mout_audss_p), | 142 | mout_audss_p, ARRAY_SIZE(mout_audss_p), |
122 | CLK_SET_RATE_NO_REPARENT, | 143 | CLK_SET_RATE_NO_REPARENT, |
@@ -203,6 +224,9 @@ unregister: | |||
203 | clk_unregister(clk_table[i]); | 224 | clk_unregister(clk_table[i]); |
204 | } | 225 | } |
205 | 226 | ||
227 | if (!IS_ERR(epll)) | ||
228 | clk_disable_unprepare(epll); | ||
229 | |||
206 | return ret; | 230 | return ret; |
207 | } | 231 | } |
208 | 232 | ||
@@ -221,6 +245,9 @@ static int exynos_audss_clk_remove(struct platform_device *pdev) | |||
221 | clk_unregister(clk_table[i]); | 245 | clk_unregister(clk_table[i]); |
222 | } | 246 | } |
223 | 247 | ||
248 | if (!IS_ERR(epll)) | ||
249 | clk_disable_unprepare(epll); | ||
250 | |||
224 | return 0; | 251 | return 0; |
225 | } | 252 | } |
226 | 253 | ||