blob: 04c14493c642f196a767e1edf810fba555cee30f [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 Kondeti8be99cf2011-08-04 10:48:08 +0530538static int msm_otg_set_suspend(struct otg_transceiver *otg, int suspend)
539{
540 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
541
542 /*
543 * Allow bus suspend only for host mode. Device mode bus suspend
544 * is not implemented yet.
545 */
546 if (!test_bit(ID, &motg->inputs) || test_bit(ID_A, &motg->inputs)) {
547 if (suspend)
548 pm_runtime_put(otg->dev);
549 else
550 pm_runtime_resume(otg->dev);
551 }
552
553 return 0;
554}
555
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530556#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
Pavankumar Kondeti70187732011-02-15 09:42:34 +0530557#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
558
559#ifdef CONFIG_PM_SLEEP
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530560static int msm_otg_suspend(struct msm_otg *motg)
561{
562 struct otg_transceiver *otg = &motg->otg;
563 struct usb_bus *bus = otg->host;
564 struct msm_otg_platform_data *pdata = motg->pdata;
565 int cnt = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700566 bool session_active;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530567
568 if (atomic_read(&motg->in_lpm))
569 return 0;
570
571 disable_irq(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700572 session_active = (otg->host && !test_bit(ID, &motg->inputs)) ||
573 test_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530574 /*
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530575 * Chipidea 45-nm PHY suspend sequence:
576 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530577 * Interrupt Latch Register auto-clear feature is not present
578 * in all PHY versions. Latch register is clear on read type.
579 * Clear latch register to avoid spurious wakeup from
580 * low power mode (LPM).
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530581 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530582 * PHY comparators are disabled when PHY enters into low power
583 * mode (LPM). Keep PHY comparators ON in LPM only when we expect
584 * VBUS/Id notifications from USB PHY. Otherwise turn off USB
585 * PHY comparators. This save significant amount of power.
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530586 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530587 * PLL is not turned off when PHY enters into low power mode (LPM).
588 * Disable PLL for maximum power savings.
589 */
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530590
591 if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) {
592 ulpi_read(otg, 0x14);
593 if (pdata->otg_control == OTG_PHY_CONTROL)
594 ulpi_write(otg, 0x01, 0x30);
595 ulpi_write(otg, 0x08, 0x09);
596 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530597
598 /*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700599 * Turn off the OTG comparators, if depends on PMIC for
600 * VBUS and ID notifications.
601 */
602 if ((motg->caps & ALLOW_PHY_COMP_DISABLE) && !session_active) {
603 ulpi_write(otg, OTG_COMP_DISABLE,
604 ULPI_SET(ULPI_PWR_CLK_MNG_REG));
605 motg->lpm_flags |= PHY_OTG_COMP_DISABLED;
606 }
607
608 /*
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530609 * PHY may take some time or even fail to enter into low power
610 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
611 * in failure case.
612 */
613 writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
614 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
615 if (readl(USB_PORTSC) & PORTSC_PHCD)
616 break;
617 udelay(1);
618 cnt++;
619 }
620
621 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
622 dev_err(otg->dev, "Unable to suspend PHY\n");
623 msm_otg_reset(otg);
624 enable_irq(motg->irq);
625 return -ETIMEDOUT;
626 }
627
628 /*
629 * PHY has capability to generate interrupt asynchronously in low
630 * power mode (LPM). This interrupt is level triggered. So USB IRQ
631 * line must be disabled till async interrupt enable bit is cleared
632 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
633 * block data communication from PHY.
634 */
635 writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);
636
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700637 if (motg->caps & ALLOW_PHY_RETENTION && !session_active) {
638 writel_relaxed(readl_relaxed(USB_PHY_CTRL) & ~PHY_RETEN,
639 USB_PHY_CTRL);
640 motg->lpm_flags |= PHY_RETENTIONED;
641 }
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530642
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700643 /* Ensure that above operation is completed before turning off clocks */
644 mb();
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530645 clk_disable(motg->pclk);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530646 if (motg->core_clk)
647 clk_disable(motg->core_clk);
648
Amit Blay137575f2011-11-06 15:20:54 +0200649 if (!IS_ERR(motg->system_clk))
650 clk_disable(motg->system_clk);
651
Anji jonnala0f73cac2011-05-04 10:19:46 +0530652 if (!IS_ERR(motg->pclk_src))
653 clk_disable(motg->pclk_src);
654
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700655 if (motg->caps & ALLOW_PHY_POWER_COLLAPSE && !session_active) {
656 msm_hsusb_ldo_enable(motg, 0);
657 motg->lpm_flags |= PHY_PWR_COLLAPSED;
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530658 }
659
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530660 if (motg->lpm_flags & PHY_RETENTIONED) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700661 msm_hsusb_config_vddcx(0);
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530662 msm_hsusb_mhl_switch_enable(motg, 0);
663 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700664
665 if (device_may_wakeup(otg->dev)) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530666 enable_irq_wake(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700667 if (motg->pdata->pmic_id_irq)
668 enable_irq_wake(motg->pdata->pmic_id_irq);
669 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530670 if (bus)
671 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
672
673 atomic_set(&motg->in_lpm, 1);
674 enable_irq(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700675 wake_unlock(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530676
677 dev_info(otg->dev, "USB in low power mode\n");
678
679 return 0;
680}
681
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530682static int msm_otg_resume(struct msm_otg *motg)
683{
684 struct otg_transceiver *otg = &motg->otg;
685 struct usb_bus *bus = otg->host;
686 int cnt = 0;
687 unsigned temp;
688
689 if (!atomic_read(&motg->in_lpm))
690 return 0;
691
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700692 wake_lock(&motg->wlock);
Anji jonnala0f73cac2011-05-04 10:19:46 +0530693 if (!IS_ERR(motg->pclk_src))
694 clk_enable(motg->pclk_src);
695
Amit Blay137575f2011-11-06 15:20:54 +0200696 if (!IS_ERR(motg->system_clk))
697 clk_enable(motg->system_clk);
698
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530699 clk_enable(motg->pclk);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530700 if (motg->core_clk)
701 clk_enable(motg->core_clk);
702
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700703 if (motg->lpm_flags & PHY_PWR_COLLAPSED) {
704 msm_hsusb_ldo_enable(motg, 1);
705 motg->lpm_flags &= ~PHY_PWR_COLLAPSED;
706 }
707
708 if (motg->lpm_flags & PHY_RETENTIONED) {
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +0530709 msm_hsusb_mhl_switch_enable(motg, 1);
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530710 msm_hsusb_config_vddcx(1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700711 writel_relaxed(readl_relaxed(USB_PHY_CTRL) | PHY_RETEN,
712 USB_PHY_CTRL);
713 motg->lpm_flags &= ~PHY_RETENTIONED;
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530714 }
715
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530716 temp = readl(USB_USBCMD);
717 temp &= ~ASYNC_INTR_CTRL;
718 temp &= ~ULPI_STP_CTRL;
719 writel(temp, USB_USBCMD);
720
721 /*
722 * PHY comes out of low power mode (LPM) in case of wakeup
723 * from asynchronous interrupt.
724 */
725 if (!(readl(USB_PORTSC) & PORTSC_PHCD))
726 goto skip_phy_resume;
727
728 writel(readl(USB_PORTSC) & ~PORTSC_PHCD, USB_PORTSC);
729 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
730 if (!(readl(USB_PORTSC) & PORTSC_PHCD))
731 break;
732 udelay(1);
733 cnt++;
734 }
735
736 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
737 /*
738 * This is a fatal error. Reset the link and
739 * PHY. USB state can not be restored. Re-insertion
740 * of USB cable is the only way to get USB working.
741 */
742 dev_err(otg->dev, "Unable to resume USB."
743 "Re-plugin the cable\n");
744 msm_otg_reset(otg);
745 }
746
747skip_phy_resume:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700748 /* Turn on the OTG comparators on resume */
749 if (motg->lpm_flags & PHY_OTG_COMP_DISABLED) {
750 ulpi_write(otg, OTG_COMP_DISABLE,
751 ULPI_CLR(ULPI_PWR_CLK_MNG_REG));
752 motg->lpm_flags &= ~PHY_OTG_COMP_DISABLED;
753 }
754 if (device_may_wakeup(otg->dev)) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530755 disable_irq_wake(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700756 if (motg->pdata->pmic_id_irq)
757 disable_irq_wake(motg->pdata->pmic_id_irq);
758 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530759 if (bus)
760 set_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
761
Pavankumar Kondeti2ce2c3a2011-05-02 11:56:33 +0530762 atomic_set(&motg->in_lpm, 0);
763
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530764 if (motg->async_int) {
765 motg->async_int = 0;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530766 enable_irq(motg->irq);
767 }
768
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530769 dev_info(otg->dev, "USB exited from low power mode\n");
770
771 return 0;
772}
Pavankumar Kondeti70187732011-02-15 09:42:34 +0530773#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530774
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530775static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA)
776{
777 if (motg->cur_power == mA)
778 return;
779
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530780 dev_info(motg->otg.dev, "Avail curr from USB = %u\n", mA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700781 pm8921_charger_vbus_draw(mA);
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530782 motg->cur_power = mA;
783}
784
785static int msm_otg_set_power(struct otg_transceiver *otg, unsigned mA)
786{
787 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
788
789 /*
790 * Gadget driver uses set_power method to notify about the
791 * available current based on suspend/configured states.
792 *
793 * IDEV_CHG can be drawn irrespective of suspend/un-configured
794 * states when CDP/ACA is connected.
795 */
796 if (motg->chg_type == USB_SDP_CHARGER)
797 msm_otg_notify_charger(motg, mA);
798
799 return 0;
800}
801
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530802static void msm_otg_start_host(struct otg_transceiver *otg, int on)
803{
804 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
805 struct msm_otg_platform_data *pdata = motg->pdata;
806 struct usb_hcd *hcd;
807
808 if (!otg->host)
809 return;
810
811 hcd = bus_to_hcd(otg->host);
812
813 if (on) {
814 dev_dbg(otg->dev, "host on\n");
815
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530816 /*
817 * Some boards have a switch cotrolled by gpio
818 * to enable/disable internal HUB. Enable internal
819 * HUB before kicking the host.
820 */
821 if (pdata->setup_gpio)
822 pdata->setup_gpio(OTG_STATE_A_HOST);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530823 usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530824 } else {
825 dev_dbg(otg->dev, "host off\n");
826
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530827 usb_remove_hcd(hcd);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530828 if (pdata->setup_gpio)
829 pdata->setup_gpio(OTG_STATE_UNDEFINED);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530830 }
831}
832
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700833static int msm_otg_usbdev_notify(struct notifier_block *self,
834 unsigned long action, void *priv)
835{
836 struct msm_otg *motg = container_of(self, struct msm_otg, usbdev_nb);
837 struct usb_device *udev;
838
839 switch (action) {
840 case USB_DEVICE_ADD:
841 case USB_DEVICE_CONFIG:
842 udev = priv;
843 /*
844 * Interested in devices connected directly to the root hub.
845 * ACA dock can supply IDEV_CHG irrespective devices connected
846 * on the accessory port.
847 */
848 if (!udev->parent || udev->parent->parent ||
849 motg->chg_type == USB_ACA_DOCK_CHARGER)
850 break;
851 if (udev->actconfig)
852 motg->mA_port = udev->actconfig->desc.bMaxPower * 2;
853 else
854 motg->mA_port = IUNIT;
855
856 if (test_bit(ID_A, &motg->inputs))
857 msm_otg_notify_charger(motg, IDEV_CHG_MIN -
858 motg->mA_port);
859 break;
860 default:
861 break;
862 }
863 return NOTIFY_OK;
864}
865
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530866static int msm_otg_set_host(struct otg_transceiver *otg, struct usb_bus *host)
867{
868 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
869 struct usb_hcd *hcd;
870
871 /*
872 * Fail host registration if this board can support
873 * only peripheral configuration.
874 */
875 if (motg->pdata->mode == USB_PERIPHERAL) {
876 dev_info(otg->dev, "Host mode is not supported\n");
877 return -ENODEV;
878 }
879
880 if (!host) {
881 if (otg->state == OTG_STATE_A_HOST) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530882 pm_runtime_get_sync(otg->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700883 usb_unregister_notify(&motg->usbdev_nb);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530884 msm_otg_start_host(otg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700885 if (motg->pdata->vbus_power)
886 motg->pdata->vbus_power(0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530887 otg->host = NULL;
888 otg->state = OTG_STATE_UNDEFINED;
889 schedule_work(&motg->sm_work);
890 } else {
891 otg->host = NULL;
892 }
893
894 return 0;
895 }
896
897 hcd = bus_to_hcd(host);
898 hcd->power_budget = motg->pdata->power_budget;
899
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700900 motg->usbdev_nb.notifier_call = msm_otg_usbdev_notify;
901 usb_register_notify(&motg->usbdev_nb);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530902 otg->host = host;
903 dev_dbg(otg->dev, "host driver registered w/ tranceiver\n");
904
905 /*
906 * Kick the state machine work, if peripheral is not supported
907 * or peripheral is already registered with us.
908 */
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530909 if (motg->pdata->mode == USB_HOST || otg->gadget) {
910 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530911 schedule_work(&motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530912 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530913
914 return 0;
915}
916
917static void msm_otg_start_peripheral(struct otg_transceiver *otg, int on)
918{
919 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
920 struct msm_otg_platform_data *pdata = motg->pdata;
921
922 if (!otg->gadget)
923 return;
924
925 if (on) {
926 dev_dbg(otg->dev, "gadget on\n");
927 /*
928 * Some boards have a switch cotrolled by gpio
929 * to enable/disable internal HUB. Disable internal
930 * HUB before kicking the gadget.
931 */
932 if (pdata->setup_gpio)
933 pdata->setup_gpio(OTG_STATE_B_PERIPHERAL);
934 usb_gadget_vbus_connect(otg->gadget);
935 } else {
936 dev_dbg(otg->dev, "gadget off\n");
937 usb_gadget_vbus_disconnect(otg->gadget);
938 if (pdata->setup_gpio)
939 pdata->setup_gpio(OTG_STATE_UNDEFINED);
940 }
941
942}
943
944static int msm_otg_set_peripheral(struct otg_transceiver *otg,
945 struct usb_gadget *gadget)
946{
947 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
948
949 /*
950 * Fail peripheral registration if this board can support
951 * only host configuration.
952 */
953 if (motg->pdata->mode == USB_HOST) {
954 dev_info(otg->dev, "Peripheral mode is not supported\n");
955 return -ENODEV;
956 }
957
958 if (!gadget) {
959 if (otg->state == OTG_STATE_B_PERIPHERAL) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530960 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530961 msm_otg_start_peripheral(otg, 0);
962 otg->gadget = NULL;
963 otg->state = OTG_STATE_UNDEFINED;
964 schedule_work(&motg->sm_work);
965 } else {
966 otg->gadget = NULL;
967 }
968
969 return 0;
970 }
971 otg->gadget = gadget;
972 dev_dbg(otg->dev, "peripheral driver registered w/ tranceiver\n");
973
974 /*
975 * Kick the state machine work, if host is not supported
976 * or host is already registered with us.
977 */
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530978 if (motg->pdata->mode == USB_PERIPHERAL || otg->host) {
979 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530980 schedule_work(&motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530981 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530982
983 return 0;
984}
985
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700986#ifdef CONFIG_USB_MSM_ACA
987static bool msm_chg_aca_detect(struct msm_otg *motg)
988{
989 struct otg_transceiver *otg = &motg->otg;
990 u32 int_sts;
991 bool ret = false;
992
993 if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY)
994 goto out;
995
996 int_sts = ulpi_read(otg, 0x87);
997 switch (int_sts & 0x1C) {
998 case 0x08:
999 if (!test_and_set_bit(ID_A, &motg->inputs)) {
1000 dev_dbg(otg->dev, "ID_A\n");
1001 motg->chg_type = USB_ACA_A_CHARGER;
1002 motg->chg_state = USB_CHG_STATE_DETECTED;
1003 clear_bit(ID_B, &motg->inputs);
1004 clear_bit(ID_C, &motg->inputs);
1005 ret = true;
1006 }
1007 break;
1008 case 0x0C:
1009 if (!test_and_set_bit(ID_B, &motg->inputs)) {
1010 dev_dbg(otg->dev, "ID_B\n");
1011 motg->chg_type = USB_ACA_B_CHARGER;
1012 motg->chg_state = USB_CHG_STATE_DETECTED;
1013 clear_bit(ID_A, &motg->inputs);
1014 clear_bit(ID_C, &motg->inputs);
1015 ret = true;
1016 }
1017 break;
1018 case 0x10:
1019 if (!test_and_set_bit(ID_C, &motg->inputs)) {
1020 dev_dbg(otg->dev, "ID_C\n");
1021 motg->chg_type = USB_ACA_C_CHARGER;
1022 motg->chg_state = USB_CHG_STATE_DETECTED;
1023 clear_bit(ID_A, &motg->inputs);
1024 clear_bit(ID_B, &motg->inputs);
1025 ret = true;
1026 }
1027 break;
1028 default:
1029 ret = test_and_clear_bit(ID_A, &motg->inputs) |
1030 test_and_clear_bit(ID_B, &motg->inputs) |
1031 test_and_clear_bit(ID_C, &motg->inputs);
1032 if (ret) {
1033 dev_dbg(otg->dev, "ID A/B/C is no more\n");
1034 motg->chg_type = USB_INVALID_CHARGER;
1035 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1036 }
1037 }
1038out:
1039 return ret;
1040}
1041
1042static void msm_chg_enable_aca_det(struct msm_otg *motg)
1043{
1044 struct otg_transceiver *otg = &motg->otg;
1045
1046 switch (motg->pdata->phy_type) {
1047 case SNPS_28NM_INTEGRATED_PHY:
1048 /* ACA ID pin resistance detection enable */
1049 ulpi_write(otg, 0x20, 0x85);
1050 break;
1051 default:
1052 break;
1053 }
1054}
1055
1056static void msm_chg_enable_aca_intr(struct msm_otg *motg)
1057{
1058 struct otg_transceiver *otg = &motg->otg;
1059
1060 switch (motg->pdata->phy_type) {
1061 case SNPS_28NM_INTEGRATED_PHY:
1062 /* Enables ACA Detection interrupt (on any RID change) */
1063 ulpi_write(otg, 0x20, 0x94);
1064 break;
1065 default:
1066 break;
1067 }
1068}
1069
1070static bool msm_chg_check_aca_intr(struct msm_otg *motg)
1071{
1072 struct otg_transceiver *otg = &motg->otg;
1073 bool ret = false;
1074
1075 switch (motg->pdata->phy_type) {
1076 case SNPS_28NM_INTEGRATED_PHY:
1077 if (ulpi_read(otg, 0x91) & 1) {
1078 dev_dbg(otg->dev, "RID change\n");
1079 ulpi_write(otg, 0x01, 0x92);
1080 ret = msm_chg_aca_detect(motg);
1081 }
1082 default:
1083 break;
1084 }
1085 return ret;
1086}
1087#endif
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301088static bool msm_chg_check_secondary_det(struct msm_otg *motg)
1089{
1090 struct otg_transceiver *otg = &motg->otg;
1091 u32 chg_det;
1092 bool ret = false;
1093
1094 switch (motg->pdata->phy_type) {
1095 case CI_45NM_INTEGRATED_PHY:
1096 chg_det = ulpi_read(otg, 0x34);
1097 ret = chg_det & (1 << 4);
1098 break;
1099 case SNPS_28NM_INTEGRATED_PHY:
1100 chg_det = ulpi_read(otg, 0x87);
1101 ret = chg_det & 1;
1102 break;
1103 default:
1104 break;
1105 }
1106 return ret;
1107}
1108
1109static void msm_chg_enable_secondary_det(struct msm_otg *motg)
1110{
1111 struct otg_transceiver *otg = &motg->otg;
1112 u32 chg_det;
1113
1114 switch (motg->pdata->phy_type) {
1115 case CI_45NM_INTEGRATED_PHY:
1116 chg_det = ulpi_read(otg, 0x34);
1117 /* Turn off charger block */
1118 chg_det |= ~(1 << 1);
1119 ulpi_write(otg, chg_det, 0x34);
1120 udelay(20);
1121 /* control chg block via ULPI */
1122 chg_det &= ~(1 << 3);
1123 ulpi_write(otg, chg_det, 0x34);
1124 /* put it in host mode for enabling D- source */
1125 chg_det &= ~(1 << 2);
1126 ulpi_write(otg, chg_det, 0x34);
1127 /* Turn on chg detect block */
1128 chg_det &= ~(1 << 1);
1129 ulpi_write(otg, chg_det, 0x34);
1130 udelay(20);
1131 /* enable chg detection */
1132 chg_det &= ~(1 << 0);
1133 ulpi_write(otg, chg_det, 0x34);
1134 break;
1135 case SNPS_28NM_INTEGRATED_PHY:
1136 /*
1137 * Configure DM as current source, DP as current sink
1138 * and enable battery charging comparators.
1139 */
1140 ulpi_write(otg, 0x8, 0x85);
1141 ulpi_write(otg, 0x2, 0x85);
1142 ulpi_write(otg, 0x1, 0x85);
1143 break;
1144 default:
1145 break;
1146 }
1147}
1148
1149static bool msm_chg_check_primary_det(struct msm_otg *motg)
1150{
1151 struct otg_transceiver *otg = &motg->otg;
1152 u32 chg_det;
1153 bool ret = false;
1154
1155 switch (motg->pdata->phy_type) {
1156 case CI_45NM_INTEGRATED_PHY:
1157 chg_det = ulpi_read(otg, 0x34);
1158 ret = chg_det & (1 << 4);
1159 break;
1160 case SNPS_28NM_INTEGRATED_PHY:
1161 chg_det = ulpi_read(otg, 0x87);
1162 ret = chg_det & 1;
1163 break;
1164 default:
1165 break;
1166 }
1167 return ret;
1168}
1169
1170static void msm_chg_enable_primary_det(struct msm_otg *motg)
1171{
1172 struct otg_transceiver *otg = &motg->otg;
1173 u32 chg_det;
1174
1175 switch (motg->pdata->phy_type) {
1176 case CI_45NM_INTEGRATED_PHY:
1177 chg_det = ulpi_read(otg, 0x34);
1178 /* enable chg detection */
1179 chg_det &= ~(1 << 0);
1180 ulpi_write(otg, chg_det, 0x34);
1181 break;
1182 case SNPS_28NM_INTEGRATED_PHY:
1183 /*
1184 * Configure DP as current source, DM as current sink
1185 * and enable battery charging comparators.
1186 */
1187 ulpi_write(otg, 0x2, 0x85);
1188 ulpi_write(otg, 0x1, 0x85);
1189 break;
1190 default:
1191 break;
1192 }
1193}
1194
1195static bool msm_chg_check_dcd(struct msm_otg *motg)
1196{
1197 struct otg_transceiver *otg = &motg->otg;
1198 u32 line_state;
1199 bool ret = false;
1200
1201 switch (motg->pdata->phy_type) {
1202 case CI_45NM_INTEGRATED_PHY:
1203 line_state = ulpi_read(otg, 0x15);
1204 ret = !(line_state & 1);
1205 break;
1206 case SNPS_28NM_INTEGRATED_PHY:
1207 line_state = ulpi_read(otg, 0x87);
1208 ret = line_state & 2;
1209 break;
1210 default:
1211 break;
1212 }
1213 return ret;
1214}
1215
1216static void msm_chg_disable_dcd(struct msm_otg *motg)
1217{
1218 struct otg_transceiver *otg = &motg->otg;
1219 u32 chg_det;
1220
1221 switch (motg->pdata->phy_type) {
1222 case CI_45NM_INTEGRATED_PHY:
1223 chg_det = ulpi_read(otg, 0x34);
1224 chg_det &= ~(1 << 5);
1225 ulpi_write(otg, chg_det, 0x34);
1226 break;
1227 case SNPS_28NM_INTEGRATED_PHY:
1228 ulpi_write(otg, 0x10, 0x86);
1229 break;
1230 default:
1231 break;
1232 }
1233}
1234
1235static void msm_chg_enable_dcd(struct msm_otg *motg)
1236{
1237 struct otg_transceiver *otg = &motg->otg;
1238 u32 chg_det;
1239
1240 switch (motg->pdata->phy_type) {
1241 case CI_45NM_INTEGRATED_PHY:
1242 chg_det = ulpi_read(otg, 0x34);
1243 /* Turn on D+ current source */
1244 chg_det |= (1 << 5);
1245 ulpi_write(otg, chg_det, 0x34);
1246 break;
1247 case SNPS_28NM_INTEGRATED_PHY:
1248 /* Data contact detection enable */
1249 ulpi_write(otg, 0x10, 0x85);
1250 break;
1251 default:
1252 break;
1253 }
1254}
1255
1256static void msm_chg_block_on(struct msm_otg *motg)
1257{
1258 struct otg_transceiver *otg = &motg->otg;
1259 u32 func_ctrl, chg_det;
1260
1261 /* put the controller in non-driving mode */
1262 func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
1263 func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
1264 func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
1265 ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
1266
1267 switch (motg->pdata->phy_type) {
1268 case CI_45NM_INTEGRATED_PHY:
1269 chg_det = ulpi_read(otg, 0x34);
1270 /* control chg block via ULPI */
1271 chg_det &= ~(1 << 3);
1272 ulpi_write(otg, chg_det, 0x34);
1273 /* Turn on chg detect block */
1274 chg_det &= ~(1 << 1);
1275 ulpi_write(otg, chg_det, 0x34);
1276 udelay(20);
1277 break;
1278 case SNPS_28NM_INTEGRATED_PHY:
1279 /* Clear charger detecting control bits */
1280 ulpi_write(otg, 0x3F, 0x86);
1281 /* Clear alt interrupt latch and enable bits */
1282 ulpi_write(otg, 0x1F, 0x92);
1283 ulpi_write(otg, 0x1F, 0x95);
1284 udelay(100);
1285 break;
1286 default:
1287 break;
1288 }
1289}
1290
1291static void msm_chg_block_off(struct msm_otg *motg)
1292{
1293 struct otg_transceiver *otg = &motg->otg;
1294 u32 func_ctrl, chg_det;
1295
1296 switch (motg->pdata->phy_type) {
1297 case CI_45NM_INTEGRATED_PHY:
1298 chg_det = ulpi_read(otg, 0x34);
1299 /* Turn off charger block */
1300 chg_det |= ~(1 << 1);
1301 ulpi_write(otg, chg_det, 0x34);
1302 break;
1303 case SNPS_28NM_INTEGRATED_PHY:
1304 /* Clear charger detecting control bits */
1305 ulpi_write(otg, 0x3F, 0x86);
1306 /* Clear alt interrupt latch and enable bits */
1307 ulpi_write(otg, 0x1F, 0x92);
1308 ulpi_write(otg, 0x1F, 0x95);
1309 break;
1310 default:
1311 break;
1312 }
1313
1314 /* put the controller in normal mode */
1315 func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
1316 func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
1317 func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
1318 ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
1319}
1320
Anji jonnalad270e2d2011-08-09 11:28:32 +05301321static const char *chg_to_string(enum usb_chg_type chg_type)
1322{
1323 switch (chg_type) {
1324 case USB_SDP_CHARGER: return "USB_SDP_CHARGER";
1325 case USB_DCP_CHARGER: return "USB_DCP_CHARGER";
1326 case USB_CDP_CHARGER: return "USB_CDP_CHARGER";
1327 case USB_ACA_A_CHARGER: return "USB_ACA_A_CHARGER";
1328 case USB_ACA_B_CHARGER: return "USB_ACA_B_CHARGER";
1329 case USB_ACA_C_CHARGER: return "USB_ACA_C_CHARGER";
1330 case USB_ACA_DOCK_CHARGER: return "USB_ACA_DOCK_CHARGER";
1331 default: return "INVALID_CHARGER";
1332 }
1333}
1334
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301335#define MSM_CHG_DCD_POLL_TIME (100 * HZ/1000) /* 100 msec */
1336#define MSM_CHG_DCD_MAX_RETRIES 6 /* Tdcd_tmout = 6 * 100 msec */
1337#define MSM_CHG_PRIMARY_DET_TIME (40 * HZ/1000) /* TVDPSRC_ON */
1338#define MSM_CHG_SECONDARY_DET_TIME (40 * HZ/1000) /* TVDMSRC_ON */
1339static void msm_chg_detect_work(struct work_struct *w)
1340{
1341 struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
1342 struct otg_transceiver *otg = &motg->otg;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001343 bool is_dcd, tmout, vout, is_aca;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301344 unsigned long delay;
1345
1346 dev_dbg(otg->dev, "chg detection work\n");
1347 switch (motg->chg_state) {
1348 case USB_CHG_STATE_UNDEFINED:
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301349 msm_chg_block_on(motg);
1350 msm_chg_enable_dcd(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001351 msm_chg_enable_aca_det(motg);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301352 motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
1353 motg->dcd_retries = 0;
1354 delay = MSM_CHG_DCD_POLL_TIME;
1355 break;
1356 case USB_CHG_STATE_WAIT_FOR_DCD:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001357 is_aca = msm_chg_aca_detect(motg);
1358 if (is_aca) {
1359 /*
1360 * ID_A can be ACA dock too. continue
1361 * primary detection after DCD.
1362 */
1363 if (test_bit(ID_A, &motg->inputs)) {
1364 motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
1365 } else {
1366 delay = 0;
1367 break;
1368 }
1369 }
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301370 is_dcd = msm_chg_check_dcd(motg);
1371 tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES;
1372 if (is_dcd || tmout) {
1373 msm_chg_disable_dcd(motg);
1374 msm_chg_enable_primary_det(motg);
1375 delay = MSM_CHG_PRIMARY_DET_TIME;
1376 motg->chg_state = USB_CHG_STATE_DCD_DONE;
1377 } else {
1378 delay = MSM_CHG_DCD_POLL_TIME;
1379 }
1380 break;
1381 case USB_CHG_STATE_DCD_DONE:
1382 vout = msm_chg_check_primary_det(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001383 is_aca = msm_chg_aca_detect(motg);
1384 if (is_aca) {
1385 if (vout && test_bit(ID_A, &motg->inputs))
1386 motg->chg_type = USB_ACA_DOCK_CHARGER;
1387 delay = 0;
1388 break;
1389 }
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301390 if (vout) {
1391 msm_chg_enable_secondary_det(motg);
1392 delay = MSM_CHG_SECONDARY_DET_TIME;
1393 motg->chg_state = USB_CHG_STATE_PRIMARY_DONE;
1394 } else {
1395 motg->chg_type = USB_SDP_CHARGER;
1396 motg->chg_state = USB_CHG_STATE_DETECTED;
1397 delay = 0;
1398 }
1399 break;
1400 case USB_CHG_STATE_PRIMARY_DONE:
1401 vout = msm_chg_check_secondary_det(motg);
1402 if (vout)
1403 motg->chg_type = USB_DCP_CHARGER;
1404 else
1405 motg->chg_type = USB_CDP_CHARGER;
1406 motg->chg_state = USB_CHG_STATE_SECONDARY_DONE;
1407 /* fall through */
1408 case USB_CHG_STATE_SECONDARY_DONE:
1409 motg->chg_state = USB_CHG_STATE_DETECTED;
1410 case USB_CHG_STATE_DETECTED:
1411 msm_chg_block_off(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001412 msm_chg_enable_aca_det(motg);
1413 msm_chg_enable_aca_intr(motg);
Anji jonnalad270e2d2011-08-09 11:28:32 +05301414 dev_dbg(otg->dev, "chg_type = %s\n",
1415 chg_to_string(motg->chg_type));
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301416 schedule_work(&motg->sm_work);
1417 return;
1418 default:
1419 return;
1420 }
1421
1422 schedule_delayed_work(&motg->chg_work, delay);
1423}
1424
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301425/*
1426 * We support OTG, Peripheral only and Host only configurations. In case
1427 * of OTG, mode switch (host-->peripheral/peripheral-->host) can happen
1428 * via Id pin status or user request (debugfs). Id/BSV interrupts are not
1429 * enabled when switch is controlled by user and default mode is supplied
1430 * by board file, which can be changed by userspace later.
1431 */
1432static void msm_otg_init_sm(struct msm_otg *motg)
1433{
1434 struct msm_otg_platform_data *pdata = motg->pdata;
1435 u32 otgsc = readl(USB_OTGSC);
1436
1437 switch (pdata->mode) {
1438 case USB_OTG:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001439 if (pdata->otg_control == OTG_USER_CONTROL) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301440 if (pdata->default_mode == USB_HOST) {
1441 clear_bit(ID, &motg->inputs);
1442 } else if (pdata->default_mode == USB_PERIPHERAL) {
1443 set_bit(ID, &motg->inputs);
1444 set_bit(B_SESS_VLD, &motg->inputs);
1445 } else {
1446 set_bit(ID, &motg->inputs);
1447 clear_bit(B_SESS_VLD, &motg->inputs);
1448 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001449 } else {
1450 if (otgsc & OTGSC_ID)
1451 set_bit(ID, &motg->inputs);
1452 else
1453 clear_bit(ID, &motg->inputs);
1454
1455 if (otgsc & OTGSC_BSV)
1456 set_bit(B_SESS_VLD, &motg->inputs);
1457 else
1458 clear_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301459 }
1460 break;
1461 case USB_HOST:
1462 clear_bit(ID, &motg->inputs);
1463 break;
1464 case USB_PERIPHERAL:
1465 set_bit(ID, &motg->inputs);
1466 if (otgsc & OTGSC_BSV)
1467 set_bit(B_SESS_VLD, &motg->inputs);
1468 else
1469 clear_bit(B_SESS_VLD, &motg->inputs);
1470 break;
1471 default:
1472 break;
1473 }
1474}
1475
1476static void msm_otg_sm_work(struct work_struct *w)
1477{
1478 struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
1479 struct otg_transceiver *otg = &motg->otg;
1480
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301481 pm_runtime_resume(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301482 switch (otg->state) {
1483 case OTG_STATE_UNDEFINED:
1484 dev_dbg(otg->dev, "OTG_STATE_UNDEFINED state\n");
1485 msm_otg_reset(otg);
1486 msm_otg_init_sm(motg);
1487 otg->state = OTG_STATE_B_IDLE;
1488 /* FALL THROUGH */
1489 case OTG_STATE_B_IDLE:
1490 dev_dbg(otg->dev, "OTG_STATE_B_IDLE state\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001491 if ((!test_bit(ID, &motg->inputs) ||
1492 test_bit(ID_A, &motg->inputs)) && otg->host) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301493 /* disable BSV bit */
1494 writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001495 if (motg->chg_type == USB_ACA_DOCK_CHARGER)
1496 msm_otg_notify_charger(motg,
1497 IDEV_CHG_MAX);
1498 else if (!test_bit(ID_A, &motg->inputs) &&
1499 motg->pdata->vbus_power)
1500 motg->pdata->vbus_power(1);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301501 msm_otg_start_host(otg, 1);
1502 otg->state = OTG_STATE_A_HOST;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301503 } else if (test_bit(B_SESS_VLD, &motg->inputs)) {
1504 switch (motg->chg_state) {
1505 case USB_CHG_STATE_UNDEFINED:
1506 msm_chg_detect_work(&motg->chg_work.work);
1507 break;
1508 case USB_CHG_STATE_DETECTED:
1509 switch (motg->chg_type) {
1510 case USB_DCP_CHARGER:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001511 case USB_ACA_B_CHARGER:
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301512 msm_otg_notify_charger(motg,
1513 IDEV_CHG_MAX);
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301514 pm_runtime_put_noidle(otg->dev);
1515 pm_runtime_suspend(otg->dev);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301516 break;
1517 case USB_CDP_CHARGER:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001518 case USB_ACA_C_CHARGER:
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301519 msm_otg_notify_charger(motg,
1520 IDEV_CHG_MAX);
1521 msm_otg_start_peripheral(otg, 1);
1522 otg->state = OTG_STATE_B_PERIPHERAL;
1523 break;
1524 case USB_SDP_CHARGER:
1525 msm_otg_notify_charger(motg, IUNIT);
1526 msm_otg_start_peripheral(otg, 1);
1527 otg->state = OTG_STATE_B_PERIPHERAL;
1528 break;
1529 default:
1530 break;
1531 }
1532 break;
1533 default:
1534 break;
1535 }
1536 } else {
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301537 if (cancel_delayed_work_sync(&motg->chg_work))
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301538 msm_otg_reset(otg);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301539 msm_otg_notify_charger(motg, 0);
1540 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1541 motg->chg_type = USB_INVALID_CHARGER;
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301542 pm_runtime_put_noidle(otg->dev);
1543 pm_runtime_suspend(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301544 }
1545 break;
1546 case OTG_STATE_B_PERIPHERAL:
1547 dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n");
1548 if (!test_bit(B_SESS_VLD, &motg->inputs) ||
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001549 !test_bit(ID, &motg->inputs) ||
1550 !test_bit(ID_C, &motg->inputs)) {
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301551 msm_otg_notify_charger(motg, 0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301552 msm_otg_start_peripheral(otg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001553 if (!test_bit(ID_B, &motg->inputs) &&
1554 !test_bit(ID_A, &motg->inputs)) {
1555 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1556 motg->chg_type = USB_INVALID_CHARGER;
1557 }
1558 otg->state = OTG_STATE_B_IDLE;
1559 msm_otg_reset(otg);
1560 schedule_work(w);
1561 } else if (test_bit(ID_C, &motg->inputs)) {
1562 msm_otg_notify_charger(motg, IDEV_CHG_MAX);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001563 }
1564 break;
1565 case OTG_STATE_A_HOST:
1566 dev_dbg(otg->dev, "OTG_STATE_A_HOST state\n");
1567 if (test_bit(ID, &motg->inputs) &&
1568 !test_bit(ID_A, &motg->inputs)) {
1569 msm_otg_start_host(otg, 0);
1570 writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
1571 if (motg->pdata->vbus_power)
1572 motg->pdata->vbus_power(0);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301573 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1574 motg->chg_type = USB_INVALID_CHARGER;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301575 otg->state = OTG_STATE_B_IDLE;
1576 msm_otg_reset(otg);
1577 schedule_work(w);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001578 } else if (test_bit(ID_A, &motg->inputs)) {
1579 writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
1580 if (motg->pdata->vbus_power)
1581 motg->pdata->vbus_power(0);
1582 msm_otg_notify_charger(motg,
1583 IDEV_CHG_MIN - motg->mA_port);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001584 } else if (!test_bit(ID, &motg->inputs)) {
1585 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1586 motg->chg_type = USB_INVALID_CHARGER;
1587 msm_otg_notify_charger(motg, 0);
1588 writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
1589 if (motg->pdata->vbus_power)
1590 motg->pdata->vbus_power(1);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301591 }
1592 break;
1593 default:
1594 break;
1595 }
1596}
1597
1598static irqreturn_t msm_otg_irq(int irq, void *data)
1599{
1600 struct msm_otg *motg = data;
1601 struct otg_transceiver *otg = &motg->otg;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001602 u32 otgsc = 0, usbsts;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301603
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301604 if (atomic_read(&motg->in_lpm)) {
1605 disable_irq_nosync(irq);
1606 motg->async_int = 1;
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301607 pm_request_resume(otg->dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301608 return IRQ_HANDLED;
1609 }
1610
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001611 usbsts = readl(USB_USBSTS);
1612 if ((usbsts & PHY_ALT_INT)) {
1613 writel(PHY_ALT_INT, USB_USBSTS);
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301614 if (msm_chg_check_aca_intr(motg))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001615 schedule_work(&motg->sm_work);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001616 return IRQ_HANDLED;
1617 }
1618
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301619 otgsc = readl(USB_OTGSC);
1620 if (!(otgsc & (OTGSC_IDIS | OTGSC_BSVIS)))
1621 return IRQ_NONE;
1622
1623 if ((otgsc & OTGSC_IDIS) && (otgsc & OTGSC_IDIE)) {
1624 if (otgsc & OTGSC_ID)
1625 set_bit(ID, &motg->inputs);
1626 else
1627 clear_bit(ID, &motg->inputs);
1628 dev_dbg(otg->dev, "ID set/clear\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001629 schedule_work(&motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301630 } else if ((otgsc & OTGSC_BSVIS) && (otgsc & OTGSC_BSVIE)) {
1631 if (otgsc & OTGSC_BSV)
1632 set_bit(B_SESS_VLD, &motg->inputs);
1633 else
1634 clear_bit(B_SESS_VLD, &motg->inputs);
1635 dev_dbg(otg->dev, "BSV set/clear\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001636 schedule_work(&motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301637 }
1638
1639 writel(otgsc, USB_OTGSC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001640 return IRQ_HANDLED;
1641}
1642
1643static void msm_otg_set_vbus_state(int online)
1644{
1645 struct msm_otg *motg = the_msm_otg;
1646
1647 /* We depend on PMIC for only VBUS ON interrupt */
1648 if (!atomic_read(&motg->in_lpm) || !online)
1649 return;
1650
1651 /*
1652 * Let interrupt handler take care of resuming
1653 * the hardware.
1654 */
1655 msm_otg_irq(motg->irq, (void *) motg);
1656}
1657
1658static irqreturn_t msm_pmic_id_irq(int irq, void *data)
1659{
1660 struct msm_otg *motg = data;
1661
1662 if (atomic_read(&motg->in_lpm) && !motg->async_int)
1663 msm_otg_irq(motg->irq, motg);
1664
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301665 return IRQ_HANDLED;
1666}
1667
1668static int msm_otg_mode_show(struct seq_file *s, void *unused)
1669{
1670 struct msm_otg *motg = s->private;
1671 struct otg_transceiver *otg = &motg->otg;
1672
1673 switch (otg->state) {
1674 case OTG_STATE_A_HOST:
1675 seq_printf(s, "host\n");
1676 break;
1677 case OTG_STATE_B_PERIPHERAL:
1678 seq_printf(s, "peripheral\n");
1679 break;
1680 default:
1681 seq_printf(s, "none\n");
1682 break;
1683 }
1684
1685 return 0;
1686}
1687
1688static int msm_otg_mode_open(struct inode *inode, struct file *file)
1689{
1690 return single_open(file, msm_otg_mode_show, inode->i_private);
1691}
1692
1693static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf,
1694 size_t count, loff_t *ppos)
1695{
Pavankumar Kondetie2904ee2011-02-15 09:42:35 +05301696 struct seq_file *s = file->private_data;
1697 struct msm_otg *motg = s->private;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301698 char buf[16];
1699 struct otg_transceiver *otg = &motg->otg;
1700 int status = count;
1701 enum usb_mode_type req_mode;
1702
1703 memset(buf, 0x00, sizeof(buf));
1704
1705 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) {
1706 status = -EFAULT;
1707 goto out;
1708 }
1709
1710 if (!strncmp(buf, "host", 4)) {
1711 req_mode = USB_HOST;
1712 } else if (!strncmp(buf, "peripheral", 10)) {
1713 req_mode = USB_PERIPHERAL;
1714 } else if (!strncmp(buf, "none", 4)) {
1715 req_mode = USB_NONE;
1716 } else {
1717 status = -EINVAL;
1718 goto out;
1719 }
1720
1721 switch (req_mode) {
1722 case USB_NONE:
1723 switch (otg->state) {
1724 case OTG_STATE_A_HOST:
1725 case OTG_STATE_B_PERIPHERAL:
1726 set_bit(ID, &motg->inputs);
1727 clear_bit(B_SESS_VLD, &motg->inputs);
1728 break;
1729 default:
1730 goto out;
1731 }
1732 break;
1733 case USB_PERIPHERAL:
1734 switch (otg->state) {
1735 case OTG_STATE_B_IDLE:
1736 case OTG_STATE_A_HOST:
1737 set_bit(ID, &motg->inputs);
1738 set_bit(B_SESS_VLD, &motg->inputs);
1739 break;
1740 default:
1741 goto out;
1742 }
1743 break;
1744 case USB_HOST:
1745 switch (otg->state) {
1746 case OTG_STATE_B_IDLE:
1747 case OTG_STATE_B_PERIPHERAL:
1748 clear_bit(ID, &motg->inputs);
1749 break;
1750 default:
1751 goto out;
1752 }
1753 break;
1754 default:
1755 goto out;
1756 }
1757
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301758 pm_runtime_resume(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301759 schedule_work(&motg->sm_work);
1760out:
1761 return status;
1762}
1763
1764const struct file_operations msm_otg_mode_fops = {
1765 .open = msm_otg_mode_open,
1766 .read = seq_read,
1767 .write = msm_otg_mode_write,
1768 .llseek = seq_lseek,
1769 .release = single_release,
1770};
1771
Anji jonnalad270e2d2011-08-09 11:28:32 +05301772static int msm_otg_show_chg_type(struct seq_file *s, void *unused)
1773{
1774 struct msm_otg *motg = s->private;
1775
1776 seq_printf(s, chg_to_string(motg->chg_type));
1777 return 0;
1778}
1779
1780static int msm_otg_chg_open(struct inode *inode, struct file *file)
1781{
1782 return single_open(file, msm_otg_show_chg_type, inode->i_private);
1783}
1784
1785const struct file_operations msm_otg_chg_fops = {
1786 .open = msm_otg_chg_open,
1787 .read = seq_read,
1788 .llseek = seq_lseek,
1789 .release = single_release,
1790};
1791
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301792static struct dentry *msm_otg_dbg_root;
1793static struct dentry *msm_otg_dbg_mode;
Anji jonnalad270e2d2011-08-09 11:28:32 +05301794static struct dentry *msm_otg_chg_type;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301795
1796static int msm_otg_debugfs_init(struct msm_otg *motg)
1797{
Anji jonnalad270e2d2011-08-09 11:28:32 +05301798
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301799 msm_otg_dbg_root = debugfs_create_dir("msm_otg", NULL);
1800
1801 if (!msm_otg_dbg_root || IS_ERR(msm_otg_dbg_root))
1802 return -ENODEV;
1803
Anji jonnalad270e2d2011-08-09 11:28:32 +05301804 if (motg->pdata->mode == USB_OTG &&
1805 motg->pdata->otg_control == OTG_USER_CONTROL) {
1806
1807 msm_otg_dbg_mode = debugfs_create_file("mode", S_IRUGO |
1808 S_IWUSR, msm_otg_dbg_root, motg,
1809 &msm_otg_mode_fops);
1810
1811 if (!msm_otg_dbg_mode) {
1812 debugfs_remove(msm_otg_dbg_root);
1813 msm_otg_dbg_root = NULL;
1814 return -ENODEV;
1815 }
1816 }
1817
1818 msm_otg_chg_type = debugfs_create_file("chg_type", S_IRUGO,
1819 msm_otg_dbg_root, motg,
1820 &msm_otg_chg_fops);
1821
1822 if (!msm_otg_chg_type) {
1823 debugfs_remove(msm_otg_dbg_mode);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301824 debugfs_remove(msm_otg_dbg_root);
1825 msm_otg_dbg_root = NULL;
Anji jonnalad270e2d2011-08-09 11:28:32 +05301826 msm_otg_dbg_mode = NULL;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301827 return -ENODEV;
1828 }
1829
1830 return 0;
1831}
1832
1833static void msm_otg_debugfs_cleanup(void)
1834{
Anji jonnalad270e2d2011-08-09 11:28:32 +05301835 debugfs_remove_recursive(msm_otg_dbg_root);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301836}
1837
1838static int __init msm_otg_probe(struct platform_device *pdev)
1839{
1840 int ret = 0;
1841 struct resource *res;
1842 struct msm_otg *motg;
1843 struct otg_transceiver *otg;
1844
1845 dev_info(&pdev->dev, "msm_otg probe\n");
1846 if (!pdev->dev.platform_data) {
1847 dev_err(&pdev->dev, "No platform data given. Bailing out\n");
1848 return -ENODEV;
1849 }
1850
1851 motg = kzalloc(sizeof(struct msm_otg), GFP_KERNEL);
1852 if (!motg) {
1853 dev_err(&pdev->dev, "unable to allocate msm_otg\n");
1854 return -ENOMEM;
1855 }
1856
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001857 the_msm_otg = motg;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301858 motg->pdata = pdev->dev.platform_data;
1859 otg = &motg->otg;
1860 otg->dev = &pdev->dev;
1861
Amit Blay02eff132011-09-21 16:46:24 +03001862 /* Some targets don't support PHY clock. */
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301863 motg->phy_reset_clk = clk_get(&pdev->dev, "usb_phy_clk");
Amit Blay02eff132011-09-21 16:46:24 +03001864 if (IS_ERR(motg->phy_reset_clk))
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301865 dev_err(&pdev->dev, "failed to get usb_phy_clk\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301866
1867 motg->clk = clk_get(&pdev->dev, "usb_hs_clk");
1868 if (IS_ERR(motg->clk)) {
1869 dev_err(&pdev->dev, "failed to get usb_hs_clk\n");
1870 ret = PTR_ERR(motg->clk);
1871 goto put_phy_reset_clk;
1872 }
Anji jonnala0f73cac2011-05-04 10:19:46 +05301873 clk_set_rate(motg->clk, 60000000);
1874
1875 /*
1876 * If USB Core is running its protocol engine based on CORE CLK,
1877 * CORE CLK must be running at >55Mhz for correct HSUSB
1878 * operation and USB core cannot tolerate frequency changes on
1879 * CORE CLK. For such USB cores, vote for maximum clk frequency
1880 * on pclk source
1881 */
1882 if (motg->pdata->pclk_src_name) {
1883 motg->pclk_src = clk_get(&pdev->dev,
1884 motg->pdata->pclk_src_name);
1885 if (IS_ERR(motg->pclk_src))
1886 goto put_clk;
1887 clk_set_rate(motg->pclk_src, INT_MAX);
1888 clk_enable(motg->pclk_src);
1889 } else
1890 motg->pclk_src = ERR_PTR(-ENOENT);
1891
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301892 motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk");
1893 if (IS_ERR(motg->pclk)) {
1894 dev_err(&pdev->dev, "failed to get usb_hs_pclk\n");
1895 ret = PTR_ERR(motg->pclk);
Anji jonnala0f73cac2011-05-04 10:19:46 +05301896 goto put_pclk_src;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301897 }
1898
Amit Blay02eff132011-09-21 16:46:24 +03001899 motg->system_clk = clk_get(&pdev->dev, "usb_hs_system_clk");
1900 if (!IS_ERR(motg->system_clk))
1901 clk_enable(motg->system_clk);
1902
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301903 /*
1904 * USB core clock is not present on all MSM chips. This
1905 * clock is introduced to remove the dependency on AXI
1906 * bus frequency.
1907 */
1908 motg->core_clk = clk_get(&pdev->dev, "usb_hs_core_clk");
1909 if (IS_ERR(motg->core_clk))
1910 motg->core_clk = NULL;
1911
1912 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1913 if (!res) {
1914 dev_err(&pdev->dev, "failed to get platform resource mem\n");
1915 ret = -ENODEV;
1916 goto put_core_clk;
1917 }
1918
1919 motg->regs = ioremap(res->start, resource_size(res));
1920 if (!motg->regs) {
1921 dev_err(&pdev->dev, "ioremap failed\n");
1922 ret = -ENOMEM;
1923 goto put_core_clk;
1924 }
1925 dev_info(&pdev->dev, "OTG regs = %p\n", motg->regs);
1926
1927 motg->irq = platform_get_irq(pdev, 0);
1928 if (!motg->irq) {
1929 dev_err(&pdev->dev, "platform_get_irq failed\n");
1930 ret = -ENODEV;
1931 goto free_regs;
1932 }
1933
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301934 clk_enable(motg->pclk);
Anji jonnala11aa5c42011-05-04 10:19:48 +05301935
1936 ret = msm_hsusb_init_vddcx(motg, 1);
1937 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001938 dev_err(&pdev->dev, "hsusb vddcx init failed\n");
Anji jonnala11aa5c42011-05-04 10:19:48 +05301939 goto free_regs;
1940 }
1941
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001942 ret = msm_hsusb_config_vddcx(1);
1943 if (ret) {
1944 dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
1945 goto free_init_vddcx;
1946 }
1947
Anji jonnala11aa5c42011-05-04 10:19:48 +05301948 ret = msm_hsusb_ldo_init(motg, 1);
1949 if (ret) {
1950 dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001951 goto free_init_vddcx;
Anji jonnala11aa5c42011-05-04 10:19:48 +05301952 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001953
1954 ret = msm_hsusb_ldo_enable(motg, 1);
Anji jonnala11aa5c42011-05-04 10:19:48 +05301955 if (ret) {
1956 dev_err(&pdev->dev, "hsusb vreg enable failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001957 goto free_ldo_init;
Anji jonnala11aa5c42011-05-04 10:19:48 +05301958 }
1959
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301960 if (motg->core_clk)
1961 clk_enable(motg->core_clk);
1962
1963 writel(0, USB_USBINTR);
1964 writel(0, USB_OTGSC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001965 /* Ensure that above STOREs are completed before enabling interrupts */
1966 mb();
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301967
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001968 wake_lock_init(&motg->wlock, WAKE_LOCK_SUSPEND, "msm_otg");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301969 INIT_WORK(&motg->sm_work, msm_otg_sm_work);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301970 INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301971 ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
1972 "msm_otg", motg);
1973 if (ret) {
1974 dev_err(&pdev->dev, "request irq failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001975 goto destroy_wlock;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301976 }
1977
1978 otg->init = msm_otg_reset;
1979 otg->set_host = msm_otg_set_host;
1980 otg->set_peripheral = msm_otg_set_peripheral;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301981 otg->set_power = msm_otg_set_power;
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05301982 otg->set_suspend = msm_otg_set_suspend;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301983
1984 otg->io_ops = &msm_otg_io_ops;
1985
1986 ret = otg_set_transceiver(&motg->otg);
1987 if (ret) {
1988 dev_err(&pdev->dev, "otg_set_transceiver failed\n");
1989 goto free_irq;
1990 }
1991
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001992 if (motg->pdata->otg_control == OTG_PMIC_CONTROL) {
1993 if (motg->pdata->pmic_id_irq) {
1994 ret = request_irq(motg->pdata->pmic_id_irq,
1995 msm_pmic_id_irq,
1996 IRQF_TRIGGER_RISING |
1997 IRQF_TRIGGER_FALLING,
1998 "msm_otg", motg);
1999 if (ret) {
2000 dev_err(&pdev->dev, "request irq failed for PMIC ID\n");
2001 goto remove_otg;
2002 }
2003 } else {
2004 ret = -ENODEV;
2005 dev_err(&pdev->dev, "PMIC IRQ for ID notifications doesn't exist\n");
2006 goto remove_otg;
2007 }
2008 }
2009
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +05302010 msm_hsusb_mhl_switch_enable(motg, 1);
2011
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302012 platform_set_drvdata(pdev, motg);
2013 device_init_wakeup(&pdev->dev, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002014 motg->mA_port = IUNIT;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302015
Anji jonnalad270e2d2011-08-09 11:28:32 +05302016 ret = msm_otg_debugfs_init(motg);
2017 if (ret)
2018 dev_dbg(&pdev->dev, "mode debugfs file is"
2019 "not available\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302020
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002021 if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
2022 pm8921_charger_register_vbus_sn(&msm_otg_set_vbus_state);
2023
2024 if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
2025 motg->pdata->otg_control == OTG_PMIC_CONTROL &&
2026 motg->pdata->pmic_id_irq)
2027 motg->caps = ALLOW_PHY_POWER_COLLAPSE |
2028 ALLOW_PHY_RETENTION |
2029 ALLOW_PHY_COMP_DISABLE;
2030
2031 wake_lock(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302032 pm_runtime_set_active(&pdev->dev);
2033 pm_runtime_enable(&pdev->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302034
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302035 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002036
2037remove_otg:
2038 otg_set_transceiver(NULL);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302039free_irq:
2040 free_irq(motg->irq, motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002041destroy_wlock:
2042 wake_lock_destroy(&motg->wlock);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302043 clk_disable(motg->pclk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002044 msm_hsusb_ldo_enable(motg, 0);
2045free_ldo_init:
Anji jonnala11aa5c42011-05-04 10:19:48 +05302046 msm_hsusb_ldo_init(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002047free_init_vddcx:
Anji jonnala11aa5c42011-05-04 10:19:48 +05302048 msm_hsusb_init_vddcx(motg, 0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302049free_regs:
2050 iounmap(motg->regs);
2051put_core_clk:
2052 if (motg->core_clk)
2053 clk_put(motg->core_clk);
Amit Blay02eff132011-09-21 16:46:24 +03002054
2055 if (!IS_ERR(motg->system_clk)) {
2056 clk_disable(motg->system_clk);
2057 clk_put(motg->system_clk);
2058 }
Anji jonnala0f73cac2011-05-04 10:19:46 +05302059put_pclk_src:
2060 if (!IS_ERR(motg->pclk_src)) {
2061 clk_disable(motg->pclk_src);
2062 clk_put(motg->pclk_src);
2063 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302064put_clk:
2065 clk_put(motg->clk);
2066put_phy_reset_clk:
Amit Blay02eff132011-09-21 16:46:24 +03002067 if (!IS_ERR(motg->phy_reset_clk))
2068 clk_put(motg->phy_reset_clk);
2069
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302070 kfree(motg);
2071 return ret;
2072}
2073
2074static int __devexit msm_otg_remove(struct platform_device *pdev)
2075{
2076 struct msm_otg *motg = platform_get_drvdata(pdev);
2077 struct otg_transceiver *otg = &motg->otg;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302078 int cnt = 0;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302079
2080 if (otg->host || otg->gadget)
2081 return -EBUSY;
2082
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002083 if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
2084 pm8921_charger_unregister_vbus_sn(0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302085 msm_otg_debugfs_cleanup();
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302086 cancel_delayed_work_sync(&motg->chg_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302087 cancel_work_sync(&motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302088
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302089 pm_runtime_resume(&pdev->dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302090
2091 device_init_wakeup(&pdev->dev, 0);
2092 pm_runtime_disable(&pdev->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002093 wake_lock_destroy(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302094
Vijayavardhan Vennapusafc464f02011-11-04 21:54:00 +05302095 msm_hsusb_mhl_switch_enable(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002096 if (motg->pdata->pmic_id_irq)
2097 free_irq(motg->pdata->pmic_id_irq, motg);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302098 otg_set_transceiver(NULL);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302099 free_irq(motg->irq, motg);
2100
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302101 /*
2102 * Put PHY in low power mode.
2103 */
2104 ulpi_read(otg, 0x14);
2105 ulpi_write(otg, 0x08, 0x09);
2106
2107 writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
2108 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
2109 if (readl(USB_PORTSC) & PORTSC_PHCD)
2110 break;
2111 udelay(1);
2112 cnt++;
2113 }
2114 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC)
2115 dev_err(otg->dev, "Unable to suspend PHY\n");
2116
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302117 clk_disable(motg->pclk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302118 if (motg->core_clk)
2119 clk_disable(motg->core_clk);
Amit Blay137575f2011-11-06 15:20:54 +02002120 if (!IS_ERR(motg->system_clk))
2121 clk_disable(motg->system_clk);
Anji jonnala0f73cac2011-05-04 10:19:46 +05302122 if (!IS_ERR(motg->pclk_src)) {
2123 clk_disable(motg->pclk_src);
2124 clk_put(motg->pclk_src);
2125 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002126 msm_hsusb_ldo_enable(motg, 0);
Anji jonnala11aa5c42011-05-04 10:19:48 +05302127 msm_hsusb_ldo_init(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002128 msm_hsusb_init_vddcx(motg, 0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302129
2130 iounmap(motg->regs);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302131 pm_runtime_set_suspended(&pdev->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302132
Amit Blay02eff132011-09-21 16:46:24 +03002133 if (!IS_ERR(motg->phy_reset_clk))
2134 clk_put(motg->phy_reset_clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302135 clk_put(motg->pclk);
2136 clk_put(motg->clk);
2137 if (motg->core_clk)
2138 clk_put(motg->core_clk);
Amit Blay02eff132011-09-21 16:46:24 +03002139 if (!IS_ERR(motg->system_clk))
2140 clk_put(motg->system_clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302141
2142 kfree(motg);
2143
2144 return 0;
2145}
2146
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302147#ifdef CONFIG_PM_RUNTIME
2148static int msm_otg_runtime_idle(struct device *dev)
2149{
2150 struct msm_otg *motg = dev_get_drvdata(dev);
2151 struct otg_transceiver *otg = &motg->otg;
2152
2153 dev_dbg(dev, "OTG runtime idle\n");
2154
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302155 if (otg->state == OTG_STATE_UNDEFINED)
2156 return -EAGAIN;
2157 else
2158 return 0;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302159}
2160
2161static int msm_otg_runtime_suspend(struct device *dev)
2162{
2163 struct msm_otg *motg = dev_get_drvdata(dev);
2164
2165 dev_dbg(dev, "OTG runtime suspend\n");
2166 return msm_otg_suspend(motg);
2167}
2168
2169static int msm_otg_runtime_resume(struct device *dev)
2170{
2171 struct msm_otg *motg = dev_get_drvdata(dev);
2172
2173 dev_dbg(dev, "OTG runtime resume\n");
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302174 pm_runtime_get_noresume(dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302175 return msm_otg_resume(motg);
2176}
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302177#endif
2178
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302179#ifdef CONFIG_PM_SLEEP
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302180static int msm_otg_pm_suspend(struct device *dev)
2181{
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302182 int ret;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302183
2184 dev_dbg(dev, "OTG PM suspend\n");
Pavankumar Kondeti8be99cf2011-08-04 10:48:08 +05302185
2186#ifdef CONFIG_PM_RUNTIME
2187 ret = pm_runtime_suspend(dev);
2188 if (ret > 0)
2189 ret = 0;
2190#else
2191 ret = msm_otg_suspend(dev_get_drvdata(dev));
2192#endif
2193 return ret;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302194}
2195
2196static int msm_otg_pm_resume(struct device *dev)
2197{
2198 struct msm_otg *motg = dev_get_drvdata(dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302199
2200 dev_dbg(dev, "OTG PM resume\n");
2201
Manu Gautamf284c052011-09-08 16:52:48 +05302202#ifdef CONFIG_PM_RUNTIME
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302203 /*
Manu Gautamf284c052011-09-08 16:52:48 +05302204 * Do not resume hardware as part of system resume,
2205 * rather, wait for the ASYNC INT from the h/w
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302206 */
Gregory Beanebd8ca22011-10-11 12:02:35 -07002207 return 0;
Manu Gautamf284c052011-09-08 16:52:48 +05302208#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302209
Manu Gautamf284c052011-09-08 16:52:48 +05302210 return msm_otg_resume(motg);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302211}
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302212#endif
2213
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302214#ifdef CONFIG_PM
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302215static const struct dev_pm_ops msm_otg_dev_pm_ops = {
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302216 SET_SYSTEM_SLEEP_PM_OPS(msm_otg_pm_suspend, msm_otg_pm_resume)
2217 SET_RUNTIME_PM_OPS(msm_otg_runtime_suspend, msm_otg_runtime_resume,
2218 msm_otg_runtime_idle)
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302219};
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302220#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302221
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302222static struct platform_driver msm_otg_driver = {
2223 .remove = __devexit_p(msm_otg_remove),
2224 .driver = {
2225 .name = DRIVER_NAME,
2226 .owner = THIS_MODULE,
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302227#ifdef CONFIG_PM
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302228 .pm = &msm_otg_dev_pm_ops,
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302229#endif
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302230 },
2231};
2232
2233static int __init msm_otg_init(void)
2234{
2235 return platform_driver_probe(&msm_otg_driver, msm_otg_probe);
2236}
2237
2238static void __exit msm_otg_exit(void)
2239{
2240 platform_driver_unregister(&msm_otg_driver);
2241}
2242
2243module_init(msm_otg_init);
2244module_exit(msm_otg_exit);
2245
2246MODULE_LICENSE("GPL v2");
2247MODULE_DESCRIPTION("MSM USB transceiver driver");