blob: fcdf5dc76076871ff7dcc0d229832b7f0e4011ef [file] [log] [blame]
Meng Wang43bbb872018-12-10 12:32:05 +08001// SPDX-License-Identifier: GPL-2.0-only
Mangesh Kunchamwarcdd68db2019-01-10 16:21:00 +05302/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303 */
4
5#include <linux/kernel.h>
6#include <linux/init.h>
7#include <linux/err.h>
8#include <linux/module.h>
9#include <linux/of.h>
10#include <linux/clk.h>
11#include <linux/clk-provider.h>
12#include "../../../drivers/clk/qcom/common.h"
Meng Wang15c825d2018-09-06 10:49:18 +080013#include <linux/pinctrl/consumer.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053014#include <linux/platform_device.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053015#include <dt-bindings/clock/qcom,audio-ext-clk.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053016#include <dsp/q6afe-v2.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053017#include "audio-ext-clk-up.h"
18
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -080019enum {
20 AUDIO_EXT_CLK_PMI,
21 AUDIO_EXT_CLK_LNBB2,
22 AUDIO_EXT_CLK_LPASS,
Laxminath Kasamd712cc72018-07-17 23:43:21 +053023 AUDIO_EXT_CLK_LPASS2,
24 AUDIO_EXT_CLK_LPASS3,
Aditya Bavanari7259ca62018-07-30 12:03:03 +053025 AUDIO_EXT_CLK_LPASS4,
26 AUDIO_EXT_CLK_LPASS5,
27 AUDIO_EXT_CLK_LPASS6,
28 AUDIO_EXT_CLK_LPASS7,
Mangesh Kunchamwarcdd68db2019-01-10 16:21:00 +053029 AUDIO_EXT_CLK_LPASS_CORE_HW_VOTE,
Sudheer Papothia1351b92019-03-07 18:52:08 +053030 AUDIO_EXT_CLK_LPASS8,
Laxminath Kasamd712cc72018-07-17 23:43:21 +053031 AUDIO_EXT_CLK_LPASS_MAX,
Rohit kumar68725bb2018-11-23 16:52:58 +053032 AUDIO_EXT_CLK_EXTERNAL_PLL = AUDIO_EXT_CLK_LPASS_MAX,
33 AUDIO_EXT_CLK_MAX,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053034};
35
36struct pinctrl_info {
37 struct pinctrl *pinctrl;
38 struct pinctrl_state *sleep;
39 struct pinctrl_state *active;
40 char __iomem *base;
41};
42
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -080043struct audio_ext_clk {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053044 struct pinctrl_info pnctrl_info;
45 struct clk_fixed_factor fact;
46};
47
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -080048struct audio_ext_clk_priv {
49 struct device *dev;
50 int clk_src;
51 struct afe_clk_set clk_cfg;
52 struct audio_ext_clk audio_clk;
Surendar Karka0a915f82018-07-09 20:30:03 +053053 const char *clk_name;
Mangesh Kunchamwarcdd68db2019-01-10 16:21:00 +053054 uint32_t lpass_core_hwvote_client_handle;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053055};
56
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -080057static inline struct audio_ext_clk_priv *to_audio_clk(struct clk_hw *hw)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053058{
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -080059 return container_of(hw, struct audio_ext_clk_priv, audio_clk.fact.hw);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053060}
61
62static int audio_ext_clk_prepare(struct clk_hw *hw)
63{
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -080064 struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw);
65 struct pinctrl_info *pnctrl_info = &clk_priv->audio_clk.pnctrl_info;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053066 int ret;
67
Laxminath Kasamd712cc72018-07-17 23:43:21 +053068 if ((clk_priv->clk_src >= AUDIO_EXT_CLK_LPASS) &&
69 (clk_priv->clk_src < AUDIO_EXT_CLK_LPASS_MAX)) {
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -080070 clk_priv->clk_cfg.enable = 1;
71 ret = afe_set_lpass_clk_cfg(IDX_RSVD_3, &clk_priv->clk_cfg);
72 if (ret < 0) {
73 pr_err("%s afe_set_digital_codec_core_clock failed\n",
74 __func__);
75 return ret;
76 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053077 }
78
79 if (pnctrl_info->pinctrl) {
80 ret = pinctrl_select_state(pnctrl_info->pinctrl,
81 pnctrl_info->active);
82 if (ret) {
83 pr_err("%s: active state select failed with %d\n",
84 __func__, ret);
85 return -EIO;
86 }
87 }
88
89 if (pnctrl_info->base)
90 iowrite32(1, pnctrl_info->base);
91 return 0;
92}
93
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -080094static void audio_ext_clk_unprepare(struct clk_hw *hw)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053095{
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -080096 struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw);
97 struct pinctrl_info *pnctrl_info = &clk_priv->audio_clk.pnctrl_info;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053098 int ret;
99
100 if (pnctrl_info->pinctrl) {
101 ret = pinctrl_select_state(pnctrl_info->pinctrl,
102 pnctrl_info->sleep);
103 if (ret) {
104 pr_err("%s: active state select failed with %d\n",
105 __func__, ret);
106 return;
107 }
108 }
109
Laxminath Kasamd712cc72018-07-17 23:43:21 +0530110 if ((clk_priv->clk_src >= AUDIO_EXT_CLK_LPASS) &&
111 (clk_priv->clk_src < AUDIO_EXT_CLK_LPASS_MAX)) {
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800112 clk_priv->clk_cfg.enable = 0;
113 ret = afe_set_lpass_clk_cfg(IDX_RSVD_3, &clk_priv->clk_cfg);
114 if (ret < 0)
115 pr_err("%s: afe_set_lpass_clk_cfg failed, ret = %d\n",
116 __func__, ret);
117 }
118
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530119 if (pnctrl_info->base)
120 iowrite32(0, pnctrl_info->base);
121}
122
Surendar Karka0a915f82018-07-09 20:30:03 +0530123static u8 audio_ext_clk_get_parent(struct clk_hw *hw)
124{
125 struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw);
126 int num_parents = clk_hw_get_num_parents(hw);
127 const char * const *parent_names = hw->init->parent_names;
128 u8 i = 0, ret = hw->init->num_parents + 1;
129
130 if ((clk_priv->clk_src == AUDIO_EXT_CLK_PMI) && clk_priv->clk_name) {
131 for (i = 0; i < num_parents; i++) {
132 if (!strcmp(parent_names[i], clk_priv->clk_name))
133 ret = i;
134 }
135 pr_debug("%s: parent index = %u\n", __func__, ret);
136 return ret;
137 } else
138 return 0;
139}
140
Mangesh Kunchamwarcdd68db2019-01-10 16:21:00 +0530141static int lpass_hw_vote_prepare(struct clk_hw *hw)
Mangesh Kunchamwar912a96a2018-11-13 16:04:53 +0530142{
143 struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw);
144 int ret;
145
Mangesh Kunchamwarcdd68db2019-01-10 16:21:00 +0530146 if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_CORE_HW_VOTE) {
147 ret = afe_vote_lpass_core_hw(AFE_LPASS_CORE_HW_MACRO_BLOCK,
148 "LPASS_HW_MACRO",
149 &clk_priv->lpass_core_hwvote_client_handle);
150 if (ret < 0) {
151 pr_err("%s lpass core hw vote failed %d\n",
152 __func__, ret);
153 return ret;
Mangesh Kunchamwar912a96a2018-11-13 16:04:53 +0530154 }
155 }
156
157 return 0;
158}
159
Mangesh Kunchamwarcdd68db2019-01-10 16:21:00 +0530160static void lpass_hw_vote_unprepare(struct clk_hw *hw)
Mangesh Kunchamwar912a96a2018-11-13 16:04:53 +0530161{
162 struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw);
163 int ret = 0;
164
Mangesh Kunchamwarcdd68db2019-01-10 16:21:00 +0530165 if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_CORE_HW_VOTE) {
166 ret = afe_unvote_lpass_core_hw(
167 AFE_LPASS_CORE_HW_MACRO_BLOCK,
168 clk_priv->lpass_core_hwvote_client_handle);
169 if (ret < 0) {
170 pr_err("%s lpass core hw vote failed %d\n",
171 __func__, ret);
Mangesh Kunchamwar912a96a2018-11-13 16:04:53 +0530172 }
173 }
174}
175
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800176static const struct clk_ops audio_ext_clk_ops = {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530177 .prepare = audio_ext_clk_prepare,
178 .unprepare = audio_ext_clk_unprepare,
Surendar Karka0a915f82018-07-09 20:30:03 +0530179 .get_parent = audio_ext_clk_get_parent,
180};
181
Mangesh Kunchamwarcdd68db2019-01-10 16:21:00 +0530182static const struct clk_ops lpass_hw_vote_ops = {
183 .prepare = lpass_hw_vote_prepare,
184 .unprepare = lpass_hw_vote_unprepare,
Mangesh Kunchamwar912a96a2018-11-13 16:04:53 +0530185};
186
Surendar Karka0a915f82018-07-09 20:30:03 +0530187static const char * const audio_ext_pmi_div_clk[] = {
188 "qpnp_clkdiv_1",
189 "pms405_div_clk1",
190 "pm6150_div_clk1",
Aditya Bavanari94eb98b2019-01-25 21:55:05 +0530191 "pm6125_div_clk1",
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530192};
193
Sudheer Papothi9b51e3e2018-07-21 05:20:10 +0530194static int audio_ext_clk_dummy_prepare(struct clk_hw *hw)
195{
196 return 0;
197}
198
199static void audio_ext_clk_dummy_unprepare(struct clk_hw *hw)
200{
201
202}
203
204static const struct clk_ops audio_ext_clk_dummy_ops = {
205 .prepare = audio_ext_clk_dummy_prepare,
206 .unprepare = audio_ext_clk_dummy_unprepare,
207};
208
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800209static struct audio_ext_clk audio_clk_array[] = {
210 {
211 .pnctrl_info = {NULL},
212 .fact = {
213 .mult = 1,
214 .div = 1,
215 .hw.init = &(struct clk_init_data){
216 .name = "audio_ext_pmi_clk",
Surendar Karka0a915f82018-07-09 20:30:03 +0530217 .parent_names = audio_ext_pmi_div_clk,
218 .num_parents =
219 ARRAY_SIZE(audio_ext_pmi_div_clk),
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800220 .ops = &audio_ext_clk_ops,
221 },
222 },
223 },
224 {
225 .pnctrl_info = {NULL},
226 .fact = {
227 .mult = 1,
228 .div = 1,
229 .hw.init = &(struct clk_init_data){
230 .name = "audio_ext_pmi_lnbb_clk",
231 .parent_names = (const char *[])
232 { "ln_bb_clk2" },
233 .num_parents = 1,
Sudheer Papothi9b51e3e2018-07-21 05:20:10 +0530234 .ops = &audio_ext_clk_dummy_ops,
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800235 },
236 },
237 },
238 {
239 .pnctrl_info = {NULL},
240 .fact = {
241 .mult = 1,
242 .div = 1,
243 .hw.init = &(struct clk_init_data){
244 .name = "audio_lpass_mclk",
245 .ops = &audio_ext_clk_ops,
246 },
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530247 },
248 },
Laxminath Kasamd712cc72018-07-17 23:43:21 +0530249 {
250 .pnctrl_info = {NULL},
251 .fact = {
252 .mult = 1,
253 .div = 1,
254 .hw.init = &(struct clk_init_data){
255 .name = "audio_lpass_mclk2",
256 .ops = &audio_ext_clk_ops,
257 },
258 },
259 },
260 {
261 .pnctrl_info = {NULL},
262 .fact = {
263 .mult = 1,
264 .div = 1,
265 .hw.init = &(struct clk_init_data){
266 .name = "audio_lpass_mclk3",
267 .ops = &audio_ext_clk_ops,
268 },
269 },
270 },
Aditya Bavanari7259ca62018-07-30 12:03:03 +0530271 {
272 .pnctrl_info = {NULL},
273 .fact = {
274 .mult = 1,
275 .div = 1,
276 .hw.init = &(struct clk_init_data){
277 .name = "audio_lpass_mclk4",
278 .ops = &audio_ext_clk_ops,
279 },
280 },
281 },
282 {
283 .pnctrl_info = {NULL},
284 .fact = {
285 .mult = 1,
286 .div = 1,
287 .hw.init = &(struct clk_init_data){
288 .name = "audio_lpass_mclk5",
289 .ops = &audio_ext_clk_ops,
290 },
291 },
292 },
293 {
294 .pnctrl_info = {NULL},
295 .fact = {
296 .mult = 1,
297 .div = 1,
298 .hw.init = &(struct clk_init_data){
299 .name = "audio_lpass_mclk6",
300 .ops = &audio_ext_clk_ops,
301 },
302 },
303 },
304 {
305 .pnctrl_info = {NULL},
306 .fact = {
307 .mult = 1,
308 .div = 1,
309 .hw.init = &(struct clk_init_data){
310 .name = "audio_lpass_mclk7",
311 .ops = &audio_ext_clk_ops,
312 },
313 },
314 },
Mangesh Kunchamwar912a96a2018-11-13 16:04:53 +0530315 {
316 .pnctrl_info = {NULL},
317 .fact = {
318 .hw.init = &(struct clk_init_data){
Mangesh Kunchamwarcdd68db2019-01-10 16:21:00 +0530319 .name = "lpass_hw_vote_clk",
320 .ops = &lpass_hw_vote_ops,
Mangesh Kunchamwar912a96a2018-11-13 16:04:53 +0530321 },
322 },
323 },
Rohit kumar68725bb2018-11-23 16:52:58 +0530324 {
325 .pnctrl_info = {NULL},
326 .fact = {
327 .mult = 1,
328 .div = 1,
329 .hw.init = &(struct clk_init_data){
Sudheer Papothia1351b92019-03-07 18:52:08 +0530330 .name = "audio_lpass_mclk8",
331 .ops = &audio_ext_clk_ops,
332 },
333 },
334 },
335 {
336 .pnctrl_info = {NULL},
337 .fact = {
338 .mult = 1,
339 .div = 1,
340 .hw.init = &(struct clk_init_data){
Rohit kumar68725bb2018-11-23 16:52:58 +0530341 .name = "audio_external_pll_clk",
342 .ops = &audio_ext_clk_ops,
343 },
344 },
345 },
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530346};
347
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800348static int audio_get_pinctrl(struct platform_device *pdev)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530349{
350 struct device *dev = &pdev->dev;
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800351 struct audio_ext_clk_priv *clk_priv = platform_get_drvdata(pdev);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530352 struct pinctrl_info *pnctrl_info;
353 struct pinctrl *pinctrl;
354 int ret;
355 u32 reg;
356
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800357 pnctrl_info = &clk_priv->audio_clk.pnctrl_info;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530358 if (pnctrl_info->pinctrl) {
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800359 dev_err(dev, "%s: already requested before\n",
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530360 __func__);
361 return -EINVAL;
362 }
363
364 pinctrl = devm_pinctrl_get(dev);
365 if (IS_ERR_OR_NULL(pinctrl)) {
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800366 dev_err(dev, "%s: Unable to get pinctrl handle\n",
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530367 __func__);
368 return -EINVAL;
369 }
370 pnctrl_info->pinctrl = pinctrl;
371 /* get all state handles from Device Tree */
372 pnctrl_info->sleep = pinctrl_lookup_state(pinctrl, "sleep");
373 if (IS_ERR(pnctrl_info->sleep)) {
374 dev_err(dev, "%s: could not get sleep pinstate\n",
375 __func__);
376 goto err;
377 }
378 pnctrl_info->active = pinctrl_lookup_state(pinctrl, "active");
379 if (IS_ERR(pnctrl_info->active)) {
380 dev_err(dev, "%s: could not get active pinstate\n",
381 __func__);
382 goto err;
383 }
384 /* Reset the TLMM pins to a default state */
385 ret = pinctrl_select_state(pnctrl_info->pinctrl,
386 pnctrl_info->sleep);
387 if (ret) {
388 dev_err(dev, "%s: Disable TLMM pins failed with %d\n",
389 __func__, ret);
390 goto err;
391 }
392
393 ret = of_property_read_u32(dev->of_node, "qcom,mclk-clk-reg", &reg);
394 if (ret < 0) {
395 dev_dbg(dev, "%s: miss mclk reg\n", __func__);
396 } else {
397 pnctrl_info->base = ioremap(reg, sizeof(u32));
398 if (pnctrl_info->base == NULL) {
399 dev_err(dev, "%s ioremap failed\n", __func__);
400 goto err;
401 }
402 }
403
404 return 0;
405
406err:
407 devm_pinctrl_put(pnctrl_info->pinctrl);
408 return -EINVAL;
409}
410
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800411static int audio_put_pinctrl(struct platform_device *pdev)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530412{
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800413 struct audio_ext_clk_priv *clk_priv = platform_get_drvdata(pdev);
414 struct pinctrl_info *pnctrl_info = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530415
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800416 pnctrl_info = &clk_priv->audio_clk.pnctrl_info;
417 if (pnctrl_info && pnctrl_info->pinctrl) {
418 devm_pinctrl_put(pnctrl_info->pinctrl);
419 pnctrl_info->pinctrl = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530420 }
421
422 return 0;
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800423}
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530424
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800425static int audio_get_clk_data(struct platform_device *pdev)
426{
427 int ret;
428 struct clk *audio_clk;
429 struct clk_hw *clkhw;
430 struct clk_onecell_data *clk_data;
431 struct audio_ext_clk_priv *clk_priv = platform_get_drvdata(pdev);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530432
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800433 clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL);
434 if (!clk_data)
435 return -ENOMEM;
436
437 clk_data->clk_num = 1;
438 clk_data->clks = devm_kzalloc(&pdev->dev,
439 sizeof(struct clk *),
440 GFP_KERNEL);
441 if (!clk_data->clks)
442 return -ENOMEM;
443
444 clkhw = &clk_priv->audio_clk.fact.hw;
445 audio_clk = devm_clk_register(&pdev->dev, clkhw);
446 if (IS_ERR(audio_clk)) {
447 dev_err(&pdev->dev,
448 "%s: clock register failed for clk_src = %d\\n",
449 __func__, clk_priv->clk_src);
450 ret = PTR_ERR(audio_clk);
451 return ret;
452 }
453 clk_data->clks[0] = audio_clk;
454
455 ret = of_clk_add_provider(pdev->dev.of_node,
456 of_clk_src_onecell_get, clk_data);
457 if (ret)
458 dev_err(&pdev->dev, "%s: clock add failed for clk_src = %d\n",
459 __func__, clk_priv->clk_src);
460
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530461 return ret;
462}
463
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800464static int audio_ref_clk_probe(struct platform_device *pdev)
465{
466 int ret;
467 struct audio_ext_clk_priv *clk_priv;
Laxminath Kasam43c1a132018-06-15 13:18:07 +0530468 u32 clk_freq = 0, clk_id = 0, clk_src = 0, use_pinctrl = 0;
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800469
470 clk_priv = devm_kzalloc(&pdev->dev, sizeof(*clk_priv), GFP_KERNEL);
471 if (!clk_priv)
472 return -ENOMEM;
473
474 ret = of_property_read_u32(pdev->dev.of_node,
475 "qcom,codec-ext-clk-src",
476 &clk_src);
477 if (ret) {
478 dev_err(&pdev->dev, "%s: could not get clk source, ret = %d\n",
479 __func__, ret);
480 return ret;
481 }
482
483 if (clk_src >= AUDIO_EXT_CLK_MAX) {
484 dev_err(&pdev->dev, "%s: Invalid clk source = %d\n",
485 __func__, clk_src);
486 return -EINVAL;
487 }
Surendar Karka0a915f82018-07-09 20:30:03 +0530488 clk_priv->clk_name = NULL;
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800489 clk_priv->clk_src = clk_src;
490 memcpy(&clk_priv->audio_clk, &audio_clk_array[clk_src],
491 sizeof(struct audio_ext_clk));
492
493 /* Init lpass clk default values */
494 clk_priv->clk_cfg.clk_set_minor_version =
495 Q6AFE_LPASS_CLK_CONFIG_API_VERSION;
496 clk_priv->clk_cfg.clk_id = Q6AFE_LPASS_CLK_ID_SPEAKER_I2S_OSR;
497 clk_priv->clk_cfg.clk_freq_in_hz = Q6AFE_LPASS_OSR_CLK_9_P600_MHZ;
498 clk_priv->clk_cfg.clk_attri = Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO;
499
500 ret = of_property_read_u32(pdev->dev.of_node,
501 "qcom,codec-lpass-ext-clk-freq",
502 &clk_freq);
503 if (!ret)
504 clk_priv->clk_cfg.clk_freq_in_hz = clk_freq;
505
506 ret = of_property_read_u32(pdev->dev.of_node,
507 "qcom,codec-lpass-clk-id",
508 &clk_id);
509 if (!ret)
510 clk_priv->clk_cfg.clk_id = clk_id;
511
512 dev_dbg(&pdev->dev, "%s: ext-clk freq: %d, lpass clk_id: %d, clk_src: %d\n",
513 __func__, clk_priv->clk_cfg.clk_freq_in_hz,
514 clk_priv->clk_cfg.clk_id, clk_priv->clk_src);
515 platform_set_drvdata(pdev, clk_priv);
516
Surendar Karka0a915f82018-07-09 20:30:03 +0530517 ret = of_property_read_string(pdev->dev.of_node, "pmic-clock-names",
518 &clk_priv->clk_name);
519 if (ret)
520 dev_dbg(&pdev->dev, "%s: could not find pmic clock names\n",
521 __func__);
Laxminath Kasam43c1a132018-06-15 13:18:07 +0530522 /*
523 * property qcom,use-pinctrl to be defined in DTSI to val 1
524 * for clock nodes using pinctrl
525 */
526 of_property_read_u32(pdev->dev.of_node, "qcom,use-pinctrl",
527 &use_pinctrl);
528 dev_dbg(&pdev->dev, "%s: use-pinctrl : %d\n",
529 __func__, use_pinctrl);
530
531 if (use_pinctrl) {
532 ret = audio_get_pinctrl(pdev);
533 if (ret) {
534 dev_err(&pdev->dev, "%s: Parsing PMI pinctrl failed\n",
535 __func__);
536 return ret;
537 }
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800538 }
539
540 ret = audio_get_clk_data(pdev);
541 if (ret) {
542 dev_err(&pdev->dev, "%s: clk_init is failed\n",
543 __func__);
544 audio_put_pinctrl(pdev);
545 return ret;
546 }
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800547 return 0;
548}
549
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530550static int audio_ref_clk_remove(struct platform_device *pdev)
551{
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800552 audio_put_pinctrl(pdev);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530553
554 return 0;
555}
556
557static const struct of_device_id audio_ref_clk_match[] = {
558 {.compatible = "qcom,audio-ref-clk"},
559 {}
560};
561MODULE_DEVICE_TABLE(of, audio_ref_clk_match);
562
563static struct platform_driver audio_ref_clk_driver = {
564 .driver = {
565 .name = "audio-ref-clk",
566 .owner = THIS_MODULE,
567 .of_match_table = audio_ref_clk_match,
Xiaojun Sang53cd13a2018-06-29 15:14:37 +0800568 .suppress_bind_attrs = true,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530569 },
570 .probe = audio_ref_clk_probe,
571 .remove = audio_ref_clk_remove,
572};
573
574int audio_ref_clk_platform_init(void)
575{
576 return platform_driver_register(&audio_ref_clk_driver);
577}
578
579void audio_ref_clk_platform_exit(void)
580{
581 platform_driver_unregister(&audio_ref_clk_driver);
582}
583
584MODULE_DESCRIPTION("Audio Ref Up Clock module platform driver");
585MODULE_LICENSE("GPL v2");