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