blob: 03ceb2efd532d0ecc5013f63f12ea0b0346c13ff [file] [log] [blame]
Paul Walmsleydf791b32010-01-26 20:13:04 -07001/*
2 * clkt_clksel.c - OMAP2/3/4 clksel clock functions
3 *
4 * Copyright (C) 2005-2008 Texas Instruments, Inc.
5 * Copyright (C) 2004-2010 Nokia Corporation
6 *
7 * Contacts:
8 * Richard Woodruff <r-woodruff2@ti.com>
9 * Paul Walmsley
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 *
Paul Walmsley435699d2010-05-18 18:40:24 -060015 *
16 * clksel clocks are clocks that do not have a fixed parent, or that
17 * can divide their parent's rate, or possibly both at the same time, based
18 * on the contents of a hardware register bitfield.
19 *
20 * All of the various mux and divider settings can be encoded into
21 * struct clksel* data structures, and then these can be autogenerated
22 * from some hardware database for each new chip generation. This
23 * should avoid the need to write, review, and validate a lot of new
24 * clock code for each new chip, since it can be exported from the SoC
25 * design flow. This is now done on OMAP4.
26 *
27 * The fusion of mux and divider clocks is a software creation. In
28 * hardware reality, the multiplexer (parent selection) and the
29 * divider exist separately. XXX At some point these clksel clocks
30 * should be split into "divider" clocks and "mux" clocks to better
31 * match the hardware.
32 *
33 * (The name "clksel" comes from the name of the corresponding
34 * register field in the OMAP2/3 family of SoCs.)
Paul Walmsleydf791b32010-01-26 20:13:04 -070035 *
36 * XXX Currently these clocks are only used in the OMAP2/3/4 code, but
37 * many of the OMAP1 clocks should be convertible to use this
38 * mechanism.
39 */
40#undef DEBUG
41
42#include <linux/kernel.h>
43#include <linux/errno.h>
Mike Turquette32cc0022012-11-10 16:58:41 -070044#ifdef CONFIG_COMMON_CLK
45#include <linux/clk-provider.h>
46#else
Paul Walmsleydf791b32010-01-26 20:13:04 -070047#include <linux/clk.h>
Mike Turquette32cc0022012-11-10 16:58:41 -070048#endif
Paul Walmsleydf791b32010-01-26 20:13:04 -070049#include <linux/io.h>
Tony Lindgrend9a5f4d2012-03-07 17:28:01 -080050#include <linux/bug.h>
Paul Walmsleydf791b32010-01-26 20:13:04 -070051
Paul Walmsleydf791b32010-01-26 20:13:04 -070052#include "clock.h"
Paul Walmsleydf791b32010-01-26 20:13:04 -070053
54/* Private functions */
55
56/**
Paul Walmsley435699d2010-05-18 18:40:24 -060057 * _get_clksel_by_parent() - return clksel struct for a given clk & parent
Paul Walmsleydf791b32010-01-26 20:13:04 -070058 * @clk: OMAP struct clk ptr to inspect
59 * @src_clk: OMAP struct clk ptr of the parent clk to search for
60 *
61 * Scan the struct clksel array associated with the clock to find
62 * the element associated with the supplied parent clock address.
63 * Returns a pointer to the struct clksel on success or NULL on error.
64 */
Mike Turquette32cc0022012-11-10 16:58:41 -070065#ifdef CONFIG_COMMON_CLK
66static const struct clksel *_get_clksel_by_parent(struct clk_hw_omap *clk,
67#else
Paul Walmsley435699d2010-05-18 18:40:24 -060068static const struct clksel *_get_clksel_by_parent(struct clk *clk,
Mike Turquette32cc0022012-11-10 16:58:41 -070069#endif
Paul Walmsley435699d2010-05-18 18:40:24 -060070 struct clk *src_clk)
Paul Walmsleydf791b32010-01-26 20:13:04 -070071{
72 const struct clksel *clks;
73
Mike Turquette32cc0022012-11-10 16:58:41 -070074 if (!src_clk)
75 return NULL;
76
Paul Walmsley435699d2010-05-18 18:40:24 -060077 for (clks = clk->clksel; clks->parent; clks++)
Paul Walmsleydf791b32010-01-26 20:13:04 -070078 if (clks->parent == src_clk)
79 break; /* Found the requested parent */
Paul Walmsleydf791b32010-01-26 20:13:04 -070080
81 if (!clks->parent) {
Paul Walmsley435699d2010-05-18 18:40:24 -060082 /* This indicates a data problem */
Paul Walmsley7852ec02012-07-26 00:54:26 -060083 WARN(1, "clock: %s: could not find parent clock %s in clksel array\n",
Mike Turquette32cc0022012-11-10 16:58:41 -070084#ifdef CONFIG_COMMON_CLK
85 __clk_get_name(clk->hw.clk), __clk_get_name(src_clk));
86#else
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -060087 __clk_get_name(clk), __clk_get_name(src_clk));
Mike Turquette32cc0022012-11-10 16:58:41 -070088#endif
Paul Walmsleydf791b32010-01-26 20:13:04 -070089 return NULL;
90 }
91
92 return clks;
93}
94
Paul Walmsleyd74b4942010-05-18 18:40:24 -060095/**
Paul Walmsley435699d2010-05-18 18:40:24 -060096 * _get_div_and_fieldval() - find the new clksel divisor and field value to use
Paul Walmsleyd74b4942010-05-18 18:40:24 -060097 * @src_clk: planned new parent struct clk *
98 * @clk: struct clk * that is being reparented
99 * @field_val: pointer to a u32 to contain the register data for the divisor
100 *
101 * Given an intended new parent struct clk * @src_clk, and the struct
102 * clk * @clk to the clock that is being reparented, find the
103 * appropriate rate divisor for the new clock (returned as the return
104 * value), and the corresponding register bitfield data to program to
105 * reach that divisor (returned in the u32 pointed to by @field_val).
106 * Returns 0 on error, or returns the newly-selected divisor upon
107 * success (in this latter case, the corresponding register bitfield
108 * value is passed back in the variable pointed to by @field_val)
Paul Walmsleydf791b32010-01-26 20:13:04 -0700109 */
Mike Turquette32cc0022012-11-10 16:58:41 -0700110#ifndef CONFIG_COMMON_CLK
Paul Walmsley435699d2010-05-18 18:40:24 -0600111static u8 _get_div_and_fieldval(struct clk *src_clk, struct clk *clk,
112 u32 *field_val)
Paul Walmsleydf791b32010-01-26 20:13:04 -0700113{
114 const struct clksel *clks;
Felipe Balbi405505c2011-01-16 13:22:03 +0200115 const struct clksel_rate *clkr, *max_clkr = NULL;
Paul Walmsleyd74b4942010-05-18 18:40:24 -0600116 u8 max_div = 0;
Paul Walmsleydf791b32010-01-26 20:13:04 -0700117
Paul Walmsley435699d2010-05-18 18:40:24 -0600118 clks = _get_clksel_by_parent(clk, src_clk);
Paul Walmsleydf791b32010-01-26 20:13:04 -0700119 if (!clks)
120 return 0;
121
Paul Walmsleyd74b4942010-05-18 18:40:24 -0600122 /*
123 * Find the highest divisor (e.g., the one resulting in the
124 * lowest rate) to use as the default. This should avoid
125 * clock rates that are too high for the device. XXX A better
126 * solution here would be to try to determine if there is a
127 * divisor matching the original clock rate before the parent
128 * switch, and if it cannot be found, to fall back to the
129 * highest divisor.
130 */
Paul Walmsleydf791b32010-01-26 20:13:04 -0700131 for (clkr = clks->rates; clkr->div; clkr++) {
Paul Walmsleyd74b4942010-05-18 18:40:24 -0600132 if (!(clkr->flags & cpu_mask))
133 continue;
134
135 if (clkr->div > max_div) {
136 max_div = clkr->div;
137 max_clkr = clkr;
138 }
Paul Walmsleydf791b32010-01-26 20:13:04 -0700139 }
140
Paul Walmsleyd74b4942010-05-18 18:40:24 -0600141 if (max_div == 0) {
Paul Walmsley435699d2010-05-18 18:40:24 -0600142 /* This indicates an error in the clksel data */
Paul Walmsley7852ec02012-07-26 00:54:26 -0600143 WARN(1, "clock: %s: could not find divisor for parent %s\n",
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600144 __clk_get_name(clk),
145 __clk_get_name(__clk_get_parent(src_clk)));
Paul Walmsleydf791b32010-01-26 20:13:04 -0700146 return 0;
147 }
148
Paul Walmsleyd74b4942010-05-18 18:40:24 -0600149 *field_val = max_clkr->val;
Paul Walmsleydf791b32010-01-26 20:13:04 -0700150
Paul Walmsleyd74b4942010-05-18 18:40:24 -0600151 return max_div;
Paul Walmsleydf791b32010-01-26 20:13:04 -0700152}
Mike Turquette32cc0022012-11-10 16:58:41 -0700153#endif
Paul Walmsleydf791b32010-01-26 20:13:04 -0700154
Paul Walmsley435699d2010-05-18 18:40:24 -0600155/**
156 * _write_clksel_reg() - program a clock's clksel register in hardware
157 * @clk: struct clk * to program
158 * @v: clksel bitfield value to program (with LSB at bit 0)
159 *
160 * Shift the clksel register bitfield value @v to its appropriate
161 * location in the clksel register and write it in. This function
162 * will ensure that the write to the clksel_reg reaches its
163 * destination before returning -- important since PRM and CM register
164 * accesses can be quite slow compared to ARM cycles -- but does not
165 * take into account any time the hardware might take to switch the
166 * clock source.
167 */
Mike Turquette32cc0022012-11-10 16:58:41 -0700168#ifdef CONFIG_COMMON_CLK
169static void _write_clksel_reg(struct clk_hw_omap *clk, u32 field_val)
170#else
Paul Walmsley435699d2010-05-18 18:40:24 -0600171static void _write_clksel_reg(struct clk *clk, u32 field_val)
Mike Turquette32cc0022012-11-10 16:58:41 -0700172#endif
Paul Walmsley435699d2010-05-18 18:40:24 -0600173{
174 u32 v;
175
176 v = __raw_readl(clk->clksel_reg);
177 v &= ~clk->clksel_mask;
178 v |= field_val << __ffs(clk->clksel_mask);
179 __raw_writel(v, clk->clksel_reg);
180
181 v = __raw_readl(clk->clksel_reg); /* OCP barrier */
182}
183
184/**
185 * _clksel_to_divisor() - turn clksel field value into integer divider
186 * @clk: OMAP struct clk to use
187 * @field_val: register field value to find
188 *
189 * Given a struct clk of a rate-selectable clksel clock, and a register field
190 * value to search for, find the corresponding clock divisor. The register
191 * field value should be pre-masked and shifted down so the LSB is at bit 0
192 * before calling. Returns 0 on error or returns the actual integer divisor
193 * upon success.
194 */
Mike Turquette32cc0022012-11-10 16:58:41 -0700195#ifdef CONFIG_COMMON_CLK
196static u32 _clksel_to_divisor(struct clk_hw_omap *clk, u32 field_val)
197#else
Paul Walmsley435699d2010-05-18 18:40:24 -0600198static u32 _clksel_to_divisor(struct clk *clk, u32 field_val)
Mike Turquette32cc0022012-11-10 16:58:41 -0700199#endif
Paul Walmsley435699d2010-05-18 18:40:24 -0600200{
201 const struct clksel *clks;
202 const struct clksel_rate *clkr;
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600203 struct clk *parent;
Paul Walmsley435699d2010-05-18 18:40:24 -0600204
Mike Turquette32cc0022012-11-10 16:58:41 -0700205#ifdef CONFIG_COMMON_CLK
206 parent = __clk_get_parent(clk->hw.clk);
207#else
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600208 parent = __clk_get_parent(clk);
Mike Turquette32cc0022012-11-10 16:58:41 -0700209#endif
210
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600211 clks = _get_clksel_by_parent(clk, parent);
Paul Walmsley435699d2010-05-18 18:40:24 -0600212 if (!clks)
213 return 0;
214
215 for (clkr = clks->rates; clkr->div; clkr++) {
216 if (!(clkr->flags & cpu_mask))
217 continue;
218
219 if (clkr->val == field_val)
220 break;
221 }
222
223 if (!clkr->div) {
224 /* This indicates a data error */
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600225 WARN(1, "clock: %s: could not find fieldval %d for parent %s\n",
Mike Turquette32cc0022012-11-10 16:58:41 -0700226#ifdef CONFIG_COMMON_CLK
227 __clk_get_name(clk->hw.clk), field_val,
228 __clk_get_name(parent));
229#else
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600230 __clk_get_name(clk), field_val, __clk_get_name(parent));
Mike Turquette32cc0022012-11-10 16:58:41 -0700231#endif
Paul Walmsley435699d2010-05-18 18:40:24 -0600232 return 0;
233 }
234
235 return clkr->div;
236}
237
238/**
239 * _divisor_to_clksel() - turn clksel integer divisor into a field value
240 * @clk: OMAP struct clk to use
241 * @div: integer divisor to search for
242 *
243 * Given a struct clk of a rate-selectable clksel clock, and a clock
244 * divisor, find the corresponding register field value. Returns the
245 * register field value _before_ left-shifting (i.e., LSB is at bit
246 * 0); or returns 0xFFFFFFFF (~0) upon error.
247 */
Mike Turquette32cc0022012-11-10 16:58:41 -0700248#ifdef CONFIG_COMMON_CLK
249static u32 _divisor_to_clksel(struct clk_hw_omap *clk, u32 div)
250#else
Paul Walmsley435699d2010-05-18 18:40:24 -0600251static u32 _divisor_to_clksel(struct clk *clk, u32 div)
Mike Turquette32cc0022012-11-10 16:58:41 -0700252#endif
Paul Walmsley435699d2010-05-18 18:40:24 -0600253{
254 const struct clksel *clks;
255 const struct clksel_rate *clkr;
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600256 struct clk *parent;
Paul Walmsley435699d2010-05-18 18:40:24 -0600257
258 /* should never happen */
259 WARN_ON(div == 0);
260
Mike Turquette32cc0022012-11-10 16:58:41 -0700261#ifdef CONFIG_COMMON_CLK
262 parent = __clk_get_parent(clk->hw.clk);
263#else
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600264 parent = __clk_get_parent(clk);
Mike Turquette32cc0022012-11-10 16:58:41 -0700265#endif
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600266 clks = _get_clksel_by_parent(clk, parent);
Paul Walmsley435699d2010-05-18 18:40:24 -0600267 if (!clks)
268 return ~0;
269
270 for (clkr = clks->rates; clkr->div; clkr++) {
271 if (!(clkr->flags & cpu_mask))
272 continue;
273
274 if (clkr->div == div)
275 break;
276 }
277
278 if (!clkr->div) {
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600279 pr_err("clock: %s: could not find divisor %d for parent %s\n",
Mike Turquette32cc0022012-11-10 16:58:41 -0700280#ifdef CONFIG_COMMON_CLK
281 __clk_get_name(clk->hw.clk), div,
282 __clk_get_name(parent));
283#else
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600284 __clk_get_name(clk), div, __clk_get_name(parent));
Mike Turquette32cc0022012-11-10 16:58:41 -0700285#endif
Paul Walmsley435699d2010-05-18 18:40:24 -0600286 return ~0;
287 }
288
289 return clkr->val;
290}
291
292/**
293 * _read_divisor() - get current divisor applied to parent clock (from hdwr)
294 * @clk: OMAP struct clk to use.
295 *
296 * Read the current divisor register value for @clk that is programmed
297 * into the hardware, convert it into the actual divisor value, and
298 * return it; or return 0 on error.
299 */
Mike Turquette32cc0022012-11-10 16:58:41 -0700300#ifdef CONFIG_COMMON_CLK
301static u32 _read_divisor(struct clk_hw_omap *clk)
302#else
Paul Walmsley435699d2010-05-18 18:40:24 -0600303static u32 _read_divisor(struct clk *clk)
Mike Turquette32cc0022012-11-10 16:58:41 -0700304#endif
Paul Walmsley435699d2010-05-18 18:40:24 -0600305{
306 u32 v;
307
308 if (!clk->clksel || !clk->clksel_mask)
309 return 0;
310
311 v = __raw_readl(clk->clksel_reg);
312 v &= clk->clksel_mask;
313 v >>= __ffs(clk->clksel_mask);
314
315 return _clksel_to_divisor(clk, v);
316}
Paul Walmsleydf791b32010-01-26 20:13:04 -0700317
318/* Public functions */
319
320/**
Paul Walmsley435699d2010-05-18 18:40:24 -0600321 * omap2_clksel_round_rate_div() - find divisor for the given clock and rate
Paul Walmsleydf791b32010-01-26 20:13:04 -0700322 * @clk: OMAP struct clk to use
323 * @target_rate: desired clock rate
324 * @new_div: ptr to where we should store the divisor
325 *
326 * Finds 'best' divider value in an array based on the source and target
327 * rates. The divider array must be sorted with smallest divider first.
Paul Walmsley435699d2010-05-18 18:40:24 -0600328 * This function is also used by the DPLL3 M2 divider code.
Paul Walmsleydf791b32010-01-26 20:13:04 -0700329 *
330 * Returns the rounded clock rate or returns 0xffffffff on error.
331 */
Mike Turquette32cc0022012-11-10 16:58:41 -0700332#ifdef CONFIG_COMMON_CLK
333u32 omap2_clksel_round_rate_div(struct clk_hw_omap *clk,
334 unsigned long target_rate,
335#else
Paul Walmsleydf791b32010-01-26 20:13:04 -0700336u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
Mike Turquette32cc0022012-11-10 16:58:41 -0700337#endif
Paul Walmsleydf791b32010-01-26 20:13:04 -0700338 u32 *new_div)
339{
340 unsigned long test_rate;
341 const struct clksel *clks;
342 const struct clksel_rate *clkr;
343 u32 last_div = 0;
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600344 struct clk *parent;
345 unsigned long parent_rate;
346 const char *clk_name;
347
Mike Turquette32cc0022012-11-10 16:58:41 -0700348#ifdef CONFIG_COMMON_CLK
349 parent = __clk_get_parent(clk->hw.clk);
350 clk_name = __clk_get_name(clk->hw.clk);
351#else
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600352 parent = __clk_get_parent(clk);
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600353 clk_name = __clk_get_name(clk);
Mike Turquette32cc0022012-11-10 16:58:41 -0700354#endif
355 parent_rate = __clk_get_rate(parent);
Paul Walmsleydf791b32010-01-26 20:13:04 -0700356
Paul Walmsley435699d2010-05-18 18:40:24 -0600357 if (!clk->clksel || !clk->clksel_mask)
358 return ~0;
359
Paul Walmsleydf791b32010-01-26 20:13:04 -0700360 pr_debug("clock: clksel_round_rate_div: %s target_rate %ld\n",
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600361 clk_name, target_rate);
Paul Walmsleydf791b32010-01-26 20:13:04 -0700362
363 *new_div = 1;
364
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600365 clks = _get_clksel_by_parent(clk, parent);
Paul Walmsleydf791b32010-01-26 20:13:04 -0700366 if (!clks)
367 return ~0;
368
369 for (clkr = clks->rates; clkr->div; clkr++) {
370 if (!(clkr->flags & cpu_mask))
371 continue;
372
373 /* Sanity check */
374 if (clkr->div <= last_div)
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600375 pr_err("clock: %s: clksel_rate table not sorted\n",
376 clk_name);
Paul Walmsleydf791b32010-01-26 20:13:04 -0700377
378 last_div = clkr->div;
379
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600380 test_rate = parent_rate / clkr->div;
Paul Walmsleydf791b32010-01-26 20:13:04 -0700381
382 if (test_rate <= target_rate)
383 break; /* found it */
384 }
385
386 if (!clkr->div) {
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600387 pr_err("clock: %s: could not find divisor for target rate %ld for parent %s\n",
388 clk_name, target_rate, __clk_get_name(parent));
Paul Walmsleydf791b32010-01-26 20:13:04 -0700389 return ~0;
390 }
391
392 *new_div = clkr->div;
393
394 pr_debug("clock: new_div = %d, new_rate = %ld\n", *new_div,
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600395 (parent_rate / clkr->div));
Paul Walmsleydf791b32010-01-26 20:13:04 -0700396
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600397 return parent_rate / clkr->div;
Paul Walmsleydf791b32010-01-26 20:13:04 -0700398}
399
Paul Walmsley435699d2010-05-18 18:40:24 -0600400/*
401 * Clocktype interface functions to the OMAP clock code
402 * (i.e., those used in struct clk field function pointers, etc.)
403 */
404
Mike Turquette32cc0022012-11-10 16:58:41 -0700405#ifdef CONFIG_COMMON_CLK
406/**
407 * omap2_clksel_find_parent_index() - return the array index of the current
408 * hardware parent of @hw
409 * @hw: struct clk_hw * to find the current hardware parent of
410 *
411 * Given a struct clk_hw pointer @hw to the 'hw' member of a struct
412 * clk_hw_omap record representing a source-selectable hardware clock,
413 * read the hardware register and determine what its parent is
414 * currently set to. Intended to be called only by the common clock
415 * framework struct clk_hw_ops.get_parent function pointer. Return
416 * the array index of this parent clock upon success -- there is no
417 * way to return an error, so if we encounter an error, just WARN()
418 * and pretend that we know that we're doing.
419 */
420u8 omap2_clksel_find_parent_index(struct clk_hw *hw)
421{
422 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
423 const struct clksel *clks;
424 const struct clksel_rate *clkr;
425 u32 r, found = 0;
426 struct clk *parent;
427 const char *clk_name;
428 int ret = 0, f = 0;
429
430 parent = __clk_get_parent(hw->clk);
431 clk_name = __clk_get_name(hw->clk);
432
433 /* XXX should be able to return an error */
434 WARN((!clk->clksel || !clk->clksel_mask),
435 "clock: %s: attempt to call on a non-clksel clock", clk_name);
436
437 r = __raw_readl(clk->clksel_reg) & clk->clksel_mask;
438 r >>= __ffs(clk->clksel_mask);
439
440 for (clks = clk->clksel; clks->parent && !found; clks++) {
441 for (clkr = clks->rates; clkr->div && !found; clkr++) {
442 if (!(clkr->flags & cpu_mask))
443 continue;
444
445 if (clkr->val == r) {
446 found = 1;
447 ret = f;
448 }
449 }
450 f++;
451 }
452
453 /* This indicates a data error */
454 WARN(!found, "clock: %s: init parent: could not find regval %0x\n",
455 clk_name, r);
456
457 return ret;
458}
459
460#else
461
Paul Walmsleydf791b32010-01-26 20:13:04 -0700462/**
Paul Walmsley435699d2010-05-18 18:40:24 -0600463 * omap2_init_clksel_parent() - set a clksel clk's parent field from the hdwr
464 * @clk: OMAP clock struct ptr to use
465 *
466 * Given a pointer @clk to a source-selectable struct clk, read the
467 * hardware register and determine what its parent is currently set
468 * to. Update @clk's .parent field with the appropriate clk ptr. No
469 * return value.
470 */
471void omap2_init_clksel_parent(struct clk *clk)
472{
473 const struct clksel *clks;
474 const struct clksel_rate *clkr;
475 u32 r, found = 0;
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600476 struct clk *parent;
477 const char *clk_name;
Paul Walmsley435699d2010-05-18 18:40:24 -0600478
479 if (!clk->clksel || !clk->clksel_mask)
480 return;
481
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600482 parent = __clk_get_parent(clk);
483 clk_name = __clk_get_name(clk);
484
Paul Walmsley435699d2010-05-18 18:40:24 -0600485 r = __raw_readl(clk->clksel_reg) & clk->clksel_mask;
486 r >>= __ffs(clk->clksel_mask);
487
488 for (clks = clk->clksel; clks->parent && !found; clks++) {
489 for (clkr = clks->rates; clkr->div && !found; clkr++) {
490 if (!(clkr->flags & cpu_mask))
491 continue;
492
493 if (clkr->val == r) {
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600494 if (parent != clks->parent) {
Paul Walmsley7852ec02012-07-26 00:54:26 -0600495 pr_debug("clock: %s: inited parent to %s (was %s)\n",
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600496 clk_name,
497 __clk_get_name(clks->parent),
498 ((parent) ?
499 __clk_get_name(parent) :
500 "NULL"));
Paul Walmsley435699d2010-05-18 18:40:24 -0600501 clk_reparent(clk, clks->parent);
Peter Senna Tschudinc09fcc432012-09-18 18:36:11 +0200502 }
Paul Walmsley435699d2010-05-18 18:40:24 -0600503 found = 1;
504 }
505 }
506 }
507
508 /* This indicates a data error */
509 WARN(!found, "clock: %s: init parent: could not find regval %0x\n",
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600510 clk_name, r);
Paul Walmsley435699d2010-05-18 18:40:24 -0600511
512 return;
513}
514
Mike Turquette32cc0022012-11-10 16:58:41 -0700515#endif
516
Paul Walmsley435699d2010-05-18 18:40:24 -0600517/**
518 * omap2_clksel_recalc() - function ptr to pass via struct clk .recalc field
519 * @clk: struct clk *
520 *
521 * This function is intended to be called only by the clock framework.
522 * Each clksel clock should have its struct clk .recalc field set to this
523 * function. Returns the clock's current rate, based on its parent's rate
524 * and its current divisor setting in the hardware.
525 */
Mike Turquette32cc0022012-11-10 16:58:41 -0700526#ifdef CONFIG_COMMON_CLK
527unsigned long omap2_clksel_recalc(struct clk_hw *hw, unsigned long parent_rate)
528{
529 unsigned long rate;
530 u32 div = 0;
531 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
532
533 if (!parent_rate)
534 return 0;
535
536 div = _read_divisor(clk);
537 if (!div)
538 rate = parent_rate;
539 else
540 rate = parent_rate / div;
541
542 pr_debug("%s: recalc'd %s's rate to %lu (div %d)\n", __func__,
543 __clk_get_name(hw->clk), rate, div);
544
545 return rate;
546}
547#else
Paul Walmsley435699d2010-05-18 18:40:24 -0600548unsigned long omap2_clksel_recalc(struct clk *clk)
549{
550 unsigned long rate;
551 u32 div = 0;
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600552 struct clk *parent;
Paul Walmsley435699d2010-05-18 18:40:24 -0600553
554 div = _read_divisor(clk);
555 if (div == 0)
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600556 return __clk_get_rate(clk);
Paul Walmsley435699d2010-05-18 18:40:24 -0600557
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600558 parent = __clk_get_parent(clk);
559 rate = __clk_get_rate(parent) / div;
Paul Walmsley435699d2010-05-18 18:40:24 -0600560
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600561 pr_debug("clock: %s: recalc'd rate is %ld (div %d)\n",
562 __clk_get_name(clk), rate, div);
Paul Walmsley435699d2010-05-18 18:40:24 -0600563
564 return rate;
565}
Mike Turquette32cc0022012-11-10 16:58:41 -0700566#endif
Paul Walmsley435699d2010-05-18 18:40:24 -0600567
568/**
569 * omap2_clksel_round_rate() - find rounded rate for the given clock and rate
Paul Walmsleydf791b32010-01-26 20:13:04 -0700570 * @clk: OMAP struct clk to use
571 * @target_rate: desired clock rate
572 *
Paul Walmsley435699d2010-05-18 18:40:24 -0600573 * This function is intended to be called only by the clock framework.
Paul Walmsleydf791b32010-01-26 20:13:04 -0700574 * Finds best target rate based on the source clock and possible dividers.
575 * rates. The divider array must be sorted with smallest divider first.
Paul Walmsleydf791b32010-01-26 20:13:04 -0700576 *
577 * Returns the rounded clock rate or returns 0xffffffff on error.
578 */
Mike Turquette32cc0022012-11-10 16:58:41 -0700579#ifdef CONFIG_COMMON_CLK
580long omap2_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate,
581 unsigned long *parent_rate)
582{
583 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
584#else
Paul Walmsleydf791b32010-01-26 20:13:04 -0700585long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate)
586{
Mike Turquette32cc0022012-11-10 16:58:41 -0700587#endif
Paul Walmsleydf791b32010-01-26 20:13:04 -0700588 u32 new_div;
589
590 return omap2_clksel_round_rate_div(clk, target_rate, &new_div);
591}
592
Paul Walmsleydf791b32010-01-26 20:13:04 -0700593/**
Paul Walmsley435699d2010-05-18 18:40:24 -0600594 * omap2_clksel_set_rate() - program clock rate in hardware
595 * @clk: struct clk * to program rate
596 * @rate: target rate to program
Paul Walmsleydf791b32010-01-26 20:13:04 -0700597 *
Paul Walmsley435699d2010-05-18 18:40:24 -0600598 * This function is intended to be called only by the clock framework.
599 * Program @clk's rate to @rate in the hardware. The clock can be
600 * either enabled or disabled when this happens, although if the clock
601 * is enabled, some downstream devices may glitch or behave
602 * unpredictably when the clock rate is changed - this depends on the
603 * hardware. This function does not currently check the usecount of
604 * the clock, so if multiple drivers are using the clock, and the rate
605 * is changed, they will all be affected without any notification.
606 * Returns -EINVAL upon error, or 0 upon success.
Paul Walmsleydf791b32010-01-26 20:13:04 -0700607 */
Mike Turquette32cc0022012-11-10 16:58:41 -0700608#ifdef CONFIG_COMMON_CLK
609int omap2_clksel_set_rate(struct clk_hw *hw, unsigned long rate,
610 unsigned long parent_rate)
611{
612 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
613#else
Paul Walmsleydf791b32010-01-26 20:13:04 -0700614int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
615{
Mike Turquette32cc0022012-11-10 16:58:41 -0700616#endif
Paul Walmsley435699d2010-05-18 18:40:24 -0600617 u32 field_val, validrate, new_div = 0;
Paul Walmsleydf791b32010-01-26 20:13:04 -0700618
Paul Walmsley435699d2010-05-18 18:40:24 -0600619 if (!clk->clksel || !clk->clksel_mask)
Paul Walmsleydf791b32010-01-26 20:13:04 -0700620 return -EINVAL;
621
622 validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
623 if (validrate != rate)
624 return -EINVAL;
625
Paul Walmsley435699d2010-05-18 18:40:24 -0600626 field_val = _divisor_to_clksel(clk, new_div);
Paul Walmsleydf791b32010-01-26 20:13:04 -0700627 if (field_val == ~0)
628 return -EINVAL;
629
Paul Walmsley435699d2010-05-18 18:40:24 -0600630 _write_clksel_reg(clk, field_val);
Paul Walmsleydf791b32010-01-26 20:13:04 -0700631
Mike Turquette32cc0022012-11-10 16:58:41 -0700632#ifdef CONFIG_COMMON_CLK
633 pr_debug("clock: %s: set rate to %ld\n", __clk_get_name(hw->clk),
634 __clk_get_rate(hw->clk));
635#else
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600636 pr_debug("clock: %s: set rate to %ld\n", __clk_get_name(clk),
637 __clk_get_rate(clk));
Paul Walmsley435699d2010-05-18 18:40:24 -0600638
Mike Turquette32cc0022012-11-10 16:58:41 -0700639 clk->rate = __clk_get_rate(__clk_get_parent(clk)) / new_div;
640#endif
641
Paul Walmsleydf791b32010-01-26 20:13:04 -0700642 return 0;
643}
644
Paul Walmsley435699d2010-05-18 18:40:24 -0600645/*
646 * Clksel parent setting function - not passed in struct clk function
647 * pointer - instead, the OMAP clock code currently assumes that any
648 * parent-setting clock is a clksel clock, and calls
649 * omap2_clksel_set_parent() by default
650 */
651
652/**
653 * omap2_clksel_set_parent() - change a clock's parent clock
654 * @clk: struct clk * of the child clock
655 * @new_parent: struct clk * of the new parent clock
656 *
657 * This function is intended to be called only by the clock framework.
658 * Change the parent clock of clock @clk to @new_parent. This is
659 * intended to be used while @clk is disabled. This function does not
660 * currently check the usecount of the clock, so if multiple drivers
661 * are using the clock, and the parent is changed, they will all be
662 * affected without any notification. Returns -EINVAL upon error, or
663 * 0 upon success.
664 */
Mike Turquette32cc0022012-11-10 16:58:41 -0700665#ifdef CONFIG_COMMON_CLK
666int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val)
667{
668 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
669
670 if (!clk->clksel || !clk->clksel_mask)
671 return -EINVAL;
672
673 _write_clksel_reg(clk, field_val);
674 return 0;
675}
676#else
Paul Walmsleydf791b32010-01-26 20:13:04 -0700677int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent)
678{
Paul Walmsley435699d2010-05-18 18:40:24 -0600679 u32 field_val = 0;
680 u32 parent_div;
Paul Walmsleydf791b32010-01-26 20:13:04 -0700681
Paul Walmsleyd74b4942010-05-18 18:40:24 -0600682 if (!clk->clksel || !clk->clksel_mask)
Paul Walmsleydf791b32010-01-26 20:13:04 -0700683 return -EINVAL;
684
Paul Walmsley435699d2010-05-18 18:40:24 -0600685 parent_div = _get_div_and_fieldval(new_parent, clk, &field_val);
Paul Walmsleydf791b32010-01-26 20:13:04 -0700686 if (!parent_div)
687 return -EINVAL;
Paul Walmsley435699d2010-05-18 18:40:24 -0600688 _write_clksel_reg(clk, field_val);
Paul Walmsleydf791b32010-01-26 20:13:04 -0700689
Paul Walmsleydf791b32010-01-26 20:13:04 -0700690 clk_reparent(clk, new_parent);
691
692 /* CLKSEL clocks follow their parents' rates, divided by a divisor */
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600693 clk->rate = __clk_get_rate(new_parent);
Paul Walmsleydf791b32010-01-26 20:13:04 -0700694
695 if (parent_div > 0)
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600696 __clk_get_rate(clk) /= parent_div;
Paul Walmsley435699d2010-05-18 18:40:24 -0600697 pr_debug("clock: %s: set parent to %s (new rate %ld)\n",
Rajendra Nayak5dcc3b92012-09-22 02:24:17 -0600698 __clk_get_name(clk),
699 __clk_get_name(__clk_get_parent(clk)),
700 __clk_get_rate(clk));
Paul Walmsleydf791b32010-01-26 20:13:04 -0700701
702 return 0;
703}
Mike Turquette32cc0022012-11-10 16:58:41 -0700704#endif