blob: 37d904f7d82a6a4a25e77ad8d48d949c201f7e43 [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
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700575 /* enable phy auto-resume */
576 writel_relaxed(0x91, qphy->base + qphy->phy_reg[TEST1]);
577 /* flush the previous write before next write */
578 wmb();
579 writel_relaxed(0x90, qphy->base + qphy->phy_reg[TEST1]);
580
Mayank Rana3cb43a32016-08-02 12:10:20 -0700581 dev_dbg(phy->dev, "%s: intr_mask = %x\n",
582 __func__, intr_mask);
583
584 /* Makes sure that above write goes through */
585 wmb();
586 qusb_phy_enable_clocks(qphy, false);
587 } else { /* Cable disconnect case */
588 /* Disable all interrupts */
589 writel_relaxed(0x00,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700590 qphy->base + qphy->phy_reg[INTR_CTRL]);
Mayank Ranab7f212e2017-04-06 17:54:35 -0700591 qusb_phy_reset(qphy);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700592 qusb_phy_enable_clocks(qphy, false);
Hemant Kumar7dc63722017-04-27 17:51:11 -0700593 qusb_phy_enable_power(qphy, false);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700594 }
595 qphy->suspended = true;
596 } else {
597 /* Bus resume case */
598 if (qphy->cable_connected ||
599 (qphy->phy.flags & PHY_HOST_MODE)) {
600 qusb_phy_enable_clocks(qphy, true);
601 /* Clear all interrupts on resume */
602 writel_relaxed(0x00,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700603 qphy->base + qphy->phy_reg[INTR_CTRL]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700604
Mayank Ranab7f212e2017-04-06 17:54:35 -0700605 /* bring core PLL out of reset */
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700606 writel_relaxed(CORE_PLL_EN_FROM_RESET, qphy->base +
607 qphy->phy_reg[PLL_CORE_INPUT_OVERRIDE]);
Mayank Ranab7f212e2017-04-06 17:54:35 -0700608
Mayank Rana3cb43a32016-08-02 12:10:20 -0700609 /* Makes sure that above write goes through */
610 wmb();
611 } else { /* Cable connect case */
Mayank Rana3cb43a32016-08-02 12:10:20 -0700612 qusb_phy_enable_clocks(qphy, true);
613 }
614 qphy->suspended = false;
615 }
616
617 return 0;
618}
619
620static int qusb_phy_notify_connect(struct usb_phy *phy,
621 enum usb_device_speed speed)
622{
623 struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy);
624
625 qphy->cable_connected = true;
626
627 if (qphy->qusb_phy_host_init_seq && qphy->phy.flags & PHY_HOST_MODE)
628 qusb_phy_host_init(phy);
629
630 dev_dbg(phy->dev, "QUSB PHY: connect notification cable_connected=%d\n",
631 qphy->cable_connected);
632 return 0;
633}
634
635static int qusb_phy_notify_disconnect(struct usb_phy *phy,
636 enum usb_device_speed speed)
637{
638 struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy);
639
640 qphy->cable_connected = false;
641
642 dev_dbg(phy->dev, "QUSB PHY: connect notification cable_connected=%d\n",
643 qphy->cable_connected);
644 return 0;
645}
646
647static int qusb_phy_dpdm_regulator_enable(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, true);
Mayank Ranadadae592017-07-21 09:03:32 -0700657 if (ret < 0) {
658 dev_dbg(qphy->phy.dev,
659 "dpdm regulator enable 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 = true;
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_disable(struct regulator_dev *rdev)
669{
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700670 int ret = 0;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700671 struct qusb_phy *qphy = rdev_get_drvdata(rdev);
672
Mayank Ranadadae592017-07-21 09:03:32 -0700673 dev_dbg(qphy->phy.dev, "%s dpdm_enable:%d\n",
674 __func__, qphy->dpdm_enable);
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700675
Mayank Ranadadae592017-07-21 09:03:32 -0700676 if (qphy->dpdm_enable) {
Hemant Kumar7dc63722017-04-27 17:51:11 -0700677 ret = qusb_phy_enable_power(qphy, false);
Mayank Ranadadae592017-07-21 09:03:32 -0700678 if (ret < 0) {
679 dev_dbg(qphy->phy.dev,
680 "dpdm regulator disable failed:%d\n", ret);
681 return ret;
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700682 }
Mayank Ranadadae592017-07-21 09:03:32 -0700683 qphy->dpdm_enable = false;
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700684 }
685
686 return ret;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700687}
688
689static int qusb_phy_dpdm_regulator_is_enabled(struct regulator_dev *rdev)
690{
691 struct qusb_phy *qphy = rdev_get_drvdata(rdev);
692
Mayank Ranadadae592017-07-21 09:03:32 -0700693 dev_dbg(qphy->phy.dev, "%s qphy->dpdm_enable = %d\n", __func__,
694 qphy->dpdm_enable);
695 return qphy->dpdm_enable;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700696}
697
698static struct regulator_ops qusb_phy_dpdm_regulator_ops = {
699 .enable = qusb_phy_dpdm_regulator_enable,
700 .disable = qusb_phy_dpdm_regulator_disable,
701 .is_enabled = qusb_phy_dpdm_regulator_is_enabled,
702};
703
704static int qusb_phy_regulator_init(struct qusb_phy *qphy)
705{
706 struct device *dev = qphy->phy.dev;
707 struct regulator_config cfg = {};
708 struct regulator_init_data *init_data;
709
710 init_data = devm_kzalloc(dev, sizeof(*init_data), GFP_KERNEL);
711 if (!init_data)
712 return -ENOMEM;
713
714 init_data->constraints.valid_ops_mask |= REGULATOR_CHANGE_STATUS;
715 qphy->dpdm_rdesc.owner = THIS_MODULE;
716 qphy->dpdm_rdesc.type = REGULATOR_VOLTAGE;
717 qphy->dpdm_rdesc.ops = &qusb_phy_dpdm_regulator_ops;
718 qphy->dpdm_rdesc.name = kbasename(dev->of_node->full_name);
719
720 cfg.dev = dev;
721 cfg.init_data = init_data;
722 cfg.driver_data = qphy;
723 cfg.of_node = dev->of_node;
724
725 qphy->dpdm_rdev = devm_regulator_register(dev, &qphy->dpdm_rdesc, &cfg);
726 if (IS_ERR(qphy->dpdm_rdev))
727 return PTR_ERR(qphy->dpdm_rdev);
728
729 return 0;
730}
731
732static int qusb_phy_probe(struct platform_device *pdev)
733{
734 struct qusb_phy *qphy;
735 struct device *dev = &pdev->dev;
736 struct resource *res;
737 int ret = 0, size = 0;
738
739 qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL);
740 if (!qphy)
741 return -ENOMEM;
742
743 qphy->phy.dev = dev;
744 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
745 "qusb_phy_base");
746 qphy->base = devm_ioremap_resource(dev, res);
747 if (IS_ERR(qphy->base))
748 return PTR_ERR(qphy->base);
749
750 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
751 "emu_phy_base");
752 if (res) {
753 qphy->emu_phy_base = devm_ioremap_resource(dev, res);
754 if (IS_ERR(qphy->emu_phy_base)) {
755 dev_dbg(dev, "couldn't ioremap emu_phy_base\n");
756 qphy->emu_phy_base = NULL;
757 }
758 }
759
760 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700761 "efuse_addr");
Mayank Rana3cb43a32016-08-02 12:10:20 -0700762 if (res) {
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700763 qphy->efuse_reg = devm_ioremap_nocache(dev, res->start,
Mayank Rana3cb43a32016-08-02 12:10:20 -0700764 resource_size(res));
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700765 if (!IS_ERR_OR_NULL(qphy->efuse_reg)) {
Mayank Rana3cb43a32016-08-02 12:10:20 -0700766 ret = of_property_read_u32(dev->of_node,
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700767 "qcom,efuse-bit-pos",
768 &qphy->efuse_bit_pos);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700769 if (!ret) {
770 ret = of_property_read_u32(dev->of_node,
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700771 "qcom,efuse-num-bits",
772 &qphy->efuse_num_of_bits);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700773 }
774
775 if (ret) {
776 dev_err(dev,
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700777 "DT Value for efuse is invalid.\n");
Mayank Rana3cb43a32016-08-02 12:10:20 -0700778 return -EINVAL;
779 }
780 }
781 }
782
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700783 /* ref_clk_src is needed irrespective of SE_CLK or DIFF_CLK usage */
Mayank Rana3cb43a32016-08-02 12:10:20 -0700784 qphy->ref_clk_src = devm_clk_get(dev, "ref_clk_src");
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700785 if (IS_ERR(qphy->ref_clk_src)) {
Mayank Rana3cb43a32016-08-02 12:10:20 -0700786 dev_dbg(dev, "clk get failed for ref_clk_src\n");
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700787 ret = PTR_ERR(qphy->ref_clk_src);
788 return ret;
789 }
Mayank Rana3cb43a32016-08-02 12:10:20 -0700790
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700791 /* ref_clk is needed only for DIFF_CLK case, hence make it optional. */
792 if (of_property_match_string(pdev->dev.of_node,
793 "clock-names", "ref_clk") >= 0) {
794 qphy->ref_clk = devm_clk_get(dev, "ref_clk");
795 if (IS_ERR(qphy->ref_clk)) {
796 ret = PTR_ERR(qphy->ref_clk);
797 if (ret != -EPROBE_DEFER)
798 dev_dbg(dev,
799 "clk get failed for ref_clk\n");
800 return ret;
801 }
802
Mayank Rana3cb43a32016-08-02 12:10:20 -0700803 clk_set_rate(qphy->ref_clk, 19200000);
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700804 }
Mayank Rana3cb43a32016-08-02 12:10:20 -0700805
806 if (of_property_match_string(pdev->dev.of_node,
807 "clock-names", "cfg_ahb_clk") >= 0) {
808 qphy->cfg_ahb_clk = devm_clk_get(dev, "cfg_ahb_clk");
809 if (IS_ERR(qphy->cfg_ahb_clk)) {
810 ret = PTR_ERR(qphy->cfg_ahb_clk);
811 if (ret != -EPROBE_DEFER)
812 dev_err(dev,
813 "clk get failed for cfg_ahb_clk ret %d\n", ret);
814 return ret;
815 }
816 }
817
Amit Nischal4d278212016-06-06 17:54:34 +0530818 qphy->phy_reset = devm_reset_control_get(dev, "phy_reset");
Mayank Rana3cb43a32016-08-02 12:10:20 -0700819 if (IS_ERR(qphy->phy_reset))
820 return PTR_ERR(qphy->phy_reset);
821
822 qphy->emulation = of_property_read_bool(dev->of_node,
823 "qcom,emulation");
824
825 of_get_property(dev->of_node, "qcom,emu-init-seq", &size);
826 if (size) {
827 qphy->emu_init_seq = devm_kzalloc(dev,
828 size, GFP_KERNEL);
829 if (qphy->emu_init_seq) {
830 qphy->emu_init_seq_len =
831 (size / sizeof(*qphy->emu_init_seq));
832 if (qphy->emu_init_seq_len % 2) {
833 dev_err(dev, "invalid emu_init_seq_len\n");
834 return -EINVAL;
835 }
836
837 of_property_read_u32_array(dev->of_node,
Mayank Rana147f41d2016-08-12 10:07:45 -0700838 "qcom,emu-init-seq",
Mayank Rana3cb43a32016-08-02 12:10:20 -0700839 qphy->emu_init_seq,
840 qphy->emu_init_seq_len);
841 } else {
842 dev_dbg(dev,
843 "error allocating memory for emu_init_seq\n");
844 }
845 }
846
Mayank Rana147f41d2016-08-12 10:07:45 -0700847 size = 0;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700848 of_get_property(dev->of_node, "qcom,phy-pll-reset-seq", &size);
849 if (size) {
850 qphy->phy_pll_reset_seq = devm_kzalloc(dev,
851 size, GFP_KERNEL);
852 if (qphy->phy_pll_reset_seq) {
853 qphy->phy_pll_reset_seq_len =
854 (size / sizeof(*qphy->phy_pll_reset_seq));
855 if (qphy->phy_pll_reset_seq_len % 2) {
856 dev_err(dev, "invalid phy_pll_reset_seq_len\n");
857 return -EINVAL;
858 }
859
860 of_property_read_u32_array(dev->of_node,
861 "qcom,phy-pll-reset-seq",
862 qphy->phy_pll_reset_seq,
863 qphy->phy_pll_reset_seq_len);
864 } else {
865 dev_dbg(dev,
866 "error allocating memory for phy_pll_reset_seq\n");
867 }
868 }
869
Mayank Rana147f41d2016-08-12 10:07:45 -0700870 size = 0;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700871 of_get_property(dev->of_node, "qcom,emu-dcm-reset-seq", &size);
872 if (size) {
873 qphy->emu_dcm_reset_seq = devm_kzalloc(dev,
874 size, GFP_KERNEL);
875 if (qphy->emu_dcm_reset_seq) {
876 qphy->emu_dcm_reset_seq_len =
877 (size / sizeof(*qphy->emu_dcm_reset_seq));
878 if (qphy->emu_dcm_reset_seq_len % 2) {
879 dev_err(dev, "invalid emu_dcm_reset_seq_len\n");
880 return -EINVAL;
881 }
882
883 of_property_read_u32_array(dev->of_node,
884 "qcom,emu-dcm-reset-seq",
885 qphy->emu_dcm_reset_seq,
886 qphy->emu_dcm_reset_seq_len);
887 } else {
888 dev_dbg(dev,
889 "error allocating memory for emu_dcm_reset_seq\n");
890 }
891 }
892
Mayank Rana147f41d2016-08-12 10:07:45 -0700893 size = 0;
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700894 of_get_property(dev->of_node, "qcom,qusb-phy-reg-offset", &size);
895 if (size) {
896 qphy->phy_reg = devm_kzalloc(dev, size, GFP_KERNEL);
897 if (qphy->phy_reg) {
898 qphy->qusb_phy_reg_offset_cnt =
899 size / sizeof(*qphy->phy_reg);
900 if (qphy->qusb_phy_reg_offset_cnt > USB2_PHY_REG_MAX) {
901 dev_err(dev, "invalid reg offset count\n");
902 return -EINVAL;
903 }
904
905 of_property_read_u32_array(dev->of_node,
906 "qcom,qusb-phy-reg-offset",
907 qphy->phy_reg,
908 qphy->qusb_phy_reg_offset_cnt);
909 } else {
910 dev_err(dev, "err mem alloc for qusb_phy_reg_offset\n");
911 return -ENOMEM;
912 }
913 } else {
914 dev_err(dev, "err provide qcom,qmp-phy-reg-offset\n");
915 return -EINVAL;
916 }
917
918 size = 0;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700919 of_get_property(dev->of_node, "qcom,qusb-phy-init-seq", &size);
920 if (size) {
921 qphy->qusb_phy_init_seq = devm_kzalloc(dev,
922 size, GFP_KERNEL);
923 if (qphy->qusb_phy_init_seq) {
924 qphy->init_seq_len =
925 (size / sizeof(*qphy->qusb_phy_init_seq));
926 if (qphy->init_seq_len % 2) {
927 dev_err(dev, "invalid init_seq_len\n");
928 return -EINVAL;
929 }
930
931 of_property_read_u32_array(dev->of_node,
932 "qcom,qusb-phy-init-seq",
933 qphy->qusb_phy_init_seq,
934 qphy->init_seq_len);
935 } else {
936 dev_err(dev,
937 "error allocating memory for phy_init_seq\n");
938 }
939 }
940
941 qphy->host_init_seq_len = of_property_count_elems_of_size(dev->of_node,
942 "qcom,qusb-phy-host-init-seq",
943 sizeof(*qphy->qusb_phy_host_init_seq));
944 if (qphy->host_init_seq_len > 0) {
945 qphy->qusb_phy_host_init_seq = devm_kcalloc(dev,
946 qphy->host_init_seq_len,
947 sizeof(*qphy->qusb_phy_host_init_seq),
948 GFP_KERNEL);
949 if (qphy->qusb_phy_host_init_seq)
950 of_property_read_u32_array(dev->of_node,
951 "qcom,qusb-phy-host-init-seq",
952 qphy->qusb_phy_host_init_seq,
953 qphy->host_init_seq_len);
954 else
955 return -ENOMEM;
956 }
957
958 ret = of_property_read_u32_array(dev->of_node, "qcom,vdd-voltage-level",
959 (u32 *) qphy->vdd_levels,
960 ARRAY_SIZE(qphy->vdd_levels));
961 if (ret) {
962 dev_err(dev, "error reading qcom,vdd-voltage-level property\n");
963 return ret;
964 }
965
966 qphy->vdd = devm_regulator_get(dev, "vdd");
967 if (IS_ERR(qphy->vdd)) {
968 dev_err(dev, "unable to get vdd supply\n");
969 return PTR_ERR(qphy->vdd);
970 }
971
972 qphy->vdda33 = devm_regulator_get(dev, "vdda33");
973 if (IS_ERR(qphy->vdda33)) {
974 dev_err(dev, "unable to get vdda33 supply\n");
975 return PTR_ERR(qphy->vdda33);
976 }
977
978 qphy->vdda18 = devm_regulator_get(dev, "vdda18");
979 if (IS_ERR(qphy->vdda18)) {
980 dev_err(dev, "unable to get vdda18 supply\n");
981 return PTR_ERR(qphy->vdda18);
982 }
983
Hemant Kumar164cc1b2017-04-27 19:39:58 -0700984 mutex_init(&qphy->lock);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700985 platform_set_drvdata(pdev, qphy);
986
987 qphy->phy.label = "msm-qusb-phy-v2";
988 qphy->phy.init = qusb_phy_init;
989 qphy->phy.set_suspend = qusb_phy_set_suspend;
990 qphy->phy.shutdown = qusb_phy_shutdown;
991 qphy->phy.type = USB_PHY_TYPE_USB2;
992 qphy->phy.notify_connect = qusb_phy_notify_connect;
993 qphy->phy.notify_disconnect = qusb_phy_notify_disconnect;
994
995 ret = usb_add_phy_dev(&qphy->phy);
996 if (ret)
997 return ret;
998
999 ret = qusb_phy_regulator_init(qphy);
1000 if (ret)
1001 usb_remove_phy(&qphy->phy);
1002
1003 return ret;
1004}
1005
1006static int qusb_phy_remove(struct platform_device *pdev)
1007{
1008 struct qusb_phy *qphy = platform_get_drvdata(pdev);
1009
1010 usb_remove_phy(&qphy->phy);
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -07001011 qusb_phy_enable_clocks(qphy, false);
Hemant Kumar7dc63722017-04-27 17:51:11 -07001012 qusb_phy_enable_power(qphy, false);
Mayank Rana3cb43a32016-08-02 12:10:20 -07001013
1014 return 0;
1015}
1016
1017static const struct of_device_id qusb_phy_id_table[] = {
1018 { .compatible = "qcom,qusb2phy-v2", },
1019 { },
1020};
1021MODULE_DEVICE_TABLE(of, qusb_phy_id_table);
1022
1023static struct platform_driver qusb_phy_driver = {
1024 .probe = qusb_phy_probe,
1025 .remove = qusb_phy_remove,
1026 .driver = {
1027 .name = "msm-qusb-phy-v2",
1028 .of_match_table = of_match_ptr(qusb_phy_id_table),
1029 },
1030};
1031
1032module_platform_driver(qusb_phy_driver);
1033
1034MODULE_DESCRIPTION("MSM QUSB2 PHY v2 driver");
1035MODULE_LICENSE("GPL v2");