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 21enum { 22 P_XO, 23 P_APSS_PLL_EARLY, 24}; 25 26static const struct clk_parent_data parents_apcs_alias0_clk_src[] = { 27 { .fw_name = "xo" }, 28 { .fw_name = "pll" }, 29}; 30 31static const struct parent_map parents_apcs_alias0_clk_src_map[] = { 32 { P_XO, 0 }, 33 { P_APSS_PLL_EARLY, 5 }, 34}; 35 36static 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 49static 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 65static 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 73static 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 78static 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 84static 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 95static struct platform_driver apss_ipq6018_driver = { 96 .probe = apss_ipq6018_probe, 97 .driver = { 98 .name = "qcom,apss-ipq6018-clk", 99 }, 100}; 101 102module_platform_driver(apss_ipq6018_driver); 103 104MODULE_DESCRIPTION("QCOM APSS IPQ 6018 CLK Driver"); 105MODULE_LICENSE("GPL v2"); 106