blob: 6103172615c2592889580044c145e70d9891467f [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;
Hemant Kumar164cc1b2017-04-27 19:39:58 -070082 struct mutex lock;
Mayank Rana3cb43a32016-08-02 12:10:20 -070083 void __iomem *base;
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -070084 void __iomem *efuse_reg;
Mayank Rana3cb43a32016-08-02 12:10:20 -070085
86 struct clk *ref_clk_src;
87 struct clk *ref_clk;
88 struct clk *cfg_ahb_clk;
Amit Nischal4d278212016-06-06 17:54:34 +053089 struct reset_control *phy_reset;
Mayank Rana3cb43a32016-08-02 12:10:20 -070090
91 struct regulator *vdd;
92 struct regulator *vdda33;
93 struct regulator *vdda18;
94 int vdd_levels[3]; /* none, low, high */
95 int init_seq_len;
96 int *qusb_phy_init_seq;
97 int host_init_seq_len;
98 int *qusb_phy_host_init_seq;
99
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700100 unsigned int *phy_reg;
101 int qusb_phy_reg_offset_cnt;
102
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700103 u32 tune_val;
104 int efuse_bit_pos;
105 int efuse_num_of_bits;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700106
Hemant Kumar164cc1b2017-04-27 19:39:58 -0700107 int power_enabled_ref;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700108 bool clocks_enabled;
109 bool cable_connected;
110 bool suspended;
Mayank Ranadadae592017-07-21 09:03:32 -0700111 bool dpdm_enable;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700112
113 struct regulator_desc dpdm_rdesc;
114 struct regulator_dev *dpdm_rdev;
115
116 /* emulation targets specific */
117 void __iomem *emu_phy_base;
118 bool emulation;
119 int *emu_init_seq;
120 int emu_init_seq_len;
121 int *phy_pll_reset_seq;
122 int phy_pll_reset_seq_len;
123 int *emu_dcm_reset_seq;
124 int emu_dcm_reset_seq_len;
125};
126
127static void qusb_phy_enable_clocks(struct qusb_phy *qphy, bool on)
128{
129 dev_dbg(qphy->phy.dev, "%s(): clocks_enabled:%d on:%d\n",
130 __func__, qphy->clocks_enabled, on);
131
132 if (!qphy->clocks_enabled && on) {
133 clk_prepare_enable(qphy->ref_clk_src);
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700134 if (qphy->ref_clk)
135 clk_prepare_enable(qphy->ref_clk);
136
137 if (qphy->cfg_ahb_clk)
138 clk_prepare_enable(qphy->cfg_ahb_clk);
139
Mayank Rana3cb43a32016-08-02 12:10:20 -0700140 qphy->clocks_enabled = true;
141 }
142
143 if (qphy->clocks_enabled && !on) {
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700144 if (qphy->cfg_ahb_clk)
145 clk_disable_unprepare(qphy->cfg_ahb_clk);
146
147 if (qphy->ref_clk)
148 clk_disable_unprepare(qphy->ref_clk);
149
Mayank Rana3cb43a32016-08-02 12:10:20 -0700150 clk_disable_unprepare(qphy->ref_clk_src);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700151 qphy->clocks_enabled = false;
152 }
153
154 dev_dbg(qphy->phy.dev, "%s(): clocks_enabled:%d\n", __func__,
155 qphy->clocks_enabled);
156}
157
158static int qusb_phy_config_vdd(struct qusb_phy *qphy, int high)
159{
160 int min, ret;
161
162 min = high ? 1 : 0; /* low or none? */
163 ret = regulator_set_voltage(qphy->vdd, qphy->vdd_levels[min],
164 qphy->vdd_levels[2]);
165 if (ret) {
166 dev_err(qphy->phy.dev, "unable to set voltage for qusb vdd\n");
167 return ret;
168 }
169
170 dev_dbg(qphy->phy.dev, "min_vol:%d max_vol:%d\n",
171 qphy->vdd_levels[min], qphy->vdd_levels[2]);
172 return ret;
173}
174
Hemant Kumar7dc63722017-04-27 17:51:11 -0700175static int qusb_phy_enable_power(struct qusb_phy *qphy, bool on)
Mayank Rana3cb43a32016-08-02 12:10:20 -0700176{
177 int ret = 0;
178
Hemant Kumar164cc1b2017-04-27 19:39:58 -0700179 mutex_lock(&qphy->lock);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700180
Hemant Kumar164cc1b2017-04-27 19:39:58 -0700181 dev_dbg(qphy->phy.dev,
182 "%s:req to turn %s regulators. power_enabled_ref:%d\n",
183 __func__, on ? "on" : "off", qphy->power_enabled_ref);
184
185 if (on && ++qphy->power_enabled_ref > 1) {
186 dev_dbg(qphy->phy.dev, "PHYs' regulators are already on\n");
187 goto done;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700188 }
189
Hemant Kumar164cc1b2017-04-27 19:39:58 -0700190 if (!on) {
191 if (on == qphy->power_enabled_ref) {
192 dev_dbg(qphy->phy.dev,
193 "PHYs' regulators are already off\n");
194 goto done;
195 }
196
197 qphy->power_enabled_ref--;
198 if (!qphy->power_enabled_ref)
199 goto disable_vdda33;
200
201 dev_dbg(qphy->phy.dev, "Skip turning off PHYs' regulators\n");
202 goto done;
203 }
Mayank Rana3cb43a32016-08-02 12:10:20 -0700204
Hemant Kumar7dc63722017-04-27 17:51:11 -0700205 ret = qusb_phy_config_vdd(qphy, true);
206 if (ret) {
207 dev_err(qphy->phy.dev, "Unable to config VDD:%d\n",
208 ret);
209 goto err_vdd;
210 }
Mayank Rana3cb43a32016-08-02 12:10:20 -0700211
Hemant Kumar7dc63722017-04-27 17:51:11 -0700212 ret = regulator_enable(qphy->vdd);
213 if (ret) {
214 dev_err(qphy->phy.dev, "Unable to enable VDD\n");
215 goto unconfig_vdd;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700216 }
217
218 ret = regulator_set_load(qphy->vdda18, QUSB2PHY_1P8_HPM_LOAD);
219 if (ret < 0) {
220 dev_err(qphy->phy.dev, "Unable to set HPM of vdda18:%d\n", ret);
221 goto disable_vdd;
222 }
223
224 ret = regulator_set_voltage(qphy->vdda18, QUSB2PHY_1P8_VOL_MIN,
225 QUSB2PHY_1P8_VOL_MAX);
226 if (ret) {
227 dev_err(qphy->phy.dev,
228 "Unable to set voltage for vdda18:%d\n", ret);
229 goto put_vdda18_lpm;
230 }
231
232 ret = regulator_enable(qphy->vdda18);
233 if (ret) {
234 dev_err(qphy->phy.dev, "Unable to enable vdda18:%d\n", ret);
235 goto unset_vdda18;
236 }
237
238 ret = regulator_set_load(qphy->vdda33, QUSB2PHY_3P3_HPM_LOAD);
239 if (ret < 0) {
240 dev_err(qphy->phy.dev, "Unable to set HPM of vdda33:%d\n", ret);
241 goto disable_vdda18;
242 }
243
244 ret = regulator_set_voltage(qphy->vdda33, QUSB2PHY_3P3_VOL_MIN,
245 QUSB2PHY_3P3_VOL_MAX);
246 if (ret) {
247 dev_err(qphy->phy.dev,
248 "Unable to set voltage for vdda33:%d\n", ret);
249 goto put_vdda33_lpm;
250 }
251
252 ret = regulator_enable(qphy->vdda33);
253 if (ret) {
254 dev_err(qphy->phy.dev, "Unable to enable vdda33:%d\n", ret);
255 goto unset_vdd33;
256 }
257
Mayank Rana3cb43a32016-08-02 12:10:20 -0700258 pr_debug("%s(): QUSB PHY's regulators are turned ON.\n", __func__);
Hemant Kumar164cc1b2017-04-27 19:39:58 -0700259
260 mutex_unlock(&qphy->lock);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700261 return ret;
262
263disable_vdda33:
264 ret = regulator_disable(qphy->vdda33);
265 if (ret)
266 dev_err(qphy->phy.dev, "Unable to disable vdda33:%d\n", ret);
267
268unset_vdd33:
269 ret = regulator_set_voltage(qphy->vdda33, 0, QUSB2PHY_3P3_VOL_MAX);
270 if (ret)
271 dev_err(qphy->phy.dev,
272 "Unable to set (0) voltage for vdda33:%d\n", ret);
273
274put_vdda33_lpm:
275 ret = regulator_set_load(qphy->vdda33, 0);
276 if (ret < 0)
277 dev_err(qphy->phy.dev, "Unable to set (0) HPM of vdda33\n");
278
279disable_vdda18:
280 ret = regulator_disable(qphy->vdda18);
281 if (ret)
282 dev_err(qphy->phy.dev, "Unable to disable vdda18:%d\n", ret);
283
284unset_vdda18:
285 ret = regulator_set_voltage(qphy->vdda18, 0, QUSB2PHY_1P8_VOL_MAX);
286 if (ret)
287 dev_err(qphy->phy.dev,
288 "Unable to set (0) voltage for vdda18:%d\n", ret);
289
290put_vdda18_lpm:
291 ret = regulator_set_load(qphy->vdda18, 0);
292 if (ret < 0)
293 dev_err(qphy->phy.dev, "Unable to set LPM of vdda18\n");
294
295disable_vdd:
Hemant Kumar7dc63722017-04-27 17:51:11 -0700296 ret = regulator_disable(qphy->vdd);
297 if (ret)
298 dev_err(qphy->phy.dev, "Unable to disable vdd:%d\n",
299 ret);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700300
301unconfig_vdd:
Hemant Kumar7dc63722017-04-27 17:51:11 -0700302 ret = qusb_phy_config_vdd(qphy, false);
303 if (ret)
304 dev_err(qphy->phy.dev, "Unable unconfig VDD:%d\n",
305 ret);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700306err_vdd:
Mayank Rana3cb43a32016-08-02 12:10:20 -0700307 dev_dbg(qphy->phy.dev, "QUSB PHY's regulators are turned OFF.\n");
Hemant Kumar164cc1b2017-04-27 19:39:58 -0700308
309 /* in case of error in turning on regulators */
310 if (qphy->power_enabled_ref)
311 qphy->power_enabled_ref--;
312done:
313 mutex_unlock(&qphy->lock);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700314 return ret;
315}
316
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700317static void qusb_phy_get_tune1_param(struct qusb_phy *qphy)
Mayank Rana3cb43a32016-08-02 12:10:20 -0700318{
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700319 u8 reg;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700320 u32 bit_mask = 1;
321
322 pr_debug("%s(): num_of_bits:%d bit_pos:%d\n", __func__,
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700323 qphy->efuse_num_of_bits,
324 qphy->efuse_bit_pos);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700325
326 /* get bit mask based on number of bits to use with efuse reg */
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700327 bit_mask = (bit_mask << qphy->efuse_num_of_bits) - 1;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700328
329 /*
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700330 * if efuse reg is updated (i.e non-zero) then use it to program
331 * tune parameters
Mayank Rana3cb43a32016-08-02 12:10:20 -0700332 */
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700333 qphy->tune_val = readl_relaxed(qphy->efuse_reg);
334 pr_debug("%s(): bit_mask:%d efuse based tune1 value:%d\n",
335 __func__, bit_mask, qphy->tune_val);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700336
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700337 qphy->tune_val = TUNE_VAL_MASK(qphy->tune_val,
338 qphy->efuse_bit_pos, bit_mask);
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700339 reg = readb_relaxed(qphy->base + qphy->phy_reg[PORT_TUNE1]);
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700340 if (qphy->tune_val) {
341 reg = reg & 0x0f;
342 reg |= (qphy->tune_val << 4);
343 }
Mayank Rana3cb43a32016-08-02 12:10:20 -0700344
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700345 qphy->tune_val = reg;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700346}
347
348static void qusb_phy_write_seq(void __iomem *base, u32 *seq, int cnt,
349 unsigned long delay)
350{
351 int i;
352
353 pr_debug("Seq count:%d\n", cnt);
354 for (i = 0; i < cnt; i = i+2) {
355 pr_debug("write 0x%02x to 0x%02x\n", seq[i], seq[i+1]);
356 writel_relaxed(seq[i], base + seq[i+1]);
357 if (delay)
358 usleep_range(delay, (delay + 2000));
359 }
360}
361
Mayank Ranab7f212e2017-04-06 17:54:35 -0700362static void qusb_phy_reset(struct qusb_phy *qphy)
363{
364 int ret;
365
366 ret = reset_control_assert(qphy->phy_reset);
367 if (ret)
368 dev_err(qphy->phy.dev, "%s: phy_reset assert failed\n",
369 __func__);
370 usleep_range(100, 150);
371
372 ret = reset_control_deassert(qphy->phy_reset);
373 if (ret)
374 dev_err(qphy->phy.dev, "%s: phy_reset deassert failed\n",
375 __func__);
376}
377
Mayank Rana3cb43a32016-08-02 12:10:20 -0700378static void qusb_phy_host_init(struct usb_phy *phy)
379{
380 u8 reg;
381 struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy);
382
383 dev_dbg(phy->dev, "%s\n", __func__);
384
Mayank Ranab7f212e2017-04-06 17:54:35 -0700385 qusb_phy_reset(qphy);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700386 qusb_phy_write_seq(qphy->base, qphy->qusb_phy_host_init_seq,
387 qphy->host_init_seq_len, 0);
388
389 /* Ensure above write is completed before turning ON ref clk */
390 wmb();
391
392 /* Require to get phy pll lock successfully */
393 usleep_range(150, 160);
394
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700395 reg = readb_relaxed(qphy->base + qphy->phy_reg[PLL_COMMON_STATUS_ONE]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700396 dev_dbg(phy->dev, "QUSB2PHY_PLL_COMMON_STATUS_ONE:%x\n", reg);
397 if (!(reg & CORE_READY_STATUS)) {
398 dev_err(phy->dev, "QUSB PHY PLL LOCK fails:%x\n", reg);
399 WARN_ON(1);
400 }
401}
402
403static int qusb_phy_init(struct usb_phy *phy)
404{
405 struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy);
406 int ret;
407 u8 reg;
408
409 dev_dbg(phy->dev, "%s\n", __func__);
410
Hemant Kumar7dc63722017-04-27 17:51:11 -0700411 ret = qusb_phy_enable_power(qphy, true);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700412 if (ret)
413 return ret;
414
415 qusb_phy_enable_clocks(qphy, true);
416
Mayank Ranab7f212e2017-04-06 17:54:35 -0700417 qusb_phy_reset(qphy);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700418 if (qphy->emulation) {
419 if (qphy->emu_init_seq)
Mayank Rana147f41d2016-08-12 10:07:45 -0700420 qusb_phy_write_seq(qphy->emu_phy_base + 0x8000,
421 qphy->emu_init_seq,
422 qphy->emu_init_seq_len, 10000);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700423
424 if (qphy->qusb_phy_init_seq)
425 qusb_phy_write_seq(qphy->base, qphy->qusb_phy_init_seq,
426 qphy->init_seq_len, 0);
427
428 /* Wait for 5ms as per QUSB2 RUMI sequence */
429 usleep_range(5000, 7000);
430
431 if (qphy->phy_pll_reset_seq)
432 qusb_phy_write_seq(qphy->base, qphy->phy_pll_reset_seq,
433 qphy->phy_pll_reset_seq_len, 10000);
434
435 if (qphy->emu_dcm_reset_seq)
436 qusb_phy_write_seq(qphy->emu_phy_base,
437 qphy->emu_dcm_reset_seq,
438 qphy->emu_dcm_reset_seq_len, 10000);
439
440 return 0;
441 }
442
443 /* Disable the PHY */
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700444 writel_relaxed(readl_relaxed(qphy->base + qphy->phy_reg[PWR_CTRL1]) |
Mayank Rana3cb43a32016-08-02 12:10:20 -0700445 PWR_CTRL1_POWR_DOWN,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700446 qphy->base + qphy->phy_reg[PWR_CTRL1]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700447
448 if (qphy->qusb_phy_init_seq)
449 qusb_phy_write_seq(qphy->base, qphy->qusb_phy_init_seq,
450 qphy->init_seq_len, 0);
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700451 if (qphy->efuse_reg) {
452 if (!qphy->tune_val)
453 qusb_phy_get_tune1_param(qphy);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700454
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700455 pr_debug("%s(): Programming TUNE1 parameter as:%x\n", __func__,
456 qphy->tune_val);
457 writel_relaxed(qphy->tune_val,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700458 qphy->base + qphy->phy_reg[PORT_TUNE1]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700459 }
460
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700461 /* If phy_tune1 modparam set, override tune1 value */
462 if (phy_tune1) {
463 pr_debug("%s(): (modparam) TUNE1 val:0x%02x\n",
464 __func__, phy_tune1);
465 writel_relaxed(phy_tune1,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700466 qphy->base + qphy->phy_reg[PORT_TUNE1]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700467 }
468
469 /* ensure above writes are completed before re-enabling PHY */
470 wmb();
471
472 /* Enable the PHY */
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700473 writel_relaxed(readl_relaxed(qphy->base + qphy->phy_reg[PWR_CTRL1]) &
Mayank Rana3cb43a32016-08-02 12:10:20 -0700474 ~PWR_CTRL1_POWR_DOWN,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700475 qphy->base + qphy->phy_reg[PWR_CTRL1]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700476
477 /* Ensure above write is completed before turning ON ref clk */
478 wmb();
479
480 /* Require to get phy pll lock successfully */
481 usleep_range(150, 160);
482
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700483 reg = readb_relaxed(qphy->base + qphy->phy_reg[PLL_COMMON_STATUS_ONE]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700484 dev_dbg(phy->dev, "QUSB2PHY_PLL_COMMON_STATUS_ONE:%x\n", reg);
485 if (!(reg & CORE_READY_STATUS)) {
486 dev_err(phy->dev, "QUSB PHY PLL LOCK fails:%x\n", reg);
487 WARN_ON(1);
488 }
489 return 0;
490}
491
492static void qusb_phy_shutdown(struct usb_phy *phy)
493{
494 struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy);
495
496 dev_dbg(phy->dev, "%s\n", __func__);
497
498 qusb_phy_enable_clocks(qphy, true);
499
500 /* Disable the PHY */
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700501 writel_relaxed(readl_relaxed(qphy->base + qphy->phy_reg[PWR_CTRL1]) |
Mayank Rana3cb43a32016-08-02 12:10:20 -0700502 PWR_CTRL1_POWR_DOWN,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700503 qphy->base + qphy->phy_reg[PWR_CTRL1]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700504
505 /* Makes sure that above write goes through */
506 wmb();
507
508 qusb_phy_enable_clocks(qphy, false);
509}
510
511static u32 qusb_phy_get_linestate(struct qusb_phy *qphy)
512{
513 u32 linestate = 0;
514
515 if (qphy->cable_connected) {
516 if (qphy->phy.flags & PHY_HSFS_MODE)
517 linestate |= LINESTATE_DP;
518 else if (qphy->phy.flags & PHY_LS_MODE)
519 linestate |= LINESTATE_DM;
520 }
521 return linestate;
522}
523
524/**
525 * Performs QUSB2 PHY suspend/resume functionality.
526 *
527 * @uphy - usb phy pointer.
528 * @suspend - to enable suspend or not. 1 - suspend, 0 - resume
529 *
530 */
531static int qusb_phy_set_suspend(struct usb_phy *phy, int suspend)
532{
533 struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy);
534 u32 linestate = 0, intr_mask = 0;
535
536 if (qphy->suspended && suspend) {
537 dev_dbg(phy->dev, "%s: USB PHY is already suspended\n",
538 __func__);
539 return 0;
540 }
541
542 if (suspend) {
543 /* Bus suspend case */
544 if (qphy->cable_connected ||
545 (qphy->phy.flags & PHY_HOST_MODE)) {
546 /* Disable all interrupts */
547 writel_relaxed(0x00,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700548 qphy->base + qphy->phy_reg[INTR_CTRL]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700549
550 linestate = qusb_phy_get_linestate(qphy);
551 /*
552 * D+/D- interrupts are level-triggered, but we are
553 * only interested if the line state changes, so enable
554 * the high/low trigger based on current state. In
555 * other words, enable the triggers _opposite_ of what
556 * the current D+/D- levels are.
557 * e.g. if currently D+ high, D- low (HS 'J'/Suspend),
558 * configure the mask to trigger on D+ low OR D- high
559 */
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700560 intr_mask = DPSE_INTR_EN | DMSE_INTR_EN;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700561 if (!(linestate & LINESTATE_DP)) /* D+ low */
562 intr_mask |= DPSE_INTR_HIGH_SEL;
563 if (!(linestate & LINESTATE_DM)) /* D- low */
564 intr_mask |= DMSE_INTR_HIGH_SEL;
565
566 writel_relaxed(intr_mask,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700567 qphy->base + qphy->phy_reg[INTR_CTRL]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700568
Mayank Ranab7f212e2017-04-06 17:54:35 -0700569 /* hold core PLL into reset */
570 writel_relaxed(CORE_PLL_EN_FROM_RESET |
571 CORE_RESET | CORE_RESET_MUX,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700572 qphy->base +
573 qphy->phy_reg[PLL_CORE_INPUT_OVERRIDE]);
Mayank Ranab7f212e2017-04-06 17:54:35 -0700574
Vijayavardhan Vennapusa46a01442017-07-06 10:52:30 +0530575 if (linestate & (LINESTATE_DP | LINESTATE_DM)) {
576 /* enable phy auto-resume */
577 writel_relaxed(0x91,
578 qphy->base + qphy->phy_reg[TEST1]);
579 /* flush the previous write before next write */
580 wmb();
581 writel_relaxed(0x90,
582 qphy->base + qphy->phy_reg[TEST1]);
583 }
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700584
Mayank Rana3cb43a32016-08-02 12:10:20 -0700585 dev_dbg(phy->dev, "%s: intr_mask = %x\n",
586 __func__, intr_mask);
587
588 /* Makes sure that above write goes through */
589 wmb();
590 qusb_phy_enable_clocks(qphy, false);
591 } else { /* Cable disconnect case */
592 /* Disable all interrupts */
593 writel_relaxed(0x00,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700594 qphy->base + qphy->phy_reg[INTR_CTRL]);
Mayank Ranab7f212e2017-04-06 17:54:35 -0700595 qusb_phy_reset(qphy);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700596 qusb_phy_enable_clocks(qphy, false);
Hemant Kumar7dc63722017-04-27 17:51:11 -0700597 qusb_phy_enable_power(qphy, false);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700598 }
599 qphy->suspended = true;
600 } else {
601 /* Bus resume case */
602 if (qphy->cable_connected ||
603 (qphy->phy.flags & PHY_HOST_MODE)) {
604 qusb_phy_enable_clocks(qphy, true);
605 /* Clear all interrupts on resume */
606 writel_relaxed(0x00,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700607 qphy->base + qphy->phy_reg[INTR_CTRL]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700608
Mayank Ranab7f212e2017-04-06 17:54:35 -0700609 /* bring core PLL out of reset */
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700610 writel_relaxed(CORE_PLL_EN_FROM_RESET, qphy->base +
611 qphy->phy_reg[PLL_CORE_INPUT_OVERRIDE]);
Mayank Ranab7f212e2017-04-06 17:54:35 -0700612
Mayank Rana3cb43a32016-08-02 12:10:20 -0700613 /* Makes sure that above write goes through */
614 wmb();
615 } else { /* Cable connect case */
Mayank Rana3cb43a32016-08-02 12:10:20 -0700616 qusb_phy_enable_clocks(qphy, true);
617 }
618 qphy->suspended = false;
619 }
620
621 return 0;
622}
623
624static int qusb_phy_notify_connect(struct usb_phy *phy,
625 enum usb_device_speed speed)
626{
627 struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy);
628
629 qphy->cable_connected = true;
630
631 if (qphy->qusb_phy_host_init_seq && qphy->phy.flags & PHY_HOST_MODE)
632 qusb_phy_host_init(phy);
633
634 dev_dbg(phy->dev, "QUSB PHY: connect notification cable_connected=%d\n",
635 qphy->cable_connected);
636 return 0;
637}
638
639static int qusb_phy_notify_disconnect(struct usb_phy *phy,
640 enum usb_device_speed speed)
641{
642 struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy);
643
644 qphy->cable_connected = false;
645
646 dev_dbg(phy->dev, "QUSB PHY: connect notification cable_connected=%d\n",
647 qphy->cable_connected);
648 return 0;
649}
650
651static int qusb_phy_dpdm_regulator_enable(struct regulator_dev *rdev)
652{
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700653 int ret = 0;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700654 struct qusb_phy *qphy = rdev_get_drvdata(rdev);
655
Mayank Ranadadae592017-07-21 09:03:32 -0700656 dev_dbg(qphy->phy.dev, "%s dpdm_enable:%d\n",
657 __func__, qphy->dpdm_enable);
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700658
Mayank Ranadadae592017-07-21 09:03:32 -0700659 if (!qphy->dpdm_enable) {
Hemant Kumar7dc63722017-04-27 17:51:11 -0700660 ret = qusb_phy_enable_power(qphy, true);
Mayank Ranadadae592017-07-21 09:03:32 -0700661 if (ret < 0) {
662 dev_dbg(qphy->phy.dev,
663 "dpdm regulator enable failed:%d\n", ret);
664 return ret;
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700665 }
Mayank Ranadadae592017-07-21 09:03:32 -0700666 qphy->dpdm_enable = true;
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700667 }
668
669 return ret;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700670}
671
672static int qusb_phy_dpdm_regulator_disable(struct regulator_dev *rdev)
673{
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700674 int ret = 0;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700675 struct qusb_phy *qphy = rdev_get_drvdata(rdev);
676
Mayank Ranadadae592017-07-21 09:03:32 -0700677 dev_dbg(qphy->phy.dev, "%s dpdm_enable:%d\n",
678 __func__, qphy->dpdm_enable);
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700679
Mayank Ranadadae592017-07-21 09:03:32 -0700680 if (qphy->dpdm_enable) {
Hemant Kumar7dc63722017-04-27 17:51:11 -0700681 ret = qusb_phy_enable_power(qphy, false);
Mayank Ranadadae592017-07-21 09:03:32 -0700682 if (ret < 0) {
683 dev_dbg(qphy->phy.dev,
684 "dpdm regulator disable failed:%d\n", ret);
685 return ret;
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700686 }
Mayank Ranadadae592017-07-21 09:03:32 -0700687 qphy->dpdm_enable = false;
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700688 }
689
690 return ret;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700691}
692
693static int qusb_phy_dpdm_regulator_is_enabled(struct regulator_dev *rdev)
694{
695 struct qusb_phy *qphy = rdev_get_drvdata(rdev);
696
Mayank Ranadadae592017-07-21 09:03:32 -0700697 dev_dbg(qphy->phy.dev, "%s qphy->dpdm_enable = %d\n", __func__,
698 qphy->dpdm_enable);
699 return qphy->dpdm_enable;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700700}
701
702static struct regulator_ops qusb_phy_dpdm_regulator_ops = {
703 .enable = qusb_phy_dpdm_regulator_enable,
704 .disable = qusb_phy_dpdm_regulator_disable,
705 .is_enabled = qusb_phy_dpdm_regulator_is_enabled,
706};
707
708static int qusb_phy_regulator_init(struct qusb_phy *qphy)
709{
710 struct device *dev = qphy->phy.dev;
711 struct regulator_config cfg = {};
712 struct regulator_init_data *init_data;
713
714 init_data = devm_kzalloc(dev, sizeof(*init_data), GFP_KERNEL);
715 if (!init_data)
716 return -ENOMEM;
717
718 init_data->constraints.valid_ops_mask |= REGULATOR_CHANGE_STATUS;
719 qphy->dpdm_rdesc.owner = THIS_MODULE;
720 qphy->dpdm_rdesc.type = REGULATOR_VOLTAGE;
721 qphy->dpdm_rdesc.ops = &qusb_phy_dpdm_regulator_ops;
722 qphy->dpdm_rdesc.name = kbasename(dev->of_node->full_name);
723
724 cfg.dev = dev;
725 cfg.init_data = init_data;
726 cfg.driver_data = qphy;
727 cfg.of_node = dev->of_node;
728
729 qphy->dpdm_rdev = devm_regulator_register(dev, &qphy->dpdm_rdesc, &cfg);
730 if (IS_ERR(qphy->dpdm_rdev))
731 return PTR_ERR(qphy->dpdm_rdev);
732
733 return 0;
734}
735
736static int qusb_phy_probe(struct platform_device *pdev)
737{
738 struct qusb_phy *qphy;
739 struct device *dev = &pdev->dev;
740 struct resource *res;
741 int ret = 0, size = 0;
742
743 qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL);
744 if (!qphy)
745 return -ENOMEM;
746
747 qphy->phy.dev = dev;
748 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
749 "qusb_phy_base");
750 qphy->base = devm_ioremap_resource(dev, res);
751 if (IS_ERR(qphy->base))
752 return PTR_ERR(qphy->base);
753
754 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
755 "emu_phy_base");
756 if (res) {
757 qphy->emu_phy_base = devm_ioremap_resource(dev, res);
758 if (IS_ERR(qphy->emu_phy_base)) {
759 dev_dbg(dev, "couldn't ioremap emu_phy_base\n");
760 qphy->emu_phy_base = NULL;
761 }
762 }
763
764 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700765 "efuse_addr");
Mayank Rana3cb43a32016-08-02 12:10:20 -0700766 if (res) {
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700767 qphy->efuse_reg = devm_ioremap_nocache(dev, res->start,
Mayank Rana3cb43a32016-08-02 12:10:20 -0700768 resource_size(res));
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700769 if (!IS_ERR_OR_NULL(qphy->efuse_reg)) {
Mayank Rana3cb43a32016-08-02 12:10:20 -0700770 ret = of_property_read_u32(dev->of_node,
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700771 "qcom,efuse-bit-pos",
772 &qphy->efuse_bit_pos);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700773 if (!ret) {
774 ret = of_property_read_u32(dev->of_node,
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700775 "qcom,efuse-num-bits",
776 &qphy->efuse_num_of_bits);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700777 }
778
779 if (ret) {
780 dev_err(dev,
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700781 "DT Value for efuse is invalid.\n");
Mayank Rana3cb43a32016-08-02 12:10:20 -0700782 return -EINVAL;
783 }
784 }
785 }
786
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700787 /* ref_clk_src is needed irrespective of SE_CLK or DIFF_CLK usage */
Mayank Rana3cb43a32016-08-02 12:10:20 -0700788 qphy->ref_clk_src = devm_clk_get(dev, "ref_clk_src");
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700789 if (IS_ERR(qphy->ref_clk_src)) {
Mayank Rana3cb43a32016-08-02 12:10:20 -0700790 dev_dbg(dev, "clk get failed for ref_clk_src\n");
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700791 ret = PTR_ERR(qphy->ref_clk_src);
792 return ret;
793 }
Mayank Rana3cb43a32016-08-02 12:10:20 -0700794
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700795 /* ref_clk is needed only for DIFF_CLK case, hence make it optional. */
796 if (of_property_match_string(pdev->dev.of_node,
797 "clock-names", "ref_clk") >= 0) {
798 qphy->ref_clk = devm_clk_get(dev, "ref_clk");
799 if (IS_ERR(qphy->ref_clk)) {
800 ret = PTR_ERR(qphy->ref_clk);
801 if (ret != -EPROBE_DEFER)
802 dev_dbg(dev,
803 "clk get failed for ref_clk\n");
804 return ret;
805 }
806
Mayank Rana3cb43a32016-08-02 12:10:20 -0700807 clk_set_rate(qphy->ref_clk, 19200000);
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700808 }
Mayank Rana3cb43a32016-08-02 12:10:20 -0700809
810 if (of_property_match_string(pdev->dev.of_node,
811 "clock-names", "cfg_ahb_clk") >= 0) {
812 qphy->cfg_ahb_clk = devm_clk_get(dev, "cfg_ahb_clk");
813 if (IS_ERR(qphy->cfg_ahb_clk)) {
814 ret = PTR_ERR(qphy->cfg_ahb_clk);
815 if (ret != -EPROBE_DEFER)
816 dev_err(dev,
817 "clk get failed for cfg_ahb_clk ret %d\n", ret);
818 return ret;
819 }
820 }
821
Amit Nischal4d278212016-06-06 17:54:34 +0530822 qphy->phy_reset = devm_reset_control_get(dev, "phy_reset");
Mayank Rana3cb43a32016-08-02 12:10:20 -0700823 if (IS_ERR(qphy->phy_reset))
824 return PTR_ERR(qphy->phy_reset);
825
826 qphy->emulation = of_property_read_bool(dev->of_node,
827 "qcom,emulation");
828
829 of_get_property(dev->of_node, "qcom,emu-init-seq", &size);
830 if (size) {
831 qphy->emu_init_seq = devm_kzalloc(dev,
832 size, GFP_KERNEL);
833 if (qphy->emu_init_seq) {
834 qphy->emu_init_seq_len =
835 (size / sizeof(*qphy->emu_init_seq));
836 if (qphy->emu_init_seq_len % 2) {
837 dev_err(dev, "invalid emu_init_seq_len\n");
838 return -EINVAL;
839 }
840
841 of_property_read_u32_array(dev->of_node,
Mayank Rana147f41d2016-08-12 10:07:45 -0700842 "qcom,emu-init-seq",
Mayank Rana3cb43a32016-08-02 12:10:20 -0700843 qphy->emu_init_seq,
844 qphy->emu_init_seq_len);
845 } else {
846 dev_dbg(dev,
847 "error allocating memory for emu_init_seq\n");
848 }
849 }
850
Mayank Rana147f41d2016-08-12 10:07:45 -0700851 size = 0;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700852 of_get_property(dev->of_node, "qcom,phy-pll-reset-seq", &size);
853 if (size) {
854 qphy->phy_pll_reset_seq = devm_kzalloc(dev,
855 size, GFP_KERNEL);
856 if (qphy->phy_pll_reset_seq) {
857 qphy->phy_pll_reset_seq_len =
858 (size / sizeof(*qphy->phy_pll_reset_seq));
859 if (qphy->phy_pll_reset_seq_len % 2) {
860 dev_err(dev, "invalid phy_pll_reset_seq_len\n");
861 return -EINVAL;
862 }
863
864 of_property_read_u32_array(dev->of_node,
865 "qcom,phy-pll-reset-seq",
866 qphy->phy_pll_reset_seq,
867 qphy->phy_pll_reset_seq_len);
868 } else {
869 dev_dbg(dev,
870 "error allocating memory for phy_pll_reset_seq\n");
871 }
872 }
873
Mayank Rana147f41d2016-08-12 10:07:45 -0700874 size = 0;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700875 of_get_property(dev->of_node, "qcom,emu-dcm-reset-seq", &size);
876 if (size) {
877 qphy->emu_dcm_reset_seq = devm_kzalloc(dev,
878 size, GFP_KERNEL);
879 if (qphy->emu_dcm_reset_seq) {
880 qphy->emu_dcm_reset_seq_len =
881 (size / sizeof(*qphy->emu_dcm_reset_seq));
882 if (qphy->emu_dcm_reset_seq_len % 2) {
883 dev_err(dev, "invalid emu_dcm_reset_seq_len\n");
884 return -EINVAL;
885 }
886
887 of_property_read_u32_array(dev->of_node,
888 "qcom,emu-dcm-reset-seq",
889 qphy->emu_dcm_reset_seq,
890 qphy->emu_dcm_reset_seq_len);
891 } else {
892 dev_dbg(dev,
893 "error allocating memory for emu_dcm_reset_seq\n");
894 }
895 }
896
Mayank Rana147f41d2016-08-12 10:07:45 -0700897 size = 0;
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700898 of_get_property(dev->of_node, "qcom,qusb-phy-reg-offset", &size);
899 if (size) {
900 qphy->phy_reg = devm_kzalloc(dev, size, GFP_KERNEL);
901 if (qphy->phy_reg) {
902 qphy->qusb_phy_reg_offset_cnt =
903 size / sizeof(*qphy->phy_reg);
904 if (qphy->qusb_phy_reg_offset_cnt > USB2_PHY_REG_MAX) {
905 dev_err(dev, "invalid reg offset count\n");
906 return -EINVAL;
907 }
908
909 of_property_read_u32_array(dev->of_node,
910 "qcom,qusb-phy-reg-offset",
911 qphy->phy_reg,
912 qphy->qusb_phy_reg_offset_cnt);
913 } else {
914 dev_err(dev, "err mem alloc for qusb_phy_reg_offset\n");
915 return -ENOMEM;
916 }
917 } else {
918 dev_err(dev, "err provide qcom,qmp-phy-reg-offset\n");
919 return -EINVAL;
920 }
921
922 size = 0;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700923 of_get_property(dev->of_node, "qcom,qusb-phy-init-seq", &size);
924 if (size) {
925 qphy->qusb_phy_init_seq = devm_kzalloc(dev,
926 size, GFP_KERNEL);
927 if (qphy->qusb_phy_init_seq) {
928 qphy->init_seq_len =
929 (size / sizeof(*qphy->qusb_phy_init_seq));
930 if (qphy->init_seq_len % 2) {
931 dev_err(dev, "invalid init_seq_len\n");
932 return -EINVAL;
933 }
934
935 of_property_read_u32_array(dev->of_node,
936 "qcom,qusb-phy-init-seq",
937 qphy->qusb_phy_init_seq,
938 qphy->init_seq_len);
939 } else {
940 dev_err(dev,
941 "error allocating memory for phy_init_seq\n");
942 }
943 }
944
945 qphy->host_init_seq_len = of_property_count_elems_of_size(dev->of_node,
946 "qcom,qusb-phy-host-init-seq",
947 sizeof(*qphy->qusb_phy_host_init_seq));
948 if (qphy->host_init_seq_len > 0) {
949 qphy->qusb_phy_host_init_seq = devm_kcalloc(dev,
950 qphy->host_init_seq_len,
951 sizeof(*qphy->qusb_phy_host_init_seq),
952 GFP_KERNEL);
953 if (qphy->qusb_phy_host_init_seq)
954 of_property_read_u32_array(dev->of_node,
955 "qcom,qusb-phy-host-init-seq",
956 qphy->qusb_phy_host_init_seq,
957 qphy->host_init_seq_len);
958 else
959 return -ENOMEM;
960 }
961
962 ret = of_property_read_u32_array(dev->of_node, "qcom,vdd-voltage-level",
963 (u32 *) qphy->vdd_levels,
964 ARRAY_SIZE(qphy->vdd_levels));
965 if (ret) {
966 dev_err(dev, "error reading qcom,vdd-voltage-level property\n");
967 return ret;
968 }
969
970 qphy->vdd = devm_regulator_get(dev, "vdd");
971 if (IS_ERR(qphy->vdd)) {
972 dev_err(dev, "unable to get vdd supply\n");
973 return PTR_ERR(qphy->vdd);
974 }
975
976 qphy->vdda33 = devm_regulator_get(dev, "vdda33");
977 if (IS_ERR(qphy->vdda33)) {
978 dev_err(dev, "unable to get vdda33 supply\n");
979 return PTR_ERR(qphy->vdda33);
980 }
981
982 qphy->vdda18 = devm_regulator_get(dev, "vdda18");
983 if (IS_ERR(qphy->vdda18)) {
984 dev_err(dev, "unable to get vdda18 supply\n");
985 return PTR_ERR(qphy->vdda18);
986 }
987
Hemant Kumar164cc1b2017-04-27 19:39:58 -0700988 mutex_init(&qphy->lock);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700989 platform_set_drvdata(pdev, qphy);
990
991 qphy->phy.label = "msm-qusb-phy-v2";
992 qphy->phy.init = qusb_phy_init;
993 qphy->phy.set_suspend = qusb_phy_set_suspend;
994 qphy->phy.shutdown = qusb_phy_shutdown;
995 qphy->phy.type = USB_PHY_TYPE_USB2;
996 qphy->phy.notify_connect = qusb_phy_notify_connect;
997 qphy->phy.notify_disconnect = qusb_phy_notify_disconnect;
998
999 ret = usb_add_phy_dev(&qphy->phy);
1000 if (ret)
1001 return ret;
1002
1003 ret = qusb_phy_regulator_init(qphy);
1004 if (ret)
1005 usb_remove_phy(&qphy->phy);
1006
1007 return ret;
1008}
1009
1010static int qusb_phy_remove(struct platform_device *pdev)
1011{
1012 struct qusb_phy *qphy = platform_get_drvdata(pdev);
1013
1014 usb_remove_phy(&qphy->phy);
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -07001015 qusb_phy_enable_clocks(qphy, false);
Hemant Kumar7dc63722017-04-27 17:51:11 -07001016 qusb_phy_enable_power(qphy, false);
Mayank Rana3cb43a32016-08-02 12:10:20 -07001017
1018 return 0;
1019}
1020
1021static const struct of_device_id qusb_phy_id_table[] = {
1022 { .compatible = "qcom,qusb2phy-v2", },
1023 { },
1024};
1025MODULE_DEVICE_TABLE(of, qusb_phy_id_table);
1026
1027static struct platform_driver qusb_phy_driver = {
1028 .probe = qusb_phy_probe,
1029 .remove = qusb_phy_remove,
1030 .driver = {
1031 .name = "msm-qusb-phy-v2",
1032 .of_match_table = of_match_ptr(qusb_phy_id_table),
1033 },
1034};
1035
1036module_platform_driver(qusb_phy_driver);
1037
1038MODULE_DESCRIPTION("MSM QUSB2 PHY v2 driver");
1039MODULE_LICENSE("GPL v2");