blob: 81c39a34c3ccae7866c0189045b66794b3ff8e96 [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 Rana76a040f2017-11-20 14:10:37 -080029#include <linux/debugfs.h>
Mayank Rana3cb43a32016-08-02 12:10:20 -070030
Mayank Rana9c6b12d2017-06-22 16:23:26 -070031/* QUSB2PHY_PWR_CTRL1 register related bits */
Mayank Rana3cb43a32016-08-02 12:10:20 -070032#define PWR_CTRL1_POWR_DOWN BIT(0)
33
Mayank Rana9c6b12d2017-06-22 16:23:26 -070034/* QUSB2PHY_PLL_COMMON_STATUS_ONE register related bits */
Mayank Rana3cb43a32016-08-02 12:10:20 -070035#define CORE_READY_STATUS BIT(0)
36
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -070037/* Get TUNE value from efuse bit-mask */
38#define TUNE_VAL_MASK(val, pos, mask) ((val >> pos) & mask)
Mayank Rana3cb43a32016-08-02 12:10:20 -070039
Mayank Rana9c6b12d2017-06-22 16:23:26 -070040/* QUSB2PHY_INTR_CTRL register related bits */
Mayank Rana3cb43a32016-08-02 12:10:20 -070041#define DMSE_INTR_HIGH_SEL BIT(4)
42#define DPSE_INTR_HIGH_SEL BIT(3)
43#define CHG_DET_INTR_EN BIT(2)
44#define DMSE_INTR_EN BIT(1)
45#define DPSE_INTR_EN BIT(0)
46
Mayank Rana9c6b12d2017-06-22 16:23:26 -070047/* QUSB2PHY_PLL_CORE_INPUT_OVERRIDE register related bits */
Mayank Ranab7f212e2017-04-06 17:54:35 -070048#define CORE_PLL_RATE BIT(0)
49#define CORE_PLL_RATE_MUX BIT(1)
50#define CORE_PLL_EN BIT(2)
51#define CORE_PLL_EN_MUX BIT(3)
52#define CORE_PLL_EN_FROM_RESET BIT(4)
53#define CORE_RESET BIT(5)
54#define CORE_RESET_MUX BIT(6)
55
Mayank Rana3cb43a32016-08-02 12:10:20 -070056#define QUSB2PHY_1P8_VOL_MIN 1800000 /* uV */
57#define QUSB2PHY_1P8_VOL_MAX 1800000 /* uV */
58#define QUSB2PHY_1P8_HPM_LOAD 30000 /* uA */
59
60#define QUSB2PHY_3P3_VOL_MIN 3075000 /* uV */
61#define QUSB2PHY_3P3_VOL_MAX 3200000 /* uV */
62#define QUSB2PHY_3P3_HPM_LOAD 30000 /* uA */
63
64#define LINESTATE_DP BIT(0)
65#define LINESTATE_DM BIT(1)
66
Mayank Rana547e24c2017-11-01 15:47:04 -070067#define BIAS_CTRL_2_OVERRIDE_VAL 0x28
68
Hemant Kumar91f5e542017-11-20 16:25:46 -080069#define SQ_CTRL1_CHIRP_DISABLE 0x20
70#define SQ_CTRL2_CHIRP_DISABLE 0x80
71
Mayank Rana547e24c2017-11-01 15:47:04 -070072/* PERIPH_SS_PHY_REFGEN_NORTH_BG_CTRL register bits */
73#define BANDGAP_BYPASS BIT(0)
74
Mayank Rana9c6b12d2017-06-22 16:23:26 -070075enum qusb_phy_reg {
76 PORT_TUNE1,
77 PLL_COMMON_STATUS_ONE,
78 PWR_CTRL1,
79 INTR_CTRL,
80 PLL_CORE_INPUT_OVERRIDE,
81 TEST1,
Mayank Rana129111e2017-11-01 15:31:22 -070082 BIAS_CTRL_2,
Hemant Kumar91f5e542017-11-20 16:25:46 -080083 SQ_CTRL1,
84 SQ_CTRL2,
Mayank Rana9c6b12d2017-06-22 16:23:26 -070085 USB2_PHY_REG_MAX,
86};
87
Mayank Rana3cb43a32016-08-02 12:10:20 -070088struct qusb_phy {
89 struct usb_phy phy;
Hemant Kumar164cc1b2017-04-27 19:39:58 -070090 struct mutex lock;
Mayank Rana3cb43a32016-08-02 12:10:20 -070091 void __iomem *base;
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -070092 void __iomem *efuse_reg;
Mayank Rana547e24c2017-11-01 15:47:04 -070093 void __iomem *refgen_north_bg_reg;
Mayank Rana3cb43a32016-08-02 12:10:20 -070094
95 struct clk *ref_clk_src;
96 struct clk *ref_clk;
97 struct clk *cfg_ahb_clk;
Amit Nischal4d278212016-06-06 17:54:34 +053098 struct reset_control *phy_reset;
Mayank Rana3cb43a32016-08-02 12:10:20 -070099
100 struct regulator *vdd;
101 struct regulator *vdda33;
102 struct regulator *vdda18;
103 int vdd_levels[3]; /* none, low, high */
104 int init_seq_len;
105 int *qusb_phy_init_seq;
106 int host_init_seq_len;
107 int *qusb_phy_host_init_seq;
108
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700109 unsigned int *phy_reg;
110 int qusb_phy_reg_offset_cnt;
111
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700112 u32 tune_val;
113 int efuse_bit_pos;
114 int efuse_num_of_bits;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700115
Hemant Kumar164cc1b2017-04-27 19:39:58 -0700116 int power_enabled_ref;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700117 bool clocks_enabled;
118 bool cable_connected;
119 bool suspended;
Mayank Ranadadae592017-07-21 09:03:32 -0700120 bool dpdm_enable;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700121
122 struct regulator_desc dpdm_rdesc;
123 struct regulator_dev *dpdm_rdev;
124
Hemant Kumar91f5e542017-11-20 16:25:46 -0800125 u32 sq_ctrl1_default;
126 u32 sq_ctrl2_default;
127 bool chirp_disable;
128
Mayank Rana3cb43a32016-08-02 12:10:20 -0700129 /* emulation targets specific */
130 void __iomem *emu_phy_base;
131 bool emulation;
132 int *emu_init_seq;
133 int emu_init_seq_len;
134 int *phy_pll_reset_seq;
135 int phy_pll_reset_seq_len;
136 int *emu_dcm_reset_seq;
137 int emu_dcm_reset_seq_len;
Mayank Rana76a040f2017-11-20 14:10:37 -0800138
139 /* override TUNEX registers value */
140 struct dentry *root;
141 u8 tune[5];
Mayank Rana3cb43a32016-08-02 12:10:20 -0700142};
143
144static void qusb_phy_enable_clocks(struct qusb_phy *qphy, bool on)
145{
146 dev_dbg(qphy->phy.dev, "%s(): clocks_enabled:%d on:%d\n",
147 __func__, qphy->clocks_enabled, on);
148
149 if (!qphy->clocks_enabled && on) {
150 clk_prepare_enable(qphy->ref_clk_src);
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700151 if (qphy->ref_clk)
152 clk_prepare_enable(qphy->ref_clk);
153
154 if (qphy->cfg_ahb_clk)
155 clk_prepare_enable(qphy->cfg_ahb_clk);
156
Mayank Rana3cb43a32016-08-02 12:10:20 -0700157 qphy->clocks_enabled = true;
158 }
159
160 if (qphy->clocks_enabled && !on) {
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700161 if (qphy->cfg_ahb_clk)
162 clk_disable_unprepare(qphy->cfg_ahb_clk);
163
164 if (qphy->ref_clk)
165 clk_disable_unprepare(qphy->ref_clk);
166
Mayank Rana3cb43a32016-08-02 12:10:20 -0700167 clk_disable_unprepare(qphy->ref_clk_src);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700168 qphy->clocks_enabled = false;
169 }
170
171 dev_dbg(qphy->phy.dev, "%s(): clocks_enabled:%d\n", __func__,
172 qphy->clocks_enabled);
173}
174
175static int qusb_phy_config_vdd(struct qusb_phy *qphy, int high)
176{
177 int min, ret;
178
179 min = high ? 1 : 0; /* low or none? */
180 ret = regulator_set_voltage(qphy->vdd, qphy->vdd_levels[min],
181 qphy->vdd_levels[2]);
182 if (ret) {
183 dev_err(qphy->phy.dev, "unable to set voltage for qusb vdd\n");
184 return ret;
185 }
186
187 dev_dbg(qphy->phy.dev, "min_vol:%d max_vol:%d\n",
188 qphy->vdd_levels[min], qphy->vdd_levels[2]);
189 return ret;
190}
191
Hemant Kumar7dc63722017-04-27 17:51:11 -0700192static int qusb_phy_enable_power(struct qusb_phy *qphy, bool on)
Mayank Rana3cb43a32016-08-02 12:10:20 -0700193{
194 int ret = 0;
195
Hemant Kumar164cc1b2017-04-27 19:39:58 -0700196 mutex_lock(&qphy->lock);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700197
Hemant Kumar164cc1b2017-04-27 19:39:58 -0700198 dev_dbg(qphy->phy.dev,
199 "%s:req to turn %s regulators. power_enabled_ref:%d\n",
200 __func__, on ? "on" : "off", qphy->power_enabled_ref);
201
202 if (on && ++qphy->power_enabled_ref > 1) {
203 dev_dbg(qphy->phy.dev, "PHYs' regulators are already on\n");
204 goto done;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700205 }
206
Hemant Kumar164cc1b2017-04-27 19:39:58 -0700207 if (!on) {
208 if (on == qphy->power_enabled_ref) {
209 dev_dbg(qphy->phy.dev,
210 "PHYs' regulators are already off\n");
211 goto done;
212 }
213
214 qphy->power_enabled_ref--;
215 if (!qphy->power_enabled_ref)
216 goto disable_vdda33;
217
218 dev_dbg(qphy->phy.dev, "Skip turning off PHYs' regulators\n");
219 goto done;
220 }
Mayank Rana3cb43a32016-08-02 12:10:20 -0700221
Hemant Kumar7dc63722017-04-27 17:51:11 -0700222 ret = qusb_phy_config_vdd(qphy, true);
223 if (ret) {
224 dev_err(qphy->phy.dev, "Unable to config VDD:%d\n",
225 ret);
226 goto err_vdd;
227 }
Mayank Rana3cb43a32016-08-02 12:10:20 -0700228
Hemant Kumar7dc63722017-04-27 17:51:11 -0700229 ret = regulator_enable(qphy->vdd);
230 if (ret) {
231 dev_err(qphy->phy.dev, "Unable to enable VDD\n");
232 goto unconfig_vdd;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700233 }
234
235 ret = regulator_set_load(qphy->vdda18, QUSB2PHY_1P8_HPM_LOAD);
236 if (ret < 0) {
237 dev_err(qphy->phy.dev, "Unable to set HPM of vdda18:%d\n", ret);
238 goto disable_vdd;
239 }
240
241 ret = regulator_set_voltage(qphy->vdda18, QUSB2PHY_1P8_VOL_MIN,
242 QUSB2PHY_1P8_VOL_MAX);
243 if (ret) {
244 dev_err(qphy->phy.dev,
245 "Unable to set voltage for vdda18:%d\n", ret);
246 goto put_vdda18_lpm;
247 }
248
249 ret = regulator_enable(qphy->vdda18);
250 if (ret) {
251 dev_err(qphy->phy.dev, "Unable to enable vdda18:%d\n", ret);
252 goto unset_vdda18;
253 }
254
255 ret = regulator_set_load(qphy->vdda33, QUSB2PHY_3P3_HPM_LOAD);
256 if (ret < 0) {
257 dev_err(qphy->phy.dev, "Unable to set HPM of vdda33:%d\n", ret);
258 goto disable_vdda18;
259 }
260
261 ret = regulator_set_voltage(qphy->vdda33, QUSB2PHY_3P3_VOL_MIN,
262 QUSB2PHY_3P3_VOL_MAX);
263 if (ret) {
264 dev_err(qphy->phy.dev,
265 "Unable to set voltage for vdda33:%d\n", ret);
266 goto put_vdda33_lpm;
267 }
268
269 ret = regulator_enable(qphy->vdda33);
270 if (ret) {
271 dev_err(qphy->phy.dev, "Unable to enable vdda33:%d\n", ret);
272 goto unset_vdd33;
273 }
274
Mayank Rana3cb43a32016-08-02 12:10:20 -0700275 pr_debug("%s(): QUSB PHY's regulators are turned ON.\n", __func__);
Hemant Kumar164cc1b2017-04-27 19:39:58 -0700276
277 mutex_unlock(&qphy->lock);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700278 return ret;
279
280disable_vdda33:
281 ret = regulator_disable(qphy->vdda33);
282 if (ret)
283 dev_err(qphy->phy.dev, "Unable to disable vdda33:%d\n", ret);
284
285unset_vdd33:
286 ret = regulator_set_voltage(qphy->vdda33, 0, QUSB2PHY_3P3_VOL_MAX);
287 if (ret)
288 dev_err(qphy->phy.dev,
289 "Unable to set (0) voltage for vdda33:%d\n", ret);
290
291put_vdda33_lpm:
292 ret = regulator_set_load(qphy->vdda33, 0);
293 if (ret < 0)
294 dev_err(qphy->phy.dev, "Unable to set (0) HPM of vdda33\n");
295
296disable_vdda18:
297 ret = regulator_disable(qphy->vdda18);
298 if (ret)
299 dev_err(qphy->phy.dev, "Unable to disable vdda18:%d\n", ret);
300
301unset_vdda18:
302 ret = regulator_set_voltage(qphy->vdda18, 0, QUSB2PHY_1P8_VOL_MAX);
303 if (ret)
304 dev_err(qphy->phy.dev,
305 "Unable to set (0) voltage for vdda18:%d\n", ret);
306
307put_vdda18_lpm:
308 ret = regulator_set_load(qphy->vdda18, 0);
309 if (ret < 0)
310 dev_err(qphy->phy.dev, "Unable to set LPM of vdda18\n");
311
312disable_vdd:
Hemant Kumar7dc63722017-04-27 17:51:11 -0700313 ret = regulator_disable(qphy->vdd);
314 if (ret)
315 dev_err(qphy->phy.dev, "Unable to disable vdd:%d\n",
316 ret);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700317
318unconfig_vdd:
Hemant Kumar7dc63722017-04-27 17:51:11 -0700319 ret = qusb_phy_config_vdd(qphy, false);
320 if (ret)
321 dev_err(qphy->phy.dev, "Unable unconfig VDD:%d\n",
322 ret);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700323err_vdd:
Mayank Rana3cb43a32016-08-02 12:10:20 -0700324 dev_dbg(qphy->phy.dev, "QUSB PHY's regulators are turned OFF.\n");
Hemant Kumar164cc1b2017-04-27 19:39:58 -0700325
326 /* in case of error in turning on regulators */
327 if (qphy->power_enabled_ref)
328 qphy->power_enabled_ref--;
329done:
330 mutex_unlock(&qphy->lock);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700331 return ret;
332}
333
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700334static void qusb_phy_get_tune1_param(struct qusb_phy *qphy)
Mayank Rana3cb43a32016-08-02 12:10:20 -0700335{
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700336 u8 reg;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700337 u32 bit_mask = 1;
338
339 pr_debug("%s(): num_of_bits:%d bit_pos:%d\n", __func__,
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700340 qphy->efuse_num_of_bits,
341 qphy->efuse_bit_pos);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700342
343 /* get bit mask based on number of bits to use with efuse reg */
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700344 bit_mask = (bit_mask << qphy->efuse_num_of_bits) - 1;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700345
346 /*
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700347 * if efuse reg is updated (i.e non-zero) then use it to program
348 * tune parameters
Mayank Rana3cb43a32016-08-02 12:10:20 -0700349 */
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700350 qphy->tune_val = readl_relaxed(qphy->efuse_reg);
351 pr_debug("%s(): bit_mask:%d efuse based tune1 value:%d\n",
352 __func__, bit_mask, qphy->tune_val);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700353
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700354 qphy->tune_val = TUNE_VAL_MASK(qphy->tune_val,
355 qphy->efuse_bit_pos, bit_mask);
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700356 reg = readb_relaxed(qphy->base + qphy->phy_reg[PORT_TUNE1]);
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700357 if (qphy->tune_val) {
358 reg = reg & 0x0f;
359 reg |= (qphy->tune_val << 4);
360 }
Mayank Rana3cb43a32016-08-02 12:10:20 -0700361
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700362 qphy->tune_val = reg;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700363}
364
365static void qusb_phy_write_seq(void __iomem *base, u32 *seq, int cnt,
366 unsigned long delay)
367{
368 int i;
369
370 pr_debug("Seq count:%d\n", cnt);
371 for (i = 0; i < cnt; i = i+2) {
372 pr_debug("write 0x%02x to 0x%02x\n", seq[i], seq[i+1]);
373 writel_relaxed(seq[i], base + seq[i+1]);
374 if (delay)
375 usleep_range(delay, (delay + 2000));
376 }
377}
378
Mayank Ranab7f212e2017-04-06 17:54:35 -0700379static void qusb_phy_reset(struct qusb_phy *qphy)
380{
381 int ret;
382
383 ret = reset_control_assert(qphy->phy_reset);
384 if (ret)
385 dev_err(qphy->phy.dev, "%s: phy_reset assert failed\n",
386 __func__);
387 usleep_range(100, 150);
388
389 ret = reset_control_deassert(qphy->phy_reset);
390 if (ret)
391 dev_err(qphy->phy.dev, "%s: phy_reset deassert failed\n",
392 __func__);
393}
394
Mayank Rana3cb43a32016-08-02 12:10:20 -0700395static void qusb_phy_host_init(struct usb_phy *phy)
396{
397 u8 reg;
398 struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy);
399
400 dev_dbg(phy->dev, "%s\n", __func__);
401
Mayank Ranab7f212e2017-04-06 17:54:35 -0700402 qusb_phy_reset(qphy);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700403 qusb_phy_write_seq(qphy->base, qphy->qusb_phy_host_init_seq,
404 qphy->host_init_seq_len, 0);
405
406 /* Ensure above write is completed before turning ON ref clk */
407 wmb();
408
409 /* Require to get phy pll lock successfully */
410 usleep_range(150, 160);
411
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700412 reg = readb_relaxed(qphy->base + qphy->phy_reg[PLL_COMMON_STATUS_ONE]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700413 dev_dbg(phy->dev, "QUSB2PHY_PLL_COMMON_STATUS_ONE:%x\n", reg);
414 if (!(reg & CORE_READY_STATUS)) {
415 dev_err(phy->dev, "QUSB PHY PLL LOCK fails:%x\n", reg);
416 WARN_ON(1);
417 }
418}
419
420static int qusb_phy_init(struct usb_phy *phy)
421{
422 struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy);
Mayank Rana76a040f2017-11-20 14:10:37 -0800423 int ret, p_index;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700424 u8 reg;
425
426 dev_dbg(phy->dev, "%s\n", __func__);
427
Hemant Kumar7dc63722017-04-27 17:51:11 -0700428 ret = qusb_phy_enable_power(qphy, true);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700429 if (ret)
430 return ret;
431
432 qusb_phy_enable_clocks(qphy, true);
433
Mayank Ranab7f212e2017-04-06 17:54:35 -0700434 qusb_phy_reset(qphy);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700435 if (qphy->emulation) {
436 if (qphy->emu_init_seq)
Mayank Rana147f41d2016-08-12 10:07:45 -0700437 qusb_phy_write_seq(qphy->emu_phy_base + 0x8000,
438 qphy->emu_init_seq,
439 qphy->emu_init_seq_len, 10000);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700440
441 if (qphy->qusb_phy_init_seq)
442 qusb_phy_write_seq(qphy->base, qphy->qusb_phy_init_seq,
443 qphy->init_seq_len, 0);
444
445 /* Wait for 5ms as per QUSB2 RUMI sequence */
446 usleep_range(5000, 7000);
447
448 if (qphy->phy_pll_reset_seq)
449 qusb_phy_write_seq(qphy->base, qphy->phy_pll_reset_seq,
450 qphy->phy_pll_reset_seq_len, 10000);
451
452 if (qphy->emu_dcm_reset_seq)
453 qusb_phy_write_seq(qphy->emu_phy_base,
454 qphy->emu_dcm_reset_seq,
455 qphy->emu_dcm_reset_seq_len, 10000);
456
457 return 0;
458 }
459
460 /* Disable the PHY */
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700461 writel_relaxed(readl_relaxed(qphy->base + qphy->phy_reg[PWR_CTRL1]) |
Mayank Rana3cb43a32016-08-02 12:10:20 -0700462 PWR_CTRL1_POWR_DOWN,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700463 qphy->base + qphy->phy_reg[PWR_CTRL1]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700464
465 if (qphy->qusb_phy_init_seq)
466 qusb_phy_write_seq(qphy->base, qphy->qusb_phy_init_seq,
467 qphy->init_seq_len, 0);
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700468 if (qphy->efuse_reg) {
469 if (!qphy->tune_val)
470 qusb_phy_get_tune1_param(qphy);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700471
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700472 pr_debug("%s(): Programming TUNE1 parameter as:%x\n", __func__,
473 qphy->tune_val);
474 writel_relaxed(qphy->tune_val,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700475 qphy->base + qphy->phy_reg[PORT_TUNE1]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700476 }
477
Mayank Rana76a040f2017-11-20 14:10:37 -0800478 /* if debugfs based tunex params are set, use that value. */
479 for (p_index = 0; p_index < 5; p_index++) {
480 if (qphy->tune[p_index])
481 writel_relaxed(qphy->tune[p_index],
482 qphy->base + qphy->phy_reg[PORT_TUNE1] +
483 (4 * p_index));
Mayank Rana3cb43a32016-08-02 12:10:20 -0700484 }
485
Mayank Rana547e24c2017-11-01 15:47:04 -0700486 if (qphy->refgen_north_bg_reg)
487 if (readl_relaxed(qphy->refgen_north_bg_reg) & BANDGAP_BYPASS)
488 writel_relaxed(BIAS_CTRL_2_OVERRIDE_VAL,
489 qphy->base + qphy->phy_reg[BIAS_CTRL_2]);
490
Mayank Rana3cb43a32016-08-02 12:10:20 -0700491 /* ensure above writes are completed before re-enabling PHY */
492 wmb();
493
494 /* Enable the PHY */
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700495 writel_relaxed(readl_relaxed(qphy->base + qphy->phy_reg[PWR_CTRL1]) &
Mayank Rana3cb43a32016-08-02 12:10:20 -0700496 ~PWR_CTRL1_POWR_DOWN,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700497 qphy->base + qphy->phy_reg[PWR_CTRL1]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700498
499 /* Ensure above write is completed before turning ON ref clk */
500 wmb();
501
502 /* Require to get phy pll lock successfully */
503 usleep_range(150, 160);
504
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700505 reg = readb_relaxed(qphy->base + qphy->phy_reg[PLL_COMMON_STATUS_ONE]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700506 dev_dbg(phy->dev, "QUSB2PHY_PLL_COMMON_STATUS_ONE:%x\n", reg);
507 if (!(reg & CORE_READY_STATUS)) {
508 dev_err(phy->dev, "QUSB PHY PLL LOCK fails:%x\n", reg);
509 WARN_ON(1);
510 }
511 return 0;
512}
513
514static void qusb_phy_shutdown(struct usb_phy *phy)
515{
516 struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy);
517
518 dev_dbg(phy->dev, "%s\n", __func__);
519
Vamsi Krishna Samavedam246d8442017-10-17 21:15:55 -0700520 qusb_phy_enable_power(qphy, false);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700521
Mayank Rana3cb43a32016-08-02 12:10:20 -0700522}
523
524static u32 qusb_phy_get_linestate(struct qusb_phy *qphy)
525{
526 u32 linestate = 0;
527
528 if (qphy->cable_connected) {
529 if (qphy->phy.flags & PHY_HSFS_MODE)
530 linestate |= LINESTATE_DP;
531 else if (qphy->phy.flags & PHY_LS_MODE)
532 linestate |= LINESTATE_DM;
533 }
534 return linestate;
535}
536
537/**
538 * Performs QUSB2 PHY suspend/resume functionality.
539 *
540 * @uphy - usb phy pointer.
541 * @suspend - to enable suspend or not. 1 - suspend, 0 - resume
542 *
543 */
544static int qusb_phy_set_suspend(struct usb_phy *phy, int suspend)
545{
546 struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy);
547 u32 linestate = 0, intr_mask = 0;
548
549 if (qphy->suspended && suspend) {
550 dev_dbg(phy->dev, "%s: USB PHY is already suspended\n",
551 __func__);
552 return 0;
553 }
554
555 if (suspend) {
556 /* Bus suspend case */
557 if (qphy->cable_connected ||
558 (qphy->phy.flags & PHY_HOST_MODE)) {
559 /* Disable all interrupts */
560 writel_relaxed(0x00,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700561 qphy->base + qphy->phy_reg[INTR_CTRL]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700562
563 linestate = qusb_phy_get_linestate(qphy);
564 /*
565 * D+/D- interrupts are level-triggered, but we are
566 * only interested if the line state changes, so enable
567 * the high/low trigger based on current state. In
568 * other words, enable the triggers _opposite_ of what
569 * the current D+/D- levels are.
570 * e.g. if currently D+ high, D- low (HS 'J'/Suspend),
571 * configure the mask to trigger on D+ low OR D- high
572 */
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700573 intr_mask = DPSE_INTR_EN | DMSE_INTR_EN;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700574 if (!(linestate & LINESTATE_DP)) /* D+ low */
575 intr_mask |= DPSE_INTR_HIGH_SEL;
576 if (!(linestate & LINESTATE_DM)) /* D- low */
577 intr_mask |= DMSE_INTR_HIGH_SEL;
578
579 writel_relaxed(intr_mask,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700580 qphy->base + qphy->phy_reg[INTR_CTRL]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700581
Mayank Ranab7f212e2017-04-06 17:54:35 -0700582 /* hold core PLL into reset */
583 writel_relaxed(CORE_PLL_EN_FROM_RESET |
584 CORE_RESET | CORE_RESET_MUX,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700585 qphy->base +
586 qphy->phy_reg[PLL_CORE_INPUT_OVERRIDE]);
Mayank Ranab7f212e2017-04-06 17:54:35 -0700587
Vijayavardhan Vennapusa46a01442017-07-06 10:52:30 +0530588 if (linestate & (LINESTATE_DP | LINESTATE_DM)) {
589 /* enable phy auto-resume */
590 writel_relaxed(0x91,
591 qphy->base + qphy->phy_reg[TEST1]);
592 /* flush the previous write before next write */
593 wmb();
594 writel_relaxed(0x90,
595 qphy->base + qphy->phy_reg[TEST1]);
596 }
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700597
Mayank Rana3cb43a32016-08-02 12:10:20 -0700598 dev_dbg(phy->dev, "%s: intr_mask = %x\n",
599 __func__, intr_mask);
600
601 /* Makes sure that above write goes through */
602 wmb();
603 qusb_phy_enable_clocks(qphy, false);
604 } else { /* Cable disconnect case */
605 /* Disable all interrupts */
606 writel_relaxed(0x00,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700607 qphy->base + qphy->phy_reg[INTR_CTRL]);
Mayank Ranab7f212e2017-04-06 17:54:35 -0700608 qusb_phy_reset(qphy);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700609 qusb_phy_enable_clocks(qphy, false);
Hemant Kumar7dc63722017-04-27 17:51:11 -0700610 qusb_phy_enable_power(qphy, false);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700611 }
612 qphy->suspended = true;
613 } else {
614 /* Bus resume case */
615 if (qphy->cable_connected ||
616 (qphy->phy.flags & PHY_HOST_MODE)) {
617 qusb_phy_enable_clocks(qphy, true);
618 /* Clear all interrupts on resume */
619 writel_relaxed(0x00,
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700620 qphy->base + qphy->phy_reg[INTR_CTRL]);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700621
Mayank Ranab7f212e2017-04-06 17:54:35 -0700622 /* bring core PLL out of reset */
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700623 writel_relaxed(CORE_PLL_EN_FROM_RESET, qphy->base +
624 qphy->phy_reg[PLL_CORE_INPUT_OVERRIDE]);
Mayank Ranab7f212e2017-04-06 17:54:35 -0700625
Mayank Rana3cb43a32016-08-02 12:10:20 -0700626 /* Makes sure that above write goes through */
627 wmb();
628 } else { /* Cable connect case */
Mayank Rana3cb43a32016-08-02 12:10:20 -0700629 qusb_phy_enable_clocks(qphy, true);
630 }
631 qphy->suspended = false;
632 }
633
634 return 0;
635}
636
637static int qusb_phy_notify_connect(struct usb_phy *phy,
638 enum usb_device_speed speed)
639{
640 struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy);
641
642 qphy->cable_connected = true;
643
644 if (qphy->qusb_phy_host_init_seq && qphy->phy.flags & PHY_HOST_MODE)
645 qusb_phy_host_init(phy);
646
647 dev_dbg(phy->dev, "QUSB PHY: connect notification cable_connected=%d\n",
648 qphy->cable_connected);
649 return 0;
650}
651
652static int qusb_phy_notify_disconnect(struct usb_phy *phy,
653 enum usb_device_speed speed)
654{
655 struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy);
656
657 qphy->cable_connected = false;
658
659 dev_dbg(phy->dev, "QUSB PHY: connect notification cable_connected=%d\n",
660 qphy->cable_connected);
661 return 0;
662}
663
Hemant Kumar91f5e542017-11-20 16:25:46 -0800664static int qusb_phy_disable_chirp(struct usb_phy *phy, bool disable)
665{
666 struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy);
667 int ret = 0;
668
669 dev_dbg(phy->dev, "%s qphy chirp disable %d disable %d\n", __func__,
670 qphy->chirp_disable, disable);
671
672 mutex_lock(&qphy->lock);
673
674 if (qphy->chirp_disable == disable) {
675 ret = -EALREADY;
676 goto done;
677 }
678
679 qphy->chirp_disable = disable;
680
681 if (disable) {
682 qphy->sq_ctrl1_default =
683 readl_relaxed(qphy->base + qphy->phy_reg[SQ_CTRL1]);
684 qphy->sq_ctrl2_default =
685 readl_relaxed(qphy->base + qphy->phy_reg[SQ_CTRL2]);
686
687 writel_relaxed(SQ_CTRL1_CHIRP_DISABLE,
688 qphy->base + qphy->phy_reg[SQ_CTRL1]);
689 readl_relaxed(qphy->base + qphy->phy_reg[SQ_CTRL1]);
690
691 writel_relaxed(SQ_CTRL1_CHIRP_DISABLE,
692 qphy->base + qphy->phy_reg[SQ_CTRL2]);
693 readl_relaxed(qphy->base + qphy->phy_reg[SQ_CTRL2]);
694
695 goto done;
696 }
697
698 writel_relaxed(qphy->sq_ctrl1_default,
699 qphy->base + qphy->phy_reg[SQ_CTRL1]);
700 readl_relaxed(qphy->base + qphy->phy_reg[SQ_CTRL1]);
701
702 writel_relaxed(qphy->sq_ctrl2_default,
703 qphy->base + qphy->phy_reg[SQ_CTRL2]);
704 readl_relaxed(qphy->base + qphy->phy_reg[SQ_CTRL2]);
705done:
706 mutex_unlock(&qphy->lock);
707 return ret;
708}
709
Mayank Rana3cb43a32016-08-02 12:10:20 -0700710static int qusb_phy_dpdm_regulator_enable(struct regulator_dev *rdev)
711{
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700712 int ret = 0;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700713 struct qusb_phy *qphy = rdev_get_drvdata(rdev);
714
Mayank Ranadadae592017-07-21 09:03:32 -0700715 dev_dbg(qphy->phy.dev, "%s dpdm_enable:%d\n",
716 __func__, qphy->dpdm_enable);
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700717
Mayank Ranadadae592017-07-21 09:03:32 -0700718 if (!qphy->dpdm_enable) {
Hemant Kumar7dc63722017-04-27 17:51:11 -0700719 ret = qusb_phy_enable_power(qphy, true);
Mayank Ranadadae592017-07-21 09:03:32 -0700720 if (ret < 0) {
721 dev_dbg(qphy->phy.dev,
722 "dpdm regulator enable failed:%d\n", ret);
723 return ret;
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700724 }
Mayank Ranadadae592017-07-21 09:03:32 -0700725 qphy->dpdm_enable = true;
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700726 }
727
728 return ret;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700729}
730
731static int qusb_phy_dpdm_regulator_disable(struct regulator_dev *rdev)
732{
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700733 int ret = 0;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700734 struct qusb_phy *qphy = rdev_get_drvdata(rdev);
735
Mayank Ranadadae592017-07-21 09:03:32 -0700736 dev_dbg(qphy->phy.dev, "%s dpdm_enable:%d\n",
737 __func__, qphy->dpdm_enable);
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700738
Mayank Ranadadae592017-07-21 09:03:32 -0700739 if (qphy->dpdm_enable) {
Hemant Kumar7dc63722017-04-27 17:51:11 -0700740 ret = qusb_phy_enable_power(qphy, false);
Mayank Ranadadae592017-07-21 09:03:32 -0700741 if (ret < 0) {
742 dev_dbg(qphy->phy.dev,
743 "dpdm regulator disable failed:%d\n", ret);
744 return ret;
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700745 }
Mayank Ranadadae592017-07-21 09:03:32 -0700746 qphy->dpdm_enable = false;
Mayank Ranaa69fe6c2016-08-09 18:04:58 -0700747 }
748
749 return ret;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700750}
751
752static int qusb_phy_dpdm_regulator_is_enabled(struct regulator_dev *rdev)
753{
754 struct qusb_phy *qphy = rdev_get_drvdata(rdev);
755
Mayank Ranadadae592017-07-21 09:03:32 -0700756 dev_dbg(qphy->phy.dev, "%s qphy->dpdm_enable = %d\n", __func__,
757 qphy->dpdm_enable);
758 return qphy->dpdm_enable;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700759}
760
761static struct regulator_ops qusb_phy_dpdm_regulator_ops = {
762 .enable = qusb_phy_dpdm_regulator_enable,
763 .disable = qusb_phy_dpdm_regulator_disable,
764 .is_enabled = qusb_phy_dpdm_regulator_is_enabled,
765};
766
767static int qusb_phy_regulator_init(struct qusb_phy *qphy)
768{
769 struct device *dev = qphy->phy.dev;
770 struct regulator_config cfg = {};
771 struct regulator_init_data *init_data;
772
773 init_data = devm_kzalloc(dev, sizeof(*init_data), GFP_KERNEL);
774 if (!init_data)
775 return -ENOMEM;
776
777 init_data->constraints.valid_ops_mask |= REGULATOR_CHANGE_STATUS;
778 qphy->dpdm_rdesc.owner = THIS_MODULE;
779 qphy->dpdm_rdesc.type = REGULATOR_VOLTAGE;
780 qphy->dpdm_rdesc.ops = &qusb_phy_dpdm_regulator_ops;
781 qphy->dpdm_rdesc.name = kbasename(dev->of_node->full_name);
782
783 cfg.dev = dev;
784 cfg.init_data = init_data;
785 cfg.driver_data = qphy;
786 cfg.of_node = dev->of_node;
787
788 qphy->dpdm_rdev = devm_regulator_register(dev, &qphy->dpdm_rdesc, &cfg);
789 if (IS_ERR(qphy->dpdm_rdev))
790 return PTR_ERR(qphy->dpdm_rdev);
791
792 return 0;
793}
794
Mayank Rana76a040f2017-11-20 14:10:37 -0800795static int qusb_phy_create_debugfs(struct qusb_phy *qphy)
796{
797 struct dentry *file;
798 int ret = 0, i;
799 char name[6];
800
801 qphy->root = debugfs_create_dir(dev_name(qphy->phy.dev), NULL);
802 if (IS_ERR_OR_NULL(qphy->root)) {
803 dev_err(qphy->phy.dev,
804 "can't create debugfs root for %s\n",
805 dev_name(qphy->phy.dev));
806 ret = -ENOMEM;
807 goto create_err;
808 }
809
810 for (i = 0; i < 5; i++) {
811 snprintf(name, sizeof(name), "tune%d", (i + 1));
812 file = debugfs_create_x8(name, 0644, qphy->root,
813 &qphy->tune[i]);
814 if (IS_ERR_OR_NULL(file)) {
815 dev_err(qphy->phy.dev,
816 "can't create debugfs entry for %s\n", name);
817 debugfs_remove_recursive(qphy->root);
818 ret = ENOMEM;
819 goto create_err;
820 }
821 }
822
823create_err:
824 return ret;
825}
826
Mayank Rana3cb43a32016-08-02 12:10:20 -0700827static int qusb_phy_probe(struct platform_device *pdev)
828{
829 struct qusb_phy *qphy;
830 struct device *dev = &pdev->dev;
831 struct resource *res;
832 int ret = 0, size = 0;
833
834 qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL);
835 if (!qphy)
836 return -ENOMEM;
837
838 qphy->phy.dev = dev;
839 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
840 "qusb_phy_base");
841 qphy->base = devm_ioremap_resource(dev, res);
842 if (IS_ERR(qphy->base))
843 return PTR_ERR(qphy->base);
844
845 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
846 "emu_phy_base");
847 if (res) {
848 qphy->emu_phy_base = devm_ioremap_resource(dev, res);
849 if (IS_ERR(qphy->emu_phy_base)) {
850 dev_dbg(dev, "couldn't ioremap emu_phy_base\n");
851 qphy->emu_phy_base = NULL;
852 }
853 }
854
855 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700856 "efuse_addr");
Mayank Rana3cb43a32016-08-02 12:10:20 -0700857 if (res) {
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700858 qphy->efuse_reg = devm_ioremap_nocache(dev, res->start,
Mayank Rana3cb43a32016-08-02 12:10:20 -0700859 resource_size(res));
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700860 if (!IS_ERR_OR_NULL(qphy->efuse_reg)) {
Mayank Rana3cb43a32016-08-02 12:10:20 -0700861 ret = of_property_read_u32(dev->of_node,
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700862 "qcom,efuse-bit-pos",
863 &qphy->efuse_bit_pos);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700864 if (!ret) {
865 ret = of_property_read_u32(dev->of_node,
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700866 "qcom,efuse-num-bits",
867 &qphy->efuse_num_of_bits);
Mayank Rana3cb43a32016-08-02 12:10:20 -0700868 }
869
870 if (ret) {
871 dev_err(dev,
Vamsi Krishna Samavedamf4da1dc2016-08-25 13:57:21 -0700872 "DT Value for efuse is invalid.\n");
Mayank Rana3cb43a32016-08-02 12:10:20 -0700873 return -EINVAL;
874 }
875 }
876 }
877
Mayank Rana547e24c2017-11-01 15:47:04 -0700878 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
879 "refgen_north_bg_reg_addr");
880 if (res)
881 qphy->refgen_north_bg_reg = devm_ioremap(dev, res->start,
882 resource_size(res));
883
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700884 /* ref_clk_src is needed irrespective of SE_CLK or DIFF_CLK usage */
Mayank Rana3cb43a32016-08-02 12:10:20 -0700885 qphy->ref_clk_src = devm_clk_get(dev, "ref_clk_src");
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700886 if (IS_ERR(qphy->ref_clk_src)) {
Mayank Rana3cb43a32016-08-02 12:10:20 -0700887 dev_dbg(dev, "clk get failed for ref_clk_src\n");
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700888 ret = PTR_ERR(qphy->ref_clk_src);
889 return ret;
890 }
Mayank Rana3cb43a32016-08-02 12:10:20 -0700891
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700892 /* ref_clk is needed only for DIFF_CLK case, hence make it optional. */
893 if (of_property_match_string(pdev->dev.of_node,
894 "clock-names", "ref_clk") >= 0) {
895 qphy->ref_clk = devm_clk_get(dev, "ref_clk");
896 if (IS_ERR(qphy->ref_clk)) {
897 ret = PTR_ERR(qphy->ref_clk);
898 if (ret != -EPROBE_DEFER)
899 dev_dbg(dev,
900 "clk get failed for ref_clk\n");
901 return ret;
902 }
903
Mayank Rana3cb43a32016-08-02 12:10:20 -0700904 clk_set_rate(qphy->ref_clk, 19200000);
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -0700905 }
Mayank Rana3cb43a32016-08-02 12:10:20 -0700906
907 if (of_property_match_string(pdev->dev.of_node,
908 "clock-names", "cfg_ahb_clk") >= 0) {
909 qphy->cfg_ahb_clk = devm_clk_get(dev, "cfg_ahb_clk");
910 if (IS_ERR(qphy->cfg_ahb_clk)) {
911 ret = PTR_ERR(qphy->cfg_ahb_clk);
912 if (ret != -EPROBE_DEFER)
913 dev_err(dev,
914 "clk get failed for cfg_ahb_clk ret %d\n", ret);
915 return ret;
916 }
917 }
918
Amit Nischal4d278212016-06-06 17:54:34 +0530919 qphy->phy_reset = devm_reset_control_get(dev, "phy_reset");
Mayank Rana3cb43a32016-08-02 12:10:20 -0700920 if (IS_ERR(qphy->phy_reset))
921 return PTR_ERR(qphy->phy_reset);
922
923 qphy->emulation = of_property_read_bool(dev->of_node,
924 "qcom,emulation");
925
926 of_get_property(dev->of_node, "qcom,emu-init-seq", &size);
927 if (size) {
928 qphy->emu_init_seq = devm_kzalloc(dev,
929 size, GFP_KERNEL);
930 if (qphy->emu_init_seq) {
931 qphy->emu_init_seq_len =
932 (size / sizeof(*qphy->emu_init_seq));
933 if (qphy->emu_init_seq_len % 2) {
934 dev_err(dev, "invalid emu_init_seq_len\n");
935 return -EINVAL;
936 }
937
938 of_property_read_u32_array(dev->of_node,
Mayank Rana147f41d2016-08-12 10:07:45 -0700939 "qcom,emu-init-seq",
Mayank Rana3cb43a32016-08-02 12:10:20 -0700940 qphy->emu_init_seq,
941 qphy->emu_init_seq_len);
942 } else {
943 dev_dbg(dev,
944 "error allocating memory for emu_init_seq\n");
945 }
946 }
947
Mayank Rana147f41d2016-08-12 10:07:45 -0700948 size = 0;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700949 of_get_property(dev->of_node, "qcom,phy-pll-reset-seq", &size);
950 if (size) {
951 qphy->phy_pll_reset_seq = devm_kzalloc(dev,
952 size, GFP_KERNEL);
953 if (qphy->phy_pll_reset_seq) {
954 qphy->phy_pll_reset_seq_len =
955 (size / sizeof(*qphy->phy_pll_reset_seq));
956 if (qphy->phy_pll_reset_seq_len % 2) {
957 dev_err(dev, "invalid phy_pll_reset_seq_len\n");
958 return -EINVAL;
959 }
960
961 of_property_read_u32_array(dev->of_node,
962 "qcom,phy-pll-reset-seq",
963 qphy->phy_pll_reset_seq,
964 qphy->phy_pll_reset_seq_len);
965 } else {
966 dev_dbg(dev,
967 "error allocating memory for phy_pll_reset_seq\n");
968 }
969 }
970
Mayank Rana147f41d2016-08-12 10:07:45 -0700971 size = 0;
Mayank Rana3cb43a32016-08-02 12:10:20 -0700972 of_get_property(dev->of_node, "qcom,emu-dcm-reset-seq", &size);
973 if (size) {
974 qphy->emu_dcm_reset_seq = devm_kzalloc(dev,
975 size, GFP_KERNEL);
976 if (qphy->emu_dcm_reset_seq) {
977 qphy->emu_dcm_reset_seq_len =
978 (size / sizeof(*qphy->emu_dcm_reset_seq));
979 if (qphy->emu_dcm_reset_seq_len % 2) {
980 dev_err(dev, "invalid emu_dcm_reset_seq_len\n");
981 return -EINVAL;
982 }
983
984 of_property_read_u32_array(dev->of_node,
985 "qcom,emu-dcm-reset-seq",
986 qphy->emu_dcm_reset_seq,
987 qphy->emu_dcm_reset_seq_len);
988 } else {
989 dev_dbg(dev,
990 "error allocating memory for emu_dcm_reset_seq\n");
991 }
992 }
993
Mayank Rana147f41d2016-08-12 10:07:45 -0700994 size = 0;
Mayank Rana9c6b12d2017-06-22 16:23:26 -0700995 of_get_property(dev->of_node, "qcom,qusb-phy-reg-offset", &size);
996 if (size) {
997 qphy->phy_reg = devm_kzalloc(dev, size, GFP_KERNEL);
998 if (qphy->phy_reg) {
999 qphy->qusb_phy_reg_offset_cnt =
1000 size / sizeof(*qphy->phy_reg);
Mayank Rana129111e2017-11-01 15:31:22 -07001001 if (qphy->qusb_phy_reg_offset_cnt != USB2_PHY_REG_MAX) {
Mayank Rana9c6b12d2017-06-22 16:23:26 -07001002 dev_err(dev, "invalid reg offset count\n");
1003 return -EINVAL;
1004 }
1005
1006 of_property_read_u32_array(dev->of_node,
1007 "qcom,qusb-phy-reg-offset",
1008 qphy->phy_reg,
1009 qphy->qusb_phy_reg_offset_cnt);
1010 } else {
1011 dev_err(dev, "err mem alloc for qusb_phy_reg_offset\n");
1012 return -ENOMEM;
1013 }
1014 } else {
1015 dev_err(dev, "err provide qcom,qmp-phy-reg-offset\n");
1016 return -EINVAL;
1017 }
1018
1019 size = 0;
Mayank Rana3cb43a32016-08-02 12:10:20 -07001020 of_get_property(dev->of_node, "qcom,qusb-phy-init-seq", &size);
1021 if (size) {
1022 qphy->qusb_phy_init_seq = devm_kzalloc(dev,
1023 size, GFP_KERNEL);
1024 if (qphy->qusb_phy_init_seq) {
1025 qphy->init_seq_len =
1026 (size / sizeof(*qphy->qusb_phy_init_seq));
1027 if (qphy->init_seq_len % 2) {
1028 dev_err(dev, "invalid init_seq_len\n");
1029 return -EINVAL;
1030 }
1031
1032 of_property_read_u32_array(dev->of_node,
1033 "qcom,qusb-phy-init-seq",
1034 qphy->qusb_phy_init_seq,
1035 qphy->init_seq_len);
1036 } else {
1037 dev_err(dev,
1038 "error allocating memory for phy_init_seq\n");
1039 }
1040 }
1041
1042 qphy->host_init_seq_len = of_property_count_elems_of_size(dev->of_node,
1043 "qcom,qusb-phy-host-init-seq",
1044 sizeof(*qphy->qusb_phy_host_init_seq));
1045 if (qphy->host_init_seq_len > 0) {
1046 qphy->qusb_phy_host_init_seq = devm_kcalloc(dev,
1047 qphy->host_init_seq_len,
1048 sizeof(*qphy->qusb_phy_host_init_seq),
1049 GFP_KERNEL);
1050 if (qphy->qusb_phy_host_init_seq)
1051 of_property_read_u32_array(dev->of_node,
1052 "qcom,qusb-phy-host-init-seq",
1053 qphy->qusb_phy_host_init_seq,
1054 qphy->host_init_seq_len);
1055 else
1056 return -ENOMEM;
1057 }
1058
1059 ret = of_property_read_u32_array(dev->of_node, "qcom,vdd-voltage-level",
1060 (u32 *) qphy->vdd_levels,
1061 ARRAY_SIZE(qphy->vdd_levels));
1062 if (ret) {
1063 dev_err(dev, "error reading qcom,vdd-voltage-level property\n");
1064 return ret;
1065 }
1066
1067 qphy->vdd = devm_regulator_get(dev, "vdd");
1068 if (IS_ERR(qphy->vdd)) {
1069 dev_err(dev, "unable to get vdd supply\n");
1070 return PTR_ERR(qphy->vdd);
1071 }
1072
1073 qphy->vdda33 = devm_regulator_get(dev, "vdda33");
1074 if (IS_ERR(qphy->vdda33)) {
1075 dev_err(dev, "unable to get vdda33 supply\n");
1076 return PTR_ERR(qphy->vdda33);
1077 }
1078
1079 qphy->vdda18 = devm_regulator_get(dev, "vdda18");
1080 if (IS_ERR(qphy->vdda18)) {
1081 dev_err(dev, "unable to get vdda18 supply\n");
1082 return PTR_ERR(qphy->vdda18);
1083 }
1084
Hemant Kumar164cc1b2017-04-27 19:39:58 -07001085 mutex_init(&qphy->lock);
Mayank Rana3cb43a32016-08-02 12:10:20 -07001086 platform_set_drvdata(pdev, qphy);
1087
1088 qphy->phy.label = "msm-qusb-phy-v2";
1089 qphy->phy.init = qusb_phy_init;
1090 qphy->phy.set_suspend = qusb_phy_set_suspend;
1091 qphy->phy.shutdown = qusb_phy_shutdown;
1092 qphy->phy.type = USB_PHY_TYPE_USB2;
1093 qphy->phy.notify_connect = qusb_phy_notify_connect;
1094 qphy->phy.notify_disconnect = qusb_phy_notify_disconnect;
Hemant Kumar91f5e542017-11-20 16:25:46 -08001095 qphy->phy.disable_chirp = qusb_phy_disable_chirp;
Mayank Rana3cb43a32016-08-02 12:10:20 -07001096
1097 ret = usb_add_phy_dev(&qphy->phy);
1098 if (ret)
1099 return ret;
1100
1101 ret = qusb_phy_regulator_init(qphy);
1102 if (ret)
1103 usb_remove_phy(&qphy->phy);
1104
Mayank Rana76a040f2017-11-20 14:10:37 -08001105 qusb_phy_create_debugfs(qphy);
1106
Mayank Rana3cb43a32016-08-02 12:10:20 -07001107 return ret;
1108}
1109
1110static int qusb_phy_remove(struct platform_device *pdev)
1111{
1112 struct qusb_phy *qphy = platform_get_drvdata(pdev);
1113
1114 usb_remove_phy(&qphy->phy);
Devdutt Patnaik1c03dfd2017-03-19 23:38:43 -07001115 qusb_phy_enable_clocks(qphy, false);
Hemant Kumar7dc63722017-04-27 17:51:11 -07001116 qusb_phy_enable_power(qphy, false);
Mayank Rana76a040f2017-11-20 14:10:37 -08001117 debugfs_remove_recursive(qphy->root);
Mayank Rana3cb43a32016-08-02 12:10:20 -07001118
1119 return 0;
1120}
1121
1122static const struct of_device_id qusb_phy_id_table[] = {
1123 { .compatible = "qcom,qusb2phy-v2", },
1124 { },
1125};
1126MODULE_DEVICE_TABLE(of, qusb_phy_id_table);
1127
1128static struct platform_driver qusb_phy_driver = {
1129 .probe = qusb_phy_probe,
1130 .remove = qusb_phy_remove,
1131 .driver = {
1132 .name = "msm-qusb-phy-v2",
1133 .of_match_table = of_match_ptr(qusb_phy_id_table),
1134 },
1135};
1136
1137module_platform_driver(qusb_phy_driver);
1138
1139MODULE_DESCRIPTION("MSM QUSB2 PHY v2 driver");
1140MODULE_LICENSE("GPL v2");