0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/clk-provider.h>
0011 #include <linux/slab.h>
0012 #include <linux/io.h>
0013 #include <linux/of.h>
0014 #include <linux/of_address.h>
0015 #include <linux/clk/ti.h>
0016 #include <linux/list.h>
0017
0018 #include "clock.h"
0019
0020 #undef pr_fmt
0021 #define pr_fmt(fmt) "%s: " fmt, __func__
0022
0023 static unsigned long ti_composite_recalc_rate(struct clk_hw *hw,
0024 unsigned long parent_rate)
0025 {
0026 return ti_clk_divider_ops.recalc_rate(hw, parent_rate);
0027 }
0028
0029 static long ti_composite_round_rate(struct clk_hw *hw, unsigned long rate,
0030 unsigned long *prate)
0031 {
0032 return -EINVAL;
0033 }
0034
0035 static int ti_composite_set_rate(struct clk_hw *hw, unsigned long rate,
0036 unsigned long parent_rate)
0037 {
0038 return -EINVAL;
0039 }
0040
0041 static const struct clk_ops ti_composite_divider_ops = {
0042 .recalc_rate = &ti_composite_recalc_rate,
0043 .round_rate = &ti_composite_round_rate,
0044 .set_rate = &ti_composite_set_rate,
0045 };
0046
0047 static const struct clk_ops ti_composite_gate_ops = {
0048 .enable = &omap2_dflt_clk_enable,
0049 .disable = &omap2_dflt_clk_disable,
0050 .is_enabled = &omap2_dflt_clk_is_enabled,
0051 };
0052
0053 struct component_clk {
0054 int num_parents;
0055 const char **parent_names;
0056 struct device_node *node;
0057 int type;
0058 struct clk_hw *hw;
0059 struct list_head link;
0060 };
0061
0062 static const char * const component_clk_types[] __initconst = {
0063 "gate", "divider", "mux"
0064 };
0065
0066 static LIST_HEAD(component_clks);
0067
0068 static struct device_node *_get_component_node(struct device_node *node, int i)
0069 {
0070 int rc;
0071 struct of_phandle_args clkspec;
0072
0073 rc = of_parse_phandle_with_args(node, "clocks", "#clock-cells", i,
0074 &clkspec);
0075 if (rc)
0076 return NULL;
0077
0078 return clkspec.np;
0079 }
0080
0081 static struct component_clk *_lookup_component(struct device_node *node)
0082 {
0083 struct component_clk *comp;
0084
0085 list_for_each_entry(comp, &component_clks, link) {
0086 if (comp->node == node)
0087 return comp;
0088 }
0089 return NULL;
0090 }
0091
0092 struct clk_hw_omap_comp {
0093 struct clk_hw hw;
0094 struct device_node *comp_nodes[CLK_COMPONENT_TYPE_MAX];
0095 struct component_clk *comp_clks[CLK_COMPONENT_TYPE_MAX];
0096 };
0097
0098 static inline struct clk_hw *_get_hw(struct clk_hw_omap_comp *clk, int idx)
0099 {
0100 if (!clk)
0101 return NULL;
0102
0103 if (!clk->comp_clks[idx])
0104 return NULL;
0105
0106 return clk->comp_clks[idx]->hw;
0107 }
0108
0109 #define to_clk_hw_comp(_hw) container_of(_hw, struct clk_hw_omap_comp, hw)
0110
0111 static void __init _register_composite(void *user,
0112 struct device_node *node)
0113 {
0114 struct clk_hw *hw = user;
0115 struct clk *clk;
0116 struct clk_hw_omap_comp *cclk = to_clk_hw_comp(hw);
0117 struct component_clk *comp;
0118 int num_parents = 0;
0119 const char **parent_names = NULL;
0120 const char *name;
0121 int i;
0122 int ret;
0123
0124
0125 for (i = 0; i < CLK_COMPONENT_TYPE_MAX; i++) {
0126 if (!cclk->comp_nodes[i])
0127 continue;
0128
0129 comp = _lookup_component(cclk->comp_nodes[i]);
0130 if (!comp) {
0131 pr_debug("component %s not ready for %pOFn, retry\n",
0132 cclk->comp_nodes[i]->name, node);
0133 if (!ti_clk_retry_init(node, hw,
0134 _register_composite))
0135 return;
0136
0137 goto cleanup;
0138 }
0139 if (cclk->comp_clks[comp->type] != NULL) {
0140 pr_err("duplicate component types for %pOFn (%s)!\n",
0141 node, component_clk_types[comp->type]);
0142 goto cleanup;
0143 }
0144
0145 cclk->comp_clks[comp->type] = comp;
0146
0147
0148 cclk->comp_nodes[i] = NULL;
0149 }
0150
0151
0152 for (i = CLK_COMPONENT_TYPE_MAX - 1; i >= 0; i--) {
0153 comp = cclk->comp_clks[i];
0154 if (!comp)
0155 continue;
0156 if (comp->num_parents) {
0157 num_parents = comp->num_parents;
0158 parent_names = comp->parent_names;
0159 break;
0160 }
0161 }
0162
0163 if (!num_parents) {
0164 pr_err("%s: no parents found for %pOFn!\n", __func__, node);
0165 goto cleanup;
0166 }
0167
0168 name = ti_dt_clk_name(node);
0169 clk = clk_register_composite(NULL, name,
0170 parent_names, num_parents,
0171 _get_hw(cclk, CLK_COMPONENT_TYPE_MUX),
0172 &ti_clk_mux_ops,
0173 _get_hw(cclk, CLK_COMPONENT_TYPE_DIVIDER),
0174 &ti_composite_divider_ops,
0175 _get_hw(cclk, CLK_COMPONENT_TYPE_GATE),
0176 &ti_composite_gate_ops, 0);
0177
0178 if (!IS_ERR(clk)) {
0179 ret = ti_clk_add_alias(NULL, clk, name);
0180 if (ret) {
0181 clk_unregister(clk);
0182 goto cleanup;
0183 }
0184 of_clk_add_provider(node, of_clk_src_simple_get, clk);
0185 }
0186
0187 cleanup:
0188
0189 for (i = 0; i < CLK_COMPONENT_TYPE_MAX; i++) {
0190 if (!cclk->comp_clks[i])
0191 continue;
0192 list_del(&cclk->comp_clks[i]->link);
0193 kfree(cclk->comp_clks[i]->parent_names);
0194 kfree(cclk->comp_clks[i]);
0195 }
0196
0197 kfree(cclk);
0198 }
0199
0200 static void __init of_ti_composite_clk_setup(struct device_node *node)
0201 {
0202 unsigned int num_clks;
0203 int i;
0204 struct clk_hw_omap_comp *cclk;
0205
0206
0207 num_clks = of_clk_get_parent_count(node);
0208
0209 if (!num_clks) {
0210 pr_err("composite clk %pOFn must have component(s)\n", node);
0211 return;
0212 }
0213
0214 cclk = kzalloc(sizeof(*cclk), GFP_KERNEL);
0215 if (!cclk)
0216 return;
0217
0218
0219 for (i = 0; i < num_clks; i++)
0220 cclk->comp_nodes[i] = _get_component_node(node, i);
0221
0222 _register_composite(&cclk->hw, node);
0223 }
0224 CLK_OF_DECLARE(ti_composite_clock, "ti,composite-clock",
0225 of_ti_composite_clk_setup);
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236 int __init ti_clk_add_component(struct device_node *node, struct clk_hw *hw,
0237 int type)
0238 {
0239 unsigned int num_parents;
0240 const char **parent_names;
0241 struct component_clk *clk;
0242
0243 num_parents = of_clk_get_parent_count(node);
0244
0245 if (!num_parents) {
0246 pr_err("component-clock %pOFn must have parent(s)\n", node);
0247 return -EINVAL;
0248 }
0249
0250 parent_names = kcalloc(num_parents, sizeof(char *), GFP_KERNEL);
0251 if (!parent_names)
0252 return -ENOMEM;
0253
0254 of_clk_parent_fill(node, parent_names, num_parents);
0255
0256 clk = kzalloc(sizeof(*clk), GFP_KERNEL);
0257 if (!clk) {
0258 kfree(parent_names);
0259 return -ENOMEM;
0260 }
0261
0262 clk->num_parents = num_parents;
0263 clk->parent_names = parent_names;
0264 clk->hw = hw;
0265 clk->node = node;
0266 clk->type = type;
0267 list_add(&clk->link, &component_clks);
0268
0269 return 0;
0270 }