2 * OMAP clkctrl clock support
4 * Copyright (C) 2017 Texas Instruments, Inc.
6 * Tero Kristo <t-kristo@ti.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
12 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
13 * kind, whether express or implied; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
18 #include <linux/clk-provider.h>
19 #include <linux/slab.h>
21 #include <linux/of_address.h>
22 #include <linux/clk/ti.h>
23 #include <linux/delay.h>
28 #define OMAP4_MODULEMODE_MASK 0x3
30 #define MODULEMODE_HWCTRL 0x1
31 #define MODULEMODE_SWCTRL 0x2
33 #define OMAP4_IDLEST_MASK (0x3 << 16)
34 #define OMAP4_IDLEST_SHIFT 16
36 #define CLKCTRL_IDLEST_FUNCTIONAL 0x0
37 #define CLKCTRL_IDLEST_INTERFACE_IDLE 0x2
38 #define CLKCTRL_IDLEST_DISABLED 0x3
40 /* These timeouts are in us */
41 #define OMAP4_MAX_MODULE_READY_TIME 2000
42 #define OMAP4_MAX_MODULE_DISABLE_TIME 5000
44 static bool _early_timeout
= true;
46 struct omap_clkctrl_provider
{
48 struct list_head clocks
;
51 struct omap_clkctrl_clk
{
55 struct list_head node
;
63 static const struct omap_clkctrl_data default_clkctrl_data
[] __initconst
= {
67 static u32
_omap4_idlest(u32 val
)
69 val
&= OMAP4_IDLEST_MASK
;
70 val
>>= OMAP4_IDLEST_SHIFT
;
75 static bool _omap4_is_idle(u32 val
)
77 val
= _omap4_idlest(val
);
79 return val
== CLKCTRL_IDLEST_DISABLED
;
82 static bool _omap4_is_ready(u32 val
)
84 val
= _omap4_idlest(val
);
86 return val
== CLKCTRL_IDLEST_FUNCTIONAL
||
87 val
== CLKCTRL_IDLEST_INTERFACE_IDLE
;
90 static bool _omap4_is_timeout(union omap4_timeout
*time
, u32 timeout
)
92 if (unlikely(_early_timeout
)) {
93 if (time
->cycles
++ < timeout
) {
98 if (!ktime_to_ns(time
->start
)) {
99 time
->start
= ktime_get();
103 if (ktime_us_delta(ktime_get(), time
->start
) < timeout
) {
112 static int __init
_omap4_disable_early_timeout(void)
114 _early_timeout
= false;
118 arch_initcall(_omap4_disable_early_timeout
);
120 static int _omap4_clkctrl_clk_enable(struct clk_hw
*hw
)
122 struct clk_hw_omap
*clk
= to_clk_hw_omap(hw
);
125 union omap4_timeout timeout
= { 0 };
127 if (!clk
->enable_bit
)
131 ret
= ti_clk_ll_ops
->clkdm_clk_enable(clk
->clkdm
, hw
->clk
);
134 "%s: could not enable %s's clockdomain %s: %d\n",
135 __func__
, clk_hw_get_name(hw
),
136 clk
->clkdm_name
, ret
);
141 val
= ti_clk_ll_ops
->clk_readl(&clk
->enable_reg
);
143 val
&= ~OMAP4_MODULEMODE_MASK
;
144 val
|= clk
->enable_bit
;
146 ti_clk_ll_ops
->clk_writel(val
, &clk
->enable_reg
);
148 if (clk
->flags
& NO_IDLEST
)
151 /* Wait until module is enabled */
152 while (!_omap4_is_ready(ti_clk_ll_ops
->clk_readl(&clk
->enable_reg
))) {
153 if (_omap4_is_timeout(&timeout
, OMAP4_MAX_MODULE_READY_TIME
)) {
154 pr_err("%s: failed to enable\n", clk_hw_get_name(hw
));
162 static void _omap4_clkctrl_clk_disable(struct clk_hw
*hw
)
164 struct clk_hw_omap
*clk
= to_clk_hw_omap(hw
);
166 union omap4_timeout timeout
= { 0 };
168 if (!clk
->enable_bit
)
171 val
= ti_clk_ll_ops
->clk_readl(&clk
->enable_reg
);
173 val
&= ~OMAP4_MODULEMODE_MASK
;
175 ti_clk_ll_ops
->clk_writel(val
, &clk
->enable_reg
);
177 if (clk
->flags
& NO_IDLEST
)
180 /* Wait until module is disabled */
181 while (!_omap4_is_idle(ti_clk_ll_ops
->clk_readl(&clk
->enable_reg
))) {
182 if (_omap4_is_timeout(&timeout
,
183 OMAP4_MAX_MODULE_DISABLE_TIME
)) {
184 pr_err("%s: failed to disable\n", clk_hw_get_name(hw
));
191 ti_clk_ll_ops
->clkdm_clk_disable(clk
->clkdm
, hw
->clk
);
194 static int _omap4_clkctrl_clk_is_enabled(struct clk_hw
*hw
)
196 struct clk_hw_omap
*clk
= to_clk_hw_omap(hw
);
199 val
= ti_clk_ll_ops
->clk_readl(&clk
->enable_reg
);
201 if (val
& clk
->enable_bit
)
207 static const struct clk_ops omap4_clkctrl_clk_ops
= {
208 .enable
= _omap4_clkctrl_clk_enable
,
209 .disable
= _omap4_clkctrl_clk_disable
,
210 .is_enabled
= _omap4_clkctrl_clk_is_enabled
,
213 static struct clk_hw
*_ti_omap4_clkctrl_xlate(struct of_phandle_args
*clkspec
,
216 struct omap_clkctrl_provider
*provider
= data
;
217 struct omap_clkctrl_clk
*entry
;
219 if (clkspec
->args_count
!= 2)
220 return ERR_PTR(-EINVAL
);
222 pr_debug("%s: looking for %x:%x\n", __func__
,
223 clkspec
->args
[0], clkspec
->args
[1]);
225 list_for_each_entry(entry
, &provider
->clocks
, node
) {
226 if (entry
->reg_offset
== clkspec
->args
[0] &&
227 entry
->bit_offset
== clkspec
->args
[1])
232 return ERR_PTR(-EINVAL
);
238 _ti_clkctrl_clk_register(struct omap_clkctrl_provider
*provider
,
239 struct device_node
*node
, struct clk_hw
*clk_hw
,
240 u16 offset
, u8 bit
, const char * const *parents
,
241 int num_parents
, const struct clk_ops
*ops
)
243 struct clk_init_data init
= { NULL
};
245 struct omap_clkctrl_clk
*clkctrl_clk
;
248 init
.name
= kasprintf(GFP_KERNEL
, "%s:%s:%04x:%d", node
->parent
->name
,
249 node
->name
, offset
, bit
);
250 clkctrl_clk
= kzalloc(sizeof(*clkctrl_clk
), GFP_KERNEL
);
251 if (!init
.name
|| !clkctrl_clk
) {
256 clk_hw
->init
= &init
;
257 init
.parent_names
= parents
;
258 init
.num_parents
= num_parents
;
260 init
.flags
= CLK_IS_BASIC
;
262 clk
= ti_clk_register(NULL
, clk_hw
, init
.name
);
263 if (IS_ERR_OR_NULL(clk
)) {
268 clkctrl_clk
->reg_offset
= offset
;
269 clkctrl_clk
->bit_offset
= bit
;
270 clkctrl_clk
->clk
= clk_hw
;
272 list_add(&clkctrl_clk
->node
, &provider
->clocks
);
283 _ti_clkctrl_setup_gate(struct omap_clkctrl_provider
*provider
,
284 struct device_node
*node
, u16 offset
,
285 const struct omap_clkctrl_bit_data
*data
,
288 struct clk_hw_omap
*clk_hw
;
290 clk_hw
= kzalloc(sizeof(*clk_hw
), GFP_KERNEL
);
294 clk_hw
->enable_bit
= data
->bit
;
295 clk_hw
->enable_reg
.ptr
= reg
;
297 if (_ti_clkctrl_clk_register(provider
, node
, &clk_hw
->hw
, offset
,
298 data
->bit
, data
->parents
, 1,
304 _ti_clkctrl_setup_mux(struct omap_clkctrl_provider
*provider
,
305 struct device_node
*node
, u16 offset
,
306 const struct omap_clkctrl_bit_data
*data
,
309 struct clk_omap_mux
*mux
;
311 const char * const *pname
;
313 mux
= kzalloc(sizeof(*mux
), GFP_KERNEL
);
317 pname
= data
->parents
;
323 mux
->mask
= num_parents
;
324 mux
->mask
= (1 << fls(mux
->mask
)) - 1;
326 mux
->shift
= data
->bit
;
329 if (_ti_clkctrl_clk_register(provider
, node
, &mux
->hw
, offset
,
330 data
->bit
, data
->parents
, num_parents
,
336 _ti_clkctrl_setup_div(struct omap_clkctrl_provider
*provider
,
337 struct device_node
*node
, u16 offset
,
338 const struct omap_clkctrl_bit_data
*data
,
341 struct clk_omap_divider
*div
;
342 const struct omap_clkctrl_div_data
*div_data
= data
->data
;
344 div
= kzalloc(sizeof(*div
), GFP_KERNEL
);
349 div
->shift
= data
->bit
;
351 if (ti_clk_parse_divider_data((int *)div_data
->dividers
,
352 div_data
->max_div
, 0, 0,
353 &div
->width
, &div
->table
)) {
354 pr_err("%s: Data parsing for %s:%04x:%d failed\n", __func__
,
355 node
->name
, offset
, data
->bit
);
360 if (_ti_clkctrl_clk_register(provider
, node
, &div
->hw
, offset
,
361 data
->bit
, data
->parents
, 1,
362 &ti_clk_divider_ops
))
367 _ti_clkctrl_setup_subclks(struct omap_clkctrl_provider
*provider
,
368 struct device_node
*node
,
369 const struct omap_clkctrl_reg_data
*data
,
372 const struct omap_clkctrl_bit_data
*bits
= data
->bit_data
;
378 switch (bits
->type
) {
380 _ti_clkctrl_setup_gate(provider
, node
, data
->offset
,
385 _ti_clkctrl_setup_div(provider
, node
, data
->offset
,
390 _ti_clkctrl_setup_mux(provider
, node
, data
->offset
,
395 pr_err("%s: bad subclk type: %d\n", __func__
,
403 static void __init
_ti_omap4_clkctrl_setup(struct device_node
*node
)
405 struct omap_clkctrl_provider
*provider
;
406 const struct omap_clkctrl_data
*data
= default_clkctrl_data
;
407 const struct omap_clkctrl_reg_data
*reg_data
;
408 struct clk_init_data init
= { NULL
};
409 struct clk_hw_omap
*hw
;
411 struct omap_clkctrl_clk
*clkctrl_clk
;
415 addrp
= of_get_address(node
, 0, NULL
, NULL
);
416 addr
= (u32
)of_translate_address(node
, addrp
);
418 #ifdef CONFIG_ARCH_OMAP4
419 if (of_machine_is_compatible("ti,omap4"))
420 data
= omap4_clkctrl_data
;
424 if (addr
== data
->addr
)
431 pr_err("%s not found from clkctrl data.\n", node
->name
);
435 provider
= kzalloc(sizeof(*provider
), GFP_KERNEL
);
439 provider
->base
= of_iomap(node
, 0);
441 INIT_LIST_HEAD(&provider
->clocks
);
443 /* Generate clocks */
444 reg_data
= data
->regs
;
446 while (reg_data
->parent
) {
447 hw
= kzalloc(sizeof(*hw
), GFP_KERNEL
);
451 hw
->enable_reg
.ptr
= provider
->base
+ reg_data
->offset
;
453 _ti_clkctrl_setup_subclks(provider
, node
, reg_data
,
456 if (reg_data
->flags
& CLKF_SW_SUP
)
457 hw
->enable_bit
= MODULEMODE_SWCTRL
;
458 if (reg_data
->flags
& CLKF_HW_SUP
)
459 hw
->enable_bit
= MODULEMODE_HWCTRL
;
460 if (reg_data
->flags
& CLKF_NO_IDLEST
)
461 hw
->flags
|= NO_IDLEST
;
463 init
.parent_names
= ®_data
->parent
;
464 init
.num_parents
= 1;
466 init
.name
= kasprintf(GFP_KERNEL
, "%s:%s:%04x:%d",
467 node
->parent
->name
, node
->name
,
468 reg_data
->offset
, 0);
469 clkctrl_clk
= kzalloc(sizeof(*clkctrl_clk
), GFP_KERNEL
);
470 if (!init
.name
|| !clkctrl_clk
)
473 init
.ops
= &omap4_clkctrl_clk_ops
;
476 clk
= ti_clk_register(NULL
, &hw
->hw
, init
.name
);
477 if (IS_ERR_OR_NULL(clk
))
480 clkctrl_clk
->reg_offset
= reg_data
->offset
;
481 clkctrl_clk
->clk
= &hw
->hw
;
483 list_add(&clkctrl_clk
->node
, &provider
->clocks
);
488 of_clk_add_hw_provider(node
, _ti_omap4_clkctrl_xlate
, provider
);
496 CLK_OF_DECLARE(ti_omap4_clkctrl_clock
, "ti,clkctrl",
497 _ti_omap4_clkctrl_setup
);