blob: b093015df233ca609b5caaea439ad8af0700d155 [file] [log] [blame]
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +053012 */
13
14#include <linux/module.h>
15#include <linux/device.h>
16#include <linux/platform_device.h>
17#include <linux/clk.h>
18#include <linux/slab.h>
19#include <linux/interrupt.h>
20#include <linux/err.h>
21#include <linux/delay.h>
22#include <linux/io.h>
23#include <linux/ioport.h>
24#include <linux/uaccess.h>
25#include <linux/debugfs.h>
26#include <linux/seq_file.h>
Pavankumar Kondeti87c01042010-12-07 17:53:58 +053027#include <linux/pm_runtime.h>
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +053028
29#include <linux/usb.h>
30#include <linux/usb/otg.h>
31#include <linux/usb/ulpi.h>
32#include <linux/usb/gadget.h>
33#include <linux/usb/hcd.h>
34#include <linux/usb/msm_hsusb.h>
35#include <linux/usb/msm_hsusb_hw.h>
Anji jonnala11aa5c42011-05-04 10:19:48 +053036#include <linux/regulator/consumer.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070037#include <linux/mfd/pm8xxx/pm8921-charger.h>
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +053038
39#include <mach/clk.h>
40
41#define MSM_USB_BASE (motg->regs)
42#define DRIVER_NAME "msm_otg"
43
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070044#ifdef CONFIG_USB_MSM_ACA
45static void msm_chg_enable_aca_det(struct msm_otg *motg);
46static void msm_chg_enable_aca_intr(struct msm_otg *motg);
47#else
48static inline bool msm_chg_aca_detect(struct msm_otg *motg)
49{
50 return false;
51}
52
53static inline void msm_chg_enable_aca_det(struct msm_otg *motg)
54{
55}
56static inline void msm_chg_enable_aca_intr(struct msm_otg *motg)
57{
58}
59static inline bool msm_chg_check_aca_intr(struct msm_otg *motg)
60{
61 return false;
62}
63#endif
64
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +053065#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
Anji jonnala11aa5c42011-05-04 10:19:48 +053066
67#define USB_PHY_3P3_VOL_MIN 3050000 /* uV */
68#define USB_PHY_3P3_VOL_MAX 3300000 /* uV */
69#define USB_PHY_3P3_HPM_LOAD 50000 /* uA */
70#define USB_PHY_3P3_LPM_LOAD 4000 /* uA */
71
72#define USB_PHY_1P8_VOL_MIN 1800000 /* uV */
73#define USB_PHY_1P8_VOL_MAX 1800000 /* uV */
74#define USB_PHY_1P8_HPM_LOAD 50000 /* uA */
75#define USB_PHY_1P8_LPM_LOAD 4000 /* uA */
76
77#define USB_PHY_VDD_DIG_VOL_MIN 1000000 /* uV */
78#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
79
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070080static struct msm_otg *the_msm_otg;
81
Anji jonnala11aa5c42011-05-04 10:19:48 +053082static struct regulator *hsusb_3p3;
83static struct regulator *hsusb_1p8;
84static struct regulator *hsusb_vddcx;
85
86static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init)
87{
88 int ret = 0;
89
90 if (init) {
91 hsusb_vddcx = regulator_get(motg->otg.dev, "HSUSB_VDDCX");
92 if (IS_ERR(hsusb_vddcx)) {
93 dev_err(motg->otg.dev, "unable to get hsusb vddcx\n");
94 return PTR_ERR(hsusb_vddcx);
95 }
96
97 ret = regulator_set_voltage(hsusb_vddcx,
98 USB_PHY_VDD_DIG_VOL_MIN,
99 USB_PHY_VDD_DIG_VOL_MAX);
100 if (ret) {
101 dev_err(motg->otg.dev, "unable to set the voltage "
102 "for hsusb vddcx\n");
103 regulator_put(hsusb_vddcx);
104 return ret;
105 }
106
107 ret = regulator_enable(hsusb_vddcx);
108 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700109 regulator_set_voltage(hsusb_vddcx, 0,
110 USB_PHY_VDD_DIG_VOL_MIN);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530111 regulator_put(hsusb_vddcx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700112 dev_err(motg->otg.dev, "unable to enable the hsusb vddcx\n");
113 return ret;
Anji jonnala11aa5c42011-05-04 10:19:48 +0530114 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700115
Anji jonnala11aa5c42011-05-04 10:19:48 +0530116 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700117
Anji jonnala11aa5c42011-05-04 10:19:48 +0530118 ret = regulator_disable(hsusb_vddcx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700119 if (ret) {
Anji jonnala11aa5c42011-05-04 10:19:48 +0530120 dev_err(motg->otg.dev, "unable to disable hsusb vddcx\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700121 return ret;
122 }
123
124 ret = regulator_set_voltage(hsusb_vddcx, 0,
125 USB_PHY_VDD_DIG_VOL_MIN);
126 if (ret) {
127 dev_err(motg->otg.dev, "unable to set the voltage"
128 "for hsusb vddcx\n");
129 return ret;
130 }
Anji jonnala11aa5c42011-05-04 10:19:48 +0530131
132 regulator_put(hsusb_vddcx);
133 }
134
135 return ret;
136}
137
138static int msm_hsusb_ldo_init(struct msm_otg *motg, int init)
139{
140 int rc = 0;
141
142 if (init) {
143 hsusb_3p3 = regulator_get(motg->otg.dev, "HSUSB_3p3");
144 if (IS_ERR(hsusb_3p3)) {
145 dev_err(motg->otg.dev, "unable to get hsusb 3p3\n");
146 return PTR_ERR(hsusb_3p3);
147 }
148
149 rc = regulator_set_voltage(hsusb_3p3, USB_PHY_3P3_VOL_MIN,
150 USB_PHY_3P3_VOL_MAX);
151 if (rc) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700152 dev_err(motg->otg.dev, "unable to set voltage level for"
153 "hsusb 3p3\n");
Anji jonnala11aa5c42011-05-04 10:19:48 +0530154 goto put_3p3;
155 }
156 hsusb_1p8 = regulator_get(motg->otg.dev, "HSUSB_1p8");
157 if (IS_ERR(hsusb_1p8)) {
158 dev_err(motg->otg.dev, "unable to get hsusb 1p8\n");
159 rc = PTR_ERR(hsusb_1p8);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700160 goto put_3p3_lpm;
Anji jonnala11aa5c42011-05-04 10:19:48 +0530161 }
162 rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN,
163 USB_PHY_1P8_VOL_MAX);
164 if (rc) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700165 dev_err(motg->otg.dev, "unable to set voltage level for"
166 "hsusb 1p8\n");
Anji jonnala11aa5c42011-05-04 10:19:48 +0530167 goto put_1p8;
168 }
169
170 return 0;
171 }
172
Anji jonnala11aa5c42011-05-04 10:19:48 +0530173put_1p8:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700174 regulator_set_voltage(hsusb_1p8, 0, USB_PHY_1P8_VOL_MAX);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530175 regulator_put(hsusb_1p8);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700176put_3p3_lpm:
177 regulator_set_voltage(hsusb_3p3, 0, USB_PHY_3P3_VOL_MAX);
Anji jonnala11aa5c42011-05-04 10:19:48 +0530178put_3p3:
179 regulator_put(hsusb_3p3);
180 return rc;
181}
182
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530183#ifdef CONFIG_PM_SLEEP
184#define USB_PHY_SUSP_DIG_VOL 500000
185static int msm_hsusb_config_vddcx(int high)
186{
187 int max_vol = USB_PHY_VDD_DIG_VOL_MAX;
188 int min_vol;
189 int ret;
190
191 if (high)
192 min_vol = USB_PHY_VDD_DIG_VOL_MIN;
193 else
194 min_vol = USB_PHY_SUSP_DIG_VOL;
195
196 ret = regulator_set_voltage(hsusb_vddcx, min_vol, max_vol);
197 if (ret) {
198 pr_err("%s: unable to set the voltage for regulator "
199 "HSUSB_VDDCX\n", __func__);
200 return ret;
201 }
202
203 pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol);
204
205 return ret;
206}
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
218 if (!hsusb_1p8 || IS_ERR(hsusb_1p8)) {
219 pr_err("%s: HSUSB_1p8 is not initialized\n", __func__);
220 return -ENODEV;
221 }
222
223 if (!hsusb_3p3 || IS_ERR(hsusb_3p3)) {
224 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
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530294static int ulpi_read(struct otg_transceiver *otg, u32 reg)
295{
296 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
297 int cnt = 0;
298
299 /* initiate read operation */
300 writel(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
301 USB_ULPI_VIEWPORT);
302
303 /* wait for completion */
304 while (cnt < ULPI_IO_TIMEOUT_USEC) {
305 if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN))
306 break;
307 udelay(1);
308 cnt++;
309 }
310
311 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
312 dev_err(otg->dev, "ulpi_read: timeout %08x\n",
313 readl(USB_ULPI_VIEWPORT));
314 return -ETIMEDOUT;
315 }
316 return ULPI_DATA_READ(readl(USB_ULPI_VIEWPORT));
317}
318
319static int ulpi_write(struct otg_transceiver *otg, u32 val, u32 reg)
320{
321 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
322 int cnt = 0;
323
324 /* initiate write operation */
325 writel(ULPI_RUN | ULPI_WRITE |
326 ULPI_ADDR(reg) | ULPI_DATA(val),
327 USB_ULPI_VIEWPORT);
328
329 /* wait for completion */
330 while (cnt < ULPI_IO_TIMEOUT_USEC) {
331 if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN))
332 break;
333 udelay(1);
334 cnt++;
335 }
336
337 if (cnt >= ULPI_IO_TIMEOUT_USEC) {
338 dev_err(otg->dev, "ulpi_write: timeout\n");
339 return -ETIMEDOUT;
340 }
341 return 0;
342}
343
344static struct otg_io_access_ops msm_otg_io_ops = {
345 .read = ulpi_read,
346 .write = ulpi_write,
347};
348
349static void ulpi_init(struct msm_otg *motg)
350{
351 struct msm_otg_platform_data *pdata = motg->pdata;
352 int *seq = pdata->phy_init_seq;
353
354 if (!seq)
355 return;
356
357 while (seq[0] >= 0) {
358 dev_vdbg(motg->otg.dev, "ulpi: write 0x%02x to 0x%02x\n",
359 seq[0], seq[1]);
360 ulpi_write(&motg->otg, seq[0], seq[1]);
361 seq += 2;
362 }
363}
364
365static int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert)
366{
367 int ret;
368
369 if (assert) {
370 ret = clk_reset(motg->clk, CLK_RESET_ASSERT);
371 if (ret)
372 dev_err(motg->otg.dev, "usb hs_clk assert failed\n");
373 } else {
374 ret = clk_reset(motg->clk, CLK_RESET_DEASSERT);
375 if (ret)
376 dev_err(motg->otg.dev, "usb hs_clk deassert failed\n");
377 }
378 return ret;
379}
380
381static int msm_otg_phy_clk_reset(struct msm_otg *motg)
382{
383 int ret;
384
385 ret = clk_reset(motg->phy_reset_clk, CLK_RESET_ASSERT);
386 if (ret) {
387 dev_err(motg->otg.dev, "usb phy clk assert failed\n");
388 return ret;
389 }
390 usleep_range(10000, 12000);
391 ret = clk_reset(motg->phy_reset_clk, CLK_RESET_DEASSERT);
392 if (ret)
393 dev_err(motg->otg.dev, "usb phy clk deassert failed\n");
394 return ret;
395}
396
397static int msm_otg_phy_reset(struct msm_otg *motg)
398{
399 u32 val;
400 int ret;
401 int retries;
402
403 ret = msm_otg_link_clk_reset(motg, 1);
404 if (ret)
405 return ret;
406 ret = msm_otg_phy_clk_reset(motg);
407 if (ret)
408 return ret;
409 ret = msm_otg_link_clk_reset(motg, 0);
410 if (ret)
411 return ret;
412
413 val = readl(USB_PORTSC) & ~PORTSC_PTS_MASK;
414 writel(val | PORTSC_PTS_ULPI, USB_PORTSC);
415
416 for (retries = 3; retries > 0; retries--) {
417 ret = ulpi_write(&motg->otg, ULPI_FUNC_CTRL_SUSPENDM,
418 ULPI_CLR(ULPI_FUNC_CTRL));
419 if (!ret)
420 break;
421 ret = msm_otg_phy_clk_reset(motg);
422 if (ret)
423 return ret;
424 }
425 if (!retries)
426 return -ETIMEDOUT;
427
428 /* This reset calibrates the phy, if the above write succeeded */
429 ret = msm_otg_phy_clk_reset(motg);
430 if (ret)
431 return ret;
432
433 for (retries = 3; retries > 0; retries--) {
434 ret = ulpi_read(&motg->otg, ULPI_DEBUG);
435 if (ret != -ETIMEDOUT)
436 break;
437 ret = msm_otg_phy_clk_reset(motg);
438 if (ret)
439 return ret;
440 }
441 if (!retries)
442 return -ETIMEDOUT;
443
444 dev_info(motg->otg.dev, "phy_reset: success\n");
445 return 0;
446}
447
448#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
449static int msm_otg_reset(struct otg_transceiver *otg)
450{
451 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
452 struct msm_otg_platform_data *pdata = motg->pdata;
453 int cnt = 0;
454 int ret;
455 u32 val = 0;
456 u32 ulpi_val = 0;
457
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700458 clk_enable(motg->clk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530459 ret = msm_otg_phy_reset(motg);
460 if (ret) {
461 dev_err(otg->dev, "phy_reset failed\n");
462 return ret;
463 }
464
465 ulpi_init(motg);
466
467 writel(USBCMD_RESET, USB_USBCMD);
468 while (cnt < LINK_RESET_TIMEOUT_USEC) {
469 if (!(readl(USB_USBCMD) & USBCMD_RESET))
470 break;
471 udelay(1);
472 cnt++;
473 }
474 if (cnt >= LINK_RESET_TIMEOUT_USEC)
475 return -ETIMEDOUT;
476
477 /* select ULPI phy */
478 writel(0x80000000, USB_PORTSC);
479
480 msleep(100);
481
482 writel(0x0, USB_AHBBURST);
483 writel(0x00, USB_AHBMODE);
484
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700485 /* Ensure that RESET operation is completed before turning off clock */
486 mb();
487 clk_disable(motg->clk);
488
489 val = readl_relaxed(USB_OTGSC);
490 if (pdata->mode == USB_OTG) {
491 ulpi_val = ULPI_INT_IDGRD | ULPI_INT_SESS_VALID;
492 val |= OTGSC_IDIE | OTGSC_BSVIE;
493 } else if (pdata->mode == USB_PERIPHERAL) {
494 ulpi_val = ULPI_INT_SESS_VALID;
495 val |= OTGSC_BSVIE;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530496 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700497 writel_relaxed(val, USB_OTGSC);
498 ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_RISE);
499 ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_FALL);
500
501 msm_chg_enable_aca_det(motg);
502 msm_chg_enable_aca_intr(motg);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530503
504 return 0;
505}
506
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530507#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
Pavankumar Kondeti70187732011-02-15 09:42:34 +0530508#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
509
510#ifdef CONFIG_PM_SLEEP
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530511static int msm_otg_suspend(struct msm_otg *motg)
512{
513 struct otg_transceiver *otg = &motg->otg;
514 struct usb_bus *bus = otg->host;
515 struct msm_otg_platform_data *pdata = motg->pdata;
516 int cnt = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700517 bool session_active;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530518
519 if (atomic_read(&motg->in_lpm))
520 return 0;
521
522 disable_irq(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700523 session_active = (otg->host && !test_bit(ID, &motg->inputs)) ||
524 test_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530525 /*
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530526 * Chipidea 45-nm PHY suspend sequence:
527 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530528 * Interrupt Latch Register auto-clear feature is not present
529 * in all PHY versions. Latch register is clear on read type.
530 * Clear latch register to avoid spurious wakeup from
531 * low power mode (LPM).
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530532 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530533 * PHY comparators are disabled when PHY enters into low power
534 * mode (LPM). Keep PHY comparators ON in LPM only when we expect
535 * VBUS/Id notifications from USB PHY. Otherwise turn off USB
536 * PHY comparators. This save significant amount of power.
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530537 *
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530538 * PLL is not turned off when PHY enters into low power mode (LPM).
539 * Disable PLL for maximum power savings.
540 */
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530541
542 if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) {
543 ulpi_read(otg, 0x14);
544 if (pdata->otg_control == OTG_PHY_CONTROL)
545 ulpi_write(otg, 0x01, 0x30);
546 ulpi_write(otg, 0x08, 0x09);
547 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530548
549 /*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700550 * Turn off the OTG comparators, if depends on PMIC for
551 * VBUS and ID notifications.
552 */
553 if ((motg->caps & ALLOW_PHY_COMP_DISABLE) && !session_active) {
554 ulpi_write(otg, OTG_COMP_DISABLE,
555 ULPI_SET(ULPI_PWR_CLK_MNG_REG));
556 motg->lpm_flags |= PHY_OTG_COMP_DISABLED;
557 }
558
559 /*
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530560 * PHY may take some time or even fail to enter into low power
561 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
562 * in failure case.
563 */
564 writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
565 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
566 if (readl(USB_PORTSC) & PORTSC_PHCD)
567 break;
568 udelay(1);
569 cnt++;
570 }
571
572 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) {
573 dev_err(otg->dev, "Unable to suspend PHY\n");
574 msm_otg_reset(otg);
575 enable_irq(motg->irq);
576 return -ETIMEDOUT;
577 }
578
579 /*
580 * PHY has capability to generate interrupt asynchronously in low
581 * power mode (LPM). This interrupt is level triggered. So USB IRQ
582 * line must be disabled till async interrupt enable bit is cleared
583 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
584 * block data communication from PHY.
585 */
586 writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);
587
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700588 if (motg->caps & ALLOW_PHY_RETENTION && !session_active) {
589 writel_relaxed(readl_relaxed(USB_PHY_CTRL) & ~PHY_RETEN,
590 USB_PHY_CTRL);
591 motg->lpm_flags |= PHY_RETENTIONED;
592 }
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530593
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700594 /* Ensure that above operation is completed before turning off clocks */
595 mb();
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530596 clk_disable(motg->pclk);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530597 if (motg->core_clk)
598 clk_disable(motg->core_clk);
599
Anji jonnala0f73cac2011-05-04 10:19:46 +0530600 if (!IS_ERR(motg->pclk_src))
601 clk_disable(motg->pclk_src);
602
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700603 if (motg->caps & ALLOW_PHY_POWER_COLLAPSE && !session_active) {
604 msm_hsusb_ldo_enable(motg, 0);
605 motg->lpm_flags |= PHY_PWR_COLLAPSED;
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530606 }
607
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700608 if (motg->lpm_flags & PHY_RETENTIONED)
609 msm_hsusb_config_vddcx(0);
610
611 if (device_may_wakeup(otg->dev)) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530612 enable_irq_wake(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700613 if (motg->pdata->pmic_id_irq)
614 enable_irq_wake(motg->pdata->pmic_id_irq);
615 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530616 if (bus)
617 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
618
619 atomic_set(&motg->in_lpm, 1);
620 enable_irq(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700621 wake_unlock(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530622
623 dev_info(otg->dev, "USB in low power mode\n");
624
625 return 0;
626}
627
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530628static int msm_otg_resume(struct msm_otg *motg)
629{
630 struct otg_transceiver *otg = &motg->otg;
631 struct usb_bus *bus = otg->host;
632 int cnt = 0;
633 unsigned temp;
634
635 if (!atomic_read(&motg->in_lpm))
636 return 0;
637
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700638 wake_lock(&motg->wlock);
Anji jonnala0f73cac2011-05-04 10:19:46 +0530639 if (!IS_ERR(motg->pclk_src))
640 clk_enable(motg->pclk_src);
641
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530642 clk_enable(motg->pclk);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530643 if (motg->core_clk)
644 clk_enable(motg->core_clk);
645
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700646 if (motg->lpm_flags & PHY_PWR_COLLAPSED) {
647 msm_hsusb_ldo_enable(motg, 1);
648 motg->lpm_flags &= ~PHY_PWR_COLLAPSED;
649 }
650
651 if (motg->lpm_flags & PHY_RETENTIONED) {
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530652 msm_hsusb_config_vddcx(1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700653 writel_relaxed(readl_relaxed(USB_PHY_CTRL) | PHY_RETEN,
654 USB_PHY_CTRL);
655 motg->lpm_flags &= ~PHY_RETENTIONED;
Pavankumar Kondeti04aebcb2011-05-04 10:19:49 +0530656 }
657
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530658 temp = readl(USB_USBCMD);
659 temp &= ~ASYNC_INTR_CTRL;
660 temp &= ~ULPI_STP_CTRL;
661 writel(temp, USB_USBCMD);
662
663 /*
664 * PHY comes out of low power mode (LPM) in case of wakeup
665 * from asynchronous interrupt.
666 */
667 if (!(readl(USB_PORTSC) & PORTSC_PHCD))
668 goto skip_phy_resume;
669
670 writel(readl(USB_PORTSC) & ~PORTSC_PHCD, USB_PORTSC);
671 while (cnt < PHY_RESUME_TIMEOUT_USEC) {
672 if (!(readl(USB_PORTSC) & PORTSC_PHCD))
673 break;
674 udelay(1);
675 cnt++;
676 }
677
678 if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
679 /*
680 * This is a fatal error. Reset the link and
681 * PHY. USB state can not be restored. Re-insertion
682 * of USB cable is the only way to get USB working.
683 */
684 dev_err(otg->dev, "Unable to resume USB."
685 "Re-plugin the cable\n");
686 msm_otg_reset(otg);
687 }
688
689skip_phy_resume:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700690 /* Turn on the OTG comparators on resume */
691 if (motg->lpm_flags & PHY_OTG_COMP_DISABLED) {
692 ulpi_write(otg, OTG_COMP_DISABLE,
693 ULPI_CLR(ULPI_PWR_CLK_MNG_REG));
694 motg->lpm_flags &= ~PHY_OTG_COMP_DISABLED;
695 }
696 if (device_may_wakeup(otg->dev)) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530697 disable_irq_wake(motg->irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700698 if (motg->pdata->pmic_id_irq)
699 disable_irq_wake(motg->pdata->pmic_id_irq);
700 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530701 if (bus)
702 set_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
703
Pavankumar Kondeti2ce2c3a2011-05-02 11:56:33 +0530704 atomic_set(&motg->in_lpm, 0);
705
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530706 if (motg->async_int) {
707 motg->async_int = 0;
708 pm_runtime_put(otg->dev);
709 enable_irq(motg->irq);
710 }
711
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530712 dev_info(otg->dev, "USB exited from low power mode\n");
713
714 return 0;
715}
Pavankumar Kondeti70187732011-02-15 09:42:34 +0530716#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530717
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530718static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA)
719{
720 if (motg->cur_power == mA)
721 return;
722
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530723 dev_info(motg->otg.dev, "Avail curr from USB = %u\n", mA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700724 pm8921_charger_vbus_draw(mA);
Pavankumar Kondetid8608522011-05-04 10:19:47 +0530725 motg->cur_power = mA;
726}
727
728static int msm_otg_set_power(struct otg_transceiver *otg, unsigned mA)
729{
730 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
731
732 /*
733 * Gadget driver uses set_power method to notify about the
734 * available current based on suspend/configured states.
735 *
736 * IDEV_CHG can be drawn irrespective of suspend/un-configured
737 * states when CDP/ACA is connected.
738 */
739 if (motg->chg_type == USB_SDP_CHARGER)
740 msm_otg_notify_charger(motg, mA);
741
742 return 0;
743}
744
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530745static void msm_otg_start_host(struct otg_transceiver *otg, int on)
746{
747 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
748 struct msm_otg_platform_data *pdata = motg->pdata;
749 struct usb_hcd *hcd;
750
751 if (!otg->host)
752 return;
753
754 hcd = bus_to_hcd(otg->host);
755
756 if (on) {
757 dev_dbg(otg->dev, "host on\n");
758
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530759 /*
760 * Some boards have a switch cotrolled by gpio
761 * to enable/disable internal HUB. Enable internal
762 * HUB before kicking the host.
763 */
764 if (pdata->setup_gpio)
765 pdata->setup_gpio(OTG_STATE_A_HOST);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530766 usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530767 } else {
768 dev_dbg(otg->dev, "host off\n");
769
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530770 usb_remove_hcd(hcd);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530771 if (pdata->setup_gpio)
772 pdata->setup_gpio(OTG_STATE_UNDEFINED);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530773 }
774}
775
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700776static int msm_otg_usbdev_notify(struct notifier_block *self,
777 unsigned long action, void *priv)
778{
779 struct msm_otg *motg = container_of(self, struct msm_otg, usbdev_nb);
780 struct usb_device *udev;
781
782 switch (action) {
783 case USB_DEVICE_ADD:
784 case USB_DEVICE_CONFIG:
785 udev = priv;
786 /*
787 * Interested in devices connected directly to the root hub.
788 * ACA dock can supply IDEV_CHG irrespective devices connected
789 * on the accessory port.
790 */
791 if (!udev->parent || udev->parent->parent ||
792 motg->chg_type == USB_ACA_DOCK_CHARGER)
793 break;
794 if (udev->actconfig)
795 motg->mA_port = udev->actconfig->desc.bMaxPower * 2;
796 else
797 motg->mA_port = IUNIT;
798
799 if (test_bit(ID_A, &motg->inputs))
800 msm_otg_notify_charger(motg, IDEV_CHG_MIN -
801 motg->mA_port);
802 break;
803 default:
804 break;
805 }
806 return NOTIFY_OK;
807}
808
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530809static int msm_otg_set_host(struct otg_transceiver *otg, struct usb_bus *host)
810{
811 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
812 struct usb_hcd *hcd;
813
814 /*
815 * Fail host registration if this board can support
816 * only peripheral configuration.
817 */
818 if (motg->pdata->mode == USB_PERIPHERAL) {
819 dev_info(otg->dev, "Host mode is not supported\n");
820 return -ENODEV;
821 }
822
823 if (!host) {
824 if (otg->state == OTG_STATE_A_HOST) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530825 pm_runtime_get_sync(otg->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700826 usb_unregister_notify(&motg->usbdev_nb);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530827 msm_otg_start_host(otg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700828 if (motg->pdata->vbus_power)
829 motg->pdata->vbus_power(0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530830 otg->host = NULL;
831 otg->state = OTG_STATE_UNDEFINED;
832 schedule_work(&motg->sm_work);
833 } else {
834 otg->host = NULL;
835 }
836
837 return 0;
838 }
839
840 hcd = bus_to_hcd(host);
841 hcd->power_budget = motg->pdata->power_budget;
842
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700843 motg->usbdev_nb.notifier_call = msm_otg_usbdev_notify;
844 usb_register_notify(&motg->usbdev_nb);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530845 otg->host = host;
846 dev_dbg(otg->dev, "host driver registered w/ tranceiver\n");
847
848 /*
849 * Kick the state machine work, if peripheral is not supported
850 * or peripheral is already registered with us.
851 */
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530852 if (motg->pdata->mode == USB_HOST || otg->gadget) {
853 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530854 schedule_work(&motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530855 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530856
857 return 0;
858}
859
860static void msm_otg_start_peripheral(struct otg_transceiver *otg, int on)
861{
862 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
863 struct msm_otg_platform_data *pdata = motg->pdata;
864
865 if (!otg->gadget)
866 return;
867
868 if (on) {
869 dev_dbg(otg->dev, "gadget on\n");
870 /*
871 * Some boards have a switch cotrolled by gpio
872 * to enable/disable internal HUB. Disable internal
873 * HUB before kicking the gadget.
874 */
875 if (pdata->setup_gpio)
876 pdata->setup_gpio(OTG_STATE_B_PERIPHERAL);
877 usb_gadget_vbus_connect(otg->gadget);
878 } else {
879 dev_dbg(otg->dev, "gadget off\n");
880 usb_gadget_vbus_disconnect(otg->gadget);
881 if (pdata->setup_gpio)
882 pdata->setup_gpio(OTG_STATE_UNDEFINED);
883 }
884
885}
886
887static int msm_otg_set_peripheral(struct otg_transceiver *otg,
888 struct usb_gadget *gadget)
889{
890 struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
891
892 /*
893 * Fail peripheral registration if this board can support
894 * only host configuration.
895 */
896 if (motg->pdata->mode == USB_HOST) {
897 dev_info(otg->dev, "Peripheral mode is not supported\n");
898 return -ENODEV;
899 }
900
901 if (!gadget) {
902 if (otg->state == OTG_STATE_B_PERIPHERAL) {
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530903 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530904 msm_otg_start_peripheral(otg, 0);
905 otg->gadget = NULL;
906 otg->state = OTG_STATE_UNDEFINED;
907 schedule_work(&motg->sm_work);
908 } else {
909 otg->gadget = NULL;
910 }
911
912 return 0;
913 }
914 otg->gadget = gadget;
915 dev_dbg(otg->dev, "peripheral driver registered w/ tranceiver\n");
916
917 /*
918 * Kick the state machine work, if host is not supported
919 * or host is already registered with us.
920 */
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530921 if (motg->pdata->mode == USB_PERIPHERAL || otg->host) {
922 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530923 schedule_work(&motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +0530924 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +0530925
926 return 0;
927}
928
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700929#ifdef CONFIG_USB_MSM_ACA
930static bool msm_chg_aca_detect(struct msm_otg *motg)
931{
932 struct otg_transceiver *otg = &motg->otg;
933 u32 int_sts;
934 bool ret = false;
935
936 if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY)
937 goto out;
938
939 int_sts = ulpi_read(otg, 0x87);
940 switch (int_sts & 0x1C) {
941 case 0x08:
942 if (!test_and_set_bit(ID_A, &motg->inputs)) {
943 dev_dbg(otg->dev, "ID_A\n");
944 motg->chg_type = USB_ACA_A_CHARGER;
945 motg->chg_state = USB_CHG_STATE_DETECTED;
946 clear_bit(ID_B, &motg->inputs);
947 clear_bit(ID_C, &motg->inputs);
948 ret = true;
949 }
950 break;
951 case 0x0C:
952 if (!test_and_set_bit(ID_B, &motg->inputs)) {
953 dev_dbg(otg->dev, "ID_B\n");
954 motg->chg_type = USB_ACA_B_CHARGER;
955 motg->chg_state = USB_CHG_STATE_DETECTED;
956 clear_bit(ID_A, &motg->inputs);
957 clear_bit(ID_C, &motg->inputs);
958 ret = true;
959 }
960 break;
961 case 0x10:
962 if (!test_and_set_bit(ID_C, &motg->inputs)) {
963 dev_dbg(otg->dev, "ID_C\n");
964 motg->chg_type = USB_ACA_C_CHARGER;
965 motg->chg_state = USB_CHG_STATE_DETECTED;
966 clear_bit(ID_A, &motg->inputs);
967 clear_bit(ID_B, &motg->inputs);
968 ret = true;
969 }
970 break;
971 default:
972 ret = test_and_clear_bit(ID_A, &motg->inputs) |
973 test_and_clear_bit(ID_B, &motg->inputs) |
974 test_and_clear_bit(ID_C, &motg->inputs);
975 if (ret) {
976 dev_dbg(otg->dev, "ID A/B/C is no more\n");
977 motg->chg_type = USB_INVALID_CHARGER;
978 motg->chg_state = USB_CHG_STATE_UNDEFINED;
979 }
980 }
981out:
982 return ret;
983}
984
985static void msm_chg_enable_aca_det(struct msm_otg *motg)
986{
987 struct otg_transceiver *otg = &motg->otg;
988
989 switch (motg->pdata->phy_type) {
990 case SNPS_28NM_INTEGRATED_PHY:
991 /* ACA ID pin resistance detection enable */
992 ulpi_write(otg, 0x20, 0x85);
993 break;
994 default:
995 break;
996 }
997}
998
999static void msm_chg_enable_aca_intr(struct msm_otg *motg)
1000{
1001 struct otg_transceiver *otg = &motg->otg;
1002
1003 switch (motg->pdata->phy_type) {
1004 case SNPS_28NM_INTEGRATED_PHY:
1005 /* Enables ACA Detection interrupt (on any RID change) */
1006 ulpi_write(otg, 0x20, 0x94);
1007 break;
1008 default:
1009 break;
1010 }
1011}
1012
1013static bool msm_chg_check_aca_intr(struct msm_otg *motg)
1014{
1015 struct otg_transceiver *otg = &motg->otg;
1016 bool ret = false;
1017
1018 switch (motg->pdata->phy_type) {
1019 case SNPS_28NM_INTEGRATED_PHY:
1020 if (ulpi_read(otg, 0x91) & 1) {
1021 dev_dbg(otg->dev, "RID change\n");
1022 ulpi_write(otg, 0x01, 0x92);
1023 ret = msm_chg_aca_detect(motg);
1024 }
1025 default:
1026 break;
1027 }
1028 return ret;
1029}
1030#endif
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301031static bool msm_chg_check_secondary_det(struct msm_otg *motg)
1032{
1033 struct otg_transceiver *otg = &motg->otg;
1034 u32 chg_det;
1035 bool ret = false;
1036
1037 switch (motg->pdata->phy_type) {
1038 case CI_45NM_INTEGRATED_PHY:
1039 chg_det = ulpi_read(otg, 0x34);
1040 ret = chg_det & (1 << 4);
1041 break;
1042 case SNPS_28NM_INTEGRATED_PHY:
1043 chg_det = ulpi_read(otg, 0x87);
1044 ret = chg_det & 1;
1045 break;
1046 default:
1047 break;
1048 }
1049 return ret;
1050}
1051
1052static void msm_chg_enable_secondary_det(struct msm_otg *motg)
1053{
1054 struct otg_transceiver *otg = &motg->otg;
1055 u32 chg_det;
1056
1057 switch (motg->pdata->phy_type) {
1058 case CI_45NM_INTEGRATED_PHY:
1059 chg_det = ulpi_read(otg, 0x34);
1060 /* Turn off charger block */
1061 chg_det |= ~(1 << 1);
1062 ulpi_write(otg, chg_det, 0x34);
1063 udelay(20);
1064 /* control chg block via ULPI */
1065 chg_det &= ~(1 << 3);
1066 ulpi_write(otg, chg_det, 0x34);
1067 /* put it in host mode for enabling D- source */
1068 chg_det &= ~(1 << 2);
1069 ulpi_write(otg, chg_det, 0x34);
1070 /* Turn on chg detect block */
1071 chg_det &= ~(1 << 1);
1072 ulpi_write(otg, chg_det, 0x34);
1073 udelay(20);
1074 /* enable chg detection */
1075 chg_det &= ~(1 << 0);
1076 ulpi_write(otg, chg_det, 0x34);
1077 break;
1078 case SNPS_28NM_INTEGRATED_PHY:
1079 /*
1080 * Configure DM as current source, DP as current sink
1081 * and enable battery charging comparators.
1082 */
1083 ulpi_write(otg, 0x8, 0x85);
1084 ulpi_write(otg, 0x2, 0x85);
1085 ulpi_write(otg, 0x1, 0x85);
1086 break;
1087 default:
1088 break;
1089 }
1090}
1091
1092static bool msm_chg_check_primary_det(struct msm_otg *motg)
1093{
1094 struct otg_transceiver *otg = &motg->otg;
1095 u32 chg_det;
1096 bool ret = false;
1097
1098 switch (motg->pdata->phy_type) {
1099 case CI_45NM_INTEGRATED_PHY:
1100 chg_det = ulpi_read(otg, 0x34);
1101 ret = chg_det & (1 << 4);
1102 break;
1103 case SNPS_28NM_INTEGRATED_PHY:
1104 chg_det = ulpi_read(otg, 0x87);
1105 ret = chg_det & 1;
1106 break;
1107 default:
1108 break;
1109 }
1110 return ret;
1111}
1112
1113static void msm_chg_enable_primary_det(struct msm_otg *motg)
1114{
1115 struct otg_transceiver *otg = &motg->otg;
1116 u32 chg_det;
1117
1118 switch (motg->pdata->phy_type) {
1119 case CI_45NM_INTEGRATED_PHY:
1120 chg_det = ulpi_read(otg, 0x34);
1121 /* enable chg detection */
1122 chg_det &= ~(1 << 0);
1123 ulpi_write(otg, chg_det, 0x34);
1124 break;
1125 case SNPS_28NM_INTEGRATED_PHY:
1126 /*
1127 * Configure DP as current source, DM as current sink
1128 * and enable battery charging comparators.
1129 */
1130 ulpi_write(otg, 0x2, 0x85);
1131 ulpi_write(otg, 0x1, 0x85);
1132 break;
1133 default:
1134 break;
1135 }
1136}
1137
1138static bool msm_chg_check_dcd(struct msm_otg *motg)
1139{
1140 struct otg_transceiver *otg = &motg->otg;
1141 u32 line_state;
1142 bool ret = false;
1143
1144 switch (motg->pdata->phy_type) {
1145 case CI_45NM_INTEGRATED_PHY:
1146 line_state = ulpi_read(otg, 0x15);
1147 ret = !(line_state & 1);
1148 break;
1149 case SNPS_28NM_INTEGRATED_PHY:
1150 line_state = ulpi_read(otg, 0x87);
1151 ret = line_state & 2;
1152 break;
1153 default:
1154 break;
1155 }
1156 return ret;
1157}
1158
1159static void msm_chg_disable_dcd(struct msm_otg *motg)
1160{
1161 struct otg_transceiver *otg = &motg->otg;
1162 u32 chg_det;
1163
1164 switch (motg->pdata->phy_type) {
1165 case CI_45NM_INTEGRATED_PHY:
1166 chg_det = ulpi_read(otg, 0x34);
1167 chg_det &= ~(1 << 5);
1168 ulpi_write(otg, chg_det, 0x34);
1169 break;
1170 case SNPS_28NM_INTEGRATED_PHY:
1171 ulpi_write(otg, 0x10, 0x86);
1172 break;
1173 default:
1174 break;
1175 }
1176}
1177
1178static void msm_chg_enable_dcd(struct msm_otg *motg)
1179{
1180 struct otg_transceiver *otg = &motg->otg;
1181 u32 chg_det;
1182
1183 switch (motg->pdata->phy_type) {
1184 case CI_45NM_INTEGRATED_PHY:
1185 chg_det = ulpi_read(otg, 0x34);
1186 /* Turn on D+ current source */
1187 chg_det |= (1 << 5);
1188 ulpi_write(otg, chg_det, 0x34);
1189 break;
1190 case SNPS_28NM_INTEGRATED_PHY:
1191 /* Data contact detection enable */
1192 ulpi_write(otg, 0x10, 0x85);
1193 break;
1194 default:
1195 break;
1196 }
1197}
1198
1199static void msm_chg_block_on(struct msm_otg *motg)
1200{
1201 struct otg_transceiver *otg = &motg->otg;
1202 u32 func_ctrl, chg_det;
1203
1204 /* put the controller in non-driving mode */
1205 func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
1206 func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
1207 func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
1208 ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
1209
1210 switch (motg->pdata->phy_type) {
1211 case CI_45NM_INTEGRATED_PHY:
1212 chg_det = ulpi_read(otg, 0x34);
1213 /* control chg block via ULPI */
1214 chg_det &= ~(1 << 3);
1215 ulpi_write(otg, chg_det, 0x34);
1216 /* Turn on chg detect block */
1217 chg_det &= ~(1 << 1);
1218 ulpi_write(otg, chg_det, 0x34);
1219 udelay(20);
1220 break;
1221 case SNPS_28NM_INTEGRATED_PHY:
1222 /* Clear charger detecting control bits */
1223 ulpi_write(otg, 0x3F, 0x86);
1224 /* Clear alt interrupt latch and enable bits */
1225 ulpi_write(otg, 0x1F, 0x92);
1226 ulpi_write(otg, 0x1F, 0x95);
1227 udelay(100);
1228 break;
1229 default:
1230 break;
1231 }
1232}
1233
1234static void msm_chg_block_off(struct msm_otg *motg)
1235{
1236 struct otg_transceiver *otg = &motg->otg;
1237 u32 func_ctrl, chg_det;
1238
1239 switch (motg->pdata->phy_type) {
1240 case CI_45NM_INTEGRATED_PHY:
1241 chg_det = ulpi_read(otg, 0x34);
1242 /* Turn off charger block */
1243 chg_det |= ~(1 << 1);
1244 ulpi_write(otg, chg_det, 0x34);
1245 break;
1246 case SNPS_28NM_INTEGRATED_PHY:
1247 /* Clear charger detecting control bits */
1248 ulpi_write(otg, 0x3F, 0x86);
1249 /* Clear alt interrupt latch and enable bits */
1250 ulpi_write(otg, 0x1F, 0x92);
1251 ulpi_write(otg, 0x1F, 0x95);
1252 break;
1253 default:
1254 break;
1255 }
1256
1257 /* put the controller in normal mode */
1258 func_ctrl = ulpi_read(otg, ULPI_FUNC_CTRL);
1259 func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
1260 func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
1261 ulpi_write(otg, func_ctrl, ULPI_FUNC_CTRL);
1262}
1263
Anji jonnalad270e2d2011-08-09 11:28:32 +05301264static const char *chg_to_string(enum usb_chg_type chg_type)
1265{
1266 switch (chg_type) {
1267 case USB_SDP_CHARGER: return "USB_SDP_CHARGER";
1268 case USB_DCP_CHARGER: return "USB_DCP_CHARGER";
1269 case USB_CDP_CHARGER: return "USB_CDP_CHARGER";
1270 case USB_ACA_A_CHARGER: return "USB_ACA_A_CHARGER";
1271 case USB_ACA_B_CHARGER: return "USB_ACA_B_CHARGER";
1272 case USB_ACA_C_CHARGER: return "USB_ACA_C_CHARGER";
1273 case USB_ACA_DOCK_CHARGER: return "USB_ACA_DOCK_CHARGER";
1274 default: return "INVALID_CHARGER";
1275 }
1276}
1277
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301278#define MSM_CHG_DCD_POLL_TIME (100 * HZ/1000) /* 100 msec */
1279#define MSM_CHG_DCD_MAX_RETRIES 6 /* Tdcd_tmout = 6 * 100 msec */
1280#define MSM_CHG_PRIMARY_DET_TIME (40 * HZ/1000) /* TVDPSRC_ON */
1281#define MSM_CHG_SECONDARY_DET_TIME (40 * HZ/1000) /* TVDMSRC_ON */
1282static void msm_chg_detect_work(struct work_struct *w)
1283{
1284 struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
1285 struct otg_transceiver *otg = &motg->otg;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001286 bool is_dcd, tmout, vout, is_aca;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301287 unsigned long delay;
1288
1289 dev_dbg(otg->dev, "chg detection work\n");
1290 switch (motg->chg_state) {
1291 case USB_CHG_STATE_UNDEFINED:
1292 pm_runtime_get_sync(otg->dev);
1293 msm_chg_block_on(motg);
1294 msm_chg_enable_dcd(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001295 msm_chg_enable_aca_det(motg);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301296 motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
1297 motg->dcd_retries = 0;
1298 delay = MSM_CHG_DCD_POLL_TIME;
1299 break;
1300 case USB_CHG_STATE_WAIT_FOR_DCD:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001301 is_aca = msm_chg_aca_detect(motg);
1302 if (is_aca) {
1303 /*
1304 * ID_A can be ACA dock too. continue
1305 * primary detection after DCD.
1306 */
1307 if (test_bit(ID_A, &motg->inputs)) {
1308 motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
1309 } else {
1310 delay = 0;
1311 break;
1312 }
1313 }
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301314 is_dcd = msm_chg_check_dcd(motg);
1315 tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES;
1316 if (is_dcd || tmout) {
1317 msm_chg_disable_dcd(motg);
1318 msm_chg_enable_primary_det(motg);
1319 delay = MSM_CHG_PRIMARY_DET_TIME;
1320 motg->chg_state = USB_CHG_STATE_DCD_DONE;
1321 } else {
1322 delay = MSM_CHG_DCD_POLL_TIME;
1323 }
1324 break;
1325 case USB_CHG_STATE_DCD_DONE:
1326 vout = msm_chg_check_primary_det(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001327 is_aca = msm_chg_aca_detect(motg);
1328 if (is_aca) {
1329 if (vout && test_bit(ID_A, &motg->inputs))
1330 motg->chg_type = USB_ACA_DOCK_CHARGER;
1331 delay = 0;
1332 break;
1333 }
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301334 if (vout) {
1335 msm_chg_enable_secondary_det(motg);
1336 delay = MSM_CHG_SECONDARY_DET_TIME;
1337 motg->chg_state = USB_CHG_STATE_PRIMARY_DONE;
1338 } else {
1339 motg->chg_type = USB_SDP_CHARGER;
1340 motg->chg_state = USB_CHG_STATE_DETECTED;
1341 delay = 0;
1342 }
1343 break;
1344 case USB_CHG_STATE_PRIMARY_DONE:
1345 vout = msm_chg_check_secondary_det(motg);
1346 if (vout)
1347 motg->chg_type = USB_DCP_CHARGER;
1348 else
1349 motg->chg_type = USB_CDP_CHARGER;
1350 motg->chg_state = USB_CHG_STATE_SECONDARY_DONE;
1351 /* fall through */
1352 case USB_CHG_STATE_SECONDARY_DONE:
1353 motg->chg_state = USB_CHG_STATE_DETECTED;
1354 case USB_CHG_STATE_DETECTED:
1355 msm_chg_block_off(motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001356 msm_chg_enable_aca_det(motg);
1357 msm_chg_enable_aca_intr(motg);
Anji jonnalad270e2d2011-08-09 11:28:32 +05301358 dev_dbg(otg->dev, "chg_type = %s\n",
1359 chg_to_string(motg->chg_type));
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301360 schedule_work(&motg->sm_work);
1361 return;
1362 default:
1363 return;
1364 }
1365
1366 schedule_delayed_work(&motg->chg_work, delay);
1367}
1368
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301369/*
1370 * We support OTG, Peripheral only and Host only configurations. In case
1371 * of OTG, mode switch (host-->peripheral/peripheral-->host) can happen
1372 * via Id pin status or user request (debugfs). Id/BSV interrupts are not
1373 * enabled when switch is controlled by user and default mode is supplied
1374 * by board file, which can be changed by userspace later.
1375 */
1376static void msm_otg_init_sm(struct msm_otg *motg)
1377{
1378 struct msm_otg_platform_data *pdata = motg->pdata;
1379 u32 otgsc = readl(USB_OTGSC);
1380
1381 switch (pdata->mode) {
1382 case USB_OTG:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001383 if (pdata->otg_control == OTG_USER_CONTROL) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301384 if (pdata->default_mode == USB_HOST) {
1385 clear_bit(ID, &motg->inputs);
1386 } else if (pdata->default_mode == USB_PERIPHERAL) {
1387 set_bit(ID, &motg->inputs);
1388 set_bit(B_SESS_VLD, &motg->inputs);
1389 } else {
1390 set_bit(ID, &motg->inputs);
1391 clear_bit(B_SESS_VLD, &motg->inputs);
1392 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001393 } else {
1394 if (otgsc & OTGSC_ID)
1395 set_bit(ID, &motg->inputs);
1396 else
1397 clear_bit(ID, &motg->inputs);
1398
1399 if (otgsc & OTGSC_BSV)
1400 set_bit(B_SESS_VLD, &motg->inputs);
1401 else
1402 clear_bit(B_SESS_VLD, &motg->inputs);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301403 }
1404 break;
1405 case USB_HOST:
1406 clear_bit(ID, &motg->inputs);
1407 break;
1408 case USB_PERIPHERAL:
1409 set_bit(ID, &motg->inputs);
1410 if (otgsc & OTGSC_BSV)
1411 set_bit(B_SESS_VLD, &motg->inputs);
1412 else
1413 clear_bit(B_SESS_VLD, &motg->inputs);
1414 break;
1415 default:
1416 break;
1417 }
1418}
1419
1420static void msm_otg_sm_work(struct work_struct *w)
1421{
1422 struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
1423 struct otg_transceiver *otg = &motg->otg;
1424
1425 switch (otg->state) {
1426 case OTG_STATE_UNDEFINED:
1427 dev_dbg(otg->dev, "OTG_STATE_UNDEFINED state\n");
1428 msm_otg_reset(otg);
1429 msm_otg_init_sm(motg);
1430 otg->state = OTG_STATE_B_IDLE;
1431 /* FALL THROUGH */
1432 case OTG_STATE_B_IDLE:
1433 dev_dbg(otg->dev, "OTG_STATE_B_IDLE state\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001434 if ((!test_bit(ID, &motg->inputs) ||
1435 test_bit(ID_A, &motg->inputs)) && otg->host) {
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301436 /* disable BSV bit */
1437 writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001438 if (motg->chg_type == USB_ACA_DOCK_CHARGER)
1439 msm_otg_notify_charger(motg,
1440 IDEV_CHG_MAX);
1441 else if (!test_bit(ID_A, &motg->inputs) &&
1442 motg->pdata->vbus_power)
1443 motg->pdata->vbus_power(1);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301444 msm_otg_start_host(otg, 1);
1445 otg->state = OTG_STATE_A_HOST;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301446 } else if (test_bit(B_SESS_VLD, &motg->inputs)) {
1447 switch (motg->chg_state) {
1448 case USB_CHG_STATE_UNDEFINED:
1449 msm_chg_detect_work(&motg->chg_work.work);
1450 break;
1451 case USB_CHG_STATE_DETECTED:
1452 switch (motg->chg_type) {
1453 case USB_DCP_CHARGER:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001454 case USB_ACA_B_CHARGER:
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301455 msm_otg_notify_charger(motg,
1456 IDEV_CHG_MAX);
1457 break;
1458 case USB_CDP_CHARGER:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001459 case USB_ACA_C_CHARGER:
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301460 msm_otg_notify_charger(motg,
1461 IDEV_CHG_MAX);
1462 msm_otg_start_peripheral(otg, 1);
1463 otg->state = OTG_STATE_B_PERIPHERAL;
1464 break;
1465 case USB_SDP_CHARGER:
1466 msm_otg_notify_charger(motg, IUNIT);
1467 msm_otg_start_peripheral(otg, 1);
1468 otg->state = OTG_STATE_B_PERIPHERAL;
1469 break;
1470 default:
1471 break;
1472 }
1473 break;
1474 default:
1475 break;
1476 }
1477 } else {
1478 /*
1479 * If charger detection work is pending, decrement
1480 * the pm usage counter to balance with the one that
1481 * is incremented in charger detection work.
1482 */
1483 if (cancel_delayed_work_sync(&motg->chg_work)) {
1484 pm_runtime_put_sync(otg->dev);
1485 msm_otg_reset(otg);
1486 }
1487 msm_otg_notify_charger(motg, 0);
1488 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1489 motg->chg_type = USB_INVALID_CHARGER;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301490 }
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301491 pm_runtime_put_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301492 break;
1493 case OTG_STATE_B_PERIPHERAL:
1494 dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n");
1495 if (!test_bit(B_SESS_VLD, &motg->inputs) ||
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001496 !test_bit(ID, &motg->inputs) ||
1497 !test_bit(ID_C, &motg->inputs)) {
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301498 msm_otg_notify_charger(motg, 0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301499 msm_otg_start_peripheral(otg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001500 if (!test_bit(ID_B, &motg->inputs) &&
1501 !test_bit(ID_A, &motg->inputs)) {
1502 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1503 motg->chg_type = USB_INVALID_CHARGER;
1504 }
1505 otg->state = OTG_STATE_B_IDLE;
1506 msm_otg_reset(otg);
1507 schedule_work(w);
1508 } else if (test_bit(ID_C, &motg->inputs)) {
1509 msm_otg_notify_charger(motg, IDEV_CHG_MAX);
1510 pm_runtime_put_sync(otg->dev);
1511 }
1512 break;
1513 case OTG_STATE_A_HOST:
1514 dev_dbg(otg->dev, "OTG_STATE_A_HOST state\n");
1515 if (test_bit(ID, &motg->inputs) &&
1516 !test_bit(ID_A, &motg->inputs)) {
1517 msm_otg_start_host(otg, 0);
1518 writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
1519 if (motg->pdata->vbus_power)
1520 motg->pdata->vbus_power(0);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301521 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1522 motg->chg_type = USB_INVALID_CHARGER;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301523 otg->state = OTG_STATE_B_IDLE;
1524 msm_otg_reset(otg);
1525 schedule_work(w);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001526 } else if (test_bit(ID_A, &motg->inputs)) {
1527 writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
1528 if (motg->pdata->vbus_power)
1529 motg->pdata->vbus_power(0);
1530 msm_otg_notify_charger(motg,
1531 IDEV_CHG_MIN - motg->mA_port);
1532 pm_runtime_put_sync(otg->dev);
1533 } else if (!test_bit(ID, &motg->inputs)) {
1534 motg->chg_state = USB_CHG_STATE_UNDEFINED;
1535 motg->chg_type = USB_INVALID_CHARGER;
1536 msm_otg_notify_charger(motg, 0);
1537 writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
1538 if (motg->pdata->vbus_power)
1539 motg->pdata->vbus_power(1);
1540 pm_runtime_put_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301541 }
1542 break;
1543 default:
1544 break;
1545 }
1546}
1547
1548static irqreturn_t msm_otg_irq(int irq, void *data)
1549{
1550 struct msm_otg *motg = data;
1551 struct otg_transceiver *otg = &motg->otg;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001552 u32 otgsc = 0, usbsts;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301553
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301554 if (atomic_read(&motg->in_lpm)) {
1555 disable_irq_nosync(irq);
1556 motg->async_int = 1;
1557 pm_runtime_get(otg->dev);
1558 return IRQ_HANDLED;
1559 }
1560
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001561 usbsts = readl(USB_USBSTS);
1562 if ((usbsts & PHY_ALT_INT)) {
1563 writel(PHY_ALT_INT, USB_USBSTS);
1564 if (msm_chg_check_aca_intr(motg)) {
1565 pm_runtime_get_noresume(otg->dev);
1566 schedule_work(&motg->sm_work);
1567 }
1568 return IRQ_HANDLED;
1569 }
1570
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301571 otgsc = readl(USB_OTGSC);
1572 if (!(otgsc & (OTGSC_IDIS | OTGSC_BSVIS)))
1573 return IRQ_NONE;
1574
1575 if ((otgsc & OTGSC_IDIS) && (otgsc & OTGSC_IDIE)) {
1576 if (otgsc & OTGSC_ID)
1577 set_bit(ID, &motg->inputs);
1578 else
1579 clear_bit(ID, &motg->inputs);
1580 dev_dbg(otg->dev, "ID set/clear\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001581 schedule_work(&motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301582 pm_runtime_get_noresume(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301583 } else if ((otgsc & OTGSC_BSVIS) && (otgsc & OTGSC_BSVIE)) {
1584 if (otgsc & OTGSC_BSV)
1585 set_bit(B_SESS_VLD, &motg->inputs);
1586 else
1587 clear_bit(B_SESS_VLD, &motg->inputs);
1588 dev_dbg(otg->dev, "BSV set/clear\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001589 schedule_work(&motg->sm_work);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301590 pm_runtime_get_noresume(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301591 }
1592
1593 writel(otgsc, USB_OTGSC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001594 return IRQ_HANDLED;
1595}
1596
1597static void msm_otg_set_vbus_state(int online)
1598{
1599 struct msm_otg *motg = the_msm_otg;
1600
1601 /* We depend on PMIC for only VBUS ON interrupt */
1602 if (!atomic_read(&motg->in_lpm) || !online)
1603 return;
1604
1605 /*
1606 * Let interrupt handler take care of resuming
1607 * the hardware.
1608 */
1609 msm_otg_irq(motg->irq, (void *) motg);
1610}
1611
1612static irqreturn_t msm_pmic_id_irq(int irq, void *data)
1613{
1614 struct msm_otg *motg = data;
1615
1616 if (atomic_read(&motg->in_lpm) && !motg->async_int)
1617 msm_otg_irq(motg->irq, motg);
1618
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301619 return IRQ_HANDLED;
1620}
1621
1622static int msm_otg_mode_show(struct seq_file *s, void *unused)
1623{
1624 struct msm_otg *motg = s->private;
1625 struct otg_transceiver *otg = &motg->otg;
1626
1627 switch (otg->state) {
1628 case OTG_STATE_A_HOST:
1629 seq_printf(s, "host\n");
1630 break;
1631 case OTG_STATE_B_PERIPHERAL:
1632 seq_printf(s, "peripheral\n");
1633 break;
1634 default:
1635 seq_printf(s, "none\n");
1636 break;
1637 }
1638
1639 return 0;
1640}
1641
1642static int msm_otg_mode_open(struct inode *inode, struct file *file)
1643{
1644 return single_open(file, msm_otg_mode_show, inode->i_private);
1645}
1646
1647static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf,
1648 size_t count, loff_t *ppos)
1649{
Pavankumar Kondetie2904ee2011-02-15 09:42:35 +05301650 struct seq_file *s = file->private_data;
1651 struct msm_otg *motg = s->private;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301652 char buf[16];
1653 struct otg_transceiver *otg = &motg->otg;
1654 int status = count;
1655 enum usb_mode_type req_mode;
1656
1657 memset(buf, 0x00, sizeof(buf));
1658
1659 if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) {
1660 status = -EFAULT;
1661 goto out;
1662 }
1663
1664 if (!strncmp(buf, "host", 4)) {
1665 req_mode = USB_HOST;
1666 } else if (!strncmp(buf, "peripheral", 10)) {
1667 req_mode = USB_PERIPHERAL;
1668 } else if (!strncmp(buf, "none", 4)) {
1669 req_mode = USB_NONE;
1670 } else {
1671 status = -EINVAL;
1672 goto out;
1673 }
1674
1675 switch (req_mode) {
1676 case USB_NONE:
1677 switch (otg->state) {
1678 case OTG_STATE_A_HOST:
1679 case OTG_STATE_B_PERIPHERAL:
1680 set_bit(ID, &motg->inputs);
1681 clear_bit(B_SESS_VLD, &motg->inputs);
1682 break;
1683 default:
1684 goto out;
1685 }
1686 break;
1687 case USB_PERIPHERAL:
1688 switch (otg->state) {
1689 case OTG_STATE_B_IDLE:
1690 case OTG_STATE_A_HOST:
1691 set_bit(ID, &motg->inputs);
1692 set_bit(B_SESS_VLD, &motg->inputs);
1693 break;
1694 default:
1695 goto out;
1696 }
1697 break;
1698 case USB_HOST:
1699 switch (otg->state) {
1700 case OTG_STATE_B_IDLE:
1701 case OTG_STATE_B_PERIPHERAL:
1702 clear_bit(ID, &motg->inputs);
1703 break;
1704 default:
1705 goto out;
1706 }
1707 break;
1708 default:
1709 goto out;
1710 }
1711
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301712 pm_runtime_get_sync(otg->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301713 schedule_work(&motg->sm_work);
1714out:
1715 return status;
1716}
1717
1718const struct file_operations msm_otg_mode_fops = {
1719 .open = msm_otg_mode_open,
1720 .read = seq_read,
1721 .write = msm_otg_mode_write,
1722 .llseek = seq_lseek,
1723 .release = single_release,
1724};
1725
Anji jonnalad270e2d2011-08-09 11:28:32 +05301726static int msm_otg_show_chg_type(struct seq_file *s, void *unused)
1727{
1728 struct msm_otg *motg = s->private;
1729
1730 seq_printf(s, chg_to_string(motg->chg_type));
1731 return 0;
1732}
1733
1734static int msm_otg_chg_open(struct inode *inode, struct file *file)
1735{
1736 return single_open(file, msm_otg_show_chg_type, inode->i_private);
1737}
1738
1739const struct file_operations msm_otg_chg_fops = {
1740 .open = msm_otg_chg_open,
1741 .read = seq_read,
1742 .llseek = seq_lseek,
1743 .release = single_release,
1744};
1745
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301746static struct dentry *msm_otg_dbg_root;
1747static struct dentry *msm_otg_dbg_mode;
Anji jonnalad270e2d2011-08-09 11:28:32 +05301748static struct dentry *msm_otg_chg_type;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301749
1750static int msm_otg_debugfs_init(struct msm_otg *motg)
1751{
Anji jonnalad270e2d2011-08-09 11:28:32 +05301752
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301753 msm_otg_dbg_root = debugfs_create_dir("msm_otg", NULL);
1754
1755 if (!msm_otg_dbg_root || IS_ERR(msm_otg_dbg_root))
1756 return -ENODEV;
1757
Anji jonnalad270e2d2011-08-09 11:28:32 +05301758 if (motg->pdata->mode == USB_OTG &&
1759 motg->pdata->otg_control == OTG_USER_CONTROL) {
1760
1761 msm_otg_dbg_mode = debugfs_create_file("mode", S_IRUGO |
1762 S_IWUSR, msm_otg_dbg_root, motg,
1763 &msm_otg_mode_fops);
1764
1765 if (!msm_otg_dbg_mode) {
1766 debugfs_remove(msm_otg_dbg_root);
1767 msm_otg_dbg_root = NULL;
1768 return -ENODEV;
1769 }
1770 }
1771
1772 msm_otg_chg_type = debugfs_create_file("chg_type", S_IRUGO,
1773 msm_otg_dbg_root, motg,
1774 &msm_otg_chg_fops);
1775
1776 if (!msm_otg_chg_type) {
1777 debugfs_remove(msm_otg_dbg_mode);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301778 debugfs_remove(msm_otg_dbg_root);
1779 msm_otg_dbg_root = NULL;
Anji jonnalad270e2d2011-08-09 11:28:32 +05301780 msm_otg_dbg_mode = NULL;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301781 return -ENODEV;
1782 }
1783
1784 return 0;
1785}
1786
1787static void msm_otg_debugfs_cleanup(void)
1788{
Anji jonnalad270e2d2011-08-09 11:28:32 +05301789 debugfs_remove_recursive(msm_otg_dbg_root);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301790}
1791
1792static int __init msm_otg_probe(struct platform_device *pdev)
1793{
1794 int ret = 0;
1795 struct resource *res;
1796 struct msm_otg *motg;
1797 struct otg_transceiver *otg;
1798
1799 dev_info(&pdev->dev, "msm_otg probe\n");
1800 if (!pdev->dev.platform_data) {
1801 dev_err(&pdev->dev, "No platform data given. Bailing out\n");
1802 return -ENODEV;
1803 }
1804
1805 motg = kzalloc(sizeof(struct msm_otg), GFP_KERNEL);
1806 if (!motg) {
1807 dev_err(&pdev->dev, "unable to allocate msm_otg\n");
1808 return -ENOMEM;
1809 }
1810
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001811 the_msm_otg = motg;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301812 motg->pdata = pdev->dev.platform_data;
1813 otg = &motg->otg;
1814 otg->dev = &pdev->dev;
1815
1816 motg->phy_reset_clk = clk_get(&pdev->dev, "usb_phy_clk");
1817 if (IS_ERR(motg->phy_reset_clk)) {
1818 dev_err(&pdev->dev, "failed to get usb_phy_clk\n");
1819 ret = PTR_ERR(motg->phy_reset_clk);
1820 goto free_motg;
1821 }
1822
1823 motg->clk = clk_get(&pdev->dev, "usb_hs_clk");
1824 if (IS_ERR(motg->clk)) {
1825 dev_err(&pdev->dev, "failed to get usb_hs_clk\n");
1826 ret = PTR_ERR(motg->clk);
1827 goto put_phy_reset_clk;
1828 }
Anji jonnala0f73cac2011-05-04 10:19:46 +05301829 clk_set_rate(motg->clk, 60000000);
1830
1831 /*
1832 * If USB Core is running its protocol engine based on CORE CLK,
1833 * CORE CLK must be running at >55Mhz for correct HSUSB
1834 * operation and USB core cannot tolerate frequency changes on
1835 * CORE CLK. For such USB cores, vote for maximum clk frequency
1836 * on pclk source
1837 */
1838 if (motg->pdata->pclk_src_name) {
1839 motg->pclk_src = clk_get(&pdev->dev,
1840 motg->pdata->pclk_src_name);
1841 if (IS_ERR(motg->pclk_src))
1842 goto put_clk;
1843 clk_set_rate(motg->pclk_src, INT_MAX);
1844 clk_enable(motg->pclk_src);
1845 } else
1846 motg->pclk_src = ERR_PTR(-ENOENT);
1847
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301848
1849 motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk");
1850 if (IS_ERR(motg->pclk)) {
1851 dev_err(&pdev->dev, "failed to get usb_hs_pclk\n");
1852 ret = PTR_ERR(motg->pclk);
Anji jonnala0f73cac2011-05-04 10:19:46 +05301853 goto put_pclk_src;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301854 }
1855
1856 /*
1857 * USB core clock is not present on all MSM chips. This
1858 * clock is introduced to remove the dependency on AXI
1859 * bus frequency.
1860 */
1861 motg->core_clk = clk_get(&pdev->dev, "usb_hs_core_clk");
1862 if (IS_ERR(motg->core_clk))
1863 motg->core_clk = NULL;
1864
1865 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1866 if (!res) {
1867 dev_err(&pdev->dev, "failed to get platform resource mem\n");
1868 ret = -ENODEV;
1869 goto put_core_clk;
1870 }
1871
1872 motg->regs = ioremap(res->start, resource_size(res));
1873 if (!motg->regs) {
1874 dev_err(&pdev->dev, "ioremap failed\n");
1875 ret = -ENOMEM;
1876 goto put_core_clk;
1877 }
1878 dev_info(&pdev->dev, "OTG regs = %p\n", motg->regs);
1879
1880 motg->irq = platform_get_irq(pdev, 0);
1881 if (!motg->irq) {
1882 dev_err(&pdev->dev, "platform_get_irq failed\n");
1883 ret = -ENODEV;
1884 goto free_regs;
1885 }
1886
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301887 clk_enable(motg->pclk);
Anji jonnala11aa5c42011-05-04 10:19:48 +05301888
1889 ret = msm_hsusb_init_vddcx(motg, 1);
1890 if (ret) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001891 dev_err(&pdev->dev, "hsusb vddcx init failed\n");
Anji jonnala11aa5c42011-05-04 10:19:48 +05301892 goto free_regs;
1893 }
1894
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001895 ret = msm_hsusb_config_vddcx(1);
1896 if (ret) {
1897 dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
1898 goto free_init_vddcx;
1899 }
1900
Anji jonnala11aa5c42011-05-04 10:19:48 +05301901 ret = msm_hsusb_ldo_init(motg, 1);
1902 if (ret) {
1903 dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001904 goto free_init_vddcx;
Anji jonnala11aa5c42011-05-04 10:19:48 +05301905 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001906
1907 ret = msm_hsusb_ldo_enable(motg, 1);
Anji jonnala11aa5c42011-05-04 10:19:48 +05301908 if (ret) {
1909 dev_err(&pdev->dev, "hsusb vreg enable failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001910 goto free_ldo_init;
Anji jonnala11aa5c42011-05-04 10:19:48 +05301911 }
1912
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301913 if (motg->core_clk)
1914 clk_enable(motg->core_clk);
1915
1916 writel(0, USB_USBINTR);
1917 writel(0, USB_OTGSC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001918 /* Ensure that above STOREs are completed before enabling interrupts */
1919 mb();
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301920
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001921 wake_lock_init(&motg->wlock, WAKE_LOCK_SUSPEND, "msm_otg");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301922 INIT_WORK(&motg->sm_work, msm_otg_sm_work);
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301923 INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301924 ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
1925 "msm_otg", motg);
1926 if (ret) {
1927 dev_err(&pdev->dev, "request irq failed\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001928 goto destroy_wlock;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301929 }
1930
1931 otg->init = msm_otg_reset;
1932 otg->set_host = msm_otg_set_host;
1933 otg->set_peripheral = msm_otg_set_peripheral;
Pavankumar Kondetid8608522011-05-04 10:19:47 +05301934 otg->set_power = msm_otg_set_power;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301935
1936 otg->io_ops = &msm_otg_io_ops;
1937
1938 ret = otg_set_transceiver(&motg->otg);
1939 if (ret) {
1940 dev_err(&pdev->dev, "otg_set_transceiver failed\n");
1941 goto free_irq;
1942 }
1943
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001944 if (motg->pdata->otg_control == OTG_PMIC_CONTROL) {
1945 if (motg->pdata->pmic_id_irq) {
1946 ret = request_irq(motg->pdata->pmic_id_irq,
1947 msm_pmic_id_irq,
1948 IRQF_TRIGGER_RISING |
1949 IRQF_TRIGGER_FALLING,
1950 "msm_otg", motg);
1951 if (ret) {
1952 dev_err(&pdev->dev, "request irq failed for PMIC ID\n");
1953 goto remove_otg;
1954 }
1955 } else {
1956 ret = -ENODEV;
1957 dev_err(&pdev->dev, "PMIC IRQ for ID notifications doesn't exist\n");
1958 goto remove_otg;
1959 }
1960 }
1961
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301962 platform_set_drvdata(pdev, motg);
1963 device_init_wakeup(&pdev->dev, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001964 motg->mA_port = IUNIT;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301965
Anji jonnalad270e2d2011-08-09 11:28:32 +05301966 ret = msm_otg_debugfs_init(motg);
1967 if (ret)
1968 dev_dbg(&pdev->dev, "mode debugfs file is"
1969 "not available\n");
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301970
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001971 if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
1972 pm8921_charger_register_vbus_sn(&msm_otg_set_vbus_state);
1973
1974 if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
1975 motg->pdata->otg_control == OTG_PMIC_CONTROL &&
1976 motg->pdata->pmic_id_irq)
1977 motg->caps = ALLOW_PHY_POWER_COLLAPSE |
1978 ALLOW_PHY_RETENTION |
1979 ALLOW_PHY_COMP_DISABLE;
1980
1981 wake_lock(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301982 pm_runtime_set_active(&pdev->dev);
1983 pm_runtime_enable(&pdev->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301984
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05301985 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001986
1987remove_otg:
1988 otg_set_transceiver(NULL);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301989free_irq:
1990 free_irq(motg->irq, motg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001991destroy_wlock:
1992 wake_lock_destroy(&motg->wlock);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301993 clk_disable(motg->pclk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001994 msm_hsusb_ldo_enable(motg, 0);
1995free_ldo_init:
Anji jonnala11aa5c42011-05-04 10:19:48 +05301996 msm_hsusb_ldo_init(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001997free_init_vddcx:
Anji jonnala11aa5c42011-05-04 10:19:48 +05301998 msm_hsusb_init_vddcx(motg, 0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05301999free_regs:
2000 iounmap(motg->regs);
2001put_core_clk:
2002 if (motg->core_clk)
2003 clk_put(motg->core_clk);
Anji jonnala0f73cac2011-05-04 10:19:46 +05302004put_pclk_src:
2005 if (!IS_ERR(motg->pclk_src)) {
2006 clk_disable(motg->pclk_src);
2007 clk_put(motg->pclk_src);
2008 }
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302009put_clk:
2010 clk_put(motg->clk);
2011put_phy_reset_clk:
2012 clk_put(motg->phy_reset_clk);
2013free_motg:
2014 kfree(motg);
2015 return ret;
2016}
2017
2018static int __devexit msm_otg_remove(struct platform_device *pdev)
2019{
2020 struct msm_otg *motg = platform_get_drvdata(pdev);
2021 struct otg_transceiver *otg = &motg->otg;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302022 int cnt = 0;
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302023
2024 if (otg->host || otg->gadget)
2025 return -EBUSY;
2026
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002027 if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
2028 pm8921_charger_unregister_vbus_sn(0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302029 msm_otg_debugfs_cleanup();
Pavankumar Kondetid8608522011-05-04 10:19:47 +05302030 cancel_delayed_work_sync(&motg->chg_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302031 cancel_work_sync(&motg->sm_work);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302032
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302033 pm_runtime_resume(&pdev->dev);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302034
2035 device_init_wakeup(&pdev->dev, 0);
2036 pm_runtime_disable(&pdev->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002037 wake_lock_destroy(&motg->wlock);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302038
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002039 if (motg->pdata->pmic_id_irq)
2040 free_irq(motg->pdata->pmic_id_irq, motg);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302041 otg_set_transceiver(NULL);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302042 free_irq(motg->irq, motg);
2043
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302044 /*
2045 * Put PHY in low power mode.
2046 */
2047 ulpi_read(otg, 0x14);
2048 ulpi_write(otg, 0x08, 0x09);
2049
2050 writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
2051 while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
2052 if (readl(USB_PORTSC) & PORTSC_PHCD)
2053 break;
2054 udelay(1);
2055 cnt++;
2056 }
2057 if (cnt >= PHY_SUSPEND_TIMEOUT_USEC)
2058 dev_err(otg->dev, "Unable to suspend PHY\n");
2059
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302060 clk_disable(motg->pclk);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302061 if (motg->core_clk)
2062 clk_disable(motg->core_clk);
Anji jonnala0f73cac2011-05-04 10:19:46 +05302063 if (!IS_ERR(motg->pclk_src)) {
2064 clk_disable(motg->pclk_src);
2065 clk_put(motg->pclk_src);
2066 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002067 msm_hsusb_ldo_enable(motg, 0);
Anji jonnala11aa5c42011-05-04 10:19:48 +05302068 msm_hsusb_ldo_init(motg, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002069 msm_hsusb_init_vddcx(motg, 0);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302070
2071 iounmap(motg->regs);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302072 pm_runtime_set_suspended(&pdev->dev);
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302073
2074 clk_put(motg->phy_reset_clk);
2075 clk_put(motg->pclk);
2076 clk_put(motg->clk);
2077 if (motg->core_clk)
2078 clk_put(motg->core_clk);
2079
2080 kfree(motg);
2081
2082 return 0;
2083}
2084
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302085#ifdef CONFIG_PM_RUNTIME
2086static int msm_otg_runtime_idle(struct device *dev)
2087{
2088 struct msm_otg *motg = dev_get_drvdata(dev);
2089 struct otg_transceiver *otg = &motg->otg;
2090
2091 dev_dbg(dev, "OTG runtime idle\n");
2092
2093 /*
2094 * It is observed some times that a spurious interrupt
2095 * comes when PHY is put into LPM immediately after PHY reset.
2096 * This 1 sec delay also prevents entering into LPM immediately
2097 * after asynchronous interrupt.
2098 */
2099 if (otg->state != OTG_STATE_UNDEFINED)
2100 pm_schedule_suspend(dev, 1000);
2101
2102 return -EAGAIN;
2103}
2104
2105static int msm_otg_runtime_suspend(struct device *dev)
2106{
2107 struct msm_otg *motg = dev_get_drvdata(dev);
2108
2109 dev_dbg(dev, "OTG runtime suspend\n");
2110 return msm_otg_suspend(motg);
2111}
2112
2113static int msm_otg_runtime_resume(struct device *dev)
2114{
2115 struct msm_otg *motg = dev_get_drvdata(dev);
2116
2117 dev_dbg(dev, "OTG runtime resume\n");
2118 return msm_otg_resume(motg);
2119}
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302120#endif
2121
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302122#ifdef CONFIG_PM_SLEEP
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302123static int msm_otg_pm_suspend(struct device *dev)
2124{
2125 struct msm_otg *motg = dev_get_drvdata(dev);
2126
2127 dev_dbg(dev, "OTG PM suspend\n");
2128 return msm_otg_suspend(motg);
2129}
2130
2131static int msm_otg_pm_resume(struct device *dev)
2132{
2133 struct msm_otg *motg = dev_get_drvdata(dev);
Manu Gautamf284c052011-09-08 16:52:48 +05302134 int ret = 0;
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302135
2136 dev_dbg(dev, "OTG PM resume\n");
2137
Manu Gautamf284c052011-09-08 16:52:48 +05302138#ifdef CONFIG_PM_RUNTIME
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302139 /*
Manu Gautamf284c052011-09-08 16:52:48 +05302140 * Do not resume hardware as part of system resume,
2141 * rather, wait for the ASYNC INT from the h/w
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302142 */
Manu Gautamf284c052011-09-08 16:52:48 +05302143 return ret;
2144#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302145
Manu Gautamf284c052011-09-08 16:52:48 +05302146 return msm_otg_resume(motg);
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302147}
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302148#endif
2149
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302150#ifdef CONFIG_PM
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302151static const struct dev_pm_ops msm_otg_dev_pm_ops = {
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302152 SET_SYSTEM_SLEEP_PM_OPS(msm_otg_pm_suspend, msm_otg_pm_resume)
2153 SET_RUNTIME_PM_OPS(msm_otg_runtime_suspend, msm_otg_runtime_resume,
2154 msm_otg_runtime_idle)
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302155};
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302156#endif
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302157
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302158static struct platform_driver msm_otg_driver = {
2159 .remove = __devexit_p(msm_otg_remove),
2160 .driver = {
2161 .name = DRIVER_NAME,
2162 .owner = THIS_MODULE,
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302163#ifdef CONFIG_PM
Pavankumar Kondeti87c01042010-12-07 17:53:58 +05302164 .pm = &msm_otg_dev_pm_ops,
Pavankumar Kondeti70187732011-02-15 09:42:34 +05302165#endif
Pavankumar Kondetie0c201f2010-12-07 17:53:55 +05302166 },
2167};
2168
2169static int __init msm_otg_init(void)
2170{
2171 return platform_driver_probe(&msm_otg_driver, msm_otg_probe);
2172}
2173
2174static void __exit msm_otg_exit(void)
2175{
2176 platform_driver_unregister(&msm_otg_driver);
2177}
2178
2179module_init(msm_otg_init);
2180module_exit(msm_otg_exit);
2181
2182MODULE_LICENSE("GPL v2");
2183MODULE_DESCRIPTION("MSM USB transceiver driver");