diff options
author | Sahitya Tummala <stummala@codeaurora.org> | 2014-09-25 08:32:33 -0400 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2014-10-01 07:11:25 -0400 |
commit | 4cff6d991e4a291cf50fe2659da2ea9ad46620bf (patch) | |
tree | c82f172707927470412a8ec0c2ff2feb5bc8baa7 | |
parent | 1ab27c9cf8b63dd8dec9e17b5c17721c7f3b6cc7 (diff) |
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>
-rw-r--r-- | Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt | 12 | ||||
-rw-r--r-- | drivers/scsi/ufs/ufshcd-pltfrm.c | 48 | ||||
-rw-r--r-- | drivers/scsi/ufs/ufshcd.h | 2 |
3 files changed, 43 insertions, 19 deletions
diff --git a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt index fb1234e0532c..53579197eca2 100644 --- a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt +++ b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt | |||
@@ -26,11 +26,11 @@ Optional properties: | |||
26 | - clocks : List of phandle and clock specifier pairs | 26 | - clocks : List of phandle and clock specifier pairs |
27 | - clock-names : List of clock input name strings sorted in the same | 27 | - clock-names : List of clock input name strings sorted in the same |
28 | order as the clocks property. | 28 | order as the clocks property. |
29 | - max-clock-frequency-hz : List of maximum operating frequency stored in the same | 29 | - freq-table-hz : Array of <min max> operating frequencies stored in the same |
30 | order as the clocks property. If this property is not | 30 | order as the clocks property. If this property is not |
31 | defined or a value in the array is "0" then it is assumed | 31 | defined or a value in the array is "0" then it is assumed |
32 | that the frequency is set by the parent clock or a | 32 | that the frequency is set by the parent clock or a |
33 | fixed rate clock source. | 33 | fixed rate clock source. |
34 | 34 | ||
35 | Note: If above properties are not defined it can be assumed that the supply | 35 | Note: If above properties are not defined it can be assumed that the supply |
36 | regulators or clocks are always on. | 36 | regulators or clocks are always on. |
@@ -53,5 +53,5 @@ Example: | |||
53 | 53 | ||
54 | clocks = <&core 0>, <&ref 0>, <&iface 0>; | 54 | clocks = <&core 0>, <&ref 0>, <&iface 0>; |
55 | clock-names = "core_clk", "ref_clk", "iface_clk"; | 55 | clock-names = "core_clk", "ref_clk", "iface_clk"; |
56 | max-clock-frequency-hz = <100000000 19200000 0>; | 56 | freq-table-hz = <100000000 200000000>, <0 0>, <0 0>; |
57 | }; | 57 | }; |
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c index 2482bbac3681..8adf067ff019 100644 --- a/drivers/scsi/ufs/ufshcd-pltfrm.c +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c | |||
@@ -63,6 +63,8 @@ static int ufshcd_parse_clock_info(struct ufs_hba *hba) | |||
63 | char *name; | 63 | char *name; |
64 | u32 *clkfreq = NULL; | 64 | u32 *clkfreq = NULL; |
65 | struct ufs_clk_info *clki; | 65 | struct ufs_clk_info *clki; |
66 | int len = 0; | ||
67 | size_t sz = 0; | ||
66 | 68 | ||
67 | if (!np) | 69 | if (!np) |
68 | goto out; | 70 | goto out; |
@@ -82,39 +84,59 @@ static int ufshcd_parse_clock_info(struct ufs_hba *hba) | |||
82 | if (cnt <= 0) | 84 | if (cnt <= 0) |
83 | goto out; | 85 | goto out; |
84 | 86 | ||
85 | clkfreq = kzalloc(cnt * sizeof(*clkfreq), GFP_KERNEL); | 87 | if (!of_get_property(np, "freq-table-hz", &len)) { |
88 | dev_info(dev, "freq-table-hz property not specified\n"); | ||
89 | goto out; | ||
90 | } | ||
91 | |||
92 | if (len <= 0) | ||
93 | goto out; | ||
94 | |||
95 | sz = len / sizeof(*clkfreq); | ||
96 | if (sz != 2 * cnt) { | ||
97 | dev_err(dev, "%s len mismatch\n", "freq-table-hz"); | ||
98 | ret = -EINVAL; | ||
99 | goto out; | ||
100 | } | ||
101 | |||
102 | clkfreq = devm_kzalloc(dev, sz * sizeof(*clkfreq), | ||
103 | GFP_KERNEL); | ||
86 | if (!clkfreq) { | 104 | if (!clkfreq) { |
105 | dev_err(dev, "%s: no memory\n", "freq-table-hz"); | ||
87 | ret = -ENOMEM; | 106 | ret = -ENOMEM; |
88 | dev_err(dev, "%s: memory alloc failed\n", __func__); | ||
89 | goto out; | 107 | goto out; |
90 | } | 108 | } |
91 | 109 | ||
92 | ret = of_property_read_u32_array(np, | 110 | ret = of_property_read_u32_array(np, "freq-table-hz", |
93 | "max-clock-frequency-hz", clkfreq, cnt); | 111 | clkfreq, sz); |
94 | if (ret && (ret != -EINVAL)) { | 112 | if (ret && (ret != -EINVAL)) { |
95 | dev_err(dev, "%s: invalid max-clock-frequency-hz property, %d\n", | 113 | dev_err(dev, "%s: error reading array %d\n", |
96 | __func__, ret); | 114 | "freq-table-hz", ret); |
97 | goto out; | 115 | goto free_clkfreq; |
98 | } | 116 | } |
99 | 117 | ||
100 | for (i = 0; i < cnt; i++) { | 118 | for (i = 0; i < sz; i += 2) { |
101 | ret = of_property_read_string_index(np, | 119 | ret = of_property_read_string_index(np, |
102 | "clock-names", i, (const char **)&name); | 120 | "clock-names", i/2, (const char **)&name); |
103 | if (ret) | 121 | if (ret) |
104 | goto out; | 122 | goto free_clkfreq; |
105 | 123 | ||
106 | clki = devm_kzalloc(dev, sizeof(*clki), GFP_KERNEL); | 124 | clki = devm_kzalloc(dev, sizeof(*clki), GFP_KERNEL); |
107 | if (!clki) { | 125 | if (!clki) { |
108 | ret = -ENOMEM; | 126 | ret = -ENOMEM; |
109 | goto out; | 127 | goto free_clkfreq; |
110 | } | 128 | } |
111 | 129 | ||
112 | clki->max_freq = clkfreq[i]; | 130 | clki->min_freq = clkfreq[i]; |
131 | clki->max_freq = clkfreq[i+1]; | ||
113 | clki->name = kstrdup(name, GFP_KERNEL); | 132 | clki->name = kstrdup(name, GFP_KERNEL); |
133 | dev_dbg(dev, "%s: min %u max %u name %s\n", "freq-table-hz", | ||
134 | clki->min_freq, clki->max_freq, clki->name); | ||
114 | list_add_tail(&clki->list, &hba->clk_list_head); | 135 | list_add_tail(&clki->list, &hba->clk_list_head); |
115 | } | 136 | } |
116 | out: | 137 | free_clkfreq: |
117 | kfree(clkfreq); | 138 | kfree(clkfreq); |
139 | out: | ||
118 | return ret; | 140 | return ret; |
119 | } | 141 | } |
120 | 142 | ||
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 29d34d3aa5ee..ac72a6daf50e 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h | |||
@@ -209,6 +209,7 @@ struct ufs_dev_cmd { | |||
209 | * @clk: clock node | 209 | * @clk: clock node |
210 | * @name: clock name | 210 | * @name: clock name |
211 | * @max_freq: maximum frequency supported by the clock | 211 | * @max_freq: maximum frequency supported by the clock |
212 | * @min_freq: min frequency that can be used for clock scaling | ||
212 | * @enabled: variable to check against multiple enable/disable | 213 | * @enabled: variable to check against multiple enable/disable |
213 | */ | 214 | */ |
214 | struct ufs_clk_info { | 215 | struct ufs_clk_info { |
@@ -216,6 +217,7 @@ struct ufs_clk_info { | |||
216 | struct clk *clk; | 217 | struct clk *clk; |
217 | const char *name; | 218 | const char *name; |
218 | u32 max_freq; | 219 | u32 max_freq; |
220 | u32 min_freq; | ||
219 | bool enabled; | 221 | bool enabled; |
220 | }; | 222 | }; |
221 | 223 | ||