blob: 1eb8511a41696fe9eab063bd813a3c4835fd0535 [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
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +053044#define ID_TIMER_FREQ (jiffies + msecs_to_jiffies(2000))
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +053045#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
Anji jonnala11aa5c42011-05-04 10:19:48 +053046
47#define USB_PHY_3P3_VOL_MIN 3050000 /* uV */
48#define USB_PHY_3P3_VOL_MAX 3300000 /* uV */
49#define USB_PHY_3P3_HPM_LOAD 50000 /* uA */
50#define USB_PHY_3P3_LPM_LOAD 4000 /* uA */
51
52#define USB_PHY_1P8_VOL_MIN 1800000 /* uV */
53#define USB_PHY_1P8_VOL_MAX 1800000 /* uV */
54#define USB_PHY_1P8_HPM_LOAD 50000 /* uA */
55#define USB_PHY_1P8_LPM_LOAD 4000 /* uA */
56
Vamsi Krishna132b2762011-11-11 16:09:20 -080057#define USB_PHY_VDD_DIG_VOL_MIN 1045000 /* uV */
Anji jonnala11aa5c42011-05-04 10:19:48 +053058#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
59
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070060static struct msm_otg *the_msm_otg;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +053061static bool debug_aca_enabled;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070062
Anji jonnala11aa5c42011-05-04 10:19:48 +053063static struct regulator *hsusb_3p3;
64static struct regulator *hsusb_1p8;
65static struct regulator *hsusb_vddcx;
66
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +053067static inline bool aca_enabled(void)
68{
69#ifdef CONFIG_USB_MSM_ACA
70 return true;
71#else
72 return debug_aca_enabled;
73#endif
74}
75
Anji jonnala11aa5c42011-05-04 10:19:48 +053076static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init)
77{
78 int ret = 0;
79
80 if (init) {
81 hsusb_vddcx = regulator_get(motg->otg.dev, "HSUSB_VDDCX");
82 if (IS_ERR(hsusb_vddcx)) {
83 dev_err(motg->otg.dev, "unable to get hsusb vddcx\n");
84 return PTR_ERR(hsusb_vddcx);
85 }
86
87 ret = regulator_set_voltage(hsusb_vddcx,
88 USB_PHY_VDD_DIG_VOL_MIN,
89 USB_PHY_VDD_DIG_VOL_MAX);
90 if (ret) {
91 dev_err(motg->otg.dev, "unable to set the voltage "
92 "for hsusb vddcx\n");
93 regulator_put(hsusb_vddcx);
94 return ret;
95 }
96
97 ret = regulator_enable(hsusb_vddcx);
98 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070099 regulator_set_voltage(hsusb_vddcx, 0,
100 USB_PHY_VDD_DIG_VOL_MIN);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530101 regulator_put(hsusb_vddcx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700102 dev_err(motg->otg.dev, "unable to enable the hsusb vddcx\n");
103 return ret;
Anji jonnala11aa5c42011-05-04 10:19:48 +0530104 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700105
Anji jonnala11aa5c42011-05-04 10:19:48 +0530106 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700107
Anji jonnala11aa5c42011-05-04 10:19:48 +0530108 ret = regulator_disable(hsusb_vddcx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700109 if (ret) {
Anji jonnala11aa5c42011-05-04 10:19:48 +0530110 dev_err(motg->otg.dev, "unable to disable hsusb vddcx\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700111 return ret;
112 }
113
114 ret = regulator_set_voltage(hsusb_vddcx, 0,
115 USB_PHY_VDD_DIG_VOL_MIN);
116 if (ret) {
117 dev_err(motg->otg.dev, "unable to set the voltage"
118 "for hsusb vddcx\n");
119 return ret;
120 }
Anji jonnala11aa5c42011-05-04 10:19:48 +0530121
122 regulator_put(hsusb_vddcx);
123 }
124
125 return ret;
126}
127
128static int msm_hsusb_ldo_init(struct msm_otg *motg, int init)
129{
130 int rc = 0;
131
132 if (init) {
133 hsusb_3p3 = regulator_get(motg->otg.dev, "HSUSB_3p3");
134 if (IS_ERR(hsusb_3p3)) {
135 dev_err(motg->otg.dev, "unable to get hsusb 3p3\n");
136 return PTR_ERR(hsusb_3p3);
137 }
138
139 rc = regulator_set_voltage(hsusb_3p3, USB_PHY_3P3_VOL_MIN,
140 USB_PHY_3P3_VOL_MAX);
141 if (rc) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700142 dev_err(motg->otg.dev, "unable to set voltage level for"
143 "hsusb 3p3\n");
Anji jonnala11aa5c42011-05-04 10:19:48 +0530144 goto put_3p3;
145 }
146 hsusb_1p8 = regulator_get(motg->otg.dev, "HSUSB_1p8");
147 if (IS_ERR(hsusb_1p8)) {
148 dev_err(motg->otg.dev, "unable to get hsusb 1p8\n");
149 rc = PTR_ERR(hsusb_1p8);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700150 goto put_3p3_lpm;
Anji jonnala11aa5c42011-05-04 10:19:48 +0530151 }
152 rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN,
153 USB_PHY_1P8_VOL_MAX);
154 if (rc) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700155 dev_err(motg->otg.dev, "unable to set voltage level for"
156 "hsusb 1p8\n");
Anji jonnala11aa5c42011-05-04 10:19:48 +0530157 goto put_1p8;
158 }
159
160 return 0;
161 }
162
Anji jonnala11aa5c42011-05-04 10:19:48 +0530163put_1p8:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700164 regulator_set_voltage(hsusb_1p8, 0, USB_PHY_1P8_VOL_MAX);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530165 regulator_put(hsusb_1p8);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700166put_3p3_lpm:
167 regulator_set_voltage(hsusb_3p3, 0, USB_PHY_3P3_VOL_MAX);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530168put_3p3:
169 regulator_put(hsusb_3p3);
170 return rc;
171}
172
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530173#ifdef CONFIG_PM_SLEEP
174#define USB_PHY_SUSP_DIG_VOL 500000
175static int msm_hsusb_config_vddcx(int high)
176{
177 int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
178 int min_vol;
179 int ret;
180
181 if (high)
182 min_vol = USB_PHY_VDD_DIG_VOL_MIN;
183 else
184 min_vol = USB_PHY_SUSP_DIG_VOL;
185
186 ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
187 if (ret) {
188 pr_err("%s: unable to set the voltage for regulator "
189 "HSUSB_VDDCX\n", __func__);
190 return ret;
191 }
192
193 pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol);
194
195 return ret;
196}
Hemant Kumar8e7bd072011-08-01 14:14:24 -0700197#else
198static int msm_hsusb_config_vddcx(int high)
199{
200 return 0;
201}
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530202#endif
203
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700204static int msm_hsusb_ldo_enable(struct msm_otg *motg, int on)
Anji jonnala11aa5c42011-05-04 10:19:48 +0530205{
206 int ret = 0;
207
Pavankumar Kondeti68964c92011-10-27 14:58:56 +0530208 if (IS_ERR(hsusb_1p8)) {
Anji jonnala11aa5c42011-05-04 10:19:48 +0530209 pr_err("%s: HSUSB_1p8 is not initialized\n", __func__);
210 return -ENODEV;
211 }
212
Pavankumar Kondeti68964c92011-10-27 14:58:56 +0530213 if (IS_ERR(hsusb_3p3)) {
Anji jonnala11aa5c42011-05-04 10:19:48 +0530214 pr_err("%s: HSUSB_3p3 is not initialized\n", __func__);
215 return -ENODEV;
216 }
217
218 if (on) {
219 ret = regulator_set_optimum_mode(hsusb_1p8,
220 USB_PHY_1P8_HPM_LOAD);
221 if (ret < 0) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700222 pr_err("%s: Unable to set HPM of the regulator:"
Anji jonnala11aa5c42011-05-04 10:19:48 +0530223 "HSUSB_1p8\n", __func__);
224 return ret;
225 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700226
227 ret = regulator_enable(hsusb_1p8);
228 if (ret) {
229 dev_err(motg->otg.dev, "%s: unable to enable the hsusb 1p8\n",
230 __func__);
231 regulator_set_optimum_mode(hsusb_1p8, 0);
232 return ret;
233 }
234
Anji jonnala11aa5c42011-05-04 10:19:48 +0530235 ret = regulator_set_optimum_mode(hsusb_3p3,
236 USB_PHY_3P3_HPM_LOAD);
237 if (ret < 0) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700238 pr_err("%s: Unable to set HPM of the regulator:"
Anji jonnala11aa5c42011-05-04 10:19:48 +0530239 "HSUSB_3p3\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700240 regulator_set_optimum_mode(hsusb_1p8, 0);
241 regulator_disable(hsusb_1p8);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530242 return ret;
243 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700244
245 ret = regulator_enable(hsusb_3p3);
246 if (ret) {
247 dev_err(motg->otg.dev, "%s: unable to enable the hsusb 3p3\n",
248 __func__);
249 regulator_set_optimum_mode(hsusb_3p3, 0);
250 regulator_set_optimum_mode(hsusb_1p8, 0);
251 regulator_disable(hsusb_1p8);
252 return ret;
253 }
254
Anji jonnala11aa5c42011-05-04 10:19:48 +0530255 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700256 ret = regulator_disable(hsusb_1p8);
257 if (ret) {
258 dev_err(motg->otg.dev, "%s: unable to disable the hsusb 1p8\n",
259 __func__);
260 return ret;
261 }
262
263 ret = regulator_set_optimum_mode(hsusb_1p8, 0);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530264 if (ret < 0)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700265 pr_err("%s: Unable to set LPM of the regulator:"
Anji jonnala11aa5c42011-05-04 10:19:48 +0530266 "HSUSB_1p8\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700267
268 ret = regulator_disable(hsusb_3p3);
269 if (ret) {
270 dev_err(motg->otg.dev, "%s: unable to disable the hsusb 3p3\n",
271 __func__);
272 return ret;
273 }
274 ret = regulator_set_optimum_mode(hsusb_3p3, 0);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530275 if (ret < 0)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700276 pr_err("%s: Unable to set LPM of the regulator:"
Anji jonnala11aa5c42011-05-04 10:19:48 +0530277 "HSUSB_3p3\n", __func__);
278 }
279
280 pr_debug("reg (%s)\n", on ? "HPM" : "LPM");
281 return ret < 0 ? ret : 0;
282}
283
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530284static void msm_hsusb_mhl_switch_enable(struct msm_otg *motg, bool on)
285{
286 static struct regulator *mhl_analog_switch;
287 struct msm_otg_platform_data *pdata = motg->pdata;
288
289 if (!pdata->mhl_enable)
290 return;
291
292 if (on) {
293 mhl_analog_switch = regulator_get(motg->otg.dev,
294 "mhl_ext_3p3v");
295 if (IS_ERR(mhl_analog_switch)) {
296 pr_err("Unable to get mhl_analog_switch\n");
297 return;
298 }
299
300 if (regulator_enable(mhl_analog_switch)) {
301 pr_err("unable to enable mhl_analog_switch\n");
302 goto put_analog_switch;
303 }
304 return;
305 }
306
307 regulator_disable(mhl_analog_switch);
308put_analog_switch:
309 regulator_put(mhl_analog_switch);
310}
311
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530312static int ulpi_read(struct otg_transceiver *otg, u32 reg)
313{
314 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
315 int cnt = 0;
316
317 /* initiate read operation */
318 writel(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
319 USB_ULPI_VIEWPORT);
320
321 /* wait for completion */
322 while (cnt < ULPI_IO_TIMEOUT_USEC) {
323 if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN))
324 break;
325 udelay(1);
326 cnt++;
327 }
328
329 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
330 dev_err(otg->dev, "ulpi_read: timeout %08x\n",
331 readl(USB_ULPI_VIEWPORT));
332 return -ETIMEDOUT;
333 }
334 return ULPI_DATA_READ(readl(USB_ULPI_VIEWPORT));
335}
336
337static int ulpi_write(struct otg_transceiver *otg, u32 val, u32 reg)
338{
339 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
340 int cnt = 0;
341
342 /* initiate write operation */
343 writel(ULPI_RUN | ULPI_WRITE |
344 ULPI_ADDR(reg) | ULPI_DATA(val),
345 USB_ULPI_VIEWPORT);
346
347 /* wait for completion */
348 while (cnt < ULPI_IO_TIMEOUT_USEC) {
349 if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN))
350 break;
351 udelay(1);
352 cnt++;
353 }
354
355 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
356 dev_err(otg->dev, "ulpi_write: timeout\n");
357 return -ETIMEDOUT;
358 }
359 return 0;
360}
361
362static struct otg_io_access_ops msm_otg_io_ops = {
363 .read = ulpi_read,
364 .write = ulpi_write,
365};
366
367static void ulpi_init(struct msm_otg *motg)
368{
369 struct msm_otg_platform_data *pdata = motg->pdata;
370 int *seq = pdata->phy_init_seq;
371
372 if (!seq)
373 return;
374
375 while (seq[0] >= 0) {
376 dev_vdbg(motg->otg.dev, "ulpi: write 0x%02x to 0x%02x\n",
377 seq[0], seq[1]);
378 ulpi_write(&motg->otg, seq[0], seq[1]);
379 seq += 2;
380 }
381}
382
383static int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert)
384{
385 int ret;
386
387 if (assert) {
388 ret = clk_reset(motg->clk, CLK_RESET_ASSERT);
389 if (ret)
390 dev_err(motg->otg.dev, "usb hs_clk assert failed\n");
391 } else {
392 ret = clk_reset(motg->clk, CLK_RESET_DEASSERT);
393 if (ret)
394 dev_err(motg->otg.dev, "usb hs_clk deassert failed\n");
395 }
396 return ret;
397}
398
399static int msm_otg_phy_clk_reset(struct msm_otg *motg)
400{
401 int ret;
402
Amit Blay02eff132011-09-21 16:46:24 +0300403 if (IS_ERR(motg->phy_reset_clk))
404 return 0;
405
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530406 ret = clk_reset(motg->phy_reset_clk, CLK_RESET_ASSERT);
407 if (ret) {
408 dev_err(motg->otg.dev, "usb phy clk assert failed\n");
409 return ret;
410 }
411 usleep_range(10000, 12000);
412 ret = clk_reset(motg->phy_reset_clk, CLK_RESET_DEASSERT);
413 if (ret)
414 dev_err(motg->otg.dev, "usb phy clk deassert failed\n");
415 return ret;
416}
417
418static int msm_otg_phy_reset(struct msm_otg *motg)
419{
420 u32 val;
421 int ret;
422 int retries;
423
424 ret = msm_otg_link_clk_reset(motg, 1);
425 if (ret)
426 return ret;
427 ret = msm_otg_phy_clk_reset(motg);
428 if (ret)
429 return ret;
430 ret = msm_otg_link_clk_reset(motg, 0);
431 if (ret)
432 return ret;
433
434 val = readl(USB_PORTSC) & ~PORTSC_PTS_MASK;
435 writel(val | PORTSC_PTS_ULPI, USB_PORTSC);
436
437 for (retries = 3; retries > 0; retries--) {
438 ret = ulpi_write(&motg->otg, ULPI_FUNC_CTRL_SUSPENDM,
439 ULPI_CLR(ULPI_FUNC_CTRL));
440 if (!ret)
441 break;
442 ret = msm_otg_phy_clk_reset(motg);
443 if (ret)
444 return ret;
445 }
446 if (!retries)
447 return -ETIMEDOUT;
448
449 /* This reset calibrates the phy, if the above write succeeded */
450 ret = msm_otg_phy_clk_reset(motg);
451 if (ret)
452 return ret;
453
454 for (retries = 3; retries > 0; retries--) {
455 ret = ulpi_read(&motg->otg, ULPI_DEBUG);
456 if (ret != -ETIMEDOUT)
457 break;
458 ret = msm_otg_phy_clk_reset(motg);
459 if (ret)
460 return ret;
461 }
462 if (!retries)
463 return -ETIMEDOUT;
464
465 dev_info(motg->otg.dev, "phy_reset: success\n");
466 return 0;
467}
468
469#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530470static int msm_otg_link_reset(struct msm_otg *motg)
471{
472 int cnt = 0;
473
474 writel_relaxed(USBCMD_RESET, USB_USBCMD);
475 while (cnt < LINK_RESET_TIMEOUT_USEC) {
476 if (!(readl_relaxed(USB_USBCMD) & USBCMD_RESET))
477 break;
478 udelay(1);
479 cnt++;
480 }
481 if (cnt >= LINK_RESET_TIMEOUT_USEC)
482 return -ETIMEDOUT;
483
484 /* select ULPI phy */
485 writel_relaxed(0x80000000, USB_PORTSC);
486 writel_relaxed(0x0, USB_AHBBURST);
487 writel_relaxed(0x00, USB_AHBMODE);
488
489 return 0;
490}
491
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530492static int msm_otg_reset(struct otg_transceiver *otg)
493{
494 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
495 struct msm_otg_platform_data *pdata = motg->pdata;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530496 int ret;
497 u32 val = 0;
498 u32 ulpi_val = 0;
499
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700500 clk_enable(motg->clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530501 ret = msm_otg_phy_reset(motg);
502 if (ret) {
503 dev_err(otg->dev, "phy_reset failed\n");
504 return ret;
505 }
506
507 ulpi_init(motg);
508
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530509 ret = msm_otg_link_reset(motg);
510 if (ret) {
511 dev_err(otg->dev, "link reset failed\n");
512 return ret;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530513 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530514 msleep(100);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700515 /* Ensure that RESET operation is completed before turning off clock */
516 mb();
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530517
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700518 clk_disable(motg->clk);
519
520 val = readl_relaxed(USB_OTGSC);
521 if (pdata->mode == USB_OTG) {
522 ulpi_val = ULPI_INT_IDGRD | ULPI_INT_SESS_VALID;
523 val |= OTGSC_IDIE | OTGSC_BSVIE;
524 } else if (pdata->mode == USB_PERIPHERAL) {
525 ulpi_val = ULPI_INT_SESS_VALID;
526 val |= OTGSC_BSVIE;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530527 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700528 writel_relaxed(val, USB_OTGSC);
529 ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_RISE);
530 ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_FALL);
531
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530532 return 0;
533}
534
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +0530535static int msm_otg_set_suspend(struct otg_transceiver *otg, int suspend)
536{
537 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
538
539 /*
540 * Allow bus suspend only for host mode. Device mode bus suspend
541 * is not implemented yet.
542 */
543 if (!test_bit(ID, &motg->inputs) || test_bit(ID_A, &motg->inputs)) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530544 /*
545 * ID_GND --> ID_A transition can not be detected in LPM.
546 * Disallow host bus suspend when ACA is enabled.
547 */
548 if (suspend && !aca_enabled())
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +0530549 pm_runtime_put(otg->dev);
550 else
551 pm_runtime_resume(otg->dev);
552 }
553
554 return 0;
555}
556
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530557#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
Pavankumar Kondeti70187732011-02-15 09:42:34 +0530558#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
559
560#ifdef CONFIG_PM_SLEEP
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530561static int msm_otg_suspend(struct msm_otg *motg)
562{
563 struct otg_transceiver *otg = &motg->otg;
564 struct usb_bus *bus = otg->host;
565 struct msm_otg_platform_data *pdata = motg->pdata;
566 int cnt = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700567 bool session_active;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530568
569 if (atomic_read(&motg->in_lpm))
570 return 0;
571
572 disable_irq(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700573 session_active = (otg->host && !test_bit(ID, &motg->inputs)) ||
574 test_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530575 /*
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530576 * Chipidea 45-nm PHY suspend sequence:
577 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530578 * Interrupt Latch Register auto-clear feature is not present
579 * in all PHY versions. Latch register is clear on read type.
580 * Clear latch register to avoid spurious wakeup from
581 * low power mode (LPM).
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530582 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530583 * PHY comparators are disabled when PHY enters into low power
584 * mode (LPM). Keep PHY comparators ON in LPM only when we expect
585 * VBUS/Id notifications from USB PHY. Otherwise turn off USB
586 * PHY comparators. This save significant amount of power.
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530587 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530588 * PLL is not turned off when PHY enters into low power mode (LPM).
589 * Disable PLL for maximum power savings.
590 */
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530591
592 if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) {
593 ulpi_read(otg, 0x14);
594 if (pdata->otg_control == OTG_PHY_CONTROL)
595 ulpi_write(otg, 0x01, 0x30);
596 ulpi_write(otg, 0x08, 0x09);
597 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530598
599 /*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700600 * Turn off the OTG comparators, if depends on PMIC for
601 * VBUS and ID notifications.
602 */
603 if ((motg->caps & ALLOW_PHY_COMP_DISABLE) && !session_active) {
604 ulpi_write(otg, OTG_COMP_DISABLE,
605 ULPI_SET(ULPI_PWR_CLK_MNG_REG));
606 motg->lpm_flags |= PHY_OTG_COMP_DISABLED;
607 }
608
609 /*
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530610 * PHY may take some time or even fail to enter into low power
611 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
612 * in failure case.
613 */
614 writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
615 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
616 if (readl(USB_PORTSC) & PORTSC_PHCD)
617 break;
618 udelay(1);
619 cnt++;
620 }
621
622 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
623 dev_err(otg->dev, "Unable to suspend PHY\n");
624 msm_otg_reset(otg);
625 enable_irq(motg->irq);
626 return -ETIMEDOUT;
627 }
628
629 /*
630 * PHY has capability to generate interrupt asynchronously in low
631 * power mode (LPM). This interrupt is level triggered. So USB IRQ
632 * line must be disabled till async interrupt enable bit is cleared
633 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
634 * block data communication from PHY.
635 */
636 writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);
637
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700638 if (motg->caps & ALLOW_PHY_RETENTION && !session_active) {
639 writel_relaxed(readl_relaxed(USB_PHY_CTRL) & ~PHY_RETEN,
640 USB_PHY_CTRL);
641 motg->lpm_flags |= PHY_RETENTIONED;
642 }
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530643
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700644 /* Ensure that above operation is completed before turning off clocks */
645 mb();
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530646 clk_disable(motg->pclk);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530647 if (motg->core_clk)
648 clk_disable(motg->core_clk);
649
Amit Blay137575f2011-11-06 15:20:54 +0200650 if (!IS_ERR(motg->system_clk))
651 clk_disable(motg->system_clk);
652
Anji jonnala0f73cac2011-05-04 10:19:46 +0530653 if (!IS_ERR(motg->pclk_src))
654 clk_disable(motg->pclk_src);
655
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700656 if (motg->caps & ALLOW_PHY_POWER_COLLAPSE && !session_active) {
657 msm_hsusb_ldo_enable(motg, 0);
658 motg->lpm_flags |= PHY_PWR_COLLAPSED;
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530659 }
660
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530661 if (motg->lpm_flags & PHY_RETENTIONED) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700662 msm_hsusb_config_vddcx(0);
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530663 msm_hsusb_mhl_switch_enable(motg, 0);
664 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700665
666 if (device_may_wakeup(otg->dev)) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530667 enable_irq_wake(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700668 if (motg->pdata->pmic_id_irq)
669 enable_irq_wake(motg->pdata->pmic_id_irq);
670 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530671 if (bus)
672 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
673
674 atomic_set(&motg->in_lpm, 1);
675 enable_irq(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700676 wake_unlock(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530677
678 dev_info(otg->dev, "USB in low power mode\n");
679
680 return 0;
681}
682
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530683static int msm_otg_resume(struct msm_otg *motg)
684{
685 struct otg_transceiver *otg = &motg->otg;
686 struct usb_bus *bus = otg->host;
687 int cnt = 0;
688 unsigned temp;
689
690 if (!atomic_read(&motg->in_lpm))
691 return 0;
692
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700693 wake_lock(&motg->wlock);
Anji jonnala0f73cac2011-05-04 10:19:46 +0530694 if (!IS_ERR(motg->pclk_src))
695 clk_enable(motg->pclk_src);
696
Amit Blay137575f2011-11-06 15:20:54 +0200697 if (!IS_ERR(motg->system_clk))
698 clk_enable(motg->system_clk);
699
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530700 clk_enable(motg->pclk);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530701 if (motg->core_clk)
702 clk_enable(motg->core_clk);
703
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700704 if (motg->lpm_flags & PHY_PWR_COLLAPSED) {
705 msm_hsusb_ldo_enable(motg, 1);
706 motg->lpm_flags &= ~PHY_PWR_COLLAPSED;
707 }
708
709 if (motg->lpm_flags & PHY_RETENTIONED) {
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530710 msm_hsusb_mhl_switch_enable(motg, 1);
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530711 msm_hsusb_config_vddcx(1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700712 writel_relaxed(readl_relaxed(USB_PHY_CTRL) | PHY_RETEN,
713 USB_PHY_CTRL);
714 motg->lpm_flags &= ~PHY_RETENTIONED;
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530715 }
716
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530717 temp = readl(USB_USBCMD);
718 temp &= ~ASYNC_INTR_CTRL;
719 temp &= ~ULPI_STP_CTRL;
720 writel(temp, USB_USBCMD);
721
722 /*
723 * PHY comes out of low power mode (LPM) in case of wakeup
724 * from asynchronous interrupt.
725 */
726 if (!(readl(USB_PORTSC) & PORTSC_PHCD))
727 goto skip_phy_resume;
728
729 writel(readl(USB_PORTSC) & ~PORTSC_PHCD, USB_PORTSC);
730 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
731 if (!(readl(USB_PORTSC) & PORTSC_PHCD))
732 break;
733 udelay(1);
734 cnt++;
735 }
736
737 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
738 /*
739 * This is a fatal error. Reset the link and
740 * PHY. USB state can not be restored. Re-insertion
741 * of USB cable is the only way to get USB working.
742 */
743 dev_err(otg->dev, "Unable to resume USB."
744 "Re-plugin the cable\n");
745 msm_otg_reset(otg);
746 }
747
748skip_phy_resume:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700749 /* Turn on the OTG comparators on resume */
750 if (motg->lpm_flags & PHY_OTG_COMP_DISABLED) {
751 ulpi_write(otg, OTG_COMP_DISABLE,
752 ULPI_CLR(ULPI_PWR_CLK_MNG_REG));
753 motg->lpm_flags &= ~PHY_OTG_COMP_DISABLED;
754 }
755 if (device_may_wakeup(otg->dev)) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530756 disable_irq_wake(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700757 if (motg->pdata->pmic_id_irq)
758 disable_irq_wake(motg->pdata->pmic_id_irq);
759 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530760 if (bus)
761 set_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
762
Pavankumar Kondeti2ce2c3a2011-05-02 11:56:33 +0530763 atomic_set(&motg->in_lpm, 0);
764
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530765 if (aca_enabled() && !irq_read_line(motg->pdata->pmic_id_irq)) {
766 clear_bit(ID, &motg->inputs);
767 schedule_work(&motg->sm_work);
768 }
769
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530770 if (motg->async_int) {
771 motg->async_int = 0;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530772 enable_irq(motg->irq);
773 }
774
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530775 dev_info(otg->dev, "USB exited from low power mode\n");
776
777 return 0;
778}
Pavankumar Kondeti70187732011-02-15 09:42:34 +0530779#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530780
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530781static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA)
782{
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530783 if ((motg->chg_type == USB_ACA_DOCK_CHARGER ||
784 motg->chg_type == USB_ACA_A_CHARGER ||
785 motg->chg_type == USB_ACA_B_CHARGER ||
786 motg->chg_type == USB_ACA_C_CHARGER) &&
787 mA > IDEV_ACA_CHG_LIMIT)
788 mA = IDEV_ACA_CHG_LIMIT;
789
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530790 if (motg->cur_power == mA)
791 return;
792
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530793 dev_info(motg->otg.dev, "Avail curr from USB = %u\n", mA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700794 pm8921_charger_vbus_draw(mA);
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530795 motg->cur_power = mA;
796}
797
798static int msm_otg_set_power(struct otg_transceiver *otg, unsigned mA)
799{
800 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
801
802 /*
803 * Gadget driver uses set_power method to notify about the
804 * available current based on suspend/configured states.
805 *
806 * IDEV_CHG can be drawn irrespective of suspend/un-configured
807 * states when CDP/ACA is connected.
808 */
809 if (motg->chg_type == USB_SDP_CHARGER)
810 msm_otg_notify_charger(motg, mA);
811
812 return 0;
813}
814
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530815static void msm_otg_start_host(struct otg_transceiver *otg, int on)
816{
817 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
818 struct msm_otg_platform_data *pdata = motg->pdata;
819 struct usb_hcd *hcd;
820
821 if (!otg->host)
822 return;
823
824 hcd = bus_to_hcd(otg->host);
825
826 if (on) {
827 dev_dbg(otg->dev, "host on\n");
828
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530829 /*
830 * Some boards have a switch cotrolled by gpio
831 * to enable/disable internal HUB. Enable internal
832 * HUB before kicking the host.
833 */
834 if (pdata->setup_gpio)
835 pdata->setup_gpio(OTG_STATE_A_HOST);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530836 usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530837 } else {
838 dev_dbg(otg->dev, "host off\n");
839
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530840 usb_remove_hcd(hcd);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530841 /* HCD core reset all bits of PORTSC. select ULPI phy */
842 writel_relaxed(0x80000000, USB_PORTSC);
843
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530844 if (pdata->setup_gpio)
845 pdata->setup_gpio(OTG_STATE_UNDEFINED);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530846 }
847}
848
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700849static int msm_otg_usbdev_notify(struct notifier_block *self,
850 unsigned long action, void *priv)
851{
852 struct msm_otg *motg = container_of(self, struct msm_otg, usbdev_nb);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530853 struct usb_device *udev = priv;
854
855 if (!aca_enabled())
856 goto out;
857
858 if (action == USB_BUS_ADD || action == USB_BUS_REMOVE)
859 goto out;
860
861 if (udev->bus != motg->otg.host)
862 goto out;
863 /*
864 * Interested in devices connected directly to the root hub.
865 * ACA dock can supply IDEV_CHG irrespective devices connected
866 * on the accessory port.
867 */
868 if (!udev->parent || udev->parent->parent ||
869 motg->chg_type == USB_ACA_DOCK_CHARGER)
870 goto out;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700871
872 switch (action) {
873 case USB_DEVICE_ADD:
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530874 usb_disable_autosuspend(udev);
875 /* fall through */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700876 case USB_DEVICE_CONFIG:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700877 if (udev->actconfig)
878 motg->mA_port = udev->actconfig->desc.bMaxPower * 2;
879 else
880 motg->mA_port = IUNIT;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530881 break;
882 case USB_DEVICE_REMOVE:
883 motg->mA_port = IUNIT;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700884 break;
885 default:
886 break;
887 }
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +0530888 if (test_bit(ID_A, &motg->inputs))
889 msm_otg_notify_charger(motg, IDEV_ACA_CHG_MAX -
890 motg->mA_port);
891out:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700892 return NOTIFY_OK;
893}
894
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530895static int msm_otg_set_host(struct otg_transceiver *otg, struct usb_bus *host)
896{
897 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
898 struct usb_hcd *hcd;
899
900 /*
901 * Fail host registration if this board can support
902 * only peripheral configuration.
903 */
904 if (motg->pdata->mode == USB_PERIPHERAL) {
905 dev_info(otg->dev, "Host mode is not supported\n");
906 return -ENODEV;
907 }
908
909 if (!host) {
910 if (otg->state == OTG_STATE_A_HOST) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530911 pm_runtime_get_sync(otg->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700912 usb_unregister_notify(&motg->usbdev_nb);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530913 msm_otg_start_host(otg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700914 if (motg->pdata->vbus_power)
915 motg->pdata->vbus_power(0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530916 otg->host = NULL;
917 otg->state = OTG_STATE_UNDEFINED;
918 schedule_work(&motg->sm_work);
919 } else {
920 otg->host = NULL;
921 }
922
923 return 0;
924 }
925
926 hcd = bus_to_hcd(host);
927 hcd->power_budget = motg->pdata->power_budget;
928
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700929 motg->usbdev_nb.notifier_call = msm_otg_usbdev_notify;
930 usb_register_notify(&motg->usbdev_nb);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530931 otg->host = host;
932 dev_dbg(otg->dev, "host driver registered w/ tranceiver\n");
933
934 /*
935 * Kick the state machine work, if peripheral is not supported
936 * or peripheral is already registered with us.
937 */
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530938 if (motg->pdata->mode == USB_HOST || otg->gadget) {
939 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530940 schedule_work(&motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530941 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530942
943 return 0;
944}
945
946static void msm_otg_start_peripheral(struct otg_transceiver *otg, int on)
947{
948 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
949 struct msm_otg_platform_data *pdata = motg->pdata;
950
951 if (!otg->gadget)
952 return;
953
954 if (on) {
955 dev_dbg(otg->dev, "gadget on\n");
956 /*
957 * Some boards have a switch cotrolled by gpio
958 * to enable/disable internal HUB. Disable internal
959 * HUB before kicking the gadget.
960 */
961 if (pdata->setup_gpio)
962 pdata->setup_gpio(OTG_STATE_B_PERIPHERAL);
963 usb_gadget_vbus_connect(otg->gadget);
964 } else {
965 dev_dbg(otg->dev, "gadget off\n");
966 usb_gadget_vbus_disconnect(otg->gadget);
967 if (pdata->setup_gpio)
968 pdata->setup_gpio(OTG_STATE_UNDEFINED);
969 }
970
971}
972
973static int msm_otg_set_peripheral(struct otg_transceiver *otg,
974 struct usb_gadget *gadget)
975{
976 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
977
978 /*
979 * Fail peripheral registration if this board can support
980 * only host configuration.
981 */
982 if (motg->pdata->mode == USB_HOST) {
983 dev_info(otg->dev, "Peripheral mode is not supported\n");
984 return -ENODEV;
985 }
986
987 if (!gadget) {
988 if (otg->state == OTG_STATE_B_PERIPHERAL) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530989 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530990 msm_otg_start_peripheral(otg, 0);
991 otg->gadget = NULL;
992 otg->state = OTG_STATE_UNDEFINED;
993 schedule_work(&motg->sm_work);
994 } else {
995 otg->gadget = NULL;
996 }
997
998 return 0;
999 }
1000 otg->gadget = gadget;
1001 dev_dbg(otg->dev, "peripheral driver registered w/ tranceiver\n");
1002
1003 /*
1004 * Kick the state machine work, if host is not supported
1005 * or host is already registered with us.
1006 */
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301007 if (motg->pdata->mode == USB_PERIPHERAL || otg->host) {
1008 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301009 schedule_work(&motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301010 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301011
1012 return 0;
1013}
1014
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001015static bool msm_chg_aca_detect(struct msm_otg *motg)
1016{
1017 struct otg_transceiver *otg = &motg->otg;
1018 u32 int_sts;
1019 bool ret = false;
1020
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301021 if (!aca_enabled())
1022 goto out;
1023
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001024 if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY)
1025 goto out;
1026
1027 int_sts = ulpi_read(otg, 0x87);
1028 switch (int_sts & 0x1C) {
1029 case 0x08:
1030 if (!test_and_set_bit(ID_A, &motg->inputs)) {
1031 dev_dbg(otg->dev, "ID_A\n");
1032 motg->chg_type = USB_ACA_A_CHARGER;
1033 motg->chg_state = USB_CHG_STATE_DETECTED;
1034 clear_bit(ID_B, &motg->inputs);
1035 clear_bit(ID_C, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301036 set_bit(ID, &motg->inputs);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001037 ret = true;
1038 }
1039 break;
1040 case 0x0C:
1041 if (!test_and_set_bit(ID_B, &motg->inputs)) {
1042 dev_dbg(otg->dev, "ID_B\n");
1043 motg->chg_type = USB_ACA_B_CHARGER;
1044 motg->chg_state = USB_CHG_STATE_DETECTED;
1045 clear_bit(ID_A, &motg->inputs);
1046 clear_bit(ID_C, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301047 set_bit(ID, &motg->inputs);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001048 ret = true;
1049 }
1050 break;
1051 case 0x10:
1052 if (!test_and_set_bit(ID_C, &motg->inputs)) {
1053 dev_dbg(otg->dev, "ID_C\n");
1054 motg->chg_type = USB_ACA_C_CHARGER;
1055 motg->chg_state = USB_CHG_STATE_DETECTED;
1056 clear_bit(ID_A, &motg->inputs);
1057 clear_bit(ID_B, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301058 set_bit(ID, &motg->inputs);
1059 ret = true;
1060 }
1061 break;
1062 case 0x04:
1063 if (test_and_clear_bit(ID, &motg->inputs)) {
1064 dev_dbg(otg->dev, "ID_GND\n");
1065 motg->chg_type = USB_INVALID_CHARGER;
1066 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1067 clear_bit(ID_A, &motg->inputs);
1068 clear_bit(ID_B, &motg->inputs);
1069 clear_bit(ID_C, &motg->inputs);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001070 ret = true;
1071 }
1072 break;
1073 default:
1074 ret = test_and_clear_bit(ID_A, &motg->inputs) |
1075 test_and_clear_bit(ID_B, &motg->inputs) |
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301076 test_and_clear_bit(ID_C, &motg->inputs) |
1077 !test_and_set_bit(ID, &motg->inputs);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001078 if (ret) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301079 dev_dbg(otg->dev, "ID A/B/C/GND is no more\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001080 motg->chg_type = USB_INVALID_CHARGER;
1081 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1082 }
1083 }
1084out:
1085 return ret;
1086}
1087
1088static void msm_chg_enable_aca_det(struct msm_otg *motg)
1089{
1090 struct otg_transceiver *otg = &motg->otg;
1091
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301092 if (!aca_enabled())
1093 return;
1094
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001095 switch (motg->pdata->phy_type) {
1096 case SNPS_28NM_INTEGRATED_PHY:
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301097 /* Disable ID_GND in link and PHY */
1098 writel_relaxed(readl_relaxed(USB_OTGSC) & ~(OTGSC_IDPU |
1099 OTGSC_IDIE), USB_OTGSC);
1100 ulpi_write(otg, 0x01, 0x0C);
1101 ulpi_write(otg, 0x10, 0x0F);
1102 ulpi_write(otg, 0x10, 0x12);
1103 /* Enable ACA ID detection */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001104 ulpi_write(otg, 0x20, 0x85);
1105 break;
1106 default:
1107 break;
1108 }
1109}
1110
1111static void msm_chg_enable_aca_intr(struct msm_otg *motg)
1112{
1113 struct otg_transceiver *otg = &motg->otg;
1114
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301115 if (!aca_enabled())
1116 return;
1117
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001118 switch (motg->pdata->phy_type) {
1119 case SNPS_28NM_INTEGRATED_PHY:
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301120 /* Enable ACA Detection interrupt (on any RID change) */
1121 ulpi_write(otg, 0x01, 0x94);
1122 break;
1123 default:
1124 break;
1125 }
1126}
1127
1128static void msm_chg_disable_aca_intr(struct msm_otg *motg)
1129{
1130 struct otg_transceiver *otg = &motg->otg;
1131
1132 if (!aca_enabled())
1133 return;
1134
1135 switch (motg->pdata->phy_type) {
1136 case SNPS_28NM_INTEGRATED_PHY:
1137 ulpi_write(otg, 0x01, 0x95);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001138 break;
1139 default:
1140 break;
1141 }
1142}
1143
1144static bool msm_chg_check_aca_intr(struct msm_otg *motg)
1145{
1146 struct otg_transceiver *otg = &motg->otg;
1147 bool ret = false;
1148
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301149 if (!aca_enabled())
1150 return ret;
1151
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001152 switch (motg->pdata->phy_type) {
1153 case SNPS_28NM_INTEGRATED_PHY:
1154 if (ulpi_read(otg, 0x91) & 1) {
1155 dev_dbg(otg->dev, "RID change\n");
1156 ulpi_write(otg, 0x01, 0x92);
1157 ret = msm_chg_aca_detect(motg);
1158 }
1159 default:
1160 break;
1161 }
1162 return ret;
1163}
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301164
1165static void msm_otg_id_timer_func(unsigned long data)
1166{
1167 struct msm_otg *motg = (struct msm_otg *) data;
1168
1169 if (!aca_enabled())
1170 return;
1171
1172 if (atomic_read(&motg->in_lpm)) {
1173 dev_dbg(motg->otg.dev, "timer: in lpm\n");
1174 return;
1175 }
1176
1177 if (msm_chg_check_aca_intr(motg)) {
1178 dev_dbg(motg->otg.dev, "timer: aca work\n");
1179 schedule_work(&motg->sm_work);
1180 }
1181
1182 if (!test_bit(ID, &motg->inputs) || test_bit(ID_A, &motg->inputs))
1183 mod_timer(&motg->id_timer, ID_TIMER_FREQ);
1184}
1185
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301186static bool msm_chg_check_secondary_det(struct msm_otg *motg)
1187{
1188 struct otg_transceiver *otg = &motg->otg;
1189 u32 chg_det;
1190 bool ret = false;
1191
1192 switch (motg->pdata->phy_type) {
1193 case CI_45NM_INTEGRATED_PHY:
1194 chg_det = ulpi_read(otg, 0x34);
1195 ret = chg_det & (1 << 4);
1196 break;
1197 case SNPS_28NM_INTEGRATED_PHY:
1198 chg_det = ulpi_read(otg, 0x87);
1199 ret = chg_det & 1;
1200 break;
1201 default:
1202 break;
1203 }
1204 return ret;
1205}
1206
1207static void msm_chg_enable_secondary_det(struct msm_otg *motg)
1208{
1209 struct otg_transceiver *otg = &motg->otg;
1210 u32 chg_det;
1211
1212 switch (motg->pdata->phy_type) {
1213 case CI_45NM_INTEGRATED_PHY:
1214 chg_det = ulpi_read(otg, 0x34);
1215 /* Turn off charger block */
1216 chg_det |= ~(1 << 1);
1217 ulpi_write(otg, chg_det, 0x34);
1218 udelay(20);
1219 /* control chg block via ULPI */
1220 chg_det &= ~(1 << 3);
1221 ulpi_write(otg, chg_det, 0x34);
1222 /* put it in host mode for enabling D- source */
1223 chg_det &= ~(1 << 2);
1224 ulpi_write(otg, chg_det, 0x34);
1225 /* Turn on chg detect block */
1226 chg_det &= ~(1 << 1);
1227 ulpi_write(otg, chg_det, 0x34);
1228 udelay(20);
1229 /* enable chg detection */
1230 chg_det &= ~(1 << 0);
1231 ulpi_write(otg, chg_det, 0x34);
1232 break;
1233 case SNPS_28NM_INTEGRATED_PHY:
1234 /*
1235 * Configure DM as current source, DP as current sink
1236 * and enable battery charging comparators.
1237 */
1238 ulpi_write(otg, 0x8, 0x85);
1239 ulpi_write(otg, 0x2, 0x85);
1240 ulpi_write(otg, 0x1, 0x85);
1241 break;
1242 default:
1243 break;
1244 }
1245}
1246
1247static bool msm_chg_check_primary_det(struct msm_otg *motg)
1248{
1249 struct otg_transceiver *otg = &motg->otg;
1250 u32 chg_det;
1251 bool ret = false;
1252
1253 switch (motg->pdata->phy_type) {
1254 case CI_45NM_INTEGRATED_PHY:
1255 chg_det = ulpi_read(otg, 0x34);
1256 ret = chg_det & (1 << 4);
1257 break;
1258 case SNPS_28NM_INTEGRATED_PHY:
1259 chg_det = ulpi_read(otg, 0x87);
1260 ret = chg_det & 1;
1261 break;
1262 default:
1263 break;
1264 }
1265 return ret;
1266}
1267
1268static void msm_chg_enable_primary_det(struct msm_otg *motg)
1269{
1270 struct otg_transceiver *otg = &motg->otg;
1271 u32 chg_det;
1272
1273 switch (motg->pdata->phy_type) {
1274 case CI_45NM_INTEGRATED_PHY:
1275 chg_det = ulpi_read(otg, 0x34);
1276 /* enable chg detection */
1277 chg_det &= ~(1 << 0);
1278 ulpi_write(otg, chg_det, 0x34);
1279 break;
1280 case SNPS_28NM_INTEGRATED_PHY:
1281 /*
1282 * Configure DP as current source, DM as current sink
1283 * and enable battery charging comparators.
1284 */
1285 ulpi_write(otg, 0x2, 0x85);
1286 ulpi_write(otg, 0x1, 0x85);
1287 break;
1288 default:
1289 break;
1290 }
1291}
1292
1293static bool msm_chg_check_dcd(struct msm_otg *motg)
1294{
1295 struct otg_transceiver *otg = &motg->otg;
1296 u32 line_state;
1297 bool ret = false;
1298
1299 switch (motg->pdata->phy_type) {
1300 case CI_45NM_INTEGRATED_PHY:
1301 line_state = ulpi_read(otg, 0x15);
1302 ret = !(line_state & 1);
1303 break;
1304 case SNPS_28NM_INTEGRATED_PHY:
1305 line_state = ulpi_read(otg, 0x87);
1306 ret = line_state & 2;
1307 break;
1308 default:
1309 break;
1310 }
1311 return ret;
1312}
1313
1314static void msm_chg_disable_dcd(struct msm_otg *motg)
1315{
1316 struct otg_transceiver *otg = &motg->otg;
1317 u32 chg_det;
1318
1319 switch (motg->pdata->phy_type) {
1320 case CI_45NM_INTEGRATED_PHY:
1321 chg_det = ulpi_read(otg, 0x34);
1322 chg_det &= ~(1 << 5);
1323 ulpi_write(otg, chg_det, 0x34);
1324 break;
1325 case SNPS_28NM_INTEGRATED_PHY:
1326 ulpi_write(otg, 0x10, 0x86);
1327 break;
1328 default:
1329 break;
1330 }
1331}
1332
1333static void msm_chg_enable_dcd(struct msm_otg *motg)
1334{
1335 struct otg_transceiver *otg = &motg->otg;
1336 u32 chg_det;
1337
1338 switch (motg->pdata->phy_type) {
1339 case CI_45NM_INTEGRATED_PHY:
1340 chg_det = ulpi_read(otg, 0x34);
1341 /* Turn on D+ current source */
1342 chg_det |= (1 << 5);
1343 ulpi_write(otg, chg_det, 0x34);
1344 break;
1345 case SNPS_28NM_INTEGRATED_PHY:
1346 /* Data contact detection enable */
1347 ulpi_write(otg, 0x10, 0x85);
1348 break;
1349 default:
1350 break;
1351 }
1352}
1353
1354static void msm_chg_block_on(struct msm_otg *motg)
1355{
1356 struct otg_transceiver *otg = &motg->otg;
1357 u32 func_ctrl, chg_det;
1358
1359 /* put the controller in non-driving mode */
1360 func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
1361 func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
1362 func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
1363 ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
1364
1365 switch (motg->pdata->phy_type) {
1366 case CI_45NM_INTEGRATED_PHY:
1367 chg_det = ulpi_read(otg, 0x34);
1368 /* control chg block via ULPI */
1369 chg_det &= ~(1 << 3);
1370 ulpi_write(otg, chg_det, 0x34);
1371 /* Turn on chg detect block */
1372 chg_det &= ~(1 << 1);
1373 ulpi_write(otg, chg_det, 0x34);
1374 udelay(20);
1375 break;
1376 case SNPS_28NM_INTEGRATED_PHY:
1377 /* Clear charger detecting control bits */
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301378 ulpi_write(otg, 0x1F, 0x86);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301379 /* Clear alt interrupt latch and enable bits */
1380 ulpi_write(otg, 0x1F, 0x92);
1381 ulpi_write(otg, 0x1F, 0x95);
1382 udelay(100);
1383 break;
1384 default:
1385 break;
1386 }
1387}
1388
1389static void msm_chg_block_off(struct msm_otg *motg)
1390{
1391 struct otg_transceiver *otg = &motg->otg;
1392 u32 func_ctrl, chg_det;
1393
1394 switch (motg->pdata->phy_type) {
1395 case CI_45NM_INTEGRATED_PHY:
1396 chg_det = ulpi_read(otg, 0x34);
1397 /* Turn off charger block */
1398 chg_det |= ~(1 << 1);
1399 ulpi_write(otg, chg_det, 0x34);
1400 break;
1401 case SNPS_28NM_INTEGRATED_PHY:
1402 /* Clear charger detecting control bits */
1403 ulpi_write(otg, 0x3F, 0x86);
1404 /* Clear alt interrupt latch and enable bits */
1405 ulpi_write(otg, 0x1F, 0x92);
1406 ulpi_write(otg, 0x1F, 0x95);
1407 break;
1408 default:
1409 break;
1410 }
1411
1412 /* put the controller in normal mode */
1413 func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
1414 func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
1415 func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
1416 ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
1417}
1418
Anji jonnalad270e2d2011-08-09 11:28:32 +05301419static const char *chg_to_string(enum usb_chg_type chg_type)
1420{
1421 switch (chg_type) {
1422 case USB_SDP_CHARGER: return "USB_SDP_CHARGER";
1423 case USB_DCP_CHARGER: return "USB_DCP_CHARGER";
1424 case USB_CDP_CHARGER: return "USB_CDP_CHARGER";
1425 case USB_ACA_A_CHARGER: return "USB_ACA_A_CHARGER";
1426 case USB_ACA_B_CHARGER: return "USB_ACA_B_CHARGER";
1427 case USB_ACA_C_CHARGER: return "USB_ACA_C_CHARGER";
1428 case USB_ACA_DOCK_CHARGER: return "USB_ACA_DOCK_CHARGER";
1429 default: return "INVALID_CHARGER";
1430 }
1431}
1432
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301433#define MSM_CHG_DCD_POLL_TIME (100 * HZ/1000) /* 100 msec */
1434#define MSM_CHG_DCD_MAX_RETRIES 6 /* Tdcd_tmout = 6 * 100 msec */
1435#define MSM_CHG_PRIMARY_DET_TIME (40 * HZ/1000) /* TVDPSRC_ON */
1436#define MSM_CHG_SECONDARY_DET_TIME (40 * HZ/1000) /* TVDMSRC_ON */
1437static void msm_chg_detect_work(struct work_struct *w)
1438{
1439 struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
1440 struct otg_transceiver *otg = &motg->otg;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001441 bool is_dcd, tmout, vout, is_aca;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301442 unsigned long delay;
1443
1444 dev_dbg(otg->dev, "chg detection work\n");
1445 switch (motg->chg_state) {
1446 case USB_CHG_STATE_UNDEFINED:
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301447 msm_chg_block_on(motg);
1448 msm_chg_enable_dcd(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001449 msm_chg_enable_aca_det(motg);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301450 motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
1451 motg->dcd_retries = 0;
1452 delay = MSM_CHG_DCD_POLL_TIME;
1453 break;
1454 case USB_CHG_STATE_WAIT_FOR_DCD:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001455 is_aca = msm_chg_aca_detect(motg);
1456 if (is_aca) {
1457 /*
1458 * ID_A can be ACA dock too. continue
1459 * primary detection after DCD.
1460 */
1461 if (test_bit(ID_A, &motg->inputs)) {
1462 motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
1463 } else {
1464 delay = 0;
1465 break;
1466 }
1467 }
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301468 is_dcd = msm_chg_check_dcd(motg);
1469 tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES;
1470 if (is_dcd || tmout) {
1471 msm_chg_disable_dcd(motg);
1472 msm_chg_enable_primary_det(motg);
1473 delay = MSM_CHG_PRIMARY_DET_TIME;
1474 motg->chg_state = USB_CHG_STATE_DCD_DONE;
1475 } else {
1476 delay = MSM_CHG_DCD_POLL_TIME;
1477 }
1478 break;
1479 case USB_CHG_STATE_DCD_DONE:
1480 vout = msm_chg_check_primary_det(motg);
1481 if (vout) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301482 if (test_bit(ID_A, &motg->inputs)) {
1483 motg->chg_type = USB_ACA_DOCK_CHARGER;
1484 motg->chg_state = USB_CHG_STATE_DETECTED;
1485 delay = 0;
1486 break;
1487 }
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301488 msm_chg_enable_secondary_det(motg);
1489 delay = MSM_CHG_SECONDARY_DET_TIME;
1490 motg->chg_state = USB_CHG_STATE_PRIMARY_DONE;
1491 } else {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301492 if (test_bit(ID_A, &motg->inputs)) {
1493 motg->chg_type = USB_ACA_A_CHARGER;
1494 motg->chg_state = USB_CHG_STATE_DETECTED;
1495 delay = 0;
1496 break;
1497 }
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301498 motg->chg_type = USB_SDP_CHARGER;
1499 motg->chg_state = USB_CHG_STATE_DETECTED;
1500 delay = 0;
1501 }
1502 break;
1503 case USB_CHG_STATE_PRIMARY_DONE:
1504 vout = msm_chg_check_secondary_det(motg);
1505 if (vout)
1506 motg->chg_type = USB_DCP_CHARGER;
1507 else
1508 motg->chg_type = USB_CDP_CHARGER;
1509 motg->chg_state = USB_CHG_STATE_SECONDARY_DONE;
1510 /* fall through */
1511 case USB_CHG_STATE_SECONDARY_DONE:
1512 motg->chg_state = USB_CHG_STATE_DETECTED;
1513 case USB_CHG_STATE_DETECTED:
1514 msm_chg_block_off(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001515 msm_chg_enable_aca_det(motg);
1516 msm_chg_enable_aca_intr(motg);
Anji jonnalad270e2d2011-08-09 11:28:32 +05301517 dev_dbg(otg->dev, "chg_type = %s\n",
1518 chg_to_string(motg->chg_type));
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301519 schedule_work(&motg->sm_work);
1520 return;
1521 default:
1522 return;
1523 }
1524
1525 schedule_delayed_work(&motg->chg_work, delay);
1526}
1527
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301528/*
1529 * We support OTG, Peripheral only and Host only configurations. In case
1530 * of OTG, mode switch (host-->peripheral/peripheral-->host) can happen
1531 * via Id pin status or user request (debugfs). Id/BSV interrupts are not
1532 * enabled when switch is controlled by user and default mode is supplied
1533 * by board file, which can be changed by userspace later.
1534 */
1535static void msm_otg_init_sm(struct msm_otg *motg)
1536{
1537 struct msm_otg_platform_data *pdata = motg->pdata;
1538 u32 otgsc = readl(USB_OTGSC);
1539
1540 switch (pdata->mode) {
1541 case USB_OTG:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001542 if (pdata->otg_control == OTG_USER_CONTROL) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301543 if (pdata->default_mode == USB_HOST) {
1544 clear_bit(ID, &motg->inputs);
1545 } else if (pdata->default_mode == USB_PERIPHERAL) {
1546 set_bit(ID, &motg->inputs);
1547 set_bit(B_SESS_VLD, &motg->inputs);
1548 } else {
1549 set_bit(ID, &motg->inputs);
1550 clear_bit(B_SESS_VLD, &motg->inputs);
1551 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001552 } else {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301553 if (aca_enabled()) {
1554 if (irq_read_line(motg->pdata->pmic_id_irq))
1555 set_bit(ID, &motg->inputs);
1556 else
1557 clear_bit(ID, &motg->inputs);
1558
1559 } else {
1560 if (otgsc & OTGSC_ID)
1561 set_bit(ID, &motg->inputs);
1562 else
1563 clear_bit(ID, &motg->inputs);
1564 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001565
1566 if (otgsc & OTGSC_BSV)
1567 set_bit(B_SESS_VLD, &motg->inputs);
1568 else
1569 clear_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301570 }
1571 break;
1572 case USB_HOST:
1573 clear_bit(ID, &motg->inputs);
1574 break;
1575 case USB_PERIPHERAL:
1576 set_bit(ID, &motg->inputs);
1577 if (otgsc & OTGSC_BSV)
1578 set_bit(B_SESS_VLD, &motg->inputs);
1579 else
1580 clear_bit(B_SESS_VLD, &motg->inputs);
1581 break;
1582 default:
1583 break;
1584 }
1585}
1586
1587static void msm_otg_sm_work(struct work_struct *w)
1588{
1589 struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
1590 struct otg_transceiver *otg = &motg->otg;
1591
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301592 pm_runtime_resume(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301593 switch (otg->state) {
1594 case OTG_STATE_UNDEFINED:
1595 dev_dbg(otg->dev, "OTG_STATE_UNDEFINED state\n");
1596 msm_otg_reset(otg);
1597 msm_otg_init_sm(motg);
1598 otg->state = OTG_STATE_B_IDLE;
1599 /* FALL THROUGH */
1600 case OTG_STATE_B_IDLE:
1601 dev_dbg(otg->dev, "OTG_STATE_B_IDLE state\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001602 if ((!test_bit(ID, &motg->inputs) ||
1603 test_bit(ID_A, &motg->inputs)) && otg->host) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001604 if (motg->chg_type == USB_ACA_DOCK_CHARGER)
1605 msm_otg_notify_charger(motg,
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301606 IDEV_ACA_CHG_MAX);
1607 else if (test_bit(ID_A, &motg->inputs))
1608 msm_otg_notify_charger(motg,
1609 IDEV_ACA_CHG_MAX - IUNIT);
1610 else if (motg->pdata->vbus_power)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001611 motg->pdata->vbus_power(1);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301612 msm_otg_start_host(otg, 1);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301613 /*
1614 * Link can not generate PHY_ALT interrupt
1615 * in host mode when no device is attached
1616 * to the port. It is also observed PHY_ALT
1617 * interrupt missing upon Micro-A cable disconnect.
1618 * Hence disable PHY_ALT interrupt and perform
1619 * polling to detect RID change.
1620 */
1621 msm_chg_enable_aca_det(motg);
1622 msm_chg_disable_aca_intr(motg);
1623 mod_timer(&motg->id_timer, ID_TIMER_FREQ);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301624 otg->state = OTG_STATE_A_HOST;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301625 } else if (test_bit(B_SESS_VLD, &motg->inputs)) {
1626 switch (motg->chg_state) {
1627 case USB_CHG_STATE_UNDEFINED:
1628 msm_chg_detect_work(&motg->chg_work.work);
1629 break;
1630 case USB_CHG_STATE_DETECTED:
1631 switch (motg->chg_type) {
1632 case USB_DCP_CHARGER:
1633 msm_otg_notify_charger(motg,
1634 IDEV_CHG_MAX);
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301635 pm_runtime_put_noidle(otg->dev);
1636 pm_runtime_suspend(otg->dev);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301637 break;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301638 case USB_ACA_B_CHARGER:
1639 msm_otg_notify_charger(motg,
1640 IDEV_ACA_CHG_MAX);
1641 /*
1642 * (ID_B --> ID_C) PHY_ALT interrupt can
1643 * not be detected in LPM.
1644 */
1645 break;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301646 case USB_CDP_CHARGER:
1647 msm_otg_notify_charger(motg,
1648 IDEV_CHG_MAX);
1649 msm_otg_start_peripheral(otg, 1);
1650 otg->state = OTG_STATE_B_PERIPHERAL;
1651 break;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301652 case USB_ACA_C_CHARGER:
1653 msm_otg_notify_charger(motg,
1654 IDEV_ACA_CHG_MAX);
1655 msm_otg_start_peripheral(otg, 1);
1656 otg->state = OTG_STATE_B_PERIPHERAL;
1657 break;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301658 case USB_SDP_CHARGER:
1659 msm_otg_notify_charger(motg, IUNIT);
1660 msm_otg_start_peripheral(otg, 1);
1661 otg->state = OTG_STATE_B_PERIPHERAL;
1662 break;
1663 default:
1664 break;
1665 }
1666 break;
1667 default:
1668 break;
1669 }
1670 } else {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301671 cancel_delayed_work_sync(&motg->chg_work);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301672 msm_otg_notify_charger(motg, 0);
1673 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1674 motg->chg_type = USB_INVALID_CHARGER;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301675 msm_otg_reset(otg);
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301676 pm_runtime_put_noidle(otg->dev);
1677 pm_runtime_suspend(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301678 }
1679 break;
1680 case OTG_STATE_B_PERIPHERAL:
1681 dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n");
1682 if (!test_bit(B_SESS_VLD, &motg->inputs) ||
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001683 !test_bit(ID, &motg->inputs) ||
1684 !test_bit(ID_C, &motg->inputs)) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301685 msm_otg_start_peripheral(otg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001686 otg->state = OTG_STATE_B_IDLE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001687 schedule_work(w);
1688 } else if (test_bit(ID_C, &motg->inputs)) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301689 msm_otg_notify_charger(motg, IDEV_ACA_CHG_MAX);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001690 }
1691 break;
1692 case OTG_STATE_A_HOST:
1693 dev_dbg(otg->dev, "OTG_STATE_A_HOST state\n");
1694 if (test_bit(ID, &motg->inputs) &&
1695 !test_bit(ID_A, &motg->inputs)) {
1696 msm_otg_start_host(otg, 0);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301697 if (motg->pdata->vbus_power) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001698 motg->pdata->vbus_power(0);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301699 msleep(100); /* TA_WAIT_VFALL */
1700 }
1701 /*
1702 * Exit point of host mode.
1703 *
1704 * 1. Micro-A cable disconnect: Just schedule
1705 * the work. PHY is reset in B_IDLE and LPM
1706 * is allowed.
1707 * 2. ID_GND --> ID_B: No need to reset the PHY.
1708 * HCD core clears all PORTSC bits and initializes
1709 * the controller to host mode in remove_hcd.
1710 * Restore PORTSC transceiver select bits (ULPI)
1711 * and reset the controller to change MODE bits.
1712 * PHY_ALT interrupt can not occur in host mode.
1713 */
1714 del_timer_sync(&motg->id_timer);
1715 if (motg->chg_state != USB_CHG_STATE_UNDEFINED) {
1716 msm_otg_link_reset(motg);
1717 msm_chg_enable_aca_intr(motg);
1718 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301719 otg->state = OTG_STATE_B_IDLE;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301720 schedule_work(w);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001721 } else if (test_bit(ID_A, &motg->inputs)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001722 if (motg->pdata->vbus_power)
1723 motg->pdata->vbus_power(0);
1724 msm_otg_notify_charger(motg,
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301725 IDEV_ACA_CHG_MAX - motg->mA_port);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001726 } else if (!test_bit(ID, &motg->inputs)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001727 msm_otg_notify_charger(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001728 if (motg->pdata->vbus_power)
1729 motg->pdata->vbus_power(1);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301730 }
1731 break;
1732 default:
1733 break;
1734 }
1735}
1736
1737static irqreturn_t msm_otg_irq(int irq, void *data)
1738{
1739 struct msm_otg *motg = data;
1740 struct otg_transceiver *otg = &motg->otg;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001741 u32 otgsc = 0, usbsts;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301742
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301743 if (atomic_read(&motg->in_lpm)) {
1744 disable_irq_nosync(irq);
1745 motg->async_int = 1;
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301746 pm_request_resume(otg->dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301747 return IRQ_HANDLED;
1748 }
1749
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001750 usbsts = readl(USB_USBSTS);
1751 if ((usbsts & PHY_ALT_INT)) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301752 dev_dbg(otg->dev, "PHY_ALT interrupt\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001753 writel(PHY_ALT_INT, USB_USBSTS);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301754 if (msm_chg_check_aca_intr(motg)) {
1755 dev_dbg(otg->dev, "ACA work from IRQ\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001756 schedule_work(&motg->sm_work);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301757 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001758 return IRQ_HANDLED;
1759 }
1760
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301761 otgsc = readl(USB_OTGSC);
1762 if (!(otgsc & (OTGSC_IDIS | OTGSC_BSVIS)))
1763 return IRQ_NONE;
1764
1765 if ((otgsc & OTGSC_IDIS) && (otgsc & OTGSC_IDIE)) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301766 if (otgsc & OTGSC_ID) {
1767 dev_dbg(otg->dev, "ID set\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301768 set_bit(ID, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301769 } else {
1770 dev_dbg(otg->dev, "ID clear\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301771 clear_bit(ID, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301772 msm_chg_enable_aca_det(motg);
1773 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001774 schedule_work(&motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301775 } else if ((otgsc & OTGSC_BSVIS) && (otgsc & OTGSC_BSVIE)) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301776 if (otgsc & OTGSC_BSV) {
1777 dev_dbg(otg->dev, "BSV set\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301778 set_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301779 } else {
1780 dev_dbg(otg->dev, "BSV clear\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301781 clear_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301782 msm_chg_check_aca_intr(motg);
1783 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001784 schedule_work(&motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301785 }
1786
1787 writel(otgsc, USB_OTGSC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001788 return IRQ_HANDLED;
1789}
1790
1791static void msm_otg_set_vbus_state(int online)
1792{
1793 struct msm_otg *motg = the_msm_otg;
1794
1795 /* We depend on PMIC for only VBUS ON interrupt */
1796 if (!atomic_read(&motg->in_lpm) || !online)
1797 return;
1798
1799 /*
1800 * Let interrupt handler take care of resuming
1801 * the hardware.
1802 */
1803 msm_otg_irq(motg->irq, (void *) motg);
1804}
1805
1806static irqreturn_t msm_pmic_id_irq(int irq, void *data)
1807{
1808 struct msm_otg *motg = data;
1809
1810 if (atomic_read(&motg->in_lpm) && !motg->async_int)
1811 msm_otg_irq(motg->irq, motg);
1812
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301813 return IRQ_HANDLED;
1814}
1815
1816static int msm_otg_mode_show(struct seq_file *s, void *unused)
1817{
1818 struct msm_otg *motg = s->private;
1819 struct otg_transceiver *otg = &motg->otg;
1820
1821 switch (otg->state) {
1822 case OTG_STATE_A_HOST:
1823 seq_printf(s, "host\n");
1824 break;
1825 case OTG_STATE_B_PERIPHERAL:
1826 seq_printf(s, "peripheral\n");
1827 break;
1828 default:
1829 seq_printf(s, "none\n");
1830 break;
1831 }
1832
1833 return 0;
1834}
1835
1836static int msm_otg_mode_open(struct inode *inode, struct file *file)
1837{
1838 return single_open(file, msm_otg_mode_show, inode->i_private);
1839}
1840
1841static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf,
1842 size_t count, loff_t *ppos)
1843{
Pavankumar Kondetie2904ee2011-02-15 09:42:35 +05301844 struct seq_file *s = file->private_data;
1845 struct msm_otg *motg = s->private;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301846 char buf[16];
1847 struct otg_transceiver *otg = &motg->otg;
1848 int status = count;
1849 enum usb_mode_type req_mode;
1850
1851 memset(buf, 0x00, sizeof(buf));
1852
1853 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) {
1854 status = -EFAULT;
1855 goto out;
1856 }
1857
1858 if (!strncmp(buf, "host", 4)) {
1859 req_mode = USB_HOST;
1860 } else if (!strncmp(buf, "peripheral", 10)) {
1861 req_mode = USB_PERIPHERAL;
1862 } else if (!strncmp(buf, "none", 4)) {
1863 req_mode = USB_NONE;
1864 } else {
1865 status = -EINVAL;
1866 goto out;
1867 }
1868
1869 switch (req_mode) {
1870 case USB_NONE:
1871 switch (otg->state) {
1872 case OTG_STATE_A_HOST:
1873 case OTG_STATE_B_PERIPHERAL:
1874 set_bit(ID, &motg->inputs);
1875 clear_bit(B_SESS_VLD, &motg->inputs);
1876 break;
1877 default:
1878 goto out;
1879 }
1880 break;
1881 case USB_PERIPHERAL:
1882 switch (otg->state) {
1883 case OTG_STATE_B_IDLE:
1884 case OTG_STATE_A_HOST:
1885 set_bit(ID, &motg->inputs);
1886 set_bit(B_SESS_VLD, &motg->inputs);
1887 break;
1888 default:
1889 goto out;
1890 }
1891 break;
1892 case USB_HOST:
1893 switch (otg->state) {
1894 case OTG_STATE_B_IDLE:
1895 case OTG_STATE_B_PERIPHERAL:
1896 clear_bit(ID, &motg->inputs);
1897 break;
1898 default:
1899 goto out;
1900 }
1901 break;
1902 default:
1903 goto out;
1904 }
1905
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301906 pm_runtime_resume(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301907 schedule_work(&motg->sm_work);
1908out:
1909 return status;
1910}
1911
1912const struct file_operations msm_otg_mode_fops = {
1913 .open = msm_otg_mode_open,
1914 .read = seq_read,
1915 .write = msm_otg_mode_write,
1916 .llseek = seq_lseek,
1917 .release = single_release,
1918};
1919
Anji jonnalad270e2d2011-08-09 11:28:32 +05301920static int msm_otg_show_chg_type(struct seq_file *s, void *unused)
1921{
1922 struct msm_otg *motg = s->private;
1923
1924 seq_printf(s, chg_to_string(motg->chg_type));
1925 return 0;
1926}
1927
1928static int msm_otg_chg_open(struct inode *inode, struct file *file)
1929{
1930 return single_open(file, msm_otg_show_chg_type, inode->i_private);
1931}
1932
1933const struct file_operations msm_otg_chg_fops = {
1934 .open = msm_otg_chg_open,
1935 .read = seq_read,
1936 .llseek = seq_lseek,
1937 .release = single_release,
1938};
1939
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301940static int msm_otg_aca_show(struct seq_file *s, void *unused)
1941{
1942 if (debug_aca_enabled)
1943 seq_printf(s, "enabled\n");
1944 else
1945 seq_printf(s, "disabled\n");
1946
1947 return 0;
1948}
1949
1950static int msm_otg_aca_open(struct inode *inode, struct file *file)
1951{
1952 return single_open(file, msm_otg_aca_show, inode->i_private);
1953}
1954
1955static ssize_t msm_otg_aca_write(struct file *file, const char __user *ubuf,
1956 size_t count, loff_t *ppos)
1957{
1958 char buf[8];
1959
1960 memset(buf, 0x00, sizeof(buf));
1961
1962 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
1963 return -EFAULT;
1964
1965 if (!strncmp(buf, "enable", 6))
1966 debug_aca_enabled = true;
1967 else
1968 debug_aca_enabled = false;
1969
1970 return count;
1971}
1972
1973const struct file_operations msm_otg_aca_fops = {
1974 .open = msm_otg_aca_open,
1975 .read = seq_read,
1976 .write = msm_otg_aca_write,
1977 .llseek = seq_lseek,
1978 .release = single_release,
1979};
1980
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301981static struct dentry *msm_otg_dbg_root;
1982static struct dentry *msm_otg_dbg_mode;
Anji jonnalad270e2d2011-08-09 11:28:32 +05301983static struct dentry *msm_otg_chg_type;
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05301984static struct dentry *msm_otg_dbg_aca;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301985
1986static int msm_otg_debugfs_init(struct msm_otg *motg)
1987{
Anji jonnalad270e2d2011-08-09 11:28:32 +05301988
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301989 msm_otg_dbg_root = debugfs_create_dir("msm_otg", NULL);
1990
1991 if (!msm_otg_dbg_root || IS_ERR(msm_otg_dbg_root))
1992 return -ENODEV;
1993
Anji jonnalad270e2d2011-08-09 11:28:32 +05301994 if (motg->pdata->mode == USB_OTG &&
1995 motg->pdata->otg_control == OTG_USER_CONTROL) {
1996
1997 msm_otg_dbg_mode = debugfs_create_file("mode", S_IRUGO |
1998 S_IWUSR, msm_otg_dbg_root, motg,
1999 &msm_otg_mode_fops);
2000
2001 if (!msm_otg_dbg_mode) {
2002 debugfs_remove(msm_otg_dbg_root);
2003 msm_otg_dbg_root = NULL;
2004 return -ENODEV;
2005 }
2006 }
2007
2008 msm_otg_chg_type = debugfs_create_file("chg_type", S_IRUGO,
2009 msm_otg_dbg_root, motg,
2010 &msm_otg_chg_fops);
2011
2012 if (!msm_otg_chg_type) {
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302013 debugfs_remove_recursive(msm_otg_dbg_root);
2014 return -ENODEV;
2015 }
2016
2017 msm_otg_dbg_aca = debugfs_create_file("aca", S_IRUGO | S_IWUSR,
2018 msm_otg_dbg_root, motg,
2019 &msm_otg_aca_fops);
2020
2021 if (!msm_otg_dbg_aca) {
2022 debugfs_remove_recursive(msm_otg_dbg_root);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302023 return -ENODEV;
2024 }
2025
2026 return 0;
2027}
2028
2029static void msm_otg_debugfs_cleanup(void)
2030{
Anji jonnalad270e2d2011-08-09 11:28:32 +05302031 debugfs_remove_recursive(msm_otg_dbg_root);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302032}
2033
2034static int __init msm_otg_probe(struct platform_device *pdev)
2035{
2036 int ret = 0;
2037 struct resource *res;
2038 struct msm_otg *motg;
2039 struct otg_transceiver *otg;
2040
2041 dev_info(&pdev->dev, "msm_otg probe\n");
2042 if (!pdev->dev.platform_data) {
2043 dev_err(&pdev->dev, "No platform data given. Bailing out\n");
2044 return -ENODEV;
2045 }
2046
2047 motg = kzalloc(sizeof(struct msm_otg), GFP_KERNEL);
2048 if (!motg) {
2049 dev_err(&pdev->dev, "unable to allocate msm_otg\n");
2050 return -ENOMEM;
2051 }
2052
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002053 the_msm_otg = motg;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302054 motg->pdata = pdev->dev.platform_data;
2055 otg = &motg->otg;
2056 otg->dev = &pdev->dev;
2057
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302058 /*
2059 * ACA ID_GND threshold range is overlapped with OTG ID_FLOAT. Hence
2060 * PHY treat ACA ID_GND as float and no interrupt is generated. But
2061 * PMIC can detect ACA ID_GND and generate an interrupt.
2062 */
2063 if (aca_enabled() && motg->pdata->otg_control != OTG_PMIC_CONTROL) {
2064 dev_err(&pdev->dev, "ACA can not be enabled without PMIC\n");
2065 ret = -EINVAL;
2066 goto free_motg;
2067 }
2068
Amit Blay02eff132011-09-21 16:46:24 +03002069 /* Some targets don't support PHY clock. */
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302070 motg->phy_reset_clk = clk_get(&pdev->dev, "usb_phy_clk");
Amit Blay02eff132011-09-21 16:46:24 +03002071 if (IS_ERR(motg->phy_reset_clk))
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302072 dev_err(&pdev->dev, "failed to get usb_phy_clk\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302073
2074 motg->clk = clk_get(&pdev->dev, "usb_hs_clk");
2075 if (IS_ERR(motg->clk)) {
2076 dev_err(&pdev->dev, "failed to get usb_hs_clk\n");
2077 ret = PTR_ERR(motg->clk);
2078 goto put_phy_reset_clk;
2079 }
Anji jonnala0f73cac2011-05-04 10:19:46 +05302080 clk_set_rate(motg->clk, 60000000);
2081
2082 /*
2083 * If USB Core is running its protocol engine based on CORE CLK,
2084 * CORE CLK must be running at >55Mhz for correct HSUSB
2085 * operation and USB core cannot tolerate frequency changes on
2086 * CORE CLK. For such USB cores, vote for maximum clk frequency
2087 * on pclk source
2088 */
2089 if (motg->pdata->pclk_src_name) {
2090 motg->pclk_src = clk_get(&pdev->dev,
2091 motg->pdata->pclk_src_name);
2092 if (IS_ERR(motg->pclk_src))
2093 goto put_clk;
2094 clk_set_rate(motg->pclk_src, INT_MAX);
2095 clk_enable(motg->pclk_src);
2096 } else
2097 motg->pclk_src = ERR_PTR(-ENOENT);
2098
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302099 motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk");
2100 if (IS_ERR(motg->pclk)) {
2101 dev_err(&pdev->dev, "failed to get usb_hs_pclk\n");
2102 ret = PTR_ERR(motg->pclk);
Anji jonnala0f73cac2011-05-04 10:19:46 +05302103 goto put_pclk_src;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302104 }
2105
Amit Blay02eff132011-09-21 16:46:24 +03002106 motg->system_clk = clk_get(&pdev->dev, "usb_hs_system_clk");
2107 if (!IS_ERR(motg->system_clk))
2108 clk_enable(motg->system_clk);
2109
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302110 /*
2111 * USB core clock is not present on all MSM chips. This
2112 * clock is introduced to remove the dependency on AXI
2113 * bus frequency.
2114 */
2115 motg->core_clk = clk_get(&pdev->dev, "usb_hs_core_clk");
2116 if (IS_ERR(motg->core_clk))
2117 motg->core_clk = NULL;
2118
2119 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2120 if (!res) {
2121 dev_err(&pdev->dev, "failed to get platform resource mem\n");
2122 ret = -ENODEV;
2123 goto put_core_clk;
2124 }
2125
2126 motg->regs = ioremap(res->start, resource_size(res));
2127 if (!motg->regs) {
2128 dev_err(&pdev->dev, "ioremap failed\n");
2129 ret = -ENOMEM;
2130 goto put_core_clk;
2131 }
2132 dev_info(&pdev->dev, "OTG regs = %p\n", motg->regs);
2133
2134 motg->irq = platform_get_irq(pdev, 0);
2135 if (!motg->irq) {
2136 dev_err(&pdev->dev, "platform_get_irq failed\n");
2137 ret = -ENODEV;
2138 goto free_regs;
2139 }
2140
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302141 clk_enable(motg->pclk);
Anji jonnala11aa5c42011-05-04 10:19:48 +05302142
2143 ret = msm_hsusb_init_vddcx(motg, 1);
2144 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002145 dev_err(&pdev->dev, "hsusb vddcx init failed\n");
Anji jonnala11aa5c42011-05-04 10:19:48 +05302146 goto free_regs;
2147 }
2148
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002149 ret = msm_hsusb_config_vddcx(1);
2150 if (ret) {
2151 dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
2152 goto free_init_vddcx;
2153 }
2154
Anji jonnala11aa5c42011-05-04 10:19:48 +05302155 ret = msm_hsusb_ldo_init(motg, 1);
2156 if (ret) {
2157 dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002158 goto free_init_vddcx;
Anji jonnala11aa5c42011-05-04 10:19:48 +05302159 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002160
2161 ret = msm_hsusb_ldo_enable(motg, 1);
Anji jonnala11aa5c42011-05-04 10:19:48 +05302162 if (ret) {
2163 dev_err(&pdev->dev, "hsusb vreg enable failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002164 goto free_ldo_init;
Anji jonnala11aa5c42011-05-04 10:19:48 +05302165 }
2166
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302167 if (motg->core_clk)
2168 clk_enable(motg->core_clk);
2169
2170 writel(0, USB_USBINTR);
2171 writel(0, USB_OTGSC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002172 /* Ensure that above STOREs are completed before enabling interrupts */
2173 mb();
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302174
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002175 wake_lock_init(&motg->wlock, WAKE_LOCK_SUSPEND, "msm_otg");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302176 INIT_WORK(&motg->sm_work, msm_otg_sm_work);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302177 INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302178 setup_timer(&motg->id_timer, msm_otg_id_timer_func,
2179 (unsigned long) motg);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302180 ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
2181 "msm_otg", motg);
2182 if (ret) {
2183 dev_err(&pdev->dev, "request irq failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002184 goto destroy_wlock;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302185 }
2186
2187 otg->init = msm_otg_reset;
2188 otg->set_host = msm_otg_set_host;
2189 otg->set_peripheral = msm_otg_set_peripheral;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302190 otg->set_power = msm_otg_set_power;
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302191 otg->set_suspend = msm_otg_set_suspend;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302192
2193 otg->io_ops = &msm_otg_io_ops;
2194
2195 ret = otg_set_transceiver(&motg->otg);
2196 if (ret) {
2197 dev_err(&pdev->dev, "otg_set_transceiver failed\n");
2198 goto free_irq;
2199 }
2200
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002201 if (motg->pdata->otg_control == OTG_PMIC_CONTROL) {
2202 if (motg->pdata->pmic_id_irq) {
2203 ret = request_irq(motg->pdata->pmic_id_irq,
2204 msm_pmic_id_irq,
2205 IRQF_TRIGGER_RISING |
2206 IRQF_TRIGGER_FALLING,
2207 "msm_otg", motg);
2208 if (ret) {
2209 dev_err(&pdev->dev, "request irq failed for PMIC ID\n");
2210 goto remove_otg;
2211 }
2212 } else {
2213 ret = -ENODEV;
2214 dev_err(&pdev->dev, "PMIC IRQ for ID notifications doesn't exist\n");
2215 goto remove_otg;
2216 }
2217 }
2218
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +05302219 msm_hsusb_mhl_switch_enable(motg, 1);
2220
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302221 platform_set_drvdata(pdev, motg);
2222 device_init_wakeup(&pdev->dev, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002223 motg->mA_port = IUNIT;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302224
Anji jonnalad270e2d2011-08-09 11:28:32 +05302225 ret = msm_otg_debugfs_init(motg);
2226 if (ret)
2227 dev_dbg(&pdev->dev, "mode debugfs file is"
2228 "not available\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302229
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002230 if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
2231 pm8921_charger_register_vbus_sn(&msm_otg_set_vbus_state);
2232
2233 if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
2234 motg->pdata->otg_control == OTG_PMIC_CONTROL &&
2235 motg->pdata->pmic_id_irq)
2236 motg->caps = ALLOW_PHY_POWER_COLLAPSE |
2237 ALLOW_PHY_RETENTION |
2238 ALLOW_PHY_COMP_DISABLE;
2239
2240 wake_lock(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302241 pm_runtime_set_active(&pdev->dev);
2242 pm_runtime_enable(&pdev->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302243
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302244 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002245
2246remove_otg:
2247 otg_set_transceiver(NULL);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302248free_irq:
2249 free_irq(motg->irq, motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002250destroy_wlock:
2251 wake_lock_destroy(&motg->wlock);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302252 clk_disable(motg->pclk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002253 msm_hsusb_ldo_enable(motg, 0);
2254free_ldo_init:
Anji jonnala11aa5c42011-05-04 10:19:48 +05302255 msm_hsusb_ldo_init(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002256free_init_vddcx:
Anji jonnala11aa5c42011-05-04 10:19:48 +05302257 msm_hsusb_init_vddcx(motg, 0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302258free_regs:
2259 iounmap(motg->regs);
2260put_core_clk:
2261 if (motg->core_clk)
2262 clk_put(motg->core_clk);
Amit Blay02eff132011-09-21 16:46:24 +03002263
2264 if (!IS_ERR(motg->system_clk)) {
2265 clk_disable(motg->system_clk);
2266 clk_put(motg->system_clk);
2267 }
Anji jonnala0f73cac2011-05-04 10:19:46 +05302268put_pclk_src:
2269 if (!IS_ERR(motg->pclk_src)) {
2270 clk_disable(motg->pclk_src);
2271 clk_put(motg->pclk_src);
2272 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302273put_clk:
2274 clk_put(motg->clk);
2275put_phy_reset_clk:
Amit Blay02eff132011-09-21 16:46:24 +03002276 if (!IS_ERR(motg->phy_reset_clk))
2277 clk_put(motg->phy_reset_clk);
Pavankumar Kondetiaa449e12011-11-04 11:09:26 +05302278free_motg:
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302279 kfree(motg);
2280 return ret;
2281}
2282
2283static int __devexit msm_otg_remove(struct platform_device *pdev)
2284{
2285 struct msm_otg *motg = platform_get_drvdata(pdev);
2286 struct otg_transceiver *otg = &motg->otg;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302287 int cnt = 0;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302288
2289 if (otg->host || otg->gadget)
2290 return -EBUSY;
2291
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002292 if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
2293 pm8921_charger_unregister_vbus_sn(0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302294 msm_otg_debugfs_cleanup();
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302295 cancel_delayed_work_sync(&motg->chg_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302296 cancel_work_sync(&motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302297
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302298 pm_runtime_resume(&pdev->dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302299
2300 device_init_wakeup(&pdev->dev, 0);
2301 pm_runtime_disable(&pdev->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002302 wake_lock_destroy(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302303
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +05302304 msm_hsusb_mhl_switch_enable(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002305 if (motg->pdata->pmic_id_irq)
2306 free_irq(motg->pdata->pmic_id_irq, motg);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302307 otg_set_transceiver(NULL);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302308 free_irq(motg->irq, motg);
2309
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302310 /*
2311 * Put PHY in low power mode.
2312 */
2313 ulpi_read(otg, 0x14);
2314 ulpi_write(otg, 0x08, 0x09);
2315
2316 writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
2317 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
2318 if (readl(USB_PORTSC) & PORTSC_PHCD)
2319 break;
2320 udelay(1);
2321 cnt++;
2322 }
2323 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC)
2324 dev_err(otg->dev, "Unable to suspend PHY\n");
2325
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302326 clk_disable(motg->pclk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302327 if (motg->core_clk)
2328 clk_disable(motg->core_clk);
Amit Blay137575f2011-11-06 15:20:54 +02002329 if (!IS_ERR(motg->system_clk))
2330 clk_disable(motg->system_clk);
Anji jonnala0f73cac2011-05-04 10:19:46 +05302331 if (!IS_ERR(motg->pclk_src)) {
2332 clk_disable(motg->pclk_src);
2333 clk_put(motg->pclk_src);
2334 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002335 msm_hsusb_ldo_enable(motg, 0);
Anji jonnala11aa5c42011-05-04 10:19:48 +05302336 msm_hsusb_ldo_init(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002337 msm_hsusb_init_vddcx(motg, 0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302338
2339 iounmap(motg->regs);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302340 pm_runtime_set_suspended(&pdev->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302341
Amit Blay02eff132011-09-21 16:46:24 +03002342 if (!IS_ERR(motg->phy_reset_clk))
2343 clk_put(motg->phy_reset_clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302344 clk_put(motg->pclk);
2345 clk_put(motg->clk);
2346 if (motg->core_clk)
2347 clk_put(motg->core_clk);
Amit Blay02eff132011-09-21 16:46:24 +03002348 if (!IS_ERR(motg->system_clk))
2349 clk_put(motg->system_clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302350
2351 kfree(motg);
2352
2353 return 0;
2354}
2355
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302356#ifdef CONFIG_PM_RUNTIME
2357static int msm_otg_runtime_idle(struct device *dev)
2358{
2359 struct msm_otg *motg = dev_get_drvdata(dev);
2360 struct otg_transceiver *otg = &motg->otg;
2361
2362 dev_dbg(dev, "OTG runtime idle\n");
2363
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302364 if (otg->state == OTG_STATE_UNDEFINED)
2365 return -EAGAIN;
2366 else
2367 return 0;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302368}
2369
2370static int msm_otg_runtime_suspend(struct device *dev)
2371{
2372 struct msm_otg *motg = dev_get_drvdata(dev);
2373
2374 dev_dbg(dev, "OTG runtime suspend\n");
2375 return msm_otg_suspend(motg);
2376}
2377
2378static int msm_otg_runtime_resume(struct device *dev)
2379{
2380 struct msm_otg *motg = dev_get_drvdata(dev);
2381
2382 dev_dbg(dev, "OTG runtime resume\n");
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302383 pm_runtime_get_noresume(dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302384 return msm_otg_resume(motg);
2385}
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302386#endif
2387
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302388#ifdef CONFIG_PM_SLEEP
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302389static int msm_otg_pm_suspend(struct device *dev)
2390{
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302391 int ret;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302392
2393 dev_dbg(dev, "OTG PM suspend\n");
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302394
2395#ifdef CONFIG_PM_RUNTIME
2396 ret = pm_runtime_suspend(dev);
2397 if (ret > 0)
2398 ret = 0;
2399#else
2400 ret = msm_otg_suspend(dev_get_drvdata(dev));
2401#endif
2402 return ret;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302403}
2404
2405static int msm_otg_pm_resume(struct device *dev)
2406{
2407 struct msm_otg *motg = dev_get_drvdata(dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302408
2409 dev_dbg(dev, "OTG PM resume\n");
2410
Manu Gautamf284c052011-09-08 16:52:48 +05302411#ifdef CONFIG_PM_RUNTIME
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302412 /*
Manu Gautamf284c052011-09-08 16:52:48 +05302413 * Do not resume hardware as part of system resume,
2414 * rather, wait for the ASYNC INT from the h/w
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302415 */
Gregory Beanebd8ca22011-10-11 12:02:35 -07002416 return 0;
Manu Gautamf284c052011-09-08 16:52:48 +05302417#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302418
Manu Gautamf284c052011-09-08 16:52:48 +05302419 return msm_otg_resume(motg);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302420}
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302421#endif
2422
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302423#ifdef CONFIG_PM
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302424static const struct dev_pm_ops msm_otg_dev_pm_ops = {
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302425 SET_SYSTEM_SLEEP_PM_OPS(msm_otg_pm_suspend, msm_otg_pm_resume)
2426 SET_RUNTIME_PM_OPS(msm_otg_runtime_suspend, msm_otg_runtime_resume,
2427 msm_otg_runtime_idle)
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302428};
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302429#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302430
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302431static struct platform_driver msm_otg_driver = {
2432 .remove = __devexit_p(msm_otg_remove),
2433 .driver = {
2434 .name = DRIVER_NAME,
2435 .owner = THIS_MODULE,
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302436#ifdef CONFIG_PM
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302437 .pm = &msm_otg_dev_pm_ops,
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302438#endif
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302439 },
2440};
2441
2442static int __init msm_otg_init(void)
2443{
2444 return platform_driver_probe(&msm_otg_driver, msm_otg_probe);
2445}
2446
2447static void __exit msm_otg_exit(void)
2448{
2449 platform_driver_unregister(&msm_otg_driver);
2450}
2451
2452module_init(msm_otg_init);
2453module_exit(msm_otg_exit);
2454
2455MODULE_LICENSE("GPL v2");
2456MODULE_DESCRIPTION("MSM USB transceiver driver");