File Index
Files and directories
Sign in
FILE

apss-ipq-pll.c

File preview with syntax highlighting.

linux-6.19.14/drivers/clk/qcom/apss-ipq-pll.c C
  1// SPDX-License-Identifier: GPL-2.0
  2// Copyright (c) 2018, The Linux Foundation. All rights reserved.
  3#include <linux/clk-provider.h>
  4#include <linux/module.h>
  5#include <linux/of.h>
  6#include <linux/platform_device.h>
  7#include <linux/regmap.h>
  8
  9#include "clk-alpha-pll.h"
 10
 11static struct clk_alpha_pll ipq_pll_huayra = {
 12	.offset = 0x0,
 13	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_HUAYRA_APSS],
 14	.flags = SUPPORTS_DYNAMIC_UPDATE,
 15	.clkr = {
 16		.enable_reg = 0x0,
 17		.enable_mask = BIT(0),
 18		.hw.init = &(const struct clk_init_data) {
 19			.name = "a53pll",
 20			.parent_data = &(const struct clk_parent_data) {
 21				.fw_name = "xo",
 22			},
 23			.num_parents = 1,
 24			.ops = &clk_alpha_pll_huayra_ops,
 25		},
 26	},
 27};
 28
 29static struct clk_alpha_pll ipq_pll_stromer = {
 30	.offset = 0x0,
 31	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_STROMER],
 32	.flags = SUPPORTS_DYNAMIC_UPDATE,
 33	.clkr = {
 34		.enable_reg = 0x0,
 35		.enable_mask = BIT(0),
 36		.hw.init = &(const struct clk_init_data) {
 37			.name = "a53pll",
 38			.parent_data = &(const struct clk_parent_data) {
 39				.fw_name = "xo",
 40			},
 41			.num_parents = 1,
 42			.ops = &clk_alpha_pll_stromer_ops,
 43		},
 44	},
 45};
 46
 47static struct clk_alpha_pll ipq_pll_stromer_plus = {
 48	.offset = 0x0,
 49	/*
 50	 * The register offsets of the Stromer Plus PLL used in IPQ5332
 51	 * are the same as the Stromer PLL's offsets.
 52	 */
 53	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_STROMER],
 54	.flags = SUPPORTS_DYNAMIC_UPDATE,
 55	.clkr = {
 56		.enable_reg = 0x0,
 57		.enable_mask = BIT(0),
 58		.hw.init = &(const struct clk_init_data) {
 59			.name = "a53pll",
 60			.parent_data = &(const struct clk_parent_data) {
 61				.fw_name = "xo",
 62			},
 63			.num_parents = 1,
 64			.ops = &clk_alpha_pll_stromer_plus_ops,
 65		},
 66	},
 67};
 68
 69/* 1.008 GHz configuration */
 70static const struct alpha_pll_config ipq5018_pll_config = {
 71	.l = 0x2a,
 72	.config_ctl_val = 0x4001075b,
 73	.main_output_mask = BIT(0),
 74	.aux_output_mask = BIT(1),
 75	.early_output_mask = BIT(3),
 76	.status_val = 0x3,
 77	.status_mask = GENMASK(10, 8),
 78	.lock_det = BIT(2),
 79	.test_ctl_hi_val = 0x00400003,
 80};
 81
 82/* 1.080 GHz configuration */
 83static const struct alpha_pll_config ipq5332_pll_config = {
 84	.l = 0x2d,
 85	.config_ctl_val = 0x4001075b,
 86	.main_output_mask = BIT(0),
 87	.aux_output_mask = BIT(1),
 88	.early_output_mask = BIT(3),
 89	.status_val = 0x3,
 90	.status_mask = GENMASK(10, 8),
 91	.lock_det = BIT(2),
 92	.test_ctl_hi_val = 0x00400003,
 93};
 94
 95static const struct alpha_pll_config ipq6018_pll_config = {
 96	.l = 0x37,
 97	.config_ctl_val = 0x240d4828,
 98	.config_ctl_hi_val = 0x6,
 99	.early_output_mask = BIT(3),
100	.aux2_output_mask = BIT(2),
101	.aux_output_mask = BIT(1),
102	.main_output_mask = BIT(0),
103	.test_ctl_val = 0x1c0000C0,
104	.test_ctl_hi_val = 0x4000,
105};
106
107static const struct alpha_pll_config ipq8074_pll_config = {
108	.l = 0x48,
109	.config_ctl_val = 0x200d4828,
110	.config_ctl_hi_val = 0x6,
111	.early_output_mask = BIT(3),
112	.aux2_output_mask = BIT(2),
113	.aux_output_mask = BIT(1),
114	.main_output_mask = BIT(0),
115	.test_ctl_val = 0x1c000000,
116	.test_ctl_hi_val = 0x4000,
117};
118
119static const struct alpha_pll_config ipq9574_pll_config = {
120	.l = 0x3b,
121	.config_ctl_val = 0x200d4828,
122	.config_ctl_hi_val = 0x6,
123	.early_output_mask = BIT(3),
124	.aux2_output_mask = BIT(2),
125	.aux_output_mask = BIT(1),
126	.main_output_mask = BIT(0),
127	.test_ctl_val = 0x0,
128	.test_ctl_hi_val = 0x4000,
129};
130
131struct apss_pll_data {
132	int pll_type;
133	struct clk_alpha_pll *pll;
134	const struct alpha_pll_config *pll_config;
135};
136
137static const struct apss_pll_data ipq5018_pll_data = {
138	.pll_type = CLK_ALPHA_PLL_TYPE_STROMER,
139	.pll = &ipq_pll_stromer,
140	.pll_config = &ipq5018_pll_config,
141};
142
143static const struct apss_pll_data ipq5332_pll_data = {
144	.pll_type = CLK_ALPHA_PLL_TYPE_STROMER_PLUS,
145	.pll = &ipq_pll_stromer_plus,
146	.pll_config = &ipq5332_pll_config,
147};
148
149static const struct apss_pll_data ipq8074_pll_data = {
150	.pll_type = CLK_ALPHA_PLL_TYPE_HUAYRA,
151	.pll = &ipq_pll_huayra,
152	.pll_config = &ipq8074_pll_config,
153};
154
155static const struct apss_pll_data ipq6018_pll_data = {
156	.pll_type = CLK_ALPHA_PLL_TYPE_HUAYRA,
157	.pll = &ipq_pll_huayra,
158	.pll_config = &ipq6018_pll_config,
159};
160
161static const struct apss_pll_data ipq9574_pll_data = {
162	.pll_type = CLK_ALPHA_PLL_TYPE_HUAYRA,
163	.pll = &ipq_pll_huayra,
164	.pll_config = &ipq9574_pll_config,
165};
166
167static const struct regmap_config ipq_pll_regmap_config = {
168	.reg_bits		= 32,
169	.reg_stride		= 4,
170	.val_bits		= 32,
171	.max_register		= 0x40,
172};
173
174static int apss_ipq_pll_probe(struct platform_device *pdev)
175{
176	const struct apss_pll_data *data;
177	struct device *dev = &pdev->dev;
178	struct regmap *regmap;
179	void __iomem *base;
180	int ret;
181
182	base = devm_platform_ioremap_resource(pdev, 0);
183	if (IS_ERR(base))
184		return PTR_ERR(base);
185
186	regmap = devm_regmap_init_mmio(dev, base, &ipq_pll_regmap_config);
187	if (IS_ERR(regmap))
188		return PTR_ERR(regmap);
189
190	data = of_device_get_match_data(&pdev->dev);
191	if (!data)
192		return -ENODEV;
193
194	if (data->pll_type == CLK_ALPHA_PLL_TYPE_HUAYRA)
195		clk_alpha_pll_configure(data->pll, regmap, data->pll_config);
196	else if (data->pll_type == CLK_ALPHA_PLL_TYPE_STROMER ||
197		 data->pll_type == CLK_ALPHA_PLL_TYPE_STROMER_PLUS)
198		clk_stromer_pll_configure(data->pll, regmap, data->pll_config);
199
200	ret = devm_clk_register_regmap(dev, &data->pll->clkr);
201	if (ret)
202		return ret;
203
204	return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
205					   &data->pll->clkr.hw);
206}
207
208static const struct of_device_id apss_ipq_pll_match_table[] = {
209	{ .compatible = "qcom,ipq5018-a53pll", .data = &ipq5018_pll_data },
210	{ .compatible = "qcom,ipq5332-a53pll", .data = &ipq5332_pll_data },
211	{ .compatible = "qcom,ipq6018-a53pll", .data = &ipq6018_pll_data },
212	{ .compatible = "qcom,ipq8074-a53pll", .data = &ipq8074_pll_data },
213	{ .compatible = "qcom,ipq9574-a73pll", .data = &ipq9574_pll_data },
214	{ }
215};
216MODULE_DEVICE_TABLE(of, apss_ipq_pll_match_table);
217
218static struct platform_driver apss_ipq_pll_driver = {
219	.probe = apss_ipq_pll_probe,
220	.driver = {
221		.name = "qcom-ipq-apss-pll",
222		.of_match_table = apss_ipq_pll_match_table,
223	},
224};
225module_platform_driver(apss_ipq_pll_driver);
226
227MODULE_DESCRIPTION("Qualcomm technology Inc APSS ALPHA PLL Driver");
228MODULE_LICENSE("GPL v2");
~/ Read-only file preview.