1*24ba8ce4SVivek Aknurwar // SPDX-License-Identifier: GPL-2.0-only 2*24ba8ce4SVivek Aknurwar /* 3*24ba8ce4SVivek Aknurwar * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. 4*24ba8ce4SVivek Aknurwar */ 5*24ba8ce4SVivek Aknurwar 6*24ba8ce4SVivek Aknurwar #include <linux/clk-provider.h> 7*24ba8ce4SVivek Aknurwar #include <linux/mod_devicetable.h> 8*24ba8ce4SVivek Aknurwar #include <linux/module.h> 9*24ba8ce4SVivek Aknurwar #include <linux/of.h> 10*24ba8ce4SVivek Aknurwar #include <linux/platform_device.h> 11*24ba8ce4SVivek Aknurwar #include <linux/regmap.h> 12*24ba8ce4SVivek Aknurwar 13*24ba8ce4SVivek Aknurwar #include <dt-bindings/clock/qcom,hawi-tcsrcc.h> 14*24ba8ce4SVivek Aknurwar 15*24ba8ce4SVivek Aknurwar #include "clk-alpha-pll.h" 16*24ba8ce4SVivek Aknurwar #include "clk-branch.h" 17*24ba8ce4SVivek Aknurwar #include "clk-pll.h" 18*24ba8ce4SVivek Aknurwar #include "clk-rcg.h" 19*24ba8ce4SVivek Aknurwar #include "clk-regmap.h" 20*24ba8ce4SVivek Aknurwar #include "clk-regmap-divider.h" 21*24ba8ce4SVivek Aknurwar #include "clk-regmap-mux.h" 22*24ba8ce4SVivek Aknurwar #include "common.h" 23*24ba8ce4SVivek Aknurwar #include "reset.h" 24*24ba8ce4SVivek Aknurwar 25*24ba8ce4SVivek Aknurwar enum { 26*24ba8ce4SVivek Aknurwar DT_BI_TCXO_PAD, 27*24ba8ce4SVivek Aknurwar }; 28*24ba8ce4SVivek Aknurwar 29*24ba8ce4SVivek Aknurwar static struct clk_branch tcsr_pcie_0_clkref_en = { 30*24ba8ce4SVivek Aknurwar .halt_reg = 0x4c, 31*24ba8ce4SVivek Aknurwar .halt_check = BRANCH_HALT_DELAY, 32*24ba8ce4SVivek Aknurwar .clkr = { 33*24ba8ce4SVivek Aknurwar .enable_reg = 0x4c, 34*24ba8ce4SVivek Aknurwar .enable_mask = BIT(0), 35*24ba8ce4SVivek Aknurwar .hw.init = &(const struct clk_init_data) { 36*24ba8ce4SVivek Aknurwar .name = "tcsr_pcie_0_clkref_en", 37*24ba8ce4SVivek Aknurwar .parent_data = &(const struct clk_parent_data){ 38*24ba8ce4SVivek Aknurwar .index = DT_BI_TCXO_PAD, 39*24ba8ce4SVivek Aknurwar }, 40*24ba8ce4SVivek Aknurwar .num_parents = 1, 41*24ba8ce4SVivek Aknurwar .ops = &clk_branch2_ops, 42*24ba8ce4SVivek Aknurwar }, 43*24ba8ce4SVivek Aknurwar }, 44*24ba8ce4SVivek Aknurwar }; 45*24ba8ce4SVivek Aknurwar 46*24ba8ce4SVivek Aknurwar static struct clk_branch tcsr_pcie_1_clkref_en = { 47*24ba8ce4SVivek Aknurwar .halt_reg = 0x0, 48*24ba8ce4SVivek Aknurwar .halt_check = BRANCH_HALT_DELAY, 49*24ba8ce4SVivek Aknurwar .clkr = { 50*24ba8ce4SVivek Aknurwar .enable_reg = 0x0, 51*24ba8ce4SVivek Aknurwar .enable_mask = BIT(0), 52*24ba8ce4SVivek Aknurwar .hw.init = &(const struct clk_init_data) { 53*24ba8ce4SVivek Aknurwar .name = "tcsr_pcie_1_clkref_en", 54*24ba8ce4SVivek Aknurwar .parent_data = &(const struct clk_parent_data){ 55*24ba8ce4SVivek Aknurwar .index = DT_BI_TCXO_PAD, 56*24ba8ce4SVivek Aknurwar }, 57*24ba8ce4SVivek Aknurwar .num_parents = 1, 58*24ba8ce4SVivek Aknurwar .ops = &clk_branch2_ops, 59*24ba8ce4SVivek Aknurwar }, 60*24ba8ce4SVivek Aknurwar }, 61*24ba8ce4SVivek Aknurwar }; 62*24ba8ce4SVivek Aknurwar 63*24ba8ce4SVivek Aknurwar static struct clk_branch tcsr_ufs_clkref_en = { 64*24ba8ce4SVivek Aknurwar .halt_reg = 0x10, 65*24ba8ce4SVivek Aknurwar .halt_check = BRANCH_HALT_DELAY, 66*24ba8ce4SVivek Aknurwar .clkr = { 67*24ba8ce4SVivek Aknurwar .enable_reg = 0x10, 68*24ba8ce4SVivek Aknurwar .enable_mask = BIT(0), 69*24ba8ce4SVivek Aknurwar .hw.init = &(const struct clk_init_data) { 70*24ba8ce4SVivek Aknurwar .name = "tcsr_ufs_clkref_en", 71*24ba8ce4SVivek Aknurwar .parent_data = &(const struct clk_parent_data){ 72*24ba8ce4SVivek Aknurwar .index = DT_BI_TCXO_PAD, 73*24ba8ce4SVivek Aknurwar }, 74*24ba8ce4SVivek Aknurwar .num_parents = 1, 75*24ba8ce4SVivek Aknurwar .ops = &clk_branch2_ops, 76*24ba8ce4SVivek Aknurwar }, 77*24ba8ce4SVivek Aknurwar }, 78*24ba8ce4SVivek Aknurwar }; 79*24ba8ce4SVivek Aknurwar 80*24ba8ce4SVivek Aknurwar static struct clk_branch tcsr_usb2_clkref_en = { 81*24ba8ce4SVivek Aknurwar .halt_reg = 0x18, 82*24ba8ce4SVivek Aknurwar .halt_check = BRANCH_HALT_DELAY, 83*24ba8ce4SVivek Aknurwar .clkr = { 84*24ba8ce4SVivek Aknurwar .enable_reg = 0x18, 85*24ba8ce4SVivek Aknurwar .enable_mask = BIT(0), 86*24ba8ce4SVivek Aknurwar .hw.init = &(const struct clk_init_data) { 87*24ba8ce4SVivek Aknurwar .name = "tcsr_usb2_clkref_en", 88*24ba8ce4SVivek Aknurwar .parent_data = &(const struct clk_parent_data){ 89*24ba8ce4SVivek Aknurwar .index = DT_BI_TCXO_PAD, 90*24ba8ce4SVivek Aknurwar }, 91*24ba8ce4SVivek Aknurwar .num_parents = 1, 92*24ba8ce4SVivek Aknurwar .ops = &clk_branch2_ops, 93*24ba8ce4SVivek Aknurwar }, 94*24ba8ce4SVivek Aknurwar }, 95*24ba8ce4SVivek Aknurwar }; 96*24ba8ce4SVivek Aknurwar 97*24ba8ce4SVivek Aknurwar static struct clk_branch tcsr_usb3_clkref_en = { 98*24ba8ce4SVivek Aknurwar .halt_reg = 0x8, 99*24ba8ce4SVivek Aknurwar .halt_check = BRANCH_HALT_DELAY, 100*24ba8ce4SVivek Aknurwar .clkr = { 101*24ba8ce4SVivek Aknurwar .enable_reg = 0x8, 102*24ba8ce4SVivek Aknurwar .enable_mask = BIT(0), 103*24ba8ce4SVivek Aknurwar .hw.init = &(const struct clk_init_data) { 104*24ba8ce4SVivek Aknurwar .name = "tcsr_usb3_clkref_en", 105*24ba8ce4SVivek Aknurwar .parent_data = &(const struct clk_parent_data){ 106*24ba8ce4SVivek Aknurwar .index = DT_BI_TCXO_PAD, 107*24ba8ce4SVivek Aknurwar }, 108*24ba8ce4SVivek Aknurwar .num_parents = 1, 109*24ba8ce4SVivek Aknurwar .ops = &clk_branch2_ops, 110*24ba8ce4SVivek Aknurwar }, 111*24ba8ce4SVivek Aknurwar }, 112*24ba8ce4SVivek Aknurwar }; 113*24ba8ce4SVivek Aknurwar 114*24ba8ce4SVivek Aknurwar static struct clk_regmap *tcsr_cc_hawi_clocks[] = { 115*24ba8ce4SVivek Aknurwar [TCSR_PCIE_0_CLKREF_EN] = &tcsr_pcie_0_clkref_en.clkr, 116*24ba8ce4SVivek Aknurwar [TCSR_PCIE_1_CLKREF_EN] = &tcsr_pcie_1_clkref_en.clkr, 117*24ba8ce4SVivek Aknurwar [TCSR_UFS_CLKREF_EN] = &tcsr_ufs_clkref_en.clkr, 118*24ba8ce4SVivek Aknurwar [TCSR_USB2_CLKREF_EN] = &tcsr_usb2_clkref_en.clkr, 119*24ba8ce4SVivek Aknurwar [TCSR_USB3_CLKREF_EN] = &tcsr_usb3_clkref_en.clkr, 120*24ba8ce4SVivek Aknurwar }; 121*24ba8ce4SVivek Aknurwar 122*24ba8ce4SVivek Aknurwar static const struct regmap_config tcsr_cc_hawi_regmap_config = { 123*24ba8ce4SVivek Aknurwar .reg_bits = 32, 124*24ba8ce4SVivek Aknurwar .reg_stride = 4, 125*24ba8ce4SVivek Aknurwar .val_bits = 32, 126*24ba8ce4SVivek Aknurwar .max_register = 0x4c, 127*24ba8ce4SVivek Aknurwar .fast_io = true, 128*24ba8ce4SVivek Aknurwar }; 129*24ba8ce4SVivek Aknurwar 130*24ba8ce4SVivek Aknurwar static const struct qcom_cc_desc tcsr_cc_hawi_desc = { 131*24ba8ce4SVivek Aknurwar .config = &tcsr_cc_hawi_regmap_config, 132*24ba8ce4SVivek Aknurwar .clks = tcsr_cc_hawi_clocks, 133*24ba8ce4SVivek Aknurwar .num_clks = ARRAY_SIZE(tcsr_cc_hawi_clocks), 134*24ba8ce4SVivek Aknurwar }; 135*24ba8ce4SVivek Aknurwar 136*24ba8ce4SVivek Aknurwar static const struct of_device_id tcsr_cc_hawi_match_table[] = { 137*24ba8ce4SVivek Aknurwar { .compatible = "qcom,hawi-tcsrcc" }, 138*24ba8ce4SVivek Aknurwar { } 139*24ba8ce4SVivek Aknurwar }; 140*24ba8ce4SVivek Aknurwar MODULE_DEVICE_TABLE(of, tcsr_cc_hawi_match_table); 141*24ba8ce4SVivek Aknurwar 142*24ba8ce4SVivek Aknurwar static int tcsr_cc_hawi_probe(struct platform_device *pdev) 143*24ba8ce4SVivek Aknurwar { 144*24ba8ce4SVivek Aknurwar return qcom_cc_probe(pdev, &tcsr_cc_hawi_desc); 145*24ba8ce4SVivek Aknurwar } 146*24ba8ce4SVivek Aknurwar 147*24ba8ce4SVivek Aknurwar static struct platform_driver tcsr_cc_hawi_driver = { 148*24ba8ce4SVivek Aknurwar .probe = tcsr_cc_hawi_probe, 149*24ba8ce4SVivek Aknurwar .driver = { 150*24ba8ce4SVivek Aknurwar .name = "tcsrcc-hawi", 151*24ba8ce4SVivek Aknurwar .of_match_table = tcsr_cc_hawi_match_table, 152*24ba8ce4SVivek Aknurwar }, 153*24ba8ce4SVivek Aknurwar }; 154*24ba8ce4SVivek Aknurwar 155*24ba8ce4SVivek Aknurwar module_platform_driver(tcsr_cc_hawi_driver); 156*24ba8ce4SVivek Aknurwar 157*24ba8ce4SVivek Aknurwar MODULE_DESCRIPTION("QTI TCSRCC HAWI Driver"); 158*24ba8ce4SVivek Aknurwar MODULE_LICENSE("GPL"); 159