.. | .. |
---|
68 | 68 | /** |
---|
69 | 69 | * struct qcom_snps_hsphy - snps hs phy attributes |
---|
70 | 70 | * |
---|
| 71 | + * @dev: device structure |
---|
| 72 | + * |
---|
71 | 73 | * @phy: generic phy |
---|
72 | 74 | * @base: iomapped memory space for snps hs phy |
---|
73 | 75 | * |
---|
74 | | - * @cfg_ahb_clk: AHB2PHY interface clock |
---|
75 | | - * @ref_clk: phy reference clock |
---|
76 | | - * @iface_clk: phy interface clock |
---|
| 76 | + * @num_clks: number of clocks |
---|
| 77 | + * @clks: array of clocks |
---|
77 | 78 | * @phy_reset: phy reset control |
---|
78 | 79 | * @vregs: regulator supplies bulk data |
---|
79 | 80 | * @phy_initialized: if PHY has been initialized correctly |
---|
80 | 81 | * @mode: contains the current mode the PHY is in |
---|
| 82 | + * @update_seq_cfg: tuning parameters for phy init |
---|
81 | 83 | */ |
---|
82 | 84 | struct qcom_snps_hsphy { |
---|
| 85 | + struct device *dev; |
---|
| 86 | + |
---|
83 | 87 | struct phy *phy; |
---|
84 | 88 | void __iomem *base; |
---|
85 | 89 | |
---|
86 | | - struct clk *cfg_ahb_clk; |
---|
87 | | - struct clk *ref_clk; |
---|
| 90 | + int num_clks; |
---|
| 91 | + struct clk_bulk_data *clks; |
---|
88 | 92 | struct reset_control *phy_reset; |
---|
89 | 93 | struct regulator_bulk_data vregs[SNPS_HS_NUM_VREGS]; |
---|
90 | 94 | |
---|
91 | 95 | bool phy_initialized; |
---|
92 | 96 | enum phy_mode mode; |
---|
93 | 97 | }; |
---|
| 98 | + |
---|
| 99 | +static int qcom_snps_hsphy_clk_init(struct qcom_snps_hsphy *hsphy) |
---|
| 100 | +{ |
---|
| 101 | + struct device *dev = hsphy->dev; |
---|
| 102 | + |
---|
| 103 | + hsphy->num_clks = 2; |
---|
| 104 | + hsphy->clks = devm_kcalloc(dev, hsphy->num_clks, sizeof(*hsphy->clks), GFP_KERNEL); |
---|
| 105 | + if (!hsphy->clks) |
---|
| 106 | + return -ENOMEM; |
---|
| 107 | + |
---|
| 108 | + /* |
---|
| 109 | + * TODO: Currently no device tree instantiation of the PHY is using the clock. |
---|
| 110 | + * This needs to be fixed in order for this code to be able to use devm_clk_bulk_get(). |
---|
| 111 | + */ |
---|
| 112 | + hsphy->clks[0].id = "cfg_ahb"; |
---|
| 113 | + hsphy->clks[0].clk = devm_clk_get_optional(dev, "cfg_ahb"); |
---|
| 114 | + if (IS_ERR(hsphy->clks[0].clk)) |
---|
| 115 | + return dev_err_probe(dev, PTR_ERR(hsphy->clks[0].clk), |
---|
| 116 | + "failed to get cfg_ahb clk\n"); |
---|
| 117 | + |
---|
| 118 | + hsphy->clks[1].id = "ref"; |
---|
| 119 | + hsphy->clks[1].clk = devm_clk_get(dev, "ref"); |
---|
| 120 | + if (IS_ERR(hsphy->clks[1].clk)) |
---|
| 121 | + return dev_err_probe(dev, PTR_ERR(hsphy->clks[1].clk), |
---|
| 122 | + "failed to get ref clk\n"); |
---|
| 123 | + |
---|
| 124 | + return 0; |
---|
| 125 | +} |
---|
94 | 126 | |
---|
95 | 127 | static inline void qcom_snps_hsphy_write_mask(void __iomem *base, u32 offset, |
---|
96 | 128 | u32 mask, u32 val) |
---|
.. | .. |
---|
122 | 154 | 0, USB2_AUTO_RESUME); |
---|
123 | 155 | } |
---|
124 | 156 | |
---|
125 | | - clk_disable_unprepare(hsphy->cfg_ahb_clk); |
---|
126 | 157 | return 0; |
---|
127 | 158 | } |
---|
128 | 159 | |
---|
129 | 160 | static int qcom_snps_hsphy_resume(struct qcom_snps_hsphy *hsphy) |
---|
130 | 161 | { |
---|
131 | | - int ret; |
---|
132 | | - |
---|
133 | 162 | dev_dbg(&hsphy->phy->dev, "Resume QCOM SNPS PHY, mode\n"); |
---|
134 | | - |
---|
135 | | - ret = clk_prepare_enable(hsphy->cfg_ahb_clk); |
---|
136 | | - if (ret) { |
---|
137 | | - dev_err(&hsphy->phy->dev, "failed to enable cfg ahb clock\n"); |
---|
138 | | - return ret; |
---|
139 | | - } |
---|
140 | 163 | |
---|
141 | 164 | return 0; |
---|
142 | 165 | } |
---|
.. | .. |
---|
148 | 171 | if (!hsphy->phy_initialized) |
---|
149 | 172 | return 0; |
---|
150 | 173 | |
---|
151 | | - qcom_snps_hsphy_suspend(hsphy); |
---|
152 | | - return 0; |
---|
| 174 | + return qcom_snps_hsphy_suspend(hsphy); |
---|
153 | 175 | } |
---|
154 | 176 | |
---|
155 | 177 | static int __maybe_unused qcom_snps_hsphy_runtime_resume(struct device *dev) |
---|
.. | .. |
---|
159 | 181 | if (!hsphy->phy_initialized) |
---|
160 | 182 | return 0; |
---|
161 | 183 | |
---|
162 | | - qcom_snps_hsphy_resume(hsphy); |
---|
163 | | - return 0; |
---|
| 184 | + return qcom_snps_hsphy_resume(hsphy); |
---|
164 | 185 | } |
---|
165 | 186 | |
---|
166 | 187 | static int qcom_snps_hsphy_set_mode(struct phy *phy, enum phy_mode mode, |
---|
.. | .. |
---|
183 | 204 | if (ret) |
---|
184 | 205 | return ret; |
---|
185 | 206 | |
---|
186 | | - ret = clk_prepare_enable(hsphy->cfg_ahb_clk); |
---|
| 207 | + ret = clk_bulk_prepare_enable(hsphy->num_clks, hsphy->clks); |
---|
187 | 208 | if (ret) { |
---|
188 | | - dev_err(&phy->dev, "failed to enable cfg ahb clock, %d\n", ret); |
---|
| 209 | + dev_err(&phy->dev, "failed to enable clocks, %d\n", ret); |
---|
189 | 210 | goto poweroff_phy; |
---|
190 | 211 | } |
---|
191 | 212 | |
---|
192 | 213 | ret = reset_control_assert(hsphy->phy_reset); |
---|
193 | 214 | if (ret) { |
---|
194 | 215 | dev_err(&phy->dev, "failed to assert phy_reset, %d\n", ret); |
---|
195 | | - goto disable_ahb_clk; |
---|
| 216 | + goto disable_clks; |
---|
196 | 217 | } |
---|
197 | 218 | |
---|
198 | 219 | usleep_range(100, 150); |
---|
.. | .. |
---|
200 | 221 | ret = reset_control_deassert(hsphy->phy_reset); |
---|
201 | 222 | if (ret) { |
---|
202 | 223 | dev_err(&phy->dev, "failed to de-assert phy_reset, %d\n", ret); |
---|
203 | | - goto disable_ahb_clk; |
---|
| 224 | + goto disable_clks; |
---|
204 | 225 | } |
---|
205 | 226 | |
---|
206 | 227 | qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_CFG0, |
---|
.. | .. |
---|
246 | 267 | |
---|
247 | 268 | return 0; |
---|
248 | 269 | |
---|
249 | | -disable_ahb_clk: |
---|
250 | | - clk_disable_unprepare(hsphy->cfg_ahb_clk); |
---|
| 270 | +disable_clks: |
---|
| 271 | + clk_bulk_disable_unprepare(hsphy->num_clks, hsphy->clks); |
---|
251 | 272 | poweroff_phy: |
---|
252 | 273 | regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs); |
---|
253 | 274 | |
---|
.. | .. |
---|
259 | 280 | struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy); |
---|
260 | 281 | |
---|
261 | 282 | reset_control_assert(hsphy->phy_reset); |
---|
262 | | - clk_disable_unprepare(hsphy->cfg_ahb_clk); |
---|
| 283 | + clk_bulk_disable_unprepare(hsphy->num_clks, hsphy->clks); |
---|
263 | 284 | regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs); |
---|
264 | 285 | hsphy->phy_initialized = false; |
---|
265 | 286 | |
---|
.. | .. |
---|
299 | 320 | if (!hsphy) |
---|
300 | 321 | return -ENOMEM; |
---|
301 | 322 | |
---|
| 323 | + hsphy->dev = dev; |
---|
| 324 | + |
---|
302 | 325 | hsphy->base = devm_platform_ioremap_resource(pdev, 0); |
---|
303 | 326 | if (IS_ERR(hsphy->base)) |
---|
304 | 327 | return PTR_ERR(hsphy->base); |
---|
305 | 328 | |
---|
306 | | - hsphy->ref_clk = devm_clk_get(dev, "ref"); |
---|
307 | | - if (IS_ERR(hsphy->ref_clk)) { |
---|
308 | | - ret = PTR_ERR(hsphy->ref_clk); |
---|
309 | | - if (ret != -EPROBE_DEFER) |
---|
310 | | - dev_err(dev, "failed to get ref clk, %d\n", ret); |
---|
311 | | - return ret; |
---|
312 | | - } |
---|
| 329 | + ret = qcom_snps_hsphy_clk_init(hsphy); |
---|
| 330 | + if (ret) |
---|
| 331 | + return dev_err_probe(dev, ret, "failed to initialize clocks\n"); |
---|
313 | 332 | |
---|
314 | 333 | hsphy->phy_reset = devm_reset_control_get_exclusive(&pdev->dev, NULL); |
---|
315 | 334 | if (IS_ERR(hsphy->phy_reset)) { |
---|
.. | .. |
---|
322 | 341 | hsphy->vregs[i].supply = qcom_snps_hsphy_vreg_names[i]; |
---|
323 | 342 | |
---|
324 | 343 | ret = devm_regulator_bulk_get(dev, num, hsphy->vregs); |
---|
325 | | - if (ret) { |
---|
326 | | - if (ret != -EPROBE_DEFER) |
---|
327 | | - dev_err(dev, "failed to get regulator supplies: %d\n", |
---|
328 | | - ret); |
---|
329 | | - return ret; |
---|
330 | | - } |
---|
| 344 | + if (ret) |
---|
| 345 | + return dev_err_probe(dev, ret, |
---|
| 346 | + "failed to get regulator supplies\n"); |
---|
331 | 347 | |
---|
332 | 348 | pm_runtime_set_active(dev); |
---|
333 | 349 | pm_runtime_enable(dev); |
---|