1c5e7fca9SKai Chieh Chuang /*
2c5e7fca9SKai Chieh Chuang  * mt6797-afe-clk.c  --  Mediatek 6797 afe clock ctrl
3c5e7fca9SKai Chieh Chuang  *
4c5e7fca9SKai Chieh Chuang  * Copyright (c) 2018 MediaTek Inc.
5c5e7fca9SKai Chieh Chuang  * Author: KaiChieh Chuang <kaichieh.chuang@mediatek.com>
6c5e7fca9SKai Chieh Chuang  *
7c5e7fca9SKai Chieh Chuang  * This program is free software; you can redistribute it and/or modify
8c5e7fca9SKai Chieh Chuang  * it under the terms of the GNU General Public License version 2 and
9c5e7fca9SKai Chieh Chuang  * only version 2 as published by the Free Software Foundation.
10c5e7fca9SKai Chieh Chuang  *
11c5e7fca9SKai Chieh Chuang  * This program is distributed in the hope that it will be useful,
12c5e7fca9SKai Chieh Chuang  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13c5e7fca9SKai Chieh Chuang  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14c5e7fca9SKai Chieh Chuang  * GNU General Public License for more details.
15c5e7fca9SKai Chieh Chuang  */
16c5e7fca9SKai Chieh Chuang 
17c5e7fca9SKai Chieh Chuang #include <linux/clk.h>
18c5e7fca9SKai Chieh Chuang 
19c5e7fca9SKai Chieh Chuang #include "mt6797-afe-common.h"
20c5e7fca9SKai Chieh Chuang #include "mt6797-afe-clk.h"
21c5e7fca9SKai Chieh Chuang 
22c5e7fca9SKai Chieh Chuang enum {
23c5e7fca9SKai Chieh Chuang 	CLK_INFRA_SYS_AUD,
24c5e7fca9SKai Chieh Chuang 	CLK_INFRA_SYS_AUD_26M,
25c5e7fca9SKai Chieh Chuang 	CLK_TOP_MUX_AUD,
26c5e7fca9SKai Chieh Chuang 	CLK_TOP_MUX_AUD_BUS,
27c5e7fca9SKai Chieh Chuang 	CLK_TOP_SYSPLL3_D4,
28c5e7fca9SKai Chieh Chuang 	CLK_TOP_SYSPLL1_D4,
29c5e7fca9SKai Chieh Chuang 	CLK_CLK26M,
30c5e7fca9SKai Chieh Chuang 	CLK_NUM
31c5e7fca9SKai Chieh Chuang };
32c5e7fca9SKai Chieh Chuang 
33c5e7fca9SKai Chieh Chuang static const char *aud_clks[CLK_NUM] = {
34c5e7fca9SKai Chieh Chuang 	[CLK_INFRA_SYS_AUD] = "infra_sys_audio_clk",
35c5e7fca9SKai Chieh Chuang 	[CLK_INFRA_SYS_AUD_26M] = "infra_sys_audio_26m",
36c5e7fca9SKai Chieh Chuang 	[CLK_TOP_MUX_AUD] = "top_mux_audio",
37c5e7fca9SKai Chieh Chuang 	[CLK_TOP_MUX_AUD_BUS] = "top_mux_aud_intbus",
38c5e7fca9SKai Chieh Chuang 	[CLK_TOP_SYSPLL3_D4] = "top_sys_pll3_d4",
39c5e7fca9SKai Chieh Chuang 	[CLK_TOP_SYSPLL1_D4] = "top_sys_pll1_d4",
40c5e7fca9SKai Chieh Chuang 	[CLK_CLK26M] = "top_clk26m_clk",
41c5e7fca9SKai Chieh Chuang };
42c5e7fca9SKai Chieh Chuang 
43c5e7fca9SKai Chieh Chuang int mt6797_init_clock(struct mtk_base_afe *afe)
44c5e7fca9SKai Chieh Chuang {
45c5e7fca9SKai Chieh Chuang 	struct mt6797_afe_private *afe_priv = afe->platform_priv;
46c5e7fca9SKai Chieh Chuang 	int i;
47c5e7fca9SKai Chieh Chuang 
48c5e7fca9SKai Chieh Chuang 	afe_priv->clk = devm_kcalloc(afe->dev, CLK_NUM, sizeof(*afe_priv->clk),
49c5e7fca9SKai Chieh Chuang 				     GFP_KERNEL);
50c5e7fca9SKai Chieh Chuang 	if (!afe_priv->clk)
51c5e7fca9SKai Chieh Chuang 		return -ENOMEM;
52c5e7fca9SKai Chieh Chuang 
53c5e7fca9SKai Chieh Chuang 	for (i = 0; i < CLK_NUM; i++) {
54c5e7fca9SKai Chieh Chuang 		afe_priv->clk[i] = devm_clk_get(afe->dev, aud_clks[i]);
55c5e7fca9SKai Chieh Chuang 		if (IS_ERR(afe_priv->clk[i])) {
56c5e7fca9SKai Chieh Chuang 			dev_err(afe->dev, "%s(), devm_clk_get %s fail, ret %ld\n",
57c5e7fca9SKai Chieh Chuang 				__func__, aud_clks[i],
58c5e7fca9SKai Chieh Chuang 				PTR_ERR(afe_priv->clk[i]));
59c5e7fca9SKai Chieh Chuang 			return PTR_ERR(afe_priv->clk[i]);
60c5e7fca9SKai Chieh Chuang 		}
61c5e7fca9SKai Chieh Chuang 	}
62c5e7fca9SKai Chieh Chuang 
63c5e7fca9SKai Chieh Chuang 	return 0;
64c5e7fca9SKai Chieh Chuang }
65c5e7fca9SKai Chieh Chuang 
66c5e7fca9SKai Chieh Chuang int mt6797_afe_enable_clock(struct mtk_base_afe *afe)
67c5e7fca9SKai Chieh Chuang {
68c5e7fca9SKai Chieh Chuang 	struct mt6797_afe_private *afe_priv = afe->platform_priv;
69c5e7fca9SKai Chieh Chuang 	int ret;
70c5e7fca9SKai Chieh Chuang 
71c5e7fca9SKai Chieh Chuang 	ret = clk_prepare_enable(afe_priv->clk[CLK_INFRA_SYS_AUD]);
72c5e7fca9SKai Chieh Chuang 	if (ret) {
73c5e7fca9SKai Chieh Chuang 		dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n",
74c5e7fca9SKai Chieh Chuang 			__func__, aud_clks[CLK_INFRA_SYS_AUD], ret);
75c5e7fca9SKai Chieh Chuang 		goto CLK_INFRA_SYS_AUDIO_ERR;
76c5e7fca9SKai Chieh Chuang 	}
77c5e7fca9SKai Chieh Chuang 
78c5e7fca9SKai Chieh Chuang 	ret = clk_prepare_enable(afe_priv->clk[CLK_INFRA_SYS_AUD_26M]);
79c5e7fca9SKai Chieh Chuang 	if (ret) {
80c5e7fca9SKai Chieh Chuang 		dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n",
81c5e7fca9SKai Chieh Chuang 			__func__, aud_clks[CLK_INFRA_SYS_AUD_26M], ret);
82c5e7fca9SKai Chieh Chuang 		goto CLK_INFRA_SYS_AUD_26M_ERR;
83c5e7fca9SKai Chieh Chuang 	}
84c5e7fca9SKai Chieh Chuang 
85c5e7fca9SKai Chieh Chuang 	ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD]);
86c5e7fca9SKai Chieh Chuang 	if (ret) {
87c5e7fca9SKai Chieh Chuang 		dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n",
88c5e7fca9SKai Chieh Chuang 			__func__, aud_clks[CLK_TOP_MUX_AUD], ret);
89c5e7fca9SKai Chieh Chuang 		goto CLK_MUX_AUDIO_ERR;
90c5e7fca9SKai Chieh Chuang 	}
91c5e7fca9SKai Chieh Chuang 
92c5e7fca9SKai Chieh Chuang 	ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD],
93c5e7fca9SKai Chieh Chuang 			     afe_priv->clk[CLK_CLK26M]);
94c5e7fca9SKai Chieh Chuang 	if (ret) {
95c5e7fca9SKai Chieh Chuang 		dev_err(afe->dev, "%s(), clk_set_parent %s-%s fail %d\n",
96c5e7fca9SKai Chieh Chuang 			__func__, aud_clks[CLK_TOP_MUX_AUD],
97c5e7fca9SKai Chieh Chuang 			aud_clks[CLK_CLK26M], ret);
98c5e7fca9SKai Chieh Chuang 		goto CLK_MUX_AUDIO_ERR;
99c5e7fca9SKai Chieh Chuang 	}
100c5e7fca9SKai Chieh Chuang 
101c5e7fca9SKai Chieh Chuang 	ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_BUS]);
102c5e7fca9SKai Chieh Chuang 	if (ret) {
103c5e7fca9SKai Chieh Chuang 		dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n",
104c5e7fca9SKai Chieh Chuang 			__func__, aud_clks[CLK_TOP_MUX_AUD_BUS], ret);
105c5e7fca9SKai Chieh Chuang 		goto CLK_MUX_AUDIO_INTBUS_ERR;
106c5e7fca9SKai Chieh Chuang 	}
107c5e7fca9SKai Chieh Chuang 
108c5e7fca9SKai Chieh Chuang 	return ret;
109c5e7fca9SKai Chieh Chuang 
110c5e7fca9SKai Chieh Chuang CLK_MUX_AUDIO_INTBUS_ERR:
111c5e7fca9SKai Chieh Chuang 	clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_BUS]);
112c5e7fca9SKai Chieh Chuang CLK_MUX_AUDIO_ERR:
113c5e7fca9SKai Chieh Chuang 	clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD]);
114c5e7fca9SKai Chieh Chuang CLK_INFRA_SYS_AUD_26M_ERR:
115c5e7fca9SKai Chieh Chuang 	clk_disable_unprepare(afe_priv->clk[CLK_INFRA_SYS_AUD_26M]);
116c5e7fca9SKai Chieh Chuang CLK_INFRA_SYS_AUDIO_ERR:
117c5e7fca9SKai Chieh Chuang 	clk_disable_unprepare(afe_priv->clk[CLK_INFRA_SYS_AUD]);
118c5e7fca9SKai Chieh Chuang 
119c5e7fca9SKai Chieh Chuang 	return 0;
120c5e7fca9SKai Chieh Chuang }
121c5e7fca9SKai Chieh Chuang 
122c5e7fca9SKai Chieh Chuang int mt6797_afe_disable_clock(struct mtk_base_afe *afe)
123c5e7fca9SKai Chieh Chuang {
124c5e7fca9SKai Chieh Chuang 	struct mt6797_afe_private *afe_priv = afe->platform_priv;
125c5e7fca9SKai Chieh Chuang 
126c5e7fca9SKai Chieh Chuang 	clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_BUS]);
127c5e7fca9SKai Chieh Chuang 	clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD]);
128c5e7fca9SKai Chieh Chuang 	clk_disable_unprepare(afe_priv->clk[CLK_INFRA_SYS_AUD_26M]);
129c5e7fca9SKai Chieh Chuang 	clk_disable_unprepare(afe_priv->clk[CLK_INFRA_SYS_AUD]);
130c5e7fca9SKai Chieh Chuang 
131c5e7fca9SKai Chieh Chuang 	return 0;
132c5e7fca9SKai Chieh Chuang }
133