blob: e86b30eed11ab0c9a6ad497e328f1b968751e515 [file] [log] [blame]
Meng Wang43bbb872018-12-10 12:32:05 +08001// SPDX-License-Identifier: GPL-2.0-only
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -08002/* Copyright (c) 2015-2018, 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>
Mangesh Kunchamwar912a96a2018-11-13 16:04:53 +053017#include <dsp/q6core.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053018#include "audio-ext-clk-up.h"
19
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -080020enum {
21 AUDIO_EXT_CLK_PMI,
22 AUDIO_EXT_CLK_LNBB2,
23 AUDIO_EXT_CLK_LPASS,
Laxminath Kasamd712cc72018-07-17 23:43:21 +053024 AUDIO_EXT_CLK_LPASS2,
25 AUDIO_EXT_CLK_LPASS3,
Aditya Bavanari7259ca62018-07-30 12:03:03 +053026 AUDIO_EXT_CLK_LPASS4,
27 AUDIO_EXT_CLK_LPASS5,
28 AUDIO_EXT_CLK_LPASS6,
29 AUDIO_EXT_CLK_LPASS7,
Mangesh Kunchamwar912a96a2018-11-13 16:04:53 +053030 AUDIO_EXT_CLK_LPASS_NPA_RSC_ISLAND,
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 Kunchamwar912a96a2018-11-13 16:04:53 +053054 uint32_t npa_rsc_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 Kunchamwar912a96a2018-11-13 16:04:53 +0530141static int lpass_npa_rsc_prepare(struct clk_hw *hw)
142{
143 struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw);
144 int ret;
145
146 if ((clk_priv->clk_src >= AUDIO_EXT_CLK_LPASS_NPA_RSC_ISLAND) &&
147 (clk_priv->clk_src < AUDIO_EXT_CLK_LPASS_MAX)) {
148 if (q6core_get_avcs_api_version_per_service(
149 APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= AVCS_API_VERSION_V4) {
150 ret = q6core_request_island_transition(
151 clk_priv->npa_rsc_client_handle, false);
152 if (ret < 0) {
153 pr_err("%s q6core_request_island_transition failed %d\n",
154 __func__, ret);
155 return ret;
156 }
157 }
158 }
159
160 return 0;
161}
162
163static void lpass_npa_rsc_unprepare(struct clk_hw *hw)
164{
165 struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw);
166 int ret = 0;
167
168 if ((clk_priv->clk_src >= AUDIO_EXT_CLK_LPASS_NPA_RSC_ISLAND) &&
169 (clk_priv->clk_src < AUDIO_EXT_CLK_LPASS_MAX)) {
170 if (q6core_get_avcs_api_version_per_service(
171 APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= AVCS_API_VERSION_V4) {
172 ret = q6core_request_island_transition(
173 clk_priv->npa_rsc_client_handle, true);
174 if (ret < 0) {
175 pr_err("%s q6core_request_island_transition failed %d\n",
176 __func__, ret);
177 }
178 }
179 }
180}
181
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800182static const struct clk_ops audio_ext_clk_ops = {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530183 .prepare = audio_ext_clk_prepare,
184 .unprepare = audio_ext_clk_unprepare,
Surendar Karka0a915f82018-07-09 20:30:03 +0530185 .get_parent = audio_ext_clk_get_parent,
186};
187
Mangesh Kunchamwar912a96a2018-11-13 16:04:53 +0530188static const struct clk_ops lpass_npa_rsc_ops = {
189 .prepare = lpass_npa_rsc_prepare,
190 .unprepare = lpass_npa_rsc_unprepare,
191};
192
Surendar Karka0a915f82018-07-09 20:30:03 +0530193static const char * const audio_ext_pmi_div_clk[] = {
194 "qpnp_clkdiv_1",
195 "pms405_div_clk1",
196 "pm6150_div_clk1",
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530197};
198
Sudheer Papothi9b51e3e2018-07-21 05:20:10 +0530199static int audio_ext_clk_dummy_prepare(struct clk_hw *hw)
200{
201 return 0;
202}
203
204static void audio_ext_clk_dummy_unprepare(struct clk_hw *hw)
205{
206
207}
208
209static const struct clk_ops audio_ext_clk_dummy_ops = {
210 .prepare = audio_ext_clk_dummy_prepare,
211 .unprepare = audio_ext_clk_dummy_unprepare,
212};
213
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800214static struct audio_ext_clk audio_clk_array[] = {
215 {
216 .pnctrl_info = {NULL},
217 .fact = {
218 .mult = 1,
219 .div = 1,
220 .hw.init = &(struct clk_init_data){
221 .name = "audio_ext_pmi_clk",
Surendar Karka0a915f82018-07-09 20:30:03 +0530222 .parent_names = audio_ext_pmi_div_clk,
223 .num_parents =
224 ARRAY_SIZE(audio_ext_pmi_div_clk),
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800225 .ops = &audio_ext_clk_ops,
226 },
227 },
228 },
229 {
230 .pnctrl_info = {NULL},
231 .fact = {
232 .mult = 1,
233 .div = 1,
234 .hw.init = &(struct clk_init_data){
235 .name = "audio_ext_pmi_lnbb_clk",
236 .parent_names = (const char *[])
237 { "ln_bb_clk2" },
238 .num_parents = 1,
Sudheer Papothi9b51e3e2018-07-21 05:20:10 +0530239 .ops = &audio_ext_clk_dummy_ops,
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800240 },
241 },
242 },
243 {
244 .pnctrl_info = {NULL},
245 .fact = {
246 .mult = 1,
247 .div = 1,
248 .hw.init = &(struct clk_init_data){
249 .name = "audio_lpass_mclk",
250 .ops = &audio_ext_clk_ops,
251 },
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530252 },
253 },
Laxminath Kasamd712cc72018-07-17 23:43:21 +0530254 {
255 .pnctrl_info = {NULL},
256 .fact = {
257 .mult = 1,
258 .div = 1,
259 .hw.init = &(struct clk_init_data){
260 .name = "audio_lpass_mclk2",
261 .ops = &audio_ext_clk_ops,
262 },
263 },
264 },
265 {
266 .pnctrl_info = {NULL},
267 .fact = {
268 .mult = 1,
269 .div = 1,
270 .hw.init = &(struct clk_init_data){
271 .name = "audio_lpass_mclk3",
272 .ops = &audio_ext_clk_ops,
273 },
274 },
275 },
Aditya Bavanari7259ca62018-07-30 12:03:03 +0530276 {
277 .pnctrl_info = {NULL},
278 .fact = {
279 .mult = 1,
280 .div = 1,
281 .hw.init = &(struct clk_init_data){
282 .name = "audio_lpass_mclk4",
283 .ops = &audio_ext_clk_ops,
284 },
285 },
286 },
287 {
288 .pnctrl_info = {NULL},
289 .fact = {
290 .mult = 1,
291 .div = 1,
292 .hw.init = &(struct clk_init_data){
293 .name = "audio_lpass_mclk5",
294 .ops = &audio_ext_clk_ops,
295 },
296 },
297 },
298 {
299 .pnctrl_info = {NULL},
300 .fact = {
301 .mult = 1,
302 .div = 1,
303 .hw.init = &(struct clk_init_data){
304 .name = "audio_lpass_mclk6",
305 .ops = &audio_ext_clk_ops,
306 },
307 },
308 },
309 {
310 .pnctrl_info = {NULL},
311 .fact = {
312 .mult = 1,
313 .div = 1,
314 .hw.init = &(struct clk_init_data){
315 .name = "audio_lpass_mclk7",
316 .ops = &audio_ext_clk_ops,
317 },
318 },
319 },
Mangesh Kunchamwar912a96a2018-11-13 16:04:53 +0530320 {
321 .pnctrl_info = {NULL},
322 .fact = {
323 .hw.init = &(struct clk_init_data){
324 .name = "lpass_npa_rsc_island_clk",
325 .ops = &lpass_npa_rsc_ops,
326 },
327 },
328 },
Rohit kumar68725bb2018-11-23 16:52:58 +0530329 {
330 .pnctrl_info = {NULL},
331 .fact = {
332 .mult = 1,
333 .div = 1,
334 .hw.init = &(struct clk_init_data){
335 .name = "audio_external_pll_clk",
336 .ops = &audio_ext_clk_ops,
337 },
338 },
339 },
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530340};
341
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800342static int audio_get_pinctrl(struct platform_device *pdev)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530343{
344 struct device *dev = &pdev->dev;
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800345 struct audio_ext_clk_priv *clk_priv = platform_get_drvdata(pdev);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530346 struct pinctrl_info *pnctrl_info;
347 struct pinctrl *pinctrl;
348 int ret;
349 u32 reg;
350
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800351 pnctrl_info = &clk_priv->audio_clk.pnctrl_info;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530352 if (pnctrl_info->pinctrl) {
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800353 dev_err(dev, "%s: already requested before\n",
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530354 __func__);
355 return -EINVAL;
356 }
357
358 pinctrl = devm_pinctrl_get(dev);
359 if (IS_ERR_OR_NULL(pinctrl)) {
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800360 dev_err(dev, "%s: Unable to get pinctrl handle\n",
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530361 __func__);
362 return -EINVAL;
363 }
364 pnctrl_info->pinctrl = pinctrl;
365 /* get all state handles from Device Tree */
366 pnctrl_info->sleep = pinctrl_lookup_state(pinctrl, "sleep");
367 if (IS_ERR(pnctrl_info->sleep)) {
368 dev_err(dev, "%s: could not get sleep pinstate\n",
369 __func__);
370 goto err;
371 }
372 pnctrl_info->active = pinctrl_lookup_state(pinctrl, "active");
373 if (IS_ERR(pnctrl_info->active)) {
374 dev_err(dev, "%s: could not get active pinstate\n",
375 __func__);
376 goto err;
377 }
378 /* Reset the TLMM pins to a default state */
379 ret = pinctrl_select_state(pnctrl_info->pinctrl,
380 pnctrl_info->sleep);
381 if (ret) {
382 dev_err(dev, "%s: Disable TLMM pins failed with %d\n",
383 __func__, ret);
384 goto err;
385 }
386
387 ret = of_property_read_u32(dev->of_node, "qcom,mclk-clk-reg", &reg);
388 if (ret < 0) {
389 dev_dbg(dev, "%s: miss mclk reg\n", __func__);
390 } else {
391 pnctrl_info->base = ioremap(reg, sizeof(u32));
392 if (pnctrl_info->base == NULL) {
393 dev_err(dev, "%s ioremap failed\n", __func__);
394 goto err;
395 }
396 }
397
398 return 0;
399
400err:
401 devm_pinctrl_put(pnctrl_info->pinctrl);
402 return -EINVAL;
403}
404
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800405static int audio_put_pinctrl(struct platform_device *pdev)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530406{
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800407 struct audio_ext_clk_priv *clk_priv = platform_get_drvdata(pdev);
408 struct pinctrl_info *pnctrl_info = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530409
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800410 pnctrl_info = &clk_priv->audio_clk.pnctrl_info;
411 if (pnctrl_info && pnctrl_info->pinctrl) {
412 devm_pinctrl_put(pnctrl_info->pinctrl);
413 pnctrl_info->pinctrl = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530414 }
415
416 return 0;
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800417}
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530418
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800419static int audio_get_clk_data(struct platform_device *pdev)
420{
421 int ret;
422 struct clk *audio_clk;
423 struct clk_hw *clkhw;
424 struct clk_onecell_data *clk_data;
425 struct audio_ext_clk_priv *clk_priv = platform_get_drvdata(pdev);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530426
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800427 clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL);
428 if (!clk_data)
429 return -ENOMEM;
430
431 clk_data->clk_num = 1;
432 clk_data->clks = devm_kzalloc(&pdev->dev,
433 sizeof(struct clk *),
434 GFP_KERNEL);
435 if (!clk_data->clks)
436 return -ENOMEM;
437
438 clkhw = &clk_priv->audio_clk.fact.hw;
439 audio_clk = devm_clk_register(&pdev->dev, clkhw);
440 if (IS_ERR(audio_clk)) {
441 dev_err(&pdev->dev,
442 "%s: clock register failed for clk_src = %d\\n",
443 __func__, clk_priv->clk_src);
444 ret = PTR_ERR(audio_clk);
445 return ret;
446 }
447 clk_data->clks[0] = audio_clk;
448
449 ret = of_clk_add_provider(pdev->dev.of_node,
450 of_clk_src_onecell_get, clk_data);
451 if (ret)
452 dev_err(&pdev->dev, "%s: clock add failed for clk_src = %d\n",
453 __func__, clk_priv->clk_src);
454
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530455 return ret;
456}
457
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800458static int audio_ref_clk_probe(struct platform_device *pdev)
459{
460 int ret;
461 struct audio_ext_clk_priv *clk_priv;
Laxminath Kasam43c1a132018-06-15 13:18:07 +0530462 u32 clk_freq = 0, clk_id = 0, clk_src = 0, use_pinctrl = 0;
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800463
464 clk_priv = devm_kzalloc(&pdev->dev, sizeof(*clk_priv), GFP_KERNEL);
465 if (!clk_priv)
466 return -ENOMEM;
467
468 ret = of_property_read_u32(pdev->dev.of_node,
469 "qcom,codec-ext-clk-src",
470 &clk_src);
471 if (ret) {
472 dev_err(&pdev->dev, "%s: could not get clk source, ret = %d\n",
473 __func__, ret);
474 return ret;
475 }
476
477 if (clk_src >= AUDIO_EXT_CLK_MAX) {
478 dev_err(&pdev->dev, "%s: Invalid clk source = %d\n",
479 __func__, clk_src);
480 return -EINVAL;
481 }
Surendar Karka0a915f82018-07-09 20:30:03 +0530482 clk_priv->clk_name = NULL;
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800483 clk_priv->clk_src = clk_src;
484 memcpy(&clk_priv->audio_clk, &audio_clk_array[clk_src],
485 sizeof(struct audio_ext_clk));
486
487 /* Init lpass clk default values */
488 clk_priv->clk_cfg.clk_set_minor_version =
489 Q6AFE_LPASS_CLK_CONFIG_API_VERSION;
490 clk_priv->clk_cfg.clk_id = Q6AFE_LPASS_CLK_ID_SPEAKER_I2S_OSR;
491 clk_priv->clk_cfg.clk_freq_in_hz = Q6AFE_LPASS_OSR_CLK_9_P600_MHZ;
492 clk_priv->clk_cfg.clk_attri = Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO;
493
494 ret = of_property_read_u32(pdev->dev.of_node,
495 "qcom,codec-lpass-ext-clk-freq",
496 &clk_freq);
497 if (!ret)
498 clk_priv->clk_cfg.clk_freq_in_hz = clk_freq;
499
500 ret = of_property_read_u32(pdev->dev.of_node,
501 "qcom,codec-lpass-clk-id",
502 &clk_id);
503 if (!ret)
504 clk_priv->clk_cfg.clk_id = clk_id;
505
506 dev_dbg(&pdev->dev, "%s: ext-clk freq: %d, lpass clk_id: %d, clk_src: %d\n",
507 __func__, clk_priv->clk_cfg.clk_freq_in_hz,
508 clk_priv->clk_cfg.clk_id, clk_priv->clk_src);
509 platform_set_drvdata(pdev, clk_priv);
510
Surendar Karka0a915f82018-07-09 20:30:03 +0530511 ret = of_property_read_string(pdev->dev.of_node, "pmic-clock-names",
512 &clk_priv->clk_name);
513 if (ret)
514 dev_dbg(&pdev->dev, "%s: could not find pmic clock names\n",
515 __func__);
Laxminath Kasam43c1a132018-06-15 13:18:07 +0530516 /*
517 * property qcom,use-pinctrl to be defined in DTSI to val 1
518 * for clock nodes using pinctrl
519 */
520 of_property_read_u32(pdev->dev.of_node, "qcom,use-pinctrl",
521 &use_pinctrl);
522 dev_dbg(&pdev->dev, "%s: use-pinctrl : %d\n",
523 __func__, use_pinctrl);
524
525 if (use_pinctrl) {
526 ret = audio_get_pinctrl(pdev);
527 if (ret) {
528 dev_err(&pdev->dev, "%s: Parsing PMI pinctrl failed\n",
529 __func__);
530 return ret;
531 }
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800532 }
533
534 ret = audio_get_clk_data(pdev);
535 if (ret) {
536 dev_err(&pdev->dev, "%s: clk_init is failed\n",
537 __func__);
538 audio_put_pinctrl(pdev);
539 return ret;
540 }
541
Mangesh Kunchamwar912a96a2018-11-13 16:04:53 +0530542 if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_NPA_RSC_ISLAND) {
543 if (q6core_get_avcs_api_version_per_service(
544 APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= AVCS_API_VERSION_V4) {
545 ret = q6core_create_lpass_npa_client(
546 AVCS_SLEEP_NODE_ISLAND_TRANSITION_RESOURCE_ID,
547 "lpass_npa_rsc_mgr",
548 &clk_priv->npa_rsc_client_handle);
549 if (ret) {
550 dev_err(&pdev->dev, "%s: q6core_create_lpass_npa_client is failed %d\n",
551 __func__, ret);
552 audio_put_pinctrl(pdev);
553 return ret;
554 }
555 }
556 }
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800557 return 0;
558}
559
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530560static int audio_ref_clk_remove(struct platform_device *pdev)
561{
Mangesh Kunchamwar912a96a2018-11-13 16:04:53 +0530562 struct audio_ext_clk_priv *clk_priv = platform_get_drvdata(pdev);
563
564 if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_NPA_RSC_ISLAND) {
565 if (q6core_get_avcs_api_version_per_service(
566 APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= AVCS_API_VERSION_V4)
567 q6core_destroy_lpass_npa_client(
568 clk_priv->npa_rsc_client_handle);
569 }
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800570 audio_put_pinctrl(pdev);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530571
572 return 0;
573}
574
575static const struct of_device_id audio_ref_clk_match[] = {
576 {.compatible = "qcom,audio-ref-clk"},
577 {}
578};
579MODULE_DEVICE_TABLE(of, audio_ref_clk_match);
580
581static struct platform_driver audio_ref_clk_driver = {
582 .driver = {
583 .name = "audio-ref-clk",
584 .owner = THIS_MODULE,
585 .of_match_table = audio_ref_clk_match,
586 },
587 .probe = audio_ref_clk_probe,
588 .remove = audio_ref_clk_remove,
589};
590
591int audio_ref_clk_platform_init(void)
592{
593 return platform_driver_register(&audio_ref_clk_driver);
594}
595
596void audio_ref_clk_platform_exit(void)
597{
598 platform_driver_unregister(&audio_ref_clk_driver);
599}
600
601MODULE_DESCRIPTION("Audio Ref Up Clock module platform driver");
602MODULE_LICENSE("GPL v2");