blob: b531508d19ec33cf69da1889654e3f617ef0acde [file] [log] [blame]
Mayank Rana3cb43a32016-08-02 12:10:20 -07001/*
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -07002 * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
Mayank Rana3cb43a32016-08-02 12:10:20 -07003 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/err.h>
17#include <linux/slab.h>
18#include <linux/clk.h>
Mayank Rana3cb43a32016-08-02 12:10:20 -070019#include <linux/delay.h>
20#include <linux/io.h>
21#include <linux/of.h>
22#include <linux/platform_device.h>
23#include <linux/power_supply.h>
24#include <linux/regulator/consumer.h>
25#include <linux/regulator/driver.h>
26#include <linux/regulator/machine.h>
27#include <linux/usb/phy.h>
Amit Nischal4d278212016-06-06 17:54:34 +053028#include <linux/reset.h>
Mayank Rana3cb43a32016-08-02 12:10:20 -070029
Mayank Rana9c6b12d2017-06-22 16:23:26 -070030/* QUSB2PHY_PWR_CTRL1 register related bits */
Mayank Rana3cb43a32016-08-02 12:10:20 -070031#define PWR_CTRL1_POWR_DOWN BIT(0)
32
Mayank Rana9c6b12d2017-06-22 16:23:26 -070033/* QUSB2PHY_PLL_COMMON_STATUS_ONE register related bits */
Mayank Rana3cb43a32016-08-02 12:10:20 -070034#define CORE_READY_STATUS BIT(0)
35
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -070036/* Get TUNE value from efuse bit-mask */
37#define TUNE_VAL_MASK(val, pos, mask) ((val >> pos) & mask)
Mayank Rana3cb43a32016-08-02 12:10:20 -070038
Mayank Rana9c6b12d2017-06-22 16:23:26 -070039/* QUSB2PHY_INTR_CTRL register related bits */
Mayank Rana3cb43a32016-08-02 12:10:20 -070040#define DMSE_INTR_HIGH_SEL BIT(4)
41#define DPSE_INTR_HIGH_SEL BIT(3)
42#define CHG_DET_INTR_EN BIT(2)
43#define DMSE_INTR_EN BIT(1)
44#define DPSE_INTR_EN BIT(0)
45
Mayank Rana9c6b12d2017-06-22 16:23:26 -070046/* QUSB2PHY_PLL_CORE_INPUT_OVERRIDE register related bits */
Mayank Ranab7f212e2017-04-06 17:54:35 -070047#define CORE_PLL_RATE BIT(0)
48#define CORE_PLL_RATE_MUX BIT(1)
49#define CORE_PLL_EN BIT(2)
50#define CORE_PLL_EN_MUX BIT(3)
51#define CORE_PLL_EN_FROM_RESET BIT(4)
52#define CORE_RESET BIT(5)
53#define CORE_RESET_MUX BIT(6)
54
Mayank Rana3cb43a32016-08-02 12:10:20 -070055#define QUSB2PHY_1P8_VOL_MIN 1800000 /* uV */
56#define QUSB2PHY_1P8_VOL_MAX 1800000 /* uV */
57#define QUSB2PHY_1P8_HPM_LOAD 30000 /* uA */
58
59#define QUSB2PHY_3P3_VOL_MIN 3075000 /* uV */
60#define QUSB2PHY_3P3_VOL_MAX 3200000 /* uV */
61#define QUSB2PHY_3P3_HPM_LOAD 30000 /* uA */
62
63#define LINESTATE_DP BIT(0)
64#define LINESTATE_DM BIT(1)
65
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -070066unsigned int phy_tune1;
67module_param(phy_tune1, uint, 0644);
68MODULE_PARM_DESC(phy_tune1, "QUSB PHY v2 TUNE1");
Mayank Rana3cb43a32016-08-02 12:10:20 -070069
Mayank Rana9c6b12d2017-06-22 16:23:26 -070070enum qusb_phy_reg {
71 PORT_TUNE1,
72 PLL_COMMON_STATUS_ONE,
73 PWR_CTRL1,
74 INTR_CTRL,
75 PLL_CORE_INPUT_OVERRIDE,
76 TEST1,
77 USB2_PHY_REG_MAX,
78};
79
Mayank Rana3cb43a32016-08-02 12:10:20 -070080struct qusb_phy {
81 struct usb_phy phy;
82 void __iomem *base;
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -070083 void __iomem *efuse_reg;
Mayank Rana3cb43a32016-08-02 12:10:20 -070084
85 struct clk *ref_clk_src;
86 struct clk *ref_clk;
87 struct clk *cfg_ahb_clk;
Amit Nischal4d278212016-06-06 17:54:34 +053088 struct reset_control *phy_reset;
Mayank Rana3cb43a32016-08-02 12:10:20 -070089
90 struct regulator *vdd;
91 struct regulator *vdda33;
92 struct regulator *vdda18;
93 int vdd_levels[3]; /* none, low, high */
94 int init_seq_len;
95 int *qusb_phy_init_seq;
96 int host_init_seq_len;
97 int *qusb_phy_host_init_seq;
98
Mayank Rana9c6b12d2017-06-22 16:23:26 -070099 unsigned int *phy_reg;
100 int qusb_phy_reg_offset_cnt;
101
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700102 u32 tune_val;
103 int efuse_bit_pos;
104 int efuse_num_of_bits;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700105
106 bool power_enabled;
107 bool clocks_enabled;
108 bool cable_connected;
109 bool suspended;
Mayank Ranadadae592017-07-21 09:03:32 -0700110 bool dpdm_enable;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700111
112 struct regulator_desc dpdm_rdesc;
113 struct regulator_dev *dpdm_rdev;
114
115 /* emulation targets specific */
116 void __iomem *emu_phy_base;
117 bool emulation;
118 int *emu_init_seq;
119 int emu_init_seq_len;
120 int *phy_pll_reset_seq;
121 int phy_pll_reset_seq_len;
122 int *emu_dcm_reset_seq;
123 int emu_dcm_reset_seq_len;
124};
125
126static void qusb_phy_enable_clocks(struct qusb_phy *qphy, bool on)
127{
128 dev_dbg(qphy->phy.dev, "%s(): clocks_enabled:%d on:%d\n",
129 __func__, qphy->clocks_enabled, on);
130
131 if (!qphy->clocks_enabled && on) {
132 clk_prepare_enable(qphy->ref_clk_src);
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700133 if (qphy->ref_clk)
134 clk_prepare_enable(qphy->ref_clk);
135
136 if (qphy->cfg_ahb_clk)
137 clk_prepare_enable(qphy->cfg_ahb_clk);
138
Mayank Rana3cb43a32016-08-02 12:10:20 -0700139 qphy->clocks_enabled = true;
140 }
141
142 if (qphy->clocks_enabled && !on) {
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700143 if (qphy->cfg_ahb_clk)
144 clk_disable_unprepare(qphy->cfg_ahb_clk);
145
146 if (qphy->ref_clk)
147 clk_disable_unprepare(qphy->ref_clk);
148
Mayank Rana3cb43a32016-08-02 12:10:20 -0700149 clk_disable_unprepare(qphy->ref_clk_src);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700150 qphy->clocks_enabled = false;
151 }
152
153 dev_dbg(qphy->phy.dev, "%s(): clocks_enabled:%d\n", __func__,
154 qphy->clocks_enabled);
155}
156
157static int qusb_phy_config_vdd(struct qusb_phy *qphy, int high)
158{
159 int min, ret;
160
161 min = high ? 1 : 0; /* low or none? */
162 ret = regulator_set_voltage(qphy->vdd, qphy->vdd_levels[min],
163 qphy->vdd_levels[2]);
164 if (ret) {
165 dev_err(qphy->phy.dev, "unable to set voltage for qusb vdd\n");
166 return ret;
167 }
168
169 dev_dbg(qphy->phy.dev, "min_vol:%d max_vol:%d\n",
170 qphy->vdd_levels[min], qphy->vdd_levels[2]);
171 return ret;
172}
173
Hemant Kumar7dc63722017-04-27 17:51:11 -0700174static int qusb_phy_enable_power(struct qusb_phy *qphy, bool on)
Mayank Rana3cb43a32016-08-02 12:10:20 -0700175{
176 int ret = 0;
177
178 dev_dbg(qphy->phy.dev, "%s turn %s regulators. power_enabled:%d\n",
179 __func__, on ? "on" : "off", qphy->power_enabled);
180
Hemant Kumar7dc63722017-04-27 17:51:11 -0700181 if (qphy->power_enabled == on) {
Mayank Rana3cb43a32016-08-02 12:10:20 -0700182 dev_dbg(qphy->phy.dev, "PHYs' regulators are already ON.\n");
183 return 0;
184 }
185
186 if (!on)
187 goto disable_vdda33;
188
Hemant Kumar7dc63722017-04-27 17:51:11 -0700189 ret = qusb_phy_config_vdd(qphy, true);
190 if (ret) {
191 dev_err(qphy->phy.dev, "Unable to config VDD:%d\n",
192 ret);
193 goto err_vdd;
194 }
Mayank Rana3cb43a32016-08-02 12:10:20 -0700195
Hemant Kumar7dc63722017-04-27 17:51:11 -0700196 ret = regulator_enable(qphy->vdd);
197 if (ret) {
198 dev_err(qphy->phy.dev, "Unable to enable VDD\n");
199 goto unconfig_vdd;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700200 }
201
202 ret = regulator_set_load(qphy->vdda18, QUSB2PHY_1P8_HPM_LOAD);
203 if (ret < 0) {
204 dev_err(qphy->phy.dev, "Unable to set HPM of vdda18:%d\n", ret);
205 goto disable_vdd;
206 }
207
208 ret = regulator_set_voltage(qphy->vdda18, QUSB2PHY_1P8_VOL_MIN,
209 QUSB2PHY_1P8_VOL_MAX);
210 if (ret) {
211 dev_err(qphy->phy.dev,
212 "Unable to set voltage for vdda18:%d\n", ret);
213 goto put_vdda18_lpm;
214 }
215
216 ret = regulator_enable(qphy->vdda18);
217 if (ret) {
218 dev_err(qphy->phy.dev, "Unable to enable vdda18:%d\n", ret);
219 goto unset_vdda18;
220 }
221
222 ret = regulator_set_load(qphy->vdda33, QUSB2PHY_3P3_HPM_LOAD);
223 if (ret < 0) {
224 dev_err(qphy->phy.dev, "Unable to set HPM of vdda33:%d\n", ret);
225 goto disable_vdda18;
226 }
227
228 ret = regulator_set_voltage(qphy->vdda33, QUSB2PHY_3P3_VOL_MIN,
229 QUSB2PHY_3P3_VOL_MAX);
230 if (ret) {
231 dev_err(qphy->phy.dev,
232 "Unable to set voltage for vdda33:%d\n", ret);
233 goto put_vdda33_lpm;
234 }
235
236 ret = regulator_enable(qphy->vdda33);
237 if (ret) {
238 dev_err(qphy->phy.dev, "Unable to enable vdda33:%d\n", ret);
239 goto unset_vdd33;
240 }
241
Hemant Kumar7dc63722017-04-27 17:51:11 -0700242 qphy->power_enabled = true;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700243
244 pr_debug("%s(): QUSB PHY's regulators are turned ON.\n", __func__);
245 return ret;
246
247disable_vdda33:
248 ret = regulator_disable(qphy->vdda33);
249 if (ret)
250 dev_err(qphy->phy.dev, "Unable to disable vdda33:%d\n", ret);
251
252unset_vdd33:
253 ret = regulator_set_voltage(qphy->vdda33, 0, QUSB2PHY_3P3_VOL_MAX);
254 if (ret)
255 dev_err(qphy->phy.dev,
256 "Unable to set (0) voltage for vdda33:%d\n", ret);
257
258put_vdda33_lpm:
259 ret = regulator_set_load(qphy->vdda33, 0);
260 if (ret < 0)
261 dev_err(qphy->phy.dev, "Unable to set (0) HPM of vdda33\n");
262
263disable_vdda18:
264 ret = regulator_disable(qphy->vdda18);
265 if (ret)
266 dev_err(qphy->phy.dev, "Unable to disable vdda18:%d\n", ret);
267
268unset_vdda18:
269 ret = regulator_set_voltage(qphy->vdda18, 0, QUSB2PHY_1P8_VOL_MAX);
270 if (ret)
271 dev_err(qphy->phy.dev,
272 "Unable to set (0) voltage for vdda18:%d\n", ret);
273
274put_vdda18_lpm:
275 ret = regulator_set_load(qphy->vdda18, 0);
276 if (ret < 0)
277 dev_err(qphy->phy.dev, "Unable to set LPM of vdda18\n");
278
279disable_vdd:
Hemant Kumar7dc63722017-04-27 17:51:11 -0700280 ret = regulator_disable(qphy->vdd);
281 if (ret)
282 dev_err(qphy->phy.dev, "Unable to disable vdd:%d\n",
283 ret);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700284
285unconfig_vdd:
Hemant Kumar7dc63722017-04-27 17:51:11 -0700286 ret = qusb_phy_config_vdd(qphy, false);
287 if (ret)
288 dev_err(qphy->phy.dev, "Unable unconfig VDD:%d\n",
289 ret);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700290err_vdd:
Hemant Kumar7dc63722017-04-27 17:51:11 -0700291 qphy->power_enabled = false;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700292 dev_dbg(qphy->phy.dev, "QUSB PHY's regulators are turned OFF.\n");
293 return ret;
294}
295
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700296static void qusb_phy_get_tune1_param(struct qusb_phy *qphy)
Mayank Rana3cb43a32016-08-02 12:10:20 -0700297{
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700298 u8 reg;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700299 u32 bit_mask = 1;
300
301 pr_debug("%s(): num_of_bits:%d bit_pos:%d\n", __func__,
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700302 qphy->efuse_num_of_bits,
303 qphy->efuse_bit_pos);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700304
305 /* get bit mask based on number of bits to use with efuse reg */
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700306 bit_mask = (bit_mask << qphy->efuse_num_of_bits) - 1;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700307
308 /*
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700309 * if efuse reg is updated (i.e non-zero) then use it to program
310 * tune parameters
Mayank Rana3cb43a32016-08-02 12:10:20 -0700311 */
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700312 qphy->tune_val = readl_relaxed(qphy->efuse_reg);
313 pr_debug("%s(): bit_mask:%d efuse based tune1 value:%d\n",
314 __func__, bit_mask, qphy->tune_val);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700315
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700316 qphy->tune_val = TUNE_VAL_MASK(qphy->tune_val,
317 qphy->efuse_bit_pos, bit_mask);
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700318 reg = readb_relaxed(qphy->base + qphy->phy_reg[PORT_TUNE1]);
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700319 if (qphy->tune_val) {
320 reg = reg & 0x0f;
321 reg |= (qphy->tune_val << 4);
322 }
Mayank Rana3cb43a32016-08-02 12:10:20 -0700323
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700324 qphy->tune_val = reg;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700325}
326
327static void qusb_phy_write_seq(void __iomem *base, u32 *seq, int cnt,
328 unsigned long delay)
329{
330 int i;
331
332 pr_debug("Seq count:%d\n", cnt);
333 for (i = 0; i < cnt; i = i+2) {
334 pr_debug("write 0x%02x to 0x%02x\n", seq[i], seq[i+1]);
335 writel_relaxed(seq[i], base + seq[i+1]);
336 if (delay)
337 usleep_range(delay, (delay + 2000));
338 }
339}
340
Mayank Ranab7f212e2017-04-06 17:54:35 -0700341static void qusb_phy_reset(struct qusb_phy *qphy)
342{
343 int ret;
344
345 ret = reset_control_assert(qphy->phy_reset);
346 if (ret)
347 dev_err(qphy->phy.dev, "%s: phy_reset assert failed\n",
348 __func__);
349 usleep_range(100, 150);
350
351 ret = reset_control_deassert(qphy->phy_reset);
352 if (ret)
353 dev_err(qphy->phy.dev, "%s: phy_reset deassert failed\n",
354 __func__);
355}
356
Mayank Rana3cb43a32016-08-02 12:10:20 -0700357static void qusb_phy_host_init(struct usb_phy *phy)
358{
359 u8 reg;
360 struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy);
361
362 dev_dbg(phy->dev, "%s\n", __func__);
363
Mayank Ranab7f212e2017-04-06 17:54:35 -0700364 qusb_phy_reset(qphy);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700365 qusb_phy_write_seq(qphy->base, qphy->qusb_phy_host_init_seq,
366 qphy->host_init_seq_len, 0);
367
368 /* Ensure above write is completed before turning ON ref clk */
369 wmb();
370
371 /* Require to get phy pll lock successfully */
372 usleep_range(150, 160);
373
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700374 reg = readb_relaxed(qphy->base + qphy->phy_reg[PLL_COMMON_STATUS_ONE]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700375 dev_dbg(phy->dev, "QUSB2PHY_PLL_COMMON_STATUS_ONE:%x\n", reg);
376 if (!(reg & CORE_READY_STATUS)) {
377 dev_err(phy->dev, "QUSB PHY PLL LOCK fails:%x\n", reg);
378 WARN_ON(1);
379 }
380}
381
382static int qusb_phy_init(struct usb_phy *phy)
383{
384 struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy);
385 int ret;
386 u8 reg;
387
388 dev_dbg(phy->dev, "%s\n", __func__);
389
Hemant Kumar7dc63722017-04-27 17:51:11 -0700390 ret = qusb_phy_enable_power(qphy, true);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700391 if (ret)
392 return ret;
393
394 qusb_phy_enable_clocks(qphy, true);
395
Mayank Ranab7f212e2017-04-06 17:54:35 -0700396 qusb_phy_reset(qphy);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700397 if (qphy->emulation) {
398 if (qphy->emu_init_seq)
Mayank Rana147f41d2016-08-12 10:07:45 -0700399 qusb_phy_write_seq(qphy->emu_phy_base + 0x8000,
400 qphy->emu_init_seq,
401 qphy->emu_init_seq_len, 10000);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700402
403 if (qphy->qusb_phy_init_seq)
404 qusb_phy_write_seq(qphy->base, qphy->qusb_phy_init_seq,
405 qphy->init_seq_len, 0);
406
407 /* Wait for 5ms as per QUSB2 RUMI sequence */
408 usleep_range(5000, 7000);
409
410 if (qphy->phy_pll_reset_seq)
411 qusb_phy_write_seq(qphy->base, qphy->phy_pll_reset_seq,
412 qphy->phy_pll_reset_seq_len, 10000);
413
414 if (qphy->emu_dcm_reset_seq)
415 qusb_phy_write_seq(qphy->emu_phy_base,
416 qphy->emu_dcm_reset_seq,
417 qphy->emu_dcm_reset_seq_len, 10000);
418
419 return 0;
420 }
421
422 /* Disable the PHY */
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700423 writel_relaxed(readl_relaxed(qphy->base + qphy->phy_reg[PWR_CTRL1]) |
Mayank Rana3cb43a32016-08-02 12:10:20 -0700424 PWR_CTRL1_POWR_DOWN,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700425 qphy->base + qphy->phy_reg[PWR_CTRL1]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700426
427 if (qphy->qusb_phy_init_seq)
428 qusb_phy_write_seq(qphy->base, qphy->qusb_phy_init_seq,
429 qphy->init_seq_len, 0);
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700430 if (qphy->efuse_reg) {
431 if (!qphy->tune_val)
432 qusb_phy_get_tune1_param(qphy);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700433
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700434 pr_debug("%s(): Programming TUNE1 parameter as:%x\n", __func__,
435 qphy->tune_val);
436 writel_relaxed(qphy->tune_val,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700437 qphy->base + qphy->phy_reg[PORT_TUNE1]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700438 }
439
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700440 /* If phy_tune1 modparam set, override tune1 value */
441 if (phy_tune1) {
442 pr_debug("%s(): (modparam) TUNE1 val:0x%02x\n",
443 __func__, phy_tune1);
444 writel_relaxed(phy_tune1,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700445 qphy->base + qphy->phy_reg[PORT_TUNE1]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700446 }
447
448 /* ensure above writes are completed before re-enabling PHY */
449 wmb();
450
451 /* Enable the PHY */
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700452 writel_relaxed(readl_relaxed(qphy->base + qphy->phy_reg[PWR_CTRL1]) &
Mayank Rana3cb43a32016-08-02 12:10:20 -0700453 ~PWR_CTRL1_POWR_DOWN,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700454 qphy->base + qphy->phy_reg[PWR_CTRL1]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700455
456 /* Ensure above write is completed before turning ON ref clk */
457 wmb();
458
459 /* Require to get phy pll lock successfully */
460 usleep_range(150, 160);
461
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700462 reg = readb_relaxed(qphy->base + qphy->phy_reg[PLL_COMMON_STATUS_ONE]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700463 dev_dbg(phy->dev, "QUSB2PHY_PLL_COMMON_STATUS_ONE:%x\n", reg);
464 if (!(reg & CORE_READY_STATUS)) {
465 dev_err(phy->dev, "QUSB PHY PLL LOCK fails:%x\n", reg);
466 WARN_ON(1);
467 }
468 return 0;
469}
470
471static void qusb_phy_shutdown(struct usb_phy *phy)
472{
473 struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy);
474
475 dev_dbg(phy->dev, "%s\n", __func__);
476
477 qusb_phy_enable_clocks(qphy, true);
478
479 /* Disable the PHY */
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700480 writel_relaxed(readl_relaxed(qphy->base + qphy->phy_reg[PWR_CTRL1]) |
Mayank Rana3cb43a32016-08-02 12:10:20 -0700481 PWR_CTRL1_POWR_DOWN,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700482 qphy->base + qphy->phy_reg[PWR_CTRL1]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700483
484 /* Makes sure that above write goes through */
485 wmb();
486
487 qusb_phy_enable_clocks(qphy, false);
488}
489
490static u32 qusb_phy_get_linestate(struct qusb_phy *qphy)
491{
492 u32 linestate = 0;
493
494 if (qphy->cable_connected) {
495 if (qphy->phy.flags & PHY_HSFS_MODE)
496 linestate |= LINESTATE_DP;
497 else if (qphy->phy.flags & PHY_LS_MODE)
498 linestate |= LINESTATE_DM;
499 }
500 return linestate;
501}
502
503/**
504 * Performs QUSB2 PHY suspend/resume functionality.
505 *
506 * @uphy - usb phy pointer.
507 * @suspend - to enable suspend or not. 1 - suspend, 0 - resume
508 *
509 */
510static int qusb_phy_set_suspend(struct usb_phy *phy, int suspend)
511{
512 struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy);
513 u32 linestate = 0, intr_mask = 0;
514
515 if (qphy->suspended && suspend) {
516 dev_dbg(phy->dev, "%s: USB PHY is already suspended\n",
517 __func__);
518 return 0;
519 }
520
521 if (suspend) {
522 /* Bus suspend case */
523 if (qphy->cable_connected ||
524 (qphy->phy.flags & PHY_HOST_MODE)) {
525 /* Disable all interrupts */
526 writel_relaxed(0x00,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700527 qphy->base + qphy->phy_reg[INTR_CTRL]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700528
529 linestate = qusb_phy_get_linestate(qphy);
530 /*
531 * D+/D- interrupts are level-triggered, but we are
532 * only interested if the line state changes, so enable
533 * the high/low trigger based on current state. In
534 * other words, enable the triggers _opposite_ of what
535 * the current D+/D- levels are.
536 * e.g. if currently D+ high, D- low (HS 'J'/Suspend),
537 * configure the mask to trigger on D+ low OR D- high
538 */
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700539 intr_mask = DPSE_INTR_EN | DMSE_INTR_EN;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700540 if (!(linestate & LINESTATE_DP)) /* D+ low */
541 intr_mask |= DPSE_INTR_HIGH_SEL;
542 if (!(linestate & LINESTATE_DM)) /* D- low */
543 intr_mask |= DMSE_INTR_HIGH_SEL;
544
545 writel_relaxed(intr_mask,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700546 qphy->base + qphy->phy_reg[INTR_CTRL]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700547
Mayank Ranab7f212e2017-04-06 17:54:35 -0700548 /* hold core PLL into reset */
549 writel_relaxed(CORE_PLL_EN_FROM_RESET |
550 CORE_RESET | CORE_RESET_MUX,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700551 qphy->base +
552 qphy->phy_reg[PLL_CORE_INPUT_OVERRIDE]);
Mayank Ranab7f212e2017-04-06 17:54:35 -0700553
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700554 /* enable phy auto-resume */
555 writel_relaxed(0x91, qphy->base + qphy->phy_reg[TEST1]);
556 /* flush the previous write before next write */
557 wmb();
558 writel_relaxed(0x90, qphy->base + qphy->phy_reg[TEST1]);
559
Mayank Rana3cb43a32016-08-02 12:10:20 -0700560 dev_dbg(phy->dev, "%s: intr_mask = %x\n",
561 __func__, intr_mask);
562
563 /* Makes sure that above write goes through */
564 wmb();
565 qusb_phy_enable_clocks(qphy, false);
566 } else { /* Cable disconnect case */
567 /* Disable all interrupts */
568 writel_relaxed(0x00,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700569 qphy->base + qphy->phy_reg[INTR_CTRL]);
Mayank Ranab7f212e2017-04-06 17:54:35 -0700570 qusb_phy_reset(qphy);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700571 qusb_phy_enable_clocks(qphy, false);
Hemant Kumar7dc63722017-04-27 17:51:11 -0700572 qusb_phy_enable_power(qphy, false);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700573 }
574 qphy->suspended = true;
575 } else {
576 /* Bus resume case */
577 if (qphy->cable_connected ||
578 (qphy->phy.flags & PHY_HOST_MODE)) {
579 qusb_phy_enable_clocks(qphy, true);
580 /* Clear all interrupts on resume */
581 writel_relaxed(0x00,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700582 qphy->base + qphy->phy_reg[INTR_CTRL]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700583
Mayank Ranab7f212e2017-04-06 17:54:35 -0700584 /* bring core PLL out of reset */
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700585 writel_relaxed(CORE_PLL_EN_FROM_RESET, qphy->base +
586 qphy->phy_reg[PLL_CORE_INPUT_OVERRIDE]);
Mayank Ranab7f212e2017-04-06 17:54:35 -0700587
Mayank Rana3cb43a32016-08-02 12:10:20 -0700588 /* Makes sure that above write goes through */
589 wmb();
590 } else { /* Cable connect case */
Mayank Rana3cb43a32016-08-02 12:10:20 -0700591 qusb_phy_enable_clocks(qphy, true);
592 }
593 qphy->suspended = false;
594 }
595
596 return 0;
597}
598
599static int qusb_phy_notify_connect(struct usb_phy *phy,
600 enum usb_device_speed speed)
601{
602 struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy);
603
604 qphy->cable_connected = true;
605
606 if (qphy->qusb_phy_host_init_seq && qphy->phy.flags & PHY_HOST_MODE)
607 qusb_phy_host_init(phy);
608
609 dev_dbg(phy->dev, "QUSB PHY: connect notification cable_connected=%d\n",
610 qphy->cable_connected);
611 return 0;
612}
613
614static int qusb_phy_notify_disconnect(struct usb_phy *phy,
615 enum usb_device_speed speed)
616{
617 struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy);
618
619 qphy->cable_connected = false;
620
621 dev_dbg(phy->dev, "QUSB PHY: connect notification cable_connected=%d\n",
622 qphy->cable_connected);
623 return 0;
624}
625
626static int qusb_phy_dpdm_regulator_enable(struct regulator_dev *rdev)
627{
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700628 int ret = 0;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700629 struct qusb_phy *qphy = rdev_get_drvdata(rdev);
630
Mayank Ranadadae592017-07-21 09:03:32 -0700631 dev_dbg(qphy->phy.dev, "%s dpdm_enable:%d\n",
632 __func__, qphy->dpdm_enable);
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700633
Mayank Ranadadae592017-07-21 09:03:32 -0700634 if (!qphy->dpdm_enable) {
Hemant Kumar7dc63722017-04-27 17:51:11 -0700635 ret = qusb_phy_enable_power(qphy, true);
Mayank Ranadadae592017-07-21 09:03:32 -0700636 if (ret < 0) {
637 dev_dbg(qphy->phy.dev,
638 "dpdm regulator enable failed:%d\n", ret);
639 return ret;
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700640 }
Mayank Ranadadae592017-07-21 09:03:32 -0700641 qphy->dpdm_enable = true;
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700642 }
643
644 return ret;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700645}
646
647static int qusb_phy_dpdm_regulator_disable(struct regulator_dev *rdev)
648{
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700649 int ret = 0;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700650 struct qusb_phy *qphy = rdev_get_drvdata(rdev);
651
Mayank Ranadadae592017-07-21 09:03:32 -0700652 dev_dbg(qphy->phy.dev, "%s dpdm_enable:%d\n",
653 __func__, qphy->dpdm_enable);
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700654
Mayank Ranadadae592017-07-21 09:03:32 -0700655 if (qphy->dpdm_enable) {
Hemant Kumar7dc63722017-04-27 17:51:11 -0700656 ret = qusb_phy_enable_power(qphy, false);
Mayank Ranadadae592017-07-21 09:03:32 -0700657 if (ret < 0) {
658 dev_dbg(qphy->phy.dev,
659 "dpdm regulator disable failed:%d\n", ret);
660 return ret;
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700661 }
Mayank Ranadadae592017-07-21 09:03:32 -0700662 qphy->dpdm_enable = false;
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700663 }
664
665 return ret;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700666}
667
668static int qusb_phy_dpdm_regulator_is_enabled(struct regulator_dev *rdev)
669{
670 struct qusb_phy *qphy = rdev_get_drvdata(rdev);
671
Mayank Ranadadae592017-07-21 09:03:32 -0700672 dev_dbg(qphy->phy.dev, "%s qphy->dpdm_enable = %d\n", __func__,
673 qphy->dpdm_enable);
674 return qphy->dpdm_enable;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700675}
676
677static struct regulator_ops qusb_phy_dpdm_regulator_ops = {
678 .enable = qusb_phy_dpdm_regulator_enable,
679 .disable = qusb_phy_dpdm_regulator_disable,
680 .is_enabled = qusb_phy_dpdm_regulator_is_enabled,
681};
682
683static int qusb_phy_regulator_init(struct qusb_phy *qphy)
684{
685 struct device *dev = qphy->phy.dev;
686 struct regulator_config cfg = {};
687 struct regulator_init_data *init_data;
688
689 init_data = devm_kzalloc(dev, sizeof(*init_data), GFP_KERNEL);
690 if (!init_data)
691 return -ENOMEM;
692
693 init_data->constraints.valid_ops_mask |= REGULATOR_CHANGE_STATUS;
694 qphy->dpdm_rdesc.owner = THIS_MODULE;
695 qphy->dpdm_rdesc.type = REGULATOR_VOLTAGE;
696 qphy->dpdm_rdesc.ops = &qusb_phy_dpdm_regulator_ops;
697 qphy->dpdm_rdesc.name = kbasename(dev->of_node->full_name);
698
699 cfg.dev = dev;
700 cfg.init_data = init_data;
701 cfg.driver_data = qphy;
702 cfg.of_node = dev->of_node;
703
704 qphy->dpdm_rdev = devm_regulator_register(dev, &qphy->dpdm_rdesc, &cfg);
705 if (IS_ERR(qphy->dpdm_rdev))
706 return PTR_ERR(qphy->dpdm_rdev);
707
708 return 0;
709}
710
711static int qusb_phy_probe(struct platform_device *pdev)
712{
713 struct qusb_phy *qphy;
714 struct device *dev = &pdev->dev;
715 struct resource *res;
716 int ret = 0, size = 0;
717
718 qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL);
719 if (!qphy)
720 return -ENOMEM;
721
722 qphy->phy.dev = dev;
723 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
724 "qusb_phy_base");
725 qphy->base = devm_ioremap_resource(dev, res);
726 if (IS_ERR(qphy->base))
727 return PTR_ERR(qphy->base);
728
729 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
730 "emu_phy_base");
731 if (res) {
732 qphy->emu_phy_base = devm_ioremap_resource(dev, res);
733 if (IS_ERR(qphy->emu_phy_base)) {
734 dev_dbg(dev, "couldn't ioremap emu_phy_base\n");
735 qphy->emu_phy_base = NULL;
736 }
737 }
738
739 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700740 "efuse_addr");
Mayank Rana3cb43a32016-08-02 12:10:20 -0700741 if (res) {
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700742 qphy->efuse_reg = devm_ioremap_nocache(dev, res->start,
Mayank Rana3cb43a32016-08-02 12:10:20 -0700743 resource_size(res));
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700744 if (!IS_ERR_OR_NULL(qphy->efuse_reg)) {
Mayank Rana3cb43a32016-08-02 12:10:20 -0700745 ret = of_property_read_u32(dev->of_node,
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700746 "qcom,efuse-bit-pos",
747 &qphy->efuse_bit_pos);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700748 if (!ret) {
749 ret = of_property_read_u32(dev->of_node,
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700750 "qcom,efuse-num-bits",
751 &qphy->efuse_num_of_bits);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700752 }
753
754 if (ret) {
755 dev_err(dev,
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700756 "DT Value for efuse is invalid.\n");
Mayank Rana3cb43a32016-08-02 12:10:20 -0700757 return -EINVAL;
758 }
759 }
760 }
761
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700762 /* ref_clk_src is needed irrespective of SE_CLK or DIFF_CLK usage */
Mayank Rana3cb43a32016-08-02 12:10:20 -0700763 qphy->ref_clk_src = devm_clk_get(dev, "ref_clk_src");
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700764 if (IS_ERR(qphy->ref_clk_src)) {
Mayank Rana3cb43a32016-08-02 12:10:20 -0700765 dev_dbg(dev, "clk get failed for ref_clk_src\n");
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700766 ret = PTR_ERR(qphy->ref_clk_src);
767 return ret;
768 }
Mayank Rana3cb43a32016-08-02 12:10:20 -0700769
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700770 /* ref_clk is needed only for DIFF_CLK case, hence make it optional. */
771 if (of_property_match_string(pdev->dev.of_node,
772 "clock-names", "ref_clk") >= 0) {
773 qphy->ref_clk = devm_clk_get(dev, "ref_clk");
774 if (IS_ERR(qphy->ref_clk)) {
775 ret = PTR_ERR(qphy->ref_clk);
776 if (ret != -EPROBE_DEFER)
777 dev_dbg(dev,
778 "clk get failed for ref_clk\n");
779 return ret;
780 }
781
Mayank Rana3cb43a32016-08-02 12:10:20 -0700782 clk_set_rate(qphy->ref_clk, 19200000);
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700783 }
Mayank Rana3cb43a32016-08-02 12:10:20 -0700784
785 if (of_property_match_string(pdev->dev.of_node,
786 "clock-names", "cfg_ahb_clk") >= 0) {
787 qphy->cfg_ahb_clk = devm_clk_get(dev, "cfg_ahb_clk");
788 if (IS_ERR(qphy->cfg_ahb_clk)) {
789 ret = PTR_ERR(qphy->cfg_ahb_clk);
790 if (ret != -EPROBE_DEFER)
791 dev_err(dev,
792 "clk get failed for cfg_ahb_clk ret %d\n", ret);
793 return ret;
794 }
795 }
796
Amit Nischal4d278212016-06-06 17:54:34 +0530797 qphy->phy_reset = devm_reset_control_get(dev, "phy_reset");
Mayank Rana3cb43a32016-08-02 12:10:20 -0700798 if (IS_ERR(qphy->phy_reset))
799 return PTR_ERR(qphy->phy_reset);
800
801 qphy->emulation = of_property_read_bool(dev->of_node,
802 "qcom,emulation");
803
804 of_get_property(dev->of_node, "qcom,emu-init-seq", &size);
805 if (size) {
806 qphy->emu_init_seq = devm_kzalloc(dev,
807 size, GFP_KERNEL);
808 if (qphy->emu_init_seq) {
809 qphy->emu_init_seq_len =
810 (size / sizeof(*qphy->emu_init_seq));
811 if (qphy->emu_init_seq_len % 2) {
812 dev_err(dev, "invalid emu_init_seq_len\n");
813 return -EINVAL;
814 }
815
816 of_property_read_u32_array(dev->of_node,
Mayank Rana147f41d2016-08-12 10:07:45 -0700817 "qcom,emu-init-seq",
Mayank Rana3cb43a32016-08-02 12:10:20 -0700818 qphy->emu_init_seq,
819 qphy->emu_init_seq_len);
820 } else {
821 dev_dbg(dev,
822 "error allocating memory for emu_init_seq\n");
823 }
824 }
825
Mayank Rana147f41d2016-08-12 10:07:45 -0700826 size = 0;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700827 of_get_property(dev->of_node, "qcom,phy-pll-reset-seq", &size);
828 if (size) {
829 qphy->phy_pll_reset_seq = devm_kzalloc(dev,
830 size, GFP_KERNEL);
831 if (qphy->phy_pll_reset_seq) {
832 qphy->phy_pll_reset_seq_len =
833 (size / sizeof(*qphy->phy_pll_reset_seq));
834 if (qphy->phy_pll_reset_seq_len % 2) {
835 dev_err(dev, "invalid phy_pll_reset_seq_len\n");
836 return -EINVAL;
837 }
838
839 of_property_read_u32_array(dev->of_node,
840 "qcom,phy-pll-reset-seq",
841 qphy->phy_pll_reset_seq,
842 qphy->phy_pll_reset_seq_len);
843 } else {
844 dev_dbg(dev,
845 "error allocating memory for phy_pll_reset_seq\n");
846 }
847 }
848
Mayank Rana147f41d2016-08-12 10:07:45 -0700849 size = 0;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700850 of_get_property(dev->of_node, "qcom,emu-dcm-reset-seq", &size);
851 if (size) {
852 qphy->emu_dcm_reset_seq = devm_kzalloc(dev,
853 size, GFP_KERNEL);
854 if (qphy->emu_dcm_reset_seq) {
855 qphy->emu_dcm_reset_seq_len =
856 (size / sizeof(*qphy->emu_dcm_reset_seq));
857 if (qphy->emu_dcm_reset_seq_len % 2) {
858 dev_err(dev, "invalid emu_dcm_reset_seq_len\n");
859 return -EINVAL;
860 }
861
862 of_property_read_u32_array(dev->of_node,
863 "qcom,emu-dcm-reset-seq",
864 qphy->emu_dcm_reset_seq,
865 qphy->emu_dcm_reset_seq_len);
866 } else {
867 dev_dbg(dev,
868 "error allocating memory for emu_dcm_reset_seq\n");
869 }
870 }
871
Mayank Rana147f41d2016-08-12 10:07:45 -0700872 size = 0;
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700873 of_get_property(dev->of_node, "qcom,qusb-phy-reg-offset", &size);
874 if (size) {
875 qphy->phy_reg = devm_kzalloc(dev, size, GFP_KERNEL);
876 if (qphy->phy_reg) {
877 qphy->qusb_phy_reg_offset_cnt =
878 size / sizeof(*qphy->phy_reg);
879 if (qphy->qusb_phy_reg_offset_cnt > USB2_PHY_REG_MAX) {
880 dev_err(dev, "invalid reg offset count\n");
881 return -EINVAL;
882 }
883
884 of_property_read_u32_array(dev->of_node,
885 "qcom,qusb-phy-reg-offset",
886 qphy->phy_reg,
887 qphy->qusb_phy_reg_offset_cnt);
888 } else {
889 dev_err(dev, "err mem alloc for qusb_phy_reg_offset\n");
890 return -ENOMEM;
891 }
892 } else {
893 dev_err(dev, "err provide qcom,qmp-phy-reg-offset\n");
894 return -EINVAL;
895 }
896
897 size = 0;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700898 of_get_property(dev->of_node, "qcom,qusb-phy-init-seq", &size);
899 if (size) {
900 qphy->qusb_phy_init_seq = devm_kzalloc(dev,
901 size, GFP_KERNEL);
902 if (qphy->qusb_phy_init_seq) {
903 qphy->init_seq_len =
904 (size / sizeof(*qphy->qusb_phy_init_seq));
905 if (qphy->init_seq_len % 2) {
906 dev_err(dev, "invalid init_seq_len\n");
907 return -EINVAL;
908 }
909
910 of_property_read_u32_array(dev->of_node,
911 "qcom,qusb-phy-init-seq",
912 qphy->qusb_phy_init_seq,
913 qphy->init_seq_len);
914 } else {
915 dev_err(dev,
916 "error allocating memory for phy_init_seq\n");
917 }
918 }
919
920 qphy->host_init_seq_len = of_property_count_elems_of_size(dev->of_node,
921 "qcom,qusb-phy-host-init-seq",
922 sizeof(*qphy->qusb_phy_host_init_seq));
923 if (qphy->host_init_seq_len > 0) {
924 qphy->qusb_phy_host_init_seq = devm_kcalloc(dev,
925 qphy->host_init_seq_len,
926 sizeof(*qphy->qusb_phy_host_init_seq),
927 GFP_KERNEL);
928 if (qphy->qusb_phy_host_init_seq)
929 of_property_read_u32_array(dev->of_node,
930 "qcom,qusb-phy-host-init-seq",
931 qphy->qusb_phy_host_init_seq,
932 qphy->host_init_seq_len);
933 else
934 return -ENOMEM;
935 }
936
937 ret = of_property_read_u32_array(dev->of_node, "qcom,vdd-voltage-level",
938 (u32 *) qphy->vdd_levels,
939 ARRAY_SIZE(qphy->vdd_levels));
940 if (ret) {
941 dev_err(dev, "error reading qcom,vdd-voltage-level property\n");
942 return ret;
943 }
944
945 qphy->vdd = devm_regulator_get(dev, "vdd");
946 if (IS_ERR(qphy->vdd)) {
947 dev_err(dev, "unable to get vdd supply\n");
948 return PTR_ERR(qphy->vdd);
949 }
950
951 qphy->vdda33 = devm_regulator_get(dev, "vdda33");
952 if (IS_ERR(qphy->vdda33)) {
953 dev_err(dev, "unable to get vdda33 supply\n");
954 return PTR_ERR(qphy->vdda33);
955 }
956
957 qphy->vdda18 = devm_regulator_get(dev, "vdda18");
958 if (IS_ERR(qphy->vdda18)) {
959 dev_err(dev, "unable to get vdda18 supply\n");
960 return PTR_ERR(qphy->vdda18);
961 }
962
963 platform_set_drvdata(pdev, qphy);
964
965 qphy->phy.label = "msm-qusb-phy-v2";
966 qphy->phy.init = qusb_phy_init;
967 qphy->phy.set_suspend = qusb_phy_set_suspend;
968 qphy->phy.shutdown = qusb_phy_shutdown;
969 qphy->phy.type = USB_PHY_TYPE_USB2;
970 qphy->phy.notify_connect = qusb_phy_notify_connect;
971 qphy->phy.notify_disconnect = qusb_phy_notify_disconnect;
972
973 ret = usb_add_phy_dev(&qphy->phy);
974 if (ret)
975 return ret;
976
977 ret = qusb_phy_regulator_init(qphy);
978 if (ret)
979 usb_remove_phy(&qphy->phy);
980
981 return ret;
982}
983
984static int qusb_phy_remove(struct platform_device *pdev)
985{
986 struct qusb_phy *qphy = platform_get_drvdata(pdev);
987
988 usb_remove_phy(&qphy->phy);
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700989 qusb_phy_enable_clocks(qphy, false);
Hemant Kumar7dc63722017-04-27 17:51:11 -0700990 qusb_phy_enable_power(qphy, false);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700991
992 return 0;
993}
994
995static const struct of_device_id qusb_phy_id_table[] = {
996 { .compatible = "qcom,qusb2phy-v2", },
997 { },
998};
999MODULE_DEVICE_TABLE(of, qusb_phy_id_table);
1000
1001static struct platform_driver qusb_phy_driver = {
1002 .probe = qusb_phy_probe,
1003 .remove = qusb_phy_remove,
1004 .driver = {
1005 .name = "msm-qusb-phy-v2",
1006 .of_match_table = of_match_ptr(qusb_phy_id_table),
1007 },
1008};
1009
1010module_platform_driver(qusb_phy_driver);
1011
1012MODULE_DESCRIPTION("MSM QUSB2 PHY v2 driver");
1013MODULE_LICENSE("GPL v2");