提交 4cff6d99 编写于 作者: S Sahitya Tummala 提交者: Christoph Hellwig

ufs: Add freq-table-hz property for UFS device

Add freq-table-hz propery for UFS device to keep track of
<min max> frequencies supported by UFS clocks.
Signed-off-by: NSahitya Tummala <stummala@codeaurora.org>
Signed-off-by: NDolev Raviv <draviv@codeaurora.org>
Signed-off-by: NChristoph Hellwig <hch@lst.de>
上级 1ab27c9c
...@@ -26,11 +26,11 @@ Optional properties: ...@@ -26,11 +26,11 @@ Optional properties:
- clocks : List of phandle and clock specifier pairs - clocks : List of phandle and clock specifier pairs
- clock-names : List of clock input name strings sorted in the same - clock-names : List of clock input name strings sorted in the same
order as the clocks property. order as the clocks property.
- max-clock-frequency-hz : List of maximum operating frequency stored in the same - freq-table-hz : Array of <min max> operating frequencies stored in the same
order as the clocks property. If this property is not order as the clocks property. If this property is not
defined or a value in the array is "0" then it is assumed defined or a value in the array is "0" then it is assumed
that the frequency is set by the parent clock or a that the frequency is set by the parent clock or a
fixed rate clock source. fixed rate clock source.
Note: If above properties are not defined it can be assumed that the supply Note: If above properties are not defined it can be assumed that the supply
regulators or clocks are always on. regulators or clocks are always on.
...@@ -53,5 +53,5 @@ Example: ...@@ -53,5 +53,5 @@ Example:
clocks = <&core 0>, <&ref 0>, <&iface 0>; clocks = <&core 0>, <&ref 0>, <&iface 0>;
clock-names = "core_clk", "ref_clk", "iface_clk"; clock-names = "core_clk", "ref_clk", "iface_clk";
max-clock-frequency-hz = <100000000 19200000 0>; freq-table-hz = <100000000 200000000>, <0 0>, <0 0>;
}; };
...@@ -63,6 +63,8 @@ static int ufshcd_parse_clock_info(struct ufs_hba *hba) ...@@ -63,6 +63,8 @@ static int ufshcd_parse_clock_info(struct ufs_hba *hba)
char *name; char *name;
u32 *clkfreq = NULL; u32 *clkfreq = NULL;
struct ufs_clk_info *clki; struct ufs_clk_info *clki;
int len = 0;
size_t sz = 0;
if (!np) if (!np)
goto out; goto out;
...@@ -82,39 +84,59 @@ static int ufshcd_parse_clock_info(struct ufs_hba *hba) ...@@ -82,39 +84,59 @@ static int ufshcd_parse_clock_info(struct ufs_hba *hba)
if (cnt <= 0) if (cnt <= 0)
goto out; goto out;
clkfreq = kzalloc(cnt * sizeof(*clkfreq), GFP_KERNEL); if (!of_get_property(np, "freq-table-hz", &len)) {
dev_info(dev, "freq-table-hz property not specified\n");
goto out;
}
if (len <= 0)
goto out;
sz = len / sizeof(*clkfreq);
if (sz != 2 * cnt) {
dev_err(dev, "%s len mismatch\n", "freq-table-hz");
ret = -EINVAL;
goto out;
}
clkfreq = devm_kzalloc(dev, sz * sizeof(*clkfreq),
GFP_KERNEL);
if (!clkfreq) { if (!clkfreq) {
dev_err(dev, "%s: no memory\n", "freq-table-hz");
ret = -ENOMEM; ret = -ENOMEM;
dev_err(dev, "%s: memory alloc failed\n", __func__);
goto out; goto out;
} }
ret = of_property_read_u32_array(np, ret = of_property_read_u32_array(np, "freq-table-hz",
"max-clock-frequency-hz", clkfreq, cnt); clkfreq, sz);
if (ret && (ret != -EINVAL)) { if (ret && (ret != -EINVAL)) {
dev_err(dev, "%s: invalid max-clock-frequency-hz property, %d\n", dev_err(dev, "%s: error reading array %d\n",
__func__, ret); "freq-table-hz", ret);
goto out; goto free_clkfreq;
} }
for (i = 0; i < cnt; i++) { for (i = 0; i < sz; i += 2) {
ret = of_property_read_string_index(np, ret = of_property_read_string_index(np,
"clock-names", i, (const char **)&name); "clock-names", i/2, (const char **)&name);
if (ret) if (ret)
goto out; goto free_clkfreq;
clki = devm_kzalloc(dev, sizeof(*clki), GFP_KERNEL); clki = devm_kzalloc(dev, sizeof(*clki), GFP_KERNEL);
if (!clki) { if (!clki) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto free_clkfreq;
} }
clki->max_freq = clkfreq[i]; clki->min_freq = clkfreq[i];
clki->max_freq = clkfreq[i+1];
clki->name = kstrdup(name, GFP_KERNEL); clki->name = kstrdup(name, GFP_KERNEL);
dev_dbg(dev, "%s: min %u max %u name %s\n", "freq-table-hz",
clki->min_freq, clki->max_freq, clki->name);
list_add_tail(&clki->list, &hba->clk_list_head); list_add_tail(&clki->list, &hba->clk_list_head);
} }
out: free_clkfreq:
kfree(clkfreq); kfree(clkfreq);
out:
return ret; return ret;
} }
......
...@@ -209,6 +209,7 @@ struct ufs_dev_cmd { ...@@ -209,6 +209,7 @@ struct ufs_dev_cmd {
* @clk: clock node * @clk: clock node
* @name: clock name * @name: clock name
* @max_freq: maximum frequency supported by the clock * @max_freq: maximum frequency supported by the clock
* @min_freq: min frequency that can be used for clock scaling
* @enabled: variable to check against multiple enable/disable * @enabled: variable to check against multiple enable/disable
*/ */
struct ufs_clk_info { struct ufs_clk_info {
...@@ -216,6 +217,7 @@ struct ufs_clk_info { ...@@ -216,6 +217,7 @@ struct ufs_clk_info {
struct clk *clk; struct clk *clk;
const char *name; const char *name;
u32 max_freq; u32 max_freq;
u32 min_freq;
bool enabled; bool enabled;
}; };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册