18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2018, The Linux Foundation. All rights reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/kernel.h> 78c2ecf20Sopenharmony_ci#include <linux/err.h> 88c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 98c2ecf20Sopenharmony_ci#include <linux/clk-provider.h> 108c2ecf20Sopenharmony_ci#include <linux/regmap.h> 118c2ecf20Sopenharmony_ci#include <linux/module.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <dt-bindings/clock/qcom,apss-ipq.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include "common.h" 168c2ecf20Sopenharmony_ci#include "clk-regmap.h" 178c2ecf20Sopenharmony_ci#include "clk-branch.h" 188c2ecf20Sopenharmony_ci#include "clk-alpha-pll.h" 198c2ecf20Sopenharmony_ci#include "clk-regmap-mux.h" 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cienum { 228c2ecf20Sopenharmony_ci P_XO, 238c2ecf20Sopenharmony_ci P_APSS_PLL_EARLY, 248c2ecf20Sopenharmony_ci}; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistatic const struct clk_parent_data parents_apcs_alias0_clk_src[] = { 278c2ecf20Sopenharmony_ci { .fw_name = "xo" }, 288c2ecf20Sopenharmony_ci { .fw_name = "pll" }, 298c2ecf20Sopenharmony_ci}; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic const struct parent_map parents_apcs_alias0_clk_src_map[] = { 328c2ecf20Sopenharmony_ci { P_XO, 0 }, 338c2ecf20Sopenharmony_ci { P_APSS_PLL_EARLY, 5 }, 348c2ecf20Sopenharmony_ci}; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic struct clk_regmap_mux apcs_alias0_clk_src = { 378c2ecf20Sopenharmony_ci .reg = 0x0050, 388c2ecf20Sopenharmony_ci .width = 3, 398c2ecf20Sopenharmony_ci .shift = 7, 408c2ecf20Sopenharmony_ci .parent_map = parents_apcs_alias0_clk_src_map, 418c2ecf20Sopenharmony_ci .clkr.hw.init = &(struct clk_init_data){ 428c2ecf20Sopenharmony_ci .name = "apcs_alias0_clk_src", 438c2ecf20Sopenharmony_ci .parent_data = parents_apcs_alias0_clk_src, 448c2ecf20Sopenharmony_ci .num_parents = 2, 458c2ecf20Sopenharmony_ci .ops = &clk_regmap_mux_closest_ops, 468c2ecf20Sopenharmony_ci .flags = CLK_SET_RATE_PARENT, 478c2ecf20Sopenharmony_ci }, 488c2ecf20Sopenharmony_ci}; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistatic struct clk_branch apcs_alias0_core_clk = { 518c2ecf20Sopenharmony_ci .halt_reg = 0x0058, 528c2ecf20Sopenharmony_ci .clkr = { 538c2ecf20Sopenharmony_ci .enable_reg = 0x0058, 548c2ecf20Sopenharmony_ci .enable_mask = BIT(0), 558c2ecf20Sopenharmony_ci .hw.init = &(struct clk_init_data){ 568c2ecf20Sopenharmony_ci .name = "apcs_alias0_core_clk", 578c2ecf20Sopenharmony_ci .parent_hws = (const struct clk_hw *[]){ 588c2ecf20Sopenharmony_ci &apcs_alias0_clk_src.clkr.hw }, 598c2ecf20Sopenharmony_ci .num_parents = 1, 608c2ecf20Sopenharmony_ci .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 618c2ecf20Sopenharmony_ci .ops = &clk_branch2_ops, 628c2ecf20Sopenharmony_ci }, 638c2ecf20Sopenharmony_ci }, 648c2ecf20Sopenharmony_ci}; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_cistatic const struct regmap_config apss_ipq6018_regmap_config = { 678c2ecf20Sopenharmony_ci .reg_bits = 32, 688c2ecf20Sopenharmony_ci .reg_stride = 4, 698c2ecf20Sopenharmony_ci .val_bits = 32, 708c2ecf20Sopenharmony_ci .max_register = 0x1000, 718c2ecf20Sopenharmony_ci .fast_io = true, 728c2ecf20Sopenharmony_ci}; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistatic struct clk_regmap *apss_ipq6018_clks[] = { 758c2ecf20Sopenharmony_ci [APCS_ALIAS0_CLK_SRC] = &apcs_alias0_clk_src.clkr, 768c2ecf20Sopenharmony_ci [APCS_ALIAS0_CORE_CLK] = &apcs_alias0_core_clk.clkr, 778c2ecf20Sopenharmony_ci}; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cistatic const struct qcom_cc_desc apss_ipq6018_desc = { 808c2ecf20Sopenharmony_ci .config = &apss_ipq6018_regmap_config, 818c2ecf20Sopenharmony_ci .clks = apss_ipq6018_clks, 828c2ecf20Sopenharmony_ci .num_clks = ARRAY_SIZE(apss_ipq6018_clks), 838c2ecf20Sopenharmony_ci}; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistatic int apss_ipq6018_probe(struct platform_device *pdev) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci struct regmap *regmap; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci regmap = dev_get_regmap(pdev->dev.parent, NULL); 908c2ecf20Sopenharmony_ci if (!regmap) 918c2ecf20Sopenharmony_ci return -ENODEV; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci return qcom_cc_really_probe(pdev, &apss_ipq6018_desc, regmap); 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic struct platform_driver apss_ipq6018_driver = { 978c2ecf20Sopenharmony_ci .probe = apss_ipq6018_probe, 988c2ecf20Sopenharmony_ci .driver = { 998c2ecf20Sopenharmony_ci .name = "qcom,apss-ipq6018-clk", 1008c2ecf20Sopenharmony_ci }, 1018c2ecf20Sopenharmony_ci}; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cimodule_platform_driver(apss_ipq6018_driver); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("QCOM APSS IPQ 6018 CLK Driver"); 1068c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 107