Commit 47b00dcf authored by Tero Kristo's avatar Tero Kristo

clk: ti: clkctrl: support multiple clkctrl nodes under a cm node

Currently, only one clkctrl node can be added under a specific CM node
due to limitation with the implementation. Modify the code to pick-up
clockdomain name from the clkctrl node instead of CM node if provided.
Also, add a new flag to the TI clock driver so that both modes can
be supported simultaneously.
Signed-off-by: default avatarTero Kristo <t-kristo@ti.com>
Tested-by: default avatarTony Lindgren <tony@atomide.com>
parent 8fa45095
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
struct ti_clk_ll_ops *ti_clk_ll_ops; struct ti_clk_ll_ops *ti_clk_ll_ops;
static struct device_node *clocks_node_ptr[CLK_MAX_MEMMAPS]; static struct device_node *clocks_node_ptr[CLK_MAX_MEMMAPS];
static struct ti_clk_features ti_clk_features; struct ti_clk_features ti_clk_features;
struct clk_iomap { struct clk_iomap {
struct regmap *regmap; struct regmap *regmap;
...@@ -140,6 +140,9 @@ void __init ti_dt_clocks_register(struct ti_dt_clk oclks[]) ...@@ -140,6 +140,9 @@ void __init ti_dt_clocks_register(struct ti_dt_clk oclks[])
int ret; int ret;
static bool clkctrl_nodes_missing; static bool clkctrl_nodes_missing;
static bool has_clkctrl_data; static bool has_clkctrl_data;
static bool compat_mode;
compat_mode = ti_clk_get_features()->flags & TI_CLK_CLKCTRL_COMPAT;
for (c = oclks; c->node_name != NULL; c++) { for (c = oclks; c->node_name != NULL; c++) {
strcpy(buf, c->node_name); strcpy(buf, c->node_name);
...@@ -164,7 +167,7 @@ void __init ti_dt_clocks_register(struct ti_dt_clk oclks[]) ...@@ -164,7 +167,7 @@ void __init ti_dt_clocks_register(struct ti_dt_clk oclks[])
continue; continue;
node = of_find_node_by_name(NULL, buf); node = of_find_node_by_name(NULL, buf);
if (num_args) { if (num_args && compat_mode) {
parent = node; parent = node;
node = of_get_child_by_name(parent, "clk"); node = of_get_child_by_name(parent, "clk");
of_node_put(parent); of_node_put(parent);
......
...@@ -259,8 +259,13 @@ _ti_clkctrl_clk_register(struct omap_clkctrl_provider *provider, ...@@ -259,8 +259,13 @@ _ti_clkctrl_clk_register(struct omap_clkctrl_provider *provider,
struct omap_clkctrl_clk *clkctrl_clk; struct omap_clkctrl_clk *clkctrl_clk;
int ret = 0; int ret = 0;
init.name = kasprintf(GFP_KERNEL, "%s:%s:%04x:%d", node->parent->name, if (ti_clk_get_features()->flags & TI_CLK_CLKCTRL_COMPAT)
node->name, offset, bit); init.name = kasprintf(GFP_KERNEL, "%s:%s:%04x:%d",
node->parent->name, node->name, offset,
bit);
else
init.name = kasprintf(GFP_KERNEL, "%s:%04x:%d", node->name,
offset, bit);
clkctrl_clk = kzalloc(sizeof(*clkctrl_clk), GFP_KERNEL); clkctrl_clk = kzalloc(sizeof(*clkctrl_clk), GFP_KERNEL);
if (!init.name || !clkctrl_clk) { if (!init.name || !clkctrl_clk) {
ret = -ENOMEM; ret = -ENOMEM;
...@@ -441,6 +446,10 @@ static void __init _ti_omap4_clkctrl_setup(struct device_node *node) ...@@ -441,6 +446,10 @@ static void __init _ti_omap4_clkctrl_setup(struct device_node *node)
u32 addr; u32 addr;
int ret; int ret;
if (!(ti_clk_get_features()->flags & TI_CLK_CLKCTRL_COMPAT) &&
!strcmp(node->name, "clk"))
ti_clk_features.flags |= TI_CLK_CLKCTRL_COMPAT;
addrp = of_get_address(node, 0, NULL, NULL); addrp = of_get_address(node, 0, NULL, NULL);
addr = (u32)of_translate_address(node, addrp); addr = (u32)of_translate_address(node, addrp);
...@@ -492,19 +501,35 @@ static void __init _ti_omap4_clkctrl_setup(struct device_node *node) ...@@ -492,19 +501,35 @@ static void __init _ti_omap4_clkctrl_setup(struct device_node *node)
provider->base = of_iomap(node, 0); provider->base = of_iomap(node, 0);
provider->clkdm_name = kmalloc(strlen(node->parent->name) + 3, if (ti_clk_get_features()->flags & TI_CLK_CLKCTRL_COMPAT) {
GFP_KERNEL); provider->clkdm_name = kmalloc(strlen(node->parent->name) + 3,
if (!provider->clkdm_name) { GFP_KERNEL);
kfree(provider); if (!provider->clkdm_name) {
return; kfree(provider);
return;
}
/*
* Create default clkdm name, replace _cm from end of parent
* node name with _clkdm
*/
strcpy(provider->clkdm_name, node->parent->name);
provider->clkdm_name[strlen(provider->clkdm_name) - 2] = 0;
} else {
provider->clkdm_name = kmalloc(strlen(node->name), GFP_KERNEL);
if (!provider->clkdm_name) {
kfree(provider);
return;
}
/*
* Create default clkdm name, replace _clkctrl from end of
* node name with _clkdm
*/
strcpy(provider->clkdm_name, node->name);
provider->clkdm_name[strlen(provider->clkdm_name) - 7] = 0;
} }
/*
* Create default clkdm name, replace _cm from end of parent node
* name with _clkdm
*/
strcpy(provider->clkdm_name, node->parent->name);
provider->clkdm_name[strlen(provider->clkdm_name) - 2] = 0;
strcat(provider->clkdm_name, "clkdm"); strcat(provider->clkdm_name, "clkdm");
INIT_LIST_HEAD(&provider->clocks); INIT_LIST_HEAD(&provider->clocks);
...@@ -539,9 +564,13 @@ static void __init _ti_omap4_clkctrl_setup(struct device_node *node) ...@@ -539,9 +564,13 @@ static void __init _ti_omap4_clkctrl_setup(struct device_node *node)
init.flags = 0; init.flags = 0;
if (reg_data->flags & CLKF_SET_RATE_PARENT) if (reg_data->flags & CLKF_SET_RATE_PARENT)
init.flags |= CLK_SET_RATE_PARENT; init.flags |= CLK_SET_RATE_PARENT;
init.name = kasprintf(GFP_KERNEL, "%s:%s:%04x:%d", if (ti_clk_get_features()->flags & TI_CLK_CLKCTRL_COMPAT)
node->parent->name, node->name, init.name = kasprintf(GFP_KERNEL, "%s:%s:%04x:%d",
reg_data->offset, 0); node->parent->name, node->name,
reg_data->offset, 0);
else
init.name = kasprintf(GFP_KERNEL, "%s:%04x:%d",
node->name, reg_data->offset, 0);
clkctrl_clk = kzalloc(sizeof(*clkctrl_clk), GFP_KERNEL); clkctrl_clk = kzalloc(sizeof(*clkctrl_clk), GFP_KERNEL);
if (!init.name || !clkctrl_clk) if (!init.name || !clkctrl_clk)
goto cleanup; goto cleanup;
......
...@@ -233,6 +233,8 @@ extern const struct clk_ops ti_clk_divider_ops; ...@@ -233,6 +233,8 @@ extern const struct clk_ops ti_clk_divider_ops;
extern const struct clk_ops ti_clk_mux_ops; extern const struct clk_ops ti_clk_mux_ops;
extern const struct clk_ops omap_gate_clk_ops; extern const struct clk_ops omap_gate_clk_ops;
extern struct ti_clk_features ti_clk_features;
void omap2_init_clk_clkdm(struct clk_hw *hw); void omap2_init_clk_clkdm(struct clk_hw *hw);
int omap2_clkops_enable_clkdm(struct clk_hw *hw); int omap2_clkops_enable_clkdm(struct clk_hw *hw);
void omap2_clkops_disable_clkdm(struct clk_hw *hw); void omap2_clkops_disable_clkdm(struct clk_hw *hw);
......
...@@ -290,6 +290,7 @@ struct ti_clk_features { ...@@ -290,6 +290,7 @@ struct ti_clk_features {
#define TI_CLK_DPLL4_DENY_REPROGRAM BIT(1) #define TI_CLK_DPLL4_DENY_REPROGRAM BIT(1)
#define TI_CLK_DISABLE_CLKDM_CONTROL BIT(2) #define TI_CLK_DISABLE_CLKDM_CONTROL BIT(2)
#define TI_CLK_ERRATA_I810 BIT(3) #define TI_CLK_ERRATA_I810 BIT(3)
#define TI_CLK_CLKCTRL_COMPAT BIT(4)
void ti_clk_setup_features(struct ti_clk_features *features); void ti_clk_setup_features(struct ti_clk_features *features);
const struct ti_clk_features *ti_clk_get_features(void); const struct ti_clk_features *ti_clk_get_features(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment