16cdef273SGovind Singh // SPDX-License-Identifier: GPL-2.0 26cdef273SGovind Singh /* 36cdef273SGovind Singh * Copyright (c) 2018, The Linux Foundation. All rights reserved. 46cdef273SGovind Singh */ 56cdef273SGovind Singh 66cdef273SGovind Singh #include <linux/bitops.h> 76cdef273SGovind Singh #include <linux/err.h> 86cdef273SGovind Singh #include <linux/module.h> 96cdef273SGovind Singh #include <linux/platform_device.h> 106cdef273SGovind Singh #include <linux/pm_clock.h> 116cdef273SGovind Singh #include <linux/pm_runtime.h> 126cdef273SGovind Singh #include <linux/regmap.h> 136cdef273SGovind Singh 146cdef273SGovind Singh #include <dt-bindings/clock/qcom,q6sstopcc-qcs404.h> 156cdef273SGovind Singh 166cdef273SGovind Singh #include "clk-regmap.h" 176cdef273SGovind Singh #include "clk-branch.h" 186cdef273SGovind Singh #include "common.h" 196cdef273SGovind Singh #include "reset.h" 206cdef273SGovind Singh 216cdef273SGovind Singh static struct clk_branch lcc_ahbfabric_cbc_clk = { 226cdef273SGovind Singh .halt_reg = 0x1b004, 236cdef273SGovind Singh .halt_check = BRANCH_HALT, 246cdef273SGovind Singh .clkr = { 256cdef273SGovind Singh .enable_reg = 0x1b004, 266cdef273SGovind Singh .enable_mask = BIT(0), 276cdef273SGovind Singh .hw.init = &(struct clk_init_data){ 286cdef273SGovind Singh .name = "lcc_ahbfabric_cbc_clk", 296cdef273SGovind Singh .ops = &clk_branch2_ops, 306cdef273SGovind Singh }, 316cdef273SGovind Singh }, 326cdef273SGovind Singh }; 336cdef273SGovind Singh 346cdef273SGovind Singh static struct clk_branch lcc_q6ss_ahbs_cbc_clk = { 356cdef273SGovind Singh .halt_reg = 0x22000, 366cdef273SGovind Singh .halt_check = BRANCH_VOTED, 376cdef273SGovind Singh .clkr = { 386cdef273SGovind Singh .enable_reg = 0x22000, 396cdef273SGovind Singh .enable_mask = BIT(0), 406cdef273SGovind Singh .hw.init = &(struct clk_init_data){ 416cdef273SGovind Singh .name = "lcc_q6ss_ahbs_cbc_clk", 426cdef273SGovind Singh .ops = &clk_branch2_ops, 436cdef273SGovind Singh }, 446cdef273SGovind Singh }, 456cdef273SGovind Singh }; 466cdef273SGovind Singh 476cdef273SGovind Singh static struct clk_branch lcc_q6ss_tcm_slave_cbc_clk = { 486cdef273SGovind Singh .halt_reg = 0x1c000, 496cdef273SGovind Singh .halt_check = BRANCH_VOTED, 506cdef273SGovind Singh .clkr = { 516cdef273SGovind Singh .enable_reg = 0x1c000, 526cdef273SGovind Singh .enable_mask = BIT(0), 536cdef273SGovind Singh .hw.init = &(struct clk_init_data){ 546cdef273SGovind Singh .name = "lcc_q6ss_tcm_slave_cbc_clk", 556cdef273SGovind Singh .ops = &clk_branch2_ops, 566cdef273SGovind Singh }, 576cdef273SGovind Singh }, 586cdef273SGovind Singh }; 596cdef273SGovind Singh 606cdef273SGovind Singh static struct clk_branch lcc_q6ss_ahbm_cbc_clk = { 616cdef273SGovind Singh .halt_reg = 0x22004, 626cdef273SGovind Singh .halt_check = BRANCH_VOTED, 636cdef273SGovind Singh .clkr = { 646cdef273SGovind Singh .enable_reg = 0x22004, 656cdef273SGovind Singh .enable_mask = BIT(0), 666cdef273SGovind Singh .hw.init = &(struct clk_init_data){ 676cdef273SGovind Singh .name = "lcc_q6ss_ahbm_cbc_clk", 686cdef273SGovind Singh .ops = &clk_branch2_ops, 696cdef273SGovind Singh }, 706cdef273SGovind Singh }, 716cdef273SGovind Singh }; 726cdef273SGovind Singh 736cdef273SGovind Singh static struct clk_branch lcc_q6ss_axim_cbc_clk = { 746cdef273SGovind Singh .halt_reg = 0x1c004, 756cdef273SGovind Singh .halt_check = BRANCH_VOTED, 766cdef273SGovind Singh .clkr = { 776cdef273SGovind Singh .enable_reg = 0x1c004, 786cdef273SGovind Singh .enable_mask = BIT(0), 796cdef273SGovind Singh .hw.init = &(struct clk_init_data){ 806cdef273SGovind Singh .name = "lcc_q6ss_axim_cbc_clk", 816cdef273SGovind Singh .ops = &clk_branch2_ops, 826cdef273SGovind Singh }, 836cdef273SGovind Singh }, 846cdef273SGovind Singh }; 856cdef273SGovind Singh 866cdef273SGovind Singh static struct clk_branch lcc_q6ss_bcr_sleep_clk = { 876cdef273SGovind Singh .halt_reg = 0x6004, 886cdef273SGovind Singh .halt_check = BRANCH_VOTED, 896cdef273SGovind Singh .clkr = { 906cdef273SGovind Singh .enable_reg = 0x6004, 916cdef273SGovind Singh .enable_mask = BIT(0), 926cdef273SGovind Singh .hw.init = &(struct clk_init_data){ 936cdef273SGovind Singh .name = "lcc_q6ss_bcr_sleep_clk", 946cdef273SGovind Singh .ops = &clk_branch2_ops, 956cdef273SGovind Singh }, 966cdef273SGovind Singh }, 976cdef273SGovind Singh }; 986cdef273SGovind Singh 996cdef273SGovind Singh /* TCSR clock */ 1006cdef273SGovind Singh static struct clk_branch tcsr_lcc_csr_cbcr_clk = { 1016cdef273SGovind Singh .halt_reg = 0x8008, 1026cdef273SGovind Singh .halt_check = BRANCH_VOTED, 1036cdef273SGovind Singh .clkr = { 1046cdef273SGovind Singh .enable_reg = 0x8008, 1056cdef273SGovind Singh .enable_mask = BIT(0), 1066cdef273SGovind Singh .hw.init = &(struct clk_init_data){ 1076cdef273SGovind Singh .name = "tcsr_lcc_csr_cbcr_clk", 1086cdef273SGovind Singh .ops = &clk_branch2_ops, 1096cdef273SGovind Singh }, 1106cdef273SGovind Singh }, 1116cdef273SGovind Singh }; 1126cdef273SGovind Singh 1136cdef273SGovind Singh static struct regmap_config q6sstop_regmap_config = { 1146cdef273SGovind Singh .reg_bits = 32, 1156cdef273SGovind Singh .reg_stride = 4, 1166cdef273SGovind Singh .val_bits = 32, 1176cdef273SGovind Singh .fast_io = true, 1186cdef273SGovind Singh }; 1196cdef273SGovind Singh 1206cdef273SGovind Singh static struct clk_regmap *q6sstop_qcs404_clocks[] = { 1216cdef273SGovind Singh [LCC_AHBFABRIC_CBC_CLK] = &lcc_ahbfabric_cbc_clk.clkr, 1226cdef273SGovind Singh [LCC_Q6SS_AHBS_CBC_CLK] = &lcc_q6ss_ahbs_cbc_clk.clkr, 1236cdef273SGovind Singh [LCC_Q6SS_TCM_SLAVE_CBC_CLK] = &lcc_q6ss_tcm_slave_cbc_clk.clkr, 1246cdef273SGovind Singh [LCC_Q6SS_AHBM_CBC_CLK] = &lcc_q6ss_ahbm_cbc_clk.clkr, 1256cdef273SGovind Singh [LCC_Q6SS_AXIM_CBC_CLK] = &lcc_q6ss_axim_cbc_clk.clkr, 1266cdef273SGovind Singh [LCC_Q6SS_BCR_SLEEP_CLK] = &lcc_q6ss_bcr_sleep_clk.clkr, 1276cdef273SGovind Singh }; 1286cdef273SGovind Singh 1296cdef273SGovind Singh static const struct qcom_reset_map q6sstop_qcs404_resets[] = { 1306cdef273SGovind Singh [Q6SSTOP_BCR_RESET] = { 0x6000 }, 1316cdef273SGovind Singh }; 1326cdef273SGovind Singh 1336cdef273SGovind Singh static const struct qcom_cc_desc q6sstop_qcs404_desc = { 1346cdef273SGovind Singh .config = &q6sstop_regmap_config, 1356cdef273SGovind Singh .clks = q6sstop_qcs404_clocks, 1366cdef273SGovind Singh .num_clks = ARRAY_SIZE(q6sstop_qcs404_clocks), 1376cdef273SGovind Singh .resets = q6sstop_qcs404_resets, 1386cdef273SGovind Singh .num_resets = ARRAY_SIZE(q6sstop_qcs404_resets), 1396cdef273SGovind Singh }; 1406cdef273SGovind Singh 1416cdef273SGovind Singh static struct clk_regmap *tcsr_qcs404_clocks[] = { 1426cdef273SGovind Singh [TCSR_Q6SS_LCC_CBCR_CLK] = &tcsr_lcc_csr_cbcr_clk.clkr, 1436cdef273SGovind Singh }; 1446cdef273SGovind Singh 1456cdef273SGovind Singh static const struct qcom_cc_desc tcsr_qcs404_desc = { 1466cdef273SGovind Singh .config = &q6sstop_regmap_config, 1476cdef273SGovind Singh .clks = tcsr_qcs404_clocks, 1486cdef273SGovind Singh .num_clks = ARRAY_SIZE(tcsr_qcs404_clocks), 1496cdef273SGovind Singh }; 1506cdef273SGovind Singh 1516cdef273SGovind Singh static const struct of_device_id q6sstopcc_qcs404_match_table[] = { 1526cdef273SGovind Singh { .compatible = "qcom,qcs404-q6sstopcc" }, 1536cdef273SGovind Singh { } 1546cdef273SGovind Singh }; 1556cdef273SGovind Singh MODULE_DEVICE_TABLE(of, q6sstopcc_qcs404_match_table); 1566cdef273SGovind Singh 1576cdef273SGovind Singh static int q6sstopcc_qcs404_probe(struct platform_device *pdev) 1586cdef273SGovind Singh { 1596cdef273SGovind Singh const struct qcom_cc_desc *desc; 1606cdef273SGovind Singh int ret; 1616cdef273SGovind Singh 162*72cfc73fSDmitry Baryshkov ret = devm_pm_runtime_enable(&pdev->dev); 1636cdef273SGovind Singh if (ret) 164*72cfc73fSDmitry Baryshkov return ret; 165*72cfc73fSDmitry Baryshkov 166*72cfc73fSDmitry Baryshkov ret = devm_pm_clk_create(&pdev->dev); 167*72cfc73fSDmitry Baryshkov if (ret) 168*72cfc73fSDmitry Baryshkov return ret; 1696cdef273SGovind Singh 1706cdef273SGovind Singh ret = pm_clk_add(&pdev->dev, NULL); 1716cdef273SGovind Singh if (ret < 0) { 1726cdef273SGovind Singh dev_err(&pdev->dev, "failed to acquire iface clock\n"); 173*72cfc73fSDmitry Baryshkov return ret; 1746cdef273SGovind Singh } 1756cdef273SGovind Singh 1766cdef273SGovind Singh q6sstop_regmap_config.name = "q6sstop_tcsr"; 1776cdef273SGovind Singh desc = &tcsr_qcs404_desc; 1786cdef273SGovind Singh 1796cdef273SGovind Singh ret = qcom_cc_probe_by_index(pdev, 1, desc); 1806cdef273SGovind Singh if (ret) 181*72cfc73fSDmitry Baryshkov return ret; 1826cdef273SGovind Singh 1836cdef273SGovind Singh q6sstop_regmap_config.name = "q6sstop_cc"; 1846cdef273SGovind Singh desc = &q6sstop_qcs404_desc; 1856cdef273SGovind Singh 1866cdef273SGovind Singh ret = qcom_cc_probe_by_index(pdev, 0, desc); 1876cdef273SGovind Singh if (ret) 1886cdef273SGovind Singh return ret; 1896cdef273SGovind Singh 1906cdef273SGovind Singh return 0; 1916cdef273SGovind Singh } 1926cdef273SGovind Singh 1936cdef273SGovind Singh static const struct dev_pm_ops q6sstopcc_pm_ops = { 1946cdef273SGovind Singh SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL) 1956cdef273SGovind Singh }; 1966cdef273SGovind Singh 1976cdef273SGovind Singh static struct platform_driver q6sstopcc_qcs404_driver = { 1986cdef273SGovind Singh .probe = q6sstopcc_qcs404_probe, 1996cdef273SGovind Singh .driver = { 2006cdef273SGovind Singh .name = "qcs404-q6sstopcc", 2016cdef273SGovind Singh .of_match_table = q6sstopcc_qcs404_match_table, 2026cdef273SGovind Singh .pm = &q6sstopcc_pm_ops, 2036cdef273SGovind Singh }, 2046cdef273SGovind Singh }; 2056cdef273SGovind Singh 2066cdef273SGovind Singh module_platform_driver(q6sstopcc_qcs404_driver); 2076cdef273SGovind Singh 2086cdef273SGovind Singh MODULE_DESCRIPTION("QTI QCS404 Q6SSTOP Clock Controller Driver"); 2096cdef273SGovind Singh MODULE_LICENSE("GPL v2"); 210