blob: dd04f49ea2fa36a2221af2b9774e3bacb901ed45 [file] [log] [blame]
Manu Gautam91223e02011-11-08 15:27:22 +05301/* ehci-msm2.c - HSUSB Host Controller Driver Implementation
2 *
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +05303 * Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
Manu Gautam91223e02011-11-08 15:27:22 +05304 *
5 * Partly derived from ehci-fsl.c and ehci-hcd.c
6 * Copyright (c) 2000-2004 by David Brownell
7 * Copyright (c) 2005 MontaVista Software
8 *
9 * All source code in this file is licensed under the following license except
10 * where indicated.
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License version 2 as published
14 * by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 * See the GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, you can find it at http://www.fsf.org
23 */
24
25#include <linux/platform_device.h>
26#include <linux/clk.h>
27#include <linux/err.h>
Hemant Kumar153f9972013-06-19 16:49:45 -070028#include <linux/pm_wakeup.h>
Manu Gautam91223e02011-11-08 15:27:22 +053029#include <linux/pm_runtime.h>
30#include <linux/regulator/consumer.h>
Hemant Kumara7d531d2013-06-18 22:12:18 -070031#include <linux/gpio.h>
32#include <linux/of_gpio.h>
Hemant Kumar17011ce2013-06-10 17:40:08 -070033#include <linux/irq.h>
Manu Gautam91223e02011-11-08 15:27:22 +053034
35#include <linux/usb/ulpi.h>
36#include <linux/usb/msm_hsusb_hw.h>
37#include <linux/usb/msm_hsusb.h>
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +053038#include <linux/of.h>
Manu Gautam91223e02011-11-08 15:27:22 +053039#include <mach/clk.h>
Hemant Kumar8c0f2a82012-05-03 19:17:26 -070040#include <mach/msm_xo.h>
Manu Gautam91223e02011-11-08 15:27:22 +053041#include <mach/msm_iomap.h>
Rajkumar Raghupathyad8d68e2013-06-06 17:48:39 +053042#include <linux/debugfs.h>
Vijayavardhan Vennapusa916bcdb2013-08-16 13:25:11 +053043#include <mach/rpm-regulator.h>
Manu Gautam91223e02011-11-08 15:27:22 +053044
45#define MSM_USB_BASE (hcd->regs)
46
Hemant Kumar8c0f2a82012-05-03 19:17:26 -070047#define PDEV_NAME_LEN 20
48
Manu Gautam91223e02011-11-08 15:27:22 +053049struct msm_hcd {
50 struct ehci_hcd ehci;
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +053051 spinlock_t wakeup_lock;
Manu Gautam91223e02011-11-08 15:27:22 +053052 struct device *dev;
Vijayavardhan Vennapusa16fcaf92013-03-04 10:24:21 +053053 struct clk *xo_clk;
Manu Gautam91223e02011-11-08 15:27:22 +053054 struct clk *iface_clk;
55 struct clk *core_clk;
56 struct clk *alt_core_clk;
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +053057 struct clk *phy_sleep_clk;
Manu Gautam91223e02011-11-08 15:27:22 +053058 struct regulator *hsusb_vddcx;
59 struct regulator *hsusb_3p3;
60 struct regulator *hsusb_1p8;
61 struct regulator *vbus;
Hemant Kumar8c0f2a82012-05-03 19:17:26 -070062 struct msm_xo_voter *xo_handle;
Manu Gautam91223e02011-11-08 15:27:22 +053063 bool async_int;
Hemant Kumar56925352012-02-13 16:59:52 -080064 bool vbus_on;
Manu Gautam91223e02011-11-08 15:27:22 +053065 atomic_t in_lpm;
Vijayavardhan Vennapusa4fa13692012-08-02 14:35:03 +053066 int pmic_gpio_dp_irq;
67 bool pmic_gpio_dp_irq_enabled;
68 uint32_t pmic_gpio_int_cnt;
69 atomic_t pm_usage_cnt;
Hemant Kumar153f9972013-06-19 16:49:45 -070070 struct wakeup_source ws;
Chiranjeevi Velempatice169582012-08-25 14:15:41 +053071 struct work_struct phy_susp_fail_work;
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +053072 int async_irq;
73 bool async_irq_enabled;
74 uint32_t async_int_cnt;
Hemant Kumara7d531d2013-06-18 22:12:18 -070075 int resume_gpio;
Hemant Kumar17011ce2013-06-10 17:40:08 -070076
77 int wakeup_int_cnt;
78 bool wakeup_irq_enabled;
79 int wakeup_irq;
Vijayavardhan Vennapusa916bcdb2013-08-16 13:25:11 +053080 enum usb_vdd_type vdd_type;
Manu Gautam91223e02011-11-08 15:27:22 +053081};
82
83static inline struct msm_hcd *hcd_to_mhcd(struct usb_hcd *hcd)
84{
85 return (struct msm_hcd *) (hcd->hcd_priv);
86}
87
88static inline struct usb_hcd *mhcd_to_hcd(struct msm_hcd *mhcd)
89{
90 return container_of((void *) mhcd, struct usb_hcd, hcd_priv);
91}
92
93#define HSUSB_PHY_3P3_VOL_MIN 3050000 /* uV */
94#define HSUSB_PHY_3P3_VOL_MAX 3300000 /* uV */
95#define HSUSB_PHY_3P3_HPM_LOAD 50000 /* uA */
96
97#define HSUSB_PHY_1P8_VOL_MIN 1800000 /* uV */
98#define HSUSB_PHY_1P8_VOL_MAX 1800000 /* uV */
99#define HSUSB_PHY_1P8_HPM_LOAD 50000 /* uA */
100
Vijayavardhan Vennapusa916bcdb2013-08-16 13:25:11 +0530101#define HSUSB_PHY_VDD_DIG_VOL_NONE 0 /* uV */
Manu Gautam91223e02011-11-08 15:27:22 +0530102#define HSUSB_PHY_VDD_DIG_VOL_MIN 1045000 /* uV */
103#define HSUSB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
104#define HSUSB_PHY_VDD_DIG_LOAD 49360 /* uA */
105
Vijayavardhan Vennapusa916bcdb2013-08-16 13:25:11 +0530106#define HSUSB_PHY_SUSP_DIG_VOL_P50 500000
107#define HSUSB_PHY_SUSP_DIG_VOL_P75 750000
108enum hsusb_vdd_value {
109 VDD_MIN_NONE = 0,
110 VDD_MIN_P50,
111 VDD_MIN_P75,
112 VDD_MIN_OP,
113 VDD_MAX_OP,
114 VDD_VAL_MAX_OP,
115};
116
117static int hsusb_vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX_OP] = {
118 { /* VDD_CX CORNER Voting */
119 [VDD_MIN_NONE] = RPM_VREG_CORNER_NONE,
120 [VDD_MIN_P50] = RPM_VREG_CORNER_NONE,
121 [VDD_MIN_P75] = RPM_VREG_CORNER_NONE,
122 [VDD_MIN_OP] = RPM_VREG_CORNER_NOMINAL,
123 [VDD_MAX_OP] = RPM_VREG_CORNER_HIGH,
124 },
125 { /* VDD_CX Voltage Voting */
126 [VDD_MIN_NONE] = HSUSB_PHY_VDD_DIG_VOL_NONE,
127 [VDD_MIN_P50] = HSUSB_PHY_SUSP_DIG_VOL_P50,
128 [VDD_MIN_P75] = HSUSB_PHY_SUSP_DIG_VOL_P75,
129 [VDD_MIN_OP] = HSUSB_PHY_VDD_DIG_VOL_MIN,
130 [VDD_MAX_OP] = HSUSB_PHY_VDD_DIG_VOL_MAX,
131 },
132};
133
Manu Gautam91223e02011-11-08 15:27:22 +0530134static int msm_ehci_init_vddcx(struct msm_hcd *mhcd, int init)
135{
136 int ret = 0;
Vijayavardhan Vennapusa916bcdb2013-08-16 13:25:11 +0530137 int none_vol, min_vol, max_vol;
138 u32 tmp[5];
139 int len = 0;
Manu Gautam91223e02011-11-08 15:27:22 +0530140
Vijayavardhan Vennapusa916bcdb2013-08-16 13:25:11 +0530141 if (!init) {
142 none_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_NONE];
143 max_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MAX_OP];
Manu Gautam91223e02011-11-08 15:27:22 +0530144 goto disable_reg;
Manu Gautam91223e02011-11-08 15:27:22 +0530145 }
146
Vijayavardhan Vennapusa916bcdb2013-08-16 13:25:11 +0530147 mhcd->vdd_type = VDDCX_CORNER;
148 mhcd->hsusb_vddcx = devm_regulator_get(mhcd->dev, "hsusb_vdd_dig");
149 if (IS_ERR(mhcd->hsusb_vddcx)) {
150 mhcd->hsusb_vddcx = devm_regulator_get(mhcd->dev,
151 "HSUSB_VDDCX");
152 if (IS_ERR(mhcd->hsusb_vddcx)) {
153 dev_err(mhcd->dev, "unable to get ehci vddcx\n");
154 return PTR_ERR(mhcd->hsusb_vddcx);
155 }
156 mhcd->vdd_type = VDDCX;
157 }
158
159 if (mhcd->dev->of_node) {
160 of_get_property(mhcd->dev->of_node,
161 "qcom,vdd-voltage-level",
162 &len);
163 if (len == sizeof(tmp)) {
164 of_property_read_u32_array(mhcd->dev->of_node,
165 "qcom,vdd-voltage-level",
166 tmp, len/sizeof(*tmp));
167 hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_NONE] = tmp[0];
168 hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_P50] = tmp[1];
169 hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_P75] = tmp[2];
170 hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_OP] = tmp[3];
171 hsusb_vdd_val[mhcd->vdd_type][VDD_MAX_OP] = tmp[4];
172 } else {
173 dev_dbg(mhcd->dev, "Use default vdd config\n");
174 }
175 }
176
177 none_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_NONE];
178 min_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_OP];
179 max_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MAX_OP];
180
181 ret = regulator_set_voltage(mhcd->hsusb_vddcx, min_vol, max_vol);
Manu Gautam91223e02011-11-08 15:27:22 +0530182 if (ret) {
183 dev_err(mhcd->dev, "unable to set the voltage"
184 "for ehci vddcx\n");
Mayank Rana2f416c22012-03-24 05:23:25 +0530185 return ret;
Manu Gautam91223e02011-11-08 15:27:22 +0530186 }
187
188 ret = regulator_set_optimum_mode(mhcd->hsusb_vddcx,
189 HSUSB_PHY_VDD_DIG_LOAD);
190 if (ret < 0) {
191 dev_err(mhcd->dev, "%s: Unable to set optimum mode of the"
192 " regulator: VDDCX\n", __func__);
193 goto reg_optimum_mode_err;
194 }
195
196 ret = regulator_enable(mhcd->hsusb_vddcx);
197 if (ret) {
198 dev_err(mhcd->dev, "unable to enable ehci vddcx\n");
199 goto reg_enable_err;
200 }
201
202 return 0;
203
204disable_reg:
205 regulator_disable(mhcd->hsusb_vddcx);
206reg_enable_err:
207 regulator_set_optimum_mode(mhcd->hsusb_vddcx, 0);
208reg_optimum_mode_err:
Vijayavardhan Vennapusa916bcdb2013-08-16 13:25:11 +0530209 regulator_set_voltage(mhcd->hsusb_vddcx, none_vol, max_vol);
Manu Gautam91223e02011-11-08 15:27:22 +0530210 return ret;
211
212}
213
214static int msm_ehci_ldo_init(struct msm_hcd *mhcd, int init)
215{
216 int rc = 0;
217
218 if (!init)
219 goto put_1p8;
220
Mayank Rana2f416c22012-03-24 05:23:25 +0530221 mhcd->hsusb_3p3 = devm_regulator_get(mhcd->dev, "HSUSB_3p3");
Manu Gautam91223e02011-11-08 15:27:22 +0530222 if (IS_ERR(mhcd->hsusb_3p3)) {
223 dev_err(mhcd->dev, "unable to get hsusb 3p3\n");
224 return PTR_ERR(mhcd->hsusb_3p3);
225 }
226
227 rc = regulator_set_voltage(mhcd->hsusb_3p3,
228 HSUSB_PHY_3P3_VOL_MIN, HSUSB_PHY_3P3_VOL_MAX);
229 if (rc) {
230 dev_err(mhcd->dev, "unable to set voltage level for"
231 "hsusb 3p3\n");
Mayank Rana2f416c22012-03-24 05:23:25 +0530232 return rc;
Manu Gautam91223e02011-11-08 15:27:22 +0530233 }
Mayank Rana2f416c22012-03-24 05:23:25 +0530234 mhcd->hsusb_1p8 = devm_regulator_get(mhcd->dev, "HSUSB_1p8");
Manu Gautam91223e02011-11-08 15:27:22 +0530235 if (IS_ERR(mhcd->hsusb_1p8)) {
236 dev_err(mhcd->dev, "unable to get hsusb 1p8\n");
237 rc = PTR_ERR(mhcd->hsusb_1p8);
238 goto put_3p3_lpm;
239 }
240 rc = regulator_set_voltage(mhcd->hsusb_1p8,
241 HSUSB_PHY_1P8_VOL_MIN, HSUSB_PHY_1P8_VOL_MAX);
242 if (rc) {
243 dev_err(mhcd->dev, "unable to set voltage level for"
244 "hsusb 1p8\n");
245 goto put_1p8;
246 }
247
248 return 0;
249
250put_1p8:
251 regulator_set_voltage(mhcd->hsusb_1p8, 0, HSUSB_PHY_1P8_VOL_MAX);
Manu Gautam91223e02011-11-08 15:27:22 +0530252put_3p3_lpm:
253 regulator_set_voltage(mhcd->hsusb_3p3, 0, HSUSB_PHY_3P3_VOL_MAX);
Manu Gautam91223e02011-11-08 15:27:22 +0530254
255 return rc;
256}
257
258#ifdef CONFIG_PM_SLEEP
Manu Gautam91223e02011-11-08 15:27:22 +0530259static int msm_ehci_config_vddcx(struct msm_hcd *mhcd, int high)
260{
Hemant Kumar441356be2012-02-13 16:12:49 -0800261 struct msm_usb_host_platform_data *pdata;
Vijayavardhan Vennapusa916bcdb2013-08-16 13:25:11 +0530262 int max_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MAX_OP];
Manu Gautam91223e02011-11-08 15:27:22 +0530263 int min_vol;
264 int ret;
265
Hemant Kumar441356be2012-02-13 16:12:49 -0800266 pdata = mhcd->dev->platform_data;
267
Manu Gautam91223e02011-11-08 15:27:22 +0530268 if (high)
Vijayavardhan Vennapusa916bcdb2013-08-16 13:25:11 +0530269 min_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_OP];
Hemant Kumar441356be2012-02-13 16:12:49 -0800270 else if (pdata && pdata->dock_connect_irq &&
271 !irq_read_line(pdata->dock_connect_irq))
Vijayavardhan Vennapusa916bcdb2013-08-16 13:25:11 +0530272 min_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_P75];
Manu Gautam91223e02011-11-08 15:27:22 +0530273 else
Vijayavardhan Vennapusa916bcdb2013-08-16 13:25:11 +0530274 min_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_P50];
Manu Gautam91223e02011-11-08 15:27:22 +0530275
276 ret = regulator_set_voltage(mhcd->hsusb_vddcx, min_vol, max_vol);
277 if (ret) {
278 dev_err(mhcd->dev, "%s: unable to set the voltage of regulator"
279 " HSUSB_VDDCX\n", __func__);
280 return ret;
281 }
282
283 dev_dbg(mhcd->dev, "%s: min_vol:%d max_vol:%d\n", __func__, min_vol,
284 max_vol);
285
286 return ret;
287}
288#else
289static int msm_ehci_config_vddcx(struct msm_hcd *mhcd, int high)
290{
291 return 0;
292}
293#endif
294
Manu Gautam91223e02011-11-08 15:27:22 +0530295static void msm_ehci_vbus_power(struct msm_hcd *mhcd, bool on)
296{
297 int ret;
298
299 if (!mhcd->vbus) {
300 pr_err("vbus is NULL.");
301 return;
302 }
Hemant Kumar56925352012-02-13 16:59:52 -0800303
304 if (mhcd->vbus_on == on)
305 return;
306
Manu Gautam91223e02011-11-08 15:27:22 +0530307 if (on) {
308 ret = regulator_enable(mhcd->vbus);
309 if (ret) {
310 pr_err("unable to enable vbus\n");
311 return;
312 }
Hemant Kumar56925352012-02-13 16:59:52 -0800313 mhcd->vbus_on = true;
Manu Gautam91223e02011-11-08 15:27:22 +0530314 } else {
315 ret = regulator_disable(mhcd->vbus);
316 if (ret) {
317 pr_err("unable to disable vbus\n");
318 return;
319 }
Hemant Kumar56925352012-02-13 16:59:52 -0800320 mhcd->vbus_on = false;
Manu Gautam91223e02011-11-08 15:27:22 +0530321 }
322}
323
Hemant Kumar56925352012-02-13 16:59:52 -0800324static irqreturn_t msm_ehci_dock_connect_irq(int irq, void *data)
325{
326 const struct msm_usb_host_platform_data *pdata;
327 struct msm_hcd *mhcd = data;
328 struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
329
330 pdata = mhcd->dev->platform_data;
331
332 if (atomic_read(&mhcd->in_lpm))
333 usb_hcd_resume_root_hub(hcd);
334
335 if (irq_read_line(pdata->dock_connect_irq)) {
336 dev_dbg(mhcd->dev, "%s:Dock removed disable vbus\n", __func__);
337 msm_ehci_vbus_power(mhcd, 0);
338 } else {
339 dev_dbg(mhcd->dev, "%s:Dock connected enable vbus\n", __func__);
340 msm_ehci_vbus_power(mhcd, 1);
341 }
342
343 return IRQ_HANDLED;
344}
345
346static int msm_ehci_init_vbus(struct msm_hcd *mhcd, int init)
347{
348 int rc = 0;
349 struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
350 const struct msm_usb_host_platform_data *pdata;
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +0530351 int ret = 0;
Hemant Kumar56925352012-02-13 16:59:52 -0800352
353 pdata = mhcd->dev->platform_data;
354
355 if (!init) {
Hemant Kumar56925352012-02-13 16:59:52 -0800356 if (pdata && pdata->dock_connect_irq)
357 free_irq(pdata->dock_connect_irq, mhcd);
358 return rc;
359 }
360
Mayank Rana2f416c22012-03-24 05:23:25 +0530361 mhcd->vbus = devm_regulator_get(mhcd->dev, "vbus");
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +0530362 ret = PTR_ERR(mhcd->vbus);
363 if (ret == -EPROBE_DEFER) {
364 pr_debug("failed to get vbus handle, defer probe\n");
365 return ret;
366 } else if (IS_ERR(mhcd->vbus)) {
Hemant Kumar56925352012-02-13 16:59:52 -0800367 pr_err("Unable to get vbus\n");
368 return -ENODEV;
369 }
370
371 if (pdata) {
372 hcd->power_budget = pdata->power_budget;
373
374 if (pdata->dock_connect_irq) {
375 rc = request_threaded_irq(pdata->dock_connect_irq, NULL,
376 msm_ehci_dock_connect_irq,
377 IRQF_TRIGGER_FALLING |
378 IRQF_TRIGGER_RISING |
379 IRQF_ONESHOT, "msm_ehci_host", mhcd);
380 if (!rc)
381 enable_irq_wake(pdata->dock_connect_irq);
382 }
383 }
384 return rc;
385}
386
Manu Gautam91223e02011-11-08 15:27:22 +0530387static int msm_ehci_ldo_enable(struct msm_hcd *mhcd, int on)
388{
389 int ret = 0;
390
391 if (IS_ERR(mhcd->hsusb_1p8)) {
392 dev_err(mhcd->dev, "%s: HSUSB_1p8 is not initialized\n",
393 __func__);
394 return -ENODEV;
395 }
396
397 if (IS_ERR(mhcd->hsusb_3p3)) {
398 dev_err(mhcd->dev, "%s: HSUSB_3p3 is not initialized\n",
399 __func__);
400 return -ENODEV;
401 }
402
403 if (on) {
404 ret = regulator_set_optimum_mode(mhcd->hsusb_1p8,
405 HSUSB_PHY_1P8_HPM_LOAD);
406 if (ret < 0) {
407 dev_err(mhcd->dev, "%s: Unable to set HPM of the"
408 " regulator: HSUSB_1p8\n", __func__);
409 return ret;
410 }
411
412 ret = regulator_enable(mhcd->hsusb_1p8);
413 if (ret) {
414 dev_err(mhcd->dev, "%s: unable to enable the hsusb"
415 " 1p8\n", __func__);
416 regulator_set_optimum_mode(mhcd->hsusb_1p8, 0);
417 return ret;
418 }
419
420 ret = regulator_set_optimum_mode(mhcd->hsusb_3p3,
421 HSUSB_PHY_3P3_HPM_LOAD);
422 if (ret < 0) {
423 dev_err(mhcd->dev, "%s: Unable to set HPM of the "
424 "regulator: HSUSB_3p3\n", __func__);
425 regulator_set_optimum_mode(mhcd->hsusb_1p8, 0);
426 regulator_disable(mhcd->hsusb_1p8);
427 return ret;
428 }
429
430 ret = regulator_enable(mhcd->hsusb_3p3);
431 if (ret) {
432 dev_err(mhcd->dev, "%s: unable to enable the "
433 "hsusb 3p3\n", __func__);
434 regulator_set_optimum_mode(mhcd->hsusb_3p3, 0);
435 regulator_set_optimum_mode(mhcd->hsusb_1p8, 0);
436 regulator_disable(mhcd->hsusb_1p8);
437 return ret;
438 }
439
440 } else {
441 ret = regulator_disable(mhcd->hsusb_1p8);
442 if (ret) {
443 dev_err(mhcd->dev, "%s: unable to disable the "
444 "hsusb 1p8\n", __func__);
445 return ret;
446 }
447
448 ret = regulator_set_optimum_mode(mhcd->hsusb_1p8, 0);
449 if (ret < 0)
450 dev_err(mhcd->dev, "%s: Unable to set LPM of the "
451 "regulator: HSUSB_1p8\n", __func__);
452
453 ret = regulator_disable(mhcd->hsusb_3p3);
454 if (ret) {
455 dev_err(mhcd->dev, "%s: unable to disable the "
456 "hsusb 3p3\n", __func__);
457 return ret;
458 }
459 ret = regulator_set_optimum_mode(mhcd->hsusb_3p3, 0);
460 if (ret < 0)
461 dev_err(mhcd->dev, "%s: Unable to set LPM of the "
462 "regulator: HSUSB_3p3\n", __func__);
463 }
464
465 dev_dbg(mhcd->dev, "reg (%s)\n", on ? "HPM" : "LPM");
466
467 return ret < 0 ? ret : 0;
468}
469
470
471#define ULPI_IO_TIMEOUT_USECS (10 * 1000)
472static int msm_ulpi_read(struct msm_hcd *mhcd, u32 reg)
473{
474 struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
475 unsigned long timeout;
476
477 /* initiate read operation */
478 writel_relaxed(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
479 USB_ULPI_VIEWPORT);
480
481 /* wait for completion */
482 timeout = jiffies + usecs_to_jiffies(ULPI_IO_TIMEOUT_USECS);
483 while (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN) {
484 if (time_after(jiffies, timeout)) {
485 dev_err(mhcd->dev, "msm_ulpi_read: timeout %08x\n",
486 readl_relaxed(USB_ULPI_VIEWPORT));
487 return -ETIMEDOUT;
488 }
489 udelay(1);
490 }
491
492 return ULPI_DATA_READ(readl_relaxed(USB_ULPI_VIEWPORT));
493}
494
495
496static int msm_ulpi_write(struct msm_hcd *mhcd, u32 val, u32 reg)
497{
498 struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
499 unsigned long timeout;
500
501 /* initiate write operation */
502 writel_relaxed(ULPI_RUN | ULPI_WRITE |
503 ULPI_ADDR(reg) | ULPI_DATA(val),
504 USB_ULPI_VIEWPORT);
505
506 /* wait for completion */
507 timeout = jiffies + usecs_to_jiffies(ULPI_IO_TIMEOUT_USECS);
508 while (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN) {
509 if (time_after(jiffies, timeout)) {
510 dev_err(mhcd->dev, "msm_ulpi_write: timeout\n");
511 return -ETIMEDOUT;
512 }
513 udelay(1);
514 }
515
516 return 0;
517}
518
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +0530519/**
520 * Do hard reset to USB hardware block using one of reset methodology based
521 * on availablity of alt_core_clk. There are two kinds of hardware resets.
522 * 1. Conventional synchronous reset where clocks to blocks to be ON while
523 * issuing the reset. 2. Asynchronous reset which requires clocks to be OFF.
524 */
Manu Gautam91223e02011-11-08 15:27:22 +0530525static int msm_ehci_link_clk_reset(struct msm_hcd *mhcd, bool assert)
526{
527 int ret;
528
529 if (assert) {
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +0530530 if (!IS_ERR(mhcd->alt_core_clk)) {
531 ret = clk_reset(mhcd->alt_core_clk, CLK_RESET_ASSERT);
532 } else {
533 /* Using asynchronous block reset to the hardware */
534 clk_disable(mhcd->iface_clk);
535 clk_disable(mhcd->core_clk);
536 ret = clk_reset(mhcd->core_clk, CLK_RESET_ASSERT);
537 }
Manu Gautam91223e02011-11-08 15:27:22 +0530538 if (ret)
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +0530539 dev_err(mhcd->dev, "usb clk assert failed\n");
Manu Gautam91223e02011-11-08 15:27:22 +0530540 } else {
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +0530541 if (!IS_ERR(mhcd->alt_core_clk)) {
542 ret = clk_reset(mhcd->alt_core_clk, CLK_RESET_DEASSERT);
543 } else {
544 ret = clk_reset(mhcd->core_clk, CLK_RESET_DEASSERT);
545 ndelay(200);
546 clk_enable(mhcd->core_clk);
547 clk_enable(mhcd->iface_clk);
548 }
Manu Gautam91223e02011-11-08 15:27:22 +0530549 if (ret)
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +0530550 dev_err(mhcd->dev, "usb clk deassert failed\n");
Manu Gautam91223e02011-11-08 15:27:22 +0530551 }
552
553 return ret;
554}
555
556static int msm_ehci_phy_reset(struct msm_hcd *mhcd)
557{
558 struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +0530559 struct msm_usb_host_platform_data *pdata;
Manu Gautam91223e02011-11-08 15:27:22 +0530560 u32 val;
561 int ret;
562 int retries;
563
564 ret = msm_ehci_link_clk_reset(mhcd, 1);
565 if (ret)
566 return ret;
567
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +0530568 usleep_range(10, 12);
Manu Gautam91223e02011-11-08 15:27:22 +0530569
570 ret = msm_ehci_link_clk_reset(mhcd, 0);
571 if (ret)
572 return ret;
573
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +0530574 pdata = mhcd->dev->platform_data;
575 if (pdata && pdata->use_sec_phy)
576 /* select secondary phy if offset is set for USB operation */
577 writel_relaxed(readl_relaxed(USB_PHY_CTRL2) | (1<<16),
578 USB_PHY_CTRL2);
Manu Gautam91223e02011-11-08 15:27:22 +0530579 val = readl_relaxed(USB_PORTSC) & ~PORTSC_PTS_MASK;
580 writel_relaxed(val | PORTSC_PTS_ULPI, USB_PORTSC);
581
582 for (retries = 3; retries > 0; retries--) {
583 ret = msm_ulpi_write(mhcd, ULPI_FUNC_CTRL_SUSPENDM,
584 ULPI_CLR(ULPI_FUNC_CTRL));
585 if (!ret)
586 break;
587 }
588 if (!retries)
589 return -ETIMEDOUT;
590
591 /* Wakeup the PHY with a reg-access for calibration */
592 for (retries = 3; retries > 0; retries--) {
593 ret = msm_ulpi_read(mhcd, ULPI_DEBUG);
594 if (ret != -ETIMEDOUT)
595 break;
596 }
597 if (!retries)
598 return -ETIMEDOUT;
599
600 dev_info(mhcd->dev, "phy_reset: success\n");
601
602 return 0;
603}
604
605#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
606static int msm_hsusb_reset(struct msm_hcd *mhcd)
607{
608 struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +0530609 struct msm_usb_host_platform_data *pdata;
Manu Gautam91223e02011-11-08 15:27:22 +0530610 unsigned long timeout;
611 int ret;
612
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +0530613 if (!IS_ERR(mhcd->alt_core_clk))
614 clk_prepare_enable(mhcd->alt_core_clk);
615
Manu Gautam91223e02011-11-08 15:27:22 +0530616 ret = msm_ehci_phy_reset(mhcd);
617 if (ret) {
618 dev_err(mhcd->dev, "phy_reset failed\n");
619 return ret;
620 }
621
622 writel_relaxed(USBCMD_RESET, USB_USBCMD);
623
624 timeout = jiffies + usecs_to_jiffies(LINK_RESET_TIMEOUT_USEC);
625 while (readl_relaxed(USB_USBCMD) & USBCMD_RESET) {
626 if (time_after(jiffies, timeout))
627 return -ETIMEDOUT;
628 udelay(1);
629 }
630
631 /* select ULPI phy */
632 writel_relaxed(0x80000000, USB_PORTSC);
633
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +0530634 pdata = mhcd->dev->platform_data;
635 if (pdata && pdata->use_sec_phy)
636 writel_relaxed(readl_relaxed(USB_PHY_CTRL2) | (1<<16),
637 USB_PHY_CTRL2);
638
Manu Gautam91223e02011-11-08 15:27:22 +0530639 msleep(100);
640
641 writel_relaxed(0x0, USB_AHBBURST);
Vijayavardhan Vennapusa5f32d7a2012-03-14 16:30:26 +0530642 writel_relaxed(0x08, USB_AHBMODE);
Manu Gautam91223e02011-11-08 15:27:22 +0530643
644 /* Ensure that RESET operation is completed before turning off clock */
645 mb();
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +0530646
647 if (!IS_ERR(mhcd->alt_core_clk))
648 clk_disable_unprepare(mhcd->alt_core_clk);
Manu Gautam91223e02011-11-08 15:27:22 +0530649
650 /*rising edge interrupts with Dp rise and fall enabled*/
651 msm_ulpi_write(mhcd, ULPI_INT_DP, ULPI_USB_INT_EN_RISE);
652 msm_ulpi_write(mhcd, ULPI_INT_DP, ULPI_USB_INT_EN_FALL);
653
654 /*Clear the PHY interrupts by reading the PHY interrupt latch register*/
655 msm_ulpi_read(mhcd, ULPI_USB_INT_LATCH);
656
657 return 0;
658}
659
Chiranjeevi Velempatice169582012-08-25 14:15:41 +0530660static void msm_ehci_phy_susp_fail_work(struct work_struct *w)
661{
662 struct msm_hcd *mhcd = container_of(w, struct msm_hcd,
663 phy_susp_fail_work);
664 struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
665
666 msm_ehci_vbus_power(mhcd, 0);
667 usb_remove_hcd(hcd);
668 msm_hsusb_reset(mhcd);
669 usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
670 msm_ehci_vbus_power(mhcd, 1);
671}
672
Hemant Kumar8d3aca32013-06-05 18:53:54 -0700673#define PHY_SUSP_TIMEOUT_MSEC 500
674#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
Manu Gautam91223e02011-11-08 15:27:22 +0530675
676#ifdef CONFIG_PM_SLEEP
677static int msm_ehci_suspend(struct msm_hcd *mhcd)
678{
679 struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
680 unsigned long timeout;
Hemant Kumar8c0f2a82012-05-03 19:17:26 -0700681 int ret;
Manu Gautam91223e02011-11-08 15:27:22 +0530682 u32 portsc;
683
684 if (atomic_read(&mhcd->in_lpm)) {
685 dev_dbg(mhcd->dev, "%s called in lpm\n", __func__);
686 return 0;
687 }
688
689 disable_irq(hcd->irq);
690
Hemant Kumar17011ce2013-06-10 17:40:08 -0700691 /* make sure we don't race against a remote wakeup */
692 if (test_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags) ||
693 readl_relaxed(USB_PORTSC) & PORT_RESUME) {
694 dev_dbg(mhcd->dev, "wakeup pending, aborting suspend\n");
695 enable_irq(hcd->irq);
696 return -EBUSY;
697 }
698
Hemant Kumar8d3aca32013-06-05 18:53:54 -0700699 /* If port is enabled wait 5ms for PHCD to come up. Reset PHY
700 * and link if it fails to do so.
701 * If port is not enabled set the PHCD bit and poll for it to
702 * come up with in 500ms. Reset phy and link if it fails to do so.
Manu Gautam91223e02011-11-08 15:27:22 +0530703 */
704 portsc = readl_relaxed(USB_PORTSC);
Hemant Kumar8d3aca32013-06-05 18:53:54 -0700705 if (portsc & PORT_PE) {
Manu Gautam91223e02011-11-08 15:27:22 +0530706
Hemant Kumar8d3aca32013-06-05 18:53:54 -0700707 usleep_range(5000, 5000);
708
709 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD)) {
710 dev_err(mhcd->dev,
711 "Unable to suspend PHY. portsc: %8x\n",
712 readl_relaxed(USB_PORTSC));
713 goto reset_phy_and_link;
714 }
715 } else {
716 writel_relaxed(portsc | PORTSC_PHCD, USB_PORTSC);
717
718 timeout = jiffies + msecs_to_jiffies(PHY_SUSP_TIMEOUT_MSEC);
Manu Gautam91223e02011-11-08 15:27:22 +0530719 while (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD)) {
720 if (time_after(jiffies, timeout)) {
Hemant Kumar8d3aca32013-06-05 18:53:54 -0700721 dev_err(mhcd->dev,
722 "Unable to suspend PHY. portsc: %8x\n",
723 readl_relaxed(USB_PORTSC));
724 goto reset_phy_and_link;
Manu Gautam91223e02011-11-08 15:27:22 +0530725 }
Hemant Kumar8d3aca32013-06-05 18:53:54 -0700726 usleep_range(10000, 10000);
Manu Gautam91223e02011-11-08 15:27:22 +0530727 }
728 }
729
730 /*
731 * PHY has capability to generate interrupt asynchronously in low
732 * power mode (LPM). This interrupt is level triggered. So USB IRQ
733 * line must be disabled till async interrupt enable bit is cleared
734 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
Hemant Kumar17011ce2013-06-10 17:40:08 -0700735 * block data communication from PHY. Enable asynchronous interrupt
736 * only when wakeup gpio IRQ is not present.
Manu Gautam91223e02011-11-08 15:27:22 +0530737 */
Hemant Kumar17011ce2013-06-10 17:40:08 -0700738 if (mhcd->wakeup_irq)
739 writel_relaxed(readl_relaxed(USB_USBCMD) | ULPI_STP_CTRL,
740 USB_USBCMD);
741 else
742 writel_relaxed(readl_relaxed(USB_USBCMD) | ASYNC_INTR_CTRL |
Manu Gautam91223e02011-11-08 15:27:22 +0530743 ULPI_STP_CTRL, USB_USBCMD);
744
745 /*
746 * Ensure that hardware is put in low power mode before
747 * clocks are turned OFF and VDD is allowed to minimize.
748 */
749 mb();
750
751 clk_disable_unprepare(mhcd->iface_clk);
752 clk_disable_unprepare(mhcd->core_clk);
753
Hemant Kumar8c0f2a82012-05-03 19:17:26 -0700754 /* usb phy does not require TCXO clock, hence vote for TCXO disable */
Vijayavardhan Vennapusa16fcaf92013-03-04 10:24:21 +0530755 if (!IS_ERR(mhcd->xo_clk)) {
756 clk_disable_unprepare(mhcd->xo_clk);
757 } else {
758 ret = msm_xo_mode_vote(mhcd->xo_handle, MSM_XO_MODE_OFF);
759 if (ret)
760 dev_err(mhcd->dev, "%s failed to devote for TCXO %d\n",
761 __func__, ret);
762 }
Hemant Kumar8c0f2a82012-05-03 19:17:26 -0700763
Manu Gautam91223e02011-11-08 15:27:22 +0530764 msm_ehci_config_vddcx(mhcd, 0);
765
766 atomic_set(&mhcd->in_lpm, 1);
767 enable_irq(hcd->irq);
Hemant Kumar17011ce2013-06-10 17:40:08 -0700768
769 if (mhcd->wakeup_irq) {
770 mhcd->wakeup_irq_enabled = 1;
771 enable_irq_wake(mhcd->wakeup_irq);
772 enable_irq(mhcd->wakeup_irq);
773 }
774
Vijayavardhan Vennapusa4fa13692012-08-02 14:35:03 +0530775 if (mhcd->pmic_gpio_dp_irq) {
776 mhcd->pmic_gpio_dp_irq_enabled = 1;
777 enable_irq_wake(mhcd->pmic_gpio_dp_irq);
778 enable_irq(mhcd->pmic_gpio_dp_irq);
779 }
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +0530780 if (mhcd->async_irq) {
781 mhcd->async_irq_enabled = 1;
782 enable_irq_wake(mhcd->async_irq);
783 enable_irq(mhcd->async_irq);
784 }
Hemant Kumar153f9972013-06-19 16:49:45 -0700785 pm_relax(mhcd->dev);
Manu Gautam91223e02011-11-08 15:27:22 +0530786
787 dev_info(mhcd->dev, "EHCI USB in low power mode\n");
788
789 return 0;
Hemant Kumar8d3aca32013-06-05 18:53:54 -0700790
791reset_phy_and_link:
792 schedule_work(&mhcd->phy_susp_fail_work);
793 return -ETIMEDOUT;
Manu Gautam91223e02011-11-08 15:27:22 +0530794}
795
796static int msm_ehci_resume(struct msm_hcd *mhcd)
797{
798 struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
799 unsigned long timeout;
800 unsigned temp;
Hemant Kumar8c0f2a82012-05-03 19:17:26 -0700801 int ret;
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +0530802 unsigned long flags;
Manu Gautam91223e02011-11-08 15:27:22 +0530803
804 if (!atomic_read(&mhcd->in_lpm)) {
805 dev_dbg(mhcd->dev, "%s called in !in_lpm\n", __func__);
806 return 0;
807 }
808
Vijayavardhan Vennapusa4fa13692012-08-02 14:35:03 +0530809 if (mhcd->pmic_gpio_dp_irq_enabled) {
810 disable_irq_wake(mhcd->pmic_gpio_dp_irq);
811 disable_irq_nosync(mhcd->pmic_gpio_dp_irq);
812 mhcd->pmic_gpio_dp_irq_enabled = 0;
813 }
Hemant Kumar17011ce2013-06-10 17:40:08 -0700814
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +0530815 spin_lock_irqsave(&mhcd->wakeup_lock, flags);
816 if (mhcd->async_irq_enabled) {
817 disable_irq_wake(mhcd->async_irq);
818 disable_irq_nosync(mhcd->async_irq);
819 mhcd->async_irq_enabled = 0;
820 }
Hemant Kumar17011ce2013-06-10 17:40:08 -0700821
822 if (mhcd->wakeup_irq) {
823 if (mhcd->wakeup_irq_enabled) {
824 disable_irq_wake(mhcd->wakeup_irq);
825 disable_irq_nosync(mhcd->wakeup_irq);
826 mhcd->wakeup_irq_enabled = 0;
827 }
828 }
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +0530829 spin_unlock_irqrestore(&mhcd->wakeup_lock, flags);
830
Hemant Kumar153f9972013-06-19 16:49:45 -0700831 pm_stay_awake(mhcd->dev);
Manu Gautam91223e02011-11-08 15:27:22 +0530832
Hemant Kumar8c0f2a82012-05-03 19:17:26 -0700833 /* Vote for TCXO when waking up the phy */
Vijayavardhan Vennapusa16fcaf92013-03-04 10:24:21 +0530834 if (!IS_ERR(mhcd->xo_clk)) {
835 clk_prepare_enable(mhcd->xo_clk);
836 } else {
837 ret = msm_xo_mode_vote(mhcd->xo_handle, MSM_XO_MODE_ON);
838 if (ret)
839 dev_err(mhcd->dev, "%s failed to vote for TCXO D0 %d\n",
840 __func__, ret);
841 }
Hemant Kumar8c0f2a82012-05-03 19:17:26 -0700842
Manu Gautam91223e02011-11-08 15:27:22 +0530843 clk_prepare_enable(mhcd->core_clk);
844 clk_prepare_enable(mhcd->iface_clk);
845
846 msm_ehci_config_vddcx(mhcd, 1);
847
848 temp = readl_relaxed(USB_USBCMD);
849 temp &= ~ASYNC_INTR_CTRL;
850 temp &= ~ULPI_STP_CTRL;
851 writel_relaxed(temp, USB_USBCMD);
852
853 if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD))
854 goto skip_phy_resume;
855
856 temp = readl_relaxed(USB_PORTSC) & ~PORTSC_PHCD;
857 writel_relaxed(temp, USB_PORTSC);
858
859 timeout = jiffies + usecs_to_jiffies(PHY_RESUME_TIMEOUT_USEC);
860 while ((readl_relaxed(USB_PORTSC) & PORTSC_PHCD) ||
861 !(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_SYNC_STATE)) {
862 if (time_after(jiffies, timeout)) {
863 /*This is a fatal error. Reset the link and PHY*/
864 dev_err(mhcd->dev, "Unable to resume USB. Resetting the h/w\n");
865 msm_hsusb_reset(mhcd);
866 break;
867 }
868 udelay(1);
869 }
870
871skip_phy_resume:
872
Chiranjeevi Velempati35d46ab2012-07-18 20:36:53 +0530873 usb_hcd_resume_root_hub(hcd);
Manu Gautam91223e02011-11-08 15:27:22 +0530874 atomic_set(&mhcd->in_lpm, 0);
875
876 if (mhcd->async_int) {
877 mhcd->async_int = false;
878 pm_runtime_put_noidle(mhcd->dev);
879 enable_irq(hcd->irq);
880 }
881
Vijayavardhan Vennapusa4fa13692012-08-02 14:35:03 +0530882 if (atomic_read(&mhcd->pm_usage_cnt)) {
883 atomic_set(&mhcd->pm_usage_cnt, 0);
884 pm_runtime_put_noidle(mhcd->dev);
885 }
886
Manu Gautam91223e02011-11-08 15:27:22 +0530887 dev_info(mhcd->dev, "EHCI USB exited from low power mode\n");
888
889 return 0;
890}
891#endif
892
893static irqreturn_t msm_ehci_irq(struct usb_hcd *hcd)
894{
895 struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
896
897 if (atomic_read(&mhcd->in_lpm)) {
Hemant Kumar17011ce2013-06-10 17:40:08 -0700898 dev_dbg(mhcd->dev, "phy async intr\n");
Manu Gautam91223e02011-11-08 15:27:22 +0530899 disable_irq_nosync(hcd->irq);
900 mhcd->async_int = true;
901 pm_runtime_get(mhcd->dev);
902 return IRQ_HANDLED;
903 }
904
905 return ehci_irq(hcd);
906}
907
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +0530908static irqreturn_t msm_async_irq(int irq, void *data)
909{
910 struct msm_hcd *mhcd = data;
911 int ret;
912
913 mhcd->async_int_cnt++;
914 dev_dbg(mhcd->dev, "%s: hsusb host remote wakeup interrupt cnt: %u\n",
915 __func__, mhcd->async_int_cnt);
916
Hemant Kumar153f9972013-06-19 16:49:45 -0700917 pm_stay_awake(mhcd->dev);
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +0530918
919 spin_lock(&mhcd->wakeup_lock);
920 if (mhcd->async_irq_enabled) {
921 mhcd->async_irq_enabled = 0;
922 disable_irq_wake(irq);
923 disable_irq_nosync(irq);
924 }
925 spin_unlock(&mhcd->wakeup_lock);
926
927 if (!atomic_read(&mhcd->pm_usage_cnt)) {
928 ret = pm_runtime_get(mhcd->dev);
929 if ((ret == 1) || (ret == -EINPROGRESS))
930 pm_runtime_put_noidle(mhcd->dev);
931 else
932 atomic_set(&mhcd->pm_usage_cnt, 1);
933 }
934
935 return IRQ_HANDLED;
936}
937
Vijayavardhan Vennapusa4fa13692012-08-02 14:35:03 +0530938static irqreturn_t msm_ehci_host_wakeup_irq(int irq, void *data)
939{
940
941 struct msm_hcd *mhcd = data;
942
943 mhcd->pmic_gpio_int_cnt++;
944 dev_dbg(mhcd->dev, "%s: hsusb host remote wakeup interrupt cnt: %u\n",
945 __func__, mhcd->pmic_gpio_int_cnt);
946
947
Hemant Kumar153f9972013-06-19 16:49:45 -0700948 pm_stay_awake(mhcd->dev);
Vijayavardhan Vennapusa4fa13692012-08-02 14:35:03 +0530949
950 if (mhcd->pmic_gpio_dp_irq_enabled) {
951 mhcd->pmic_gpio_dp_irq_enabled = 0;
952 disable_irq_wake(irq);
953 disable_irq_nosync(irq);
954 }
955
956 if (!atomic_read(&mhcd->pm_usage_cnt)) {
957 atomic_set(&mhcd->pm_usage_cnt, 1);
958 pm_runtime_get(mhcd->dev);
959 }
960
961 return IRQ_HANDLED;
962}
963
Manu Gautam91223e02011-11-08 15:27:22 +0530964static int msm_ehci_reset(struct usb_hcd *hcd)
965{
966 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +0530967 struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
968 struct msm_usb_host_platform_data *pdata;
Manu Gautam91223e02011-11-08 15:27:22 +0530969 int retval;
970
971 ehci->caps = USB_CAPLENGTH;
972 ehci->regs = USB_CAPLENGTH +
973 HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
974 dbg_hcs_params(ehci, "reset");
975 dbg_hcc_params(ehci, "reset");
976
977 /* cache the data to minimize the chip reads*/
978 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
979
980 hcd->has_tt = 1;
981 ehci->sbrn = HCD_USB2;
982
983 retval = ehci_halt(ehci);
984 if (retval)
985 return retval;
986
987 /* data structure init */
988 retval = ehci_init(hcd);
989 if (retval)
990 return retval;
991
992 retval = ehci_reset(ehci);
993 if (retval)
994 return retval;
995
996 /* bursts of unspecified length. */
997 writel_relaxed(0, USB_AHBBURST);
998 /* Use the AHB transactor */
Vijayavardhan Vennapusa5f32d7a2012-03-14 16:30:26 +0530999 writel_relaxed(0x08, USB_AHBMODE);
Manu Gautam91223e02011-11-08 15:27:22 +05301000 /* Disable streaming mode and select host mode */
1001 writel_relaxed(0x13, USB_USBMODE);
1002
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +05301003 pdata = mhcd->dev->platform_data;
1004 if (pdata && pdata->use_sec_phy)
1005 writel_relaxed(readl_relaxed(USB_PHY_CTRL2) | (1<<16),
1006 USB_PHY_CTRL2);
1007
Manu Gautam91223e02011-11-08 15:27:22 +05301008 ehci_port_power(ehci, 1);
1009 return 0;
1010}
1011
Hemant Kumara7d531d2013-06-18 22:12:18 -07001012static int msm_ehci_bus_resume_with_gpio(struct usb_hcd *hcd)
1013{
1014 struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
1015 int ret;
1016
1017 gpio_direction_output(mhcd->resume_gpio, 1);
1018
1019 ret = ehci_bus_resume(hcd);
1020
1021 gpio_direction_output(mhcd->resume_gpio, 0);
1022
1023 return ret;
1024}
1025
Rajkumar Raghupathyad8d68e2013-06-06 17:48:39 +05301026#if defined(CONFIG_DEBUG_FS)
1027static u32 addr;
1028#define BUF_SIZE 32
1029static ssize_t debug_read_phy_data(struct file *file, char __user *ubuf,
1030 size_t count, loff_t *ppos)
1031{
1032 struct msm_hcd *mhcd = file->private_data;
1033 char *kbuf;
1034 size_t c = 0;
1035 u32 data = 0;
1036 int ret = 0;
1037
1038 kbuf = kzalloc(sizeof(char) * BUF_SIZE, GFP_KERNEL);
1039 pm_runtime_get(mhcd->dev);
1040 data = msm_ulpi_read(mhcd, addr);
1041 pm_runtime_put(mhcd->dev);
1042 if (data < 0) {
1043 dev_err(mhcd->dev,
1044 "%s(): ulpi read timeout\n", __func__);
1045 return -ETIMEDOUT;
1046 }
1047
1048 c = scnprintf(kbuf, BUF_SIZE, "addr: 0x%x: data: 0x%x\n", addr, data);
1049
1050 ret = simple_read_from_buffer(ubuf, count, ppos, kbuf, c);
1051
1052 kfree(kbuf);
1053
1054 return ret;
1055}
1056
1057static ssize_t debug_write_phy_data(struct file *file, const char __user *buf,
1058 size_t count, loff_t *ppos)
1059{
1060 struct msm_hcd *mhcd = file->private_data;
1061 char kbuf[10];
1062 u32 data = 0;
1063
1064 memset(kbuf, 0, 10);
1065
1066 if (copy_from_user(kbuf, buf, count > 10 ? 10 : count))
1067 return -EFAULT;
1068
1069 if (sscanf(kbuf, "%x", &data) != 1)
1070 return -EINVAL;
1071
1072 pm_runtime_get(mhcd->dev);
1073 if (msm_ulpi_write(mhcd, data, addr) < 0) {
1074 dev_err(mhcd->dev,
1075 "%s(): ulpi write timeout\n", __func__);
1076 return -ETIMEDOUT;
1077 }
1078 pm_runtime_put(mhcd->dev);
1079
1080 return count;
1081}
1082
1083static ssize_t debug_phy_write_addr(struct file *file, const char __user *buf,
1084 size_t count, loff_t *ppos)
1085{
1086 char kbuf[10];
1087 u32 temp;
1088
1089 memset(kbuf, 0, 10);
1090
1091 if (copy_from_user(kbuf, buf, count > 10 ? 10 : count))
1092 return -EFAULT;
1093
1094 if (sscanf(kbuf, "%x", &temp) != 1)
1095 return -EINVAL;
1096
1097 if (temp > 0x3F)
1098 return -EINVAL;
1099
1100 addr = temp;
1101
1102 return count;
1103}
1104
1105static int debug_open(struct inode *inode, struct file *file)
1106{
1107 file->private_data = inode->i_private;
1108 return 0;
1109}
1110
1111const struct file_operations debug_rw_phy_ops = {
1112 .open = debug_open,
1113 .read = debug_read_phy_data,
1114 .write = debug_write_phy_data,
1115};
1116
1117const struct file_operations debug_write_phy_ops = {
1118 .open = debug_open,
1119 .write = debug_phy_write_addr,
1120};
1121
1122static struct dentry *dent_ehci;
1123
1124static int ehci_debugfs_init(struct msm_hcd *mhcd)
1125{
1126 struct dentry *debug_phy_data;
1127 struct dentry *debug_phy_addr;
1128
1129 dent_ehci = debugfs_create_dir(dev_name(mhcd->dev), 0);
1130 if (IS_ERR(dent_ehci))
1131 return -ENOENT;
1132
1133 debug_phy_data = debugfs_create_file("phy_reg_data", 0666,
1134 dent_ehci, mhcd, &debug_rw_phy_ops);
1135 if (!debug_phy_data) {
1136 debugfs_remove(dent_ehci);
1137 return -ENOENT;
1138 }
1139
1140 debug_phy_addr = debugfs_create_file("phy_reg_addr", 0666,
1141 dent_ehci, mhcd, &debug_write_phy_ops);
1142 if (!debug_phy_addr) {
1143 debugfs_remove_recursive(dent_ehci);
1144 return -ENOENT;
1145 }
1146 return 0;
1147}
1148#else
1149static int ehci_debugfs_init(struct msm_hcd *mhcd)
1150{
1151 return 0;
1152}
1153#endif
1154
Manu Gautam91223e02011-11-08 15:27:22 +05301155static struct hc_driver msm_hc2_driver = {
1156 .description = hcd_name,
1157 .product_desc = "Qualcomm EHCI Host Controller",
1158 .hcd_priv_size = sizeof(struct msm_hcd),
1159
1160 /*
1161 * generic hardware linkage
1162 */
1163 .irq = msm_ehci_irq,
1164 .flags = HCD_USB2 | HCD_MEMORY,
1165
1166 .reset = msm_ehci_reset,
1167 .start = ehci_run,
1168
1169 .stop = ehci_stop,
1170 .shutdown = ehci_shutdown,
1171
1172 /*
1173 * managing i/o requests and associated device resources
1174 */
1175 .urb_enqueue = ehci_urb_enqueue,
1176 .urb_dequeue = ehci_urb_dequeue,
1177 .endpoint_disable = ehci_endpoint_disable,
1178 .endpoint_reset = ehci_endpoint_reset,
1179 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
1180
1181 /*
1182 * scheduling support
1183 */
1184 .get_frame_number = ehci_get_frame,
1185
1186 /*
1187 * root hub support
1188 */
1189 .hub_status_data = ehci_hub_status_data,
1190 .hub_control = ehci_hub_control,
1191 .relinquish_port = ehci_relinquish_port,
1192 .port_handed_over = ehci_port_handed_over,
1193
1194 /*
1195 * PM support
1196 */
1197 .bus_suspend = ehci_bus_suspend,
1198 .bus_resume = ehci_bus_resume,
1199};
1200
Hemant Kumar17011ce2013-06-10 17:40:08 -07001201static irqreturn_t msm_hsusb_wakeup_irq(int irq, void *data)
1202{
1203 struct msm_hcd *mhcd = data;
1204 int ret;
1205
1206 mhcd->wakeup_int_cnt++;
1207 dev_dbg(mhcd->dev, "%s: hsic remote wakeup interrupt cnt: %u\n",
1208 __func__, mhcd->wakeup_int_cnt);
1209
1210 pm_stay_awake(mhcd->dev);
1211
1212 spin_lock(&mhcd->wakeup_lock);
1213 if (mhcd->wakeup_irq_enabled) {
1214 mhcd->wakeup_irq_enabled = 0;
1215 disable_irq_wake(irq);
1216 disable_irq_nosync(irq);
1217 }
1218 spin_unlock(&mhcd->wakeup_lock);
1219
1220 if (!atomic_read(&mhcd->pm_usage_cnt)) {
1221 ret = pm_runtime_get(mhcd->dev);
1222 /*
1223 * controller runtime resume can race with us.
1224 * if we are active (ret == 1) or resuming
1225 * (ret == -EINPROGRESS), decrement the
1226 * PM usage counter before returning.
1227 */
1228 if ((ret == 1) || (ret == -EINPROGRESS)) {
1229 pm_runtime_put_noidle(mhcd->dev);
1230 } else {
1231 /* Let khubd know of hub port status change */
1232 if (mhcd->ehci.no_selective_suspend)
1233 mhcd->ehci.suspended_ports = 1;
1234 atomic_set(&mhcd->pm_usage_cnt, 1);
1235 }
1236 }
1237
1238 return IRQ_HANDLED;
1239}
1240
Manu Gautam91223e02011-11-08 15:27:22 +05301241static int msm_ehci_init_clocks(struct msm_hcd *mhcd, u32 init)
1242{
1243 int ret = 0;
1244
1245 if (!init)
1246 goto put_clocks;
1247
1248 /* 60MHz alt_core_clk is for LINK to be used during PHY RESET */
1249 mhcd->alt_core_clk = clk_get(mhcd->dev, "alt_core_clk");
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +05301250 if (IS_ERR(mhcd->alt_core_clk))
1251 dev_dbg(mhcd->dev, "failed to get alt_core_clk\n");
1252 else
1253 clk_set_rate(mhcd->alt_core_clk, 60000000);
Manu Gautam91223e02011-11-08 15:27:22 +05301254
1255 /* iface_clk is required for data transfers */
1256 mhcd->iface_clk = clk_get(mhcd->dev, "iface_clk");
1257 if (IS_ERR(mhcd->iface_clk)) {
1258 dev_err(mhcd->dev, "failed to get iface_clk\n");
1259 ret = PTR_ERR(mhcd->iface_clk);
1260 goto put_alt_core_clk;
1261 }
1262
1263 /* Link's protocol engine is based on pclk which must
1264 * be running >55Mhz and frequency should also not change.
1265 * Hence, vote for maximum clk frequency on its source
1266 */
1267 mhcd->core_clk = clk_get(mhcd->dev, "core_clk");
1268 if (IS_ERR(mhcd->core_clk)) {
1269 dev_err(mhcd->dev, "failed to get core_clk\n");
1270 ret = PTR_ERR(mhcd->core_clk);
1271 goto put_iface_clk;
1272 }
1273 clk_set_rate(mhcd->core_clk, INT_MAX);
1274
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +05301275 mhcd->phy_sleep_clk = clk_get(mhcd->dev, "sleep_clk");
1276 if (IS_ERR(mhcd->phy_sleep_clk))
1277 dev_dbg(mhcd->dev, "failed to get sleep_clk\n");
1278 else
1279 clk_prepare_enable(mhcd->phy_sleep_clk);
1280
Manu Gautam91223e02011-11-08 15:27:22 +05301281 clk_prepare_enable(mhcd->core_clk);
1282 clk_prepare_enable(mhcd->iface_clk);
1283
1284 return 0;
1285
1286put_clocks:
Jack Pham35fba312013-01-21 19:19:21 -08001287 if (!atomic_read(&mhcd->in_lpm)) {
1288 clk_disable_unprepare(mhcd->iface_clk);
1289 clk_disable_unprepare(mhcd->core_clk);
1290 }
Manu Gautam91223e02011-11-08 15:27:22 +05301291 clk_put(mhcd->core_clk);
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +05301292 if (!IS_ERR(mhcd->phy_sleep_clk)) {
1293 clk_disable_unprepare(mhcd->phy_sleep_clk);
1294 clk_put(mhcd->phy_sleep_clk);
1295 }
Manu Gautam91223e02011-11-08 15:27:22 +05301296put_iface_clk:
1297 clk_put(mhcd->iface_clk);
1298put_alt_core_clk:
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +05301299 if (!IS_ERR(mhcd->alt_core_clk))
1300 clk_put(mhcd->alt_core_clk);
Manu Gautam91223e02011-11-08 15:27:22 +05301301
1302 return ret;
1303}
1304
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +05301305struct msm_usb_host_platform_data *ehci_msm2_dt_to_pdata(
1306 struct platform_device *pdev)
1307{
1308 struct device_node *node = pdev->dev.of_node;
1309 struct msm_usb_host_platform_data *pdata;
1310
1311 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
1312 if (!pdata) {
1313 dev_err(&pdev->dev, "unable to allocate platform data\n");
1314 return NULL;
1315 }
1316
1317 pdata->use_sec_phy = of_property_read_bool(node,
1318 "qcom,usb2-enable-hsphy2");
1319 of_property_read_u32(node, "qcom,usb2-power-budget",
1320 &pdata->power_budget);
Hemant Kumarb8fc9592013-04-17 19:29:39 -07001321 pdata->no_selective_suspend = of_property_read_bool(node,
1322 "qcom,no-selective-suspend");
Hemant Kumara7d531d2013-06-18 22:12:18 -07001323 pdata->resume_gpio = of_get_named_gpio(node, "qcom,resume-gpio", 0);
1324 if (pdata->resume_gpio < 0)
1325 pdata->resume_gpio = 0;
1326
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +05301327 return pdata;
1328}
1329
1330static u64 ehci_msm_dma_mask = DMA_BIT_MASK(64);
Manu Gautam91223e02011-11-08 15:27:22 +05301331static int __devinit ehci_msm2_probe(struct platform_device *pdev)
1332{
1333 struct usb_hcd *hcd;
1334 struct resource *res;
1335 struct msm_hcd *mhcd;
Hemant Kumar56925352012-02-13 16:59:52 -08001336 const struct msm_usb_host_platform_data *pdata;
Hemant Kumar8c0f2a82012-05-03 19:17:26 -07001337 char pdev_name[PDEV_NAME_LEN];
Manu Gautam91223e02011-11-08 15:27:22 +05301338 int ret;
1339
1340 dev_dbg(&pdev->dev, "ehci_msm2 probe\n");
1341
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +05301342 if (pdev->dev.of_node) {
1343 dev_dbg(&pdev->dev, "device tree enabled\n");
1344 pdev->dev.platform_data = ehci_msm2_dt_to_pdata(pdev);
1345 }
1346
1347 if (!pdev->dev.platform_data)
1348 dev_dbg(&pdev->dev, "No platform data given\n");
1349
Hemant Kumara7d531d2013-06-18 22:12:18 -07001350 pdata = pdev->dev.platform_data;
1351
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +05301352 if (!pdev->dev.dma_mask)
1353 pdev->dev.dma_mask = &ehci_msm_dma_mask;
1354 if (!pdev->dev.coherent_dma_mask)
1355 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
1356
Manu Gautam91223e02011-11-08 15:27:22 +05301357 hcd = usb_create_hcd(&msm_hc2_driver, &pdev->dev,
1358 dev_name(&pdev->dev));
1359 if (!hcd) {
1360 dev_err(&pdev->dev, "Unable to create HCD\n");
1361 return -ENOMEM;
1362 }
1363
Manu Gautam578656b2013-03-19 15:30:08 +05301364 hcd_to_bus(hcd)->skip_resume = true;
1365
Manu Gautam91223e02011-11-08 15:27:22 +05301366 hcd->irq = platform_get_irq(pdev, 0);
1367 if (hcd->irq < 0) {
1368 dev_err(&pdev->dev, "Unable to get IRQ resource\n");
1369 ret = hcd->irq;
1370 goto put_hcd;
1371 }
1372
1373 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1374 if (!res) {
1375 dev_err(&pdev->dev, "Unable to get memory resource\n");
1376 ret = -ENODEV;
1377 goto put_hcd;
1378 }
1379
1380 hcd->rsrc_start = res->start;
1381 hcd->rsrc_len = resource_size(res);
1382 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
1383 if (!hcd->regs) {
1384 dev_err(&pdev->dev, "ioremap failed\n");
1385 ret = -ENOMEM;
1386 goto put_hcd;
1387 }
1388
1389 mhcd = hcd_to_mhcd(hcd);
1390 mhcd->dev = &pdev->dev;
1391
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +05301392 spin_lock_init(&mhcd->wakeup_lock);
1393
1394 mhcd->async_irq = platform_get_irq_byname(pdev, "async_irq");
1395 if (mhcd->async_irq < 0) {
1396 dev_dbg(&pdev->dev, "platform_get_irq for async_int failed\n");
1397 mhcd->async_irq = 0;
1398 } else {
1399 ret = request_irq(mhcd->async_irq, msm_async_irq,
1400 IRQF_TRIGGER_RISING, "msm_ehci_host", mhcd);
1401 if (ret) {
1402 dev_err(&pdev->dev, "request irq failed (ASYNC INT)\n");
1403 goto unmap;
1404 }
1405 disable_irq(mhcd->async_irq);
1406 }
1407
Hemant Kumar8c0f2a82012-05-03 19:17:26 -07001408 snprintf(pdev_name, PDEV_NAME_LEN, "%s.%d", pdev->name, pdev->id);
Vijayavardhan Vennapusa16fcaf92013-03-04 10:24:21 +05301409 mhcd->xo_clk = clk_get(&pdev->dev, "xo");
1410 if (!IS_ERR(mhcd->xo_clk)) {
1411 ret = clk_prepare_enable(mhcd->xo_clk);
1412 } else {
1413 mhcd->xo_handle = msm_xo_get(MSM_XO_TCXO_D0, pdev_name);
1414 if (IS_ERR(mhcd->xo_handle)) {
1415 dev_err(&pdev->dev, "%s fail to get handle for X0 D0\n",
1416 __func__);
1417 ret = PTR_ERR(mhcd->xo_handle);
1418 goto free_async_irq;
1419 } else {
1420 ret = msm_xo_mode_vote(mhcd->xo_handle, MSM_XO_MODE_ON);
1421 }
Hemant Kumar8c0f2a82012-05-03 19:17:26 -07001422 }
Hemant Kumar8c0f2a82012-05-03 19:17:26 -07001423 if (ret) {
Vijayavardhan Vennapusa16fcaf92013-03-04 10:24:21 +05301424 dev_err(&pdev->dev, "%s failed to vote for TCXO %d\n",
1425 __func__, ret);
Hemant Kumar8c0f2a82012-05-03 19:17:26 -07001426 goto free_xo_handle;
1427 }
1428
Hemant Kumara7d531d2013-06-18 22:12:18 -07001429 if (pdata && pdata->resume_gpio) {
1430 mhcd->resume_gpio = pdata->resume_gpio;
1431 ret = gpio_request(mhcd->resume_gpio, "hsusb_resume");
1432 if (ret) {
1433 dev_err(&pdev->dev,
1434 "resume gpio(%d) request failed:%d\n",
1435 mhcd->resume_gpio, ret);
1436 mhcd->resume_gpio = 0;
1437 } else {
1438 msm_hc2_driver.bus_resume =
1439 msm_ehci_bus_resume_with_gpio;
1440 }
1441 }
1442
Hemant Kumar17011ce2013-06-10 17:40:08 -07001443 spin_lock_init(&mhcd->wakeup_lock);
1444
Manu Gautam91223e02011-11-08 15:27:22 +05301445 ret = msm_ehci_init_clocks(mhcd, 1);
1446 if (ret) {
1447 dev_err(&pdev->dev, "unable to initialize clocks\n");
1448 ret = -ENODEV;
Hemant Kumar8c0f2a82012-05-03 19:17:26 -07001449 goto devote_xo_handle;
Manu Gautam91223e02011-11-08 15:27:22 +05301450 }
1451
1452 ret = msm_ehci_init_vddcx(mhcd, 1);
1453 if (ret) {
1454 dev_err(&pdev->dev, "unable to initialize VDDCX\n");
1455 ret = -ENODEV;
1456 goto deinit_clocks;
1457 }
1458
1459 ret = msm_ehci_config_vddcx(mhcd, 1);
1460 if (ret) {
1461 dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
1462 goto deinit_vddcx;
1463 }
1464
1465 ret = msm_ehci_ldo_init(mhcd, 1);
1466 if (ret) {
1467 dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
1468 goto deinit_vddcx;
1469 }
1470
1471 ret = msm_ehci_ldo_enable(mhcd, 1);
1472 if (ret) {
1473 dev_err(&pdev->dev, "hsusb vreg enable failed\n");
1474 goto deinit_ldo;
1475 }
1476
1477 ret = msm_ehci_init_vbus(mhcd, 1);
1478 if (ret) {
1479 dev_err(&pdev->dev, "unable to get vbus\n");
1480 goto disable_ldo;
1481 }
1482
1483 ret = msm_hsusb_reset(mhcd);
1484 if (ret) {
1485 dev_err(&pdev->dev, "hsusb PHY initialization failed\n");
1486 goto vbus_deinit;
1487 }
1488
1489 ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
1490 if (ret) {
1491 dev_err(&pdev->dev, "unable to register HCD\n");
1492 goto vbus_deinit;
1493 }
1494
Hemant Kumar56925352012-02-13 16:59:52 -08001495 pdata = mhcd->dev->platform_data;
1496 if (pdata && (!pdata->dock_connect_irq ||
1497 !irq_read_line(pdata->dock_connect_irq)))
1498 msm_ehci_vbus_power(mhcd, 1);
Manu Gautam91223e02011-11-08 15:27:22 +05301499
Hemant Kumarb8fc9592013-04-17 19:29:39 -07001500 /* For peripherals directly conneted to downstream port of root hub
1501 * and require to drive suspend and resume by controller driver instead
1502 * of root hub.
1503 */
1504 if (pdata)
1505 mhcd->ehci.no_selective_suspend = pdata->no_selective_suspend;
1506
Hemant Kumar17011ce2013-06-10 17:40:08 -07001507 mhcd->wakeup_irq = platform_get_irq_byname(pdev, "wakeup_irq");
1508 if (mhcd->wakeup_irq > 0) {
1509 dev_dbg(&pdev->dev, "wakeup irq:%d\n", mhcd->wakeup_irq);
1510
1511 irq_set_status_flags(mhcd->wakeup_irq, IRQ_NOAUTOEN);
1512 ret = request_irq(mhcd->wakeup_irq, msm_hsusb_wakeup_irq,
1513 IRQF_TRIGGER_HIGH,
1514 "msm_hsusb_wakeup", mhcd);
1515 if (ret) {
1516 dev_err(&pdev->dev, "request_irq(%d) failed:%d\n",
1517 mhcd->wakeup_irq, ret);
1518 mhcd->wakeup_irq = 0;
1519 }
1520 } else {
1521 mhcd->wakeup_irq = 0;
1522 }
1523
Manu Gautam91223e02011-11-08 15:27:22 +05301524 device_init_wakeup(&pdev->dev, 1);
Hemant Kumar153f9972013-06-19 16:49:45 -07001525 wakeup_source_init(&mhcd->ws, dev_name(&pdev->dev));
1526 pm_stay_awake(mhcd->dev);
Chiranjeevi Velempatice169582012-08-25 14:15:41 +05301527 INIT_WORK(&mhcd->phy_susp_fail_work, msm_ehci_phy_susp_fail_work);
Manu Gautam91223e02011-11-08 15:27:22 +05301528 /*
1529 * This pdev->dev is assigned parent of root-hub by USB core,
1530 * hence, runtime framework automatically calls this driver's
1531 * runtime APIs based on root-hub's state.
1532 */
Vijayavardhan Vennapusa4fa13692012-08-02 14:35:03 +05301533 /* configure pmic_gpio_irq for D+ change */
1534 if (pdata && pdata->pmic_gpio_dp_irq)
1535 mhcd->pmic_gpio_dp_irq = pdata->pmic_gpio_dp_irq;
1536 if (mhcd->pmic_gpio_dp_irq) {
1537 ret = request_threaded_irq(mhcd->pmic_gpio_dp_irq, NULL,
1538 msm_ehci_host_wakeup_irq,
1539 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
1540 "msm_ehci_host_wakeup", mhcd);
1541 if (!ret) {
1542 disable_irq_nosync(mhcd->pmic_gpio_dp_irq);
1543 } else {
1544 dev_err(&pdev->dev, "request_irq(%d) failed: %d\n",
1545 mhcd->pmic_gpio_dp_irq, ret);
1546 mhcd->pmic_gpio_dp_irq = 0;
1547 }
1548 }
Manu Gautam91223e02011-11-08 15:27:22 +05301549 pm_runtime_set_active(&pdev->dev);
1550 pm_runtime_enable(&pdev->dev);
1551
Rajkumar Raghupathyad8d68e2013-06-06 17:48:39 +05301552 if (ehci_debugfs_init(mhcd) < 0)
1553 dev_err(mhcd->dev, "%s: debugfs init failed\n", __func__);
1554
Manu Gautam91223e02011-11-08 15:27:22 +05301555 return 0;
1556
1557vbus_deinit:
1558 msm_ehci_init_vbus(mhcd, 0);
1559disable_ldo:
1560 msm_ehci_ldo_enable(mhcd, 0);
1561deinit_ldo:
1562 msm_ehci_ldo_init(mhcd, 0);
1563deinit_vddcx:
1564 msm_ehci_init_vddcx(mhcd, 0);
1565deinit_clocks:
1566 msm_ehci_init_clocks(mhcd, 0);
Hemant Kumar8c0f2a82012-05-03 19:17:26 -07001567devote_xo_handle:
Hemant Kumara7d531d2013-06-18 22:12:18 -07001568 if (mhcd->resume_gpio)
1569 gpio_free(mhcd->resume_gpio);
Vijayavardhan Vennapusa16fcaf92013-03-04 10:24:21 +05301570 if (!IS_ERR(mhcd->xo_clk))
1571 clk_disable_unprepare(mhcd->xo_clk);
1572 else
1573 msm_xo_mode_vote(mhcd->xo_handle, MSM_XO_MODE_OFF);
Hemant Kumar8c0f2a82012-05-03 19:17:26 -07001574free_xo_handle:
Vijayavardhan Vennapusa16fcaf92013-03-04 10:24:21 +05301575 if (!IS_ERR(mhcd->xo_clk))
1576 clk_put(mhcd->xo_clk);
1577 else
1578 msm_xo_put(mhcd->xo_handle);
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +05301579free_async_irq:
1580 if (mhcd->async_irq)
1581 free_irq(mhcd->async_irq, mhcd);
Manu Gautam91223e02011-11-08 15:27:22 +05301582unmap:
1583 iounmap(hcd->regs);
1584put_hcd:
1585 usb_put_hcd(hcd);
1586
1587 return ret;
1588}
1589
1590static int __devexit ehci_msm2_remove(struct platform_device *pdev)
1591{
1592 struct usb_hcd *hcd = platform_get_drvdata(pdev);
1593 struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
1594
Vijayavardhan Vennapusa4fa13692012-08-02 14:35:03 +05301595 if (mhcd->pmic_gpio_dp_irq) {
1596 if (mhcd->pmic_gpio_dp_irq_enabled)
1597 disable_irq_wake(mhcd->pmic_gpio_dp_irq);
1598 free_irq(mhcd->pmic_gpio_dp_irq, mhcd);
1599 }
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +05301600 if (mhcd->async_irq) {
1601 if (mhcd->async_irq_enabled)
1602 disable_irq_wake(mhcd->async_irq);
1603 free_irq(mhcd->async_irq, mhcd);
1604 }
Hemant Kumara7d531d2013-06-18 22:12:18 -07001605
Hemant Kumar17011ce2013-06-10 17:40:08 -07001606 if (mhcd->wakeup_irq) {
1607 if (mhcd->wakeup_irq_enabled)
1608 disable_irq_wake(mhcd->wakeup_irq);
1609 free_irq(mhcd->wakeup_irq, mhcd);
1610 }
1611
Hemant Kumara7d531d2013-06-18 22:12:18 -07001612 if (mhcd->resume_gpio)
1613 gpio_free(mhcd->resume_gpio);
1614
Manu Gautam91223e02011-11-08 15:27:22 +05301615 device_init_wakeup(&pdev->dev, 0);
Manu Gautam91223e02011-11-08 15:27:22 +05301616 pm_runtime_set_suspended(&pdev->dev);
1617
1618 usb_remove_hcd(hcd);
Hemant Kumar56925352012-02-13 16:59:52 -08001619
Vijayavardhan Vennapusa16fcaf92013-03-04 10:24:21 +05301620 if (!IS_ERR(mhcd->xo_clk)) {
1621 clk_disable_unprepare(mhcd->xo_clk);
1622 clk_put(mhcd->xo_clk);
1623 } else {
1624 msm_xo_put(mhcd->xo_handle);
1625 }
Manu Gautam91223e02011-11-08 15:27:22 +05301626 msm_ehci_vbus_power(mhcd, 0);
1627 msm_ehci_init_vbus(mhcd, 0);
1628 msm_ehci_ldo_enable(mhcd, 0);
1629 msm_ehci_ldo_init(mhcd, 0);
1630 msm_ehci_init_vddcx(mhcd, 0);
1631
1632 msm_ehci_init_clocks(mhcd, 0);
Hemant Kumar153f9972013-06-19 16:49:45 -07001633 wakeup_source_trash(&mhcd->ws);
Manu Gautam91223e02011-11-08 15:27:22 +05301634 iounmap(hcd->regs);
1635 usb_put_hcd(hcd);
1636
Rajkumar Raghupathyad8d68e2013-06-06 17:48:39 +05301637#if defined(CONFIG_DEBUG_FS)
1638 debugfs_remove_recursive(dent_ehci);
1639#endif
Manu Gautam91223e02011-11-08 15:27:22 +05301640 return 0;
1641}
1642
1643#ifdef CONFIG_PM_SLEEP
1644static int ehci_msm2_pm_suspend(struct device *dev)
1645{
1646 struct usb_hcd *hcd = dev_get_drvdata(dev);
1647 struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
1648
1649 dev_dbg(dev, "ehci-msm2 PM suspend\n");
1650
1651 if (device_may_wakeup(dev))
1652 enable_irq_wake(hcd->irq);
1653
1654 return msm_ehci_suspend(mhcd);
1655
1656}
1657
1658static int ehci_msm2_pm_resume(struct device *dev)
1659{
1660 int ret;
1661 struct usb_hcd *hcd = dev_get_drvdata(dev);
1662 struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
1663
1664 dev_dbg(dev, "ehci-msm2 PM resume\n");
1665
1666 if (device_may_wakeup(dev))
1667 disable_irq_wake(hcd->irq);
1668
1669 ret = msm_ehci_resume(mhcd);
1670 if (ret)
1671 return ret;
1672
1673 /* Bring the device to full powered state upon system resume */
1674 pm_runtime_disable(dev);
1675 pm_runtime_set_active(dev);
1676 pm_runtime_enable(dev);
1677
1678 return 0;
1679}
1680#endif
1681
1682#ifdef CONFIG_PM_RUNTIME
1683static int ehci_msm2_runtime_idle(struct device *dev)
1684{
1685 dev_dbg(dev, "EHCI runtime idle\n");
1686
1687 return 0;
1688}
1689
1690static int ehci_msm2_runtime_suspend(struct device *dev)
1691{
1692 struct usb_hcd *hcd = dev_get_drvdata(dev);
1693 struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
1694
1695 dev_dbg(dev, "EHCI runtime suspend\n");
1696 return msm_ehci_suspend(mhcd);
1697}
1698
1699static int ehci_msm2_runtime_resume(struct device *dev)
1700{
1701 struct usb_hcd *hcd = dev_get_drvdata(dev);
1702 struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
1703
1704 dev_dbg(dev, "EHCI runtime resume\n");
1705 return msm_ehci_resume(mhcd);
1706}
1707#endif
1708
1709#ifdef CONFIG_PM
1710static const struct dev_pm_ops ehci_msm2_dev_pm_ops = {
1711 SET_SYSTEM_SLEEP_PM_OPS(ehci_msm2_pm_suspend, ehci_msm2_pm_resume)
1712 SET_RUNTIME_PM_OPS(ehci_msm2_runtime_suspend, ehci_msm2_runtime_resume,
1713 ehci_msm2_runtime_idle)
1714};
1715#endif
1716
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +05301717static const struct of_device_id ehci_msm2_dt_match[] = {
1718 { .compatible = "qcom,ehci-host",
1719 },
1720 {}
1721};
1722
Manu Gautam91223e02011-11-08 15:27:22 +05301723static struct platform_driver ehci_msm2_driver = {
1724 .probe = ehci_msm2_probe,
1725 .remove = __devexit_p(ehci_msm2_remove),
1726 .driver = {
1727 .name = "msm_ehci_host",
1728#ifdef CONFIG_PM
1729 .pm = &ehci_msm2_dev_pm_ops,
1730#endif
Vijayavardhan Vennapusa1f5da0b2013-01-08 20:03:57 +05301731 .of_match_table = ehci_msm2_dt_match,
Manu Gautam91223e02011-11-08 15:27:22 +05301732 },
1733};