diff options
| -rw-r--r-- | drivers/clk/clk.c | 46 | ||||
| -rw-r--r-- | drivers/clk/clk.h | 5 | ||||
| -rw-r--r-- | drivers/clk/clkdev.c | 83 |
3 files changed, 69 insertions, 65 deletions
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index d46e8b9b9c9f..04288063847b 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c | |||
| @@ -4065,6 +4065,42 @@ void devm_of_clk_del_provider(struct device *dev) | |||
| 4065 | } | 4065 | } |
| 4066 | EXPORT_SYMBOL(devm_of_clk_del_provider); | 4066 | EXPORT_SYMBOL(devm_of_clk_del_provider); |
| 4067 | 4067 | ||
| 4068 | int of_parse_clkspec(const struct device_node *np, int index, const char *name, | ||
| 4069 | struct of_phandle_args *out_args) | ||
| 4070 | { | ||
| 4071 | int ret = -ENOENT; | ||
| 4072 | |||
| 4073 | /* Walk up the tree of devices looking for a clock property that matches */ | ||
| 4074 | while (np) { | ||
| 4075 | /* | ||
| 4076 | * For named clocks, first look up the name in the | ||
| 4077 | * "clock-names" property. If it cannot be found, then index | ||
| 4078 | * will be an error code and of_parse_phandle_with_args() will | ||
| 4079 | * return -EINVAL. | ||
| 4080 | */ | ||
| 4081 | if (name) | ||
| 4082 | index = of_property_match_string(np, "clock-names", name); | ||
| 4083 | ret = of_parse_phandle_with_args(np, "clocks", "#clock-cells", | ||
| 4084 | index, out_args); | ||
| 4085 | if (!ret) | ||
| 4086 | break; | ||
| 4087 | if (name && index >= 0) | ||
| 4088 | break; | ||
| 4089 | |||
| 4090 | /* | ||
| 4091 | * No matching clock found on this node. If the parent node | ||
| 4092 | * has a "clock-ranges" property, then we can try one of its | ||
| 4093 | * clocks. | ||
| 4094 | */ | ||
| 4095 | np = np->parent; | ||
| 4096 | if (np && !of_get_property(np, "clock-ranges", NULL)) | ||
| 4097 | break; | ||
| 4098 | index = 0; | ||
| 4099 | } | ||
| 4100 | |||
| 4101 | return ret; | ||
| 4102 | } | ||
| 4103 | |||
| 4068 | static struct clk_hw * | 4104 | static struct clk_hw * |
| 4069 | __of_clk_get_hw_from_provider(struct of_clk_provider *provider, | 4105 | __of_clk_get_hw_from_provider(struct of_clk_provider *provider, |
| 4070 | struct of_phandle_args *clkspec) | 4106 | struct of_phandle_args *clkspec) |
| @@ -4080,8 +4116,7 @@ __of_clk_get_hw_from_provider(struct of_clk_provider *provider, | |||
| 4080 | return __clk_get_hw(clk); | 4116 | return __clk_get_hw(clk); |
| 4081 | } | 4117 | } |
| 4082 | 4118 | ||
| 4083 | struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, | 4119 | struct clk_hw *of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec) |
| 4084 | const char *dev_id, const char *con_id) | ||
| 4085 | { | 4120 | { |
| 4086 | struct of_clk_provider *provider; | 4121 | struct of_clk_provider *provider; |
| 4087 | struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER); | 4122 | struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER); |
| @@ -4089,7 +4124,6 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, | |||
| 4089 | if (!clkspec) | 4124 | if (!clkspec) |
| 4090 | return ERR_PTR(-EINVAL); | 4125 | return ERR_PTR(-EINVAL); |
| 4091 | 4126 | ||
| 4092 | /* Check if we have such a provider in our array */ | ||
| 4093 | mutex_lock(&of_clk_mutex); | 4127 | mutex_lock(&of_clk_mutex); |
| 4094 | list_for_each_entry(provider, &of_clk_providers, link) { | 4128 | list_for_each_entry(provider, &of_clk_providers, link) { |
| 4095 | if (provider->node == clkspec->np) { | 4129 | if (provider->node == clkspec->np) { |
| @@ -4100,7 +4134,7 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, | |||
| 4100 | } | 4134 | } |
| 4101 | mutex_unlock(&of_clk_mutex); | 4135 | mutex_unlock(&of_clk_mutex); |
| 4102 | 4136 | ||
| 4103 | return clk_hw_create_clk(hw, dev_id, con_id); | 4137 | return hw; |
| 4104 | } | 4138 | } |
| 4105 | 4139 | ||
| 4106 | /** | 4140 | /** |
| @@ -4113,7 +4147,9 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, | |||
| 4113 | */ | 4147 | */ |
| 4114 | struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec) | 4148 | struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec) |
| 4115 | { | 4149 | { |
| 4116 | return __of_clk_get_from_provider(clkspec, NULL, __func__); | 4150 | struct clk_hw *hw = of_clk_get_hw_from_clkspec(clkspec); |
| 4151 | |||
| 4152 | return clk_hw_create_clk(hw, NULL, __func__); | ||
| 4117 | } | 4153 | } |
| 4118 | EXPORT_SYMBOL_GPL(of_clk_get_from_provider); | 4154 | EXPORT_SYMBOL_GPL(of_clk_get_from_provider); |
| 4119 | 4155 | ||
diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h index 4cdf30b0008c..5a0ca0e3c1f1 100644 --- a/drivers/clk/clk.h +++ b/drivers/clk/clk.h | |||
| @@ -7,8 +7,9 @@ | |||
| 7 | struct clk_hw; | 7 | struct clk_hw; |
| 8 | 8 | ||
| 9 | #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) | 9 | #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) |
| 10 | struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, | 10 | int of_parse_clkspec(const struct device_node *np, int index, const char *name, |
| 11 | const char *dev_id, const char *con_id); | 11 | struct of_phandle_args *out_args); |
| 12 | struct clk_hw *of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec); | ||
| 12 | #endif | 13 | #endif |
| 13 | 14 | ||
| 14 | #ifdef CONFIG_COMMON_CLK | 15 | #ifdef CONFIG_COMMON_CLK |
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index bdeaffc950ae..5ebb2119c0b9 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c | |||
| @@ -28,69 +28,37 @@ static LIST_HEAD(clocks); | |||
| 28 | static DEFINE_MUTEX(clocks_mutex); | 28 | static DEFINE_MUTEX(clocks_mutex); |
| 29 | 29 | ||
| 30 | #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) | 30 | #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) |
| 31 | static struct clk *__of_clk_get(struct device_node *np, int index, | 31 | static struct clk_hw *of_clk_get_hw(struct device_node *np, |
| 32 | const char *dev_id, const char *con_id) | 32 | int index, const char *con_id) |
| 33 | { | 33 | { |
| 34 | int ret; | ||
| 35 | struct clk_hw *hw; | ||
| 34 | struct of_phandle_args clkspec; | 36 | struct of_phandle_args clkspec; |
| 35 | struct clk *clk; | ||
| 36 | int rc; | ||
| 37 | 37 | ||
| 38 | rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index, | 38 | ret = of_parse_clkspec(np, index, con_id, &clkspec); |
| 39 | &clkspec); | 39 | if (ret) |
| 40 | if (rc) | 40 | return ERR_PTR(ret); |
| 41 | return ERR_PTR(rc); | ||
| 42 | 41 | ||
| 43 | clk = __of_clk_get_from_provider(&clkspec, dev_id, con_id); | 42 | hw = of_clk_get_hw_from_clkspec(&clkspec); |
| 44 | of_node_put(clkspec.np); | 43 | of_node_put(clkspec.np); |
| 45 | 44 | ||
| 46 | return clk; | 45 | return hw; |
| 47 | } | 46 | } |
| 48 | 47 | ||
| 49 | struct clk *of_clk_get(struct device_node *np, int index) | 48 | static struct clk *__of_clk_get(struct device_node *np, |
| 49 | int index, const char *dev_id, | ||
| 50 | const char *con_id) | ||
| 50 | { | 51 | { |
| 51 | return __of_clk_get(np, index, np->full_name, NULL); | 52 | struct clk_hw *hw = of_clk_get_hw(np, index, con_id); |
| 53 | |||
| 54 | return clk_hw_create_clk(hw, dev_id, con_id); | ||
| 52 | } | 55 | } |
| 53 | EXPORT_SYMBOL(of_clk_get); | ||
| 54 | 56 | ||
| 55 | static struct clk *__of_clk_get_by_name(struct device_node *np, | 57 | struct clk *of_clk_get(struct device_node *np, int index) |
| 56 | const char *dev_id, | ||
| 57 | const char *name) | ||
| 58 | { | 58 | { |
| 59 | struct clk *clk = ERR_PTR(-ENOENT); | 59 | return __of_clk_get(np, index, np->full_name, NULL); |
| 60 | |||
| 61 | /* Walk up the tree of devices looking for a clock that matches */ | ||
| 62 | while (np) { | ||
| 63 | int index = 0; | ||
| 64 | |||
| 65 | /* | ||
| 66 | * For named clocks, first look up the name in the | ||
| 67 | * "clock-names" property. If it cannot be found, then | ||
| 68 | * index will be an error code, and of_clk_get() will fail. | ||
| 69 | */ | ||
| 70 | if (name) | ||
| 71 | index = of_property_match_string(np, "clock-names", name); | ||
| 72 | clk = __of_clk_get(np, index, dev_id, name); | ||
| 73 | if (!IS_ERR(clk)) { | ||
| 74 | break; | ||
| 75 | } else if (name && index >= 0) { | ||
| 76 | if (PTR_ERR(clk) != -EPROBE_DEFER) | ||
| 77 | pr_err("ERROR: could not get clock %pOF:%s(%i)\n", | ||
| 78 | np, name ? name : "", index); | ||
| 79 | return clk; | ||
| 80 | } | ||
| 81 | |||
| 82 | /* | ||
| 83 | * No matching clock found on this node. If the parent node | ||
| 84 | * has a "clock-ranges" property, then we can try one of its | ||
| 85 | * clocks. | ||
| 86 | */ | ||
| 87 | np = np->parent; | ||
| 88 | if (np && !of_get_property(np, "clock-ranges", NULL)) | ||
| 89 | break; | ||
| 90 | } | ||
| 91 | |||
| 92 | return clk; | ||
| 93 | } | 60 | } |
| 61 | EXPORT_SYMBOL(of_clk_get); | ||
| 94 | 62 | ||
| 95 | /** | 63 | /** |
| 96 | * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node | 64 | * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node |
| @@ -106,15 +74,14 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name) | |||
| 106 | if (!np) | 74 | if (!np) |
| 107 | return ERR_PTR(-ENOENT); | 75 | return ERR_PTR(-ENOENT); |
| 108 | 76 | ||
| 109 | return __of_clk_get_by_name(np, np->full_name, name); | 77 | return __of_clk_get(np, -1, np->full_name, name); |
| 110 | } | 78 | } |
| 111 | EXPORT_SYMBOL(of_clk_get_by_name); | 79 | EXPORT_SYMBOL(of_clk_get_by_name); |
| 112 | 80 | ||
| 113 | #else /* defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) */ | 81 | #else /* defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) */ |
| 114 | 82 | ||
| 115 | static struct clk *__of_clk_get_by_name(struct device_node *np, | 83 | static struct clk_hw *of_clk_get_hw(struct device_node *np, |
| 116 | const char *dev_id, | 84 | int index, const char *con_id) |
| 117 | const char *name) | ||
| 118 | { | 85 | { |
| 119 | return ERR_PTR(-ENOENT); | 86 | return ERR_PTR(-ENOENT); |
| 120 | } | 87 | } |
| @@ -187,12 +154,12 @@ EXPORT_SYMBOL(clk_get_sys); | |||
| 187 | struct clk *clk_get(struct device *dev, const char *con_id) | 154 | struct clk *clk_get(struct device *dev, const char *con_id) |
| 188 | { | 155 | { |
| 189 | const char *dev_id = dev ? dev_name(dev) : NULL; | 156 | const char *dev_id = dev ? dev_name(dev) : NULL; |
| 190 | struct clk *clk; | 157 | struct clk_hw *hw; |
| 191 | 158 | ||
| 192 | if (dev && dev->of_node) { | 159 | if (dev && dev->of_node) { |
| 193 | clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id); | 160 | hw = of_clk_get_hw(dev->of_node, 0, con_id); |
| 194 | if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER) | 161 | if (!IS_ERR(hw) || PTR_ERR(hw) == -EPROBE_DEFER) |
| 195 | return clk; | 162 | return clk_hw_create_clk(hw, dev_id, con_id); |
| 196 | } | 163 | } |
| 197 | 164 | ||
| 198 | return clk_get_sys(dev_id, con_id); | 165 | return clk_get_sys(dev_id, con_id); |
