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-regmap-mux.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_regmap_mux apcs_alias0_clk_src = { 37 .reg = 0x0050, 38 .width = 3, 39 .shift = 7, 40 .parent_map = parents_apcs_alias0_clk_src_map, 41 .clkr.hw.init = &(struct clk_init_data){ 42 .name = "apcs_alias0_clk_src", 43 .parent_data = parents_apcs_alias0_clk_src, 44 .num_parents = 2, 45 .ops = &clk_regmap_mux_closest_ops, 46 .flags = CLK_SET_RATE_PARENT, 47 }, 48 }; 49 50 static struct clk_branch apcs_alias0_core_clk = { 51 .halt_reg = 0x0058, 52 .clkr = { 53 .enable_reg = 0x0058, 54 .enable_mask = BIT(0), 55 .hw.init = &(struct clk_init_data){ 56 .name = "apcs_alias0_core_clk", 57 .parent_hws = (const struct clk_hw *[]){ 58 &apcs_alias0_clk_src.clkr.hw }, 59 .num_parents = 1, 60 .flags = CLK_SET_RATE_PARENT, 61 .ops = &clk_branch2_ops, 62 }, 63 }, 64 }; 65 66 static const struct regmap_config apss_ipq6018_regmap_config = { 67 .reg_bits = 32, 68 .reg_stride = 4, 69 .val_bits = 32, 70 .max_register = 0x1000, 71 .fast_io = true, 72 }; 73 74 static struct clk_regmap *apss_ipq6018_clks[] = { 75 [APCS_ALIAS0_CLK_SRC] = &apcs_alias0_clk_src.clkr, 76 [APCS_ALIAS0_CORE_CLK] = &apcs_alias0_core_clk.clkr, 77 }; 78 79 static const struct qcom_cc_desc apss_ipq6018_desc = { 80 .config = &apss_ipq6018_regmap_config, 81 .clks = apss_ipq6018_clks, 82 .num_clks = ARRAY_SIZE(apss_ipq6018_clks), 83 }; 84 85 static int apss_ipq6018_probe(struct platform_device *pdev) 86 { 87 struct regmap *regmap; 88 89 regmap = dev_get_regmap(pdev->dev.parent, NULL); 90 if (!regmap) 91 return -ENODEV; 92 93 return qcom_cc_really_probe(pdev, &apss_ipq6018_desc, regmap); 94 } 95 96 static struct platform_driver apss_ipq6018_driver = { 97 .probe = apss_ipq6018_probe, 98 .driver = { 99 .name = "qcom,apss-ipq6018-clk", 100 }, 101 }; 102 103 module_platform_driver(apss_ipq6018_driver); 104 105 MODULE_DESCRIPTION("QCOM APSS IPQ 6018 CLK Driver"); 106 MODULE_LICENSE("GPL v2"); 107