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.c68
1 files changed, 43 insertions, 25 deletions
diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
index b1a6f7144f3f..337abe5909e1 100644
--- a/drivers/clk/ti/clk.c
+++ b/drivers/clk/ti/clk.c
@@ -25,8 +25,8 @@
25#undef pr_fmt 25#undef pr_fmt
26#define pr_fmt(fmt) "%s: " fmt, __func__ 26#define pr_fmt(fmt) "%s: " fmt, __func__
27 27
28static int ti_dt_clk_memmap_index;
29struct ti_clk_ll_ops *ti_clk_ll_ops; 28struct ti_clk_ll_ops *ti_clk_ll_ops;
29static struct device_node *clocks_node_ptr[CLK_MAX_MEMMAPS];
30 30
31/** 31/**
32 * ti_dt_clocks_register - register DT alias clocks during boot 32 * ti_dt_clocks_register - register DT alias clocks during boot
@@ -108,9 +108,21 @@ void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index)
108 struct clk_omap_reg *reg; 108 struct clk_omap_reg *reg;
109 u32 val; 109 u32 val;
110 u32 tmp; 110 u32 tmp;
111 int i;
111 112
112 reg = (struct clk_omap_reg *)&tmp; 113 reg = (struct clk_omap_reg *)&tmp;
113 reg->index = ti_dt_clk_memmap_index; 114
115 for (i = 0; i < CLK_MAX_MEMMAPS; i++) {
116 if (clocks_node_ptr[i] == node->parent)
117 break;
118 }
119
120 if (i == CLK_MAX_MEMMAPS) {
121 pr_err("clk-provider not found for %s!\n", node->name);
122 return NULL;
123 }
124
125 reg->index = i;
114 126
115 if (of_property_read_u32_index(node, "reg", index, &val)) { 127 if (of_property_read_u32_index(node, "reg", index, &val)) {
116 pr_err("%s must have reg[%d]!\n", node->name, index); 128 pr_err("%s must have reg[%d]!\n", node->name, index);
@@ -127,20 +139,14 @@ void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index)
127 * @parent: master node 139 * @parent: master node
128 * @index: internal index for clk_reg_ops 140 * @index: internal index for clk_reg_ops
129 * 141 *
130 * Initializes a master clock IP block and its child clock nodes. 142 * Initializes a master clock IP block. This basically sets up the
131 * Regmap is provided for accessing the register space for the 143 * mapping from clocks node to the memory map index. All the clocks
132 * IP block and all the clocks under it. 144 * are then initialized through the common of_clk_init call, and the
145 * clocks will access their memory maps based on the node layout.
133 */ 146 */
134void ti_dt_clk_init_provider(struct device_node *parent, int index) 147void ti_dt_clk_init_provider(struct device_node *parent, int index)
135{ 148{
136 const struct of_device_id *match;
137 struct device_node *np;
138 struct device_node *clocks; 149 struct device_node *clocks;
139 of_clk_init_cb_t clk_init_cb;
140 struct clk_init_item *retry;
141 struct clk_init_item *tmp;
142
143 ti_dt_clk_memmap_index = index;
144 150
145 /* get clocks for this parent */ 151 /* get clocks for this parent */
146 clocks = of_get_child_by_name(parent, "clocks"); 152 clocks = of_get_child_by_name(parent, "clocks");
@@ -149,19 +155,31 @@ void ti_dt_clk_init_provider(struct device_node *parent, int index)
149 return; 155 return;
150 } 156 }
151 157
152 for_each_child_of_node(clocks, np) { 158 /* add clocks node info */
153 match = of_match_node(&__clk_of_table, np); 159 clocks_node_ptr[index] = clocks;
154 if (!match) 160}
155 continue;
156 clk_init_cb = (of_clk_init_cb_t)match->data;
157 pr_debug("%s: initializing: %s\n", __func__, np->name);
158 clk_init_cb(np);
159 }
160 161
161 list_for_each_entry_safe(retry, tmp, &retry_list, link) { 162/**
162 pr_debug("retry-init: %s\n", retry->node->name); 163 * ti_dt_clk_init_retry_clks - init clocks from the retry list
163 retry->func(retry->hw, retry->node); 164 *
164 list_del(&retry->link); 165 * Initializes any clocks that have failed to initialize before,
165 kfree(retry); 166 * reasons being missing parent node(s) during earlier init. This
167 * typically happens only for DPLLs which need to have both of their
168 * parent clocks ready during init.
169 */
170void ti_dt_clk_init_retry_clks(void)
171{
172 struct clk_init_item *retry;
173 struct clk_init_item *tmp;
174 int retries = 5;
175
176 while (!list_empty(&retry_list) && retries) {
177 list_for_each_entry_safe(retry, tmp, &retry_list, link) {
178 pr_debug("retry-init: %s\n", retry->node->name);
179 retry->func(retry->hw, retry->node);
180 list_del(&retry->link);
181 kfree(retry);
182 }
183 retries--;
166 } 184 }
167} 185}