aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/ti/clk.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/ti/clk.c')
-rw-r--r--drivers/clk/ti/clk.c98
1 files changed, 79 insertions, 19 deletions
diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
index 3da33c786d77..1dc2f15fb75b 100644
--- a/drivers/clk/ti/clk.c
+++ b/drivers/clk/ti/clk.c
@@ -1,18 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* TI clock 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.h>
@@ -119,19 +111,60 @@ int ti_clk_setup_ll_ops(struct ti_clk_ll_ops *ops)
return 0;
}
+/*
+ * Eventually we could standardize to using '_' for clk-*.c files to follow the
+ * TRM naming and leave out the tmp name here.
+ */
+static struct device_node *ti_find_clock_provider(struct device_node *from,
+ const char *name)
+{
+ struct device_node *np;
+ bool found = false;
+ const char *n;
+ char *tmp;
+
+ tmp = kstrdup(name, GFP_KERNEL);
+ if (!tmp)
+ return NULL;
+ strreplace(tmp, '-', '_');
+
+ /* Node named "clock" with "clock-output-names" */
+ for_each_of_allnodes_from(from, np) {
+ if (of_property_read_string_index(np, "clock-output-names",
+ 0, &n))
+ continue;
+
+ if (!strncmp(n, tmp, strlen(tmp))) {
+ of_node_get(np);
+ found = true;
+ break;
+ }
+ }
+ kfree(tmp);
+
+ if (found) {
+ of_node_put(from);
+ return np;
+ }
+
+ /* Fall back to using old node name base provider name */
+ return of_find_node_by_name(from, name);
+}
+
/**
* ti_dt_clocks_register - register DT alias clocks during boot
* @oclks: list of clocks to register
*
* Register alias or non-standard DT clock entries during boot. By
- * default, DT clocks are found based on their node name. If any
+ * default, DT clocks are found based on their clock-output-names
+ * property, or the clock node name for legacy cases. If any
* additional con-id / dev-id -> clock mapping is required, use this
* function to list these.
*/
void __init ti_dt_clocks_register(struct ti_dt_clk oclks[])
{
struct ti_dt_clk *c;
- struct device_node *node, *parent;
+ struct device_node *node, *parent, *child;
struct clk *clk;
struct of_phandle_args clkspec;
char buf[64];
@@ -168,13 +201,16 @@ void __init ti_dt_clocks_register(struct ti_dt_clk oclks[])
if (num_args && clkctrl_nodes_missing)
continue;
- node = of_find_node_by_name(NULL, buf);
+ node = ti_find_clock_provider(NULL, buf);
if (num_args && compat_mode) {
parent = node;
- node = of_get_child_by_name(parent, "clock");
- if (!node)
- node = of_get_child_by_name(parent, "clk");
- of_node_put(parent);
+ child = of_get_child_by_name(parent, "clock");
+ if (!child)
+ child = of_get_child_by_name(parent, "clk");
+ if (child) {
+ of_node_put(parent);
+ node = child;
+ }
}
clkspec.np = node;
@@ -271,6 +307,8 @@ int ti_clk_get_reg_addr(struct device_node *node, int index,
for (i = 0; i < CLK_MAX_MEMMAPS; i++) {
if (clocks_node_ptr[i] == node->parent)
break;
+ if (clocks_node_ptr[i] == node->parent->parent)
+ break;
}
if (i == CLK_MAX_MEMMAPS) {
@@ -281,8 +319,12 @@ int ti_clk_get_reg_addr(struct device_node *node, int index,
reg->index = i;
if (of_property_read_u32_index(node, "reg", index, &val)) {
- pr_err("%pOFn must have reg[%d]!\n", node, index);
- return -EINVAL;
+ if (of_property_read_u32_index(node->parent, "reg",
+ index, &val)) {
+ pr_err("%pOFn or parent must have reg[%d]!\n",
+ node, index);
+ return -EINVAL;
+ }
}
reg->offset = val;
@@ -400,6 +442,24 @@ static const struct of_device_id simple_clk_match_table[] __initconst = {
};
/**
+ * ti_dt_clk_name - init clock name from first output name or node name
+ * @np: device node
+ *
+ * Use the first clock-output-name for the clock name if found. Fall back
+ * to legacy naming based on node name.
+ */
+const char *ti_dt_clk_name(struct device_node *np)
+{
+ const char *name;
+
+ if (!of_property_read_string_index(np, "clock-output-names", 0,
+ &name))
+ return name;
+
+ return np->name;
+}
+
+/**
* ti_clk_add_aliases - setup clock aliases
*
* Sets up any missing clock aliases. No return value.
@@ -415,7 +475,7 @@ void __init ti_clk_add_aliases(void)
clkspec.np = np;
clk = of_clk_get_from_provider(&clkspec);
- ti_clk_add_alias(NULL, clk, np->name);
+ ti_clk_add_alias(NULL, clk, ti_dt_clk_name(np));
}
}