xref: /rk3399_rockchip-uboot/drivers/clk/clk-uclass.c (revision 7423daa60eb30b6613dfc19a51c55de23fd4d703)
1f26c8a8eSSimon Glass /*
2f26c8a8eSSimon Glass  * Copyright (C) 2015 Google, Inc
3f26c8a8eSSimon Glass  * Written by Simon Glass <sjg@chromium.org>
4135aa950SStephen Warren  * Copyright (c) 2016, NVIDIA CORPORATION.
5f26c8a8eSSimon Glass  *
6f26c8a8eSSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
7f26c8a8eSSimon Glass  */
8f26c8a8eSSimon Glass 
9f26c8a8eSSimon Glass #include <common.h>
10f26c8a8eSSimon Glass #include <clk.h>
11135aa950SStephen Warren #include <clk-uclass.h>
12f26c8a8eSSimon Glass #include <dm.h>
13*7423daa6SSimon Glass #include <dt-structs.h>
14f26c8a8eSSimon Glass #include <errno.h>
15f26c8a8eSSimon Glass 
16e70cc438SSimon Glass DECLARE_GLOBAL_DATA_PTR;
17e70cc438SSimon Glass 
18135aa950SStephen Warren static inline struct clk_ops *clk_dev_ops(struct udevice *dev)
19f26c8a8eSSimon Glass {
20135aa950SStephen Warren 	return (struct clk_ops *)dev->driver->ops;
21f26c8a8eSSimon Glass }
22f26c8a8eSSimon Glass 
23e70cc438SSimon Glass #if CONFIG_IS_ENABLED(OF_CONTROL)
24135aa950SStephen Warren #ifdef CONFIG_SPL_BUILD
25*7423daa6SSimon Glass # if CONFIG_IS_ENABLED(OF_PLATDATA)
26*7423daa6SSimon Glass int clk_get_by_index_platdata(struct udevice *dev, int index,
27*7423daa6SSimon Glass 			      struct phandle_2_cell *cells, struct clk *clk)
28*7423daa6SSimon Glass {
29*7423daa6SSimon Glass 	int ret;
30*7423daa6SSimon Glass 
31*7423daa6SSimon Glass 	if (index != 0)
32*7423daa6SSimon Glass 		return -ENOSYS;
33*7423daa6SSimon Glass 	ret = uclass_get_device(UCLASS_CLK, 0, &clk->dev);
34*7423daa6SSimon Glass 	if (ret)
35*7423daa6SSimon Glass 		return ret;
36*7423daa6SSimon Glass 	clk->id = cells[0].id;
37*7423daa6SSimon Glass 
38*7423daa6SSimon Glass 	return 0;
39*7423daa6SSimon Glass }
40*7423daa6SSimon Glass # else
41135aa950SStephen Warren int clk_get_by_index(struct udevice *dev, int index, struct clk *clk)
42e70cc438SSimon Glass {
43e70cc438SSimon Glass 	int ret;
44a4b10c08SSimon Glass 	u32 cell[2];
45a4b10c08SSimon Glass 
46a4b10c08SSimon Glass 	if (index != 0)
47a4b10c08SSimon Glass 		return -ENOSYS;
48135aa950SStephen Warren 	assert(clk);
49135aa950SStephen Warren 	ret = uclass_get_device(UCLASS_CLK, 0, &clk->dev);
50a4b10c08SSimon Glass 	if (ret)
51a4b10c08SSimon Glass 		return ret;
52a4b10c08SSimon Glass 	ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, "clocks",
53a4b10c08SSimon Glass 				   cell, 2);
54a4b10c08SSimon Glass 	if (ret)
55a4b10c08SSimon Glass 		return ret;
56135aa950SStephen Warren 	clk->id = cell[1];
57135aa950SStephen Warren 	return 0;
58135aa950SStephen Warren }
59*7423daa6SSimon Glass # endif /* OF_PLATDATA */
60e70cc438SSimon Glass 
61135aa950SStephen Warren int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk)
62135aa950SStephen Warren {
63135aa950SStephen Warren 	return -ENOSYS;
64135aa950SStephen Warren }
65135aa950SStephen Warren #else
66135aa950SStephen Warren static int clk_of_xlate_default(struct clk *clk,
67135aa950SStephen Warren 				struct fdtdec_phandle_args *args)
68135aa950SStephen Warren {
69135aa950SStephen Warren 	debug("%s(clk=%p)\n", __func__, clk);
70135aa950SStephen Warren 
71135aa950SStephen Warren 	if (args->args_count > 1) {
72135aa950SStephen Warren 		debug("Invaild args_count: %d\n", args->args_count);
73135aa950SStephen Warren 		return -EINVAL;
74135aa950SStephen Warren 	}
75135aa950SStephen Warren 
76135aa950SStephen Warren 	if (args->args_count)
77135aa950SStephen Warren 		clk->id = args->args[0];
78135aa950SStephen Warren 	else
79135aa950SStephen Warren 		clk->id = 0;
80135aa950SStephen Warren 
81135aa950SStephen Warren 	return 0;
82135aa950SStephen Warren }
83135aa950SStephen Warren 
84135aa950SStephen Warren int clk_get_by_index(struct udevice *dev, int index, struct clk *clk)
85135aa950SStephen Warren {
86135aa950SStephen Warren 	int ret;
87135aa950SStephen Warren 	struct fdtdec_phandle_args args;
88135aa950SStephen Warren 	struct udevice *dev_clk;
89135aa950SStephen Warren 	struct clk_ops *ops;
90135aa950SStephen Warren 
91135aa950SStephen Warren 	debug("%s(dev=%p, index=%d, clk=%p)\n", __func__, dev, index, clk);
92135aa950SStephen Warren 
93135aa950SStephen Warren 	assert(clk);
94e70cc438SSimon Glass 	ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset,
95e70cc438SSimon Glass 					     "clocks", "#clock-cells", 0, index,
96e70cc438SSimon Glass 					     &args);
97e70cc438SSimon Glass 	if (ret) {
98e70cc438SSimon Glass 		debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
99e70cc438SSimon Glass 		      __func__, ret);
100e70cc438SSimon Glass 		return ret;
101e70cc438SSimon Glass 	}
102e70cc438SSimon Glass 
103135aa950SStephen Warren 	ret = uclass_get_device_by_of_offset(UCLASS_CLK, args.node, &dev_clk);
104e70cc438SSimon Glass 	if (ret) {
105e70cc438SSimon Glass 		debug("%s: uclass_get_device_by_of_offset failed: err=%d\n",
106e70cc438SSimon Glass 		      __func__, ret);
107e70cc438SSimon Glass 		return ret;
108e70cc438SSimon Glass 	}
109135aa950SStephen Warren 	ops = clk_dev_ops(dev_clk);
110135aa950SStephen Warren 
111135aa950SStephen Warren 	if (ops->of_xlate)
112135aa950SStephen Warren 		ret = ops->of_xlate(clk, &args);
113135aa950SStephen Warren 	else
114135aa950SStephen Warren 		ret = clk_of_xlate_default(clk, &args);
115135aa950SStephen Warren 	if (ret) {
116135aa950SStephen Warren 		debug("of_xlate() failed: %d\n", ret);
117135aa950SStephen Warren 		return ret;
118135aa950SStephen Warren 	}
119135aa950SStephen Warren 
120135aa950SStephen Warren 	return clk_request(dev_clk, clk);
121135aa950SStephen Warren }
122135aa950SStephen Warren 
123135aa950SStephen Warren int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk)
124135aa950SStephen Warren {
125135aa950SStephen Warren 	int index;
126135aa950SStephen Warren 
127135aa950SStephen Warren 	debug("%s(dev=%p, name=%s, clk=%p)\n", __func__, dev, name, clk);
128135aa950SStephen Warren 
129135aa950SStephen Warren 	index = fdt_find_string(gd->fdt_blob, dev->of_offset, "clock-names",
130135aa950SStephen Warren 				name);
131135aa950SStephen Warren 	if (index < 0) {
132135aa950SStephen Warren 		debug("fdt_find_string() failed: %d\n", index);
133135aa950SStephen Warren 		return index;
134135aa950SStephen Warren 	}
135135aa950SStephen Warren 
136135aa950SStephen Warren 	return clk_get_by_index(dev, index, clk);
137e70cc438SSimon Glass }
138*7423daa6SSimon Glass #endif /* CONFIG_SPL_BUILD */
139*7423daa6SSimon Glass #endif /* OF_CONTROL */
140135aa950SStephen Warren 
141135aa950SStephen Warren int clk_request(struct udevice *dev, struct clk *clk)
142135aa950SStephen Warren {
143135aa950SStephen Warren 	struct clk_ops *ops = clk_dev_ops(dev);
144135aa950SStephen Warren 
145135aa950SStephen Warren 	debug("%s(dev=%p, clk=%p)\n", __func__, dev, clk);
146135aa950SStephen Warren 
147135aa950SStephen Warren 	clk->dev = dev;
148135aa950SStephen Warren 
149135aa950SStephen Warren 	if (!ops->request)
150135aa950SStephen Warren 		return 0;
151135aa950SStephen Warren 
152135aa950SStephen Warren 	return ops->request(clk);
153135aa950SStephen Warren }
154135aa950SStephen Warren 
155135aa950SStephen Warren int clk_free(struct clk *clk)
156135aa950SStephen Warren {
157135aa950SStephen Warren 	struct clk_ops *ops = clk_dev_ops(clk->dev);
158135aa950SStephen Warren 
159135aa950SStephen Warren 	debug("%s(clk=%p)\n", __func__, clk);
160135aa950SStephen Warren 
161135aa950SStephen Warren 	if (!ops->free)
162135aa950SStephen Warren 		return 0;
163135aa950SStephen Warren 
164135aa950SStephen Warren 	return ops->free(clk);
165135aa950SStephen Warren }
166135aa950SStephen Warren 
167135aa950SStephen Warren ulong clk_get_rate(struct clk *clk)
168135aa950SStephen Warren {
169135aa950SStephen Warren 	struct clk_ops *ops = clk_dev_ops(clk->dev);
170135aa950SStephen Warren 
171135aa950SStephen Warren 	debug("%s(clk=%p)\n", __func__, clk);
172135aa950SStephen Warren 
173135aa950SStephen Warren 	if (!ops->get_rate)
174135aa950SStephen Warren 		return -ENOSYS;
175135aa950SStephen Warren 
176135aa950SStephen Warren 	return ops->get_rate(clk);
177135aa950SStephen Warren }
178135aa950SStephen Warren 
179135aa950SStephen Warren ulong clk_set_rate(struct clk *clk, ulong rate)
180135aa950SStephen Warren {
181135aa950SStephen Warren 	struct clk_ops *ops = clk_dev_ops(clk->dev);
182135aa950SStephen Warren 
183135aa950SStephen Warren 	debug("%s(clk=%p, rate=%lu)\n", __func__, clk, rate);
184135aa950SStephen Warren 
185135aa950SStephen Warren 	if (!ops->set_rate)
186135aa950SStephen Warren 		return -ENOSYS;
187135aa950SStephen Warren 
188135aa950SStephen Warren 	return ops->set_rate(clk, rate);
189135aa950SStephen Warren }
190135aa950SStephen Warren 
191135aa950SStephen Warren int clk_enable(struct clk *clk)
192135aa950SStephen Warren {
193135aa950SStephen Warren 	struct clk_ops *ops = clk_dev_ops(clk->dev);
194135aa950SStephen Warren 
195135aa950SStephen Warren 	debug("%s(clk=%p)\n", __func__, clk);
196135aa950SStephen Warren 
197135aa950SStephen Warren 	if (!ops->enable)
198135aa950SStephen Warren 		return -ENOSYS;
199135aa950SStephen Warren 
200135aa950SStephen Warren 	return ops->enable(clk);
201135aa950SStephen Warren }
202135aa950SStephen Warren 
203135aa950SStephen Warren int clk_disable(struct clk *clk)
204135aa950SStephen Warren {
205135aa950SStephen Warren 	struct clk_ops *ops = clk_dev_ops(clk->dev);
206135aa950SStephen Warren 
207135aa950SStephen Warren 	debug("%s(clk=%p)\n", __func__, clk);
208135aa950SStephen Warren 
209135aa950SStephen Warren 	if (!ops->disable)
210135aa950SStephen Warren 		return -ENOSYS;
211135aa950SStephen Warren 
212135aa950SStephen Warren 	return ops->disable(clk);
213135aa950SStephen Warren }
214e70cc438SSimon Glass 
215f26c8a8eSSimon Glass UCLASS_DRIVER(clk) = {
216f26c8a8eSSimon Glass 	.id		= UCLASS_CLK,
217f26c8a8eSSimon Glass 	.name		= "clk",
218f26c8a8eSSimon Glass };
219