1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2018, The Linux Foundation. All rights reserved. 4 */ 5 6 #include <linux/kernel.h> 7 #include <linux/err.h> 8 #include <linux/platform_device.h> 9 #include <linux/clk-provider.h> 10 #include <linux/regmap.h> 11 #include <linux/module.h> 12 13 #include <dt-bindings/clock/qcom,apss-ipq.h> 14 15 #include "common.h" 16 #include "clk-regmap.h" 17 #include "clk-branch.h" 18 #include "clk-alpha-pll.h" 19 #include "clk-rcg.h" 20 21 enum { 22 P_XO, 23 P_APSS_PLL_EARLY, 24 }; 25 26 static const struct clk_parent_data parents_apcs_alias0_clk_src[] = { 27 { .fw_name = "xo" }, 28 { .fw_name = "pll" }, 29 }; 30 31 static const struct parent_map parents_apcs_alias0_clk_src_map[] = { 32 { P_XO, 0 }, 33 { P_APSS_PLL_EARLY, 5 }, 34 }; 35 36 static struct clk_rcg2 apcs_alias0_clk_src = { 37 .cmd_rcgr = 0x0050, 38 .hid_width = 5, 39 .parent_map = parents_apcs_alias0_clk_src_map, 40 .clkr.hw.init = &(struct clk_init_data){ 41 .name = "apcs_alias0_clk_src", 42 .parent_data = parents_apcs_alias0_clk_src, 43 .num_parents = ARRAY_SIZE(parents_apcs_alias0_clk_src), 44 .ops = &clk_rcg2_mux_closest_ops, 45 .flags = CLK_SET_RATE_PARENT, 46 }, 47 }; 48 49 static struct clk_branch apcs_alias0_core_clk = { 50 .halt_reg = 0x0058, 51 .clkr = { 52 .enable_reg = 0x0058, 53 .enable_mask = BIT(0), 54 .hw.init = &(struct clk_init_data){ 55 .name = "apcs_alias0_core_clk", 56 .parent_hws = (const struct clk_hw *[]){ 57 &apcs_alias0_clk_src.clkr.hw }, 58 .num_parents = 1, 59 .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 60 .ops = &clk_branch2_ops, 61 }, 62 }, 63 }; 64 65 static const struct regmap_config apss_ipq6018_regmap_config = { 66 .reg_bits = 32, 67 .reg_stride = 4, 68 .val_bits = 32, 69 .max_register = 0x1000, 70 .fast_io = true, 71 }; 72 73 static struct clk_regmap *apss_ipq6018_clks[] = { 74 [APCS_ALIAS0_CLK_SRC] = &apcs_alias0_clk_src.clkr, 75 [APCS_ALIAS0_CORE_CLK] = &apcs_alias0_core_clk.clkr, 76 }; 77 78 static const struct qcom_cc_desc apss_ipq6018_desc = { 79 .config = &apss_ipq6018_regmap_config, 80 .clks = apss_ipq6018_clks, 81 .num_clks = ARRAY_SIZE(apss_ipq6018_clks), 82 }; 83 84 static int apss_ipq6018_probe(struct platform_device *pdev) 85 { 86 struct regmap *regmap; 87 88 regmap = dev_get_regmap(pdev->dev.parent, NULL); 89 if (!regmap) 90 return -ENODEV; 91 92 return qcom_cc_really_probe(pdev, &apss_ipq6018_desc, regmap); 93 } 94 95 static struct platform_driver apss_ipq6018_driver = { 96 .probe = apss_ipq6018_probe, 97 .driver = { 98 .name = "qcom,apss-ipq6018-clk", 99 }, 100 }; 101 102 module_platform_driver(apss_ipq6018_driver); 103 104 MODULE_DESCRIPTION("QCOM APSS IPQ 6018 CLK Driver"); 105 MODULE_LICENSE("GPL v2"); 106