blob: ead2976571c94eb976a06dbc69afdeaca5bfb8bf [file] [log] [blame]
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +053012 */
13
14#include <linux/module.h>
15#include <linux/device.h>
16#include <linux/platform_device.h>
17#include <linux/clk.h>
18#include <linux/slab.h>
19#include <linux/interrupt.h>
20#include <linux/err.h>
21#include <linux/delay.h>
22#include <linux/io.h>
23#include <linux/ioport.h>
24#include <linux/uaccess.h>
25#include <linux/debugfs.h>
26#include <linux/seq_file.h>
Pavankumar Kondeti87c01042010-12-07 17:53:58 +053027#include <linux/pm_runtime.h>
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +053028
29#include <linux/usb.h>
30#include <linux/usb/otg.h>
31#include <linux/usb/ulpi.h>
32#include <linux/usb/gadget.h>
33#include <linux/usb/hcd.h>
34#include <linux/usb/msm_hsusb.h>
35#include <linux/usb/msm_hsusb_hw.h>
Anji jonnala11aa5c42011-05-04 10:19:48 +053036#include <linux/regulator/consumer.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070037#include <linux/mfd/pm8xxx/pm8921-charger.h>
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +053038
39#include <mach/clk.h>
40
41#define MSM_USB_BASE (motg->regs)
42#define DRIVER_NAME "msm_otg"
43
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070044#ifdef CONFIG_USB_MSM_ACA
45static void msm_chg_enable_aca_det(struct msm_otg *motg);
46static void msm_chg_enable_aca_intr(struct msm_otg *motg);
47#else
48static inline bool msm_chg_aca_detect(struct msm_otg *motg)
49{
50 return false;
51}
52
53static inline void msm_chg_enable_aca_det(struct msm_otg *motg)
54{
55}
56static inline void msm_chg_enable_aca_intr(struct msm_otg *motg)
57{
58}
59static inline bool msm_chg_check_aca_intr(struct msm_otg *motg)
60{
61 return false;
62}
63#endif
64
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +053065#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
Anji jonnala11aa5c42011-05-04 10:19:48 +053066
67#define USB_PHY_3P3_VOL_MIN 3050000 /* uV */
68#define USB_PHY_3P3_VOL_MAX 3300000 /* uV */
69#define USB_PHY_3P3_HPM_LOAD 50000 /* uA */
70#define USB_PHY_3P3_LPM_LOAD 4000 /* uA */
71
72#define USB_PHY_1P8_VOL_MIN 1800000 /* uV */
73#define USB_PHY_1P8_VOL_MAX 1800000 /* uV */
74#define USB_PHY_1P8_HPM_LOAD 50000 /* uA */
75#define USB_PHY_1P8_LPM_LOAD 4000 /* uA */
76
77#define USB_PHY_VDD_DIG_VOL_MIN 1000000 /* uV */
78#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
79
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070080static struct msm_otg *the_msm_otg;
81
Anji jonnala11aa5c42011-05-04 10:19:48 +053082static struct regulator *hsusb_3p3;
83static struct regulator *hsusb_1p8;
84static struct regulator *hsusb_vddcx;
85
86static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init)
87{
88 int ret = 0;
89
90 if (init) {
91 hsusb_vddcx = regulator_get(motg->otg.dev, "HSUSB_VDDCX");
92 if (IS_ERR(hsusb_vddcx)) {
93 dev_err(motg->otg.dev, "unable to get hsusb vddcx\n");
94 return PTR_ERR(hsusb_vddcx);
95 }
96
97 ret = regulator_set_voltage(hsusb_vddcx,
98 USB_PHY_VDD_DIG_VOL_MIN,
99 USB_PHY_VDD_DIG_VOL_MAX);
100 if (ret) {
101 dev_err(motg->otg.dev, "unable to set the voltage "
102 "for hsusb vddcx\n");
103 regulator_put(hsusb_vddcx);
104 return ret;
105 }
106
107 ret = regulator_enable(hsusb_vddcx);
108 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700109 regulator_set_voltage(hsusb_vddcx, 0,
110 USB_PHY_VDD_DIG_VOL_MIN);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530111 regulator_put(hsusb_vddcx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700112 dev_err(motg->otg.dev, "unable to enable the hsusb vddcx\n");
113 return ret;
Anji jonnala11aa5c42011-05-04 10:19:48 +0530114 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700115
Anji jonnala11aa5c42011-05-04 10:19:48 +0530116 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700117
Anji jonnala11aa5c42011-05-04 10:19:48 +0530118 ret = regulator_disable(hsusb_vddcx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700119 if (ret) {
Anji jonnala11aa5c42011-05-04 10:19:48 +0530120 dev_err(motg->otg.dev, "unable to disable hsusb vddcx\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700121 return ret;
122 }
123
124 ret = regulator_set_voltage(hsusb_vddcx, 0,
125 USB_PHY_VDD_DIG_VOL_MIN);
126 if (ret) {
127 dev_err(motg->otg.dev, "unable to set the voltage"
128 "for hsusb vddcx\n");
129 return ret;
130 }
Anji jonnala11aa5c42011-05-04 10:19:48 +0530131
132 regulator_put(hsusb_vddcx);
133 }
134
135 return ret;
136}
137
138static int msm_hsusb_ldo_init(struct msm_otg *motg, int init)
139{
140 int rc = 0;
141
142 if (init) {
143 hsusb_3p3 = regulator_get(motg->otg.dev, "HSUSB_3p3");
144 if (IS_ERR(hsusb_3p3)) {
145 dev_err(motg->otg.dev, "unable to get hsusb 3p3\n");
146 return PTR_ERR(hsusb_3p3);
147 }
148
149 rc = regulator_set_voltage(hsusb_3p3, USB_PHY_3P3_VOL_MIN,
150 USB_PHY_3P3_VOL_MAX);
151 if (rc) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700152 dev_err(motg->otg.dev, "unable to set voltage level for"
153 "hsusb 3p3\n");
Anji jonnala11aa5c42011-05-04 10:19:48 +0530154 goto put_3p3;
155 }
156 hsusb_1p8 = regulator_get(motg->otg.dev, "HSUSB_1p8");
157 if (IS_ERR(hsusb_1p8)) {
158 dev_err(motg->otg.dev, "unable to get hsusb 1p8\n");
159 rc = PTR_ERR(hsusb_1p8);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700160 goto put_3p3_lpm;
Anji jonnala11aa5c42011-05-04 10:19:48 +0530161 }
162 rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN,
163 USB_PHY_1P8_VOL_MAX);
164 if (rc) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700165 dev_err(motg->otg.dev, "unable to set voltage level for"
166 "hsusb 1p8\n");
Anji jonnala11aa5c42011-05-04 10:19:48 +0530167 goto put_1p8;
168 }
169
170 return 0;
171 }
172
Anji jonnala11aa5c42011-05-04 10:19:48 +0530173put_1p8:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700174 regulator_set_voltage(hsusb_1p8, 0, USB_PHY_1P8_VOL_MAX);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530175 regulator_put(hsusb_1p8);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700176put_3p3_lpm:
177 regulator_set_voltage(hsusb_3p3, 0, USB_PHY_3P3_VOL_MAX);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530178put_3p3:
179 regulator_put(hsusb_3p3);
180 return rc;
181}
182
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530183#ifdef CONFIG_PM_SLEEP
184#define USB_PHY_SUSP_DIG_VOL 500000
185static int msm_hsusb_config_vddcx(int high)
186{
187 int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
188 int min_vol;
189 int ret;
190
191 if (high)
192 min_vol = USB_PHY_VDD_DIG_VOL_MIN;
193 else
194 min_vol = USB_PHY_SUSP_DIG_VOL;
195
196 ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
197 if (ret) {
198 pr_err("%s: unable to set the voltage for regulator "
199 "HSUSB_VDDCX\n", __func__);
200 return ret;
201 }
202
203 pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol);
204
205 return ret;
206}
207#endif
208
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700209static int msm_hsusb_ldo_enable(struct msm_otg *motg, int on)
Anji jonnala11aa5c42011-05-04 10:19:48 +0530210{
211 int ret = 0;
212
213 if (!hsusb_1p8 || IS_ERR(hsusb_1p8)) {
214 pr_err("%s: HSUSB_1p8 is not initialized\n", __func__);
215 return -ENODEV;
216 }
217
218 if (!hsusb_3p3 || IS_ERR(hsusb_3p3)) {
219 pr_err("%s: HSUSB_3p3 is not initialized\n", __func__);
220 return -ENODEV;
221 }
222
223 if (on) {
224 ret = regulator_set_optimum_mode(hsusb_1p8,
225 USB_PHY_1P8_HPM_LOAD);
226 if (ret < 0) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700227 pr_err("%s: Unable to set HPM of the regulator:"
Anji jonnala11aa5c42011-05-04 10:19:48 +0530228 "HSUSB_1p8\n", __func__);
229 return ret;
230 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700231
232 ret = regulator_enable(hsusb_1p8);
233 if (ret) {
234 dev_err(motg->otg.dev, "%s: unable to enable the hsusb 1p8\n",
235 __func__);
236 regulator_set_optimum_mode(hsusb_1p8, 0);
237 return ret;
238 }
239
Anji jonnala11aa5c42011-05-04 10:19:48 +0530240 ret = regulator_set_optimum_mode(hsusb_3p3,
241 USB_PHY_3P3_HPM_LOAD);
242 if (ret < 0) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700243 pr_err("%s: Unable to set HPM of the regulator:"
Anji jonnala11aa5c42011-05-04 10:19:48 +0530244 "HSUSB_3p3\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700245 regulator_set_optimum_mode(hsusb_1p8, 0);
246 regulator_disable(hsusb_1p8);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530247 return ret;
248 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700249
250 ret = regulator_enable(hsusb_3p3);
251 if (ret) {
252 dev_err(motg->otg.dev, "%s: unable to enable the hsusb 3p3\n",
253 __func__);
254 regulator_set_optimum_mode(hsusb_3p3, 0);
255 regulator_set_optimum_mode(hsusb_1p8, 0);
256 regulator_disable(hsusb_1p8);
257 return ret;
258 }
259
Anji jonnala11aa5c42011-05-04 10:19:48 +0530260 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700261 ret = regulator_disable(hsusb_1p8);
262 if (ret) {
263 dev_err(motg->otg.dev, "%s: unable to disable the hsusb 1p8\n",
264 __func__);
265 return ret;
266 }
267
268 ret = regulator_set_optimum_mode(hsusb_1p8, 0);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530269 if (ret < 0)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700270 pr_err("%s: Unable to set LPM of the regulator:"
Anji jonnala11aa5c42011-05-04 10:19:48 +0530271 "HSUSB_1p8\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700272
273 ret = regulator_disable(hsusb_3p3);
274 if (ret) {
275 dev_err(motg->otg.dev, "%s: unable to disable the hsusb 3p3\n",
276 __func__);
277 return ret;
278 }
279 ret = regulator_set_optimum_mode(hsusb_3p3, 0);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530280 if (ret < 0)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700281 pr_err("%s: Unable to set LPM of the regulator:"
Anji jonnala11aa5c42011-05-04 10:19:48 +0530282 "HSUSB_3p3\n", __func__);
283 }
284
285 pr_debug("reg (%s)\n", on ? "HPM" : "LPM");
286 return ret < 0 ? ret : 0;
287}
288
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530289static int ulpi_read(struct otg_transceiver *otg, u32 reg)
290{
291 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
292 int cnt = 0;
293
294 /* initiate read operation */
295 writel(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
296 USB_ULPI_VIEWPORT);
297
298 /* wait for completion */
299 while (cnt < ULPI_IO_TIMEOUT_USEC) {
300 if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN))
301 break;
302 udelay(1);
303 cnt++;
304 }
305
306 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
307 dev_err(otg->dev, "ulpi_read: timeout %08x\n",
308 readl(USB_ULPI_VIEWPORT));
309 return -ETIMEDOUT;
310 }
311 return ULPI_DATA_READ(readl(USB_ULPI_VIEWPORT));
312}
313
314static int ulpi_write(struct otg_transceiver *otg, u32 val, u32 reg)
315{
316 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
317 int cnt = 0;
318
319 /* initiate write operation */
320 writel(ULPI_RUN | ULPI_WRITE |
321 ULPI_ADDR(reg) | ULPI_DATA(val),
322 USB_ULPI_VIEWPORT);
323
324 /* wait for completion */
325 while (cnt < ULPI_IO_TIMEOUT_USEC) {
326 if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN))
327 break;
328 udelay(1);
329 cnt++;
330 }
331
332 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
333 dev_err(otg->dev, "ulpi_write: timeout\n");
334 return -ETIMEDOUT;
335 }
336 return 0;
337}
338
339static struct otg_io_access_ops msm_otg_io_ops = {
340 .read = ulpi_read,
341 .write = ulpi_write,
342};
343
344static void ulpi_init(struct msm_otg *motg)
345{
346 struct msm_otg_platform_data *pdata = motg->pdata;
347 int *seq = pdata->phy_init_seq;
348
349 if (!seq)
350 return;
351
352 while (seq[0] >= 0) {
353 dev_vdbg(motg->otg.dev, "ulpi: write 0x%02x to 0x%02x\n",
354 seq[0], seq[1]);
355 ulpi_write(&motg->otg, seq[0], seq[1]);
356 seq += 2;
357 }
358}
359
360static int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert)
361{
362 int ret;
363
364 if (assert) {
365 ret = clk_reset(motg->clk, CLK_RESET_ASSERT);
366 if (ret)
367 dev_err(motg->otg.dev, "usb hs_clk assert failed\n");
368 } else {
369 ret = clk_reset(motg->clk, CLK_RESET_DEASSERT);
370 if (ret)
371 dev_err(motg->otg.dev, "usb hs_clk deassert failed\n");
372 }
373 return ret;
374}
375
376static int msm_otg_phy_clk_reset(struct msm_otg *motg)
377{
378 int ret;
379
380 ret = clk_reset(motg->phy_reset_clk, CLK_RESET_ASSERT);
381 if (ret) {
382 dev_err(motg->otg.dev, "usb phy clk assert failed\n");
383 return ret;
384 }
385 usleep_range(10000, 12000);
386 ret = clk_reset(motg->phy_reset_clk, CLK_RESET_DEASSERT);
387 if (ret)
388 dev_err(motg->otg.dev, "usb phy clk deassert failed\n");
389 return ret;
390}
391
392static int msm_otg_phy_reset(struct msm_otg *motg)
393{
394 u32 val;
395 int ret;
396 int retries;
397
398 ret = msm_otg_link_clk_reset(motg, 1);
399 if (ret)
400 return ret;
401 ret = msm_otg_phy_clk_reset(motg);
402 if (ret)
403 return ret;
404 ret = msm_otg_link_clk_reset(motg, 0);
405 if (ret)
406 return ret;
407
408 val = readl(USB_PORTSC) & ~PORTSC_PTS_MASK;
409 writel(val | PORTSC_PTS_ULPI, USB_PORTSC);
410
411 for (retries = 3; retries > 0; retries--) {
412 ret = ulpi_write(&motg->otg, ULPI_FUNC_CTRL_SUSPENDM,
413 ULPI_CLR(ULPI_FUNC_CTRL));
414 if (!ret)
415 break;
416 ret = msm_otg_phy_clk_reset(motg);
417 if (ret)
418 return ret;
419 }
420 if (!retries)
421 return -ETIMEDOUT;
422
423 /* This reset calibrates the phy, if the above write succeeded */
424 ret = msm_otg_phy_clk_reset(motg);
425 if (ret)
426 return ret;
427
428 for (retries = 3; retries > 0; retries--) {
429 ret = ulpi_read(&motg->otg, ULPI_DEBUG);
430 if (ret != -ETIMEDOUT)
431 break;
432 ret = msm_otg_phy_clk_reset(motg);
433 if (ret)
434 return ret;
435 }
436 if (!retries)
437 return -ETIMEDOUT;
438
439 dev_info(motg->otg.dev, "phy_reset: success\n");
440 return 0;
441}
442
443#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
444static int msm_otg_reset(struct otg_transceiver *otg)
445{
446 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
447 struct msm_otg_platform_data *pdata = motg->pdata;
448 int cnt = 0;
449 int ret;
450 u32 val = 0;
451 u32 ulpi_val = 0;
452
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700453 clk_enable(motg->clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530454 ret = msm_otg_phy_reset(motg);
455 if (ret) {
456 dev_err(otg->dev, "phy_reset failed\n");
457 return ret;
458 }
459
460 ulpi_init(motg);
461
462 writel(USBCMD_RESET, USB_USBCMD);
463 while (cnt < LINK_RESET_TIMEOUT_USEC) {
464 if (!(readl(USB_USBCMD) & USBCMD_RESET))
465 break;
466 udelay(1);
467 cnt++;
468 }
469 if (cnt >= LINK_RESET_TIMEOUT_USEC)
470 return -ETIMEDOUT;
471
472 /* select ULPI phy */
473 writel(0x80000000, USB_PORTSC);
474
475 msleep(100);
476
477 writel(0x0, USB_AHBBURST);
478 writel(0x00, USB_AHBMODE);
479
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700480 /* Ensure that RESET operation is completed before turning off clock */
481 mb();
482 clk_disable(motg->clk);
483
484 val = readl_relaxed(USB_OTGSC);
485 if (pdata->mode == USB_OTG) {
486 ulpi_val = ULPI_INT_IDGRD | ULPI_INT_SESS_VALID;
487 val |= OTGSC_IDIE | OTGSC_BSVIE;
488 } else if (pdata->mode == USB_PERIPHERAL) {
489 ulpi_val = ULPI_INT_SESS_VALID;
490 val |= OTGSC_BSVIE;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530491 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700492 writel_relaxed(val, USB_OTGSC);
493 ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_RISE);
494 ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_FALL);
495
496 msm_chg_enable_aca_det(motg);
497 msm_chg_enable_aca_intr(motg);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530498
499 return 0;
500}
501
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530502#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
Pavankumar Kondeti70187732011-02-15 09:42:34 +0530503#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
504
505#ifdef CONFIG_PM_SLEEP
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530506static int msm_otg_suspend(struct msm_otg *motg)
507{
508 struct otg_transceiver *otg = &motg->otg;
509 struct usb_bus *bus = otg->host;
510 struct msm_otg_platform_data *pdata = motg->pdata;
511 int cnt = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700512 bool session_active;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530513
514 if (atomic_read(&motg->in_lpm))
515 return 0;
516
517 disable_irq(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700518 session_active = (otg->host && !test_bit(ID, &motg->inputs)) ||
519 test_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530520 /*
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530521 * Chipidea 45-nm PHY suspend sequence:
522 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530523 * Interrupt Latch Register auto-clear feature is not present
524 * in all PHY versions. Latch register is clear on read type.
525 * Clear latch register to avoid spurious wakeup from
526 * low power mode (LPM).
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530527 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530528 * PHY comparators are disabled when PHY enters into low power
529 * mode (LPM). Keep PHY comparators ON in LPM only when we expect
530 * VBUS/Id notifications from USB PHY. Otherwise turn off USB
531 * PHY comparators. This save significant amount of power.
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530532 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530533 * PLL is not turned off when PHY enters into low power mode (LPM).
534 * Disable PLL for maximum power savings.
535 */
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530536
537 if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) {
538 ulpi_read(otg, 0x14);
539 if (pdata->otg_control == OTG_PHY_CONTROL)
540 ulpi_write(otg, 0x01, 0x30);
541 ulpi_write(otg, 0x08, 0x09);
542 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530543
544 /*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700545 * Turn off the OTG comparators, if depends on PMIC for
546 * VBUS and ID notifications.
547 */
548 if ((motg->caps & ALLOW_PHY_COMP_DISABLE) && !session_active) {
549 ulpi_write(otg, OTG_COMP_DISABLE,
550 ULPI_SET(ULPI_PWR_CLK_MNG_REG));
551 motg->lpm_flags |= PHY_OTG_COMP_DISABLED;
552 }
553
554 /*
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530555 * PHY may take some time or even fail to enter into low power
556 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
557 * in failure case.
558 */
559 writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
560 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
561 if (readl(USB_PORTSC) & PORTSC_PHCD)
562 break;
563 udelay(1);
564 cnt++;
565 }
566
567 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
568 dev_err(otg->dev, "Unable to suspend PHY\n");
569 msm_otg_reset(otg);
570 enable_irq(motg->irq);
571 return -ETIMEDOUT;
572 }
573
574 /*
575 * PHY has capability to generate interrupt asynchronously in low
576 * power mode (LPM). This interrupt is level triggered. So USB IRQ
577 * line must be disabled till async interrupt enable bit is cleared
578 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
579 * block data communication from PHY.
580 */
581 writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);
582
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700583 if (motg->caps & ALLOW_PHY_RETENTION && !session_active) {
584 writel_relaxed(readl_relaxed(USB_PHY_CTRL) & ~PHY_RETEN,
585 USB_PHY_CTRL);
586 motg->lpm_flags |= PHY_RETENTIONED;
587 }
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530588
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700589 /* Ensure that above operation is completed before turning off clocks */
590 mb();
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530591 clk_disable(motg->pclk);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530592 if (motg->core_clk)
593 clk_disable(motg->core_clk);
594
Anji jonnala0f73cac2011-05-04 10:19:46 +0530595 if (!IS_ERR(motg->pclk_src))
596 clk_disable(motg->pclk_src);
597
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700598 if (motg->caps & ALLOW_PHY_POWER_COLLAPSE && !session_active) {
599 msm_hsusb_ldo_enable(motg, 0);
600 motg->lpm_flags |= PHY_PWR_COLLAPSED;
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530601 }
602
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700603 if (motg->lpm_flags & PHY_RETENTIONED)
604 msm_hsusb_config_vddcx(0);
605
606 if (device_may_wakeup(otg->dev)) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530607 enable_irq_wake(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700608 if (motg->pdata->pmic_id_irq)
609 enable_irq_wake(motg->pdata->pmic_id_irq);
610 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530611 if (bus)
612 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
613
614 atomic_set(&motg->in_lpm, 1);
615 enable_irq(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700616 wake_unlock(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530617
618 dev_info(otg->dev, "USB in low power mode\n");
619
620 return 0;
621}
622
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530623static int msm_otg_resume(struct msm_otg *motg)
624{
625 struct otg_transceiver *otg = &motg->otg;
626 struct usb_bus *bus = otg->host;
627 int cnt = 0;
628 unsigned temp;
629
630 if (!atomic_read(&motg->in_lpm))
631 return 0;
632
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700633 wake_lock(&motg->wlock);
Anji jonnala0f73cac2011-05-04 10:19:46 +0530634 if (!IS_ERR(motg->pclk_src))
635 clk_enable(motg->pclk_src);
636
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530637 clk_enable(motg->pclk);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530638 if (motg->core_clk)
639 clk_enable(motg->core_clk);
640
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700641 if (motg->lpm_flags & PHY_PWR_COLLAPSED) {
642 msm_hsusb_ldo_enable(motg, 1);
643 motg->lpm_flags &= ~PHY_PWR_COLLAPSED;
644 }
645
646 if (motg->lpm_flags & PHY_RETENTIONED) {
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530647 msm_hsusb_config_vddcx(1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700648 writel_relaxed(readl_relaxed(USB_PHY_CTRL) | PHY_RETEN,
649 USB_PHY_CTRL);
650 motg->lpm_flags &= ~PHY_RETENTIONED;
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530651 }
652
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530653 temp = readl(USB_USBCMD);
654 temp &= ~ASYNC_INTR_CTRL;
655 temp &= ~ULPI_STP_CTRL;
656 writel(temp, USB_USBCMD);
657
658 /*
659 * PHY comes out of low power mode (LPM) in case of wakeup
660 * from asynchronous interrupt.
661 */
662 if (!(readl(USB_PORTSC) & PORTSC_PHCD))
663 goto skip_phy_resume;
664
665 writel(readl(USB_PORTSC) & ~PORTSC_PHCD, USB_PORTSC);
666 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
667 if (!(readl(USB_PORTSC) & PORTSC_PHCD))
668 break;
669 udelay(1);
670 cnt++;
671 }
672
673 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
674 /*
675 * This is a fatal error. Reset the link and
676 * PHY. USB state can not be restored. Re-insertion
677 * of USB cable is the only way to get USB working.
678 */
679 dev_err(otg->dev, "Unable to resume USB."
680 "Re-plugin the cable\n");
681 msm_otg_reset(otg);
682 }
683
684skip_phy_resume:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700685 /* Turn on the OTG comparators on resume */
686 if (motg->lpm_flags & PHY_OTG_COMP_DISABLED) {
687 ulpi_write(otg, OTG_COMP_DISABLE,
688 ULPI_CLR(ULPI_PWR_CLK_MNG_REG));
689 motg->lpm_flags &= ~PHY_OTG_COMP_DISABLED;
690 }
691 if (device_may_wakeup(otg->dev)) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530692 disable_irq_wake(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700693 if (motg->pdata->pmic_id_irq)
694 disable_irq_wake(motg->pdata->pmic_id_irq);
695 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530696 if (bus)
697 set_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
698
Pavankumar Kondeti2ce2c3a2011-05-02 11:56:33 +0530699 atomic_set(&motg->in_lpm, 0);
700
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530701 if (motg->async_int) {
702 motg->async_int = 0;
703 pm_runtime_put(otg->dev);
704 enable_irq(motg->irq);
705 }
706
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530707 dev_info(otg->dev, "USB exited from low power mode\n");
708
709 return 0;
710}
Pavankumar Kondeti70187732011-02-15 09:42:34 +0530711#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530712
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530713static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA)
714{
715 if (motg->cur_power == mA)
716 return;
717
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530718 dev_info(motg->otg.dev, "Avail curr from USB = %u\n", mA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700719 pm8921_charger_vbus_draw(mA);
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530720 motg->cur_power = mA;
721}
722
723static int msm_otg_set_power(struct otg_transceiver *otg, unsigned mA)
724{
725 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
726
727 /*
728 * Gadget driver uses set_power method to notify about the
729 * available current based on suspend/configured states.
730 *
731 * IDEV_CHG can be drawn irrespective of suspend/un-configured
732 * states when CDP/ACA is connected.
733 */
734 if (motg->chg_type == USB_SDP_CHARGER)
735 msm_otg_notify_charger(motg, mA);
736
737 return 0;
738}
739
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530740static void msm_otg_start_host(struct otg_transceiver *otg, int on)
741{
742 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
743 struct msm_otg_platform_data *pdata = motg->pdata;
744 struct usb_hcd *hcd;
745
746 if (!otg->host)
747 return;
748
749 hcd = bus_to_hcd(otg->host);
750
751 if (on) {
752 dev_dbg(otg->dev, "host on\n");
753
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530754 /*
755 * Some boards have a switch cotrolled by gpio
756 * to enable/disable internal HUB. Enable internal
757 * HUB before kicking the host.
758 */
759 if (pdata->setup_gpio)
760 pdata->setup_gpio(OTG_STATE_A_HOST);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530761 usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530762 } else {
763 dev_dbg(otg->dev, "host off\n");
764
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530765 usb_remove_hcd(hcd);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530766 if (pdata->setup_gpio)
767 pdata->setup_gpio(OTG_STATE_UNDEFINED);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530768 }
769}
770
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700771static int msm_otg_usbdev_notify(struct notifier_block *self,
772 unsigned long action, void *priv)
773{
774 struct msm_otg *motg = container_of(self, struct msm_otg, usbdev_nb);
775 struct usb_device *udev;
776
777 switch (action) {
778 case USB_DEVICE_ADD:
779 case USB_DEVICE_CONFIG:
780 udev = priv;
781 /*
782 * Interested in devices connected directly to the root hub.
783 * ACA dock can supply IDEV_CHG irrespective devices connected
784 * on the accessory port.
785 */
786 if (!udev->parent || udev->parent->parent ||
787 motg->chg_type == USB_ACA_DOCK_CHARGER)
788 break;
789 if (udev->actconfig)
790 motg->mA_port = udev->actconfig->desc.bMaxPower * 2;
791 else
792 motg->mA_port = IUNIT;
793
794 if (test_bit(ID_A, &motg->inputs))
795 msm_otg_notify_charger(motg, IDEV_CHG_MIN -
796 motg->mA_port);
797 break;
798 default:
799 break;
800 }
801 return NOTIFY_OK;
802}
803
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530804static int msm_otg_set_host(struct otg_transceiver *otg, struct usb_bus *host)
805{
806 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
807 struct usb_hcd *hcd;
808
809 /*
810 * Fail host registration if this board can support
811 * only peripheral configuration.
812 */
813 if (motg->pdata->mode == USB_PERIPHERAL) {
814 dev_info(otg->dev, "Host mode is not supported\n");
815 return -ENODEV;
816 }
817
818 if (!host) {
819 if (otg->state == OTG_STATE_A_HOST) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530820 pm_runtime_get_sync(otg->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700821 usb_unregister_notify(&motg->usbdev_nb);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530822 msm_otg_start_host(otg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700823 if (motg->pdata->vbus_power)
824 motg->pdata->vbus_power(0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530825 otg->host = NULL;
826 otg->state = OTG_STATE_UNDEFINED;
827 schedule_work(&motg->sm_work);
828 } else {
829 otg->host = NULL;
830 }
831
832 return 0;
833 }
834
835 hcd = bus_to_hcd(host);
836 hcd->power_budget = motg->pdata->power_budget;
837
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700838 motg->usbdev_nb.notifier_call = msm_otg_usbdev_notify;
839 usb_register_notify(&motg->usbdev_nb);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530840 otg->host = host;
841 dev_dbg(otg->dev, "host driver registered w/ tranceiver\n");
842
843 /*
844 * Kick the state machine work, if peripheral is not supported
845 * or peripheral is already registered with us.
846 */
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530847 if (motg->pdata->mode == USB_HOST || otg->gadget) {
848 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530849 schedule_work(&motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530850 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530851
852 return 0;
853}
854
855static void msm_otg_start_peripheral(struct otg_transceiver *otg, int on)
856{
857 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
858 struct msm_otg_platform_data *pdata = motg->pdata;
859
860 if (!otg->gadget)
861 return;
862
863 if (on) {
864 dev_dbg(otg->dev, "gadget on\n");
865 /*
866 * Some boards have a switch cotrolled by gpio
867 * to enable/disable internal HUB. Disable internal
868 * HUB before kicking the gadget.
869 */
870 if (pdata->setup_gpio)
871 pdata->setup_gpio(OTG_STATE_B_PERIPHERAL);
872 usb_gadget_vbus_connect(otg->gadget);
873 } else {
874 dev_dbg(otg->dev, "gadget off\n");
875 usb_gadget_vbus_disconnect(otg->gadget);
876 if (pdata->setup_gpio)
877 pdata->setup_gpio(OTG_STATE_UNDEFINED);
878 }
879
880}
881
882static int msm_otg_set_peripheral(struct otg_transceiver *otg,
883 struct usb_gadget *gadget)
884{
885 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
886
887 /*
888 * Fail peripheral registration if this board can support
889 * only host configuration.
890 */
891 if (motg->pdata->mode == USB_HOST) {
892 dev_info(otg->dev, "Peripheral mode is not supported\n");
893 return -ENODEV;
894 }
895
896 if (!gadget) {
897 if (otg->state == OTG_STATE_B_PERIPHERAL) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530898 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530899 msm_otg_start_peripheral(otg, 0);
900 otg->gadget = NULL;
901 otg->state = OTG_STATE_UNDEFINED;
902 schedule_work(&motg->sm_work);
903 } else {
904 otg->gadget = NULL;
905 }
906
907 return 0;
908 }
909 otg->gadget = gadget;
910 dev_dbg(otg->dev, "peripheral driver registered w/ tranceiver\n");
911
912 /*
913 * Kick the state machine work, if host is not supported
914 * or host is already registered with us.
915 */
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530916 if (motg->pdata->mode == USB_PERIPHERAL || otg->host) {
917 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530918 schedule_work(&motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530919 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530920
921 return 0;
922}
923
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700924#ifdef CONFIG_USB_MSM_ACA
925static bool msm_chg_aca_detect(struct msm_otg *motg)
926{
927 struct otg_transceiver *otg = &motg->otg;
928 u32 int_sts;
929 bool ret = false;
930
931 if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY)
932 goto out;
933
934 int_sts = ulpi_read(otg, 0x87);
935 switch (int_sts & 0x1C) {
936 case 0x08:
937 if (!test_and_set_bit(ID_A, &motg->inputs)) {
938 dev_dbg(otg->dev, "ID_A\n");
939 motg->chg_type = USB_ACA_A_CHARGER;
940 motg->chg_state = USB_CHG_STATE_DETECTED;
941 clear_bit(ID_B, &motg->inputs);
942 clear_bit(ID_C, &motg->inputs);
943 ret = true;
944 }
945 break;
946 case 0x0C:
947 if (!test_and_set_bit(ID_B, &motg->inputs)) {
948 dev_dbg(otg->dev, "ID_B\n");
949 motg->chg_type = USB_ACA_B_CHARGER;
950 motg->chg_state = USB_CHG_STATE_DETECTED;
951 clear_bit(ID_A, &motg->inputs);
952 clear_bit(ID_C, &motg->inputs);
953 ret = true;
954 }
955 break;
956 case 0x10:
957 if (!test_and_set_bit(ID_C, &motg->inputs)) {
958 dev_dbg(otg->dev, "ID_C\n");
959 motg->chg_type = USB_ACA_C_CHARGER;
960 motg->chg_state = USB_CHG_STATE_DETECTED;
961 clear_bit(ID_A, &motg->inputs);
962 clear_bit(ID_B, &motg->inputs);
963 ret = true;
964 }
965 break;
966 default:
967 ret = test_and_clear_bit(ID_A, &motg->inputs) |
968 test_and_clear_bit(ID_B, &motg->inputs) |
969 test_and_clear_bit(ID_C, &motg->inputs);
970 if (ret) {
971 dev_dbg(otg->dev, "ID A/B/C is no more\n");
972 motg->chg_type = USB_INVALID_CHARGER;
973 motg->chg_state = USB_CHG_STATE_UNDEFINED;
974 }
975 }
976out:
977 return ret;
978}
979
980static void msm_chg_enable_aca_det(struct msm_otg *motg)
981{
982 struct otg_transceiver *otg = &motg->otg;
983
984 switch (motg->pdata->phy_type) {
985 case SNPS_28NM_INTEGRATED_PHY:
986 /* ACA ID pin resistance detection enable */
987 ulpi_write(otg, 0x20, 0x85);
988 break;
989 default:
990 break;
991 }
992}
993
994static void msm_chg_enable_aca_intr(struct msm_otg *motg)
995{
996 struct otg_transceiver *otg = &motg->otg;
997
998 switch (motg->pdata->phy_type) {
999 case SNPS_28NM_INTEGRATED_PHY:
1000 /* Enables ACA Detection interrupt (on any RID change) */
1001 ulpi_write(otg, 0x20, 0x94);
1002 break;
1003 default:
1004 break;
1005 }
1006}
1007
1008static bool msm_chg_check_aca_intr(struct msm_otg *motg)
1009{
1010 struct otg_transceiver *otg = &motg->otg;
1011 bool ret = false;
1012
1013 switch (motg->pdata->phy_type) {
1014 case SNPS_28NM_INTEGRATED_PHY:
1015 if (ulpi_read(otg, 0x91) & 1) {
1016 dev_dbg(otg->dev, "RID change\n");
1017 ulpi_write(otg, 0x01, 0x92);
1018 ret = msm_chg_aca_detect(motg);
1019 }
1020 default:
1021 break;
1022 }
1023 return ret;
1024}
1025#endif
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301026static bool msm_chg_check_secondary_det(struct msm_otg *motg)
1027{
1028 struct otg_transceiver *otg = &motg->otg;
1029 u32 chg_det;
1030 bool ret = false;
1031
1032 switch (motg->pdata->phy_type) {
1033 case CI_45NM_INTEGRATED_PHY:
1034 chg_det = ulpi_read(otg, 0x34);
1035 ret = chg_det & (1 << 4);
1036 break;
1037 case SNPS_28NM_INTEGRATED_PHY:
1038 chg_det = ulpi_read(otg, 0x87);
1039 ret = chg_det & 1;
1040 break;
1041 default:
1042 break;
1043 }
1044 return ret;
1045}
1046
1047static void msm_chg_enable_secondary_det(struct msm_otg *motg)
1048{
1049 struct otg_transceiver *otg = &motg->otg;
1050 u32 chg_det;
1051
1052 switch (motg->pdata->phy_type) {
1053 case CI_45NM_INTEGRATED_PHY:
1054 chg_det = ulpi_read(otg, 0x34);
1055 /* Turn off charger block */
1056 chg_det |= ~(1 << 1);
1057 ulpi_write(otg, chg_det, 0x34);
1058 udelay(20);
1059 /* control chg block via ULPI */
1060 chg_det &= ~(1 << 3);
1061 ulpi_write(otg, chg_det, 0x34);
1062 /* put it in host mode for enabling D- source */
1063 chg_det &= ~(1 << 2);
1064 ulpi_write(otg, chg_det, 0x34);
1065 /* Turn on chg detect block */
1066 chg_det &= ~(1 << 1);
1067 ulpi_write(otg, chg_det, 0x34);
1068 udelay(20);
1069 /* enable chg detection */
1070 chg_det &= ~(1 << 0);
1071 ulpi_write(otg, chg_det, 0x34);
1072 break;
1073 case SNPS_28NM_INTEGRATED_PHY:
1074 /*
1075 * Configure DM as current source, DP as current sink
1076 * and enable battery charging comparators.
1077 */
1078 ulpi_write(otg, 0x8, 0x85);
1079 ulpi_write(otg, 0x2, 0x85);
1080 ulpi_write(otg, 0x1, 0x85);
1081 break;
1082 default:
1083 break;
1084 }
1085}
1086
1087static bool msm_chg_check_primary_det(struct msm_otg *motg)
1088{
1089 struct otg_transceiver *otg = &motg->otg;
1090 u32 chg_det;
1091 bool ret = false;
1092
1093 switch (motg->pdata->phy_type) {
1094 case CI_45NM_INTEGRATED_PHY:
1095 chg_det = ulpi_read(otg, 0x34);
1096 ret = chg_det & (1 << 4);
1097 break;
1098 case SNPS_28NM_INTEGRATED_PHY:
1099 chg_det = ulpi_read(otg, 0x87);
1100 ret = chg_det & 1;
1101 break;
1102 default:
1103 break;
1104 }
1105 return ret;
1106}
1107
1108static void msm_chg_enable_primary_det(struct msm_otg *motg)
1109{
1110 struct otg_transceiver *otg = &motg->otg;
1111 u32 chg_det;
1112
1113 switch (motg->pdata->phy_type) {
1114 case CI_45NM_INTEGRATED_PHY:
1115 chg_det = ulpi_read(otg, 0x34);
1116 /* enable chg detection */
1117 chg_det &= ~(1 << 0);
1118 ulpi_write(otg, chg_det, 0x34);
1119 break;
1120 case SNPS_28NM_INTEGRATED_PHY:
1121 /*
1122 * Configure DP as current source, DM as current sink
1123 * and enable battery charging comparators.
1124 */
1125 ulpi_write(otg, 0x2, 0x85);
1126 ulpi_write(otg, 0x1, 0x85);
1127 break;
1128 default:
1129 break;
1130 }
1131}
1132
1133static bool msm_chg_check_dcd(struct msm_otg *motg)
1134{
1135 struct otg_transceiver *otg = &motg->otg;
1136 u32 line_state;
1137 bool ret = false;
1138
1139 switch (motg->pdata->phy_type) {
1140 case CI_45NM_INTEGRATED_PHY:
1141 line_state = ulpi_read(otg, 0x15);
1142 ret = !(line_state & 1);
1143 break;
1144 case SNPS_28NM_INTEGRATED_PHY:
1145 line_state = ulpi_read(otg, 0x87);
1146 ret = line_state & 2;
1147 break;
1148 default:
1149 break;
1150 }
1151 return ret;
1152}
1153
1154static void msm_chg_disable_dcd(struct msm_otg *motg)
1155{
1156 struct otg_transceiver *otg = &motg->otg;
1157 u32 chg_det;
1158
1159 switch (motg->pdata->phy_type) {
1160 case CI_45NM_INTEGRATED_PHY:
1161 chg_det = ulpi_read(otg, 0x34);
1162 chg_det &= ~(1 << 5);
1163 ulpi_write(otg, chg_det, 0x34);
1164 break;
1165 case SNPS_28NM_INTEGRATED_PHY:
1166 ulpi_write(otg, 0x10, 0x86);
1167 break;
1168 default:
1169 break;
1170 }
1171}
1172
1173static void msm_chg_enable_dcd(struct msm_otg *motg)
1174{
1175 struct otg_transceiver *otg = &motg->otg;
1176 u32 chg_det;
1177
1178 switch (motg->pdata->phy_type) {
1179 case CI_45NM_INTEGRATED_PHY:
1180 chg_det = ulpi_read(otg, 0x34);
1181 /* Turn on D+ current source */
1182 chg_det |= (1 << 5);
1183 ulpi_write(otg, chg_det, 0x34);
1184 break;
1185 case SNPS_28NM_INTEGRATED_PHY:
1186 /* Data contact detection enable */
1187 ulpi_write(otg, 0x10, 0x85);
1188 break;
1189 default:
1190 break;
1191 }
1192}
1193
1194static void msm_chg_block_on(struct msm_otg *motg)
1195{
1196 struct otg_transceiver *otg = &motg->otg;
1197 u32 func_ctrl, chg_det;
1198
1199 /* put the controller in non-driving mode */
1200 func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
1201 func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
1202 func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
1203 ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
1204
1205 switch (motg->pdata->phy_type) {
1206 case CI_45NM_INTEGRATED_PHY:
1207 chg_det = ulpi_read(otg, 0x34);
1208 /* control chg block via ULPI */
1209 chg_det &= ~(1 << 3);
1210 ulpi_write(otg, chg_det, 0x34);
1211 /* Turn on chg detect block */
1212 chg_det &= ~(1 << 1);
1213 ulpi_write(otg, chg_det, 0x34);
1214 udelay(20);
1215 break;
1216 case SNPS_28NM_INTEGRATED_PHY:
1217 /* Clear charger detecting control bits */
1218 ulpi_write(otg, 0x3F, 0x86);
1219 /* Clear alt interrupt latch and enable bits */
1220 ulpi_write(otg, 0x1F, 0x92);
1221 ulpi_write(otg, 0x1F, 0x95);
1222 udelay(100);
1223 break;
1224 default:
1225 break;
1226 }
1227}
1228
1229static void msm_chg_block_off(struct msm_otg *motg)
1230{
1231 struct otg_transceiver *otg = &motg->otg;
1232 u32 func_ctrl, chg_det;
1233
1234 switch (motg->pdata->phy_type) {
1235 case CI_45NM_INTEGRATED_PHY:
1236 chg_det = ulpi_read(otg, 0x34);
1237 /* Turn off charger block */
1238 chg_det |= ~(1 << 1);
1239 ulpi_write(otg, chg_det, 0x34);
1240 break;
1241 case SNPS_28NM_INTEGRATED_PHY:
1242 /* Clear charger detecting control bits */
1243 ulpi_write(otg, 0x3F, 0x86);
1244 /* Clear alt interrupt latch and enable bits */
1245 ulpi_write(otg, 0x1F, 0x92);
1246 ulpi_write(otg, 0x1F, 0x95);
1247 break;
1248 default:
1249 break;
1250 }
1251
1252 /* put the controller in normal mode */
1253 func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
1254 func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
1255 func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
1256 ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
1257}
1258
1259#define MSM_CHG_DCD_POLL_TIME (100 * HZ/1000) /* 100 msec */
1260#define MSM_CHG_DCD_MAX_RETRIES 6 /* Tdcd_tmout = 6 * 100 msec */
1261#define MSM_CHG_PRIMARY_DET_TIME (40 * HZ/1000) /* TVDPSRC_ON */
1262#define MSM_CHG_SECONDARY_DET_TIME (40 * HZ/1000) /* TVDMSRC_ON */
1263static void msm_chg_detect_work(struct work_struct *w)
1264{
1265 struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
1266 struct otg_transceiver *otg = &motg->otg;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001267 bool is_dcd, tmout, vout, is_aca;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301268 unsigned long delay;
1269
1270 dev_dbg(otg->dev, "chg detection work\n");
1271 switch (motg->chg_state) {
1272 case USB_CHG_STATE_UNDEFINED:
1273 pm_runtime_get_sync(otg->dev);
1274 msm_chg_block_on(motg);
1275 msm_chg_enable_dcd(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001276 msm_chg_enable_aca_det(motg);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301277 motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
1278 motg->dcd_retries = 0;
1279 delay = MSM_CHG_DCD_POLL_TIME;
1280 break;
1281 case USB_CHG_STATE_WAIT_FOR_DCD:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001282 is_aca = msm_chg_aca_detect(motg);
1283 if (is_aca) {
1284 /*
1285 * ID_A can be ACA dock too. continue
1286 * primary detection after DCD.
1287 */
1288 if (test_bit(ID_A, &motg->inputs)) {
1289 motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
1290 } else {
1291 delay = 0;
1292 break;
1293 }
1294 }
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301295 is_dcd = msm_chg_check_dcd(motg);
1296 tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES;
1297 if (is_dcd || tmout) {
1298 msm_chg_disable_dcd(motg);
1299 msm_chg_enable_primary_det(motg);
1300 delay = MSM_CHG_PRIMARY_DET_TIME;
1301 motg->chg_state = USB_CHG_STATE_DCD_DONE;
1302 } else {
1303 delay = MSM_CHG_DCD_POLL_TIME;
1304 }
1305 break;
1306 case USB_CHG_STATE_DCD_DONE:
1307 vout = msm_chg_check_primary_det(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001308 is_aca = msm_chg_aca_detect(motg);
1309 if (is_aca) {
1310 if (vout && test_bit(ID_A, &motg->inputs))
1311 motg->chg_type = USB_ACA_DOCK_CHARGER;
1312 delay = 0;
1313 break;
1314 }
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301315 if (vout) {
1316 msm_chg_enable_secondary_det(motg);
1317 delay = MSM_CHG_SECONDARY_DET_TIME;
1318 motg->chg_state = USB_CHG_STATE_PRIMARY_DONE;
1319 } else {
1320 motg->chg_type = USB_SDP_CHARGER;
1321 motg->chg_state = USB_CHG_STATE_DETECTED;
1322 delay = 0;
1323 }
1324 break;
1325 case USB_CHG_STATE_PRIMARY_DONE:
1326 vout = msm_chg_check_secondary_det(motg);
1327 if (vout)
1328 motg->chg_type = USB_DCP_CHARGER;
1329 else
1330 motg->chg_type = USB_CDP_CHARGER;
1331 motg->chg_state = USB_CHG_STATE_SECONDARY_DONE;
1332 /* fall through */
1333 case USB_CHG_STATE_SECONDARY_DONE:
1334 motg->chg_state = USB_CHG_STATE_DETECTED;
1335 case USB_CHG_STATE_DETECTED:
1336 msm_chg_block_off(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001337 msm_chg_enable_aca_det(motg);
1338 msm_chg_enable_aca_intr(motg);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301339 dev_dbg(otg->dev, "charger = %d\n", motg->chg_type);
1340 schedule_work(&motg->sm_work);
1341 return;
1342 default:
1343 return;
1344 }
1345
1346 schedule_delayed_work(&motg->chg_work, delay);
1347}
1348
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301349/*
1350 * We support OTG, Peripheral only and Host only configurations. In case
1351 * of OTG, mode switch (host-->peripheral/peripheral-->host) can happen
1352 * via Id pin status or user request (debugfs). Id/BSV interrupts are not
1353 * enabled when switch is controlled by user and default mode is supplied
1354 * by board file, which can be changed by userspace later.
1355 */
1356static void msm_otg_init_sm(struct msm_otg *motg)
1357{
1358 struct msm_otg_platform_data *pdata = motg->pdata;
1359 u32 otgsc = readl(USB_OTGSC);
1360
1361 switch (pdata->mode) {
1362 case USB_OTG:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001363 if (pdata->otg_control == OTG_USER_CONTROL) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301364 if (pdata->default_mode == USB_HOST) {
1365 clear_bit(ID, &motg->inputs);
1366 } else if (pdata->default_mode == USB_PERIPHERAL) {
1367 set_bit(ID, &motg->inputs);
1368 set_bit(B_SESS_VLD, &motg->inputs);
1369 } else {
1370 set_bit(ID, &motg->inputs);
1371 clear_bit(B_SESS_VLD, &motg->inputs);
1372 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001373 } else {
1374 if (otgsc & OTGSC_ID)
1375 set_bit(ID, &motg->inputs);
1376 else
1377 clear_bit(ID, &motg->inputs);
1378
1379 if (otgsc & OTGSC_BSV)
1380 set_bit(B_SESS_VLD, &motg->inputs);
1381 else
1382 clear_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301383 }
1384 break;
1385 case USB_HOST:
1386 clear_bit(ID, &motg->inputs);
1387 break;
1388 case USB_PERIPHERAL:
1389 set_bit(ID, &motg->inputs);
1390 if (otgsc & OTGSC_BSV)
1391 set_bit(B_SESS_VLD, &motg->inputs);
1392 else
1393 clear_bit(B_SESS_VLD, &motg->inputs);
1394 break;
1395 default:
1396 break;
1397 }
1398}
1399
1400static void msm_otg_sm_work(struct work_struct *w)
1401{
1402 struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
1403 struct otg_transceiver *otg = &motg->otg;
1404
1405 switch (otg->state) {
1406 case OTG_STATE_UNDEFINED:
1407 dev_dbg(otg->dev, "OTG_STATE_UNDEFINED state\n");
1408 msm_otg_reset(otg);
1409 msm_otg_init_sm(motg);
1410 otg->state = OTG_STATE_B_IDLE;
1411 /* FALL THROUGH */
1412 case OTG_STATE_B_IDLE:
1413 dev_dbg(otg->dev, "OTG_STATE_B_IDLE state\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001414 if ((!test_bit(ID, &motg->inputs) ||
1415 test_bit(ID_A, &motg->inputs)) && otg->host) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301416 /* disable BSV bit */
1417 writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001418 if (motg->chg_type == USB_ACA_DOCK_CHARGER)
1419 msm_otg_notify_charger(motg,
1420 IDEV_CHG_MAX);
1421 else if (!test_bit(ID_A, &motg->inputs) &&
1422 motg->pdata->vbus_power)
1423 motg->pdata->vbus_power(1);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301424 msm_otg_start_host(otg, 1);
1425 otg->state = OTG_STATE_A_HOST;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301426 } else if (test_bit(B_SESS_VLD, &motg->inputs)) {
1427 switch (motg->chg_state) {
1428 case USB_CHG_STATE_UNDEFINED:
1429 msm_chg_detect_work(&motg->chg_work.work);
1430 break;
1431 case USB_CHG_STATE_DETECTED:
1432 switch (motg->chg_type) {
1433 case USB_DCP_CHARGER:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001434 case USB_ACA_B_CHARGER:
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301435 msm_otg_notify_charger(motg,
1436 IDEV_CHG_MAX);
1437 break;
1438 case USB_CDP_CHARGER:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001439 case USB_ACA_C_CHARGER:
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301440 msm_otg_notify_charger(motg,
1441 IDEV_CHG_MAX);
1442 msm_otg_start_peripheral(otg, 1);
1443 otg->state = OTG_STATE_B_PERIPHERAL;
1444 break;
1445 case USB_SDP_CHARGER:
1446 msm_otg_notify_charger(motg, IUNIT);
1447 msm_otg_start_peripheral(otg, 1);
1448 otg->state = OTG_STATE_B_PERIPHERAL;
1449 break;
1450 default:
1451 break;
1452 }
1453 break;
1454 default:
1455 break;
1456 }
1457 } else {
1458 /*
1459 * If charger detection work is pending, decrement
1460 * the pm usage counter to balance with the one that
1461 * is incremented in charger detection work.
1462 */
1463 if (cancel_delayed_work_sync(&motg->chg_work)) {
1464 pm_runtime_put_sync(otg->dev);
1465 msm_otg_reset(otg);
1466 }
1467 msm_otg_notify_charger(motg, 0);
1468 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1469 motg->chg_type = USB_INVALID_CHARGER;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301470 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301471 pm_runtime_put_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301472 break;
1473 case OTG_STATE_B_PERIPHERAL:
1474 dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n");
1475 if (!test_bit(B_SESS_VLD, &motg->inputs) ||
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001476 !test_bit(ID, &motg->inputs) ||
1477 !test_bit(ID_C, &motg->inputs)) {
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301478 msm_otg_notify_charger(motg, 0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301479 msm_otg_start_peripheral(otg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001480 if (!test_bit(ID_B, &motg->inputs) &&
1481 !test_bit(ID_A, &motg->inputs)) {
1482 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1483 motg->chg_type = USB_INVALID_CHARGER;
1484 }
1485 otg->state = OTG_STATE_B_IDLE;
1486 msm_otg_reset(otg);
1487 schedule_work(w);
1488 } else if (test_bit(ID_C, &motg->inputs)) {
1489 msm_otg_notify_charger(motg, IDEV_CHG_MAX);
1490 pm_runtime_put_sync(otg->dev);
1491 }
1492 break;
1493 case OTG_STATE_A_HOST:
1494 dev_dbg(otg->dev, "OTG_STATE_A_HOST state\n");
1495 if (test_bit(ID, &motg->inputs) &&
1496 !test_bit(ID_A, &motg->inputs)) {
1497 msm_otg_start_host(otg, 0);
1498 writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
1499 if (motg->pdata->vbus_power)
1500 motg->pdata->vbus_power(0);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301501 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1502 motg->chg_type = USB_INVALID_CHARGER;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301503 otg->state = OTG_STATE_B_IDLE;
1504 msm_otg_reset(otg);
1505 schedule_work(w);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001506 } else if (test_bit(ID_A, &motg->inputs)) {
1507 writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
1508 if (motg->pdata->vbus_power)
1509 motg->pdata->vbus_power(0);
1510 msm_otg_notify_charger(motg,
1511 IDEV_CHG_MIN - motg->mA_port);
1512 pm_runtime_put_sync(otg->dev);
1513 } else if (!test_bit(ID, &motg->inputs)) {
1514 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1515 motg->chg_type = USB_INVALID_CHARGER;
1516 msm_otg_notify_charger(motg, 0);
1517 writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
1518 if (motg->pdata->vbus_power)
1519 motg->pdata->vbus_power(1);
1520 pm_runtime_put_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301521 }
1522 break;
1523 default:
1524 break;
1525 }
1526}
1527
1528static irqreturn_t msm_otg_irq(int irq, void *data)
1529{
1530 struct msm_otg *motg = data;
1531 struct otg_transceiver *otg = &motg->otg;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001532 u32 otgsc = 0, usbsts;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301533
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301534 if (atomic_read(&motg->in_lpm)) {
1535 disable_irq_nosync(irq);
1536 motg->async_int = 1;
1537 pm_runtime_get(otg->dev);
1538 return IRQ_HANDLED;
1539 }
1540
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001541 usbsts = readl(USB_USBSTS);
1542 if ((usbsts & PHY_ALT_INT)) {
1543 writel(PHY_ALT_INT, USB_USBSTS);
1544 if (msm_chg_check_aca_intr(motg)) {
1545 pm_runtime_get_noresume(otg->dev);
1546 schedule_work(&motg->sm_work);
1547 }
1548 return IRQ_HANDLED;
1549 }
1550
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301551 otgsc = readl(USB_OTGSC);
1552 if (!(otgsc & (OTGSC_IDIS | OTGSC_BSVIS)))
1553 return IRQ_NONE;
1554
1555 if ((otgsc & OTGSC_IDIS) && (otgsc & OTGSC_IDIE)) {
1556 if (otgsc & OTGSC_ID)
1557 set_bit(ID, &motg->inputs);
1558 else
1559 clear_bit(ID, &motg->inputs);
1560 dev_dbg(otg->dev, "ID set/clear\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001561 schedule_work(&motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301562 pm_runtime_get_noresume(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301563 } else if ((otgsc & OTGSC_BSVIS) && (otgsc & OTGSC_BSVIE)) {
1564 if (otgsc & OTGSC_BSV)
1565 set_bit(B_SESS_VLD, &motg->inputs);
1566 else
1567 clear_bit(B_SESS_VLD, &motg->inputs);
1568 dev_dbg(otg->dev, "BSV set/clear\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001569 schedule_work(&motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301570 pm_runtime_get_noresume(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301571 }
1572
1573 writel(otgsc, USB_OTGSC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001574 return IRQ_HANDLED;
1575}
1576
1577static void msm_otg_set_vbus_state(int online)
1578{
1579 struct msm_otg *motg = the_msm_otg;
1580
1581 /* We depend on PMIC for only VBUS ON interrupt */
1582 if (!atomic_read(&motg->in_lpm) || !online)
1583 return;
1584
1585 /*
1586 * Let interrupt handler take care of resuming
1587 * the hardware.
1588 */
1589 msm_otg_irq(motg->irq, (void *) motg);
1590}
1591
1592static irqreturn_t msm_pmic_id_irq(int irq, void *data)
1593{
1594 struct msm_otg *motg = data;
1595
1596 if (atomic_read(&motg->in_lpm) && !motg->async_int)
1597 msm_otg_irq(motg->irq, motg);
1598
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301599 return IRQ_HANDLED;
1600}
1601
1602static int msm_otg_mode_show(struct seq_file *s, void *unused)
1603{
1604 struct msm_otg *motg = s->private;
1605 struct otg_transceiver *otg = &motg->otg;
1606
1607 switch (otg->state) {
1608 case OTG_STATE_A_HOST:
1609 seq_printf(s, "host\n");
1610 break;
1611 case OTG_STATE_B_PERIPHERAL:
1612 seq_printf(s, "peripheral\n");
1613 break;
1614 default:
1615 seq_printf(s, "none\n");
1616 break;
1617 }
1618
1619 return 0;
1620}
1621
1622static int msm_otg_mode_open(struct inode *inode, struct file *file)
1623{
1624 return single_open(file, msm_otg_mode_show, inode->i_private);
1625}
1626
1627static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf,
1628 size_t count, loff_t *ppos)
1629{
Pavankumar Kondetie2904ee2011-02-15 09:42:35 +05301630 struct seq_file *s = file->private_data;
1631 struct msm_otg *motg = s->private;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301632 char buf[16];
1633 struct otg_transceiver *otg = &motg->otg;
1634 int status = count;
1635 enum usb_mode_type req_mode;
1636
1637 memset(buf, 0x00, sizeof(buf));
1638
1639 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) {
1640 status = -EFAULT;
1641 goto out;
1642 }
1643
1644 if (!strncmp(buf, "host", 4)) {
1645 req_mode = USB_HOST;
1646 } else if (!strncmp(buf, "peripheral", 10)) {
1647 req_mode = USB_PERIPHERAL;
1648 } else if (!strncmp(buf, "none", 4)) {
1649 req_mode = USB_NONE;
1650 } else {
1651 status = -EINVAL;
1652 goto out;
1653 }
1654
1655 switch (req_mode) {
1656 case USB_NONE:
1657 switch (otg->state) {
1658 case OTG_STATE_A_HOST:
1659 case OTG_STATE_B_PERIPHERAL:
1660 set_bit(ID, &motg->inputs);
1661 clear_bit(B_SESS_VLD, &motg->inputs);
1662 break;
1663 default:
1664 goto out;
1665 }
1666 break;
1667 case USB_PERIPHERAL:
1668 switch (otg->state) {
1669 case OTG_STATE_B_IDLE:
1670 case OTG_STATE_A_HOST:
1671 set_bit(ID, &motg->inputs);
1672 set_bit(B_SESS_VLD, &motg->inputs);
1673 break;
1674 default:
1675 goto out;
1676 }
1677 break;
1678 case USB_HOST:
1679 switch (otg->state) {
1680 case OTG_STATE_B_IDLE:
1681 case OTG_STATE_B_PERIPHERAL:
1682 clear_bit(ID, &motg->inputs);
1683 break;
1684 default:
1685 goto out;
1686 }
1687 break;
1688 default:
1689 goto out;
1690 }
1691
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301692 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301693 schedule_work(&motg->sm_work);
1694out:
1695 return status;
1696}
1697
1698const struct file_operations msm_otg_mode_fops = {
1699 .open = msm_otg_mode_open,
1700 .read = seq_read,
1701 .write = msm_otg_mode_write,
1702 .llseek = seq_lseek,
1703 .release = single_release,
1704};
1705
1706static struct dentry *msm_otg_dbg_root;
1707static struct dentry *msm_otg_dbg_mode;
1708
1709static int msm_otg_debugfs_init(struct msm_otg *motg)
1710{
1711 msm_otg_dbg_root = debugfs_create_dir("msm_otg", NULL);
1712
1713 if (!msm_otg_dbg_root || IS_ERR(msm_otg_dbg_root))
1714 return -ENODEV;
1715
1716 msm_otg_dbg_mode = debugfs_create_file("mode", S_IRUGO | S_IWUSR,
1717 msm_otg_dbg_root, motg, &msm_otg_mode_fops);
1718 if (!msm_otg_dbg_mode) {
1719 debugfs_remove(msm_otg_dbg_root);
1720 msm_otg_dbg_root = NULL;
1721 return -ENODEV;
1722 }
1723
1724 return 0;
1725}
1726
1727static void msm_otg_debugfs_cleanup(void)
1728{
1729 debugfs_remove(msm_otg_dbg_mode);
1730 debugfs_remove(msm_otg_dbg_root);
1731}
1732
1733static int __init msm_otg_probe(struct platform_device *pdev)
1734{
1735 int ret = 0;
1736 struct resource *res;
1737 struct msm_otg *motg;
1738 struct otg_transceiver *otg;
1739
1740 dev_info(&pdev->dev, "msm_otg probe\n");
1741 if (!pdev->dev.platform_data) {
1742 dev_err(&pdev->dev, "No platform data given. Bailing out\n");
1743 return -ENODEV;
1744 }
1745
1746 motg = kzalloc(sizeof(struct msm_otg), GFP_KERNEL);
1747 if (!motg) {
1748 dev_err(&pdev->dev, "unable to allocate msm_otg\n");
1749 return -ENOMEM;
1750 }
1751
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001752 the_msm_otg = motg;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301753 motg->pdata = pdev->dev.platform_data;
1754 otg = &motg->otg;
1755 otg->dev = &pdev->dev;
1756
1757 motg->phy_reset_clk = clk_get(&pdev->dev, "usb_phy_clk");
1758 if (IS_ERR(motg->phy_reset_clk)) {
1759 dev_err(&pdev->dev, "failed to get usb_phy_clk\n");
1760 ret = PTR_ERR(motg->phy_reset_clk);
1761 goto free_motg;
1762 }
1763
1764 motg->clk = clk_get(&pdev->dev, "usb_hs_clk");
1765 if (IS_ERR(motg->clk)) {
1766 dev_err(&pdev->dev, "failed to get usb_hs_clk\n");
1767 ret = PTR_ERR(motg->clk);
1768 goto put_phy_reset_clk;
1769 }
Anji jonnala0f73cac2011-05-04 10:19:46 +05301770 clk_set_rate(motg->clk, 60000000);
1771
1772 /*
1773 * If USB Core is running its protocol engine based on CORE CLK,
1774 * CORE CLK must be running at >55Mhz for correct HSUSB
1775 * operation and USB core cannot tolerate frequency changes on
1776 * CORE CLK. For such USB cores, vote for maximum clk frequency
1777 * on pclk source
1778 */
1779 if (motg->pdata->pclk_src_name) {
1780 motg->pclk_src = clk_get(&pdev->dev,
1781 motg->pdata->pclk_src_name);
1782 if (IS_ERR(motg->pclk_src))
1783 goto put_clk;
1784 clk_set_rate(motg->pclk_src, INT_MAX);
1785 clk_enable(motg->pclk_src);
1786 } else
1787 motg->pclk_src = ERR_PTR(-ENOENT);
1788
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301789
1790 motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk");
1791 if (IS_ERR(motg->pclk)) {
1792 dev_err(&pdev->dev, "failed to get usb_hs_pclk\n");
1793 ret = PTR_ERR(motg->pclk);
Anji jonnala0f73cac2011-05-04 10:19:46 +05301794 goto put_pclk_src;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301795 }
1796
1797 /*
1798 * USB core clock is not present on all MSM chips. This
1799 * clock is introduced to remove the dependency on AXI
1800 * bus frequency.
1801 */
1802 motg->core_clk = clk_get(&pdev->dev, "usb_hs_core_clk");
1803 if (IS_ERR(motg->core_clk))
1804 motg->core_clk = NULL;
1805
1806 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1807 if (!res) {
1808 dev_err(&pdev->dev, "failed to get platform resource mem\n");
1809 ret = -ENODEV;
1810 goto put_core_clk;
1811 }
1812
1813 motg->regs = ioremap(res->start, resource_size(res));
1814 if (!motg->regs) {
1815 dev_err(&pdev->dev, "ioremap failed\n");
1816 ret = -ENOMEM;
1817 goto put_core_clk;
1818 }
1819 dev_info(&pdev->dev, "OTG regs = %p\n", motg->regs);
1820
1821 motg->irq = platform_get_irq(pdev, 0);
1822 if (!motg->irq) {
1823 dev_err(&pdev->dev, "platform_get_irq failed\n");
1824 ret = -ENODEV;
1825 goto free_regs;
1826 }
1827
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301828 clk_enable(motg->pclk);
Anji jonnala11aa5c42011-05-04 10:19:48 +05301829
1830 ret = msm_hsusb_init_vddcx(motg, 1);
1831 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001832 dev_err(&pdev->dev, "hsusb vddcx init failed\n");
Anji jonnala11aa5c42011-05-04 10:19:48 +05301833 goto free_regs;
1834 }
1835
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001836 ret = msm_hsusb_config_vddcx(1);
1837 if (ret) {
1838 dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
1839 goto free_init_vddcx;
1840 }
1841
Anji jonnala11aa5c42011-05-04 10:19:48 +05301842 ret = msm_hsusb_ldo_init(motg, 1);
1843 if (ret) {
1844 dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001845 goto free_init_vddcx;
Anji jonnala11aa5c42011-05-04 10:19:48 +05301846 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001847
1848 ret = msm_hsusb_ldo_enable(motg, 1);
Anji jonnala11aa5c42011-05-04 10:19:48 +05301849 if (ret) {
1850 dev_err(&pdev->dev, "hsusb vreg enable failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001851 goto free_ldo_init;
Anji jonnala11aa5c42011-05-04 10:19:48 +05301852 }
1853
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301854 if (motg->core_clk)
1855 clk_enable(motg->core_clk);
1856
1857 writel(0, USB_USBINTR);
1858 writel(0, USB_OTGSC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001859 /* Ensure that above STOREs are completed before enabling interrupts */
1860 mb();
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301861
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001862 wake_lock_init(&motg->wlock, WAKE_LOCK_SUSPEND, "msm_otg");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301863 INIT_WORK(&motg->sm_work, msm_otg_sm_work);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301864 INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301865 ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
1866 "msm_otg", motg);
1867 if (ret) {
1868 dev_err(&pdev->dev, "request irq failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001869 goto destroy_wlock;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301870 }
1871
1872 otg->init = msm_otg_reset;
1873 otg->set_host = msm_otg_set_host;
1874 otg->set_peripheral = msm_otg_set_peripheral;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301875 otg->set_power = msm_otg_set_power;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301876
1877 otg->io_ops = &msm_otg_io_ops;
1878
1879 ret = otg_set_transceiver(&motg->otg);
1880 if (ret) {
1881 dev_err(&pdev->dev, "otg_set_transceiver failed\n");
1882 goto free_irq;
1883 }
1884
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001885 if (motg->pdata->otg_control == OTG_PMIC_CONTROL) {
1886 if (motg->pdata->pmic_id_irq) {
1887 ret = request_irq(motg->pdata->pmic_id_irq,
1888 msm_pmic_id_irq,
1889 IRQF_TRIGGER_RISING |
1890 IRQF_TRIGGER_FALLING,
1891 "msm_otg", motg);
1892 if (ret) {
1893 dev_err(&pdev->dev, "request irq failed for PMIC ID\n");
1894 goto remove_otg;
1895 }
1896 } else {
1897 ret = -ENODEV;
1898 dev_err(&pdev->dev, "PMIC IRQ for ID notifications doesn't exist\n");
1899 goto remove_otg;
1900 }
1901 }
1902
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301903 platform_set_drvdata(pdev, motg);
1904 device_init_wakeup(&pdev->dev, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001905 motg->mA_port = IUNIT;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301906
1907 if (motg->pdata->mode == USB_OTG &&
1908 motg->pdata->otg_control == OTG_USER_CONTROL) {
1909 ret = msm_otg_debugfs_init(motg);
1910 if (ret)
1911 dev_dbg(&pdev->dev, "mode debugfs file is"
1912 "not available\n");
1913 }
1914
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001915 if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
1916 pm8921_charger_register_vbus_sn(&msm_otg_set_vbus_state);
1917
1918 if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
1919 motg->pdata->otg_control == OTG_PMIC_CONTROL &&
1920 motg->pdata->pmic_id_irq)
1921 motg->caps = ALLOW_PHY_POWER_COLLAPSE |
1922 ALLOW_PHY_RETENTION |
1923 ALLOW_PHY_COMP_DISABLE;
1924
1925 wake_lock(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301926 pm_runtime_set_active(&pdev->dev);
1927 pm_runtime_enable(&pdev->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301928
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301929 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001930
1931remove_otg:
1932 otg_set_transceiver(NULL);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301933free_irq:
1934 free_irq(motg->irq, motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001935destroy_wlock:
1936 wake_lock_destroy(&motg->wlock);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301937 clk_disable(motg->pclk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001938 msm_hsusb_ldo_enable(motg, 0);
1939free_ldo_init:
Anji jonnala11aa5c42011-05-04 10:19:48 +05301940 msm_hsusb_ldo_init(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001941free_init_vddcx:
Anji jonnala11aa5c42011-05-04 10:19:48 +05301942 msm_hsusb_init_vddcx(motg, 0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301943free_regs:
1944 iounmap(motg->regs);
1945put_core_clk:
1946 if (motg->core_clk)
1947 clk_put(motg->core_clk);
Anji jonnala0f73cac2011-05-04 10:19:46 +05301948put_pclk_src:
1949 if (!IS_ERR(motg->pclk_src)) {
1950 clk_disable(motg->pclk_src);
1951 clk_put(motg->pclk_src);
1952 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301953put_clk:
1954 clk_put(motg->clk);
1955put_phy_reset_clk:
1956 clk_put(motg->phy_reset_clk);
1957free_motg:
1958 kfree(motg);
1959 return ret;
1960}
1961
1962static int __devexit msm_otg_remove(struct platform_device *pdev)
1963{
1964 struct msm_otg *motg = platform_get_drvdata(pdev);
1965 struct otg_transceiver *otg = &motg->otg;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301966 int cnt = 0;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301967
1968 if (otg->host || otg->gadget)
1969 return -EBUSY;
1970
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001971 if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
1972 pm8921_charger_unregister_vbus_sn(0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301973 msm_otg_debugfs_cleanup();
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301974 cancel_delayed_work_sync(&motg->chg_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301975 cancel_work_sync(&motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301976
Pavankumar Kondeti70187732011-02-15 09:42:34 +05301977 pm_runtime_resume(&pdev->dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301978
1979 device_init_wakeup(&pdev->dev, 0);
1980 pm_runtime_disable(&pdev->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001981 wake_lock_destroy(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301982
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001983 if (motg->pdata->pmic_id_irq)
1984 free_irq(motg->pdata->pmic_id_irq, motg);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301985 otg_set_transceiver(NULL);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301986 free_irq(motg->irq, motg);
1987
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301988 /*
1989 * Put PHY in low power mode.
1990 */
1991 ulpi_read(otg, 0x14);
1992 ulpi_write(otg, 0x08, 0x09);
1993
1994 writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
1995 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
1996 if (readl(USB_PORTSC) & PORTSC_PHCD)
1997 break;
1998 udelay(1);
1999 cnt++;
2000 }
2001 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC)
2002 dev_err(otg->dev, "Unable to suspend PHY\n");
2003
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302004 clk_disable(motg->pclk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302005 if (motg->core_clk)
2006 clk_disable(motg->core_clk);
Anji jonnala0f73cac2011-05-04 10:19:46 +05302007 if (!IS_ERR(motg->pclk_src)) {
2008 clk_disable(motg->pclk_src);
2009 clk_put(motg->pclk_src);
2010 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002011 msm_hsusb_ldo_enable(motg, 0);
Anji jonnala11aa5c42011-05-04 10:19:48 +05302012 msm_hsusb_ldo_init(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002013 msm_hsusb_init_vddcx(motg, 0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302014
2015 iounmap(motg->regs);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302016 pm_runtime_set_suspended(&pdev->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302017
2018 clk_put(motg->phy_reset_clk);
2019 clk_put(motg->pclk);
2020 clk_put(motg->clk);
2021 if (motg->core_clk)
2022 clk_put(motg->core_clk);
2023
2024 kfree(motg);
2025
2026 return 0;
2027}
2028
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302029#ifdef CONFIG_PM_RUNTIME
2030static int msm_otg_runtime_idle(struct device *dev)
2031{
2032 struct msm_otg *motg = dev_get_drvdata(dev);
2033 struct otg_transceiver *otg = &motg->otg;
2034
2035 dev_dbg(dev, "OTG runtime idle\n");
2036
2037 /*
2038 * It is observed some times that a spurious interrupt
2039 * comes when PHY is put into LPM immediately after PHY reset.
2040 * This 1 sec delay also prevents entering into LPM immediately
2041 * after asynchronous interrupt.
2042 */
2043 if (otg->state != OTG_STATE_UNDEFINED)
2044 pm_schedule_suspend(dev, 1000);
2045
2046 return -EAGAIN;
2047}
2048
2049static int msm_otg_runtime_suspend(struct device *dev)
2050{
2051 struct msm_otg *motg = dev_get_drvdata(dev);
2052
2053 dev_dbg(dev, "OTG runtime suspend\n");
2054 return msm_otg_suspend(motg);
2055}
2056
2057static int msm_otg_runtime_resume(struct device *dev)
2058{
2059 struct msm_otg *motg = dev_get_drvdata(dev);
2060
2061 dev_dbg(dev, "OTG runtime resume\n");
2062 return msm_otg_resume(motg);
2063}
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302064#endif
2065
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302066#ifdef CONFIG_PM_SLEEP
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302067static int msm_otg_pm_suspend(struct device *dev)
2068{
2069 struct msm_otg *motg = dev_get_drvdata(dev);
2070
2071 dev_dbg(dev, "OTG PM suspend\n");
2072 return msm_otg_suspend(motg);
2073}
2074
2075static int msm_otg_pm_resume(struct device *dev)
2076{
2077 struct msm_otg *motg = dev_get_drvdata(dev);
2078 int ret;
2079
2080 dev_dbg(dev, "OTG PM resume\n");
2081
2082 ret = msm_otg_resume(motg);
2083 if (ret)
2084 return ret;
2085
2086 /*
2087 * Runtime PM Documentation recommends bringing the
2088 * device to full powered state upon resume.
2089 */
2090 pm_runtime_disable(dev);
2091 pm_runtime_set_active(dev);
2092 pm_runtime_enable(dev);
2093
2094 return 0;
2095}
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302096#endif
2097
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302098#ifdef CONFIG_PM
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302099static const struct dev_pm_ops msm_otg_dev_pm_ops = {
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302100 SET_SYSTEM_SLEEP_PM_OPS(msm_otg_pm_suspend, msm_otg_pm_resume)
2101 SET_RUNTIME_PM_OPS(msm_otg_runtime_suspend, msm_otg_runtime_resume,
2102 msm_otg_runtime_idle)
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302103};
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302104#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302105
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302106static struct platform_driver msm_otg_driver = {
2107 .remove = __devexit_p(msm_otg_remove),
2108 .driver = {
2109 .name = DRIVER_NAME,
2110 .owner = THIS_MODULE,
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302111#ifdef CONFIG_PM
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302112 .pm = &msm_otg_dev_pm_ops,
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302113#endif
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302114 },
2115};
2116
2117static int __init msm_otg_init(void)
2118{
2119 return platform_driver_probe(&msm_otg_driver, msm_otg_probe);
2120}
2121
2122static void __exit msm_otg_exit(void)
2123{
2124 platform_driver_unregister(&msm_otg_driver);
2125}
2126
2127module_init(msm_otg_init);
2128module_exit(msm_otg_exit);
2129
2130MODULE_LICENSE("GPL v2");
2131MODULE_DESCRIPTION("MSM USB transceiver driver");