From bad018aefc79de4fed3365f4727275f675308863 Mon Sep 17 00:00:00 2001 From: Mehul Raninga Date: Mon, 1 Jul 2024 15:50:18 +0530 Subject: [PATCH 1/8] Slimbus: slim-msm-ngd: Avoid accessing deallocated stack The functions ngd_xfer_msg declare a local completion variable called done. However, this variable is accessed beyond the scope of these functions. To address this issue: 1. Instead of keeping done as a local variable, move it to msm_slim_ctrl. 2. Initialize done during the probe phase. 3. Use this variable for handling transfer and synchronization messages. Change-Id: If97b71e2db730ab21bfd07479d2737b0546e1f8e Signed-off-by: Mehul Raninga Signed-off-by: Chintan Kothari --- drivers/slimbus/slim-msm-ngd.c | 9 +++++++-- drivers/slimbus/slim-msm.h | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c index db36dd9e2a71..d6bafe6ff44e 100644 --- a/drivers/slimbus/slim-msm-ngd.c +++ b/drivers/slimbus/slim-msm-ngd.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -477,7 +478,6 @@ static int ngd_check_hw_status(struct msm_slim_ctrl *dev) static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn) { - DECLARE_COMPLETION_ONSTACK(done); DECLARE_COMPLETION_ONSTACK(tx_sent); struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl); @@ -491,6 +491,8 @@ static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn) bool report_sat = false; bool sync_wr = true; + reinit_completion(&dev->xfer_done); + if (txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG) return -EPROTONOSUPPORT; @@ -649,7 +651,9 @@ static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn) wbuf[i++] = txn->wbuf[0]; if (txn->mc != SLIM_USR_MC_DISCONNECT_PORT) wbuf[i++] = txn->wbuf[1]; - ret = ngd_get_tid(ctrl, txn, &wbuf[i++], &done); + + txn->comp = &dev->xfer_done; + ret = ngd_get_tid(ctrl, txn, &wbuf[i++], &dev->xfer_done); if (ret) { SLIM_ERR(dev, "TID for connect/disconnect fail:%d\n", ret); @@ -2015,6 +2019,7 @@ static int ngd_slim_probe(struct platform_device *pdev) init_completion(&dev->reconf); init_completion(&dev->ctrl_up); init_completion(&dev->qmi_up); + init_completion(&dev->xfer_done); mutex_init(&dev->tx_lock); mutex_init(&dev->ssr_lock); spin_lock_init(&dev->tx_buf_lock); diff --git a/drivers/slimbus/slim-msm.h b/drivers/slimbus/slim-msm.h index eabcecfef110..93a85ec2d68c 100644 --- a/drivers/slimbus/slim-msm.h +++ b/drivers/slimbus/slim-msm.h @@ -308,6 +308,8 @@ struct msm_slim_ctrl { bool chan_active; enum msm_ctrl_state state; struct completion ctrl_up; + struct completion xfer_done; + struct completion sync_done; int nsats; u32 ver; struct msm_slim_qmi qmi; From 740cf694a7274570baf50f4de272c74cbd38e868 Mon Sep 17 00:00:00 2001 From: Jagadeesh Ponduru Date: Mon, 19 Aug 2024 16:34:58 +0530 Subject: [PATCH 2/8] msm: ipa: clean up netdev resources in AFTER_SHUTDOWN cb Make changes to clean up netdev resource in AFTER_SHUTDOWN callback to not delay SSR processing. Change-Id: I41792d1e6600b8abc4baf60b19982d3043432cf9 Signed-off-by: Jagadeesh Ponduru --- drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c index a0284deed24f..0a0128b614b5 100644 --- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. */ /* @@ -2569,15 +2570,8 @@ static int ipa3_wwan_remove(struct platform_device *pdev) if (ipa3_rmnet_res.ipa_napi_enable) netif_napi_del(&(rmnet_ipa3_ctx->wwan_priv->napi)); mutex_unlock(&rmnet_ipa3_ctx->pipe_handle_guard); - IPAWANDBG("rmnet_ipa unregister_netdev started\n"); - unregister_netdev(IPA_NETDEV()); - IPAWANDBG("rmnet_ipa unregister_netdev completed\n"); - ipa3_wwan_deregister_netdev_pm_client(); cancel_work_sync(&ipa3_tx_wakequeue_work); cancel_delayed_work(&ipa_tether_stats_poll_wakequeue_work); - if (IPA_NETDEV()) - free_netdev(IPA_NETDEV()); - rmnet_ipa3_ctx->wwan_priv = NULL; /* No need to remove wwan_ioctl during SSR */ if (!atomic_read(&rmnet_ipa3_ctx->is_ssr)) ipa3_wan_ioctl_deinit(); @@ -2778,6 +2772,15 @@ static int ipa3_lcl_mdm_ssr_notifier_cb(struct notifier_block *this, break; case SUBSYS_AFTER_SHUTDOWN: IPAWANINFO("IPA Received MPSS AFTER_SHUTDOWN\n"); + + IPAWANINFO("rmnet_ipa unregister_netdev\n"); + if (IPA_NETDEV()) + unregister_netdev(IPA_NETDEV()); + ipa3_wwan_deregister_netdev_pm_client(); + if (IPA_NETDEV()) + free_netdev(IPA_NETDEV()); + rmnet_ipa3_ctx->wwan_priv = NULL; + if (atomic_read(&rmnet_ipa3_ctx->is_ssr) && ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) ipa3_q6_post_shutdown_cleanup(); From 99c1e1b0713701b24a6c31cdec5a8589acfeba99 Mon Sep 17 00:00:00 2001 From: Smeet Raj Date: Fri, 27 Sep 2024 09:50:46 +0530 Subject: [PATCH 3/8] dt-bindings: clk: lpasscc-scuba: Add support for LPASS AONCC and AUDIOCC Add bindings for LPASS AON, AUDIO clock controllers on scuba platform for clients to be able to request for clocks from these clock controllers. Change-Id: I5d09794c3bfdc1f1874b2edfadfac60863b44b81 Signed-off-by: Smeet Raj --- .../dt-bindings/clock/qcom,scuba-lpassaoncc.h | 57 +++++++++++++++ .../clock/qcom,scuba-lpassaudiocc.h | 70 +++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 include/dt-bindings/clock/qcom,scuba-lpassaoncc.h create mode 100644 include/dt-bindings/clock/qcom,scuba-lpassaudiocc.h diff --git a/include/dt-bindings/clock/qcom,scuba-lpassaoncc.h b/include/dt-bindings/clock/qcom,scuba-lpassaoncc.h new file mode 100644 index 000000000000..de346d56f7aa --- /dev/null +++ b/include/dt-bindings/clock/qcom,scuba-lpassaoncc.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_LPASS_AON_CC_SCUBA_H +#define _DT_BINDINGS_CLK_QCOM_LPASS_AON_CC_SCUBA_H + +/* LPASS_AON_CC clocks */ +#define LPASS_AON_CC_AHB_TIMEOUT_CLK 0 +#define LPASS_AON_CC_AON_H_CLK 1 +#define LPASS_AON_CC_AUDIO_HM_H_CLK 2 +#define LPASS_AON_CC_AUDIO_HM_SLEEP_CLK 3 +#define LPASS_AON_CC_BUS_ALT_CLK 4 +#define LPASS_AON_CC_CDIV_TX_MCLK_DIV_CLK_SRC 5 +#define LPASS_AON_CC_CDIV_VA_DIV_CLK_SRC 6 +#define LPASS_AON_CC_CPR_CLK 7 +#define LPASS_AON_CC_CPR_CLK_SRC 8 +#define LPASS_AON_CC_CSR_H_CLK 9 +#define LPASS_AON_CC_MAIN_RCG_CLK_SRC 10 +#define LPASS_AON_CC_MCC_ACCESS_CLK 11 +#define LPASS_AON_CC_PDC_GDS_CLK 12 +#define LPASS_AON_CC_PDC_H_CLK 13 +#define LPASS_AON_CC_PLL 14 +#define LPASS_AON_CC_PLL_OUT_AUX 15 +#define LPASS_AON_CC_PLL_OUT_AUX2 16 +#define LPASS_AON_CC_Q6_AHBM_CLK 17 +#define LPASS_AON_CC_Q6_AHBS_CLK 18 +#define LPASS_AON_CC_Q6_ATBM_CLK 19 +#define LPASS_AON_CC_Q6_XO_CLK 20 +#define LPASS_AON_CC_Q6_XO_CLK_SRC 21 +#define LPASS_AON_CC_Q6_XPU2_CLIENT_CLK 22 +#define LPASS_AON_CC_Q6_XPU2_CONFIG_CLK 23 +#define LPASS_AON_CC_QSM_XO_CLK 24 +#define LPASS_AON_CC_RO_CLK 25 +#define LPASS_AON_CC_RO_PLL 26 +#define LPASS_AON_CC_RO_PLL_OUT_EVEN 27 +#define LPASS_AON_CC_RO_PLL_OUT_MAIN 28 +#define LPASS_AON_CC_RSC_HCLK_CLK 29 +#define LPASS_AON_CC_SLEEP_CLK 30 +#define LPASS_AON_CC_SSC_H_CLK 31 +#define LPASS_AON_CC_TX_MCLK_2X_CLK 32 +#define LPASS_AON_CC_TX_MCLK_CLK 33 +#define LPASS_AON_CC_TX_MCLK_RCG_CLK_SRC 34 +#define LPASS_AON_CC_VA_2X_CLK 35 +#define LPASS_AON_CC_VA_CLK 36 +#define LPASS_AON_CC_VA_MEM0_CLK 37 +#define LPASS_AON_CC_VA_RCG_CLK_SRC 38 +#define LPASS_AON_CC_VA_XPU2_CLIENT_CLK 39 +#define LPASS_AON_CC_VS_VDDCX_CLK 40 +#define LPASS_AON_CC_VS_VDDCX_CLK_SRC 41 +#define LPASS_AON_CC_VS_VDDMX_CLK 42 +#define LPASS_AON_CC_VS_VDDMX_CLK_SRC 43 +#define LPASS_QDSP6SS_SLEEP_CLK 44 +#define LPASS_QDSP6SS_XO_CLK 45 + +#endif diff --git a/include/dt-bindings/clock/qcom,scuba-lpassaudiocc.h b/include/dt-bindings/clock/qcom,scuba-lpassaudiocc.h new file mode 100644 index 000000000000..fa0c090acd76 --- /dev/null +++ b/include/dt-bindings/clock/qcom,scuba-lpassaudiocc.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_LPASS_AUDIO_CC_SCUBA_H +#define _DT_BINDINGS_CLK_QCOM_LPASS_AUDIO_CC_SCUBA_H + +/* LPASS_AUDIO_CC clocks */ +#define AUD_SLIMBUS_CLK_SRC 0 +#define LPASS_AUDIO_CC_AUD_SLIMBUS_CLK 1 +#define LPASS_AUDIO_CC_AUD_SLIMBUS_CORE_CLK 2 +#define LPASS_AUDIO_CC_AUD_SLIMBUS_NPL_CLK 3 +#define LPASS_AUDIO_CC_BUS_CLK 4 +#define LPASS_AUDIO_CC_BUS_TIMEOUT_CLK 5 +#define LPASS_AUDIO_CC_CDIV_RX_MCLK_DIV_CLK_SRC 6 +#define LPASS_AUDIO_CC_CDIV_WSA_MCLK_DIV_CLK_SRC 7 +#define LPASS_AUDIO_CC_CODEC_MEM0_CLK 8 +#define LPASS_AUDIO_CC_CODEC_MEM1_CLK 9 +#define LPASS_AUDIO_CC_CODEC_MEM2_CLK 10 +#define LPASS_AUDIO_CC_CODEC_MEM3_CLK 11 +#define LPASS_AUDIO_CC_CODEC_MEM_CLK 12 +#define LPASS_AUDIO_CC_DIG_PLL 13 +#define LPASS_AUDIO_CC_DIG_PLL_OUT_AUX 14 +#define LPASS_AUDIO_CC_EXT_IF1_CLK_SRC 15 +#define LPASS_AUDIO_CC_EXT_IF1_EBIT_CLK 16 +#define LPASS_AUDIO_CC_EXT_IF1_IBIT_CLK 17 +#define LPASS_AUDIO_CC_EXT_IF2_CLK_SRC 18 +#define LPASS_AUDIO_CC_EXT_IF2_EBIT_CLK 19 +#define LPASS_AUDIO_CC_EXT_IF2_IBIT_CLK 20 +#define LPASS_AUDIO_CC_EXT_IF3_CLK_SRC 21 +#define LPASS_AUDIO_CC_EXT_IF3_EBIT_CLK 22 +#define LPASS_AUDIO_CC_EXT_IF3_IBIT_CLK 23 +#define LPASS_AUDIO_CC_EXT_IF4_CLK_SRC 24 +#define LPASS_AUDIO_CC_EXT_IF4_EBIT_CLK 25 +#define LPASS_AUDIO_CC_EXT_IF4_IBIT_CLK 26 +#define LPASS_AUDIO_CC_EXT_MCLK0_CLK 27 +#define LPASS_AUDIO_CC_EXT_MCLK0_CLK_SRC 28 +#define LPASS_AUDIO_CC_EXT_MCLK1_CLK 29 +#define LPASS_AUDIO_CC_EXT_MCLK1_CLK_SRC 30 +#define LPASS_AUDIO_CC_LPAIF_PCMOE_CLK 31 +#define LPASS_AUDIO_CC_LPAIF_PCMOE_CLK_SRC 32 +#define LPASS_AUDIO_CC_PLL 33 +#define LPASS_AUDIO_CC_PLL_OUT_AUX 34 +#define LPASS_AUDIO_CC_PLL_OUT_AUX2 35 +#define LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC 36 +#define LPASS_AUDIO_CC_RX_MCLK_2X_CLK 37 +#define LPASS_AUDIO_CC_RX_MCLK_CLK 38 +#define LPASS_AUDIO_CC_RX_MCLK_CLK_SRC 39 +#define LPASS_AUDIO_CC_SAMPLING_CLK 40 +#define LPASS_AUDIO_CC_WSA_MCLK_2X_CLK 41 +#define LPASS_AUDIO_CC_WSA_MCLK_CLK 42 +#define LPASS_AUDIO_CC_WSA_MCLK_CLK_SRC 43 +#define LPASS_AUDIO_CC_XPU2_CLIENT_CLK 44 +#define LPASS_AON_CC_PLL_OUT_ODD_CLK 45 + +/* LPASS_AUDIO_CC resets */ +#define LPASS_AUDIO_CC_EXT_IF1_BCR 0 +#define LPASS_AUDIO_CC_EXT_IF2_BCR 1 +#define LPASS_AUDIO_CC_EXT_IF3_BCR 2 +#define LPASS_AUDIO_CC_EXT_IF4_BCR 3 +#define LPASS_AUDIO_CC_EXT_MCLK0_BCR 4 +#define LPASS_AUDIO_CC_EXT_MCLK1_BCR 5 +#define LPASS_AUDIO_CC_PCM_DATA_OE_BCR 6 +#define LPASS_AUDIO_CC_QCA_SLIMBUS_BCR 7 +#define LPASS_AUDIO_CC_RX_MCLK_BCR 8 +#define LPASS_AUDIO_CC_TX_MCLK_BCR 9 +#define LPASS_AUDIO_CC_WSA_MCLK_BCR 10 + +#endif From 5a7dfc9bd57fb366f330015997438b166cfc60d2 Mon Sep 17 00:00:00 2001 From: Smeet Raj Date: Fri, 27 Sep 2024 09:35:06 +0530 Subject: [PATCH 4/8] clk: qcom: lpasscc-scuba: Add Support for AON & AUDIO clock drivers Add Support for LPASS AON and AUDIO Clock Controller drivers for Audio clients to be able to control clocks. Change-Id: I830f00c8342f70479f0e8aff2051966d128e64e2 Signed-off-by: Smeet Raj --- drivers/clk/qcom/Kconfig | 9 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/lpassaoncc-scuba.c | 854 +++++++++++++++++ drivers/clk/qcom/lpassaudiocc-scuba.c | 1217 +++++++++++++++++++++++++ 4 files changed, 2081 insertions(+) create mode 100644 drivers/clk/qcom/lpassaoncc-scuba.c create mode 100644 drivers/clk/qcom/lpassaudiocc-scuba.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 228cdec287ba..61e2df623496 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -544,6 +544,15 @@ config QM_DEBUGCC_SCUBA SCUBA devices. Say Y if you want to support the clock measurement functionality. +config QM_LPASS_AUDIOCC_SCUBA + tristate "SCUBA Audio Clock Controllers" + select QM_GCC_SCUBA + help + Support for the LPASS(Low-Power Audio Subsytem) aon & audio clock + controllers on Qualcomm Technologies, Inc SCUBA devices. + Say Y if you want to use LPASS AUDIOCC and AONCC clocks required + to support audio devices and its functionalities. + config SDM_GCC_660 tristate "SDM660 Global Clock Controller" depends on COMMON_CLK_QCOM diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 15abfd421a12..8834fc9bfc04 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -54,6 +54,7 @@ obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o obj-$(CONFIG_QM_DISPCC_SCUBA) += dispcc-scuba.o obj-$(CONFIG_QM_GCC_SCUBA) += gcc-scuba.o obj-$(CONFIG_QM_GPUCC_SCUBA) += gpucc-scuba.o +obj-$(CONFIG_QM_LPASS_AUDIOCC_SCUBA) += lpassaoncc-scuba.o lpassaudiocc-scuba.o obj-$(CONFIG_QM_DEBUGCC_SCUBA) += debugcc-scuba.o obj-$(CONFIG_SDM_CAMCC_LAGOON) += camcc-lagoon.o obj-$(CONFIG_SDM_DEBUGCC_429W) += debugcc-sdm429w.o diff --git a/drivers/clk/qcom/lpassaoncc-scuba.c b/drivers/clk/qcom/lpassaoncc-scuba.c new file mode 100644 index 000000000000..8172f0a5a398 --- /dev/null +++ b/drivers/clk/qcom/lpassaoncc-scuba.c @@ -0,0 +1,854 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-regmap-mux.h" +#include "common.h" +#include "reset.h" +#include "vdd-level.h" + +static DEFINE_VDD_REGULATORS(vdd_lpi_cx, VDD_NUM + 1, 1, vdd_corner); + +enum { + P_BI_TCXO, + P_LPASS_AON_CC_PLL_OUT_AUX, + P_LPASS_AON_CC_PLL_OUT_AUX2, + P_LPASS_AON_CC_PLL_OUT_EARLY, + P_LPASS_AUDIO_CC_PLL_MAIN_DIV_CLK, + P_LPASS_CORE_CC_PLL_ODD_CLK, +}; + +static const struct parent_map lpass_aon_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_LPASS_AON_CC_PLL_OUT_EARLY, 2 }, +}; + +static const char * const lpass_aon_cc_parent_names_0[] = { + "bi_tcxo", + "lpass_aon_cc_pll", +}; + +static const struct parent_map lpass_aon_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_BI_TCXO, 4 }, +}; + +static const char * const lpass_aon_cc_parent_names_1_ao[] = { + "bi_tcxo_ao", + "bi_tcxo", +}; + +static const struct parent_map lpass_aon_cc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_LPASS_AON_CC_PLL_OUT_AUX2, 4 }, +}; + +static const char * const lpass_aon_cc_parent_names_2[] = { + "bi_tcxo", + "lpass_aon_cc_pll_out_aux2", +}; + +static const struct parent_map lpass_aon_cc_parent_map_3[] = { + { P_BI_TCXO, 0 }, + { P_LPASS_AON_CC_PLL_OUT_AUX, 1 }, + { P_LPASS_CORE_CC_PLL_ODD_CLK, 2 }, + { P_LPASS_AUDIO_CC_PLL_MAIN_DIV_CLK, 6 }, +}; + +static const char * const lpass_aon_cc_parent_names_3[] = { + "bi_tcxo", + "lpass_aon_cc_pll_out_aux", + "lpass_core_cc_pll_odd_clk", + "lpass_audio_cc_pll_main_div_clk", +}; + +static const struct parent_map lpass_aon_cc_parent_map_4[] = { + { P_BI_TCXO, 0 }, +}; + +static const char * const lpass_aon_cc_parent_names_4[] = { + "bi_tcxo", +}; + +static const struct pll_vco aoncc_pll_vco[] = { + { 1000000000, 2000000000, 0 }, + { 750000000, 1500000000, 1 }, + { 500000000, 1000000000, 2 }, + { 250000000, 500000000, 3 }, +}; + +/* 614.4 MHz Configuration */ +static const struct alpha_pll_config lpass_aon_cc_pll_config = { + .l = 0x20, + .config_ctl_val = 0x4001055b, + .user_ctl_val = 0x200101, + .user_ctl_hi_val = 0x4, + .test_ctl_val = 0, + .test_ctl_hi_val = 0x1, + .main_output_mask = BIT(0), + .aux_output_mask = BIT(1), + .aux2_output_mask = BIT(2), + .early_output_mask = BIT(3), + .post_div_val = 0x281 << 8, + .post_div_mask = GENMASK(17, 8), + .vco_val = 0x2 << 20, + .vco_mask = GENMASK(21, 20), + .test_ctl_mask = GENMASK(31, 0), + .test_ctl_hi_mask = 0x1, +}; + +static struct clk_alpha_pll lpass_aon_cc_pll = { + .offset = 0x0, + .vco_table = aoncc_pll_vco, + .num_vco = ARRAY_SIZE(aoncc_pll_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_pll", + .parent_names = (const char *[]){ "bi_tcxo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + .vdd_class = &vdd_lpi_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_MIN] = 1000000000, + [VDD_NOMINAL] = 2000000000}, + }, + }, +}; + +static const struct clk_div_table post_div_table_lpass_aon_cc_pll_out_aux[] = { + { 0x5, 5 }, + { } +}; + +static struct clk_alpha_pll_postdiv lpass_aon_cc_pll_out_aux = { + .offset = 0x0, + .post_div_shift = 15, + .post_div_table = post_div_table_lpass_aon_cc_pll_out_aux, + .num_post_div = ARRAY_SIZE(post_div_table_lpass_aon_cc_pll_out_aux), + .width = 3, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_pll_out_aux", + .parent_names = (const char *[]){ "lpass_aon_cc_pll" }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_fabia_ops, + }, +}; + +static const struct clk_div_table post_div_table_lpass_aon_cc_pll_out_aux2[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv lpass_aon_cc_pll_out_aux2 = { + .offset = 0x0, + .post_div_shift = 8, + .post_div_table = post_div_table_lpass_aon_cc_pll_out_aux2, + .num_post_div = ARRAY_SIZE(post_div_table_lpass_aon_cc_pll_out_aux2), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_pll_out_aux2", + .parent_names = (const char *[]){ "lpass_aon_cc_pll" }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_fabia_ops, + }, +}; + +static struct clk_regmap_div lpass_aon_cc_cdiv_tx_mclk_div_clk_src = { + .reg = 0x13010, + .shift = 0, + .width = 2, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_cdiv_tx_mclk_div_clk_src", + .parent_names = (const char *[]) + { "lpass_aon_cc_tx_mclk_rcg_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div lpass_aon_cc_cdiv_va_div_clk_src = { + .reg = 0x12010, + .shift = 0, + .width = 2, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_cdiv_va_div_clk_src", + .parent_names = (const char *[]) + { "lpass_aon_cc_va_rcg_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static const struct freq_tbl ftbl_lpass_aon_cc_cpr_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 lpass_aon_cc_cpr_clk_src = { + .cmd_rcgr = 0x2004, + .mnd_width = 0, + .hid_width = 5, + .parent_map = lpass_aon_cc_parent_map_1, + .freq_tbl = ftbl_lpass_aon_cc_cpr_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_cpr_clk_src", + .parent_names = lpass_aon_cc_parent_names_1_ao, + .num_parents = ARRAY_SIZE(lpass_aon_cc_parent_names_1_ao), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_lpass_aon_cc_main_rcg_clk_src[] = { + F(38400000, P_LPASS_AON_CC_PLL_OUT_AUX2, 8, 0, 0), + F(76800000, P_LPASS_AON_CC_PLL_OUT_AUX2, 4, 0, 0), + { } +}; + +static struct clk_rcg2 lpass_aon_cc_main_rcg_clk_src = { + .cmd_rcgr = 0x1000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = lpass_aon_cc_parent_map_2, + .freq_tbl = ftbl_lpass_aon_cc_main_rcg_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_main_rcg_clk_src", + .parent_names = lpass_aon_cc_parent_names_2, + .num_parents = ARRAY_SIZE(lpass_aon_cc_parent_names_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_lpi_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 38400000, + [VDD_NOMINAL] = 76800000}, + }, +}; + +static struct clk_rcg2 lpass_aon_cc_q6_xo_clk_src = { + .cmd_rcgr = 0x8004, + .mnd_width = 0, + .hid_width = 5, + .parent_map = lpass_aon_cc_parent_map_1, + .freq_tbl = ftbl_lpass_aon_cc_cpr_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_q6_xo_clk_src", + .parent_names = lpass_aon_cc_parent_names_1_ao, + .num_parents = ARRAY_SIZE(lpass_aon_cc_parent_names_1_ao), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_lpass_aon_cc_tx_mclk_rcg_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(24576000, P_LPASS_AON_CC_PLL_OUT_AUX, 5, 0, 0), + { } +}; + +static struct clk_rcg2 lpass_aon_cc_tx_mclk_rcg_clk_src = { + .cmd_rcgr = 0x13004, + .mnd_width = 0, + .hid_width = 5, + .parent_map = lpass_aon_cc_parent_map_3, + .freq_tbl = ftbl_lpass_aon_cc_tx_mclk_rcg_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_tx_mclk_rcg_clk_src", + .parent_names = lpass_aon_cc_parent_names_3, + .num_parents = ARRAY_SIZE(lpass_aon_cc_parent_names_3), + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_lpi_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 24576000}, + }, +}; + +static const struct freq_tbl ftbl_lpass_aon_cc_va_rcg_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 lpass_aon_cc_va_rcg_clk_src = { + .cmd_rcgr = 0x12004, + .mnd_width = 0, + .hid_width = 5, + .parent_map = lpass_aon_cc_parent_map_4, + .freq_tbl = ftbl_lpass_aon_cc_va_rcg_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_va_rcg_clk_src", + .parent_names = lpass_aon_cc_parent_names_4, + .num_parents = ARRAY_SIZE(lpass_aon_cc_parent_names_4), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_lpi_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 19200000}, + }, +}; + +static const struct freq_tbl ftbl_lpass_aon_cc_vs_vddcx_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(614400000, P_LPASS_AON_CC_PLL_OUT_EARLY, 1, 0, 0), + { } +}; + +static struct clk_rcg2 lpass_aon_cc_vs_vddcx_clk_src = { + .cmd_rcgr = 0x15010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = lpass_aon_cc_parent_map_0, + .freq_tbl = ftbl_lpass_aon_cc_vs_vddcx_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_vs_vddcx_clk_src", + .parent_names = lpass_aon_cc_parent_names_0, + .num_parents = ARRAY_SIZE(lpass_aon_cc_parent_names_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_lpi_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 614400000}, + }, +}; + +static struct clk_rcg2 lpass_aon_cc_vs_vddmx_clk_src = { + .cmd_rcgr = 0x15000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = lpass_aon_cc_parent_map_0, + .freq_tbl = ftbl_lpass_aon_cc_vs_vddcx_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_vs_vddmx_clk_src", + .parent_names = lpass_aon_cc_parent_names_0, + .num_parents = ARRAY_SIZE(lpass_aon_cc_parent_names_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_lpi_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 614400000}, + }, +}; + +static struct clk_branch lpass_aon_cc_ahb_timeout_clk = { + .halt_reg = 0x9030, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x9030, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_ahb_timeout_clk", + .parent_names = (const char *[]){ + "lpass_aon_cc_main_rcg_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_aon_cc_aon_h_clk = { + .halt_reg = 0x903c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x903c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_aon_h_clk", + .parent_names = (const char *[]){ + "lpass_aon_cc_main_rcg_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_aon_cc_bus_alt_clk = { + .halt_reg = 0x9048, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9048, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_bus_alt_clk", + .parent_names = (const char *[]){ + "lpass_aon_cc_main_rcg_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_aon_cc_csr_h_clk = { + .halt_reg = 0x9010, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x9010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_csr_h_clk", + .parent_names = (const char *[]){ + "lpass_aon_cc_main_rcg_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_aon_cc_mcc_access_clk = { + .halt_reg = 0x904c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x904c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_mcc_access_clk", + .parent_names = (const char *[]){ + "lpass_aon_cc_main_rcg_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_aon_cc_pdc_h_clk = { + .halt_reg = 0x900c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x900c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_pdc_h_clk", + .parent_names = (const char *[]){ + "lpass_aon_cc_main_rcg_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_aon_cc_q6_atbm_clk = { + .halt_reg = 0xa010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_q6_atbm_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_aon_cc_qsm_xo_clk = { + .halt_reg = 0x6000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_qsm_xo_clk", + .parent_names = (const char *[]){ + "lpass_aon_cc_q6_xo_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_aon_cc_rsc_hclk_clk = { + .halt_reg = 0x9078, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x9078, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x9078, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_rsc_hclk_clk", + .parent_names = (const char *[]){ + "lpass_aon_cc_main_rcg_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_aon_cc_sleep_clk = { + .halt_reg = 0x10004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_aon_cc_ssc_h_clk = { + .halt_reg = 0x9040, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9040, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_ssc_h_clk", + .parent_names = (const char *[]){ + "lpass_aon_cc_main_rcg_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_aon_cc_tx_mclk_2x_clk = { + .halt_reg = 0x1300c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1300c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_tx_mclk_2x_clk", + .parent_names = (const char *[]){ + "lpass_aon_cc_tx_mclk_rcg_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_aon_cc_tx_mclk_clk = { + .halt_reg = 0x13014, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13014, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_tx_mclk_clk", + .parent_names = (const char *[]){ + "lpass_aon_cc_cdiv_tx_mclk_div_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_aon_cc_va_2x_clk = { + .halt_reg = 0x1200c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1200c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_va_2x_clk", + .parent_names = (const char *[]){ + "lpass_aon_cc_va_rcg_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_aon_cc_va_clk = { + .halt_reg = 0x12014, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12014, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_va_clk", + .parent_names = (const char *[]){ + "lpass_aon_cc_cdiv_va_div_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_aon_cc_va_mem0_clk = { + .halt_reg = 0x9028, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9028, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_va_mem0_clk", + .parent_names = (const char *[]){ + "lpass_aon_cc_main_rcg_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_aon_cc_vs_vddcx_clk = { + .halt_reg = 0x15018, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x15018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_vs_vddcx_clk", + .parent_names = (const char *[]){ + "lpass_aon_cc_vs_vddcx_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_aon_cc_vs_vddmx_clk = { + .halt_reg = 0x15008, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x15008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_vs_vddmx_clk", + .parent_names = (const char *[]){ + "lpass_aon_cc_vs_vddmx_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_qdsp6ss_sleep_clk = { + .halt_reg = 0x3c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x3c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_qdsp6ss_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_qdsp6ss_xo_clk = { + .halt_reg = 0x38, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x38, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_qdsp6ss_xo_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_regmap *lpass_aon_cc_scuba_clocks[] = { + [LPASS_AON_CC_AHB_TIMEOUT_CLK] = &lpass_aon_cc_ahb_timeout_clk.clkr, + [LPASS_AON_CC_AON_H_CLK] = &lpass_aon_cc_aon_h_clk.clkr, + [LPASS_AON_CC_BUS_ALT_CLK] = &lpass_aon_cc_bus_alt_clk.clkr, + [LPASS_AON_CC_CDIV_TX_MCLK_DIV_CLK_SRC] = + &lpass_aon_cc_cdiv_tx_mclk_div_clk_src.clkr, + [LPASS_AON_CC_CDIV_VA_DIV_CLK_SRC] = + &lpass_aon_cc_cdiv_va_div_clk_src.clkr, + [LPASS_AON_CC_CPR_CLK_SRC] = &lpass_aon_cc_cpr_clk_src.clkr, + [LPASS_AON_CC_CSR_H_CLK] = &lpass_aon_cc_csr_h_clk.clkr, + [LPASS_AON_CC_MAIN_RCG_CLK_SRC] = &lpass_aon_cc_main_rcg_clk_src.clkr, + [LPASS_AON_CC_MCC_ACCESS_CLK] = &lpass_aon_cc_mcc_access_clk.clkr, + [LPASS_AON_CC_PDC_H_CLK] = &lpass_aon_cc_pdc_h_clk.clkr, + [LPASS_AON_CC_PLL] = &lpass_aon_cc_pll.clkr, + [LPASS_AON_CC_PLL_OUT_AUX] = &lpass_aon_cc_pll_out_aux.clkr, + [LPASS_AON_CC_PLL_OUT_AUX2] = &lpass_aon_cc_pll_out_aux2.clkr, + [LPASS_AON_CC_Q6_ATBM_CLK] = &lpass_aon_cc_q6_atbm_clk.clkr, + [LPASS_AON_CC_Q6_XO_CLK_SRC] = &lpass_aon_cc_q6_xo_clk_src.clkr, + [LPASS_AON_CC_QSM_XO_CLK] = &lpass_aon_cc_qsm_xo_clk.clkr, + [LPASS_AON_CC_RSC_HCLK_CLK] = &lpass_aon_cc_rsc_hclk_clk.clkr, + [LPASS_AON_CC_SLEEP_CLK] = &lpass_aon_cc_sleep_clk.clkr, + [LPASS_AON_CC_SSC_H_CLK] = &lpass_aon_cc_ssc_h_clk.clkr, + [LPASS_AON_CC_TX_MCLK_2X_CLK] = &lpass_aon_cc_tx_mclk_2x_clk.clkr, + [LPASS_AON_CC_TX_MCLK_CLK] = &lpass_aon_cc_tx_mclk_clk.clkr, + [LPASS_AON_CC_TX_MCLK_RCG_CLK_SRC] = + &lpass_aon_cc_tx_mclk_rcg_clk_src.clkr, + [LPASS_AON_CC_VA_2X_CLK] = &lpass_aon_cc_va_2x_clk.clkr, + [LPASS_AON_CC_VA_CLK] = &lpass_aon_cc_va_clk.clkr, + [LPASS_AON_CC_VA_MEM0_CLK] = &lpass_aon_cc_va_mem0_clk.clkr, + [LPASS_AON_CC_VA_RCG_CLK_SRC] = &lpass_aon_cc_va_rcg_clk_src.clkr, + [LPASS_AON_CC_VS_VDDCX_CLK] = &lpass_aon_cc_vs_vddcx_clk.clkr, + [LPASS_AON_CC_VS_VDDCX_CLK_SRC] = &lpass_aon_cc_vs_vddcx_clk_src.clkr, + [LPASS_AON_CC_VS_VDDMX_CLK] = &lpass_aon_cc_vs_vddmx_clk.clkr, + [LPASS_AON_CC_VS_VDDMX_CLK_SRC] = &lpass_aon_cc_vs_vddmx_clk_src.clkr, + [LPASS_QDSP6SS_SLEEP_CLK] = &lpass_qdsp6ss_sleep_clk.clkr, + [LPASS_QDSP6SS_XO_CLK] = &lpass_qdsp6ss_xo_clk.clkr, +}; + +static const struct regmap_config lpass_aon_cc_scuba_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x20008, + .fast_io = true, +}; + +static const struct qcom_cc_desc lpass_aon_cc_scuba_desc = { + .config = &lpass_aon_cc_scuba_regmap_config, + .clks = lpass_aon_cc_scuba_clocks, + .num_clks = ARRAY_SIZE(lpass_aon_cc_scuba_clocks), +}; + +static const struct of_device_id lpass_aon_cc_scuba_match_table[] = { + { .compatible = "qcom,lpassaoncc-scuba" }, + { } +}; +MODULE_DEVICE_TABLE(of, lpass_aon_cc_scuba_match_table); + +static int lpass_aon_cc_scuba_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + int ret; + + vdd_lpi_cx.regulator[0] = devm_regulator_get(&pdev->dev, "vdd_lpi_cx"); + if (IS_ERR(vdd_lpi_cx.regulator[0])) { + if (PTR_ERR(vdd_lpi_cx.regulator[0]) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Unable to get vdd_lpi_cx regulator\n"); + return PTR_ERR(vdd_lpi_cx.regulator[0]); + } + + pm_runtime_enable(&pdev->dev); + ret = pm_clk_create(&pdev->dev); + if (ret) + return ret; + + ret = pm_clk_add(&pdev->dev, "iface_clk"); + if (ret < 0) { + dev_err(&pdev->dev, "failed to acquire gcc sway clock\n"); + goto err_destroy_pm_clk; + } + + ret = pm_runtime_get_sync(&pdev->dev); + if (ret) + goto err_destroy_pm_clk; + + regmap = qcom_cc_map(pdev, &lpass_aon_cc_scuba_desc); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + goto err_put_rpm; + } + + clk_alpha_pll_configure(&lpass_aon_cc_pll, regmap, + &lpass_aon_cc_pll_config); + + /* + * Keep clocks always enabled: + * lpass_aon_cc_q6_ahbs_clk + * lpass_aon_cc_q6_ahbm_clk + */ + regmap_update_bits(regmap, 0x9020, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x901C, BIT(0), BIT(0)); + + ret = qcom_cc_really_probe(pdev, &lpass_aon_cc_scuba_desc, regmap); + if (ret) { + dev_err(&pdev->dev, "Register Fail LPASS Aon clocks ret=%d\n", + ret); + goto err_put_rpm; + } + + pm_runtime_put_sync(&pdev->dev); + dev_info(&pdev->dev, "Registered LPASS Aon clocks\n"); + return 0; + +err_put_rpm: + pm_runtime_put_sync(&pdev->dev); +err_destroy_pm_clk: + pm_clk_destroy(&pdev->dev); + return ret; +} + +static const struct dev_pm_ops lpass_aon_cc_scuba_pm_ops = { + SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL) +}; + +static struct platform_driver lpass_aon_cc_scuba_driver = { + .probe = lpass_aon_cc_scuba_probe, + .driver = { + .name = "lpassaoncc-scuba", + .of_match_table = lpass_aon_cc_scuba_match_table, + .pm = &lpass_aon_cc_scuba_pm_ops, + }, +}; + +static int __init lpass_aon_cc_scuba_init(void) +{ + return platform_driver_register(&lpass_aon_cc_scuba_driver); +} +subsys_initcall(lpass_aon_cc_scuba_init); + +static void __exit lpass_aon_cc_scuba_exit(void) +{ + platform_driver_unregister(&lpass_aon_cc_scuba_driver); +} +module_exit(lpass_aon_cc_scuba_exit); + +MODULE_DESCRIPTION("QTI LPASSAONCC SCUBA Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/qcom/lpassaudiocc-scuba.c b/drivers/clk/qcom/lpassaudiocc-scuba.c new file mode 100644 index 000000000000..d306b9f0f934 --- /dev/null +++ b/drivers/clk/qcom/lpassaudiocc-scuba.c @@ -0,0 +1,1217 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-regmap-mux.h" +#include "common.h" +#include "reset.h" +#include "vdd-level.h" + +static DEFINE_VDD_REGULATORS(vdd_lpi_cx, VDD_NUM + 1, 1, vdd_corner); + +enum { + P_BI_TCXO, + P_LPASS_AON_CC_PLL_OUT_AUX, + P_LPASS_AUDIO_CC_DIG_PLL_OUT_AUX, + P_LPASS_AUDIO_CC_PLL_OUT_AUX, + P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, +}; + +static const struct parent_map lpass_audio_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_LPASS_AUDIO_CC_PLL_OUT_AUX, 3 }, + { P_LPASS_AUDIO_CC_DIG_PLL_OUT_AUX, 4 }, + { P_LPASS_AON_CC_PLL_OUT_AUX, 5 }, + { P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 6 }, +}; + +static const char * const lpass_audio_cc_parent_names_0[] = { + "bi_tcxo", + "lpass_audio_cc_pll_out_aux", + "lpass_audio_cc_dig_pll_out_aux", + "lpass_aon_cc_pll_out_aux", + "lpass_audio_cc_pll_out_aux2_div_clk_src", +}; + +static const struct parent_map lpass_audio_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_LPASS_AUDIO_CC_DIG_PLL_OUT_AUX, 4 }, + { P_LPASS_AON_CC_PLL_OUT_AUX, 5 }, +}; + +static const char * const lpass_audio_cc_parent_names_1[] = { + "bi_tcxo", + "lpass_audio_cc_dig_pll_out_aux", + "lpass_aon_cc_pll_out_aux", +}; + +static const struct parent_map lpass_audio_cc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_LPASS_AUDIO_CC_DIG_PLL_OUT_AUX, 4 }, + { P_LPASS_AON_CC_PLL_OUT_AUX, 5 }, + { P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 6 }, +}; + +static const char * const lpass_audio_cc_parent_names_2[] = { + "bi_tcxo", + "lpass_audio_cc_dig_pll_out_aux", + "lpass_aon_cc_pll_out_aux", + "lpass_audio_cc_pll_out_aux2_div_clk_src", +}; + +static const u8 clk_alpha_pll_regs_offset[][PLL_OFF_MAX_REGS] = { + [CLK_ALPHA_PLL_TYPE_BRAMMO] = { + [PLL_OFF_L_VAL] = 0x04, + [PLL_OFF_ALPHA_VAL] = 0x08, + [PLL_OFF_ALPHA_VAL_U] = 0x0c, + [PLL_OFF_USER_CTL] = 0x10, + [PLL_OFF_CONFIG_CTL] = 0x14, + [PLL_OFF_TEST_CTL] = 0x18, + [PLL_OFF_TEST_CTL_U] = 0x1c, + [PLL_OFF_STATUS] = 0x20, + }, +}; + +static const struct pll_vco audiocc_pll_vco[] = { + { 500000000, 1250000000, 0 }, +}; + +static const struct pll_vco audiocc_dig_pll_vco[] = { + { 1000000000, 2000000000, 0 }, + { 750000000, 1500000000, 1 }, + { 500000000, 1000000000, 2 }, + { 250000000, 500000000, 3 }, +}; + +/* 614.4 MHz Configuration */ +static const struct alpha_pll_config lpass_audio_cc_dig_pll_config = { + .l = 0x20, + .config_ctl_val = 0x4001055b, + .user_ctl_val = 0x00200101, + .user_ctl_hi_val = 0x4, + .test_ctl_hi_val = 0x1, + .main_output_mask = BIT(0), + .aux_output_mask = BIT(1), + .post_div_val = 0x1 << 8, + .post_div_mask = GENMASK(11, 8), + .vco_val = 0x1 << 21, + .vco_mask = GENMASK(21, 20), + .test_ctl_hi_mask = 0x1, +}; + +static struct clk_alpha_pll lpass_audio_cc_dig_pll = { + .offset = 0x3e8, + .vco_table = audiocc_dig_pll_vco, + .num_vco = ARRAY_SIZE(audiocc_dig_pll_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_dig_pll", + .parent_names = (const char *[]){ "bi_tcxo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + .vdd_class = &vdd_lpi_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_MIN] = 1000000000, + [VDD_NOMINAL] = 2000000000}, + }, + }, +}; + +static const struct clk_div_table post_div_table_audio_cc_dig_pll_out_aux[] = { + { 0x5, 5 }, + { } +}; + +static struct clk_alpha_pll_postdiv lpass_audio_cc_dig_pll_out_aux = { + .offset = 0x3e8, + .post_div_shift = 15, + .post_div_table = post_div_table_audio_cc_dig_pll_out_aux, + .num_post_div = ARRAY_SIZE(post_div_table_audio_cc_dig_pll_out_aux), + .width = 3, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_dig_pll_out_aux", + .parent_names = (const char *[]){ "lpass_audio_cc_dig_pll" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_ops, + }, +}; + +/* 1128.96 MHz Configuration */ +static const struct alpha_pll_config lpass_audio_cc_pll_config = { + .l = 0x3a, + .alpha = 0xcccccccc, + .alpha_hi = 0xcc, + .post_div_val = 0x1 << 8, + .post_div_mask = GENMASK(9, 8), + .config_ctl_val = 0x00004289, + .test_ctl_val = 0x08000000, + .main_output_mask = BIT(0), + .aux_output_mask = BIT(1), + .aux2_output_mask = BIT(2), + .early_output_mask = BIT(3), + .alpha_en_mask = BIT(24), + .test_ctl_mask = GENMASK(31, 0), +}; + +static struct clk_alpha_pll lpass_audio_cc_pll = { + .offset = 0x7d0, + .vco_table = audiocc_pll_vco, + .num_vco = ARRAY_SIZE(audiocc_pll_vco), + .regs = clk_alpha_pll_regs_offset[CLK_ALPHA_PLL_TYPE_BRAMMO], + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_pll", + .parent_names = (const char *[]){ "bi_tcxo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + .vdd_class = &vdd_lpi_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_LOWER] = 1250000000, + [VDD_LOW] = 1250000000, + [VDD_NOMINAL] = 1250000000}, + }, + }, +}; + +static const struct clk_div_table post_div_table_audio_cc_pll_out_aux[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv lpass_audio_cc_pll_out_aux = { + .offset = 0x7d0, + .post_div_shift = 8, + .post_div_table = post_div_table_audio_cc_pll_out_aux, + .num_post_div = ARRAY_SIZE(post_div_table_audio_cc_pll_out_aux), + .width = 2, + .regs = clk_alpha_pll_regs_offset[CLK_ALPHA_PLL_TYPE_BRAMMO], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_pll_out_aux", + .parent_names = (const char *[]){ "lpass_audio_cc_pll" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_ro_ops, + }, +}; + +static const struct clk_div_table post_div_table_audio_cc_pll_out_aux2[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv lpass_audio_cc_pll_out_aux2 = { + .offset = 0x7d0, + .post_div_shift = 8, + .post_div_table = post_div_table_audio_cc_pll_out_aux2, + .num_post_div = ARRAY_SIZE(post_div_table_audio_cc_pll_out_aux2), + .width = 2, + .regs = clk_alpha_pll_regs_offset[CLK_ALPHA_PLL_TYPE_BRAMMO], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_pll_out_aux2", + .parent_names = (const char *[]){ "lpass_audio_cc_pll" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_ro_ops, + }, +}; + +static struct clk_regmap_div lpass_audio_cc_cdiv_rx_mclk_div_clk_src = { + .reg = 0x240d0, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_cdiv_rx_mclk_div_clk_src", + .parent_names = (const char *[]) + { "lpass_audio_cc_rx_mclk_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div lpass_audio_cc_cdiv_wsa_mclk_div_clk_src = { + .reg = 0x220d0, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_cdiv_wsa_mclk_div_clk_src", + .parent_names = (const char *[]) + { "lpass_audio_cc_wsa_mclk_clk_src" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div lpass_audio_cc_pll_out_aux2_div_clk_src = { + .reg = 0x48, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_pll_out_aux2_div_clk_src", + .parent_names = (const char *[]) + { "lpass_audio_cc_pll_out_aux2" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static const struct freq_tbl ftbl_aud_slimbus_clk_src[] = { + F(6144000, P_LPASS_AUDIO_CC_DIG_PLL_OUT_AUX, 10, 1, 2), + F(12288000, P_LPASS_AUDIO_CC_DIG_PLL_OUT_AUX, 10, 0, 0), + F(24576000, P_LPASS_AUDIO_CC_DIG_PLL_OUT_AUX, 5, 0, 0), + { } +}; + +static struct clk_rcg2 aud_slimbus_clk_src = { + .cmd_rcgr = 0x17000, + .mnd_width = 8, + .hid_width = 5, + .parent_map = lpass_audio_cc_parent_map_1, + .freq_tbl = ftbl_aud_slimbus_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "aud_slimbus_clk_src", + .parent_names = lpass_audio_cc_parent_names_1, + .num_parents = ARRAY_SIZE(lpass_audio_cc_parent_names_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_lpi_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_MIN] = 24576000}, + }, +}; + +static const struct freq_tbl ftbl_lpass_audio_cc_ext_if1_clk_src[] = { + F(256000, P_LPASS_AON_CC_PLL_OUT_AUX, 15, 1, 32), + F(352800, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 1, 32), + F(512000, P_LPASS_AON_CC_PLL_OUT_AUX, 15, 1, 16), + F(705600, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 1, 16), + F(768000, P_LPASS_AON_CC_PLL_OUT_AUX, 10, 1, 16), + F(1024000, P_LPASS_AON_CC_PLL_OUT_AUX, 15, 1, 8), + F(1411200, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 1, 8), + F(1536000, P_LPASS_AON_CC_PLL_OUT_AUX, 10, 1, 8), + F(2048000, P_LPASS_AON_CC_PLL_OUT_AUX, 15, 1, 4), + F(2822400, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 1, 4), + F(3072000, P_LPASS_AON_CC_PLL_OUT_AUX, 10, 1, 4), + F(4096000, P_LPASS_AON_CC_PLL_OUT_AUX, 15, 1, 2), + F(5644800, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 1, 2), + F(6144000, P_LPASS_AON_CC_PLL_OUT_AUX, 10, 1, 2), + F(8192000, P_LPASS_AON_CC_PLL_OUT_AUX, 15, 0, 0), + F(9600000, P_BI_TCXO, 2, 0, 0), + F(11289600, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 0, 0), + F(12288000, P_LPASS_AON_CC_PLL_OUT_AUX, 10, 0, 0), + { } +}; + +static struct clk_rcg2 lpass_audio_cc_ext_if1_clk_src = { + .cmd_rcgr = 0x10004, + .mnd_width = 16, + .hid_width = 5, + .parent_map = lpass_audio_cc_parent_map_0, + .freq_tbl = ftbl_lpass_audio_cc_ext_if1_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_ext_if1_clk_src", + .parent_names = lpass_audio_cc_parent_names_0, + .num_parents = ARRAY_SIZE(lpass_audio_cc_parent_names_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_lpi_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_MIN] = 1536000, + [VDD_LOWER] = 3072000, + [VDD_LOW] = 6144000, + [VDD_NOMINAL] = 12288000}, + }, +}; + +static const struct freq_tbl ftbl_lpass_audio_cc_ext_if2_clk_src[] = { + F(256000, P_LPASS_AON_CC_PLL_OUT_AUX, 15, 1, 32), + F(352800, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 1, 32), + F(512000, P_LPASS_AON_CC_PLL_OUT_AUX, 15, 1, 16), + F(705600, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 1, 16), + F(768000, P_LPASS_AON_CC_PLL_OUT_AUX, 10, 1, 16), + F(1024000, P_LPASS_AON_CC_PLL_OUT_AUX, 15, 1, 8), + F(1411200, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 1, 8), + F(1536000, P_LPASS_AON_CC_PLL_OUT_AUX, 10, 1, 8), + F(2048000, P_LPASS_AON_CC_PLL_OUT_AUX, 15, 1, 4), + F(2822400, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 1, 4), + F(3072000, P_LPASS_AON_CC_PLL_OUT_AUX, 10, 1, 4), + F(4096000, P_LPASS_AON_CC_PLL_OUT_AUX, 15, 1, 2), + F(5644800, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 1, 2), + F(6144000, P_LPASS_AON_CC_PLL_OUT_AUX, 10, 1, 2), + F(8192000, P_LPASS_AON_CC_PLL_OUT_AUX, 15, 0, 0), + F(9600000, P_BI_TCXO, 2, 0, 0), + F(11289600, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 0, 0), + F(12288000, P_LPASS_AON_CC_PLL_OUT_AUX, 10, 0, 0), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(22579200, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 5, 0, 0), + F(24576000, P_LPASS_AON_CC_PLL_OUT_AUX, 5, 0, 0), + { } +}; + +static struct clk_rcg2 lpass_audio_cc_ext_if2_clk_src = { + .cmd_rcgr = 0x11004, + .mnd_width = 16, + .hid_width = 5, + .parent_map = lpass_audio_cc_parent_map_0, + .freq_tbl = ftbl_lpass_audio_cc_ext_if2_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_ext_if2_clk_src", + .parent_names = lpass_audio_cc_parent_names_0, + .num_parents = ARRAY_SIZE(lpass_audio_cc_parent_names_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_lpi_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_MIN] = 3072000, + [VDD_LOWER] = 6144000, + [VDD_LOW] = 12288000, + [VDD_NOMINAL] = 24576000}, + }, +}; + +static struct clk_rcg2 lpass_audio_cc_ext_if3_clk_src = { + .cmd_rcgr = 0x12004, + .mnd_width = 16, + .hid_width = 5, + .parent_map = lpass_audio_cc_parent_map_0, + .freq_tbl = ftbl_lpass_audio_cc_ext_if1_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_ext_if3_clk_src", + .parent_names = lpass_audio_cc_parent_names_0, + .num_parents = ARRAY_SIZE(lpass_audio_cc_parent_names_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_lpi_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_MIN] = 1536000, + [VDD_LOWER] = 3072000, + [VDD_LOW] = 6144000, + [VDD_NOMINAL] = 12288000}, + }, +}; + +static struct clk_rcg2 lpass_audio_cc_ext_if4_clk_src = { + .cmd_rcgr = 0x13008, + .mnd_width = 16, + .hid_width = 5, + .parent_map = lpass_audio_cc_parent_map_0, + .freq_tbl = ftbl_lpass_audio_cc_ext_if1_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_ext_if4_clk_src", + .parent_names = lpass_audio_cc_parent_names_0, + .num_parents = ARRAY_SIZE(lpass_audio_cc_parent_names_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_lpi_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_MIN] = 1536000, + [VDD_LOWER] = 3072000, + [VDD_LOW] = 6144000, + [VDD_NOMINAL] = 12288000}, + }, +}; + +static struct clk_rcg2 lpass_audio_cc_ext_mclk0_clk_src = { + .cmd_rcgr = 0x20004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = lpass_audio_cc_parent_map_0, + .freq_tbl = ftbl_lpass_audio_cc_ext_if2_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_ext_mclk0_clk_src", + .parent_names = lpass_audio_cc_parent_names_0, + .num_parents = ARRAY_SIZE(lpass_audio_cc_parent_names_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_lpi_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_MIN] = 24576000}, + }, +}; + +static struct clk_rcg2 lpass_audio_cc_ext_mclk1_clk_src = { + .cmd_rcgr = 0x21004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = lpass_audio_cc_parent_map_0, + .freq_tbl = ftbl_lpass_audio_cc_ext_if2_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_ext_mclk1_clk_src", + .parent_names = lpass_audio_cc_parent_names_0, + .num_parents = ARRAY_SIZE(lpass_audio_cc_parent_names_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_lpi_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_MIN] = 24576000}, + }, +}; + +static const struct freq_tbl ftbl_lpass_audio_cc_lpaif_pcmoe_clk_src[] = { + F(15360000, P_LPASS_AON_CC_PLL_OUT_AUX, 8, 0, 0), + F(30720000, P_LPASS_AON_CC_PLL_OUT_AUX, 4, 0, 0), + F(61440000, P_LPASS_AON_CC_PLL_OUT_AUX, 2, 0, 0), + F(122880000, P_LPASS_AON_CC_PLL_OUT_AUX, 1, 0, 0), + { } +}; + +static struct clk_rcg2 lpass_audio_cc_lpaif_pcmoe_clk_src = { + .cmd_rcgr = 0x19004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = lpass_audio_cc_parent_map_2, + .freq_tbl = ftbl_lpass_audio_cc_lpaif_pcmoe_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_lpaif_pcmoe_clk_src", + .parent_names = lpass_audio_cc_parent_names_2, + .num_parents = ARRAY_SIZE(lpass_audio_cc_parent_names_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_lpi_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_MIN] = 122880000}, + }, +}; + +static struct clk_rcg2 lpass_audio_cc_rx_mclk_clk_src = { + .cmd_rcgr = 0x24004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = lpass_audio_cc_parent_map_0, + .freq_tbl = ftbl_lpass_audio_cc_ext_if2_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_rx_mclk_clk_src", + .parent_names = lpass_audio_cc_parent_names_0, + .num_parents = ARRAY_SIZE(lpass_audio_cc_parent_names_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_lpi_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_MIN] = 24576000}, + }, +}; + +static struct clk_rcg2 lpass_audio_cc_wsa_mclk_clk_src = { + .cmd_rcgr = 0x22004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = lpass_audio_cc_parent_map_0, + .freq_tbl = ftbl_lpass_audio_cc_ext_if2_clk_src, + .enable_safe_config = true, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_wsa_mclk_clk_src", + .parent_names = lpass_audio_cc_parent_names_0, + .num_parents = ARRAY_SIZE(lpass_audio_cc_parent_names_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + .vdd_class = &vdd_lpi_cx, + .num_rate_max = VDD_NUM, + .rate_max = (unsigned long[VDD_NUM]) { + [VDD_MIN] = 24576000}, + }, +}; + +static struct clk_branch lpass_audio_cc_aud_slimbus_clk = { + .halt_reg = 0x17014, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x17014, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_aud_slimbus_clk", + .parent_names = (const char *[]){ + "aud_slimbus_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_aud_slimbus_core_clk = { + .halt_reg = 0x1e018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1e018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_aud_slimbus_core_clk", + .parent_names = (const char *[]){ + "lpass_aon_cc_main_rcg_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_aud_slimbus_npl_clk = { + .halt_reg = 0x1701c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x1701c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1701c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_aud_slimbus_npl_clk", + .parent_names = (const char *[]){ + "aud_slimbus_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_bus_clk = { + .halt_reg = 0x1f000, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x1f000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_bus_clk", + .parent_names = (const char *[]){ + "lpass_aon_cc_main_rcg_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_bus_timeout_clk = { + .halt_reg = 0x1e014, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1e014, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_bus_timeout_clk", + .parent_names = (const char *[]){ + "lpass_aon_cc_main_rcg_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_codec_mem0_clk = { + .halt_reg = 0x1e004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1e004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_codec_mem0_clk", + .parent_names = (const char *[]){ + "lpass_aon_cc_main_rcg_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_codec_mem1_clk = { + .halt_reg = 0x1e008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1e008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_codec_mem1_clk", + .parent_names = (const char *[]){ + "lpass_aon_cc_main_rcg_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_codec_mem2_clk = { + .halt_reg = 0x1e00c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1e00c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_codec_mem2_clk", + .parent_names = (const char *[]){ + "lpass_aon_cc_main_rcg_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_codec_mem3_clk = { + .halt_reg = 0x1e010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1e010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_codec_mem3_clk", + .parent_names = (const char *[]){ + "lpass_aon_cc_main_rcg_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_codec_mem_clk = { + .halt_reg = 0x1e000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1e000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_codec_mem_clk", + .parent_names = (const char *[]){ + "lpass_aon_cc_main_rcg_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_ext_if1_ebit_clk = { + .halt_reg = 0x10020, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10020, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_ext_if1_ebit_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_ext_if1_ibit_clk = { + .halt_reg = 0x1001c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1001c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_ext_if1_ibit_clk", + .parent_names = (const char *[]){ + "lpass_audio_cc_ext_if1_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_ext_if2_ebit_clk = { + .halt_reg = 0x11020, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11020, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_ext_if2_ebit_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_ext_if2_ibit_clk = { + .halt_reg = 0x1101c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1101c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_ext_if2_ibit_clk", + .parent_names = (const char *[]){ + "lpass_audio_cc_ext_if2_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_ext_if3_ebit_clk = { + .halt_reg = 0x12020, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12020, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_ext_if3_ebit_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_ext_if3_ibit_clk = { + .halt_reg = 0x1201c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1201c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_ext_if3_ibit_clk", + .parent_names = (const char *[]){ + "lpass_audio_cc_ext_if3_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_ext_if4_ebit_clk = { + .halt_reg = 0x13024, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13024, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_ext_if4_ebit_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_ext_if4_ibit_clk = { + .halt_reg = 0x13020, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13020, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_ext_if4_ibit_clk", + .parent_names = (const char *[]){ + "lpass_audio_cc_ext_if4_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_ext_mclk0_clk = { + .halt_reg = 0x20018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x20018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_ext_mclk0_clk", + .parent_names = (const char *[]){ + "lpass_audio_cc_ext_mclk0_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_ext_mclk1_clk = { + .halt_reg = 0x21018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x21018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_ext_mclk1_clk", + .parent_names = (const char *[]){ + "lpass_audio_cc_ext_mclk1_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_lpaif_pcmoe_clk = { + .halt_reg = 0x19018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x19018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_lpaif_pcmoe_clk", + .parent_names = (const char *[]){ + "lpass_audio_cc_lpaif_pcmoe_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_rx_mclk_2x_clk = { + .halt_reg = 0x240cc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x240cc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_rx_mclk_2x_clk", + .parent_names = (const char *[]){ + "lpass_audio_cc_rx_mclk_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_rx_mclk_clk = { + .halt_reg = 0x240d4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x240d4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_rx_mclk_clk", + .parent_names = (const char *[]){ + "lpass_audio_cc_cdiv_rx_mclk_div_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_sampling_clk = { + .halt_reg = 0x13000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_sampling_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_wsa_mclk_2x_clk = { + .halt_reg = 0x220cc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x220cc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_wsa_mclk_2x_clk", + .parent_names = (const char *[]){ + "lpass_audio_cc_wsa_mclk_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_wsa_mclk_clk = { + .halt_reg = 0x220d4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x220d4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_wsa_mclk_clk", + .parent_names = (const char *[]){ + "lpass_audio_cc_cdiv_wsa_mclk_div_clk_src", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_regmap *lpass_audio_cc_scuba_clocks[] = { + [AUD_SLIMBUS_CLK_SRC] = &aud_slimbus_clk_src.clkr, + [LPASS_AUDIO_CC_AUD_SLIMBUS_CLK] = &lpass_audio_cc_aud_slimbus_clk.clkr, + [LPASS_AUDIO_CC_AUD_SLIMBUS_CORE_CLK] = + &lpass_audio_cc_aud_slimbus_core_clk.clkr, + [LPASS_AUDIO_CC_AUD_SLIMBUS_NPL_CLK] = + &lpass_audio_cc_aud_slimbus_npl_clk.clkr, + [LPASS_AUDIO_CC_BUS_CLK] = &lpass_audio_cc_bus_clk.clkr, + [LPASS_AUDIO_CC_BUS_TIMEOUT_CLK] = &lpass_audio_cc_bus_timeout_clk.clkr, + [LPASS_AUDIO_CC_CDIV_RX_MCLK_DIV_CLK_SRC] = + &lpass_audio_cc_cdiv_rx_mclk_div_clk_src.clkr, + [LPASS_AUDIO_CC_CDIV_WSA_MCLK_DIV_CLK_SRC] = + &lpass_audio_cc_cdiv_wsa_mclk_div_clk_src.clkr, + [LPASS_AUDIO_CC_CODEC_MEM0_CLK] = &lpass_audio_cc_codec_mem0_clk.clkr, + [LPASS_AUDIO_CC_CODEC_MEM1_CLK] = &lpass_audio_cc_codec_mem1_clk.clkr, + [LPASS_AUDIO_CC_CODEC_MEM2_CLK] = &lpass_audio_cc_codec_mem2_clk.clkr, + [LPASS_AUDIO_CC_CODEC_MEM3_CLK] = &lpass_audio_cc_codec_mem3_clk.clkr, + [LPASS_AUDIO_CC_CODEC_MEM_CLK] = &lpass_audio_cc_codec_mem_clk.clkr, + [LPASS_AUDIO_CC_DIG_PLL] = &lpass_audio_cc_dig_pll.clkr, + [LPASS_AUDIO_CC_DIG_PLL_OUT_AUX] = &lpass_audio_cc_dig_pll_out_aux.clkr, + [LPASS_AUDIO_CC_EXT_IF1_CLK_SRC] = &lpass_audio_cc_ext_if1_clk_src.clkr, + [LPASS_AUDIO_CC_EXT_IF1_EBIT_CLK] = + &lpass_audio_cc_ext_if1_ebit_clk.clkr, + [LPASS_AUDIO_CC_EXT_IF1_IBIT_CLK] = + &lpass_audio_cc_ext_if1_ibit_clk.clkr, + [LPASS_AUDIO_CC_EXT_IF2_CLK_SRC] = &lpass_audio_cc_ext_if2_clk_src.clkr, + [LPASS_AUDIO_CC_EXT_IF2_EBIT_CLK] = + &lpass_audio_cc_ext_if2_ebit_clk.clkr, + [LPASS_AUDIO_CC_EXT_IF2_IBIT_CLK] = + &lpass_audio_cc_ext_if2_ibit_clk.clkr, + [LPASS_AUDIO_CC_EXT_IF3_CLK_SRC] = &lpass_audio_cc_ext_if3_clk_src.clkr, + [LPASS_AUDIO_CC_EXT_IF3_EBIT_CLK] = + &lpass_audio_cc_ext_if3_ebit_clk.clkr, + [LPASS_AUDIO_CC_EXT_IF3_IBIT_CLK] = + &lpass_audio_cc_ext_if3_ibit_clk.clkr, + [LPASS_AUDIO_CC_EXT_IF4_CLK_SRC] = &lpass_audio_cc_ext_if4_clk_src.clkr, + [LPASS_AUDIO_CC_EXT_IF4_EBIT_CLK] = + &lpass_audio_cc_ext_if4_ebit_clk.clkr, + [LPASS_AUDIO_CC_EXT_IF4_IBIT_CLK] = + &lpass_audio_cc_ext_if4_ibit_clk.clkr, + [LPASS_AUDIO_CC_EXT_MCLK0_CLK] = &lpass_audio_cc_ext_mclk0_clk.clkr, + [LPASS_AUDIO_CC_EXT_MCLK0_CLK_SRC] = + &lpass_audio_cc_ext_mclk0_clk_src.clkr, + [LPASS_AUDIO_CC_EXT_MCLK1_CLK] = &lpass_audio_cc_ext_mclk1_clk.clkr, + [LPASS_AUDIO_CC_EXT_MCLK1_CLK_SRC] = + &lpass_audio_cc_ext_mclk1_clk_src.clkr, + [LPASS_AUDIO_CC_LPAIF_PCMOE_CLK] = &lpass_audio_cc_lpaif_pcmoe_clk.clkr, + [LPASS_AUDIO_CC_LPAIF_PCMOE_CLK_SRC] = + &lpass_audio_cc_lpaif_pcmoe_clk_src.clkr, + [LPASS_AUDIO_CC_PLL] = &lpass_audio_cc_pll.clkr, + [LPASS_AUDIO_CC_PLL_OUT_AUX] = &lpass_audio_cc_pll_out_aux.clkr, + [LPASS_AUDIO_CC_PLL_OUT_AUX2] = &lpass_audio_cc_pll_out_aux2.clkr, + [LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC] = + &lpass_audio_cc_pll_out_aux2_div_clk_src.clkr, + [LPASS_AUDIO_CC_RX_MCLK_2X_CLK] = &lpass_audio_cc_rx_mclk_2x_clk.clkr, + [LPASS_AUDIO_CC_RX_MCLK_CLK] = &lpass_audio_cc_rx_mclk_clk.clkr, + [LPASS_AUDIO_CC_RX_MCLK_CLK_SRC] = &lpass_audio_cc_rx_mclk_clk_src.clkr, + [LPASS_AUDIO_CC_SAMPLING_CLK] = &lpass_audio_cc_sampling_clk.clkr, + [LPASS_AUDIO_CC_WSA_MCLK_2X_CLK] = &lpass_audio_cc_wsa_mclk_2x_clk.clkr, + [LPASS_AUDIO_CC_WSA_MCLK_CLK] = &lpass_audio_cc_wsa_mclk_clk.clkr, + [LPASS_AUDIO_CC_WSA_MCLK_CLK_SRC] = + &lpass_audio_cc_wsa_mclk_clk_src.clkr, +}; + +static const struct qcom_reset_map lpass_audio_cc_scuba_resets[] = { + [LPASS_AUDIO_CC_EXT_IF1_BCR] = { 0x10000 }, + [LPASS_AUDIO_CC_EXT_IF2_BCR] = { 0x11000 }, + [LPASS_AUDIO_CC_EXT_IF3_BCR] = { 0x12000 }, + [LPASS_AUDIO_CC_EXT_IF4_BCR] = { 0x13004 }, + [LPASS_AUDIO_CC_EXT_MCLK0_BCR] = { 0x20000 }, + [LPASS_AUDIO_CC_EXT_MCLK1_BCR] = { 0x21000 }, + [LPASS_AUDIO_CC_PCM_DATA_OE_BCR] = { 0x19000 }, + [LPASS_AUDIO_CC_QCA_SLIMBUS_BCR] = { 0x16ffc }, + [LPASS_AUDIO_CC_RX_MCLK_BCR] = { 0x24000 }, + [LPASS_AUDIO_CC_TX_MCLK_BCR] = { 0x23000 }, + [LPASS_AUDIO_CC_WSA_MCLK_BCR] = { 0x22000 }, +}; + +static const struct regmap_config lpass_audio_cc_scuba_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x2f100, + .fast_io = true, +}; + +static const struct qcom_cc_desc lpass_audio_cc_scuba_desc = { + .config = &lpass_audio_cc_scuba_regmap_config, + .clks = lpass_audio_cc_scuba_clocks, + .num_clks = ARRAY_SIZE(lpass_audio_cc_scuba_clocks), + .resets = lpass_audio_cc_scuba_resets, + .num_resets = ARRAY_SIZE(lpass_audio_cc_scuba_resets), +}; + +static const struct of_device_id lpass_audio_cc_scuba_match_table[] = { + { .compatible = "qcom,lpassaudiocc-scuba" }, + { } +}; +MODULE_DEVICE_TABLE(of, lpass_audio_cc_scuba_match_table); + +static int lpass_audio_cc_scuba_probe(struct platform_device *pdev) +{ + static struct regulator *audio_hm_regulator; + struct regmap *regmap; + int ret; + + vdd_lpi_cx.regulator[0] = devm_regulator_get(&pdev->dev, "vdd_lpi_cx"); + if (IS_ERR(vdd_lpi_cx.regulator[0])) { + if (PTR_ERR(vdd_lpi_cx.regulator[0]) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Unable to get vdd_lpi_cx\n"); + return PTR_ERR(vdd_lpi_cx.regulator[0]); + } + + audio_hm_regulator = devm_regulator_get(&pdev->dev, "audio_hm"); + if (IS_ERR(audio_hm_regulator)) { + if (PTR_ERR(audio_hm_regulator) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Unable to get audio_hm regulator\n"); + return PTR_ERR(audio_hm_regulator); + } + + platform_set_drvdata(pdev, audio_hm_regulator); + + pm_runtime_enable(&pdev->dev); + + /* Get the GCC LPASS Sway clock */ + ret = pm_clk_create(&pdev->dev); + if (ret) + return ret; + + ret = pm_clk_add(&pdev->dev, "iface_clk"); + if (ret < 0) { + dev_err(&pdev->dev, "failed to acquire gcc sway clock\n"); + goto err_destroy_pm_clk; + } + + ret = pm_runtime_get_sync(&pdev->dev); + if (ret) + goto err_destroy_pm_clk; + + regmap = qcom_cc_map(pdev, &lpass_audio_cc_scuba_desc); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + goto err_put_rpm; + } + + clk_alpha_pll_configure(&lpass_audio_cc_dig_pll, regmap, + &lpass_audio_cc_dig_pll_config); + clk_alpha_pll_configure(&lpass_audio_cc_pll, regmap, + &lpass_audio_cc_pll_config); + + ret = qcom_cc_really_probe(pdev, &lpass_audio_cc_scuba_desc, regmap); + if (ret) { + dev_err(&pdev->dev, "Audio clocks Register fail ret=%d\n", ret); + goto err_put_rpm; + } + + pm_runtime_put_sync(&pdev->dev); + dev_info(&pdev->dev, "Registered LPASS Audio clocks\n"); + return 0; + +err_put_rpm: + pm_runtime_put_sync(&pdev->dev); +err_destroy_pm_clk: + pm_clk_destroy(&pdev->dev); + return ret; +} + +static int lpass_audio_cc_scuba_runtime_resume(struct device *dev) +{ + int ret; + struct regulator *audio_hm_regulator = dev_get_drvdata(dev); + + ret = pm_clk_resume(dev); + if (ret) { + dev_err(dev, "Lpass Audio enabling GCC sway clock failed\n"); + return ret; + } + + return regulator_enable(audio_hm_regulator); +} + +static int lpass_audio_cc_scuba_runtime_suspend(struct device *dev) +{ + struct regulator *audio_hm_regulator = dev_get_drvdata(dev); + + regulator_disable(audio_hm_regulator); + return pm_clk_suspend(dev); +} + +static const struct dev_pm_ops lpass_audio_cc_scuba_pm_ops = { + SET_RUNTIME_PM_OPS(lpass_audio_cc_scuba_runtime_suspend, + lpass_audio_cc_scuba_runtime_resume, NULL) +}; + +static struct platform_driver lpass_audio_cc_scuba_driver = { + .probe = lpass_audio_cc_scuba_probe, + .driver = { + .name = "lpassaudiocc-scuba", + .of_match_table = lpass_audio_cc_scuba_match_table, + .pm = &lpass_audio_cc_scuba_pm_ops, + }, +}; + +static int __init lpass_audio_cc_scuba_init(void) +{ + return platform_driver_register(&lpass_audio_cc_scuba_driver); +} +subsys_initcall(lpass_audio_cc_scuba_init); + +static void __exit lpass_audio_cc_scuba_exit(void) +{ + platform_driver_unregister(&lpass_audio_cc_scuba_driver); +} +module_exit(lpass_audio_cc_scuba_exit); + +MODULE_DESCRIPTION("QTI LPASSAUDIOCC SCUBA Driver"); +MODULE_LICENSE("GPL v2"); From c29b6939006bec2e9c24fc22e74159e415b12652 Mon Sep 17 00:00:00 2001 From: Gao Wang Date: Mon, 23 Dec 2024 02:22:07 -0800 Subject: [PATCH 5/8] msm: npu: Fix use after free issue There is possibility that network will be used after free. This change is to fix this issue. Change-Id: I39aa81ddc4a7d1801b2f7157aa21f0051ff2d5a5 Signed-off-by: Gao Wang --- drivers/media/platform/msm/npu/npu_mgr.c | 16 ++++++++++++++++ drivers/media/platform/msm/npu/npu_mgr.h | 2 ++ 2 files changed, 18 insertions(+) diff --git a/drivers/media/platform/msm/npu/npu_mgr.c b/drivers/media/platform/msm/npu/npu_mgr.c index c2f9379dd314..a88089e25fc2 100644 --- a/drivers/media/platform/msm/npu/npu_mgr.c +++ b/drivers/media/platform/msm/npu/npu_mgr.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. */ /* ------------------------------------------------------------------------- @@ -2544,6 +2545,13 @@ int32_t npu_host_unload_network(struct npu_client *client, return -EINVAL; } + if (network->is_executing) { + pr_err("network is in execution\n"); + network_put(network); + mutex_unlock(&host_ctx->lock); + return -EINVAL; + } + if (network->fw_error) { NPU_ERR("fw in error state, skip unload network in fw\n"); goto free_network; @@ -2707,6 +2715,12 @@ int32_t npu_host_exec_network_v2(struct npu_client *client, goto exec_v2_done; } + if (network->is_executing) { + pr_err("network is already in execution\n"); + ret = -EINVAL; + goto exec_v2_done; + } + if (host_ctx->dev_shuttingdown) { NPU_ERR("device is shutting down\n"); ret = -EIO; @@ -2724,6 +2738,7 @@ int32_t npu_host_exec_network_v2(struct npu_client *client, goto exec_v2_done; } + network->is_executing = true; for (i = 0; i < num_patch_params; i++) { exec_packet->patch_params[i].id = patch_buf_info[i].buf_id; NPU_DBG("%d: patch_id: %x\n", i, @@ -2833,6 +2848,7 @@ int32_t npu_host_exec_network_v2(struct npu_client *client, npu_free_network_cmd(host_ctx, exec_cmd); free_exec_packet: kfree(exec_packet); + network->is_executing = false; exec_v2_done: network_put(network); mutex_unlock(&host_ctx->lock); diff --git a/drivers/media/platform/msm/npu/npu_mgr.h b/drivers/media/platform/msm/npu/npu_mgr.h index 69e9bbcad251..472b5e17a551 100644 --- a/drivers/media/platform/msm/npu/npu_mgr.h +++ b/drivers/media/platform/msm/npu/npu_mgr.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _NPU_MGR_H @@ -85,6 +86,7 @@ struct npu_network { bool is_valid; bool is_active; bool is_unloading; + bool is_executing; bool fw_error; struct npu_client *client; struct list_head cmd_list; From b9426ee6207047a2b9793b318aaad4d39cb18ca5 Mon Sep 17 00:00:00 2001 From: Gao Wang Date: Mon, 23 Dec 2024 02:22:07 -0800 Subject: [PATCH 6/8] msm: npu: Fix use after free issue There is possibility that network will be used after free. This change is to fix this issue. Change-Id: I39aa81ddc4a7d1801b2f7157aa21f0051ff2d5a5 Signed-off-by: Gao Wang (cherry picked from commit c29b6939006bec2e9c24fc22e74159e415b12652) --- drivers/media/platform/msm/npu/npu_mgr.c | 16 ++++++++++++++++ drivers/media/platform/msm/npu/npu_mgr.h | 2 ++ 2 files changed, 18 insertions(+) diff --git a/drivers/media/platform/msm/npu/npu_mgr.c b/drivers/media/platform/msm/npu/npu_mgr.c index c2f9379dd314..a88089e25fc2 100644 --- a/drivers/media/platform/msm/npu/npu_mgr.c +++ b/drivers/media/platform/msm/npu/npu_mgr.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. */ /* ------------------------------------------------------------------------- @@ -2544,6 +2545,13 @@ int32_t npu_host_unload_network(struct npu_client *client, return -EINVAL; } + if (network->is_executing) { + pr_err("network is in execution\n"); + network_put(network); + mutex_unlock(&host_ctx->lock); + return -EINVAL; + } + if (network->fw_error) { NPU_ERR("fw in error state, skip unload network in fw\n"); goto free_network; @@ -2707,6 +2715,12 @@ int32_t npu_host_exec_network_v2(struct npu_client *client, goto exec_v2_done; } + if (network->is_executing) { + pr_err("network is already in execution\n"); + ret = -EINVAL; + goto exec_v2_done; + } + if (host_ctx->dev_shuttingdown) { NPU_ERR("device is shutting down\n"); ret = -EIO; @@ -2724,6 +2738,7 @@ int32_t npu_host_exec_network_v2(struct npu_client *client, goto exec_v2_done; } + network->is_executing = true; for (i = 0; i < num_patch_params; i++) { exec_packet->patch_params[i].id = patch_buf_info[i].buf_id; NPU_DBG("%d: patch_id: %x\n", i, @@ -2833,6 +2848,7 @@ int32_t npu_host_exec_network_v2(struct npu_client *client, npu_free_network_cmd(host_ctx, exec_cmd); free_exec_packet: kfree(exec_packet); + network->is_executing = false; exec_v2_done: network_put(network); mutex_unlock(&host_ctx->lock); diff --git a/drivers/media/platform/msm/npu/npu_mgr.h b/drivers/media/platform/msm/npu/npu_mgr.h index 69e9bbcad251..472b5e17a551 100644 --- a/drivers/media/platform/msm/npu/npu_mgr.h +++ b/drivers/media/platform/msm/npu/npu_mgr.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _NPU_MGR_H @@ -85,6 +86,7 @@ struct npu_network { bool is_valid; bool is_active; bool is_unloading; + bool is_executing; bool fw_error; struct npu_client *client; struct list_head cmd_list; From 1f0408fc9dc4e2947998337c315647ab5244877a Mon Sep 17 00:00:00 2001 From: Abhinav Parihar Date: Mon, 30 Dec 2024 14:48:16 +0530 Subject: [PATCH 7/8] msm: adsprpc: Avoid double free on map Decrement and check the ref count of map inside the lock. Otherwise, two threads may free the same map. Change-Id: I081b937bfd3e8da3e2480f062cad6966662994b5 Acked-by: Sharad Kumar Signed-off-by: Abhinav Parihar --- drivers/char/adsprpc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 0355847f68b0..8bc094fd2d80 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -900,9 +900,11 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags) map->refs--; if (!map->refs) hlist_del_init(&map->hn); - spin_unlock(&me->hlock); - if (map->refs > 0) + if (map->refs > 0) { + spin_unlock(&me->hlock); return; + } + spin_unlock(&me->hlock); } else { if (map->refs) map->refs--; From 52996a0685fb17a24263f3d2a435c09e4776229e Mon Sep 17 00:00:00 2001 From: Gopireddy Arunteja Reddy Date: Mon, 27 Jan 2025 16:25:31 +0530 Subject: [PATCH 8/8] msm: eva: Copy back the validated size to avoid security issue As we are reading the packet from a shared queue, there is a possibility to corrupt the packet->size data of shared queue by malicious FW after validating it in the kernel driver. Change-Id: I3aae85dea560e2805e7bff2c48d4be763da597de Signed-off-by: Gopireddy Arunteja Reddy --- drivers/media/platform/msm/cvp/cvp_hfi.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/cvp/cvp_hfi.c b/drivers/media/platform/msm/cvp/cvp_hfi.c index 549249695b46..1f2fb953c0c4 100644 --- a/drivers/media/platform/msm/cvp/cvp_hfi.c +++ b/drivers/media/platform/msm/cvp/cvp_hfi.c @@ -781,7 +781,7 @@ static int __read_queue(struct cvp_iface_q_info *qinfo, u8 *packet, u32 *read_ptr; u32 receive_request = 0; u32 read_idx, write_idx; - int rc = 0; + int rc = 0; if (!qinfo || !packet || !pb_tx_req_is_set) { dprintk(CVP_ERR, "Invalid Params\n"); @@ -871,6 +871,12 @@ static int __read_queue(struct cvp_iface_q_info *qinfo, u8 *packet, (u8 *)qinfo->q_array.align_virtual_addr, new_read_idx << 2); } + /* + * Copy back the validated size to avoid security issue. As we are reading + * the packet from a shared queue, there is a possibility to get the + * packet->size data corrupted of shared queue by mallicious FW. + */ + *((u32 *) packet) = packet_size_in_words << 2; } else { dprintk(CVP_WARN, "BAD packet received, read_idx: %#x, pkt_size: %d\n",