mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-14 09:09:56 +00:00
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: Sahitya Tummala <stummala@codeaurora.org> Signed-off-by: Dolev Raviv <draviv@codeaurora.org> Signed-off-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
1ab27c9cf8
commit
4cff6d991e
@ -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:
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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 {
|
|||||||
* @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 {
|
|||||||
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user