1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright 2013 Emilio López
4 *
5 * Emilio López <emilio@elopez.com.ar>
6 */
7
8#include <linux/clk.h>
9#include <linux/clk-provider.h>
10#include <linux/io.h>
11#include <linux/of_address.h>
12#include <linux/platform_device.h>
13#include <linux/slab.h>
14
15#include "clk-factors.h"
16
17/**
18 * sun4i_a10_get_mod0_factors() - calculates m, n factors for MOD0-style clocks
19 * MOD0 rate is calculated as follows
20 * rate = (parent_rate >> p) / (m + 1);
21 */
22
23static void sun4i_a10_get_mod0_factors(struct factors_request *req)
24{
25	u8 div, calcm, calcp;
26
27	/* These clocks can only divide, so we will never be able to achieve
28	 * frequencies higher than the parent frequency */
29	if (req->rate > req->parent_rate)
30		req->rate = req->parent_rate;
31
32	div = DIV_ROUND_UP(req->parent_rate, req->rate);
33
34	if (div < 16)
35		calcp = 0;
36	else if (div / 2 < 16)
37		calcp = 1;
38	else if (div / 4 < 16)
39		calcp = 2;
40	else
41		calcp = 3;
42
43	calcm = DIV_ROUND_UP(div, 1 << calcp);
44
45	req->rate = (req->parent_rate >> calcp) / calcm;
46	req->m = calcm - 1;
47	req->p = calcp;
48}
49
50/* user manual says "n" but it's really "p" */
51static const struct clk_factors_config sun4i_a10_mod0_config = {
52	.mshift = 0,
53	.mwidth = 4,
54	.pshift = 16,
55	.pwidth = 2,
56};
57
58static const struct factors_data sun4i_a10_mod0_data = {
59	.enable = 31,
60	.mux = 24,
61	.muxmask = BIT(1) | BIT(0),
62	.table = &sun4i_a10_mod0_config,
63	.getter = sun4i_a10_get_mod0_factors,
64};
65
66static DEFINE_SPINLOCK(sun4i_a10_mod0_lock);
67
68static void __init sun4i_a10_mod0_setup(struct device_node *node)
69{
70	void __iomem *reg;
71
72	reg = of_iomap(node, 0);
73	if (!reg) {
74		/*
75		 * This happens with mod0 clk nodes instantiated through
76		 * mfd, as those do not have their resources assigned at
77		 * CLK_OF_DECLARE time yet, so do not print an error.
78		 */
79		return;
80	}
81
82	sunxi_factors_register(node, &sun4i_a10_mod0_data,
83			       &sun4i_a10_mod0_lock, reg);
84}
85CLK_OF_DECLARE_DRIVER(sun4i_a10_mod0, "allwinner,sun4i-a10-mod0-clk",
86		      sun4i_a10_mod0_setup);
87
88static int sun4i_a10_mod0_clk_probe(struct platform_device *pdev)
89{
90	struct device_node *np = pdev->dev.of_node;
91	struct resource *r;
92	void __iomem *reg;
93
94	if (!np)
95		return -ENODEV;
96
97	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
98	reg = devm_ioremap_resource(&pdev->dev, r);
99	if (IS_ERR(reg))
100		return PTR_ERR(reg);
101
102	sunxi_factors_register(np, &sun4i_a10_mod0_data,
103			       &sun4i_a10_mod0_lock, reg);
104	return 0;
105}
106
107static const struct of_device_id sun4i_a10_mod0_clk_dt_ids[] = {
108	{ .compatible = "allwinner,sun4i-a10-mod0-clk" },
109	{ /* sentinel */ }
110};
111
112static struct platform_driver sun4i_a10_mod0_clk_driver = {
113	.driver = {
114		.name = "sun4i-a10-mod0-clk",
115		.of_match_table = sun4i_a10_mod0_clk_dt_ids,
116	},
117	.probe = sun4i_a10_mod0_clk_probe,
118};
119builtin_platform_driver(sun4i_a10_mod0_clk_driver);
120
121static const struct factors_data sun9i_a80_mod0_data __initconst = {
122	.enable = 31,
123	.mux = 24,
124	.muxmask = BIT(3) | BIT(2) | BIT(1) | BIT(0),
125	.table = &sun4i_a10_mod0_config,
126	.getter = sun4i_a10_get_mod0_factors,
127};
128
129static void __init sun9i_a80_mod0_setup(struct device_node *node)
130{
131	void __iomem *reg;
132
133	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
134	if (IS_ERR(reg)) {
135		pr_err("Could not get registers for mod0-clk: %pOFn\n",
136		       node);
137		return;
138	}
139
140	sunxi_factors_register(node, &sun9i_a80_mod0_data,
141			       &sun4i_a10_mod0_lock, reg);
142}
143CLK_OF_DECLARE(sun9i_a80_mod0, "allwinner,sun9i-a80-mod0-clk", sun9i_a80_mod0_setup);
144
145static DEFINE_SPINLOCK(sun5i_a13_mbus_lock);
146
147static void __init sun5i_a13_mbus_setup(struct device_node *node)
148{
149	void __iomem *reg;
150
151	reg = of_iomap(node, 0);
152	if (!reg) {
153		pr_err("Could not get registers for a13-mbus-clk\n");
154		return;
155	}
156
157	/* The MBUS clocks needs to be always enabled */
158	sunxi_factors_register_critical(node, &sun4i_a10_mod0_data,
159					&sun5i_a13_mbus_lock, reg);
160}
161CLK_OF_DECLARE(sun5i_a13_mbus, "allwinner,sun5i-a13-mbus-clk", sun5i_a13_mbus_setup);
162
163struct mmc_phase {
164	struct clk_hw		hw;
165	u8			offset;
166	void __iomem		*reg;
167	spinlock_t		*lock;
168};
169
170#define to_mmc_phase(_hw) container_of(_hw, struct mmc_phase, hw)
171
172static int mmc_get_phase(struct clk_hw *hw)
173{
174	struct clk *mmc, *mmc_parent, *clk = hw->clk;
175	struct mmc_phase *phase = to_mmc_phase(hw);
176	unsigned int mmc_rate, mmc_parent_rate;
177	u16 step, mmc_div;
178	u32 value;
179	u8 delay;
180
181	value = readl(phase->reg);
182	delay = (value >> phase->offset) & 0x3;
183
184	if (!delay)
185		return 180;
186
187	/* Get the main MMC clock */
188	mmc = clk_get_parent(clk);
189	if (!mmc)
190		return -EINVAL;
191
192	/* And its rate */
193	mmc_rate = clk_get_rate(mmc);
194	if (!mmc_rate)
195		return -EINVAL;
196
197	/* Now, get the MMC parent (most likely some PLL) */
198	mmc_parent = clk_get_parent(mmc);
199	if (!mmc_parent)
200		return -EINVAL;
201
202	/* And its rate */
203	mmc_parent_rate = clk_get_rate(mmc_parent);
204	if (!mmc_parent_rate)
205		return -EINVAL;
206
207	/* Get MMC clock divider */
208	mmc_div = mmc_parent_rate / mmc_rate;
209
210	step = DIV_ROUND_CLOSEST(360, mmc_div);
211	return delay * step;
212}
213
214static int mmc_set_phase(struct clk_hw *hw, int degrees)
215{
216	struct clk *mmc, *mmc_parent, *clk = hw->clk;
217	struct mmc_phase *phase = to_mmc_phase(hw);
218	unsigned int mmc_rate, mmc_parent_rate;
219	unsigned long flags;
220	u32 value;
221	u8 delay;
222
223	/* Get the main MMC clock */
224	mmc = clk_get_parent(clk);
225	if (!mmc)
226		return -EINVAL;
227
228	/* And its rate */
229	mmc_rate = clk_get_rate(mmc);
230	if (!mmc_rate)
231		return -EINVAL;
232
233	/* Now, get the MMC parent (most likely some PLL) */
234	mmc_parent = clk_get_parent(mmc);
235	if (!mmc_parent)
236		return -EINVAL;
237
238	/* And its rate */
239	mmc_parent_rate = clk_get_rate(mmc_parent);
240	if (!mmc_parent_rate)
241		return -EINVAL;
242
243	if (degrees != 180) {
244		u16 step, mmc_div;
245
246		/* Get MMC clock divider */
247		mmc_div = mmc_parent_rate / mmc_rate;
248
249		/*
250		 * We can only outphase the clocks by multiple of the
251		 * PLL's period.
252		 *
253		 * Since the MMC clock in only a divider, and the
254		 * formula to get the outphasing in degrees is deg =
255		 * 360 * delta / period
256		 *
257		 * If we simplify this formula, we can see that the
258		 * only thing that we're concerned about is the number
259		 * of period we want to outphase our clock from, and
260		 * the divider set by the MMC clock.
261		 */
262		step = DIV_ROUND_CLOSEST(360, mmc_div);
263		delay = DIV_ROUND_CLOSEST(degrees, step);
264	} else {
265		delay = 0;
266	}
267
268	spin_lock_irqsave(phase->lock, flags);
269	value = readl(phase->reg);
270	value &= ~GENMASK(phase->offset + 3, phase->offset);
271	value |= delay << phase->offset;
272	writel(value, phase->reg);
273	spin_unlock_irqrestore(phase->lock, flags);
274
275	return 0;
276}
277
278static const struct clk_ops mmc_clk_ops = {
279	.get_phase	= mmc_get_phase,
280	.set_phase	= mmc_set_phase,
281};
282
283/*
284 * sunxi_mmc_setup - Common setup function for mmc module clocks
285 *
286 * The only difference between module clocks on different platforms is the
287 * width of the mux register bits and the valid values, which are passed in
288 * through struct factors_data. The phase clocks parts are identical.
289 */
290static void __init sunxi_mmc_setup(struct device_node *node,
291				   const struct factors_data *data,
292				   spinlock_t *lock)
293{
294	struct clk_onecell_data *clk_data;
295	const char *parent;
296	void __iomem *reg;
297	int i;
298
299	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
300	if (IS_ERR(reg)) {
301		pr_err("Couldn't map the %pOFn clock registers\n", node);
302		return;
303	}
304
305	clk_data = kmalloc(sizeof(*clk_data), GFP_KERNEL);
306	if (!clk_data)
307		return;
308
309	clk_data->clks = kcalloc(3, sizeof(*clk_data->clks), GFP_KERNEL);
310	if (!clk_data->clks)
311		goto err_free_data;
312
313	clk_data->clk_num = 3;
314	clk_data->clks[0] = sunxi_factors_register(node, data, lock, reg);
315	if (!clk_data->clks[0])
316		goto err_free_clks;
317
318	parent = __clk_get_name(clk_data->clks[0]);
319
320	for (i = 1; i < 3; i++) {
321		struct clk_init_data init = {
322			.num_parents	= 1,
323			.parent_names	= &parent,
324			.ops		= &mmc_clk_ops,
325		};
326		struct mmc_phase *phase;
327
328		phase = kmalloc(sizeof(*phase), GFP_KERNEL);
329		if (!phase)
330			continue;
331
332		phase->hw.init = &init;
333		phase->reg = reg;
334		phase->lock = lock;
335
336		if (i == 1)
337			phase->offset = 8;
338		else
339			phase->offset = 20;
340
341		if (of_property_read_string_index(node, "clock-output-names",
342						  i, &init.name))
343			init.name = node->name;
344
345		clk_data->clks[i] = clk_register(NULL, &phase->hw);
346		if (IS_ERR(clk_data->clks[i])) {
347			kfree(phase);
348			continue;
349		}
350	}
351
352	of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
353
354	return;
355
356err_free_clks:
357	kfree(clk_data->clks);
358err_free_data:
359	kfree(clk_data);
360}
361
362static DEFINE_SPINLOCK(sun4i_a10_mmc_lock);
363
364static void __init sun4i_a10_mmc_setup(struct device_node *node)
365{
366	sunxi_mmc_setup(node, &sun4i_a10_mod0_data, &sun4i_a10_mmc_lock);
367}
368CLK_OF_DECLARE(sun4i_a10_mmc, "allwinner,sun4i-a10-mmc-clk", sun4i_a10_mmc_setup);
369
370static DEFINE_SPINLOCK(sun9i_a80_mmc_lock);
371
372static void __init sun9i_a80_mmc_setup(struct device_node *node)
373{
374	sunxi_mmc_setup(node, &sun9i_a80_mod0_data, &sun9i_a80_mmc_lock);
375}
376CLK_OF_DECLARE(sun9i_a80_mmc, "allwinner,sun9i-a80-mmc-clk", sun9i_a80_mmc_setup);
377