1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (c) 2021, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. 5 * Copyright (c) 2022, Linaro Limited 6 */ 7 8#include <linux/clk-provider.h> 9#include <linux/module.h> 10#include <linux/of.h> 11#include <linux/platform_device.h> 12#include <linux/regmap.h> 13 14#include <dt-bindings/clock/qcom,sm8550-tcsr.h> 15 16#include "clk-alpha-pll.h" 17#include "clk-branch.h" 18#include "clk-pll.h" 19#include "clk-rcg.h" 20#include "clk-regmap.h" 21#include "clk-regmap-divider.h" 22#include "clk-regmap-mux.h" 23#include "common.h" 24#include "reset.h" 25 26enum { 27 DT_BI_TCXO_PAD, 28}; 29 30static struct clk_branch tcsr_pcie_0_clkref_en = { 31 .halt_reg = 0x15100, 32 .halt_check = BRANCH_HALT_SKIP, 33 .clkr = { 34 .enable_reg = 0x15100, 35 .enable_mask = BIT(0), 36 .hw.init = &(struct clk_init_data){ 37 .name = "tcsr_pcie_0_clkref_en", 38 .parent_data = &(const struct clk_parent_data){ 39 .index = DT_BI_TCXO_PAD, 40 }, 41 .num_parents = 1, 42 .ops = &clk_branch2_ops, 43 }, 44 }, 45}; 46 47static struct clk_branch tcsr_pcie_1_clkref_en = { 48 .halt_reg = 0x15114, 49 .halt_check = BRANCH_HALT_SKIP, 50 .clkr = { 51 .enable_reg = 0x15114, 52 .enable_mask = BIT(0), 53 .hw.init = &(struct clk_init_data){ 54 .name = "tcsr_pcie_1_clkref_en", 55 .parent_data = &(const struct clk_parent_data){ 56 .index = DT_BI_TCXO_PAD, 57 }, 58 .num_parents = 1, 59 .ops = &clk_branch2_ops, 60 }, 61 }, 62}; 63 64static struct clk_branch tcsr_ufs_clkref_en = { 65 .halt_reg = 0x15110, 66 .halt_check = BRANCH_HALT_SKIP, 67 .clkr = { 68 .enable_reg = 0x15110, 69 .enable_mask = BIT(0), 70 .hw.init = &(struct clk_init_data){ 71 .name = "tcsr_ufs_clkref_en", 72 .parent_data = &(const struct clk_parent_data){ 73 .index = DT_BI_TCXO_PAD, 74 }, 75 .num_parents = 1, 76 .ops = &clk_branch2_ops, 77 }, 78 }, 79}; 80 81static struct clk_branch tcsr_ufs_pad_clkref_en = { 82 .halt_reg = 0x15104, 83 .halt_check = BRANCH_HALT_SKIP, 84 .clkr = { 85 .enable_reg = 0x15104, 86 .enable_mask = BIT(0), 87 .hw.init = &(struct clk_init_data){ 88 .name = "tcsr_ufs_pad_clkref_en", 89 .parent_data = &(const struct clk_parent_data){ 90 .index = DT_BI_TCXO_PAD, 91 }, 92 .num_parents = 1, 93 .ops = &clk_branch2_ops, 94 }, 95 }, 96}; 97 98static struct clk_branch tcsr_usb2_clkref_en = { 99 .halt_reg = 0x15118, 100 .halt_check = BRANCH_HALT_SKIP, 101 .clkr = { 102 .enable_reg = 0x15118, 103 .enable_mask = BIT(0), 104 .hw.init = &(struct clk_init_data){ 105 .name = "tcsr_usb2_clkref_en", 106 .parent_data = &(const struct clk_parent_data){ 107 .index = DT_BI_TCXO_PAD, 108 }, 109 .num_parents = 1, 110 .ops = &clk_branch2_ops, 111 }, 112 }, 113}; 114 115static struct clk_branch tcsr_usb3_clkref_en = { 116 .halt_reg = 0x15108, 117 .halt_check = BRANCH_HALT_SKIP, 118 .clkr = { 119 .enable_reg = 0x15108, 120 .enable_mask = BIT(0), 121 .hw.init = &(struct clk_init_data){ 122 .name = "tcsr_usb3_clkref_en", 123 .parent_data = &(const struct clk_parent_data){ 124 .index = DT_BI_TCXO_PAD, 125 }, 126 .num_parents = 1, 127 .ops = &clk_branch2_ops, 128 }, 129 }, 130}; 131 132static struct clk_regmap *tcsr_cc_sm8550_clocks[] = { 133 [TCSR_PCIE_0_CLKREF_EN] = &tcsr_pcie_0_clkref_en.clkr, 134 [TCSR_PCIE_1_CLKREF_EN] = &tcsr_pcie_1_clkref_en.clkr, 135 [TCSR_UFS_CLKREF_EN] = &tcsr_ufs_clkref_en.clkr, 136 [TCSR_UFS_PAD_CLKREF_EN] = &tcsr_ufs_pad_clkref_en.clkr, 137 [TCSR_USB2_CLKREF_EN] = &tcsr_usb2_clkref_en.clkr, 138 [TCSR_USB3_CLKREF_EN] = &tcsr_usb3_clkref_en.clkr, 139}; 140 141static const struct regmap_config tcsr_cc_sm8550_regmap_config = { 142 .reg_bits = 32, 143 .reg_stride = 4, 144 .val_bits = 32, 145 .max_register = 0x2f000, 146 .fast_io = true, 147}; 148 149static const struct qcom_cc_desc tcsr_cc_sm8550_desc = { 150 .config = &tcsr_cc_sm8550_regmap_config, 151 .clks = tcsr_cc_sm8550_clocks, 152 .num_clks = ARRAY_SIZE(tcsr_cc_sm8550_clocks), 153}; 154 155static const struct of_device_id tcsr_cc_sm8550_match_table[] = { 156 { .compatible = "qcom,sm8550-tcsr" }, 157 { } 158}; 159MODULE_DEVICE_TABLE(of, tcsr_cc_sm8550_match_table); 160 161static int tcsr_cc_sm8550_probe(struct platform_device *pdev) 162{ 163 struct regmap *regmap; 164 165 regmap = qcom_cc_map(pdev, &tcsr_cc_sm8550_desc); 166 if (IS_ERR(regmap)) 167 return PTR_ERR(regmap); 168 169 return qcom_cc_really_probe(pdev, &tcsr_cc_sm8550_desc, regmap); 170} 171 172static struct platform_driver tcsr_cc_sm8550_driver = { 173 .probe = tcsr_cc_sm8550_probe, 174 .driver = { 175 .name = "tcsr_cc-sm8550", 176 .of_match_table = tcsr_cc_sm8550_match_table, 177 }, 178}; 179 180static int __init tcsr_cc_sm8550_init(void) 181{ 182 return platform_driver_register(&tcsr_cc_sm8550_driver); 183} 184subsys_initcall(tcsr_cc_sm8550_init); 185 186static void __exit tcsr_cc_sm8550_exit(void) 187{ 188 platform_driver_unregister(&tcsr_cc_sm8550_driver); 189} 190module_exit(tcsr_cc_sm8550_exit); 191 192MODULE_DESCRIPTION("QTI TCSRCC SM8550 Driver"); 193MODULE_LICENSE("GPL"); 194