-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
TI clk driver now routes some of the basic clocks through own registration routine to allow autoidle support. This routine just checks a couple of device node properties and adds autoidle support if required, and just passes the registration forward to basic clocks. Signed-off-by: Tero Kristo <t-kristo@ti.com> Acked-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Mike Turquette <mturquette@linaro.org>
- Loading branch information
Tero Kristo
authored and
Mike Turquette
committed
Jan 17, 2014
1 parent
f38b0dd
commit b1a07b4
Showing
5 changed files
with
188 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
Binding for Texas Instruments autoidle clock. | ||
|
||
Binding status: Unstable - ABI compatibility may be broken in the future | ||
|
||
This binding uses the common clock binding[1]. It assumes a register mapped | ||
clock which can be put to idle automatically by hardware based on the usage | ||
and a configuration bit setting. Autoidle clock is never an individual | ||
clock, it is always a derivative of some basic clock like a gate, divider, | ||
or fixed-factor. | ||
|
||
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt | ||
|
||
Required properties: | ||
- reg : offset for the register controlling the autoidle | ||
- ti,autoidle-shift : bit shift of the autoidle enable bit | ||
- ti,invert-autoidle-bit : autoidle is enabled by setting the bit to 0 | ||
|
||
Examples: | ||
dpll_core_m4_ck: dpll_core_m4_ck { | ||
#clock-cells = <0>; | ||
compatible = "ti,divider-clock"; | ||
clocks = <&dpll_core_x2_ck>; | ||
ti,max-div = <31>; | ||
ti,autoidle-shift = <8>; | ||
reg = <0x2d38>; | ||
ti,index-starts-at-one; | ||
ti,invert-autoidle-bit; | ||
}; | ||
|
||
dpll_usb_clkdcoldo_ck: dpll_usb_clkdcoldo_ck { | ||
#clock-cells = <0>; | ||
compatible = "ti,fixed-factor-clock"; | ||
clocks = <&dpll_usb_ck>; | ||
ti,clock-div = <1>; | ||
ti,autoidle-shift = <8>; | ||
reg = <0x01b4>; | ||
ti,clock-mult = <1>; | ||
ti,invert-autoidle-bit; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
ifneq ($(CONFIG_OF),) | ||
obj-y += clk.o | ||
obj-y += clk.o autoidle.o | ||
clk-common = dpll.o | ||
endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
/* | ||
* TI clock autoidle support | ||
* | ||
* Copyright (C) 2013 Texas Instruments, Inc. | ||
* | ||
* Tero Kristo <t-kristo@ti.com> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
* | ||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
* kind, whether express or implied; without even the implied warranty | ||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
*/ | ||
|
||
#include <linux/clk-provider.h> | ||
#include <linux/slab.h> | ||
#include <linux/io.h> | ||
#include <linux/of.h> | ||
#include <linux/of_address.h> | ||
#include <linux/clk/ti.h> | ||
|
||
struct clk_ti_autoidle { | ||
void __iomem *reg; | ||
u8 shift; | ||
u8 flags; | ||
const char *name; | ||
struct list_head node; | ||
}; | ||
|
||
#define AUTOIDLE_LOW 0x1 | ||
|
||
static LIST_HEAD(autoidle_clks); | ||
|
||
static void ti_allow_autoidle(struct clk_ti_autoidle *clk) | ||
{ | ||
u32 val; | ||
|
||
val = ti_clk_ll_ops->clk_readl(clk->reg); | ||
|
||
if (clk->flags & AUTOIDLE_LOW) | ||
val &= ~(1 << clk->shift); | ||
else | ||
val |= (1 << clk->shift); | ||
|
||
ti_clk_ll_ops->clk_writel(val, clk->reg); | ||
} | ||
|
||
static void ti_deny_autoidle(struct clk_ti_autoidle *clk) | ||
{ | ||
u32 val; | ||
|
||
val = ti_clk_ll_ops->clk_readl(clk->reg); | ||
|
||
if (clk->flags & AUTOIDLE_LOW) | ||
val |= (1 << clk->shift); | ||
else | ||
val &= ~(1 << clk->shift); | ||
|
||
ti_clk_ll_ops->clk_writel(val, clk->reg); | ||
} | ||
|
||
/** | ||
* of_ti_clk_allow_autoidle_all - enable autoidle for all clocks | ||
* | ||
* Enables hardware autoidle for all registered DT clocks, which have | ||
* the feature. | ||
*/ | ||
void of_ti_clk_allow_autoidle_all(void) | ||
{ | ||
struct clk_ti_autoidle *c; | ||
|
||
list_for_each_entry(c, &autoidle_clks, node) | ||
ti_allow_autoidle(c); | ||
} | ||
|
||
/** | ||
* of_ti_clk_deny_autoidle_all - disable autoidle for all clocks | ||
* | ||
* Disables hardware autoidle for all registered DT clocks, which have | ||
* the feature. | ||
*/ | ||
void of_ti_clk_deny_autoidle_all(void) | ||
{ | ||
struct clk_ti_autoidle *c; | ||
|
||
list_for_each_entry(c, &autoidle_clks, node) | ||
ti_deny_autoidle(c); | ||
} | ||
|
||
/** | ||
* of_ti_clk_autoidle_setup - sets up hardware autoidle for a clock | ||
* @node: pointer to the clock device node | ||
* | ||
* Checks if a clock has hardware autoidle support or not (check | ||
* for presence of 'ti,autoidle-shift' property in the device tree | ||
* node) and sets up the hardware autoidle feature for the clock | ||
* if available. If autoidle is available, the clock is also added | ||
* to the autoidle list for later processing. Returns 0 on success, | ||
* negative error value on failure. | ||
*/ | ||
int __init of_ti_clk_autoidle_setup(struct device_node *node) | ||
{ | ||
u32 shift; | ||
struct clk_ti_autoidle *clk; | ||
|
||
/* Check if this clock has autoidle support or not */ | ||
if (of_property_read_u32(node, "ti,autoidle-shift", &shift)) | ||
return 0; | ||
|
||
clk = kzalloc(sizeof(*clk), GFP_KERNEL); | ||
|
||
if (!clk) | ||
return -ENOMEM; | ||
|
||
clk->shift = shift; | ||
clk->name = node->name; | ||
clk->reg = ti_clk_get_reg_addr(node, 0); | ||
|
||
if (!clk->reg) { | ||
kfree(clk); | ||
return -EINVAL; | ||
} | ||
|
||
if (of_property_read_bool(node, "ti,invert-autoidle-bit")) | ||
clk->flags |= AUTOIDLE_LOW; | ||
|
||
list_add(&clk->node, &autoidle_clks); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters