162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2018, The Linux Foundation. All rights reserved. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/clk-provider.h> 762306a36Sopenharmony_ci#include <linux/platform_device.h> 862306a36Sopenharmony_ci#include <linux/module.h> 962306a36Sopenharmony_ci#include <linux/of_address.h> 1062306a36Sopenharmony_ci#include <linux/regmap.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <dt-bindings/clock/qcom,lpass-sdm845.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include "clk-regmap.h" 1562306a36Sopenharmony_ci#include "clk-branch.h" 1662306a36Sopenharmony_ci#include "common.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistatic struct clk_branch lpass_q6ss_ahbm_aon_clk = { 1962306a36Sopenharmony_ci .halt_reg = 0x12000, 2062306a36Sopenharmony_ci .halt_check = BRANCH_VOTED, 2162306a36Sopenharmony_ci .clkr = { 2262306a36Sopenharmony_ci .enable_reg = 0x12000, 2362306a36Sopenharmony_ci .enable_mask = BIT(0), 2462306a36Sopenharmony_ci .hw.init = &(struct clk_init_data){ 2562306a36Sopenharmony_ci .name = "lpass_q6ss_ahbm_aon_clk", 2662306a36Sopenharmony_ci .ops = &clk_branch2_ops, 2762306a36Sopenharmony_ci }, 2862306a36Sopenharmony_ci }, 2962306a36Sopenharmony_ci}; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cistatic struct clk_branch lpass_q6ss_ahbs_aon_clk = { 3262306a36Sopenharmony_ci .halt_reg = 0x1f000, 3362306a36Sopenharmony_ci .halt_check = BRANCH_VOTED, 3462306a36Sopenharmony_ci .clkr = { 3562306a36Sopenharmony_ci .enable_reg = 0x1f000, 3662306a36Sopenharmony_ci .enable_mask = BIT(0), 3762306a36Sopenharmony_ci .hw.init = &(struct clk_init_data){ 3862306a36Sopenharmony_ci .name = "lpass_q6ss_ahbs_aon_clk", 3962306a36Sopenharmony_ci .ops = &clk_branch2_ops, 4062306a36Sopenharmony_ci }, 4162306a36Sopenharmony_ci }, 4262306a36Sopenharmony_ci}; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic struct clk_branch lpass_qdsp6ss_core_clk = { 4562306a36Sopenharmony_ci .halt_reg = 0x20, 4662306a36Sopenharmony_ci /* CLK_OFF would not toggle until LPASS is out of reset */ 4762306a36Sopenharmony_ci .halt_check = BRANCH_HALT_SKIP, 4862306a36Sopenharmony_ci .clkr = { 4962306a36Sopenharmony_ci .enable_reg = 0x20, 5062306a36Sopenharmony_ci .enable_mask = BIT(0), 5162306a36Sopenharmony_ci .hw.init = &(struct clk_init_data){ 5262306a36Sopenharmony_ci .name = "lpass_qdsp6ss_core_clk", 5362306a36Sopenharmony_ci .ops = &clk_branch2_ops, 5462306a36Sopenharmony_ci }, 5562306a36Sopenharmony_ci }, 5662306a36Sopenharmony_ci}; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistatic struct clk_branch lpass_qdsp6ss_xo_clk = { 5962306a36Sopenharmony_ci .halt_reg = 0x38, 6062306a36Sopenharmony_ci /* CLK_OFF would not toggle until LPASS is out of reset */ 6162306a36Sopenharmony_ci .halt_check = BRANCH_HALT_SKIP, 6262306a36Sopenharmony_ci .clkr = { 6362306a36Sopenharmony_ci .enable_reg = 0x38, 6462306a36Sopenharmony_ci .enable_mask = BIT(0), 6562306a36Sopenharmony_ci .hw.init = &(struct clk_init_data){ 6662306a36Sopenharmony_ci .name = "lpass_qdsp6ss_xo_clk", 6762306a36Sopenharmony_ci .ops = &clk_branch2_ops, 6862306a36Sopenharmony_ci }, 6962306a36Sopenharmony_ci }, 7062306a36Sopenharmony_ci}; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_cistatic struct clk_branch lpass_qdsp6ss_sleep_clk = { 7362306a36Sopenharmony_ci .halt_reg = 0x3c, 7462306a36Sopenharmony_ci /* CLK_OFF would not toggle until LPASS is out of reset */ 7562306a36Sopenharmony_ci .halt_check = BRANCH_HALT_SKIP, 7662306a36Sopenharmony_ci .clkr = { 7762306a36Sopenharmony_ci .enable_reg = 0x3c, 7862306a36Sopenharmony_ci .enable_mask = BIT(0), 7962306a36Sopenharmony_ci .hw.init = &(struct clk_init_data){ 8062306a36Sopenharmony_ci .name = "lpass_qdsp6ss_sleep_clk", 8162306a36Sopenharmony_ci .ops = &clk_branch2_ops, 8262306a36Sopenharmony_ci }, 8362306a36Sopenharmony_ci }, 8462306a36Sopenharmony_ci}; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistatic struct regmap_config lpass_regmap_config = { 8762306a36Sopenharmony_ci .reg_bits = 32, 8862306a36Sopenharmony_ci .reg_stride = 4, 8962306a36Sopenharmony_ci .val_bits = 32, 9062306a36Sopenharmony_ci .fast_io = true, 9162306a36Sopenharmony_ci}; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistatic struct clk_regmap *lpass_cc_sdm845_clocks[] = { 9462306a36Sopenharmony_ci [LPASS_Q6SS_AHBM_AON_CLK] = &lpass_q6ss_ahbm_aon_clk.clkr, 9562306a36Sopenharmony_ci [LPASS_Q6SS_AHBS_AON_CLK] = &lpass_q6ss_ahbs_aon_clk.clkr, 9662306a36Sopenharmony_ci}; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_cistatic const struct qcom_cc_desc lpass_cc_sdm845_desc = { 9962306a36Sopenharmony_ci .config = &lpass_regmap_config, 10062306a36Sopenharmony_ci .clks = lpass_cc_sdm845_clocks, 10162306a36Sopenharmony_ci .num_clks = ARRAY_SIZE(lpass_cc_sdm845_clocks), 10262306a36Sopenharmony_ci}; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic struct clk_regmap *lpass_qdsp6ss_sdm845_clocks[] = { 10562306a36Sopenharmony_ci [LPASS_QDSP6SS_XO_CLK] = &lpass_qdsp6ss_xo_clk.clkr, 10662306a36Sopenharmony_ci [LPASS_QDSP6SS_SLEEP_CLK] = &lpass_qdsp6ss_sleep_clk.clkr, 10762306a36Sopenharmony_ci [LPASS_QDSP6SS_CORE_CLK] = &lpass_qdsp6ss_core_clk.clkr, 10862306a36Sopenharmony_ci}; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistatic const struct qcom_cc_desc lpass_qdsp6ss_sdm845_desc = { 11162306a36Sopenharmony_ci .config = &lpass_regmap_config, 11262306a36Sopenharmony_ci .clks = lpass_qdsp6ss_sdm845_clocks, 11362306a36Sopenharmony_ci .num_clks = ARRAY_SIZE(lpass_qdsp6ss_sdm845_clocks), 11462306a36Sopenharmony_ci}; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_cistatic int lpass_cc_sdm845_probe(struct platform_device *pdev) 11762306a36Sopenharmony_ci{ 11862306a36Sopenharmony_ci const struct qcom_cc_desc *desc; 11962306a36Sopenharmony_ci int ret; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci lpass_regmap_config.name = "cc"; 12262306a36Sopenharmony_ci desc = &lpass_cc_sdm845_desc; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci ret = qcom_cc_probe_by_index(pdev, 0, desc); 12562306a36Sopenharmony_ci if (ret) 12662306a36Sopenharmony_ci return ret; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci lpass_regmap_config.name = "qdsp6ss"; 12962306a36Sopenharmony_ci desc = &lpass_qdsp6ss_sdm845_desc; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci return qcom_cc_probe_by_index(pdev, 1, desc); 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cistatic const struct of_device_id lpass_cc_sdm845_match_table[] = { 13562306a36Sopenharmony_ci { .compatible = "qcom,sdm845-lpasscc" }, 13662306a36Sopenharmony_ci { } 13762306a36Sopenharmony_ci}; 13862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, lpass_cc_sdm845_match_table); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cistatic struct platform_driver lpass_cc_sdm845_driver = { 14162306a36Sopenharmony_ci .probe = lpass_cc_sdm845_probe, 14262306a36Sopenharmony_ci .driver = { 14362306a36Sopenharmony_ci .name = "sdm845-lpasscc", 14462306a36Sopenharmony_ci .of_match_table = lpass_cc_sdm845_match_table, 14562306a36Sopenharmony_ci }, 14662306a36Sopenharmony_ci}; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_cistatic int __init lpass_cc_sdm845_init(void) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci return platform_driver_register(&lpass_cc_sdm845_driver); 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_cisubsys_initcall(lpass_cc_sdm845_init); 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_cistatic void __exit lpass_cc_sdm845_exit(void) 15562306a36Sopenharmony_ci{ 15662306a36Sopenharmony_ci platform_driver_unregister(&lpass_cc_sdm845_driver); 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_cimodule_exit(lpass_cc_sdm845_exit); 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ciMODULE_DESCRIPTION("QTI LPASS_CC SDM845 Driver"); 16162306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 162