18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci// Copyright (c) 2020, Linaro Limited
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include <linux/err.h>
58c2ecf20Sopenharmony_ci#include <linux/init.h>
68c2ecf20Sopenharmony_ci#include <linux/clk-provider.h>
78c2ecf20Sopenharmony_ci#include <linux/module.h>
88c2ecf20Sopenharmony_ci#include <linux/device.h>
98c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
108c2ecf20Sopenharmony_ci#include <linux/of.h>
118c2ecf20Sopenharmony_ci#include <linux/slab.h>
128c2ecf20Sopenharmony_ci#include "q6afe.h"
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#define Q6AFE_CLK(id) &(struct q6afe_clk) {		\
158c2ecf20Sopenharmony_ci		.clk_id	= id,				\
168c2ecf20Sopenharmony_ci		.afe_clk_id	= Q6AFE_##id,		\
178c2ecf20Sopenharmony_ci		.name = #id,				\
188c2ecf20Sopenharmony_ci		.attributes = LPASS_CLK_ATTRIBUTE_COUPLE_NO, \
198c2ecf20Sopenharmony_ci		.rate = 19200000,			\
208c2ecf20Sopenharmony_ci		.hw.init = &(struct clk_init_data) {	\
218c2ecf20Sopenharmony_ci			.ops = &clk_q6afe_ops,		\
228c2ecf20Sopenharmony_ci			.name = #id,			\
238c2ecf20Sopenharmony_ci		},					\
248c2ecf20Sopenharmony_ci	}
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#define Q6AFE_VOTE_CLK(id, blkid, n) &(struct q6afe_clk) { \
278c2ecf20Sopenharmony_ci		.clk_id	= id,				\
288c2ecf20Sopenharmony_ci		.afe_clk_id = blkid,			\
298c2ecf20Sopenharmony_ci		.name = #n,				\
308c2ecf20Sopenharmony_ci		.hw.init = &(struct clk_init_data) {	\
318c2ecf20Sopenharmony_ci			.ops = &clk_vote_q6afe_ops,	\
328c2ecf20Sopenharmony_ci			.name = #id,			\
338c2ecf20Sopenharmony_ci		},					\
348c2ecf20Sopenharmony_ci	}
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_cistruct q6afe_clk {
378c2ecf20Sopenharmony_ci	struct device *dev;
388c2ecf20Sopenharmony_ci	int clk_id;
398c2ecf20Sopenharmony_ci	int afe_clk_id;
408c2ecf20Sopenharmony_ci	char *name;
418c2ecf20Sopenharmony_ci	int attributes;
428c2ecf20Sopenharmony_ci	int rate;
438c2ecf20Sopenharmony_ci	uint32_t handle;
448c2ecf20Sopenharmony_ci	struct clk_hw hw;
458c2ecf20Sopenharmony_ci};
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci#define to_q6afe_clk(_hw) container_of(_hw, struct q6afe_clk, hw)
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_cistruct q6afe_cc {
508c2ecf20Sopenharmony_ci	struct device *dev;
518c2ecf20Sopenharmony_ci	struct q6afe_clk **clks;
528c2ecf20Sopenharmony_ci	int num_clks;
538c2ecf20Sopenharmony_ci};
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_cistatic int clk_q6afe_prepare(struct clk_hw *hw)
568c2ecf20Sopenharmony_ci{
578c2ecf20Sopenharmony_ci	struct q6afe_clk *clk = to_q6afe_clk(hw);
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	return q6afe_set_lpass_clock(clk->dev, clk->afe_clk_id, clk->attributes,
608c2ecf20Sopenharmony_ci				     Q6AFE_LPASS_CLK_ROOT_DEFAULT, clk->rate);
618c2ecf20Sopenharmony_ci}
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_cistatic void clk_q6afe_unprepare(struct clk_hw *hw)
648c2ecf20Sopenharmony_ci{
658c2ecf20Sopenharmony_ci	struct q6afe_clk *clk = to_q6afe_clk(hw);
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	q6afe_set_lpass_clock(clk->dev, clk->afe_clk_id, clk->attributes,
688c2ecf20Sopenharmony_ci			      Q6AFE_LPASS_CLK_ROOT_DEFAULT, 0);
698c2ecf20Sopenharmony_ci}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_cistatic int clk_q6afe_set_rate(struct clk_hw *hw, unsigned long rate,
728c2ecf20Sopenharmony_ci			      unsigned long parent_rate)
738c2ecf20Sopenharmony_ci{
748c2ecf20Sopenharmony_ci	struct q6afe_clk *clk = to_q6afe_clk(hw);
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	clk->rate = rate;
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	return 0;
798c2ecf20Sopenharmony_ci}
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cistatic unsigned long clk_q6afe_recalc_rate(struct clk_hw *hw,
828c2ecf20Sopenharmony_ci					   unsigned long parent_rate)
838c2ecf20Sopenharmony_ci{
848c2ecf20Sopenharmony_ci	struct q6afe_clk *clk = to_q6afe_clk(hw);
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	return clk->rate;
878c2ecf20Sopenharmony_ci}
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_cistatic long clk_q6afe_round_rate(struct clk_hw *hw, unsigned long rate,
908c2ecf20Sopenharmony_ci				 unsigned long *parent_rate)
918c2ecf20Sopenharmony_ci{
928c2ecf20Sopenharmony_ci	return rate;
938c2ecf20Sopenharmony_ci}
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_cistatic const struct clk_ops clk_q6afe_ops = {
968c2ecf20Sopenharmony_ci	.prepare	= clk_q6afe_prepare,
978c2ecf20Sopenharmony_ci	.unprepare	= clk_q6afe_unprepare,
988c2ecf20Sopenharmony_ci	.set_rate	= clk_q6afe_set_rate,
998c2ecf20Sopenharmony_ci	.round_rate	= clk_q6afe_round_rate,
1008c2ecf20Sopenharmony_ci	.recalc_rate	= clk_q6afe_recalc_rate,
1018c2ecf20Sopenharmony_ci};
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_cistatic int clk_vote_q6afe_block(struct clk_hw *hw)
1048c2ecf20Sopenharmony_ci{
1058c2ecf20Sopenharmony_ci	struct q6afe_clk *clk = to_q6afe_clk(hw);
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	return q6afe_vote_lpass_core_hw(clk->dev, clk->afe_clk_id,
1088c2ecf20Sopenharmony_ci					clk->name, &clk->handle);
1098c2ecf20Sopenharmony_ci}
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_cistatic void clk_unvote_q6afe_block(struct clk_hw *hw)
1128c2ecf20Sopenharmony_ci{
1138c2ecf20Sopenharmony_ci	struct q6afe_clk *clk = to_q6afe_clk(hw);
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	q6afe_unvote_lpass_core_hw(clk->dev, clk->afe_clk_id, clk->handle);
1168c2ecf20Sopenharmony_ci}
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_cistatic const struct clk_ops clk_vote_q6afe_ops = {
1198c2ecf20Sopenharmony_ci	.prepare	= clk_vote_q6afe_block,
1208c2ecf20Sopenharmony_ci	.unprepare	= clk_unvote_q6afe_block,
1218c2ecf20Sopenharmony_ci};
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_cistruct q6afe_clk *q6afe_clks[Q6AFE_MAX_CLK_ID] = {
1248c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_PRI_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_PRI_MI2S_IBIT),
1258c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_PRI_MI2S_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_PRI_MI2S_EBIT),
1268c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_SEC_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_SEC_MI2S_IBIT),
1278c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_SEC_MI2S_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_SEC_MI2S_EBIT),
1288c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_TER_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_TER_MI2S_IBIT),
1298c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_TER_MI2S_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_TER_MI2S_EBIT),
1308c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_QUAD_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUAD_MI2S_IBIT),
1318c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_QUAD_MI2S_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUAD_MI2S_EBIT),
1328c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_SPEAKER_I2S_IBIT] =
1338c2ecf20Sopenharmony_ci				Q6AFE_CLK(LPASS_CLK_ID_SPEAKER_I2S_IBIT),
1348c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_SPEAKER_I2S_EBIT] =
1358c2ecf20Sopenharmony_ci				Q6AFE_CLK(LPASS_CLK_ID_SPEAKER_I2S_EBIT),
1368c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_SPEAKER_I2S_OSR] =
1378c2ecf20Sopenharmony_ci				Q6AFE_CLK(LPASS_CLK_ID_SPEAKER_I2S_OSR),
1388c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_QUI_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUI_MI2S_IBIT),
1398c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_QUI_MI2S_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUI_MI2S_EBIT),
1408c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_SEN_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_SEN_MI2S_IBIT),
1418c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_SEN_MI2S_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_SEN_MI2S_EBIT),
1428c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_INT0_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_INT0_MI2S_IBIT),
1438c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_INT1_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_INT1_MI2S_IBIT),
1448c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_INT2_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_INT2_MI2S_IBIT),
1458c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_INT3_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_INT3_MI2S_IBIT),
1468c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_INT4_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_INT4_MI2S_IBIT),
1478c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_INT5_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_INT5_MI2S_IBIT),
1488c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_INT6_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_INT6_MI2S_IBIT),
1498c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_QUI_MI2S_OSR] = Q6AFE_CLK(LPASS_CLK_ID_QUI_MI2S_OSR),
1508c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_PRI_PCM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_PRI_PCM_IBIT),
1518c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_PRI_PCM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_PRI_PCM_EBIT),
1528c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_SEC_PCM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_SEC_PCM_IBIT),
1538c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_SEC_PCM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_SEC_PCM_EBIT),
1548c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_TER_PCM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_TER_PCM_IBIT),
1558c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_TER_PCM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_TER_PCM_EBIT),
1568c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_QUAD_PCM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUAD_PCM_IBIT),
1578c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_QUAD_PCM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUAD_PCM_EBIT),
1588c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_QUIN_PCM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUIN_PCM_IBIT),
1598c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_QUIN_PCM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUIN_PCM_EBIT),
1608c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_QUI_PCM_OSR] = Q6AFE_CLK(LPASS_CLK_ID_QUI_PCM_OSR),
1618c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_PRI_TDM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_PRI_TDM_IBIT),
1628c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_PRI_TDM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_PRI_TDM_EBIT),
1638c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_SEC_TDM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_SEC_TDM_IBIT),
1648c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_SEC_TDM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_SEC_TDM_EBIT),
1658c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_TER_TDM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_TER_TDM_IBIT),
1668c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_TER_TDM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_TER_TDM_EBIT),
1678c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_QUAD_TDM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUAD_TDM_IBIT),
1688c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_QUAD_TDM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUAD_TDM_EBIT),
1698c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_QUIN_TDM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUIN_TDM_IBIT),
1708c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_QUIN_TDM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUIN_TDM_EBIT),
1718c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_QUIN_TDM_OSR] = Q6AFE_CLK(LPASS_CLK_ID_QUIN_TDM_OSR),
1728c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_MCLK_1] = Q6AFE_CLK(LPASS_CLK_ID_MCLK_1),
1738c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_MCLK_2] = Q6AFE_CLK(LPASS_CLK_ID_MCLK_2),
1748c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_MCLK_3] = Q6AFE_CLK(LPASS_CLK_ID_MCLK_3),
1758c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_MCLK_4] = Q6AFE_CLK(LPASS_CLK_ID_MCLK_4),
1768c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE] =
1778c2ecf20Sopenharmony_ci		Q6AFE_CLK(LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE),
1788c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_INT_MCLK_0] = Q6AFE_CLK(LPASS_CLK_ID_INT_MCLK_0),
1798c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_INT_MCLK_1] = Q6AFE_CLK(LPASS_CLK_ID_INT_MCLK_1),
1808c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_WSA_CORE_MCLK] = Q6AFE_CLK(LPASS_CLK_ID_WSA_CORE_MCLK),
1818c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_WSA_CORE_NPL_MCLK] =
1828c2ecf20Sopenharmony_ci				Q6AFE_CLK(LPASS_CLK_ID_WSA_CORE_NPL_MCLK),
1838c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_VA_CORE_MCLK] = Q6AFE_CLK(LPASS_CLK_ID_VA_CORE_MCLK),
1848c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_TX_CORE_MCLK] = Q6AFE_CLK(LPASS_CLK_ID_TX_CORE_MCLK),
1858c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_TX_CORE_NPL_MCLK] =
1868c2ecf20Sopenharmony_ci			Q6AFE_CLK(LPASS_CLK_ID_TX_CORE_NPL_MCLK),
1878c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_RX_CORE_MCLK] = Q6AFE_CLK(LPASS_CLK_ID_RX_CORE_MCLK),
1888c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_RX_CORE_NPL_MCLK] =
1898c2ecf20Sopenharmony_ci				Q6AFE_CLK(LPASS_CLK_ID_RX_CORE_NPL_MCLK),
1908c2ecf20Sopenharmony_ci	[LPASS_CLK_ID_VA_CORE_2X_MCLK] =
1918c2ecf20Sopenharmony_ci				Q6AFE_CLK(LPASS_CLK_ID_VA_CORE_2X_MCLK),
1928c2ecf20Sopenharmony_ci	[LPASS_HW_AVTIMER_VOTE] = Q6AFE_VOTE_CLK(LPASS_HW_AVTIMER_VOTE,
1938c2ecf20Sopenharmony_ci						 Q6AFE_LPASS_CORE_AVTIMER_BLOCK,
1948c2ecf20Sopenharmony_ci						 "LPASS_AVTIMER_MACRO"),
1958c2ecf20Sopenharmony_ci	[LPASS_HW_MACRO_VOTE] = Q6AFE_VOTE_CLK(LPASS_HW_MACRO_VOTE,
1968c2ecf20Sopenharmony_ci						Q6AFE_LPASS_CORE_HW_MACRO_BLOCK,
1978c2ecf20Sopenharmony_ci						"LPASS_HW_MACRO"),
1988c2ecf20Sopenharmony_ci	[LPASS_HW_DCODEC_VOTE] = Q6AFE_VOTE_CLK(LPASS_HW_DCODEC_VOTE,
1998c2ecf20Sopenharmony_ci					Q6AFE_LPASS_CORE_HW_DCODEC_BLOCK,
2008c2ecf20Sopenharmony_ci					"LPASS_HW_DCODEC"),
2018c2ecf20Sopenharmony_ci};
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_cistatic struct clk_hw *q6afe_of_clk_hw_get(struct of_phandle_args *clkspec,
2048c2ecf20Sopenharmony_ci					  void *data)
2058c2ecf20Sopenharmony_ci{
2068c2ecf20Sopenharmony_ci	struct q6afe_cc *cc = data;
2078c2ecf20Sopenharmony_ci	unsigned int idx = clkspec->args[0];
2088c2ecf20Sopenharmony_ci	unsigned int attr = clkspec->args[1];
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	if (idx >= cc->num_clks || attr > LPASS_CLK_ATTRIBUTE_COUPLE_DIVISOR) {
2118c2ecf20Sopenharmony_ci		dev_err(cc->dev, "Invalid clk specifier (%d, %d)\n", idx, attr);
2128c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
2138c2ecf20Sopenharmony_ci	}
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	if (cc->clks[idx]) {
2168c2ecf20Sopenharmony_ci		cc->clks[idx]->attributes = attr;
2178c2ecf20Sopenharmony_ci		return &cc->clks[idx]->hw;
2188c2ecf20Sopenharmony_ci	}
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	return ERR_PTR(-ENOENT);
2218c2ecf20Sopenharmony_ci}
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_cistatic int q6afe_clock_dev_probe(struct platform_device *pdev)
2248c2ecf20Sopenharmony_ci{
2258c2ecf20Sopenharmony_ci	struct q6afe_cc *cc;
2268c2ecf20Sopenharmony_ci	struct device *dev = &pdev->dev;
2278c2ecf20Sopenharmony_ci	int i, ret;
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	cc = devm_kzalloc(dev, sizeof(*cc), GFP_KERNEL);
2308c2ecf20Sopenharmony_ci	if (!cc)
2318c2ecf20Sopenharmony_ci		return -ENOMEM;
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	cc->clks = &q6afe_clks[0];
2348c2ecf20Sopenharmony_ci	cc->num_clks = ARRAY_SIZE(q6afe_clks);
2358c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(q6afe_clks); i++) {
2368c2ecf20Sopenharmony_ci		if (!q6afe_clks[i])
2378c2ecf20Sopenharmony_ci			continue;
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci		q6afe_clks[i]->dev = dev;
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci		ret = devm_clk_hw_register(dev, &q6afe_clks[i]->hw);
2428c2ecf20Sopenharmony_ci		if (ret)
2438c2ecf20Sopenharmony_ci			return ret;
2448c2ecf20Sopenharmony_ci	}
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci	ret = of_clk_add_hw_provider(dev->of_node, q6afe_of_clk_hw_get, cc);
2478c2ecf20Sopenharmony_ci	if (ret)
2488c2ecf20Sopenharmony_ci		return ret;
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	dev_set_drvdata(dev, cc);
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	return 0;
2538c2ecf20Sopenharmony_ci}
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci#ifdef CONFIG_OF
2568c2ecf20Sopenharmony_cistatic const struct of_device_id q6afe_clock_device_id[] = {
2578c2ecf20Sopenharmony_ci	{ .compatible = "qcom,q6afe-clocks" },
2588c2ecf20Sopenharmony_ci	{},
2598c2ecf20Sopenharmony_ci};
2608c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, q6afe_clock_device_id);
2618c2ecf20Sopenharmony_ci#endif
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_cistatic struct platform_driver q6afe_clock_platform_driver = {
2648c2ecf20Sopenharmony_ci	.driver = {
2658c2ecf20Sopenharmony_ci		.name = "q6afe-clock",
2668c2ecf20Sopenharmony_ci		.of_match_table = of_match_ptr(q6afe_clock_device_id),
2678c2ecf20Sopenharmony_ci	},
2688c2ecf20Sopenharmony_ci	.probe = q6afe_clock_dev_probe,
2698c2ecf20Sopenharmony_ci};
2708c2ecf20Sopenharmony_cimodule_platform_driver(q6afe_clock_platform_driver);
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Q6 Audio Frontend clock driver");
2738c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
274