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