blob: d16fcdabbc1b8ae8c6494e5262fcd5e3bb142625 [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
Vamsi Krishna132b2762011-11-11 16:09:20 -080077#define USB_PHY_VDD_DIG_VOL_MIN 1045000 /* uV */
Anji jonnala11aa5c42011-05-04 10:19:48 +053078#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}
Hemant Kumar8e7bd072011-08-01 14:14:24 -0700207#else
208static int msm_hsusb_config_vddcx(int high)
209{
210 return 0;
211}
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530212#endif
213
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700214static int msm_hsusb_ldo_enable(struct msm_otg *motg, int on)
Anji jonnala11aa5c42011-05-04 10:19:48 +0530215{
216 int ret = 0;
217
Pavankumar Kondeti68964c92011-10-27 14:58:56 +0530218 if (IS_ERR(hsusb_1p8)) {
Anji jonnala11aa5c42011-05-04 10:19:48 +0530219 pr_err("%s: HSUSB_1p8 is not initialized\n", __func__);
220 return -ENODEV;
221 }
222
Pavankumar Kondeti68964c92011-10-27 14:58:56 +0530223 if (IS_ERR(hsusb_3p3)) {
Anji jonnala11aa5c42011-05-04 10:19:48 +0530224 pr_err("%s: HSUSB_3p3 is not initialized\n", __func__);
225 return -ENODEV;
226 }
227
228 if (on) {
229 ret = regulator_set_optimum_mode(hsusb_1p8,
230 USB_PHY_1P8_HPM_LOAD);
231 if (ret < 0) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700232 pr_err("%s: Unable to set HPM of the regulator:"
Anji jonnala11aa5c42011-05-04 10:19:48 +0530233 "HSUSB_1p8\n", __func__);
234 return ret;
235 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700236
237 ret = regulator_enable(hsusb_1p8);
238 if (ret) {
239 dev_err(motg->otg.dev, "%s: unable to enable the hsusb 1p8\n",
240 __func__);
241 regulator_set_optimum_mode(hsusb_1p8, 0);
242 return ret;
243 }
244
Anji jonnala11aa5c42011-05-04 10:19:48 +0530245 ret = regulator_set_optimum_mode(hsusb_3p3,
246 USB_PHY_3P3_HPM_LOAD);
247 if (ret < 0) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700248 pr_err("%s: Unable to set HPM of the regulator:"
Anji jonnala11aa5c42011-05-04 10:19:48 +0530249 "HSUSB_3p3\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700250 regulator_set_optimum_mode(hsusb_1p8, 0);
251 regulator_disable(hsusb_1p8);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530252 return ret;
253 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700254
255 ret = regulator_enable(hsusb_3p3);
256 if (ret) {
257 dev_err(motg->otg.dev, "%s: unable to enable the hsusb 3p3\n",
258 __func__);
259 regulator_set_optimum_mode(hsusb_3p3, 0);
260 regulator_set_optimum_mode(hsusb_1p8, 0);
261 regulator_disable(hsusb_1p8);
262 return ret;
263 }
264
Anji jonnala11aa5c42011-05-04 10:19:48 +0530265 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700266 ret = regulator_disable(hsusb_1p8);
267 if (ret) {
268 dev_err(motg->otg.dev, "%s: unable to disable the hsusb 1p8\n",
269 __func__);
270 return ret;
271 }
272
273 ret = regulator_set_optimum_mode(hsusb_1p8, 0);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530274 if (ret < 0)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700275 pr_err("%s: Unable to set LPM of the regulator:"
Anji jonnala11aa5c42011-05-04 10:19:48 +0530276 "HSUSB_1p8\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700277
278 ret = regulator_disable(hsusb_3p3);
279 if (ret) {
280 dev_err(motg->otg.dev, "%s: unable to disable the hsusb 3p3\n",
281 __func__);
282 return ret;
283 }
284 ret = regulator_set_optimum_mode(hsusb_3p3, 0);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530285 if (ret < 0)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700286 pr_err("%s: Unable to set LPM of the regulator:"
Anji jonnala11aa5c42011-05-04 10:19:48 +0530287 "HSUSB_3p3\n", __func__);
288 }
289
290 pr_debug("reg (%s)\n", on ? "HPM" : "LPM");
291 return ret < 0 ? ret : 0;
292}
293
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530294static void msm_hsusb_mhl_switch_enable(struct msm_otg *motg, bool on)
295{
296 static struct regulator *mhl_analog_switch;
297 struct msm_otg_platform_data *pdata = motg->pdata;
298
299 if (!pdata->mhl_enable)
300 return;
301
302 if (on) {
303 mhl_analog_switch = regulator_get(motg->otg.dev,
304 "mhl_ext_3p3v");
305 if (IS_ERR(mhl_analog_switch)) {
306 pr_err("Unable to get mhl_analog_switch\n");
307 return;
308 }
309
310 if (regulator_enable(mhl_analog_switch)) {
311 pr_err("unable to enable mhl_analog_switch\n");
312 goto put_analog_switch;
313 }
314 return;
315 }
316
317 regulator_disable(mhl_analog_switch);
318put_analog_switch:
319 regulator_put(mhl_analog_switch);
320}
321
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530322static int ulpi_read(struct otg_transceiver *otg, u32 reg)
323{
324 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
325 int cnt = 0;
326
327 /* initiate read operation */
328 writel(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
329 USB_ULPI_VIEWPORT);
330
331 /* wait for completion */
332 while (cnt < ULPI_IO_TIMEOUT_USEC) {
333 if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN))
334 break;
335 udelay(1);
336 cnt++;
337 }
338
339 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
340 dev_err(otg->dev, "ulpi_read: timeout %08x\n",
341 readl(USB_ULPI_VIEWPORT));
342 return -ETIMEDOUT;
343 }
344 return ULPI_DATA_READ(readl(USB_ULPI_VIEWPORT));
345}
346
347static int ulpi_write(struct otg_transceiver *otg, u32 val, u32 reg)
348{
349 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
350 int cnt = 0;
351
352 /* initiate write operation */
353 writel(ULPI_RUN | ULPI_WRITE |
354 ULPI_ADDR(reg) | ULPI_DATA(val),
355 USB_ULPI_VIEWPORT);
356
357 /* wait for completion */
358 while (cnt < ULPI_IO_TIMEOUT_USEC) {
359 if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN))
360 break;
361 udelay(1);
362 cnt++;
363 }
364
365 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
366 dev_err(otg->dev, "ulpi_write: timeout\n");
367 return -ETIMEDOUT;
368 }
369 return 0;
370}
371
372static struct otg_io_access_ops msm_otg_io_ops = {
373 .read = ulpi_read,
374 .write = ulpi_write,
375};
376
377static void ulpi_init(struct msm_otg *motg)
378{
379 struct msm_otg_platform_data *pdata = motg->pdata;
380 int *seq = pdata->phy_init_seq;
381
382 if (!seq)
383 return;
384
385 while (seq[0] >= 0) {
386 dev_vdbg(motg->otg.dev, "ulpi: write 0x%02x to 0x%02x\n",
387 seq[0], seq[1]);
388 ulpi_write(&motg->otg, seq[0], seq[1]);
389 seq += 2;
390 }
391}
392
393static int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert)
394{
395 int ret;
396
397 if (assert) {
398 ret = clk_reset(motg->clk, CLK_RESET_ASSERT);
399 if (ret)
400 dev_err(motg->otg.dev, "usb hs_clk assert failed\n");
401 } else {
402 ret = clk_reset(motg->clk, CLK_RESET_DEASSERT);
403 if (ret)
404 dev_err(motg->otg.dev, "usb hs_clk deassert failed\n");
405 }
406 return ret;
407}
408
409static int msm_otg_phy_clk_reset(struct msm_otg *motg)
410{
411 int ret;
412
Amit Blay02eff132011-09-21 16:46:24 +0300413 if (IS_ERR(motg->phy_reset_clk))
414 return 0;
415
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530416 ret = clk_reset(motg->phy_reset_clk, CLK_RESET_ASSERT);
417 if (ret) {
418 dev_err(motg->otg.dev, "usb phy clk assert failed\n");
419 return ret;
420 }
421 usleep_range(10000, 12000);
422 ret = clk_reset(motg->phy_reset_clk, CLK_RESET_DEASSERT);
423 if (ret)
424 dev_err(motg->otg.dev, "usb phy clk deassert failed\n");
425 return ret;
426}
427
428static int msm_otg_phy_reset(struct msm_otg *motg)
429{
430 u32 val;
431 int ret;
432 int retries;
433
434 ret = msm_otg_link_clk_reset(motg, 1);
435 if (ret)
436 return ret;
437 ret = msm_otg_phy_clk_reset(motg);
438 if (ret)
439 return ret;
440 ret = msm_otg_link_clk_reset(motg, 0);
441 if (ret)
442 return ret;
443
444 val = readl(USB_PORTSC) & ~PORTSC_PTS_MASK;
445 writel(val | PORTSC_PTS_ULPI, USB_PORTSC);
446
447 for (retries = 3; retries > 0; retries--) {
448 ret = ulpi_write(&motg->otg, ULPI_FUNC_CTRL_SUSPENDM,
449 ULPI_CLR(ULPI_FUNC_CTRL));
450 if (!ret)
451 break;
452 ret = msm_otg_phy_clk_reset(motg);
453 if (ret)
454 return ret;
455 }
456 if (!retries)
457 return -ETIMEDOUT;
458
459 /* This reset calibrates the phy, if the above write succeeded */
460 ret = msm_otg_phy_clk_reset(motg);
461 if (ret)
462 return ret;
463
464 for (retries = 3; retries > 0; retries--) {
465 ret = ulpi_read(&motg->otg, ULPI_DEBUG);
466 if (ret != -ETIMEDOUT)
467 break;
468 ret = msm_otg_phy_clk_reset(motg);
469 if (ret)
470 return ret;
471 }
472 if (!retries)
473 return -ETIMEDOUT;
474
475 dev_info(motg->otg.dev, "phy_reset: success\n");
476 return 0;
477}
478
479#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
480static int msm_otg_reset(struct otg_transceiver *otg)
481{
482 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
483 struct msm_otg_platform_data *pdata = motg->pdata;
484 int cnt = 0;
485 int ret;
486 u32 val = 0;
487 u32 ulpi_val = 0;
488
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700489 clk_enable(motg->clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530490 ret = msm_otg_phy_reset(motg);
491 if (ret) {
492 dev_err(otg->dev, "phy_reset failed\n");
493 return ret;
494 }
495
496 ulpi_init(motg);
497
498 writel(USBCMD_RESET, USB_USBCMD);
499 while (cnt < LINK_RESET_TIMEOUT_USEC) {
500 if (!(readl(USB_USBCMD) & USBCMD_RESET))
501 break;
502 udelay(1);
503 cnt++;
504 }
505 if (cnt >= LINK_RESET_TIMEOUT_USEC)
506 return -ETIMEDOUT;
507
508 /* select ULPI phy */
509 writel(0x80000000, USB_PORTSC);
510
511 msleep(100);
512
513 writel(0x0, USB_AHBBURST);
514 writel(0x00, USB_AHBMODE);
515
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700516 /* Ensure that RESET operation is completed before turning off clock */
517 mb();
518 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
532 msm_chg_enable_aca_det(motg);
533 msm_chg_enable_aca_intr(motg);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530534
535 return 0;
536}
537
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530538#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
Pavankumar Kondeti70187732011-02-15 09:42:34 +0530539#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
540
541#ifdef CONFIG_PM_SLEEP
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530542static int msm_otg_suspend(struct msm_otg *motg)
543{
544 struct otg_transceiver *otg = &motg->otg;
545 struct usb_bus *bus = otg->host;
546 struct msm_otg_platform_data *pdata = motg->pdata;
547 int cnt = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700548 bool session_active;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530549
550 if (atomic_read(&motg->in_lpm))
551 return 0;
552
553 disable_irq(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700554 session_active = (otg->host && !test_bit(ID, &motg->inputs)) ||
555 test_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530556 /*
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530557 * Chipidea 45-nm PHY suspend sequence:
558 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530559 * Interrupt Latch Register auto-clear feature is not present
560 * in all PHY versions. Latch register is clear on read type.
561 * Clear latch register to avoid spurious wakeup from
562 * low power mode (LPM).
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530563 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530564 * PHY comparators are disabled when PHY enters into low power
565 * mode (LPM). Keep PHY comparators ON in LPM only when we expect
566 * VBUS/Id notifications from USB PHY. Otherwise turn off USB
567 * PHY comparators. This save significant amount of power.
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530568 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530569 * PLL is not turned off when PHY enters into low power mode (LPM).
570 * Disable PLL for maximum power savings.
571 */
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530572
573 if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) {
574 ulpi_read(otg, 0x14);
575 if (pdata->otg_control == OTG_PHY_CONTROL)
576 ulpi_write(otg, 0x01, 0x30);
577 ulpi_write(otg, 0x08, 0x09);
578 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530579
580 /*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700581 * Turn off the OTG comparators, if depends on PMIC for
582 * VBUS and ID notifications.
583 */
584 if ((motg->caps & ALLOW_PHY_COMP_DISABLE) && !session_active) {
585 ulpi_write(otg, OTG_COMP_DISABLE,
586 ULPI_SET(ULPI_PWR_CLK_MNG_REG));
587 motg->lpm_flags |= PHY_OTG_COMP_DISABLED;
588 }
589
590 /*
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530591 * PHY may take some time or even fail to enter into low power
592 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
593 * in failure case.
594 */
595 writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
596 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
597 if (readl(USB_PORTSC) & PORTSC_PHCD)
598 break;
599 udelay(1);
600 cnt++;
601 }
602
603 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
604 dev_err(otg->dev, "Unable to suspend PHY\n");
605 msm_otg_reset(otg);
606 enable_irq(motg->irq);
607 return -ETIMEDOUT;
608 }
609
610 /*
611 * PHY has capability to generate interrupt asynchronously in low
612 * power mode (LPM). This interrupt is level triggered. So USB IRQ
613 * line must be disabled till async interrupt enable bit is cleared
614 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
615 * block data communication from PHY.
616 */
617 writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);
618
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700619 if (motg->caps & ALLOW_PHY_RETENTION && !session_active) {
620 writel_relaxed(readl_relaxed(USB_PHY_CTRL) & ~PHY_RETEN,
621 USB_PHY_CTRL);
622 motg->lpm_flags |= PHY_RETENTIONED;
623 }
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530624
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700625 /* Ensure that above operation is completed before turning off clocks */
626 mb();
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530627 clk_disable(motg->pclk);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530628 if (motg->core_clk)
629 clk_disable(motg->core_clk);
630
Amit Blay137575f2011-11-06 15:20:54 +0200631 if (!IS_ERR(motg->system_clk))
632 clk_disable(motg->system_clk);
633
Anji jonnala0f73cac2011-05-04 10:19:46 +0530634 if (!IS_ERR(motg->pclk_src))
635 clk_disable(motg->pclk_src);
636
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700637 if (motg->caps & ALLOW_PHY_POWER_COLLAPSE && !session_active) {
638 msm_hsusb_ldo_enable(motg, 0);
639 motg->lpm_flags |= PHY_PWR_COLLAPSED;
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530640 }
641
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530642 if (motg->lpm_flags & PHY_RETENTIONED) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700643 msm_hsusb_config_vddcx(0);
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530644 msm_hsusb_mhl_switch_enable(motg, 0);
645 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700646
647 if (device_may_wakeup(otg->dev)) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530648 enable_irq_wake(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700649 if (motg->pdata->pmic_id_irq)
650 enable_irq_wake(motg->pdata->pmic_id_irq);
651 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530652 if (bus)
653 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
654
655 atomic_set(&motg->in_lpm, 1);
656 enable_irq(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700657 wake_unlock(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530658
659 dev_info(otg->dev, "USB in low power mode\n");
660
661 return 0;
662}
663
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530664static int msm_otg_resume(struct msm_otg *motg)
665{
666 struct otg_transceiver *otg = &motg->otg;
667 struct usb_bus *bus = otg->host;
668 int cnt = 0;
669 unsigned temp;
670
671 if (!atomic_read(&motg->in_lpm))
672 return 0;
673
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700674 wake_lock(&motg->wlock);
Anji jonnala0f73cac2011-05-04 10:19:46 +0530675 if (!IS_ERR(motg->pclk_src))
676 clk_enable(motg->pclk_src);
677
Amit Blay137575f2011-11-06 15:20:54 +0200678 if (!IS_ERR(motg->system_clk))
679 clk_enable(motg->system_clk);
680
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530681 clk_enable(motg->pclk);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530682 if (motg->core_clk)
683 clk_enable(motg->core_clk);
684
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700685 if (motg->lpm_flags & PHY_PWR_COLLAPSED) {
686 msm_hsusb_ldo_enable(motg, 1);
687 motg->lpm_flags &= ~PHY_PWR_COLLAPSED;
688 }
689
690 if (motg->lpm_flags & PHY_RETENTIONED) {
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530691 msm_hsusb_mhl_switch_enable(motg, 1);
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530692 msm_hsusb_config_vddcx(1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700693 writel_relaxed(readl_relaxed(USB_PHY_CTRL) | PHY_RETEN,
694 USB_PHY_CTRL);
695 motg->lpm_flags &= ~PHY_RETENTIONED;
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530696 }
697
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530698 temp = readl(USB_USBCMD);
699 temp &= ~ASYNC_INTR_CTRL;
700 temp &= ~ULPI_STP_CTRL;
701 writel(temp, USB_USBCMD);
702
703 /*
704 * PHY comes out of low power mode (LPM) in case of wakeup
705 * from asynchronous interrupt.
706 */
707 if (!(readl(USB_PORTSC) & PORTSC_PHCD))
708 goto skip_phy_resume;
709
710 writel(readl(USB_PORTSC) & ~PORTSC_PHCD, USB_PORTSC);
711 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
712 if (!(readl(USB_PORTSC) & PORTSC_PHCD))
713 break;
714 udelay(1);
715 cnt++;
716 }
717
718 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
719 /*
720 * This is a fatal error. Reset the link and
721 * PHY. USB state can not be restored. Re-insertion
722 * of USB cable is the only way to get USB working.
723 */
724 dev_err(otg->dev, "Unable to resume USB."
725 "Re-plugin the cable\n");
726 msm_otg_reset(otg);
727 }
728
729skip_phy_resume:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700730 /* Turn on the OTG comparators on resume */
731 if (motg->lpm_flags & PHY_OTG_COMP_DISABLED) {
732 ulpi_write(otg, OTG_COMP_DISABLE,
733 ULPI_CLR(ULPI_PWR_CLK_MNG_REG));
734 motg->lpm_flags &= ~PHY_OTG_COMP_DISABLED;
735 }
736 if (device_may_wakeup(otg->dev)) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530737 disable_irq_wake(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700738 if (motg->pdata->pmic_id_irq)
739 disable_irq_wake(motg->pdata->pmic_id_irq);
740 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530741 if (bus)
742 set_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
743
Pavankumar Kondeti2ce2c3a2011-05-02 11:56:33 +0530744 atomic_set(&motg->in_lpm, 0);
745
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530746 if (motg->async_int) {
747 motg->async_int = 0;
748 pm_runtime_put(otg->dev);
749 enable_irq(motg->irq);
750 }
751
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530752 dev_info(otg->dev, "USB exited from low power mode\n");
753
754 return 0;
755}
Pavankumar Kondeti70187732011-02-15 09:42:34 +0530756#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530757
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530758static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA)
759{
760 if (motg->cur_power == mA)
761 return;
762
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530763 dev_info(motg->otg.dev, "Avail curr from USB = %u\n", mA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700764 pm8921_charger_vbus_draw(mA);
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530765 motg->cur_power = mA;
766}
767
768static int msm_otg_set_power(struct otg_transceiver *otg, unsigned mA)
769{
770 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
771
772 /*
773 * Gadget driver uses set_power method to notify about the
774 * available current based on suspend/configured states.
775 *
776 * IDEV_CHG can be drawn irrespective of suspend/un-configured
777 * states when CDP/ACA is connected.
778 */
779 if (motg->chg_type == USB_SDP_CHARGER)
780 msm_otg_notify_charger(motg, mA);
781
782 return 0;
783}
784
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530785static void msm_otg_start_host(struct otg_transceiver *otg, int on)
786{
787 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
788 struct msm_otg_platform_data *pdata = motg->pdata;
789 struct usb_hcd *hcd;
790
791 if (!otg->host)
792 return;
793
794 hcd = bus_to_hcd(otg->host);
795
796 if (on) {
797 dev_dbg(otg->dev, "host on\n");
798
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530799 /*
800 * Some boards have a switch cotrolled by gpio
801 * to enable/disable internal HUB. Enable internal
802 * HUB before kicking the host.
803 */
804 if (pdata->setup_gpio)
805 pdata->setup_gpio(OTG_STATE_A_HOST);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530806 usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530807 } else {
808 dev_dbg(otg->dev, "host off\n");
809
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530810 usb_remove_hcd(hcd);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530811 if (pdata->setup_gpio)
812 pdata->setup_gpio(OTG_STATE_UNDEFINED);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530813 }
814}
815
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700816static int msm_otg_usbdev_notify(struct notifier_block *self,
817 unsigned long action, void *priv)
818{
819 struct msm_otg *motg = container_of(self, struct msm_otg, usbdev_nb);
820 struct usb_device *udev;
821
822 switch (action) {
823 case USB_DEVICE_ADD:
824 case USB_DEVICE_CONFIG:
825 udev = priv;
826 /*
827 * Interested in devices connected directly to the root hub.
828 * ACA dock can supply IDEV_CHG irrespective devices connected
829 * on the accessory port.
830 */
831 if (!udev->parent || udev->parent->parent ||
832 motg->chg_type == USB_ACA_DOCK_CHARGER)
833 break;
834 if (udev->actconfig)
835 motg->mA_port = udev->actconfig->desc.bMaxPower * 2;
836 else
837 motg->mA_port = IUNIT;
838
839 if (test_bit(ID_A, &motg->inputs))
840 msm_otg_notify_charger(motg, IDEV_CHG_MIN -
841 motg->mA_port);
842 break;
843 default:
844 break;
845 }
846 return NOTIFY_OK;
847}
848
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530849static int msm_otg_set_host(struct otg_transceiver *otg, struct usb_bus *host)
850{
851 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
852 struct usb_hcd *hcd;
853
854 /*
855 * Fail host registration if this board can support
856 * only peripheral configuration.
857 */
858 if (motg->pdata->mode == USB_PERIPHERAL) {
859 dev_info(otg->dev, "Host mode is not supported\n");
860 return -ENODEV;
861 }
862
863 if (!host) {
864 if (otg->state == OTG_STATE_A_HOST) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530865 pm_runtime_get_sync(otg->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700866 usb_unregister_notify(&motg->usbdev_nb);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530867 msm_otg_start_host(otg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700868 if (motg->pdata->vbus_power)
869 motg->pdata->vbus_power(0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530870 otg->host = NULL;
871 otg->state = OTG_STATE_UNDEFINED;
872 schedule_work(&motg->sm_work);
873 } else {
874 otg->host = NULL;
875 }
876
877 return 0;
878 }
879
880 hcd = bus_to_hcd(host);
881 hcd->power_budget = motg->pdata->power_budget;
882
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700883 motg->usbdev_nb.notifier_call = msm_otg_usbdev_notify;
884 usb_register_notify(&motg->usbdev_nb);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530885 otg->host = host;
886 dev_dbg(otg->dev, "host driver registered w/ tranceiver\n");
887
888 /*
889 * Kick the state machine work, if peripheral is not supported
890 * or peripheral is already registered with us.
891 */
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530892 if (motg->pdata->mode == USB_HOST || otg->gadget) {
893 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530894 schedule_work(&motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530895 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530896
897 return 0;
898}
899
900static void msm_otg_start_peripheral(struct otg_transceiver *otg, int on)
901{
902 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
903 struct msm_otg_platform_data *pdata = motg->pdata;
904
905 if (!otg->gadget)
906 return;
907
908 if (on) {
909 dev_dbg(otg->dev, "gadget on\n");
910 /*
911 * Some boards have a switch cotrolled by gpio
912 * to enable/disable internal HUB. Disable internal
913 * HUB before kicking the gadget.
914 */
915 if (pdata->setup_gpio)
916 pdata->setup_gpio(OTG_STATE_B_PERIPHERAL);
917 usb_gadget_vbus_connect(otg->gadget);
918 } else {
919 dev_dbg(otg->dev, "gadget off\n");
920 usb_gadget_vbus_disconnect(otg->gadget);
921 if (pdata->setup_gpio)
922 pdata->setup_gpio(OTG_STATE_UNDEFINED);
923 }
924
925}
926
927static int msm_otg_set_peripheral(struct otg_transceiver *otg,
928 struct usb_gadget *gadget)
929{
930 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
931
932 /*
933 * Fail peripheral registration if this board can support
934 * only host configuration.
935 */
936 if (motg->pdata->mode == USB_HOST) {
937 dev_info(otg->dev, "Peripheral mode is not supported\n");
938 return -ENODEV;
939 }
940
941 if (!gadget) {
942 if (otg->state == OTG_STATE_B_PERIPHERAL) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530943 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530944 msm_otg_start_peripheral(otg, 0);
945 otg->gadget = NULL;
946 otg->state = OTG_STATE_UNDEFINED;
947 schedule_work(&motg->sm_work);
948 } else {
949 otg->gadget = NULL;
950 }
951
952 return 0;
953 }
954 otg->gadget = gadget;
955 dev_dbg(otg->dev, "peripheral driver registered w/ tranceiver\n");
956
957 /*
958 * Kick the state machine work, if host is not supported
959 * or host is already registered with us.
960 */
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530961 if (motg->pdata->mode == USB_PERIPHERAL || otg->host) {
962 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530963 schedule_work(&motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530964 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530965
966 return 0;
967}
968
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700969#ifdef CONFIG_USB_MSM_ACA
970static bool msm_chg_aca_detect(struct msm_otg *motg)
971{
972 struct otg_transceiver *otg = &motg->otg;
973 u32 int_sts;
974 bool ret = false;
975
976 if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY)
977 goto out;
978
979 int_sts = ulpi_read(otg, 0x87);
980 switch (int_sts & 0x1C) {
981 case 0x08:
982 if (!test_and_set_bit(ID_A, &motg->inputs)) {
983 dev_dbg(otg->dev, "ID_A\n");
984 motg->chg_type = USB_ACA_A_CHARGER;
985 motg->chg_state = USB_CHG_STATE_DETECTED;
986 clear_bit(ID_B, &motg->inputs);
987 clear_bit(ID_C, &motg->inputs);
988 ret = true;
989 }
990 break;
991 case 0x0C:
992 if (!test_and_set_bit(ID_B, &motg->inputs)) {
993 dev_dbg(otg->dev, "ID_B\n");
994 motg->chg_type = USB_ACA_B_CHARGER;
995 motg->chg_state = USB_CHG_STATE_DETECTED;
996 clear_bit(ID_A, &motg->inputs);
997 clear_bit(ID_C, &motg->inputs);
998 ret = true;
999 }
1000 break;
1001 case 0x10:
1002 if (!test_and_set_bit(ID_C, &motg->inputs)) {
1003 dev_dbg(otg->dev, "ID_C\n");
1004 motg->chg_type = USB_ACA_C_CHARGER;
1005 motg->chg_state = USB_CHG_STATE_DETECTED;
1006 clear_bit(ID_A, &motg->inputs);
1007 clear_bit(ID_B, &motg->inputs);
1008 ret = true;
1009 }
1010 break;
1011 default:
1012 ret = test_and_clear_bit(ID_A, &motg->inputs) |
1013 test_and_clear_bit(ID_B, &motg->inputs) |
1014 test_and_clear_bit(ID_C, &motg->inputs);
1015 if (ret) {
1016 dev_dbg(otg->dev, "ID A/B/C is no more\n");
1017 motg->chg_type = USB_INVALID_CHARGER;
1018 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1019 }
1020 }
1021out:
1022 return ret;
1023}
1024
1025static void msm_chg_enable_aca_det(struct msm_otg *motg)
1026{
1027 struct otg_transceiver *otg = &motg->otg;
1028
1029 switch (motg->pdata->phy_type) {
1030 case SNPS_28NM_INTEGRATED_PHY:
1031 /* ACA ID pin resistance detection enable */
1032 ulpi_write(otg, 0x20, 0x85);
1033 break;
1034 default:
1035 break;
1036 }
1037}
1038
1039static void msm_chg_enable_aca_intr(struct msm_otg *motg)
1040{
1041 struct otg_transceiver *otg = &motg->otg;
1042
1043 switch (motg->pdata->phy_type) {
1044 case SNPS_28NM_INTEGRATED_PHY:
1045 /* Enables ACA Detection interrupt (on any RID change) */
1046 ulpi_write(otg, 0x20, 0x94);
1047 break;
1048 default:
1049 break;
1050 }
1051}
1052
1053static bool msm_chg_check_aca_intr(struct msm_otg *motg)
1054{
1055 struct otg_transceiver *otg = &motg->otg;
1056 bool ret = false;
1057
1058 switch (motg->pdata->phy_type) {
1059 case SNPS_28NM_INTEGRATED_PHY:
1060 if (ulpi_read(otg, 0x91) & 1) {
1061 dev_dbg(otg->dev, "RID change\n");
1062 ulpi_write(otg, 0x01, 0x92);
1063 ret = msm_chg_aca_detect(motg);
1064 }
1065 default:
1066 break;
1067 }
1068 return ret;
1069}
1070#endif
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301071static bool msm_chg_check_secondary_det(struct msm_otg *motg)
1072{
1073 struct otg_transceiver *otg = &motg->otg;
1074 u32 chg_det;
1075 bool ret = false;
1076
1077 switch (motg->pdata->phy_type) {
1078 case CI_45NM_INTEGRATED_PHY:
1079 chg_det = ulpi_read(otg, 0x34);
1080 ret = chg_det & (1 << 4);
1081 break;
1082 case SNPS_28NM_INTEGRATED_PHY:
1083 chg_det = ulpi_read(otg, 0x87);
1084 ret = chg_det & 1;
1085 break;
1086 default:
1087 break;
1088 }
1089 return ret;
1090}
1091
1092static void msm_chg_enable_secondary_det(struct msm_otg *motg)
1093{
1094 struct otg_transceiver *otg = &motg->otg;
1095 u32 chg_det;
1096
1097 switch (motg->pdata->phy_type) {
1098 case CI_45NM_INTEGRATED_PHY:
1099 chg_det = ulpi_read(otg, 0x34);
1100 /* Turn off charger block */
1101 chg_det |= ~(1 << 1);
1102 ulpi_write(otg, chg_det, 0x34);
1103 udelay(20);
1104 /* control chg block via ULPI */
1105 chg_det &= ~(1 << 3);
1106 ulpi_write(otg, chg_det, 0x34);
1107 /* put it in host mode for enabling D- source */
1108 chg_det &= ~(1 << 2);
1109 ulpi_write(otg, chg_det, 0x34);
1110 /* Turn on chg detect block */
1111 chg_det &= ~(1 << 1);
1112 ulpi_write(otg, chg_det, 0x34);
1113 udelay(20);
1114 /* enable chg detection */
1115 chg_det &= ~(1 << 0);
1116 ulpi_write(otg, chg_det, 0x34);
1117 break;
1118 case SNPS_28NM_INTEGRATED_PHY:
1119 /*
1120 * Configure DM as current source, DP as current sink
1121 * and enable battery charging comparators.
1122 */
1123 ulpi_write(otg, 0x8, 0x85);
1124 ulpi_write(otg, 0x2, 0x85);
1125 ulpi_write(otg, 0x1, 0x85);
1126 break;
1127 default:
1128 break;
1129 }
1130}
1131
1132static bool msm_chg_check_primary_det(struct msm_otg *motg)
1133{
1134 struct otg_transceiver *otg = &motg->otg;
1135 u32 chg_det;
1136 bool ret = false;
1137
1138 switch (motg->pdata->phy_type) {
1139 case CI_45NM_INTEGRATED_PHY:
1140 chg_det = ulpi_read(otg, 0x34);
1141 ret = chg_det & (1 << 4);
1142 break;
1143 case SNPS_28NM_INTEGRATED_PHY:
1144 chg_det = ulpi_read(otg, 0x87);
1145 ret = chg_det & 1;
1146 break;
1147 default:
1148 break;
1149 }
1150 return ret;
1151}
1152
1153static void msm_chg_enable_primary_det(struct msm_otg *motg)
1154{
1155 struct otg_transceiver *otg = &motg->otg;
1156 u32 chg_det;
1157
1158 switch (motg->pdata->phy_type) {
1159 case CI_45NM_INTEGRATED_PHY:
1160 chg_det = ulpi_read(otg, 0x34);
1161 /* enable chg detection */
1162 chg_det &= ~(1 << 0);
1163 ulpi_write(otg, chg_det, 0x34);
1164 break;
1165 case SNPS_28NM_INTEGRATED_PHY:
1166 /*
1167 * Configure DP as current source, DM as current sink
1168 * and enable battery charging comparators.
1169 */
1170 ulpi_write(otg, 0x2, 0x85);
1171 ulpi_write(otg, 0x1, 0x85);
1172 break;
1173 default:
1174 break;
1175 }
1176}
1177
1178static bool msm_chg_check_dcd(struct msm_otg *motg)
1179{
1180 struct otg_transceiver *otg = &motg->otg;
1181 u32 line_state;
1182 bool ret = false;
1183
1184 switch (motg->pdata->phy_type) {
1185 case CI_45NM_INTEGRATED_PHY:
1186 line_state = ulpi_read(otg, 0x15);
1187 ret = !(line_state & 1);
1188 break;
1189 case SNPS_28NM_INTEGRATED_PHY:
1190 line_state = ulpi_read(otg, 0x87);
1191 ret = line_state & 2;
1192 break;
1193 default:
1194 break;
1195 }
1196 return ret;
1197}
1198
1199static void msm_chg_disable_dcd(struct msm_otg *motg)
1200{
1201 struct otg_transceiver *otg = &motg->otg;
1202 u32 chg_det;
1203
1204 switch (motg->pdata->phy_type) {
1205 case CI_45NM_INTEGRATED_PHY:
1206 chg_det = ulpi_read(otg, 0x34);
1207 chg_det &= ~(1 << 5);
1208 ulpi_write(otg, chg_det, 0x34);
1209 break;
1210 case SNPS_28NM_INTEGRATED_PHY:
1211 ulpi_write(otg, 0x10, 0x86);
1212 break;
1213 default:
1214 break;
1215 }
1216}
1217
1218static void msm_chg_enable_dcd(struct msm_otg *motg)
1219{
1220 struct otg_transceiver *otg = &motg->otg;
1221 u32 chg_det;
1222
1223 switch (motg->pdata->phy_type) {
1224 case CI_45NM_INTEGRATED_PHY:
1225 chg_det = ulpi_read(otg, 0x34);
1226 /* Turn on D+ current source */
1227 chg_det |= (1 << 5);
1228 ulpi_write(otg, chg_det, 0x34);
1229 break;
1230 case SNPS_28NM_INTEGRATED_PHY:
1231 /* Data contact detection enable */
1232 ulpi_write(otg, 0x10, 0x85);
1233 break;
1234 default:
1235 break;
1236 }
1237}
1238
1239static void msm_chg_block_on(struct msm_otg *motg)
1240{
1241 struct otg_transceiver *otg = &motg->otg;
1242 u32 func_ctrl, chg_det;
1243
1244 /* put the controller in non-driving mode */
1245 func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
1246 func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
1247 func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
1248 ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
1249
1250 switch (motg->pdata->phy_type) {
1251 case CI_45NM_INTEGRATED_PHY:
1252 chg_det = ulpi_read(otg, 0x34);
1253 /* control chg block via ULPI */
1254 chg_det &= ~(1 << 3);
1255 ulpi_write(otg, chg_det, 0x34);
1256 /* Turn on chg detect block */
1257 chg_det &= ~(1 << 1);
1258 ulpi_write(otg, chg_det, 0x34);
1259 udelay(20);
1260 break;
1261 case SNPS_28NM_INTEGRATED_PHY:
1262 /* Clear charger detecting control bits */
1263 ulpi_write(otg, 0x3F, 0x86);
1264 /* Clear alt interrupt latch and enable bits */
1265 ulpi_write(otg, 0x1F, 0x92);
1266 ulpi_write(otg, 0x1F, 0x95);
1267 udelay(100);
1268 break;
1269 default:
1270 break;
1271 }
1272}
1273
1274static void msm_chg_block_off(struct msm_otg *motg)
1275{
1276 struct otg_transceiver *otg = &motg->otg;
1277 u32 func_ctrl, chg_det;
1278
1279 switch (motg->pdata->phy_type) {
1280 case CI_45NM_INTEGRATED_PHY:
1281 chg_det = ulpi_read(otg, 0x34);
1282 /* Turn off charger block */
1283 chg_det |= ~(1 << 1);
1284 ulpi_write(otg, chg_det, 0x34);
1285 break;
1286 case SNPS_28NM_INTEGRATED_PHY:
1287 /* Clear charger detecting control bits */
1288 ulpi_write(otg, 0x3F, 0x86);
1289 /* Clear alt interrupt latch and enable bits */
1290 ulpi_write(otg, 0x1F, 0x92);
1291 ulpi_write(otg, 0x1F, 0x95);
1292 break;
1293 default:
1294 break;
1295 }
1296
1297 /* put the controller in normal mode */
1298 func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
1299 func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
1300 func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
1301 ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
1302}
1303
Anji jonnalad270e2d2011-08-09 11:28:32 +05301304static const char *chg_to_string(enum usb_chg_type chg_type)
1305{
1306 switch (chg_type) {
1307 case USB_SDP_CHARGER: return "USB_SDP_CHARGER";
1308 case USB_DCP_CHARGER: return "USB_DCP_CHARGER";
1309 case USB_CDP_CHARGER: return "USB_CDP_CHARGER";
1310 case USB_ACA_A_CHARGER: return "USB_ACA_A_CHARGER";
1311 case USB_ACA_B_CHARGER: return "USB_ACA_B_CHARGER";
1312 case USB_ACA_C_CHARGER: return "USB_ACA_C_CHARGER";
1313 case USB_ACA_DOCK_CHARGER: return "USB_ACA_DOCK_CHARGER";
1314 default: return "INVALID_CHARGER";
1315 }
1316}
1317
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301318#define MSM_CHG_DCD_POLL_TIME (100 * HZ/1000) /* 100 msec */
1319#define MSM_CHG_DCD_MAX_RETRIES 6 /* Tdcd_tmout = 6 * 100 msec */
1320#define MSM_CHG_PRIMARY_DET_TIME (40 * HZ/1000) /* TVDPSRC_ON */
1321#define MSM_CHG_SECONDARY_DET_TIME (40 * HZ/1000) /* TVDMSRC_ON */
1322static void msm_chg_detect_work(struct work_struct *w)
1323{
1324 struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
1325 struct otg_transceiver *otg = &motg->otg;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001326 bool is_dcd, tmout, vout, is_aca;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301327 unsigned long delay;
1328
1329 dev_dbg(otg->dev, "chg detection work\n");
1330 switch (motg->chg_state) {
1331 case USB_CHG_STATE_UNDEFINED:
1332 pm_runtime_get_sync(otg->dev);
1333 msm_chg_block_on(motg);
1334 msm_chg_enable_dcd(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001335 msm_chg_enable_aca_det(motg);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301336 motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
1337 motg->dcd_retries = 0;
1338 delay = MSM_CHG_DCD_POLL_TIME;
1339 break;
1340 case USB_CHG_STATE_WAIT_FOR_DCD:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001341 is_aca = msm_chg_aca_detect(motg);
1342 if (is_aca) {
1343 /*
1344 * ID_A can be ACA dock too. continue
1345 * primary detection after DCD.
1346 */
1347 if (test_bit(ID_A, &motg->inputs)) {
1348 motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
1349 } else {
1350 delay = 0;
1351 break;
1352 }
1353 }
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301354 is_dcd = msm_chg_check_dcd(motg);
1355 tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES;
1356 if (is_dcd || tmout) {
1357 msm_chg_disable_dcd(motg);
1358 msm_chg_enable_primary_det(motg);
1359 delay = MSM_CHG_PRIMARY_DET_TIME;
1360 motg->chg_state = USB_CHG_STATE_DCD_DONE;
1361 } else {
1362 delay = MSM_CHG_DCD_POLL_TIME;
1363 }
1364 break;
1365 case USB_CHG_STATE_DCD_DONE:
1366 vout = msm_chg_check_primary_det(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001367 is_aca = msm_chg_aca_detect(motg);
1368 if (is_aca) {
1369 if (vout && test_bit(ID_A, &motg->inputs))
1370 motg->chg_type = USB_ACA_DOCK_CHARGER;
1371 delay = 0;
1372 break;
1373 }
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301374 if (vout) {
1375 msm_chg_enable_secondary_det(motg);
1376 delay = MSM_CHG_SECONDARY_DET_TIME;
1377 motg->chg_state = USB_CHG_STATE_PRIMARY_DONE;
1378 } else {
1379 motg->chg_type = USB_SDP_CHARGER;
1380 motg->chg_state = USB_CHG_STATE_DETECTED;
1381 delay = 0;
1382 }
1383 break;
1384 case USB_CHG_STATE_PRIMARY_DONE:
1385 vout = msm_chg_check_secondary_det(motg);
1386 if (vout)
1387 motg->chg_type = USB_DCP_CHARGER;
1388 else
1389 motg->chg_type = USB_CDP_CHARGER;
1390 motg->chg_state = USB_CHG_STATE_SECONDARY_DONE;
1391 /* fall through */
1392 case USB_CHG_STATE_SECONDARY_DONE:
1393 motg->chg_state = USB_CHG_STATE_DETECTED;
1394 case USB_CHG_STATE_DETECTED:
1395 msm_chg_block_off(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001396 msm_chg_enable_aca_det(motg);
1397 msm_chg_enable_aca_intr(motg);
Anji jonnalad270e2d2011-08-09 11:28:32 +05301398 dev_dbg(otg->dev, "chg_type = %s\n",
1399 chg_to_string(motg->chg_type));
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301400 schedule_work(&motg->sm_work);
1401 return;
1402 default:
1403 return;
1404 }
1405
1406 schedule_delayed_work(&motg->chg_work, delay);
1407}
1408
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301409/*
1410 * We support OTG, Peripheral only and Host only configurations. In case
1411 * of OTG, mode switch (host-->peripheral/peripheral-->host) can happen
1412 * via Id pin status or user request (debugfs). Id/BSV interrupts are not
1413 * enabled when switch is controlled by user and default mode is supplied
1414 * by board file, which can be changed by userspace later.
1415 */
1416static void msm_otg_init_sm(struct msm_otg *motg)
1417{
1418 struct msm_otg_platform_data *pdata = motg->pdata;
1419 u32 otgsc = readl(USB_OTGSC);
1420
1421 switch (pdata->mode) {
1422 case USB_OTG:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001423 if (pdata->otg_control == OTG_USER_CONTROL) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301424 if (pdata->default_mode == USB_HOST) {
1425 clear_bit(ID, &motg->inputs);
1426 } else if (pdata->default_mode == USB_PERIPHERAL) {
1427 set_bit(ID, &motg->inputs);
1428 set_bit(B_SESS_VLD, &motg->inputs);
1429 } else {
1430 set_bit(ID, &motg->inputs);
1431 clear_bit(B_SESS_VLD, &motg->inputs);
1432 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001433 } else {
1434 if (otgsc & OTGSC_ID)
1435 set_bit(ID, &motg->inputs);
1436 else
1437 clear_bit(ID, &motg->inputs);
1438
1439 if (otgsc & OTGSC_BSV)
1440 set_bit(B_SESS_VLD, &motg->inputs);
1441 else
1442 clear_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301443 }
1444 break;
1445 case USB_HOST:
1446 clear_bit(ID, &motg->inputs);
1447 break;
1448 case USB_PERIPHERAL:
1449 set_bit(ID, &motg->inputs);
1450 if (otgsc & OTGSC_BSV)
1451 set_bit(B_SESS_VLD, &motg->inputs);
1452 else
1453 clear_bit(B_SESS_VLD, &motg->inputs);
1454 break;
1455 default:
1456 break;
1457 }
1458}
1459
1460static void msm_otg_sm_work(struct work_struct *w)
1461{
1462 struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
1463 struct otg_transceiver *otg = &motg->otg;
1464
1465 switch (otg->state) {
1466 case OTG_STATE_UNDEFINED:
1467 dev_dbg(otg->dev, "OTG_STATE_UNDEFINED state\n");
1468 msm_otg_reset(otg);
1469 msm_otg_init_sm(motg);
1470 otg->state = OTG_STATE_B_IDLE;
1471 /* FALL THROUGH */
1472 case OTG_STATE_B_IDLE:
1473 dev_dbg(otg->dev, "OTG_STATE_B_IDLE state\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001474 if ((!test_bit(ID, &motg->inputs) ||
1475 test_bit(ID_A, &motg->inputs)) && otg->host) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301476 /* disable BSV bit */
1477 writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001478 if (motg->chg_type == USB_ACA_DOCK_CHARGER)
1479 msm_otg_notify_charger(motg,
1480 IDEV_CHG_MAX);
1481 else if (!test_bit(ID_A, &motg->inputs) &&
1482 motg->pdata->vbus_power)
1483 motg->pdata->vbus_power(1);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301484 msm_otg_start_host(otg, 1);
1485 otg->state = OTG_STATE_A_HOST;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301486 } else if (test_bit(B_SESS_VLD, &motg->inputs)) {
1487 switch (motg->chg_state) {
1488 case USB_CHG_STATE_UNDEFINED:
1489 msm_chg_detect_work(&motg->chg_work.work);
1490 break;
1491 case USB_CHG_STATE_DETECTED:
1492 switch (motg->chg_type) {
1493 case USB_DCP_CHARGER:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001494 case USB_ACA_B_CHARGER:
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301495 msm_otg_notify_charger(motg,
1496 IDEV_CHG_MAX);
1497 break;
1498 case USB_CDP_CHARGER:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001499 case USB_ACA_C_CHARGER:
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301500 msm_otg_notify_charger(motg,
1501 IDEV_CHG_MAX);
1502 msm_otg_start_peripheral(otg, 1);
1503 otg->state = OTG_STATE_B_PERIPHERAL;
1504 break;
1505 case USB_SDP_CHARGER:
1506 msm_otg_notify_charger(motg, IUNIT);
1507 msm_otg_start_peripheral(otg, 1);
1508 otg->state = OTG_STATE_B_PERIPHERAL;
1509 break;
1510 default:
1511 break;
1512 }
1513 break;
1514 default:
1515 break;
1516 }
1517 } else {
1518 /*
1519 * If charger detection work is pending, decrement
1520 * the pm usage counter to balance with the one that
1521 * is incremented in charger detection work.
1522 */
1523 if (cancel_delayed_work_sync(&motg->chg_work)) {
1524 pm_runtime_put_sync(otg->dev);
1525 msm_otg_reset(otg);
1526 }
1527 msm_otg_notify_charger(motg, 0);
1528 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1529 motg->chg_type = USB_INVALID_CHARGER;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301530 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301531 pm_runtime_put_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301532 break;
1533 case OTG_STATE_B_PERIPHERAL:
1534 dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n");
1535 if (!test_bit(B_SESS_VLD, &motg->inputs) ||
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001536 !test_bit(ID, &motg->inputs) ||
1537 !test_bit(ID_C, &motg->inputs)) {
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301538 msm_otg_notify_charger(motg, 0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301539 msm_otg_start_peripheral(otg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001540 if (!test_bit(ID_B, &motg->inputs) &&
1541 !test_bit(ID_A, &motg->inputs)) {
1542 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1543 motg->chg_type = USB_INVALID_CHARGER;
1544 }
1545 otg->state = OTG_STATE_B_IDLE;
1546 msm_otg_reset(otg);
1547 schedule_work(w);
1548 } else if (test_bit(ID_C, &motg->inputs)) {
1549 msm_otg_notify_charger(motg, IDEV_CHG_MAX);
1550 pm_runtime_put_sync(otg->dev);
1551 }
1552 break;
1553 case OTG_STATE_A_HOST:
1554 dev_dbg(otg->dev, "OTG_STATE_A_HOST state\n");
1555 if (test_bit(ID, &motg->inputs) &&
1556 !test_bit(ID_A, &motg->inputs)) {
1557 msm_otg_start_host(otg, 0);
1558 writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
1559 if (motg->pdata->vbus_power)
1560 motg->pdata->vbus_power(0);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301561 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1562 motg->chg_type = USB_INVALID_CHARGER;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301563 otg->state = OTG_STATE_B_IDLE;
1564 msm_otg_reset(otg);
1565 schedule_work(w);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001566 } else if (test_bit(ID_A, &motg->inputs)) {
1567 writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
1568 if (motg->pdata->vbus_power)
1569 motg->pdata->vbus_power(0);
1570 msm_otg_notify_charger(motg,
1571 IDEV_CHG_MIN - motg->mA_port);
1572 pm_runtime_put_sync(otg->dev);
1573 } else if (!test_bit(ID, &motg->inputs)) {
1574 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1575 motg->chg_type = USB_INVALID_CHARGER;
1576 msm_otg_notify_charger(motg, 0);
1577 writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
1578 if (motg->pdata->vbus_power)
1579 motg->pdata->vbus_power(1);
1580 pm_runtime_put_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301581 }
1582 break;
1583 default:
1584 break;
1585 }
1586}
1587
1588static irqreturn_t msm_otg_irq(int irq, void *data)
1589{
1590 struct msm_otg *motg = data;
1591 struct otg_transceiver *otg = &motg->otg;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001592 u32 otgsc = 0, usbsts;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301593
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301594 if (atomic_read(&motg->in_lpm)) {
1595 disable_irq_nosync(irq);
1596 motg->async_int = 1;
1597 pm_runtime_get(otg->dev);
1598 return IRQ_HANDLED;
1599 }
1600
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001601 usbsts = readl(USB_USBSTS);
1602 if ((usbsts & PHY_ALT_INT)) {
1603 writel(PHY_ALT_INT, USB_USBSTS);
1604 if (msm_chg_check_aca_intr(motg)) {
1605 pm_runtime_get_noresume(otg->dev);
1606 schedule_work(&motg->sm_work);
1607 }
1608 return IRQ_HANDLED;
1609 }
1610
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301611 otgsc = readl(USB_OTGSC);
1612 if (!(otgsc & (OTGSC_IDIS | OTGSC_BSVIS)))
1613 return IRQ_NONE;
1614
1615 if ((otgsc & OTGSC_IDIS) && (otgsc & OTGSC_IDIE)) {
1616 if (otgsc & OTGSC_ID)
1617 set_bit(ID, &motg->inputs);
1618 else
1619 clear_bit(ID, &motg->inputs);
1620 dev_dbg(otg->dev, "ID set/clear\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001621 schedule_work(&motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301622 pm_runtime_get_noresume(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301623 } else if ((otgsc & OTGSC_BSVIS) && (otgsc & OTGSC_BSVIE)) {
1624 if (otgsc & OTGSC_BSV)
1625 set_bit(B_SESS_VLD, &motg->inputs);
1626 else
1627 clear_bit(B_SESS_VLD, &motg->inputs);
1628 dev_dbg(otg->dev, "BSV set/clear\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001629 schedule_work(&motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301630 pm_runtime_get_noresume(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301631 }
1632
1633 writel(otgsc, USB_OTGSC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001634 return IRQ_HANDLED;
1635}
1636
1637static void msm_otg_set_vbus_state(int online)
1638{
1639 struct msm_otg *motg = the_msm_otg;
1640
1641 /* We depend on PMIC for only VBUS ON interrupt */
1642 if (!atomic_read(&motg->in_lpm) || !online)
1643 return;
1644
1645 /*
1646 * Let interrupt handler take care of resuming
1647 * the hardware.
1648 */
1649 msm_otg_irq(motg->irq, (void *) motg);
1650}
1651
1652static irqreturn_t msm_pmic_id_irq(int irq, void *data)
1653{
1654 struct msm_otg *motg = data;
1655
1656 if (atomic_read(&motg->in_lpm) && !motg->async_int)
1657 msm_otg_irq(motg->irq, motg);
1658
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301659 return IRQ_HANDLED;
1660}
1661
1662static int msm_otg_mode_show(struct seq_file *s, void *unused)
1663{
1664 struct msm_otg *motg = s->private;
1665 struct otg_transceiver *otg = &motg->otg;
1666
1667 switch (otg->state) {
1668 case OTG_STATE_A_HOST:
1669 seq_printf(s, "host\n");
1670 break;
1671 case OTG_STATE_B_PERIPHERAL:
1672 seq_printf(s, "peripheral\n");
1673 break;
1674 default:
1675 seq_printf(s, "none\n");
1676 break;
1677 }
1678
1679 return 0;
1680}
1681
1682static int msm_otg_mode_open(struct inode *inode, struct file *file)
1683{
1684 return single_open(file, msm_otg_mode_show, inode->i_private);
1685}
1686
1687static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf,
1688 size_t count, loff_t *ppos)
1689{
Pavankumar Kondetie2904ee2011-02-15 09:42:35 +05301690 struct seq_file *s = file->private_data;
1691 struct msm_otg *motg = s->private;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301692 char buf[16];
1693 struct otg_transceiver *otg = &motg->otg;
1694 int status = count;
1695 enum usb_mode_type req_mode;
1696
1697 memset(buf, 0x00, sizeof(buf));
1698
1699 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) {
1700 status = -EFAULT;
1701 goto out;
1702 }
1703
1704 if (!strncmp(buf, "host", 4)) {
1705 req_mode = USB_HOST;
1706 } else if (!strncmp(buf, "peripheral", 10)) {
1707 req_mode = USB_PERIPHERAL;
1708 } else if (!strncmp(buf, "none", 4)) {
1709 req_mode = USB_NONE;
1710 } else {
1711 status = -EINVAL;
1712 goto out;
1713 }
1714
1715 switch (req_mode) {
1716 case USB_NONE:
1717 switch (otg->state) {
1718 case OTG_STATE_A_HOST:
1719 case OTG_STATE_B_PERIPHERAL:
1720 set_bit(ID, &motg->inputs);
1721 clear_bit(B_SESS_VLD, &motg->inputs);
1722 break;
1723 default:
1724 goto out;
1725 }
1726 break;
1727 case USB_PERIPHERAL:
1728 switch (otg->state) {
1729 case OTG_STATE_B_IDLE:
1730 case OTG_STATE_A_HOST:
1731 set_bit(ID, &motg->inputs);
1732 set_bit(B_SESS_VLD, &motg->inputs);
1733 break;
1734 default:
1735 goto out;
1736 }
1737 break;
1738 case USB_HOST:
1739 switch (otg->state) {
1740 case OTG_STATE_B_IDLE:
1741 case OTG_STATE_B_PERIPHERAL:
1742 clear_bit(ID, &motg->inputs);
1743 break;
1744 default:
1745 goto out;
1746 }
1747 break;
1748 default:
1749 goto out;
1750 }
1751
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301752 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301753 schedule_work(&motg->sm_work);
1754out:
1755 return status;
1756}
1757
1758const struct file_operations msm_otg_mode_fops = {
1759 .open = msm_otg_mode_open,
1760 .read = seq_read,
1761 .write = msm_otg_mode_write,
1762 .llseek = seq_lseek,
1763 .release = single_release,
1764};
1765
Anji jonnalad270e2d2011-08-09 11:28:32 +05301766static int msm_otg_show_chg_type(struct seq_file *s, void *unused)
1767{
1768 struct msm_otg *motg = s->private;
1769
1770 seq_printf(s, chg_to_string(motg->chg_type));
1771 return 0;
1772}
1773
1774static int msm_otg_chg_open(struct inode *inode, struct file *file)
1775{
1776 return single_open(file, msm_otg_show_chg_type, inode->i_private);
1777}
1778
1779const struct file_operations msm_otg_chg_fops = {
1780 .open = msm_otg_chg_open,
1781 .read = seq_read,
1782 .llseek = seq_lseek,
1783 .release = single_release,
1784};
1785
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301786static struct dentry *msm_otg_dbg_root;
1787static struct dentry *msm_otg_dbg_mode;
Anji jonnalad270e2d2011-08-09 11:28:32 +05301788static struct dentry *msm_otg_chg_type;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301789
1790static int msm_otg_debugfs_init(struct msm_otg *motg)
1791{
Anji jonnalad270e2d2011-08-09 11:28:32 +05301792
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301793 msm_otg_dbg_root = debugfs_create_dir("msm_otg", NULL);
1794
1795 if (!msm_otg_dbg_root || IS_ERR(msm_otg_dbg_root))
1796 return -ENODEV;
1797
Anji jonnalad270e2d2011-08-09 11:28:32 +05301798 if (motg->pdata->mode == USB_OTG &&
1799 motg->pdata->otg_control == OTG_USER_CONTROL) {
1800
1801 msm_otg_dbg_mode = debugfs_create_file("mode", S_IRUGO |
1802 S_IWUSR, msm_otg_dbg_root, motg,
1803 &msm_otg_mode_fops);
1804
1805 if (!msm_otg_dbg_mode) {
1806 debugfs_remove(msm_otg_dbg_root);
1807 msm_otg_dbg_root = NULL;
1808 return -ENODEV;
1809 }
1810 }
1811
1812 msm_otg_chg_type = debugfs_create_file("chg_type", S_IRUGO,
1813 msm_otg_dbg_root, motg,
1814 &msm_otg_chg_fops);
1815
1816 if (!msm_otg_chg_type) {
1817 debugfs_remove(msm_otg_dbg_mode);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301818 debugfs_remove(msm_otg_dbg_root);
1819 msm_otg_dbg_root = NULL;
Anji jonnalad270e2d2011-08-09 11:28:32 +05301820 msm_otg_dbg_mode = NULL;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301821 return -ENODEV;
1822 }
1823
1824 return 0;
1825}
1826
1827static void msm_otg_debugfs_cleanup(void)
1828{
Anji jonnalad270e2d2011-08-09 11:28:32 +05301829 debugfs_remove_recursive(msm_otg_dbg_root);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301830}
1831
1832static int __init msm_otg_probe(struct platform_device *pdev)
1833{
1834 int ret = 0;
1835 struct resource *res;
1836 struct msm_otg *motg;
1837 struct otg_transceiver *otg;
1838
1839 dev_info(&pdev->dev, "msm_otg probe\n");
1840 if (!pdev->dev.platform_data) {
1841 dev_err(&pdev->dev, "No platform data given. Bailing out\n");
1842 return -ENODEV;
1843 }
1844
1845 motg = kzalloc(sizeof(struct msm_otg), GFP_KERNEL);
1846 if (!motg) {
1847 dev_err(&pdev->dev, "unable to allocate msm_otg\n");
1848 return -ENOMEM;
1849 }
1850
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001851 the_msm_otg = motg;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301852 motg->pdata = pdev->dev.platform_data;
1853 otg = &motg->otg;
1854 otg->dev = &pdev->dev;
1855
Amit Blay02eff132011-09-21 16:46:24 +03001856 /* Some targets don't support PHY clock. */
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301857 motg->phy_reset_clk = clk_get(&pdev->dev, "usb_phy_clk");
Amit Blay02eff132011-09-21 16:46:24 +03001858 if (IS_ERR(motg->phy_reset_clk))
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301859 dev_err(&pdev->dev, "failed to get usb_phy_clk\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301860
1861 motg->clk = clk_get(&pdev->dev, "usb_hs_clk");
1862 if (IS_ERR(motg->clk)) {
1863 dev_err(&pdev->dev, "failed to get usb_hs_clk\n");
1864 ret = PTR_ERR(motg->clk);
1865 goto put_phy_reset_clk;
1866 }
Anji jonnala0f73cac2011-05-04 10:19:46 +05301867 clk_set_rate(motg->clk, 60000000);
1868
1869 /*
1870 * If USB Core is running its protocol engine based on CORE CLK,
1871 * CORE CLK must be running at >55Mhz for correct HSUSB
1872 * operation and USB core cannot tolerate frequency changes on
1873 * CORE CLK. For such USB cores, vote for maximum clk frequency
1874 * on pclk source
1875 */
1876 if (motg->pdata->pclk_src_name) {
1877 motg->pclk_src = clk_get(&pdev->dev,
1878 motg->pdata->pclk_src_name);
1879 if (IS_ERR(motg->pclk_src))
1880 goto put_clk;
1881 clk_set_rate(motg->pclk_src, INT_MAX);
1882 clk_enable(motg->pclk_src);
1883 } else
1884 motg->pclk_src = ERR_PTR(-ENOENT);
1885
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301886 motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk");
1887 if (IS_ERR(motg->pclk)) {
1888 dev_err(&pdev->dev, "failed to get usb_hs_pclk\n");
1889 ret = PTR_ERR(motg->pclk);
Anji jonnala0f73cac2011-05-04 10:19:46 +05301890 goto put_pclk_src;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301891 }
1892
Amit Blay02eff132011-09-21 16:46:24 +03001893 motg->system_clk = clk_get(&pdev->dev, "usb_hs_system_clk");
1894 if (!IS_ERR(motg->system_clk))
1895 clk_enable(motg->system_clk);
1896
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301897 /*
1898 * USB core clock is not present on all MSM chips. This
1899 * clock is introduced to remove the dependency on AXI
1900 * bus frequency.
1901 */
1902 motg->core_clk = clk_get(&pdev->dev, "usb_hs_core_clk");
1903 if (IS_ERR(motg->core_clk))
1904 motg->core_clk = NULL;
1905
1906 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1907 if (!res) {
1908 dev_err(&pdev->dev, "failed to get platform resource mem\n");
1909 ret = -ENODEV;
1910 goto put_core_clk;
1911 }
1912
1913 motg->regs = ioremap(res->start, resource_size(res));
1914 if (!motg->regs) {
1915 dev_err(&pdev->dev, "ioremap failed\n");
1916 ret = -ENOMEM;
1917 goto put_core_clk;
1918 }
1919 dev_info(&pdev->dev, "OTG regs = %p\n", motg->regs);
1920
1921 motg->irq = platform_get_irq(pdev, 0);
1922 if (!motg->irq) {
1923 dev_err(&pdev->dev, "platform_get_irq failed\n");
1924 ret = -ENODEV;
1925 goto free_regs;
1926 }
1927
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301928 clk_enable(motg->pclk);
Anji jonnala11aa5c42011-05-04 10:19:48 +05301929
1930 ret = msm_hsusb_init_vddcx(motg, 1);
1931 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001932 dev_err(&pdev->dev, "hsusb vddcx init failed\n");
Anji jonnala11aa5c42011-05-04 10:19:48 +05301933 goto free_regs;
1934 }
1935
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001936 ret = msm_hsusb_config_vddcx(1);
1937 if (ret) {
1938 dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
1939 goto free_init_vddcx;
1940 }
1941
Anji jonnala11aa5c42011-05-04 10:19:48 +05301942 ret = msm_hsusb_ldo_init(motg, 1);
1943 if (ret) {
1944 dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001945 goto free_init_vddcx;
Anji jonnala11aa5c42011-05-04 10:19:48 +05301946 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001947
1948 ret = msm_hsusb_ldo_enable(motg, 1);
Anji jonnala11aa5c42011-05-04 10:19:48 +05301949 if (ret) {
1950 dev_err(&pdev->dev, "hsusb vreg enable failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001951 goto free_ldo_init;
Anji jonnala11aa5c42011-05-04 10:19:48 +05301952 }
1953
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301954 if (motg->core_clk)
1955 clk_enable(motg->core_clk);
1956
1957 writel(0, USB_USBINTR);
1958 writel(0, USB_OTGSC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001959 /* Ensure that above STOREs are completed before enabling interrupts */
1960 mb();
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301961
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001962 wake_lock_init(&motg->wlock, WAKE_LOCK_SUSPEND, "msm_otg");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301963 INIT_WORK(&motg->sm_work, msm_otg_sm_work);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301964 INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301965 ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
1966 "msm_otg", motg);
1967 if (ret) {
1968 dev_err(&pdev->dev, "request irq failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001969 goto destroy_wlock;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301970 }
1971
1972 otg->init = msm_otg_reset;
1973 otg->set_host = msm_otg_set_host;
1974 otg->set_peripheral = msm_otg_set_peripheral;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301975 otg->set_power = msm_otg_set_power;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301976
1977 otg->io_ops = &msm_otg_io_ops;
1978
1979 ret = otg_set_transceiver(&motg->otg);
1980 if (ret) {
1981 dev_err(&pdev->dev, "otg_set_transceiver failed\n");
1982 goto free_irq;
1983 }
1984
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001985 if (motg->pdata->otg_control == OTG_PMIC_CONTROL) {
1986 if (motg->pdata->pmic_id_irq) {
1987 ret = request_irq(motg->pdata->pmic_id_irq,
1988 msm_pmic_id_irq,
1989 IRQF_TRIGGER_RISING |
1990 IRQF_TRIGGER_FALLING,
1991 "msm_otg", motg);
1992 if (ret) {
1993 dev_err(&pdev->dev, "request irq failed for PMIC ID\n");
1994 goto remove_otg;
1995 }
1996 } else {
1997 ret = -ENODEV;
1998 dev_err(&pdev->dev, "PMIC IRQ for ID notifications doesn't exist\n");
1999 goto remove_otg;
2000 }
2001 }
2002
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +05302003 msm_hsusb_mhl_switch_enable(motg, 1);
2004
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302005 platform_set_drvdata(pdev, motg);
2006 device_init_wakeup(&pdev->dev, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002007 motg->mA_port = IUNIT;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302008
Anji jonnalad270e2d2011-08-09 11:28:32 +05302009 ret = msm_otg_debugfs_init(motg);
2010 if (ret)
2011 dev_dbg(&pdev->dev, "mode debugfs file is"
2012 "not available\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302013
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002014 if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
2015 pm8921_charger_register_vbus_sn(&msm_otg_set_vbus_state);
2016
2017 if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
2018 motg->pdata->otg_control == OTG_PMIC_CONTROL &&
2019 motg->pdata->pmic_id_irq)
2020 motg->caps = ALLOW_PHY_POWER_COLLAPSE |
2021 ALLOW_PHY_RETENTION |
2022 ALLOW_PHY_COMP_DISABLE;
2023
2024 wake_lock(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302025 pm_runtime_set_active(&pdev->dev);
2026 pm_runtime_enable(&pdev->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302027
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302028 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002029
2030remove_otg:
2031 otg_set_transceiver(NULL);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302032free_irq:
2033 free_irq(motg->irq, motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002034destroy_wlock:
2035 wake_lock_destroy(&motg->wlock);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302036 clk_disable(motg->pclk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002037 msm_hsusb_ldo_enable(motg, 0);
2038free_ldo_init:
Anji jonnala11aa5c42011-05-04 10:19:48 +05302039 msm_hsusb_ldo_init(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002040free_init_vddcx:
Anji jonnala11aa5c42011-05-04 10:19:48 +05302041 msm_hsusb_init_vddcx(motg, 0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302042free_regs:
2043 iounmap(motg->regs);
2044put_core_clk:
2045 if (motg->core_clk)
2046 clk_put(motg->core_clk);
Amit Blay02eff132011-09-21 16:46:24 +03002047
2048 if (!IS_ERR(motg->system_clk)) {
2049 clk_disable(motg->system_clk);
2050 clk_put(motg->system_clk);
2051 }
Anji jonnala0f73cac2011-05-04 10:19:46 +05302052put_pclk_src:
2053 if (!IS_ERR(motg->pclk_src)) {
2054 clk_disable(motg->pclk_src);
2055 clk_put(motg->pclk_src);
2056 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302057put_clk:
2058 clk_put(motg->clk);
2059put_phy_reset_clk:
Amit Blay02eff132011-09-21 16:46:24 +03002060 if (!IS_ERR(motg->phy_reset_clk))
2061 clk_put(motg->phy_reset_clk);
2062
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302063 kfree(motg);
2064 return ret;
2065}
2066
2067static int __devexit msm_otg_remove(struct platform_device *pdev)
2068{
2069 struct msm_otg *motg = platform_get_drvdata(pdev);
2070 struct otg_transceiver *otg = &motg->otg;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302071 int cnt = 0;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302072
2073 if (otg->host || otg->gadget)
2074 return -EBUSY;
2075
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002076 if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
2077 pm8921_charger_unregister_vbus_sn(0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302078 msm_otg_debugfs_cleanup();
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302079 cancel_delayed_work_sync(&motg->chg_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302080 cancel_work_sync(&motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302081
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302082 pm_runtime_resume(&pdev->dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302083
2084 device_init_wakeup(&pdev->dev, 0);
2085 pm_runtime_disable(&pdev->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002086 wake_lock_destroy(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302087
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +05302088 msm_hsusb_mhl_switch_enable(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002089 if (motg->pdata->pmic_id_irq)
2090 free_irq(motg->pdata->pmic_id_irq, motg);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302091 otg_set_transceiver(NULL);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302092 free_irq(motg->irq, motg);
2093
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302094 /*
2095 * Put PHY in low power mode.
2096 */
2097 ulpi_read(otg, 0x14);
2098 ulpi_write(otg, 0x08, 0x09);
2099
2100 writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
2101 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
2102 if (readl(USB_PORTSC) & PORTSC_PHCD)
2103 break;
2104 udelay(1);
2105 cnt++;
2106 }
2107 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC)
2108 dev_err(otg->dev, "Unable to suspend PHY\n");
2109
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302110 clk_disable(motg->pclk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302111 if (motg->core_clk)
2112 clk_disable(motg->core_clk);
Amit Blay137575f2011-11-06 15:20:54 +02002113 if (!IS_ERR(motg->system_clk))
2114 clk_disable(motg->system_clk);
Anji jonnala0f73cac2011-05-04 10:19:46 +05302115 if (!IS_ERR(motg->pclk_src)) {
2116 clk_disable(motg->pclk_src);
2117 clk_put(motg->pclk_src);
2118 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002119 msm_hsusb_ldo_enable(motg, 0);
Anji jonnala11aa5c42011-05-04 10:19:48 +05302120 msm_hsusb_ldo_init(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002121 msm_hsusb_init_vddcx(motg, 0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302122
2123 iounmap(motg->regs);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302124 pm_runtime_set_suspended(&pdev->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302125
Amit Blay02eff132011-09-21 16:46:24 +03002126 if (!IS_ERR(motg->phy_reset_clk))
2127 clk_put(motg->phy_reset_clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302128 clk_put(motg->pclk);
2129 clk_put(motg->clk);
2130 if (motg->core_clk)
2131 clk_put(motg->core_clk);
Amit Blay02eff132011-09-21 16:46:24 +03002132 if (!IS_ERR(motg->system_clk))
2133 clk_put(motg->system_clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302134
2135 kfree(motg);
2136
2137 return 0;
2138}
2139
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302140#ifdef CONFIG_PM_RUNTIME
2141static int msm_otg_runtime_idle(struct device *dev)
2142{
2143 struct msm_otg *motg = dev_get_drvdata(dev);
2144 struct otg_transceiver *otg = &motg->otg;
2145
2146 dev_dbg(dev, "OTG runtime idle\n");
2147
2148 /*
2149 * It is observed some times that a spurious interrupt
2150 * comes when PHY is put into LPM immediately after PHY reset.
2151 * This 1 sec delay also prevents entering into LPM immediately
2152 * after asynchronous interrupt.
2153 */
2154 if (otg->state != OTG_STATE_UNDEFINED)
2155 pm_schedule_suspend(dev, 1000);
2156
2157 return -EAGAIN;
2158}
2159
2160static int msm_otg_runtime_suspend(struct device *dev)
2161{
2162 struct msm_otg *motg = dev_get_drvdata(dev);
2163
2164 dev_dbg(dev, "OTG runtime suspend\n");
2165 return msm_otg_suspend(motg);
2166}
2167
2168static int msm_otg_runtime_resume(struct device *dev)
2169{
2170 struct msm_otg *motg = dev_get_drvdata(dev);
2171
2172 dev_dbg(dev, "OTG runtime resume\n");
2173 return msm_otg_resume(motg);
2174}
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302175#endif
2176
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302177#ifdef CONFIG_PM_SLEEP
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302178static int msm_otg_pm_suspend(struct device *dev)
2179{
2180 struct msm_otg *motg = dev_get_drvdata(dev);
2181
2182 dev_dbg(dev, "OTG PM suspend\n");
2183 return msm_otg_suspend(motg);
2184}
2185
2186static int msm_otg_pm_resume(struct device *dev)
2187{
2188 struct msm_otg *motg = dev_get_drvdata(dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302189
2190 dev_dbg(dev, "OTG PM resume\n");
2191
Manu Gautamf284c052011-09-08 16:52:48 +05302192#ifdef CONFIG_PM_RUNTIME
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302193 /*
Manu Gautamf284c052011-09-08 16:52:48 +05302194 * Do not resume hardware as part of system resume,
2195 * rather, wait for the ASYNC INT from the h/w
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302196 */
Gregory Beanebd8ca22011-10-11 12:02:35 -07002197 return 0;
Manu Gautamf284c052011-09-08 16:52:48 +05302198#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302199
Manu Gautamf284c052011-09-08 16:52:48 +05302200 return msm_otg_resume(motg);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302201}
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302202#endif
2203
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302204#ifdef CONFIG_PM
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302205static const struct dev_pm_ops msm_otg_dev_pm_ops = {
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302206 SET_SYSTEM_SLEEP_PM_OPS(msm_otg_pm_suspend, msm_otg_pm_resume)
2207 SET_RUNTIME_PM_OPS(msm_otg_runtime_suspend, msm_otg_runtime_resume,
2208 msm_otg_runtime_idle)
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302209};
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302210#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302211
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302212static struct platform_driver msm_otg_driver = {
2213 .remove = __devexit_p(msm_otg_remove),
2214 .driver = {
2215 .name = DRIVER_NAME,
2216 .owner = THIS_MODULE,
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302217#ifdef CONFIG_PM
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302218 .pm = &msm_otg_dev_pm_ops,
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302219#endif
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302220 },
2221};
2222
2223static int __init msm_otg_init(void)
2224{
2225 return platform_driver_probe(&msm_otg_driver, msm_otg_probe);
2226}
2227
2228static void __exit msm_otg_exit(void)
2229{
2230 platform_driver_unregister(&msm_otg_driver);
2231}
2232
2233module_init(msm_otg_init);
2234module_exit(msm_otg_exit);
2235
2236MODULE_LICENSE("GPL v2");
2237MODULE_DESCRIPTION("MSM USB transceiver driver");