1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2020, Linaro Limited
5 #include <linux/init.h>
6 #include <linux/clk-provider.h>
7 #include <linux/module.h>
8 #include <linux/device.h>
9 #include <linux/platform_device.h>
11 #include <linux/slab.h>
14 #define Q6AFE_CLK(id) &(struct q6afe_clk) { \
16 .afe_clk_id = Q6AFE_##id, \
18 .attributes = LPASS_CLK_ATTRIBUTE_COUPLE_NO, \
20 .hw.init = &(struct clk_init_data) { \
21 .ops = &clk_q6afe_ops, \
26 #define Q6AFE_VOTE_CLK(id, blkid, n) &(struct q6afe_clk) { \
28 .afe_clk_id = blkid, \
30 .hw.init = &(struct clk_init_data) { \
31 .ops = &clk_vote_q6afe_ops, \
47 #define to_q6afe_clk(_hw) container_of(_hw, struct q6afe_clk, hw)
51 struct q6afe_clk
**clks
;
55 static int clk_q6afe_prepare(struct clk_hw
*hw
)
57 struct q6afe_clk
*clk
= to_q6afe_clk(hw
);
59 return q6afe_set_lpass_clock(clk
->dev
, clk
->afe_clk_id
, clk
->attributes
,
60 Q6AFE_LPASS_CLK_ROOT_DEFAULT
, clk
->rate
);
63 static void clk_q6afe_unprepare(struct clk_hw
*hw
)
65 struct q6afe_clk
*clk
= to_q6afe_clk(hw
);
67 q6afe_set_lpass_clock(clk
->dev
, clk
->afe_clk_id
, clk
->attributes
,
68 Q6AFE_LPASS_CLK_ROOT_DEFAULT
, 0);
71 static int clk_q6afe_set_rate(struct clk_hw
*hw
, unsigned long rate
,
72 unsigned long parent_rate
)
74 struct q6afe_clk
*clk
= to_q6afe_clk(hw
);
81 static unsigned long clk_q6afe_recalc_rate(struct clk_hw
*hw
,
82 unsigned long parent_rate
)
84 struct q6afe_clk
*clk
= to_q6afe_clk(hw
);
89 static long clk_q6afe_round_rate(struct clk_hw
*hw
, unsigned long rate
,
90 unsigned long *parent_rate
)
95 static const struct clk_ops clk_q6afe_ops
= {
96 .prepare
= clk_q6afe_prepare
,
97 .unprepare
= clk_q6afe_unprepare
,
98 .set_rate
= clk_q6afe_set_rate
,
99 .round_rate
= clk_q6afe_round_rate
,
100 .recalc_rate
= clk_q6afe_recalc_rate
,
103 static int clk_vote_q6afe_block(struct clk_hw
*hw
)
105 struct q6afe_clk
*clk
= to_q6afe_clk(hw
);
107 return q6afe_vote_lpass_core_hw(clk
->dev
, clk
->afe_clk_id
,
108 clk
->name
, &clk
->handle
);
111 static void clk_unvote_q6afe_block(struct clk_hw
*hw
)
113 struct q6afe_clk
*clk
= to_q6afe_clk(hw
);
115 q6afe_unvote_lpass_core_hw(clk
->dev
, clk
->afe_clk_id
, clk
->handle
);
118 static const struct clk_ops clk_vote_q6afe_ops
= {
119 .prepare
= clk_vote_q6afe_block
,
120 .unprepare
= clk_unvote_q6afe_block
,
123 static struct q6afe_clk
*q6afe_clks
[Q6AFE_MAX_CLK_ID
] = {
124 [LPASS_CLK_ID_PRI_MI2S_IBIT
] = Q6AFE_CLK(LPASS_CLK_ID_PRI_MI2S_IBIT
),
125 [LPASS_CLK_ID_PRI_MI2S_EBIT
] = Q6AFE_CLK(LPASS_CLK_ID_PRI_MI2S_EBIT
),
126 [LPASS_CLK_ID_SEC_MI2S_IBIT
] = Q6AFE_CLK(LPASS_CLK_ID_SEC_MI2S_IBIT
),
127 [LPASS_CLK_ID_SEC_MI2S_EBIT
] = Q6AFE_CLK(LPASS_CLK_ID_SEC_MI2S_EBIT
),
128 [LPASS_CLK_ID_TER_MI2S_IBIT
] = Q6AFE_CLK(LPASS_CLK_ID_TER_MI2S_IBIT
),
129 [LPASS_CLK_ID_TER_MI2S_EBIT
] = Q6AFE_CLK(LPASS_CLK_ID_TER_MI2S_EBIT
),
130 [LPASS_CLK_ID_QUAD_MI2S_IBIT
] = Q6AFE_CLK(LPASS_CLK_ID_QUAD_MI2S_IBIT
),
131 [LPASS_CLK_ID_QUAD_MI2S_EBIT
] = Q6AFE_CLK(LPASS_CLK_ID_QUAD_MI2S_EBIT
),
132 [LPASS_CLK_ID_SPEAKER_I2S_IBIT
] =
133 Q6AFE_CLK(LPASS_CLK_ID_SPEAKER_I2S_IBIT
),
134 [LPASS_CLK_ID_SPEAKER_I2S_EBIT
] =
135 Q6AFE_CLK(LPASS_CLK_ID_SPEAKER_I2S_EBIT
),
136 [LPASS_CLK_ID_SPEAKER_I2S_OSR
] =
137 Q6AFE_CLK(LPASS_CLK_ID_SPEAKER_I2S_OSR
),
138 [LPASS_CLK_ID_QUI_MI2S_IBIT
] = Q6AFE_CLK(LPASS_CLK_ID_QUI_MI2S_IBIT
),
139 [LPASS_CLK_ID_QUI_MI2S_EBIT
] = Q6AFE_CLK(LPASS_CLK_ID_QUI_MI2S_EBIT
),
140 [LPASS_CLK_ID_SEN_MI2S_IBIT
] = Q6AFE_CLK(LPASS_CLK_ID_SEN_MI2S_IBIT
),
141 [LPASS_CLK_ID_SEN_MI2S_EBIT
] = Q6AFE_CLK(LPASS_CLK_ID_SEN_MI2S_EBIT
),
142 [LPASS_CLK_ID_INT0_MI2S_IBIT
] = Q6AFE_CLK(LPASS_CLK_ID_INT0_MI2S_IBIT
),
143 [LPASS_CLK_ID_INT1_MI2S_IBIT
] = Q6AFE_CLK(LPASS_CLK_ID_INT1_MI2S_IBIT
),
144 [LPASS_CLK_ID_INT2_MI2S_IBIT
] = Q6AFE_CLK(LPASS_CLK_ID_INT2_MI2S_IBIT
),
145 [LPASS_CLK_ID_INT3_MI2S_IBIT
] = Q6AFE_CLK(LPASS_CLK_ID_INT3_MI2S_IBIT
),
146 [LPASS_CLK_ID_INT4_MI2S_IBIT
] = Q6AFE_CLK(LPASS_CLK_ID_INT4_MI2S_IBIT
),
147 [LPASS_CLK_ID_INT5_MI2S_IBIT
] = Q6AFE_CLK(LPASS_CLK_ID_INT5_MI2S_IBIT
),
148 [LPASS_CLK_ID_INT6_MI2S_IBIT
] = Q6AFE_CLK(LPASS_CLK_ID_INT6_MI2S_IBIT
),
149 [LPASS_CLK_ID_QUI_MI2S_OSR
] = Q6AFE_CLK(LPASS_CLK_ID_QUI_MI2S_OSR
),
150 [LPASS_CLK_ID_PRI_PCM_IBIT
] = Q6AFE_CLK(LPASS_CLK_ID_PRI_PCM_IBIT
),
151 [LPASS_CLK_ID_PRI_PCM_EBIT
] = Q6AFE_CLK(LPASS_CLK_ID_PRI_PCM_EBIT
),
152 [LPASS_CLK_ID_SEC_PCM_IBIT
] = Q6AFE_CLK(LPASS_CLK_ID_SEC_PCM_IBIT
),
153 [LPASS_CLK_ID_SEC_PCM_EBIT
] = Q6AFE_CLK(LPASS_CLK_ID_SEC_PCM_EBIT
),
154 [LPASS_CLK_ID_TER_PCM_IBIT
] = Q6AFE_CLK(LPASS_CLK_ID_TER_PCM_IBIT
),
155 [LPASS_CLK_ID_TER_PCM_EBIT
] = Q6AFE_CLK(LPASS_CLK_ID_TER_PCM_EBIT
),
156 [LPASS_CLK_ID_QUAD_PCM_IBIT
] = Q6AFE_CLK(LPASS_CLK_ID_QUAD_PCM_IBIT
),
157 [LPASS_CLK_ID_QUAD_PCM_EBIT
] = Q6AFE_CLK(LPASS_CLK_ID_QUAD_PCM_EBIT
),
158 [LPASS_CLK_ID_QUIN_PCM_IBIT
] = Q6AFE_CLK(LPASS_CLK_ID_QUIN_PCM_IBIT
),
159 [LPASS_CLK_ID_QUIN_PCM_EBIT
] = Q6AFE_CLK(LPASS_CLK_ID_QUIN_PCM_EBIT
),
160 [LPASS_CLK_ID_QUI_PCM_OSR
] = Q6AFE_CLK(LPASS_CLK_ID_QUI_PCM_OSR
),
161 [LPASS_CLK_ID_PRI_TDM_IBIT
] = Q6AFE_CLK(LPASS_CLK_ID_PRI_TDM_IBIT
),
162 [LPASS_CLK_ID_PRI_TDM_EBIT
] = Q6AFE_CLK(LPASS_CLK_ID_PRI_TDM_EBIT
),
163 [LPASS_CLK_ID_SEC_TDM_IBIT
] = Q6AFE_CLK(LPASS_CLK_ID_SEC_TDM_IBIT
),
164 [LPASS_CLK_ID_SEC_TDM_EBIT
] = Q6AFE_CLK(LPASS_CLK_ID_SEC_TDM_EBIT
),
165 [LPASS_CLK_ID_TER_TDM_IBIT
] = Q6AFE_CLK(LPASS_CLK_ID_TER_TDM_IBIT
),
166 [LPASS_CLK_ID_TER_TDM_EBIT
] = Q6AFE_CLK(LPASS_CLK_ID_TER_TDM_EBIT
),
167 [LPASS_CLK_ID_QUAD_TDM_IBIT
] = Q6AFE_CLK(LPASS_CLK_ID_QUAD_TDM_IBIT
),
168 [LPASS_CLK_ID_QUAD_TDM_EBIT
] = Q6AFE_CLK(LPASS_CLK_ID_QUAD_TDM_EBIT
),
169 [LPASS_CLK_ID_QUIN_TDM_IBIT
] = Q6AFE_CLK(LPASS_CLK_ID_QUIN_TDM_IBIT
),
170 [LPASS_CLK_ID_QUIN_TDM_EBIT
] = Q6AFE_CLK(LPASS_CLK_ID_QUIN_TDM_EBIT
),
171 [LPASS_CLK_ID_QUIN_TDM_OSR
] = Q6AFE_CLK(LPASS_CLK_ID_QUIN_TDM_OSR
),
172 [LPASS_CLK_ID_MCLK_1
] = Q6AFE_CLK(LPASS_CLK_ID_MCLK_1
),
173 [LPASS_CLK_ID_MCLK_2
] = Q6AFE_CLK(LPASS_CLK_ID_MCLK_2
),
174 [LPASS_CLK_ID_MCLK_3
] = Q6AFE_CLK(LPASS_CLK_ID_MCLK_3
),
175 [LPASS_CLK_ID_MCLK_4
] = Q6AFE_CLK(LPASS_CLK_ID_MCLK_4
),
176 [LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE
] =
177 Q6AFE_CLK(LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE
),
178 [LPASS_CLK_ID_INT_MCLK_0
] = Q6AFE_CLK(LPASS_CLK_ID_INT_MCLK_0
),
179 [LPASS_CLK_ID_INT_MCLK_1
] = Q6AFE_CLK(LPASS_CLK_ID_INT_MCLK_1
),
180 [LPASS_CLK_ID_WSA_CORE_MCLK
] = Q6AFE_CLK(LPASS_CLK_ID_WSA_CORE_MCLK
),
181 [LPASS_CLK_ID_WSA_CORE_NPL_MCLK
] =
182 Q6AFE_CLK(LPASS_CLK_ID_WSA_CORE_NPL_MCLK
),
183 [LPASS_CLK_ID_VA_CORE_MCLK
] = Q6AFE_CLK(LPASS_CLK_ID_VA_CORE_MCLK
),
184 [LPASS_CLK_ID_TX_CORE_MCLK
] = Q6AFE_CLK(LPASS_CLK_ID_TX_CORE_MCLK
),
185 [LPASS_CLK_ID_TX_CORE_NPL_MCLK
] =
186 Q6AFE_CLK(LPASS_CLK_ID_TX_CORE_NPL_MCLK
),
187 [LPASS_CLK_ID_RX_CORE_MCLK
] = Q6AFE_CLK(LPASS_CLK_ID_RX_CORE_MCLK
),
188 [LPASS_CLK_ID_RX_CORE_NPL_MCLK
] =
189 Q6AFE_CLK(LPASS_CLK_ID_RX_CORE_NPL_MCLK
),
190 [LPASS_CLK_ID_VA_CORE_2X_MCLK
] =
191 Q6AFE_CLK(LPASS_CLK_ID_VA_CORE_2X_MCLK
),
192 [LPASS_HW_AVTIMER_VOTE
] = Q6AFE_VOTE_CLK(LPASS_HW_AVTIMER_VOTE
,
193 Q6AFE_LPASS_CORE_AVTIMER_BLOCK
,
194 "LPASS_AVTIMER_MACRO"),
195 [LPASS_HW_MACRO_VOTE
] = Q6AFE_VOTE_CLK(LPASS_HW_MACRO_VOTE
,
196 Q6AFE_LPASS_CORE_HW_MACRO_BLOCK
,
198 [LPASS_HW_DCODEC_VOTE
] = Q6AFE_VOTE_CLK(LPASS_HW_DCODEC_VOTE
,
199 Q6AFE_LPASS_CORE_HW_DCODEC_BLOCK
,
203 static struct clk_hw
*q6afe_of_clk_hw_get(struct of_phandle_args
*clkspec
,
206 struct q6afe_cc
*cc
= data
;
207 unsigned int idx
= clkspec
->args
[0];
208 unsigned int attr
= clkspec
->args
[1];
210 if (idx
>= cc
->num_clks
|| attr
> LPASS_CLK_ATTRIBUTE_COUPLE_DIVISOR
) {
211 dev_err(cc
->dev
, "Invalid clk specifier (%d, %d)\n", idx
, attr
);
212 return ERR_PTR(-EINVAL
);
216 cc
->clks
[idx
]->attributes
= attr
;
217 return &cc
->clks
[idx
]->hw
;
220 return ERR_PTR(-ENOENT
);
223 static int q6afe_clock_dev_probe(struct platform_device
*pdev
)
226 struct device
*dev
= &pdev
->dev
;
229 cc
= devm_kzalloc(dev
, sizeof(*cc
), GFP_KERNEL
);
233 cc
->clks
= &q6afe_clks
[0];
234 cc
->num_clks
= ARRAY_SIZE(q6afe_clks
);
235 for (i
= 0; i
< ARRAY_SIZE(q6afe_clks
); i
++) {
239 q6afe_clks
[i
]->dev
= dev
;
241 ret
= devm_clk_hw_register(dev
, &q6afe_clks
[i
]->hw
);
246 ret
= of_clk_add_hw_provider(dev
->of_node
, q6afe_of_clk_hw_get
, cc
);
250 dev_set_drvdata(dev
, cc
);
256 static const struct of_device_id q6afe_clock_device_id
[] = {
257 { .compatible
= "qcom,q6afe-clocks" },
260 MODULE_DEVICE_TABLE(of
, q6afe_clock_device_id
);
263 static struct platform_driver q6afe_clock_platform_driver
= {
265 .name
= "q6afe-clock",
266 .of_match_table
= of_match_ptr(q6afe_clock_device_id
),
268 .probe
= q6afe_clock_dev_probe
,
270 module_platform_driver(q6afe_clock_platform_driver
);
272 MODULE_DESCRIPTION("Q6 Audio Frontend clock driver");
273 MODULE_LICENSE("GPL v2");