blob: ba72fd8f6107374f171fd0251c62605cec31279b [file] [log] [blame]
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -08001/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/err.h>
16#include <linux/module.h>
17#include <linux/of.h>
18#include <linux/clk.h>
19#include <linux/clk-provider.h>
20#include "../../../drivers/clk/qcom/common.h"
21#include <linux/platform_device.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053022#include <dt-bindings/clock/qcom,audio-ext-clk.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053023#include <dsp/q6afe-v2.h>
Mangesh Kunchamwar912a96a2018-11-13 16:04:53 +053024#include <dsp/q6core.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053025#include "audio-ext-clk-up.h"
26
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -080027enum {
28 AUDIO_EXT_CLK_PMI,
29 AUDIO_EXT_CLK_LNBB2,
30 AUDIO_EXT_CLK_LPASS,
Laxminath Kasamd712cc72018-07-17 23:43:21 +053031 AUDIO_EXT_CLK_LPASS2,
32 AUDIO_EXT_CLK_LPASS3,
Aditya Bavanari7259ca62018-07-30 12:03:03 +053033 AUDIO_EXT_CLK_LPASS4,
34 AUDIO_EXT_CLK_LPASS5,
35 AUDIO_EXT_CLK_LPASS6,
36 AUDIO_EXT_CLK_LPASS7,
Mangesh Kunchamwar912a96a2018-11-13 16:04:53 +053037 AUDIO_EXT_CLK_LPASS_NPA_RSC_ISLAND,
Laxminath Kasamd712cc72018-07-17 23:43:21 +053038 AUDIO_EXT_CLK_LPASS_MAX,
39 AUDIO_EXT_CLK_MAX = AUDIO_EXT_CLK_LPASS_MAX,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053040};
41
42struct pinctrl_info {
43 struct pinctrl *pinctrl;
44 struct pinctrl_state *sleep;
45 struct pinctrl_state *active;
46 char __iomem *base;
47};
48
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -080049struct audio_ext_clk {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053050 struct pinctrl_info pnctrl_info;
51 struct clk_fixed_factor fact;
52};
53
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -080054struct audio_ext_clk_priv {
55 struct device *dev;
56 int clk_src;
57 struct afe_clk_set clk_cfg;
58 struct audio_ext_clk audio_clk;
Surendar Karka0a915f82018-07-09 20:30:03 +053059 const char *clk_name;
Mangesh Kunchamwar912a96a2018-11-13 16:04:53 +053060 uint32_t npa_rsc_client_handle;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053061};
62
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -080063static inline struct audio_ext_clk_priv *to_audio_clk(struct clk_hw *hw)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053064{
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -080065 return container_of(hw, struct audio_ext_clk_priv, audio_clk.fact.hw);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053066}
67
68static int audio_ext_clk_prepare(struct clk_hw *hw)
69{
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -080070 struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw);
71 struct pinctrl_info *pnctrl_info = &clk_priv->audio_clk.pnctrl_info;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053072 int ret;
73
Laxminath Kasamd712cc72018-07-17 23:43:21 +053074 if ((clk_priv->clk_src >= AUDIO_EXT_CLK_LPASS) &&
75 (clk_priv->clk_src < AUDIO_EXT_CLK_LPASS_MAX)) {
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -080076 clk_priv->clk_cfg.enable = 1;
77 ret = afe_set_lpass_clk_cfg(IDX_RSVD_3, &clk_priv->clk_cfg);
78 if (ret < 0) {
79 pr_err("%s afe_set_digital_codec_core_clock failed\n",
80 __func__);
81 return ret;
82 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053083 }
84
85 if (pnctrl_info->pinctrl) {
86 ret = pinctrl_select_state(pnctrl_info->pinctrl,
87 pnctrl_info->active);
88 if (ret) {
89 pr_err("%s: active state select failed with %d\n",
90 __func__, ret);
91 return -EIO;
92 }
93 }
94
95 if (pnctrl_info->base)
96 iowrite32(1, pnctrl_info->base);
97 return 0;
98}
99
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800100static void audio_ext_clk_unprepare(struct clk_hw *hw)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530101{
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800102 struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw);
103 struct pinctrl_info *pnctrl_info = &clk_priv->audio_clk.pnctrl_info;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530104 int ret;
105
106 if (pnctrl_info->pinctrl) {
107 ret = pinctrl_select_state(pnctrl_info->pinctrl,
108 pnctrl_info->sleep);
109 if (ret) {
110 pr_err("%s: active state select failed with %d\n",
111 __func__, ret);
112 return;
113 }
114 }
115
Laxminath Kasamd712cc72018-07-17 23:43:21 +0530116 if ((clk_priv->clk_src >= AUDIO_EXT_CLK_LPASS) &&
117 (clk_priv->clk_src < AUDIO_EXT_CLK_LPASS_MAX)) {
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800118 clk_priv->clk_cfg.enable = 0;
119 ret = afe_set_lpass_clk_cfg(IDX_RSVD_3, &clk_priv->clk_cfg);
120 if (ret < 0)
121 pr_err("%s: afe_set_lpass_clk_cfg failed, ret = %d\n",
122 __func__, ret);
123 }
124
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530125 if (pnctrl_info->base)
126 iowrite32(0, pnctrl_info->base);
127}
128
Surendar Karka0a915f82018-07-09 20:30:03 +0530129static u8 audio_ext_clk_get_parent(struct clk_hw *hw)
130{
131 struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw);
132 int num_parents = clk_hw_get_num_parents(hw);
133 const char * const *parent_names = hw->init->parent_names;
134 u8 i = 0, ret = hw->init->num_parents + 1;
135
136 if ((clk_priv->clk_src == AUDIO_EXT_CLK_PMI) && clk_priv->clk_name) {
137 for (i = 0; i < num_parents; i++) {
138 if (!strcmp(parent_names[i], clk_priv->clk_name))
139 ret = i;
140 }
141 pr_debug("%s: parent index = %u\n", __func__, ret);
142 return ret;
143 } else
144 return 0;
145}
146
Mangesh Kunchamwar912a96a2018-11-13 16:04:53 +0530147static int lpass_npa_rsc_prepare(struct clk_hw *hw)
148{
149 struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw);
150 int ret;
151
152 if ((clk_priv->clk_src >= AUDIO_EXT_CLK_LPASS_NPA_RSC_ISLAND) &&
153 (clk_priv->clk_src < AUDIO_EXT_CLK_LPASS_MAX)) {
154 if (q6core_get_avcs_api_version_per_service(
155 APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= AVCS_API_VERSION_V4) {
156 ret = q6core_request_island_transition(
157 clk_priv->npa_rsc_client_handle, false);
158 if (ret < 0) {
159 pr_err("%s q6core_request_island_transition failed %d\n",
160 __func__, ret);
161 return ret;
162 }
163 }
164 }
165
166 return 0;
167}
168
169static void lpass_npa_rsc_unprepare(struct clk_hw *hw)
170{
171 struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw);
172 int ret = 0;
173
174 if ((clk_priv->clk_src >= AUDIO_EXT_CLK_LPASS_NPA_RSC_ISLAND) &&
175 (clk_priv->clk_src < AUDIO_EXT_CLK_LPASS_MAX)) {
176 if (q6core_get_avcs_api_version_per_service(
177 APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= AVCS_API_VERSION_V4) {
178 ret = q6core_request_island_transition(
179 clk_priv->npa_rsc_client_handle, true);
180 if (ret < 0) {
181 pr_err("%s q6core_request_island_transition failed %d\n",
182 __func__, ret);
183 }
184 }
185 }
186}
187
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800188static const struct clk_ops audio_ext_clk_ops = {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530189 .prepare = audio_ext_clk_prepare,
190 .unprepare = audio_ext_clk_unprepare,
Surendar Karka0a915f82018-07-09 20:30:03 +0530191 .get_parent = audio_ext_clk_get_parent,
192};
193
Mangesh Kunchamwar912a96a2018-11-13 16:04:53 +0530194static const struct clk_ops lpass_npa_rsc_ops = {
195 .prepare = lpass_npa_rsc_prepare,
196 .unprepare = lpass_npa_rsc_unprepare,
197};
198
Surendar Karka0a915f82018-07-09 20:30:03 +0530199static const char * const audio_ext_pmi_div_clk[] = {
200 "qpnp_clkdiv_1",
201 "pms405_div_clk1",
202 "pm6150_div_clk1",
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530203};
204
Sudheer Papothi9b51e3e2018-07-21 05:20:10 +0530205static int audio_ext_clk_dummy_prepare(struct clk_hw *hw)
206{
207 return 0;
208}
209
210static void audio_ext_clk_dummy_unprepare(struct clk_hw *hw)
211{
212
213}
214
215static const struct clk_ops audio_ext_clk_dummy_ops = {
216 .prepare = audio_ext_clk_dummy_prepare,
217 .unprepare = audio_ext_clk_dummy_unprepare,
218};
219
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800220static struct audio_ext_clk audio_clk_array[] = {
221 {
222 .pnctrl_info = {NULL},
223 .fact = {
224 .mult = 1,
225 .div = 1,
226 .hw.init = &(struct clk_init_data){
227 .name = "audio_ext_pmi_clk",
Surendar Karka0a915f82018-07-09 20:30:03 +0530228 .parent_names = audio_ext_pmi_div_clk,
229 .num_parents =
230 ARRAY_SIZE(audio_ext_pmi_div_clk),
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800231 .ops = &audio_ext_clk_ops,
232 },
233 },
234 },
235 {
236 .pnctrl_info = {NULL},
237 .fact = {
238 .mult = 1,
239 .div = 1,
240 .hw.init = &(struct clk_init_data){
241 .name = "audio_ext_pmi_lnbb_clk",
242 .parent_names = (const char *[])
243 { "ln_bb_clk2" },
244 .num_parents = 1,
Sudheer Papothi9b51e3e2018-07-21 05:20:10 +0530245 .ops = &audio_ext_clk_dummy_ops,
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800246 },
247 },
248 },
249 {
250 .pnctrl_info = {NULL},
251 .fact = {
252 .mult = 1,
253 .div = 1,
254 .hw.init = &(struct clk_init_data){
255 .name = "audio_lpass_mclk",
256 .ops = &audio_ext_clk_ops,
257 },
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530258 },
259 },
Laxminath Kasamd712cc72018-07-17 23:43:21 +0530260 {
261 .pnctrl_info = {NULL},
262 .fact = {
263 .mult = 1,
264 .div = 1,
265 .hw.init = &(struct clk_init_data){
266 .name = "audio_lpass_mclk2",
267 .ops = &audio_ext_clk_ops,
268 },
269 },
270 },
271 {
272 .pnctrl_info = {NULL},
273 .fact = {
274 .mult = 1,
275 .div = 1,
276 .hw.init = &(struct clk_init_data){
277 .name = "audio_lpass_mclk3",
278 .ops = &audio_ext_clk_ops,
279 },
280 },
281 },
Aditya Bavanari7259ca62018-07-30 12:03:03 +0530282 {
283 .pnctrl_info = {NULL},
284 .fact = {
285 .mult = 1,
286 .div = 1,
287 .hw.init = &(struct clk_init_data){
288 .name = "audio_lpass_mclk4",
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_mclk5",
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_mclk6",
311 .ops = &audio_ext_clk_ops,
312 },
313 },
314 },
315 {
316 .pnctrl_info = {NULL},
317 .fact = {
318 .mult = 1,
319 .div = 1,
320 .hw.init = &(struct clk_init_data){
321 .name = "audio_lpass_mclk7",
322 .ops = &audio_ext_clk_ops,
323 },
324 },
325 },
Mangesh Kunchamwar912a96a2018-11-13 16:04:53 +0530326 {
327 .pnctrl_info = {NULL},
328 .fact = {
329 .hw.init = &(struct clk_init_data){
330 .name = "lpass_npa_rsc_island_clk",
331 .ops = &lpass_npa_rsc_ops,
332 },
333 },
334 },
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530335};
336
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800337static int audio_get_pinctrl(struct platform_device *pdev)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530338{
339 struct device *dev = &pdev->dev;
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800340 struct audio_ext_clk_priv *clk_priv = platform_get_drvdata(pdev);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530341 struct pinctrl_info *pnctrl_info;
342 struct pinctrl *pinctrl;
343 int ret;
344 u32 reg;
345
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800346 pnctrl_info = &clk_priv->audio_clk.pnctrl_info;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530347 if (pnctrl_info->pinctrl) {
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800348 dev_err(dev, "%s: already requested before\n",
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530349 __func__);
350 return -EINVAL;
351 }
352
353 pinctrl = devm_pinctrl_get(dev);
354 if (IS_ERR_OR_NULL(pinctrl)) {
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800355 dev_err(dev, "%s: Unable to get pinctrl handle\n",
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530356 __func__);
357 return -EINVAL;
358 }
359 pnctrl_info->pinctrl = pinctrl;
360 /* get all state handles from Device Tree */
361 pnctrl_info->sleep = pinctrl_lookup_state(pinctrl, "sleep");
362 if (IS_ERR(pnctrl_info->sleep)) {
363 dev_err(dev, "%s: could not get sleep pinstate\n",
364 __func__);
365 goto err;
366 }
367 pnctrl_info->active = pinctrl_lookup_state(pinctrl, "active");
368 if (IS_ERR(pnctrl_info->active)) {
369 dev_err(dev, "%s: could not get active pinstate\n",
370 __func__);
371 goto err;
372 }
373 /* Reset the TLMM pins to a default state */
374 ret = pinctrl_select_state(pnctrl_info->pinctrl,
375 pnctrl_info->sleep);
376 if (ret) {
377 dev_err(dev, "%s: Disable TLMM pins failed with %d\n",
378 __func__, ret);
379 goto err;
380 }
381
382 ret = of_property_read_u32(dev->of_node, "qcom,mclk-clk-reg", &reg);
383 if (ret < 0) {
384 dev_dbg(dev, "%s: miss mclk reg\n", __func__);
385 } else {
386 pnctrl_info->base = ioremap(reg, sizeof(u32));
387 if (pnctrl_info->base == NULL) {
388 dev_err(dev, "%s ioremap failed\n", __func__);
389 goto err;
390 }
391 }
392
393 return 0;
394
395err:
396 devm_pinctrl_put(pnctrl_info->pinctrl);
397 return -EINVAL;
398}
399
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800400static int audio_put_pinctrl(struct platform_device *pdev)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530401{
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800402 struct audio_ext_clk_priv *clk_priv = platform_get_drvdata(pdev);
403 struct pinctrl_info *pnctrl_info = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530404
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800405 pnctrl_info = &clk_priv->audio_clk.pnctrl_info;
406 if (pnctrl_info && pnctrl_info->pinctrl) {
407 devm_pinctrl_put(pnctrl_info->pinctrl);
408 pnctrl_info->pinctrl = NULL;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530409 }
410
411 return 0;
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800412}
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530413
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800414static int audio_get_clk_data(struct platform_device *pdev)
415{
416 int ret;
417 struct clk *audio_clk;
418 struct clk_hw *clkhw;
419 struct clk_onecell_data *clk_data;
420 struct audio_ext_clk_priv *clk_priv = platform_get_drvdata(pdev);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530421
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800422 clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL);
423 if (!clk_data)
424 return -ENOMEM;
425
426 clk_data->clk_num = 1;
427 clk_data->clks = devm_kzalloc(&pdev->dev,
428 sizeof(struct clk *),
429 GFP_KERNEL);
430 if (!clk_data->clks)
431 return -ENOMEM;
432
433 clkhw = &clk_priv->audio_clk.fact.hw;
434 audio_clk = devm_clk_register(&pdev->dev, clkhw);
435 if (IS_ERR(audio_clk)) {
436 dev_err(&pdev->dev,
437 "%s: clock register failed for clk_src = %d\\n",
438 __func__, clk_priv->clk_src);
439 ret = PTR_ERR(audio_clk);
440 return ret;
441 }
442 clk_data->clks[0] = audio_clk;
443
444 ret = of_clk_add_provider(pdev->dev.of_node,
445 of_clk_src_onecell_get, clk_data);
446 if (ret)
447 dev_err(&pdev->dev, "%s: clock add failed for clk_src = %d\n",
448 __func__, clk_priv->clk_src);
449
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530450 return ret;
451}
452
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800453static int audio_ref_clk_probe(struct platform_device *pdev)
454{
455 int ret;
456 struct audio_ext_clk_priv *clk_priv;
Laxminath Kasam43c1a132018-06-15 13:18:07 +0530457 u32 clk_freq = 0, clk_id = 0, clk_src = 0, use_pinctrl = 0;
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800458
459 clk_priv = devm_kzalloc(&pdev->dev, sizeof(*clk_priv), GFP_KERNEL);
460 if (!clk_priv)
461 return -ENOMEM;
462
463 ret = of_property_read_u32(pdev->dev.of_node,
464 "qcom,codec-ext-clk-src",
465 &clk_src);
466 if (ret) {
467 dev_err(&pdev->dev, "%s: could not get clk source, ret = %d\n",
468 __func__, ret);
469 return ret;
470 }
471
472 if (clk_src >= AUDIO_EXT_CLK_MAX) {
473 dev_err(&pdev->dev, "%s: Invalid clk source = %d\n",
474 __func__, clk_src);
475 return -EINVAL;
476 }
Surendar Karka0a915f82018-07-09 20:30:03 +0530477 clk_priv->clk_name = NULL;
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800478 clk_priv->clk_src = clk_src;
479 memcpy(&clk_priv->audio_clk, &audio_clk_array[clk_src],
480 sizeof(struct audio_ext_clk));
481
482 /* Init lpass clk default values */
483 clk_priv->clk_cfg.clk_set_minor_version =
484 Q6AFE_LPASS_CLK_CONFIG_API_VERSION;
485 clk_priv->clk_cfg.clk_id = Q6AFE_LPASS_CLK_ID_SPEAKER_I2S_OSR;
486 clk_priv->clk_cfg.clk_freq_in_hz = Q6AFE_LPASS_OSR_CLK_9_P600_MHZ;
487 clk_priv->clk_cfg.clk_attri = Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO;
488
489 ret = of_property_read_u32(pdev->dev.of_node,
490 "qcom,codec-lpass-ext-clk-freq",
491 &clk_freq);
492 if (!ret)
493 clk_priv->clk_cfg.clk_freq_in_hz = clk_freq;
494
495 ret = of_property_read_u32(pdev->dev.of_node,
496 "qcom,codec-lpass-clk-id",
497 &clk_id);
498 if (!ret)
499 clk_priv->clk_cfg.clk_id = clk_id;
500
501 dev_dbg(&pdev->dev, "%s: ext-clk freq: %d, lpass clk_id: %d, clk_src: %d\n",
502 __func__, clk_priv->clk_cfg.clk_freq_in_hz,
503 clk_priv->clk_cfg.clk_id, clk_priv->clk_src);
504 platform_set_drvdata(pdev, clk_priv);
505
Surendar Karka0a915f82018-07-09 20:30:03 +0530506 ret = of_property_read_string(pdev->dev.of_node, "pmic-clock-names",
507 &clk_priv->clk_name);
508 if (ret)
509 dev_dbg(&pdev->dev, "%s: could not find pmic clock names\n",
510 __func__);
Laxminath Kasam43c1a132018-06-15 13:18:07 +0530511 /*
512 * property qcom,use-pinctrl to be defined in DTSI to val 1
513 * for clock nodes using pinctrl
514 */
515 of_property_read_u32(pdev->dev.of_node, "qcom,use-pinctrl",
516 &use_pinctrl);
517 dev_dbg(&pdev->dev, "%s: use-pinctrl : %d\n",
518 __func__, use_pinctrl);
519
520 if (use_pinctrl) {
521 ret = audio_get_pinctrl(pdev);
522 if (ret) {
523 dev_err(&pdev->dev, "%s: Parsing PMI pinctrl failed\n",
524 __func__);
525 return ret;
526 }
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800527 }
528
529 ret = audio_get_clk_data(pdev);
530 if (ret) {
531 dev_err(&pdev->dev, "%s: clk_init is failed\n",
532 __func__);
533 audio_put_pinctrl(pdev);
534 return ret;
535 }
536
Mangesh Kunchamwar912a96a2018-11-13 16:04:53 +0530537 if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_NPA_RSC_ISLAND) {
538 if (q6core_get_avcs_api_version_per_service(
539 APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= AVCS_API_VERSION_V4) {
540 ret = q6core_create_lpass_npa_client(
541 AVCS_SLEEP_NODE_ISLAND_TRANSITION_RESOURCE_ID,
542 "lpass_npa_rsc_mgr",
543 &clk_priv->npa_rsc_client_handle);
544 if (ret) {
545 dev_err(&pdev->dev, "%s: q6core_create_lpass_npa_client is failed %d\n",
546 __func__, ret);
547 audio_put_pinctrl(pdev);
548 return ret;
549 }
550 }
551 }
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800552 return 0;
553}
554
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530555static int audio_ref_clk_remove(struct platform_device *pdev)
556{
Mangesh Kunchamwar912a96a2018-11-13 16:04:53 +0530557 struct audio_ext_clk_priv *clk_priv = platform_get_drvdata(pdev);
558
559 if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_NPA_RSC_ISLAND) {
560 if (q6core_get_avcs_api_version_per_service(
561 APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= AVCS_API_VERSION_V4)
562 q6core_destroy_lpass_npa_client(
563 clk_priv->npa_rsc_client_handle);
564 }
Vidyakumar Athotaecc4eda2017-12-13 16:24:10 -0800565 audio_put_pinctrl(pdev);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530566
567 return 0;
568}
569
570static const struct of_device_id audio_ref_clk_match[] = {
571 {.compatible = "qcom,audio-ref-clk"},
572 {}
573};
574MODULE_DEVICE_TABLE(of, audio_ref_clk_match);
575
576static struct platform_driver audio_ref_clk_driver = {
577 .driver = {
578 .name = "audio-ref-clk",
579 .owner = THIS_MODULE,
580 .of_match_table = audio_ref_clk_match,
581 },
582 .probe = audio_ref_clk_probe,
583 .remove = audio_ref_clk_remove,
584};
585
586int audio_ref_clk_platform_init(void)
587{
588 return platform_driver_register(&audio_ref_clk_driver);
589}
590
591void audio_ref_clk_platform_exit(void)
592{
593 platform_driver_unregister(&audio_ref_clk_driver);
594}
595
596MODULE_DESCRIPTION("Audio Ref Up Clock module platform driver");
597MODULE_LICENSE("GPL v2");