diff options
Diffstat (limited to 'drivers/clk/ti/clk.c')
-rw-r--r-- | drivers/clk/ti/clk.c | 68 |
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 | ||
28 | static int ti_dt_clk_memmap_index; | ||
29 | struct ti_clk_ll_ops *ti_clk_ll_ops; | 28 | struct ti_clk_ll_ops *ti_clk_ll_ops; |
29 | static 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 | */ |
134 | void ti_dt_clk_init_provider(struct device_node *parent, int index) | 147 | void 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 | */ | ||
170 | void 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 | } |